Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hypervisor/x86/xen: Unset X86_BUG_SYSRET_SS_ATTRS on Xen PV guests

Commit 61f01dd941ba ("x86_64, asm: Work around AMD SYSRET SS descriptor
attribute issue") makes AMD processors set SS to __KERNEL_DS in
__switch_to() to deal with cases when SS is NULL.

This breaks Xen PV guests who do not want to load SS with__KERNEL_DS.

Since the problem that the commit is trying to address would have to be
fixed in the hypervisor (if it in fact exists under Xen) there is no
reason to set X86_BUG_SYSRET_SS_ATTRS flag for PV VPCUs here.

This can be easily achieved by adding x86_hyper_xen_hvm.set_cpu_features
op which will clear this flag. (And since this structure is no longer
HVM-specific we should do some renaming).

Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reported-by: Sander Eikelenboom <linux@eikelenboom.it>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>

authored by

Boris Ostrovsky and committed by
David Vrabel
a71dbdaa 16e6bd59

+22 -13
+1 -1
arch/x86/include/asm/hypervisor.h
··· 50 50 /* Recognized hypervisors */ 51 51 extern const struct hypervisor_x86 x86_hyper_vmware; 52 52 extern const struct hypervisor_x86 x86_hyper_ms_hyperv; 53 - extern const struct hypervisor_x86 x86_hyper_xen_hvm; 53 + extern const struct hypervisor_x86 x86_hyper_xen; 54 54 extern const struct hypervisor_x86 x86_hyper_kvm; 55 55 56 56 extern void init_hypervisor(struct cpuinfo_x86 *c);
+2 -2
arch/x86/kernel/cpu/hypervisor.c
··· 27 27 28 28 static const __initconst struct hypervisor_x86 * const hypervisors[] = 29 29 { 30 - #ifdef CONFIG_XEN_PVHVM 31 - &x86_hyper_xen_hvm, 30 + #ifdef CONFIG_XEN 31 + &x86_hyper_xen, 32 32 #endif 33 33 &x86_hyper_vmware, 34 34 &x86_hyper_ms_hyperv,
+19 -10
arch/x86/xen/enlighten.c
··· 1760 1760 1761 1761 static void __init xen_hvm_guest_init(void) 1762 1762 { 1763 + if (xen_pv_domain()) 1764 + return; 1765 + 1763 1766 init_hvm_pv_info(); 1764 1767 1765 1768 xen_hvm_init_shared_info(); ··· 1778 1775 xen_hvm_init_time_ops(); 1779 1776 xen_hvm_init_mmu_ops(); 1780 1777 } 1778 + #endif 1781 1779 1782 1780 static bool xen_nopv = false; 1783 1781 static __init int xen_parse_nopv(char *arg) ··· 1788 1784 } 1789 1785 early_param("xen_nopv", xen_parse_nopv); 1790 1786 1791 - static uint32_t __init xen_hvm_platform(void) 1787 + static uint32_t __init xen_platform(void) 1792 1788 { 1793 1789 if (xen_nopv) 1794 - return 0; 1795 - 1796 - if (xen_pv_domain()) 1797 1790 return 0; 1798 1791 1799 1792 return xen_cpuid_base(); ··· 1810 1809 } 1811 1810 EXPORT_SYMBOL_GPL(xen_hvm_need_lapic); 1812 1811 1813 - const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = { 1814 - .name = "Xen HVM", 1815 - .detect = xen_hvm_platform, 1812 + static void xen_set_cpu_features(struct cpuinfo_x86 *c) 1813 + { 1814 + if (xen_pv_domain()) 1815 + clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); 1816 + } 1817 + 1818 + const struct hypervisor_x86 x86_hyper_xen = { 1819 + .name = "Xen", 1820 + .detect = xen_platform, 1821 + #ifdef CONFIG_XEN_PVHVM 1816 1822 .init_platform = xen_hvm_guest_init, 1817 - .x2apic_available = xen_x2apic_para_available, 1818 - }; 1819 - EXPORT_SYMBOL(x86_hyper_xen_hvm); 1820 1823 #endif 1824 + .x2apic_available = xen_x2apic_para_available, 1825 + .set_cpu_features = xen_set_cpu_features, 1826 + }; 1827 + EXPORT_SYMBOL(x86_hyper_xen);