From d776fd53f7fdf12f297838ca476948bc7083c82a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 11 Jul 2012 14:19:19 +0100 Subject: [PATCH] Implemented arch_cpu_user_*() for x86_64, based on the x86 versions. --- src/system/kernel/arch/x86/64/arch.S | 141 +++++++++++++++++++++++- src/system/kernel/arch/x86/64/stubs.cpp | 23 ---- 2 files changed, 140 insertions(+), 24 deletions(-) diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index 4fe65734c1..58b4bcb994 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -1,6 +1,12 @@ /* * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Copyright 2002, Michael Noisternig. All rights reserved. + * Distributed under the terms of the NewOS License. */ @@ -78,7 +84,7 @@ FUNCTION_END(x86_64_thread_entry) /* void x86_context_switch(struct arch_thread* oldState, - struct arch_thread* newState); */ + struct arch_thread* newState); */ FUNCTION(x86_context_switch): // Just need to save callee-save registers: RBP, RBX, R12-15. push %r15 @@ -121,3 +127,136 @@ FUNCTION(x86_reboot): done: jmp done FUNCTION_END(x86_reboot) + + +/* status_t arch_cpu_user_memcpy(void* to, const void* from, size_t size, + addr_t* faultHandler) */ +FUNCTION(arch_cpu_user_memcpy): + // faultHandler -> r8, size -> rcx. + movq %rcx, %r8 + movq %rdx, %rcx + + // Set the fault handler, preserve old in rax. + movq (%r8), %rax + movq $.L_user_memcpy_error, (%r8) + + // Move by quadwords. + cld + movq %rcx, %r9 + shrq $3, %rcx + rep + movsq + + // Move any remaining data by bytes. + movq %r9, %rcx + andq $7, %rcx + rep + movsb + + // Restore the old fault handler and return. + movq %rax, (%r8) + xorl %eax, %eax + ret + +.L_user_memcpy_error: + // Restore the old fault handler. Return a generic error, the wrapper + // routine will deal with it. + movq %rax, (%r8) + movl $-1, %eax + ret +FUNCTION_END(arch_cpu_user_memcpy) + + +/* status_t arch_cpu_user_memset(void* to, char c, size_t count, + addr_t* faultHandler) */ +FUNCTION(arch_cpu_user_memset): + // c -> al, faultHandler -> r8, size -> rcx. + movw %si, %ax + movq %rcx, %r8 + movq %rdx, %rcx + + // Set the fault handler, preserve old in rdx. + movq (%r8), %rdx + movq $.L_user_memset_error, (%r8) + + rep + stosb + + // Restore the old fault handler and return. + movq %rdx, (%r8) + xorl %eax, %eax + ret + +.L_user_memset_error: + // Restore the old fault handler. Return a generic error, the wrapper + // routine will deal with it. + movq %rdx, (%r8) + movl $-1, %eax + ret +FUNCTION_END(arch_cpu_user_memset) + + +/* ssize_t arch_cpu_user_strlcpy(void* to, const void* from, size_t size, + addr_t* faultHandler) */ +FUNCTION(arch_cpu_user_strlcpy): + // faultHandler -> r8, size -> rcx, source -> r9 (original value needed to + // calculate return value). + movq %rcx, %r8 + movq %rdx, %rcx + movq %rsi, %r9 + + // Set the fault handler, preserve old in rax. + movq (%r8), %rax + movq $.L_user_strlcpy_error, (%r8) + + // Check for 0 length. + cmp $0, %rcx + je .L_user_strlcpy_source_count + + // Copy at most count - 1 bytes. + dec %rcx + + // If count is now 0, skip straight to null terminating as our loop will + // otherwise overflow. + jnz .L_user_strlcpy_copy_begin + movb $0, (%rdi) + jmp .L_user_strlcpy_source_count + +.L_user_strlcpy_copy_begin: + cld +.L_user_strlcpy_copy_loop: + // Move data by bytes. + lodsb + stosb + test %al, %al + jz .L_user_strlcpy_source_done + loop .L_user_strlcpy_copy_loop + + // Null terminate string. + movb $0, (%rdi) + dec %rsi + +.L_user_strlcpy_source_count: + // Count remaining bytes in src + not %rcx + xor %al, %al + repnz + scasb + +.L_user_strlcpy_source_done: + // Restore the old fault handler + movq %rax, (%r8) + + // Calculate total string length and return. + movq %rsi, %rax + subq %r9, %rax + dec %rax + ret + +.L_user_strlcpy_error: + // Restore the old fault handler. Return a generic error, the wrapper + // routine will deal with it. + movq %rax, (%r8) + movq $-1, %rax + ret +FUNCTION_END(arch_cpu_user_strlcpy) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 2651c32a47..e4a02c973a 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -51,29 +51,6 @@ arch_commpage_init_post_cpus(void) } -ssize_t -arch_cpu_user_strlcpy(char* to, const char* from, size_t size, - addr_t* faultHandler) -{ - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memcpy(void* to, const void* from, size_t size, - addr_t* faultHandler) -{ - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memset(void* s, char c, size_t count, addr_t* faultHandler) -{ - return B_BAD_ADDRESS; -} - - void arch_debug_save_registers(struct arch_debug_registers* registers) {