kernel/arm: implement entering userspace
Change-Id: Icf3945db979a8f4444856fc7157649f48b297c29 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5037 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Fredrik Holmqvist <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
6acf0b3e21
commit
6804f6c764
@@ -37,4 +37,15 @@ struct arch_fork_arg {
|
|||||||
char dummy;
|
char dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void arch_return_to_userland(struct iframe *);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* KERNEL_ARCH_ARM_THREAD_TYPES_H */
|
#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.
|
* Copyright 2007, Travis Geiselbrecht. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _SYSTEM_ARCH_M68K_COMMPAGE_DEFS_H
|
#ifndef _SYSTEM_ARCH_ARM_COMMPAGE_DEFS_H
|
||||||
#define _SYSTEM_ARCH_M68K_COMMPAGE_DEFS_H
|
#define _SYSTEM_ARCH_ARM_COMMPAGE_DEFS_H
|
||||||
|
|
||||||
#ifndef _SYSTEM_COMMPAGE_DEFS_H
|
#ifndef _SYSTEM_COMMPAGE_DEFS_H
|
||||||
# error Must not be included directly. Include <commpage_defs.h> instead!
|
# error Must not be included directly. Include <commpage_defs.h> instead!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define COMMPAGE_ENTRY_M68K_SYSCALL (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0)
|
#define COMMPAGE_ENTRY_ARM_THREAD_EXIT (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0)
|
||||||
//#define COMMPAGE_ENTRY_M68K_MEMCPY (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 1)
|
|
||||||
|
|
||||||
#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_MASK 0x1f
|
||||||
#define CPSR_MODE_USR 0x10
|
#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
|
#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.
|
* Copyright 2009, Wischert, johanneswi@gmail.com.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* 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.h>
|
||||||
|
#include <arch/arm/arch_cpu_defs.h>
|
||||||
|
|
||||||
#include <asm_defs.h>
|
#include <asm_defs.h>
|
||||||
|
|
||||||
#include "asm_offsets.h"
|
#include "asm_offsets.h"
|
||||||
|
#include "syscall_numbers.h"
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
@@ -253,3 +258,42 @@ FUNCTION(arch_debug_call_with_fault_handler):
|
|||||||
mov r1, #1
|
mov r1, #1
|
||||||
b longjmp
|
b longjmp
|
||||||
FUNCTION_END(arch_debug_call_with_fault_handler)
|
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, [email protected].
|
* Copyright 2009, Johannes Wischert, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -15,14 +18,36 @@
|
|||||||
#include <smp.h>
|
#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
|
status_t
|
||||||
arch_commpage_init(void)
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +55,10 @@ arch_commpage_init(void)
|
|||||||
status_t
|
status_t
|
||||||
arch_commpage_init_post_cpus(void)
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <arch_cpu.h>
|
#include <arch_cpu.h>
|
||||||
#include <arch/thread.h>
|
#include <arch/thread.h>
|
||||||
#include <boot/stage2.h>
|
#include <boot/stage2.h>
|
||||||
|
#include <commpage.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
@@ -198,9 +199,37 @@ arch_thread_dump_info(void *info)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_thread_enter_userspace(Thread *thread, addr_t entry,
|
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;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ dummy()
|
|||||||
|
|
||||||
// struct iframe
|
// struct iframe
|
||||||
DEFINE_SIZEOF_MACRO(IFRAME, 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
|
// struct signal_frame_data
|
||||||
DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data);
|
DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data);
|
||||||
|
|||||||
Reference in New Issue
Block a user