Added posix code

This commit is contained in:
Bahadir Balban
2009-09-29 21:55:59 +03:00
parent 54272ccb63
commit f0bb0a4657
478 changed files with 63161 additions and 0 deletions

Binary file not shown.

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

View File

@@ -0,0 +1,28 @@
#ifndef __BOOT_H__
#define __BOOT_H__
#include <vm_area.h>
#include <task.h>
/* Structures to use when sending new task information to vfs */
struct task_data {
unsigned long tid;
unsigned long shpage_address;
};
struct task_data_head {
unsigned long total;
struct task_data tdata[];
};
int boottask_setup_regions(struct vm_file *file, struct tcb *task,
unsigned long task_start, unsigned long task_end);
int boottask_mmap_regions(struct tcb *task, struct vm_file *file);
struct tcb *boottask_exec(struct vm_file *f, unsigned long task_region_start,
unsigned long task_region_end, struct task_ids *ids);
int vfs_send_task_data(struct tcb *vfs);
#endif /* __BOOT_H__ */

View File

@@ -0,0 +1,21 @@
#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__));
struct initdata;
void read_bootdesc(struct initdata *initdata);
#endif /* __BOOTDESC_H__ */

View File

@@ -0,0 +1,9 @@
#ifndef __PAGER_BOOTM_H__
#define __PAGER_BOOTM_H__
#define __initdata SECTION(".init.data")
void *alloc_bootmem(int size, int alignment);
#endif /* __PAGER_BOOTM_H__ */

View File

@@ -0,0 +1,44 @@
/*
* Capability-related operations of the pager.
*
* Copyright (C) 2009 Bahadir Balban
*/
#ifndef __MM0_CAPABILITY_H__
#define __MM0_CAPABILITY_H__
#include <l4lib/types.h>
#include <l4/lib/list.h>
struct cap_list {
int ncaps;
struct link caps;
};
struct capability {
struct link list;
/* Capability identifiers */
l4id_t capid; /* Unique capability ID */
l4id_t resid; /* Targeted resource ID */
l4id_t owner; /* Capability owner ID */
unsigned int type; /* Capability and target resource type */
/* Capability limits/permissions */
u32 access; /* Permitted operations */
/* Limits on the resource */
unsigned long start; /* Resource start value */
unsigned long end; /* Resource end value */
unsigned long size; /* Resource size */
unsigned long used; /* Resource used size */
};
extern struct cap_list capability_list;
struct initdata;
int read_kernel_capabilities(struct initdata *);
void copy_boot_capabilities(struct initdata *initdata);
#endif /* __MM0_CAPABILITY_H__ */

View File

@@ -0,0 +1,17 @@
#ifndef __CLONE_H__
#define __CLONE_H__
/* Linux clone() system call flags */
#define CLONE_VM 0x100
#define CLONE_FS 0x200
#define CLONE_FILES 0x400
#define CLONE_SIGHAND 0x800
#define CLONE_VFORK 0x4000
#define CLONE_PARENT 0x8000
#define CLONE_THREAD 0x10000
#define CLONE_NEWNS 0x20000
#define CLONE_STOPPED 0x2000000
#endif /* __CLONE_H__ */

View File

@@ -0,0 +1,25 @@
/*
* Definitions for executables
*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __EXEC_H__
#define __EXEC_H__
/*
* This presents extra executable file information that is
* not present in the tcb, in a generic format.
*/
struct exec_file_desc {
unsigned long text_offset; /* File offset of text section */
unsigned long data_offset; /* File offset of data section */
unsigned long bss_offset; /* File offset of bss section */
};
struct args_struct {
int argc;
char **argv;
int size; /* Size of strings + string pointers */
};
#endif /* __EXEC_H__ */

View File

@@ -0,0 +1,13 @@
/*
* Definitions for do_exit() flags
*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __EXIT_H__
#define __EXIT_H__
void do_exit(struct tcb *task, int status);
int execve_recycle_task(struct tcb *new, struct tcb *orig);
#endif /* __EXIT_H__ */

View File

@@ -0,0 +1,38 @@
#ifndef __MM0_FILE_H__
#define __MM0_FILE_H__
#include <l4/lib/list.h>
#include <l4lib/types.h>
#include <posix/sys/types.h>
#include <task.h>
int vfs_read(unsigned long vnum, unsigned long f_offset, unsigned long npages,
void *pagebuf);
int vfs_write(unsigned long vnum, unsigned long f_offset, unsigned long npages,
void *pagebuf);
int sys_read(struct tcb *sender, int fd, void *buf, int count);
int sys_write(struct tcb *sender, int fd, void *buf, int count);
int sys_lseek(struct tcb *sender, int fd, off_t offset, int whence);
int sys_close(struct tcb *sender, int fd);
int sys_fsync(struct tcb *sender, int fd);
int file_open(struct tcb *opener, int fd);
int vfs_open_bypath(const char *pathname, unsigned long *vnum, unsigned long *length);
struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length);
int flush_file_pages(struct vm_file *f);
int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
unsigned long pfn_end);
struct vfs_file_data {
unsigned long vnum;
};
#define vm_file_to_vnum(f) \
(((struct vfs_file_data *)((f)->priv_data))->vnum)
struct vm_file *vfs_file_create(void);
extern struct link vm_file_list;
#endif /* __MM0_FILE_H__ */

View File

@@ -0,0 +1,13 @@
#ifndef __GLOBALS_H__
#define __GLOBALS_H__
struct global_list {
int total;
struct link list;
};
extern struct global_list global_vm_files;
extern struct global_list global_vm_objects;
extern struct global_list global_tasks;
#endif /* __GLOBALS_H__ */

View File

@@ -0,0 +1,39 @@
/*
* Data that comes from the kernel, and other init data.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MM_INIT_H__
#define __MM_INIT_H__
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#include INC_GLUE(memlayout.h)
#include <bootdesc.h>
#include <physmem.h>
#include <vm_area.h>
#include <capability.h>
struct initdata {
struct capability *bootcaps;
struct capability *physmem;
struct bootdesc *bootdesc;
struct page_bitmap *page_map;
unsigned long pager_utcb_virt;
unsigned long pager_utcb_phys;
struct link boot_file_list;
};
extern struct initdata initdata;
void init_pager(void);
/* TODO: Remove this stuff from here. */
int init_devzero(void);
struct vm_file *get_devzero(void);
int init_boot_files(struct initdata *initdata);
#endif /* __MM_INIT_H__ */

View File

@@ -0,0 +1,26 @@
/*
* Address allocation pool
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __ADDR_H__
#define __ADDR_H__
#include <lib/idpool.h>
/* Address pool to allocate from a range of addresses */
struct address_pool {
struct id_pool *idpool;
unsigned long start;
unsigned long end;
};
int address_pool_init_with_idpool(struct address_pool *pool,
struct id_pool *idpool,
unsigned long start, unsigned long end);
int address_pool_init(struct address_pool *pool, unsigned long start,
unsigned long end);
void *address_new(struct address_pool *pool, int npages);
int address_del(struct address_pool *, void *addr, int npages);
#endif /* __ADDR_H__ */

View File

@@ -0,0 +1,44 @@
#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);
int check_and_set_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__ */

View File

@@ -0,0 +1,64 @@
/*
* Definitions for Executable Linking Format
* Based on Portable Formats Specification v1.1
*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __ELF_H__
#define __ELF_H__
#include <l4/types.h>
/* ELF identification indices */
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_PAD 7
/* Size of ELF identification field */
#define EI_NIDENT 16
/* Values for ELF identification fields */
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
/* Values for the ELF Class field */
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
/* Values for the ELF Data field */
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
struct elf_header {
u8 e_ident[EI_NIDENT]; /* ELF identification */
u16 e_type; /* Object file type */
u16 e_machine; /* Machine architecture */
u32 e_version; /* Object file version */
u32 e_entry; /* Virtual entry address */
u32 e_phoff; /* Program header offset */
u32 e_shoff; /* Section header offset */
u32 e_flags; /* Processor specific flags */
u16 e_ehsize; /* ELF header size */
u16 e_phentsize; /* Program header entry size */
u16 e_phnum; /* Number of program headers */
u16 e_shentsize; /* Section header entry size */
u16 e_shnum; /* Number of section headers */
u16 e_shstrndx; /* Shtable index for strings */
} __attribute__((__packed__));
int elf_parse_executable(struct tcb *task, struct vm_file *file,
struct exec_file_desc *efd);
#endif /* __ELF_H__ */

View File

@@ -0,0 +1,35 @@
/*
* Definitions for ELF program headers
* Based on Portable Formats Specification v1.1
*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __ELFPRG_H__
#define __ELFPRG_H__
#include <l4/types.h>
struct elf_program_header {
u32 p_type; /* Type of segment */
u32 p_offset; /* Segment file offset */
u32 p_vaddr; /* Virtual start address */
u32 p_paddr; /* Physical start address */
u32 p_filesz; /* Size in stored file */
u32 p_memsz; /* Size in memory image */
u32 p_flags; /* Segment attributes */
u32 p_align; /* Alignment requirement */
} __attribute__((__packed__));
/* Program segment type definitions */
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7FFFFFFF
#endif /* __ELFPRG_H__ */

View File

@@ -0,0 +1,60 @@
/*
* Definitions for ELF Sections
* Based on Portable Formats Specification v1.1
*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __ELFSECT_H__
#define __ELFSECT_H__
#include <l4/types.h>
/* Special section indices */
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xFF00
#define SHN_LOPROC 0xFF00
#define SHN_HIPROC 0xFF1F
#define SHN_ABS 0xFFF1
#define SHN_COMMON 0xFFF2
#define SHN_HIRESERVE 0xFFFF
struct elf_section_header {
u32 sh_name; /* Index to section header str table for name */
u32 sh_type; /* Categorises section's semantics */
u32 sh_flags; /* Flags that define various attributes */
u32 sh_addr; /* Virtual address for section */
u32 sh_offset; /* Offset to contents from file beginning */
u32 sh_size; /* Size of section (note SHT_NOBITS) */
u32 sh_link;
u32 sh_info; /* Extra section info */
u32 sh_addralign; /* Section alignment in power of 2 */
u32 sh_entsize; /* Size of each entry if fixed */
} __attribute__((__packed__));
/* Section type codes */
#define SHT_NULL 0 /* Inactive */
#define SHT_PROGBITS 1 /* Program contents */
#define SHT_SYMTAB 2 /* Symbol table */
#define SHT_STRTAB 3 /* String table */
#define SHT_RELA 4 /* Relocation entries */
#define SHT_HASH 5 /* Symbol hash table */
#define SHT_DYNAMIC 6 /* Dynamic linking info */
#define SHT_NOTE 7 /* Optional, additional info */
#define SHT_NOBITS 8 /* Does not occupy file space */
#define SHT_REL 9 /* Relocation entries */
#define SHT_SHLIB 10 /* Reserved */
#define SHT_DYNSYM 11 /* Symbols for dynamic linking */
#define SHT_LOPROC 0x70000000 /* Reserved for processors */
#define SHT_HIPROC 0x7FFFFFFF /* Reserved for processors */
#define SHT_LOUSER 0x80000000 /* Reserved for user progs */
#define SHT_HIUSER 0xFFFFFFFF /* Reserved for user progs */
/* Section attribute flags */
#define SHF_WRITE (1 << 0) /* Writeable */
#define SHF_ALLOC (1 << 1) /* Occupies actual memory */
#define SHF_EXECINSTR (1 << 2) /* Executable */
#define SHF_MASCPROC 0xF0000000 /* Reserved for processors */
#endif /* __ELFSECT_H__ */

View File

@@ -0,0 +1,59 @@
/*
* Definitions for ELF Symbol tables, symbols
* Based on Portable Formats Specification v1.1
*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __ELFSYM_H__
#define __ELFSYM_H__
#include <l4/types.h>
struct elf_symbol_entry {
u32 st_name; /* Index into string table */
u32 st_value; /* Symbol value; address, aboslute etc. */
u32 st_size; /* Number of bytes contained in object */
u8 st_info; /* Type and binding attributes */
u8 st_other; /* Unused, 0 */
u16 st_shndx; /* Section header index associated with entry */
} __attribute__((__packed__));
/* To manipulate binding and type attributes on st_info field */
#define ELF32_ST_BIND(i) ((i) >> 4)
#define ELF32_ST_TYPE(i) ((i) & 0xF)
#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xF))
/* Symbol binding codes */
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15
/* Symbol types */
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_LOPROC 13
#define STT_HIPROC 15
/* Relocation structures */
struct elf_rel {
u32 r_offset;
u32 r_info;
} __attribute__((__packed__));
struct elf_rela {
u32 r_offset;
u32 r_info;
s32 r_addend;
} __attribute__((__packed__));
/* Macros to manipulate r_info field */
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((u8)(i))
#define ELF32_R_INFO(s,t) (((s) << 8) + (u8)(t))
#endif /* __ELFSYM_H__ */

View File

@@ -0,0 +1,21 @@
#ifndef __MM0_IDPOOL_H__
#define __MM0_IDPOOL_H__
#include <lib/bit.h>
#include <lib/spinlock.h>
struct id_pool {
int nwords;
int bitlimit;
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 id_get(struct id_pool *pool, int id);
int id_is_empty(struct id_pool *pool);
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,20 @@
#ifndef __PRIVATE_MALLOC_H__
#define __PRIVATE_MALLOC_H__
#include <stddef.h>
#include <string.h>
#include <stdio.h>
void *kmalloc(size_t size);
void kfree(void *blk);
static inline void *kzalloc(size_t size)
{
void *buf = kmalloc(size);
memset(buf, 0, size);
return buf;
}
#endif /*__PRIVATE_MALLOC_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,57 @@
/*
* 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;
physical_base = 0x8000;
/* INCLUDE "include/physical_base.lds" */
/* physical_base = 0x228000; */
pager_offset = virtual_base - physical_base;
ENTRY(_start)
SECTIONS
{
. = virtual_base;
_start_text = .;
.text : AT (ADDR(.text) - pager_offset) { *(.text.head) *(.text) }
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - pager_offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - pager_offset) { *(.rodata1) }
.data : AT (ADDR(.data) - pager_offset)
{
*(.data)
}
.bss : AT (ADDR(.bss) - pager_offset) { *(.bss) }
. = ALIGN(4K);
. += 0x2000; /* BSS doesnt increment link counter??? */
.stack : AT (ADDR(.stack) - pager_offset)
{
*(.stack)
}
. = ALIGN(4K);
__stack = .; /* This is the preallocated boot stack */
/* Below part is to be discarded after boot */
_start_init = .;
.init : AT (ADDR(.init) - pager_offset)
{
*(.init.data)
*(.init.bootmem)
}
_end_init = .;
_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 <init.h>
#include <physmem.h>
void init_mm_descriptors(struct page_bitmap *page_map,
struct bootdesc *bootdesc, struct membank *membank);
void init_physmem(struct initdata *initdata, struct membank *membank);
int pager_address_pool_init(void);
void *pager_new_address(int npages);
int pager_delete_address(void *virt_addr, int npages);
void *pager_map_pages(struct vm_file *f, unsigned long page_offset, unsigned long npages);
void pager_unmap_pages(void *addr, unsigned long npages);
void *pager_map_page(struct vm_file *f, unsigned long page_offset);
void pager_unmap_page(void *addr);
void *pager_map_file_range(struct vm_file *f, unsigned long byte_offset,
unsigned long size);
void *pager_validate_map_user_range2(struct tcb *user, void *userptr,
unsigned long size, unsigned int vm_flags);
void *l4_new_virtual(int npages);
void *l4_del_virtual(void *virt, int npages);
#endif /* __MEMORY_H__ */

View File

@@ -0,0 +1,35 @@
/*
* 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>
/* POSIX-defined mmap flags */
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define PROT_EXEC 0x4
#define PROT_NONE 0x0
#define MAP_ANONYMOUS 0x20
#define MAP_FIXED 0x10
#define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02
#define MAP_GROWSDOWN 0x00100
struct vm_area *vma_new(unsigned long pfn_start, unsigned long npages,
unsigned int flags, unsigned long file_offset);
int do_munmap(struct tcb *task, unsigned long vaddr, unsigned long size);
void *do_mmap(struct vm_file *mapfile, unsigned long f_offset, struct tcb *t,
unsigned long map_address, unsigned int flags, unsigned int pages);
int mmap_address_validate(struct tcb *t, unsigned long map_address,
unsigned int vm_flags);
#endif /* __MM0_MMAP_H__ */

View File

@@ -0,0 +1,45 @@
/*
* Physical memory descriptors
*
* Copyright (C) 2007 - 2009 Bahadir Balban
*/
#ifndef __PAGER_PHYSMEM_H__
#define __PAGER_PHYSMEM_H__
/* 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[];
};
/* 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;
};
struct membank {
unsigned long start;
unsigned long end;
unsigned long free;
struct page *page_array;
};
extern struct membank membank[];
/* Describes bitmap of used/unused state for all physical pages */
extern struct page_bitmap page_map;
extern struct memdesc physmem;
/* Sets the global page map as used/unused. Aligns input when needed. */
int set_page_map(struct page_bitmap *pmap, unsigned long start,
int numpages, int val);
struct initdata;
void init_physmem_primary(struct initdata *initdata);
void init_physmem_secondary(struct initdata *initdata, struct membank *membank);
#endif /* __PAGER_PHYSMEM_H__ */

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __SHM_H__
#define __SHM_H__
#include <l4/lib/list.h>
#include <l4/api/space.h>
#include <l4/macros.h>
#include <l4lib/types.h>
#include <task.h>
#include <posix/sys/ipc.h>
#include <posix/sys/shm.h>
#include <posix/sys/types.h>
struct shm_descriptor {
int key;
l4id_t shmid;
void *shm_addr;
unsigned long npages;
struct vm_file *devzero;
};
#if 0
struct shm_descriptor {
int key; /* IPC key supplied by user task */
l4id_t shmid; /* SHM area id, allocated by mm0 */
struct link 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 in pages */
unsigned int flags;
int refcnt;
};
#endif
#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 10
/* Initialises shared memory bookkeeping structures */
int shm_pool_init();
void *shmat_shmget_internal(struct tcb *task, key_t key, void *shmaddr);
struct vm_file *shm_new(key_t key, unsigned long npages);
void *shm_new_address(int npages);
/* Below is the special-case per-task default shared memory page prototypes */
/* Prefaults shared page after mapping */
#define SHPAGE_PREFAULT (1 << 0)
/* Creates new shm segment for default shpage */
#define SHPAGE_NEW_SHM (1 << 1)
/* Allocates a virtual address for default shpage */
#define SHPAGE_NEW_ADDRESS (1 << 2)
/* IPC to send utcb address information to tasks */
void *task_send_shpage_address(struct tcb *sender, l4id_t taskid);
int shpage_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags);
int shpage_unmap_from_task(struct tcb *owner, struct tcb *mapper);
/* Prefault a *mmaped* default shared page */
int shpage_prefault(struct tcb *task, unsigned int vmflags);
#endif /* __SHM_H__ */

View File

@@ -0,0 +1,40 @@
/*
* 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>
#include <l4lib/types.h>
#include <task.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;
};
void *sys_mmap(struct tcb *task, struct sys_mmap_args *args);
int sys_munmap(struct tcb *sender, void *vaddr, unsigned long size);
int sys_msync(struct tcb *task, void *start, unsigned long length, int flags);
void *sys_shmat(struct tcb *task, l4id_t shmid, const void *shmadr, int shmflg);
int sys_shmdt(struct tcb *requester, const void *shmaddr);
int sys_shmget(key_t key, int size, int shmflg);
int sys_execve(struct tcb *sender, char *pathname, char *argv[], char *envp[]);
int sys_fork(struct tcb *parent);
int sys_clone(struct tcb *parent, void *child_stack, unsigned int clone_flags);
void sys_exit(struct tcb *task, int status);
#endif /* __MM0_SYSARGS_H__ */

View File

@@ -0,0 +1,157 @@
/*
* Thread control block.
*
* Copyright (C) 2007, 2008 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/arch/types.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/utcb.h>
#include <lib/addr.h>
#include <l4/api/kip.h>
#include <exec.h>
#define __TASKNAME__ __PAGERNAME__
#define ARGS_MAX DEFAULT_ENV_SIZE
#define PATH_MAX PAGE_SIZE
#define TASK_FILES_MAX 32
/* POSIX minimum is 4Kb */
#define DEFAULT_ENV_SIZE SZ_4K
#define DEFAULT_STACK_SIZE SZ_32K
#define DEFAULT_SHPAGE_SIZE PAGE_SIZE
#define TASK_SIZE 0x10000000
#define TCB_NO_SHARING 0
#define TCB_SHARED_VM (1 << 0)
#define TCB_SHARED_FILES (1 << 1)
#define TCB_SHARED_FS (1 << 2)
#define TCB_SHARED_TGROUP (1 << 3)
#define TCB_SHARED_PARENT (1 << 4)
struct vm_file;
struct file_descriptor {
unsigned long vnum;
unsigned long cursor;
struct vm_file *vmfile;
};
struct task_fd_head {
struct file_descriptor fd[TASK_FILES_MAX];
int tcb_refs;
};
struct task_vma_head {
struct link list;
int tcb_refs;
};
struct utcb_desc {
struct link list;
unsigned long utcb_base;
struct id_pool *slots;
};
struct utcb_head {
struct link list;
int tcb_refs;
};
/* Stores all task information that can be kept in userspace. */
struct tcb {
/* Task list */
struct link list;
/* Fields for parent-child relations */
struct link child_ref; /* Child ref in parent's list */
struct link children; /* List of children */
struct tcb *parent; /* Parent task */
/* Task creation flags */
unsigned int clone_flags;
/* Name of the task */
char name[16];
/* Task ids */
int tid;
int spid;
int tgid;
/* Related task ids */
unsigned int pagerid; /* Task's pager */
/* Task's main address space region, usually USER_AREA_START/END */
unsigned long start;
unsigned long end;
/* Page aligned program segment marks, ends exclusive as usual */
unsigned long entry;
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;
unsigned long heap_start;
unsigned long heap_end;
unsigned long args_start;
unsigned long args_end;
/* Task's mmappable region */
unsigned long map_start;
unsigned long map_end;
/* Default ipc-shared-page information */
void *shared_page;
/* Chain of utcb descriptors */
struct utcb_head *utcb_head;
/* Unique utcb address of this task */
unsigned long utcb_address;
/* Virtual memory areas */
struct task_vma_head *vm_area_head;
/* File descriptors for this task */
struct task_fd_head *files;
};
struct tcb_head {
struct link list;
int total; /* Total threads */
};
struct tcb *find_task(int tid);
void global_add_task(struct tcb *task);
void global_remove_task(struct tcb *task);
void task_map_prefault_utcb(struct tcb *mapper, struct tcb *owner);
int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_desc *efd,
struct args_struct *args, struct args_struct *env);
int task_setup_registers(struct tcb *task, unsigned int pc,
unsigned int sp, l4id_t pager);
struct tcb *tcb_alloc_init(unsigned int flags);
int tcb_destroy(struct tcb *task);
int task_start(struct tcb *task);
int copy_tcb(struct tcb *to, struct tcb *from, unsigned int flags);
int task_release_vmas(struct task_vma_head *vma_head);
int task_prefault_regions(struct tcb *task, struct vm_file *f);
struct tcb *task_create(struct tcb *orig,
struct task_ids *ids,
unsigned int ctrl_flags,
unsigned int alloc_flags);
#endif /* __TASK_H__ */

View File

@@ -0,0 +1,7 @@
#ifndef __TEST_H__
#define __TEST_H__
int mm0_test_global_vm_integrity(void);
#endif /* __TEST_H__ */

View File

@@ -0,0 +1,12 @@
#ifndef __USER_H__
#define __USER_H__
#include <task.h>
int pager_validate_user_range(struct tcb *user, void *userptr, unsigned long size,
unsigned int vm_flags);
void *pager_validate_map_user_range(struct tcb *user, void *userptr,
unsigned long size, unsigned int vm_flags);
void pager_unmap_user_range(void *mapped_ptr, unsigned long size);
#endif /* __USER_H__ */

View File

@@ -0,0 +1,14 @@
#ifndef __MM0_UTCB_H__
#define __MM0_UTCB_H__
int utcb_pool_init();
void *utcb_new_address(int npages);
int utcb_delete_address(void *shm_addr, int npages);
unsigned long utcb_slot(struct utcb_desc *desc);
unsigned long task_new_utcb_desc(struct tcb *task);
int task_setup_utcb(struct tcb *task);
int task_destroy_utcb(struct tcb *task);
#endif /* __MM0_UTCB_H__ */

View File

@@ -0,0 +1,267 @@
/*
* Virtual memory area descriptors.
*
* Copyright (C) 2007, 2008 Bahadir Balban
*/
#ifndef __VM_AREA_H__
#define __VM_AREA_H__
#include <stdio.h>
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <task.h>
#include <arch/mm.h>
#include <lib/spinlock.h>
#include <physmem.h>
// #define DEBUG_FAULT_HANDLING
#ifdef DEBUG_FAULT_HANDLING
#define dprintf(...) printf(__VA_ARGS__)
#else
#define dprintf(...)
#endif
/* 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)
/* Shared copy of a file */
#define VMA_SHARED (1 << 4)
/* VMA that's not file-backed, always maps devzero as VMA_COW */
#define VMA_ANONYMOUS (1 << 5)
/* Private copy of a file */
#define VMA_PRIVATE (1 << 6)
/* For wired pages */
#define VMA_FIXED (1 << 7)
/* For stack, where mmap returns end address */
#define VMA_GROWSDOWN (1 << 8)
/* Set when the page is dirty in cache but not written to disk */
#define VM_DIRTY (1 << 9)
/* Defines the type of file. A device file? Regular file? One used at boot? */
enum VM_FILE_TYPE {
VM_FILE_DEVZERO = 1,
VM_FILE_VFS,
VM_FILE_BOOTFILE,
VM_FILE_SHM,
};
/* Defines the type of object. A file? Just a standalone object? */
#define VM_OBJ_SHADOW (1 << 10) /* Anonymous pages, swap_pager */
#define VM_OBJ_FILE (1 << 11) /* VFS file and device pages */
struct page {
int refcnt; /* Refcount */
struct spinlock lock; /* Page lock. */
struct link list; /* For list of a vm_object's in-memory pages */
struct vm_object *owner;/* The vm_object the page belongs to */
unsigned long virtual; /* If refs >1, first mapper's virtual address */
unsigned int flags; /* Flags associated with the page. */
unsigned long offset; /* The offset page resides in its owner */
};
extern struct page *page_array;
/*
* A suggestion to how a non-page_array (i.e. a device)
* page could tell its physical address.
*/
struct devpage {
struct page page;
unsigned long phys;
};
#define page_refcnt(x) ((x)->count + 1)
#define virtual(x) ((x)->virtual)
#define phys_to_page(x) (page_array + __pfn((x) - membank[0].start))
#define page_to_phys(x) (__pfn_to_addr((((void *)(x)) - \
(void *)page_array) / \
sizeof(struct page)) + \
membank[0].start)
/* Fault data specific to this task + ptr to kernel's data */
struct fault_data {
fault_kdata_t *kdata; /* Generic data forged by the kernel */
unsigned int reason; /* Generic fault reason flags */
unsigned int address; /* Aborted address */
unsigned int pte_flags; /* Generic protection flags on pte */
struct vm_area *vma; /* Inittask-related fault data */
struct tcb *task; /* Inittask-related fault data */
};
struct vm_pager_ops {
struct page *(*page_in)(struct vm_object *vm_obj,
unsigned long pfn_offset);
int (*page_out)(struct vm_object *vm_obj,
unsigned long pfn_offset);
int (*release_pages)(struct vm_object *vm_obj);
};
/* Describes the pager task that handles a vm_area. */
struct vm_pager {
struct vm_pager_ops ops; /* The ops the pager does on area */
};
/*
* Describes the in-memory representation of a resource. This could
* point at a file or another resource, e.g. a device area, swapper space,
* the anonymous internal state of a process, etc. This covers more than
* just files, e.g. during a fork, captures the state of internal shared
* copy of private pages for a process, which is really not a file.
*/
struct vm_object {
int npages; /* Number of pages in memory */
int nlinks; /* Number of mapper links that refer */
int shadows; /* Number of shadows that refer */
struct link shref; /* Shadow reference from original object */
struct link shdw_list; /* List of vm objects that shadows this one */
struct link link_list; /* List of links that refer to this object */
struct vm_object *orig_obj; /* Original object that this one shadows */
unsigned int flags; /* Defines the type and flags of the object */
struct link list; /* List of all vm objects in memory */
struct vm_pager *pager; /* The pager for this object */
struct link page_cache;/* List of in-memory pages */
};
/* In memory representation of either a vfs file, a device. */
struct vm_file {
int openers;
struct link list;
unsigned long length;
unsigned int type;
struct vm_object vm_obj;
void (*destroy_priv_data)(struct vm_file *f);
void *priv_data; /* Device pagers use to access device info */
};
/* To create per-vma vm_object lists */
struct vm_obj_link {
struct link list;
struct link linkref;
struct vm_object *obj;
};
static inline void vm_link_object(struct vm_obj_link *link, struct vm_object *obj)
{
link->obj = obj;
list_insert(&link->linkref, &obj->link_list);
obj->nlinks++;
}
static inline struct vm_object *vm_unlink_object(struct vm_obj_link *link)
{
/* Delete link from object's link list */
list_remove(&link->linkref);
/* Reduce object's mapper link count */
link->obj->nlinks--;
return link->obj;
}
#define vm_object_to_file(obj) container_of(obj, struct vm_file, vm_obj)
/*
* 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.
*
* COW: Upon copy-on-write, each copy-on-write instance creates a shadow of the
* original vm object which supersedes the original vm object with its copied
* modified pages. This creates a stack of shadow vm objects, where the top
* object's copy of pages supersede the ones lower in the stack.
*/
struct vm_area {
struct link list; /* Per-task vma list */
struct link vm_obj_list; /* Head for vm_object list. */
unsigned long pfn_start; /* Region start virtual pfn */
unsigned long pfn_end; /* Region end virtual pfn, exclusive */
unsigned long flags; /* Protection flags. */
unsigned long file_offset; /* File offset in pfns */
};
/*
* Finds the vma that has the given address.
* TODO: In the future a lot of use cases may need to traverse each vma
* rather than searching the address. E.g. munmap/msync
*/
static inline struct vm_area *find_vma(unsigned long addr,
struct link *vm_area_list)
{
struct vm_area *vma;
unsigned long pfn = __pfn(addr);
list_foreach_struct(vma, vm_area_list, list)
if ((pfn >= vma->pfn_start) && (pfn < vma->pfn_end))
return vma;
return 0;
}
/* Adds a page to its vm_objects's page cache in order of offset. */
int insert_page_olist(struct page *this, struct vm_object *vm_obj);
/* Find a page in page cache via page offset */
struct page *find_page(struct vm_object *obj, unsigned long pfn);
/* Pagers */
extern struct vm_pager file_pager;
extern struct vm_pager bootfile_pager;
extern struct vm_pager devzero_pager;
extern struct vm_pager swap_pager;
/* vm object and vm file lists */
extern struct link vm_object_list;
/* vm object link related functions */
struct vm_obj_link *vm_objlink_create(void);
struct vm_obj_link *vma_next_link(struct link *link,
struct link *head);
/* vm file and object initialisation */
struct vm_object *vm_object_create(void);
struct vm_file *vm_file_create(void);
int vm_file_delete(struct vm_file *f);
int vm_object_delete(struct vm_object *vmo);
void vm_file_put(struct vm_file *f);
/* Printing objects, files */
void vm_object_print(struct vm_object *vmo);
void vm_print_objects(struct link *vmo_list);
void vm_print_files(struct link *file_list);
/* Used for pre-faulting a page from mm0 */
int prefault_page(struct tcb *task, unsigned long address,
unsigned int vmflags);
struct page *page_init(struct page *page);
struct page *find_page(struct vm_object *vmo, unsigned long page_offset);
void *pager_map_page(struct vm_file *f, unsigned long page_offset);
void pager_unmap_page(void *vaddr);
/* To get currently mapped page of a virtual address on a task */
struct page *task_virt_to_page(struct tcb *t, unsigned long virtual);
int validate_task_range(struct tcb *t, unsigned long start,
unsigned long end, unsigned int vmflags);
/* Changes all shadows and their ptes to read-only */
int vm_freeze_shadows(struct tcb *task);
int task_insert_vma(struct vm_area *vma, struct link *vma_list);
/* Main page fault entry point */
int page_fault_handler(struct tcb *faulty_task, fault_kdata_t *fkdata);
int vma_copy_links(struct vm_area *new_vma, struct vm_area *vma);
int vma_drop_merge_delete(struct vm_area *vma, struct vm_obj_link *link);
int vma_drop_merge_delete_all(struct vm_area *vma);
void global_add_vm_object(struct vm_object *obj);
void global_remove_vm_object(struct vm_object *obj);
void global_add_vm_file(struct vm_file *f);
void global_remove_vm_file(struct vm_file *f);
#endif /* __VM_AREA_H__ */