Message ID | 1417037064-3973-2-git-send-email-chris.j.arges@canonical.com |
---|---|
State | New |
Headers | show |
On 26.11.2014 22:24, Chris J Arges wrote: > From: Paolo Bonzini <pbonzini@redhat.com> > > BugLink: http://bugs.launchpad.net/bugs/1379340 > > On x86_64, kernel text mappings are mapped read-only with CONFIG_DEBUG_RODATA. > In that case, KVM will fail to patch VMCALL instructions to VMMCALL > as required on AMD processors. > > The failure mode is currently a divide-by-zero exception, which obviously > is a KVM bug that has to be fixed. However, picking the right instruction > between VMCALL and VMMCALL will be faster and will help if you cannot upgrade > the hypervisor. > > Reported-by: Chris Webb <chris@arachsys.com> > Tested-by: Chris Webb <chris@arachsys.com> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Ingo Molnar <mingo@redhat.com> > Cc: "H. Peter Anvin" <hpa@zytor.com> > Cc: x86@kernel.org > Acked-by: Borislav Petkov <bp@suse.de> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > (cherry picked from commit c1118b3602c2329671ad5ec8bdf8e374323d6343) Nitpick: in the emails sent to stable you say only v3.17 does cherry-pick and provide backports for older kernels. So would this and the Trusty one not be "backported"? Also in the bug report I saw you could reproduce this but the final comment sounds not like you did actively verify the solution. You surely did that, didn't you? -Stefan > Signed-off-by: Chris J Arges <chris.j.arges@canonical.com> > > Conflicts: > arch/x86/include/asm/cpufeature.h > --- > arch/x86/include/asm/cpufeature.h | 1 + > arch/x86/include/asm/kvm_para.h | 10 ++++++++-- > arch/x86/kernel/cpu/amd.c | 7 +++++++ > 3 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h > index e265ff9..51f7550 100644 > --- a/arch/x86/include/asm/cpufeature.h > +++ b/arch/x86/include/asm/cpufeature.h > @@ -203,6 +203,7 @@ > #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ > #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ > #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ > +#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ > > > /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ > diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h > index c7678e4..e62cf89 100644 > --- a/arch/x86/include/asm/kvm_para.h > +++ b/arch/x86/include/asm/kvm_para.h > @@ -2,6 +2,7 @@ > #define _ASM_X86_KVM_PARA_H > > #include <asm/processor.h> > +#include <asm/alternative.h> > #include <uapi/asm/kvm_para.h> > > extern void kvmclock_init(void); > @@ -16,10 +17,15 @@ static inline bool kvm_check_and_clear_guest_paused(void) > } > #endif /* CONFIG_KVM_GUEST */ > > -/* This instruction is vmcall. On non-VT architectures, it will generate a > - * trap that we will then rewrite to the appropriate instruction. > +#ifdef CONFIG_DEBUG_RODATA > +#define KVM_HYPERCALL \ > + ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) > +#else > +/* On AMD processors, vmcall will generate a trap that we will > + * then rewrite to the appropriate instruction. > */ > #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" > +#endif > > /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall > * instruction. The hypervisor may replace it with something else but only the > diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c > index ce8b8ff..edefaca 100644 > --- a/arch/x86/kernel/cpu/amd.c > +++ b/arch/x86/kernel/cpu/amd.c > @@ -506,6 +506,13 @@ static void early_init_amd(struct cpuinfo_x86 *c) > } > #endif > > + /* > + * This is only needed to tell the kernel whether to use VMCALL > + * and VMMCALL. VMMCALL is never executed except under virt, so > + * we can set it unconditionally. > + */ > + set_cpu_cap(c, X86_FEATURE_VMMCALL); > + > /* F16h erratum 793, CVE-2013-6885 */ > if (c->x86 == 0x16 && c->x86_model <= 0xf) > msr_set_bit(MSR_AMD64_LS_CFG, 15); >
On Wed, Nov 26, 2014 at 03:24:24PM -0600, Chris J Arges wrote: > From: Paolo Bonzini <pbonzini@redhat.com> > > BugLink: http://bugs.launchpad.net/bugs/1379340 > > On x86_64, kernel text mappings are mapped read-only with CONFIG_DEBUG_RODATA. > In that case, KVM will fail to patch VMCALL instructions to VMMCALL > as required on AMD processors. > > The failure mode is currently a divide-by-zero exception, which obviously > is a KVM bug that has to be fixed. However, picking the right instruction > between VMCALL and VMMCALL will be faster and will help if you cannot upgrade > the hypervisor. > > Reported-by: Chris Webb <chris@arachsys.com> > Tested-by: Chris Webb <chris@arachsys.com> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Ingo Molnar <mingo@redhat.com> > Cc: "H. Peter Anvin" <hpa@zytor.com> > Cc: x86@kernel.org > Acked-by: Borislav Petkov <bp@suse.de> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > (cherry picked from commit c1118b3602c2329671ad5ec8bdf8e374323d6343) This is definatly "backported from" as there is a minor spacing change in the context. That said it is a very minor context change so the working payload is unchanged. Applier should fix that to backported though. > Signed-off-by: Chris J Arges <chris.j.arges@canonical.com> > > Conflicts: > arch/x86/include/asm/cpufeature.h > --- > arch/x86/include/asm/cpufeature.h | 1 + > arch/x86/include/asm/kvm_para.h | 10 ++++++++-- > arch/x86/kernel/cpu/amd.c | 7 +++++++ > 3 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h > index e265ff9..51f7550 100644 > --- a/arch/x86/include/asm/cpufeature.h > +++ b/arch/x86/include/asm/cpufeature.h > @@ -203,6 +203,7 @@ > #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ > #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ > #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ > +#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ > > > /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ > diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h > index c7678e4..e62cf89 100644 > --- a/arch/x86/include/asm/kvm_para.h > +++ b/arch/x86/include/asm/kvm_para.h > @@ -2,6 +2,7 @@ > #define _ASM_X86_KVM_PARA_H > > #include <asm/processor.h> > +#include <asm/alternative.h> > #include <uapi/asm/kvm_para.h> > > extern void kvmclock_init(void); > @@ -16,10 +17,15 @@ static inline bool kvm_check_and_clear_guest_paused(void) > } > #endif /* CONFIG_KVM_GUEST */ > > -/* This instruction is vmcall. On non-VT architectures, it will generate a > - * trap that we will then rewrite to the appropriate instruction. > +#ifdef CONFIG_DEBUG_RODATA > +#define KVM_HYPERCALL \ > + ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) > +#else > +/* On AMD processors, vmcall will generate a trap that we will > + * then rewrite to the appropriate instruction. > */ > #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" > +#endif > > /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall > * instruction. The hypervisor may replace it with something else but only the > diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c > index ce8b8ff..edefaca 100644 > --- a/arch/x86/kernel/cpu/amd.c > +++ b/arch/x86/kernel/cpu/amd.c > @@ -506,6 +506,13 @@ static void early_init_amd(struct cpuinfo_x86 *c) > } > #endif > > + /* > + * This is only needed to tell the kernel whether to use VMCALL > + * and VMMCALL. VMMCALL is never executed except under virt, so > + * we can set it unconditionally. > + */ > + set_cpu_cap(c, X86_FEATURE_VMMCALL); > + > /* F16h erratum 793, CVE-2013-6885 */ > if (c->x86 == 0x16 && c->x86_model <= 0xf) > msr_set_bit(MSR_AMD64_LS_CFG, 15); > -- Looks to do waht is claimed, can really only affect KVM and should be trivially testable if soneone has AMD and Intel h/w to test. Therefore: Acked-by: Andy Whitcroft <apw@canonical.com> -apw
Applied to Utopic. I changed this to be marked as a backport on application. -apw
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index e265ff9..51f7550 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -203,6 +203,7 @@ #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ +#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index c7678e4..e62cf89 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h @@ -2,6 +2,7 @@ #define _ASM_X86_KVM_PARA_H #include <asm/processor.h> +#include <asm/alternative.h> #include <uapi/asm/kvm_para.h> extern void kvmclock_init(void); @@ -16,10 +17,15 @@ static inline bool kvm_check_and_clear_guest_paused(void) } #endif /* CONFIG_KVM_GUEST */ -/* This instruction is vmcall. On non-VT architectures, it will generate a - * trap that we will then rewrite to the appropriate instruction. +#ifdef CONFIG_DEBUG_RODATA +#define KVM_HYPERCALL \ + ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) +#else +/* On AMD processors, vmcall will generate a trap that we will + * then rewrite to the appropriate instruction. */ #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" +#endif /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall * instruction. The hypervisor may replace it with something else but only the diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index ce8b8ff..edefaca 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -506,6 +506,13 @@ static void early_init_amd(struct cpuinfo_x86 *c) } #endif + /* + * This is only needed to tell the kernel whether to use VMCALL + * and VMMCALL. VMMCALL is never executed except under virt, so + * we can set it unconditionally. + */ + set_cpu_cap(c, X86_FEATURE_VMMCALL); + /* F16h erratum 793, CVE-2013-6885 */ if (c->x86 == 0x16 && c->x86_model <= 0xf) msr_set_bit(MSR_AMD64_LS_CFG, 15);