diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2010-11-30 12:03:58 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-01-12 04:30:11 -0500 |
commit | 3aed041a4c1b78cac87db76cf264b081df64dd37 (patch) | |
tree | dfaa91c967b0ccf261bae663069fc5dabc5bdccb | |
parent | 4ee546b434504a618eac40421e595c68e494da9f (diff) |
KVM: SVM: Add manipulation functions for DRx intercepts
This patch wraps changes to the DRx intercepts of SVM into
seperate functions to abstract nested-svm better and prepare
the implementation of the vmcb-clean-bits feature.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/include/asm/svm.h | 27 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 80 |
2 files changed, 61 insertions, 46 deletions
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 39f9ddf07136..11dbca7a582a 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h | |||
@@ -52,8 +52,7 @@ enum { | |||
52 | 52 | ||
53 | struct __attribute__ ((__packed__)) vmcb_control_area { | 53 | struct __attribute__ ((__packed__)) vmcb_control_area { |
54 | u32 intercept_cr; | 54 | u32 intercept_cr; |
55 | u16 intercept_dr_read; | 55 | u32 intercept_dr; |
56 | u16 intercept_dr_write; | ||
57 | u32 intercept_exceptions; | 56 | u32 intercept_exceptions; |
58 | u64 intercept; | 57 | u64 intercept; |
59 | u8 reserved_1[42]; | 58 | u8 reserved_1[42]; |
@@ -212,14 +211,22 @@ struct __attribute__ ((__packed__)) vmcb { | |||
212 | #define INTERCEPT_CR4_WRITE (16 + 4) | 211 | #define INTERCEPT_CR4_WRITE (16 + 4) |
213 | #define INTERCEPT_CR8_WRITE (16 + 8) | 212 | #define INTERCEPT_CR8_WRITE (16 + 8) |
214 | 213 | ||
215 | #define INTERCEPT_DR0_MASK 1 | 214 | #define INTERCEPT_DR0_READ 0 |
216 | #define INTERCEPT_DR1_MASK (1 << 1) | 215 | #define INTERCEPT_DR1_READ 1 |
217 | #define INTERCEPT_DR2_MASK (1 << 2) | 216 | #define INTERCEPT_DR2_READ 2 |
218 | #define INTERCEPT_DR3_MASK (1 << 3) | 217 | #define INTERCEPT_DR3_READ 3 |
219 | #define INTERCEPT_DR4_MASK (1 << 4) | 218 | #define INTERCEPT_DR4_READ 4 |
220 | #define INTERCEPT_DR5_MASK (1 << 5) | 219 | #define INTERCEPT_DR5_READ 5 |
221 | #define INTERCEPT_DR6_MASK (1 << 6) | 220 | #define INTERCEPT_DR6_READ 6 |
222 | #define INTERCEPT_DR7_MASK (1 << 7) | 221 | #define INTERCEPT_DR7_READ 7 |
222 | #define INTERCEPT_DR0_WRITE (16 + 0) | ||
223 | #define INTERCEPT_DR1_WRITE (16 + 1) | ||
224 | #define INTERCEPT_DR2_WRITE (16 + 2) | ||
225 | #define INTERCEPT_DR3_WRITE (16 + 3) | ||
226 | #define INTERCEPT_DR4_WRITE (16 + 4) | ||
227 | #define INTERCEPT_DR5_WRITE (16 + 5) | ||
228 | #define INTERCEPT_DR6_WRITE (16 + 6) | ||
229 | #define INTERCEPT_DR7_WRITE (16 + 7) | ||
223 | 230 | ||
224 | #define SVM_EVTINJ_VEC_MASK 0xff | 231 | #define SVM_EVTINJ_VEC_MASK 0xff |
225 | 232 | ||
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1e7bb9c77084..a7c38eb9d2e3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -99,8 +99,7 @@ struct nested_state { | |||
99 | 99 | ||
100 | /* cache for intercepts of the guest */ | 100 | /* cache for intercepts of the guest */ |
101 | u32 intercept_cr; | 101 | u32 intercept_cr; |
102 | u16 intercept_dr_read; | 102 | u32 intercept_dr; |
103 | u16 intercept_dr_write; | ||
104 | u32 intercept_exceptions; | 103 | u32 intercept_exceptions; |
105 | u64 intercept; | 104 | u64 intercept; |
106 | 105 | ||
@@ -204,8 +203,7 @@ static void recalc_intercepts(struct vcpu_svm *svm) | |||
204 | g = &svm->nested; | 203 | g = &svm->nested; |
205 | 204 | ||
206 | c->intercept_cr = h->intercept_cr | g->intercept_cr; | 205 | c->intercept_cr = h->intercept_cr | g->intercept_cr; |
207 | c->intercept_dr_read = h->intercept_dr_read | g->intercept_dr_read; | 206 | c->intercept_dr = h->intercept_dr | g->intercept_dr; |
208 | c->intercept_dr_write = h->intercept_dr_write | g->intercept_dr_write; | ||
209 | c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions; | 207 | c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions; |
210 | c->intercept = h->intercept | g->intercept; | 208 | c->intercept = h->intercept | g->intercept; |
211 | } | 209 | } |
@@ -243,6 +241,24 @@ static inline bool is_cr_intercept(struct vcpu_svm *svm, int bit) | |||
243 | return vmcb->control.intercept_cr & (1U << bit); | 241 | return vmcb->control.intercept_cr & (1U << bit); |
244 | } | 242 | } |
245 | 243 | ||
244 | static inline void set_dr_intercept(struct vcpu_svm *svm, int bit) | ||
245 | { | ||
246 | struct vmcb *vmcb = get_host_vmcb(svm); | ||
247 | |||
248 | vmcb->control.intercept_dr |= (1U << bit); | ||
249 | |||
250 | recalc_intercepts(svm); | ||
251 | } | ||
252 | |||
253 | static inline void clr_dr_intercept(struct vcpu_svm *svm, int bit) | ||
254 | { | ||
255 | struct vmcb *vmcb = get_host_vmcb(svm); | ||
256 | |||
257 | vmcb->control.intercept_dr &= ~(1U << bit); | ||
258 | |||
259 | recalc_intercepts(svm); | ||
260 | } | ||
261 | |||
246 | static inline void enable_gif(struct vcpu_svm *svm) | 262 | static inline void enable_gif(struct vcpu_svm *svm) |
247 | { | 263 | { |
248 | svm->vcpu.arch.hflags |= HF_GIF_MASK; | 264 | svm->vcpu.arch.hflags |= HF_GIF_MASK; |
@@ -807,23 +823,23 @@ static void init_vmcb(struct vcpu_svm *svm) | |||
807 | set_cr_intercept(svm, INTERCEPT_CR4_WRITE); | 823 | set_cr_intercept(svm, INTERCEPT_CR4_WRITE); |
808 | set_cr_intercept(svm, INTERCEPT_CR8_WRITE); | 824 | set_cr_intercept(svm, INTERCEPT_CR8_WRITE); |
809 | 825 | ||
810 | control->intercept_dr_read = INTERCEPT_DR0_MASK | | 826 | set_dr_intercept(svm, INTERCEPT_DR0_READ); |
811 | INTERCEPT_DR1_MASK | | 827 | set_dr_intercept(svm, INTERCEPT_DR1_READ); |
812 | INTERCEPT_DR2_MASK | | 828 | set_dr_intercept(svm, INTERCEPT_DR2_READ); |
813 | INTERCEPT_DR3_MASK | | 829 | set_dr_intercept(svm, INTERCEPT_DR3_READ); |
814 | INTERCEPT_DR4_MASK | | 830 | set_dr_intercept(svm, INTERCEPT_DR4_READ); |
815 | INTERCEPT_DR5_MASK | | 831 | set_dr_intercept(svm, INTERCEPT_DR5_READ); |
816 | INTERCEPT_DR6_MASK | | 832 | set_dr_intercept(svm, INTERCEPT_DR6_READ); |
817 | INTERCEPT_DR7_MASK; | 833 | set_dr_intercept(svm, INTERCEPT_DR7_READ); |
818 | 834 | ||
819 | control->intercept_dr_write = INTERCEPT_DR0_MASK | | 835 | set_dr_intercept(svm, INTERCEPT_DR0_WRITE); |
820 | INTERCEPT_DR1_MASK | | 836 | set_dr_intercept(svm, INTERCEPT_DR1_WRITE); |
821 | INTERCEPT_DR2_MASK | | 837 | set_dr_intercept(svm, INTERCEPT_DR2_WRITE); |
822 | INTERCEPT_DR3_MASK | | 838 | set_dr_intercept(svm, INTERCEPT_DR3_WRITE); |
823 | INTERCEPT_DR4_MASK | | 839 | set_dr_intercept(svm, INTERCEPT_DR4_WRITE); |
824 | INTERCEPT_DR5_MASK | | 840 | set_dr_intercept(svm, INTERCEPT_DR5_WRITE); |
825 | INTERCEPT_DR6_MASK | | 841 | set_dr_intercept(svm, INTERCEPT_DR6_WRITE); |
826 | INTERCEPT_DR7_MASK; | 842 | set_dr_intercept(svm, INTERCEPT_DR7_WRITE); |
827 | 843 | ||
828 | control->intercept_exceptions = (1 << PF_VECTOR) | | 844 | control->intercept_exceptions = (1 << PF_VECTOR) | |
829 | (1 << UD_VECTOR) | | 845 | (1 << UD_VECTOR) | |
@@ -1923,15 +1939,9 @@ static int nested_svm_intercept(struct vcpu_svm *svm) | |||
1923 | vmexit = NESTED_EXIT_DONE; | 1939 | vmexit = NESTED_EXIT_DONE; |
1924 | break; | 1940 | break; |
1925 | } | 1941 | } |
1926 | case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: { | 1942 | case SVM_EXIT_READ_DR0 ... SVM_EXIT_WRITE_DR7: { |
1927 | u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0); | 1943 | u32 bit = 1U << (exit_code - SVM_EXIT_READ_DR0); |
1928 | if (svm->nested.intercept_dr_read & dr_bits) | 1944 | if (svm->nested.intercept_dr & bit) |
1929 | vmexit = NESTED_EXIT_DONE; | ||
1930 | break; | ||
1931 | } | ||
1932 | case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: { | ||
1933 | u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0); | ||
1934 | if (svm->nested.intercept_dr_write & dr_bits) | ||
1935 | vmexit = NESTED_EXIT_DONE; | 1945 | vmexit = NESTED_EXIT_DONE; |
1936 | break; | 1946 | break; |
1937 | } | 1947 | } |
@@ -1977,8 +1987,7 @@ static inline void copy_vmcb_control_area(struct vmcb *dst_vmcb, struct vmcb *fr | |||
1977 | struct vmcb_control_area *from = &from_vmcb->control; | 1987 | struct vmcb_control_area *from = &from_vmcb->control; |
1978 | 1988 | ||
1979 | dst->intercept_cr = from->intercept_cr; | 1989 | dst->intercept_cr = from->intercept_cr; |
1980 | dst->intercept_dr_read = from->intercept_dr_read; | 1990 | dst->intercept_dr = from->intercept_dr; |
1981 | dst->intercept_dr_write = from->intercept_dr_write; | ||
1982 | dst->intercept_exceptions = from->intercept_exceptions; | 1991 | dst->intercept_exceptions = from->intercept_exceptions; |
1983 | dst->intercept = from->intercept; | 1992 | dst->intercept = from->intercept; |
1984 | dst->iopm_base_pa = from->iopm_base_pa; | 1993 | dst->iopm_base_pa = from->iopm_base_pa; |
@@ -2280,8 +2289,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) | |||
2280 | 2289 | ||
2281 | /* cache intercepts */ | 2290 | /* cache intercepts */ |
2282 | svm->nested.intercept_cr = nested_vmcb->control.intercept_cr; | 2291 | svm->nested.intercept_cr = nested_vmcb->control.intercept_cr; |
2283 | svm->nested.intercept_dr_read = nested_vmcb->control.intercept_dr_read; | 2292 | svm->nested.intercept_dr = nested_vmcb->control.intercept_dr; |
2284 | svm->nested.intercept_dr_write = nested_vmcb->control.intercept_dr_write; | ||
2285 | svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions; | 2293 | svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions; |
2286 | svm->nested.intercept = nested_vmcb->control.intercept; | 2294 | svm->nested.intercept = nested_vmcb->control.intercept; |
2287 | 2295 | ||
@@ -2906,8 +2914,8 @@ void dump_vmcb(struct kvm_vcpu *vcpu) | |||
2906 | pr_err("VMCB Control Area:\n"); | 2914 | pr_err("VMCB Control Area:\n"); |
2907 | pr_err("cr_read: %04x\n", control->intercept_cr & 0xffff); | 2915 | pr_err("cr_read: %04x\n", control->intercept_cr & 0xffff); |
2908 | pr_err("cr_write: %04x\n", control->intercept_cr >> 16); | 2916 | pr_err("cr_write: %04x\n", control->intercept_cr >> 16); |
2909 | pr_err("dr_read: %04x\n", control->intercept_dr_read); | 2917 | pr_err("dr_read: %04x\n", control->intercept_dr & 0xffff); |
2910 | pr_err("dr_write: %04x\n", control->intercept_dr_write); | 2918 | pr_err("dr_write: %04x\n", control->intercept_dr >> 16); |
2911 | pr_err("exceptions: %08x\n", control->intercept_exceptions); | 2919 | pr_err("exceptions: %08x\n", control->intercept_exceptions); |
2912 | pr_err("intercepts: %016llx\n", control->intercept); | 2920 | pr_err("intercepts: %016llx\n", control->intercept); |
2913 | pr_err("pause filter count: %d\n", control->pause_filter_count); | 2921 | pr_err("pause filter count: %d\n", control->pause_filter_count); |