Initial commit

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

Binary file not shown.

1
tasks/mm0/include/arch Symbolic link
View File

@@ -0,0 +1 @@
arch-arm

View File

@@ -0,0 +1,16 @@
#ifndef __INITTASK_ARCH_MM_H__
#define __INITTASK_ARCH_MM_H__
#include <arch/offsets.h>
#include <l4/macros.h>
#include <l4/types.h>
#include INC_GLUE(memory.h)
#include <vm_area.h>
#define INITTASK_ADDR(x) ((x >= INITTASK_AREA_START) && (x < INITTASK_AREA_END))
struct fault_data;
unsigned int vm_prot_flags(pte_t pte);
void set_generic_fault_params(struct fault_data *fault);
#endif /* __INITTASK_ARCH_MM_H__ */

View File

@@ -0,0 +1,9 @@
#ifndef __INITTASK_ARCH_OFFSETS_H__
#define __INITTASK_ARCH_OFFSETS_H__
#define INITTASK_AREA_START 0xE0000000
#define INITTASK_AREA_END 0xF0000000
#define INITTASK_OFFSET INITTASK_AREA_START
#endif

9
tasks/mm0/include/init.h Normal file
View File

@@ -0,0 +1,9 @@
/*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __INIT_H__
#define __INIT_H__
void initialise(void);
#endif /* __INIT_H__ */

31
tasks/mm0/include/kdata.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* Data that comes from the kernel.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MM_KDATA_H__
#define __MM_KDATA_H__
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/generic/physmem.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#include INC_GLUE(memlayout.h)
#include INC_ARCH(bootdesc.h)
#include <vm_area.h>
#define BOOTDESC_IMAGE_START 1
struct initdata {
struct bootdesc *bootdesc;
struct vm_file *memfile;
struct page_bitmap page_map;
};
extern struct initdata initdata;
int request_initdata(struct initdata *i);
#endif /* __MM_KDATA_H__ */

View File

@@ -0,0 +1,43 @@
#ifndef __LIB_BIT_H__
#define __LIB_BIT_H__
#include <l4lib/types.h>
unsigned int __clz(unsigned int bitvector);
int find_and_set_first_free_bit(u32 *word, unsigned int lastbit);
int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit,
int nbits);
int check_and_clear_bit(u32 *word, int bit);
int check_and_clear_contig_bits(u32 *word, int first, int nbits);
/* 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__ */

View File

@@ -0,0 +1,17 @@
#ifndef __MM0_IDPOOL_H__
#define __MM0_IDPOOL_H__
#include <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);
int ids_new_contiguous(struct id_pool *pool, int numids);
int ids_del_contiguous(struct id_pool *pool, int first, int numids);
#endif /* __MM0_IDPOOL_H__ */

View File

@@ -0,0 +1,17 @@
/*
* Fake spinlock for future multi-threaded mm0
*/
#ifndef __MM0_SPINLOCK_H__
#define __MM0_SPINLOCK_H__
struct spinlock {
int lock;
};
static inline void spin_lock_init(struct spinlock *s) { }
static inline void spin_lock(struct spinlock *s) { }
static inline void spin_unlock(struct spinlock *s) { }
#endif /* __MM0_SPINLOCK_H__ */

View File

@@ -0,0 +1,17 @@
/*
* Virtual address allocation pool (for shm)
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __VADDR_H__
#define __VADDR_H__
#include <lib/idpool.h>
void vaddr_pool_init(struct id_pool *pool, unsigned long start,
unsigned long end);
void *vaddr_new(struct id_pool *pool, int npages);
int vaddr_del(struct id_pool *, void *vaddr, int npages);
#endif /* __VADDR_H__ */

View File

@@ -0,0 +1,40 @@
/*
* Simple linker script for userspace or svc tasks.
*
* Copyright (C) 2007 Bahadir Balban
*/
/*
* The only catch with this linker script is that everything
* is linked starting at virtual_base, and loaded starting
* at physical_base. virtual_base is the predefined region
* of virtual memory for userland applications. physical_base
* is determined at build-time, it is one of the subsequent pages
* that come after the kernel image's load area.
*/
/* INITTASK_AREA_START, see memlayout.h */
virtual_base = 0xE0000000;
INCLUDE "include/physical_base.lds"
/* physical_base = 0x228000; */
offset = virtual_base - physical_base;
ENTRY(_start)
SECTIONS
{
. = virtual_base;
_start_text = .;
.text : AT (ADDR(.text) - offset) { crt0.o(.text) *(.text) }
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
.data : AT (ADDR(.data) - offset) { *(.data) }
_start_init = .;
.init : AT (ADDR(.init) - offset) { *(.init.stack) }
. = ALIGN(8);
__stack = .; /* This is the preallocated boot stack */
_end_init = .;
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
_end = .;
}

View File

@@ -0,0 +1,32 @@
/*
* Physical page descriptor
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include <vm_area.h>
#include <kdata.h>
struct membank {
unsigned long start;
unsigned long end;
unsigned long free;
struct page *page_array;
};
extern struct membank membank[];
extern struct vm_file *swap_file;
void init_mm_descriptors(struct page_bitmap *page_map,
struct bootdesc *bootdesc, struct membank *membank);
void init_physmem(struct initdata *initdata, struct membank *membank);
void init_zero_page(void);
void *get_zero_page(void);
void put_zero_page(void);
int do_mmap(struct vm_file *mapfile, unsigned long f_offset, struct tcb *t,
unsigned long map_address, unsigned int flags, unsigned int pages);
#endif /* __MEMORY_H__ */

17
tasks/mm0/include/mmap.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* Prototypes for mmap/munmap functions that do the actual work.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MM0_MMAP_H__
#define __MM0_MMAP_H__
#include <task.h>
#include <vm_area.h>
int do_munmap(void *vaddr, unsigned long size, struct tcb *task);
int do_mmap(struct vm_file *mapfile, unsigned long f_offset, struct tcb *t,
unsigned long map_address, unsigned int flags, unsigned int pages);
#endif /* __MM0_MMAP_H__ */

View File

@@ -0,0 +1,17 @@
/*
* The next free p_align'ed LMA base address
*
* p_align = 0x8000
*
* Recap from ELF spec: p_align: Loadable process segments must have
* congruent values for p_vaddr and p_offset, modulo the page size.
* This member gives the value to which the segments are aligned in
* memory and in the file. Values 0 and 1 mean that no alignment is
* required. Otherwise, p_align should be a positive, integral power
* of 2, and p_addr should equal p_offset, modulo p_align.
* This essentially means next available address must be aligned at
* p_align, rather than the page_size, which one (well, I) would
* normally expect.
*/
physical_base = 0x20800;

35
tasks/mm0/include/shm.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef __SHM_H__
#define __SHM_H__
#include <l4/api/space.h>
#include <l4/lib/list.h>
#include <l4/macros.h>
#include <l4lib/types.h>
struct shm_descriptor {
int key; /* IPC key supplied by user task */
l4id_t shmid; /* SHM area id, allocated by mm0 */
struct list_head list; /* SHM list, used by mm0 */
struct vm_file *owner;
void *shm_addr; /* The virtual address for segment. */
unsigned long size; /* Size of the area */
unsigned int flags;
int refcnt;
};
#define SHM_AREA_MAX 64 /* Up to 64 shm areas */
/* Up to 10 pages per area, and at least 1 byte (implies 1 page) */
#define SHM_SHMMIN 1
#define SHM_SHMMAX (PAGE_SIZE * 10)
/*
* NOTE: This flags the unique shm vaddr pool. If its not globally unique
* and shm areas are cached, on ARMv5 cache aliasing occurs.
*/
#define SHM_DISJOINT_VADDR_POOL
/* Initialises shared memory bookkeeping structures */
void shm_init();
#endif /* __SHM_H__ */

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2007 Bahadir Balban
*
* MM0 Posix system call prototypes and structure
* definitions for converting data in message registers
* into system call argument format.
*/
#ifndef __MM0_SYSARGS_H__
#define __MM0_SYSARGS_H__
#include <sys/types.h>
/* For reading argument data from a system call */
struct sys_mmap_args {
void *start;
size_t length;
int prot;
int flags;
int fd;
off_t offset;
};
int sys_mmap(l4id_t sender, void *start, size_t length, int prot,
int flags, int fd, off_t offset);
struct sys_shmat_args {
l4id_t shmid;
const void *shmaddr;
int shmflg;
};
void *sys_shmat(l4id_t requester, l4id_t shmid, const void *shmaddr, int shmflg);
int sys_shmdt(l4id_t requester, const void *shmaddr);
struct sys_shmget_args {
key_t key;
int size;
int shmflg;
};
int sys_shmget(key_t key, int size, int shmflg);
#endif /* __MM0_SYSARGS_H__ */

70
tasks/mm0/include/task.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Thread control block.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __TASK_H__
#define __TASK_H__
#include <l4/macros.h>
#include <l4/types.h>
#include INC_GLUE(memlayout.h)
#include <l4/lib/list.h>
#include <l4lib/types.h>
#include <l4lib/utcb.h>
#define __TASKNAME__ "mm0"
/* Allow per-task anonymous memory to grow as much as 1 MB for now. */
#define TASK_SWAPFILE_MAXSIZE SZ_1MB
struct vm_file;
/* Stores all task information that can be kept in userspace. */
struct tcb {
/* Task list */
struct list_head list;
/* Name of the task */
char name[16];
/* Task ids */
int tid;
int spid;
/* Related task ids */
unsigned int pagerid; /* Task's pager */
/* Program segment marks */
unsigned long text_start;
unsigned long text_end;
unsigned long data_start;
unsigned long data_end;
unsigned long bss_start;
unsigned long bss_end;
unsigned long stack_start;
unsigned long stack_end; /* Exclusive of last currently mapped page */
unsigned long heap_start;
unsigned long heap_end; /* Exclusive of last currently mapped page */
/* Virtual memory areas */
struct list_head vm_area_list;
/* Per-task swap file for now */
struct vm_file *swap_file;
/* Pool to generate swap file offsets for fileless anonymous regions */
struct id_pool *swap_file_offset_pool;
};
struct tcb *find_task(int tid);
struct initdata;
void init_pm(struct initdata *initdata);
int start_init_tasks(struct initdata *initdata);
void dump_tasks(void);
/* Used by servers that have a reference to tcbs (e.g. a pager) */
#define current ((struct ktcb *)__L4_ARM_Utcb()->usr_handle)
#endif /* __TASK_H__ */

128
tasks/mm0/include/vm_area.h Normal file
View File

@@ -0,0 +1,128 @@
/*
* Virtual memory area descriptors. No page cache yet.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __VM_AREA_H__
#define __VM_AREA_H__
#include <stdio.h>
#include <task.h>
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <arch/mm.h>
#include <lib/spinlock.h>
/* Protection flags */
#define VM_NONE (1 << 0)
#define VM_READ (1 << 1)
#define VM_WRITE (1 << 2)
#define VM_EXEC (1 << 3)
#define VM_PROT_MASK (VM_READ | VM_WRITE | VM_EXEC)
#define VM_SWAPPED (1 << 4)
/* VMA flags */
#define VMA_SHARED (1 << 3)
/* VMA that's not file-backed, always ZI */
#define VMA_ANON (1 << 4)
/* Private copy of a file VMA, can be ZI */
#define VMA_COW (1 << 5)
/* This marks shadow vmas */
#define VMA_SHADOW (1 << 6)
struct page {
int count; /* Refcount */
struct spinlock lock; /* Page lock. */
struct list_head list; /* For list of a file's in-memory pages */
unsigned long virtual; /* If refs >1, first mapper's virtual address */
struct vm_file *owner; /* The file it belongs to */
unsigned int flags; /* Flags associated with the page. */
unsigned long f_offset; /* The offset page resides in its owner */
};
extern struct page *page_array;
#define page_refcnt(x) ((x)->count + 1)
#define virtual(x) ((x)->virtual)
#define phys_to_page(x) (page_array + __pfn(x))
#define page_to_phys(x) __pfn_to_addr((((void *)x) - \
(void *)page_array) \
/ sizeof(struct page))
/* Fault data specific to this task + ptr to kernel's data */
struct fault_data {
fault_kdata_t *kdata; /* Generic data flonged by the kernel */
unsigned int reason; /* Generic fault reason flags */
unsigned int address; /* Aborted address */
struct vm_area *vma; /* Inittask-related fault data */
struct tcb *task; /* Inittask-related fault data */
};
struct vm_pager_ops {
void (*read_page)(struct fault_data *f, void *);
void (*write_page)(struct fault_data *f, void *);
};
/* Describes the pager task that handles a vm_area. */
struct vm_pager {
struct vm_pager_ops ops; /* The ops the pager does on area */
};
/*
* TODO: Since there's no vfs yet, an inode's i_addr field is the
* virtual memory address of a file which uniquely identifies that file.
*/
struct inode {
unsigned long i_addr; /* The unique, global resource id. */
};
/*
* Describes the in-memory representation of a file. This could
* point at a file or another resource, e.g. a device area or swapper space.
*/
struct vm_file {
struct inode inode;
unsigned long length;
/* This is the cache of physical pages that this file has in memory. */
struct list_head page_cache_list;
struct vm_pager *pager;
};
/*
* Describes a virtually contiguous chunk of memory region in a task. It covers
* a unique virtual address area within its task, meaning that it does not
* overlap with other regions in the same task. The region could be backed by a
* file or various other resources. This is managed by the region's pager.
*/
struct vm_area {
struct list_head list; /* Vma list */
struct list_head shadow_list; /* Head for shadow list. See fault.c */
unsigned long pfn_start; /* Region start virtual pfn */
unsigned long pfn_end; /* Region end virtual pfn, exclusive */
unsigned long flags; /* Protection flags. */
unsigned long f_offset; /* File offset in pfns */
struct vm_file *owner; /* File that backs the area. */
};
static inline struct vm_area *find_vma(unsigned long addr,
struct list_head *vm_area_list)
{
struct vm_area *vma;
unsigned long pfn = __pfn(addr);
list_for_each_entry(vma, vm_area_list, list)
if ((pfn >= vma->pfn_start) && (pfn < vma->pfn_end))
return vma;
return 0;
}
/* Pagers */
extern struct vm_pager default_file_pager;
extern struct vm_pager swap_pager;
/* Main page fault entry point */
void page_fault_handler(l4id_t tid, fault_kdata_t *fkdata);
#endif /* __VM_AREA_H__ */