Commit 699f55df authored by Vikram Narayanan's avatar Vikram Narayanan

lcd/smp: Introduce per-lcd gs page

Introduce per-lcd global segment page where each lcd will have its
boot_info. Modify lcd_get_boot_info to pull the page from gs instead of
a hardcoded address. Now, only gs:0x0 is populated. In the future, if
needed, we can have other private per-lcd variables as well.
parent 7c485a35
......@@ -165,7 +165,7 @@
#define LCD_BOOTSTRAP_PAGES_SIZE (1 * PAGE_SIZE) /* .......... 4 KBs */
#define LCD_BOOTSTRAP_PAGE_TABLES_SIZE (16 * PAGE_SIZE) /* ... 64 KBs */
#define LCD_STACK_SIZE (2 * PAGE_SIZE) /* .................... 8 KBs */
#define LCD_STACK_PROT_SIZE PAGE_SIZE /* ..................... 4 KBs */
#define LCD_GLOBAL_SEGMENT_SIZE PAGE_SIZE /* ..................... 4 KBs */
/* Orders (for convenience) */
......@@ -175,8 +175,8 @@
(ilog2(LCD_BOOTSTRAP_PAGE_TABLES_SIZE >> PAGE_SHIFT))
#define LCD_STACK_ORDER \
(ilog2(LCD_STACK_SIZE >> PAGE_SHIFT))
#define LCD_STACK_PROT_ORDER \
(ilog2(LCD_STACK_PROT_SIZE >> PAGE_SHIFT))
#define LCD_GLOBAL_SEGMENT_ORDER \
(ilog2(LCD_GLOBAL_SEGMENT_SIZE >> PAGE_SHIFT))
/* Offsets. */
......@@ -184,10 +184,12 @@
#define LCD_UTCB_OFFSET LCD_MISC_REGION_OFFSET
#define LCD_BOOTSTRAP_PAGES_OFFSET (LCD_UTCB_OFFSET + LCD_UTCB_SIZE)
#ifndef CONFIG_LCD_SINGLE_EPT
#define LCD_BOOTSTRAP_PAGE_TABLES_OFFSET \
(LCD_BOOTSTRAP_PAGES_OFFSET + LCD_BOOTSTRAP_PAGES_SIZE)
#define LCD_STACK_PROT_PAGE_OFFSET \
(LCD_BOOTSTRAP_PAGE_TABLES_OFFSET+ LCD_BOOTSTRAP_PAGE_TABLES_SIZE)
#endif /* CONFIG_LCD_SINGLE_EPT */
/* HOLE */
......@@ -224,7 +226,10 @@
* | (1 GB) |
* +---------------------------+ 0x0000 0000 8000 0000 (2 GB)
* | Bootstrap Pagetable |
* | Pages (512 MB) |
* | Pages (256 MB) |
* +---------------------------+ (1 GB + 768 MB)
* | Global segment |
* | Pages (256MB) |
* +---------------------------+ (1 GB + 512 MB)
* | Bootstrap Pages |
* | (256MB) |
......@@ -236,20 +241,31 @@
/* Region Sizes */
#define LCD_UTCB_REGION_SIZE (1UL << 28) /* .................. 256 MBs */
#define LCD_BOOTSTRAP_PAGES_REGION_SIZE (1UL << 28) /* ........... 256 MBs */
#define LCD_GLOBAL_SEGMENT_PAGE_REGION_SIZE (1UL << 28) /* ........... 256 MBs */
/* Region offsets */
#define LCD_BOOTSTRAP_PAGES_REGION_OFFSET \
(LCD_UTCB_OFFSET + LCD_UTCB_REGION_SIZE)
#define LCD_BOOTSTRAP_PAGE_TABLES_REGION_OFFSET \
#define LCD_GLOBAL_SEGMENT_PAGE_REGION_OFFSET \
(LCD_BOOTSTRAP_PAGES_REGION_OFFSET + LCD_BOOTSTRAP_PAGES_REGION_SIZE)
#define LCD_BOOTSTRAP_PAGE_TABLES_REGION_OFFSET \
(LCD_GLOBAL_SEGMENT_PAGE_REGION_OFFSET+ LCD_GLOBAL_SEGMENT_PAGE_REGION_SIZE)
#define LCD_BOOTSTRAP_PAGE_TABLES_OFFSET LCD_BOOTSTRAP_PAGE_TABLES_REGION_OFFSET
#define LCD_GLOBAL_SEGMENT_PAGE_OFFSET LCD_GLOBAL_SEGMENT_PAGE_REGION_OFFSET
/* Offsets for LCDs within a region */
#define LCD_UTCB_OFFSET_CHILD(id) \
(LCD_MISC_REGION_OFFSET + (id * LCD_UTCB_SIZE))
(LCD_MISC_REGION_OFFSET + ((id) * LCD_UTCB_SIZE))
#define LCD_BOOTSTRAP_PAGES_OFFSET_CHILD(id) (LCD_BOOTSTRAP_PAGES_REGION_OFFSET \
+ ((id) * LCD_BOOTSTRAP_PAGES_SIZE))
#define LCD_GLOBAL_SEGMENT_PAGE_OFFSET_CHILD(id) (LCD_GLOBAL_SEGMENT_PAGE_REGION_OFFSET \
+ ((id) * LCD_GLOBAL_SEGMENT_SIZE))
#define LCD_BOOTSTRAP_PAGES_OFFSET_CHILD(id) (LCD_UTCB_OFFSET \
+ LCD_UTCB_REGION_SIZE + ((id) * LCD_BOOTSTRAP_PAGES_SIZE))
#define LCD_STACK_OFFSET_CHILD(id) \
(LCD_STACK_REGION_OFFSET + LCD_STACK_REGION_SIZE \
......@@ -265,15 +281,25 @@
/* Bootstrap pages */
#define LCD_BOOTSTRAP_PAGES_GP_ADDR_CHILD(id) \
(__gpa(LCD_PHYS_BASE + LCD_BOOTSTRAP_PAGES_OFFSET_CHILD(id)))
#define LCD_BOOTSTRAP_PAGES_GV_ADDR_LCD(id) \
#define LCD_BOOTSTRAP_PAGES_GV_ADDR_CHILD(id) \
(__gva(LCD_VIRT_BASE + LCD_BOOTSTRAP_PAGES_OFFSET_CHILD(id)))
/* global segment pages */
#define LCD_GLOBAL_SEGMENT_PAGE_GP_ADDR_CHILD(id) \
(__gpa(LCD_PHYS_BASE + LCD_GLOBAL_SEGMENT_PAGE_OFFSET_CHILD(id)))
#define LCD_GLOBAL_SEGMENT_PAGE_GV_ADDR_CHILD(id) \
(__gva(LCD_VIRT_BASE + LCD_GLOBAL_SEGMENT_PAGE_OFFSET_CHILD(id)))
/* Stack pages */
#define LCD_STACK_GP_ADDR_CHILD(id) (__gpa(LCD_PHYS_BASE \
+ LCD_STACK_OFFSET_CHILD(id)))
#define LCD_STACK_GV_ADDR_CHILD(id) (__gva(LCD_VIRT_BASE \
+ LCD_STACK_OFFSET_CHILD(id)))
#define LCD_ARCH_GS_BASE_CHILD(id) __gpa(LCD_PHYS_BASE \
+ LCD_GLOBAL_SEGMENT_PAGE_OFFSET_CHILD(id))
#define LCD_ARCH_GS_GV_BASE_CHILD(id) __gva(LCD_VIRT_BASE \
+ LCD_GLOBAL_SEGMENT_PAGE_OFFSET_CHILD(id))
#endif /* CONFIG_LCD_SINGLE_EPT */
/* HOLE */
......@@ -338,8 +364,8 @@
#define LCD_ARCH_FS_BASE __gpa(0UL)
#define LCD_ARCH_FS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GS_BASE __gpa(LCD_PHYS_BASE + LCD_STACK_PROT_PAGE_OFFSET)
#define LCD_ARCH_GS_GV_BASE __gva(LCD_VIRT_BASE + LCD_STACK_PROT_PAGE_OFFSET)
#define LCD_ARCH_GS_BASE __gpa(0UL)
#define LCD_ARCH_GS_GV_BASE __gva(0UL)
#define LCD_ARCH_GS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GDTR_BASE __gpa(0UL)
#define LCD_ARCH_GDTR_LIMIT 0x0 /* no gdt */
......
......@@ -189,8 +189,15 @@ static int setup_phys_addr_space_child_lcd(cptr_t lcd,
if (ret)
goto fail2;
c = &(lcd_to_boot_info(ctx)->lcd_boot_cptrs.gs_page);
ret = do_grant_and_map_for_mem(lcd, ctx, ctx->gs_page,
LCD_ARCH_GS_BASE_CHILD(lcd_id), c);
if (ret)
goto fail3;
return 0;
fail3:
fail2: /* Just return; caller should kill new LCD and free up resources. */
fail1:
return ret;
......@@ -228,9 +235,9 @@ static int setup_phys_addr_space(cptr_t lcd, struct lcd_create_ctx *ctx,
if (ret)
goto fail3;
c = &(lcd_to_boot_info(ctx)->lcd_boot_cptrs.stack_prot);
ret = do_grant_and_map_for_mem(lcd, ctx, ctx->stack_prot,
LCD_ARCH_GS_BASE, c);
c = &(lcd_to_boot_info(ctx)->lcd_boot_cptrs.gs_page);
ret = do_grant_and_map_for_mem(lcd, ctx, ctx->gs_page,
LCD_ARCH_GS_BASE_CHILD(lcd_id), c);
if (ret)
goto fail4;
......@@ -571,14 +578,14 @@ alloc_stack:
/*
* Alloc stack protector page
*/
p4 = lcd_alloc_pages(0, LCD_STACK_PROT_ORDER);
p4 = lcd_alloc_pages(0, LCD_GLOBAL_SEGMENT_ORDER);
if (!p4) {
LIBLCD_ERR("alloc stack prot pages failed");
ret = -ENOMEM;
goto fail5;
}
memset(lcd_page_address(p4), 0, LCD_STACK_PROT_SIZE);
ctx->stack_prot = lcd_page_address(p4);
memset(lcd_page_address(p4), 0, LCD_GLOBAL_SEGMENT_SIZE);
ctx->gs_page = lcd_page_address(p4);
return 0;
......@@ -714,6 +721,7 @@ create_lcd:
/*
* Configure initial control registers, etc. for LCD
*/
*((unsigned long *)ctx->gs_page) = gva_val(LCD_BOOTSTRAP_PAGES_GV_ADDR_CHILD(current_lcd));
ret = lcd_config_registers(lcd, m_init_func_addr,
/* implicity put a null return address and
* frame address */
......@@ -721,7 +729,7 @@ create_lcd:
LCD_STACK_SIZE - sizeof(void *)),
LCD_BOOTSTRAP_PAGE_TABLES_GP_ADDR,
LCD_UTCB_GP_ADDR_CHILD(current_lcd),
LCD_ARCH_GS_GV_BASE);
LCD_ARCH_GS_GV_BASE_CHILD(current_lcd));
if (ret) {
LIBLCD_ERR("error configuring LCDs registers");
......
......@@ -28,7 +28,7 @@
*
* This should be called before the page allocator inits.
*/
int __liblcd_mem_itree_init(void);
int __liblcd_mem_itree_init(int lcd_id);
/**
* __liblcd_mem_itree_booted -- Call this when kmalloc is initialized
*
......
......@@ -21,7 +21,7 @@ struct lcd_boot_cptrs {
cptr_t boot_pages;
cptr_t stack;
cptr_t gv;
cptr_t stack_prot;
cptr_t gs_page;
};
struct lcd_boot_info {
......@@ -47,6 +47,8 @@ struct lcd_boot_info {
cptr_t cptrs[LCD_NUM_BOOT_CPTRS];
};
#define current_lcd_id (lcd_get_boot_info()->lcd_id)
/**
* lcd_get_boot_info -- Return the bootstrap info
*
......
......@@ -148,7 +148,7 @@ struct lcd_create_ctx {
void *stack;
void *m_init_bits;
void *m_core_bits;
void *stack_prot;
void *gs_page;
};
/**
......
......@@ -17,5 +17,14 @@ struct lcd_boot_info *
LIBLCD_FUNC_ATTR
lcd_get_boot_info(void)
{
return (struct lcd_boot_info *)gva_val(LCD_BOOTSTRAP_PAGES_GV_ADDR);
#ifdef CONFIG_LCD_SINGLE_EPT
struct lcd_boot_info *info;
asm volatile ("movq %%gs:0x0, %[info]"
:[info]"=r"(info));
return info;
#else
return (struct lcd_boot_info *)gva_val(LCD_BOOTSTRAP_PAGES_GV_ADDR_CHILD(current_lcd_id));
#endif
}
......@@ -19,6 +19,8 @@
static int thc_initialized;
atomic_t lcd_initialized;
static int lcds_entered = 0;
int
LIBLCD_FUNC_ATTR
lcd_enter(void)
......@@ -31,6 +33,14 @@ lcd_enter(void)
lcd_printk("===============");
lcd_printk(" Child LCD BOOTED ");
lcd_printk("===============");
ret = _lcd_create_sync_endpoint(LCD_CPTR_CALL_ENDPOINT);
if (ret) {
LIBLCD_ERR("creating call endpoint");
goto fail;
}
LIBLCD_MSG("call endpoint created and installed for child LCD");
return 0;
}
......@@ -51,7 +61,7 @@ lcd_enter(void)
/*
* Set up internal memory interval tree / resource tree
*/
ret = __liblcd_mem_itree_init();
ret = __liblcd_mem_itree_init(lcds_entered);
if (ret) {
LIBLCD_ERR("failed to init memory interval tree");
goto fail;
......@@ -119,6 +129,8 @@ lcd_enter(void)
lcd_printk(" LCD BOOTED ");
lcd_printk("===============");
++lcds_entered;
return 0;
fail:
......
......@@ -174,7 +174,7 @@ void __liblcd_mem_itree_booted(void)
node_cache = KMEM_CACHE(lcd_resource_node, 0);
}
static int add_boot_memory(void)
static int add_boot_memory(int lcd_id)
{
struct lcd_resource_node *n;
/*
......@@ -186,6 +186,8 @@ static int add_boot_memory(void)
n->start = gpa_val(lcd_gva2gpa(lcd_get_boot_info()->module_init_base));
n->last = n->start + lcd_get_boot_info()->module_init_size - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.module_init;
LIBLCD_MSG("%s, module_init start 0x%X | last 0x%X | cptr %llu", __func__,
n->start, n->last, cptr_val(n->cptr));
lcd_resource_tree_insert(&itree, n);
/*
* Add module core
......@@ -196,6 +198,8 @@ static int add_boot_memory(void)
n->start = gpa_val(lcd_gva2gpa(lcd_get_boot_info()->module_core_base));
n->last = n->start + lcd_get_boot_info()->module_core_size - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.module_core;
LIBLCD_MSG("%s, module_core start 0x%X | last 0x%X | cptr %lu", __func__,
n->start, n->last, cptr_val(n->cptr));
lcd_resource_tree_insert(&itree, n);
/*
* Add bootstrap pages
......@@ -203,10 +207,12 @@ static int add_boot_memory(void)
n = alloc_itree_node();
if (!n)
goto fail3;
n->start = gpa_val(LCD_BOOTSTRAP_PAGES_GP_ADDR);
n->last = gpa_val(LCD_BOOTSTRAP_PAGES_GP_ADDR) +
n->start = gpa_val(LCD_BOOTSTRAP_PAGES_GP_ADDR_CHILD(lcd_id));
n->last = gpa_val(LCD_BOOTSTRAP_PAGES_GP_ADDR_CHILD(lcd_id)) +
LCD_BOOTSTRAP_PAGES_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.boot_pages;
LIBLCD_MSG("%s, bootstrap pages start 0x%X | last 0x%X | cptr %llu", __func__,
n->start, n->last, cptr_val(n->cptr));
lcd_resource_tree_insert(&itree, n);
/*
* Add stack pages
......@@ -214,21 +220,23 @@ static int add_boot_memory(void)
n = alloc_itree_node();
if (!n)
goto fail4;
n->start = gpa_val(LCD_STACK_GP_ADDR);
n->last = gpa_val(LCD_STACK_GP_ADDR) +
n->start = gpa_val(LCD_STACK_GP_ADDR_CHILD(lcd_id));
n->last = gpa_val(LCD_STACK_GP_ADDR_CHILD(lcd_id)) +
LCD_STACK_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.stack;
LIBLCD_MSG("%s, stack pages start 0x%X | last 0x%X | cptr %llu", __func__,
n->start, n->last, cptr_val(n->cptr));
lcd_resource_tree_insert(&itree, n);
/*
* Add stack canary pages
* Add global segment page
*/
n = alloc_itree_node();
if (!n)
goto fail5;
n->start = gpa_val(LCD_ARCH_GS_BASE);
n->last = gpa_val(LCD_ARCH_GS_BASE) +
LCD_STACK_PROT_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.stack_prot;
n->start = gpa_val(LCD_ARCH_GS_BASE_CHILD(lcd_id));
n->last = gpa_val(LCD_ARCH_GS_BASE_CHILD(lcd_id)) +
LCD_GLOBAL_SEGMENT_SIZE - 1;
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.gs_page;
lcd_resource_tree_insert(&itree, n);
/*
* Add boot guest virtual page tables
......@@ -240,6 +248,8 @@ static int add_boot_memory(void)
n->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;
LIBLCD_MSG("%s, bootstrap PT pages start 0x%X | last 0x%X | cptr %llu", __func__,
n->start, n->last, cptr_val(n->cptr));
lcd_resource_tree_insert(&itree, n);
return 0;
......@@ -253,7 +263,7 @@ fail1:
return -ENOMEM; /* we don't bother "freeing" nodes */
}
int __liblcd_mem_itree_init(void)
int __liblcd_mem_itree_init(int lcd_id)
{
int ret;
/*
......@@ -267,7 +277,7 @@ int __liblcd_mem_itree_init(void)
/*
* Add existing memory (at boot) to resource tree
*/
ret = add_boot_memory();
ret = add_boot_memory(lcd_id);
if (ret) {
LIBLCD_ERR("failed to add resource nodes for boot mem");
goto fail2;
......
......@@ -16,7 +16,7 @@ struct lcd_utcb *
LIBLCD_FUNC_ATTR
lcd_get_utcb(void)
{
return (struct lcd_utcb *)gva_val(LCD_UTCB_GV_ADDR);
return (struct lcd_utcb *)gva_val(LCD_UTCB_GV_ADDR_CHILD(current_lcd_id));
}
int
......
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