Initial commit

This commit is contained in:
Bahadir Balban
2008-01-13 13:53:52 +00:00
commit e2b791a3d8
789 changed files with 95825 additions and 0 deletions

143
include/l4/arch/arm/asm.h Normal file
View File

@@ -0,0 +1,143 @@
/*********************************************************************
*
* Copyright (C) 2003-2005, National ICT Australia (NICTA)
*
* File path: arch/arm/asm.h
* Description: Assembler macros etc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* $Id: asm.h,v 1.4 2004/12/02 00:15:07 cvansch Exp $
*
********************************************************************/
#ifndef __ARCH_ARM_ASM_H__
#define __ARCH_ARM_ASM_H__
/* Top nibble of the byte denotes irqs/fiqs disabled, ARM state */
#define ARM_MODE_MASK 0x1F
#define ARM_MODE_SVC 0x13
#define ARM_MODE_UND 0x1B
#define ARM_MODE_ABT 0x17
#define ARM_MODE_IRQ 0x12
#define ARM_MODE_FIQ 0x11
#define ARM_MODE_USR 0x10
#define ARM_MODE_SYS 0x1F
#define ARM_NOIRQ_SVC 0xD3
#define ARM_NOIRQ_UND 0xDB
#define ARM_NOIRQ_ABT 0xD7
#define ARM_NOIRQ_IRQ 0xD2
#define ARM_NOIRQ_FIQ 0xD1
#define ARM_NOIRQ_USR 0xD0
#define ARM_NOIRQ_SYS 0xDF
/* For enabling *clear* these bits */
#define ARM_IRQ_BIT 0x80
#define ARM_FIQ_BIT 0x40
/* Notes about ARM instructions:
*
* TST instruction:
*
* Essentially TST "AND"s two values and the result affects the Z (Zero bit)
* in CPSR, which can be used for conditions. For example in:
*
* TST r0, #VALUE
*
* If anding r0 and #VALUE results in a positive value (i.e. they have a
* common bit set as 1) then Z bit is 0, which accounts for an NE (Not equal)
* condition. Consequently, e.g. a BEQ instruction would be skipped and a BNE
* would be executed.
*
* In the opposite case, r0 and #VALUE has no common bits, and anding them
* results in 0. This means Z bit is 1, and any EQ instruction coming afterwards
* would be executed.
*
* I have made this explanation here because I think the behaviour of the Z bit
* is kind of hacky in TST. Normally Z bit is used for equivalence (e.g. CMP
* instruction) but in TST case even if two values were equal the Z bit could
* point to an NE or EQ condition depending on whether the values have non-zero
* bits.
*/
#define dbg_stop_here() __asm__ __volatile__ ( "bkpt #0\n" :: )
#define BEGIN_PROC(name) \
.global name; \
.type name,function; \
.align; \
name:
#define END_PROC(name) \
.fend_##name: \
.size name,.fend_##name - name;
/* Functions to generate symbols in the output file
* with correct relocated address for debugging
*/
#define TRAPS_BEGIN_MARKER \
.balign 4096; \
.section .data.traps; \
__vector_vaddr:
#define VECTOR_WORD(name) \
.equ vector_##name, (name - __vector_vaddr + 0xffff0000); \
.global vector_##name; \
.type vector_##name,object; \
.size vector_##name,4; \
name:
/* NOTE: These are fairly useless vector relocation macros. Why? Because
* ARM branch instructions are *relative* anyway. */
#define BEGIN_PROC_TRAPS(name) \
.global name; \
.type name,function; \
.equ vector_##name, (name - __vector_vaddr + 0xffff0000); \
.global vector_##name; \
.type vector_##name,function; \
.align; \
name:
#define END_PROC_TRAPS(name) \
.fend_##name: \
.equ .fend_vector_##name, (.fend_##name - __vector_vaddr + 0xffff0000); \
.size name,.fend_##name - name; \
.size vector_##name,.fend_vector_##name - vector_##name;
#define BEGIN_PROC_KIP(name) \
.global name; \
.type name,function; \
.align; \
name:
#define END_PROC_KIP(name) \
.fend_##name: \
.size name,.fend_##name - name;
#define CHECK_ARG(a, b) \
" .ifnc " a ", " b " \n" \
" .err \n" \
" .endif \n" \
#endif /* __ARCH_ARM_ASM_H__ */

View File

@@ -0,0 +1,25 @@
#ifndef __BOOTDESC_H__
#define __BOOTDESC_H__
/* Supervisor task at load time. */
struct svc_image {
char name[16];
unsigned int phys_start;
unsigned int phys_end;
} __attribute__((__packed__));
/* Supervisor task descriptor at load time */
struct bootdesc {
int desc_size;
int total_images;
struct svc_image images[];
} __attribute__((__packed__));
#if defined (__KERNEL__)
extern struct bootdesc *bootdesc;
void read_bootdesc(void);
void copy_bootdesc(void);
#endif
#endif /* __BOOTDESC_H__ */

View File

@@ -0,0 +1,88 @@
/*
* Definitions for exception support on ARM
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __ARCH_EXCEPTIONS_H__
#define __ARCH_EXCEPTIONS_H__
#include INC_ARCH(asm.h)
static inline void enable_irqs()
{
__asm__ __volatile__(
"mrs r0, cpsr_fc\n"
"bic r0, r0, #0x80\n" /* ARM_IRQ_BIT */
"msr cpsr_fc, r0\n"
);
}
static inline int irqs_enabled()
{
register unsigned int enabled asm("r1");
__asm__ __volatile__(
"mrs r0, cpsr_fc\n"
"tst r0, #0x80\n" /* ARM_IRQ_BIT. See asm.h for TST inst. */
"moveq r1, #1\n"
"movne r1, #0\n"
);
return enabled;
}
static inline void disable_irqs()
{
__asm__ __volatile__(
"mrs r0, cpsr_fc\n"
"orr r0, r0, #0x80\n" /* ARM_IRQ_BIT */
"msr cpsr_fc, r0\n"
);
}
#if 0 /* These will be useful for nested irq disable/enable calls */
/* Disable the irqs unconditionally, but also keep the previous state such that
* if it was already disabled before the call, the restore call would retain
* this state. */
static inline void irq_local_disable_save(unsigned long *flags)
{
unsigned long temp;
__asm__ __volatile__ (
"mrs %0, cpsr_fc\n"
"orr %1, %0, #0x80\n"
"msr cpsr_fc, %1\n"
: "=r"(*flags), "=r" (temp)
);
}
/* Simply change it back to original state supplied in @flags. This might enable
* or retain disabled state of the irqs for example. Useful for nested calls. */
static inline void irq_local_restore(unsigned long flags)
{
__asm__ __volatile__ (
"msr cpsr_fc, %0\n"
: "r" (flags)
);
}
#endif
static inline void irq_local_enable()
{
enable_irqs();
}
static inline void irq_local_disable()
{
disable_irqs();
}
/* This is filled on entry to irq handler, only if a process was interrupted.*/
extern unsigned int preempted_psr;
static inline int in_kernel()
{
return (((preempted_psr & ARM_MODE_MASK) == ARM_MODE_SVC)) ? 1 : 0;
}
static inline int in_user()
{
return !in_kernel();
}
#endif

12
include/l4/arch/arm/io.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef __ARM_IO_H__
#define __ARM_IO_H__
/*
* Arch-specific io functions/macros.
*
* Copyright (C) 2007 Bahadir Balban
*/
#define read(val, address) val = *((volatile unsigned int *) address)
#define write(val, address) *((volatile unsigned int *) address) = val
#endif /* __ARM_IO_H__ */

View File

@@ -0,0 +1,34 @@
/*
* Linker-defined variables
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __ARCH_ARM_LINKER_H__
#define __ARCH_ARM_LINKER_H__
extern unsigned long _start_kernel[];
extern unsigned long _start_text[];
extern unsigned long _end_text[];
extern unsigned long _start_data[];
extern unsigned long _end_data[];
extern unsigned long _start_vectors[];
extern unsigned long arm_high_vector[];
extern unsigned long _end_vectors[];
extern unsigned long _start_kip[];
extern unsigned long _end_kip[];
extern unsigned long _start_ptab[];
extern unsigned long _end_ptab[];
extern unsigned long _bootstack[];
extern unsigned long _end_kernel[];
extern unsigned long _start_kspace[];
extern unsigned long _start_pmd[];
extern unsigned long _end_pmd[];
extern unsigned long _end_kspace[];
extern unsigned long _end[];
/* Link markers that get modified at runtime */
unsigned long __svc_images_end;
unsigned long __pt_start;
unsigned long __pt_end;
#endif /* __ARCH_ARM_LINKER_H__ */

View File

@@ -0,0 +1,15 @@
#ifndef __ARCH_MUTEX_H__
#define __ARCH_MUTEX_H__
/*
* ARM specific low-level mutex interfaces
*
* Copyright (C) 2007 Bahadir Balban
*/
/* TODO: The return types could be improved for debug checking */
void __spin_lock(unsigned int *s);
void __spin_unlock(unsigned int *s);
unsigned int __mutex_lock(unsigned int *m);
void __mutex_unlock(unsigned int *m);
#endif

View File

@@ -0,0 +1,87 @@
/*
*
* Simple linker script
*
* Copyright (C) 2007 Bahadir Balban
*
*/
/* FIXME:
* Currently we can't include cpp #defines in linker script.
* Check that below offsets are coherent with offsets.h
*/
phys_addr_base = 0x100000;
kern_offset = 0xF0000000;
virt_addr_base = phys_addr_base + kern_offset;
/* A temporary boot stack is used before a proper kernel stack is set up */
_bootstack_physical = _bootstack - kern_offset;
/* The symbols are linked at virtual addresses. So is _start.
* We must set the entry point to a physical address, so that
* when the image is loaded, it doesn't jump to a non existing
* virtual address.
*/
_start_physical = phys_addr_base;
ENTRY(_start_physical)
SECTIONS
{
. = virt_addr_base;
_start_kernel = .;
.text : AT (ADDR(.text) - kern_offset)
{
_start_text = .;
/* Make sure head.S comes first */
/* *head.o(.text) This only works when given its full path. Bad limitation. */
*(.text.head)
*(.text)
_end_text = .;
}
. = ALIGN(4);
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - kern_offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - kern_offset) { *(.rodata1) }
.data : AT (ADDR(.data) - kern_offset)
{
_start_data = .;
*(.data)
_start_vectors = .;
*(.data.vectors)
. = ALIGN(4K);
_end_vectors = .;
_start_kip = .;
*(.data.kip)
. = ALIGN(4K);
_end_kip = .;
_start_syscalls = .;
*(.data.syscalls)
. = ALIGN(4K);
_end_syscalls = .;
_end_data = .;
}
.bss : AT (ADDR(.bss) - kern_offset)
{
*(.bss)
}
. = ALIGN(4K);
. += 0x2000; /* This is required as the link counter does not seem
* to increment for the bss section
* TODO: Change this with PAGE_SIZE */
_bootstack = .;
_end_kernel = .;
. = ALIGN(1M);
.kspace : AT(ADDR(.kspace) - kern_offset)
{
_start_kspace = .;
*(.kspace.pgd)
. = ALIGN(4K);
_start_pmd = .;
*(.kspace.pmd)
_end_pmd = .;
_end_kspace = .;
}
_end = .;
}

View File

@@ -0,0 +1,18 @@
#ifndef __ARCH_TYPES_H__
#define __ARCH_TYPES_H__
#if !defined(__ASSEMBLY__)
typedef unsigned long long u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef signed long long s64;
typedef signed int s32;
typedef signed short s16;
typedef signed char s8;
/* Thread/Space id type */
typedef unsigned int l4id_t;
#endif /* !__ASSEMBLY__ */
#endif /* !__ARCH_TYPES_H__ */

View File

@@ -0,0 +1,13 @@
/*
*
* Copyright (C) 2005 Bahadir Balban
*
*/
#ifndef __ARM926EJS__H__
#define __ARM926EJS__H__
#endif /* __ARM926EJS__H__ */

147
include/l4/arch/arm/v5/mm.h Normal file
View File

@@ -0,0 +1,147 @@
/*
* ARM v5-specific virtual memory details
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __V5_MM_H__
#define __V5_MM_H__
/* ARM specific definitions */
#define ARM_SECTION_SIZE SZ_1MB
#define ARM_SECTION_MASK (ARM_SECTION_SIZE - 1)
#define ARM_SECTION_BITS 20
#define ARM_PAGE_SIZE SZ_4K
#define ARM_PAGE_MASK 0xFFF
#define ARM_PAGE_BITS 12
#define PGD_SIZE SZ_4K * 4
#define PGD_ENTRY_TOTAL SZ_4K
#define PGD_TYPE_MASK 0x3
#define PGD_COARSE_ALIGN_MASK 0xFFFFFC00
#define PGD_SECTION_ALIGN_MASK 0xFFF00000
#define PGD_FINE_ALIGN_MASK 0xFFFFF000
#define PGD_TYPE_FAULT 0
#define PGD_TYPE_COARSE 1
#define PGD_TYPE_SECTION 2
#define PGD_TYPE_FINE 3
#define PMD_TYPE_MASK 0x3
#define PMD_TYPE_FAULT 0
#define PMD_TYPE_LARGE 1
#define PMD_TYPE_SMALL 2
#define PMD_TYPE_TINY 3
/* Permission field offsets */
#define SECTION_AP0 10
#define PMD_SIZE SZ_1K
#define PMD_ENTRY_TOTAL 256
#define PMD_MAP_SIZE SZ_1MB
/* Type-checkable page table elements */
typedef u32 pgd_t;
typedef u32 pmd_t;
typedef u32 pte_t;
/* Page global directory made up of pgd_t entries */
typedef struct pgd_table {
pgd_t entry[PGD_ENTRY_TOTAL];
} pgd_table_t;
/* Page middle directory made up of pmd_t entries */
typedef struct pmd_table {
pmd_t entry[PMD_ENTRY_TOTAL];
} pmd_table_t;
/* Applies for both small and large pages */
#define PAGE_AP0 4
#define PAGE_AP1 6
#define PAGE_AP2 8
#define PAGE_AP3 10
/* Permission values with rom and sys bits ignored */
#define SVC_RW_USR_NONE 1
#define SVC_RW_USR_RO 2
#define SVC_RW_USR_RW 3
#define PTE_PROT_MASK (0xFF << 4)
#define CACHEABILITY 3
#define BUFFERABILITY 2
#define cacheable (1 << CACHEABILITY)
#define bufferable (1 << BUFFERABILITY)
#define uncacheable 0
#define unbufferable 0
/* Helper macros for common cases */
#define __MAP_USR_RW_FLAGS (cacheable | bufferable | (SVC_RW_USR_RW << PAGE_AP0) \
| (SVC_RW_USR_RW << PAGE_AP1) | (SVC_RW_USR_RW << PAGE_AP2) \
| (SVC_RW_USR_RW << PAGE_AP3))
#define __MAP_USR_RO_FLAGS (cacheable | bufferable | (SVC_RW_USR_RO << PAGE_AP0) \
| (SVC_RW_USR_RO << PAGE_AP1) | (SVC_RW_USR_RO << PAGE_AP2) \
| (SVC_RW_USR_RO << PAGE_AP3))
#define __MAP_SVC_RW_FLAGS (cacheable | bufferable | (SVC_RW_USR_NONE << PAGE_AP0) \
| (SVC_RW_USR_NONE << PAGE_AP1) | (SVC_RW_USR_NONE << PAGE_AP2) \
| (SVC_RW_USR_NONE << PAGE_AP3))
#define __MAP_SVC_IO_FLAGS (uncacheable | unbufferable | (SVC_RW_USR_NONE << PAGE_AP0) \
| (SVC_RW_USR_NONE << PAGE_AP1) | (SVC_RW_USR_NONE << PAGE_AP2) \
| (SVC_RW_USR_NONE << PAGE_AP3))
#define __MAP_USR_IO_FLAGS (uncacheable | unbufferable | (SVC_RW_USR_RW << PAGE_AP0) \
| (SVC_RW_USR_RW << PAGE_AP1) | (SVC_RW_USR_RW << PAGE_AP2) \
| (SVC_RW_USR_RW << PAGE_AP3))
/* Abort information */
/*FIXME: Carry all these definitions to an abort.h, Also carry all abort code to abort.c. Much neater!!! */
/* Abort type */
#define ARM_PABT 1
#define ARM_DABT 0
/* The kernel makes use of bit 8 (Always Zero) of FSR to define which type of abort */
#define set_abort_type(fsr, x) { fsr &= ~(1 << 8); fsr |= ((x & 1) << 8); }
#define ARM_FSR_MASK 0xF
#define is_prefetch_abort(fsr) ((fsr >> 8) & 0x1)
#define is_data_abort(fsr) (!is_prefetch_abort(fsr))
/*
* v5 Architecture-defined data abort values for FSR ordered
* in highest to lowest priority.
*/
#define DABT_TERMINAL 0x2
#define DABT_VECTOR 0x0 /* Obsolete */
#define DABT_ALIGN 0x1
#define DABT_EXT_XLATE_LEVEL1 0xC
#define DABT_EXT_XLATE_LEVEL2 0xE
#define DABT_XLATE_SECT 0x5
#define DABT_XLATE_PAGE 0x7
#define DABT_DOMAIN_SECT 0x9
#define DABT_DOMAIN_PAGE 0xB
#define DABT_PERM_SECT 0xD
#define DABT_PERM_PAGE 0xF
#define DABT_EXT_LFETCH_SECT 0x4
#define DABT_EXT_LFETCH_PAGE 0x6
#define DABT_EXT_NON_LFETCH_SECT 0x8
#define DABT_EXT_NON_LFETCH_PAGE 0xA
/* Kernel's data about the fault */
typedef struct fault_kdata {
u32 faulty_pc;
u32 fsr;
u32 far;
pte_t pte;
} __attribute__ ((__packed__)) fault_kdata_t;
void add_section_mapping_init(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags);
void remap_as_pages(void *vstart, void *vend);
void relocate_page_tables(void);
void remove_section_mapping(unsigned long vaddr);
void copy_pgds_by_vrange(pgd_table_t *to, pgd_table_t *from,
unsigned long start, unsigned long end);
#endif /* __V5_MM_H__ */

View File

@@ -0,0 +1,33 @@
#ifndef __MMU__OPS__H__
#define __MMU__OPS__H__
/*
* Prototypes for low level mmu operations
*
* Copyright (C) 2005 Bahadir Balban
*
*/
void arm_set_ttb(unsigned int);
void arm_set_domain(unsigned int);
unsigned int arm_get_domain(void);
void arm_enable_mmu(void);
void arm_enable_icache(void);
void arm_enable_dcache(void);
void arm_enable_wbuffer(void);
void arm_enable_high_vectors(void);
void arm_invalidate_cache(void);
void arm_invalidate_icache(void);
void arm_invalidate_dcache(void);
void arm_clean_invalidate_dcache(void);
void arm_clean_invalidate_cache(void);
void arm_drain_writebuffer(void);
void arm_invalidate_tlb(void);
void arm_invalidate_itlb(void);
void arm_invalidate_dtlb(void);
static inline void arm_enable_caches(void)
{
arm_enable_icache();
arm_enable_dcache();
}
#endif /* __MMU__OPS__H__ */

View File

View File

@@ -0,0 +1,22 @@
#ifndef __LINKER_H__
#define __LINKER_H__
/*
*
* Mock-up copies of variables defined in linker.h
*
* Copyright (C) 2005 Bahadir Balban
*
*/
/* Because no special-case linker.lds is used for tests,
* actual values for these variables are stored in a linker.c
*/
/* Global that determines where free memory starts.
* Normally this is the end address of the kernel image
* in physical memory when it is loaded. See linker.h
* for other architectures.
*/
extern unsigned int _end;
#endif /* __LINKER_H__ */

View File

@@ -0,0 +1,68 @@
/*
* ARM v5-specific virtual memory details
*
* Copyright (C) 2005 Bahadir Balban
*/
#ifndef __V5__MM__H__
#define __V5__MM__H__
/* TODO: Change all LEVEL1_ prefix to PGD and
* shorten the macros in general */
#define LEVEL1_PAGETABLE_SIZE SZ_4K * 4
#define LEVEL1_PAGETABLE_NUMENT SZ_4K
#define LEVEL1_PTE_TYPE_MASK 0x3
#define LEVEL1_COARSE_ALIGN_MASK 0xFFFFFC00
#define LEVEL1_SECTION_ALIGN_MASK 0xFFF00000
#define LEVEL1_FINE_ALIGN_MASK 0xFFFFF000
#define LEVEL1_TYPE_FAULT 0
#define LEVEL1_TYPE_COARSE 1
#define LEVEL1_TYPE_SECTION 2
#define LEVEL1_TYPE_FINE 3
#define LEVEL2_TYPE_FAULT 0
#define LEVEL2_TYPE_LARGE 1
#define LEVEL2_TYPE_SMALL 2
#define LEVEL2_TYPE_TINY 3
/* Permission field offsets */
#define SECTION_AP0 10
#define PMD_SIZE SZ_1K
#define PMD_NUM_PAGES 256
/* Applies for both small and large pages */
#define PAGE_AP0 4
#define PAGE_AP1 6
#define PAGE_AP2 8
#define PAGE_AP3 10
/* Permission values with rom and sys bits ignored */
#define SVC_RW_USR_NONE 1
#define SVC_RW_USR_RO 2
#define SVC_RW_USR_RW 3
#define CACHEABILITY 3
#define BUFFERABILITY 4
#define cacheable (1 << CACHEABILITY)
#define bufferable (1 << BUFFERABILITY)
static inline void
__add_section_mapping_init(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags)
{
}
static inline void
add_section_mapping_init(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags)
{
}
static inline void
add_mapping(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags)
{
}
static inline void remove_mapping(unsigned int vaddr)
{
}
#endif /* __V5__MM__H__ */

View File

@@ -0,0 +1,13 @@
#ifndef __ARCH__ARM__TYPES_H__
#define __ARCH__ARM__TYPES_H__
typedef unsigned long long u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef signed long long s64;
typedef signed int s32;
typedef signed short s16;
typedef signed char s8;
#endif /* !__ARCH__ARM__TYPES_H__ */