Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2463 → Rev 2464

/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