x86/EPT: work around hardware erratum setting A bit

Since commit 191b3f3344 ("p2m/ept: enable PML in p2m-ept for
log-dirty"), the A and D bits of EPT paging entries are set
unconditionally, regardless of whether PML is enabled or not. This
causes a regression in Xen 4.6 on some processors due to Intel Errata
AVR41 -- HVM guests get severe memory corruption when the A bit is set
due to incorrect TLB flushing on mov to cr3. The erratum affects the
Atom C2000 family (Avoton).

To fix, do not set the A bit on this processor family.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>

Move feature suppression to feature detection code. Add command line
override.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Ross Lagerwall authored and Jan Beulich committed 2015-10-02 13:39:12 +02:00
1 parent c6e348570c
commit 33b55dc103
4 files changed
+38 -17

No files matched your search

+18 -9
View File
@@ -705,19 +705,28 @@ virtualization, to allow the L1 hypervisor to use EPT even if the L0 hypervisor
does not provide VM\_ENTRY\_LOAD\_GUEST\_PAT.
### ept (Intel)
> `= List of ( pml<boolean> )`
> `= List of ( {no-}pml | {no-}ad )`
Controls EPT related features.
> Sub-options:
> `pml`
> Default: `false`
Controls EPT related features. Currently only Page Modification Logging (PML) is
the controllable feature as boolean type.
>> PML is a new hardware feature in Intel's Broadwell Server and further
>> platforms which reduces hypervisor overhead of log-dirty mechanism by
>> automatically recording GPAs (guest physical addresses) when guest memory
>> gets dirty, and therefore significantly reducing number of EPT violation
>> caused by write protection of guest memory, which is a necessity to
>> implement log-dirty mechanism before PML.
PML is a new hardware feature in Intel's Broadwell Server and further platforms
which reduces hypervisor overhead of log-dirty mechanism by automatically
recording GPAs (guest physical addresses) when guest memory gets dirty, and
therefore significantly reducing number of EPT violation caused by write
protection of guest memory, which is a necessity to implement log-dirty
mechanism before PML.
> `ad`
> Default: Hardware dependent
>> Have hardware keep accessed/dirty (A/D) bits updated.
### gdb
> `= <baud>[/<clock_hz>][,DPS[,<io-base>[,<irq>[,<port-bdf>[,<bridge-bdf>]]]] | pci | amt ] `
+11
View File
@@ -64,12 +64,14 @@ static unsigned int __read_mostly ple_window = 4096;
integer_param("ple_window", ple_window);
static bool_t __read_mostly opt_pml_enabled = 0;
static s8 __read_mostly opt_ept_ad = -1;
/*
* The 'ept' parameter controls functionalities that depend on, or impact the
* EPT mechanism. Optional comma separated value may contain:
*
* pml Enable PML
* ad Use A/D bits
*/
static void __init parse_ept_param(char *s)
{
@@ -87,6 +89,8 @@ static void __init parse_ept_param(char *s)
if ( !strcmp(s, "pml") )
opt_pml_enabled = val;
else if ( !strcmp(s, "ad") )
opt_ept_ad = val;
s = ss + 1;
} while ( ss );
@@ -268,6 +272,13 @@ static int vmx_init_vmcs_config(void)
{
rdmsrl(MSR_IA32_VMX_EPT_VPID_CAP, _vmx_ept_vpid_cap);
if ( !opt_ept_ad )
_vmx_ept_vpid_cap &= ~VMX_EPT_AD_BIT;
else if ( /* Work around Erratum AVR41 on Avoton processors. */
boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x4d &&
opt_ept_ad < 0 )
_vmx_ept_vpid_cap &= ~VMX_EPT_AD_BIT;
/*
* Additional sanity checking before using EPT:
* 1) the CPU we are running on must support EPT WB, as we will set
+8 -8
View File
@@ -130,14 +130,14 @@ static void ept_p2m_type_to_flags(struct p2m_domain *p2m, ept_entry_t *entry,
break;
case p2m_ram_rw:
entry->r = entry->w = entry->x = 1;
entry->a = entry->d = 1;
entry->a = entry->d = !!cpu_has_vmx_ept_ad;
break;
case p2m_mmio_direct:
entry->r = entry->x = 1;
entry->w = !rangeset_contains_singleton(mmio_ro_ranges,
entry->mfn);
entry->a = 1;
entry->d = entry->w;
entry->a = !!cpu_has_vmx_ept_ad;
entry->d = entry->w && cpu_has_vmx_ept_ad;
break;
case p2m_ram_logdirty:
entry->r = entry->x = 1;
@@ -152,7 +152,7 @@ static void ept_p2m_type_to_flags(struct p2m_domain *p2m, ept_entry_t *entry,
entry->w = 1;
else
entry->w = 0;
entry->a = 1;
entry->a = !!cpu_has_vmx_ept_ad;
/* For both PML or non-PML cases we clear D bit anyway */
entry->d = 0;
break;
@@ -160,20 +160,20 @@ static void ept_p2m_type_to_flags(struct p2m_domain *p2m, ept_entry_t *entry,
case p2m_ram_shared:
entry->r = entry->x = 1;
entry->w = 0;
entry->a = 1;
entry->a = !!cpu_has_vmx_ept_ad;
entry->d = 0;
break;
case p2m_grant_map_rw:
case p2m_map_foreign:
entry->r = entry->w = 1;
entry->x = 0;
entry->a = entry->d = 1;
entry->a = entry->d = !!cpu_has_vmx_ept_ad;
break;
case p2m_grant_map_ro:
case p2m_mmio_write_dm:
entry->r = 1;
entry->w = entry->x = 0;
entry->a = 1;
entry->a = !!cpu_has_vmx_ept_ad;
entry->d = 0;
break;
}
@@ -233,7 +233,7 @@ static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
ept_entry->r = ept_entry->w = ept_entry->x = 1;
/* Manually set A bit to avoid overhead of MMU having to write it later. */
ept_entry->a = 1;
ept_entry->a = !!cpu_has_vmx_ept_ad;
ept_entry->suppress_ve = 1;
+1
View File
@@ -262,6 +262,7 @@ extern uint8_t posted_intr_vector;
(vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_1GB)
#define cpu_has_vmx_ept_2mb \
(vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_2MB)
#define cpu_has_vmx_ept_ad (vmx_ept_vpid_cap & VMX_EPT_AD_BIT)
#define cpu_has_vmx_ept_invept_single_context \
(vmx_ept_vpid_cap & VMX_EPT_INVEPT_SINGLE_CONTEXT)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.