/branches/arm/kernel/arch/arm32/src/exception.c |
---|
33,7 → 33,6 |
* @brief Exception handlers and exception initialization routines. |
*/ |
#include <arch/exception.h> |
#include <arch/debug/print.h> |
#include <arch/memstr.h> |
59,7 → 58,6 |
/** Size of memory block occupied by exception vectors. */ |
#define EXC_VECTORS_SIZE (EXC_VECTORS * 4) |
/** Switches to kernel stack and saves all registers there. |
* |
* Temporary exception stack is used to save a few registers |
67,57 → 65,57 |
*/ |
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\ |
ldr r13, [r13] \n\ |
stmfd r13!, {lr} \n\ |
stmfd r13!, {r0-r12} \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\ |
mov r2, lr \n\ |
stmfd r13!, {r4-r12} \n\ |
mov r1, r13 \n\ |
@following two lines are for debugging \n\ |
mov sp, #0 \n\ |
mov lr, #0 \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:" |
); |
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" |
/* prev mode was usermode */ |
"ldmfd r13!, {r0} \n" |
"ldr r13, =supervisor_sp \n" |
"ldr r13, [r13] \n" |
"stmfd r13!, {lr} \n" |
"stmfd r13!, {r0-r12} \n" |
"stmfd r13!, {r13, lr}^ \n" |
"mrs r0, spsr \n" |
"stmfd r13!, {r0} \n" |
"b 2f \n" |
/* mode was not usermode */ |
"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" |
"mov r3, r13 \n" |
"stmfd r13!, {r2} \n" |
"mov r2, lr \n" |
"stmfd r13!, {r4-r12} \n" |
"mov r1, r13 \n" |
/* the following two lines are for debugging */ |
"mov sp, #0 \n" |
"mov lr, #0 \n" |
"msr cpsr_c, r0 \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:\n" |
); |
} |
/** Returns from exception mode. |
* |
* Previously saved state of registers (including control register) |
125,32 → 123,34 |
*/ |
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: ldmfd r13, {r0-r12, pc}^" |
); |
asm volatile( |
"ldmfd r13!, {r0} \n" |
"msr spsr, r0 \n" |
"and r0, r0, #0x1f \n" |
"cmp r0, #0x10 \n" |
"bne 1f \n" |
/* return to user mode */ |
"ldmfd r13!, {r13, lr}^ \n" |
"b 2f \n" |
/* return to non-user mode */ |
"1:\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" |
"mov r13, r1 \n" |
"mov lr, r2 \n" |
"msr cpsr_c, r0 \n" |
/* actual return */ |
"2:\n" |
"ldmfd r13, {r0-r12, pc}^\n" |
); |
} |
159,7 → 159,7 |
* |
* The default mode for interrupt servicing (Interrupt Mode) |
* can not be used because of nested interrupts (which can occur |
* because interrupt are enabled in higher levels of interrupt handler). |
* because interrupts are enabled in higher levels of interrupt handler). |
*/ |
inline static void switch_to_irq_servicing_mode() |
{ |
187,7 → 187,6 |
); |
} |
/** Calls exception dispatch routine. */ |
#define CALL_EXC_DISPATCH(exception) \ |
asm("mov r0, %0" : : "i" (exception)); \ |
194,7 → 193,6 |
asm("mov r1, r13"); \ |
asm("bl exc_dispatch"); |
/** General exception handler. |
* |
* Stores registers, dispatches the exception, |
207,7 → 205,6 |
CALL_EXC_DISPATCH(exception) \ |
load_regs(); |
/** Updates specified exception vector to jump to given handler. |
* |
* Addresses of handlers are stored in memory following exception vectors. |
227,7 → 224,6 |
} |
/** Low-level Reset Exception handler. */ |
static void reset_exception_entry() |
{ |
234,7 → 230,6 |
PROCESS_EXCEPTION(EXC_RESET); |
} |
/** Low-level Software Interrupt Exception handler. */ |
static void swi_exception_entry() |
{ |
241,7 → 236,6 |
PROCESS_EXCEPTION(EXC_SWI); |
} |
/** Low-level Undefined Instruction Exception handler. */ |
static void undef_instr_exception_entry() |
{ |
248,7 → 242,6 |
PROCESS_EXCEPTION(EXC_UNDEF_INSTR); |
} |
/** Low-level Fast Interrupt Exception handler. */ |
static void fiq_exception_entry() |
{ |
255,7 → 248,6 |
PROCESS_EXCEPTION(EXC_FIQ); |
} |
/** Low-level Prefetch Abort Exception handler. */ |
static void prefetch_abort_exception_entry() |
{ |
263,7 → 255,6 |
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT); |
} |
/** Low-level Data Abort Exception handler. */ |
static void data_abort_exception_entry() |
{ |
271,7 → 262,6 |
PROCESS_EXCEPTION(EXC_DATA_ABORT); |
} |
/** Low-level Interrupt Exception handler. |
* |
* CPU is switched to Undefined mode before further interrupt processing |
290,7 → 280,6 |
load_regs(); |
} |
/** Software Interrupt handler. |
* |
* Dispatches the syscall. |
302,18 → 291,13 |
istate->r1, istate->r2, istate->r3, istate->r4, istate->pc); |
*/ |
istate->r0 = syscall_handler( |
istate->r0, |
istate->r1, |
istate->r2, |
istate->r3, |
istate->r4); |
istate->r0 = syscall_handler(istate->r0, istate->r1, istate->r2, |
istate->r3, istate->r4); |
} |
/** Interrupt Exception handler. |
* |
* Determines the sources of interrupt, and calls their handlers. |
* Determines the sources of interrupt and calls their handlers. |
*/ |
static void irq_exception(int exc_no, istate_t *istate) |
{ |
320,49 → 304,46 |
machine_irq_exception(exc_no, istate); |
} |
/** Fills exception vectors with appropriate exception handlers. */ |
void install_exception_handlers(void) |
{ |
install_handler((unsigned)reset_exception_entry, |
(unsigned*)EXC_RESET_VEC); |
install_handler((unsigned) reset_exception_entry, |
(unsigned *) EXC_RESET_VEC); |
install_handler((unsigned)undef_instr_exception_entry, |
(unsigned*)EXC_UNDEF_INSTR_VEC); |
install_handler((unsigned) undef_instr_exception_entry, |
(unsigned *) EXC_UNDEF_INSTR_VEC); |
install_handler((unsigned)swi_exception_entry, |
(unsigned*)EXC_SWI_VEC); |
install_handler((unsigned) swi_exception_entry, |
(unsigned *) EXC_SWI_VEC); |
install_handler((unsigned)prefetch_abort_exception_entry, |
(unsigned*)EXC_PREFETCH_ABORT_VEC); |
install_handler((unsigned) prefetch_abort_exception_entry, |
(unsigned *) EXC_PREFETCH_ABORT_VEC); |
install_handler((unsigned)data_abort_exception_entry, |
(unsigned*)EXC_DATA_ABORT_VEC); |
install_handler((unsigned) data_abort_exception_entry, |
(unsigned *) EXC_DATA_ABORT_VEC); |
install_handler((unsigned)irq_exception_entry, |
(unsigned*)EXC_IRQ_VEC); |
install_handler((unsigned) irq_exception_entry, |
(unsigned *) EXC_IRQ_VEC); |
install_handler((unsigned)fiq_exception_entry, |
(unsigned*)EXC_FIQ_VEC); |
(unsigned *) EXC_FIQ_VEC); |
} |
#ifdef HIGH_EXCEPTION_VECTORS |
/** Activates use of high exception vectors addresses. */ |
static void high_vectors() |
static void high_vectors(void) |
{ |
uint32_t control_reg; |
asm volatile( "mrc p15, 0, %0, c1, c1": "=r" (control_reg)); |
asm volatile("mrc p15, 0, %0, c1, c1" : "=r" (control_reg)); |
//switch on the high vectors bit |
/* switch on the high vectors bit */ |
control_reg |= CP15_R1_HIGH_VECTORS_BIT; |
asm volatile( "mcr p15, 0, %0, c1, c1" : : "r" (control_reg)); |
asm volatile("mcr p15, 0, %0, c1, c1" : : "r" (control_reg)); |
} |
#endif |
/** Initializes exception handling. |
* |
* Installs low-level exception handlers and then registers |
376,12 → 357,12 |
install_exception_handlers(); |
exc_register(EXC_IRQ, "interrupt", (iroutine) irq_exception); |
exc_register(EXC_PREFETCH_ABORT, "prefetch abort", (iroutine) prefetch_abort); |
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); |
} |
/** Prints #istate_t structure content. |
* |
* @param istate Structure to be printed. |
391,17 → 372,16 |
dprintf("istate dump:\n"); |
dprintf(" r0: %x r1: %x r2: %x r3: %x\n", |
istate->r0, istate->r1, istate->r2, istate->r3); |
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); |
istate->r4, istate->r5, istate->r6, istate->r7); |
dprintf(" r8: %x r8: %x r10: %x r11: %x\n", |
istate->r8, istate->r9, istate->r10, istate->r11); |
istate->r8, istate->r9, istate->r10, istate->r11); |
dprintf(" r12: %x sp: %x lr: %x spsr: %x\n", |
istate->r12, istate->sp, istate->lr, istate->spsr); |
istate->r12, istate->sp, istate->lr, istate->spsr); |
dprintf(" pc: %x\n", istate->pc); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/asm.S |
---|
96,4 → 96,3 |
memcpy_to_uspace_failover_address: |
mov r0, #0 |
ldmia sp!, {r4, pc} |
/branches/arm/kernel/arch/arm32/src/console.c |
---|
33,18 → 33,15 |
* @brief Console. |
*/ |
#include <console/console.h> |
#include <arch/console.h> |
#include <arch/machine.h> |
void console_init(devno_t devno) |
{ |
machine_console_init(devno); |
} |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
51,7 → 48,6 |
machine_grab_console(); |
} |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
58,6 → 54,5 |
machine_release_console(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/arm32.c |
---|
33,7 → 33,6 |
* @brief ARM32 architecture specific functions. |
*/ |
#include <arch.h> |
#include <arch/boot.h> |
#include <config.h> |
53,7 → 52,6 |
/** Information about loaded tasks. */ |
bootinfo_t bootinfo; |
/** Performs arm32 specific initialization before main_bsp() is called. */ |
void arch_pre_main(void) |
{ |
68,7 → 66,6 |
} |
/** Performs arm32 specific initialization before mm is initialized. */ |
void arch_pre_mm_init(void) |
{ |
76,13 → 73,12 |
interrupts_disable(); |
} |
/** Performs arm32 specific initialization afterr mm is initialized. */ |
void arch_post_mm_init(void) |
{ |
machine_hw_map_init(); |
/* Initialize dispatch table */ |
/* Initialize exception dispatch table */ |
exception_init(); |
interrupt_init(); |
94,7 → 90,6 |
#endif |
} |
/** Performs arm32 specific tasks needed after cpu is initialized. |
* |
* Currently the function is empty. |
137,10 → 132,12 |
*/ |
void before_thread_runs_arch(void) |
{ |
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA]; |
uint8_t *stck; |
stck = &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]; |
supervisor_sp = (uintptr_t) stck; |
} |
/** Performs arm32 specific tasks before a thread stops running. |
* |
* Currently the function is empty. |
149,7 → 146,6 |
{ |
} |
/** Halts CPU. */ |
void cpu_halt(void) |
{ |
158,17 → 154,3 |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/context.S |
---|
1,5 → 1,5 |
# |
# Copyright (c) 2003-2004 Jakub Jermar, 2007 Petr Stepan |
# Copyright (c) 2007 Petr Stepan |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
57,4 → 57,3 |
mov r0, #0 |
mov pc, lr |
/branches/arm/kernel/arch/arm32/src/debug/print.c |
---|
33,12 → 33,10 |
* @brief Debug print functions. |
*/ |
#include <printf/printf_core.h> |
#include <arch/debug/print.h> |
#include <arch/machine.h> |
/** Prints a character to the console. |
* |
* @param ch Character to be printed. |
48,7 → 46,6 |
machine_debug_putc(ch); |
} |
/** Prints a string to the console. |
* |
* @param str String to be printed. |
66,7 → 63,6 |
return i; |
} |
/** Prints a formated string. |
* |
* @param fmt "Printf-like" format. |
76,7 → 72,10 |
va_list args; |
va_start (args, fmt); |
struct printf_spec ps = { (int(*)(void *, size_t, void *)) debug_write, NULL }; |
struct printf_spec ps = { |
(int (*)(void *, size_t, void *)) debug_write, |
NULL |
}; |
printf_core(fmt, &ps, args); |
va_end(args); |
88,7 → 87,7 |
*/ |
void debug_puts(const char *str) |
{ |
while ( *str ) { |
while (*str) { |
putc(*str); |
str++; |
} |
/branches/arm/kernel/arch/arm32/src/cpu/cpu.c |
---|
38,28 → 38,28 |
#include <arch.h> |
#include <print.h> |
/** Number of indexes left out in the #imp_data array */ |
#define IMP_DATA_START_OFFSET 0x40 |
/** Implementators (vendor) names */ |
static char * imp_data[] = { |
"?", /* IMP_DATA_START_OFFSET */ |
"ARM Ltd", /* 0x41 */ |
"", /* 0x42 */ |
"", /* 0x43 */ |
"Digital Equipment Corporation", /* 0x44 */ |
"", "", "", "", "", "", "", "", "", "", "", /* 0x4f */ |
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0x5f */ |
"", "", "", "", "", "", "", "", "", /* 0x68 */ |
"Intel Corporation" /* 0x69 */ |
static char *imp_data[] = { |
"?", /* IMP_DATA_START_OFFSET */ |
"ARM Ltd", /* 0x41 */ |
"", /* 0x42 */ |
"", /* 0x43 */ |
"Digital Equipment Corporation", /* 0x44 */ |
"", "", "", "", "", "", "", "", "", "", /* 0x45 - 0x4e */ |
"", "", "", "", "", "", "", "", "", "", /* 0x4f - 0x58 */ |
"", "", "", "", "", "", "", "", "", "", /* 0x59 - 0x62 */ |
"", "", "", "", "", "", /* 0x63 - 0x68 */ |
"Intel Corporation" /* 0x69 */ |
}; |
/** Length of the #imp_data array */ |
static int imp_data_length = sizeof(imp_data)/sizeof(char *); |
static int imp_data_length = sizeof(imp_data) / sizeof(char *); |
/** Architecture names */ |
static char * arch_data[] = { |
static char *arch_data[] = { |
"?", /* 0x0 */ |
"4", /* 0x1 */ |
"4T", /* 0x2 */ |
71,7 → 71,7 |
}; |
/** Length of the #arch_data array */ |
static int arch_data_length = sizeof(arch_data)/sizeof(char *); |
static int arch_data_length = sizeof(arch_data) / sizeof(char *); |
/** Retrieves processor identification from CP15 register 0. |
78,11 → 78,11 |
* |
* @param cpu Structure for storing CPU identification. |
*/ |
static void arch_cpu_identify(cpu_arch_t * cpu) |
static void arch_cpu_identify(cpu_arch_t *cpu) |
{ |
uint32_t ident; |
asm volatile ( |
"mrc p15, 0, %0, c0, c0, 0 \n" |
"mrc p15, 0, %0, c0, c0, 0\n" |
: "=r" (ident) |
); |
93,13 → 93,11 |
cpu->rev_num = (ident << 28) >> 28; |
} |
/** Does nothing on ARM. */ |
void cpu_arch_init(void) |
{ |
} |
/** Retrieves processor identification and stores it to #CPU.arch */ |
void cpu_identify(void) |
{ |
106,7 → 104,6 |
arch_cpu_identify(&CPU->arch); |
} |
/** Prints CPU identification. */ |
void cpu_print_report(cpu_t *m) |
{ |
114,16 → 111,20 |
char * architecture = arch_data[0]; |
cpu_arch_t * cpu_arch = &m->arch; |
if ( (cpu_arch->imp_num) > 0 && (cpu_arch->imp_num < (imp_data_length + IMP_DATA_START_OFFSET)) ) { |
if ((cpu_arch->imp_num) > 0 && |
(cpu_arch->imp_num < (imp_data_length + IMP_DATA_START_OFFSET))) { |
vendor = imp_data[cpu_arch->imp_num - IMP_DATA_START_OFFSET]; |
} |
if ( (cpu_arch->arch_num) > 0 && (cpu_arch->arch_num < arch_data_length) ) { |
if ((cpu_arch->arch_num) > 0 && |
(cpu_arch->arch_num < arch_data_length)) { |
architecture = arch_data[cpu_arch->arch_num]; |
} |
printf("cpu%d: vendor=%s, architecture=ARM %s, part number=%x, variant=%x, revision=%x\n", |
m->id, vendor, architecture, cpu_arch->prim_part_num, cpu_arch->variant_num, cpu_arch->rev_num); |
printf("cpu%d: vendor=%s, architecture=ARM%s, part number=%x, " |
"variant=%x, revision=%x\n", |
m->id, vendor, architecture, cpu_arch->prim_part_num, |
cpu_arch->variant_num, cpu_arch->rev_num); |
} |
/** @} |
/branches/arm/kernel/arch/arm32/src/mm/tlb.c |
---|
48,11 → 48,10 |
asm volatile ( |
"eor r1, r1\n" |
"mcr p15, 0, r1, c8, c7, 0\n" |
::: "r1" |
: : : "r1" |
); |
} |
/** Invalidate all entries in TLB that belong to specified address space. |
* |
* @param asid Ignored as the ARM architecture doesn't support ASIDs. |
62,7 → 61,6 |
tlb_invalidate_all(); |
} |
/** Invalidate single entry in TLB |
* |
* @param page Virtual adress of the page |
70,15 → 68,14 |
static inline void invalidate_page(uintptr_t page) |
{ |
asm volatile ( |
"mcr p15, 0, %0, c8, c7, 1" |
"mcr p15, 0, %0, c8, c7, 1" |
: |
: "r"(page) |
: "r" (page) |
); |
} |
/** Invalidate TLB entries for specified page range belonging to specified address space. |
/** Invalidate TLB entries for specified page range belonging to specified |
* address space. |
* |
* @param asid Ignored as the ARM architecture doesn't support it. |
* @param page Address of the first page whose entry is to be invalidated. |
/branches/arm/kernel/arch/arm32/src/mm/as.c |
---|
48,6 → 48,5 |
as_operations = &as_pt_operations; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/page_fault.c |
---|
1,213 → 1,212 |
/* |
* Copyright (c) 2007 Pavel Jancik, Michal Kebrt |
* 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 arm32mm |
* @{ |
*/ |
/** @file |
* @brief Page fault related functions. |
*/ |
#include <panic.h> |
#include <arch/exception.h> |
#include <arch/debug/print.h> |
#include <arch/mm/page_fault.h> |
#include <mm/as.h> |
#include <genarch/mm/page_pt.h> |
#include <arch.h> |
#include <interrupt.h> |
/** Returns value stored in fault status register. |
* |
* @return Value stored in CP15 fault status register (FSR). |
*/ |
static inline fault_status_t read_fault_status_register(void) |
{ |
fault_status_union_t fsu; |
// fault status is stored in CP15 register 5 |
asm volatile ( |
"mrc p15, 0, %0, c5, c0, 0" |
: "=r"(fsu.dummy) |
); |
return fsu.fs; |
} |
/** Returns FAR (fault address register) content. |
* |
* @return FAR (fault address register) content (address that caused a page fault) |
*/ |
static inline uintptr_t read_fault_address_register(void) |
{ |
uintptr_t ret; |
// fault adress is stored in CP15 register 6 |
asm volatile ( |
"mrc p15, 0, %0, c6, c0, 0" |
: "=r"(ret) |
); |
return ret; |
} |
/** Decides whether the instruction is load/store or not. |
* |
* @param instr Instruction |
* |
* @return true when instruction is load/store, false otherwise |
*/ |
static inline bool is_load_store_instruction(instruction_t instr) |
{ |
// load store immediate offset |
if (instr.type == 0x2) { |
return true; |
} |
// load store register offset |
if (instr.type == 0x3 && instr.bit4 == 0) { |
return true; |
} |
// load store multiple |
if (instr.type == 0x4) { |
return true; |
} |
// coprocessor load/store |
if (instr.type == 0x6) { |
return true; |
} |
return false; |
} |
/** Decides whether the instructions is swap or not. |
* |
* @param instr Instruction |
* |
* @return true when instruction is swap, false otherwise |
*/ |
static inline bool is_swap_instruction(instruction_t instr) |
{ |
// swap, swapb instruction |
if (instr.type == 0x0 && |
(instr.opcode == 0x8 || instr.opcode == 0xa) && |
instr.access == 0x0 && instr.bits567 == 0x4 && instr.bit4 == 1) { |
return true; |
} |
return false; |
} |
/** 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. |
* |
* @return Type of access into memory, PF_ACCESS_EXEC if no memory access is requested. |
*/ |
static pf_access_t get_memory_access_type(uint32_t instr_addr, uintptr_t badvaddr) |
{ |
instruction_union_t instr_union; |
instr_union.pc = instr_addr; |
instruction_t instr = *(instr_union.instr); |
// undefined instructions |
if (instr.condition == 0xf) { |
panic("page_fault - instruction doesn't access memory (instr_code: %x, badvaddr:%x)", |
instr, badvaddr); |
return PF_ACCESS_EXEC; |
} |
// load store instructions |
if (is_load_store_instruction(instr)) { |
if (instr.access == 1) { |
return PF_ACCESS_READ; |
} else { |
return PF_ACCESS_WRITE; |
} |
} |
// swap, swpb instruction |
if (is_swap_instruction(instr)) { |
return PF_ACCESS_WRITE; |
} |
panic("page_fault - instruction doesn't access memory (instr_code: %x, badvaddr:%x)", |
instr, badvaddr); |
return PF_ACCESS_EXEC; |
} |
/** Handles "data abort" exception (load or store at invalid address). |
* |
* @param exc_no Exception number. |
* @param istate CPU state when exception occured. |
*/ |
void data_abort(int exc_no, istate_t *istate) |
{ |
fault_status_t fsr = read_fault_status_register(); |
uintptr_t badvaddr = read_fault_address_register(); |
pf_access_t access = get_memory_access_type(istate->pc, badvaddr); |
int ret = as_page_fault(badvaddr, access, istate); |
if (ret == AS_PF_FAULT) { |
print_istate(istate); |
dprintf("page fault - pc: %x, va: %x, status: %x(%x), access:%d\n", |
istate->pc, badvaddr, fsr.status, fsr, access); |
fault_if_from_uspace(istate, "Page fault: %#x", badvaddr); |
panic("page fault\n"); |
} |
} |
/** Handles "prefetch abort" exception (instruction couldn't be executed). |
* |
* @param exc_no Exception number. |
* @param istate CPU state when exception occured. |
*/ |
void prefetch_abort(int exc_no, istate_t *istate) |
{ |
int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate); |
if (ret == AS_PF_FAULT) { |
dprintf("prefetch_abort\n"); |
print_istate(istate); |
panic("page fault - prefetch_abort at address: %x\n", istate->pc); |
} |
} |
/** @} |
*/ |
/* |
* Copyright (c) 2007 Pavel Jancik, Michal Kebrt |
* 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 arm32mm |
* @{ |
*/ |
/** @file |
* @brief Page fault related functions. |
*/ |
#include <panic.h> |
#include <arch/exception.h> |
#include <arch/debug/print.h> |
#include <arch/mm/page_fault.h> |
#include <mm/as.h> |
#include <genarch/mm/page_pt.h> |
#include <arch.h> |
#include <interrupt.h> |
/** Returns value stored in fault status register. |
* |
* @return Value stored in CP15 fault status register (FSR). |
*/ |
static inline fault_status_t read_fault_status_register(void) |
{ |
fault_status_union_t fsu; |
/* fault status is stored in CP15 register 5 */ |
asm volatile ( |
"mrc p15, 0, %0, c5, c0, 0" |
: "=r"(fsu.dummy) |
); |
return fsu.fs; |
} |
/** Returns FAR (fault address register) content. |
* |
* @return FAR (fault address register) content (address that caused a page |
* fault) |
*/ |
static inline uintptr_t read_fault_address_register(void) |
{ |
uintptr_t ret; |
/* fault adress is stored in CP15 register 6 */ |
asm volatile ( |
"mrc p15, 0, %0, c6, c0, 0" |
: "=r"(ret) |
); |
return ret; |
} |
/** Decides whether the instruction is load/store or not. |
* |
* @param instr Instruction |
* |
* @return true when instruction is load/store, false otherwise |
*/ |
static inline bool is_load_store_instruction(instruction_t instr) |
{ |
/* load store immediate offset */ |
if (instr.type == 0x2) { |
return true; |
} |
/* load store register offset */ |
if (instr.type == 0x3 && instr.bit4 == 0) { |
return true; |
} |
/* load store multiple */ |
if (instr.type == 0x4) { |
return true; |
} |
/* oprocessor load/store */ |
if (instr.type == 0x6) { |
return true; |
} |
return false; |
} |
/** Decides whether the instruction is swap or not. |
* |
* @param instr Instruction |
* |
* @return true when instruction is swap, false otherwise |
*/ |
static inline bool is_swap_instruction(instruction_t instr) |
{ |
/* swap, swapb instruction */ |
if (instr.type == 0x0 && |
(instr.opcode == 0x8 || instr.opcode == 0xa) && |
instr.access == 0x0 && instr.bits567 == 0x4 && instr.bit4 == 1) { |
return true; |
} |
return false; |
} |
/** 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. |
* |
* @return Type of access into memory, PF_ACCESS_EXEC if no memory access is |
* requested. |
*/ |
static pf_access_t get_memory_access_type(uint32_t instr_addr, |
uintptr_t badvaddr) |
{ |
instruction_union_t instr_union; |
instr_union.pc = instr_addr; |
instruction_t instr = *(instr_union.instr); |
/* undefined instructions */ |
if (instr.condition == 0xf) { |
panic("page_fault - instruction doesn't access memory " |
"(instr_code: %x, badvaddr:%x)", instr, badvaddr); |
return PF_ACCESS_EXEC; |
} |
/* load store instructions */ |
if (is_load_store_instruction(instr)) { |
if (instr.access == 1) { |
return PF_ACCESS_READ; |
} else { |
return PF_ACCESS_WRITE; |
} |
} |
/* swap, swpb instruction */ |
if (is_swap_instruction(instr)) { |
return PF_ACCESS_WRITE; |
} |
panic("page_fault - instruction doesn't access memory " |
"(instr_code: %x, badvaddr:%x)", instr, badvaddr); |
return PF_ACCESS_EXEC; |
} |
/** Handles "data abort" exception (load or store at invalid address). |
* |
* @param exc_no Exception number. |
* @param istate CPU state when exception occured. |
*/ |
void data_abort(int exc_no, istate_t *istate) |
{ |
fault_status_t fsr = read_fault_status_register(); |
uintptr_t badvaddr = read_fault_address_register(); |
pf_access_t access = get_memory_access_type(istate->pc, badvaddr); |
int ret = as_page_fault(badvaddr, access, istate); |
if (ret == AS_PF_FAULT) { |
print_istate(istate); |
dprintf("page fault - pc: %x, va: %x, status: %x(%x), " |
"access:%d\n", istate->pc, badvaddr, fsr.status, fsr, |
access); |
fault_if_from_uspace(istate, "Page fault: %#x", badvaddr); |
panic("page fault\n"); |
} |
} |
/** Handles "prefetch abort" exception (instruction couldn't be executed). |
* |
* @param exc_no Exception number. |
* @param istate CPU state when exception occured. |
*/ |
void prefetch_abort(int exc_no, istate_t *istate) |
{ |
int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate); |
if (ret == AS_PF_FAULT) { |
dprintf("prefetch_abort\n"); |
print_istate(istate); |
panic("page fault - prefetch_abort at address: %x\n", |
istate->pc); |
} |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/frame.c |
---|
44,25 → 44,24 |
/** Creates memory zones. */ |
void frame_arch_init(void) |
{ |
// all memory as one zone |
zone_create(0, ADDR2PFN(config.memory_size), |
BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0); |
/* all memory as one zone */ |
zone_create(0, ADDR2PFN(config.memory_size), |
BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0); |
last_frame = config.memory_size; |
// blacklist boot page table |
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME, BOOT_PAGE_TABLE_SIZE_IN_FRAMES); |
/* blacklist boot page table */ |
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME, |
BOOT_PAGE_TABLE_SIZE_IN_FRAMES); |
} |
/** Frees the boot page table. */ |
void boot_page_table_free(void) |
{ |
int i; |
for (i = 0; i < BOOT_PAGE_TABLE_SIZE_IN_FRAMES; ++i) { |
frame_free (i * FRAME_SIZE + BOOT_PAGE_TABLE_ADDRESS); |
for (i = 0; i < BOOT_PAGE_TABLE_SIZE_IN_FRAMES; i++) { |
frame_free(i * FRAME_SIZE + BOOT_PAGE_TABLE_ADDRESS); |
} |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/memory_init.c |
---|
46,6 → 46,5 |
return machine_get_memory_size(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/page.c |
---|
44,7 → 44,6 |
#include <interrupt.h> |
#include <arch/mm/frame.h> |
/** Initializes page tables. |
* |
* 1:1 virtual-physical mapping is created in kernel address space. Mapping |
59,18 → 58,18 |
flags = PAGE_CACHEABLE; |
// PA2KA(identity) mapping for all frames until last_frame |
/* PA2KA(identity) mapping for all frames until last_frame */ |
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) { |
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags); |
} |
// create mapping for exception table at high offset |
#ifdef HIGH_EXCEPTION_VECTORS |
void *virtaddr = frame_alloc(ONE_FRAME, FRAME_KA); |
page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr), flags); |
#else |
#error "Only high exception vector supported now" |
#endif |
/* create mapping for exception table at high offset */ |
#ifdef HIGH_EXCEPTION_VECTORS |
void *virtaddr = frame_alloc(ONE_FRAME, FRAME_KA); |
page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr), flags); |
#else |
#error "Only high exception vector supported now" |
#endif |
as_switch(NULL, AS_KERNEL); |
89,15 → 88,18 |
*/ |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) { |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > |
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) { |
panic("Unable to map physical memory %p (%d bytes)", |
physaddr, size) |
} |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) { |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), |
PAGE_NOT_CACHEABLE | PAGE_READ | PAGE_WRITE | PAGE_KERNEL); |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), |
physaddr + PFN2ADDR(i), |
PAGE_NOT_CACHEABLE | PAGE_READ | PAGE_WRITE | PAGE_KERNEL); |
} |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
104,7 → 106,5 |
return virtaddr; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/panic.S |
---|
33,4 → 33,3 |
panic_printf: |
bl debug_printf |
bl cpu_halt |
/branches/arm/kernel/arch/arm32/src/userspace.c |
---|
35,7 → 35,6 |
#include <userspace.h> |
/** Struct for holding all general purpose registers. |
* |
* Used to set registers when going to userspace. |
59,50 → 58,48 |
uint32_t pc; |
} ustate_t; |
/** Changes processor mode and jumps to the address specified in the first parameter. |
/** 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 |
/* 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; |
/* 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 |
/* set user stack */ |
ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + PAGE_SIZE; |
// set where uspace execution starts |
/* set where uspace execution starts */ |
ustate.pc = (uintptr_t) kernel_uarg->uspace_entry; |
// status register in user mode |
ipl_t user_mode = current_status_reg_read() & (~STATUS_REG_MODE_MASK | USER_MODE); |
/* status register in user mode */ |
ipl_t user_mode = current_status_reg_read() & |
(~STATUS_REG_MODE_MASK | USER_MODE); |
// set user mode, set registers, jump |
asm __volatile__ ( |
"mov r0, %0 \n" |
"msr spsr_c, %1 \n" |
"ldmfd r0!, {r0-r12, sp, lr}^ \n" |
"ldmfd r0!, {pc}^" |
/* set user mode, set registers, jump */ |
asm volatile ( |
"mov r0, %0 \n" |
"msr spsr_c, %1 \n" |
"ldmfd r0!, {r0-r12, sp, lr}^ \n" |
"ldmfd r0!, {pc}^\n" |
: |
: "r"(&ustate), "r"(user_mode) |
: "r" (&ustate), "r" (user_mode) |
: "r0", "r1" |
); |
// unreachable |
while(1) ; |
/* unreachable */ |
while(1) |
; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/interrupt.c |
---|
42,7 → 42,6 |
/** Initial size of a table holding interrupt handlers. */ |
#define IRQ_COUNT 8 |
/** Disable interrupts. |
* |
* @return Old interrupt priority level. |
56,7 → 55,6 |
return ipl; |
} |
/** Enable interrupts. |
* |
* @return Old interrupt priority level. |
70,7 → 68,6 |
return ipl; |
} |
/** Restore interrupt priority level. |
* |
* @param ipl Saved interrupt priority level. |
78,12 → 75,10 |
void interrupts_restore(ipl_t ipl) |
{ |
current_status_reg_control_write( |
(current_status_reg_read() & ~STATUS_REG_IRQ_DISABLED_BIT) | |
(ipl & STATUS_REG_IRQ_DISABLED_BIT) |
); |
(current_status_reg_read() & ~STATUS_REG_IRQ_DISABLED_BIT) | |
(ipl & STATUS_REG_IRQ_DISABLED_BIT)); |
} |
/** Read interrupt priority level. |
* |
* @return Current interrupt priority level. |
93,7 → 88,6 |
return current_status_reg_read(); |
} |
/** Initialize basic tables for exception dispatching |
* and starts the timer. |
*/ |
103,6 → 97,5 |
machine_timer_irq_start(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/drivers/gxemul.c |
---|
45,7 → 45,6 |
#include <arch/machine.h> |
#include <arch/debug/print.h> |
/* Addresses of devices. */ |
#define GXEMUL_VIDEORAM 0x10000000 |
#define GXEMUL_KBD 0x10000000 |
60,7 → 59,6 |
#define GXEMUL_MP_MEMSIZE_OFFSET 0x0090 |
#define GXEMUL_FB 0x12000000 |
/* IRQs */ |
#define GXEMUL_KBD_IRQ 2 |
#define GXEMUL_TIMER_IRQ 4 |
88,7 → 86,7 |
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
return *(uint32_t*) gxemul_hw_map.irqc; |
return *((uint32_t *) gxemul_hw_map.irqc); |
} |
98,7 → 96,7 |
*/ |
static inline void gxemul_irqc_mask(uint32_t irq) |
{ |
*(uint32_t*) gxemul_hw_map.irqc_mask = irq; |
*((uint32_t *) gxemul_hw_map.irqc_mask) = irq; |
} |
108,7 → 106,7 |
*/ |
static inline void gxemul_irqc_unmask(uint32_t irq) |
{ |
*(uint32_t*) gxemul_hw_map.irqc_unmask = irq; |
*((uint32_t *) gxemul_hw_map.irqc_unmask) = irq; |
} |
123,7 → 121,8 |
gxemul_hw_map.rtc_freq = gxemul_hw_map.rtc + GXEMUL_RTC_FREQ_OFFSET; |
gxemul_hw_map.rtc_ack = gxemul_hw_map.rtc + GXEMUL_RTC_ACK_OFFSET; |
gxemul_hw_map.irqc_mask = gxemul_hw_map.irqc + GXEMUL_IRQC_MASK_OFFSET; |
gxemul_hw_map.irqc_unmask = gxemul_hw_map.irqc + GXEMUL_IRQC_UNMASK_OFFSET; |
gxemul_hw_map.irqc_unmask = gxemul_hw_map.irqc + |
GXEMUL_IRQC_UNMASK_OFFSET; |
hw_map_init_called = true; |
} |
139,7 → 138,6 |
*((char *) gxemul_hw_map.videoram) = ch; |
} |
/** Enables gxemul keyboard (interrupt unmasked). |
* |
* @param dev Not used. |
151,7 → 149,6 |
gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
} |
/** Disables gxemul keyboard (interrupt masked). |
* |
* @param dev not used |
163,7 → 160,6 |
gxemul_irqc_mask(GXEMUL_KBD_IRQ); |
} |
/** Read character using polling, assume interrupts disabled. |
* |
* @param dev Not used. |
184,7 → 180,6 |
} |
} |
/** Process keyboard interrupt. |
* |
* @param irq IRQ information. |
208,7 → 203,6 |
} |
} |
static irq_ownership_t gxemul_claim(void) |
{ |
return IRQ_ACCEPT; |
225,7 → 219,6 |
interrupts_restore(ipl); |
} |
/** Return console to userspace. */ |
void gxemul_release_console(void) |
{ |
238,7 → 231,6 |
interrupts_restore(ipl); |
} |
/** Initializes console object representing gxemul console. |
* |
* @param devno device number. |
264,8 → 256,6 |
sysinfo_set_item_val("kbd.address.virtual", NULL, gxemul_hw_map.kbd); |
} |
/** Starts gxemul Real Time Clock device, which asserts regular interrupts. |
* |
* @param frequency Interrupts frequency (0 disables RTC). |
272,16 → 262,14 |
*/ |
static void gxemul_timer_start(uint32_t frequency) |
{ |
*(uint32_t*) gxemul_hw_map.rtc_freq = frequency; |
*((uint32_t*) gxemul_hw_map.rtc_freq) = frequency; |
} |
static irq_ownership_t gxemul_timer_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
/** Timer interrupt handler. |
* |
* @param irq Interrupt information. |
298,12 → 286,11 |
spinlock_lock(&irq->lock); |
/* acknowledge tick */ |
*(uint32_t*) gxemul_hw_map.rtc_ack = 0; |
*((uint32_t*) gxemul_hw_map.rtc_ack) = 0; |
} |
/** Initializes and registers timer interrupt handler. */ |
static void gxemul_timer_irq_init() |
static void gxemul_timer_irq_init(void) |
{ |
irq_initialize(&gxemul_timer_irq); |
gxemul_timer_irq.devno = device_assign_devno(); |
320,13 → 307,12 |
* Initiates regular timer interrupts after initializing |
* corresponding interrupt handler. |
*/ |
void gxemul_timer_irq_start() |
void gxemul_timer_irq_start(void) |
{ |
gxemul_timer_irq_init(); |
gxemul_timer_start(GXEMUL_TIMER_FREQ); |
} |
/** Returns the size of emulated memory. |
* |
* @return Size in bytes. |
333,10 → 319,9 |
*/ |
size_t gxemul_get_memory_size(void) |
{ |
return *((int*)(GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
return *((int *) (GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
} |
/** Prints a character. |
* |
* @param ch Character to be printed. |
343,7 → 328,7 |
*/ |
void gxemul_debug_putc(char ch) |
{ |
char * addr = 0; |
char *addr = 0; |
if (!hw_map_init_called) { |
addr = (char *) GXEMUL_KBD; |
} else { |
353,7 → 338,6 |
*(addr) = ch; |
} |
/** Stops gxemul. */ |
void gxemul_cpu_halt(void) |
{ |
367,7 → 351,6 |
*(addr + GXEMUL_HALT_OFFSET) = '\0'; |
} |
/** Gxemul specific interrupt exception handler. |
* |
* Determines sources of the interrupt from interrupt controller and |
379,8 → 362,9 |
void gxemul_irq_exception(int exc_no, istate_t *istate) |
{ |
uint32_t sources = gxemul_irqc_get_sources(); |
int i = 0; |
for (; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
int i; |
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
389,7 → 373,8 |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
dprintf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
dprintf("cpu%d: spurious interrupt (inum=%d)\n", |
CPU->id, i); |
} |
} |
} |
/branches/arm/kernel/arch/arm32/src/start.S |
---|
34,7 → 34,6 |
.global exc_stack |
.global supervisor_sp |
kernel_image_start: |
# switch to supervisor mode |