210 lines
7.6 KiB
Diff
210 lines
7.6 KiB
Diff
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 <asm/hvm/vpt.h>
|
|
#include <public/hvm/save.h>
|
|
#include <asm/hvm/trace.h>
|
|
+#include <asm/hap.h>
|
|
|
|
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,
|