static char evaluate_freeable(char *ptr, char *previous, char *mem, char *next) { if (*PAGE_SIZE(mem) == ROUND_PAGE(*DATA_SIZE(ptr, 0) + PAGE_META + DATA_META)) return (unmap_page(previous, mem, next)); delete_memory(ptr, mem); if (!memory_is_set(mem + PAGE_META, *PAGE_SIZE(mem) - PAGE_META)) return (unmap_page(previous, mem, next)); return (0); }
static char has_one_page_available() { char *mem; char av; av = 0; mem = get_page_list(0, (void *)-1); while (mem && av != 3) { if (*PAGE_SIZE(mem) == get_alloc_size(TINY)) av |= 1; else if (*PAGE_SIZE(mem) == get_alloc_size(SMALL)) av |= 2; mem = *PAGE_NEXT(mem); } return (av == 3); }
static int tmpfs_mount(void *dev, void *dir) { struct node *dir_node, *dev_node; struct nas *dir_nas, *dev_nas; struct tmpfs_file_info *fi; struct tmpfs_fs_info *fsi; struct node_fi *dev_fi; dev_node = dev; dev_nas = dev_node->nas; dir_node = dir; dir_nas = dir_node->nas; if (NULL == (dev_fi = dev_nas->fi)) { return -ENODEV; } if (NULL == (dir_nas->fs = filesystem_create("tmpfs"))) { return -ENOMEM; } dir_nas->fs->bdev = dev_fi->privdata; /* allocate this fs info */ if(NULL == (fsi = pool_alloc(&tmpfs_fs_pool))) { filesystem_free(dir_nas->fs); return -ENOMEM; } memset(fsi, 0, sizeof(struct tmpfs_fs_info)); dir_nas->fs->fsi = fsi; fsi->block_per_file = MAX_FILE_SIZE; fsi->block_size = PAGE_SIZE(); fsi->numblocks = block_dev(dev_fi->privdata)->size / PAGE_SIZE(); /* allocate this directory info */ if(NULL == (fi = pool_alloc(&tmpfs_file_pool))) { return -ENOMEM; } memset(fi, 0, sizeof(struct tmpfs_file_info)); fi->index = fi->mode = 0; dir_nas->fi->privdata = (void *) fi; return 0; }
static int heap_init(void) { size_t heap_size = (size_t)&_heap_end - (size_t)&_heap_start; __heap_pgallocator = page_allocator_init((char *)&_heap_start, heap_size, PAGE_SIZE()); if (NULL == __heap_pgallocator) { return -ENOSUPP; } return 0; }
static int tmpfs_truncate(struct node *node, off_t length) { struct nas *nas = node->nas; if (length > MAX_FILE_SIZE * PAGE_SIZE()) { return -EFBIG; } nas->fi->ni.size = length; return 0; }
static char unmap_page(char *previous, char *mem, char *next) { if (!has_one_page_available()) return (0); if (previous) *PAGE_NEXT(previous) = next; else get_page_list(0, next); munmap((void *)mem, *PAGE_SIZE(mem)); return (0); }
static char delete_ptrs_page(char *ptr) { char *mem; char *previous; char *next; previous = NULL; mem = get_page_list(0, (void *)-1); while (mem) { next = *PAGE_NEXT(mem); if (ptr >= mem + PAGE_META && ptr < mem + *PAGE_SIZE(mem)) return (evaluate_freeable(ptr, previous, mem, next)); previous = mem; mem = next; } return (0); }
static int tmpfs_format(void *dev) { node_t *dev_node; struct nas *dev_nas; struct node_fi *dev_fi; if (NULL == (dev_node = dev)) { return -ENODEV;/*device not found*/ } if(!node_is_block_dev(dev_node)) { return -ENODEV; } dev_nas = dev_node->nas; dev_fi = dev_nas->fi; if(MAX_FILE_SIZE > block_dev(dev_fi->privdata)->size / PAGE_SIZE()) { return -ENOSPC; } return 0; }
static int bochs_init(struct pci_slot_dev *pci_dev) { char *mmap_base = (char *)(pci_dev->bar[0] & ~0xf); /* FIXME */ size_t mmap_len = binalign_bound(VBE_DISPI_MAX_XRES * VBE_DISPI_MAX_YRES * VBE_DISPI_MAX_BPP / 8, PAGE_SIZE()); struct fb_info *info; if (MAP_FAILED == mmap_device_memory(mmap_base, mmap_len, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_FIXED, (unsigned long) mmap_base)) { return -EIO; } info = fb_create(&bochs_ops, mmap_base, mmap_len); if (info == NULL) { munmap(mmap_base, mmap_len); return -ENOMEM; } return 0; }
static int tmpfs_init(void * par) { struct path dir_path, dev_path, root; struct node *dev_node; int res; struct ramdisk *ramdisk; if (!par) { return 0; } /*TODO */ if (0 != vfs_lookup(TMPFS_DIR, &dir_path)) { return -ENOENT; } ramdisk = ramdisk_create(tmpfs_dev, FILESYSTEM_SIZE * PAGE_SIZE()); if (0 != (res = err(ramdisk))) { return res; } dev_node = ramdisk->bdev->dev_vfs_info; if (!dev_node) { return -1; } /* format filesystem */ if (0 != (res = tmpfs_format((void *) dev_node))) { return res; } /* mount filesystem */ dev_path.node = dev_node; dev_path.mnt_desc = root.mnt_desc; return tmpfs_mount(dev_path.node, dir_path.node); }
static int bochs_init(struct pci_slot_dev *pci_dev) { int ret; struct fb_info *info; size_t mmap_len; assert(pci_dev != NULL); info = fb_alloc(); if (info == NULL) { return -ENOMEM; } memcpy(&info->fix, &bochs_fix_screeninfo, sizeof info->fix); fill_var(&info->var); info->ops = &bochs_ops; info->screen_base = (void *)(pci_dev->bar[0] & ~0xf); /* FIXME */ mmap_len = binalign_bound(VBE_DISPI_MAX_XRES * VBE_DISPI_MAX_YRES * VBE_DISPI_MAX_BPP / 8, PAGE_SIZE()); if (MAP_FAILED == mmap_device_memory(info->screen_base, mmap_len, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_FIXED, (unsigned long) info->screen_base)) { return -EIO; } ret = fb_register(info); if (ret != 0) { fb_release(info); return ret; } return 0; }
POOL_DEF(tmpfs_fs_pool, struct tmpfs_fs_info, OPTION_GET(NUMBER,tmpfs_descriptor_quantity)); /* tmpfs file description pool */ POOL_DEF(tmpfs_file_pool, struct tmpfs_file_info, OPTION_GET(NUMBER,inode_quantity)); INDEX_DEF(tmpfs_file_idx,0,OPTION_GET(NUMBER,inode_quantity)); /* define sizes in 4096 blocks */ #define MAX_FILE_SIZE OPTION_GET(NUMBER,tmpfs_file_size) #define FILESYSTEM_SIZE OPTION_GET(NUMBER,tmpfs_filesystem_size) #define TMPFS_NAME "tmpfs" #define TMPFS_DEV "/dev/ram#" #define TMPFS_DIR "/tmp" static char sector_buff[PAGE_SIZE()];/* TODO */ static char tmpfs_dev[] = TMPFS_DEV; static int tmpfs_format(void *path); static int tmpfs_mount(void *dev, void *dir); static int tmpfs_init(void * par) { struct path dir_path, dev_path, root; struct node *dev_node; int res; struct ramdisk *ramdisk; if (!par) { return 0; }
GSList* get_va_pages_ia32e(vmi_instance_t vmi, addr_t dtb) { GSList *ret = NULL; uint8_t entry_size = 0x8; #define IA32E_ENTRIES_PER_PAGE 0x200 // 0x1000/0x8 uint64_t *pml4_page = malloc(VMI_PS_4KB); addr_t pml4e_location = dtb & VMI_BIT_MASK(12,51); if (VMI_PS_4KB != vmi_read_pa(vmi, pml4e_location, pml4_page, VMI_PS_4KB)) { free(pml4_page); return ret; } uint64_t *pdpt_page = malloc(VMI_PS_4KB); uint64_t *pgd_page = malloc(VMI_PS_4KB); uint64_t *pt_page = malloc(VMI_PS_4KB); uint64_t pml4e_index; for(pml4e_index = 0; pml4e_index < IA32E_ENTRIES_PER_PAGE; pml4e_index++, pml4e_location += entry_size) { uint64_t pml4e_value = pml4_page[pml4e_index]; if(!ENTRY_PRESENT(vmi->os_type, pml4e_value)) { continue; } uint64_t pdpte_location = pml4e_value & VMI_BIT_MASK(12,51); if (VMI_PS_4KB != vmi_read_pa(vmi, pdpte_location, pdpt_page, VMI_PS_4KB)) { continue; } uint64_t pdpte_index; for(pdpte_index = 0; pdpte_index < IA32E_ENTRIES_PER_PAGE; pdpte_index++, pdpte_location++) { uint64_t pdpte_value = pdpt_page[pdpte_index]; if(!ENTRY_PRESENT(vmi->os_type, pdpte_value)) { continue; } if(PAGE_SIZE(pdpte_value)) { page_info_t *info = g_malloc0(sizeof(page_info_t)); info->vaddr = (pml4e_index << 39) | (pdpte_index << 30); info->paddr = get_gigpage_ia32e(info->vaddr, pdpte_value); info->size = VMI_PS_1GB; info->x86_ia32e.pml4e_location = pml4e_location; info->x86_ia32e.pml4e_value = pml4e_value; info->x86_ia32e.pdpte_location = pdpte_location; info->x86_ia32e.pdpte_value = pdpte_value; ret = g_slist_prepend(ret, info); continue; } uint64_t pgd_location = pdpte_value & VMI_BIT_MASK(12,51); if (VMI_PS_4KB != vmi_read_pa(vmi, pgd_location, pgd_page, VMI_PS_4KB)) { continue; } uint64_t pgde_index; for(pgde_index = 0; pgde_index < IA32E_ENTRIES_PER_PAGE; pgde_index++, pgd_location += entry_size) { uint64_t pgd_value = pgd_page[pgde_index]; if(ENTRY_PRESENT(vmi->os_type, pgd_value)) { if(PAGE_SIZE(pgd_value)) { page_info_t *info = g_malloc0(sizeof(page_info_t)); info->vaddr = (pml4e_index << 39) | (pdpte_index << 30) | (pgde_index << 21); info->paddr = get_2megpage_ia32e(info->vaddr, pgd_value); info->size = VMI_PS_2MB; info->x86_ia32e.pml4e_location = pml4e_location; info->x86_ia32e.pml4e_value = pml4e_value; info->x86_ia32e.pdpte_location = pdpte_location; info->x86_ia32e.pdpte_value = pdpte_value; info->x86_ia32e.pgd_location = pgd_location; info->x86_ia32e.pgd_value = pgd_value; ret = g_slist_prepend(ret, info); continue; } uint64_t pte_location = (pgd_value & VMI_BIT_MASK(12,51)); if (VMI_PS_4KB != vmi_read_pa(vmi, pte_location, pt_page, VMI_PS_4KB)) { continue; } uint64_t pte_index; for(pte_index = 0; pte_index < IA32E_ENTRIES_PER_PAGE; pte_index++, pte_location += entry_size) { uint64_t pte_value = pt_page[pte_index]; if(ENTRY_PRESENT(vmi->os_type, pte_value)) { page_info_t *info = g_malloc0(sizeof(page_info_t)); info->vaddr = (pml4e_index << 39) | (pdpte_index << 30) | (pgde_index << 21) | (pte_index << 12); info->paddr = get_paddr_ia32e(info->vaddr, pte_value); info->size = VMI_PS_4KB; info->x86_ia32e.pml4e_location = pml4e_location; info->x86_ia32e.pml4e_value = pml4e_value; info->x86_ia32e.pdpte_location = pdpte_location; info->x86_ia32e.pdpte_value = pdpte_value; info->x86_ia32e.pgd_location = pgd_location; info->x86_ia32e.pgd_value = pgd_value; info->x86_ia32e.pte_location = pte_location; info->x86_ia32e.pte_value = pte_value; ret = g_slist_prepend(ret, info); continue; } } } } } } free(pt_page); free(pgd_page); free(pdpt_page); free(pml4_page); return ret; }
status_t v2p_ia32e (vmi_instance_t vmi, addr_t dtb, addr_t vaddr, page_info_t *info) { status_t status = VMI_FAILURE; // are we in compatibility mode OR 64-bit mode ??? // validate address based on above (e.g., is it canonical?) // determine what MAXPHYADDR is dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: lookup vaddr = 0x%.16"PRIx64"\n", vaddr); dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: dtb = 0x%.16"PRIx64"\n", dtb); status = get_pml4e(vmi, vaddr, dtb, &info->x86_ia32e.pml4e_location, &info->x86_ia32e.pml4e_value); if (status != VMI_SUCCESS) { goto done; } if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pml4e_value)) { status = VMI_FAILURE; goto done; } status = get_pdpte_ia32e(vmi, vaddr, info->x86_ia32e.pml4e_value, &info->x86_ia32e.pdpte_location, &info->x86_ia32e.pdpte_value); if (status != VMI_SUCCESS) { goto done; } if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pdpte_value)) { status = VMI_FAILURE; goto done; } if (PAGE_SIZE(info->x86_ia32e.pdpte_value)) { // pdpte maps a 1GB page info->size = VMI_PS_1GB; info->paddr = get_gigpage_ia32e(vaddr, info->x86_ia32e.pdpte_value); status = VMI_SUCCESS; dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: 1GB page\n"); goto done; } status = get_pde_ia32e(vmi, vaddr, info->x86_ia32e.pdpte_value, &info->x86_ia32e.pgd_location, &info->x86_ia32e.pgd_value); if (status != VMI_SUCCESS) { goto done; } if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pgd_value)) { status = VMI_FAILURE; goto done; } if (PAGE_SIZE(info->x86_ia32e.pgd_value)) { // pde maps a 2MB page info->size = VMI_PS_2MB; info->paddr = get_2megpage_ia32e(vaddr, info->x86_ia32e.pgd_value); status = VMI_SUCCESS; dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: 2MB page\n"); goto done; } status = get_pte_ia32e(vmi, vaddr, info->x86_ia32e.pgd_value, &info->x86_ia32e.pte_location, &info->x86_ia32e.pte_value); if (status != VMI_SUCCESS) { goto done; } if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pte_value)) { status = VMI_FAILURE; goto done; } info->size = VMI_PS_4KB; info->paddr = get_paddr_ia32e(vaddr, info->x86_ia32e.pte_value); status = VMI_SUCCESS; done: dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: paddr = 0x%.16"PRIx64"\n", info->paddr); return status; }
#include <mem/page.h> #include <kernel/thread.h> #include <mem/misc/pool.h> #include <assert.h> #define STACK_SZ OPTION_GET(NUMBER, thread_stack_size) static_assert(STACK_SZ > sizeof(struct thread)); #define POOL_SZ OPTION_GET(NUMBER, thread_pool_size) typedef union thread_pool_entry { struct thread thread; char stack[STACK_SZ]; } thread_pool_entry_t __attribute__((aligned(PAGE_SIZE()))); POOL_DEF(thread_pool, thread_pool_entry_t, POOL_SZ); struct thread *thread_alloc(void) { thread_pool_entry_t *block; struct thread *t; if (!(block = (thread_pool_entry_t *) pool_alloc(&thread_pool))) { return NULL; } memset(block, 0x53, sizeof(*block)); t = &block->thread; thread_stack_init(t, STACK_SZ);