/branches/arm/kernel/arch/arm32/src/machine_func.c |
---|
File deleted |
/branches/arm/kernel/arch/arm32/src/exc_handler.S |
---|
File deleted |
/branches/arm/kernel/arch/arm32/src/mach/testarm/testarm.c |
---|
File deleted |
Property changes: |
Deleted: svn:mergeinfo |
/branches/arm/kernel/arch/arm32/src/mach/integratorcp/integratorcp.c |
---|
File deleted |
/branches/arm/kernel/arch/arm32/src/cpu/cpu.c |
---|
36,30 → 36,30 |
#include <arch/cpu.h> |
#include <cpu.h> |
#include <arch.h> |
#include <print.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 */ |
"", "", "", "", "", "", "", "", "", "", /* 0x45 - 0x4e */ |
"", "", "", "", "", "", "", "", "", "", /* 0x4f - 0x58 */ |
"", "", "", "", "", "", "", "", "", "", /* 0x59 - 0x62 */ |
"", "", "", "", "", "", /* 0x63 - 0x68 */ |
"Intel Corporation" /* 0x69 */ |
static char * imp_data[] = { |
"?", /* IMP_DATA_START_OFFSET */ |
"ARM Ltd", /* 0x41 */ |
"", /* 0x42 */ |
"", /* 0x43 */ |
"Digital Equipment Corporation", /* 0x44 */ |
"", "", "", "", "", "", "", "", "", "", "", /* 0x4f */ |
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0x5f */ |
"", "", "", "", "", "", "", "", "", /* 0x68 */ |
"Intel Corporation" /* 0x69 */ |
}; |
/** Length of the #imp_data array */ |
static unsigned 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 unsigned 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,14 → 78,14 |
* |
* @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, %[ident], c0, c0, 0\n" |
: [ident] "=r" (ident) |
"mrc p15, 0, %0, c0, c0, 0 \n" |
: "=r" (ident) |
); |
cpu->imp_num = ident >> 24; |
cpu->variant_num = (ident << 8) >> 28; |
cpu->arch_num = (ident << 12) >> 28; |
93,11 → 93,13 |
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) |
{ |
104,6 → 106,7 |
arch_cpu_identify(&CPU->arch); |
} |
/** Prints CPU identification. */ |
void cpu_print_report(cpu_t *m) |
{ |
111,20 → 114,16 |
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/drivers/gxemul.c |
---|
0,0 → 1,408 |
/* |
* Copyright (c) 2007 Michal Kebrt, Petr Stepan |
* 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 arm32gxemul |
* @{ |
*/ |
/** @file |
* @brief GXemul drivers. |
*/ |
#include <interrupt.h> |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <arch/drivers/gxemul.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <print.h> |
#include <ddi/device.h> |
#include <mm/page.h> |
#include <arch/machine.h> |
#include <arch/debug/print.h> |
/* Addresses of devices. */ |
#define GXEMUL_VIDEORAM 0x10000000 |
#define GXEMUL_KBD 0x10000000 |
#define GXEMUL_HALT_OFFSET 0x10 |
#define GXEMUL_RTC 0x15000000 |
#define GXEMUL_RTC_FREQ_OFFSET 0x100 |
#define GXEMUL_RTC_ACK_OFFSET 0x110 |
#define GXEMUL_IRQC 0x16000000 |
#define GXEMUL_IRQC_MASK_OFFSET 0x4 |
#define GXEMUL_IRQC_UNMASK_OFFSET 0x8 |
#define GXEMUL_MP 0x11000000 |
#define GXEMUL_MP_MEMSIZE_OFFSET 0x0090 |
#define GXEMUL_FB 0x12000000 |
/* IRQs */ |
#define GXEMUL_KBD_IRQ 2 |
#define GXEMUL_TIMER_IRQ 4 |
static gxemul_hw_map_t gxemul_hw_map; |
static chardev_t console; |
static irq_t gxemul_console_irq; |
static irq_t gxemul_timer_irq; |
static bool hw_map_init_called = false; |
static void gxemul_kbd_enable(chardev_t *dev); |
static void gxemul_kbd_disable(chardev_t *dev); |
static void gxemul_write(chardev_t *dev, const char ch); |
static char gxemul_do_read(chardev_t *dev); |
static chardev_operations_t gxemul_ops = { |
.resume = gxemul_kbd_enable, |
.suspend = gxemul_kbd_disable, |
.write = gxemul_write, |
.read = gxemul_do_read, |
}; |
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
return *(uint32_t*) gxemul_hw_map.irqc; |
} |
/** Masks interrupt. |
* |
* @param irq interrupt number |
*/ |
static inline void gxemul_irqc_mask(uint32_t irq) |
{ |
*(uint32_t*) gxemul_hw_map.irqc_mask = irq; |
} |
/** Unmasks interrupt. |
* |
* @param irq interrupt number |
*/ |
static inline void gxemul_irqc_unmask(uint32_t irq) |
{ |
*(uint32_t*) gxemul_hw_map.irqc_unmask = irq; |
} |
/** Initializes #gxemul_hw_map. */ |
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); |
gxemul_hw_map.rtc = hw_map(GXEMUL_RTC, PAGE_SIZE); |
gxemul_hw_map.irqc = hw_map(GXEMUL_IRQC, PAGE_SIZE); |
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; |
hw_map_init_called = true; |
} |
/** Putchar that works with gxemul. |
* |
* @param dev Not used. |
* @param ch Characted to be printed. |
*/ |
static void gxemul_write(chardev_t *dev, const char ch) |
{ |
*((char *) gxemul_hw_map.videoram) = ch; |
} |
/** Enables gxemul keyboard (interrupt unmasked). |
* |
* @param dev Not used. |
* |
* Called from getc(). |
*/ |
static void gxemul_kbd_enable(chardev_t *dev) |
{ |
gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
} |
/** Disables gxemul keyboard (interrupt masked). |
* |
* @param dev not used |
* |
* Called from getc(). |
*/ |
static void gxemul_kbd_disable(chardev_t *dev) |
{ |
gxemul_irqc_mask(GXEMUL_KBD_IRQ); |
} |
/** Read character using polling, assume interrupts disabled. |
* |
* @param dev Not used. |
*/ |
static char gxemul_do_read(chardev_t *dev) |
{ |
char ch; |
while (1) { |
ch = *((volatile char *) gxemul_hw_map.kbd); |
if (ch) { |
if (ch == '\r') |
return '\n'; |
if (ch == 0x7f) |
return '\b'; |
return ch; |
} |
} |
} |
/** Process keyboard interrupt. |
* |
* @param irq IRQ information. |
* @param arg Not used. |
*/ |
static void gxemul_irq_handler(irq_t *irq, void *arg, ...) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
ipc_irq_send_notif(irq); |
} else { |
char ch = 0; |
ch = *((char *) gxemul_hw_map.kbd); |
if (ch == '\r') { |
ch = '\n'; |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
} |
} |
static irq_ownership_t gxemul_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
/** Acquire console back for kernel. */ |
void gxemul_grab_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&gxemul_console_irq.lock); |
gxemul_console_irq.notif_cfg.notify = false; |
spinlock_unlock(&gxemul_console_irq.lock); |
interrupts_restore(ipl); |
} |
/** Return console to userspace. */ |
void gxemul_release_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&gxemul_console_irq.lock); |
if (gxemul_console_irq.notif_cfg.answerbox) { |
gxemul_console_irq.notif_cfg.notify = true; |
} |
spinlock_unlock(&gxemul_console_irq.lock); |
interrupts_restore(ipl); |
} |
/** Initializes console object representing gxemul console. |
* |
* @param devno device number. |
*/ |
void gxemul_console_init(devno_t devno) |
{ |
chardev_initialize("gxemul_console", &console, &gxemul_ops); |
stdin = &console; |
stdout = &console; |
irq_initialize(&gxemul_console_irq); |
gxemul_console_irq.devno = devno; |
gxemul_console_irq.inr = GXEMUL_KBD_IRQ; |
gxemul_console_irq.claim = gxemul_claim; |
gxemul_console_irq.handler = gxemul_irq_handler; |
irq_register(&gxemul_console_irq); |
gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ); |
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). |
*/ |
static void gxemul_timer_start(uint32_t 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. |
* @param arg Not used. |
*/ |
static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
{ |
/* |
* We are holding a lock which prevents preemption. |
* Release the lock, call clock() and reacquire the lock again. |
*/ |
spinlock_unlock(&irq->lock); |
clock(); |
spinlock_lock(&irq->lock); |
/* acknowledge tick */ |
*(uint32_t*) gxemul_hw_map.rtc_ack = 0; |
} |
/** Initializes and registers timer interrupt handler. */ |
static void gxemul_timer_irq_init() |
{ |
irq_initialize(&gxemul_timer_irq); |
gxemul_timer_irq.devno = device_assign_devno(); |
gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ; |
gxemul_timer_irq.claim = gxemul_timer_claim; |
gxemul_timer_irq.handler = gxemul_timer_irq_handler; |
irq_register(&gxemul_timer_irq); |
} |
/** Starts timer. |
* |
* Initiates regular timer interrupts after initializing |
* corresponding interrupt handler. |
*/ |
void gxemul_timer_irq_start() |
{ |
gxemul_timer_irq_init(); |
gxemul_timer_start(GXEMUL_TIMER_FREQ); |
} |
/** Returns the size of emulated memory. |
* |
* @return Size in bytes. |
*/ |
size_t gxemul_get_memory_size(void) |
{ |
return *((int*)(GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
} |
/** Prints a character. |
* |
* @param ch Character to be printed. |
*/ |
void gxemul_debug_putc(char ch) |
{ |
char * addr = 0; |
if (!hw_map_init_called) { |
addr = (char *) GXEMUL_KBD; |
} else { |
addr = (char *) gxemul_hw_map.videoram; |
} |
*(addr) = ch; |
} |
/** Stops gxemul. */ |
void gxemul_cpu_halt(void) |
{ |
char * addr = 0; |
if (!hw_map_init_called) { |
addr = (char *) GXEMUL_KBD; |
} else { |
addr = (char *) gxemul_hw_map.videoram; |
} |
*(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 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++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
dprintf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
} |
} |
} |
} |
/** Returns address of framebuffer device. |
* |
* @return Address of framebuffer device. |
*/ |
uintptr_t gxemul_get_fb_address(void) |
{ |
return (uintptr_t) GXEMUL_FB; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/page_fault.c |
---|
1,211 → 1,213 |
/* |
* 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/mm/page_fault.h> |
#include <mm/as.h> |
#include <genarch/mm/page_pt.h> |
#include <arch.h> |
#include <interrupt.h> |
#include <print.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, %[dummy], c5, c0, 0" |
: [dummy] "=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, %[ret], c6, c0, 0" |
: [ret] "=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 does not 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 __attribute__ ((unused)) = |
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); |
printf("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."); |
} |
} |
/** 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) { |
printf("prefetch_abort\n"); |
print_istate(istate); |
panic("page fault - prefetch_abort at address: %x.", |
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; |
} |
// 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); |
} |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/tlb.c |
---|
52,6 → 52,7 |
); |
} |
/** Invalidate all entries in TLB that belong to specified address space. |
* |
* @param asid Ignored as the ARM architecture doesn't support ASIDs. |
61,6 → 62,7 |
tlb_invalidate_all(); |
} |
/** Invalidate single entry in TLB |
* |
* @param page Virtual adress of the page |
68,19 → 70,21 |
static inline void invalidate_page(uintptr_t page) |
{ |
asm volatile ( |
"mcr p15, 0, %[page], c8, c7, 1\n" |
:: [page] "r" (page) |
"mcr p15, 0, %0, c8, c7, 1" |
: |
: "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. |
* @param cnt Number of entries to invalidate. |
*/ |
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, size_t cnt) |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
unsigned int i; |
88,13 → 92,5 |
invalidate_page(page + i * PAGE_SIZE); |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/as.c |
---|
48,5 → 48,6 |
as_operations = &as_pt_operations; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/frame.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32mm |
/** @addtogroup arm32mm |
* @{ |
*/ |
/** @file |
35,8 → 35,8 |
#include <mm/frame.h> |
#include <arch/mm/frame.h> |
#include <arch/machine.h> |
#include <config.h> |
#include <arch/debug/print.h> |
/** Address of the last frame in the memory. */ |
uintptr_t last_frame = 0; |
44,26 → 44,25 |
/** Creates memory zones. */ |
void frame_arch_init(void) |
{ |
last_frame = machine_get_memory_size(); |
/* All memory as one zone */ |
zone_create(0, ADDR2PFN(last_frame), |
BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0); |
/* blacklist boot page table */ |
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME, |
BOOT_PAGE_TABLE_SIZE_IN_FRAMES); |
// 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; |
machine_frame_init(); |
// 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) |
{ |
unsigned int i; |
for (i = 0; i < BOOT_PAGE_TABLE_SIZE_IN_FRAMES; i++) |
frame_free(i * FRAME_SIZE + BOOT_PAGE_TABLE_ADDRESS); |
int i; |
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/page.c |
---|
44,6 → 44,7 |
#include <interrupt.h> |
#include <arch/mm/frame.h> |
/** Initializes page tables. |
* |
* 1:1 virtual-physical mapping is created in kernel address space. Mapping |
51,24 → 52,28 |
*/ |
void page_arch_init(void) |
{ |
int flags = PAGE_CACHEABLE; |
uintptr_t cur; |
int flags; |
page_mapping_operations = &pt_mapping_operations; |
uintptr_t cur; |
/* Kernel identity mapping */ |
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) |
flags = PAGE_CACHEABLE; |
// 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); |
boot_page_table_free(); |
} |
84,23 → 89,22 |
*/ |
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); |
return virtaddr; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/mm/memory_init.c |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2007 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 arm32mm |
* @{ |
*/ |
/** @file |
* @brief Memory information functions. |
*/ |
#include <arch/mm/memory_init.h> |
#include <arch/mm/page.h> |
#include <arch/machine.h> |
/** Returns memory size. |
* |
* @return Memory size in bytes |
*/ |
size_t get_memory_size(void) |
{ |
return machine_get_memory_size(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/exception.c |
---|
33,13 → 33,14 |
* @brief Exception handlers and exception initialization routines. |
*/ |
#include <arch/exception.h> |
#include <arch/debug/print.h> |
#include <arch/memstr.h> |
#include <arch/regutils.h> |
#include <interrupt.h> |
#include <arch/machine.h> |
#include <arch/mm/page_fault.h> |
#include <arch/barrier.h> |
#include <arch/machine.h> |
#include <print.h> |
#include <syscall/syscall.h> |
58,21 → 59,168 |
/** 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 |
* before stack switch takes place. |
*/ |
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:" |
); |
} |
/** 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\ |
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}^" |
); |
} |
/** Switch CPU to mode in which interrupts are serviced (currently it |
* is Undefined mode). |
* |
* 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). |
*/ |
inline static void switch_to_irq_servicing_mode() |
{ |
/* switch to Undefined mode */ |
asm volatile( |
/* save regs used during switching */ |
"stmfd sp!, {r0-r3} \n" |
/* save stack pointer and link register to r1, r2 */ |
"mov r1, sp \n" |
"mov r2, lr \n" |
/* mode switch */ |
"mrs r0, cpsr \n" |
"bic r0, r0, #0x1f \n" |
"orr r0, r0, #0x1b \n" |
"msr cpsr_c, r0 \n" |
/* restore saved sp and lr */ |
"mov sp, r1 \n" |
"mov lr, r2 \n" |
/* restore original regs */ |
"ldmfd sp!, {r0-r3} \n" |
); |
} |
/** Calls exception dispatch routine. */ |
#define CALL_EXC_DISPATCH(exception) \ |
asm("mov r0, %0" : : "i" (exception)); \ |
asm("mov r1, r13"); \ |
asm("bl exc_dispatch"); |
/** General exception handler. |
* |
* Stores registers, dispatches the exception, |
* and finally restores registers and returns from exception processing. |
* |
* @param exception Exception number. |
*/ |
#define PROCESS_EXCEPTION(exception) \ |
setup_stack_and_save_regs(); \ |
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. |
*/ |
static void install_handler(unsigned handler_addr, unsigned *vector) |
static void install_handler (unsigned handler_addr, unsigned* vector) |
{ |
/* relative address (related to exc. vector) of the word |
* where handler's address is stored |
*/ |
volatile uint32_t handler_address_ptr = EXC_VECTORS_SIZE - |
PREFETCH_OFFSET; |
volatile uint32_t handler_address_ptr = EXC_VECTORS_SIZE - PREFETCH_OFFSET; |
/* make it LDR instruction and store at exception vector */ |
*vector = handler_address_ptr | LDR_OPCODE; |
smc_coherence(*vector); |
/* store handler's address */ |
*(vector + EXC_VECTORS) = handler_addr; |
79,6 → 227,70 |
} |
/** Low-level Reset Exception handler. */ |
static void reset_exception_entry() |
{ |
PROCESS_EXCEPTION(EXC_RESET); |
} |
/** Low-level Software Interrupt Exception handler. */ |
static void swi_exception_entry() |
{ |
PROCESS_EXCEPTION(EXC_SWI); |
} |
/** Low-level Undefined Instruction Exception handler. */ |
static void undef_instr_exception_entry() |
{ |
PROCESS_EXCEPTION(EXC_UNDEF_INSTR); |
} |
/** Low-level Fast Interrupt Exception handler. */ |
static void fiq_exception_entry() |
{ |
PROCESS_EXCEPTION(EXC_FIQ); |
} |
/** Low-level Prefetch Abort Exception handler. */ |
static void prefetch_abort_exception_entry() |
{ |
asm("sub lr, lr, #4"); |
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT); |
} |
/** Low-level Data Abort Exception handler. */ |
static void data_abort_exception_entry() |
{ |
asm("sub lr, lr, #8"); |
PROCESS_EXCEPTION(EXC_DATA_ABORT); |
} |
/** 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"); |
setup_stack_and_save_regs(); |
switch_to_irq_servicing_mode(); |
CALL_EXC_DISPATCH(EXC_IRQ) |
load_regs(); |
} |
/** Software Interrupt handler. |
* |
* Dispatches the syscall. |
85,67 → 297,74 |
*/ |
static void swi_exception(int exc_no, istate_t *istate) |
{ |
istate->r0 = syscall_handler(istate->r0, istate->r1, istate->r2, |
istate->r3, istate->r4, istate->r5, istate->r6); |
/* |
dprintf("SYSCALL: r0-r4: %x, %x, %x, %x, %x; pc: %x\n", istate->r0, |
istate->r1, istate->r2, istate->r3, istate->r4, istate->pc); |
*/ |
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. |
*/ |
static void irq_exception(int exc_no, istate_t *istate) |
{ |
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); |
install_handler((unsigned)fiq_exception_entry, |
(unsigned*)EXC_FIQ_VEC); |
} |
#ifdef HIGH_EXCEPTION_VECTORS |
/** Activates use of high exception vectors addresses. */ |
static void high_vectors(void) |
static void high_vectors() |
{ |
uint32_t control_reg; |
asm volatile ( |
"mrc p15, 0, %[control_reg], c1, c1" |
: [control_reg] "=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, %[control_reg], c1, c1" |
:: [control_reg] "r" (control_reg) |
); |
asm volatile( "mcr p15, 0, %0, c1, c1" : : "r" (control_reg)); |
} |
#endif |
/** Interrupt Exception handler. |
* |
* Determines the sources of interrupt and calls their handlers. |
*/ |
static void irq_exception(int exc_no, istate_t *istate) |
{ |
machine_irq_exception(exc_no, istate); |
} |
/** Initializes exception handling. |
* |
* |
* Installs low-level exception handlers and then registers |
* exceptions and their handlers to kernel exception dispatcher. |
*/ |
157,12 → 376,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. |
169,19 → 388,20 |
*/ |
void print_istate(istate_t *istate) |
{ |
printf("istate dump:\n"); |
printf(" r0: %x r1: %x r2: %x r3: %x\n", |
istate->r0, istate->r1, istate->r2, istate->r3); |
printf(" r4: %x r5: %x r6: %x r7: %x\n", |
istate->r4, istate->r5, istate->r6, istate->r7); |
printf(" r8: %x r8: %x r10: %x r11: %x\n", |
istate->r8, istate->r9, istate->r10, istate->r11); |
printf(" r12: %x sp: %x lr: %x spsr: %x\n", |
istate->r12, istate->sp, istate->lr, istate->spsr); |
printf(" pc: %x\n", istate->pc); |
dprintf("istate 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 r8: %x r10: %x r11: %x\n", |
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); |
dprintf(" pc: %x\n", istate->pc); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/userspace.c |
---|
35,6 → 35,7 |
#include <userspace.h> |
/** Struct for holding all general purpose registers. |
* |
* Used to set registers when going to userspace. |
58,49 → 59,50 |
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; |
/* %r1 is defined to hold pcb_ptr - set it to 0 */ |
ustate.r1 = 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; |
/* clear other registers */ |
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 sp, %[ustate]\n" |
"msr spsr_c, %[user_mode]\n" |
"ldmfd sp!, {r0-r12, sp, lr}^\n" |
"ldmfd sp!, {pc}^\n" |
:: [ustate] "r" (&ustate), [user_mode] "r" (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}^" |
: |
: "r"(&ustate), "r"(user_mode) |
: "r0", "r1" |
); |
/* unreachable */ |
while(1) |
; |
// unreachable |
while(1) ; |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/start.S |
---|
34,40 → 34,37 |
.global exc_stack |
.global supervisor_sp |
kernel_image_start: |
# switch to supervisor mode |
mrs r3, cpsr |
bic r3, r3, #0x1f |
orr r3, r3, #0x13 |
msr cpsr_c, r3 |
ldr sp, =temp_stack |
# initialize Stack pointer for exception modes |
mrs r4, cpsr |
bic r4, r4, #0x1f |
cmp r2, #0 |
beq bootinfo_end |
#FIQ Mode |
orr r3, r4, #0x11 |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
ldr r3, =bootinfo |
#IRQ Mode |
orr r3, r4, #0x12 |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
bootinfo_loop: |
ldr r4, [r1] |
str r4, [r3] |
#ABORT Mode |
orr r3, r4, #0x17 |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
add r1, r1, #4 |
add r3, r3, #4 |
add r2, r2, #-4 |
#UNDEFINED Mode |
orr r3, r4, #0x1b |
msr cpsr_c, r3 |
ldr sp, =exc_stack |
cmp r2, #0 |
bne bootinfo_loop |
bootinfo_end: |
# switch to supervisor mode |
orr r3, r4, #0x13 |
msr cpsr_c, r3 |
ldr sp, =temp_stack |
bl arch_pre_main |
bl main_bsp |
.space TEMP_STACK_SIZE |
78,3 → 75,4 |
supervisor_sp: |
.space 4 |
/branches/arm/kernel/arch/arm32/src/arm32.c |
---|
33,40 → 33,42 |
* @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) |
/** Information about loaded tasks. */ |
bootinfo_t bootinfo; |
/** Performs arm32 specific initialization before main_bsp() is called. */ |
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) |
{ |
74,24 → 76,25 |
interrupts_disable(); |
} |
/** 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(); |
console_init(device_assign_devno()); |
#ifdef CONFIG_FB |
machine_fb_init(); |
#else |
#ifdef CONFIG_ARM_PRN |
machine_srlnout_init(); |
#endif /* CONFIG_ARM_PRN */ |
#endif /* CONFIG_FB */ |
fb_init(machine_get_fb_address(), 640, 480, 1920, VISUAL_RGB_8_8_8); |
#endif |
} |
/** Performs arm32 specific tasks needed after cpu is initialized. |
* |
* Currently the function is empty. |
118,7 → 121,6 |
*/ |
void arch_post_smp_init(void) |
{ |
machine_input_init(); |
} |
125,6 → 127,7 |
/** Performs arm32 specific tasks needed before the new task is run. */ |
void before_task_runs_arch(void) |
{ |
tlb_invalidate_all(); |
} |
134,13 → 137,10 |
*/ |
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. |
149,6 → 149,7 |
{ |
} |
/** Halts CPU. */ |
void cpu_halt(void) |
{ |
155,41 → 156,19 |
machine_cpu_halt(); |
} |
/** Reboot. */ |
void arch_reboot() |
{ |
/* not implemented */ |
while (1); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
/** @} |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
machine_grab_console(); |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
} |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
machine_release_console(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/interrupt.c |
---|
35,14 → 35,14 |
#include <arch/asm.h> |
#include <arch/regutils.h> |
#include <ddi/irq.h> |
#include <arch/machine.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <interrupt.h> |
/** Initial size of a table holding interrupt handlers. */ |
#define IRQ_COUNT 8 |
/** Disable interrupts. |
* |
* @return Old interrupt priority level. |
56,6 → 56,7 |
return ipl; |
} |
/** Enable interrupts. |
* |
* @return Old interrupt priority level. |
65,10 → 66,11 |
ipl_t ipl = current_status_reg_read(); |
current_status_reg_control_write(ipl & ~STATUS_REG_IRQ_DISABLED_BIT); |
return ipl; |
} |
/** Restore interrupt priority level. |
* |
* @param ipl Saved interrupt priority level. |
76,10 → 78,12 |
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. |
89,6 → 93,7 |
return current_status_reg_read(); |
} |
/** Initialize basic tables for exception dispatching |
* and starts the timer. |
*/ |
96,8 → 101,8 |
{ |
irq_init(IRQ_COUNT, IRQ_COUNT); |
machine_timer_irq_start(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/context.S |
---|
1,5 → 1,5 |
# |
# Copyright (c) 2007 Petr Stepan |
# Copyright (c) 2003-2004 Jakub Jermar, 2007 Petr Stepan |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
57,3 → 57,4 |
mov r0, #0 |
mov pc, lr |
/branches/arm/kernel/arch/arm32/src/console.c |
---|
0,0 → 1,63 |
/* |
* Copyright (c) 2007 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 arm32 |
* @{ |
*/ |
/** @file |
* @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) |
{ |
machine_grab_console(); |
} |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
machine_release_console(); |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/debug/print.c |
---|
0,0 → 1,98 |
/* |
* Copyright (c) 2007 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 arm32 |
* @{ |
*/ |
/** @file |
* @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. |
*/ |
static void putc(char ch) |
{ |
machine_debug_putc(ch); |
} |
/** Prints a string to the console. |
* |
* @param str String to be printed. |
* @param count Number of characters to be printed. |
* @param unused Unused parameter. |
* |
* @return Number of printed characters. |
*/ |
static int debug_write(const char *str, size_t count, void *unused) |
{ |
int i; |
for (i = 0; i < count; ++i) { |
putc(str[i]); |
} |
return i; |
} |
/** Prints a formated string. |
* |
* @param fmt "Printf-like" format. |
*/ |
void debug_printf(const char *fmt, ...) |
{ |
va_list args; |
va_start (args, fmt); |
struct printf_spec ps = { (int(*)(void *, size_t, void *)) debug_write, NULL }; |
printf_core(fmt, &ps, args); |
va_end(args); |
} |
/** Prints a string. |
* |
* @param str String to print. |
*/ |
void debug_puts(const char *str) |
{ |
while ( *str ) { |
putc(*str); |
str++; |
} |
} |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/src/asm.S |
---|
30,7 → 30,6 |
.text |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
40,9 → 39,6 |
memsetb: |
b _memsetb |
memsetw: |
b _memsetw |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
49,8 → 45,7 |
add r3, r1, #3 |
bic r3, r3, #3 |
cmp r1, r3 |
stmdb sp!, {r4, r5, lr} |
mov r5, r0 /* save dst */ |
stmdb sp!, {r4, lr} |
beq 4f |
1: |
cmp r2, #0 |
63,8 → 58,8 |
cmp ip, r2 |
bne 2b |
3: |
mov r0, r5 |
ldmia sp!, {r4, r5, pc} |
mov r0, r1 |
ldmia sp!, {r4, pc} |
4: |
add r3, r0, #3 |
bic r3, r3, #3 |
99,5 → 94,6 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
mov r0, #0 |
ldmia sp!, {r4, r5, pc} |
mov r0, #0 |
ldmia sp!, {r4, pc} |
/branches/arm/kernel/arch/arm32/src/panic.S |
---|
31,5 → 31,6 |
.global panic_printf |
panic_printf: |
bl printf |
bl debug_printf |
bl cpu_halt |
/branches/arm/kernel/arch/arm32/include/machine_func.h |
---|
File deleted |
/branches/arm/kernel/arch/arm32/include/mach/testarm/testarm.h |
---|
File deleted |
/branches/arm/kernel/arch/arm32/include/mach/integratorcp/integratorcp.h |
---|
File deleted |
/branches/arm/kernel/arch/arm32/include/drivers/gxemul.h |
---|
0,0 → 1,82 |
/* |
* Copyright (c) 2007 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 arm32gxemul GXemul |
* @brief GXemul machine specific parts. |
* @ingroup arm32 |
* @{ |
*/ |
/** @file |
* @brief GXemul peripheries drivers declarations. |
*/ |
#ifndef KERN_arm32_GXEMUL_H_ |
#define KERN_arm32_GXEMUL_H_ |
#include <console/chardev.h> |
/** Last interrupt number (beginning from 0) whose status is probed |
* from interrupt controller |
*/ |
#define GXEMUL_IRQC_MAX_IRQ 8 |
/** Timer frequency */ |
#define GXEMUL_TIMER_FREQ 100 |
/** Struct containing mappings of gxemul HW devices into kernel part |
* of virtual address space. |
*/ |
typedef struct { |
uintptr_t videoram; |
uintptr_t kbd; |
uintptr_t rtc; |
uintptr_t rtc_freq; |
uintptr_t rtc_ack; |
uintptr_t irqc; |
uintptr_t irqc_mask; |
uintptr_t irqc_unmask; |
} gxemul_hw_map_t; |
extern void gxemul_hw_map_init(void); |
extern void gxemul_console_init(devno_t devno); |
extern void gxemul_release_console(void); |
extern void gxemul_grab_console(void); |
extern void gxemul_timer_irq_start(void); |
extern void gxemul_debug_putc(char ch); |
extern void gxemul_cpu_halt(void); |
extern void gxemul_irq_exception(int exc_no, istate_t *istate); |
extern size_t gxemul_get_memory_size(void); |
extern uintptr_t gxemul_get_fb_address(void); |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/types.h |
---|
42,6 → 42,10 |
# define ATTRIBUTE_PACKED |
#endif |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
53,6 → 57,8 |
typedef unsigned long long uint64_t; |
typedef uint32_t size_t; |
typedef uint32_t count_t; |
typedef uint32_t index_t; |
typedef uint32_t uintptr_t; |
typedef uint32_t pfn_t; |
62,30 → 68,14 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef struct { |
} fncptr_t; |
typedef uint8_t bool; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page table entry. |
* |
* We have different structs for level 0 and level 1 page table entries. |
95,6 → 85,7 |
unsigned dummy : 32; |
} pte_t; |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/mm/page.h |
---|
40,9 → 40,12 |
#include <mm/mm.h> |
#include <arch/exception.h> |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifndef __ASM__ |
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) |
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000) |
53,101 → 56,83 |
#ifdef KERNEL |
/* Number of entries in each level. */ |
#define PTL0_ENTRIES_ARCH (2 << 12) /* 4096 */ |
#define PTL0_ENTRIES_ARCH (2<<12) // 4096 |
#define PTL1_ENTRIES_ARCH 0 |
#define PTL2_ENTRIES_ARCH 0 |
/* coarse page tables used (256 * 4 = 1KB per page) */ |
#define PTL3_ENTRIES_ARCH (2 << 8) /* 256 */ |
/* Page table sizes for each level. */ |
/* coarse page tables used (256*4 = 1KB per page) */ |
#define PTL3_ENTRIES_ARCH (2<<8) // 256 |
#define PTL0_SIZE_ARCH FOUR_FRAMES |
#define PTL1_SIZE_ARCH 0 |
#define PTL2_SIZE_ARCH 0 |
#define PTL3_SIZE_ARCH ONE_FRAME |
/* Macros calculating indices into page tables for each level. */ |
#define PTL0_INDEX_ARCH(vaddr) (((vaddr) >> 20) & 0xfff) |
#define PTL1_INDEX_ARCH(vaddr) 0 |
#define PTL2_INDEX_ARCH(vaddr) 0 |
#define PTL3_INDEX_ARCH(vaddr) (((vaddr) >> 12) & 0x0ff) |
/* Get PTE address accessors for each level. */ |
#define GET_PTL1_ADDRESS_ARCH(ptl0, i) \ |
((pte_t *) ((((pte_level0_t *)(ptl0))[(i)]).coarse_table_addr << 10)) |
#define GET_PTL2_ADDRESS_ARCH(ptl1, i) \ |
(ptl1) |
#define GET_PTL3_ADDRESS_ARCH(ptl2, i) \ |
(ptl2) |
#define GET_FRAME_ADDRESS_ARCH(ptl3, i) \ |
((uintptr_t) ((((pte_level1_t *)(ptl3))[(i)]).frame_base_addr << 12)) |
#define GET_PTL1_ADDRESS_ARCH(ptl0, i) ((pte_t *)( (((pte_level0_t*)(ptl0))[(i)]).coarse_table_addr << 10 )) |
#define GET_PTL2_ADDRESS_ARCH(ptl1, i) (ptl1) |
#define GET_PTL3_ADDRESS_ARCH(ptl2, i) (ptl2) |
#define GET_FRAME_ADDRESS_ARCH(ptl3, i) ((uintptr_t)( (((pte_level1_t*)(ptl3))[(i)]).frame_base_addr << 12 )) |
/* Set PTE address accessors for each level. */ |
#define SET_PTL0_ADDRESS_ARCH(ptl0) \ |
(set_ptl0_addr((pte_level0_t *) (ptl0))) |
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \ |
(((pte_level0_t *) (ptl0))[(i)].coarse_table_addr = (a) >> 10) |
#define SET_PTL0_ADDRESS_ARCH(ptl0) (set_ptl0_addr((pte_level0_t *)(ptl0))) |
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) (((pte_level0_t *)(ptl0))[(i)].coarse_table_addr = (a)>>10) |
#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) |
#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) |
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \ |
(((pte_level1_t *) (ptl3))[(i)].frame_base_addr = (a) >> 12) |
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) (((pte_level1_t *)(ptl3))[(i)].frame_base_addr = (a)>>12) |
/* Get PTE flags accessors for each level. */ |
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \ |
get_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i)) |
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \ |
PAGE_PRESENT |
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \ |
PAGE_PRESENT |
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \ |
get_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i)) |
#define GET_PTL1_FLAGS_ARCH(ptl0, i) get_pt_level0_flags((pte_level0_t *)(ptl0), (index_t)(i)) |
#define GET_PTL2_FLAGS_ARCH(ptl1, i) PAGE_PRESENT |
#define GET_PTL3_FLAGS_ARCH(ptl2, i) PAGE_PRESENT |
#define GET_FRAME_FLAGS_ARCH(ptl3, i) get_pt_level1_flags((pte_level1_t *)(ptl3), (index_t)(i)) |
/* Set PTE flags accessors for each level. */ |
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \ |
set_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i), (x)) |
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) set_pt_level0_flags((pte_level0_t *)(ptl0), (index_t)(i), (x)) |
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x) |
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) |
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \ |
set_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i), (x)) |
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) set_pt_level1_flags((pte_level1_t *)(ptl3), (index_t)(i), (x)) |
/* Macros for querying the last-level PTE entries. */ |
#define PTE_VALID_ARCH(pte) \ |
(*((uint32_t *) (pte)) != 0) |
#define PTE_PRESENT_ARCH(pte) \ |
(((pte_level0_t *) (pte))->descriptor_type != 0) |
#define PTE_GET_FRAME_ARCH(pte) \ |
(((pte_level1_t *) (pte))->frame_base_addr << FRAME_WIDTH) |
#define PTE_WRITABLE_ARCH(pte) \ |
(((pte_level1_t *) (pte))->access_permission_0 == \ |
PTE_AP_USER_RW_KERNEL_RW) |
#define PTE_EXECUTABLE_ARCH(pte) \ |
1 |
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0) |
#define PTE_PRESENT_ARCH(pte) ( ((pte_level0_t *)(pte))->descriptor_type != 0 ) |
/* pte should point into ptl3 */ |
#define PTE_GET_FRAME_ARCH(pte) ( ((pte_level1_t *)(pte))->frame_base_addr << FRAME_WIDTH) |
/* pte should point into ptl3 */ |
#define PTE_WRITABLE_ARCH(pte) ( ((pte_level1_t *)(pte))->access_permission_0 == PTE_AP_USER_RW_KERNEL_RW ) |
#define PTE_EXECUTABLE_ARCH(pte) 1 |
#ifndef __ASM__ |
/** Level 0 page table entry. */ |
typedef struct { |
/* 0b01 for coarse tables, see below for details */ |
unsigned descriptor_type : 2; |
unsigned impl_specific : 3; |
unsigned domain : 4; |
unsigned should_be_zero : 1; |
/* Pointer to the coarse 2nd level page table (holding entries for small |
* (4KB) or large (64KB) pages. ARM also supports fine 2nd level page |
* tables that may hold even tiny pages (1KB) but they are bigger (4KB |
* per table in comparison with 1KB per the coarse table) |
*/ |
unsigned coarse_table_addr : 22; |
/* 01b for coarse tables, see below for details */ |
unsigned descriptor_type : 2; |
unsigned impl_specific : 3; |
unsigned domain : 4; |
unsigned should_be_zero : 1; |
/* Pointer to the coarse 2nd level page table (holding entries for small (4KB) |
* or large (64KB) pages. ARM also supports fine 2nd level page tables that |
* may hold even tiny pages (1KB) but they are bigger (4KB per table in comparison |
* with 1KB per the coarse table) |
*/ |
unsigned coarse_table_addr : 22; |
} ATTRIBUTE_PACKED pte_level0_t; |
/** Level 1 page table entry (small (4KB) pages used). */ |
typedef struct { |
/* 0b10 for small pages */ |
unsigned descriptor_type : 2; |
unsigned bufferable : 1; |
unsigned cacheable : 1; |
unsigned descriptor_type : 2; |
unsigned bufferable : 1; |
unsigned cacheable : 1; |
/* access permissions for each of 4 subparts of a page |
* (for each 1KB when small pages used */ |
155,7 → 140,7 |
unsigned access_permission_1 : 2; |
unsigned access_permission_2 : 2; |
unsigned access_permission_3 : 2; |
unsigned frame_base_addr : 20; |
unsigned frame_base_addr : 20; |
} ATTRIBUTE_PACKED pte_level1_t; |
162,28 → 147,28 |
/* Level 1 page tables access permissions */ |
/** User mode: no access, privileged mode: no access. */ |
#define PTE_AP_USER_NO_KERNEL_NO 0 |
#define PTE_AP_USER_NO_KERNEL_NO 0 |
/** User mode: no access, privileged mode: read/write. */ |
#define PTE_AP_USER_NO_KERNEL_RW 1 |
#define PTE_AP_USER_NO_KERNEL_RW 1 |
/** User mode: read only, privileged mode: read/write. */ |
#define PTE_AP_USER_RO_KERNEL_RW 2 |
#define PTE_AP_USER_RO_KERNEL_RW 2 |
/** User mode: read/write, privileged mode: read/write. */ |
#define PTE_AP_USER_RW_KERNEL_RW 3 |
#define PTE_AP_USER_RW_KERNEL_RW 3 |
/* pte_level0_t and pte_level1_t descriptor_type flags */ |
/** pte_level0_t and pte_level1_t "not present" flag (used in descriptor_type). */ |
#define PTE_DESCRIPTOR_NOT_PRESENT 0 |
#define PTE_DESCRIPTOR_NOT_PRESENT 0 |
/** pte_level0_t coarse page table flag (used in descriptor_type). */ |
#define PTE_DESCRIPTOR_COARSE_TABLE 1 |
#define PTE_DESCRIPTOR_COARSE_TABLE 1 |
/** pte_level1_t small page table flag (used in descriptor type). */ |
#define PTE_DESCRIPTOR_SMALL_PAGE 2 |
#define PTE_DESCRIPTOR_SMALL_PAGE 2 |
/** Sets the address of level 0 page table. |
190,11 → 175,12 |
* |
* @param pt Pointer to the page table to set. |
*/ |
static inline void set_ptl0_addr(pte_level0_t *pt) |
static inline void set_ptl0_addr( pte_level0_t* pt) |
{ |
asm volatile ( |
"mcr p15, 0, %[pt], c2, c0, 0\n" |
:: [pt] "r" (pt) |
"mcr p15, 0, %0, c2, c0, 0 \n" |
: |
: "r"(pt) |
); |
} |
204,37 → 190,41 |
* @param pt Level 0 page table. |
* @param i Index of the entry to return. |
*/ |
static inline int get_pt_level0_flags(pte_level0_t *pt, size_t i) |
static inline int get_pt_level0_flags(pte_level0_t *pt, index_t i) |
{ |
pte_level0_t *p = &pt[i]; |
int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT); |
return (np << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) | |
(1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) | |
(1 << PAGE_EXEC_SHIFT) | (1 << PAGE_CACHEABLE_SHIFT); |
return |
( (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT ) | |
( 1 << PAGE_USER_SHIFT ) | |
( 1 << PAGE_READ_SHIFT ) | |
( 1 << PAGE_WRITE_SHIFT ) | |
( 1 << PAGE_EXEC_SHIFT ) | |
( 1 << PAGE_CACHEABLE_SHIFT ) |
; |
} |
/** Returns level 1 page table entry flags. |
* |
* @param pt Level 1 page table. |
* @param i Index of the entry to return. |
*/ |
static inline int get_pt_level1_flags(pte_level1_t *pt, size_t i) |
static inline int get_pt_level1_flags(pte_level1_t *pt, index_t i) |
{ |
pte_level1_t *p = &pt[i]; |
int dt = p->descriptor_type; |
int ap = p->access_permission_0; |
return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) | |
((ap == PTE_AP_USER_RO_KERNEL_RW) << PAGE_READ_SHIFT) | |
((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_READ_SHIFT) | |
((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_WRITE_SHIFT) | |
((ap != PTE_AP_USER_NO_KERNEL_RW) << PAGE_USER_SHIFT) | |
((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_READ_SHIFT) | |
((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_WRITE_SHIFT) | |
(1 << PAGE_EXEC_SHIFT) | |
(p->bufferable << PAGE_CACHEABLE); |
return |
( (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) | |
( (p->access_permission_0 == PTE_AP_USER_RO_KERNEL_RW) << PAGE_READ_SHIFT ) | |
( (p->access_permission_0 == PTE_AP_USER_RW_KERNEL_RW) << PAGE_READ_SHIFT ) | |
( (p->access_permission_0 == PTE_AP_USER_RW_KERNEL_RW) << PAGE_WRITE_SHIFT ) | |
( (p->access_permission_0 != PTE_AP_USER_NO_KERNEL_RW) << PAGE_USER_SHIFT ) | |
( (p->access_permission_0 == PTE_AP_USER_NO_KERNEL_RW) << PAGE_READ_SHIFT ) | |
( (p->access_permission_0 == PTE_AP_USER_NO_KERNEL_RW) << PAGE_WRITE_SHIFT ) | |
( 1 << PAGE_EXEC_SHIFT ) | |
( p->bufferable << PAGE_CACHEABLE ) |
; |
} |
244,20 → 234,17 |
* @param i index of the entry to be changed |
* @param flags new flags |
*/ |
static inline void set_pt_level0_flags(pte_level0_t *pt, size_t i, int flags) |
static inline void set_pt_level0_flags(pte_level0_t *pt, index_t i, int flags) |
{ |
pte_level0_t *p = &pt[i]; |
if (flags & PAGE_NOT_PRESENT) { |
p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT; |
/* |
* Ensures that the entry will be recognized as valid when |
* PTE_VALID_ARCH applied. |
*/ |
p->should_be_zero = 1; |
// ensures that the entry will be recognized as valid when PTE_VALID_ARCH applied |
p->should_be_zero = 1; |
} else { |
p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE; |
p->should_be_zero = 0; |
p->should_be_zero = 0; |
} |
} |
272,16 → 259,16 |
* @param i Index of the entry to be changed. |
* @param flags New flags. |
*/ |
static inline void set_pt_level1_flags(pte_level1_t *pt, size_t i, int flags) |
static inline void set_pt_level1_flags(pte_level1_t *pt, index_t i, int flags) |
{ |
pte_level1_t *p = &pt[i]; |
if (flags & PAGE_NOT_PRESENT) { |
p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT; |
p->access_permission_3 = 1; |
p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT; |
p->access_permission_3 = 1; |
} else { |
p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE; |
p->access_permission_3 = p->access_permission_0; |
p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE; |
p->access_permission_3 = p->access_permission_0; |
} |
p->cacheable = p->bufferable = (flags & PAGE_CACHEABLE) != 0; |
288,19 → 275,18 |
/* default access permission */ |
p->access_permission_0 = p->access_permission_1 = |
p->access_permission_2 = p->access_permission_3 = |
PTE_AP_USER_NO_KERNEL_RW; |
p->access_permission_2 = p->access_permission_3 = PTE_AP_USER_NO_KERNEL_RW; |
if (flags & PAGE_USER) { |
if (flags & PAGE_READ) { |
p->access_permission_0 = p->access_permission_1 = |
p->access_permission_2 = p->access_permission_3 = |
PTE_AP_USER_RO_KERNEL_RW; |
p->access_permission_2 = p->access_permission_3 = |
PTE_AP_USER_RO_KERNEL_RW; |
} |
if (flags & PAGE_WRITE) { |
p->access_permission_0 = p->access_permission_1 = |
p->access_permission_2 = p->access_permission_3 = |
PTE_AP_USER_RW_KERNEL_RW; |
p->access_permission_2 = p->access_permission_3 = |
PTE_AP_USER_RW_KERNEL_RW; |
} |
} |
} |
317,3 → 303,4 |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/mm/page_fault.h |
---|
1,89 → 1,92 |
/* |
* 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 declarations. |
*/ |
#ifndef KERN_arm32_PAGE_FAULT_H_ |
#define KERN_arm32_PAGE_FAULT_H_ |
#include <arch/types.h> |
/** Decribes CP15 "fault status register" (FSR). */ |
typedef struct { |
unsigned status : 3; |
unsigned domain : 4; |
unsigned zero : 1; |
unsigned should_be_zero : 24; |
} ATTRIBUTE_PACKED fault_status_t; |
/** Help union used for casting integer value into #fault_status_t. */ |
typedef union { |
fault_status_t fs; |
uint32_t dummy; |
} fault_status_union_t; |
/** Simplified description of instruction code. |
* |
* @note Used for recognizing memory access instructions. |
* @see ARM architecture reference (chapter 3.1) |
*/ |
typedef struct { |
unsigned dummy1 : 4; |
unsigned bit4 : 1; |
unsigned bits567 : 3; |
unsigned dummy : 12; |
unsigned access : 1; |
unsigned opcode : 4; |
unsigned type : 3; |
unsigned condition : 4; |
} ATTRIBUTE_PACKED instruction_t; |
/** Help union used for casting pc register (uint_32_t) value into |
* #instruction_t pointer. |
*/ |
typedef union { |
instruction_t *instr; |
uint32_t pc; |
} instruction_union_t; |
extern void prefetch_abort(int n, istate_t *istate); |
extern void data_abort(int n, istate_t *istate); |
#endif |
/** @} |
*/ |
/* |
* 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 declarations. |
*/ |
#ifndef KERN_arm32_PAGE_FAULT_H_ |
#define KERN_arm32_PAGE_FAULT_H_ |
#include <arch/types.h> |
/** Decribes CP15 "fault status register" (FSR). */ |
typedef struct { |
unsigned status : 3; |
unsigned domain : 4; |
unsigned zero : 1; |
unsigned should_be_zero : 24; |
} ATTRIBUTE_PACKED fault_status_t; |
/** Help union used for casting integer value into #fault_status_t. */ |
typedef union { |
fault_status_t fs; |
uint32_t dummy; |
} fault_status_union_t; |
/** Simplified description of instruction code. |
* |
* @note Used for recognizing memory access instructions. |
* @see ARM architecture reference (chapter 3.1) |
*/ |
typedef struct { |
unsigned dummy1 : 4; |
unsigned bit4 : 1; |
unsigned bits567 : 3; |
unsigned dummy : 12; |
unsigned access : 1; |
unsigned opcode : 4; |
unsigned type : 3; |
unsigned condition : 4; |
} ATTRIBUTE_PACKED instruction_t; |
/** Help union used for casting pc register (uint_32_t) value into |
* #instruction_t pointer. |
*/ |
typedef union { |
instruction_t *instr; |
uint32_t pc; |
} instruction_union_t; |
extern void prefetch_abort(int n, istate_t *istate); |
extern void data_abort(int n, istate_t *istate); |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/mm/asid.h |
---|
44,12 → 44,12 |
typedef uint8_t asid_t; |
/* |
* This works due to fact that this file is never included alone but only |
* through "generic/include/mm/asid.h" where ASID_START is defined. |
*/ |
#define asid_get() (ASID_START + 1) |
/* this works due to fact that this file is never included alone but only |
through "generic/include/mm/asid.h" where ASID_START is defined |
*/ |
#define asid_get() ( ASID_START + 1 ) |
#define asid_put(asid) |
#endif |
/branches/arm/kernel/arch/arm32/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32mm |
/** @addtogroup arm32mm |
* @{ |
*/ |
/** @file |
36,8 → 36,8 |
#ifndef KERN_arm32_FRAME_H_ |
#define KERN_arm32_FRAME_H_ |
#define FRAME_WIDTH 12 /* 4KB frames */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 12 /* 4KB frames */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifdef KERNEL |
#ifndef __ASM__ |
44,8 → 44,8 |
#include <arch/types.h> |
#define BOOT_PAGE_TABLE_SIZE 0x4000 |
#define BOOT_PAGE_TABLE_ADDRESS 0x4000 |
#define BOOT_PAGE_TABLE_SIZE 0x4000 |
#define BOOT_PAGE_TABLE_ADDRESS 0x4000 |
#define BOOT_PAGE_TABLE_START_FRAME (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH) |
#define BOOT_PAGE_TABLE_SIZE_IN_FRAMES (BOOT_PAGE_TABLE_SIZE >> FRAME_WIDTH) |
54,7 → 54,6 |
extern void frame_arch_init(void); |
extern void boot_page_table_free(void); |
#define physmem_print() |
#endif /* __ASM__ */ |
#endif /* KERNEL */ |
/branches/arm/kernel/arch/arm32/include/mm/memory_init.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2007 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 arm32mm |
* @{ |
*/ |
/** @file |
* @brief Memory information functions declarations. |
*/ |
#ifndef KERN_arm32_MEMORY_INIT_H_ |
#define KERN_arm32_MEMORY_INIT_H_ |
#include <config.h> |
size_t get_memory_size(void); |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/mm/tlb.h |
---|
36,6 → 36,9 |
#ifndef KERN_arm32_TLB_H_ |
#define KERN_arm32_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/exception.h |
---|
136,13 → 136,6 |
extern void install_exception_handlers(void); |
extern void exception_init(void); |
extern void print_istate(istate_t *istate); |
extern void reset_exception_entry(void); |
extern void irq_exception_entry(void); |
extern void fiq_exception_entry(void); |
extern void undef_instr_exception_entry(void); |
extern void prefetch_abort_exception_entry(void); |
extern void data_abort_exception_entry(void); |
extern void swi_exception_entry(void); |
#endif |
/branches/arm/kernel/arch/arm32/include/cycle.h |
---|
36,6 → 36,7 |
#ifndef KERN_arm32_CYCLE_H_ |
#define KERN_arm32_CYCLE_H_ |
/** Returns count of CPU cycles. |
* |
* No such instruction on ARM to get count of cycles. |
47,6 → 48,7 |
return 0; |
} |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/machine.h |
---|
0,0 → 1,122 |
/* |
* Copyright (c) 2007 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 arm32 |
* @{ |
*/ |
/** @file |
* @brief Declarations of machine specific functions. |
* |
* These functions enable to differentiate more kinds of ARM emulators |
* or CPUs. It's the same concept as "arch" functions on the architecture |
* level. |
*/ |
#ifndef KERN_arm32_MACHINE_H_ |
#define KERN_arm32_MACHINE_H_ |
#include <console/console.h> |
#include <arch/types.h> |
#include <arch/exception.h> |
#include <arch/drivers/gxemul.h> |
/** Initializes console. |
* |
* @param devno Console device number. |
*/ |
extern void machine_console_init(devno_t devno); |
/** Acquire console back for kernel. */ |
extern void machine_grab_console(void); |
/** Return console to userspace. */ |
extern void machine_release_console(void); |
/** Maps HW devices to the kernel address space using #hw_map. */ |
extern void machine_hw_map_init(void); |
/** Starts timer. */ |
extern void machine_timer_irq_start(void); |
/** Halts CPU. */ |
extern void machine_cpu_halt(void); |
/** Returns size of available memory. |
* |
* @return Size of available memory. |
*/ |
extern size_t machine_get_memory_size(void); |
/** Prints a character. |
* |
* @param ch Character to be printed. |
*/ |
extern void machine_debug_putc(char ch); |
/** Interrupt exception handler. |
* |
* @param exc_no Interrupt exception number. |
* @param istate Saved processor state. |
*/ |
extern void machine_irq_exception(int exc_no, istate_t *istate); |
/** Returns address of framebuffer device. |
* |
* @return Address of framebuffer device. |
*/ |
extern uintptr_t machine_get_fb_address(void); |
#ifdef MACHINE_GXEMUL_TESTARM |
# define machine_console_init(devno) gxemul_console_init(devno) |
# define machine_grab_console gxemul_grab_console |
# define machine_release_console gxemul_release_console |
# define machine_hw_map_init gxemul_hw_map_init |
# define machine_timer_irq_start gxemul_timer_irq_start |
# define machine_cpu_halt gxemul_cpu_halt |
# define machine_get_memory_size gxemul_get_memory_size |
# define machine_debug_putc(ch) gxemul_debug_putc(ch) |
# define machine_irq_exception(exc_no, istate) gxemul_irq_exception(exc_no, istate) |
# define machine_get_fb_address gxemul_get_fb_address |
#endif |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/boot.h |
---|
0,0 → 1,76 |
/* |
* Copyright (c) 2006 Martin Decky |
* 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 |
* @brief Bootinfo declarations. |
* |
* Reflects boot/arch/arm32/loader/main.h. |
*/ |
#ifndef KERN_arm32_BOOT_H_ |
#define KERN_arm32_BOOT_H_ |
#include <arch/types.h> |
/** Maximum number of tasks in the #bootinfo_t struct. */ |
#define TASKMAP_MAX_RECORDS 32 |
/** Struct holding information about single loaded uspace task. */ |
typedef struct { |
/** Address where the task was placed. */ |
uintptr_t addr; |
/** Size of the task's binary. */ |
uint32_t size; |
} utask_t; |
/** Struct holding information about loaded uspace tasks. */ |
typedef struct { |
/** Number of loaded tasks. */ |
uint32_t cnt; |
/** Array of loaded tasks. */ |
utask_t tasks[TASKMAP_MAX_RECORDS]; |
} bootinfo_t; |
/** Bootinfo that is filled in #kernel_image_start. */ |
extern bootinfo_t bootinfo; |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/atomic.h |
---|
26,10 → 26,10 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
/** @file |
* @brief Atomic operations. |
*/ |
42,86 → 42,76 |
* @param i Value to be added. |
* |
* @return Value after addition. |
* |
*/ |
static inline long atomic_add(atomic_t *val, int i) |
{ |
int ret; |
volatile long *mem = &(val->count); |
volatile long * mem = &(val->count); |
asm volatile ( |
"1:\n" |
"ldr r2, [%[mem]]\n" |
"add r3, r2, %[i]\n" |
"str r3, %[ret]\n" |
"swp r3, r3, [%[mem]]\n" |
"cmp r3, r2\n" |
"bne 1b\n" |
: [ret] "=m" (ret) |
: [mem] "r" (mem), [i] "r" (i) |
"1: \n" |
"ldr r2, [%1] \n" |
"add r3, r2, %2 \n" |
"str r3, %0 \n" |
"swp r3, r3, [%1] \n" |
"cmp r3, r2 \n" |
"bne 1b \n" |
: "=m" (ret) |
: "r" (mem), "r" (i) |
: "r3", "r2" |
); |
return ret; |
} |
/** Atomic increment. |
* |
* @param val Variable to be incremented. |
*/ |
static inline void atomic_inc(atomic_t *val) |
{ |
atomic_add(val, 1); |
} |
static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); } |
/** Atomic decrement. |
* |
* @param val Variable to be decremented. |
*/ |
static inline void atomic_dec(atomic_t *val) { |
atomic_add(val, -1); |
} |
static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); } |
/** Atomic pre-increment. |
* |
* @param val Variable to be incremented. |
* @return Value after incrementation. |
*/ |
static inline long atomic_preinc(atomic_t *val) |
{ |
return atomic_add(val, 1); |
} |
static inline long atomic_preinc(atomic_t *val) { return atomic_add(val, 1); } |
/** Atomic pre-decrement. |
* |
* @param val Variable to be decremented. |
* @return Value after decrementation. |
*/ |
static inline long atomic_predec(atomic_t *val) |
{ |
return atomic_add(val, -1); |
} |
static inline long atomic_predec(atomic_t *val) { return atomic_add(val, -1); } |
/** Atomic post-increment. |
* |
* @param val Variable to be incremented. |
* @return Value before incrementation. |
*/ |
static inline long atomic_postinc(atomic_t *val) |
{ |
return atomic_add(val, 1) - 1; |
} |
static inline long atomic_postinc(atomic_t *val) { return atomic_add(val, 1) - 1; } |
/** Atomic post-decrement. |
* |
* @param val Variable to be decremented. |
* @return Value before decrementation. |
*/ |
static inline long atomic_postdec(atomic_t *val) |
{ |
return atomic_add(val, -1) + 1; |
} |
static inline long atomic_postdec(atomic_t *val) { return atomic_add(val, -1) + 1; } |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/asm.h |
---|
26,10 → 26,10 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
/** @file |
* @brief Declarations of functions implemented in assembly. |
*/ |
36,7 → 36,6 |
#ifndef KERN_arm32_ASM_H_ |
#define KERN_arm32_ASM_H_ |
#include <typedefs.h> |
#include <arch/types.h> |
#include <arch/stack.h> |
#include <config.h> |
47,59 → 46,30 |
{ |
} |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
/** Return base address of current stack. |
* |
* |
* Return the base address of the current stack. |
* The stack is assumed to be STACK_SIZE bytes long. |
* The stack must start on page boundary. |
* |
*/ |
static inline uintptr_t get_stack_base(void) |
{ |
uintptr_t v; |
asm volatile ( |
"and %[v], sp, %[size]\n" |
: [v] "=r" (v) |
: [size] "r" (~(STACK_SIZE - 1)) |
"and %0, sp, %1\n" |
: "=r" (v) |
: "r" (~(STACK_SIZE-1)) |
); |
return v; |
} |
extern void cpu_halt(void); |
extern void asm_delay_loop(uint32_t t); |
extern void userspace_asm(uintptr_t ustack, uintptr_t uspace_uarg, |
uintptr_t entry); |
extern void userspace_asm(uintptr_t ustack, uintptr_t uspace_uarg, uintptr_t entry); |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/cpu.h |
---|
42,22 → 42,24 |
/** Struct representing ARM CPU identifiaction. */ |
typedef struct { |
/** Implementator (vendor) number. */ |
uint32_t imp_num; |
uint32_t imp_num; |
/** Variant number. */ |
uint32_t variant_num; |
uint32_t variant_num; |
/** Architecture number. */ |
uint32_t arch_num; |
uint32_t arch_num; |
/** Primary part number. */ |
uint32_t prim_part_num; |
uint32_t prim_part_num; |
/** Revision number. */ |
uint32_t rev_num; |
uint32_t rev_num; |
} cpu_arch_t; |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/interrupt.h |
---|
37,7 → 37,6 |
#define KERN_arm32_INTERRUPT_H_ |
#include <arch/types.h> |
#include <arch/exception.h> |
/** Initial size of exception dispatch table. */ |
#define IVT_ITEMS 6 |
/branches/arm/kernel/arch/arm32/include/regutils.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** |
37,6 → 37,7 |
#ifndef KERN_arm32_REGUTILS_H_ |
#define KERN_arm32_REGUTILS_H_ |
#define STATUS_REG_IRQ_DISABLED_BIT (1 << 7) |
#define STATUS_REG_MODE_MASK 0x1f |
52,26 → 53,21 |
#define UNDEFINED_MODE 0x1b |
#define SYSTEM_MODE 0x1f |
/* [CS]PRS manipulation macros */ |
#define GEN_STATUS_READ(nm,reg) \ |
static inline uint32_t nm## _status_reg_read(void) \ |
{ \ |
uint32_t retval; \ |
asm volatile( \ |
"mrs %[retval], " #reg \ |
: [retval] "=r" (retval) \ |
); \ |
return retval; \ |
} |
static inline uint32_t nm## _status_reg_read(void) \ |
{ \ |
uint32_t retval; \ |
asm volatile("mrs %0, " #reg : "=r"(retval)); \ |
return retval; \ |
} |
#define GEN_STATUS_WRITE(nm,reg,fieldname, field) \ |
static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \ |
{ \ |
asm volatile( \ |
"msr " #reg "_" #field ", %[value]" \ |
:: [value] "r" (value) \ |
); \ |
} |
static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \ |
{ \ |
asm volatile("msr " #reg "_" #field ", %0" : : "r"(value)); \ |
} |
/** Returns the value of CPSR (Current Program Status Register). */ |
/branches/arm/kernel/arch/arm32/include/memstr.h |
---|
38,10 → 38,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
#endif |
/branches/arm/kernel/arch/arm32/include/proc/thread.h |
---|
47,3 → 47,4 |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/asm/boot.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
36,10 → 36,28 |
#ifndef KERN_arm32_ASM_BOOT_H_ |
#define KERN_arm32_ASM_BOOT_H_ |
/** Size of a temporary stack used for initial kernel start. */ |
#define TEMP_STACK_SIZE 0x100 |
#define TEMP_STACK_SIZE 0x100 |
#ifndef __ASM__ |
/** Kernel entry point. |
* |
* Implemented in assembly. Copies boot_bootinfo (declared as bootinfo in |
* boot/arch/arm32/loader/main.c) to #bootinfo struct. Then jumps to |
* #arch_pre_main and #main_bsp. |
* |
* @param entry Entry point address (not used). |
* @param boot_bootinfo Struct holding information about loaded tasks. |
* @param bootinfo_size Size of the bootinfo structure. |
*/ |
void kernel_image_start(void *entry, void *boot_bootinfo, unsigned int bootinfo_size); |
#endif |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/byteorder.h |
---|
0,0 → 1,62 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* 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 |
* @brief Endianness definitions. |
*/ |
#ifndef KERN_arm32_BYTEORDER_H_ |
#define KERN_arm32_BYTEORDER_H_ |
#include <byteorder.h> |
#ifdef BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#else |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#endif |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/debug/print.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2007 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 arm32 |
* @{ |
*/ |
/** @file |
* @brief Debug printing functions. |
*/ |
#ifndef KERN_arm32_DEBUG_PRINT_H_ |
#define KERN_arm32_DEBUG_PRINT_H_ |
#include <stdarg.h> |
#include <arch/types.h> |
extern void debug_puts(const char *str); |
extern void debug_printf(const char *fmt, ...); |
#ifdef CONFIG_DEBUG |
# define dprintf(arg1...) debug_printf(arg1) |
# define dputs(arg1) debug_puts(arg1) |
#else |
# define dprintf(arg1...) |
# define dputs(arg1) |
#endif |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/console.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2007 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 arm32 |
* @{ |
*/ |
/** @file |
* @brief Console. |
*/ |
#ifndef KERN_arm32_CONSOLE_H_ |
#define KERN_arm32_CONSOLE_H_ |
/** Initializes console. |
* |
* @param devno Console device number. |
*/ |
extern void console_init(devno_t devno); |
#endif |
/** @} |
*/ |
/branches/arm/kernel/arch/arm32/include/context.h |
---|
46,9 → 46,7 |
#include <arch/types.h> |
/** Thread context containing registers that must be preserved across function |
* calls. |
*/ |
/** Thread context containing registers that must be preserved across function calls. */ |
typedef struct { |
uint32_t cpu_mode; |
uintptr_t sp; |
/branches/arm/kernel/arch/arm32/include/stack.h |
---|
38,9 → 38,7 |
#define STACK_ITEM_SIZE 4 |
/** See <a href="http://www.arm.com/support/faqdev/14269.html">ABI</a> for |
* details |
*/ |
/** see <a href="http://www.arm.com/support/faqdev/14269.html">ABI</a> for details */ |
#define STACK_ALIGNMENT 8 |
#endif |
/branches/arm/kernel/arch/arm32/include/arch.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
36,26 → 36,6 |
#ifndef KERN_arm32_ARCH_H_ |
#define KERN_arm32_ARCH_H_ |
#define TASKMAP_MAX_RECORDS 32 |
#define CPUMAP_MAX_RECORDS 32 |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
#include <typedefs.h> |
typedef struct { |
uintptr_t addr; |
uint32_t size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} utask_t; |
typedef struct { |
uint32_t cnt; |
utask_t tasks[TASKMAP_MAX_RECORDS]; |
} bootinfo_t; |
extern void arch_pre_main(void *entry, bootinfo_t *bootinfo); |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/include/barrier.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
39,16 → 39,13 |
/* |
* TODO: implement true ARM memory barriers for macros below. |
*/ |
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory") |
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory") |
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory") |
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory") |
#define memory_barrier() asm volatile ("" ::: "memory") |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define memory_barrier() asm volatile ("" ::: "memory") |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define smc_coherence(a) |
#define smc_coherence_block(a, l) |
#endif |
/** @} |
/branches/arm/kernel/arch/arm32/Makefile.inc |
---|
29,43 → 29,67 |
## Toolchain configuration |
# |
BFD_NAME = elf32-littlearm |
BFD_NAME = elf32-little |
BFD_ARCH = arm |
BFD = binary |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm |
TOOLCHAIN_DIR = /usr/local/arm |
ATSIGN = % |
KERNEL_LOAD_ADDRESS = 0x80200000 |
GCC_CFLAGS += -fno-zero-initialized-in-bss |
ifeq ($(MACHINE), gxemul_testarm) |
DMACHINE = MACHINE_GXEMUL_TESTARM |
endif |
BITS = 32 |
ENDIANESS = LE |
CFLAGS += -fno-zero-initialized-in-bss |
DEFS += -D__32_BITS__ -DKERNEL_LOAD_ADDRESS=$(KERNEL_LOAD_ADDRESS) -D$(DMACHINE) |
# Compile with framebuffer support |
ifeq ($(CONFIG_FB), y) |
DEFS += -DCONFIG_FB |
endif |
## Compile with hierarchical page tables support. |
# |
CONFIG_PAGE_PT = y |
DEFS += -DCONFIG_PAGE_PT |
## Compile with support for address space identifiers. |
# |
# no HW support for ASIDs |
#CONFIG_ASID = y |
#CONFIG_ASID_FIFO = y |
## Compile with support with software division and multiplication. |
# |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(KARCH)/src/start.S \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/exc_handler.S \ |
arch/$(KARCH)/src/arm32.c \ |
arch/$(KARCH)/src/machine_func.c \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/dummy.S \ |
arch/$(KARCH)/src/panic.S \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/userspace.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/mm/page_fault.c |
ifeq ($(MACHINE), testarm) |
ARCH_SOURCES += arch/$(KARCH)/src/mach/testarm/testarm.c |
else ifeq ($(MACHINE), integratorcp) |
ARCH_SOURCES += arch/$(KARCH)/src/mach/integratorcp/integratorcp.c |
arch/$(ARCH)/src/start.S \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/arm32.c \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/dummy.S \ |
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/mm/tlb.c \ |
arch/$(ARCH)/src/mm/memory_init.c \ |
arch/$(ARCH)/src/mm/page_fault.c |
ifeq ($(MACHINE), gxemul_testarm) |
ARCH_SOURCES += arch/$(ARCH)/src/drivers/gxemul.c |
endif |
ifeq ($(CONFIG_PL050), y) |
ARCH_SOURCES += genarch/src/drivers/pl050/pl050.c |
endif |
/branches/arm/kernel/arch/arm32/_link.ld.in |
---|
1,16 → 1,15 |
/* |
* ARM linker script |
* |
* ARM linker script |
* |
* kernel text |
* kernel data |
* |
* |
*/ |
#define KERNEL_LOAD_ADDRESS 0x80200000 |
OUTPUT_ARCH(arm) |
ENTRY(kernel_image_start) |
ENTRY(kernel_image_start) |
SECTIONS { |
. = KERNEL_LOAD_ADDRESS; |
.text : { |
20,29 → 19,29 |
} |
.data : { |
kdata_start = .; |
*(.data); /* initialized data */ |
*(.data); /* initialized data */ |
hardcoded_ktext_size = .; |
LONG(ktext_end - ktext_start); |
LONG(ktext_end - ktext_start); |
hardcoded_kdata_size = .; |
LONG(kdata_end - kdata_start); |
hardcoded_load_address = .; |
LONG(KERNEL_LOAD_ADDRESS); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.rodata*); |
*(.sdata); |
*(.reginfo); |
symbol_table = .; |
*(symtab.*); |
*(symtab.*); |
} |
.sbss : { |
*(.sbss); |
*(.scommon); |
} |
kdata_end = .; |
/DISCARD/ : { |
*(.mdebug*); |
*(.pdr); |
49,4 → 48,5 |
*(.comment); |
*(.note); |
} |
} |