KVM: SVM: Introduce vmcb_(set_intercept/clr_intercept/_is_intercept)
authorBabu Moger <babu.moger@amd.com>
Fri, 11 Sep 2020 19:27:58 +0000 (14:27 -0500)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 28 Sep 2020 11:57:13 +0000 (07:57 -0400)
This is in preparation for the future intercept vector additions.

Add new functions vmcb_set_intercept, vmcb_clr_intercept and vmcb_is_intercept
using kernel APIs __set_bit, __clear_bit and test_bit espectively.

Signed-off-by: Babu Moger <babu.moger@amd.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Message-Id: <159985247876.11252.16039238014239824460.stgit@bmoger-ubuntu>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/svm.h
arch/x86/kvm/svm/nested.c
arch/x86/kvm/svm/svm.h

index cf13f9e..debe71f 100644 (file)
@@ -4,6 +4,14 @@
 
 #include <uapi/asm/svm.h>
 
+/*
+ * 32-bit intercept words in the VMCB Control Area, starting
+ * at Byte offset 000h.
+ */
+
+enum intercept_words {
+       MAX_INTERCEPT,
+};
 
 enum {
        INTERCEPT_INTR,
@@ -57,6 +65,7 @@ enum {
 
 
 struct __attribute__ ((__packed__)) vmcb_control_area {
+       u32 intercepts[MAX_INTERCEPT];
        u32 intercept_cr;
        u32 intercept_dr;
        u32 intercept_exceptions;
index c10a9a8..69dfd7c 100644 (file)
@@ -98,6 +98,7 @@ static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu)
 void recalc_intercepts(struct vcpu_svm *svm)
 {
        struct vmcb_control_area *c, *h, *g;
+       unsigned int i;
 
        vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 
@@ -108,6 +109,9 @@ void recalc_intercepts(struct vcpu_svm *svm)
        h = &svm->nested.hsave->control;
        g = &svm->nested.ctl;
 
+       for (i = 0; i < MAX_INTERCEPT; i++)
+               c->intercepts[i] = h->intercepts[i];
+
        c->intercept_cr = h->intercept_cr;
        c->intercept_dr = h->intercept_dr;
        c->intercept_exceptions = h->intercept_exceptions;
@@ -129,6 +133,9 @@ void recalc_intercepts(struct vcpu_svm *svm)
        /* We don't want to see VMMCALLs from a nested guest */
        c->intercept &= ~(1ULL << INTERCEPT_VMMCALL);
 
+       for (i = 0; i < MAX_INTERCEPT; i++)
+               c->intercepts[i] |= g->intercepts[i];
+
        c->intercept_cr |= g->intercept_cr;
        c->intercept_dr |= g->intercept_dr;
        c->intercept_exceptions |= g->intercept_exceptions;
@@ -138,6 +145,11 @@ void recalc_intercepts(struct vcpu_svm *svm)
 static void copy_vmcb_control_area(struct vmcb_control_area *dst,
                                   struct vmcb_control_area *from)
 {
+       unsigned int i;
+
+       for (i = 0; i < MAX_INTERCEPT; i++)
+               dst->intercepts[i] = from->intercepts[i];
+
        dst->intercept_cr         = from->intercept_cr;
        dst->intercept_dr         = from->intercept_dr;
        dst->intercept_exceptions = from->intercept_exceptions;
index e3aca71..83202c4 100644 (file)
@@ -213,6 +213,24 @@ static inline struct vmcb *get_host_vmcb(struct vcpu_svm *svm)
                return svm->vmcb;
 }
 
+static inline void vmcb_set_intercept(struct vmcb_control_area *control, u32 bit)
+{
+       WARN_ON_ONCE(bit >= 32 * MAX_INTERCEPT);
+       __set_bit(bit, (unsigned long *)&control->intercepts);
+}
+
+static inline void vmcb_clr_intercept(struct vmcb_control_area *control, u32 bit)
+{
+       WARN_ON_ONCE(bit >= 32 * MAX_INTERCEPT);
+       __clear_bit(bit, (unsigned long *)&control->intercepts);
+}
+
+static inline bool vmcb_is_intercept(struct vmcb_control_area *control, u32 bit)
+{
+       WARN_ON_ONCE(bit >= 32 * MAX_INTERCEPT);
+       return test_bit(bit, (unsigned long *)&control->intercepts);
+}
+
 static inline void set_cr_intercept(struct vcpu_svm *svm, int bit)
 {
        struct vmcb *vmcb = get_host_vmcb(svm);