/branches/arm/kernel/arch/arm32/Makefile.inc |
---|
75,14 → 75,15 |
arch/$(ARCH)/src/panic.S \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/debug/print.c \ |
arch/$(ARCH)/src/console.c \ |
arch/$(ARCH)/src/exception.c \ |
arch/$(ARCH)/src/userspace.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/debug/print.c \ |
arch/$(ARCH)/src/console.c \ |
arch/$(ARCH)/src/exception.c \ |
arch/$(ARCH)/src/mm/memory_init.c \ |
arch/$(ARCH)/src/mm/page_fault.c |
/branches/arm/kernel/arch/arm32/src/arm32.c |
---|
128,87 → 128,7 |
} |
/** 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; |
/** Changes processor mode and jumps to the address specified in the first parameter. |
* |
* @param kernel_uarg Userspace settings (entry point, stack, ...). |
*/ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
// 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); |
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) ; |
} |
void cpu_halt(void) |
{ |
machine_cpu_halt(); |
/branches/arm/kernel/arch/arm32/src/mm/page_fault.c |
---|
44,7 → 44,7 |
/** Returns value stored in fault status register. |
* FSR contain reason of page fault |
* |
* \return Value stored in CP15 fault status register (FSR). |
* @return Value stored in CP15 fault status register (FSR). |
*/ |
static inline fault_status_t read_fault_status_register(void) |
{ |
61,7 → 61,7 |
/** Returns FAR (fault address register) content. |
* |
* \return FAR (fault address register) content (address that caused a page fault) |
* @return FAR (fault address register) content (address that caused a page fault) |
*/ |
static inline uintptr_t read_fault_address_register(void) |
{ |
78,9 → 78,9 |
/** Decides whether the instructions is load/store or not. |
* |
* \param instr Instruction |
* @param instr Instruction |
* |
* \return true when instruction is load/store, false otherwise |
* @return true when instruction is load/store, false otherwise |
*/ |
static inline bool is_load_store_instruction(instruction_t instr) |
{ |
110,9 → 110,9 |
/** Decides whether the instructions is swap or not. |
* |
* \param instr Instruction |
* @param instr Instruction |
* |
* \return true when instruction is swap, false otherwise |
* @return true when instruction is swap, false otherwise |
*/ |
static inline bool is_swap_instruction(instruction_t instr) |
{ |
129,11 → 129,11 |
/** Decides whether read or write into memory is requested. |
* |
* \param instr_addr Address of instruction which tries to access memory |
* \param badvaddr Virtual address the instruction tries to access |
* @param instr_addr Address of instruction which tries to access memory |
* @param badvaddr Virtual address the instruction tries to access |
* |
* \return Type of access into memmory |
* \note Returns #PF_ACCESS_EXEC if no memory access is requested |
* @return Type of access into memmory |
* Note: Returns #PF_ACCESS_EXEC if no memory access is requested |
*/ |
static pf_access_t get_memory_access_type(uint32_t instr_addr, uintptr_t badvaddr) |
{ |
195,8 → 195,8 |
/** Handles "data abort" exception (load or store at invalid address). |
* |
* \param exc_no exception number |
* \param istate CPU state when exception occured |
* @param exc_no exception number |
* @param istate CPU state when exception occured |
*/ |
void data_abort(int exc_no, istate_t *istate) |
{ |
219,8 → 219,8 |
/** Handles "prefetch abort" exception (instruction couldn't be executed). |
* |
* \param exc_no exception number |
* \param istate CPU state when exception occured |
* @param exc_no exception number |
* @param istate CPU state when exception occured |
*/ |
void prefetch_abort(int exc_no, istate_t *istate) |
{ |
/branches/arm/kernel/arch/arm32/src/mm/page.c |
---|
84,9 → 84,9 |
* This function adds mapping of physical address that is read/write only |
* from kernel and not bufferable. |
* |
* \param physaddr Physical addres where device is connected |
* \param size Length of area where device is present |
* \return Virtual address where device will be accessable |
* @param physaddr Physical addres where device is connected |
* @param size Length of area where device is present |
* @return Virtual address where device will be accessable |
*/ |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
/branches/arm/kernel/arch/arm32/src/userspace.c |
---|
0,0 → 1,114 |
/* |
* Copyright (c) 2007 Petr Stepan, Pavel Jancik |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
*/ |
#include <userspace.h> |
/** 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; |
/** Changes processor mode and jumps to the address specified in the first parameter. |
* |
* @param kernel_uarg Userspace settings (entry point, stack, ...). |
*/ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
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 = |
ustate.lr = 0; |
//set user stack |
ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + |
PAGE_SIZE - sizeof(void*); |
//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" |
); |
// unreachable |
while(1) ; |
} |
/** @} |
*/ |