Commit 6144ba62 authored by Vikram Narayanan's avatar Vikram Narayanan

lcds: Prepare lcd creation routines for SMP

Introduce a wrapper lcd_create_module_lcds on top of lcd_create_module_lcd
to create child LCDs where we map the same code/data pages created by
the parent LCD. Add an additional parameter is_child to routines which
should differentiate between a parent and child LCD.
parent cdd190d6
......@@ -16,7 +16,7 @@
/**
* Creates the arch-dependent part of an LCD (e.g., the ept).
*/
int lcd_arch_create(struct lcd_arch **out);
int lcd_arch_create(struct lcd_arch **out, bool is_child);
/**
* Tears down arch-dep part of LCD.
*
......
......@@ -866,7 +866,7 @@ static void vmx_free_vpid(struct lcd_arch *lcd_arch)
spin_unlock(&lcd_vpids.lock);
}
int lcd_arch_create(struct lcd_arch **out)
int lcd_arch_create(struct lcd_arch **out, bool is_child)
{
struct lcd_arch *lcd_arch;
int ret;
......@@ -879,9 +879,13 @@ int lcd_arch_create(struct lcd_arch **out)
ret = -ENOMEM;
goto fail_alloc;
}
/*
* Set up ept
*/
if (is_child)
printk("%s, initializing EPT for child \n", __func__);
ret = lcd_arch_ept_init(lcd_arch);
if (ret) {
LCD_ERR("setting up etp");
......
......@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <libcap.h>
#include <liblcd/liblcd.h>
#include <lcd_domains/microkernel.h>
#include <lcd_config/post_hook.h>
......@@ -454,7 +455,7 @@ static int do_cptr_cache_init(struct cptr_cache *cache)
return 0;
}
static int get_pages_for_lcd(struct lcd_create_ctx *ctx)
static int get_pages_for_lcd(struct lcd_create_ctx *ctx, bool is_child)
{
struct page *p1, *p2, *p3;
int ret;
......@@ -543,15 +544,17 @@ static int set_struct_module(cptr_t lcd, void *m_core_bits,
#endif
int lcd_create_module_lcd(char *mdir, char *mname, cptr_t *lcd_out,
struct lcd_create_ctx **ctx_out)
struct lcd_create_ctx **ctx_out, bool is_child)
{
int ret;
cptr_t m_init_cptr, m_core_cptr;
gva_t m_init_link_addr, m_core_link_addr, m_init_func_addr;
unsigned long m_init_size, m_core_size;
static gva_t m_init_link_addr, m_core_link_addr, m_init_func_addr;
static unsigned long m_init_size, m_core_size;
unsigned long m_struct_module_core_offset;
struct lcd_create_ctx *ctx;
static struct lcd_create_ctx *parent_ctx;
cptr_t lcd;
/*
* Initialize create ctx
*/
......@@ -563,11 +566,22 @@ int lcd_create_module_lcd(char *mdir, char *mname, cptr_t *lcd_out,
/*
* Alloc boot pages, stack pages, etc. for LCD
*/
ret = get_pages_for_lcd(ctx);
ret = get_pages_for_lcd(ctx, is_child);
if (ret) {
LIBLCD_ERR("error alloc'ing boot, stack pages for LCD");
goto fail2;
}
/*
* if we are creating a child LCD, skip loading the module as it is
* already loaded in parent LCD. In child LCD, we just map the same set
* of pages to the EPT.
*/
if (is_child) {
ctx->m_init_bits = parent_ctx->m_init_bits;
ctx->m_core_bits = parent_ctx->m_core_bits;
goto create_lcd;
}
/*
* Load kernel module into caller's address space
*/
......@@ -588,7 +602,8 @@ int lcd_create_module_lcd(char *mdir, char *mname, cptr_t *lcd_out,
*
* Initialize empty LCD
*/
ret = lcd_create(&lcd);
create_lcd:
ret = lcd_create(&lcd, is_child);
if (ret) {
LIBLCD_ERR("error creating empty LCD");
goto fail4;
......@@ -632,9 +647,18 @@ int lcd_create_module_lcd(char *mdir, char *mname, cptr_t *lcd_out,
/*
* Return context and lcd
*/
LIBLCD_MSG("%s, %s LCD, ctx %p, lcd %lu", __func__, is_child ? "child" : "parent",
ctx, lcd.cptr);
*ctx_out = ctx;
*lcd_out = lcd;
/*
* Save parent ctx for the future
*/
if (!is_child) {
parent_ctx = ctx;
}
return 0;
#ifndef LCD_ISOLATE
......@@ -652,6 +676,69 @@ fail1:
return ret;
}
int lcd_create_module_lcds(char *mdir, char *mname, cptr_t *lcd_out,
struct lcd_create_ctx **ctx_out, int num_child)
{
int ret;
struct lcd *lcd_struct;
struct lcd *parent_lcd;
struct cnode *lcd_cnode;
struct cnode *parent_cnode;
int i;
/*
* create parent LCD
*/
for (i = 0; i < num_child; i++) {
LIBLCD_MSG("Creating LCD modules %d", i);
ret = lcd_create_module_lcd(mdir, mname, &lcd_out[i],
&ctx_out[i], i == 0 ? false /* parent
LCD */ :
true /* child LCD */);
if (ret) {
LIBLCD_ERR("error creating empty LCD");
goto fail2;
}
}
if (num_child) {
LIBLCD_MSG("getting parent LCD");
ret = __lcd_get(current->lcd, lcd_out[0], &parent_cnode, &parent_lcd);
if (ret)
goto fail1;
for (i = 1; i < num_child; i++) {
LIBLCD_MSG("getting child LCD %d to make link", i);
lcd_to_boot_info(ctx_out[i])->lcd_id = i;
ret = __lcd_get(current->lcd, lcd_out[i], &lcd_cnode, &lcd_struct);
if (ret)
goto fail3;
LIBLCD_MSG("adding child LCD %p to parent_lcd", lcd_struct);
list_add_tail(&parent_lcd->child_lcds, &lcd_struct->lcd_item);
lcd_struct->parent_lcd = parent_lcd;
/*
* put child LCD
*/
__lcd_put(current->lcd, lcd_cnode, lcd_struct);
}
/*
* put parent LCD
*/
fail3:
__lcd_put(current->lcd, parent_cnode, parent_lcd);
}
LIBLCD_MSG("%s creation done", __func__);
return 0;
fail2:
fail1:
return ret;
}
void lcd_destroy_create_ctx(struct lcd_create_ctx *ctx)
{
destroy_create_ctx(ctx);
......@@ -660,4 +747,5 @@ void lcd_destroy_create_ctx(struct lcd_create_ctx *ctx)
/* EXPORTS -------------------------------------------------- */
EXPORT_SYMBOL(lcd_create_module_lcd);
EXPORT_SYMBOL(lcd_create_module_lcds);
EXPORT_SYMBOL(lcd_destroy_create_ctx);
......@@ -157,6 +157,19 @@ struct lcd {
* needs to delete capability for reply endpoint)
*/
int doing_reply;
/*
* List of child LCD pointers that are tied to the parent LCD's cspace
*/
struct list_head child_lcds;
struct list_head lcd_item;
/*
* reference to the parent LCD
*/
struct lcd *parent_lcd;
bool is_child;
/*
* Send/recv queue we are on.
*
......@@ -275,14 +288,14 @@ int __lcd_create_no_vm_no_thread(struct lcd **out);
* which we need a new kthread to run the LCD's code, but we don't want
* the code to run inside an isolated VM.
*/
int __lcd_create_no_vm(struct lcd **out, const char *name);
int __lcd_create_no_vm(struct lcd **out, const char *name, bool is_child);
/**
* __lcd_create -- Create an empty isolated LCD
* @caller: the LCD doing the creating
* @slot: the slot in the @caller's cspace where the LCD capability should
* be stored
*/
int __lcd_create(struct lcd *caller, cptr_t slot);
int __lcd_create(struct lcd *caller, cptr_t slot, bool is_child);
/**
* __lcd_create_klcd -- Create an empty non-isolated LCD (kLCD)
* @caller: the LCD doing the creating
......
......@@ -35,6 +35,7 @@ struct lcd_boot_info {
gva_t module_core_base;
unsigned long module_init_size;
unsigned long module_core_size;
int lcd_id;
/*
* Capabilities to memory objects
*/
......
......@@ -38,7 +38,7 @@
* Creates a bare LCD with an empty cspace and address space (nothing is
* mapped it - except the dedicated page for the LCD's UTCB - see sync_ipc.h).
*/
int lcd_create(cptr_t *lcd);
int lcd_create(cptr_t *lcd, bool is_child);
/**
* lcd_create_klcd -- Create an LCD that runs in the non-isolated host
......@@ -177,8 +177,10 @@ struct lcd_create_ctx {
* to any other lcd, etc., this will stop and destroy the lcd.
*/
int lcd_create_module_lcd(char *mdir, char *mname, cptr_t *lcd,
struct lcd_create_ctx **ctx);
struct lcd_create_ctx **ctx, bool is_child);
int lcd_create_module_lcds(char *mdir, char *mname, cptr_t *lcd,
struct lcd_create_ctx **ctx, int num_child);
/**
* lcd_to_boot_info -- Extract lcd_boot_info from create context
* @ctx: the lcd create ctx returned from lcd_create_module_lcd
......
......@@ -8,7 +8,7 @@
#include <liblcd/liblcd.h>
#include <lcd_domains/microkernel.h>
int lcd_create(cptr_t *lcd)
int lcd_create(cptr_t *lcd, bool is_child)
{
cptr_t slot;
int ret;
......@@ -23,7 +23,7 @@ int lcd_create(cptr_t *lcd)
/*
* Make LCD
*/
ret = __lcd_create(current->lcd, slot);
ret = __lcd_create(current->lcd, slot, is_child);
if (ret) {
LIBLCD_ERR("lcd create failed");
goto fail2;
......
......@@ -13,7 +13,7 @@
#include <lcd_config/post_hook.h>
int lcd_create(cptr_t *lcd)
int lcd_create(cptr_t *lcd, bool is_child)
{
cptr_t slot;
int ret;
......
......@@ -17,12 +17,23 @@
#include <lcd_config/post_hook.h>
static int thc_initialized;
atomic_t lcd_initialized;
int
LIBLCD_FUNC_ATTR
lcd_enter(void)
{
int ret;
if (atomic_read(&lcd_initialized) == 0) {
atomic_set(&lcd_initialized, 1);
} else {
lcd_printk("===============");
lcd_printk(" Child LCD BOOTED ");
lcd_printk("===============");
return 0;
}
/*
* Aside from the call endpoint, order is important ...
*
......
......@@ -66,6 +66,10 @@ int __lcd_create_no_vm_no_thread(struct lcd **out)
* Initialize send/recv queue list element
*/
INIT_LIST_HEAD(&lcd->endpoint_queue);
/*
* Initialize child lcds queue list element
*/
INIT_LIST_HEAD(&lcd->child_lcds);
/*
* Initialize console cursor
*/
......@@ -85,18 +89,101 @@ fail1:
return ret;
}
int __lcd_create_no_vm(struct lcd **out, const char *name)
int __lcd_create_child_no_vm_no_thread(struct lcd **out)
{
struct lcd *lcd;
int ret;
/*
* More basic init
* Alloc lcd data structure
*
* (Because we're doing a zalloc, this will set the type, status,
* and so on to "defaults".)
*/
ret = __lcd_create_no_vm_no_thread(&lcd);
if (ret) {
LCD_ERR("basic lcd create failed");
lcd = kzalloc(sizeof(*lcd), GFP_KERNEL);
if (!lcd) {
LCD_ERR("error alloc'ing lcd");
ret = -ENOMEM;
goto fail1;
}
/*
* Alloc and init LCD's cspace. Use the microkernel's
* type system.
*/
lcd->cspace = cap_alloc_cspace();
if (!lcd->cspace) {
LCD_ERR("cspace alloc failed");
ret = -ENOMEM;
goto fail2;
}
ret = cap_init_cspace_with_type_system(lcd->cspace,
lcd_libcap_type_system);
if (ret) {
LCD_ERR("cspace init failed");
goto fail3;
}
/*
* Store backref (this is used during delete and revoke callbacks,
* for example, to resolve cspace -> owning lcd)
*/
cap_cspace_setowner(lcd->cspace, lcd);
/*
* Set up synchronous ipc utcb
*/
lcd->utcb = hva2va(__hva(get_zeroed_page(GFP_KERNEL)));
if (!lcd->utcb) {
LCD_ERR("utcb alloc");
goto fail2;
}
/*
* Init mutex
*/
mutex_init(&lcd->lock);
/*
* Initialize send/recv queue list element
*/
INIT_LIST_HEAD(&lcd->endpoint_queue);
INIT_LIST_HEAD(&lcd->lcd_item);
lcd->is_child = true;
/*
* Initialize console cursor
*/
lcd->console_cursor = 0;
*out = lcd;
return 0;
fail3:
fail2:
kfree(lcd);
fail1:
return ret;
}
int __lcd_create_no_vm(struct lcd **out, const char *name, bool is_child)
{
struct lcd *lcd;
int ret;
/*
* More basic init
*/
if (is_child) {
ret = __lcd_create_child_no_vm_no_thread(&lcd);
printk("%s, creating child LCD: %p\n", __func__, lcd);
if (ret) {
LCD_ERR("basic lcd create failed");
goto fail2;
}
} else {
ret = __lcd_create_no_vm_no_thread(&lcd);
if (ret) {
LCD_ERR("basic lcd create failed");
goto fail1;
}
}
/*
* Create a kernel thread (won't run till we wake it up)
*/
......@@ -124,14 +211,14 @@ fail1:
return ret;
}
int __lcd_create(struct lcd *caller, cptr_t slot)
int __lcd_create(struct lcd *caller, cptr_t slot, bool is_child)
{
struct lcd *lcd;
int ret;
/*
* Basic init of lcd
*/
ret = __lcd_create_no_vm(&lcd, "lcd");
ret = __lcd_create_no_vm(&lcd, "lcd", is_child);
if (ret) {
LCD_ERR("lcd create");
goto fail1;
......@@ -139,11 +226,12 @@ int __lcd_create(struct lcd *caller, cptr_t slot)
/*
* Alloc vm / arch-dependent part
*/
ret = lcd_arch_create(&lcd->lcd_arch);
ret = lcd_arch_create(&lcd->lcd_arch, is_child);
if(ret) {
LCD_ERR("error creating lcd_arch");
goto fail2;
}
/*
* Put in caller's cspace
*/
......@@ -174,7 +262,7 @@ int __lcd_create_klcd(struct lcd *caller, cptr_t slot)
/*
* Basic init of lcd
*/
ret = __lcd_create_no_vm(&lcd, "klcd");
ret = __lcd_create_no_vm(&lcd, "klcd", 0);
if (ret) {
LCD_ERR("lcd create");
goto fail1;
......@@ -544,6 +632,11 @@ static void destroy_kthread(struct lcd *lcd)
void __lcd_destroy_no_vm_no_thread(struct lcd *lcd)
{
struct lcd *child_lcd;
list_for_each_entry(child_lcd, &lcd->child_lcds, lcd_item) {
__lcd_destroy_no_vm_no_thread(child_lcd);
}
mark_lcd_as_dead(lcd);
destroy_cspace_and_utcb(lcd);
kfree(lcd);
......
......@@ -38,7 +38,7 @@ static int handle_syscall_create(struct lcd *lcd)
/*
* Do create
*/
return __lcd_create(lcd, lcd_slot);
return __lcd_create(lcd, lcd_slot, 0);
}
static int handle_syscall_cap_grant(struct lcd *lcd)
......
......@@ -27,7 +27,7 @@ static int boot_main(void)
*/
ret = lcd_create_module_lcd(LCD_DIR("bug/lcd"),
"lcd_test_mod_bug_lcd",
LCD_CPTR_NULL, &mi);
LCD_CPTR_NULL, &mi, 0);
if (ret) {
LIBLCD_ERR("create module lcd");
goto fail2;
......
......@@ -26,7 +26,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("async/lcd"),
"lcd_test_mod_async_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail2;
......
......@@ -36,7 +36,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("async_rpc/caller_lcd"),
"lcd_test_mod_async_rpc_caller_lcd",
&lcd1,
&ctx1);
&ctx1, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd1");
goto fail3;
......@@ -44,7 +44,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("async_rpc/callee_lcd"),
"lcd_test_mod_async_rpc_callee_lcd",
&lcd2,
&ctx2);
&ctx2, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd2");
goto fail4;
......
......@@ -32,7 +32,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("bug/lcd"),
"lcd_test_mod_bug_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("create module lcd");
goto fail2;
......
......@@ -42,7 +42,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("glue_example/vfs"),
"lcd_test_mod_glue_example_vfs",
&vfs_lcd,
&vfs_ctx);
&vfs_ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create vfs lcd");
goto fail3;
......@@ -50,7 +50,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("glue_example/minix"),
"lcd_test_mod_glue_example_minix",
&minix_lcd,
&minix_ctx);
&minix_ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create minix lcd");
goto fail4;
......
......@@ -57,7 +57,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("ioremap/lcd"),
"lcd_test_mod_ioremap_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail3;
......
......@@ -36,7 +36,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("ipc1/lcd"),
"lcd_test_mod_ipc1_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail3;
......
......@@ -36,7 +36,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("ipc2/lcd1"),
"lcd_test_mod_ipc2_lcd1",
&lcd1,
&ctx1);
&ctx1, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd1");
goto fail3;
......@@ -44,7 +44,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("ipc2/lcd2"),
"lcd_test_mod_ipc2_lcd2",
&lcd2,
&ctx2);
&ctx2, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd2");
goto fail4;
......
......@@ -59,7 +59,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("ixgbe/ixgbe_lcd"),
"lcd_test_mod_ixgbe_ixgbe_lcd",
&ixgbe_lcd,
&ixgbe_ctx);
&ixgbe_ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create ixgbe lcd");
goto fail4;
......
......@@ -26,7 +26,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("liblcd_test/lcd"),
"lcd_test_mod_liblcd_test_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail2;
......
......@@ -39,7 +39,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("llvm_example/lcd"),
"lcd_test_mod_llvm_example_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail3;
......
......@@ -27,7 +27,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("load/lcd"),
"lcd_test_mod_load_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail2;
......
......@@ -58,7 +58,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("pmfs/pmfs_lcd"),
"lcd_test_mod_pmfs_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("create module lcd");
goto destroy_vfs;
......
......@@ -192,7 +192,7 @@ static int boot_main(void)
ret = lcd_create_module_lcd(LCD_DIR("string_example/lcd"),
"lcd_test_mod_string_example_lcd",
&lcd,
&ctx);
&ctx, 0);
if (ret) {
LIBLCD_ERR("failed to create lcd");
goto fail3;
......
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