Commit 127a863f authored by Weibin Sun's avatar Weibin Sun Committed by Vikram Narayanan
Browse files

loader code done



Conflicts:
	arch/x86/lcd/lcd_main.c
Resolved-by: Vikram Narayanan's avatarVikram Narayanan <vikram186@gmail.com>
parent a62128fc
......@@ -196,29 +196,29 @@ typedef struct {
/* Memory layout */
// Range format: [begin, end)
// 0x0000 0000 0000 0000 ~ 0x0000 0000 0100 0000 : 16MB : hole (Avoid possible MMIO)
// 0x0000 0000 0100 0000 ~ 0x0000 0000 0500 0000 : 64MB : Page table structures
// 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 0500 1000 ~ 0x0000 0000 0500 2000 : 4KB : GDT
// 0x0000 0000 0500 2000 ~ 0x0000 0000 0500 3000 : 4KB : IDT
// 0x0000 0000 0500 3000 ~ 0x0000 0000 0500 4000 : 4KB : TSS page (sizeof(lcd_tss_struct))
// 4K page gap as memory guard
// 0x0000 0000 0500 5000 ~ 0x0000 0000 0500 6000 : 4KB : Common ISR code page
// 4K memory guard
// 0x0000 0000 0500 7000 ~ 0x0000 0000 0500 F000 : 32KB : stack
// 0x0000 0000 4040 5000 ~ 0x0000 0000 4040 6000 : 4KB : Common ISR code page
// 4K memory guard
// 0x0000 0000 0501 0000 ~ 0x0000 0000 0511 0000 : 1MB : 256 ISRs, 4KB code page per ISR
// 0x0000 0000 4040 7000 ~ 0x0000 0000 4040 F000 : 32KB : stack
// 4K memory guard
// 0x0000 0000 0511 1000 ~ Memory limit : Code/data (start from 81MB+68KB)
//
// Todo:
// Heap start; Heap end.
// 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_NR_PT_PAGES (1 << 14) /* #pages for page table */
#define LCD_PT_PAGES_START (0x1ULL << 24) /* above 16MB */
#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 + PAGE_SIZE) /* start from 80MB + 4KB */
#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))
......@@ -236,6 +236,8 @@ typedef struct {
#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
......@@ -255,4 +257,8 @@ const char* lcd_exit_reason(int exit_code);
// Inside LCD:
int lcd_read_mod_file(const char* filepath, void** content, long* size);
int lcd_load_vmlinux(const char* kfile, lcd_struct *lcd, u64 *elf_entry);
#endif
......@@ -440,7 +440,7 @@ static int ept_alloc_pt_item(lcd_struct *vcpu,
ret = ept_lookup_gpa(vcpu, (void*)((*gpfn) << PAGE_SHIFT), 1, &epte);
if (!ret) {
if (!epte_present(*epte)) {
*page = __get_free_page(GFP_ATOMIC);
*page = __get_free_page(GFP_KERNEL);
if (!(*page)) {
ret = -ENOMEM;
} else {
......@@ -679,44 +679,6 @@ static int vmx_setup_initial_page_table(lcd_struct *vcpu) {
gpa += PAGE_SIZE;
}
/* Test code page */
gpa = gva = LCD_TEST_CODE_ADDR;
ret = map_gva_to_gpa(vcpu, gva, gpa, 1, 0);
if (ret) {
printk(KERN_ERR "ept: populate code page failed\n");
return ret;
}
hpa = __get_free_page(GFP_KERNEL);
if (!hpa)
return -ENOMEM;
memset((void*)hpa, 0, PAGE_SIZE);
{
u8* bincode = (u8*)hpa;
/* 0: b8 e0 0f 00 01 mov $0x1000fe0,%eax*/
/* 5: c7 00 ef be ad de movl $0xdeadbeef,(%rax) */
/* ((u8*)hpa)[0] = 0xb8; ((u8*)hpa)[1] = 0xe0; ((u8*)hpa)[2] = 0xf; ((u8*)hpa)[3] = 0x10; */
/* ((u8*)hpa)[5] = 0xc7; ((u8*)hpa)[7] = 0xef; ((u8*)hpa)[8] = 0xbe; ((u8*)hpa)[9] = 0xad; */
/* ((u8*)hpa)[10] = 0xde; */
/* ((u8*)hpa)[11] = 0xf4; ((u8*)hpa)[12] = 0xf4; */
bincode[0] = 0xf; bincode[1] = 0x1; bincode[2] = 0xc1;
bincode[3] = 0xb8; bincode[4] = 0x34; bincode[5] = 0x12;
bincode[8] = 0x48; bincode[9] = 0x89; bincode[10] = 0xc1;
bincode[11] = 0xeb; bincode[12] = 0xf6;
bincode[13] = 0x90;
bincode[14] = 0xf4;
}
hpa = __pa(hpa);
ret = ept_set_epte(vcpu, gpa, hpa, 0);
if (ret) {
printk(KERN_ERR "ept: map code page failed\n");
return ret;
}
// commented to check the dynamically allocated stack
#if 0
/* Map stack PT */
gpa = gva = LCD_STACK_BOTTOM;
for (i = 0; i < (LCD_STACK_SIZE >> PAGE_SHIFT); ++i) {
......@@ -740,7 +702,7 @@ static int vmx_setup_initial_page_table(lcd_struct *vcpu) {
gva += PAGE_SIZE;
gpa += PAGE_SIZE;
}
#endif
/* Map descriptors and tables in EPT */
ret = ept_set_epte(vcpu, LCD_GDT_ADDR, __pa(vcpu->gdt), 0);
if (ret) {
......@@ -1686,11 +1648,26 @@ static int vmx_handle_ept_violation(lcd_struct *vcpu) {
return -EINVAL;
}
/* TODO: fix this. Now we fail on EPT fault unconditionally. */
/* ret = vmx_do_ept_fault(vcpu, gpa, gva, exit_qual); */
printk(KERN_INFO "EPT: get violation GPA 0x%lx, GVA: 0x%lx, fail now!\n",
gpa, gva);
ret = -EINVAL;
/*
* EPT Fault.
* TODO: lock page table?
*/
if (gpa < LCD_PHY_MEM_SIZE) {
u64 gpa_pg;
u64 pg = __get_free_page(GFP_KERNEL);
if (!pg)
ret = -ENOMEM;
else {
gpa_pg = round_down(gpa, PAGE_SIZE);
ret = lcd_map_gpa_to_hpa(vcpu, gpa_pg, __pa(pg), 0);
if (ret) {
printk(KERN_ERR "EPT: map page %p for %p failed\n",
(void*)pg, (void*)gpa_pg);
free_page(pg);
}
}
} else
ret = -EINVAL;
if (ret) {
printk(KERN_ERR "vmx: EPT violation failure "
......
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <uapi/asm/kvm.h>
#include <linux/fs.h>
......@@ -10,6 +11,7 @@
#include <asm/uaccess.h>
#include <asm/vmx.h>
#include <uapi/linux/elf.h>
#include "lcd_defs.h"
......@@ -58,7 +60,115 @@ error_out:
return err;
}
int lcd_load_vmlinux(const char* kfile, lcd_struct *lcd) {
void process_vmlinux_note(lcd_struct *lcd, Elf64_Phdr *hdr,
struct file *filp) {
char *name, *desc;
u64 ofs;
Elf64_Nhdr nhdr;
int ret;
u64 pos;
/* REQ: Name and Desc size less than half page */
name = (char*)__get_free_page(GFP_KERNEL);
if (!name) {
printk(KERN_ERR "Out of mem for note\n");
return;
}
desc = name + (PAGE_SIZE > 1);
ofs = hdr->p_offset;
pos = ofs;
while (ofs < hdr->p_offset + hdr->p_filesz) {
ret = vfs_read(filp, (char*)&nhdr, sizeof(nhdr), &pos);
if (ret != sizeof(nhdr)) {
printk(KERN_ERR "Error reading vmlinux note\n");
goto after_mem_out;
}
if (nhdr.n_namesz > 0) {
ret = vfs_read(filp, name,
round_up(nhdr.n_namesz, hdr->p_align),
&pos);
if (ret != round_up(nhdr.n_namesz, hdr->p_align)) {
printk(KERN_ERR "Error reading vmlinux note name\n");
goto after_mem_out;
}
}
if (nhdr.n_descsz > 0) {
ret = vfs_read(filp, desc,
round_up(nhdr.n_descsz, hdr->p_align),
&pos);
if (ret != round_up(nhdr.n_descsz, hdr->p_align)) {
printk(KERN_ERR "Error reading vmlinux note desc\n");
goto after_mem_out;
}
}
/* TODO: use Xen notes */
}
after_mem_out:
free_page((u64)name);
}
void load_vmlinux_segment(lcd_struct *lcd, Elf64_Phdr *hdr,
struct file *filp) {
u64 sz, left;
int ret;
u64 hva, gpa;
u64 pos;
pos = hdr->p_offset;
left = hdr->p_filesz;
gpa = round_down(hdr->p_paddr, PAGE_SIZE);
sz = PAGE_SIZE - (hdr->p_paddr - gpa);
if (sz > hdr->p_filesz)
sz = hdr->p_filesz;
while (left > 0) {
ret = lcd_find_hva_by_gpa(lcd, gpa, &hva);
if (ret == -ENOENT) {
hva = __get_free_page(GFP_KERNEL);
if (!hva) {
printk(KERN_ERR "Out of memory for vmlinux\n");
return;
}
if (lcd_map_gpa_to_hpa(lcd, gpa, __pa(hva), 0)) {
printk(KERN_ERR "Map ept page failed\n");
free_page(hva);
return;
}
if (lcd_map_gva_to_gpa(lcd, gpa, gpa, 1, 0)) {
printk(KERN_ERR "Map gva to gpa failed\n");
return;
}
} else if (ret) {
printk(KERN_ERR "Find hva error %p\n", (void*)gpa);
return;
}
if (left == hdr->p_filesz)
hva += hdr->p_paddr - gpa;
ret = vfs_read(filp, (void*)hva, sz, &pos);
if (ret != sz) {
printk(KERN_ERR "Error reading vmlinux %d\n", ret);
return;
}
left -= sz;
sz = (left > PAGE_SIZE)? PAGE_SIZE:left;
gpa += PAGE_SIZE;
}
}
int lcd_load_vmlinux(const char* kfile, lcd_struct *lcd,
u64 *elf_entry) {
Elf64_Ehdr hdr;
Elf64_Phdr *phdrs;
mm_segment_t oldfs;
......@@ -77,7 +187,7 @@ int lcd_load_vmlinux(const char* kfile, lcd_struct *lcd) {
goto error_out;
}
err = vfs_read(filp, &hdr, sizeof(hdr), &pos);
err = vfs_read(filp, (char*)&hdr, sizeof(hdr), &pos);
if (err != sizeof(hdr)) {
printk(KERN_ERR "Error when reading vmlinux %d\n", err);
goto after_open_error_out;
......@@ -90,15 +200,15 @@ int lcd_load_vmlinux(const char* kfile, lcd_struct *lcd) {
goto after_open_error_out;
}
phdrs = kmalloc(sizeof(Elf64_Phdr)*hdr.e_phnum, GPF_KERNEL);
phdrs = kmalloc(sizeof(Elf64_Phdr)*hdr.e_phnum, GFP_KERNEL);
if (!phdrs) {
err = -ENOMEM;
printk(KERN_ERR "Out of mem\n");
goto after_open_error_out;
}
pos = hdr->e_phoff;
err = vfs_read(filp, phdrs, sizeof(Elf64_Phdr)*hdr.e_phnum, &pos);
pos = hdr.e_phoff;
err = vfs_read(filp, (char*)phdrs, sizeof(Elf64_Phdr)*hdr.e_phnum, &pos);
if (err != sizeof(Elf64_Phdr)*hdr.e_phnum) {
printk(KERN_ERR "Error when reading p hdrs %d\n", err);
goto after_mem_error_out;
......@@ -110,11 +220,15 @@ int lcd_load_vmlinux(const char* kfile, lcd_struct *lcd) {
if (phdrs[i].p_type != PT_NOTE)
continue;
else {
// todo READ NOTE.
process_vmlinux_note(lcd, &phdrs[i], filp);
}
} else {
load_vmlinux_segment(lcd, &phdrs[i], filp);
}
}
*elf_entry = hdr.e_entry;
after_mem_error_out:
kfree(phdrs);
after_open_error_out:
......
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