@@ -2660,12 +2660,80 @@ static int emulate_on_interception(struct vcpu_svm *svm)
2660
2660
return emulate_instruction (& svm -> vcpu , 0 ) == EMULATE_DONE ;
2661
2661
}
2662
2662
2663
+ #define CR_VALID (1ULL << 63)
2664
+
2665
+ static int cr_interception (struct vcpu_svm * svm )
2666
+ {
2667
+ int reg , cr ;
2668
+ unsigned long val ;
2669
+ int err ;
2670
+
2671
+ if (!static_cpu_has (X86_FEATURE_DECODEASSISTS ))
2672
+ return emulate_on_interception (svm );
2673
+
2674
+ if (unlikely ((svm -> vmcb -> control .exit_info_1 & CR_VALID ) == 0 ))
2675
+ return emulate_on_interception (svm );
2676
+
2677
+ reg = svm -> vmcb -> control .exit_info_1 & SVM_EXITINFO_REG_MASK ;
2678
+ cr = svm -> vmcb -> control .exit_code - SVM_EXIT_READ_CR0 ;
2679
+
2680
+ err = 0 ;
2681
+ if (cr >= 16 ) { /* mov to cr */
2682
+ cr -= 16 ;
2683
+ val = kvm_register_read (& svm -> vcpu , reg );
2684
+ switch (cr ) {
2685
+ case 0 :
2686
+ err = kvm_set_cr0 (& svm -> vcpu , val );
2687
+ break ;
2688
+ case 3 :
2689
+ err = kvm_set_cr3 (& svm -> vcpu , val );
2690
+ break ;
2691
+ case 4 :
2692
+ err = kvm_set_cr4 (& svm -> vcpu , val );
2693
+ break ;
2694
+ case 8 :
2695
+ err = kvm_set_cr8 (& svm -> vcpu , val );
2696
+ break ;
2697
+ default :
2698
+ WARN (1 , "unhandled write to CR%d" , cr );
2699
+ kvm_queue_exception (& svm -> vcpu , UD_VECTOR );
2700
+ return 1 ;
2701
+ }
2702
+ } else { /* mov from cr */
2703
+ switch (cr ) {
2704
+ case 0 :
2705
+ val = kvm_read_cr0 (& svm -> vcpu );
2706
+ break ;
2707
+ case 2 :
2708
+ val = svm -> vcpu .arch .cr2 ;
2709
+ break ;
2710
+ case 3 :
2711
+ val = svm -> vcpu .arch .cr3 ;
2712
+ break ;
2713
+ case 4 :
2714
+ val = kvm_read_cr4 (& svm -> vcpu );
2715
+ break ;
2716
+ case 8 :
2717
+ val = kvm_get_cr8 (& svm -> vcpu );
2718
+ break ;
2719
+ default :
2720
+ WARN (1 , "unhandled read from CR%d" , cr );
2721
+ kvm_queue_exception (& svm -> vcpu , UD_VECTOR );
2722
+ return 1 ;
2723
+ }
2724
+ kvm_register_write (& svm -> vcpu , reg , val );
2725
+ }
2726
+ kvm_complete_insn_gp (& svm -> vcpu , err );
2727
+
2728
+ return 1 ;
2729
+ }
2730
+
2663
2731
static int cr0_write_interception (struct vcpu_svm * svm )
2664
2732
{
2665
2733
struct kvm_vcpu * vcpu = & svm -> vcpu ;
2666
2734
int r ;
2667
2735
2668
- r = emulate_instruction ( & svm -> vcpu , 0 );
2736
+ r = cr_interception ( svm );
2669
2737
2670
2738
if (svm -> nested .vmexit_rip ) {
2671
2739
kvm_register_write (vcpu , VCPU_REGS_RIP , svm -> nested .vmexit_rip );
@@ -2674,7 +2742,7 @@ static int cr0_write_interception(struct vcpu_svm *svm)
2674
2742
svm -> nested .vmexit_rip = 0 ;
2675
2743
}
2676
2744
2677
- return r == EMULATE_DONE ;
2745
+ return r ;
2678
2746
}
2679
2747
2680
2748
static int cr8_write_interception (struct vcpu_svm * svm )
@@ -2684,13 +2752,13 @@ static int cr8_write_interception(struct vcpu_svm *svm)
2684
2752
2685
2753
u8 cr8_prev = kvm_get_cr8 (& svm -> vcpu );
2686
2754
/* instruction emulation calls kvm_set_cr8() */
2687
- r = emulate_instruction ( & svm -> vcpu , 0 );
2755
+ r = cr_interception ( svm );
2688
2756
if (irqchip_in_kernel (svm -> vcpu .kvm )) {
2689
2757
clr_cr_intercept (svm , INTERCEPT_CR8_WRITE );
2690
- return r == EMULATE_DONE ;
2758
+ return r ;
2691
2759
}
2692
2760
if (cr8_prev <= kvm_get_cr8 (& svm -> vcpu ))
2693
- return r == EMULATE_DONE ;
2761
+ return r ;
2694
2762
kvm_run -> exit_reason = KVM_EXIT_SET_TPR ;
2695
2763
return 0 ;
2696
2764
}
@@ -2933,14 +3001,14 @@ static int pause_interception(struct vcpu_svm *svm)
2933
3001
}
2934
3002
2935
3003
static int (* svm_exit_handlers [])(struct vcpu_svm * svm ) = {
2936
- [SVM_EXIT_READ_CR0 ] = emulate_on_interception ,
2937
- [SVM_EXIT_READ_CR3 ] = emulate_on_interception ,
2938
- [SVM_EXIT_READ_CR4 ] = emulate_on_interception ,
2939
- [SVM_EXIT_READ_CR8 ] = emulate_on_interception ,
3004
+ [SVM_EXIT_READ_CR0 ] = cr_interception ,
3005
+ [SVM_EXIT_READ_CR3 ] = cr_interception ,
3006
+ [SVM_EXIT_READ_CR4 ] = cr_interception ,
3007
+ [SVM_EXIT_READ_CR8 ] = cr_interception ,
2940
3008
[SVM_EXIT_CR0_SEL_WRITE ] = emulate_on_interception ,
2941
3009
[SVM_EXIT_WRITE_CR0 ] = cr0_write_interception ,
2942
- [SVM_EXIT_WRITE_CR3 ] = emulate_on_interception ,
2943
- [SVM_EXIT_WRITE_CR4 ] = emulate_on_interception ,
3010
+ [SVM_EXIT_WRITE_CR3 ] = cr_interception ,
3011
+ [SVM_EXIT_WRITE_CR4 ] = cr_interception ,
2944
3012
[SVM_EXIT_WRITE_CR8 ] = cr8_write_interception ,
2945
3013
[SVM_EXIT_READ_DR0 ] = emulate_on_interception ,
2946
3014
[SVM_EXIT_READ_DR1 ] = emulate_on_interception ,
0 commit comments