kernel/arm: implement entering userspace
Change-Id: Icf3945db979a8f4444856fc7157649f48b297c29 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5037 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com> Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
6acf0b3e21
commit
6804f6c764
@ -37,4 +37,15 @@ struct arch_fork_arg {
|
||||
char dummy;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void arch_return_to_userland(struct iframe *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* KERNEL_ARCH_ARM_THREAD_TYPES_H */
|
||||
|
@ -1,15 +1,17 @@
|
||||
/*
|
||||
* Copyright 2022, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2007, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _SYSTEM_ARCH_M68K_COMMPAGE_DEFS_H
|
||||
#define _SYSTEM_ARCH_M68K_COMMPAGE_DEFS_H
|
||||
#ifndef _SYSTEM_ARCH_ARM_COMMPAGE_DEFS_H
|
||||
#define _SYSTEM_ARCH_ARM_COMMPAGE_DEFS_H
|
||||
|
||||
#ifndef _SYSTEM_COMMPAGE_DEFS_H
|
||||
# error Must not be included directly. Include <commpage_defs.h> instead!
|
||||
#endif
|
||||
|
||||
//#define COMMPAGE_ENTRY_M68K_SYSCALL (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0)
|
||||
//#define COMMPAGE_ENTRY_M68K_MEMCPY (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 1)
|
||||
#define COMMPAGE_ENTRY_ARM_THREAD_EXIT (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0)
|
||||
|
||||
#endif /* _SYSTEM_ARCH_M68K_COMMPAGE_DEFS_H */
|
||||
#endif /* _SYSTEM_ARCH_ARM_COMMPAGE_DEFS_H */
|
||||
|
@ -13,6 +13,12 @@
|
||||
|
||||
#define CPSR_MODE_MASK 0x1f
|
||||
#define CPSR_MODE_USR 0x10
|
||||
#define CPSR_MODE_SVC 0x13
|
||||
#define CPSR_MODE_SYS 0x1f
|
||||
|
||||
#define CPSR_T 0x20
|
||||
#define CPSR_F 0x40
|
||||
#define CPSR_I 0x80
|
||||
|
||||
#define FSR_WNR 0x800
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
/*
|
||||
* Copyright 2022, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2009, Wischert, johanneswi@gmail.com.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
@ -7,10 +10,12 @@
|
||||
*/
|
||||
|
||||
#include <arch/arm/arch_cpu.h>
|
||||
#include <arch/arm/arch_cpu_defs.h>
|
||||
|
||||
#include <asm_defs.h>
|
||||
|
||||
#include "asm_offsets.h"
|
||||
#include "syscall_numbers.h"
|
||||
|
||||
.text
|
||||
|
||||
@ -253,3 +258,42 @@ FUNCTION(arch_debug_call_with_fault_handler):
|
||||
mov r1, #1
|
||||
b longjmp
|
||||
FUNCTION_END(arch_debug_call_with_fault_handler)
|
||||
|
||||
|
||||
FUNCTION(arch_return_to_userland):
|
||||
// set SPSR to user mode, IRQ enabled, FIQ disabled
|
||||
mrs ip, cpsr
|
||||
bic ip, ip, #(CPSR_MODE_MASK | CPSR_T | CPSR_F | CPSR_I)
|
||||
orr ip, ip, #(CPSR_MODE_USR | CPSR_F)
|
||||
msr spsr, ip
|
||||
|
||||
// use system mode to load user mode SP and LR
|
||||
ldr r4, [r0, #IFRAME_usr_sp]
|
||||
ldr r5, [r0, #IFRAME_usr_lr]
|
||||
mrs ip, cpsr
|
||||
bic ip, ip, #(CPSR_MODE_MASK)
|
||||
orr ip, ip, #(CPSR_MODE_SYS)
|
||||
msr cpsr, ip
|
||||
mov sp, r4
|
||||
mov lr, r5
|
||||
bic ip, ip, #(CPSR_MODE_MASK)
|
||||
orr ip, ip, #(CPSR_MODE_SVC)
|
||||
msr cpsr, ip
|
||||
|
||||
// load user mode entry point in LR
|
||||
ldr lr, [r0, #IFRAME_pc]
|
||||
|
||||
// load general purpose registers
|
||||
mov sp, r0
|
||||
add sp, sp, #4
|
||||
ldmfd sp!, { r0-r12 }
|
||||
|
||||
// jump to user mode entry point
|
||||
movs pc, lr
|
||||
FUNCTION_END(arch_return_to_userland)
|
||||
|
||||
|
||||
FUNCTION(arch_user_thread_exit):
|
||||
svc SYSCALL_EXIT_THREAD
|
||||
bx lr
|
||||
FUNCTION_END(arch_user_thread_exit)
|
||||
|
@ -1,4 +1,7 @@
|
||||
/*
|
||||
* Copyright 2022, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2009, Johannes Wischert, johanneswi@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -15,14 +18,36 @@
|
||||
#include <smp.h>
|
||||
|
||||
|
||||
extern "C" void arch_user_thread_exit();
|
||||
|
||||
|
||||
static void
|
||||
register_commpage_function(const char* functionName, int32 commpageIndex,
|
||||
const char* commpageSymbolName, addr_t expectedAddress)
|
||||
{
|
||||
// get address and size of function
|
||||
elf_symbol_info symbolInfo;
|
||||
if (elf_lookup_kernel_symbol(functionName, &symbolInfo) != B_OK) {
|
||||
panic("register_commpage_function(): Failed to find "
|
||||
"function \"%s\"!", functionName);
|
||||
}
|
||||
|
||||
ASSERT(expectedAddress == symbolInfo.address);
|
||||
|
||||
// fill in the commpage table entry
|
||||
addr_t position = fill_commpage_entry(commpageIndex,
|
||||
(void*)symbolInfo.address, symbolInfo.size);
|
||||
|
||||
// add symbol to the commpage image
|
||||
image_id image = get_commpage_image();
|
||||
elf_add_memory_image_symbol(image, commpageSymbolName, position,
|
||||
symbolInfo.size, B_SYMBOL_TYPE_TEXT);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
arch_commpage_init(void)
|
||||
{
|
||||
/* no optimized memcpy or anything yet */
|
||||
/* we don't use it for syscall yet either */
|
||||
// add syscall to the commpage image
|
||||
// image_id image = get_commpage_image();
|
||||
#warning ARM:IMPLEMENTME
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -30,7 +55,10 @@ arch_commpage_init(void)
|
||||
status_t
|
||||
arch_commpage_init_post_cpus(void)
|
||||
{
|
||||
#warning ARM:IMPLEMENTME
|
||||
register_commpage_function("arch_user_thread_exit",
|
||||
COMMPAGE_ENTRY_ARM_THREAD_EXIT, "commpage_thread_exit",
|
||||
(addr_t)&arch_user_thread_exit);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <arch_cpu.h>
|
||||
#include <arch/thread.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <commpage.h>
|
||||
#include <kernel.h>
|
||||
#include <thread.h>
|
||||
#include <tls.h>
|
||||
@ -198,9 +199,37 @@ arch_thread_dump_info(void *info)
|
||||
|
||||
status_t
|
||||
arch_thread_enter_userspace(Thread *thread, addr_t entry,
|
||||
void *arg1, void *arg2)
|
||||
void *args1, void *args2)
|
||||
{
|
||||
panic("arch_thread_enter_uspace(): not yet implemented\n");
|
||||
arm_set_tls_context(thread);
|
||||
|
||||
addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
|
||||
|
||||
TRACE(("arch_thread_enter_userspace: entry 0x%" B_PRIxADDR ", args %p %p, "
|
||||
"ustack_top 0x%" B_PRIxADDR "\n", entry, args1, args2, stackTop));
|
||||
|
||||
//stackTop = arch_randomize_stack_pointer(stackTop - sizeof(args));
|
||||
|
||||
// Copy the address of the stub that calls exit_thread() when the thread
|
||||
// entry function returns to LR to act as the return address.
|
||||
// The stub is inside commpage.
|
||||
addr_t commPageAddress = (addr_t)thread->team->commpage_address;
|
||||
|
||||
disable_interrupts();
|
||||
|
||||
// prepare the user iframe
|
||||
iframe frame = {};
|
||||
frame.r0 = (uint32)args1;
|
||||
frame.r1 = (uint32)args2;
|
||||
frame.usr_sp = stackTop;
|
||||
frame.usr_lr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_ARM_THREAD_EXIT]
|
||||
+ commPageAddress;
|
||||
frame.pc = entry;
|
||||
|
||||
// return to userland
|
||||
arch_return_to_userland(&frame);
|
||||
|
||||
// normally we don't get here
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@ dummy()
|
||||
|
||||
// struct iframe
|
||||
DEFINE_SIZEOF_MACRO(IFRAME, iframe);
|
||||
DEFINE_OFFSET_MACRO(IFRAME, iframe, pc);
|
||||
DEFINE_OFFSET_MACRO(IFRAME, iframe, usr_sp);
|
||||
DEFINE_OFFSET_MACRO(IFRAME, iframe, usr_lr);
|
||||
|
||||
// struct signal_frame_data
|
||||
DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data);
|
||||
|
Loading…
Reference in New Issue
Block a user