mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Initial commit
This commit is contained in:
169
include/l4/api/errno.h
Normal file
169
include/l4/api/errno.h
Normal 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
29
include/l4/api/ipc.h
Normal 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
98
include/l4/api/kip.h
Normal 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
18
include/l4/api/space.h
Normal 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
43
include/l4/api/syscall.h
Normal 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
9
include/l4/api/thread.h
Normal 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
143
include/l4/arch/arm/asm.h
Normal 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__ */
|
||||
25
include/l4/arch/arm/bootdesc.h
Normal file
25
include/l4/arch/arm/bootdesc.h
Normal 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__ */
|
||||
88
include/l4/arch/arm/exception.h
Normal file
88
include/l4/arch/arm/exception.h
Normal 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
12
include/l4/arch/arm/io.h
Normal 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__ */
|
||||
34
include/l4/arch/arm/linker.h
Normal file
34
include/l4/arch/arm/linker.h
Normal 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__ */
|
||||
15
include/l4/arch/arm/mutex.h
Normal file
15
include/l4/arch/arm/mutex.h
Normal 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
|
||||
87
include/l4/arch/arm/mylink.lds
Normal file
87
include/l4/arch/arm/mylink.lds
Normal 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 = .;
|
||||
}
|
||||
|
||||
18
include/l4/arch/arm/types.h
Normal file
18
include/l4/arch/arm/types.h
Normal 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__ */
|
||||
13
include/l4/arch/arm/v5/arm926ejs/cpu.h
Normal file
13
include/l4/arch/arm/v5/arm926ejs/cpu.h
Normal 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
147
include/l4/arch/arm/v5/mm.h
Normal 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__ */
|
||||
33
include/l4/arch/arm/v5/mmu_ops.h
Normal file
33
include/l4/arch/arm/v5/mmu_ops.h
Normal 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__ */
|
||||
0
include/l4/arch/arm/v5/mutex.h
Normal file
0
include/l4/arch/arm/v5/mutex.h
Normal file
22
include/l4/arch/tests/linker.h
Normal file
22
include/l4/arch/tests/linker.h
Normal 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__ */
|
||||
68
include/l4/arch/tests/tests/mm.h
Normal file
68
include/l4/arch/tests/tests/mm.h
Normal 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__ */
|
||||
13
include/l4/arch/tests/types.h
Normal file
13
include/l4/arch/tests/types.h
Normal 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
45
include/l4/config.h
Normal 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
|
||||
|
||||
13
include/l4/drivers/irq/gic.h
Normal file
13
include/l4/drivers/irq/gic.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*
|
||||
*/
|
||||
#ifndef __GIC_H__
|
||||
#define __GIC_H__
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __GIC_H__ */
|
||||
241
include/l4/drivers/irq/intctrl.h
Normal file
241
include/l4/drivers/irq/intctrl.h
Normal 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__ */
|
||||
241
include/l4/drivers/irq/pl190/intctrl.h
Normal file
241
include/l4/drivers/irq/pl190/intctrl.h
Normal 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__ */
|
||||
56
include/l4/drivers/irq/pl190/pl190_vic.h
Normal file
56
include/l4/drivers/irq/pl190/pl190_vic.h
Normal 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__ */
|
||||
54
include/l4/drivers/misc/sp810/sp810_sysctrl.h
Normal file
54
include/l4/drivers/misc/sp810/sp810_sysctrl.h
Normal 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__ */
|
||||
27
include/l4/drivers/timer/sp804/sp804_timer.h
Normal file
27
include/l4/drivers/timer/sp804/sp804_timer.h
Normal 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__ */
|
||||
380
include/l4/drivers/uart/pl011/pl011_uart.h
Normal file
380
include/l4/drivers/uart/pl011/pl011_uart.h
Normal 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
80
include/l4/generic/irq.h
Normal 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__ */
|
||||
9
include/l4/generic/kmalloc.h
Normal file
9
include/l4/generic/kmalloc.h
Normal 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
|
||||
15
include/l4/generic/pgalloc.h
Normal file
15
include/l4/generic/pgalloc.h
Normal 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__ */
|
||||
45
include/l4/generic/physmem.h
Normal file
45
include/l4/generic/physmem.h
Normal 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__ */
|
||||
22
include/l4/generic/platform.h
Normal file
22
include/l4/generic/platform.h
Normal 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__ */
|
||||
12
include/l4/generic/preempt.h
Normal file
12
include/l4/generic/preempt.h
Normal 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__ */
|
||||
55
include/l4/generic/scheduler.h
Normal file
55
include/l4/generic/scheduler.h
Normal 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__ */
|
||||
21
include/l4/generic/space.h
Normal file
21
include/l4/generic/space.h
Normal 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
154
include/l4/generic/tcb.h
Normal 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__ */
|
||||
|
||||
14
include/l4/generic/thread.h
Normal file
14
include/l4/generic/thread.h
Normal 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
14
include/l4/generic/time.h
Normal 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__ */
|
||||
9
include/l4/glue/arm/init.h
Normal file
9
include/l4/glue/arm/init.h
Normal 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__ */
|
||||
71
include/l4/glue/arm/memlayout.h
Normal file
71
include/l4/glue/arm/memlayout.h
Normal 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__ */
|
||||
124
include/l4/glue/arm/memory.h
Normal file
124
include/l4/glue/arm/memory.h
Normal 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__ */
|
||||
|
||||
60
include/l4/glue/arm/syscall.h
Normal file
60
include/l4/glue/arm/syscall.h
Normal 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__ */
|
||||
18
include/l4/glue/arm/utcb.h
Normal file
18
include/l4/glue/arm/utcb.h
Normal 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__ */
|
||||
107
include/l4/glue/tests/memlayout.h
Normal file
107
include/l4/glue/tests/memlayout.h
Normal 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__ */
|
||||
84
include/l4/glue/tests/memory.h
Normal file
84
include/l4/glue/tests/memory.h
Normal 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__ */
|
||||
|
||||
19
include/l4/glue/tests/utcb.h
Normal file
19
include/l4/glue/tests/utcb.h
Normal 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
38
include/l4/lib/bit.h
Normal 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
15
include/l4/lib/idpool.h
Normal 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
520
include/l4/lib/list.h
Normal 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
6
include/l4/lib/math.h
Normal 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
54
include/l4/lib/memcache.h
Normal 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
45
include/l4/lib/mutex.h
Normal 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
18
include/l4/lib/printk.h
Normal 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
57
include/l4/lib/spinlock.h
Normal 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
9
include/l4/lib/string.h
Normal 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
45
include/l4/lib/wait.h
Normal 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
109
include/l4/macros.h
Normal 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__ */
|
||||
|
||||
47
include/l4/platform/pb926/debug-macro.S
Normal file
47
include/l4/platform/pb926/debug-macro.S
Normal 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__ */
|
||||
27
include/l4/platform/pb926/irq.h
Normal file
27
include/l4/platform/pb926/irq.h
Normal 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__ */
|
||||
60
include/l4/platform/pb926/offsets.h
Normal file
60
include/l4/platform/pb926/offsets.h
Normal 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__ */
|
||||
|
||||
22
include/l4/platform/pb926/platform.h
Normal file
22
include/l4/platform/pb926/platform.h
Normal 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__ */
|
||||
13
include/l4/platform/pb926/printascii.h
Normal file
13
include/l4/platform/pb926/printascii.h
Normal 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__ */
|
||||
20
include/l4/platform/pb926/uart.h
Normal file
20
include/l4/platform/pb926/uart.h
Normal 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__ */
|
||||
49
include/l4/platform/tests/debug-macro.S
Normal file
49
include/l4/platform/tests/debug-macro.S
Normal 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__ */
|
||||
50
include/l4/platform/tests/offsets.h
Normal file
50
include/l4/platform/tests/offsets.h
Normal 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__*/
|
||||
|
||||
7
include/l4/platform/tests/platform.h
Normal file
7
include/l4/platform/tests/platform.h
Normal 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__ */
|
||||
20
include/l4/platform/tests/printascii.h
Normal file
20
include/l4/platform/tests/printascii.h
Normal 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__ */
|
||||
30
include/l4/platform/tests/uart.h
Normal file
30
include/l4/platform/tests/uart.h
Normal 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
7
include/l4/types.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#include INC_ARCH(types.h)
|
||||
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
Reference in New Issue
Block a user