xen/53356c1e-x86-HVM-correct-CPUID-leaf-80000008-handling.patch
Charles Arnold 73fd9f3c19 - Upstream patches from Jan
53356c1e-x86-HVM-correct-CPUID-leaf-80000008-handling.patch
  533ad1ee-VMX-fix-PAT-value-seen-by-guest.patch
  533d413b-x86-mm-fix-checks-against-max_mapped_pfn.patch

- bnc#862608 - SLES 11 SP3 vm-install should get RHEL 7 support
  when released
  53206661-pygrub-support-linux16-and-initrd16.patch
- Upstream bug fixes
  53299d8f-xenconsole-reset-tty-on-failure.patch
  53299d8f-xenconsole-tolerate-tty-errors.patch
- fix build for armv7l and aarch64

- Remove compiletime strings from qemu-upstream
  qemu-xen-upstream-megasas-buildtime.patch

- bnc#871546 - KMPs are not signed in SUSE:SLE-12:GA? 
  xen.spec

- Upstream patches from Jan
  532fff53-x86-fix-determination-of-bit-count-for-struct-domain-allocations.patch
  5331917d-x86-enforce-preemption-in-HVM_set_mem_access-p2m_set_mem_access.patch
- Drop xsa89.patch for upstream version (see bnc#867910, 5331917d-x86-enforce...)

OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=309
2014-04-10 06:04:31 +00:00

142 lines
4.9 KiB
Diff

# Commit ef437690af8b75e6758dce77af75a22b63982883
# Date 2014-03-28 13:33:34 +0100
# Author Jan Beulich <jbeulich@suse.com>
# Committer Jan Beulich <jbeulich@suse.com>
x86/HVM: correct CPUID leaf 80000008 handling
CPUID[80000008].EAX[23:16] have been given the meaning of the guest
physical address restriction (in case it needs to be smaller than the
host's), hence we need to mirror that into vCPUID[80000008].EAX[7:0].
Enforce a lower limit at the same time, as well as a fixed value for
the virtual address bits, and zero for the guest physical address ones.
In order for the vMTRR code to see these overrides we need to make it
call hvm_cpuid() instead of domain_cpuid(), which in turn requires
special casing (and relaxing) the controlling domain.
This additionally should hide an ordering problem in the tools: Both
xend and xl appear to be restoring a guest from its image before
setting up the CPUID policy in the hypervisor, resulting in
domain_cpuid() returning all zeros and hence the check in
mtrr_var_range_msr_set() failing if the guest previously had more than
the minimum 36 physical address bits.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Tim Deegan <tim@xen.org>
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2885,6 +2885,8 @@ void hvm_cpuid(unsigned int input, unsig
switch ( input )
{
+ unsigned int sub_leaf, _eax, _ebx, _ecx, _edx;
+
case 0x1:
/* Fix up VLAPIC details. */
*ebx &= 0x00FFFFFFu;
@@ -2918,8 +2920,6 @@ void hvm_cpuid(unsigned int input, unsig
*edx = v->vcpu_id * 2;
break;
case 0xd:
- {
- unsigned int sub_leaf, _eax, _ebx, _ecx, _edx;
/* EBX value of main leaf 0 depends on enabled xsave features */
if ( count == 0 && v->arch.xcr0 )
{
@@ -2936,7 +2936,7 @@ void hvm_cpuid(unsigned int input, unsig
}
}
break;
- }
+
case 0x80000001:
/* We expose RDTSCP feature to guest only when
tsc_mode == TSC_MODE_DEFAULT and host_tsc_is_safe() returns 1 */
@@ -2950,6 +2950,23 @@ void hvm_cpuid(unsigned int input, unsig
if ( !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
*edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
break;
+
+ case 0x80000008:
+ count = cpuid_eax(0x80000008);
+ count = (count >> 16) & 0xff ?: count & 0xff;
+ if ( (*eax & 0xff) > count )
+ *eax = (*eax & ~0xff) | count;
+
+ hvm_cpuid(1, NULL, NULL, NULL, &_edx);
+ count = _edx & (cpufeat_mask(X86_FEATURE_PAE) |
+ cpufeat_mask(X86_FEATURE_PSE36)) ? 36 : 32;
+ if ( (*eax & 0xff) < count )
+ *eax = (*eax & ~0xff) | count;
+
+ hvm_cpuid(0x80000001, NULL, NULL, NULL, &_edx);
+ *eax = (*eax & ~0xffff00) | (_edx & cpufeat_mask(X86_FEATURE_LM)
+ ? 0x3000 : 0x2000);
+ break;
}
}
--- a/xen/arch/x86/hvm/mtrr.c
+++ b/xen/arch/x86/hvm/mtrr.c
@@ -145,7 +145,7 @@ bool_t is_var_mtrr_overlapped(struct mtr
static int hvm_mtrr_pat_init(void)
{
- unsigned int i, j, phys_addr;
+ unsigned int i, j;
memset(&mtrr_epat_tbl, INVALID_MEM_TYPE, sizeof(mtrr_epat_tbl));
for ( i = 0; i < MTRR_NUM_TYPES; i++ )
@@ -172,11 +172,7 @@ static int hvm_mtrr_pat_init(void)
}
}
- phys_addr = 36;
- if ( cpuid_eax(0x80000000) >= 0x80000008 )
- phys_addr = (uint8_t)cpuid_eax(0x80000008);
-
- size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
+ size_or_mask = ~((1 << (paddr_bits - PAGE_SHIFT)) - 1);
return 0;
}
@@ -455,7 +451,7 @@ bool_t mtrr_fix_range_msr_set(struct mtr
bool_t mtrr_var_range_msr_set(
struct domain *d, struct mtrr_state *m, uint32_t msr, uint64_t msr_content)
{
- uint32_t index, type, phys_addr, eax, ebx, ecx, edx;
+ uint32_t index, type, phys_addr, eax;
uint64_t msr_mask;
uint64_t *var_range_base = (uint64_t*)m->var_ranges;
@@ -468,16 +464,21 @@ bool_t mtrr_var_range_msr_set(
type == 4 || type == 5 || type == 6)) )
return 0;
- phys_addr = 36;
- domain_cpuid(d, 0x80000000, 0, &eax, &ebx, &ecx, &edx);
- if ( eax >= 0x80000008 )
+ if ( d == current->domain )
{
- domain_cpuid(d, 0x80000008, 0, &eax, &ebx, &ecx, &edx);
- phys_addr = (uint8_t)eax;
+ phys_addr = 36;
+ hvm_cpuid(0x80000000, &eax, NULL, NULL, NULL);
+ if ( eax >= 0x80000008 )
+ {
+ hvm_cpuid(0x80000008, &eax, NULL, NULL, NULL);
+ phys_addr = (uint8_t)eax;
+ }
}
+ else
+ phys_addr = paddr_bits;
msr_mask = ~((((uint64_t)1) << phys_addr) - 1);
msr_mask |= (index & 1) ? 0x7ffUL : 0xf00UL;
- if ( unlikely(msr_content && (msr_content & msr_mask)) )
+ if ( unlikely(msr_content & msr_mask) )
{
HVM_DBG_LOG(DBG_LEVEL_MSR, "invalid msr content:%"PRIx64"\n",
msr_content);