Commit 7c485a35 authored by Vikram Narayanan's avatar Vikram Narayanan

lcd: add gs segment support

Earlier the gs base was set to NULL. Now allocate a page
and configure lcd to use that page for saving and retrieving
the stack canary. Apart from stack canaries gs can be used for other
purposes as well (Such as percpu).
parent 4f3bddd0
......@@ -46,6 +46,9 @@ int lcd_arch_set_sp(struct lcd_arch *lcd_arch, gva_t a);
* guest physical address a.
*/
int lcd_arch_set_gva_root(struct lcd_arch *lcd_arch, gpa_t a);
int lcd_arch_set_gs_base(struct lcd_arch *lcd_arch, gva_t a);
/**
* Allocate memory for the VMCS for an LCD.
*/
......
......@@ -124,6 +124,32 @@ static inline int lcd_syscall_five_args(int id,
return (int)ret;
}
static inline int lcd_syscall_six_args(int id,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5)
{
long ret;
asm volatile(
"movq %7, %%r13 \n\t"
"movq %6, %%r12 \n\t"
"movq %5, %%r11 \n\t"
"movq %4, %%r10 \n\t"
"movq %3, %%r9 \n\t"
"movq %2, %%r8 \n\t"
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id), "g" (arg0), "g" (arg1), "g" (arg2), "g" (arg3),
"g" (arg4), "g" (arg5)
: "rax", "r8", "r9", "r10", "r11", "r12", "r13");
return (int)ret;
}
static inline void lcd_syscall_cap_delete(cptr_t cptr)
{
lcd_syscall_one_arg(LCD_SYSCALL_CAP_DELETE, cptr_val(cptr));
......@@ -152,11 +178,11 @@ static inline int lcd_syscall_create(cptr_t lcd_slot)
static inline int lcd_syscall_config_registers(cptr_t lcd, gva_t pc,
gva_t sp, gpa_t gva_root,
gpa_t utcb_page)
gpa_t utcb_page, gva_t gs_base)
{
return lcd_syscall_five_args(LCD_SYSCALL_CONFIG_REGISTERS,
return lcd_syscall_six_args(LCD_SYSCALL_CONFIG_REGISTERS,
cptr_val(lcd), gva_val(pc), gva_val(sp),
gpa_val(gva_root), gpa_val(utcb_page));
gpa_val(gva_root), gpa_val(utcb_page), gva_val(gs_base));
}
static inline int lcd_syscall_memory_grant_and_map(cptr_t lcd,
......
......@@ -415,6 +415,10 @@ static inline u64 lcd_arch_get_syscall_arg4(struct lcd_arch *lcd)
{
return lcd->regs.r12;
}
static inline u64 lcd_arch_get_syscall_arg5(struct lcd_arch *lcd)
{
return lcd->regs.r13;
}
static inline void lcd_arch_set_syscall_ret(struct lcd_arch *lcd, u64 val)
{
lcd->regs.rax = val;
......
......@@ -65,6 +65,10 @@ static inline u64 lcd_arch_get_syscall_arg4(struct lcd_arch *lcd)
{
return lcd->regs.r12;
}
static inline u64 lcd_arch_get_syscall_arg5(struct lcd_arch *lcd)
{
return lcd->regs.r13;
}
static inline void lcd_arch_set_syscall_ret(struct lcd_arch *lcd, u64 val)
{
lcd->regs.rax = val;
......
......@@ -165,6 +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 */
/* Orders (for convenience) */
......@@ -174,6 +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))
/* Offsets. */
......@@ -183,6 +186,8 @@
#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)
/* HOLE */
......@@ -333,7 +338,8 @@
#define LCD_ARCH_FS_BASE __gpa(0UL)
#define LCD_ARCH_FS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GS_BASE __gpa(0UL)
#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_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GDTR_BASE __gpa(0UL)
#define LCD_ARCH_GDTR_LIMIT 0x0 /* no gdt */
......
......@@ -1067,3 +1067,12 @@ void lcd_arch_irq_enable(struct lcd_arch *lcd_arch)
PIN_BASED_EXT_INTR_MASK);
vmx_put_cpu(lcd_arch);
}
int lcd_arch_set_gs_base(struct lcd_arch *lcd_arch, gva_t a)
{
lcd_arch->regs.gs = gva_val(a);
vmx_get_cpu(lcd_arch);
vmcs_writel(GUEST_GS_BASE, gva_val(a));
vmx_put_cpu(lcd_arch);
return 0;
}
......@@ -227,6 +227,13 @@ static int setup_phys_addr_space(cptr_t lcd, struct lcd_create_ctx *ctx,
LCD_STACK_GP_ADDR_CHILD(lcd_id), c);
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);
if (ret)
goto fail4;
/*
* Map and grant kernel module
*/
......@@ -234,11 +241,12 @@ static int setup_phys_addr_space(cptr_t lcd, struct lcd_create_ctx *ctx,
m_init_link_addr, m_core_link_addr,
m_init_size, m_core_size);
if (ret)
goto fail4;
goto fail5;
return 0;
fail4: /* Just return; caller should kill new LCD and free up resources. */
fail5: /* Just return; caller should kill new LCD and free up resources. */
fail4:
fail3:
fail2:
fail1:
......@@ -506,7 +514,7 @@ static int do_cptr_cache_init(struct cptr_cache *cache)
static int get_pages_for_lcd(struct lcd_create_ctx *ctx, bool is_child)
{
struct page *p1, *p2, *p3;
struct page *p1, *p2, *p3, *p4;
int ret;
/*
* We explicity zero things out. If this code is used inside
......@@ -560,8 +568,22 @@ alloc_stack:
memset(lcd_page_address(p3), 0, LCD_STACK_SIZE);
ctx->stack = lcd_page_address(p3);
/*
* Alloc stack protector page
*/
p4 = lcd_alloc_pages(0, LCD_STACK_PROT_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);
return 0;
fail5:
lcd_free_pages(p3, LCD_STACK_ORDER);
fail4:
#ifndef CONFIG_LCD_SINGLE_EPT
lcd_free_pages(p2, LCD_BOOTSTRAP_PAGE_TABLES_ORDER);
......@@ -698,7 +720,9 @@ create_lcd:
gva_add(LCD_STACK_GV_ADDR_CHILD(current_lcd),
LCD_STACK_SIZE - sizeof(void *)),
LCD_BOOTSTRAP_PAGE_TABLES_GP_ADDR,
LCD_UTCB_GP_ADDR_CHILD(current_lcd));
LCD_UTCB_GP_ADDR_CHILD(current_lcd),
LCD_ARCH_GS_GV_BASE);
if (ret) {
LIBLCD_ERR("error configuring LCDs registers");
goto fail6;
......
......@@ -331,7 +331,7 @@ void __lcd_put(struct lcd *caller, struct cnode *cnode, struct lcd *lcd);
* @utcb_page: where to map the UTCB in the LCD's address space
*/
int __lcd_config(struct lcd *caller, cptr_t lcd, gva_t pc, gva_t sp,
gpa_t gva_root, gpa_t utcb_page);
gpa_t gva_root, gpa_t utcb_page, gva_t gs_base);
/**
* __lcd_memory_grant_and_map -- Grant LCD memory object capability and
......
......@@ -21,6 +21,7 @@ struct lcd_boot_cptrs {
cptr_t boot_pages;
cptr_t stack;
cptr_t gv;
cptr_t stack_prot;
};
struct lcd_boot_info {
......
......@@ -73,7 +73,7 @@ int lcd_create_klcd(cptr_t *klcd);
* For now, we assume lcd will boot with a guest virtual address space.
*/
int lcd_config_registers(cptr_t lcd, gva_t pc, gva_t sp, gpa_t gva_root,
gpa_t utcb_page);
gpa_t utcb_page, gva_t gs_base);
/**
* lcd_memory_grant_and_map -- Grant LCD access to memory object, and map it
......@@ -148,6 +148,7 @@ struct lcd_create_ctx {
void *stack;
void *m_init_bits;
void *m_core_bits;
void *stack_prot;
};
/**
......
......@@ -71,9 +71,9 @@ fail1:
}
int lcd_config_registers(cptr_t lcd, gva_t pc, gva_t sp, gpa_t gva_root,
gpa_t utcb_page)
gpa_t utcb_page, gva_t gs_base)
{
return __lcd_config(current->lcd, lcd, pc, sp, gva_root, utcb_page);
return __lcd_config(current->lcd, lcd, pc, sp, gva_root, utcb_page, gs_base);
}
int lcd_memory_grant_and_map(cptr_t lcd, cptr_t mo, cptr_t dest_slot,
......
......@@ -41,7 +41,8 @@ int lcd_create_module_klcd(char *mdir, char *mname, cptr_t *klcd_out)
__gva(hva_val(va2hva(m->init))),
__gva(0),
__gpa(0),
__gpa(0));
__gpa(0),
__gva(0));
if (ret) {
LCD_ERR("failed to config klcd");
goto fail3;
......
......@@ -50,9 +50,9 @@ int lcd_create_klcd(cptr_t *klcd)
}
int lcd_config_registers(cptr_t lcd, gva_t pc, gva_t sp, gpa_t gva_root,
gpa_t utcb_page)
gpa_t utcb_page, gva_t gs_base)
{
return lcd_syscall_config_registers(lcd, pc, sp, gva_root, utcb_page);
return lcd_syscall_config_registers(lcd, pc, sp, gva_root, utcb_page, gs_base);
}
int lcd_memory_grant_and_map(cptr_t lcd, cptr_t mo, cptr_t dest_slot,
......
......@@ -220,11 +220,22 @@ static int add_boot_memory(void)
n->cptr = lcd_get_boot_info()->lcd_boot_cptrs.stack;
lcd_resource_tree_insert(&itree, n);
/*
* Add boot guest virtual page tables
* Add stack canary pages
*/
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;
lcd_resource_tree_insert(&itree, n);
/*
* Add boot guest virtual page tables
*/
n = alloc_itree_node();
if (!n)
goto fail6;
n->start = gpa_val(LCD_BOOTSTRAP_PAGE_TABLES_GP_ADDR);
n->last = gpa_val(LCD_BOOTSTRAP_PAGE_TABLES_GP_ADDR) +
LCD_BOOTSTRAP_PAGE_TABLES_SIZE - 1;
......@@ -233,6 +244,7 @@ static int add_boot_memory(void)
return 0;
fail6:
fail5:
fail4:
fail3:
......
......@@ -374,7 +374,7 @@ void __lcd_put(struct lcd *caller, struct cnode *cnode, struct lcd *lcd)
static int config_lcd(struct lcd *caller, struct lcd *lcd_struct,
gva_t pc, gva_t sp,
gpa_t gva_root, gpa_t utcb_page)
gpa_t gva_root, gpa_t utcb_page, gva_t gs_base)
{
int ret;
hva_t utcb_page_addr;
......@@ -392,6 +392,7 @@ static int config_lcd(struct lcd *caller, struct lcd *lcd_struct,
lcd_arch_set_pc(lcd_struct->lcd_arch, pc);
lcd_arch_set_sp(lcd_struct->lcd_arch, sp);
lcd_arch_set_gva_root(lcd_struct->lcd_arch, gva_root);
lcd_arch_set_gs_base(lcd_struct->lcd_arch, gs_base);
/*
* Map utcb page in guest physical
*/
......@@ -423,7 +424,7 @@ fail1:
static int config_klcd(struct lcd *caller, struct lcd *lcd_struct,
gva_t pc, gva_t sp,
gpa_t gva_root, gpa_t utcb_page)
gpa_t gva_root, gpa_t utcb_page, gva_t gs_base)
{
/*
* For now, we ignore everything except the program counter.
......@@ -439,7 +440,7 @@ static int config_klcd(struct lcd *caller, struct lcd *lcd_struct,
}
int __lcd_config(struct lcd *caller, cptr_t lcd, gva_t pc, gva_t sp,
gpa_t gva_root, gpa_t utcb_page)
gpa_t gva_root, gpa_t utcb_page, gva_t gs_base)
{
struct lcd *lcd_struct;
struct cnode *cnode;
......@@ -457,11 +458,11 @@ int __lcd_config(struct lcd *caller, cptr_t lcd, gva_t pc, gva_t sp,
case LCD_TYPE_ISOLATED:
ret = config_lcd(caller, lcd_struct, pc, sp, gva_root,
utcb_page);
utcb_page, gs_base);
break;
case LCD_TYPE_NONISOLATED:
ret = config_klcd(caller, lcd_struct, pc, sp, gva_root,
utcb_page);
utcb_page, gs_base);
break;
default:
/* shouldn't happen */
......
......@@ -87,7 +87,7 @@ static int handle_syscall_cap_delete(struct lcd *lcd)
static int handle_syscall_config_registers(struct lcd *lcd)
{
cptr_t dest_lcd;
gva_t pc, sp;
gva_t pc, sp, gs_base;
gpa_t gva_root, utcb_page;
/*
* Args
......@@ -97,11 +97,12 @@ static int handle_syscall_config_registers(struct lcd *lcd)
sp = __gva(lcd_arch_get_syscall_arg2(lcd->lcd_arch));
gva_root = __gpa(lcd_arch_get_syscall_arg3(lcd->lcd_arch));
utcb_page = __gpa(lcd_arch_get_syscall_arg4(lcd->lcd_arch));
gs_base = __gva(lcd_arch_get_syscall_arg5(lcd->lcd_arch));
/*
* Do config
*/
return __lcd_config(lcd, dest_lcd, pc, sp, gva_root,
utcb_page);
utcb_page, gs_base);
}
static int handle_syscall_memory_grant_and_map(struct lcd *lcd)
......
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