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/memory.c | 467 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 467 insertions(+) create mode 100644 libddekit/memory.c (limited to 'libddekit/memory.c') diff --git a/libddekit/memory.c b/libddekit/memory.c new file mode 100644 index 00000000..b6db0cac --- /dev/null +++ b/libddekit/memory.c @@ -0,0 +1,467 @@ +/* + * \brief Memory subsystem + * \author Thomas Friebel + * \author Christian Helmuth + * \date 2006-11-03 + * + * The memory subsystem provides the backing store for DMA-able memory via + * large malloc and slabs. + * + * FIXME check thread-safety and add locks where appropriate + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +/**************** + ** Page cache ** + ****************/ + +/* FIXME revisit two-linked-lists approach - we could get rid of the + * pcache_free lists, because these descriptors can also be allocated + * whenever the need arises. (XXX: Check how this hurts performance.) + */ + +/***************************************************************************** + DDEKit maintains a list of free pages that can be used for growing + existing DDEKit slabs. We distinguish between 2 types of pages: the ones + that have been allocated from physically contiguous dataspaces and the the + ones that have not. + + For each type of cache, we maintain two lists: a list of free pages that + can be used to grow a cache (pcache_used) and a list of free pcache entries + that can be used to store pages when they get freed (pcache_free). The + reason for this is that by using these two lists, cache operations can be + done atomically using cmpxchg. + + The function ddekit_slab_setup_page_cache() is used to tune the number of + cached pages. + ******************************************************************************/ + +/* page cache to minimize allocations from external servers */ +struct ddekit_pcache +{ + struct ddekit_pcache *next; + void *page; + int contig; +}; + + +/* 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 + * + * \param pages maximal number of memory pages + * + * If the maximal number of unused pages is exceeded, subsequent deallocation + * will be freed at the memory server. This page cache caches pages from all + * slabs. + */ +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 ** + *******************************/ + +/* 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 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; +} + + +/** + * Free object in slab + */ +void ddekit_slab_free(struct ddekit_slab * slab, void *objp) +{ + l4lock_lock(&slab->lock); + l4slab_free(&slab->cache, objp); + l4lock_unlock(&slab->lock); +} + + +/** + * Store user pointer in slab cache + */ +void ddekit_slab_set_data(struct ddekit_slab * slab, void *data) +{ + l4slab_set_data(&slab->cache, data); +} + + +/** + * Read user pointer from slab cache + */ +void *ddekit_slab_get_data(struct ddekit_slab * slab) +{ + return l4slab_get_data(&slab->cache); +} + + +/** + * Destroy slab cache + * + * \param slab pointer to slab cache structure + */ +void ddekit_slab_destroy (struct ddekit_slab * slab) +{ + l4slab_destroy(&slab->cache); + ddekit_simple_free(slab); +} + + +/** + * Initialize slab cache + * + * \param size size of cache objects + * \param contiguous make this slab use physically contiguous memory + * + * \return pointer to new slab cache or 0 on error + */ +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->contiguous = contiguous; + + return slab; +} + + +/********************************** + ** Large block memory allocator ** + **********************************/ + +/** + * Free large block of memory + * + * This is no useful for allocation < page size. + */ +void ddekit_large_free(void *objp) +{ + /* clear PTEs */ + ddekit_pgtab_clear_region(objp, PTE_TYPE_LARGE); + + /* release */ + l4dm_mem_release(objp); +} + + +/** + * Allocate large block of memory + * + * This is no useful for allocation < page size. + */ +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; +} + + +/** + * Allocate large block of memory (special interface) + * + * This is no useful for allocation < page size. + * + * FIXME implementation missing... + */ +void *ddekit_contig_malloc(unsigned long size, + unsigned long low, unsigned long high, + unsigned long alignment, unsigned long boundary) +{ +#if 0 + void *res; + int err; + int pages; + l4_size_t tmp; + 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); + + if (res) { + /* check if res meets low/high/alignment/boundary + * and panic if it is not the case + * XXXY + */ + + /* get physical address */ + err = l4dm_mem_phys_addr(res, 1, &dm_paddr, 1, &tmp); + if (err != 1) + ddekit_debug("contigmalloc: error getting physical address of new page!\n"); + + /* set PTE */ + ddekit_set_ptes(res, dm_paddr.addr, pages, PTE_TYPE_CONTIG); + } + + return res; +#else + ddekit_debug("%s: not implemented\n", __func__); + return 0; +#endif +} -- 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/memory.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 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/memory.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 d12886c5281918f46b02f8cf3617858b11c44812 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 7 Dec 2009 02:00:09 +0100 Subject: Use linux_kmalloc only when we need contiguous physical memory. --- libddekit/memory.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'libddekit/memory.c') diff --git a/libddekit/memory.c b/libddekit/memory.c index 27be4eeb..1ffb15b0 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -80,7 +80,10 @@ struct ddekit_slab */ void *ddekit_slab_alloc(struct ddekit_slab * slab) { - return linux_kmalloc (slab->size, 0); + if (slab->contiguous) + return linux_kmalloc (slab->size, 0); + else + return ddekit_simple_malloc (slab->size); } @@ -89,7 +92,10 @@ void *ddekit_slab_alloc(struct ddekit_slab * slab) */ void ddekit_slab_free(struct ddekit_slab * slab, void *objp) { - linux_kfree (objp); + if (slab->contiguous) + linux_kfree (objp); + else + ddekit_simple_free (objp); } @@ -168,7 +174,6 @@ void ddekit_large_free(void *objp) */ void *ddekit_large_malloc(int size) { - // TODO I hope linux_kmalloc can provide large enough pages. return linux_kmalloc (size, 0); } -- cgit v1.2.3 From 9341952a7cea0d39b871ecdb6ac153fc820524c8 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 7 Dec 2009 02:25:32 +0100 Subject: Make ddekit_simple_malloc/free inline. --- libddekit/Makefile | 2 +- libddekit/include/ddekit/memory.h | 13 +++++++++-- libddekit/malloc.c | 49 --------------------------------------- libddekit/memory.c | 3 +++ 4 files changed, 15 insertions(+), 52 deletions(-) delete mode 100644 libddekit/malloc.c (limited to 'libddekit/memory.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index 018d67c9..f2e52f25 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -19,7 +19,7 @@ dir := libddekit makemode := library libname = libddekit -SRCS= condvar.c init.c interrupt.c lock.c malloc.c memory.c \ +SRCS= condvar.c init.c interrupt.c lock.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 \ diff --git a/libddekit/include/ddekit/memory.h b/libddekit/include/ddekit/memory.h index 051a4d9e..2c573d8f 100644 --- a/libddekit/include/ddekit/memory.h +++ b/libddekit/include/ddekit/memory.h @@ -123,6 +123,9 @@ void *ddekit_contig_malloc( ** Simple memory allocator ** *****************************/ +#include +#include "ddekit/inline.h" + /** * Allocate memory block via simple allocator * @@ -132,13 +135,19 @@ void *ddekit_contig_malloc( * The blocks allocated via this allocator CANNOT be used for DMA or other * device operations, i.e., there exists no virt->phys mapping. */ -void *ddekit_simple_malloc(unsigned size); +static INLINE void *ddekit_simple_malloc(unsigned size) +{ + return malloc (size); +} /** * Free memory block via simple allocator * * \param p pointer to memory block */ -void ddekit_simple_free(void *p); +static INLINE void ddekit_simple_free(void *p) +{ + free (p); +} #endif diff --git a/libddekit/malloc.c b/libddekit/malloc.c deleted file mode 100644 index a30cd7b7..00000000 --- a/libddekit/malloc.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/** - * Allocate memory block via simple allocator - * - * \param size block size - * \return pointer to new memory block - * - * The blocks allocated via this allocator CANNOT be used for DMA or other - * device operations, i.e., there exists no virt->phys mapping. - * - * Each chunk stores its size in the first word for free() to work. - */ - -#include - -void *ddekit_simple_malloc(unsigned size) -{ - return malloc (size); -} - - -/** - * Free memory block via simple allocator - * - * \param p pointer to memory block - */ -void ddekit_simple_free(void *p) -{ - free (p); -} diff --git a/libddekit/memory.c b/libddekit/memory.c index 1ffb15b0..781a4bae 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -160,6 +160,9 @@ struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) * Free large block of memory * * This is no useful for allocation < page size. + * + * TODO The freed memory can be cached and will be still accessible ( + * no page fault when accessed). I hope it won't caused any troubles. */ void ddekit_large_free(void *objp) { -- cgit v1.2.3 From 7460caca37c30536b7b507d141cf5b7c51697cf3 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 1 Jan 2010 14:54:28 +0100 Subject: Remove c_headers.h --- libddekit/Makefile | 2 +- libddekit/c_headers.h | 7 ------- libddekit/include/ddekit/panic.h | 19 ++----------------- libddekit/include/ddekit/printf.h | 2 +- libddekit/memory.c | 2 ++ libddekit/timer.c | 1 + 6 files changed, 7 insertions(+), 26 deletions(-) delete mode 100644 libddekit/c_headers.h (limited to 'libddekit/memory.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index 018d67c9..4d5d58fa 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -20,7 +20,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 \ + pci.c pgtab.c printf.c resources.c list.c panic.c \ thread.c timer.c kmem.c LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ include/ddekit/semaphore.h include/ddekit/debug.h \ diff --git a/libddekit/c_headers.h b/libddekit/c_headers.h deleted file mode 100644 index 6141e900..00000000 --- a/libddekit/c_headers.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __C_HEADERS_H__ -#define __C_HEADERS_H__ - -#include -#include - -#endif diff --git a/libddekit/include/ddekit/panic.h b/libddekit/include/ddekit/panic.h index f036ab3e..1468675f 100644 --- a/libddekit/include/ddekit/panic.h +++ b/libddekit/include/ddekit/panic.h @@ -3,29 +3,14 @@ /** \defgroup DDEKit_util */ -#include "c_headers.h" - /** Panic - print error message and enter the kernel debugger. * \ingroup DDEKit_util */ -#define ddekit_panic(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "%s", format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (stderr); \ - abort (); \ -} while (0) +void ddekit_panic(char *fmt, ...) __attribute__((noreturn)); /** Print a debug message. * \ingroup DDEKit_util */ -#define ddekit_debug(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "%s: %s\n", __func__, format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (stderr); \ -} while (0) +void ddekit_debug(char *fmt, ...); #endif diff --git a/libddekit/include/ddekit/printf.h b/libddekit/include/ddekit/printf.h index aa086c71..35b0dfa1 100644 --- a/libddekit/include/ddekit/printf.h +++ b/libddekit/include/ddekit/printf.h @@ -1,7 +1,7 @@ #ifndef _ddekit_print_h #define _ddekit_print_h -#include "c_headers.h" +#include /** Print message. * \ingroup DDEKit_util diff --git a/libddekit/memory.c b/libddekit/memory.c index 781a4bae..69088c2a 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -10,6 +10,8 @@ * FIXME check thread-safety and add locks where appropriate */ +#include + #include "ddekit/memory.h" #include "ddekit/panic.h" diff --git a/libddekit/timer.c b/libddekit/timer.c index 4944be69..ea66e5f5 100644 --- a/libddekit/timer.c +++ b/libddekit/timer.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "ddekit/lock.h" #include "ddekit/memory.h" -- cgit v1.2.3 From 589e5402f5e90286019e33f11cdc00429f01cca8 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Thu, 22 Apr 2010 15:12:46 +0200 Subject: ddekit: print messages. --- libddekit/Makefile | 2 +- libddekit/kmem.c | 3 ++- libddekit/memory.c | 7 ++++++- libddekit/pgtab.c | 7 ++++++- 4 files changed, 15 insertions(+), 4 deletions(-) (limited to 'libddekit/memory.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index 958e67d3..04921b83 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -31,7 +31,7 @@ LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ include/ddekit/interrupt.h include/ddekit/resources.h \ include/ddekit/memory.h include/ddekit/timer.h \ include/dde.h \ - config.h list.h + config.h list.h util.h installhdrs = MIGSTUBS = deviceUser.o machUser.o diff --git a/libddekit/kmem.c b/libddekit/kmem.c index 668505ec..3b869cc9 100644 --- a/libddekit/kmem.c +++ b/libddekit/kmem.c @@ -30,6 +30,7 @@ #include #include +#include "util.h" #include "vm_param.h" #include "ddekit/panic.h" @@ -286,7 +287,7 @@ linux_kmalloc (unsigned int size, int priority) if (!err) pages_free[i].end = pages_free[i].start + size; mutex_unlock (&mem_lock); - printf ("allocate %d bytes at (virt: %x, phys: %x), slot %d\n", + 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; diff --git a/libddekit/memory.c b/libddekit/memory.c index 69088c2a..d7ea9705 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -11,7 +11,9 @@ */ #include +#include +#include "util.h" #include "ddekit/memory.h" #include "ddekit/panic.h" @@ -52,7 +54,6 @@ struct ddekit_pcache int contig; }; - /** * Setup page cache for all slabs * @@ -64,6 +65,7 @@ struct ddekit_pcache */ void ddekit_slab_setup_page_cache(unsigned pages) { + UNIMPL; } /******************************* @@ -109,6 +111,7 @@ void ddekit_slab_set_data(struct ddekit_slab * slab, void *data) #if 0 l4slab_set_data(&slab->cache, data); #endif + UNIMPL; } @@ -120,6 +123,7 @@ void *ddekit_slab_get_data(struct ddekit_slab * slab) #if 0 return l4slab_get_data(&slab->cache); #endif + UNIMPL; return NULL; } @@ -179,6 +183,7 @@ void ddekit_large_free(void *objp) */ void *ddekit_large_malloc(int size) { + ddekit_printf("ddekit_large_malloc %d bytes\n", size); return linux_kmalloc (size, 0); } diff --git a/libddekit/pgtab.c b/libddekit/pgtab.c index 88273b7c..aa652c75 100644 --- a/libddekit/pgtab.c +++ b/libddekit/pgtab.c @@ -14,7 +14,7 @@ #include #include "ddekit/pgtab.h" - +#include "util.h" #include "config.h" /***************************** @@ -59,6 +59,7 @@ int ddekit_pgtab_get_type(const void *virtual) return p->type; #endif + UNIMPL; return 0; } @@ -76,6 +77,7 @@ int ddekit_pgtab_get_size(const void *virtual) return p->size; #endif + UNIMPL; return 0; } @@ -88,6 +90,7 @@ int ddekit_pgtab_get_size(const void *virtual) */ void ddekit_pgtab_clear_region(void *virtual, int type) { + UNIMPL; } @@ -101,9 +104,11 @@ void ddekit_pgtab_clear_region(void *virtual, int type) */ void ddekit_pgtab_set_region(void *virtual, ddekit_addr_t physical, int pages, int type) { + UNIMPL; } void ddekit_pgtab_set_region_with_size(void *virt, ddekit_addr_t phys, int size, int type) { + UNIMPL; } -- cgit v1.2.3 From f04e8156038d62d6a79e05d9b022c53705e44048 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 28 May 2010 15:01:57 +0200 Subject: reimplement ddekit_large_malloc. --- libddekit/memory.c | 31 +++++++++++-- libddekit/pgtab.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 142 insertions(+), 18 deletions(-) (limited to 'libddekit/memory.c') diff --git a/libddekit/memory.c b/libddekit/memory.c index d7ea9705..03752211 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -12,10 +12,16 @@ #include #include +#include +#include +#include +#include +#include "mach_U.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); @@ -172,7 +178,12 @@ struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) */ void ddekit_large_free(void *objp) { - linux_kfree (objp); + int err; + int size = ddekit_pgtab_get_size (objp); + ddekit_pgtab_clear_region (objp, 0); + err = munmap (objp, size); + if (err < 0) + error (0, errno, "munmap"); } @@ -183,8 +194,22 @@ void ddekit_large_free(void *objp) */ void *ddekit_large_malloc(int size) { - ddekit_printf("ddekit_large_malloc %d bytes\n", size); - return linux_kmalloc (size, 0); + error_t err; + vm_address_t vstart, pstart; + extern mach_port_t priv_host; + + /* Allocate memory. */ + err = vm_dma_buff_alloc (priv_host, mach_task_self (), + size, &vstart, &pstart); + if (err) + { + error (0, err, "vm_dma_buff_alloc"); + vstart = 0; + } + else + ddekit_pgtab_set_region_with_size ((void *) vstart, pstart, size, 0); + + return (void *) vstart; } diff --git a/libddekit/pgtab.c b/libddekit/pgtab.c index aa652c75..35cc630a 100644 --- a/libddekit/pgtab.c +++ b/libddekit/pgtab.c @@ -11,16 +11,64 @@ * For this to work, dataspaces must be attached to l4rm regions! */ +#include +#include +#include #include +#include #include "ddekit/pgtab.h" #include "util.h" #include "config.h" +/* A structure of recording a region of memory. */ +struct entry +{ + void *virtual; + ddekit_addr_t physical; + int size; + int type; +}; + +static struct entry *regions; +/* The number of memory regions in the array REGIONS */ +static int num_regions; +/* The size of the array REGIONS */ +static int capability; +static struct mutex lock; +#define INIT_SIZE 128 + /***************************** ** Page-table facility API ** *****************************/ +static struct entry *get_entry_from_phys (const ddekit_addr_t phys) +{ + int i; + + for (i = 0; i < num_regions; i++) + { + if (regions[i].physical <= phys + && regions[i].physical + regions[i].size > phys) + return ®ions[i]; + } + return NULL; +} + +static struct entry *get_entry_from_virt (const ddekit_addr_t virt) +{ + int i; + + for (i = 0; i < num_regions; i++) + { + if ((ddekit_addr_t) regions[i].virtual <= virt + && ((ddekit_addr_t) regions[i].virtual) + + regions[i].size > virt) + return ®ions[i]; + } + return NULL; +} + /** * Get physical address for virtual address * @@ -29,6 +77,17 @@ */ ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virtual) { + struct entry *e; + mutex_lock (&lock); + e = get_entry_from_virt ((ddekit_addr_t) virtual); + if (e) + { + ddekit_addr_t phys = e->physical; + 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); } @@ -41,6 +100,18 @@ ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virtual) */ ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical) { + struct entry *e; + + mutex_lock (&lock); + e = get_entry_from_phys (physical); + if (e) + { + ddekit_addr_t virt = (ddekit_addr_t) e->virtual; + mutex_unlock (&lock); + return virt; + } + mutex_unlock (&lock); + extern int phys_to_virt (vm_address_t addr); return phys_to_virt (physical); } @@ -63,21 +134,18 @@ int ddekit_pgtab_get_type(const void *virtual) return 0; } -//TODO int ddekit_pgtab_get_size(const void *virtual) { -#if 0 - /* find pgtab object */ - struct pgtab_object *p = l4rm_get_userptr(virtual); - if (!p) { - /* XXX this is verbose */ - LOG_Error("no virt->phys mapping for %p", virtual); - return -1; + struct entry *e; + mutex_lock (&lock); + e = get_entry_from_virt ((ddekit_addr_t) virtual); + if (e) + { + int size = e->size; + mutex_unlock (&lock); + return size; } - - return p->size; -#endif - UNIMPL; + mutex_unlock (&lock); return 0; } @@ -90,7 +158,16 @@ int ddekit_pgtab_get_size(const void *virtual) */ void ddekit_pgtab_clear_region(void *virtual, int type) { - UNIMPL; + struct entry *e; + + mutex_lock (&lock); + e = get_entry_from_virt ((ddekit_addr_t) virtual); + if (e) + { + *e = regions[num_regions - 1]; + num_regions--; + } + mutex_unlock (&lock); } @@ -104,11 +181,33 @@ void ddekit_pgtab_clear_region(void *virtual, int type) */ void ddekit_pgtab_set_region(void *virtual, ddekit_addr_t physical, int pages, int type) { - UNIMPL; + ddekit_pgtab_set_region (virtual, physical, pages * getpagesize (), type); } void ddekit_pgtab_set_region_with_size(void *virt, ddekit_addr_t phys, int size, int type) { - UNIMPL; + mutex_lock (&lock); + if (num_regions == capability) + { + capability *= 2; + regions = realloc (regions, capability * sizeof (struct entry)); + if (regions == NULL) + error (2, errno, "realloc"); + } + regions[num_regions].virtual = virt; + regions[num_regions].physical = phys; + regions[num_regions].size = size; + regions[num_regions].type = type; + num_regions++; + mutex_unlock (&lock); + ddekit_printf ("******there are %d regions (%d bytes)\n", + num_regions, size); } +int pgtab_init () +{ + capability = INIT_SIZE; + regions = malloc (sizeof (struct entry) * capability); + mutex_init (&lock); + return 0; +} -- 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/memory.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