Commit c99648ed authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

liblcd-v2: Add memory itree code, simple LCD create code.

Memory itree code initializes resource tree needed for
address -> cptr translation. Provides interface for other liblcd
code to add/remove from tree (page allocator will use that).

Removed redundant nr_pages_order field from resource tree node. Its
size can be computed from the interval tree node.

Filled in some simple functions that are part of the liblcd
interface. Some are no-ops for isolated code.
parent 543e30a4
......@@ -238,4 +238,26 @@ __lcd_build_checks__(void)
#define LCD_KERNEL_MODULE_REGION_GV_ADDR \
__gva(LCD_VIRT_BASE + LCD_KERNEL_MODULE_REGION_OFFSET)
/**
* lcd_gva2gpa -- Convert a guest virtual to a guest physical address
* @gva: the guest virtual address to convert
*
* For non-isolated code, this is equivalent to __pa.
*
* For isolated code, this is LCD_PHYS_BASE + (gva - LCD_VIRT_BASE)
* Of course, this will give garbage results if gva is garbage.
*/
gpa_t lcd_gva2gpa(gva_t gva);
/**
* lcd_gpa2gva -- Convert a guest physical to a guest virtual address
* @gva: the guest physical address to convert
*
* For non-isolated code, this is equivalent to __va.
*
* For isolated code, this is LCD_VIRT_BASE + (gpa - LCD_PHYS_BASE)
* Of course, this will give garbage results if gpa is garbage.
*/
gva_t lcd_gpa2gva(gpa_t gpa);
#endif /* LCD_DOMAINS_ADDRESS_SPACES_H */
......@@ -427,7 +427,7 @@ void lcd_unvolunteer_vmalloc_mem(cptr_t vmalloc_mem);
* guest physical address @paddr
* @paddr: the physical address to search for
* @c_out: out param containing cptr to memory capability that contains @paddr
* @order_out: the memory object has size 2^order pages
* @size_out: the memory object is size bytes
*
* If @paddr meets these conditions:
*
......@@ -461,7 +461,7 @@ void lcd_unvolunteer_vmalloc_mem(cptr_t vmalloc_mem);
* (There is no way to get a cptr to a capability to individual pages
* in a chunk, since the microkernel doesn't currently support this.)
*/
int lcd_phys_to_cptr(gpa_t paddr, cptr_t *c_out, unsigned int *order_out);
int lcd_phys_to_cptr(gpa_t paddr, cptr_t *c_out, unsigned long *size_out);
/**
* lcd_phys_to_resource_node -- Look up the struct lcd_resource_node for the
* memory object that contains guest physical
......@@ -477,11 +477,11 @@ int lcd_phys_to_resource_node(gpa_t paddr, struct lcd_resource_node **n);
* guest virtual address @vaddr
* @vaddr: the virtual address to search for
* @c_out: out param containing cptr to memory capability that contains @paddr
* @order_out: the memory object has size 2^order pages
* @size_out: the memory object is size bytes
*
* Similar to lcd_phys_to_cptr. Similar error conditions.
*/
int lcd_virt_to_cptr(gva_t vaddr, cptr_t *c_out, unsigned int *order_out);
int lcd_virt_to_cptr(gva_t vaddr, cptr_t *c_out, unsigned long *size_out);
/* RESOURCE TREES -------------------------------------------------- */
......
......@@ -48,14 +48,13 @@ struct lcd_resource_tree {
*/
struct lcd_resource_node {
struct interval_tree_node it_node;
unsigned long nr_pages_order;
cptr_t cptr;
unsigned int flags;
};
enum {
LCD_RESOURCE_NODE_STATIC = 0, /* resource node statically alloc'd */
LCD_RESOURCE_NODE_KMALLOC = 1, /* resource node alloc'd via kmallc */
LCD_RESOURCE_NODE_STATIC = 1, /* resource node statically alloc'd */
LCD_RESOURCE_NODE_KMALLOC = 2, /* resource node alloc'd via kmallc */
};
static inline unsigned long
......@@ -71,9 +70,9 @@ lcd_resource_node_last(struct lcd_resource_node *n)
}
static inline unsigned long
lcd_resource_node_order(struct lcd_resource_node *n)
lcd_resource_node_size(struct lcd_resource_node *n)
{
return n->nr_pages_order;
return lcd_resource_node_last(n) - lcd_resource_node_start(n) + 1;
}
static inline cptr_t
......
......@@ -103,7 +103,6 @@ static int mo_insert_in_tree(struct lcd_resource_tree *t,
goto fail1;
}
n->cptr = mo_cptr;
n->nr_pages_order = mo->order;
n->it_node.start = __lcd_memory_object_start(mo);
n->it_node.last = __lcd_memory_object_last(mo);
/*
......@@ -549,7 +548,7 @@ void lcd_free_pages(struct page *base, unsigned int order)
cptr_t page_cptr;
int ret;
gpa_t gpa;
unsigned int actual_order;
unsigned long actual_size;
/*
* Translate page to physical address.
*
......@@ -560,12 +559,12 @@ void lcd_free_pages(struct page *base, unsigned int order)
/*
* Resolve pages to cptr
*/
ret = lcd_phys_to_cptr(gpa, &page_cptr, &actual_order);
ret = lcd_phys_to_cptr(gpa, &page_cptr, &actual_size);
if (ret) {
LIBLCD_ERR("warning: pages not found, so not freed");
return;
}
if (order != actual_order)
if (order != ilog2(actual_size >> PAGE_SHIFT))
LIBLCD_ERR("warning: order doesn't match actual order");
/*
* Remove pages from resource tree ("unmap")
......@@ -705,7 +704,7 @@ int lcd_map_virt(gpa_t base, unsigned int order, gva_t *gva_out)
{
int ret;
cptr_t mo_cptr;
unsigned int mo_order;
unsigned long mo_size;
/*
* On x86_64, all RAM is mapped already.
*
......@@ -718,7 +717,7 @@ int lcd_map_virt(gpa_t base, unsigned int order, gva_t *gva_out)
*
* guest virtual == host virtual for non-isolated
*/
ret = lcd_phys_to_cptr(base, &mo_cptr, &mo_order);
ret = lcd_phys_to_cptr(base, &mo_cptr, &mo_size);
if (ret) {
LIBLCD_ERR("phys not mapped?");
goto fail1;
......@@ -757,14 +756,14 @@ void lcd_unmap_phys(gpa_t base, unsigned int order)
{
int ret;
cptr_t mo_cptr;
unsigned int mo_order;
unsigned long mo_size;
/*
* No real unmapping needs to be done, but we need to
* update the resource tree.
*
* Look up cptr for physical memory
*/
ret = lcd_phys_to_cptr(base, &mo_cptr, &mo_order);
ret = lcd_phys_to_cptr(base, &mo_cptr, &mo_size);
if (ret) {
LIBLCD_ERR("phys not mapped?");
return;
......@@ -924,7 +923,7 @@ void lcd_unvolunteer_vmalloc_mem(cptr_t vmalloc_mem)
/* ADDRESS -> CPTR TRANSLATION ---------------------------------------- */
int lcd_phys_to_cptr(gpa_t paddr, cptr_t *c_out, unsigned int *order_out)
int lcd_phys_to_cptr(gpa_t paddr, cptr_t *c_out, unsigned long *size_out)
{
int ret;
struct lcd_resource_node *n;
......@@ -945,7 +944,7 @@ int lcd_phys_to_cptr(gpa_t paddr, cptr_t *c_out, unsigned int *order_out)
* Pull out memory object cptr and order
*/
*c_out = n->cptr;
*order_out = n->nr_pages_order;
*size_out = lcd_resource_node_size(n);
return 0;
......@@ -953,7 +952,7 @@ fail1:
return ret;
}
int lcd_virt_to_cptr(gva_t vaddr, cptr_t *c_out, unsigned int *order_out)
int lcd_virt_to_cptr(gva_t vaddr, cptr_t *c_out, unsigned long *size_out)
{
gpa_t gpa;
struct lcd_resource_node *n;
......@@ -973,13 +972,13 @@ int lcd_virt_to_cptr(gva_t vaddr, cptr_t *c_out, unsigned int *order_out)
* guest phys = host phys.
*/
gpa = __gpa(hpa_val(hva2hpa(__hva(gva_val(vaddr)))));
return lcd_phys_to_cptr(gpa, c_out, order_out);
return lcd_phys_to_cptr(gpa, c_out, size_out);
}
/*
* Pull out memory object cptr and order
*/
*c_out = n->cptr;
*order_out = n->nr_pages_order;
*size_out = lcd_resource_node_size(n);
return 0;
}
......@@ -1009,3 +1008,15 @@ void lcd_free_memcg_kmem_pages(unsigned long addr, unsigned int order)
/* Non-isolated code probably should never call this. */
BUG();
}
/* ADDRESS TRANSLATION -------------------------------------------------- */
gpa_t lcd_gva2gpa(gva_t gva)
{
return __gpa(__pa((void *)gva_val(gva)));
}
gva_t lcd_gpa2gva(gpa_t gpa)
{
return __gva((unsigned long)__va(gpa_val(gpa)));
}
/*
* create.c
*
* Simple LCD create functions, configuration.
*
* Copyright: University of Utah
*/
#include <lcd_config/pre_hook.h>
#include <liblcd/create.h>
#include <lcd_config/post_hook.h>
int lcd_create(cptr_t *lcd)
{
cptr_t slot;
int ret;
/*
* Alloc cptr
*/
ret = lcd_cptr_alloc(&slot);
if (ret) {
LIBLCD_ERR("cptr alloc failed");
goto fail1;
}
/*
* Create LCD syscall
*/
ret = lcd_syscall_create(slot);
if (ret) {
LIBLCD_ERR("lcd create failed");
goto fail2;
}
*lcd = slot;
return 0;
fail2:
lcd_cptr_free(slot);
fail1:
return ret;
}
int lcd_create_klcd(cptr_t *klcd)
{
return -ENOSYS; /* not available in isolated LCDs */
}
int lcd_config_registers(cptr_t lcd, gva_t pc, gva_t sp, gpa_t gva_root,
gpa_t utcb_page)
{
return lcd_syscall_config_registers(lcd, pc, sp, gva_root, utcb_page);
}
int lcd_memory_grant_and_map(cptr_t lcd, cptr_t mo, cptr_t dest_slot,
gpa_t base)
{
return lcd_syscall_memory_grant_and_map(lcd, mo, dest_slot, base);
}
int lcd_cap_grant(cptr_t lcd, cptr_t src, cptr_t dest)
{
return lcd_syscall_grant(lcd, src, dest);
}
int lcd_run(cptr_t lcd)
{
return lcd_syscall_run(lcd);
}
/*
* mem.c
*
* Isolated liblcd page allocator and related
* code.
*/
#include <lcd_config/pre_hook.h>
#include <liblcd/mem.h>
#include <lcd_config/post_hook.h>
/* VOLUNTEERING -------------------------------------------------- */
int lcd_volunteer_pages(struct page *base, unsigned int order,
cptr_t *slot_out)
{
unsigned long size;
return lcd_phys_to_cptr(
lcd_gva2gpa(__gva((unsigned long)lcd_page_address(base))),
slot_out, &size);
}
void lcd_unvolunteer_pages(cptr_t pages)
{
return;
}
int lcd_volunteer_dev_mem(gpa_t base, unsigned int order,
cptr_t *slot_out)
{
unsigned long size;
return lcd_phys_to_cptr(base, slot_out, &size);
}
void lcd_unvolunteer_dev_mem(cptr_t devmem)
{
return;
}
int lcd_volunteer_vmalloc_mem(gva_t base, unsigned int order,
cptr_t *slot_out)
{
unsigned long size;
return lcd_virt_to_cptr(base, slot_out, &size);
}
void lcd_unvolunteer_vmalloc_mem(cptr_t vmalloc_mem)
{
return;
}
/* ADDRESS TRANSLATION -------------------------------------------------- */
gpa_t lcd_gva2gpa(gva_t gva)
{
return __gpa(LCD_PHYS_BASE + (gva_val(gva) - LCD_VIRT_BASE));
}
gva_t lcd_gpa2gva(gpa_t gpa)
{
return __gva(LCD_VIRT_BASE + (gpa_val(gpa) - LCD_PHYS_BASE));
}
/* INIT/EXIT -------------------------------------------------- */
int lcd_mem_init(void)
{
}
/*
* mem_itree.c
*
* Resource trees used for address -> cptr translation.
*
* Copyright: University of Utah
*/
#include <lcd_config/pre_hook.h>
#include <liblcd/resource_tree.h>
#include <liblcd/boot_info.h>
#include <lcd_domains/liblcd.h>
#include <lcd_config/post_hook.h>
#define LCD_NR_BOOT_RESOURCE_NODES 16
static struct lcd_resource_tree itree;
static struct lcd_resource_node boot_nodes[LCD_NR_BOOT_RESOURCE_NODES];
static unsigned int boot_nodes_brk;
static int mem_itree_booted;
static void free_itree_node(struct lcd_resource_node *n)
{
if (n->flags & LCD_RESOURCE_NODE_STATIC)
return; /* node came from boot node array */
else
kfree(n);
}
static struct lcd_resource_node *early_alloc_itree_node(void)
{
if (boot_nodes_brk >= LCD_NR_BOOT_RESOURCE_NODES) {
LIBLCD_ERR("exhausted boot resource nodes");
return NULL;
} else {
return &boot_nodes[++boot_nodes_brk];
}
}
static struct lcd_resource_node *alloc_itree_node(void)
{
struct lcd_resource_node *n;
if (likely(mem_itree_booted)) {
n = kzalloc(sizeof(struct lcd_resource_node), GFP_KERNEL);
if (!n) {
LIBLCD_ERR("kmalloc failed");
return NULL;
}
n->flags = LCD_RESOURCE_NODE_KMALLOC;
return n;
} else {
n = early_alloc_itree_node();
if (!n)
return NULL;
n->flags = LCD_RESOURCE_NODE_STATIC;
return n;
}
}
/* INTERFACE -------------------------------------------------- */
int __liblcd_mem_itree_insert(gpa_t start, unsigned long size,
cptr_t mem_cptr)
{
struct lcd_resource_node *n;
n = alloc_itree_node();
if (!n) {
LIBLCD_ERR("failed to get a node");
goto fail1;
}
n->it_node.start = gpa_val(start);
n->it_node.last = gpa_val(start) + size - 1;
n->cptr = mem_cptr;
lcd_resource_tree_insert(&itree, n);
return 0;
fail1:
return -ENOMEM;
}
int lcd_phys_to_resource_node(gpa_t paddr, struct lcd_resource_node **n_out)
{
struct lcd_resource_node *n;
int ret;
/*
* Lookup
*/
ret = lcd_resource_tree_search(&itree, gpa_val(paddr), &n);
if (ret) {
LIBLCD_ERR("lookup failed");
goto fail1;
}
*n_out = n;
return 0;
fail1:
return ret;
}
int lcd_phys_to_cptr(gpa_t paddr, cptr_t *c_out, unsigned long *size_out)
{
struct lcd_resource_node *n;
int ret;
ret = lcd_phys_to_resource_node(paddr, &n);
if (ret)
return ret;
*c_out = n->cptr;
*size_out = lcd_resource_node_size(n);
return 0;
}
int lcd_virt_to_cptr(gva_t vaddr, cptr_t *c_out, unsigned long *size_out)
{
return lcd_phys_to_cptr(lcd_gva2gpa(vaddr), c_out, size_out);
}
/* INIT -------------------------------------------------- */
void __liblcd_mem_itree_booted(void)
{
mem_itree_booted = 1;
}
static int add_boot_memory(void)
{
struct lcd_resource_node *n;
/*
* Add module init
*/
n = alloc_itree_node();
if (!n)
goto fail1;
n->it_node.start = __liblcd_pa(THIS_MODULE->module_init);
n->it_node.last = n->it_node.start + THIS_MODULE->init_size - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.module_init;
lcd_tree_insert(&itree, n);
/*
* Add module core
*/
n = alloc_itree_node();
if (!n)
goto fail2;
n->it_node.start = __liblcd_pa(THIS_MODULE->module_core);
n->it_node.last = n->it_node.start + THIS_MODULE->core_size - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.module_core;
lcd_tree_insert(&itree, n);
/*
* Add bootstrap pages
*/
n = alloc_itree_node();
if (!n)
goto fail3;
n->it_node.start = gpa_val(LCD_BOOTSTRAP_PAGES_GP_ADDR);
n->it_node.last = gpa_val(LCD_BOOTSTRAP_PAGES_GP_ADDR) +
LCD_BOOTSTRAP_PAGES_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.boot_pages;
lcd_tree_insert(&itree, n);
/*
* Add stack pages
*/
n = alloc_itree_node();
if (!n)
goto fail4;
n->it_node.start = gpa_val(LCD_STACK_GP_ADDR);
n->it_node.last = gpa_val(LCD_STACK_GP_ADDR) +
LCD_STACK_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.stack;
lcd_tree_insert(&itree, n);
/*
* Add boot guest virtual page tables
*/
n = alloc_itree_node();
if (!n)
goto fail5;
n->it_node.start = gpa_val(LCD_BOOTSTRAP_PAGE_TABLES_GP_ADDR);
n->it_node.last = gpa_val(LCD_BOOTSTRAP_PAGE_TABLES_GP_ADDR) +
LCD_BOOTSTRAP_PAGE_TABLES_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.gv;
lcd_tree_insert(&itree, n);
fail5:
fail4:
fail3:
fail2:
fail1:
return -ENOMEM; /* we don't bother "freeing" nodes */
}
int __liblcd_mem_itree_init(void)
{
int ret;
/*
* Init resource tree root
*/
ret = lcd_resource_tree_init(&itree);
if (ret) {
LIBLCD_ERR("resource tree init failed");
goto fail1;
}
/*
* Add existing memory (at boot) to resource tree
*/
ret = add_boot_memory();
if (ret) {
LIBLCD_ERR("failed to add resource nodes for boot mem");
goto fail2;
}
}
/*
* module_load.c
*
* For loading a kernel module from disk.
*
* Copyright: University of Utah
*/
#include <lcd_config/pre_hook.h>
#include <liblcd/module_load.h>
#include <lcd_config/post_hook.h>
int lcd_load_module(char *mdir, char *mname,
void **m_init_bits,
void **m_core_bits,
cptr_t *m_init_pages,
cptr_t *m_core_pages,
gva_t *m_init_link_addr,
gva_t *m_core_link_addr)
{
return -ENOSYS; /* not implemented */
}
void lcd_release_module(void *m_init_bits, void *m_core_bits)
{
return; /* not implemented */
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment