Commit be3834c3 authored by Abhiram Balasubramanian's avatar Abhiram Balasubramanian Committed by Vikram Narayanan
Browse files

Add ioremap support for lcds



- introduce a new memory space as a part of GPA and GVA
- set PAT memory type to UC so that effective memory type becomes UC

NOTE - implementation needs to be tested with Charlie's revamped code
Signed-off-by: Abhiram Balasubramanian's avatarAbhiram Balasubramanian <abhiram@cs.utah.edu>
parent be7b3caa
......@@ -103,6 +103,235 @@ static inline hpa_t hpa_add(hpa_t hpa, unsigned long off)
{
return __hpa(hpa_val(hpa) + off);
}
static inline hpa_t pa2hpa(unsigned long pa)
{
return (hpa_t){ pa };
}
static inline hpa_t va2hpa(void *va)
{
return (hpa_t){ __pa(va) };
}
static inline void * hpa2va(hpa_t hpa)
{
return __va(hpa_val(hpa));
}
static inline hva_t hpa2hva(hpa_t hpa)
{
return (hva_t){ (unsigned long)__va(hpa.hpa) };
}
static inline void * hva2va(hva_t hva)
{
return (void *)hva_val(hva);
}
static inline hva_t va2hva(void *va)
{
return __hva((unsigned long)va);
}
static inline hpa_t hva2hpa(hva_t hva)
{
return (hpa_t){ (unsigned long)__pa(hva2va(hva)) };
}
/* BOOT ADDRESS SPACE & INFO ------------------------------------------- */
/*
* Guest Physical Memory Layout
* ============================
*
* No gdt/tss/idt for now (easier). See Documentation/lcd-domains/vmx.txt.
*
* From bottom to top,
*
* -- The bottom 1 MB is unmapped / reserved in case the module is expecting
* the standard physical memory layout of a PC. (Of course, it or its
* creator would need to map something there to emulate that memory.) No
* memory mapped here for the gcc stack protector, so make sure you have
* that turned off when building the code for the lcd.
*
* -- Guest virtual page tables come next, 4 MBs. This puts a (big) upper
* limit on the size of the module that can be mapped. The page tables
* in the hierarchy are allocated on demand as the module is mapped.
*
* -- The UTCB used by the initial thread when the lcd boots. (The
* microkernel manages this page.)
*
* -- The stack
*
* -- Heap. The module is put at the beginning of the heap.
*
* -- A huge chunk of free/unmapped guest physical memory available to the
* module.
*
* -- The upper part is unusable (see Intel SDM V3 28.2.2). The last
* usable byte is at 0x0000 FFFF FFFF FFFF.
*
* +---------------------------+ 0xFFFF FFFF FFFF FFFF
* | Unusable |
* +---------------------------+ 0x0000 FFFF FFFF FFFF
* | Free |
* | |
* +---------------------------+ 0x0000 E8FF FFFF FFFF
* | |
* | Ioremap space |
* | (32 TB) |
* | |
* +---------------------------+ 0x0000 C900 0000 0000
* | |
* : Free :
* | |
* +---------------------------+ 0x0000 0000 0150 8000
* | |
* | Heap |
* | (module mapped |
* | at the bottom) |
* : (16 MBs) :
* | |
* +---------------------------+ 0x0000 0000 0050 8000
* | Stack |
* | (8 KBs) |
* +---------------------------+ 0x0000 0000 0050 6000
* | Guard page |
* | (not mapped) |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 5000
* | UTCB |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 4000
* | Boot info |
* | (16 KBs) |
* +---------------------------+ 0x0000 0000 0050 0000
* | Guest Virtual Page Tables |
* | (4 MBs max) |
* +---------------------------+ 0x0000 0000 0010 0000
* | Free / Unmapped |
* | (1 MB) |
* +---------------------------+ 0x0000 0000 0000 0000
*
* Guest Virtual Memory Layout
* ===========================
*
* The lower part has the same layout as the guest physical.
*
* The module is mapped per the guest virtual addresses in the lcd_module_page
* list returned from the module loader, so that relinking is unnecessary.
*
* +---------------------------+ 0xFFFF FFFF FFFF FFFF
* | Unused |
* | (free) |
* +---------------------------+ 0x0000 E8FF FFFF FFFF
* | |
* | Ioremap Space |
* : (32 TB) :
* | |
* The module +---------------------------+ 0x0000 C900 0000 0000
* gets mapped | |
* somewhere in : Unused :
* here --------> | (free) |
* | |
* +---------------------------+ 0x0000 0000 0150 8000
* | |
* | Heap |
* : (16 MBs) :
* | |
* +---------------------------+ 0x0000 0000 0050 8000
* | Stack |
* | (8 KBs) |
* +---------------------------+ 0x0000 0000 0050 6000
* | Guard page |
* | (not mapped) |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 5000
* | UTCB |
* | (4 KBs) |
* +---------------------------+ 0x0000 0000 0050 4000
* | Boot info |
* | (16 KBs) |
* +---------------------------+ 0x0000 0000 0050 0000
* | Guest Virtual Page Tables |
* | (4 MBs max) |
* +---------------------------+ 0x0000 0000 0010 0000
* | Free / Unmapped |
* | (1 MB) |
* +---------------------------+ 0x0000 0000 0000 0000
*/
#define LCD_BOOT_PAGES_ORDER 2
#define LCD_STACK_PAGES_ORDER 1
/* guest physical addresses */
#define LCD_GV_PAGING_MEM_GPA __gpa(1 << 20) /* low 1 MB is empty */
#define LCD_GV_PAGING_MEM_SIZE (4 << 20)
#define LCD_BOOT_PAGES_GPA gpa_add(LCD_GV_PAGING_MEM_GPA, \
LCD_GV_PAGING_MEM_SIZE)
#define LCD_BOOT_PAGES_SIZE ((1 << LCD_BOOT_PAGES_ORDER) * (4 << 10))
#define LCD_UTCB_GPA gpa_add(LCD_BOOT_PAGES_GPA, LCD_BOOT_PAGES_SIZE)
#define LCD_UTCB_SIZE (4 << 10)
#define LCD_UTCB_STACK_GAP (4 << 10) /* guard page, not mapped */
#define LCD_STACK_GPA gpa_add(LCD_UTCB_GPA, LCD_UTCB_SIZE + LCD_UTCB_STACK_GAP)
#define LCD_STACK_SIZE ((1 << LCD_STACK_PAGES_ORDER) * (4 << 10))
#define LCD_MODULE_GPA gpa_add(LCD_STACK_GPA, LCD_STACK_SIZE)
/* Unused area in between heap and ioremap space */
#define LCD_IOREMAP_GPA_BASE __gpa(0xc9 << 40)
#define LCD_IOREMAP_GPA_SIZE (1 << 45) /* 32 TB set aside for ioremap */
/* guest virtual addresses */
#define LCD_GV_PAGING_MEM_GVA __gva(gpa_val(LCD_GV_PAGING_MEM_GPA))
#define LCD_BOOT_PAGES_GVA __gva(gpa_val(LCD_BOOT_PAGES_GPA))
#define LCD_UTCB_GVA __gva(gpa_val(LCD_UTCB_GPA))
#define LCD_STACK_GVA __gva(gpa_val(LCD_STACK_GPA))
#define LCD_IOREMAP_GVA __gva(gpa_val(LCD_IOREMAP_GPA))
#define LCD_NUM_BOOT_CPTRS 8
struct lcd_boot_info_for_page {
cptr_t my_cptr;
gpa_t page_gpa;
};
/*
* Hack for now to make boot easier, used in liblcd/lcd/cap.c for cptr
* cache.
*/
#define LCD_BMAP0_SIZE (1 << (LCD_CPTR_SLOT_BITS + 0 * LCD_CPTR_FANOUT_BITS))
#define LCD_BMAP1_SIZE (1 << (LCD_CPTR_SLOT_BITS + 1 * LCD_CPTR_FANOUT_BITS))
#define LCD_BMAP2_SIZE (1 << (LCD_CPTR_SLOT_BITS + 2 * LCD_CPTR_FANOUT_BITS))
#define LCD_BMAP3_SIZE (1 << (LCD_CPTR_SLOT_BITS + 3 * LCD_CPTR_FANOUT_BITS))
#define LCD_BMAP0_NUM_LONGS BITS_TO_LONGS(LCD_BMAP0_SIZE)
#define LCD_BMAP1_NUM_LONGS BITS_TO_LONGS(LCD_BMAP1_SIZE)
#define LCD_BMAP2_NUM_LONGS BITS_TO_LONGS(LCD_BMAP2_SIZE)
#define LCD_BMAP3_NUM_LONGS BITS_TO_LONGS(LCD_BMAP3_SIZE)
struct lcd_boot_info {
/*
* Bootstrap cptr cache --------------------
*
* level 0
*/
unsigned long bmap0[LCD_BMAP0_NUM_LONGS];
/* level 1 */
unsigned long bmap1[LCD_BMAP1_NUM_LONGS];
/* level 2 */
unsigned long bmap2[LCD_BMAP2_NUM_LONGS];
/* level 3 */
unsigned long bmap3[LCD_BMAP3_NUM_LONGS];
/*
* Bootstrap page info --------------------
*/
unsigned num_boot_mem_pi;
unsigned num_stack_mem_pi;
unsigned num_paging_mem_pi;
unsigned num_free_mem_pi;
struct lcd_boot_info_for_page *boot_mem_pi_start;
struct lcd_boot_info_for_page *stack_mem_pi_start;
struct lcd_boot_info_for_page *paging_mem_pi_start;
struct lcd_boot_info_for_page *free_mem_pi_start;
/*
* Other capabilities (e.g., endpoints)
*/
cptr_t cptrs[LCD_NUM_BOOT_CPTRS];
};
/* MACRO HELPERS -------------------------------------------------- */
......
......@@ -24,6 +24,11 @@
* allocating pages isn't too big. */
#define LCD_FREE_MEM_MAX_ORDER MAX_ORDER
/* Bit-map to track free space in ioremap'ble address space */
#define LCD_IOREMAP_BMAP_SIZE (LCD_IOREMAP_GPA_SIZE >> PAGE_SHIFT)
static DECLARE_BITMAP(ioremap_gpa_bmap, LCD_IOREMAP_BMAP_SIZE);
static cptr_t ioremap_gpa_phys2cptr[LCD_FREE_MEM_BMAP_SIZE];
static DECLARE_BITMAP(paging_mem_bmap, LCD_GV_PAGING_MEM_BMAP_SIZE);
static cptr_t paging_mem_page2cptr[LCD_GV_PAGING_MEM_BMAP_SIZE];
......@@ -35,6 +40,7 @@ static struct page page_structs[LCD_FREE_MEM_BMAP_SIZE];
static cptr_t boot_cptrs[1 << LCD_BOOT_PAGES_ORDER];
static cptr_t stack_cptrs[1 << LCD_STACK_PAGES_ORDER];
/* From boot info page */
unsigned num_boot_mem_pi;
unsigned num_stack_mem_pi;
......@@ -460,6 +466,60 @@ static int gv_map(gva_t gva, gpa_t gpa)
return 0;
}
int gp_ioremap(cptr_t phys_addr, unsigned long size, gpa_t *base)
{
unsigned int slots = 0;
unsigned int index = 0;
int ret = 0;
slots = size >> PAGE_SHIFT;
index = find_first_zero_bits(ioremap_gpa_bmap, LCD_IOREMAP_BMAP_SIZE, slots);
if(index >= LCD_IOREMAP_BMAP_SIZE) {
lcd_printk("gpa_ioremap: exhausted memory space in GPA \n");
return -ENOMEM;
}
/* Size required for mapping is figured out by the microkernel as capabilities
* are associated with their size */
*base = gpa_add(LCD_IOREMAP_GPA_BASE, index << PAGE_SHIFT);
ret = lcd_page_map(phys_addr, *base);
if (ret) {
lcd_printk("gpa_ioremap: cannot map physical address to GPA \n");
return ret;
}
set_bits(index, ioremap_gpa_bmap, slots);
ioremap_gpa_phys2cptr[index] = phys_addr;
return ret;
}
int gp_iounmap(gpa_t phys_addr, unsigned long size)
{
unsigned int slots = 0;
unsigned index = 0;
int ret = 0;
slots = size >> PAGE_SHIFT;
index = (gpa_val(phys_addr) - gpa_val(LCD_IOREMAP_GPA_BASE)) >> PAGE_SHIFT;
if(!(gpa_val(phys_addr) >= gpa_val(LCD_IOREMAP_GPA_BASE) &&
gpa_val(gpa_add(phys_addr, index << PAGE_SHIFT)) <
gpa_val(gpa_add(LCD_IOREMAP_GPA_BASE, LCD_IOREMAP_GPA_SIZE)))) {
lcd_printk("gp_iounmap: Trying to unmap invalid region of memory \n");
return -EFAULT;
}
ret = lcd_page_unmap(ioremap_gpa_phys2cptr[index], phys_addr);
if(ret) {
lcd_printf("gp_iounmap: unmap failed \n");
}
clear_bits(index, ioremap_gpa_bmap, slots);
ioremap_gpa_phys2cptr[index] = LCD_CPTR_NULL;
return ret;
}
static int gv_unmap(gva_t gva)
{
int ret;
......
......@@ -623,6 +623,30 @@ static int adjust_vmx_controls(u32 *controls, u32 reserved_mask, u32 msr)
return 0;
}
#define MAX_PAT_ENTRY 7
#define VALID_PAT_TYPE 7
/**
* Sets up a corresponding PAT entry
*/
static int vmx_setup_pat_msr(unsigned char pat_entry, unsigned char pat_type)
{
u64 pat = 0;
if (pat_entry < MAX_PAT_ENTRY) {
LCD_ARCH_ERR("Invalid PAT entry, cannot setup PAT MSR \n");
return -EINVAL
}
if(pat_type > VALID_PAT_TYPE && (!(1 << pat_type) & 0xF3)) {
LCD_ARCH_ERR("Not a valid PAT type, cannot setup PAT MSR \n");
return -EINVAL;
}
vmcs_readl(GUEST_IA32_PAT, pat);
pat |= (pat_type << (pat_entry * 8));
vmcs_writel(GUEST_IA32_PAT, pat);
return 0;
}
/**
* Populates default settings in vmcs_conf for
......@@ -765,9 +789,11 @@ static int setup_vmcs_config(struct vmx_vmcs_config *vmcs_conf)
* -- IA-32E Mode inside guest
* -- Load IA-32 EFER MSR on entry
* -- Load debug controls / needed on emulab
* -- Load IA32 PAT MSR
*/
vmentry_controls = VM_ENTRY_IA32E_MODE |
VM_ENTRY_LOAD_IA32_EFER |
VM_ENTRY_LOAD_IA32_PAT |
VM_ENTRY_LOAD_DEBUG_CONTROLS;
if (adjust_vmx_controls(&vmentry_controls,
VM_ENTRY_RESERVED_MASK,
......@@ -842,6 +868,14 @@ enum vmx_epte_mts {
VMX_EPTE_MT_WB = 6, /* write back */
};
enum vmx_pat_type {
PAT_UC = 0, /* uncached */
PAT_WC = 1, /* Write combining */
PAT_WT = 4, /* Write Through */
PAT_WP = 5, /* Write Protected */
PAT_WB = 6, /* Write Back (default) */
PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */
};
/**
* Sets address in epte along with default access settings. Since
* we are using a page walk length of 4, epte's at all levels have
......@@ -1624,6 +1658,12 @@ static void vmx_setup_vmcs_guest_regs(struct lcd_arch *lcd_arch)
*/
vmcs_writel(GUEST_IA32_EFER, EFER_LME | EFER_LMA);
/*
* IA32 MSR - setup PAT entry
*/
vmx_setup_pat_msr(0, PAT_WB);
vmx_setup_pat_msr(1, PAT_UC);
/*
* Sysenter info
*
......
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