From a3eba19470c09f42272dac5ca1a34bd8a5cbe834 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 17 Nov 2009 10:26:25 +0100 Subject: The original version of DDEKit. --- libddekit/init.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 libddekit/init.c (limited to 'libddekit/init.c') diff --git a/libddekit/init.c b/libddekit/init.c new file mode 100644 index 00000000..0532caed --- /dev/null +++ b/libddekit/init.c @@ -0,0 +1,35 @@ +/** + * The functions regarding DDE/BSD initialization are found here. + * + * \author Thomas Friebel + */ +#include +#include +#include + +#include +#include +#include +#include + +/* FIXME this must be initialized explicitly as some users may not need l4io, + * e.g., l4io's own pcilib. */ +static void ddekit_init_l4io(void) +{ + int err; + l4io_info_t *ioip = NULL; + + LOGd(0, "mapping io info page to %p", ioip); + err = l4io_init(&ioip, L4IO_DRV_INVALID); + if ( err | !ioip ) { + LOG("error initializing io lib: %s (err=%d, ioip=%p)", l4env_errstr(err), err, ioip); + ddekit_panic("fatal error"); + } +} + +void ddekit_init(void) +{ + ddekit_init_l4io(); + ddekit_init_threads(); +} + -- cgit v1.2.3 From 53e2cdc12fad42c3b4ddce5bb011273c46d36472 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 17 Nov 2009 11:24:33 +0100 Subject: Remove the code for initializing l4io. --- libddekit/init.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'libddekit/init.c') diff --git a/libddekit/init.c b/libddekit/init.c index 0532caed..2104d80f 100644 --- a/libddekit/init.c +++ b/libddekit/init.c @@ -3,33 +3,10 @@ * * \author Thomas Friebel */ -#include -#include -#include - -#include -#include -#include -#include - -/* FIXME this must be initialized explicitly as some users may not need l4io, - * e.g., l4io's own pcilib. */ -static void ddekit_init_l4io(void) -{ - int err; - l4io_info_t *ioip = NULL; - - LOGd(0, "mapping io info page to %p", ioip); - err = l4io_init(&ioip, L4IO_DRV_INVALID); - if ( err | !ioip ) { - LOG("error initializing io lib: %s (err=%d, ioip=%p)", l4env_errstr(err), err, ioip); - ddekit_panic("fatal error"); - } -} +#include "ddekit/thread.h" void ddekit_init(void) { - ddekit_init_l4io(); ddekit_init_threads(); } -- cgit v1.2.3 From 41a14fbb798e85fcb26b1a95ea72daeda9ec2004 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Thu, 3 Dec 2009 14:43:55 +0100 Subject: Implement a faked slab cache. --- libddekit/Makefile | 2 +- libddekit/init.c | 2 + libddekit/memory.c | 277 +++-------------------------------------------------- 3 files changed, 16 insertions(+), 265 deletions(-) (limited to 'libddekit/init.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index e9daa648..59e5c5a9 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -21,7 +21,7 @@ makemode := library libname = libddekit SRCS= condvar.c init.c initcall.c interrupt.c lock.c malloc.c memory.c \ panic.c pci.c pgtab-old.c pgtab.c printf.c resources.c list.c \ - thread.c timer.c + thread.c timer.c kmem.c LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ include/ddekit/initcall.h include/ddekit/debug.h \ include/ddekit/inline.h include/ddekit/panic.h \ diff --git a/libddekit/init.c b/libddekit/init.c index 2104d80f..9708ba1d 100644 --- a/libddekit/init.c +++ b/libddekit/init.c @@ -7,6 +7,8 @@ void ddekit_init(void) { + extern void linux_kmem_init (); ddekit_init_threads(); + linux_kmem_init (); } diff --git a/libddekit/memory.c b/libddekit/memory.c index b6db0cac..93853e55 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -10,16 +10,9 @@ * FIXME check thread-safety and add locks where appropriate */ -#include -#include -#include -#include +#include "ddekit/memory.h" -#include -#include -#include -#include -#include +extern void * linux_kmalloc (unsigned int size, int priority); /**************** @@ -56,21 +49,6 @@ struct ddekit_pcache }; -/* head of single-linked list containing used page-cache entries, non-contiguous */ -static struct ddekit_pcache *pcache_used; -/* head of single-linked list containing free page-cache entries, non-contiguous */ -static struct ddekit_pcache *pcache_free; - -/* head of single-linked list containing used page-cache entries, contiguous */ -static struct ddekit_pcache *pcache_used_contig; -/* head of single-linked list containing free page-cache entries, contiguous */ -static struct ddekit_pcache *pcache_free_contig; - -/* maximum number of pages to cache. defaults to a minimum of 1 page - * because having none hits the performance too hard. */ -static l4_uint32_t pcache_num_entries = 1; - - /** * Setup page cache for all slabs * @@ -82,88 +60,8 @@ static l4_uint32_t pcache_num_entries = 1; */ void ddekit_slab_setup_page_cache(unsigned pages) { - /* FIXME just allowing to grow at the moment */ - while (pcache_num_entries < pages) { - struct ddekit_pcache *new_entry, *new_contig; - - /* create new list element */ - new_entry = (struct ddekit_pcache *) ddekit_simple_malloc(sizeof(*new_entry)); - new_contig = (struct ddekit_pcache *) ddekit_simple_malloc(sizeof(*new_contig)); - - /* insert into lists of unused cache entries */ - do { - new_entry->next = pcache_free; - } while (!l4util_cmpxchg32((l4_uint32_t*)&pcache_free, - (l4_uint32_t)new_entry->next, - (l4_uint32_t)new_entry)); - - do { - new_contig->next = pcache_free_contig; - } while (!l4util_cmpxchg32((l4_uint32_t*)&pcache_free_contig, - (l4_uint32_t)new_entry->next, - (l4_uint32_t)new_entry)); - - /* increment number of list elements */ - l4util_inc32(&pcache_num_entries); - } } - -/** - * Try to allocate a new page from the pcache. - */ -static inline struct ddekit_pcache *_try_from_cache(int contig) -{ - struct ddekit_pcache *head = NULL; - struct ddekit_pcache *the_cache = contig ? pcache_used_contig : pcache_used; - - do { - head = the_cache; - if (!head) break; - } while (!l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)head, - (l4_uint32_t)head->next)); - - return head; -} - - -static inline void _add_to_cache(struct ddekit_pcache *entry, int contig) -{ - struct ddekit_pcache *the_cache = contig ? pcache_used_contig : pcache_used; - do { - entry->next = the_cache; - } while (! l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)entry->next, - (l4_uint32_t)entry)); -} - -/** - * Return free entry to cached entry list. - */ -static inline void _free_cache_entry(struct ddekit_pcache *entry, int contig) -{ - struct ddekit_pcache *the_cache = contig ? pcache_free_contig : pcache_free; - do { - entry->next = the_cache; - } while (!l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)entry->next, - (l4_uint32_t)entry)); -} - - -static inline struct ddekit_pcache *_get_free_cache_entry(int contig) -{ - struct ddekit_pcache *the_cache = contig ? pcache_free_contig : pcache_free; - struct ddekit_pcache *head = NULL; - - do { - head = the_cache; - if (!head) break; - } while (!l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)head, - (l4_uint32_t) head->next)); - - return head; -} - - /******************************* ** Slab cache implementation ** *******************************/ @@ -171,132 +69,16 @@ static inline struct ddekit_pcache *_get_free_cache_entry(int contig) /* ddekit slab facilitates l4slabs */ struct ddekit_slab { - l4slab_cache_t cache; - /* - * Lock to prevent concurrent access to the slab's grow() and - * shrink() functions. - */ - l4lock_t lock; + int size; int contiguous; }; - -/** - * Get the ddekit slab for a given L4 slab. - * - * We cheat here, because we know that the L4 slab is the first member - * of the ddekit slab. - */ -static inline struct ddekit_slab *ddekit_slab_from_l4slab(l4slab_cache_t *s) -{ - return (struct ddekit_slab *)s; -} - -/** - * Grow slab cache - */ -static void *_slab_grow(l4slab_cache_t *cache, void **data) -{ - /* the page(s) to be returned */ - void *res = NULL; - /* whether this cache needs physically contiguous pages */ - int is_contig = ddekit_slab_from_l4slab(cache)->contiguous; - - /* free cache entry, will be used afterwards */ - struct ddekit_pcache *head = NULL; - - /* We don't reuse pages for slabs > 1 page, because this makes caching - * somewhat harder. */ - if (cache->slab_size <= L4_PAGESIZE) - /* try to aquire cached page */ - head = _try_from_cache(is_contig); - - if (head) { - /* use cached page */ - res = head->page; - /* this cache entry is now available */ - _free_cache_entry(head, is_contig); - } else { - /* allocate new page at memory server */ - int err; - l4_size_t tmp; - l4dm_mem_addr_t dm_paddr; - int num_pages = cache->slab_size / L4_PAGESIZE; - int flags = L4DM_PINNED | L4RM_MAP | L4RM_LOG2_ALIGNED; - - if (is_contig) - flags |= L4DM_CONTIGUOUS; - - /* allocate and map new page(s) */ - res = l4dm_mem_allocate_named(num_pages * L4_PAGESIZE, - flags, - "ddekit slab"); - if (res == NULL) - ddekit_debug("__grow: error allocating a new page"); - - /* physically contiguous pages need some special treatment */ - if (is_contig) { - err = l4dm_mem_phys_addr(res, num_pages, &dm_paddr, 1, &tmp); - if (err != 1) - ddekit_debug("__grow: error getting physical address of new page!"); - - ddekit_pgtab_set_region(res, dm_paddr.addr, num_pages, PTE_TYPE_UMA); - } - } - - /* save pointer to cache in page for ddekit_slab_get_slab() */ - *data = cache; - - return res; -} - -/** - * Shrink slab cache - */ -static void _slab_shrink(l4slab_cache_t *cache, void *page, void *data) -{ - /* cache deallocated page here */ - struct ddekit_pcache *head = NULL; - /* whether this cache needs physically contiguous pages */ - int is_contig = ddekit_slab_from_l4slab(cache)->contiguous; - - /* we do not return slabs to the page cache, if they are larger than one page */ - if (cache->slab_size <= L4_PAGESIZE) - /* try to aquire free cache entry */ - head = _get_free_cache_entry(is_contig); - - if (head) { - /* use free cache entry to cache page */ - - /* set the page info */ - head->page = page; - - /* this cache entry contains a free page */ - _add_to_cache(head, is_contig); - } else { - /* cache is full */ - - if (is_contig) - /* unset pte */ - ddekit_pgtab_clear_region(page, PTE_TYPE_UMA); - - /* free page */ - l4dm_mem_release(page); - } -} - - /** * Allocate object in slab */ void *ddekit_slab_alloc(struct ddekit_slab * slab) { - void *ret = NULL; - l4lock_lock(&slab->lock); - ret = l4slab_alloc(&slab->cache); - l4lock_unlock(&slab->lock); - - return ret; + return linux_kmalloc (slab->size, 0); } @@ -305,9 +87,7 @@ void *ddekit_slab_alloc(struct ddekit_slab * slab) */ void ddekit_slab_free(struct ddekit_slab * slab, void *objp) { - l4lock_lock(&slab->lock); - l4slab_free(&slab->cache, objp); - l4lock_unlock(&slab->lock); + linux_kfree (objp); } @@ -316,7 +96,9 @@ void ddekit_slab_free(struct ddekit_slab * slab, void *objp) */ void ddekit_slab_set_data(struct ddekit_slab * slab, void *data) { +#if 0 l4slab_set_data(&slab->cache, data); +#endif } @@ -325,7 +107,9 @@ void ddekit_slab_set_data(struct ddekit_slab * slab, void *data) */ void *ddekit_slab_get_data(struct ddekit_slab * slab) { +#if 0 return l4slab_get_data(&slab->cache); +#endif } @@ -336,7 +120,6 @@ void *ddekit_slab_get_data(struct ddekit_slab * slab) */ void ddekit_slab_destroy (struct ddekit_slab * slab) { - l4slab_destroy(&slab->cache); ddekit_simple_free(slab); } @@ -352,19 +135,10 @@ void ddekit_slab_destroy (struct ddekit_slab * slab) struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) { struct ddekit_slab * slab; - int err; slab = (struct ddekit_slab *) ddekit_simple_malloc(sizeof(*slab)); - slab->lock = L4LOCK_UNLOCKED; - err = l4slab_cache_init(&slab->cache, size, 0, _slab_grow, _slab_shrink); - if (err) { - ddekit_debug("error initializing cache"); - ddekit_simple_free(slab); - return 0; - } - + slab->size = size; slab->contiguous = contiguous; - return slab; } @@ -380,11 +154,7 @@ struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) */ void ddekit_large_free(void *objp) { - /* clear PTEs */ - ddekit_pgtab_clear_region(objp, PTE_TYPE_LARGE); - - /* release */ - l4dm_mem_release(objp); + return linux_kfree (objp); } @@ -395,29 +165,8 @@ void ddekit_large_free(void *objp) */ void *ddekit_large_malloc(int size) { - void *res; - int err; - l4_size_t tmp; - int pages; - l4dm_mem_addr_t dm_paddr; - - size = l4_round_page(size); - pages = size >> L4_PAGESHIFT; - - res = l4dm_mem_allocate_named(size, - L4DM_CONTIGUOUS | L4DM_PINNED | - L4RM_MAP | L4RM_LOG2_ALIGNED, - "ddekit mem"); - if (! res) - return NULL; - - err = l4dm_mem_phys_addr(res, 1, &dm_paddr, 1, &tmp); - if (err != 1) - ddekit_debug("ddekit_large_malloc: error getting physical address of new memory!\n"); - - ddekit_pgtab_set_region(res, dm_paddr.addr, pages, PTE_TYPE_LARGE); - - return res; + // TODO I hope linux_kmalloc can provide large enough pages. + return linux_kmalloc (size, 0); } -- cgit v1.2.3 From 79a5b62aba561e8eb24aa74b789ff71d5c52be5e Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 4 Dec 2009 12:18:26 +0100 Subject: Implement printf and its variant. --- libddekit/init.c | 2 ++ libddekit/printf.c | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) (limited to 'libddekit/init.c') diff --git a/libddekit/init.c b/libddekit/init.c index 9708ba1d..6bc9d8ff 100644 --- a/libddekit/init.c +++ b/libddekit/init.c @@ -8,7 +8,9 @@ void ddekit_init(void) { extern void linux_kmem_init (); + extern int log_init (); ddekit_init_threads(); linux_kmem_init (); + log_init (); } diff --git a/libddekit/printf.c b/libddekit/printf.c index fb13a0b4..bbd58863 100644 --- a/libddekit/printf.c +++ b/libddekit/printf.c @@ -4,9 +4,12 @@ * \date 2006-03-01 */ -#include +#include +#include -#include +#include "ddekit/printf.h" + +static FILE *output; /** * Log constant string message w/o arguments @@ -15,7 +18,17 @@ */ int ddekit_print(const char *msg) { - return LOG_printf("%s", msg); + int ret; + + /* If LOG hasn't been initialized or failed its initialization, + * return the error. */ + if (output == NULL) + return -1; + + ret = fprintf (output, "%s", msg); + if (!ret) + fflush (output); + return ret; } /** @@ -42,5 +55,24 @@ int ddekit_printf(const char *fmt, ...) */ int ddekit_vprintf(const char *fmt, va_list va) { - return LOG_vprintf(fmt, va); + char *tmp = NULL; + int ret; + + ret = vasprintf (&tmp, fmt, va); + if (!ret) { + ret = ddekit_print (tmp); + free (tmp); + } + return ret; +} + +int log_init () +{ + char *log_file_name = mktemp ("/tmp/dde_log.XXXXXX"); + output = fopen (log_file_name, "a+"); + if (!output) { + error (0, errno, "open %s", log_file_name); + return -1; + } + return 0; } -- cgit v1.2.3 From b4bffcfcdf3ab7a55d664e9aa5907f88da503f38 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 6 Dec 2009 05:14:54 +0100 Subject: The code can be compiled now. --- libddekit/Makefile | 11 +- libddekit/condvar.c | 4 +- libddekit/device.defs | 204 ++++++++++ libddekit/include/Makefile | 9 - libddekit/include/ddekit/assert.h | 4 +- libddekit/include/ddekit/condvar.h | 1 + libddekit/include/ddekit/initcall.h | 42 -- libddekit/include/ddekit/thread.h | 2 + libddekit/init.c | 3 + libddekit/initcall.c | 8 - libddekit/interrupt.c | 63 ++- libddekit/kmem.c | 5 +- libddekit/list.c | 4 +- libddekit/lock.c | 3 +- libddekit/mach.defs | 779 ++++++++++++++++++++++++++++++++++++ libddekit/malloc.c | 3 + libddekit/memory.c | 5 +- libddekit/pci.c | 33 +- libddekit/printf.c | 3 + libddekit/thread.c | 68 ++-- libddekit/timer.c | 7 +- libddekit/vm_param.h | 7 + 22 files changed, 1132 insertions(+), 136 deletions(-) create mode 100644 libddekit/device.defs delete mode 100644 libddekit/include/Makefile delete mode 100644 libddekit/include/ddekit/initcall.h delete mode 100644 libddekit/initcall.c create mode 100644 libddekit/mach.defs create mode 100644 libddekit/vm_param.h (limited to 'libddekit/init.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index 1203ca38..67a3b193 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -19,22 +19,22 @@ dir := libddekit makemode := library libname = libddekit -SRCS= condvar.c init.c initcall.c interrupt.c lock.c malloc.c memory.c \ - pci.c pgtab-old.c pgtab.c printf.c resources.c list.c \ +SRCS= condvar.c init.c interrupt.c lock.c malloc.c memory.c \ + pci.c pgtab.c printf.c resources.c list.c \ thread.c timer.c kmem.c LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ - include/ddekit/initcall.h include/ddekit/debug.h \ + include/ddekit/semaphore.h include/ddekit/debug.h \ include/ddekit/inline.h include/ddekit/panic.h \ include/ddekit/thread.h include/ddekit/types.h \ include/ddekit/pgtab.h include/ddekit/printf.h \ include/ddekit/pci.h include/ddekit/assert.h \ include/ddekit/interrupt.h include/ddekit/resources.h \ include/ddekit/memory.h include/ddekit/timer.h \ - include/ddekit/semaphore.h include/dde.h \ + include/dde.h \ config.h list.h installhdrs = -MIGSTUBS = +MIGSTUBS = deviceUser.o machUser.o OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS)) HURDLIBS = threads ports @@ -44,3 +44,4 @@ MIGCOMSFLAGS = -prefix dde_ include ../Makeconf LDFLAGS += -lpciaccess +CFLAGS += -Iinclude -Iinclude/ddekit diff --git a/libddekit/condvar.c b/libddekit/condvar.c index 96e28c07..bbd49417 100644 --- a/libddekit/condvar.c +++ b/libddekit/condvar.c @@ -13,12 +13,12 @@ struct ddekit_condvar { }; ddekit_condvar_t *ddekit_condvar_init() { - ddekit_condvar_t *cvp; + struct condition *cvp; cvp = condition_alloc (); condition_init (cvp); - return cvp; + return (ddekit_condvar_t *) cvp; } void ddekit_condvar_wait(ddekit_condvar_t *cvp, ddekit_lock_t *mp) { diff --git a/libddekit/device.defs b/libddekit/device.defs new file mode 100644 index 00000000..6a73853a --- /dev/null +++ b/libddekit/device.defs @@ -0,0 +1,204 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * File: device/device.defs + * Author: Douglas Orr + * Feb 10, 1988 + * Abstract: + * Mach device support. Mach devices are accessed through + * block and character device interfaces to the kernel. + */ + +#ifdef MACH_KERNEL +simport ; /* for obsolete routines */ +#endif + +subsystem +#if KERNEL_SERVER + KernelServer +#endif + device 2800; + +#include +#include +#include + +serverprefix ds_; + +type pci_config_data_t = array[*:4] of char; +type reply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic + ctype: mach_port_t; + +routine device_open( + master_port : mach_port_t; + sreplyport reply_port : reply_port_t; + mode : dev_mode_t; + name : dev_name_t; + out device : device_t + ); + +routine device_close( + device : device_t + ); + +routine device_write( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in data : io_buf_ptr_t; + out bytes_written : int + ); + +routine device_write_inband( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in data : io_buf_ptr_inband_t; + out bytes_written : int + ); + +routine device_read( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in bytes_wanted : int; + out data : io_buf_ptr_t + ); + +routine device_read_inband( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in bytes_wanted : int; + out data : io_buf_ptr_inband_t + ); + +/* obsolete */ +routine xxx_device_set_status( + device : device_t; + in flavor : dev_flavor_t; + in status : dev_status_t, IsLong + ); + +/* obsolete */ +routine xxx_device_get_status( + device : device_t; + in flavor : dev_flavor_t; + out status : dev_status_t, IsLong + ); + +/* obsolete */ +routine xxx_device_set_filter( + device : device_t; + in receive_port : mach_port_send_t; + in priority : int; + in filter : filter_array_t, IsLong + ); + +routine device_map( + device : device_t; + in prot : vm_prot_t; + in offset : vm_offset_t; + in size : vm_size_t; + out pager : memory_object_t; + in unmap : int + ); + +routine device_set_status( + device : device_t; + in flavor : dev_flavor_t; + in status : dev_status_t + ); + +routine device_get_status( + device : device_t; + in flavor : dev_flavor_t; + out status : dev_status_t, CountInOut + ); + +routine device_set_filter( + device : device_t; + in receive_port : mach_port_send_t; + in priority : int; + in filter : filter_array_t + ); + +routine device_intr_notify( + master_port : mach_port_t; + in irq : int; + in id : int; + in receive_port : mach_port_send_t + ); + +/* + * Test whether IPC devices exist. + */ +routine pci_present( + master_port : mach_port_t); + +/* + * Find the specified PCI device. + */ +routine pci_find_device( + master_port : mach_port_t; + vendor : short; + device_id : short; + index : short; + out bus : char; + out device_fn : char); + +/* + * Read the configuration space of a IPC device. + */ +routine pci_read_config( + master_port : mach_port_t; + bus : char; + device_fn : char; + where : char; + bytes_wanted : int; + out result : pci_config_data_t); + +/* + * Write the configuration space of a IPC device. + */ +routine pci_write_config( + master_port : mach_port_t; + bus : char; + device_fn : char; + where : char; + data : pci_config_data_t); + +/* + * enable/disable the specified irq. + */ +routine device_irq_enable( + master_port : mach_port_t; + irq : int; + status : char); diff --git a/libddekit/include/Makefile b/libddekit/include/Makefile deleted file mode 100644 index 8d31023f..00000000 --- a/libddekit/include/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -PKGDIR ?= .. -L4DIR ?= $(PKGDIR)/../.. - -# All haeder files found in this directory tree will be automatically -# installed in a way that they can be included with -# #include later. -# No need to list them in this Makefile. - -include $(L4DIR)/mk/include.mk diff --git a/libddekit/include/ddekit/assert.h b/libddekit/include/ddekit/assert.h index 5d572b49..5d593662 100644 --- a/libddekit/include/ddekit/assert.h +++ b/libddekit/include/ddekit/assert.h @@ -1,8 +1,8 @@ #ifndef _ddekit_assert_h #define _ddekit_assert_h -#include -#include +#include "ddekit/printf.h" +#include "ddekit/panic.h" /** \file ddekit/assert.h */ diff --git a/libddekit/include/ddekit/condvar.h b/libddekit/include/ddekit/condvar.h index ba87358d..129a718d 100644 --- a/libddekit/include/ddekit/condvar.h +++ b/libddekit/include/ddekit/condvar.h @@ -2,6 +2,7 @@ #define _ddekit_condvar_h /** \file ddekit/condvar.h */ +#include "ddekit/lock.h" struct ddekit_condvar; typedef struct ddekit_condvar ddekit_condvar_t; diff --git a/libddekit/include/ddekit/initcall.h b/libddekit/include/ddekit/initcall.h deleted file mode 100644 index b503cc6a..00000000 --- a/libddekit/include/ddekit/initcall.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _ddekit_initcall_h -#define _ddekit_initcall_h - -// from l4/sys/compiler.h -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ >= 4 -#define L4_STICKY(x) __attribute__((used)) x -#else -#define L4_STICKY(x) __attribute__((unused)) x -#endif - -#define l4str(s) #s - -// from dde_linux/ARCH-x86/ctor.h -typedef void (*l4ddekit_initcall_t)(void); - -#define __l4ddekit_initcall(p) \ - __attribute__ ((__section__ (".l4dde_ctors." #p))) - -/** Define a function to be a DDEKit initcall. - * - * Define a function to be a DDEKit initcall. This function will then be placed - * in a separate linker section of the binary (called .l4dde_ctors). The L4Env - * construction mechanism will execute all constructors in this section during - * application startup. - * - * This is the right place to place Linux' module_init functions & Co. - * - * \param fn function - */ -#define DDEKIT_INITCALL(fn) DDEKIT_CTOR(fn, 1) - -#define DDEKIT_CTOR(fn, prio) \ - static l4ddekit_initcall_t \ - L4_STICKY(__l4ddekit_initcall_##fn) \ - __l4ddekit_initcall(prio) = (void *)fn - -/** - * Runs all registered initcalls. - */ -void ddekit_do_initcalls(void); - -#endif diff --git a/libddekit/include/ddekit/thread.h b/libddekit/include/ddekit/thread.h index 6e505818..8ed52013 100644 --- a/libddekit/include/ddekit/thread.h +++ b/libddekit/include/ddekit/thread.h @@ -3,6 +3,8 @@ /** \defgroup DDEKit_threads */ +#include "ddekit/lock.h" + struct ddekit_thread; typedef struct ddekit_thread ddekit_thread_t; diff --git a/libddekit/init.c b/libddekit/init.c index 6bc9d8ff..9114ff46 100644 --- a/libddekit/init.c +++ b/libddekit/init.c @@ -9,8 +9,11 @@ void ddekit_init(void) { extern void linux_kmem_init (); extern int log_init (); + extern void interrupt_init (); + ddekit_init_threads(); linux_kmem_init (); log_init (); + interrupt_init (); } diff --git a/libddekit/initcall.c b/libddekit/initcall.c deleted file mode 100644 index 49e1fec1..00000000 --- a/libddekit/initcall.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#include - -void ddekit_do_initcalls() { - crt0_dde_construction(); -} - diff --git a/libddekit/interrupt.c b/libddekit/interrupt.c index 6a8b3fd8..5a778f9b 100644 --- a/libddekit/interrupt.c +++ b/libddekit/interrupt.c @@ -8,9 +8,17 @@ * FIXME use consume flag to indicate IRQ was handled */ +#include +#include +#include +#include + #include "ddekit/interrupt.h" +#include "ddekit/semaphore.h" +#include "ddekit/printf.h" +#include "ddekit/memory.h" -#include +#include "device_U.h" #define DEBUG_INTERRUPTS 0 @@ -18,6 +26,15 @@ #define BLOCK_IRQ 0 +#define MACH_NOTIFY_IRQ 100 + +typedef struct +{ + mach_msg_header_t irq_header; + mach_msg_type_t irq_type; + int irq; +} mach_irq_notification_t; + /* * Internal type for interrupt loop parameters */ @@ -35,19 +52,14 @@ struct intloop_params static struct { - int handle_irq; /* nested irq disable count */ - ddekit_lock_t *irqlock; + int handle_irq; /* nested irq disable count */ + ddekit_lock_t irqlock; ddekit_thread_t *irq_thread; /* thread ID for detaching from IRQ later on */ boolean_t thread_exit; thread_t mach_thread; } ddekit_irq_ctrl[MAX_INTERRUPTS]; - -static void ddekit_irq_exit_fn(l4thread_t thread, void *data) -{ - // TODO we can remove the port for delivery of interrupt explicitly, - // though it cannot cause any harm even if we don't remove it. -} +static mach_port_t master_device; /** * Interrupt service loop @@ -57,26 +69,25 @@ static void intloop(void *arg) { kern_return_t ret; struct intloop_params *params = arg; - mach_port_t delivery_port; + mach_port_t delivery_port = mach_reply_port (); int my_index; my_index = params->irq; - ddekit_irq_ctrl[my_index]->mach_thread = mach_thread_self (); + ddekit_irq_ctrl[my_index].mach_thread = mach_thread_self (); ret = thread_priority (mach_thread_self (), DDEKIT_IRQ_PRIO, 0); if (ret) error (0, ret, "thread_priority"); // TODO I should give another parameter to show whether // the interrupt can be shared. - ret = device_intr_notify (master_device, dev->irq, - dev->dev_id, delivery_port, + ret = device_intr_notify (master_device, params->irq, + 0, delivery_port, MACH_MSG_TYPE_MAKE_SEND); if (!ret) { /* inform thread creator of error */ /* XXX does omega0 error code have any meaning to DDEKit users? */ params->start_err = ret; ddekit_sem_up(params->started); - return NULL; } #if 0 @@ -104,23 +115,25 @@ static void intloop(void *arg) /* It's an interrupt not for us. It shouldn't happen. */ if (irq_header->irq != params->irq) { - LOG("We get interrupt %d, %d is expected", - irq_header->irq, params->irq); + ddekit_printf ("We get interrupt %d, %d is expected", + irq_header->irq, params->irq); return 1; } /* only call registered handler function, if IRQ is not disabled */ ddekit_lock_lock (&ddekit_irq_ctrl[my_index].irqlock); if (ddekit_irq_ctrl[my_index].handle_irq > 0) { - LOGd(DEBUG_INTERRUPTS, "IRQ %x, handler %p", my_index,params->handler); + ddekit_printf ("IRQ %x, handler %p", + my_index,params->handler); params->handler(params->priv); } else - LOGd(DEBUG_INTERRUPTS, "not handling IRQ %x, because it is disabled.", my_index); + ddekit_printf ("not handling IRQ %x, because it is disabled.", + my_index); // ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY; - if (ddekit_irq_ctrl[irq].thread_exit) { + if (ddekit_irq_ctrl[my_index].thread_exit) { ddekit_lock_unlock (&ddekit_irq_ctrl[my_index].irqlock); ddekit_thread_exit(); return 1; @@ -129,7 +142,7 @@ static void intloop(void *arg) return 1; } - mach_msg_server (int_server, 0, delivery_port); + mach_msg_server (irq_server, 0, delivery_port); } @@ -238,3 +251,13 @@ void ddekit_interrupt_enable(int irq) ddekit_lock_unlock (&ddekit_irq_ctrl[irq].irqlock); } } + +void interrupt_init () +{ + + error_t err; + + err = get_privileged_ports (0, &master_device); + if (err) + error (1, err, "get_privileged_ports"); +} diff --git a/libddekit/kmem.c b/libddekit/kmem.c index 4769190e..2e6f7340 100644 --- a/libddekit/kmem.c +++ b/libddekit/kmem.c @@ -28,9 +28,12 @@ #include #include -#include "util.h" #include "vm_param.h" +#include "ddekit/panic.h" + +#define debug ddekit_debug + extern int printf (const char *, ...); /* Amount of memory to reserve for Linux memory allocator. diff --git a/libddekit/list.c b/libddekit/list.c index 992ea9ad..4f163584 100644 --- a/libddekit/list.c +++ b/libddekit/list.c @@ -48,7 +48,7 @@ struct list *remove_entry_head (struct list *head) { struct list *entry = head->next; - if (EMPTY_ENTRY (entry)) + if (EMPTY_LIST (entry)) return NULL; remove_entry (entry); @@ -59,7 +59,7 @@ struct list *remove_entry_end (struct list *head) { struct list *entry = head->prev; - if (EMPTY_ENTRY (entry)) + if (EMPTY_LIST (entry)) return NULL; remove_entry (entry); diff --git a/libddekit/lock.c b/libddekit/lock.c index bf643e65..4c4cff01 100644 --- a/libddekit/lock.c +++ b/libddekit/lock.c @@ -1,6 +1,7 @@ #include #include "ddekit/lock.h" +#include "ddekit/memory.h" #define DDEKIT_DEBUG_LOCKS 0 @@ -48,6 +49,6 @@ int _ddekit_lock_owner(struct ddekit_lock **mtx) { /* The return value is the address of the holder. * I hope it will be OK. At least, it is OK * for the current implementation of DDE Linux/BSD */ - return (int) (*mtx)->holder; + return (int) (*mtx)->helder; } diff --git a/libddekit/mach.defs b/libddekit/mach.defs new file mode 100644 index 00000000..764bd451 --- /dev/null +++ b/libddekit/mach.defs @@ -0,0 +1,779 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University. + * Copyright (c) 1993,1994 The University of Utah and + * the Computer Systems Laboratory (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF + * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY + * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF + * THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Matchmaker definitions file for Mach kernel interface. + */ + +#ifdef MACH_KERNEL +simport ; /* for obsolete routines */ +#endif /* MACH_KERNEL */ + +subsystem +#if KERNEL_USER + KernelUser +#endif /* KERNEL_USER */ +#if KERNEL_SERVER + KernelServer +#endif /* KERNEL_SERVER */ + mach 2000; + +#ifdef KERNEL_USER +userprefix r_; +#endif /* KERNEL_USER */ + +#include +#include + +skip; /* old port_allocate */ +skip; /* old port_deallocate */ +skip; /* old port_enable */ +skip; /* old port_disable */ +skip; /* old port_select */ +skip; /* old port_set_backlog */ +skip; /* old port_status */ + +/* + * Create a new task with an empty set of IPC rights, + * and having an address space constructed from the + * target task (or empty, if inherit_memory is FALSE). + */ +routine task_create( + target_task : task_t; + inherit_memory : boolean_t; + out child_task : task_t); + +/* + * Destroy the target task, causing all of its threads + * to be destroyed, all of its IPC rights to be deallocated, + * and all of its address space to be deallocated. + */ +routine task_terminate( + target_task : task_t); + +/* + * Get user-level handler entry points for all + * emulated system calls. + */ +routine task_get_emulation_vector( + task : task_t; + out vector_start : int; + out emulation_vector: emulation_vector_t); + +/* + * Establish user-level handlers for the specified + * system calls. Non-emulated system calls are specified + * with emulation_vector[i] == EML_ROUTINE_NULL. + */ +routine task_set_emulation_vector( + task : task_t; + vector_start : int; + emulation_vector: emulation_vector_t); + + +/* + * Returns the set of threads belonging to the target task. + */ +routine task_threads( + target_task : task_t; + out thread_list : thread_array_t); + +/* + * Returns information about the target task. + */ +routine task_info( + target_task : task_t; + flavor : int; + out task_info_out : task_info_t, CountInOut); + + +skip; /* old task_status */ +skip; /* old task_set_notify */ +skip; /* old thread_create */ + +/* + * Destroy the target thread. + */ +routine thread_terminate( + target_thread : thread_t); + +/* + * Return the selected state information for the target + * thread. If the thread is currently executing, the results + * may be stale. [Flavor THREAD_STATE_FLAVOR_LIST provides a + * list of valid flavors for the target thread.] + */ +routine thread_get_state( + target_thread : thread_t; + flavor : int; + out old_state : thread_state_t, CountInOut); + +/* + * Set the selected state information for the target thread. + * If the thread is currently executing, the state change + * may be ill-defined. + */ +routine thread_set_state( + target_thread : thread_t; + flavor : int; + new_state : thread_state_t); + +/* + * Returns information about the target thread. + */ +routine thread_info( + target_thread : thread_t; + flavor : int; + out thread_info_out : thread_info_t, CountInOut); + +skip; /* old thread_mutate */ + +/* + * Allocate zero-filled memory in the address space + * of the target task, either at the specified address, + * or wherever space can be found (if anywhere is TRUE), + * of the specified size. The address at which the + * allocation actually took place is returned. + */ +#ifdef EMULATOR +skip; /* the emulator redefines vm_allocate using vm_map */ +#else /* EMULATOR */ +routine vm_allocate( + target_task : vm_task_t; + inout address : vm_address_t; + size : vm_size_t; + anywhere : boolean_t); +#endif /* EMULATOR */ + +skip; /* old vm_allocate_with_pager */ + +/* + * Deallocate the specified range from the virtual + * address space of the target task. + */ +routine vm_deallocate( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t); + +/* + * Set the current or maximum protection attribute + * for the specified range of the virtual address + * space of the target task. The current protection + * limits the memory access rights of threads within + * the task; the maximum protection limits the accesses + * that may be given in the current protection. + * Protections are specified as a set of {read, write, execute} + * *permissions*. + */ +routine vm_protect( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + set_maximum : boolean_t; + new_protection : vm_prot_t); + +/* + * Set the inheritance attribute for the specified range + * of the virtual address space of the target task. + * The inheritance value is one of {none, copy, share}, and + * specifies how the child address space should acquire + * this memory at the time of a task_create call. + */ +routine vm_inherit( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + new_inheritance : vm_inherit_t); + +/* + * Returns the contents of the specified range of the + * virtual address space of the target task. [The + * range must be aligned on a virtual page boundary, + * and must be a multiple of pages in extent. The + * protection on the specified range must permit reading.] + */ +routine vm_read( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + out data : pointer_t); + +/* + * Writes the contents of the specified range of the + * virtual address space of the target task. [The + * range must be aligned on a virtual page boundary, + * and must be a multiple of pages in extent. The + * protection on the specified range must permit writing.] + */ +routine vm_write( + target_task : vm_task_t; + address : vm_address_t; + data : pointer_t); + +/* + * Copy the contents of the source range of the virtual + * address space of the target task to the destination + * range in that same address space. [Both of the + * ranges must be aligned on a virtual page boundary, + * and must be multiples of pages in extent. The + * protection on the source range must permit reading, + * and the protection on the destination range must + * permit writing.] + */ +routine vm_copy( + target_task : vm_task_t; + source_address : vm_address_t; + size : vm_size_t; + dest_address : vm_address_t); + +/* + * Returns information about the contents of the virtual + * address space of the target task at the specified + * address. The returned protection, inheritance, sharing + * and memory object values apply to the entire range described + * by the address range returned; the memory object offset + * corresponds to the beginning of the address range. + * [If the specified address is not allocated, the next + * highest address range is described. If no addresses beyond + * the one specified are allocated, the call returns KERN_NO_SPACE.] + */ +routine vm_region( + target_task : vm_task_t; + inout address : vm_address_t; + out size : vm_size_t; + out protection : vm_prot_t; + out max_protection : vm_prot_t; + out inheritance : vm_inherit_t; + out is_shared : boolean_t; + /* avoid out-translation of the argument */ + out object_name : memory_object_name_t = + MACH_MSG_TYPE_MOVE_SEND + ctype: mach_port_t; + out offset : vm_offset_t); + +/* + * Return virtual memory statistics for the host + * on which the target task resides. [Note that the + * statistics are not specific to the target task.] + */ +routine vm_statistics( + target_task : vm_task_t; + out vm_stats : vm_statistics_data_t); + +skip; /* old task_by_u*x_pid */ +skip; /* old vm_pageable */ + +/* + * Stash a handful of ports for the target task; child + * tasks inherit this stash at task_create time. + */ +routine mach_ports_register( + target_task : task_t; + init_port_set : mach_port_array_t = + ^array[] of mach_port_t); + +/* + * Retrieve the stashed ports for the target task. + */ +routine mach_ports_lookup( + target_task : task_t; + out init_port_set : mach_port_array_t = + ^array[] of mach_port_t); + +skip; /* old u*x_pid */ +skip; /* old netipc_listen */ +skip; /* old netipc_ignore */ + +/* + * Provide the data contents of a range of the given memory + * object, with the access restriction specified. [Only + * whole virtual pages of data can be accepted; partial pages + * will be discarded. Data should be provided on request, but + * may be provided in advance as desired. When data already + * held by this kernel is provided again, the new data is ignored. + * The access restriction is the subset of {read, write, execute} + * which are prohibited. The kernel may not provide any data (or + * protection) consistency among pages with different virtual page + * alignments within the same object.] + */ +simpleroutine memory_object_data_provided( + memory_control : memory_object_control_t; + offset : vm_offset_t; + data : pointer_t; + lock_value : vm_prot_t); + +/* + * Indicate that a range of the given temporary memory object does + * not exist, and that the backing memory object should be used + * instead (or zero-fill memory be used, if no backing object exists). + * [This call is intended for use only by the default memory manager. + * It should not be used to indicate a real error -- + * memory_object_data_error should be used for that purpose.] + */ +simpleroutine memory_object_data_unavailable( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t); + +/* + * Retrieves the attributes currently associated with + * a memory object. + */ +routine memory_object_get_attributes( + memory_control : memory_object_control_t; + out object_ready : boolean_t; + out may_cache : boolean_t; + out copy_strategy : memory_object_copy_strategy_t); + +/* + * Sets the default memory manager, the port to which + * newly-created temporary memory objects are delivered. + * [See (memory_object_default)memory_object_create.] + * The old memory manager port is returned. + */ +routine vm_set_default_memory_manager( + host_priv : host_priv_t; + inout default_manager : mach_port_make_send_t); + +skip; /* old pager_flush_request */ + +/* + * Control use of the data associated with the given + * memory object. For each page in the given range, + * perform the following operations, in order: + * 1) restrict access to the page (disallow + * forms specified by "prot"); + * 2) write back modifications (if "should_return" + * is RETURN_DIRTY and the page is dirty, or + * "should_return" is RETURN_ALL and the page + * is either dirty or precious); and, + * 3) flush the cached copy (if "should_flush" + * is asserted). + * The set of pages is defined by a starting offset + * ("offset") and size ("size"). Only pages with the + * same page alignment as the starting offset are + * considered. + * + * A single acknowledgement is sent (to the "reply_to" + * port) when these actions are complete. + * + * There are two versions of this routine because IPC distinguishes + * between booleans and integers (a 2-valued integer is NOT a + * boolean). The new routine is backwards compatible at the C + * language interface. + */ +simpleroutine xxx_memory_object_lock_request( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t; + should_clean : boolean_t; + should_flush : boolean_t; + lock_value : vm_prot_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + + +simpleroutine memory_object_lock_request( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t; + should_return : memory_object_return_t; + should_flush : boolean_t; + lock_value : vm_prot_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + +/* obsolete */ +routine xxx_task_get_emulation_vector( + task : task_t; + out vector_start : int; + out emulation_vector: xxx_emulation_vector_t, IsLong); + +/* obsolete */ +routine xxx_task_set_emulation_vector( + task : task_t; + vector_start : int; + emulation_vector: xxx_emulation_vector_t, IsLong); + +/* + * Returns information about the host on which the + * target object resides. [This object may be + * a task, thread, or memory_object_control port.] + */ +routine xxx_host_info( + target_task : mach_port_t; + out info : machine_info_data_t); + +/* + * Returns information about a particular processor on + * the host on which the target task resides. + */ +routine xxx_slot_info( + target_task : task_t; + slot : int; + out info : machine_slot_data_t); + +/* + * Performs control operations (currently only + * turning off or on) on a particular processor on + * the host on which the target task resides. + */ +routine xxx_cpu_control( + target_task : task_t; + cpu : int; + running : boolean_t); + +skip; /* old thread_statistics */ +skip; /* old task_statistics */ +skip; /* old netport_init */ +skip; /* old netport_enter */ +skip; /* old netport_remove */ +skip; /* old thread_set_priority */ + +/* + * Increment the suspend count for the target task. + * No threads within a task may run when the suspend + * count for that task is non-zero. + */ +routine task_suspend( + target_task : task_t); + +/* + * Decrement the suspend count for the target task, + * if the count is currently non-zero. If the resulting + * suspend count is zero, then threads within the task + * that also have non-zero suspend counts may execute. + */ +routine task_resume( + target_task : task_t); + +/* + * Returns the current value of the selected special port + * associated with the target task. + */ +routine task_get_special_port( + task : task_t; + which_port : int; + out special_port : mach_port_t); + +/* + * Set one of the special ports associated with the + * target task. + */ +routine task_set_special_port( + task : task_t; + which_port : int; + special_port : mach_port_t); + +/* obsolete */ +routine xxx_task_info( + target_task : task_t; + flavor : int; + out task_info_out : task_info_t, IsLong); + + +/* + * Create a new thread within the target task, returning + * the port representing that new thread. The + * initial execution state of the thread is undefined. + */ +routine thread_create( + parent_task : task_t; + out child_thread : thread_t); + +/* + * Increment the suspend count for the target thread. + * Once this call has completed, the thread will not + * execute any further user or meta- instructions. + * Once suspended, a thread may not execute again until + * its suspend count is zero, and the suspend count + * for its task is also zero. + */ +routine thread_suspend( + target_thread : thread_t); + +/* + * Decrement the suspend count for the target thread, + * if that count is not already zero. + */ +routine thread_resume( + target_thread : thread_t); + +/* + * Cause any user or meta- instructions currently being + * executed by the target thread to be aborted. [Meta- + * instructions consist of the basic traps for IPC + * (e.g., msg_send, msg_receive) and self-identification + * (e.g., task_self, thread_self, thread_reply). Calls + * described by MiG interfaces are not meta-instructions + * themselves.] + */ +routine thread_abort( + target_thread : thread_t); + +/* obsolete */ +routine xxx_thread_get_state( + target_thread : thread_t; + flavor : int; + out old_state : thread_state_t, IsLong); + +/* obsolete */ +routine xxx_thread_set_state( + target_thread : thread_t; + flavor : int; + new_state : thread_state_t, IsLong); + +/* + * Returns the current value of the selected special port + * associated with the target thread. + */ +routine thread_get_special_port( + thread : thread_t; + which_port : int; + out special_port : mach_port_t); + +/* + * Set one of the special ports associated with the + * target thread. + */ +routine thread_set_special_port( + thread : thread_t; + which_port : int; + special_port : mach_port_t); + +/* obsolete */ +routine xxx_thread_info( + target_thread : thread_t; + flavor : int; + out thread_info_out : thread_info_t, IsLong); + +/* + * Establish a user-level handler for the specified + * system call. + */ +routine task_set_emulation( + target_port : task_t; + routine_entry_pt: vm_address_t; + routine_number : int); + +/* + * Establish restart pc for interrupted atomic sequences. + * This reuses the message number for the old task_get_io_port. + * See task_info.h for description of flavors. + * + */ +routine task_ras_control( + target_task : task_t; + basepc : vm_address_t; + boundspc : vm_address_t; + flavor : int); + + + +skip; /* old host_ipc_statistics */ +skip; /* old port_names */ +skip; /* old port_type */ +skip; /* old port_rename */ +skip; /* old port_allocate */ +skip; /* old port_deallocate */ +skip; /* old port_set_backlog */ +skip; /* old port_status */ +skip; /* old port_set_allocate */ +skip; /* old port_set_deallocate */ +skip; /* old port_set_add */ +skip; /* old port_set_remove */ +skip; /* old port_set_status */ +skip; /* old port_insert_send */ +skip; /* old port_extract_send */ +skip; /* old port_insert_receive */ +skip; /* old port_extract_receive */ + +/* + * Map a user-defined memory object into the virtual address + * space of the target task. If desired (anywhere is TRUE), + * the kernel will find a suitable address range of the + * specified size; else, the specific address will be allocated. + * + * The beginning address of the range will be aligned on a virtual + * page boundary, be at or beyond the address specified, and + * meet the mask requirements (bits turned on in the mask must not + * be turned on in the result); the size of the range, in bytes, + * will be rounded up to an integral number of virtual pages. + * + * The memory in the resulting range will be associated with the + * specified memory object, with the beginning of the memory range + * referring to the specified offset into the memory object. + * + * The mapping will take the current and maximum protections and + * the inheritance attributes specified; see the vm_protect and + * vm_inherit calls for a description of these attributes. + * + * If desired (copy is TRUE), the memory range will be filled + * with a copy of the data from the memory object; this copy will + * be private to this mapping in this target task. Otherwise, + * the memory in this mapping will be shared with other mappings + * of the same memory object at the same offset (in this task or + * in other tasks). [The Mach kernel only enforces shared memory + * consistency among mappings on one host with similar page alignments. + * The user-defined memory manager for this object is responsible + * for further consistency.] + */ +#ifdef EMULATOR +routine htg_vm_map( + target_task : vm_task_t; + ureplyport reply_port : mach_port_make_send_once_t; + inout address : vm_address_t; + size : vm_size_t; + mask : vm_address_t; + anywhere : boolean_t; + memory_object : memory_object_t; + offset : vm_offset_t; + copy : boolean_t; + cur_protection : vm_prot_t; + max_protection : vm_prot_t; + inheritance : vm_inherit_t); +#else /* EMULATOR */ +routine vm_map( + target_task : vm_task_t; + inout address : vm_address_t; + size : vm_size_t; + mask : vm_address_t; + anywhere : boolean_t; + memory_object : memory_object_t; + offset : vm_offset_t; + copy : boolean_t; + cur_protection : vm_prot_t; + max_protection : vm_prot_t; + inheritance : vm_inherit_t); +#endif /* EMULATOR */ + +/* + * Indicate that a range of the specified memory object cannot + * be provided at this time. [Threads waiting for memory pages + * specified by this call will experience a memory exception. + * Only threads waiting at the time of the call are affected.] + */ +simpleroutine memory_object_data_error( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t; + error_value : kern_return_t); + +/* + * Make decisions regarding the use of the specified + * memory object. + */ +simpleroutine memory_object_set_attributes( + memory_control : memory_object_control_t; + object_ready : boolean_t; + may_cache : boolean_t; + copy_strategy : memory_object_copy_strategy_t); + +/* + */ +simpleroutine memory_object_destroy( + memory_control : memory_object_control_t; + reason : kern_return_t); + +/* + * Provide the data contents of a range of the given memory + * object, with the access restriction specified, optional + * precious attribute, and reply message. [Only + * whole virtual pages of data can be accepted; partial pages + * will be discarded. Data should be provided on request, but + * may be provided in advance as desired. When data already + * held by this kernel is provided again, the new data is ignored. + * The access restriction is the subset of {read, write, execute} + * which are prohibited. The kernel may not provide any data (or + * protection) consistency among pages with different virtual page + * alignments within the same object. The precious value controls + * how the kernel treats the data. If it is FALSE, the kernel treats + * its copy as a temporary and may throw it away if it hasn't been + * changed. If the precious value is TRUE, the kernel treats its + * copy as a data repository and promises to return it to the manager; + * the manager may tell the kernel to throw it away instead by flushing + * and not cleaning the data -- see memory_object_lock_request. The + * reply_to port is for a compeletion message; it will be + * memory_object_supply_completed.] + */ + +simpleroutine memory_object_data_supply( + memory_control : memory_object_control_t; + offset : vm_offset_t; + data : pointer_t, Dealloc[]; + lock_value : vm_prot_t; + precious : boolean_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + +simpleroutine memory_object_ready( + memory_control : memory_object_control_t; + may_cache : boolean_t; + copy_strategy : memory_object_copy_strategy_t); + +simpleroutine memory_object_change_attributes( + memory_control : memory_object_control_t; + may_cache : boolean_t; + copy_strategy : memory_object_copy_strategy_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + +skip; /* old host_callout_statistics_reset */ +skip; /* old port_set_select */ +skip; /* old port_set_backup */ + +/* + * Set/Get special properties of memory associated + * to some virtual address range, such as cachability, + * migrability, replicability. Machine-dependent. + */ +routine vm_machine_attribute( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + attribute : vm_machine_attribute_t; + inout value : vm_machine_attribute_val_t); + +/*skip;*/ /* old host_fpa_counters_reset */ + +/* + * This routine is created for allocating DMA buffers. + * We are going to get a contiguous physical memory + * and its physical address in addition to the virtual address. + */ +routine vm_dma_buff_alloc( + host_priv : host_priv_t; + target_task : vm_task_t; + size : vm_size_t; + out vaddr : vm_address_t; + out paddr : vm_address_t); + +/* + * There is no more room in this interface for additional calls. + */ diff --git a/libddekit/malloc.c b/libddekit/malloc.c index c3735bdb..a30cd7b7 100644 --- a/libddekit/malloc.c +++ b/libddekit/malloc.c @@ -29,6 +29,9 @@ * * Each chunk stores its size in the first word for free() to work. */ + +#include + void *ddekit_simple_malloc(unsigned size) { return malloc (size); diff --git a/libddekit/memory.c b/libddekit/memory.c index 93853e55..27be4eeb 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -11,8 +11,10 @@ */ #include "ddekit/memory.h" +#include "ddekit/panic.h" extern void * linux_kmalloc (unsigned int size, int priority); +extern void linux_kfree (void *p); /**************** @@ -110,6 +112,7 @@ void *ddekit_slab_get_data(struct ddekit_slab * slab) #if 0 return l4slab_get_data(&slab->cache); #endif + return NULL; } @@ -154,7 +157,7 @@ struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) */ void ddekit_large_free(void *objp) { - return linux_kfree (objp); + linux_kfree (objp); } diff --git a/libddekit/pci.c b/libddekit/pci.c index 32e02b84..5c3f4ef6 100644 --- a/libddekit/pci.c +++ b/libddekit/pci.c @@ -1,4 +1,8 @@ +#include #include + +#include "ddekit/assert.h" +#include "ddekit/printf.h" #include "ddekit/pci.h" #include "config.h" @@ -43,8 +47,8 @@ void ddekit_pci_init(void) dev_iter = pci_slot_match_iterator_create (NULL); while ((pci_dev = pci_device_next (dev_iter)) != NULL) { if (slots_found == MAX_PCI_DEVS) { - LOGd(dbg_this, "find more than %d pci devices", - slots_found); + ddekit_printf ("find more than %d pci devices", + slots_found); break; } /* Pretend all our devices are chained to exactly one bus. */ @@ -68,7 +72,7 @@ int ddekit_pci_get_device(int nr, int *bus, int *slot, int *func) { ddekit_pci_dev_t *dev; - LOGd(dbg_this, "searching for dev #%d", nr); + ddekit_printf ("searching for dev #%d", nr); if (nr >= 0 && nr < MAX_PCI_DEVS && !invalid_device(&ddekit_pci_bus[nr])) { dev = &ddekit_pci_bus[nr]; @@ -89,7 +93,8 @@ ddekit_pci_dev_t *ddekit_pci_find_device(int *bus, int *slot, int *func, Assert(slot); Assert(func); - LOGd(dbg_this, "start %p (slot %d)", start, start ? start->slot : -1); + ddekit_printf ("start %p (slot %d)", + start, start ? start->slot : -1); int idx = start ? start->slot + 1 : 0; for ( ; idx < MAX_PCI_DEVS; ++idx) { @@ -214,7 +219,8 @@ int ddekit_pci_writel(int bus, int slot, int func, int pos, ddekit_uint32_t val int ddekit_pci_enable_device(struct ddekit_pci_dev *dev) { - return pci_device_enable (dev->dev); + pci_device_enable (dev->dev); + return 0; } int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) @@ -238,7 +244,7 @@ int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) { - return dev->dev.vendor_id; + return dev->dev->vendor_id; } @@ -251,7 +257,7 @@ unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) { - return dev->dev.device_id; + return dev->dev->device_id; } @@ -264,7 +270,7 @@ unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) { - return dev->dev.subvendor_id; + return dev->dev->subvendor_id; } @@ -277,7 +283,7 @@ unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) { - return dev->dev.subdevice_id; + return dev->dev->subdevice_id; } @@ -290,7 +296,7 @@ unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) */ unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) { - return dev->dev.device_class; + return dev->dev->device_class; } @@ -303,7 +309,7 @@ unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) */ unsigned long ddekit_pci_get_irq(struct ddekit_pci_dev *dev) { - return dev->dev.irq; + return dev->dev->irq; } @@ -345,10 +351,11 @@ char *ddekit_pci_get_slot_name(struct ddekit_pci_dev *dev) */ ddekit_pci_res_t *ddekit_pci_get_resource(struct ddekit_pci_dev *dev, unsigned int idx) { - if (idx > L4IO_PCIDEV_RES) + // TODO +// if (idx > L4IO_PCIDEV_RES) return NULL; - //TODO return (ddekit_pci_res_t *)(&(dev->l4dev.res[idx])); +// return (ddekit_pci_res_t *)(&(dev->l4dev.res[idx])); } diff --git a/libddekit/printf.c b/libddekit/printf.c index bbd58863..72ff5003 100644 --- a/libddekit/printf.c +++ b/libddekit/printf.c @@ -4,7 +4,10 @@ * \date 2006-03-01 */ +#include +#include #include +#include #include #include "ddekit/printf.h" diff --git a/libddekit/thread.c b/libddekit/thread.c index a095db2f..081a4742 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -3,14 +3,18 @@ #include #include #include +#include +#include +#include +#include "ddekit/memory.h" #include "ddekit/semaphore.h" #include "list.h" #include "ddekit/thread.h" #define DDEKIT_THREAD_STACK_SIZE 0x2000 /* 8 KB */ -static struct ddekit_slab *ddekit_stack_slab = NULL; +//static struct ddekit_slab *ddekit_stack_slab = NULL; struct _ddekit_private_data { struct list list; @@ -18,8 +22,7 @@ struct _ddekit_private_data { /* point to the thread who has the private data. */ struct ddekit_thread *thread; mach_msg_header_t wakeupmsg; - -} +}; struct ddekit_thread { struct cthread thread; @@ -64,20 +67,20 @@ static error_t _create_wakeupmsg (struct _ddekit_private_data *data) return 0; } -static void setup_thread (cthread_t *t, const char *name) { +static void setup_thread (struct ddekit_thread *t, const char *name) { error_t err; struct _ddekit_private_data *private_data; if (name) { - const char *cpy = NULL; + char *cpy = NULL; - cpy = malloc (strlen (name) + 1); + cpy = ddekit_simple_malloc (strlen (name) + 1); if (cpy == NULL) error (0, 0, "fail to allocate memory"); else strcpy (cpy, name); - cthread_set_name (t, name); + cthread_set_name (&t->thread, name); } /* @@ -92,20 +95,21 @@ static void setup_thread (cthread_t *t, const char *name) { private_data->sleep_cond = condition_alloc (); condition_init (private_data->sleep_cond); - private_data->list = {&private_data->list, &private_data->list}; + private_data->list.prev = &private_data->list; + private_data->list.next = &private_data->list; private_data->thread = t; err = _create_wakeupmsg (private_data); - // TODO I need to change this. - assert_perror (err); + if (err) + error (1, err, "_create_wakeupmsg"); - cthread_set_ldata (t, private_data); + cthread_set_ldata (&t->thread, private_data); } ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { ddekit_thread_t *td = ddekit_thread_myself(); - setup_thread (&td->thread, name); + setup_thread (td, name); return td; } @@ -116,7 +120,7 @@ ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char // before initialization is completed. td = (ddekit_thread_t *) cthread_fork (fun, arg); cthread_detach (&td->thread); - setup_thread (&td->thread, name); + setup_thread (td, name); return td; } @@ -180,7 +184,7 @@ void ddekit_thread_sleep(ddekit_lock_t *lock) { // TODO condition_wait cannot guarantee that the thread is // woke up by another thread, maybe by signals. // Does it matter here? - condition_wait (data->sleep_cond, lock); + condition_wait (data->sleep_cond, (struct mutex *) *lock); } void dekit_thread_wakeup(ddekit_thread_t *td) { @@ -205,7 +209,7 @@ void ddekit_thread_exit() { name = cthread_name (t); cthread_set_name (t, NULL); - free (name); + ddekit_simple_free ((char *) name); cthread_exit (0); } @@ -225,10 +229,18 @@ void ddekit_yield(void) } void ddekit_init_threads() { + char *str = "main"; + char *name = ddekit_simple_malloc (strlen (str) + 1); + + strcpy (name, str); // TODO maybe the name has already been set. - cthread_set_name (cthread_self (), "main"); + cthread_set_name (cthread_self (), name); } +/********************************************************************** + * semaphore + **********************************************************************/ + /* Block THREAD. */ static error_t _timedblock (struct _ddekit_private_data *data, const struct timespec *abstime) @@ -281,16 +293,16 @@ static void _block (struct _ddekit_private_data *data) assert_perror (err); } -static int _sem_timedwait_internal (sem_t *restrict sem, +static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, const struct timespec *restrict timeout) { - struct ddekit_private_data *self_private_data; + struct _ddekit_private_data *self_private_data; spin_lock (&sem->lock); if (sem->value > 0) { /* Successful down. */ sem->value --; - spin_unlock (&sem->__lock); + spin_unlock (&sem->lock); return 0; } @@ -350,13 +362,14 @@ ddekit_sem_t *ddekit_sem_init(int value) { (ddekit_sem_t *) ddekit_simple_malloc (sizeof (*sem)); sem->lock = SPIN_LOCK_INITIALIZER; - sem->head = {&sem->head, &sem->head}; + sem->head.prev = &sem->head; + sem->head.next = &sem->head; sem->value = value; return sem; } void ddekit_sem_deinit(ddekit_sem_t *sem) { - if (!EMPTY_ENTRY (&sem->head)) { + if (!EMPTY_LIST (&sem->head)) { error (0, EBUSY, "ddekit_sem_deinit"); } else @@ -388,11 +401,11 @@ int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) { timeout.tv_sec = timo / 1000; timeout.tv_nsec = (timo % 1000) * 1000 * 1000; - return __sem_timedwait_internal (sem, &timeout); + return _sem_timedwait_internal (sem, &timeout); } void ddekit_sem_up(ddekit_sem_t *sem) { - struct _ddekit_thread_data *wakeup; + struct _ddekit_private_data *wakeup; spin_lock (&sem->lock); if (sem->value > 0) { @@ -400,26 +413,25 @@ void ddekit_sem_up(ddekit_sem_t *sem) { assert (EMPTY_LIST (&sem->head)); sem->value ++; spin_unlock (&sem->lock); - return 0; + return; } if (EMPTY_LIST (&sem->head)) { /* No one waiting. */ sem->value = 1; spin_unlock (&sem->lock); - return 0; + return; } /* Wake someone up. */ /* First dequeue someone. */ - wakeup = (struct _ddekit_private_data *) remove_entry_end (&sem->head); + wakeup = LIST_ENTRY (remove_entry_end (&sem->head), + struct _ddekit_private_data, list); /* Then drop the lock and transfer control. */ spin_unlock (&sem->lock); if (wakeup) _thread_wakeup (wakeup); - - return 0; } diff --git a/libddekit/timer.c b/libddekit/timer.c index d0a6ccc0..f8bfc7a1 100644 --- a/libddekit/timer.c +++ b/libddekit/timer.c @@ -2,6 +2,9 @@ #include #include +#include "ddekit/memory.h" +#include "ddekit/assert.h" +#include "ddekit/semaphore.h" #include "ddekit/timer.h" #define __DEBUG 0 @@ -118,7 +121,7 @@ int ddekit_add_timer(void (*fn)(void *), void *args, unsigned long timeout) * necessary to notify the timer thread. */ if (t == timer_list) { - Assert(!l4_is_nil_id(timer_thread)); + Assert(timer_thread); __notify_timer_thread(); } @@ -329,6 +332,6 @@ void ddekit_init_timers(void) root_jiffies = (long long) tp.tv_sec * HZ + ((long long) tp.tv_usec * HZ) / 1000000; - timer_thread = cthread_fork ((cthread_fn_t) timer_function, 0); + timer_thread = cthread_fork ((cthread_fn_t) ddekit_timer_thread, 0); cthread_detach (timer_thread); } diff --git a/libddekit/vm_param.h b/libddekit/vm_param.h new file mode 100644 index 00000000..7b615c8a --- /dev/null +++ b/libddekit/vm_param.h @@ -0,0 +1,7 @@ +#ifndef __VM_PARAM_H__ +#define __VM_PARAM_H__ + +#define PAGE_SIZE __vm_page_size +#define PAGE_MASK (PAGE_SIZE-1) + +#endif -- cgit v1.2.3 From 2665542c3ad64c96a87712971c588ecd7f510042 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 28 May 2010 16:11:56 +0200 Subject: ddekit slab uses libhurd-slab. --- libddekit/Makefile | 4 +- libddekit/init.c | 14 +- libddekit/kmem.c | 546 ----------------------------------------------------- libddekit/memory.c | 53 ++++-- libddekit/pgtab.c | 14 +- 5 files changed, 59 insertions(+), 572 deletions(-) delete mode 100644 libddekit/kmem.c (limited to 'libddekit/init.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index 04921b83..f0f6be87 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -21,7 +21,7 @@ makemode := library libname = libddekit SRCS= condvar.c init.c interrupt.c lock.c malloc.c memory.c \ pci.c pgtab.c printf.c resources.c list.c panic.c \ - thread.c timer.c kmem.c initcall.c + thread.c timer.c initcall.c LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ include/ddekit/semaphore.h include/ddekit/debug.h \ include/ddekit/inline.h include/ddekit/panic.h \ @@ -37,7 +37,7 @@ installhdrs = MIGSTUBS = deviceUser.o machUser.o OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS)) -HURDLIBS = threads ports shouldbeinlibc +HURDLIBS = threads ports shouldbeinlibc hurd-slab MIGCOMSFLAGS = -prefix dde_ diff --git a/libddekit/init.c b/libddekit/init.c index 9114ff46..7caf4c44 100644 --- a/libddekit/init.c +++ b/libddekit/init.c @@ -3,16 +3,28 @@ * * \author Thomas Friebel */ +#include +#include +#include + #include "ddekit/thread.h" +mach_port_t priv_host; + void ddekit_init(void) { extern void linux_kmem_init (); extern int log_init (); extern void interrupt_init (); + extern int pgtab_init (); + error_t err; + + err = get_privileged_ports (&priv_host, NULL); + if (err) + error (2, err, "get_privileged_ports"); ddekit_init_threads(); - linux_kmem_init (); + pgtab_init (); log_init (); interrupt_init (); } diff --git a/libddekit/kmem.c b/libddekit/kmem.c deleted file mode 100644 index 570c1f53..00000000 --- a/libddekit/kmem.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Linux memory allocation. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - * - */ - -#include -#include -#include -#include -#include "mach_U.h" -#include -#include - -#include "util.h" -#include "vm_param.h" - -#include "ddekit/panic.h" - -#define debug ddekit_debug - -extern int printf (const char *, ...); - -/* Amount of memory to reserve for Linux memory allocator. - We reserve 64K chunks to stay within DMA limits. - Increase MEM_CHUNKS if the kernel is running out of memory. */ -#define MEM_CHUNK_SIZE (64 * 1024) -#define MEM_CHUNKS 30 -#define MEM_CHUNKS_TOTAL (MEM_CHUNKS + 5) - -/* round up the size at alignment of page size. */ -#define ROUND_UP(size) ((size) + __vm_page_size - 1) & (~(__vm_page_size - 1)) - -#define CACHE_LINE 32 -/* Mininum amount that linux_kmalloc will allocate. */ -#define MIN_ALLOC CACHE_LINE - -#ifndef NBPW -#define NBPW 32 -#endif - -/* Memory block header. */ -struct blkhdr -{ - unsigned short free; /* 1 if block is free */ - unsigned short size; /* size of block */ - char stuffing[28]; -}; - -/* This structure heads a page allocated by linux_kmalloc. */ -struct pagehdr -{ - unsigned size; /* size (multiple of PAGE_SIZE) */ - struct pagehdr *next; /* next header in list */ - char stuffing[24]; -}; - -/* This structure describes a memory chunk. */ -struct chunkhdr -{ - vm_address_t start; /* start address */ - vm_address_t pstart; /* start physical address */ - vm_address_t end; /* end address */ - unsigned long bitmap; /* busy/free bitmap of pages */ -}; - -static unsigned long __get_free_pages (unsigned long order, int dma); -static void free_pages (unsigned long addr, unsigned long order); - -static struct mutex mem_lock = MUTEX_INITIALIZER; - -/* Chunks from which pages are allocated. - * The extra slots are used to hold the huge chunks (> MEM_CHUNKS_SIZE) - * which are allocated by the user. */ -static struct chunkhdr pages_free[MEM_CHUNKS_TOTAL]; - -/* Memory list maintained by linux_kmalloc. */ -static struct pagehdr *memlist; - -static mach_port_t priv_host; - -/* Some statistics. */ -int num_block_coalesce = 0; -int num_page_collect = 0; -int linux_mem_avail; - -int virt_to_phys (vm_address_t addr) -{ - int i; - - for (i = 0; i < MEM_CHUNKS_TOTAL; i++) - { - if (pages_free[i].start <= addr && pages_free[i].end > addr) - return addr - pages_free[i].start + pages_free[i].pstart; - } - debug ("an address not in any chunks."); - return -1; -} - -int phys_to_virt (vm_address_t addr) -{ -#define CHUNK_SIZE(chunk) ((chunk)->end - (chunk)->start) - int i; - - for (i = 0; i < MEM_CHUNKS_TOTAL; i++) - { - if (pages_free[i].pstart <= addr - && pages_free[i].pstart + CHUNK_SIZE (pages_free + i) > addr) - return addr - pages_free[i].pstart + pages_free[i].start; - } - debug ("an address not in any chunks."); - return -1; -} - -/* Initialize the Linux memory allocator. */ -void -linux_kmem_init () -{ - int i, j; - error_t err; - - err = get_privileged_ports (&priv_host, NULL); - if (err) - error (2, err, "get_privileged_ports"); - - for (i = 0; i < MEM_CHUNKS; i++) - { - error_t err; - - /* Allocate memory. */ - err = vm_dma_buff_alloc (priv_host, mach_task_self (), - MEM_CHUNK_SIZE, &pages_free[i].start, - &pages_free[i].pstart); - if (err) - abort (); - - assert (pages_free[i].start); - - pages_free[i].end = pages_free[i].start + MEM_CHUNK_SIZE; - assert (pages_free[i].pstart + MEM_CHUNK_SIZE <= 16 * 1024 * 1024); - - /* Initialize free page bitmap. */ - pages_free[i].bitmap = 0; - j = MEM_CHUNK_SIZE >> PAGE_SHIFT; - while (--j >= 0) - pages_free[i].bitmap |= 1 << j; - } - - /* Initialize the space for extra slots. */ - memset (pages_free + i, 0, - sizeof (pages_free[0]) * (MEM_CHUNKS_TOTAL - MEM_CHUNKS)); - - linux_mem_avail = (MEM_CHUNKS * MEM_CHUNK_SIZE) >> PAGE_SHIFT; -} - -/* Return the number by which the page size should be - shifted such that the resulting value is >= SIZE. */ -static unsigned long -get_page_order (int size) -{ - unsigned long order; - - for (order = 0; (PAGE_SIZE << order) < size; order++) - ; - return order; -} - -#ifdef LINUX_DEV_DEBUG -static void -check_page_list (int line) -{ - unsigned size; - struct pagehdr *ph; - struct blkhdr *bh; - - for (ph = memlist; ph; ph = ph->next) - { - if ((int) ph & PAGE_MASK) - panic ("%s:%d: page header not aligned", __FILE__, line); - - size = 0; - bh = (struct blkhdr *) (ph + 1); - while (bh < (struct blkhdr *) ((void *) ph + ph->size)) - { - size += bh->size + sizeof (struct blkhdr); - bh = (void *) (bh + 1) + bh->size; - } - - if (size + sizeof (struct pagehdr) != ph->size) - panic ("%s:%d: memory list destroyed", __FILE__, line); - } -} -#else -#define check_page_list(line) -#endif - -/* Merge adjacent free blocks in the memory list. */ -static void -coalesce_blocks () -{ - struct pagehdr *ph; - struct blkhdr *bh, *bhp, *ebh; - - num_block_coalesce++; - - for (ph = memlist; ph; ph = ph->next) - { - bh = (struct blkhdr *) (ph + 1); - ebh = (struct blkhdr *) ((void *) ph + ph->size); - while (1) - { - /* Skip busy blocks. */ - while (bh < ebh && !bh->free) - bh = (struct blkhdr *) ((void *) (bh + 1) + bh->size); - if (bh == ebh) - break; - - /* Merge adjacent free blocks. */ - while (1) - { - bhp = (struct blkhdr *) ((void *) (bh + 1) + bh->size); - if (bhp == ebh) - { - bh = bhp; - break; - } - if (!bhp->free) - { - bh = (struct blkhdr *) ((void *) (bhp + 1) + bhp->size); - break; - } - bh->size += bhp->size + sizeof (struct blkhdr); - } - } - } -} - -/* Allocate SIZE bytes of memory. - The PRIORITY parameter specifies various flags - such as DMA, atomicity, etc. It is not used by Mach. */ -void * -linux_kmalloc (unsigned int size, int priority) -{ - int order, coalesced = 0; - struct pagehdr *ph; - struct blkhdr *bh, *new_bh; - - if (size < MIN_ALLOC) - size = MIN_ALLOC; - else - size = (size + CACHE_LINE - 1) & ~(CACHE_LINE - 1); - - mutex_lock (&mem_lock); - - if (size > (MEM_CHUNK_SIZE - sizeof (struct pagehdr) - - sizeof (struct blkhdr))) - { - error_t err; - int i; - - /* Find an extra slot. */ - for (i = MEM_CHUNKS; i < MEM_CHUNKS_TOTAL; i++) - if (pages_free[i].end == 0) - break; - - // TODO use a dynamically allocated memory to - // record directly allocated large memory. - assert (i < MEM_CHUNKS_TOTAL); - size = ROUND_UP (size); - err = vm_dma_buff_alloc (priv_host, mach_task_self (), size, - &pages_free[i].start, &pages_free[i].pstart); - if (!err) - pages_free[i].end = pages_free[i].start + size; - mutex_unlock (&mem_lock); - fprintf (stderr, "allocate %d bytes at (virt: %x, phys: %x), slot %d\n", - size, pages_free[i].start, pages_free[i].pstart, i); - - return err ? NULL : (void *) pages_free[i].start; - } - -again: - check_page_list (__LINE__); - - /* Walk the page list and find the first free block with size - greater than or equal to the one required. */ - for (ph = memlist; ph; ph = ph->next) - { - bh = (struct blkhdr *) (ph + 1); - while (bh < (struct blkhdr *) ((void *) ph + ph->size)) - { - if (bh->free && bh->size >= size) - { - bh->free = 0; - if (bh->size - size >= MIN_ALLOC + sizeof (struct blkhdr)) - { - /* Split the current block and create a new free block. */ - new_bh = (void *) (bh + 1) + size; - new_bh->free = 1; - new_bh->size = bh->size - size - sizeof (struct blkhdr); - bh->size = size; - } - - check_page_list (__LINE__); - - mutex_unlock (&mem_lock); - return bh + 1; - } - bh = (void *) (bh + 1) + bh->size; - } - } - - check_page_list (__LINE__); - - /* Allocation failed; coalesce free blocks and try again. */ - if (!coalesced) - { - coalesce_blocks (); - coalesced = 1; - goto again; - } - - /* Allocate more pages. */ - order = get_page_order (size - + sizeof (struct pagehdr) - + sizeof (struct blkhdr)); - ph = (struct pagehdr *) __get_free_pages (order, ~0UL); - if (!ph) - { - mutex_unlock (&mem_lock); - return NULL; - } - - ph->size = PAGE_SIZE << order; - ph->next = memlist; - memlist = ph; - bh = (struct blkhdr *) (ph + 1); - bh->free = 0; - bh->size = ph->size - sizeof (struct pagehdr) - sizeof (struct blkhdr); - if (bh->size - size >= MIN_ALLOC + sizeof (struct blkhdr)) - { - new_bh = (void *) (bh + 1) + size; - new_bh->free = 1; - new_bh->size = bh->size - size - sizeof (struct blkhdr); - bh->size = size; - } - - check_page_list (__LINE__); - - mutex_unlock (&mem_lock); - return bh + 1; -} - -/* Free memory P previously allocated by linux_kmalloc. */ -void -linux_kfree (void *p) -{ - struct blkhdr *bh; - struct pagehdr *ph; - int i; - - assert (((int) p & (sizeof (int) - 1)) == 0); - - mutex_lock (&mem_lock); - - for (i = MEM_CHUNKS; i < MEM_CHUNKS_TOTAL; i++) - { - if ((vm_address_t) p == pages_free[i].start) - { - // TODO I think the page cannot be deallocated. - vm_deallocate (mach_task_self (), (vm_address_t) p, - pages_free[i].end - pages_free[i].start); - memset (pages_free + i, 0, sizeof (pages_free[i])); - mutex_unlock (&mem_lock); - return; - } - } - - check_page_list (__LINE__); - - for (ph = memlist; ph; ph = ph->next) - if (p >= (void *) ph && p < (void *) ph + ph->size) - break; - - assert (ph); - - bh = (struct blkhdr *) p - 1; - - assert (!bh->free); - assert (bh->size >= MIN_ALLOC); - assert ((bh->size & (sizeof (int) - 1)) == 0); - - bh->free = 1; - - check_page_list (__LINE__); - - mutex_unlock (&mem_lock); -} - -/* Free any pages that are not in use. - Called by __get_free_pages when pages are running low. */ -static void -collect_kmalloc_pages () -{ - struct blkhdr *bh; - struct pagehdr *ph, **prev_ph; - - check_page_list (__LINE__); - - coalesce_blocks (); - - check_page_list (__LINE__); - - ph = memlist; - prev_ph = &memlist; - while (ph) - { - bh = (struct blkhdr *) (ph + 1); - if (bh->free && (void *) (bh + 1) + bh->size == (void *) ph + ph->size) - { - *prev_ph = ph->next; - free_pages ((unsigned long) ph, get_page_order (ph->size)); - ph = *prev_ph; - } - else - { - prev_ph = &ph->next; - ph = ph->next; - } - } - - check_page_list (__LINE__); -} - -/* Allocate ORDER + 1 number of physically contiguous pages. - PRIORITY and DMA are not used in Mach. - NOTE: mem_lock has been held. - - XXX: This needs to be dynamic. To do that we need to make - the Mach page manipulation routines interrupt safe and they - must provide machine dependant hooks. */ -unsigned long -__get_free_pages (unsigned long order, int dma) -{ - int i, pages_collected = 0; - unsigned bits, off, j, len; - - assert ((PAGE_SIZE << order) <= MEM_CHUNK_SIZE); - - /* Construct bitmap of contiguous pages. */ - bits = 0; - j = 0; - len = 0; - while (len < (PAGE_SIZE << order)) - { - bits |= 1 << j++; - len += PAGE_SIZE; - } - -again: - - /* Search each chunk for the required number of contiguous pages. */ - for (i = 0; i < MEM_CHUNKS; i++) - { - off = 0; - j = bits; - while (MEM_CHUNK_SIZE - off >= (PAGE_SIZE << order)) - { - if ((pages_free[i].bitmap & j) == j) - { - pages_free[i].bitmap &= ~j; - linux_mem_avail -= order + 1; - return pages_free[i].start + off; - } - j <<= 1; - off += PAGE_SIZE; - } - } - - /* Allocation failed; collect kmalloc and buffer pages - and try again. */ - if (!pages_collected) - { - num_page_collect++; - collect_kmalloc_pages (); - pages_collected = 1; - goto again; - } - - printf ("%s:%d: __get_free_pages: ran out of pages\n", __FILE__, __LINE__); - - return 0; -} - -/* Free ORDER + 1 number of physically - contiguous pages starting at address ADDR. */ -void -free_pages (unsigned long addr, unsigned long order) -{ - int i; - unsigned bits, len, j; - - assert ((addr & PAGE_MASK) == 0); - - for (i = 0; i < MEM_CHUNKS; i++) - if (addr >= pages_free[i].start && addr < pages_free[i].end) - break; - - assert (i < MEM_CHUNKS); - - /* Contruct bitmap of contiguous pages. */ - len = 0; - j = 0; - bits = 0; - while (len < (PAGE_SIZE << order)) - { - bits |= 1 << j++; - len += PAGE_SIZE; - } - bits <<= (addr - pages_free[i].start) >> PAGE_SHIFT; - - mutex_lock (&mem_lock); - - assert ((pages_free[i].bitmap & bits) == 0); - - pages_free[i].bitmap |= bits; - linux_mem_avail += order + 1; - mutex_unlock (&mem_lock); -} diff --git a/libddekit/memory.c b/libddekit/memory.c index 03752211..79fe0ad3 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -16,16 +16,16 @@ #include #include #include + #include "mach_U.h" +#include "libhurd-slab/slab.h" #include "util.h" #include "ddekit/memory.h" #include "ddekit/panic.h" #include "ddekit/pgtab.h" -extern void * linux_kmalloc (unsigned int size, int priority); -extern void linux_kfree (void *p); - +#define CACHE_LINE_SIZE 32 /**************** ** Page cache ** @@ -81,8 +81,7 @@ void ddekit_slab_setup_page_cache(unsigned pages) /* ddekit slab facilitates l4slabs */ struct ddekit_slab { - int size; - int contiguous; + struct hurd_slab_space space; }; /** @@ -90,10 +89,9 @@ struct ddekit_slab */ void *ddekit_slab_alloc(struct ddekit_slab * slab) { - if (slab->contiguous) - return linux_kmalloc (slab->size, 0); - else - return ddekit_simple_malloc (slab->size); + void *buffer; + error_t err = hurd_slab_alloc (&slab->space, &buffer); + return err ? NULL : buffer; } @@ -102,10 +100,7 @@ void *ddekit_slab_alloc(struct ddekit_slab * slab) */ void ddekit_slab_free(struct ddekit_slab * slab, void *objp) { - if (slab->contiguous) - linux_kfree (objp); - else - ddekit_simple_free (objp); + hurd_slab_dealloc (&slab->space, objp); } @@ -141,9 +136,22 @@ void *ddekit_slab_get_data(struct ddekit_slab * slab) */ void ddekit_slab_destroy (struct ddekit_slab * slab) { - ddekit_simple_free(slab); + hurd_slab_free ((hurd_slab_space_t) slab); +} + +error_t allocate_buffer (void *hook, size_t size, void **ptr) +{ + *ptr = ddekit_large_malloc (size); + if (*ptr == NULL) + return ENOMEM; + return 0; } +error_t deallocate_buffer (void *hook, void *buffer, size_t size) +{ + ddekit_large_free (buffer); + return 0; +} /** * Initialize slab cache @@ -156,10 +164,21 @@ void ddekit_slab_destroy (struct ddekit_slab * slab) struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) { struct ddekit_slab * slab; + error_t err; - slab = (struct ddekit_slab *) ddekit_simple_malloc(sizeof(*slab)); - slab->size = size; - slab->contiguous = contiguous; + if (contiguous) + err = hurd_slab_create (size, CACHE_LINE_SIZE, allocate_buffer, + deallocate_buffer, NULL, NULL, NULL, + (hurd_slab_space_t *) &slab); + else + /* If the object isn't used by DMA, + * we can use all default settings. */ + err = hurd_slab_create (size, 0, NULL, NULL, NULL, NULL, NULL, + (hurd_slab_space_t *) &slab); + if (err) + { + error (2, err, "hurd_slab_create"); + } return slab; } diff --git a/libddekit/pgtab.c b/libddekit/pgtab.c index 35cc630a..f39fc40a 100644 --- a/libddekit/pgtab.c +++ b/libddekit/pgtab.c @@ -82,14 +82,14 @@ ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virtual) e = get_entry_from_virt ((ddekit_addr_t) virtual); if (e) { - ddekit_addr_t phys = e->physical; + ddekit_addr_t phys = e->physical + (virtual - e->virtual); mutex_unlock (&lock); return phys; } mutex_unlock (&lock); - extern int virt_to_phys (vm_address_t addr); - return virt_to_phys ((vm_address_t) virtual); + ddekit_printf ("a virtual address %p doesn't exist.\n", virtual); + return -1; } /** @@ -106,14 +106,16 @@ ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical) e = get_entry_from_phys (physical); if (e) { - ddekit_addr_t virt = (ddekit_addr_t) e->virtual; + ddekit_addr_t virt = (ddekit_addr_t) e->virtual + + (physical - e->physical); mutex_unlock (&lock); return virt; } mutex_unlock (&lock); - extern int phys_to_virt (vm_address_t addr); - return phys_to_virt (physical); + + ddekit_printf ("a physical address %p doesn't exist.\n", physical); + return -1; } // TODO -- cgit v1.2.3