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