/branches/arm/kernel/arch/arm32/include/exception.h |
---|
66,25 → 66,26 |
#define EXC_FIQ 6 |
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 spsr; |
uint32_t prev_sp; |
uint32_t prev_lr; |
uint32_t spsr; |
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; |
} istate_t; |
static inline void istate_set_retaddr(istate_t *istate, uintptr_t retaddr) |
/branches/arm/kernel/arch/arm32/src/exception.c |
---|
40,6 → 40,7 |
#include <interrupt.h> |
#include <arch/drivers/gxemul.h> |
#include <arch/mm/page_fault.h> |
#include <print.h> |
#define PREFETCH_OFFSET 0x8 |
#define BRANCH_OPCODE 0xea000000 |
48,34 → 49,128 |
#define EXC_VECTORS_SIZE 0x20 |
#define EXC_VECTORS 0x8 |
extern uintptr_t supervisor_sp; |
extern uintptr_t exc_stack; |
inline static void setup_stack_and_save_regs() |
{ |
asm volatile( "ldr r13, =exc_stack \n\ |
stmfd r13!, {r0} \n\ |
mrs r0, spsr \n\ |
and r0, r0, #0x1f \n\ |
cmp r0, #0x10 \n\ |
bne 1f \n\ |
\n\ |
@prev mode was usermode \n\ |
ldmfd r13!, {r0} \n\ |
ldr r13, =supervisor_sp \n\ |
stmfd r13!, {r0-r12, r13, lr} \n\ |
stmfd r13!, {r13, lr}^ \n\ |
mrs r0, spsr \n\ |
stmfd r13!, {r0} \n\ |
b 2f \n\ |
\n\ |
@prev mode was not usermode \n\ |
1: \n\ |
stmfd r13!, {r1, r2, r3} \n\ |
mrs r1, cpsr \n\ |
mov r2, lr \n\ |
bic r1, r1, #0x1f \n\ |
orr r1, r1, r0 \n\ |
mrs r0, cpsr \n\ |
msr cpsr_c, r1 \n\ |
\n\ |
mov r3, r13 \n\ |
stmfd r13!, {r2} \n\ |
stmfd r13!, {r3} \n\ |
stmfd r13!, {r4-r12} \n\ |
mov r2, lr \n\ |
mov r1, r13 \n\ |
msr cpsr_c, r0 \n\ |
\n\ |
ldmfd r13!, {r4, r5, r6, r7} \n\ |
stmfd r1!, {r4, r5, r6} \n\ |
stmfd r1!, {r7} \n\ |
stmfd r1!, {r2} \n\ |
stmfd r1!, {r3} \n\ |
mrs r0, spsr \n\ |
stmfd r1!, {r0} \n\ |
mov r13, r1 \n\ |
2:" |
); |
} |
inline static void load_regs() |
{ |
asm volatile( "ldmfd r13!, {r0} \n\ |
msr spsr, r0 \n\ |
and r0, r0, #0x1f \n\ |
cmp r0, #0x10 \n\ |
bne 3f \n\ |
\n\ |
@return to user mode \n\ |
ldmfd r13!, {r13, lr}^ \n\ |
b 4f \n\ |
\n\ |
@return to non-user mode \n\ |
3: \n\ |
ldmfd r13!, {r1, r2} \n\ |
mrs r3, cpsr \n\ |
bic r3, r3, #0x1f \n\ |
orr r3, r3, r0 \n\ |
mrs r0, cpsr \n\ |
msr cpsr_c, r3 \n\ |
\n\ |
mov r13, r1 \n\ |
mov lr, r2 \n\ |
msr cpsr_c, r0 \n\ |
\n\ |
@actual return \n\ |
4: \n\ |
ldmfd r13!, {r0-r12, r13, pc}^" |
); |
} |
#define SAVE_REGS_TO_STACK \ |
asm("stmfd sp!, {r0-r12, sp, lr}"); \ |
asm("stmfd r13!, {r0-r12, r13, lr}"); \ |
asm("mrs r14, spsr"); \ |
asm("stmfd sp!, {r14}"); |
asm("stmfd r13!, {r14}"); |
#define CALL_EXC_DISPATCH(exception) \ |
asm("mov r0, %0" : : "i" (exception)); \ |
asm("mov r1, sp"); \ |
asm("mov r1, r13"); \ |
asm("bl exc_dispatch"); |
/**Loads registers from the stack and resets SPSR before exitting exception |
* handler. |
*/ |
#define LOAD_REGS_FROM_STACK \ |
asm("ldmfd sp!, {r14}"); \ |
asm("ldmfd r13!, {r14}"); \ |
asm("msr spsr, r14"); \ |
asm("ldmfd sp!, {r0-r12, sp, pc}^"); |
asm("ldmfd r13!, {r0-r12, r13, pc}^"); |
/** General exception handler. |
* Stores registers, dispatches the exception, |
* and finally restores registers and returns from exception processing. |
*/ |
#define PROCESS_EXCEPTION(exception) \ |
SAVE_REGS_TO_STACK \ |
setup_stack_and_save_regs(); \ |
CALL_EXC_DISPATCH(exception) \ |
LOAD_REGS_FROM_STACK |
load_regs(); |
/* #define PROCESS_EXCEPTION(exception) \ |
SAVE_REGS_TO_STACK \ |
CALL_EXC_DISPATCH(exception) \ |
LOAD_REGS_FROM_STACK*/ |
/** Updates specified exception vector to jump to given handler. |
* Addresses of handlers are stored in memory following exception vectors. |
*/ |
91,8 → 186,10 |
/* store handler's address */ |
*(vector + EXC_VECTORS) = handler_addr; |
} |
static void reset_exception_entry() |
{ |
PROCESS_EXCEPTION(EXC_RESET); |
135,10 → 232,27 |
static void irq_exception_entry() |
{ |
asm("sub lr, lr, #4"); |
// SAVE_REGS_TO_STACK |
// CALL_EXC_DISPATCH(EXC_IRQ) |
// LOAD_REGS_FROM_STACK; |
PROCESS_EXCEPTION(EXC_IRQ); |
} |
// static void prefetch_abort_exception(int exc_no, istate_t* istate) |
// { |
// dputs("(PREFETCH|DATA) ABORT exception caught, not processed.\n"); |
// } |
static void swi_exception(int exc_no, istate_t* istate) |
{ |
dprintf("\nIstate dump:\n"); |
dprintf(" r0:%X r1:%X r2:%X r3:%X\n", istate->r0, istate->r1, istate->r2, istate->r3); |
dprintf(" r4:%X r5:%X r6:%X r7:%X\n", istate->r4, istate->r5, istate->r6, istate->r7); |
dprintf(" r8:%X r9:%X r10:%X r11:%X\n", istate->r8, istate->r9, istate->r10, istate->r11); |
dprintf(" r12:%X r13:%X lr:%X spsr:%X\n", istate->r12, istate->sp, istate->lr, istate->spsr); |
dprintf(" prev_lr:%X prev_sp:%X\n", istate->prev_lr, istate->prev_sp); |
} |
/** Interrupt Exception handler. |
* Determines the sources of interrupt, and calls their handlers. |
*/ |
206,7 → 320,7 |
install_handler((unsigned)data_abort_exception_entry, |
(unsigned*)EXC_DATA_ABORT_VEC); |
install_handler((unsigned)irq_exception_entry, |
install_handler((unsigned)irq_exception_entry, |
(unsigned*)EXC_IRQ_VEC); |
install_handler((unsigned)fiq_exception_entry, |
213,6 → 327,7 |
(unsigned*)EXC_FIQ_VEC); |
} |
#ifdef HIGH_EXCEPTION_VECTORS |
/** Activates using high exception vectors addresses. */ |
static void high_vectors() |
{ |
225,8 → 340,8 |
asm volatile( "mcr p15, 0, %0, c1, c1" : : "r" (control_reg)); |
} |
#endif |
/** Initializes exception handling. |
* |
* Installs low-level exception handlers and then registers |
237,39 → 352,42 |
#ifdef HIGH_EXCEPTION_VECTORS |
high_vectors(); |
#endif |
install_exception_handlers(); |
exc_register(EXC_IRQ, "interrupt", (iroutine) irq_exception); |
exc_register(EXC_PREFETCH_ABORT, "prefetch abort", (iroutine) prefetch_abort); |
exc_register(EXC_DATA_ABORT, "data abort", (iroutine) data_abort); |
/* TODO add next */ |
exc_register(EXC_SWI, "software interrupt", (iroutine) swi_exception); |
/* TODO add next */ |
} |
/* TODO change soon, temporary hack. */ |
/** Sets stack pointers in all supported exception modes. |
* |
* @param stack_ptr stack pointer |
*/ |
void setup_exception_stacks() |
{ |
/* switch to particular mode and set "sp" there */ |
/* switch to particular mode and set "r13" there */ |
uint32_t cspr = current_status_reg_read(); |
uint32_t cspr = current_status_reg_read(); |
/* IRQ stack */ |
current_status_reg_control_write( |
(cspr & ~STATUS_REG_MODE_MASK) | IRQ_MODE |
); |
asm("ldr sp, =irq_stack"); |
/* IRQ stack */ |
current_status_reg_control_write( |
(cspr & ~STATUS_REG_MODE_MASK) | IRQ_MODE |
); |
asm("ldr r13, =exc_stack"); |
/* abort stack */ |
current_status_reg_control_write( |
(cspr & ~STATUS_REG_MODE_MASK) | ABORT_MODE |
); |
asm("ldr sp, =abort_stack"); |
/* abort stack */ |
current_status_reg_control_write( |
(cspr & ~STATUS_REG_MODE_MASK) | ABORT_MODE |
); |
asm("ldr r13, =exc_stack"); |
/* TODO if you want to test other exceptions than IRQ, |
make stack analogous to irq_stack (in start.S), |
and then set stack pointer here */ |
/* TODO if you want to test other exceptions than IRQ, |
make stack analogous to irq_stack (in start.S), |
and then set stack pointer here */ |
current_status_reg_control_write( cspr); |
current_status_reg_control_write( cspr); |
} |
/branches/arm/kernel/arch/arm32/src/arm32.c |
---|
47,9 → 47,10 |
#include <config.h> |
#include <interrupt.h> |
#include <arch/regutils.h> |
//#include <arch/drivers/init.h> |
#include <arch/drivers/gxemul.h> |
#include <userspace.h> |
bootinfo_t bootinfo; |
uintptr_t supervisor_sp /*__attribute__ ((section (".text")))*/; |
//TODO: Remove include and move into exceptio.c |
#include <arch/exception.h> |
96,9 → 97,6 |
init.tasks[i].addr = bootinfo.tasks[i].addr; |
init.tasks[i].size = bootinfo.tasks[i].size; |
} |
/* TODO this code just setups irq testing bed */ |
setup_exception_stacks(); |
} |
void arch_pre_mm_init(void) |
107,6 → 105,9 |
/* It is not assumed by default */ |
interrupts_disable(); |
setup_exception_stacks(); |
} |
114,29 → 115,22 |
void arch_post_mm_init(void) |
{ |
dprintf("arch_post_mm_init start()\n"); |
/* Initialize dispatch table |
Note: Have to be after page_init() */ |
// dprintf("arch_post_mm_init start()\n"); |
gxemul_hw_map_init(); |
/* Initialize dispatch table */ |
exception_init(); |
// drivers_init(); |
// drivers_init(); |
interrupt_init(); |
// console_init(device_assign_devno()); |
console_init(device_assign_devno()); |
//fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8); |
// interrupts_enable(); |
// asm __volatile__ ("ldr pc, =0x70000000"); // prefetch exception |
//while(1); |
/* |
uspace_arg_t uspace; |
uspace.uspace_entry = (void*)prefetch_exception_generator; |
uspace.uspace_stack = (void*)0x6000000; |
uspace.uspace_uarg = &uspace; |
interrupts_enable(); |
dprintf("arch_post_mm_init end()\n"); |
// while(1); |
userspace(&uspace); |
*/ |
dprintf("arch_post_mm_init end()\n"); |
} |
void arch_post_cpu_init(void) |
163,7 → 157,7 |
/** Perform arm32 specific tasks needed before the new thread is scheduled. */ |
void before_thread_runs_arch(void) |
{ |
/* TODO */ |
supervisor_sp = (uintptr_t) &THREAD->kstack/*[THREAD_STACK_SIZE-SP_DELTA]*/; |
} |
void after_thread_ran_arch(void) |
/branches/arm/kernel/arch/arm32/src/mm/page_fault.c |
---|
38,6 → 38,7 |
#include <mm/as.h> |
#include <genarch/mm/page_pt.h> |
#include <arch.h> |
#include <interrupt.h> |
//TODO: remove in final version |
137,17 → 138,17 |
// get instruction op code |
instruction_t i_code = *(tmp.instr); |
dprintf("get_instruction_memmory_access\n"); |
dprintf(" instr_addr:%X\n",instr_addr); |
dprintf(" i_code:%X\n",i_code); |
dprintf(" i_code.condition:%d\n", i_code.condition); |
dprintf(" i_code.instr_type:%d\n",i_code.instr_type); |
dprintf(" i_code.opcode:%d\n",i_code.opcode); |
dprintf(" i_code.acess:%d\n", i_code.access); |
dprintf(" i_code.dummy:%d\n", i_code.dummy); |
dprintf(" i_code.bits567%d\n", i_code.bits567); |
dprintf(" i_code.bit4:%d\n", i_code.bit4); |
dprintf(" i_code.dummy1:%d\n", i_code.dummy1); |
// dprintf("get_instruction_memmory_access\n"); |
// dprintf(" instr_addr:%X\n",instr_addr); |
// dprintf(" i_code:%X\n",i_code); |
// dprintf(" i_code.condition:%d\n", i_code.condition); |
// dprintf(" i_code.instr_type:%d\n",i_code.instr_type); |
// dprintf(" i_code.opcode:%d\n",i_code.opcode); |
// dprintf(" i_code.acess:%d\n", i_code.access); |
// dprintf(" i_code.dummy:%d\n", i_code.dummy); |
// dprintf(" i_code.bits567%d\n", i_code.bits567); |
// dprintf(" i_code.bit4:%d\n", i_code.bit4); |
// dprintf(" i_code.dummy1:%d\n", i_code.dummy1); |
// undefined instructions ... (or special instructions) |
209,11 → 210,11 |
pf_access_t access = get_memmory_access_type( istate->lr, page); |
print_istate(istate); |
// print_istate(istate); |
dprintf(" page fault : ip:%X, va:%X, status:%x(%x), access:%d\n", istate->lr, page, fsr.status,fsr, access); |
/* Alf: Will be commented until stack problem will be solved ... |
as_page_fault make consequent page faults |
as_page_fault make consequent page faults*/ |
int ret = as_page_fault(page, access, istate); |
dprintf(" as_page_fault ret:%d\n", ret); |
222,7 → 223,7 |
panic("page fault\n"); |
} |
*/ |
// TODO: Remove this ... now for testing purposes ... it's bad to test page faults in kernel, where no page faults should occures |
panic("page fault ... solved\n"); |
240,7 → 241,7 |
dprintf(" prefetch_abourt ... instruction on adress:%x can't be fetched\n", istate->lr); |
/* Alf: Will be commented until stack problem will be solved ... |
as_page_fault make consequent page faults |
as_page_fault make consequent page faults*/ |
int ret = as_page_fault(istate->lr, PF_ACCESS_EXEC, istate); |
dprintf(" as_page_fault ret:%d\n", ret); |
247,8 → 248,8 |
if (ret == AS_PF_FAULT) { |
panic("page fault - instruction fetch at addr:%X\n", istate->lr); |
} |
*/ |
panic("Prefetch abourt ... solved"); |
} |
/branches/arm/kernel/arch/arm32/src/mm/page.c |
---|
74,9 → 74,15 |
// TODO: move to the kernel space |
// page_mapping_insert(AS_KERNEL, 0xffff0000, 0x00000000, flags); |
// TODO: remove when aux_printf not needed |
page_mapping_insert(AS_KERNEL, 0x10000000, 0x10000000, flags); |
// page_mapping_insert(AS_KERNEL, 0x0000000, 0x0000000, flags); |
page_mapping_insert(AS_KERNEL, 0x1000000, 0x1000000, flags); |
// page_mapping_insert(AS_KERNEL, 0x1100000, 0x1100000, flags); |
// page_mapping_insert(AS_KERNEL, 0x1500000, 0x1500000, flags); |
// page_mapping_insert(AS_KERNEL, 0x1600000, 0x1600000, flags); |
// page_mapping_insert(AS_KERNEL, 0xffff0000, 0xffff0000, flags); |
as_switch(NULL, AS_KERNEL); |
} |
/branches/arm/kernel/arch/arm32/src/drivers/gxemul.c |
---|
79,7 → 79,7 |
/** Initializes #gxemul_hw_map. */ |
void machine_hw_map_init(void) |
void gxemul_hw_map_init(void) |
{ |
gxemul_hw_map.videoram = hw_map(GXEMUL_VIDEORAM, PAGE_SIZE); |
gxemul_hw_map.kbd = hw_map(GXEMUL_KBD, PAGE_SIZE); |
143,8 → 143,7 |
ch = '\n'; |
if (ch == 0x7f) |
ch = '\b'; |
//chardev_push_character(&console, ch); |
printf("%c", ch); |
chardev_push_character(&console, ch); |
} |
} |
254,8 → 253,7 |
* Release the lock, call clock() and reacquire the lock again. |
*/ |
spinlock_unlock(&irq->lock); |
//clock(); |
puts(" "); |
// clock(); |
spinlock_lock(&irq->lock); |
/* acknowledge tick */ |
293,7 → 291,9 |
} |
void gxemul_debug_putc(char ch) { |
*((volatile char *) GXEMUL_KBD) = ch; |
// *((volatile char *) GXEMUL_KBD) = ch; |
//TODO commented version doesn't work, don't know why (as ?? |
*((char *) gxemul_hw_map.videoram) = ch; |
} |
/** @} |
/branches/arm/kernel/arch/arm32/src/start.S |
---|
31,11 → 31,11 |
.text |
.global kernel_image_start |
.global irq_stack |
.global abort_stack |
.global exc_stack |
.global exc_stack |
.global supervisor_sp |
kernel_image_start: |
ldr sp, =end_stack |
67,12 → 67,7 |
.space TEMP_STACK_SIZE |
end_stack: |
.space 1024 |
irq_stack: |
.space 1024 |
abort_stack: |
.space 1024 |
exc_stack: |
.space 4 |
supervisor_sp: |
.space 4 |