Index: xen-3.2-testing/xen/arch/x86/hvm/vmx/vmx.c =================================================================== --- xen-3.2-testing.orig/xen/arch/x86/hvm/vmx/vmx.c +++ xen-3.2-testing/xen/arch/x86/hvm/vmx/vmx.c @@ -50,6 +50,7 @@ #include #include #include +#include enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised }; @@ -2854,9 +2855,44 @@ void vmx_wbinvd_intercept(void) static void ept_handle_violation(unsigned long qualification, paddr_t gpa) { - if ( unlikely(((qualification >> 7) & 0x3) != 0x3) ) + unsigned long gla_validity = qualification & EPT_GLA_VALIDITY_MASK; + struct domain *d = current->domain; + u64 gfn = gpa >> PAGE_SHIFT; + mfn_t mfn; + p2m_type_t t; + + /* GPA exceeds GAW. */ + if ( unlikely(qualification & EPT_GAW_VIOLATION) ) { - domain_crash(current->domain); + printk("EPT violation: guest physical address %"PRIpaddr" exceeded " + "its width limit.\n", gpa); + domain_crash(d); + } + + if ( gla_validity == EPT_GLA_VALIDITY_RSVD || + gla_validity == EPT_GLA_VALIDITY_PDPTR_LOAD ) + { + printk("ept violation: reserved bit or pdptr load violation.\n"); + domain_crash(d); + } + + mfn = gfn_to_mfn(d, gfn, &t); + + if ( unlikely( gla_validity != EPT_GLA_VALIDITY_MATCH) ) + { + if ( p2m_is_ram(t) && paging_mode_log_dirty(d) ) + goto mark_dirty; + domain_crash(d); + return; + } + +mark_dirty: + + if ( p2m_is_ram(t) && paging_mode_log_dirty(d) ) + { + paging_mark_dirty(d, mfn_x(mfn)); + p2m_change_type(d, gfn, p2m_ram_logdirty, p2m_ram_rw); + flush_tlb_mask(d->domain_dirty_cpumask); return; } Index: xen-3.2-testing/xen/arch/x86/mm/hap/hap.c =================================================================== --- xen-3.2-testing.orig/xen/arch/x86/mm/hap/hap.c +++ xen-3.2-testing/xen/arch/x86/mm/hap/hap.c @@ -61,7 +61,7 @@ int hap_enable_log_dirty(struct domain * hap_unlock(d); /* set l1e entries of P2M table to be read-only. */ - p2m_change_type_global(d, p2m_ram_rw, p2m_ram_logdirty); + p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty); flush_tlb_mask(d->domain_dirty_cpumask); return 0; } @@ -73,14 +73,14 @@ int hap_disable_log_dirty(struct domain hap_unlock(d); /* set l1e entries of P2M table with normal mode */ - p2m_change_type_global(d, p2m_ram_logdirty, p2m_ram_rw); + p2m_change_entry_type_global(d, p2m_ram_logdirty, p2m_ram_rw); return 0; } void hap_clean_dirty_bitmap(struct domain *d) { /* set l1e entries of P2M table to be read-only. */ - p2m_change_type_global(d, p2m_ram_rw, p2m_ram_logdirty); + p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty); flush_tlb_mask(d->domain_dirty_cpumask); } Index: xen-3.2-testing/xen/arch/x86/mm/p2m.c =================================================================== --- xen-3.2-testing.orig/xen/arch/x86/mm/p2m.c +++ xen-3.2-testing/xen/arch/x86/mm/p2m.c @@ -279,11 +279,19 @@ void p2m_init(struct domain *d) d->arch.p2m.set_entry = p2m_set_entry; d->arch.p2m.get_entry = p2m_gfn_to_mfn; d->arch.p2m.get_entry_fast = p2m_gfn_to_mfn_fast; + d->arch.p2m.change_entry_type_global = p2m_change_type_global; if ( is_hvm_domain(d) ) hvm_p2m_init(d); } +void p2m_change_entry_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt) +{ + p2m_lock(d); + d->arch.p2m.change_entry_type_global(d, ot, nt); + p2m_unlock(d); +} + static inline int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt) { @@ -806,8 +814,6 @@ void p2m_change_type_global(struct domai if ( pagetable_get_pfn(d->arch.phys_table) == 0 ) return; - p2m_lock(d); - #if CONFIG_PAGING_LEVELS == 4 l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); #elif CONFIG_PAGING_LEVELS == 3 @@ -878,7 +884,6 @@ void p2m_change_type_global(struct domai unmap_domain_page(l2e); #endif - p2m_unlock(d); } /* Modify the p2m type of a single gfn from ot to nt, returning the Index: xen-3.2-testing/xen/include/asm-x86/domain.h =================================================================== --- xen-3.2-testing.orig/xen/include/asm-x86/domain.h +++ xen-3.2-testing/xen/include/asm-x86/domain.h @@ -171,6 +171,8 @@ struct p2m_domain { p2m_type_t *p2mt); mfn_t (*get_entry_fast)(unsigned long gfn, p2m_type_t *p2mt); + void (*change_entry_type_global)(struct domain *d, + p2m_type_t ot, p2m_type_t nt); /* Highest guest frame that's ever been mapped in the p2m */ unsigned long max_mapped_pfn; }; Index: xen-3.2-testing/xen/include/asm-x86/hap.h =================================================================== --- xen-3.2-testing.orig/xen/include/asm-x86/hap.h +++ xen-3.2-testing/xen/include/asm-x86/hap.h @@ -97,6 +97,49 @@ extern struct paging_mode hap_paging_pro extern struct paging_mode hap_paging_pae_mode; extern struct paging_mode hap_paging_long_mode; +/* EPT violation qualifications definitions */ +/* bit offset 0 in exit qualification */ +#define _EPT_READ_VIOLATION 0 +#define EPT_READ_VIOLATION (1UL<<_EPT_READ_VIOLATION) +/* bit offset 1 in exit qualification */ +#define _EPT_WRITE_VIOLATION 1 +#define EPT_WRITE_VIOLATION (1UL<<_EPT_WRITE_VIOLATION) +/* bit offset 2 in exit qualification */ +#define _EPT_EXEC_VIOLATION 2 +#define EPT_EXEC_VIOLATION (1UL<<_EPT_EXEC_VIOLATION) + +/* bit offset 3 in exit qualification */ +#define _EPT_EFFECTIVE_READ 3 +#define EPT_EFFECTIVE_READ (1UL<<_EPT_EFFECTIVE_READ) +/* bit offset 4 in exit qualification */ +#define _EPT_EFFECTIVE_WRITE 4 +#define EPT_EFFECTIVE_WRITE (1UL<<_EPT_EFFECTIVE_WRITE) +/* bit offset 5 in exit qualification */ +#define _EPT_EFFECTIVE_EXEC 5 +#define EPT_EFFECTIVE_EXEC (1UL<<_EPT_EFFECTIVE_EXEC) + +/* bit offset 6 in exit qualification */ +#define _EPT_GAW_VIOLATION 6 +#define EPT_GAW_VIOLATION (1UL<<_EPT_GAW_VIOLATION) + +/* bits offset 7 & 8 in exit qualification */ +#define _EPT_GLA_VALIDITY 7 +#define EPT_GLA_VALIDITY_MASK (3UL<<_EPT_GLA_VALIDITY) +/* gla != gpa, when load PDPTR */ +#define EPT_GLA_VALIDITY_PDPTR_LOAD (0UL<<_EPT_GLA_VALIDITY) +/* gla != gpa, during guest page table walking */ +#define EPT_GLA_VALIDITY_GPT_WALK (1UL<<_EPT_GLA_VALIDITY) +/* reserved */ +#define EPT_GLA_VALIDITY_RSVD (2UL<<_EPT_GLA_VALIDITY) +/* gla == gpa, normal case */ +#define EPT_GLA_VALIDITY_MATCH (3UL<<_EPT_GLA_VALIDITY) + +#define EPT_EFFECTIVE_MASK (EPT_EFFECTIVE_READ | \ + EPT_EFFECTIVE_WRITE | \ + EPT_EFFECTIVE_EXEC) + +#define EPT_PAGETABLE_ENTRIES 512 + #endif /* XEN_HAP_H */ /* Index: xen-3.2-testing/xen/include/asm-x86/p2m.h =================================================================== --- xen-3.2-testing.orig/xen/include/asm-x86/p2m.h +++ xen-3.2-testing/xen/include/asm-x86/p2m.h @@ -209,6 +209,7 @@ void guest_physmap_remove_page(struct do /* Change types across all p2m entries in a domain */ void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt); +void p2m_change_entry_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt); /* Compare-exchange the type of a single p2m entry */ p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,