/branches/arm/kernel/arch/arm32/include/exception.h |
---|
91,7 → 91,11 |
} istate_t; |
/** Sets Program Counter member of given istate structure. |
* |
* @param istate istate structure |
* @param retaddr new value of istate's PC member |
*/ |
static inline void istate_set_retaddr(istate_t *istate, uintptr_t retaddr) |
{ |
istate->pc = retaddr; |
98,13 → 102,13 |
} |
/** Return true if exception happened while in userspace. */ |
/** Returns true if exception happened while in userspace. */ |
static inline int istate_from_uspace(istate_t *istate) |
{ |
return (istate->spsr & STATUS_REG_MODE_MASK) == USER_MODE; |
} |
/** Returns Program Counter member of given istate structure. */ |
static inline unative_t istate_get_pc(istate_t *istate) |
{ |
return istate->pc; |
/branches/arm/kernel/arch/arm32/src/exception.c |
---|
56,28 → 56,13 |
extern uintptr_t supervisor_sp; |
extern uintptr_t exc_stack; |
/** Switches to kernel stack and saves all registers there. |
* |
* Temporary exception stack is used to save a few registers |
* before stack switch takes place. |
*/ |
inline static void setup_stack_and_save_regs() |
{ |
/* |
str r0, =exc_stack |
str r1, =exc_stack + 4 |
mrs r0, cpsr |
mrs r1, spsr |
and r0, r0, #0x1f |
and r1, r1, #0x1f |
cmp r0, r1 |
be 3f |
@different exception mode => preserve sp |
ldr r1, [=exc_stack + 4] |
ldr r0, [=exc_stack] |
3: |
mrs r0, spsr |
stmfd sp!, {r0, sp, lr} |
*/ |
asm volatile("ldr r13, =exc_stack \n\ |
stmfd r13!, {r0} \n\ |
mrs r0, spsr \n\ |
128,7 → 113,11 |
); |
} |
/** Returns from exception mode. |
* |
* Previously saved state of registers (including control register) |
* is restored from the stack. |
*/ |
inline static void load_regs() |
{ |
asm volatile( "ldmfd r13!, {r0} \n\ |
159,32 → 148,15 |
); |
} |
/*#define SAVE_REGS_TO_STACK \ |
asm("stmfd r13!, {r0-r12, r13, lr}"); \ |
asm("mrs r14, spsr"); \ |
asm("stmfd r13!, {r14}"); |
*/ |
/** Calls exception dispatch routine. */ |
#define CALL_EXC_DISPATCH(exception) \ |
asm("mov r0, %0" : : "i" (exception)); \ |
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 r13!, {r14}"); \ |
asm("msr spsr, r14"); \ |
asm("ldmfd r13!, {r0-r12, r13, pc}^"); |
*/ |
/** General exception handler. |
* |
* Stores registers, dispatches the exception, |
* and finally restores registers and returns from exception processing. |
* |
195,13 → 167,9 |
CALL_EXC_DISPATCH(exception) \ |
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. |
*/ |
static void install_handler (unsigned handler_addr, unsigned* vector) |
264,7 → 232,12 |
} |
/** Low-level Interrupt Exception handler. */ |
/** Low-level Interrupt Exception handler. |
* |
* CPU is switched to Undefined mode before further interrupt processing |
* because of possible occurence of nested interrupt exception, which |
* would overwrite (and thus spoil) stack pointer. |
*/ |
static void irq_exception_entry() |
{ |
asm("sub lr, lr, #4"); |
274,7 → 247,6 |
asm("stmfd sp!, {r0-r3}"); |
asm("mov r1, sp"); |
asm("mov r2, lr"); |
// asm("mrs r3, spsr"); |
asm("mrs r0, cpsr"); |
asm("bic r0, r0, #0x1f"); |
asm("orr r0, r0, #0x1b"); |
281,7 → 253,6 |
asm("msr cpsr_c, r0"); |
asm("mov sp, r1"); |
asm("mov lr, r2"); |
// asm("msr spsr, r3"); |
asm("ldmfd sp!, {r0-r3}"); |
CALL_EXC_DISPATCH(EXC_IRQ) |
378,37 → 349,9 |
exc_register(EXC_PREFETCH_ABORT, "prefetch abort", (iroutine) prefetch_abort); |
exc_register(EXC_DATA_ABORT, "data abort", (iroutine) data_abort); |
exc_register(EXC_SWI, "software interrupt", (iroutine) swi_exception); |
/* TODO add next */ |
} |
/** Sets stack pointers in all supported exception modes. */ |
void setup_exception_stacks() |
{ |
/* switch to particular mode and set "r13" there */ |
uint32_t cspr = current_status_reg_read(); |
/* 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 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 */ |
current_status_reg_control_write(cspr); |
} |
/** Prints #istate_t structure content. |
* |
* @param istate Structure to be printed. |
/branches/arm/kernel/arch/arm32/src/arm32.c |
---|
50,7 → 50,6 |
#include <userspace.h> |
bootinfo_t bootinfo; |
// // uintptr_t supervisor_sp /*__attribute__ ((section (".text")))*/; |
extern uintptr_t supervisor_sp; |
72,8 → 71,6 |
{ |
/* It is not assumed by default */ |
interrupts_disable(); |
setup_exception_stacks(); |
} |
157,9 → 154,9 |
*/ |
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); |
// 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; |
/branches/arm/kernel/arch/arm32/src/drivers/gxemul.c |
---|
45,7 → 45,7 |
#include <arch/debug/print.h> |
/** Address of devices. */ |
/** Addresses of devices. */ |
#define GXEMUL_VIDEORAM 0x10000000 |
#define GXEMUL_KBD 0x10000000 |
#define GXEMUL_HALT_OFFSET 0x10 |
83,7 → 83,7 |
.read = gxemul_do_read, |
}; |
/** Return the mask of active interrupts. */ |
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
return *(uint32_t*) gxemul_hw_map.irqc; |
238,6 → 238,10 |
return IRQ_ACCEPT; |
} |
/** Timer interrupt handler. |
* |
* @param irq interrupt information |
*/ |
static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
{ |
/* TODO time drifts ?? |
269,8 → 273,7 |
*/ |
} |
/** |
* Initializes and registers timer interrupt handler. |
/** Initializes and registers timer interrupt handler. |
*/ |
static void gxemul_timer_irq_init() |
{ |
283,6 → 286,11 |
irq_register(&gxemul_timer_irq); |
} |
/** Starts timer. |
* |
* Initiates regular timer interrupts after initializing |
* corresponding interrupt handler. |
*/ |
void machine_timer_irq_start() |
{ |
gxemul_timer_irq_init(); |
289,6 → 297,10 |
gxemul_timer_start(GXEMUL_TIMER_FREQ); |
} |
/** Returns the size of emulated memory. |
* |
* @return size in bytes |
*/ |
size_t machine_get_memory_size(void) |
{ |
return *((int*)(GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
306,6 → 318,7 |
*(addr) = ch; |
} |
/** Stops gxemul. */ |
void machine_cpu_halt(void) |
{ |
char * addr = 0; |
318,26 → 331,16 |
*(addr + GXEMUL_HALT_OFFSET) = '\0'; |
} |
/** Gxemul specific interrupt exception handler. |
* |
* Determines sources of the interrupt from interrupt controller and |
* calls high-level handlers for them. |
* |
* @param exc_no interrupt exception number |
* @param istate saved processor state |
*/ |
void machine_irq_exception(int exc_no, istate_t *istate) |
{ |
/* switch to Undefined mode */ |
/* |
asm volatile( |
"stmfd sp!, {r0-r3}\n" |
"mov r1, sp\n" |
"mov r2, lr\n" |
"mrs r3, spsr\n" |
"mrs r0, cpsr\n" |
"bic r0, r0, #0x1f\n" |
"orr r0, r0, #0x1b\n" |
"msr cpsr_c, r0\n" |
"mov sp, r1\n" |
"mov lr, r2\n" |
"msr spsr, r3\n" |
"ldmfd sp!, {r0-r3}\n" |
); |
*/ |
uint32_t sources = gxemul_irqc_get_sources(); |
int i = 0; |
for (; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
353,28 → 356,6 |
} |
} |
} |
/* TODO remove after testing the above code |
noirq = 0; |
if (i == CONSOLE_IRQ) { |
char readchar = *(char*)0x10000000; |
if (readchar == 0) { |
aux_puts("?"); |
} |
else { |
dprintf("%c", readchar); |
} |
} |
else if (i == TIMER_IRQ) { |
dprintf("\n.\n"); |
//acknowledge |
*(uint32_t*)0x15000110 = 0; |
} |
} |
} |
if (noirq) |
aux_puts("IRQ exception without source\n");*/ |
} |