mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Some more progress on resource management and boot up.
This commit is contained in:
83
include/l4/generic/cap-types.h
Normal file
83
include/l4/generic/cap-types.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Types of capabilities and their operations
|
||||
*
|
||||
* Copyright (C) 2009 Bahadir Balban
|
||||
*/
|
||||
#ifndef __CAP_TYPES_H__
|
||||
#define __CAP_TYPES_H__
|
||||
|
||||
/*
|
||||
* Capability types
|
||||
*/
|
||||
#define CAP_TYPE_MASK 0x0000FFFF
|
||||
#define CAP_TYPE_TCTRL (1 << 0)
|
||||
#define CAP_TYPE_EXREGS (1 << 1)
|
||||
#define CAP_TYPE_MAP (1 << 2)
|
||||
#define CAP_TYPE_IPC (1 << 3)
|
||||
#define CAP_TYPE_SCHED (1 << 4)
|
||||
#define CAP_TYPE_UMUTEX (1 << 5)
|
||||
#define CAP_TYPE_QUANTITY (1 << 6)
|
||||
|
||||
/*
|
||||
* Resource types
|
||||
*/
|
||||
#define CAP_RTYPE_MASK 0xFFFF0000
|
||||
#define CAP_RTYPE_THREAD (1 << 16)
|
||||
#define CAP_RTYPE_TGROUP (1 << 17)
|
||||
#define CAP_RTYPE_SPACE (1 << 18)
|
||||
#define CAP_RTYPE_CONTAINER (1 << 19)
|
||||
#define CAP_RTYPE_UMUTEX (1 << 20)
|
||||
#define CAP_RTYPE_VIRTMEM (1 << 21)
|
||||
#define CAP_RTYPE_PHYSMEM (1 << 22)
|
||||
#define CAP_RTYPE_CPUPOOL (1 << 23)
|
||||
#define CAP_RTYPE_THREADPOOL (1 << 24)
|
||||
#define CAP_RTYPE_SPACEPOOL (1 << 25)
|
||||
#define CAP_RTYPE_MUTEXPOOL (1 << 27)
|
||||
#define CAP_RTYPE_MEMPOOL (1 << 26) /* Do we need this ??? */
|
||||
/*
|
||||
* Access permissions
|
||||
*/
|
||||
|
||||
/* Thread control capability */
|
||||
#define CAP_TCTRL_CREATE (1 << 0)
|
||||
#define CAP_TCTRL_DESTROY (1 << 1)
|
||||
#define CAP_TCTRL_SUSPEND (1 << 2)
|
||||
#define CAP_TCTRL_RESUME (1 << 3)
|
||||
#define CAP_TCTRL_RECYCLE (1 << 4)
|
||||
|
||||
/* Exchange registers capability */
|
||||
#define CAP_EXREGS_RW_PAGER (1 << 0)
|
||||
#define CAP_EXREGS_RW_UTCB (1 << 1)
|
||||
#define CAP_EXREGS_RW_SP (1 << 2)
|
||||
#define CAP_EXREGS_RW_PC (1 << 3)
|
||||
#define CAP_EXREGS_RW_REGS (1 << 4)
|
||||
#define CAP_EXREGS_RW_CPU (1 << 5)
|
||||
#define CAP_EXREGS_RW_CPUTIME (1 << 6)
|
||||
|
||||
/* Map capability */
|
||||
#define CAP_MAP_READ (1 << 0)
|
||||
#define CAP_MAP_WRITE (1 << 1)
|
||||
#define CAP_MAP_EXEC (1 << 2)
|
||||
#define CAP_MAP_CACHED (1 << 3)
|
||||
#define CAP_MAP_UNCACHED (1 << 4)
|
||||
#define CAP_MAP_UNMAP (1 << 5)
|
||||
|
||||
/* Ipc capability */
|
||||
#define CAP_IPC_SEND (1 << 0)
|
||||
#define CAP_IPC_RECV (1 << 1)
|
||||
#define CAP_IPC_SHORT (1 << 2)
|
||||
#define CAP_IPC_FULL (1 << 3)
|
||||
#define CAP_IPC_EXTENDED (1 << 4)
|
||||
#define CAP_IPC_ASYNC (1 << 5)
|
||||
|
||||
/* Userspace mutex capability */
|
||||
#define CAP_UMUTEX_LOCK (1 << 0)
|
||||
|
||||
/* Capability control capability */
|
||||
#define CAP_CAP_SPLIT (1 << 0)
|
||||
#define CAP_CAP_SPLICE (1 << 1)
|
||||
#define CAP_CAP_REDUCE (1 << 2)
|
||||
#define CAP_CAP_REVOKE (1 << 3)
|
||||
#define CAP_CAP_GRANT (1 << 4)
|
||||
|
||||
#endif /* __CAP_TYPES_H__ */
|
||||
177
include/l4/generic/capability.h
Normal file
177
include/l4/generic/capability.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Codezero Capability Definitions
|
||||
*
|
||||
* Copyright (C) 2009 Bahadir Balban
|
||||
*/
|
||||
#ifndef __CAPABILITY_H__
|
||||
#define __CAPABILITY_H__
|
||||
|
||||
#include <l4/lib/list.h>
|
||||
|
||||
/*
|
||||
* A capability is a unique representation of security
|
||||
* qualifiers on a particular resource.
|
||||
*
|
||||
* In this structure:
|
||||
*
|
||||
* The capid denotes the unique capability ID. The resid denotes the unique ID
|
||||
* of targeted resource. The owner denotes the unique ID of capability owner.
|
||||
* This is almost always a thread ID.
|
||||
*
|
||||
* The type field contains two types: The capability type, and the targeted
|
||||
* resource type. The targeted resouce type denotes what type of resource the
|
||||
* capability is allowed to operate on. For example a thread, a thread group,
|
||||
* an address space or a memory can be of this type.
|
||||
*
|
||||
* The capability type defines the general set of operations allowed on a
|
||||
* particular resource. The resource type defines the type of resource that
|
||||
* the capability is targeting. For example a capability type may be
|
||||
* thread_control, exchange_registers, ipc, or map operations. A resource type
|
||||
* may be such as a thread, a thread group, a virtual or physical memory
|
||||
* region.
|
||||
*
|
||||
* There are also quantitative capability types. While their names denote
|
||||
* quantitative objects such as memory, threads, and address spaces, these
|
||||
* types actually define the quantitative operations available on those
|
||||
* resources such as creation and deletion of a thread, allocation and
|
||||
* deallocation of a memory region etc.
|
||||
*
|
||||
* The access field denotes the fine-grain operations available on a particular
|
||||
* resource. The meaning of each bitfield differs according to the type of the
|
||||
* capability. For example, for a capability type thread_control, the bitfields
|
||||
* may mean suspend, resume, create, delete etc.
|
||||
*/
|
||||
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 */
|
||||
};
|
||||
|
||||
struct cap_list {
|
||||
int ncaps;
|
||||
struct link caps;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* Virtual memory space allocated to container */
|
||||
struct capability cap_virtmap = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = container_id,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_VIRTMEM,
|
||||
.access = 0, /* No access operations */
|
||||
.start = 0xF0000000,
|
||||
.end = 0xF1000000,
|
||||
.size = 0x1000000
|
||||
};
|
||||
|
||||
/* Physical memory space allocated to container */
|
||||
struct capability cap_physmap = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = container_id,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_PHYSMEM,
|
||||
.access = 0, /* No access operations */
|
||||
.start = 0x0,
|
||||
.end = 0x1000000,
|
||||
.size = 0x1000000
|
||||
};
|
||||
|
||||
/* IPC operations permitted on target thread */
|
||||
struct capability cap_ipc = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = target_tid,
|
||||
.owner = tid,
|
||||
.type = CAP_TYPE_IPC,
|
||||
.access = CAP_IPC_SEND | CAP_IPC_RECV | CAP_IPC_FULL | CAP_IPC_SHORT | CAP_IPC_EXTENDED,
|
||||
.start = 0xF0000000,
|
||||
.end = 0xF1000000,
|
||||
.size = 0x1000000
|
||||
};
|
||||
|
||||
/* Thread control operations permitted on target thread */
|
||||
struct capability cap_thread_control = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = target_tid,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_THREAD_CONTROL,
|
||||
.access = CAP_THREAD_SUSPEND | CAP_THREAD_RUN | CAP_THREAD_RECYCLE | CAP_THREAD_CREATE | CAP_THREAD_DESTROY,
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.size = 0,
|
||||
};
|
||||
|
||||
/* Exregs operations permitted on target thread */
|
||||
struct capability cap_exregs = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = target_tid,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_EXREGS,
|
||||
.access = CAP_EXREGS_RW_PAGER | CAP_EXREGS_RW_SP | CAP_EXREGS_RW_PC | CAP_EXREGS_RW_UTCB | CAP_EXREGS_RW_OTHERS,
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.size = 0
|
||||
};
|
||||
|
||||
/* Number of threads allocated to container */
|
||||
struct capability cap_threads = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = container_id,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_THREADS,
|
||||
.access = 0,
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.size = 256,
|
||||
};
|
||||
|
||||
/* Number of spaces allocated to container */
|
||||
struct capability cap_spaces = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = container_id,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_SPACES,
|
||||
.access = 0,
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.size = 128,
|
||||
};
|
||||
|
||||
/* CPU time allocated to container */
|
||||
struct capability cap_cputime = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = container_id,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_CPUTIME,
|
||||
.access = 0,
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.size = 55, /* Percentage */
|
||||
};
|
||||
|
||||
struct capability cap_cpuprio = {
|
||||
.capid = id_alloc(capids),
|
||||
.resid = container_id,
|
||||
.owner = pagerid,
|
||||
.type = CAP_TYPE_CPUPRIO,
|
||||
.access = 0,
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
.size = 55, /* Priority No */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __CAPABILITY_H__ */
|
||||
@@ -9,11 +9,14 @@
|
||||
#include <l4/generic/scheduler.h>
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/generic/capability.h>
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/lib/idpool.h>
|
||||
#include <l4/api/mutex.h>
|
||||
#include <l4/lib/list.h>
|
||||
#include <l4/lib/idpool.h>
|
||||
|
||||
/* Container macro. No locks needed! */
|
||||
#define container (current->container)
|
||||
#define this_container (current->container)
|
||||
|
||||
struct container {
|
||||
/* Unique container id */
|
||||
@@ -47,21 +50,48 @@ struct container {
|
||||
/* The array of containers present on the system */
|
||||
extern struct container container[];
|
||||
|
||||
|
||||
struct memdesc {
|
||||
/* Compact, raw capability structure */
|
||||
struct cap_info {
|
||||
unsigned int type;
|
||||
u32 access;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
unsigned int flags;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct cinfo {
|
||||
char cname[32];
|
||||
struct pager_info {
|
||||
unsigned long pager_lma;
|
||||
unsigned long pager_vma;
|
||||
unsigned long pager_size;
|
||||
|
||||
unsigned long total_memdesc;
|
||||
struct memdesc memdesc[];
|
||||
/* Number of capabilities defined */
|
||||
int ncaps;
|
||||
|
||||
/*
|
||||
* Zero or more ipc caps,
|
||||
* One or more thread pool caps,
|
||||
* One or more space pool caps,
|
||||
* One or more exregs caps,
|
||||
* One or more tcontrol caps,
|
||||
* One or more cputime caps,
|
||||
* One or more physmem caps,
|
||||
* One or more virtmem caps,
|
||||
* Zero or more umutex caps,
|
||||
*/
|
||||
struct cap_info caps[];
|
||||
};
|
||||
|
||||
/*
|
||||
* This auto-generated structure is
|
||||
* used to create run-time containers
|
||||
*/
|
||||
struct container_info {
|
||||
char *name;
|
||||
int npagers;
|
||||
struct pager_info pagers[];
|
||||
};
|
||||
|
||||
extern struct container_info cinfo[];
|
||||
|
||||
#endif /* __CONTAINER_H__ */
|
||||
|
||||
|
||||
51
include/l4/generic/resource.h
Normal file
51
include/l4/generic/resource.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef __RESOURCES_H__
|
||||
#define __RESOURCES_H__
|
||||
|
||||
/* Number of containers defined at compile-time */
|
||||
#define CONTAINERS_TOTAL 1
|
||||
|
||||
#include <l4/generic/capability.h>
|
||||
|
||||
struct boot_resources {
|
||||
int nconts;
|
||||
int ncaps;
|
||||
int nids;
|
||||
int nthreads;
|
||||
int nspaces;
|
||||
int npmds;
|
||||
|
||||
/* Kernel resource usage */
|
||||
int nkpmds;
|
||||
int nkpgds;
|
||||
int nkmemcaps;
|
||||
};
|
||||
|
||||
|
||||
struct kernel_container {
|
||||
/* Physical memory caps, used/unused */
|
||||
struct cap_list physmem_used;
|
||||
struct cap_list physmem_free;
|
||||
|
||||
/* Virtual memory caps, used/unused */
|
||||
struct cap_list virtmem_used;
|
||||
struct cap_list virtmem_free;
|
||||
|
||||
/* Device memory caps, used/unused */
|
||||
struct cap_list devmem_used;
|
||||
struct cap_list devmem_free;
|
||||
|
||||
struct mem_cache *pgd_cache;
|
||||
struct mem_cache *pmd_cache;
|
||||
struct mem_cache *ktcb_cache;
|
||||
struct mem_cache *address_space_cache;
|
||||
struct mem_cache *umutex_cache;
|
||||
struct mem_cache *cap_cache;
|
||||
struct mem_cache *cont_cache;
|
||||
};
|
||||
|
||||
extern struct kernel_container kernel_container;
|
||||
|
||||
int init_system_resources(struct kernel_container *kcont,
|
||||
struct boot_resources *bootres);
|
||||
|
||||
#endif /* __RESOURCES_H__ */
|
||||
@@ -20,8 +20,10 @@
|
||||
|
||||
#if defined (__KERNEL__)
|
||||
|
||||
#include <l4/lib/spinlock.h>
|
||||
#include <l4/lib/list.h>
|
||||
#include <l4/lib/mutex.h>
|
||||
#include <l4/lib/idpool.h>
|
||||
#include INC_SUBARCH(mm.h)
|
||||
|
||||
/* A simple page table with a reference count */
|
||||
@@ -33,6 +35,17 @@ struct address_space {
|
||||
int ktcb_refs;
|
||||
};
|
||||
|
||||
struct address_space_list {
|
||||
struct link list;
|
||||
|
||||
/* Lock for list add/removal */
|
||||
struct spinlock list_lock;
|
||||
|
||||
/* Used when delete/creating spaces */
|
||||
struct mutex ref_lock;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct address_space *address_space_create(struct address_space *orig);
|
||||
void address_space_delete(struct address_space *space);
|
||||
void address_space_attach(struct ktcb *tcb, struct address_space *space);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <l4/lib/list.h>
|
||||
#include <l4/lib/mutex.h>
|
||||
#include <l4/lib/spinlock.h>
|
||||
#include <l4/generic/scheduler.h>
|
||||
#include <l4/generic/pgalloc.h>
|
||||
#include <l4/generic/space.h>
|
||||
@@ -121,6 +122,13 @@ union ktcb_union {
|
||||
};
|
||||
|
||||
|
||||
/* Hash table for all existing tasks */
|
||||
struct ktcb_list {
|
||||
struct link list;
|
||||
struct spinlock list_lock;
|
||||
int count;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
||||
@@ -30,6 +30,7 @@ struct mem_cache {
|
||||
unsigned int *bitmap;
|
||||
};
|
||||
|
||||
int mem_cache_bufsize(void *start, int struct_size, int nstructs, int aligned);
|
||||
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);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Import('env')
|
||||
|
||||
# The set of source files associated with this SConscript file.
|
||||
src_local = ['physmem.c', 'irq.c', 'scheduler.c', 'time.c', 'tcb.c', 'pgalloc.c', 'kmalloc.c', 'space.c', 'bootm.c']
|
||||
src_local = ['physmem.c', 'irq.c', 'scheduler.c', 'time.c', 'tcb.c', 'pgalloc.c', 'kmalloc.c', 'space.c', 'bootm.c', 'resource.c']
|
||||
|
||||
obj = env.Object(src_local)
|
||||
Return('obj')
|
||||
|
||||
@@ -28,6 +28,12 @@ void *alloc_bootmem(int size, int alignment)
|
||||
if (!is_aligned(cursor, alignment))
|
||||
/* Align the cursor to alignment */
|
||||
cursor = align_up(cursor, alignment);
|
||||
/* Align to 4 byte by default */
|
||||
} else if (size >= 4) {
|
||||
/* And cursor is not aligned */
|
||||
if (!is_aligned(cursor, 4))
|
||||
/* Align the cursor to alignment */
|
||||
cursor = align_up(cursor, 4);
|
||||
}
|
||||
|
||||
/* Allocate from cursor */
|
||||
|
||||
7
src/generic/capability.c
Normal file
7
src/generic/capability.c
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Capability checking for all system calls
|
||||
*
|
||||
* Copyright (C) 2009 Bahadir Balban
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,11 +1,97 @@
|
||||
/*
|
||||
* Containers defined for current build.
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
* Copyright (C) 2009 Bahadir Balban
|
||||
*/
|
||||
|
||||
struct container container[] = {
|
||||
.[0] = { 0 },
|
||||
struct container_info cinfo[] = {
|
||||
.name = "Codezero POSIX Services",
|
||||
.npagers = 1,
|
||||
.pagers = {
|
||||
.[0] = {
|
||||
.pager_lma = 0x38000,
|
||||
.pager_vma = 0xE0000000,
|
||||
.pager_size = 0x96000,
|
||||
.ncaps = 11,
|
||||
.caps = {
|
||||
.[0] = {
|
||||
.type = CAP_TYPE_MAP | CAP_RTYPE_VIRTMEM,
|
||||
.access = CAP_MAP_READ | CAP_MAP_WRITE
|
||||
| CAP_MAP_EXEC | CAP_MAP_UNMAP,
|
||||
.access = 0,
|
||||
.start = 0xE0000000,
|
||||
.end = 0xF0000000,
|
||||
.size = 0x10000000,
|
||||
},
|
||||
.[1] = {
|
||||
.type = CAP_TYPE_MAP | CAP_RTYPE_VIRTMEM,
|
||||
.access = CAP_MAP_READ | CAP_MAP_WRITE
|
||||
| CAP_MAP_EXEC | CAP_MAP_UNMAP,
|
||||
.start = 0x10000000,
|
||||
.end = 0x20000000,
|
||||
.size = 0x10000000,
|
||||
},
|
||||
.[2] = {
|
||||
.type = CAP_TYPE_MAP | CAP_RTYPE_VIRTMEM,
|
||||
.access = CAP_MAP_READ | CAP_MAP_WRITE
|
||||
| CAP_MAP_EXEC | CAP_MAP_UNMAP,
|
||||
.access = 0,
|
||||
.start = 0x20000000,
|
||||
.end = 0x30000000,
|
||||
.size = 0x10000000,
|
||||
},
|
||||
.[3] = {
|
||||
.type = CAP_TYPE_MAP | CAP_RTYPE_PHYSMEM,
|
||||
.access = CAP_MAP_CACHED | CAP_MAP_UNCACHED
|
||||
| CAP_MAP_READ | CAP_MAP_WRITE
|
||||
| CAP_MAP_EXEC | CAP_MAP_UNMAP,
|
||||
.start = 0x38000,
|
||||
.end = 0x1000000, /* 16 MB */
|
||||
},
|
||||
.[4] = {
|
||||
.type = CAP_TYPE_IPC | CAP_RTYPE_CONTAINER,
|
||||
.access = CAP_IPC_SEND | CAP_IPC_RECV
|
||||
| CAP_IPC_FULL | CAP_IPC_SHORT
|
||||
| CAP_IPC_EXTENDED,
|
||||
.start = 0, .end = 0, .size = 0,
|
||||
},
|
||||
.[5] = {
|
||||
.type = CAP_TYPE_TCTRL | CAP_RTYPE_CONTAINER,
|
||||
.access = CAP_TCTRL_CREATE | CAP_TCTRL_DESTROY
|
||||
| CAP_TCTRL_SUSPEND | CAP_TCTRL_RESUME
|
||||
| CAP_TCTRL_RECYCLE,
|
||||
.start = 0, .end = 0, .size = 0,
|
||||
},
|
||||
.[6] = {
|
||||
.type = CAP_TYPE_EXREGS | CAP_RTYPE_CONTAINER,
|
||||
.access = CAP_EXREGS_RW_PAGER
|
||||
| CAP_EXREGS_RW_UTCB | CAP_EXREGS_RW_SP
|
||||
| CAP_EXREGS_RW_PC | CAP_EXREGS_RW_REGS,
|
||||
.start = 0, .end = 0, .size = 0,
|
||||
},
|
||||
.[7] = {
|
||||
.type = CAP_TYPE_QUANTITY
|
||||
| CAP_RTYPE_THREADPOOL,
|
||||
.access = 0, .start = 0, .end = 0,
|
||||
.size = 64,
|
||||
},
|
||||
.[8] = {
|
||||
.type = CAP_TYPE_QUANTITY | CAP_RTYPE_SPACEPOOL,
|
||||
.access = 0, .start = 0, .end = 0,
|
||||
.size = 64,
|
||||
},
|
||||
.[9] = {
|
||||
.type = CAP_TYPE_QUANTITY | CAP_RTYPE_CPUPOOL,
|
||||
.access = 0, .start = 0, .end = 0,
|
||||
.size = 50, /* Percentage */
|
||||
},
|
||||
.[10] = {
|
||||
.type = CAP_TYPE_QUANTITY | CAP_RTYPE_MUTEXPOOL,
|
||||
.access = 0, .start = 0, .end = 0,
|
||||
.size = 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Initialize system resource management.
|
||||
*
|
||||
* Copyright (C) 2009 Bahadir Balban
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here are the steps used to initialize system resources:
|
||||
*
|
||||
* Check total physical memory
|
||||
* Check container memory capabilities
|
||||
* Find biggest unused physical memory region
|
||||
* Calculate how much memory is used by all containers
|
||||
* Initialize a slab-like allocator for all resources.
|
||||
* Copy boot allocations to real allocations accounted to containers and kernel.
|
||||
* E.g. initial page table may become page table of a container pager.
|
||||
* First few pmds used belong to kernel usage, etc.
|
||||
* Delete all boot memory and add it to physical memory pool.
|
||||
*/
|
||||
|
||||
#define MEM_FLAGS_VIRTUAL (1 << 0)
|
||||
#define MEM_AREA_CACHED (1 << 1)
|
||||
|
||||
struct mem_area {
|
||||
struct link list;
|
||||
l4id_t mid;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
unsigned long npages;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
|
||||
void init_system_resources()
|
||||
{
|
||||
struct mem_area *physmem = alloc_bootmem(sizeof(physmem), 4);
|
||||
struct mem_area *kernel_used = alloc_bootmem(sizeof(physmem), 4);
|
||||
|
||||
/* Initialize the first memory descriptor for total physical memory */
|
||||
physmem.start = PHYS_MEM_START;
|
||||
physmem.end = PHYS_MEM_END;
|
||||
physmem.mid = 0;
|
||||
physmem.npages = (physmem.end - physmem.start) >> PAGE_BITS;
|
||||
|
||||
/* Figure out current kernel usage */
|
||||
kernel_used.start = virt_to_phys(_kernel_start);
|
||||
kernel_used.end = virt_to_phys(_kernel_end);
|
||||
|
||||
/* Figure out each container's physical memory usage */
|
||||
for (int i = 0; i < containers->total; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
431
src/generic/resource.c
Normal file
431
src/generic/resource.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Initialize system resource management.
|
||||
*
|
||||
* Copyright (C) 2009 Bahadir Balban
|
||||
*/
|
||||
|
||||
#include <l4/generic/capability.h>
|
||||
#include <l4/generic/container.h>
|
||||
#include <l4/lib/list.h>
|
||||
#include INC_GLUE(memory.h)
|
||||
#include INC_ARCH(linker.h)
|
||||
|
||||
struct kernel_container kernel_container;
|
||||
|
||||
void cap_list_init(struct cap_list *clist)
|
||||
{
|
||||
clist->ncaps = 0;
|
||||
link_init(&clist->caps);
|
||||
}
|
||||
|
||||
void cap_list_add(struct cap_list *clist, struct capability *cap)
|
||||
{
|
||||
list_add(&cap->list, &clist->caps);
|
||||
clist->ncaps++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes kernel caplists, and sets up total of physical
|
||||
* and virtual memory as single capabilities of the kernel.
|
||||
* They will then get split into caps of different lengths
|
||||
* during the traversal of container capabilities.
|
||||
*/
|
||||
void setup_kernel_container(struct kernel_container *kcont)
|
||||
{
|
||||
struct capability *physmem, *virtmem, *kernel_area;
|
||||
|
||||
/* Initialize kernel capability lists */
|
||||
cap_list_init(&kcont->physmem_used);
|
||||
cap_list_init(&kcont->physmem_free);
|
||||
cap_list_init(&kcont->virtmem_used);
|
||||
cap_list_init(&kcont->virtmem_free);
|
||||
cap_list_init(&kcont->devmem_used);
|
||||
cap_list_init(&kcont->devmem_free);
|
||||
|
||||
/* Set up total physical memory as single capability */
|
||||
physmem = alloc_bootmem(sizeof(*physmem));
|
||||
physmem->start = __pfn(PHYS_MEM_START);
|
||||
physmem->end = __pfn(PHYS_MEM_END);
|
||||
link_init(&physmem->list);
|
||||
cap_list_add(&kcont->physmem_free, physmem);
|
||||
|
||||
/* Set up total virtual memory as single capability */
|
||||
virtmem = alloc_bootmem(sizeof(*virtmem));
|
||||
virtmem->start = __pfn(VIRT_MEM_START);
|
||||
virtmem->end = __pfn(VIRT_MEM_END);
|
||||
link_init(&virtmem->list);
|
||||
cap_list_add(&kcont->virtmem_free, virtmem);
|
||||
|
||||
/* Set up kernel used area as a single capability */
|
||||
kernel_area = alloc_bootmem(sizeof(*physmem));
|
||||
kernel_area->start = __pfn(virt_to_phys(_start_kernel));
|
||||
kernel_area->end = __pfn(virt_to_phys(_end_kernel));
|
||||
link_init(&kernel_area->list);
|
||||
list_add(&kcont->physmem_used, kernel_area);
|
||||
|
||||
/* Unmap kernel used area from free physical memory capabilities */
|
||||
memcap_unmap(&kcont->physmem_free, kernel_area->start,
|
||||
kernel_area->end);
|
||||
|
||||
/* TODO:
|
||||
* Add all virtual memory areas used by the kernel
|
||||
* e.g. kernel virtual area, syscall page, kip page,
|
||||
* vectors page, timer, sysctl and uart device pages
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* This splits a capability, splitter region must be in
|
||||
* the *middle* of original capability
|
||||
*/
|
||||
int memcap_split(struct capability *cap, struct cap_list *cap_list,
|
||||
const unsigned long start,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct capability *new;
|
||||
|
||||
/* Allocate a capability first */
|
||||
new = alloc_bootmem(sizeof(*new));
|
||||
|
||||
/*
|
||||
* Some sanity checks to show that splitter range does end up
|
||||
* producing two smaller caps.
|
||||
*/
|
||||
BUG_ON(cap->start >= start || cap->end <= end);
|
||||
|
||||
/* Update new and original caps */
|
||||
new->end = cap->end;
|
||||
new->start = end;
|
||||
cap->end = start;
|
||||
new->access = cap->access;
|
||||
|
||||
/* Add new one next to original cap */
|
||||
cap_list_add(new, cap_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This shrinks the cap from *one* end only, either start or end */
|
||||
int memcap_shrink(struct capability *cap, struct cap_list *cap_list,
|
||||
const unsigned long start, const unsigned long end)
|
||||
{
|
||||
/* Shrink from the end */
|
||||
if (cap->start < start) {
|
||||
BUG_ON(start >= cap->end);
|
||||
cap->end = start;
|
||||
|
||||
/* Shrink from the beginning */
|
||||
} else if (cap->end > end) {
|
||||
BUG_ON(end <= cap->start);
|
||||
cap->start = end;
|
||||
} else
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memcap_unmap_range(struct capability *cap,
|
||||
struct cap_list *cap_list,
|
||||
const unsigned long pfn_start,
|
||||
const unsigned long pfn_end)
|
||||
{
|
||||
/* Split needed? */
|
||||
if (cap->start < start && cap->end > end)
|
||||
return memcap_split(cap, cap_list, start, end);
|
||||
/* Shrink needed? */
|
||||
else if (((cap->start >= start) && (cap->end > end))
|
||||
|| ((cap->start < start) && (cap->end <= end)))
|
||||
return memcap_shrink(cap, cap_list, start, end);
|
||||
/* Destroy needed? */
|
||||
else if ((cap->start >= start) && (cap->end <= end))
|
||||
/* Simply unlink it */
|
||||
list_remove(&cap->list);
|
||||
else
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmaps given memory range from the list of capabilities
|
||||
* by either shrinking, splitting or destroying the
|
||||
* intersecting capability. Similar to do_munmap()
|
||||
*/
|
||||
int memcap_unmap(struct cap_list *cap_list,
|
||||
const unsigned long unmap_start,
|
||||
const unsigned long unmap_end)
|
||||
{
|
||||
struct capability *cap, *n;
|
||||
int err;
|
||||
|
||||
list_foreach_removable_struct(cap, n, &cap_list->caps, list) {
|
||||
/* Check for intersection */
|
||||
if (set_intersection(unmap_start, unmap_end,
|
||||
cap->start, cap->end)) {
|
||||
if ((err = memcap_unmap_range(cap, cap_list
|
||||
unmap_start,
|
||||
unmap_end))) {
|
||||
return err;
|
||||
}
|
||||
/* Return 1 to indicate unmap occured */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/*
|
||||
* Do all system accounting for this capability info
|
||||
* structure that belongs to a container, such as
|
||||
* count its resource requirements, remove its portion
|
||||
* from global kernel capabilities etc.
|
||||
*/
|
||||
int process_cap_info(struct cap_info *cap,
|
||||
struct boot_resources *bootres,
|
||||
struct kernel_container *kcont)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (cap->type & CAP_RTYPE_MASK) {
|
||||
case CAP_RTYPE_THREADPOOL:
|
||||
bootres->nthreads += cap->size;
|
||||
break;
|
||||
case CAP_RTYPE_SPACEPOOL:
|
||||
bootres->nspaces += cap->size;
|
||||
break;
|
||||
case CAP_RTYPE_MUTEXPOOL:
|
||||
bootres->nmutex += cap->size;
|
||||
break;
|
||||
case CAP_RTYPE_VIRTMEM:
|
||||
bootres->npmds +=
|
||||
cap->size / PMD_MAP_SIZE;
|
||||
if ((ret = memcap_unmap(&kcont->virtmem_free,
|
||||
cap->start, cap->end))) {
|
||||
if (ret < 0)
|
||||
printk("FATAL: Insufficient boot memory "
|
||||
"to split capability\n");
|
||||
if (ret > 0)
|
||||
printf("FATAL: Memory capability range "
|
||||
"overlaps with another one. "
|
||||
"start=0x%x, end=0x%x\n",
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
case CAP_RTYPE_PHYSMEM:
|
||||
if ((ret = memcap_unmap(&kcont->virtmem_free,
|
||||
cap->start, cap->end))) {
|
||||
if (ret < 0)
|
||||
printk("FATAL: Insufficient boot memory "
|
||||
"to split capability\n");
|
||||
if (ret > 0)
|
||||
printf("FATAL: Memory capability range "
|
||||
"overlaps with another one. "
|
||||
"start=0x%x, end=0x%x\n",
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Migrate any boot allocations to their relevant caches.
|
||||
*/
|
||||
void migrate_boot_resources(struct boot_resources *bootres,
|
||||
struct kernel_container *kcont)
|
||||
{
|
||||
/* Migrate boot page tables to new caches */
|
||||
migrate_page_tables(kcont);
|
||||
|
||||
/* Migrate all boot-allocated capabilities */
|
||||
migrate_boot_caps(kcont);
|
||||
}
|
||||
|
||||
/* Delete all boot memory and add it to physical memory pool. */
|
||||
int free_boot_memory(struct kernel_container *kcont,
|
||||
struct boot_resources *bootres)
|
||||
{
|
||||
/* Trim kernel used memory memcap */
|
||||
memcap_unmap(&kcont->physical_used, _bootmem_start, _bootmem_end);
|
||||
|
||||
/* Add it to unused physical memory */
|
||||
memcap_map(&kcont->physical_unused, _bootmem_start, _bootmem_end);
|
||||
}
|
||||
|
||||
|
||||
struct mem_cache *init_resource_cache(struct boot_resources *bootres,
|
||||
struct kernel_container *kcont)
|
||||
{
|
||||
struct capability *cap;
|
||||
unsigned long bufsize;
|
||||
|
||||
/* In all unused physical memory regions */
|
||||
list_foreach_struct(cap, &kcont->physical_unused, list) {
|
||||
/* Get buffer size needed for cache */
|
||||
bufsize = mem_cache_bufsize(__pfn_to_addr(cap->start),
|
||||
PGD_SIZE, bootres->nspaces,
|
||||
aligned);
|
||||
/*
|
||||
* Check if memcap region size is enough to cover
|
||||
* resource allocation
|
||||
*/
|
||||
if (__pfn_to_addr(cap->end - cap->start) >= bufsize) {
|
||||
unsigned long virtual =
|
||||
phys_to_virt(__pfn_to_addr(cap->start));
|
||||
/*
|
||||
* Map the buffer as boot mapping if pmd caches
|
||||
* are not initialized
|
||||
*/
|
||||
if (!kcont->pmd_cache) {
|
||||
add_boot_mapping(__pfn_to_addr(cap->start),
|
||||
virtual, bufsize,
|
||||
MAP_SVC_RW_FLAGS);
|
||||
} else {
|
||||
add_mapping(__pfn_to_addr(cap->start),
|
||||
virtual, bufsize,
|
||||
MAP_SVC_RW_FLAGS);
|
||||
}
|
||||
/* Unmap area from memcap */
|
||||
memcap_unmap_range(cap, &kcont->physical_unused,
|
||||
cap->start, cap->start +
|
||||
__pfn(page_align_up((bufsize))));
|
||||
|
||||
/* TODO: Manipulate memcaps for virtual range??? */
|
||||
|
||||
/* Initialize the cache */
|
||||
return mem_cache_init(virtual, bufsize, PGD_SIZE, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void create_containers(struct boot_resources *bootres,
|
||||
struct kernel_container *kcont)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void create_capabilities(struct boot_resources *bootres,
|
||||
struct kernel_container *kcont)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure to count boot pmds, and kernel capabilities
|
||||
* created in boot memory.
|
||||
*
|
||||
* Also total capabilities in the system + number of
|
||||
* capabilities containers are allowed to create dynamically.
|
||||
*
|
||||
* Count the extra pgd + space needed in case all containers quit
|
||||
*/
|
||||
void init_resource_allocators(struct boot_resources *bootres,
|
||||
struct kernel_container *kcont)
|
||||
{
|
||||
struct mem_cache *cache;
|
||||
|
||||
/* Initialise PGD cache */
|
||||
cache = init_resource_cache(bootres->nspaces,
|
||||
PGD_SIZE, kcont, 1);
|
||||
kcont->pgd_cache = cache;
|
||||
|
||||
/* Initialise PMD cache */
|
||||
cache = init_resource_cache(bootres->npmds,
|
||||
PMD_SIZE, kcont, 1);
|
||||
cache->pmd_cache = cache;
|
||||
|
||||
/* Initialise struct address_space cache */
|
||||
cache = init_resource_cache(bootres->nspaces,
|
||||
sizeof(struct address_space),
|
||||
kcont, 0);
|
||||
cache->address_space_cache = cache;
|
||||
|
||||
/* Initialise ktcb cache */
|
||||
cache = init_resource_cache(bootres->nthreads,
|
||||
PAGE_SIZE, kcont, 1);
|
||||
cache->ktcb_cache = cache;
|
||||
|
||||
/* Initialise umutex cache */
|
||||
cache = init_resource_cache(bootres->numutex,
|
||||
sizeof(struct mutex_queue),
|
||||
kcont, 0);
|
||||
cache->umutex_cache = cache;
|
||||
|
||||
/* TODO: Initialize ID cache */
|
||||
|
||||
/* # of capabilities are now constant, create capabilities cache */
|
||||
|
||||
/* Initialise capability cache */
|
||||
cache = init_resource_cache(bootres->ncaps, /* FIXME: Count correctly */
|
||||
sizeof(struct capability),
|
||||
kcont, 0);
|
||||
cache->cap_cache = cache;
|
||||
|
||||
/* Initialise container cache */
|
||||
cache = init_resource_cache(bootres->ncont,
|
||||
sizeof(struct container),
|
||||
kcont, 0);
|
||||
cache->cont_cache = cache;
|
||||
|
||||
/* Create system containers */
|
||||
create_containers(bootres, kcont);
|
||||
|
||||
/* Create capabilities */
|
||||
create_capabilities(bootres, kcont);
|
||||
}
|
||||
|
||||
int init_boot_resources(struct boot_resources *bootres, struct kernel_container *kcont)
|
||||
{
|
||||
struct cap_info *cap;
|
||||
struct pager_info *pgr;
|
||||
struct container_info *cont;
|
||||
|
||||
setup_kernel_container(kcont);
|
||||
|
||||
/* Number of containers known at compile-time */
|
||||
bootres->nconts = ncontainers;
|
||||
|
||||
/* Traverse all containers */
|
||||
for (int i = 0; i < bootres->nconts; i++) {
|
||||
/* Traverse all pagers */
|
||||
for (int j = 0; j < container[i]->npagers; j++) {
|
||||
int ncaps = container[i].pager[j].ncaps;
|
||||
|
||||
/* Count all capabilities */
|
||||
bootres->ncaps += ncaps;
|
||||
|
||||
/* Count all resources */
|
||||
for (int k = 0; k < ncaps; k++) {
|
||||
cap = container[i].pager[j].caps[k];
|
||||
proces_cap_info(cap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Count all ids needed to represent all */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Add error handling
|
||||
*/
|
||||
int init_system_resources(struct kernel_container *kcont)
|
||||
{
|
||||
|
||||
struct boot_resources bootres;
|
||||
|
||||
init_boot_resources(&bootres, &kcont);
|
||||
|
||||
init_resource_allocators(&bootres, &kcont);
|
||||
|
||||
free_boot_memory(bootres, kcont);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,16 +15,6 @@
|
||||
#include <l4/api/kip.h>
|
||||
#include <l4/lib/idpool.h>
|
||||
|
||||
struct address_space_list {
|
||||
struct link list;
|
||||
|
||||
/* Lock for list add/removal */
|
||||
struct spinlock list_lock;
|
||||
|
||||
/* Used when delete/creating spaces */
|
||||
struct mutex ref_lock;
|
||||
int count;
|
||||
};
|
||||
|
||||
static struct address_space_list address_space_list;
|
||||
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
struct id_pool *thread_id_pool;
|
||||
struct id_pool *space_id_pool;
|
||||
|
||||
/* Hash table for all existing tasks */
|
||||
struct ktcb_list {
|
||||
struct link list;
|
||||
struct spinlock list_lock;
|
||||
int count;
|
||||
};
|
||||
|
||||
static struct ktcb_list ktcb_list;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/generic/bootmem.h>
|
||||
#include <l4/generic/resource.h>
|
||||
#include INC_ARCH(linker.h)
|
||||
#include INC_ARCH(asm.h)
|
||||
#include INC_ARCH(bootdesc.h)
|
||||
|
||||
@@ -90,12 +90,50 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
struct mem_cache *mem_cache_init(void *start,
|
||||
/*
|
||||
* Given a buffer start address, structure size, number of
|
||||
* structs and alignment requirements, determines how much
|
||||
* memory is needed from that starting address
|
||||
*/
|
||||
int mem_cache_bufsize(void *start, int struct_size, int nstructs, int aligned)
|
||||
{
|
||||
unsigned long start_address = (unsigned long)start;
|
||||
int total_bytes, bwords;
|
||||
|
||||
/* Word alignment requirement */
|
||||
start_address = align_up(start_address, sizeof(int));
|
||||
|
||||
/* Total bytes to contain structures */
|
||||
total_bytes = struct_size * nstructs;
|
||||
|
||||
/* Total words to contain bitmap */
|
||||
bwords = nstructs >> 5;
|
||||
|
||||
/* An extra word if not a multiple of one word's bits */
|
||||
if (nstructs & 0x1F)
|
||||
bwords++;
|
||||
|
||||
/* Total bitmap bytes */
|
||||
bitmap_size = bwords * sizeof(int);
|
||||
|
||||
/* Current would-be start address */
|
||||
start_address += bitmap_size + total_bytes + sizeof(struct mem_cache);
|
||||
|
||||
/* Check alignment requirement */
|
||||
if (aligned)
|
||||
start_address += align_up(start_address, struct_size);
|
||||
|
||||
return start_address - (unsigned long)start;
|
||||
}
|
||||
|
||||
struct mem_cache *mem_cache_init(void *bufstart,
|
||||
int cache_size,
|
||||
int struct_size,
|
||||
unsigned int aligned)
|
||||
{
|
||||
struct mem_cache *cache = start;
|
||||
/* Align to nearest word boundary */
|
||||
void *start;
|
||||
struct mem_cache *cache;
|
||||
unsigned int area_start;
|
||||
unsigned int *bitmap;
|
||||
int bwords_in_structs;
|
||||
@@ -103,6 +141,10 @@ struct mem_cache *mem_cache_init(void *start,
|
||||
int total;
|
||||
int bsize;
|
||||
|
||||
start = (void *)align_up(bufstart, sizeof(int));
|
||||
cache_size -= (int)start - (int)bufstart;
|
||||
mem_cache = start;
|
||||
|
||||
if ((struct_size < 0) || (cache_size < 0) ||
|
||||
((unsigned long)start == ~(0))) {
|
||||
printk("Invalid parameters.\n");
|
||||
|
||||
Reference in New Issue
Block a user