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

169
include/l4/api/errno.h Normal file
View File

@@ -0,0 +1,169 @@
#ifndef __ERRNO_H__
#define __ERRNO_H__
/*
* LICENSE:
* Taken from linux errno.h
*/
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#ifdef __KERNEL__
/* Should never be seen by user programs */
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */
#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
/* Defined for the NFSv3 protocol */
#define EBADHANDLE 521 /* Illegal NFS file handle */
#define ENOTSYNC 522 /* Update synchronization mismatch */
#define EBADCOOKIE 523 /* Cookie is stale */
#define ENOTSUPP 524 /* Operation is not supported */
#define ETOOSMALL 525 /* Buffer or request is too small */
#define ESERVERFAULT 526 /* An untranslatable error occurred */
#define EBADTYPE 527 /* Type not supported by server */
#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
#define EIOCBQUEUED 529 /* iocb queued, will get completion event */
#define EIOCBRETRY 530 /* iocb queued, will trigger a retry */
#endif /* __KERNEL__ */
#endif /* __ERRNO_H__ */

29
include/l4/api/ipc.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef __IPC_H__
#define __IPC_H__
#define L4_NILTHREAD -1
#define L4_ANYTHREAD -2
#define L4_IPC_TAG_MR_OFFSET 0
/* To synchronise two threads */
#define L4_IPC_TAG_WAIT 0
/* Pagefault */
#define L4_IPC_TAG_PFAULT 2
#if defined (__KERNEL__) /* These are kernel internal calls */
/* A helper call for sys_ipc() or internally created ipc paths. */
int ipc_send(l4id_t tid);
/*
* This version sends an extra wait ipc to its receiver so that
* the receiver can explicitly make it runnable later by accepting
* this wait ipc.
*/
int ipc_sendwait(l4id_t tid);
#endif
#endif /* __IPC_H__ */

98
include/l4/api/kip.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Kernel Interface Page
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __KIP_H__
#define __KIP_H__
/* FIXME: LICENCE: Taken from a forum post. Must reimplement with GPL terms */
#define __YEAR__ ((((__DATE__ [7] - '0') * 10 + (__DATE__ [8] - '0')) * 10 \
+ (__DATE__ [9] - '0')) * 10 + (__DATE__ [10] - '0'))
#define __MONTH__ (__DATE__ [2] == 'n' ? (__DATE__ [1] == 'a' ? 0 : 5) \
: __DATE__ [2] == 'b' ? 1 \
: __DATE__ [2] == 'r' ? (__DATE__ [0] == 'M' ? 2 : 3) \
: __DATE__ [2] == 'y' ? 4 \
: __DATE__ [2] == 'l' ? 6 \
: __DATE__ [2] == 'g' ? 7 \
: __DATE__ [2] == 'p' ? 8 \
: __DATE__ [2] == 't' ? 9 \
: __DATE__ [2] == 'v' ? 10 : 11)
#define __DAY__ ((__DATE__ [4] == ' ' ? 0 : __DATE__ [4] - '0') * 10 \
+ (__DATE__ [5] - '0'))
//#define DATE_AS_INT (((YEAR - 2000) * 12 + MONTH) * 31 + DAY)
struct kernel_desc {
u16 rsrv;
u8 subid;
u8 id;
u16 gendate;
u16 date_rsrv;
u16 subsubver;
u8 subver;
u8 ver;
u32 supplier;
} __attribute__((__packed__));
/* Experimental KIP with non-standard offsets */
struct kip {
/* System descriptions */
u32 magic;
u16 version_rsrv;
u8 api_subversion;
u8 api_version;
u32 api_flags;
u32 kmem_reclaim;
u32 kmem_grant;
u32 space_control;
u32 thread_control;
u32 ipc_control;
u32 map;
u32 ipc;
u32 kread;
u32 unmap;
u32 exchange_registers;
u32 thread_switch;
u32 schedule;
u32 getid;
u32 arch_syscall0;
u32 arch_syscall1;
u32 arch_syscall2;
u32 arch_syscall3;
struct kernel_desc kdesc;
} __attribute__((__packed__));
/*
* Task id defs for priviledged server tasks. These are dynamically allocated
* from the id pool, but still the pool should allocate them in this order.
*/
#define PAGER_TID 0
#define VFS_TID 1
#define BLKDEV_TID 2
#define KERNEL_TID 3
#define MAX_PREDEFINED_TID KERNEL_TID
#define MIN_PREDEFINED_TID 0
#define __PAGERNAME__ "mm0"
#define __KERNELNAME__ "code0"
#define __VFSNAME__ "fs0"
#define __BLKDEVNAME__ "blkdev0"
#define KDATA_PAGE_MAP 0
#define KDATA_BOOTDESC 1
#define KDATA_BOOTDESC_SIZE 2
#if defined (__KERNEL__)
extern struct kip kip;
#endif /* __KERNEL__ */
#endif /* __KIP_H__ */

18
include/l4/api/space.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef __API_SPACE_H__
#define __API_SPACE_H__
enum space_control_opcode {
SPCCTRL_SHM = 0
};
#if 0
struct shm_kdata {
l4id_t creator;
unsigned long npages;
unsigned long server_pfn;
unsigned long client_pfn;
};
#endif
#endif /* __API_SPACE_H__ */

43
include/l4/api/syscall.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* Syscall offsets in the syscall page.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __SYSCALL_H__
#define __SYSCALL_H__
#include INC_GLUE(syscall.h)
#define syscall_offset_mask 0xFF
#define sys_ipc_offset 0x0
#define sys_thread_switch_offset 0x4
#define sys_thread_control_offset 0x8
#define sys_exchange_registers_offset 0xC
#define sys_schedule_offset 0x10
#define sys_unmap_offset 0x14
#define sys_space_control_offset 0x18
#define sys_ipc_control_offset 0x1C
#define sys_map_offset 0x20
#define sys_getid_offset 0x24
#define sys_kread_offset 0x28
#define sys_kmem_grant_offset 0x2C
#define sys_kmem_reclaim_offset 0x30
#define syscalls_end_offset sys_kmem_reclaim_offset
#define SYSCALLS_TOTAL ((syscalls_end_offset >> 2) + 1)
int sys_ipc(struct syscall_args *);
int sys_thread_switch(struct syscall_args *);
int sys_thread_control(struct syscall_args *);
int sys_exchange_registers(struct syscall_args *);
int sys_schedule(struct syscall_args *);
int sys_unmap(struct syscall_args *);
int sys_space_control(struct syscall_args *);
int sys_ipc_control(struct syscall_args *);
int sys_map(struct syscall_args *);
int sys_getid(struct syscall_args *);
int sys_kread(struct syscall_args *);
int sys_kmem_grant(struct syscall_args *);
int sys_kmem_reclaim(struct syscall_args *);
#endif /* __SYSCALL_H__ */

9
include/l4/api/thread.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __THREAD_H__
#define __THREAD_H__
#define THREAD_CREATE 0
#define THREAD_RUN 1
#define THREAD_SUSPEND 2
#define THREAD_RESUME 3
#endif /* __THREAD_H__ */

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__ */

45
include/l4/config.h Normal file
View File

@@ -0,0 +1,45 @@
/* Automatically generated, don't edit */
/* Generated on: bahadir-desktop */
/* At: Sun, 13 Jan 2008 12:03:34 +0000 */
/* Linux version 2.6.22-14-generic (buildd@terranova) (gcc version 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)) #1 SMP Tue Dec 18 08:02:57 UTC 2007 */
/* L4 Project Kernel Configurator */
/* Main architecture */
#undef ARCH_TEST
#define ARCH_ARM 1
/* ARM Architecture Configuration */
/* ARM Processor Type */
#undef ARM_CPU_ARM920T
#define ARM_CPU_ARM926 1
#undef ARM_CPU_ARM925
/* ARM Architecture Family */
#define ARM_SUBARCH_V5 1
#undef ARM_SUBARCH_V6
/* ARM Platform Type */
#undef ARM_PLATFORM_EB
#undef ARM_PLATFORM_AB926
#define ARM_PLATFORM_PB926 1
/* Platform Drivers */
#define DRIVER_UART_PL011 1
#define DRIVER_TIMER_SP804 1
#define DRIVER_IRQCTRL_PL190 1
#undef DUMMY
/* That's all, folks! */
/* Symbols derived from this file by SConstruct\derive_symbols() */
#define __ARCH__ arm
#define __PLATFORM__ pb926
#define __SUBARCH__ v5

View File

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

View File

@@ -0,0 +1,241 @@
/*********************************************************************
*
* Copyright (C) 2004, National ICT Australia (NICTA)
*
* File path: platform/pleb2/intctrl.h
* Description:
*
* 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: intctrl.h,v 1.2 2004/12/02 22:40:44 cvansch Exp $
*
********************************************************************/
#ifndef __PLATFORM__PB926__INTCTRL_H__
#define __PLATFORM__PB926__INTCTRL_H__
#include <intctrl.h>
#include INC_GLUE(hwspace.h)
#include INC_ARCH(thread.h)
#include INC_ARCH(clz.h)
#include INC_API(space.h)
#include INC_PLAT(offsets.h)
#include INC_PLAT(timer.h)
#include INC_CPU(cpu.h)
/* Flags to define Primary and Secondary irq controllers */
#define PB926_PIC 0
#define PB926_SIC 1
/* Flags to define fast or normal interrupts */
#define PB926_IRQ 0
#define PB926_FIQ 1
void vic_init(void);
/* IRQS */
#define IRQS 64
/* FIXME:
* IRQ handler array doesn't match with irq descriptor array, which must be taken as
* reference because its indices are unique. Make sure this happens.
*/
/* Our major OS timer */
#define PB926_IRQ_OS_TIMER
/* Virtual offsets from some virtual device base */
/* Absolute virtual addresses */
#define PB926_VIC_VBASE (IODEVICE_VADDR + PB926_VIC_VOFFSET)
#define PB926_SIC_VBASE (IODEVICE_VADDR + PB926_SIC_VOFFSET)
/* Interrupt controller register offsets (absolute virtual) */
#define PIC_IRQSTATUS (volatile word_t *)(PB926_VIC_VBASE + 0x00)
#define PIC_FIQSTATUS (volatile word_t *)(PB926_VIC_VBASE + 0x04)
#define PIC_RAWINTR (volatile word_t *)(PB926_VIC_VBASE + 0x08)
#define PIC_INTSELECT (volatile word_t *)(PB926_VIC_VBASE + 0x0C)
#define PIC_INTENABLE (volatile word_t *)(PB926_VIC_VBASE + 0x10)
#define PIC_INTENCLEAR (volatile word_t *)(PB926_VIC_VBASE + 0x14)
#define PIC_SOFTINT (volatile word_t *)(PB926_VIC_VBASE + 0x18)
#define PIC_SOFTINTCLEAR (volatile word_t *)(PB926_VIC_VBASE + 0x1C)
#define PIC_PROTECTION (volatile word_t *)(PB926_VIC_VBASE + 0x20)
#define PIC_VECTADDR (volatile word_t *)(PB926_VIC_VBASE + 0x30)
#define PIC_DEFVECTADDR (volatile word_t *)(PB926_VIC_VBASE + 0x34)
#define PIC_VECTADDR0 (volatile word_t *)(PB926_VIC_VBASE + 0x100)
/* 15 PIC_VECTADDR registers up to 0x13C */
#define PIC_VECTCNTL0 (volatile word_t *)(PB926_VIC_VBASE + 0x200)
/* 15 PIC_VECTCNTL registers up to 0x23C */
#define SIC_STATUS (volatile word_t *)(PB926_SIC_VBASE + 0x0)
#define SIC_RAWSTAT (volatile word_t *)(PB926_SIC_VBASE + 0x04)
#define SIC_ENABLE (volatile word_t *)(PB926_SIC_VBASE + 0x08)
#define SIC_ENSET (volatile word_t *)(PB926_SIC_VBASE + 0x08)
#define SIC_ENCLR (volatile word_t *)(PB926_SIC_VBASE + 0x0C)
#define SIC_SOFTINTSET (volatile word_t *)(PB926_SIC_VBASE + 0x10)
#define SIC_SOFTINTCLR (volatile word_t *)(PB926_SIC_VBASE + 0x14)
#define SIC_PICENABLE (volatile word_t *)(PB926_SIC_VBASE + 0x20)
#define SIC_PICENSET (volatile word_t *)(PB926_SIC_VBASE + 0x20)
#define SIC_PICENCLR (volatile word_t *)(PB926_SIC_VBASE + 0x24)
/*******************************************/
/* BB: IRQ Explanation for VIC
* On PB926 there are two interrupt controllers. A secondary IC is
* cascaded on the primary, using pin 31. We ack irqs by simply clearing
* the status register. We actually ack_and_mask, so for acking, we also
* disable the particular irq, on either pic or sic.
*
* What's more to cascaded irq controllers is that, you may have the
* same line number on different controllers, for different irqs. This
* causes a difficulty to uniquely identify an interrupt, because the
* line number is not a primary key anymore. One approach is to `assume'
* irqs on one controller are added to the maximum you can have on the
* other. E.g. irq 1 on intctrl P is 1, but irq 1 on intctrl S is
* (1 + 31) = 32. While this works, it's not the best approach because
* you will see that more complicated architectures on SMP machines are
* present. (See PB1176 or EB port, or even worse, try an ARM11MPCore
* on EB.)
*
* What's better is to use a struct to describe what the irq line
* `actually' is, so things are put straight, with a small memory
* trade-off.
*
* Furthermore to this, each irq is described uniquely by an irq
* descriptor; however, we still need the simplicity of a single integer
* to uniquely identify each individual irq. This integer, is the index
* of each irq descriptor, in the array of irq descriptors. This index
* is not necessarily a natural mapping from irq numbers in interrupt
* controllers, as described in paragraph 2, but it is rather a compile-
* time constant as far as the compile-time defined irq array is
* concerned, or, the set of such primary keys may expand as the array
* expands dynamically at run-time (e.g. registration of new irqs at
* run-time).
*/
extern word_t arm_high_vector;
extern word_t interrupt_handlers[IRQS];
class intctrl_t : public generic_intctrl_t {
/* Timer needs to know about its irq, stored in this class. */
friend class arm_sp804timer;
/* Defines an irq on pb926 */
public:
struct pb926dev_irq {
int intctrl; /* The irq controller this irq is on */
int irqno; /* The pin (i.e. line) on this controller */
int irqtype; /* Fast, or normal. IRQ = 0, FIQ = 1 */
};
/* TODO: The reason our static variables aren't static anymore is that,
* they need to be instantiated and initialised in global scope, in order to be
* used. E.g:
* intctrl_t::pb926_irq_watchdog = { 1, 3, 4 };
* I haven't figured out where and how to initialise them this way yet, thus
* they're non-static for now.
*/
#if 0
/* IRQ definitions */
static struct pb926dev_irq pb926_irq_watchdog = {
//.intctrl= PB926_PIC,
//.irqno = 0,
//.irqtype= PB926_IRQ
PB926_PIC, 0, PB926_IRQ
};
static struct pb926dev_irq pb926_irq_timer0_1 = {
// .intctrl= PB926_PIC,
// .irqno = 4,
// .irqtype= PB926_IRQ
PB926_PIC, 4, PB926_IRQ
};
#endif
struct pb926dev_irq pb926_irq_watchdog;
struct pb926dev_irq pb926_irq_timer0_1;
struct pb926dev_irq pb926_irq_uart0;
struct pb926dev_irq * irq_desc_array[IRQS];
public:
void init_cpu();
void init_arch(void)
{
pb926_irq_watchdog.intctrl = PB926_PIC;
pb926_irq_watchdog.irqno = 0;
pb926_irq_watchdog.irqtype = PB926_IRQ;
pb926_irq_timer0_1.intctrl = PB926_PIC;
pb926_irq_timer0_1.irqno = 4;
pb926_irq_timer0_1.irqtype = PB926_IRQ;
pb926_irq_uart0.intctrl = PB926_PIC;
pb926_irq_uart0.irqno = 12;
pb926_irq_uart0.irqtype = PB926_IRQ;
irq_desc_array[0] = &pb926_irq_watchdog;
irq_desc_array[4] = &pb926_irq_timer0_1;
irq_desc_array[12]= &pb926_irq_uart0;
vic_init();
}
int irq_number(void);
void ack(int irqno);
void mask(int irqno);
int unmask(int irq);
bool is_irq_available(int irq);
word_t get_number_irqs(void)
{
return IRQS;
}
void register_interrupt_handler (word_t vector, void (*handler)(word_t,
arm_irq_context_t *))
{
ASSERT(DEBUG, vector < IRQS);
interrupt_handlers[vector] = (word_t) handler;
TRACE_INIT("interrupt vector[%d] = %p\n", vector,
interrupt_handlers[vector]);
}
inline void disable(int irq)
{
mask(irq);
}
inline int enable(int irq)
{
return unmask(irq);
}
void disable_fiq(void) {}
void set_cpu(word_t irq, word_t cpu) {}
};
#endif /*__PLATFORM__PB926__INTCTRL_H__ */

View File

@@ -0,0 +1,241 @@
/*********************************************************************
*
* Copyright (C) 2004, National ICT Australia (NICTA)
*
* File path: platform/pleb2/intctrl.h
* Description:
*
* 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: intctrl.h,v 1.2 2004/12/02 22:40:44 cvansch Exp $
*
********************************************************************/
#ifndef __PLATFORM__PB926__INTCTRL_H__
#define __PLATFORM__PB926__INTCTRL_H__
#include <intctrl.h>
#include INC_GLUE(hwspace.h)
#include INC_ARCH(thread.h)
#include INC_ARCH(clz.h)
#include INC_API(space.h)
#include INC_PLAT(offsets.h)
#include INC_PLAT(timer.h)
#include INC_CPU(cpu.h)
/* Flags to define Primary and Secondary irq controllers */
#define PB926_PIC 0
#define PB926_SIC 1
/* Flags to define fast or normal interrupts */
#define PB926_IRQ 0
#define PB926_FIQ 1
void vic_init(void);
/* IRQS */
#define IRQS 64
/* FIXME:
* IRQ handler array doesn't match with irq descriptor array, which must be taken as
* reference because its indices are unique. Make sure this happens.
*/
/* Our major OS timer */
#define PB926_IRQ_OS_TIMER
/* Virtual offsets from some virtual device base */
/* Absolute virtual addresses */
#define PB926_VIC_VBASE (IODEVICE_VADDR + PB926_VIC_VOFFSET)
#define PB926_SIC_VBASE (IODEVICE_VADDR + PB926_SIC_VOFFSET)
/* Interrupt controller register offsets (absolute virtual) */
#define PIC_IRQSTATUS (volatile word_t *)(PB926_VIC_VBASE + 0x00)
#define PIC_FIQSTATUS (volatile word_t *)(PB926_VIC_VBASE + 0x04)
#define PIC_RAWINTR (volatile word_t *)(PB926_VIC_VBASE + 0x08)
#define PIC_INTSELECT (volatile word_t *)(PB926_VIC_VBASE + 0x0C)
#define PIC_INTENABLE (volatile word_t *)(PB926_VIC_VBASE + 0x10)
#define PIC_INTENCLEAR (volatile word_t *)(PB926_VIC_VBASE + 0x14)
#define PIC_SOFTINT (volatile word_t *)(PB926_VIC_VBASE + 0x18)
#define PIC_SOFTINTCLEAR (volatile word_t *)(PB926_VIC_VBASE + 0x1C)
#define PIC_PROTECTION (volatile word_t *)(PB926_VIC_VBASE + 0x20)
#define PIC_VECTADDR (volatile word_t *)(PB926_VIC_VBASE + 0x30)
#define PIC_DEFVECTADDR (volatile word_t *)(PB926_VIC_VBASE + 0x34)
#define PIC_VECTADDR0 (volatile word_t *)(PB926_VIC_VBASE + 0x100)
/* 15 PIC_VECTADDR registers up to 0x13C */
#define PIC_VECTCNTL0 (volatile word_t *)(PB926_VIC_VBASE + 0x200)
/* 15 PIC_VECTCNTL registers up to 0x23C */
#define SIC_STATUS (volatile word_t *)(PB926_SIC_VBASE + 0x0)
#define SIC_RAWSTAT (volatile word_t *)(PB926_SIC_VBASE + 0x04)
#define SIC_ENABLE (volatile word_t *)(PB926_SIC_VBASE + 0x08)
#define SIC_ENSET (volatile word_t *)(PB926_SIC_VBASE + 0x08)
#define SIC_ENCLR (volatile word_t *)(PB926_SIC_VBASE + 0x0C)
#define SIC_SOFTINTSET (volatile word_t *)(PB926_SIC_VBASE + 0x10)
#define SIC_SOFTINTCLR (volatile word_t *)(PB926_SIC_VBASE + 0x14)
#define SIC_PICENABLE (volatile word_t *)(PB926_SIC_VBASE + 0x20)
#define SIC_PICENSET (volatile word_t *)(PB926_SIC_VBASE + 0x20)
#define SIC_PICENCLR (volatile word_t *)(PB926_SIC_VBASE + 0x24)
/*******************************************/
/* BB: IRQ Explanation for VIC
* On PB926 there are two interrupt controllers. A secondary IC is
* cascaded on the primary, using pin 31. We ack irqs by simply clearing
* the status register. We actually ack_and_mask, so for acking, we also
* disable the particular irq, on either pic or sic.
*
* What's more to cascaded irq controllers is that, you may have the
* same line number on different controllers, for different irqs. This
* causes a difficulty to uniquely identify an interrupt, because the
* line number is not a primary key anymore. One approach is to `assume'
* irqs on one controller are added to the maximum you can have on the
* other. E.g. irq 1 on intctrl P is 1, but irq 1 on intctrl S is
* (1 + 31) = 32. While this works, it's not the best approach because
* you will see that more complicated architectures on SMP machines are
* present. (See PB1176 or EB port, or even worse, try an ARM11MPCore
* on EB.)
*
* What's better is to use a struct to describe what the irq line
* `actually' is, so things are put straight, with a small memory
* trade-off.
*
* Furthermore to this, each irq is described uniquely by an irq
* descriptor; however, we still need the simplicity of a single integer
* to uniquely identify each individual irq. This integer, is the index
* of each irq descriptor, in the array of irq descriptors. This index
* is not necessarily a natural mapping from irq numbers in interrupt
* controllers, as described in paragraph 2, but it is rather a compile-
* time constant as far as the compile-time defined irq array is
* concerned, or, the set of such primary keys may expand as the array
* expands dynamically at run-time (e.g. registration of new irqs at
* run-time).
*/
extern word_t arm_high_vector;
extern word_t interrupt_handlers[IRQS];
class intctrl_t : public generic_intctrl_t {
/* Timer needs to know about its irq, stored in this class. */
friend class arm_sp804timer;
/* Defines an irq on pb926 */
public:
struct pb926dev_irq {
int intctrl; /* The irq controller this irq is on */
int irqno; /* The pin (i.e. line) on this controller */
int irqtype; /* Fast, or normal. IRQ = 0, FIQ = 1 */
};
/* TODO: The reason our static variables aren't static anymore is that,
* they need to be instantiated and initialised in global scope, in order to be
* used. E.g:
* intctrl_t::pb926_irq_watchdog = { 1, 3, 4 };
* I haven't figured out where and how to initialise them this way yet, thus
* they're non-static for now.
*/
#if 0
/* IRQ definitions */
static struct pb926dev_irq pb926_irq_watchdog = {
//.intctrl= PB926_PIC,
//.irqno = 0,
//.irqtype= PB926_IRQ
PB926_PIC, 0, PB926_IRQ
};
static struct pb926dev_irq pb926_irq_timer0_1 = {
// .intctrl= PB926_PIC,
// .irqno = 4,
// .irqtype= PB926_IRQ
PB926_PIC, 4, PB926_IRQ
};
#endif
struct pb926dev_irq pb926_irq_watchdog;
struct pb926dev_irq pb926_irq_timer0_1;
struct pb926dev_irq pb926_irq_uart0;
struct pb926dev_irq * irq_desc_array[IRQS];
public:
void init_cpu();
void init_arch(void)
{
pb926_irq_watchdog.intctrl = PB926_PIC;
pb926_irq_watchdog.irqno = 0;
pb926_irq_watchdog.irqtype = PB926_IRQ;
pb926_irq_timer0_1.intctrl = PB926_PIC;
pb926_irq_timer0_1.irqno = 4;
pb926_irq_timer0_1.irqtype = PB926_IRQ;
pb926_irq_uart0.intctrl = PB926_PIC;
pb926_irq_uart0.irqno = 12;
pb926_irq_uart0.irqtype = PB926_IRQ;
irq_desc_array[0] = &pb926_irq_watchdog;
irq_desc_array[4] = &pb926_irq_timer0_1;
irq_desc_array[12]= &pb926_irq_uart0;
vic_init();
}
int irq_number(void);
void ack(int irqno);
void mask(int irqno);
int unmask(int irq);
bool is_irq_available(int irq);
word_t get_number_irqs(void)
{
return IRQS;
}
void register_interrupt_handler (word_t vector, void (*handler)(word_t,
arm_irq_context_t *))
{
ASSERT(DEBUG, vector < IRQS);
interrupt_handlers[vector] = (word_t) handler;
TRACE_INIT("interrupt vector[%d] = %p\n", vector,
interrupt_handlers[vector]);
}
inline void disable(int irq)
{
mask(irq);
}
inline int enable(int irq)
{
return unmask(irq);
}
void disable_fiq(void) {}
void set_cpu(word_t irq, word_t cpu) {}
};
#endif /*__PLATFORM__PB926__INTCTRL_H__ */

View File

@@ -0,0 +1,56 @@
/*
* PL190 Primecell Vectored Interrupt Controller offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __PL190_VIC_H__
#define __PL190_VIC_H__
#include INC_PLAT(platform.h)
#define PL190_BASE PLATFORM_IRQCTRL_BASE
#define PL190_SIC_BASE PLATFORM_SIRQCTRL_BASE
/* VIC register offsets */
#define PL190_VIC_IRQSTATUS (PL190_BASE + 0x00)
#define PL190_VIC_FIQSTATUS (PL190_BASE + 0x04)
#define PL190_VIC_RAWINTR (PL190_BASE + 0x08)
#define PL190_VIC_INTSELECT (PL190_BASE + 0x0C)
#define PL190_VIC_INTENABLE (PL190_BASE + 0x10)
#define PL190_VIC_INTENCLEAR (PL190_BASE + 0x14)
#define PL190_VIC_SOFTINT (PL190_BASE + 0x18)
#define PL190_VIC_SOFTINTCLEAR (PL190_BASE + 0x1C)
#define PL190_VIC_PROTECTION (PL190_BASE + 0x20)
#define PL190_VIC_VECTADDR (PL190_BASE + 0x30)
#define PL190_VIC_DEFVECTADDR (PL190_BASE + 0x34)
#define PL190_VIC_VECTADDR0 (PL190_BASE + 0x100)
/* 15 PIC_VECTADDR registers up to 0x13C */
#define PL190_VIC_VECTCNTL0 (PL190_BASE + 0x200)
/* 15 PIC_VECTCNTL registers up to 0x23C */
#define PL190_SIC_STATUS (PL190_SIC_BASE + 0x0)
#define PL190_SIC_RAWSTAT (PL190_SIC_BASE + 0x04)
#define PL190_SIC_ENABLE (PL190_SIC_BASE + 0x08)
#define PL190_SIC_ENSET (PL190_SIC_BASE + 0x08)
#define PL190_SIC_ENCLR (PL190_SIC_BASE + 0x0C)
#define PL190_SIC_SOFTINTSET (PL190_SIC_BASE + 0x10)
#define PL190_SIC_SOFTINTCLR (PL190_SIC_BASE + 0x14)
#define PL190_SIC_PICENABLE (PL190_SIC_BASE + 0x20)
#define PL190_SIC_PICENSET (PL190_SIC_BASE + 0x20)
#define PL190_SIC_PICENCLR (PL190_SIC_BASE + 0x24)
void pl190_vic_init(void);
void pl190_ack_irq(int irq);
void pl190_mask_irq(int irq);
void pl190_unmask_irq(int irq);
int pl190_read_irq(void);
int pl190_sic_read_irq(void);
void pl190_sic_mask_irq(int irq);
void pl190_sic_mask_irq(int irq);
void pl190_sic_ack_irq(int irq);
void pl190_sic_unmask_irq(int irq);
void pl190_sic_init(void);
#endif /* __PL190_VIC_H__ */

View File

@@ -0,0 +1,54 @@
/*
* SP810 Primecell system controller offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __SP810_SYSCTRL_H__
#define __SP810_SYSCTRL_H__
#include INC_PLAT(platform.h)
/* FIXME: Fix the stupid uart driver and change to single definition of this! */
#if defined(read)
#undef read
#endif
#if defined(write)
#undef write
#endif
#define read(a) *((volatile unsigned int *)(a))
#define write(v, a) (*((volatile unsigned int *)(a)) = v)
#define setbit(bit, a) write(read(a) | bit, a)
#define clrbit(bit, a) write(read(a) & ~bit, a)
#define devio(base, reg, bit, setclr) \
(setclr) ? setbit(bit, base + reg) \
: clrbit(bit, base + reg)
/* The SP810 system controller offsets */
#define SP810_BASE PLATFORM_SP810_BASE
#define SP810_SCCTRL (SP810_BASE + 0x0)
/* ... Fill in as needed. */
/* Set clock source for timers on this platform.
* @timer: The index of timer you want to set the clock for.
* On PB926 valid values are 0-4.
*
* @freq: The frequency you want to set the timer for.
* On PB926 valid values are 32KHz = 0 (0 is 32Khz because that's
* the default.) and 1MHz = non-zero.
*/
static inline void sp810_set_timclk(int timer, unsigned int freq)
{
if (timer < 0 || timer > 3)
return;
freq ? setbit((1 << (15 + (2 * timer))), SP810_SCCTRL) :
clrbit((1 << (15 + (2 * timer))), SP810_SCCTRL);
return;
}
#endif /* __SP810_SYSCTRL_H__ */

View File

@@ -0,0 +1,27 @@
/*
* SP804 Primecell Timer offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __SP804_TIMER_H__
#define __SP804_TIMER_H__
#include INC_PLAT(platform.h)
#define SP804_TIMER01_BASE PLATFORM_TIMER_BASE
#define SP804_TIMER1LOAD (SP804_TIMER01_BASE + 0x0)
#define SP804_TIMER1VALUE (SP804_TIMER01_BASE + 0x4)
#define SP804_TIMER1CONTROL (SP804_TIMER01_BASE + 0x8)
#define SP804_TIMER1INTCLR (SP804_TIMER01_BASE + 0xC)
#define SP804_TIMER1RIS (SP804_TIMER01_BASE + 0x10)
#define SP804_TIMER1MIS (SP804_TIMER01_BASE + 0x14)
#define SP804_TIMER1BGLOAD (SP804_TIMER01_BASE + 0x18)
#define SP804_TIMER2OFFSET 0x20
void sp804_init(void);
void sp804_irq_handler(void);
void sp804_enable(int timer, int enable);
void sp804_set_irq(int timer, int enable);
#endif /* __SP804_TIMER_H__ */

View File

@@ -0,0 +1,380 @@
/*
* PL011 UART Generic driver implementation.
*
* Copyright (C) 2007 Bahadir Balban
*
* The particular intention of this code is that it has been carefully written
* as decoupled from os-specific code and in a verbose way such that it clearly
* demonstrates how the device operates, reducing the amount of time to be spent
* for understanding the operational model and implementing a driver from
* scratch. This is the very first to be such a driver so far, hopefully it will
* turn out to be useful.
*/
#ifndef __PL011_UART_H__
#define __PL011_UART_H__
#include INC_PLAT(uart.h)
#include INC_ARCH(io.h)
#define PL011_BASE PLATFORM_CONSOLE_BASE
/* Register offsets */
#define PL011_UARTDR (PL011_BASE + 0x00)
#define PL011_UARTRSR (PL011_BASE + 0x04)
#define PL011_UARTECR (PL011_BASE + 0x04)
#define PL011_UARTFR (PL011_BASE + 0x18)
#define PL011_UARTILPR (PL011_BASE + 0x20)
#define PL011_UARTIBRD (PL011_BASE + 0x24)
#define PL011_UARTFBRD (PL011_BASE + 0x28)
#define PL011_UARTLCR_H (PL011_BASE + 0x2C)
#define PL011_UARTCR (PL011_BASE + 0x30)
#define PL011_UARTIFLS (PL011_BASE + 0x34)
#define PL011_UARTIMSC (PL011_BASE + 0x38)
#define PL011_UARTRIS (PL011_BASE + 0x3C)
#define PL011_UARTMIS (PL011_BASE + 0x40)
#define PL011_UARTICR (PL011_BASE + 0x44)
#define PL011_UARTDMACR (PL011_BASE + 0x48)
/* IRQ bits for each uart irq event */
#define PL011_RXIRQ (1 << 4)
#define PL011_TXIRQ (1 << 5)
#define PL011_RXTIMEOUTIRQ (1 << 6)
#define PL011_FEIRQ (1 << 7)
#define PL011_PEIRQ (1 << 8)
#define PL011_BEIRQ (1 << 9)
#define PL011_OEIRQ (1 << 10)
struct pl011_uart;
void pl011_initialise_driver();
int pl011_initialise_device(struct pl011_uart *);
int pl011_tx_char(char);
int pl011_rx_char(char *);
void pl011_set_baudrate(unsigned int, unsigned int);
void pl011_set_irq_mask(unsigned int);
void pl011_clr_irq_mask(unsigned int);
void pl011_irq_handler(struct pl011_uart *);
void pl011_tx_irq_handler(struct pl011_uart *, unsigned int);
void pl011_rx_irq_handler(struct pl011_uart *, unsigned int);
void pl011_error_irq_handler(struct pl011_uart *, unsigned int);
struct pl011_uart_ops {
int (*initialise)(struct pl011_uart *);
int (*tx_char)(char);
int (*rx_char)(char *);
void (*set_baudrate)(unsigned int, unsigned int);
void (*set_irq_mask)(unsigned int);
void (*clr_irq_mask)(unsigned int);
void (*irq_handler)(struct pl011_uart *);
void (*tx_irq_handler)(struct pl011_uart *, unsigned int);
void (*rx_irq_handler)(struct pl011_uart *, unsigned int);
void (*error_irq_handler)(struct pl011_uart *, unsigned int);
};
struct pl011_uart {
unsigned int base;
struct pl011_uart_ops ops;
unsigned int frame_errors;
unsigned int parity_errors;
unsigned int break_errors;
unsigned int overrun_errors;
unsigned int rx_timeout_errors;
};
#define PL011_UARTEN (1 << 0)
static inline void pl011_uart_enable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTCR);
val |= PL011_UARTEN;
write(val, PL011_UARTCR);
return;
}
static inline void pl011_uart_disable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTCR);
val &= ~PL011_UARTEN;
write(val, PL011_UARTCR);
return;
}
#define PL011_TXE (1 << 8)
static inline void pl011_tx_enable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTCR);
val |= PL011_TXE;
write(val, PL011_UARTCR);
return;
}
static inline void pl011_tx_disable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTCR);
val &= ~PL011_TXE;
write(val, PL011_UARTCR);
return;
}
#define PL011_RXE (1 << 9)
static inline void pl011_rx_enable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTCR);
val |= PL011_RXE;
write(val, PL011_UARTCR);
return;
}
static inline void pl011_rx_disable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTCR);
val &= ~PL011_RXE;
write(val, PL011_UARTCR);
return;
}
#define PL011_TWO_STOPBITS_SELECT (1 << 3)
static inline void pl011_set_stopbits(int stopbits)
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
if(stopbits == 2) { /* Set to two bits */
val |= PL011_TWO_STOPBITS_SELECT;
} else { /* Default is 1 */
val &= ~PL011_TWO_STOPBITS_SELECT;
}
write(val, PL011_UARTLCR_H);
return;
}
#define PL011_PARITY_ENABLE (1 << 1)
static inline void pl011_parity_enable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
val |= PL011_PARITY_ENABLE;
write(val, PL011_UARTLCR_H);
return;
}
static inline void pl011_parity_disable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
val &= ~PL011_PARITY_ENABLE;
write(val, PL011_UARTLCR_H);
return;
}
#define PL011_PARITY_EVEN (1 << 2)
static inline void pl011_set_parity_even()
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
val |= PL011_PARITY_EVEN;
write(val, PL011_UARTLCR_H);
return;
}
static inline void pl011_set_parity_odd()
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
val &= ~PL011_PARITY_EVEN;
write(val, PL011_UARTLCR_H);
return;
}
#define PL011_ENABLE_FIFOS (1 << 4)
static inline void pl011_enable_fifos()
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
val |= PL011_ENABLE_FIFOS;
write(val, PL011_UARTLCR_H);
return;
}
static inline void pl011_disable_fifos()
{
unsigned int val;
val = 0;
read(val, PL011_UARTLCR_H);
val &= ~PL011_ENABLE_FIFOS;
write(val, PL011_UARTLCR_H);
return;
}
#define PL011_WORD_WIDTH_SHIFT (5)
/* Sets the transfer word width for the data register. */
static inline void pl011_set_word_width(int size)
{
unsigned int val;
val = 0;
if(size < 5 || size > 8) /* Default is 8 */
size = 8;
/* Clear size field */
read(val, PL011_UARTLCR_H);
val &= ~(0x3 << PL011_WORD_WIDTH_SHIFT);
write(val, PL011_UARTLCR_H);
/* The formula is to write 5 less of size given:
* 11 = 8 bits
* 10 = 7 bits
* 01 = 6 bits
* 00 = 5 bits
*/
read(val, PL011_UARTLCR_H);
val |= (size - 5) << PL011_WORD_WIDTH_SHIFT;
write(val, PL011_UARTLCR_H);
return;
}
/*
* Defines at which level of fifo fullness an irq will be generated.
* @xfer: tx fifo = 0, rx fifo = 1
* @level: Generate irq if:
* 0 rxfifo >= 1/8 full txfifo <= 1/8 full
* 1 rxfifo >= 1/4 full txfifo <= 1/4 full
* 2 rxfifo >= 1/2 full txfifo <= 1/2 full
* 3 rxfifo >= 3/4 full txfifo <= 3/4 full
* 4 rxfifo >= 7/8 full txfifo <= 7/8 full
* 5-7 reserved reserved
*/
static inline void pl011_set_irq_fifolevel(unsigned int xfer, unsigned int level)
{
if(xfer != 1 && xfer != 0) /* Invalid fifo */
return;
if(level > 4) /* Invalid level */
return;
write(level << (xfer * 3), PL011_UARTIFLS);
return;
}
/* returns which irqs are masked */
static inline unsigned int pl011_read_irqmask(void)
{
unsigned int flags;
read(flags, PL011_UARTIMSC);
return flags;
}
/* returns masked irq status */
static inline unsigned int pl011_read_irqstat(void)
{
unsigned int irqstatus;
read(irqstatus, PL011_UARTMIS);
return irqstatus;
}
/* Clears the given asserted irqs */
static inline void pl011_irq_clear(unsigned int flags)
{
if(flags > 0x3FF) { /* Invalid irq clearing bitvector */
return;
}
/* Simply write the flags since it's a write-only register */
write(flags, PL011_UARTICR);
return;
}
#define PL011_TXDMAEN (1 << 1)
#define PL011_RXDMAEN (1 << 0)
/* Enables dma transfers for uart. The dma controller
* must be initialised, set-up and enabled separately.
*/
static inline void pl011_tx_dma_enable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTDMACR);
val |= PL011_TXDMAEN;
write(val, PL011_UARTDMACR);
return;
}
/* Disables dma transfers for uart */
static inline void pl011_tx_dma_disable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTDMACR);
val &= ~PL011_TXDMAEN;
write(val, PL011_UARTDMACR);
return;
}
static inline void pl011_rx_dma_enable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTDMACR);
val |= PL011_RXDMAEN;
write(val, PL011_UARTDMACR);
return;
}
static inline void pl011_rx_dma_disable()
{
unsigned int val;
val = 0;
read(val, PL011_UARTDMACR);
val &= ~PL011_RXDMAEN;
write(val, PL011_UARTDMACR);
return;
}
#endif /* __PL011_UART__ */

80
include/l4/generic/irq.h Normal file
View File

@@ -0,0 +1,80 @@
/*
* Generic irq handling definitions.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __GENERIC_IRQ_H__
#define __GENERIC_IRQ_H__
#include <l4/lib/string.h>
#include INC_PLAT(irq.h)
/* Represents none or spurious irq */
#define IRQ_NIL (-1)
/* Successful irq handling state */
#define IRQ_HANDLED 0
typedef void (*irq_op_t)(int irq);
struct irq_chip_ops {
void (*init)(void);
int (*read_irq)(void);
irq_op_t ack_and_mask;
irq_op_t unmask;
};
struct irq_chip {
char name[32];
int level; /* Cascading level */
int cascade; /* The irq that lower chip uses on this chip */
int offset; /* The global offset for this irq chip */
struct irq_chip_ops ops;
};
typedef int (*irq_handler_t)(void);
struct irq_desc {
char name[8];
struct irq_chip *chip;
/* TODO: This could be a list for multiple handlers */
irq_handler_t handler;
};
extern struct irq_desc irq_desc_array[];
extern struct irq_chip irq_chip_array[];
static inline void irq_enable(int irq_index)
{
struct irq_desc *this_irq = irq_desc_array + irq_index;
struct irq_chip *this_chip = this_irq->chip;
this_chip->ops.unmask(irq_index - this_chip->offset);
}
static inline void irq_disable(int irq_index)
{
struct irq_desc *this_irq = irq_desc_array + irq_index;
struct irq_chip *this_chip = this_irq->chip;
this_chip->ops.ack_and_mask(irq_index - this_chip->offset);
}
static inline void register_irq(char *name, int irq_index, irq_handler_t handler)
{
struct irq_desc *this_desc = irq_desc_array + irq_index;
struct irq_chip *current_chip = irq_chip_array;
strncpy(&this_desc->name[0], name, sizeof(this_desc->name));
for (int i = 0; i < IRQ_CHIPS_MAX; i++)
if (irq_index <= current_chip->offset) {
this_desc->chip = current_chip;
break;
}
this_desc->handler = handler;
}
void do_irq(void);
void irq_controllers_init(void);
#endif /* __GENERIC_IRQ_H__ */

View File

@@ -0,0 +1,9 @@
#ifndef __KMALLOC_H__
#define __KMALLOC_H__
void *kmalloc(int size);
int kfree(void *p);
void *kzalloc(int size);
void init_kmalloc();
#endif

View File

@@ -0,0 +1,15 @@
#ifndef __PGALLOC_H__
#define __PGALLOC_H__
void *zalloc_page(void);
void *alloc_page(void);
void *alloc_pmd(void);
void *alloc_pgd(void);
int free_page(void *);
int free_pmd(void *);
int free_pgd(void *);
int pgalloc_add_new_grant(unsigned long pfn, int npages);
void init_pgalloc();
#endif /* __PGALLOC_H__ */

View File

@@ -0,0 +1,45 @@
/*
* Boot time memory initialisation and memory allocator interface.
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __GENERIC_PHYSMEM_H__
#define __GENERIC_PHYSMEM_H__
#include <l4/lib/list.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#define PHYSMEM_TOTAL_PAGES ((PHYS_MEM_END - PHYS_MEM_START) >> PAGE_BITS)
/* A compact memory descriptor to determine used/unused pages in the system */
struct page_bitmap {
unsigned long pfn_start;
unsigned long pfn_end;
unsigned int map[PHYSMEM_TOTAL_PAGES >> 5];
};
/* Describes a portion of physical memory. */
struct memdesc {
unsigned int start;
unsigned int end;
unsigned int free_cur;
unsigned int free_end;
unsigned int numpages;
};
#if defined(__KERNEL__)
/* Describes bitmap of used/unused state for all physical pages */
extern struct page_bitmap page_map;
extern struct memdesc physmem;
#endif
/* Sets the global page map as used/unused. Aligns input when needed. */
int set_page_map(unsigned long start, int numpages, int val);
/* Memory allocator interface */
void physmem_init(void);
void memory_init(void);
#endif /* __GENERIC_PHYSMEM_H__ */

View File

@@ -0,0 +1,22 @@
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
/*
* Generic functions to be provided by every platform.
*/
void platform_init(void);
/* Uart APIs */
void uart_init(void);
void uart_putc(char c);
/* Timer APIs */
void timer_init(void);
void timer_start(void);
/* IRQ controller */
void irq_controller_init(void);
void platform_irq_enable(int irq);
void platform_irq_disable(int irq);
#endif /* __PLATFORM_H__ */

View File

@@ -0,0 +1,12 @@
/*
* Kernel preemption functions.
*/
#ifndef __PREEMPT_H__
#define __PREEMPT_H__
void preempt_enable(void);
void preempt_disable(void);
int preemptive(void);
int preempt_count(void);
#endif /* __PREEMPT_H__ */

View File

@@ -0,0 +1,55 @@
/*
* Scheduler and runqueue API definitions.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __SCHEDULER_H__
#define __SCHEDULER_H__
#include <l4/generic/tcb.h>
#include INC_SUBARCH(mm.h)
#include INC_GLUE(memory.h)
/* Ticks per second */
#define HZ 1000
#define TASK_TIMESLICE_DEFAULT 1
/* #define TASK_TIMESLICE_DEFAULT (HZ/100)*/
static inline struct ktcb *current_task(void)
{
register u32 stack asm("sp");
return (struct ktcb *)(stack & (~PAGE_MASK));
}
#define current current_task()
#define need_resched (current->ts_need_resched)
/* Flags set by kernel to direct the scheduler about future task state. */
#define __SCHED_FL_SUSPEND 1
#define SCHED_FL_SUSPEND (1 << __SCHED_FL_SUSPEND)
#define __SCHED_FL_RESUME 2
#define SCHED_FL_RESUME (1 << __SCHED_FL_RESUME)
#define __SCHED_FL_SLEEP 3
#define SCHED_FL_SLEEP (1 << __SCHED_FL_SLEEP)
#define SCHED_FL_MASK (SCHED_FL_SLEEP | SCHED_FL_RESUME \
| SCHED_FL_SUSPEND)
#define __IPC_FL_WAIT 4
#define IPC_FL_WAIT (1 << __IPC_FL_WAIT)
#define IPC_FL_MASK IPC_FL_WAIT
void sched_runqueue_init(void);
void sched_start_task(struct ktcb *task);
void sched_resume_task(struct ktcb *task);
void sched_suspend_task(struct ktcb *task);
void sched_process_post_ipc(struct ktcb *, struct ktcb *);
void sched_tell(struct ktcb *task, unsigned int flags);
void scheduler_start(void);
void sched_yield(void);
void schedule(void);
/* Asynchronous notifications to scheduler */
void sched_notify_resume(struct ktcb *task);
void sched_notify_sleep(struct ktcb *task);
void sched_notify_suspend(struct ktcb *task);
#endif /* __SCHEDULER_H__ */

View File

@@ -0,0 +1,21 @@
/*
* Generic address space related information.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __SPACE_H__
#define __SPACE_H__
/* The flags not embedded in the name behave as expected. E.g USR_RW is also */
#define MAP_USR_RW_FLAGS 0 /* CB as one would expect */
#define MAP_USR_RO_FLAGS 1 /* CB as one would expect */
#define MAP_SVC_RW_FLAGS 2 /* CB as one would expect */
#define MAP_USR_IO_FLAGS 3 /* Non-CB, RW */
#define MAP_SVC_IO_FLAGS 4 /* Non-CB, RW */
/* Some default aliases */
#define MAP_USR_DEFAULT_FLAGS MAP_USR_RW_FLAGS
#define MAP_SVC_DEFAULT_FLAGS MAP_SVC_RW_FLAGS
#define MAP_IO_DEFAULT_FLAGS MAP_SVC_IO_FLAGS
#endif /* __SPACE_H__ */

154
include/l4/generic/tcb.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* Thread Control Block, kernel portion.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __TCB_H__
#define __TCB_H__
#include <l4/lib/list.h>
#include <l4/lib/mutex.h>
#include <l4/generic/scheduler.h>
#include <l4/generic/pgalloc.h>
#include INC_GLUE(memory.h)
#include INC_GLUE(syscall.h)
#include INC_GLUE(utcb.h)
#include INC_SUBARCH(mm.h)
enum task_state {
TASK_INACTIVE = 0,
TASK_SLEEPING = 1,
TASK_RUNNABLE = 2,
};
/*
* This describes the user space register context of each task. Simply set them
* as regular structure fields, and they'll be copied onto real registers upon
* a context switch. In the ARM case, they're copied from memory to userspace
* registers using the LDM instruction with ^, no-pc flavor. See ARMARM.
*/
typedef struct arm_context {
u32 spsr; /* 0x0 */
u32 r0; /* 0x4 */
u32 r1; /* 0x8 */
u32 r2; /* 0xC */
u32 r3; /* 0x10 */
u32 r4; /* 0x14 */
u32 r5; /* 0x18 */
u32 r6; /* 0x1C */
u32 r7; /* 0x20 */
u32 r8; /* 0x24 */
u32 r9; /* 0x28 */
u32 r10; /* 0x2C */
u32 r11; /* 0x30 */
u32 r12; /* 0x34 */
u32 sp; /* 0x38 */
u32 lr; /* 0x3C */
u32 pc; /* 0x40 */
} __attribute__((__packed__)) task_context_t;
#define TASK_ID_INVALID -1
struct task_ids {
l4id_t tid;
l4id_t spid;
};
struct ktcb {
/* User context */
task_context_t context;
/* Reference to syscall saved context */
syscall_args_t *syscall_regs;
/* Runqueue related */
struct list_head rq_list;
struct runqueue *rq;
/* Thread information */
l4id_t tid; /* Global thread id */
l4id_t spid; /* Global space id */
/* Flags to hint scheduler on future task state */
unsigned int schedfl;
unsigned int flags;
/* Other related threads */
l4id_t pagerid;
u32 ts_need_resched; /* Scheduling flag */
enum task_state state;
struct list_head task_list; /* Global task list. */
struct utcb *utcb; /* Reference to task's utcb area */
/* Thread times */
u32 kernel_time; /* Ticks spent in kernel */
u32 user_time; /* Ticks spent in userland */
u32 ticks_left; /* Ticks left for reschedule */
/* Page table information */
pgd_table_t *pgd;
/* Fields for ipc rendezvous */
struct waitqueue_head wqh_recv;
struct waitqueue_head wqh_send;
/* Fields for checking parties blocked from doing ipc */
struct spinlock ipc_block_lock;
struct list_head ipc_block_list;
l4id_t senderid; /* Sender checks this for ipc */
};
/* Per thread kernel stack unified on a single page. */
union ktcb_union {
struct ktcb ktcb;
char kstack[PAGE_SIZE];
};
/* For traversing global task list */
extern struct list_head global_task_list;
static inline struct ktcb *find_task(l4id_t tid)
{
struct ktcb *task;
list_for_each_entry(task, &global_task_list, task_list)
if (task->tid == tid)
return task;
return 0;
}
static inline int add_task_global(struct ktcb *new)
{
INIT_LIST_HEAD(&new->task_list);
list_add(&new->task_list, &global_task_list);
return 0;
}
static inline void set_task_flags(struct ktcb *task, unsigned int fl)
{
task->flags |= fl;
}
/*
* Each task is allocated a unique global id. A thread group can only belong to
* a single leader, and every thread can only belong to a single thread group.
* These rules allow the fact that every global id can be used to define a
* unique thread group id. Thread local ids are used as an index into the thread
* group's utcb area to discover the per-thread utcb structure.
*/
static inline void set_task_ids(struct ktcb *task, struct task_ids *ids)
{
task->tid = ids->tid;
task->spid = ids->spid;
}
#define THREAD_IDS_MAX 1024
#define SPACE_IDS_MAX 1024
extern struct id_pool *thread_id_pool;
extern struct id_pool *space_id_pool;
#endif /* __TCB_H__ */

View File

@@ -0,0 +1,14 @@
/*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __THREAD_H__
#define __THREAD_H__
/* Thread id creation and deleting */
void thread_id_pool_init(void);
int thread_id_new(void);
int thread_id_del(int tid);
#endif /* __THREAD_H__ */

14
include/l4/generic/time.h Normal file
View File

@@ -0,0 +1,14 @@
/*
* System time keeping definitions
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __GENERIC_TIMER_H__
#define __GENERIC_TIMER_H__
extern volatile u32 jiffies;
int do_timer_irq(void);
#endif /* __GENERIC_TIMER_H__ */

View File

@@ -0,0 +1,9 @@
#ifndef __ARM_GLUE_INIT_H__
#define __ARM_GLUE_INIT_H__
#include <l4/generic/tcb.h>
void switch_to_user(struct ktcb *inittask);
void timer_start(void);
#endif /* __ARM_GLUE_INIT_H__ */

View File

@@ -0,0 +1,71 @@
/*
* Virtual memory layout of ARM systems.
*/
#ifndef __MEMLAYOUT_H__
#define __MEMLAYOUT_H__
#ifndef __ASSEMBLY__
#include INC_GLUE(memory.h)
#endif
#include INC_PLAT(offsets.h)
#define USER_AREA_START 0x10000000
#define USER_AREA_END 0x20000000
#define USER_AREA_SIZE (USER_AREA_END - USER_AREA_START)
#define USER_AREA_SECTIONS (USER_AREA_SIZE / ARM_SECTION_SIZE)
#define PMDS_PER_TASK (USER_AREA_SIZE / PMD_MAP_SIZE)
#define SHM_AREA_START 0x20000000
#define SHM_AREA_END 0x30000000
#define SHM_AREA_SIZE (SHM_AREA_END - SHM_AREA_START)
#define SHM_AREA_SECTIONS (SHM_AREA_SIZE / ARM_SECTION_SIZE)
#define INITTASK_AREA_START 0xE0000000
#define INITTASK_AREA_END 0xF0000000 /* 256 MB, too much. */
#define INITTASK_AREA_SIZE (INITTASK_AREA_END - INITTASK_AREA_START)
#define KERNEL_AREA_START 0xF0000000
#define KERNEL_AREA_END 0xF8000000 /* 128 MB */
#define KERNEL_AREA_SIZE (KERNEL_AREA_END - KERNEL_AREA_START)
#define KERNEL_AREA_SECTIONS (KERNEL_AREA_SIZE / ARM_SECTION_SIZE)
#define UTCB_AREA_START 0xF8000000
#define UTCB_AREA_END 0xF9000000
#define UTCB_AREA_SIZE (UTCB_AREA_END - UTCB_AREA_START)
#define UTCB_AREA_SECTIONS (UTCB_AREA_SIZE / ARM_SECTION_SIZE)
#define IO_AREA_START 0xF9000000
#define IO_AREA_END 0xFF000000
#define IO_AREA_SIZE (IO_AREA_END - IO_AREA_START)
#define IO_AREA_SECTIONS (IO_AREA_SIZE / ARM_SECTION_SIZE)
#define USER_KIP_PAGE 0xFF000000
/* ARM-specific offset in KIP that tells the address of UTCB page */
#define UTCB_KIP_OFFSET 0xFF0
#define IO_AREA0_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*0))
#define IO_AREA1_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*1))
#define IO_AREA2_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*2))
#define IO_AREA3_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*3))
#define IO_AREA4_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*4))
#define IO_AREA5_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*5))
#define IO_AREA6_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*6))
#define IO_AREA7_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*7))
#define ARM_HIGH_VECTOR 0xFFFF0000
#define ARM_SYSCALL_VECTOR 0xFFFFFF00
#define KERNEL_OFFSET (KERNEL_AREA_START - PHYS_MEM_START)
/* User tasks define them differently */
#if defined (__KERNEL__)
#define phys_to_virt(addr) ((unsigned int)(addr) + KERNEL_OFFSET)
#define virt_to_phys(addr) ((unsigned int)(addr) - KERNEL_OFFSET)
#endif
#define KERN_ADDR(x) ((x >= KERNEL_AREA_START) && (x < KERNEL_AREA_END))
#define USER_ADDR(x) ((x >= USER_AREA_START) && (x < USER_AREA_END))
#endif /* __MEMLAYOUT_H__ */

View File

@@ -0,0 +1,124 @@
/*
* Includes memory-related architecture specific definitions and their
* corresponding generic wrappers.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __GLUE_ARM_MEMORY_H__
#define __GLUE_ARM_MEMORY_H__
#include INC_ARCH(bootdesc.h) /* Definition of last loaded svc image address */
#include INC_GLUE(memlayout.h) /* Important generic definitions */
#include INC_SUBARCH(mm.h)
/* Generic definitions */
#define PAGE_SIZE ARM_PAGE_SIZE
#define PAGE_MASK ARM_PAGE_MASK
#define PAGE_BITS ARM_PAGE_BITS
/*
* This defines the largest size defined by this architecture that is
* easily mappable. ARM supports 1MB mappings so it fits well. If it's
* unsupported by the arch then a reasonable size could be 1MB.
*/
#define SECTION_SIZE ARM_SECTION_SIZE
#define SECTION_MASK ARM_SECTION_MASK
#define SECTION_BITS ARM_SECTION_BITS
/* Aligns to the upper page (ceiling) */
#define page_align_up(addr) ((((unsigned int)(addr)) + \
(PAGE_SIZE - 1)) & \
(~PAGE_MASK))
/* Aligns to the lower page (floor) */
#define page_align(addr) (((unsigned int)(addr)) & \
(~PAGE_MASK))
#define is_aligned(val, mask) (!(((unsigned long)val) & mask))
#define is_page_aligned(val) (!(((unsigned long)val) & PAGE_MASK))
/* Align to given size */
#define align(addr, size) (((unsigned int)(addr)) & (~(size-1)))
/* Extract page frame number from address and vice versa. */
#define __pfn(x) (((unsigned long)(x)) >> PAGE_BITS)
#define __pfn_to_addr(x) (((unsigned long)(x)) << PAGE_BITS)
/* Extract physical address from page table entry (pte) */
#define __pte_to_addr(x) (((unsigned long)(x)) & ~PAGE_MASK)
/* Minimum excess needed for word alignment */
#define SZ_WORD sizeof(unsigned int)
#define WORD_BITS 32
#define WORD_BITS_LOG2 5
#define BITWISE_GETWORD(x) ((x) >> WORD_BITS_LOG2) /* Divide by 32 */
#define BITWISE_GETBIT(x) (1 << ((x) % WORD_BITS))
#define align_up(addr, size) ((((unsigned long)(addr)) + ((size) - 1)) & (~((size) - 1)))
/* Endianness conversion */
static inline void be32_to_cpu(unsigned int x)
{
char *p = (char *)&x;
char tmp;
/* Swap bytes */
tmp = p[0];
p[0] = p[3];
p[3] = tmp;
tmp = p[1];
p[1] = p[2];
p[2] = tmp;
}
/* Some anticipated values in terms of memory consumption */
#define TASK_AVERAGE_SIZE SZ_16MB
#define TASKS_PER_1MB_GRANT 28
extern pgd_table_t kspace;
extern pmd_table_t pmd_tables[];
extern unsigned long pmdtab_i;
void init_pmd_tables(void);
pmd_table_t *alloc_boot_pmd(void);
/*
* Each time a pager grants memory to the kernel, these parameters are called
* for in order to distribute the granted memory for different purposes.
*
* The granted memory is used in an architecture-specific way, e.g. for pgds,
* pmds, and kernel stack. Therefore this should be defined per-arch.
*/
typedef struct kmem_usage_per_grant {
int grant_size; /* The size of the grant given by pager */
int task_size_avg; /* Average memory a task occupies */
int tasks_per_kmem_grant; /* Num of tasks to allocate for, per grant */
int pg_total; /* Total size of page allocs needed per grant */
int pmd_total; /* Total size of pmd allocs needed per grant */
int pgd_total; /* Total size of pgd allocs needed per grant */
int extra; /* Extra unused space, left per grant */
} kmem_usage_per_grant_t;
void paging_init(void);
void init_pmd_tables(void);
void init_clear_ptab(void);
unsigned int space_flags_to_ptflags(unsigned int flags);
void add_boot_mapping(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags);
void add_mapping_pgd(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags,
pgd_table_t *pgd);
void add_mapping(unsigned int paddr, unsigned int vaddr,
unsigned int size, unsigned int flags);
void remove_mapping(unsigned long vaddr);
void remove_mapping_pgd(unsigned long vaddr, pgd_table_t *pgd);
void prealloc_phys_pagedesc(void);
void copy_pgd_kern_all(pgd_table_t *);
pte_t virt_to_pte(unsigned long virtual);
pte_t virt_to_pte_from_pgd(unsigned long virtual, pgd_table_t *pgd);
#endif /* __GLUE_ARM_MEMORY_H__ */

View File

@@ -0,0 +1,60 @@
/*
* ARM-specific system call details.
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __ARM_GLUE_SYSCALL_H__
#define __ARM_GLUE_SYSCALL_H__
/* Only specific call is the trap that gives back the kip address
* from which other system calls can be discovered. */
#define L4_TRAP_KIP 0xB4
/* Used in the kernel to refer to virtual address of this page.
* User space discovers it from the KIP */
#define ARM_SYSCALL_PAGE 0xFFFFF000
extern unsigned int __syscall_page_start;
typedef struct syscall_args {
u32 r0;
u32 r1;
u32 r2;
u32 r3; /* MR0 */
u32 r4; /* MR1 */
u32 r5; /* MR2 */
u32 r6; /* MR3 */
u32 r7; /* MR4 */
u32 r8; /* MR5 */
} syscall_args_t;
typedef struct msg_regs {
u32 mr0;
u32 mr1;
u32 mr2;
u32 mr3;
u32 mr4;
u32 mr5;
} msg_regs_t;
/* NOTE:
* These references are valid only when they have been explicitly set
* by a kernel entry point, e.g. a system call, a data abort handler.
*/
#define KTCB_REF_ARG0(ktcb) (&(ktcb)->syscall_regs->r0)
#define KTCB_REF_MR0(ktcb) (&(ktcb)->syscall_regs->r3)
/* Represents each syscall. We get argument registers
* from stack for now. This is slower but the simplest. */
typedef int (*syscall_fn_t)(struct syscall_args *regs);
/* Entry point for syscall dispatching. Called from asm */
int syscall(struct syscall_args *regs, unsigned long);
/* Syscall-related initialiser called during system init. */
void syscall_init(void);
void kip_init_syscalls(void);
#endif /* __ARM_GLUE_SYSCALL_H__ */

View File

@@ -0,0 +1,18 @@
/*
* Userspace thread control block
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __GLUE_ARM_UTCB_H__
#define __GLUE_ARM_UTCB_H__
#define MR_TOTAL 6
/* Compact utcb for now! 8-) */
struct utcb {
u32 mr[MR_TOTAL];
u32 global_id; /* Thread id */
u32 usr_handle; /* Use as TLS */
};
#endif /* __GLUE_ARM_UTCB_H__ */

View File

@@ -0,0 +1,107 @@
/*
* Mock-up memory layout definitions for test purposes.
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __BASICLAYOUT_H__
#define __BASICLAYOUT_H__
#ifndef __ASSEMBLY__
#include INC_GLUE(memory.h)
#endif
#include INC_PLAT(offsets.h)
#define RESERVED_AREA_START 0x0
#define RESERVED_AREA_END 0x00400000
#define RESERVED_AREA_SIZE (RESERVED_AREA_END - RESERVED_AREA_START)
#define RESERVED_AREA_SECTIONS (RESERVED_AREA_SIZE / ARM_SECTION_SIZE)
/* 0x00400000 */
#define USER_AREA_START 0x00400000
#define USER_AREA_END 0xF0000000
#define USER_AREA_SIZE (USER_AREA_END - USER_AREA_START)
#define USER_AREA_SECTIONS (USER_AREA_SIZE / ARM_SECTION_SIZE)
/* 0xf0000000 */
#define KERNEL_AREA_START 0xF0000000
#define KERNEL_AREA_END 0xF4000000
#define KERNEL_AREA_SIZE (KERNEL_AREA_END - KERNEL_AREA_START)
#define KERNEL_AREA_SECTIONS (KERNEL_AREA_SIZE / ARM_SECTION_SIZE)
/* Kernel offset is taken as virtual memory base */
#define VIRT_ADDR_BASE KERNEL_AREA_START
/* 0xf4000000 */
#define UNCACHE_AREA_START 0xF4000000
#define UNCACHE_AREA_END 0xF8000000
#define UNCACHE_AREA_SIZE (UNCACHE_AREA_END - UNCACHE_AREA_START)
#define UNCACHE_AREA_SECTIONS (UNCACHE_AREA_SIZE / ARM_SECTION_SIZE)
/* The page tables are the main clients of uncached virtual memory */
#define PGTABLE_ADDR_BASE UNCACHE_AREA_START
/* 0xf8000000 */
#define VAR_AREA_START 0xF8000000
#define VAR_AREA_END 0xF9000000
#define VAR_AREA_SIZE (VAR_AREA_END - VAR_AREA_START)
#define VAR_AREA_SECTIONS (VAR_AREA_SIZE / ARM_SECTION_SIZE)
/* 0xf9000000 */
#define IO_AREA_START 0xF9000000
#define IO_AREA_END 0xFF000000
#define IO_AREA_SIZE (IO_AREA_END - IO_AREA_START)
#define IO_AREA_SECTIONS (IO_AREA_SIZE / ARM_SECTION_SIZE)
/* 0xff000000 */
#define MISC_AREA_START 0xFF000000
#define MISC_AREA_END 0xFFF00000
#define MISC_AREA_SIZE (MISC_AREA_END - MISC_AREA_START)
#define MISC_AREA_SECTIONS (MISC_AREA_SIZE / ARM_SECTION_SIZE)
/* First page in MISC area is used for KIP/UTCB reference page */
#define USER_KIP_PAGE MISC_AREA_START
/* 0xfff00000 */
#define EXCPT_AREA_START 0xFFF00000
#define EXCPT_AREA_END (EXCPT_AREA_START + ARM_SECTION_SIZE)
#define EXCPT_AREA_SIZE (EXCPT_AREA_END - EXCPT_AREA_START)
/* 1MB IO Areas in the Virtual Address space. Define more if needed */
#define IO_AREA0_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*0))
#define IO_AREA1_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*1))
#define IO_AREA2_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*2))
#define IO_AREA3_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*3))
#define IO_AREA4_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*4))
#define IO_AREA5_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*5))
#define IO_AREA6_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*6))
#define IO_AREA7_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*7))
/*
* Address of start of arm_high_vector - exception handling code
*/
#define ARM_HIGH_VECTOR_VADDR (EXCPT_AREA_START | 0x000f0000 )
#define ARM_SYSCALL_VECTOR (0xffffff00)
/*
* These offsets depend on where the platform defines its physical memory
* and how the system defines the virtual memory regions in arm/basiclayout.h
*/
//#define KERNEL_OFFSET (VIRT_ADDR_BASE - PHYS_ADDR_BASE)
//#define PGTABLE_OFFSET (PGTABLE_ADDR_BASE - PGTABLE_PHYS_ADDR_BASE)
/* Use a more predictible offset by just changing the top nibble */
#define KERNEL_OFFSET VIRT_ADDR_BASE
#define PGTABLE_OFFSET PGTABLE_ADDR_BASE
/*
* Convenience macros for converting between address types.
*/
#if defined(__KERNEL__)
#define phys_to_virt(addr) ((unsigned int)addr)
#define phys_to_ptab(addr) ((unsigned int)addr)
#define virt_to_phys(addr) ((unsigned int)addr)
#define virt_to_ptab(addr) (phys_to_ptab(virt_to_phys(addr)))
#endif
#endif /* __BASICLAYOUT_H__ */

View File

@@ -0,0 +1,84 @@
/*
* Memory related definitions for test purposes.
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __GLUE_TEST_MEMORY_H__
#define __GLUE_TEST_MEMORY_H__
/* ARM specific definitions */
#define TEST_SECTION_SIZE SZ_1MB
//#define TEST_PAGE_SIZE SZ_4K
//#define TEST_PAGE_MASK 0xFFF
//#define TEST_PAGE_BITS 12
#define TEST_PAGE_SIZE 128
#define TEST_PAGE_MASK (TEST_PAGE_SIZE-1)
#define TEST_PAGE_BITS 7
#define TEST_SECTION_MASK 0xFFFFF
/* Aligns to the upper page (ceiling) */
#define page_align_up(addr) ((((unsigned int)(addr)) + \
(PAGE_SIZE - 1)) & \
(~PAGE_MASK))
/* Aligns to the lower page (floor) */
#define page_align(addr) (((unsigned int)(addr)) & \
(~PAGE_MASK))
/* Align to given size */
#define align(addr, size) (((unsigned int)(addr)) & (~(size-1)))
/* Extract page frame number from address */
#define __pfn(x) (((unsigned long)(x)) >> PAGE_BITS)
#define __pfn_to_addr(x) (((unsigned long)(x)) << PAGE_BITS)
/* Extract physical address from page table entry (pte) */
#define __pte_to_addr(x) (((unsigned long)(x)) & ~PAGE_MASK)
/* Minimum excess needed for word alignment */
#define SZ_WORD sizeof(unsigned long)
#define WORD_BITS 32
#define BITWISE_GETWORD(x) ((x) >> 5) /* Divide by 32 */
#define BITWISE_GETBIT(x) (1 << ((x) % WORD_BITS))
#define align_up(addr, size) ((((unsigned long)(addr)) + ((size) - 1)) & (~((size) - 1)))
/* Generic definitions */
extern unsigned int PAGE_SIZE;
extern unsigned int PAGE_MASK;
extern unsigned int PAGE_BITS;
/* 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[SZ_4K];
} pgd_table_t;
/* Page middle directory made up of pmd_t entries */
typedef struct pmd_table {
pmd_t entry[256];
} pmd_table_t;
/* Number of pmd tables to describe all physical memory.
* TODO: Need more for IO etc. */
#define NUM_PMD_TABLES ((PHYS_MEM_END - PHYS_MEM_START) / PAGE_SIZE) \
/ PMD_NUM_PAGES
/* Page table related */
extern pgd_table_t kspace;
extern pmd_table_t pmd_tables[];
extern unsigned long pmdtab_i;
void paging_init(void);
void init_clear_ptab(void);
#endif /* __GLUE_TEST_MEMORY_H__ */

View File

@@ -0,0 +1,19 @@
#ifndef __GLUE__V4_ARM__UTCB_H__
#define __GLUE__V4_ARM__UTCB_H__
/*
* Userspace thread control block
*
* Copyright (C) 2005 Bahadir Balban
*
*/
#include <macros.h>
#include <config.h>
#include <types.h>
struct utcb {
u32 global_id;
u32 error_code;
};
#endif /* !__GLUE__V4_ARM__UTCB_H__ */

38
include/l4/lib/bit.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef __LIB_BIT_H__
#define __LIB_BIT_H__
unsigned int __clz(unsigned int bitvector);
int find_and_set_first_free_bit(u32 *word, unsigned int lastbit);
int check_and_clear_bit(u32 *word, int bit);
/* Set */
static inline void setbit(unsigned int *w, unsigned int flags)
{
*w |= flags;
}
/* Clear */
static inline void clrbit(unsigned int *w, unsigned int flags)
{
*w &= ~flags;
}
/* Test */
static inline int tstbit(unsigned int *w, unsigned int flags)
{
return *w & flags;
}
/* Test and clear */
static inline int tstclr(unsigned int *w, unsigned int flags)
{
int res = tstbit(w, flags);
clrbit(w, flags);
return res;
}
#endif /* __LIB_BIT_H__ */

15
include/l4/lib/idpool.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef __IDPOOL_H__
#define __IDPOOL_H__
#include <l4/lib/bit.h>
struct id_pool {
int nwords;
u32 bitmap[];
};
struct id_pool *id_pool_new_init(int mapsize);
int id_new(struct id_pool *pool);
int id_del(struct id_pool *pool, int id);
#endif /* __IDPOOL_H__ */

520
include/l4/lib/list.h Normal file
View File

@@ -0,0 +1,520 @@
#ifndef __LIST_H__
#define __LIST_H__
/*
* LICENSE:
* Clever linked list implementation taken from Linux.
*/
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
#define LIST_POISON1 ((void *) 0xDEADBEE0)
#define LIST_POISON2 ((void *) 0xDEADBEE4)
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next;
struct list_head *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is
* empty _and_ checks that no other CPU might be
* in the process of still modifying either member
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*
* @head: the list to test.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; /* prefetch(pos->next), */ pos != (head); \
pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
/* prefetch(pos->member.next), */ &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use as a start point in
* list_for_each_entry_continue
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - iterate over list of given type
* continuing after existing point
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type
* continuing from existing point
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue - iterate over list of given type
* continuing after existing point safe against removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from - iterate over list of given type
* from existing point safe against removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
* removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = 0 }
#define HLIST_HEAD(name) struct hlist_head name = { .first = 0 }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = 0)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = 0;
h->pprev = 0;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
* @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from existing point
* @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif /* __LIST_H__ */

6
include/l4/lib/math.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef __LIB_MATH_H__
#define __LIB_MATH_H__
#define min(x, y) (((x) < (y)) ? x : y)
#endif /* __LIB_MATH_H__ */

54
include/l4/lib/memcache.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* Bitmap-based link-listable fixed-size memory cache.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MEMCACHE_H__
#define __MEMCACHE_H__
#include <l4/config.h>
#include <l4/macros.h>
#include <l4/types.h>
#include <l4/lib/list.h>
#include <l4/lib/mutex.h>
/*
* Very basic cache structure. All it does is, keep an internal bitmap of
* items of struct_size. (Note bitmap is fairly efficient and simple for a
* fixed-size memory cache) Keeps track of free/occupied items within its
* start/end boundaries. Does not grow/shrink but you can link-list it.
*/
struct mem_cache {
struct list_head list;
struct mutex mutex;
int total;
int free;
unsigned int start;
unsigned int end;
unsigned int struct_size;
unsigned int *bitmap;
};
void *mem_cache_zalloc(struct mem_cache *cache);
void *mem_cache_alloc(struct mem_cache *cache);
int mem_cache_free(struct mem_cache *cache, void *addr);
struct mem_cache *mem_cache_init(void *start, int cache_size,
int struct_size, unsigned int alignment);
static inline int mem_cache_is_full(struct mem_cache *cache)
{
return cache->free == 0;
}
static inline int mem_cache_is_empty(struct mem_cache *cache)
{
return cache->free == cache->total;
}
static inline int mem_cache_is_last_free(struct mem_cache *cache)
{
return cache->free == 1;
}
static inline int mem_cache_total_empty(struct mem_cache *cache)
{
return cache->free;
}
#endif /* __MEMCACHE_H__ */

45
include/l4/lib/mutex.h Normal file
View File

@@ -0,0 +1,45 @@
/*
* The elementary concurrency constructs.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __LIB_MUTEX_H__
#define __LIB_MUTEX_H__
#include <l4/lib/string.h>
#include <l4/lib/spinlock.h>
#include <l4/lib/list.h>
#include <l4/lib/printk.h>
#include <l4/lib/wait.h>
#include INC_ARCH(mutex.h)
/* A mutex is a binary semaphore that can sleep. */
struct mutex {
int sleepers; /* Number of sleepers */
struct spinlock slock; /* Locks sleeper queue */
unsigned int lock; /* The mutex lock itself */
struct waitqueue wq; /* Sleeper queue head */
};
static inline void mutex_init(struct mutex *mutex)
{
memset(mutex, 0, sizeof(struct mutex));
INIT_LIST_HEAD(&mutex->wq.task_list);
}
void mutex_lock(struct mutex *mutex);
void mutex_unlock(struct mutex *mutex);
/* NOTE: Since spinlocks guard mutex acquiring & sleeping, no locks needed */
static inline int mutex_inc(unsigned int *cnt)
{
return ++*cnt;
}
static inline int mutex_dec(unsigned int *cnt)
{
return --*cnt;
}
#endif /* __LIB_MUTEX_H__ */

18
include/l4/lib/printk.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef __PRINTK_H__
#define __PRINTK_H__
#include <stdarg.h>
#if defined(ARCH_TEST)
/* For host tests all printks mean printf using the host C library */
#include <stdio.h>
#define printk printf
#elif !defined(__KERNEL__)
#define printk printf
#else
int printk(char *format, ...) __attribute__((format (printf, 1, 2)));
extern void putc(char c);
#endif
#endif /* __PRINTK_H__ */

57
include/l4/lib/spinlock.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef __LIB_SPINLOCK_H__
#define __LIB_SPINLOCK_H__
#include <l4/lib/string.h>
#include <l4/generic/preempt.h>
#include INC_ARCH(exception.h)
struct spinlock {
unsigned int lock;
};
static inline void spin_lock_init(struct spinlock *s)
{
memset(s, 0, sizeof(struct spinlock));
}
/*
* - Guards from deadlock against local processes, but not local irqs.
* - To be used for synchronising against processes on *other* cpus.
*/
static inline void spin_lock(struct spinlock *s)
{
preempt_disable();
#if defined(CONFIG_SMP)
__spin_lock(&s->lock);
#endif
}
static inline void spin_unlock(struct spinlock *s)
{
#if defined(CONFIG_SMP)
__spin_unlock(&s->lock);
#endif
preempt_enable();
}
/*
* - Guards from deadlock against local processes *and* local irqs.
* - To be used for synchronising against processes and irqs
* on other cpus.
*/
static inline void spin_lock_irq(struct spinlock *s)
{
irq_local_disable(); /* Even in UP an irq could deadlock us */
#if defined(CONFIG_SMP)
__spin_lock(&s->lock);
#endif
}
static inline void spin_unlock_irq(struct spinlock *s)
{
#if defined(CONFIG_SMP)
__spin_unlock(&s->lock);
#endif
irq_local_enable();
}
#endif /* __LIB__SPINLOCK_H__ */

9
include/l4/lib/string.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __LIB_STRING_H__
#define __LIB_STRING_H__
char *strncpy(char *dest, const char *src, int count);
int strcmp(const char *s1, const char *s2);
void *memset(void *p, int c, int size);
void *memcpy(void *d, void *s, int size);
#endif /* __LIB_STRING_H__ */

45
include/l4/lib/wait.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __LIB_WAIT_H__
#define __LIB_WAIT_H__
#include <l4/lib/list.h>
#include <l4/lib/spinlock.h>
struct ktcb;
struct waitqueue {
struct list_head task_list;
struct ktcb *task;
};
#define DECLARE_WAITQUEUE(wq, tsk) \
struct waitqueue wq = { \
.task_list = { &wq.task_list, &wq.task_list }, \
.task = tsk, \
};
// LIST_HEAD_INIT(task_list),
/*
* The waitqueue spinlock ensures waiters are added and removed atomically so
* that wake-ups and sleeps occur in sync. Otherwise, a task could try to wake
* up a waitqueue **during when a task has decided to sleep but is not in the
* queue yet. (** Take "during" here as a pseudo-concurrency term on UP)
*/
struct waitqueue_head {
int sleepers;
struct spinlock slock; /* Locks sleeper queue */
struct list_head task_list; /* Sleeper queue head */
};
static inline void waitqueue_head_init(struct waitqueue_head *head)
{
memset(head, 0, sizeof(struct waitqueue_head));
INIT_LIST_HEAD(&head->task_list);
}
/*
* Used for ipc related waitqueues who have special wait queue manipulation
* conditions.
*/
void wake_up(struct waitqueue_head *wqh);
#endif /* __LIB_WAIT_H__ */

109
include/l4/macros.h Normal file
View File

@@ -0,0 +1,109 @@
#ifndef __MACROS_H__
#define __MACROS_H__
#include "config.h"
/*
* This file is automatically included before the first line of any
* source file, using gcc's -imacro command line option. Only macro
* definitions will be extracted.
*/
#define INC_ARCH(x) <l4/arch/__ARCH__/x>
#define INC_SUBARCH(x) <l4/arch/__ARCH__/__SUBARCH__/x>
#define INC_CPU(x) <l4/arch/__ARCH__/__SUBARCH__/__CPU__/x>
#define INC_PLAT(x) <l4/platform/__PLATFORM__/x>
#define INC_API(x) <l4/api/x>
#define INC_GLUE(x) <l4/glue/__ARCH__/x>
/* use this to place code/data in a certain section */
#define SECTION(x) __attribute__((section(x)))
#define UNIT(x) __attribute__((section(".data." x)))
/*
* use WEAK to specifiy a weak function which can be replaced
* by a architecture specific optimization
* example: void WEAK bla()
*/
#define WEAK __attribute__(( weak ))
/*
* Marks a function as noreturn.
*/
#define NORETURN __attribute__(( noreturn ))
/* Functions for critical path optimizations */
#if (__GNUC__ >= 3)
#define unlikely(x) __builtin_expect((x), false)
#define likely(x) __builtin_expect((x), true)
#define likelyval(x,val) __builtin_expect((x), (val))
#else /* __GNUC__ < 3 */
#define likely(x) (x)
#define unlikely(x) (x)
#define likelyval(x,val) (x)
#endif /* __GNUC__ < 3 */
/* This guard is needed because tests use host C library and NULL is defined */
#ifndef NULL
#define NULL 0
#endif
/* Convenience functions for memory sizes. */
#define SZ_1K 1024
#define SZ_4K 0x1000
#define SZ_16K 0x4000
#define SZ_64K 0x10000
#define SZ_1MB 0x100000
#define SZ_16MB (16*SZ_1MB)
#define SZ_1K_BITS 10
#define SZ_4K_BITS 12
#define SZ_16K_BITS 14
#define SZ_1MB_BITS 20
#ifndef __ASSEMBLY__
#include <stddef.h> /* offsetof macro, defined in the `standard' way. */
#endif
/* Offset of struct fields. */
//#if (__GNUC__ >= 4)
//#define offsetof(type, field) __builtin_offsetof(type, field)
//#else
//#define offsetof(type, field) (u32)(&((type *)0)->field)
//#endif
/* LICENSE: Taken off Linux */
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
/* Prefetching is noop for now */
#define prefetch(x) x
#if !defined(__KERNEL__)
#define printk printf
#endif
/* TEST: Is this type of printk well tested? */
#define BUG() {do { \
printk("BUG in file: %s function: %s line: %d\n", \
__FILE__, __FUNCTION__, __LINE__); \
} while(0); \
while(1);}
#define BUG_ON(x) {if (x) BUG();}
#define BUG_ON_MSG(msg, x) do { \
printk(msg); \
BUG_ON(x) \
} while(0)
#define BUG_MSG(msg...) do { \
printk(msg); \
BUG(); \
} while(0)
#endif /* !__MACROS_H__ */

View File

@@ -0,0 +1,47 @@
#ifndef __DEBUG_MACRO_S__
#define __DEBUG_MACRO_S__
#include INC_PLAT(offsets.h)
#define UART01x_DR 0x00
/*
* linux/arch/arm/kernel/debug.S
*
* Copyright (C) 1994-1999 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 32-bit debugging code
*/
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
moveq \rx, #0x10000000
orreq \rx, \rx, #0x001F0000
orreq \rx, \rx, #0x00001000
/* FIXME: This offset is incorrect for now. Make sure you pass correct offset */
movne \rx, #0xf9000000 @#IO_AREA0_VADDR
@movne \rx, #IO_AREA0_VADDR
addne \rx, \rx, #PB926_UART0_VOFFSET @ UART0 page offset from
@ virtual io area base.
.endm
.macro senduart,rd,rx
strb \rd, [\rx, #UART01x_DR]
.endm
.macro waituart,rd,rx
1001: ldr \rd, [\rx, #0x18] @ UARTFLG
tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
bne 1001b
.endm
.macro busyuart,rd,rx
1001: ldr \rd, [\rx, #0x18] @ UARTFLG
tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
bne 1001b
.endm
#endif /* __DEBUG_MACRO_S__ */

View File

@@ -0,0 +1,27 @@
#ifndef __PLATFORM_IRQ_H__
#define __PLATFORM_IRQ_H__
#define IRQ_CHIPS_MAX 2
#define IRQS_MAX 64
/* IRQ indices. */
#define IRQ_TIMER01 4
#define IRQ_TIMER23 5
#define IRQ_RTC 10
#define IRQ_UART0 12
#define IRQ_UART1 13
#define IRQ_UART2 14
#define IRQ_SIC 31
/* Cascading definitions */
#define PIC_IRQS_MAX 31 /* Total irqs on PIC */
/* The local irq line of the dummy peripheral on this chip */
#define LOCALIRQ_DUMMY 15
/* The irq index offset of this chip, is the maximum of previous chip + 1 */
#define SIRQ_CHIP_OFFSET (PIC_IRQS_MAX + 1)
/* The global irq number of dummy is the local irq line + it's chip offset */
#define IRQ_DUMMY (LOCALIRQ_DUMMY + SIRQ_CHIP_OFFSET)
#endif /* __PLATFORM_IRQ_H__ */

View File

@@ -0,0 +1,60 @@
/*
* Describes physical memory layout of pb926 platform.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __PLATFORM_PB926_OFFSETS_H__
#define __PLATFORM_PB926_OFFSETS_H__
/* Physical memory base */
#define PHYS_MEM_START 0x00000000 /* inclusive */
#define PHYS_MEM_END 0x08000000 /* 128 MB, exclusive */
/*
* These bases taken from where kernel is `physically' linked at,
* also used to calculate virtual-to-physical translation offset.
* See the linker script for their sources. PHYS_ADDR_BASE can't
* use a linker variable because it's referred from assembler.
*/
#define PHYS_ADDR_BASE 0x100000
/* Device memory base */
#define PB926_DEV_PHYS 0x10000000
/* Device offsets in physical memory */
#define PB926_SYSTEM_REGISTERS 0x10000000 /* System registers */
#define PB926_SYSCTRL_BASE 0x101E0000 /* System controller */
#define PB926_WATCHDOG_BASE 0x101E1000 /* Watchdog */
#define PB926_TIMER01_BASE 0x101E2000 /* Timers 0 and 1 */
#define PB926_TIMER23_BASE 0x101E3000 /* Timers 2 and 3 */
#define PB926_RTC_BASE 0x101E8000 /* Real Time Clock */
#define PB926_VIC_BASE 0x10140000 /* Primary Vectored IC */
#define PB926_SIC_BASE 0x10003000 /* Secondary IC */
#define PB926_UART0_BASE 0x101F1000 /* Console port (UART0) */
/*
* Uart virtual address until a file-based console access
* is available for userspace
*/
#define USERSPACE_UART_BASE 0x500000
/*
* Device offsets in virtual memory. They offset to some virtual
* device base address. Each page on this virtual base is consecutively
* allocated to devices. Nice and smooth.
*/
#define PB926_TIMER01_VOFFSET 0x00000000
#define PB926_UART0_VOFFSET 0x00001000
#define PB926_VIC_VOFFSET 0x00002000
#define PB926_SIC_VOFFSET 0x00003000
#define PB926_SYSREGS_VOFFSET 0x00005000
#define PB926_SYSCTRL_VOFFSET 0x00006000
#define PB926_UART0_VBASE (IO_AREA0_VADDR + PB926_UART0_VOFFSET)
#define PB926_TIMER01_VBASE (IO_AREA0_VADDR + PB926_TIMER01_VOFFSET)
#define PB926_SYSCTRL_VBASE (IO_AREA0_VADDR + PB926_SYSCTRL_VOFFSET)
#define PB926_VIC_VBASE (IO_AREA0_VADDR + PB926_VIC_VOFFSET)
#define PB926_SIC_VBASE (IO_AREA0_VADDR + PB926_SIC_VOFFSET)
#endif /* __PLATFORM_PB926_OFFSETS_H__ */

View File

@@ -0,0 +1,22 @@
#ifndef __PLATFORM_PB926_PLATFORM_H__
#define __PLATFORM_PB926_PLATFORM_H__
/*
* Platform specific ties between drivers and generic APIs used by the kernel.
* E.g. system timer and console.
*
* Copyright (C) Bahadir Balban 2007
*/
#include INC_PLAT(offsets.h)
#include INC_GLUE(memlayout.h)
#define PLATFORM_CONSOLE_BASE PB926_UART0_VBASE
#define PLATFORM_TIMER_BASE PB926_TIMER01_VBASE
#define PLATFORM_SP810_BASE PB926_SYSCTRL_VBASE
#define PLATFORM_IRQCTRL_BASE PB926_VIC_VBASE
#define PLATFORM_SIRQCTRL_BASE PB926_SIC_VBASE
void platform_irq_enable(int irq);
void platform_irq_disable(int irq);
void timer_start(void);
#endif /* __PLATFORM_PB926_PLATFORM_H__ */

View File

@@ -0,0 +1,13 @@
#ifndef __PLATFORM__PB926__PRINTASCII__H__
#define __PLATFORM__PB926__PRINTASCII__H__
#define dprintk(str, val) \
printascii(str); \
printascii("0x"); \
printhex8((val)); \
printascii("\n");
void printascii(char *str);
void printhex8(unsigned int);
#endif /* __PLATFORM__PB926__PRINTASCII__H__ */

View File

@@ -0,0 +1,20 @@
/*
* Platform specific ties to generic uart functions that putc expects.
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __PLATFORM_PB926_UART_H__
#define __PLATFORM_PB926_UART_H__
#include INC_PLAT(offsets.h)
#include INC_GLUE(memlayout.h)
#define PLATFORM_CONSOLE_BASE PB926_UART0_VBASE
#include <l4/drivers/uart/pl011/pl011_uart.h>
void uart_init(void);
void uart_putc(char c);
#endif /* __PLATFORM_PB926_UART_H__ */

View File

@@ -0,0 +1,49 @@
#ifndef __DEBUG__MACRO__S__
#define __DEBUG__MACRO__S__
#include <macros.h>
#include <config.h>
#include INC_PLAT(offsets.h)
#define UART01x_DR 0x00
/*
* linux/arch/arm/kernel/debug.S
*
* Copyright (C) 1994-1999 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 32-bit debugging code
*/
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
moveq \rx, #0x10000000
orreq \rx, \rx, #0x001F0000
orreq \rx, \rx, #0x00001000
/* FIXME: This offset is incorrect for now. Make sure you pass correct offset */
movne \rx, #0xf9000000 @#IO_AREA0_VADDR
addne \rx, \rx, #0xF1000
@ addne \rx, \rx, #PB926_UART0_VOFFSET @ UART0 page offset from
@ virtual io area base.
.endm
.macro senduart,rd,rx
strb \rd, [\rx, #UART01x_DR]
.endm
.macro waituart,rd,rx
1001: ldr \rd, [\rx, #0x18] @ UARTFLG
tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
bne 1001b
.endm
.macro busyuart,rd,rx
1001: ldr \rd, [\rx, #0x18] @ UARTFLG
tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
bne 1001b
.endm
#endif /* __DEBUG__MACRO__S__ */

View File

@@ -0,0 +1,50 @@
/*
* Mock-up platform definition file for test purposes
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __PLATFORM_TEST_OFFSETS__H__
#define __PLATFORM_TEST_OFFSETS__H__
/* Physical memory base */
extern unsigned int PHYS_MEM_START;
extern unsigned int PHYS_MEM_END;
extern unsigned int PHYS_ADDR_BASE;
/*
* These bases taken from where kernel is `physically' linked at,
* also used to calculate virtual-to-physical translation offset.
* See the linker script for their sources. PHYS_ADDR_BASE can't
* use a linker variable because it's referred from assembler.
*/
/* Device memory base */
#define PB926_DEV_PHYS 0x10000000
/* Device offsets in physical memory */
#define PB926_SYSREGS_BASE 0x10000000 /* System registers */
#define PB926_SYSCNTL_BASE 0x101E0000 /* System controller */
#define PB926_WATCHDOG_BASE 0x101E1000 /* Watchdog */
#define PB926_TIMER0_1_BASE 0x101E2000 /* Timers 0 and 1 */
#define PB926_TIMER1_2_BASE 0x101E3000 /* Timers 2 and 3 */
#define PB926_RTC_BASE 0x101E8000 /* Real Time Clock */
#define PB926_VIC_BASE 0x10140000 /* Primary Vectored IC */
#define PB926_SIC_BASE 0x10003000 /* Secondary IC */
#define PB926_UART0_BASE 0x101F1000 /* Console port (UART0) */
/*
* BB: Device offsets in virtual memory. They offset to some virtual
* device base address. Each page on this virtual base is consecutively
* allocated to devices. Nice and smooth.
*/
#define PB926_TIMER0_1_VOFFSET 0x00001000
#define PB926_VIC_VOFFSET 0x00002000
#define PB926_SIC_VOFFSET 0x00003000
#define PB926_UART0_VOFFSET 0x00004000
#define PB926_SYSREGS_VOFFSET 0x00005000
#define PB926_SYSCNTL_VOFFSET 0x00006000
#endif /*__PLATFORM_TEST_OFFSETS_H__*/

View File

@@ -0,0 +1,7 @@
#ifndef __PLATFORM__PB926__PLATFORM__H__
#define __PLATFORM__PB926__PLATFORM__H__
void init_platform_mappings(void);
void init_platform_console(void);
#endif /* __PLATFORM_PB926__PLATFORM__H__ */

View File

@@ -0,0 +1,20 @@
#ifndef __PLATFORM__PB926__PRINTASCII__H__
#define __PLATFORM__PB926__PRINTASCII__H__
/* This include is for the C library on the host. So that
* any test executables that run on host can use it.
* Don't confuse it with anything else.
*/
#include <stdio.h>
#define printascii(str) printf(str)
#define printhex8(x) printf("0x%x",(unsigned int)x)
#define dprintk(str, val) printf("%-25s0x%x\n", str, val)
/*
#define dprintk(str, val) \
printascii(str); \
printhex8((val)); \
printascii("\n");
*/
#endif /* __PLATFORM__PB926__PRINTASCII__H__ */

View File

@@ -0,0 +1,30 @@
#ifndef __PLATFORM__PB926__UART__H__
#define __PLATFORM__PB926__UART__H__
/*
* Platform specific ties to generic uart functions that putc expects.
*
* Copyright (C) 2005 Bahadir Balban
*
*/
/* C library on host */
#include <stdio.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(basiclayout.h)
/* TODO: PL011_BASE must point at a well-known virtual uart base address */
//#define PL011_BASE PB926_UART0_BASE
#define PL011_BASE (IO_AREA0_VADDR + 0xF1000)
#include <drivers/uart/pl011/pl011_uart.h>
static inline void uart_initialise(void)
{
}
#define uart_putc(c) printf("%c",(char)c)
#endif /* __PLATFORM__PB926__UART__H__ */

7
include/l4/types.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef __TYPES_H__
#define __TYPES_H__
#include INC_ARCH(types.h)
#endif /* __TYPES_H__ */