diff options
-rw-r--r-- | libddekit/memory.c | 31 | ||||
-rw-r--r-- | libddekit/pgtab.c | 129 |
2 files changed, 142 insertions, 18 deletions
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 <stdlib.h> #include <stdio.h> +#include <errno.h> +#include <error.h> +#include <string.h> +#include <sys/mman.h> +#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 <unistd.h> +#include <error.h> +#include <errno.h> #include <mach.h> +#include <cthreads.h> #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; +} |