Implemented arch_cpu_user_*() for x86_64, based on the x86 versions.
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
* 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.
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -121,3 +127,136 @@ FUNCTION(x86_reboot):
|
|||||||
done:
|
done:
|
||||||
jmp done
|
jmp done
|
||||||
FUNCTION_END(x86_reboot)
|
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
|
void
|
||||||
arch_debug_save_registers(struct arch_debug_registers* registers)
|
arch_debug_save_registers(struct arch_debug_registers* registers)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user