Implemented arch_cpu_user_*() for x86_64, based on the x86 versions.
This commit is contained in:
parent
fc644104ac
commit
d776fd53f7
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user