All of lore.kernel.org
 help / color / mirror / Atom feed
From: Borislav Petkov <bp@alien8.de>
To: Paolo Bonzini <pbonzini@redhat.com>
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: [RFC PATCH] kvm: Make KVM DF intercept configurable
Date: Tue, 1 Mar 2016 20:28:22 +0100	[thread overview]
Message-ID: <20160301192822.GD22677@pd.tnic> (raw)

Hi Paolo,

so I've been hacking at early code recently and found this to be pretty
useful. Thoughts?

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);
-- 
2.3.5


-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

             reply	other threads:[~2016-03-01 19:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-01 19:28 Borislav Petkov [this message]
2016-03-01 21:11 ` [RFC PATCH] kvm: Make KVM DF intercept configurable Paolo Bonzini
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=20160301192822.GD22677@pd.tnic \
    --to=bp@alien8.de \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=pbonzini@redhat.com \
    --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.