Commit 5270acc4 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan
Browse files

Updated memory layout and re-factored addr space init.

New memory layout in lcd_defs.h, with macros.
-- no idt, tss, or interrupt service routines

Started re-factoring lcd address space initialization.
vmx_setup_initial_page_table will soon be replaced by
lcd_setup_addr_space.
-- lcd_setup_initial_ept for alloc'ing and mapping
   host physical memory
-- re-factored some of the ept code to make the interface
   cleaner
-- need to think about locking the ept, where it should
   be done
-- soon will have lcd_setup_initial_virt, or something
   similar, for initializing guest virtual page tables.

Copied map_gva_to_gpa routine to new tools/lcd/liblcd/vm.c.
This is where liblcd will go. liblcd will contain utilities
an lcd can call.
parent b404082a
......@@ -320,9 +320,7 @@ static int clear_epte(epte_t *epte) {
return 1;
}
static int ept_lookup_gpa(struct lcd *vcpu,
void *gpa,
int create,
static int lcd_ept_walk(struct lcd *vcpu, u64 gpa, int create,
epte_t **epte_out) {
int i;
epte_t *dir = (epte_t *) __va(vcpu->ept_root);
......@@ -356,9 +354,13 @@ static int ept_lookup_gpa(struct lcd *vcpu,
return 0;
}
static void __set_epte(struct lcd *vcpu,
epte_t* epte, u64 hpa) {
epte_t flags = __EPTE_READ | __EPTE_EXEC | __EPTE_WRITE |
static int lcd_ept_set_epte(struct lcd *vcpu, epte_t *epte_entry, u64 hpa) {
int ret;
epte_t flags;
spin_lock(&vcpu->ept_lock);
flags = __EPTE_READ | __EPTE_EXEC | __EPTE_WRITE |
__EPTE_TYPE(EPTE_TYPE_WB) | __EPTE_IPAT;
if (vcpu->ept_ad_enabled) {
......@@ -367,35 +369,6 @@ static void __set_epte(struct lcd *vcpu,
}
*epte = epte_addr(hpa) | flags;
}
static int ept_set_epte(struct lcd *vcpu,
u64 gpa,
u64 hpa,
int overwrite) {
int ret;
epte_t *epte;
spin_lock(&vcpu->ept_lock);
ret = ept_lookup_gpa(vcpu, (void *) gpa, 1, &epte);
if (ret) {
spin_unlock(&vcpu->ept_lock);
printk(KERN_ERR "ept: failed to lookup EPT entry\n");
return ret;
}
if (epte_present(*epte)) {
if (overwrite)
clear_epte(epte);
else {
spin_unlock(&vcpu->ept_lock);
printk(KERN_ERR "ept: epte exists %p\n", (void*)(*epte));
return -EINVAL;
}
}
__set_epte(vcpu, epte, hpa);
spin_unlock(&vcpu->ept_lock);
......@@ -405,13 +378,13 @@ static int ept_set_epte(struct lcd *vcpu,
static unsigned long alloc_pt_pfn(struct lcd *vcpu) {
unsigned long which = bitmap_find_next_zero_area(
vcpu->bmp_pt_pages,
LCD_NR_PT_PAGES,
LCD_PAGING_MEM_NUM_PAGES,
0, 1, 0);
if (which >= LCD_NR_PT_PAGES) {
if (which >= LCD_PAGING_MEM_NUM_PAGES) {
return 0;
} else {
bitmap_set(vcpu->bmp_pt_pages, which, 1);
return (LCD_PT_PAGES_START >> PAGE_SHIFT) + which;
return (LCD_PAGING_MEM_START >> PAGE_SHIFT) + which;
}
}
......@@ -645,124 +618,86 @@ static u64 construct_eptp(u64 root_hpa) {
return eptp;
}
static int vmx_setup_initial_page_table(struct lcd *vcpu) {
int ret = 0;
static int lcd_setup_initial_ept(struct lcd *vcpu) {
int ret;
int i;
u64 hva;
u64 gpa;
epte_t *ept_entry;
u64 gpa, hpa, gva;
/* Map guest page table structure's pages in ept */
for (i = 0, gpa = LCD_PT_PAGES_START;
i < LCD_NR_PT_PAGES; gpa+=PAGE_SIZE, ++i) {
hpa = __get_free_page(GFP_KERNEL);
if (!hpa)
return -ENOMEM;
memset((void*)hpa, 0, PAGE_SIZE);
hpa = __pa(hpa);
/* No overwriting, should not exist at all. */
ret = ept_set_epte(vcpu, gpa, hpa, 0);
if (ret) {
printk(KERN_ERR "ept: map pt pages failed at %d\n", i);
return ret;
}
}
gpa = gva = LCD_PT_PAGES_START;
/* Populate at least a page table path, 4 pages. */
for (i = 0; i < LCD_NR_PT_PAGES; ++i) {
ret = map_gva_to_gpa(vcpu, gva, gpa, 1, 0);
if (ret) {
printk(KERN_ERR "ept: populate pt failed at %d\n", i);
return ret;
}
gva += PAGE_SIZE;
gpa += PAGE_SIZE;
}
/*
* Map guest physical from LCD_BOTTOM to LCD_PAGING_MEM_START
*/
for (gpa = LCD_BOTTOM; gpa < LCD_PAGING_MEM_START; gpa += PAGE_SIZE) {
gpa = gva = LCD_STACK_BOTTOM;
for (i = 0; i < (LCD_STACK_SIZE >> PAGE_SHIFT); ++i) {
ret = map_gva_to_gpa(vcpu, gva, gpa, 1, 0);
if (ret) {
printk(KERN_ERR "ept: populate stack pt failed at %d\n", i);
return ret;
}
hpa = __get_free_page(GFP_KERNEL);
if (!hpa)
hva = __get_free_page(GFP_KERNEL);
if (!hva) {
/*
* FIXME: Need to free any prev alloc'd mem.
*/
return -ENOMEM;
memset((void*)hpa, 0, PAGE_SIZE);
hpa = __pa(hpa);
}
memset((void*)hva, 0, PAGE_SIZE);
ret = ept_set_epte(vcpu, gpa, hpa, 0);
/*
* Walk ept, allocating along the way.
*/
ret = lcd_ept_walk(vcpu, gpa, 1, &ept_entry);
if (ret) {
printk(KERN_ERR "ept: map stack pages failed at %d\n", i);
printk(KERN_ERR "lcd_ept_walk failed at %x\n", gpa);
return ret;
}
gva += PAGE_SIZE;
gpa += PAGE_SIZE;
}
ret = ept_set_epte(vcpu, LCD_BOOT_PARAMS_ADDR, __pa(vcpu->bp), 0);
if (ret) {
printk(KERN_ERR "ept: BP phy-addr occupied in EPT\n");
return ret;
}
ret = map_gva_to_gpa(vcpu, LCD_BOOT_PARAMS_ADDR, LCD_BOOT_PARAMS_ADDR, 1, 0);
if (ret) {
printk(KERN_ERR "ept: BP virt-addr occupied in guest PT\n");
return ret;
}
/* Map descriptors and tables in EPT */
ret = ept_set_epte(vcpu, LCD_GDT_ADDR, __pa(vcpu->gdt), 0);
if (ret) {
printk(KERN_ERR "ept: GDT phy-addr occupied in EPT\n");
return ret;
}
ret = ept_set_epte(vcpu, LCD_IDT_ADDR, __pa(vcpu->idt), 0);
if (ret) {
printk(KERN_ERR "ept: IDT phy-addr occupied in EPT\n");
return ret;
}
ret = ept_set_epte(vcpu, LCD_TSS_ADDR, __pa(vcpu->tss), 0);
if (ret) {
printk(KERN_ERR "ept: TSS phy-addr occupied in EPT\n");
return ret;
/*
* Map the guest physical addr to the host physical addr.
*/
lcd_ept_set_epte(vcpu, ept_entry, gpa, __pa(hva));
}
}
ret = ept_set_epte(vcpu, LCD_COMM_ISR_ADDR, __pa(vcpu->isr_page), 0);
if (ret) {
printk(KERN_ERR "ept: common ISR phy-addr occupied in EPT\n");
return ret;
}
/**
* Builds ept and guest virtual page tables.
*/
static int lcd_setup_addr_space(struct lcd *vcpu) {
int ret;
int i;
u64 hva;
u64 gva;
u64 gpa;
epte_t ept_entry;
unsigned long *paging_mem_bitmap;
ret = map_gva_to_gpa(vcpu, LCD_GDT_ADDR, LCD_GDT_ADDR, 1, 0);
if (ret) {
printk(KERN_ERR "ept: GDT virt-addr occupied in guest PT\n");
return ret;
}
/*
* Use a bitmap to track allocation of memory for
* guest virtual paging.
*/
paging_mem_bitmap = kmalloc(sizeof(long) *
BITS_TO_LONGS(LCD_PAGING_MEM_NUM_PAGES),
GFP_KERNEL);
if (!paging_mem_bitmap)
goto fail_bmp;
bitmap_zero(paging_mem_bitmap, LCD_PAGING_MEM_NUM_PAGES);
ret = map_gva_to_gpa(vcpu, LCD_IDT_ADDR, LCD_IDT_ADDR, 1, 0);
if (ret) {
printk(KERN_ERR "ept: IDT virt-addr occupied in guest PT\n");
return ret;
}
ret = map_gva_to_gpa(vcpu, LCD_TSS_ADDR, LCD_TSS_ADDR, 1, 0);
if (ret) {
printk(KERN_ERR "ept: TSS virt-addr occupied in guest PT\n");
return ret;
}
ret = map_gva_to_gpa(vcpu, LCD_COMM_ISR_ADDR, LCD_COMM_ISR_ADDR, 1, 0);
if (ret) {
printk(KERN_ERR "ept: common ISR virt-addr occupied in guest PT\n");
return ret;
for (gpa = gva = 0; gpa < LCD_FREE_START; gpa += PAGE_SIZE,
gva += PAGE_SIZE) {
/*
* Create page table structures along the way, but do
* not overwrite.
*/
ret = map_gva_to_gpa(vcpu, gva, gpa, 1, 0);
if (ret) {
printk(KERN_ERR "setup_pt: map failed at %x\n",
gpa);
return ret;
}
}
return 0;
fail_bmp:
kfree(paging_mem_bitmap);
}
static int vmx_create_ept(struct lcd *vcpu) {
......
......@@ -132,119 +132,58 @@ struct ipc_waitq {
struct list_head list;
};
<<<<<<< HEAD
typedef struct {
int cpu;
int vpid;
int launched;
spinlock_t ept_lock;
unsigned long ept_root;
unsigned long eptp;
bool ept_ad_enabled;
pgd_t* pt;
unsigned long pt_gpa;
unsigned long *bmp_pt_pages;
/* GDT_ENTRIES * desc_struct */
struct desc_struct* gdt;
/* IDT_ENTRIES * gate_desc */
gate_desc* idt;
struct lcd_tss_struct* tss;
unsigned long isr_page;
unsigned long host_idt_base;
u8 fail;
u64 exit_reason;
u64 exit_qualification;
u32 idt_vectoring_info;
u32 exit_intr_info;
u32 error_code;
u32 vec_no;
u64 host_rsp;
u64 regs[NR_VCPU_REGS];
u64 cr2;
int shutdown;
int ret_code;
struct msr_autoload {
unsigned nr;
struct vmx_msr_entry guest[NR_AUTOLOAD_MSRS];
struct vmx_msr_entry host[NR_AUTOLOAD_MSRS];
} msr_autoload;
sync_ipc_t sync_ipc;
struct vmcs *vmcs;
void *shared;
struct module *mod;
} lcd_struct;
=======
>>>>>>> Move things around
/* Memory layout */
// Range format: [begin, end)
// 0x0000 0000 0000 0000 ~ 0x0000 0000 4000 0000 : 1GB : Physical Mem
// 4K gap
// 0x0000 0000 4000 1000 ~ 0x0000 0000 4040 1000 : 4MB : Page table structures
// 0x0000 0000 4040 1000 ~ 0x0000 0000 4040 2000 : 4KB : GDT
// 0x0000 0000 4040 2000 ~ 0x0000 0000 4040 3000 : 4KB : IDT
// 0x0000 0000 4040 3000 ~ 0x0000 0000 4040 4000 : 4KB : TSS page (sizeof(lcd_tss_struct))
// 4K page gap as memory guard
// 0x0000 0000 4040 5000 ~ 0x0000 0000 4040 6000 : 4KB : Common ISR code page
// 4K memory guard
// 0x0000 0000 4040 7000 ~ 0x0000 0000 4040 F000 : 32KB : stack
// 4K memory guard
// 0x0000 0000 4041 0000 ~ 0x0000 0000 4051 0000 : 1MB : 256 ISRs, 4KB code page per ISR
// Bootup structure:
#define LCD_PHY_MEM_SIZE (1 << 30) /* 1GB physical mem */
#define LCD_BOOT_PARAMS_ADDR (1 << 20)
#define LCD_NR_PT_PAGES (1 << 10) /* #pages for page table */
#define LCD_PT_PAGES_START (LCD_PHY_MEM_SIZE + PAGE_SIZE) /* 1GB + 4KB */
#define LCD_PT_PAGES_END (LCD_PT_PAGES_START + (LCD_NR_PT_PAGES << PAGE_SHIFT))
#define LCD_GDT_ADDR (LCD_PT_PAGES_END) /* start from 1G + 4M + 4K */
#define LCD_IDT_ADDR (LCD_GDT_ADDR + PAGE_SIZE)
#define LCD_TSS_ADDR (LCD_IDT_ADDR + PAGE_SIZE)
#define LCD_TSS_SIZE (sizeof(struct lcd_tss_struct))
#define LCD_COMM_ISR_ADDR (LCD_TSS_ADDR + 2*PAGE_SIZE)
#define LCD_COMM_ISR_END (LCD_COMM_ISR_ADDR + PAGE_SIZE)
#define LCD_STACK_BOTTOM (LCD_COMM_ISR_END + PAGE_SIZE)
#define LCD_STACK_SIZE (PAGE_SIZE * 8)
#define LCD_STACK_TOP (LCD_STACK_BOTTOM + LCD_STACK_SIZE)
#define LCD_STACK_ADDR LCD_STACK_TOP
#define LCD_NR_ISRS 256
#define LCD_ISR_START (LCD_STACK_TOP + PAGE_SIZE)
#define LCD_ISR_END (LCD_ISR_START + LCD_NR_ISRS*PAGE_SIZE)
#define LCD_ISR_ADDR(n) (LCD_ISR_START + (n)*PAGE_SIZE)
#define LCD_PHY_MEM_LIMIT LCD_ISR_END
#define LCD_FREE_MEM_START (LCD_ISR_END + PAGE_SIZE)
#define LCD_TEST_CODE_ADDR LCD_FREE_MEM_START
//static int load_lcd(struct load_info * info, const char __user *uargs, int flags);
// Inside LCD:
int lcd_read_mod_file(const char* filepath, void** content, long* size);
/*
* Guest Physical and Virtual Memory Layout
* ========================================
*
* IA-32e paging is used, with a 4-level page table hierarchy (see
* Intel Manual 4.5). IA-32e paging maps 48-bit guest virtual addresses
* to 52-bit guest physical addresses. The upper 16 bits are ignored.
*
*
* +---------------------------+ 0xFFFF FFFF FFFF FFFF
* | |
* : :
* : Kernel Module :
* : Mapping Area :
* : :
* | |
* LCD_HEAP_END----------> +---------------------------+ TASK_SIZE (arch-dep)
* LCD_MODULE_START | |
* | |
* : :
* : HEAP :
* : (grows up) :
* : :
* : :
* | |
* LCD_HEAP_START--------> +---------------------------+ 0x0000 0000 0040 3000
* | Initial Guest Virtual |
* | Paging Memory | (4 MBs)
* LCD_PAGING_MEM_START--> +---------------------------+ 0x0000 0000 0000 3000
* | GDT | (4 KBs)
* LCD_GDT---------------> +---------------------------+ 0x0000 0000 0000 2000
* | |
* | Stack |
* : (grows down) : (4 KBs)
* : :
* | |
* | IPC Message Registers |
* LCD_ROOT_TCB----------> +---------------------------+ 0x0000 0000 0000 1000
* | Stack Canary Page | (4 KBs)
* LCD_STACK_CANARY,-----> +---------------------------+ 0x0000 0000 0000 0000
* LCD_BOTTOM
*/
#define LCD_BOTTOM 0x0000000000000000UL
#define LCD_STACK_CANARY LCD_BOTTOM
#define LCD_ROOT_TCB 0x0000000000001000UL
#define LCD_GDT 0x0000000000002000UL
#define LCD_PAGING_MEM_START 0x0000000000003000UL
#define LCD_HEAP_START 0x0000000000403000UL
#define LCD_HEAP_END TASK_SIZE
#define LCD_MODULE_START TASK_SIZE
#define LCD_PAGING_MEM_NUM_PAGES ((LCD_HEAP_START - LCD_PAGING_MEM_START) \
/ PAGE_SIZE)
#endif
/*
* Taken from lcd guest virtual mapping
* code. Pasted here for now.
*/
static int map_gva_to_gpa(struct lcd *vcpu,
u64 gva,
u64 gpa,
int create, int overwrite) {
int ret = 0;
unsigned long gpfn, page;
/* epte_t *epte; */
pud_t *pud_dir, *pud;
pmd_t *pmd_dir, *pmd;
pte_t *pte_dir, *pte;
pgd_t *pgd;
if (!vcpu->pt) {
if (!create)
return -ENOENT;
else {
ret = ept_alloc_pt_item(vcpu, &gpfn, &page);
if (ret)
return ret;
else {
vcpu->pt = (pgd_t*)page;
vcpu->pt_gpa = (gpfn << PAGE_SHIFT);
}
}
}
pgd = vcpu->pt + pgd_index(gva);
if (!pgd_present(*pgd)) {
if (!create) {
return -ENOENT;
} else {
ret = ept_alloc_pt_item(vcpu, &gpfn, &page);
if (ret) {
return ret;
} else {
set_pgd(pgd, mk_kernel_pgd((gpfn << PAGE_SHIFT)));
pud_dir = (pud_t*)page;
} // ept_alloc_pt_item
} // !create
} else {
ret = ept_gpa_to_hva(vcpu, pgd_val(*pgd)&PTE_PFN_MASK,
(u64*)(&pud_dir));
if (ret)
return ret;
} // !pgd_present
pud = pud_dir + pud_index(gva);
if (!pud_present(*pud)) {
if (!create) {
return -ENOENT;
} else {
ret = ept_alloc_pt_item(vcpu, &gpfn, &page);
if (ret) {
return ret;
} else {
set_pud(pud, __pud((gpfn << PAGE_SHIFT)|_KERNPG_TABLE));
pmd_dir = (pmd_t*)page;
} // ept_alloc_pt_item
} // !create
} else {
ret = ept_gpa_to_hva(vcpu, pud_val(*pud)&PTE_PFN_MASK,
(u64*)(&pmd_dir));
if (ret)
return ret;
} // !pud_present
pmd = pmd_dir + pmd_index(gva);
if (!pmd_present(*pmd)) {
if (!create) {
return -ENOENT;
} else {
ret = ept_alloc_pt_item(vcpu, &gpfn, &page);
if (ret) {
return ret;
} else {
set_pmd(pmd, __pmd((gpfn << PAGE_SHIFT)|_KERNPG_TABLE));
pte_dir = (pte_t*)page;
} // ept_alloc_pt_item
} // !create
} else {
ret = ept_gpa_to_hva(vcpu, pmd_val(*pmd)&PTE_PFN_MASK,
(u64*)(&pte_dir));
if (ret)
return ret;
} // !pmd_present
pte = pte_dir + pte_index(gva);
if (!pte_present(*pte) || overwrite) {
set_pte(pte, __pte((gpa & PTE_PFN_MASK)|__PAGE_KERNEL_EXEC));
} else {
printk(KERN_ERR "mm: pte conflicts %p %p\n", (void*)gpa,
(void*)pte_val(*pte));
ret = -EINVAL;
}
return ret;
}
/**
* lcd.c - Main file for the LCD module
* core.c - Main file for the LCD module
*
*
* Authors:
......@@ -15,6 +15,7 @@
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <lcd/lcd.h>
#include <lcd/config.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LCD driver");
......
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