From: Paolo Bonzini <pbonzini@redhat.com>
To: Borislav Petkov <bp@alien8.de>
Cc: "Jörg Rödel" <joro@8bytes.org>,
"Andy Lutomirski" <luto@amacapital.net>, x86-ml <x86@kernel.org>,
"kvm ML" <kvm@vger.kernel.org>,
lkml <linux-kernel@vger.kernel.org>
Subject: Re: [RFC PATCH] kvm: Make KVM DF intercept configurable
Date: Tue, 1 Mar 2016 22:11:57 +0100 [thread overview]
Message-ID: <56D6059D.5050606@redhat.com> (raw)
In-Reply-To: <20160301192822.GD22677@pd.tnic>
On 01/03/2016 20:28, Borislav Petkov wrote:
> Hi Paolo,
>
> so I've been hacking at early code recently and found this to be pretty
> useful. Thoughts?
I just use QEMU's binary translation mode to debug this kind of code (-d
in_asm is useful and relatively compact (because it only shows loops
once), or alternatively ept=0. But perhaps... why not. :) It's not
like it adds overhead.
Paolo
> This is AMD-only now but I'll extend it to Intel too, if there's
> interest.
>
> ---
> From: Borislav Petkov <bp@suse.de>
> Date: Tue, 1 Mar 2016 14:34:28 +0100
> Subject: [RFC PATCH] kvm: Make KVM DF intercept configurable
>
> Sometimes it is useful when testing kernels in guests to know why the
> guest triple-faults, especially if one is poking at early kernel code
> where there's no debugging output yet.
>
> So add a module parameter which makes the guest exit on a #DF and log
> error info into a #DF tracepoint. Which turns out to be very useful:
>
> 1. Early PF causing a DF:
> -------------------------
>
> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
> index 22fbf9df61bb..57d7d7a68c7d 100644
> --- a/arch/x86/kernel/head_64.S
> +++ b/arch/x86/kernel/head_64.S
> @@ -64,6 +64,8 @@ startup_64:
> * tables and then reload them.
> */
>
> + movq stack_start, %rsp
> ---
>
> We can't read that early from stack_start because we haven't enabled
> paging yet. KVM logs:
>
> qemu-system-x86-9523 [001] .... 1941.666236: kvm_df: Guest DF! rIP: 0x1000000, prev exception: 0xe, error_code: 0x0
>
> and the exception causing the #DF is a #PF (vector 0xe).
>
> 2. #GP
> -------------------------
>
> diff --git a/init/main.c b/init/main.c
> index 7c27de4577ed..869eb6110765 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -967,6 +969,9 @@ static int __ref kernel_init(void *unused)
> ramdisk_execute_command, ret);
> }
>
> + load_idt(&no_idt);
> + __asm__ __volatile__("int3");
> ---
>
> Loading a NULL IDT and causing a debug interrupt, causes a #GP.
>
> KVM logs:
>
> qemu-system-x86-12853 [000] .... 2463.500732: kvm_df: Guest DF! rIP: 0xffffffff815ba8ba, prev exception: 0xd, error_code: 0x1a
>
> and the previous exception was a #GP (vector 0xd).
>
> Signed-off-by: Borislav Petkov <bp@suse.de>
> ---
> arch/x86/kvm/svm.c | 15 +++++++++++++++
> arch/x86/kvm/trace.h | 20 ++++++++++++++++++++
> arch/x86/kvm/x86.c | 1 +
> 3 files changed, 36 insertions(+)
>
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index c13a64b7d789..09f78bbd8b47 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -205,6 +205,9 @@ module_param(npt, int, S_IRUGO);
> static int nested = true;
> module_param(nested, int, S_IRUGO);
>
> +static int intercept_df = 0;
> +module_param(intercept_df, int, S_IRUGO);
> +
> static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
> static void svm_flush_tlb(struct kvm_vcpu *vcpu);
> static void svm_complete_interrupts(struct vcpu_svm *svm);
> @@ -1023,6 +1026,8 @@ static void init_vmcb(struct vcpu_svm *svm)
> set_exception_intercept(svm, MC_VECTOR);
> set_exception_intercept(svm, AC_VECTOR);
> set_exception_intercept(svm, DB_VECTOR);
> + if (intercept_df)
> + set_exception_intercept(svm, DF_VECTOR);
>
> set_intercept(svm, INTERCEPT_INTR);
> set_intercept(svm, INTERCEPT_NMI);
> @@ -1728,6 +1733,15 @@ static int nm_interception(struct vcpu_svm *svm)
> return 1;
> }
>
> +static int df_interception(struct vcpu_svm *svm)
> +{
> + trace_kvm_df(svm->vmcb->save.rip,
> + svm->vcpu.arch.exception.nr,
> + svm->vcpu.arch.exception.has_error_code ?
> + svm->vcpu.arch.exception.error_code : 0);
> + return 1;
> +}
> +
> static bool is_erratum_383(void)
> {
> int err, i;
> @@ -3308,6 +3322,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
> [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception,
> [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
> [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
> + [SVM_EXIT_EXCP_BASE + DF_VECTOR] = df_interception,
> [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
> [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
> [SVM_EXIT_INTR] = intr_interception,
> diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
> index ad9f6a23f139..6143c53f7bde 100644
> --- a/arch/x86/kvm/trace.h
> +++ b/arch/x86/kvm/trace.h
> @@ -89,6 +89,26 @@ TRACE_EVENT(kvm_hv_hypercall,
> __entry->outgpa)
> );
>
> +TRACE_EVENT(kvm_df,
> + TP_PROTO(unsigned long rip, u8 nr, u32 error_code),
> + TP_ARGS(rip, nr, error_code),
> +
> + TP_STRUCT__entry(
> + __field( unsigned long, rip )
> + __field( u8, nr )
> + __field( u32, error_code )
> + ),
> +
> + TP_fast_assign(
> + __entry->rip = rip;
> + __entry->nr = nr;
> + __entry->error_code = error_code;
> + ),
> +
> + TP_printk("Guest DF! rIP: 0x%lx, prev exception: 0x%x, error_code: 0x%x",
> + __entry->rip, __entry->nr, __entry->error_code)
> +);
> +
> /*
> * Tracepoint for PIO.
> */
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index f18a08281015..49f1bd3279f2 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -8388,3 +8388,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_write_tsc_offset);
> EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ple_window);
> EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pml_full);
> EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_df);
>
next prev parent reply other threads:[~2016-03-01 21:12 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-01 19:28 [RFC PATCH] kvm: Make KVM DF intercept configurable Borislav Petkov
2016-03-01 21:11 ` Paolo Bonzini [this message]
2016-03-01 22:41 ` Borislav Petkov
2016-03-02 6:45 ` Jan Kiszka
2016-03-02 9:07 ` Borislav Petkov
2016-03-02 9:17 ` Paolo Bonzini
2016-03-02 9:22 ` Borislav Petkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56D6059D.5050606@redhat.com \
--to=pbonzini@redhat.com \
--cc=bp@alien8.de \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.