Commit 82aa94ed authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

Introducing types for each gpa, gva, hva, hpa.

Constructors and casting inlines are in arch-dep
code header.
parent bdc65df6
......@@ -5,6 +5,101 @@
#include <linux/spinlock.h>
#include <lcd-domains/utcb.h>
/* ADDRESS SPACE TYPES ---------------------------------------- */
typedef struct { unsigned long gva } gva_t;
typedef struct { unsigned long hva } hva_t;
typedef struct { unsigned long gpa } gpa_t;
typedef struct { unsigned long hpa } hpa_t;
static inline gva_t __gva(unsigned long gva)
{
return (gva_t){ gva };
}
static inline unsigned long gva_val(gva_t gva)
{
return gva.gva;
}
static inline unsigned long * gva_ptr(gva_t * gva)
{
return &(gva->gva);
}
static inline gva_t gva_add(gva_t gva, unsigned long off)
{
return __gva(gva_val(gva) + off);
}
static inline hva_t __hva(unsigned long hva)
{
return (hva_t){ hva };
}
static inline unsigned long hva_val(hva_t hva)
{
return hva.hva;
}
static inline unsigned long * hva_ptr(hva_t * hva)
{
return &(hva->hva);
}
static inline hva_t hva_add(hva_t hva, unsigned long off)
{
return __hva(hva_val(hva) + off);
}
static inline gpa_t __gpa(unsigned long gpa)
{
return (gpa_t){ gpa };
}
static inline unsigned long gpa_val(gpa_t gpa)
{
return gpa.gpa;
}
static inline unsigned long * gpa_ptr(gpa_t * gpa)
{
return &(gpa->gpa);
}
static inline gpa_t gpa_add(gpa_t gpa, unsigned long off)
{
return __gpa(gpa_val(gpa) + off);
}
static inline hpa_t __hpa(unsigned long hpa)
{
return (hpa_t){ hpa };
}
static inline unsigned long hpa_val(hpa_t hpa)
{
return hpa.hpa;
}
static inline unsigned long * hpa_ptr(hpa_t * hpa)
{
return &(hpa->hpa);
}
static inline hpa_t hpa_add(hpa_t hpa, unsigned long off)
{
return __hpa(hpa_val(hpa) + off);
}
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 hpa_t hva2hpa(hva_t hva)
{
return (hpa_t){ (unsigned long)__pa(hva2va(hva)) };
}
static inline void * hva2va(hva_t hva)
{
return (void *)hva_val(hva);
}
/* LCD ARCH DATA STRUCTURES ---------------------------------------- */
struct lcd_arch_vmcs {
u32 revision_id;
u32 abort;
......@@ -40,7 +135,7 @@ enum lcd_arch_reg {
struct lcd_arch_ept {
spinlock_t lock;
unsigned long root_hpa;
hpa_t root;
unsigned long vmcs_ptr;
bool access_dirty_enabled;
};
......@@ -68,8 +163,8 @@ struct lcd_arch {
* Public Data
*/
struct {
u64 gva;
u64 gpa;
gva_t gv_fault_addr;
gpa_t gp_fault_addr;
} run_info;
/*
......@@ -157,21 +252,21 @@ enum lcd_arch_status {
};
/**
* Lookup ept entry for guest physical address gpa.
* Lookup ept entry for guest physical address a.
*
* Set create = 1 to allocate ept page table data structures
* along the path as needed.
*/
int lcd_arch_ept_walk(struct lcd_arch *vcpu, u64 gpa, int create,
int lcd_arch_ept_walk(struct lcd_arch *vcpu, gpa_t a, int create,
lcd_arch_epte_t **epte_out);
/**
* Set the guest physical => host physical mapping in the ept entry.
*/
void lcd_arch_ept_set(lcd_arch_epte_t *epte, u64 hpa);
void lcd_arch_ept_set(lcd_arch_epte_t *epte, hpa_t a);
/**
* Read the host physical address stored in epte.
*/
u64 lcd_arch_ept_hpa(lcd_arch_epte_t *epte);
hpa_t lcd_arch_ept_hpa(lcd_arch_epte_t *epte);
/**
* Clears guest physical => host physical mapping in the ept.
*
......@@ -187,47 +282,48 @@ int lcd_arch_ept_unset(lcd_arch_epte_t *epte);
* overwrite = 0 => do not overwrite if ept entry is already present
* overwrite = 1 => overwrite any existing ept entry
*/
int lcd_arch_ept_map_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 hpa,
int create, int overwrite);
int lcd_arch_ept_map(struct lcd_arch *vcpu, gpa_t ga, hpa_t ha,
int create, int overwrite);
/**
* Maps
*
* gpa_start --> gpa_start + npages * PAGE_SIZE
* ga_start --> ga_start + npages * PAGE_SIZE
*
* to
*
* hpa_start --> hpa_start + npages * PAGE_SIZE
* ha_start --> ha_start + npages * PAGE_SIZE
*
* in lcd's ept.
*/
int lcd_arch_ept_map_range(struct lcd_arch *lcd, u64 gpa_start, u64 hpa_start,
u64 npages);
int lcd_arch_ept_map_range(struct lcd_arch *lcd, gpa_t ga_start,
hpa_t ha_start, unsigned long npages);
/**
* Simple routine combining ept walk and unset.
*/
int lcd_arch_ept_unmap_gpa(struct lcd_arch *vcpu, u64 gpa);
int lcd_arch_ept_unmap(struct lcd_arch *vcpu, gpa_t a);
/**
* Unmaps
*
* gpa_start --> gpa_start + npages * PAGE_SIZE
* ga_start --> ga_start + npages * PAGE_SIZE
*
* in lcd's ept.
*/
int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, u64 gpa_start, u64 npages);
int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, gpa_t ga_start,
unsigned long npages);
/**
* Simple routine combinding ept walk and get.
*/
int lcd_arch_ept_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 *hpa_out);
int lcd_arch_ept_gpa_to_hpa(struct lcd_arch *vcpu, gpa_t ga, hpa_t *ha_out);
/**
* Set the lcd's program counter to the guest physical address
* gpa.
* a.
*/
int lcd_arch_set_pc(struct lcd_arch *vcpu, u64 gpa);
int lcd_arch_set_pc(struct lcd_arch *vcpu, gpa_t a);
/**
* Set the lcd's gva root pointer (for x86, %cr3) to the
* guest physical address gpa.
* guest physical address a.
*/
int lcd_arch_set_gva_root(struct lcd_arch *vcpu, u64 gpa);
int lcd_arch_set_gva_root(struct lcd_arch *vcpu, gpa_t a);
/*
* GDT Layout
......@@ -242,16 +338,16 @@ int lcd_arch_set_gva_root(struct lcd_arch *vcpu, u64 gpa);
* See Intel SDM V3 3.4.2, 3.4.3 for segment register layout
* See Intel SDM V3 2.4.1 - 2.4.4 for gdtr, ldtr, idtr, tr
*/
#define LCD_ARCH_FS_BASE 0x0UL
#define LCD_ARCH_FS_BASE __gpa(0UL);
#define LCD_ARCH_FS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GS_BASE 0x0UL
#define LCD_ARCH_GS_BASE __gpa(0UL);
#define LCD_ARCH_GS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GDTR_BASE 0x0000000000001000UL
#define LCD_ARCH_GDTR_BASE __gpa(1UL << PAGE_SHIFT);
#define LCD_ARCH_GDTR_LIMIT ((u32)~(PAGE_SIZE - 1))
#define LCD_ARCH_TSS_BASE 0x0000000000002000UL
#define LCD_ARCH_TSS_BASE __gpa(2UL << PAGE_SHIFT);
/* tss base + limit = address of last byte in tss, hence -1 */
#define LCD_ARCH_TSS_LIMIT (sizeof(struct lcd_arch_tss) - 1)
#define LCD_ARCH_IDTR_BASE 0x0UL
#define LCD_ARCH_IDTR_BASE __gpa(0UL);
#define LCD_ARCH_IDTR_LIMIT 0x0 /* no idt right now */
#define LCD_ARCH_CS_SELECTOR (1 << 3)
......@@ -288,8 +384,8 @@ int lcd_arch_set_gva_root(struct lcd_arch *vcpu, u64 gpa);
* | (not mapped) | (4 KBs)
* +---------------------------+ 0x0000 0000 0000 0000
*/
#define LCD_ARCH_UTCB 0x0000000000003000UL
#define LCD_ARCH_STACK_TOP 0x0000000000004000UL
#define LCD_ARCH_UTCB __gpa(3UL << PAGE_SHIFT);
#define LCD_ARCH_STACK_TOP __gpa(4UL << PAGE_SHIFT);
#define LCD_ARCH_FREE LCD_ARCH_STACK_TOP
/*
......
......@@ -138,11 +138,11 @@ static inline bool cpu_has_vmx_ept_ad_bits(void)
return vmx_capability.ept & VMX_EPT_AD_BIT;
}
static inline void __invept(int ext, u64 eptp, u64 gpa)
static inline void __invept(int ext, u64 eptp, gpa_t a)
{
struct {
u64 eptp, gpa;
} operand = {eptp, gpa};
} operand = {eptp, gpa_val(a)};
asm volatile (ASM_VMX_INVEPT
/* CF==1 or ZF==1 --> rc = -1 */
......@@ -171,13 +171,13 @@ static inline void invept_single_context(u64 eptp)
invept_global_context();
}
static inline void __invvpid(int ext, u16 vpid, u64 gva)
static inline void __invvpid(int ext, u16 vpid)
{
struct {
u64 vpid : 16;
u64 rsvd : 48;
u64 gva;
} operand = { vpid, 0, gva };
u64 addr;
} operand = { vpid, 0, 0 };
asm volatile (ASM_VMX_INVVPID
/* CF==1 or ZF==1 --> rc = -1 */
......@@ -192,7 +192,7 @@ static inline void __invvpid(int ext, u16 vpid, u64 gva)
static inline void invvpid_global_context(void)
{
if (cpu_has_vmx_invvpid_global())
__invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
__invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0);
}
/**
......@@ -207,7 +207,7 @@ static inline void invvpid_single_context(u16 vpid)
return;
if (cpu_has_vmx_invvpid_single())
__invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid, 0);
__invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid);
else
invvpid_global_context();
}
......@@ -219,15 +219,15 @@ static inline void invvpid_single_context(u16 vpid)
*/
static void vmcs_clear(struct lcd_arch_vmcs *vmcs)
{
u64 phys_addr = __pa(vmcs);
hpa_t a = va2hpa(vmcs);
u8 error;
asm volatile (ASM_VMX_VMCLEAR_RAX "; setna %0"
: "=qm"(error) : "a"(&phys_addr), "m"(phys_addr)
: "=qm"(error) : "a"(hpa_ptr(&a)), "m"(hpa_val(a))
: "cc", "memory");
if (error)
printk(KERN_ERR "lcd vmx: vmclear fail: %p/%llx\n",
vmcs, phys_addr);
vmcs, hpa_val(a));
}
/**
......@@ -236,15 +236,15 @@ static void vmcs_clear(struct lcd_arch_vmcs *vmcs)
*/
static void vmcs_load(struct lcd_arch_vmcs *vmcs)
{
u64 phys_addr = __pa(vmcs);
hpa_t a = va2hpa(vmcs);
u8 error;
asm volatile (ASM_VMX_VMPTRLD_RAX "; setna %0"
: "=qm"(error) : "a"(&phys_addr), "m"(phys_addr)
: "=qm"(error) : "a"(hpa_ptr(&a)), "m"(hpa_val(a))
: "cc", "memory");
if (error)
printk(KERN_ERR "lcd vmx: vmptrld %p/%llx failed\n",
vmcs, phys_addr);
vmcs, hpa_val(a));
}
static __always_inline unsigned long vmcs_readl(unsigned long field)
......@@ -337,10 +337,10 @@ static struct lcd_arch_vmcs *vmx_alloc_vmcs(int cpu)
/* VMX ON/OFF --------------------------------------------------*/
static inline void __vmxon(u64 addr)
static inline void __vmxon(hpa_t addr)
{
asm volatile (ASM_VMX_VMXON_RAX
: : "a"(&addr), "m"(addr)
: : "a"(hpa_ptr(&addr)), "m"(addr)
: "memory", "cc");
}
......@@ -355,11 +355,11 @@ static inline void __vmxoff(void)
*/
static int __vmx_enable(struct lcd_arch_vmcs *vmxon_buf)
{
u64 phys_addr;
hpa_t a;
u64 old;
u64 test_bits;
phys_addr = __pa(vmxon_buf);
a = va2hpa(vmxon_buf);
/*
* Intel SDM V3 23.7
......@@ -390,7 +390,7 @@ static int __vmx_enable(struct lcd_arch_vmcs *vmxon_buf)
/*
* Turn on vmx
*/
__vmxon(phys_addr);
__vmxon(a);
return 0;
......@@ -887,17 +887,17 @@ void lcd_arch_exit(void)
#define VMX_EPT_ALL_MASK (VMX_EPT_READABLE_MASK | \
VMX_EPT_WRITABLE_MASK | \
VMX_EPT_EXECUTABLE_MASK)
static inline u64 vmx_epte_hpa(lcd_arch_epte_t epte)
static inline hpa_t vmx_epte_hpa(lcd_arch_epte_t epte)
{
return ((u64)epte) & VMX_EPTE_ADDR_MASK;
return __hpa(((u64)epte) & VMX_EPTE_ADDR_MASK);
}
static inline u64 vmx_epte_hva(lcd_arch_epte_t epte)
static inline hva_t vmx_epte_hva(lcd_arch_epte_t epte)
{
return (u64)__va(vmx_epte_hpa(epte));
return hpa2hva(vmx_epte_hpa(epte));
}
static inline lcd_arch_epte_t * vmx_epte_dir_hva(lcd_arch_epte_t epte)
{
return (lcd_arch_epte_t *)vmx_epte_hva(epte);
return (lcd_arch_epte_t *)hva_val(vmx_epte_hva(epte));
}
static inline int vmx_epte_present(lcd_arch_epte_t epte)
{
......@@ -909,13 +909,13 @@ static inline int vmx_epte_present(lcd_arch_epte_t epte)
* level 2 (PD) = bits 29:21 (9 bits)
* level 3 (PT) = bits 20:12 (9 bits)
*/
static inline int vmx_ept_idx(u64 gpa, int lvl)
static inline int vmx_ept_idx(gpa_t a, int lvl)
{
return (int)(((gpa) >> (12 + 9 * (3 - lvl))) & ((1 << 9) - 1));
return (int)(((gpa_val(a)) >> (12 + 9 * (3 - lvl))) & ((1 << 9) - 1));
}
static inline u64 vmx_ept_offset(u64 gpa)
static inline u64 vmx_ept_offset(gpa_t a)
{
return gpa & ~(PAGE_MASK);
return gpa_val(a) & ~(PAGE_MASK);
}
enum vmx_epte_mts {
......@@ -940,13 +940,13 @@ enum vmx_epte_mts {
*
* See Intel SDM V3 Figure 28-1 and 28.2.2.
*/
static void vmx_epte_set(lcd_arch_epte_t *epte, u64 hpa, int level)
static void vmx_epte_set(lcd_arch_epte_t *epte, hpa_t a, int level)
{
/*
* zero out epte, and set
*/
*epte = 0;
*epte = (hpa & VMX_EPTE_ADDR_MASK) | VMX_EPT_ALL_MASK;
*epte = (hpa_val(a) & VMX_EPTE_ADDR_MASK) | VMX_EPT_ALL_MASK;
if (level == 3) {
/*
* Page table entry. Set EPT memory type to write back
......@@ -957,15 +957,15 @@ static void vmx_epte_set(lcd_arch_epte_t *epte, u64 hpa, int level)
}
}
int lcd_arch_ept_walk(struct lcd_arch *vcpu, u64 gpa, int create,
int lcd_arch_ept_walk(struct lcd_arch *vcpu, gpa_t a, int create,
lcd_arch_epte_t **epte_out)
{
int i;
lcd_arch_epte_t *dir;
u64 idx;
u64 page;
hva_t page;
dir = (lcd_arch_epte_t *) __va(vcpu->ept.root_hpa);
dir = (lcd_arch_epte_t *) hpa2va(vcpu->ept.root);
/*
* Walk plm4 -> pdpt -> pd. Each step uses 9 bits
......@@ -973,39 +973,39 @@ int lcd_arch_ept_walk(struct lcd_arch *vcpu, u64 gpa, int create,
*/
for (i = 0; i < LCD_ARCH_EPT_WALK_LENGTH - 1; i++) {
idx = vmx_ept_idx(gpa, i);
idx = vmx_ept_idx(a, i);
if (!vmx_epte_present(dir[idx])) {
if (!create) {
printk(KERN_ERR "lcd_arch_ept_walk: attempted lookup for unmapped gpa %lx, create was not allowed\n",
(unsigned long)gpa);
gpa_val(a));
return -ENOENT;
}
/*
* Get host virtual addr of fresh page, and
* set the epte's addr to the host physical addr
*/
page = __get_free_page(GFP_KERNEL);
page = __hva(__get_free_page(GFP_KERNEL));
if (!page) {
printk(KERN_ERR "lcd_arch_ept_walk: alloc failed\n");
return -ENOMEM;
}
memset((void *)page, 0, PAGE_SIZE);
vmx_epte_set(&dir[idx], __pa(page), i);
memset(hva2va(page), 0, PAGE_SIZE);
vmx_epte_set(&dir[idx], hva2hpa(page), i);
}
dir = (lcd_arch_epte_t *) vmx_epte_hva(dir[idx]);
dir = (lcd_arch_epte_t *) hva2va(vmx_epte_hva(dir[idx]));
}
/*
* dir points to page table (level 3)
*/
*epte_out = &dir[vmx_ept_idx(gpa, 3)];
*epte_out = &dir[vmx_ept_idx(a, 3)];
return 0;
}
void lcd_arch_ept_set(lcd_arch_epte_t *epte, u64 hpa)
void lcd_arch_ept_set(lcd_arch_epte_t *epte, hpa_t a)
{
vmx_epte_set(epte, hpa, 3);
}
......@@ -1016,12 +1016,12 @@ int lcd_arch_ept_unset(lcd_arch_epte_t *epte)
return 0;
}
u64 lcd_arch_ept_hpa(lcd_arch_epte_t *epte)
hpa_t lcd_arch_ept_hpa(lcd_arch_epte_t *epte)
{
return vmx_epte_hpa(*epte);
}
int lcd_arch_ept_map_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 hpa,
int lcd_arch_ept_map(struct lcd_arch *vcpu, gpa_t ga, hpa_t ha,
int create, int overwrite)
{
int ret;
......@@ -1030,7 +1030,7 @@ int lcd_arch_ept_map_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 hpa,
/*
* Walk ept
*/
ret = lcd_arch_ept_walk(vcpu, gpa, create, &ept_entry);
ret = lcd_arch_ept_walk(vcpu, ga, create, &ept_entry);
if (ret)
return ret;
......@@ -1038,40 +1038,40 @@ int lcd_arch_ept_map_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 hpa,
* Check if guest physical address already mapped
*/
if (!overwrite && vmx_epte_present(*ept_entry)) {
printk(KERN_ERR "lcd_arch_map_gpa_to_hpa: would overwrite hpa %lx with hpa %lx\n",
(unsigned long)lcd_arch_ept_hpa(ept_entry),
(unsigned long)hpa);
printk(KERN_ERR "lcd_arch_ept_map: would overwrite hpa %lx with hpa %lx\n",
hpa_val(lcd_arch_ept_hpa(ept_entry)),
hpa_val(ha));
return -EINVAL;
}
/*
* Map the guest physical addr to the host physical addr.
*/
lcd_arch_ept_set(ept_entry, hpa);
lcd_arch_ept_set(ept_entry, ha);
return 0;
}
int lcd_arch_ept_map_range(struct lcd_arch *lcd, u64 gpa_start, u64 hpa_start,
u64 npages)
int lcd_arch_ept_map_range(struct lcd_arch *lcd, gpa_t ga_start, hpa_t ha_start,
unsigned long npages)
{
u64 off;
u64 len;
unsigned long off;
unsigned long len;
len = npages * PAGE_SIZE;
for (off = 0; off < len; off += PAGE_SIZE) {
if (lcd_arch_ept_map_gpa_to_hpa(lcd,
/* gpa */
gpa_start + off,
gpa_val(ga_start) + off,
/* hpa */
hpa_start + off,
hpa_val(ha_start) + off,
/* create */
1,
/* no overwrite */
0)) {
printk(KERN_ERR "lcd_arch_ept_map_range: error mapping gpa %lx to hpa %lx\n",
(unsigned long)(gpa_start + off),
(unsigned long)(hpa_start + off));
gpa_val(gpa_start) + off,
hpa_val(hpa_start) + off));
return -EIO;
}
}
......@@ -1079,7 +1079,7 @@ int lcd_arch_ept_map_range(struct lcd_arch *lcd, u64 gpa_start, u64 hpa_start,
return 0;
}
int lcd_arch_ept_unmap_gpa(struct lcd_arch *vcpu, u64 gpa)
int lcd_arch_ept_unmap_gpa(struct lcd_arch *vcpu, gpa_t a)
{
int ret;
lcd_arch_epte_t *ept_entry;
......@@ -1087,7 +1087,7 @@ int lcd_arch_ept_unmap_gpa(struct lcd_arch *vcpu, u64 gpa)
/*
* Walk ept
*/
ret = lcd_arch_ept_walk(vcpu, gpa, 0, &ept_entry);
ret = lcd_arch_ept_walk(vcpu, a, 0, &ept_entry);
if (ret)
return ret;
......@@ -1099,23 +1099,17 @@ int lcd_arch_ept_unmap_gpa(struct lcd_arch *vcpu, u64 gpa)
return 0;
}
/**
* Unmaps
*
* gpa_start --> gpa_start + npages * PAGE_SIZE
*
* in lcd's ept.
*/
int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, u64 gpa_start, u64 npages)
int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, gpa_t ga_start,
unsigned long npages)
{
u64 off;
u64 len;
unsigned long off;
unsigned long len;
len = npages * PAGE_SIZE;
for (off = 0; off < len; off += PAGE_SIZE) {
if (lcd_arch_ept_unmap_gpa(lcd, gpa_start + off)) {
if (lcd_arch_ept_unmap(lcd, gpa_add(ga_start, off))) {
printk(KERN_ERR "lcd_arch_ept_unmap_range: error unmapping gpa %lx\n",
(unsigned long)(gpa_start + off));
gpa_val(gpa_add(ga_start, off)));
return -EIO;
}
}
......@@ -1123,15 +1117,16 @@ int lcd_arch_ept_unmap_range(struct lcd_arch *lcd, u64 gpa_start, u64 npages)
return 0;
}
int lcd_arch_ept_gpa_to_hpa(struct lcd_arch *vcpu, u64 gpa, u64 *hpa_out)
int lcd_arch_ept_gpa_to_hpa(struct lcd_arch *vcpu, gpa_t ga, hpa_t *ha_out)
{
int ret;
lcd_arch_epte_t *ept_entry;
hpa_t hpa;