30,166 → 30,203 |
* @{ |
*/ |
/** @file |
* @brief ARM32 architecture specific functions. |
*/ |
|
|
#include <arch.h> |
#include <arch/boot.h> |
#include <config.h> |
#include <arch/console.h> |
#include <ddi/device.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <genarch/drivers/dsrln/dsrlnin.h> |
#include <genarch/drivers/dsrln/dsrlnout.h> |
#include <genarch/srln/srln.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <arch/machine.h> |
#include <arch/debug/print.h> |
#include <print.h> |
#include <config.h> |
#include <interrupt.h> |
#include <arch/regutils.h> |
#include <arch/machine.h> |
#include <userspace.h> |
#include <macros.h> |
#include <string.h> |
|
/** Performs arm32-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo) |
bootinfo_t bootinfo; |
// // uintptr_t supervisor_sp /*__attribute__ ((section (".text")))*/; |
extern uintptr_t supervisor_sp; |
|
|
void arch_pre_main(void) |
{ |
unsigned int i; |
int i; |
|
init.cnt = bootinfo.cnt; |
|
for (i = 0; i < bootinfo.cnt; ++i) { |
init.tasks[i].addr = bootinfo.tasks[i].addr; |
init.tasks[i].size = bootinfo.tasks[i].size; |
} |
|
init.cnt = bootinfo->cnt; |
|
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); ++i) { |
init.tasks[i].addr = bootinfo->tasks[i].addr; |
init.tasks[i].size = bootinfo->tasks[i].size; |
str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN, |
bootinfo->tasks[i].name); |
} |
} |
|
/** Performs arm32 specific initialization before mm is initialized. */ |
|
void arch_pre_mm_init(void) |
{ |
/* It is not assumed by default */ |
interrupts_disable(); |
|
setup_exception_stacks(); |
} |
|
/** Performs arm32 specific initialization afterr mm is initialized. */ |
|
void arch_post_mm_init(void) |
{ |
machine_init(); |
|
/* Initialize exception dispatch table */ |
machine_hw_map_init(); |
|
/* Initialize dispatch table */ |
exception_init(); |
|
interrupt_init(); |
|
#ifdef CONFIG_FB |
machine_fb_init(); |
#else |
#ifdef CONFIG_ARM_PRN |
machine_srlnout_init(); |
#endif /* CONFIG_ARM_PRN */ |
#endif /* CONFIG_FB */ |
console_init(device_assign_devno()); |
|
interrupts_enable(); |
} |
|
/** Performs arm32 specific tasks needed after cpu is initialized. |
* |
* Currently the function is empty. |
*/ |
|
void arch_post_cpu_init(void) |
{ |
} |
|
|
/** Performs arm32 specific tasks needed before the multiprocessing is |
* initialized. |
* |
* Currently the function is empty because SMP is not supported. |
*/ |
void arch_pre_smp_init(void) |
{ |
/* TODO */ |
} |
|
|
/** Performs arm32 specific tasks needed after the multiprocessing is |
* initialized. |
* |
* Currently the function is empty because SMP is not supported. |
*/ |
void arch_post_smp_init(void) |
{ |
machine_input_init(); |
/* TODO */ |
} |
|
|
/** Performs arm32 specific tasks needed before the new task is run. */ |
/** Perform arm32 specific tasks needed before the new task is run. */ |
void before_task_runs_arch(void) |
{ |
tlb_invalidate_all(); |
} |
|
|
/** Performs arm32 specific tasks needed before the new thread is scheduled. |
* |
* It sets supervisor_sp. |
*/ |
/** Perform arm32 specific tasks needed before the new thread is scheduled. */ |
void before_thread_runs_arch(void) |
{ |
uint8_t *stck; |
|
tlb_invalidate_all(); |
stck = &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]; |
supervisor_sp = (uintptr_t) stck; |
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA]; |
} |
|
/** Performs arm32 specific tasks before a thread stops running. |
* |
* Currently the function is empty. |
*/ |
|
void after_thread_ran_arch(void) |
{ |
} |
|
/** Halts CPU. */ |
void cpu_halt(void) |
{ |
machine_cpu_halt(); |
} |
|
/** Reboot. */ |
void arch_reboot() |
{ |
/* not implemented */ |
while (1); |
} |
/** Struct to hold general purpose register values */ |
typedef struct { |
uint32_t r0; |
uint32_t r1; |
uint32_t r2; |
uint32_t r3; |
uint32_t r4; |
uint32_t r5; |
uint32_t r6; |
uint32_t r7; |
uint32_t r8; |
uint32_t r9; |
uint32_t r10; |
uint32_t r11; |
uint32_t r12; |
uint32_t sp; |
uint32_t lr; |
uint32_t pc; |
} ustate_t; |
|
/** Construct function pointer |
|
/** Changes processor mode and jumps to the address specified in the first parameter. |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
* @param kernel_uarg Userspace settings (entry point, stack, ...). |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
return addr; |
} |
dprintf("Userspace: .uspace_uarg(%X), .uspace_entry(%X), .uspace_stack(%X)\n", |
(unsigned int)(kernel_uarg->uspace_uarg), kernel_uarg->uspace_entry, |
kernel_uarg->uspace_stack); |
|
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
machine_grab_console(); |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
volatile ustate_t ustate; |
|
// set first parameter |
ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
|
// clear other registers |
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = |
ustate.r5 = ustate.r6 = ustate.r7 = ustate.r8 = |
ustate.r9 = ustate.r10 = ustate.r11 = ustate.r12 = 1; |
|
ustate.lr = 3; |
|
//set user stack |
ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + |
PAGE_SIZE - sizeof(void*); |
//on the bottom of stack there is pointer to TLS |
|
//set where uspace execution starts |
ustate.pc = (uintptr_t) kernel_uarg->uspace_entry; |
|
//status register in user mode |
ipl_t cpsr = current_status_reg_read(); |
cpsr &= ~STATUS_REG_MODE_MASK | USER_MODE; |
|
ipl_t tmpsr = (cpsr & ~STATUS_REG_MODE_MASK) | SUPERVISOR_MODE; |
|
asm __volatile__ ( |
// save pointer into ustate struct |
"mov r0, %0 \n" |
// save cspr |
"mov r1, %1 \n" |
// change mode into any exception mode |
"msr cpsr_c, %2 \n" |
// set saved cpsr |
"msr spsr_c, r1 \n" |
|
"mov sp, r0 \n" |
// replace almost all registers |
"ldmfd sp!, {r0-r12, sp, lr}^\n" |
//jump to the usermode |
"ldmfd sp!, {pc}^" |
: // no output |
: "r"(&ustate), "r"(cpsr), "r"(tmpsr) // |
: "r0","r1" |
); |
|
while(1) ; |
} |
|
/** Return console to userspace. */ |
void arch_release_console(void) |
|
void cpu_halt(void) |
{ |
machine_release_console(); |
machine_cpu_halt(); |
} |
|
/** @} |
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|