@@ -658,143 +658,78 @@ static void dbg_to_reg(struct kvm_vcpu *vcpu,
658658 p -> regval = (* dbg_reg & mask ) >> shift ;
659659}
660660
661- static bool trap_bvr (struct kvm_vcpu * vcpu ,
662- struct sys_reg_params * p ,
663- const struct sys_reg_desc * rd )
664- {
665- u64 * dbg_reg = & vcpu -> arch .vcpu_debug_state .dbg_bvr [rd -> CRm ];
666-
667- if (p -> is_write )
668- reg_to_dbg (vcpu , p , rd , dbg_reg );
669- else
670- dbg_to_reg (vcpu , p , rd , dbg_reg );
671-
672- return true;
673- }
674-
675- static int set_bvr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
676- u64 val )
677- {
678- vcpu -> arch .vcpu_debug_state .dbg_bvr [rd -> CRm ] = val ;
679- return 0 ;
680- }
681-
682- static int get_bvr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
683- u64 * val )
684- {
685- * val = vcpu -> arch .vcpu_debug_state .dbg_bvr [rd -> CRm ];
686- return 0 ;
661+ static u64 * demux_wb_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd )
662+ {
663+ struct kvm_guest_debug_arch * dbg = & vcpu -> arch .vcpu_debug_state ;
664+
665+ switch (rd -> Op2 ) {
666+ case 0b100 :
667+ return & dbg -> dbg_bvr [rd -> CRm ];
668+ case 0b101 :
669+ return & dbg -> dbg_bcr [rd -> CRm ];
670+ case 0b110 :
671+ return & dbg -> dbg_wvr [rd -> CRm ];
672+ case 0b111 :
673+ return & dbg -> dbg_wcr [rd -> CRm ];
674+ default :
675+ KVM_BUG_ON (1 , vcpu -> kvm );
676+ return NULL ;
677+ }
687678}
688679
689- static u64 reset_bvr (struct kvm_vcpu * vcpu ,
690- const struct sys_reg_desc * rd )
680+ static bool trap_dbg_wb_reg (struct kvm_vcpu * vcpu , struct sys_reg_params * p ,
681+ const struct sys_reg_desc * rd )
691682{
692- vcpu -> arch .vcpu_debug_state .dbg_bvr [rd -> CRm ] = rd -> val ;
693- return rd -> val ;
694- }
683+ u64 * reg = demux_wb_reg (vcpu , rd );
695684
696- static bool trap_bcr (struct kvm_vcpu * vcpu ,
697- struct sys_reg_params * p ,
698- const struct sys_reg_desc * rd )
699- {
700- u64 * dbg_reg = & vcpu -> arch .vcpu_debug_state .dbg_bcr [rd -> CRm ];
685+ if (!reg )
686+ return false;
701687
702688 if (p -> is_write )
703- reg_to_dbg (vcpu , p , rd , dbg_reg );
689+ reg_to_dbg (vcpu , p , rd , reg );
704690 else
705- dbg_to_reg (vcpu , p , rd , dbg_reg );
691+ dbg_to_reg (vcpu , p , rd , reg );
706692
707693 return true;
708694}
709695
710- static int set_bcr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
711- u64 val )
712- {
713- vcpu -> arch .vcpu_debug_state .dbg_bcr [rd -> CRm ] = val ;
714- return 0 ;
715- }
716-
717- static int get_bcr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
718- u64 * val )
719- {
720- * val = vcpu -> arch .vcpu_debug_state .dbg_bcr [rd -> CRm ];
721- return 0 ;
722- }
723-
724- static u64 reset_bcr (struct kvm_vcpu * vcpu ,
725- const struct sys_reg_desc * rd )
696+ static int set_dbg_wb_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
697+ u64 val )
726698{
727- vcpu -> arch .vcpu_debug_state .dbg_bcr [rd -> CRm ] = rd -> val ;
728- return rd -> val ;
729- }
699+ u64 * reg = demux_wb_reg (vcpu , rd );
730700
731- static bool trap_wvr (struct kvm_vcpu * vcpu ,
732- struct sys_reg_params * p ,
733- const struct sys_reg_desc * rd )
734- {
735- u64 * dbg_reg = & vcpu -> arch .vcpu_debug_state .dbg_wvr [rd -> CRm ];
736-
737- if (p -> is_write )
738- reg_to_dbg (vcpu , p , rd , dbg_reg );
739- else
740- dbg_to_reg (vcpu , p , rd , dbg_reg );
741-
742- return true;
743- }
744-
745- static int set_wvr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
746- u64 val )
747- {
748- vcpu -> arch .vcpu_debug_state .dbg_wvr [rd -> CRm ] = val ;
749- return 0 ;
750- }
701+ if (!reg )
702+ return - EINVAL ;
751703
752- static int get_wvr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
753- u64 * val )
754- {
755- * val = vcpu -> arch .vcpu_debug_state .dbg_wvr [rd -> CRm ];
704+ * reg = val ;
756705 return 0 ;
757706}
758707
759- static u64 reset_wvr (struct kvm_vcpu * vcpu ,
760- const struct sys_reg_desc * rd )
761- {
762- vcpu -> arch .vcpu_debug_state .dbg_wvr [rd -> CRm ] = rd -> val ;
763- return rd -> val ;
764- }
765-
766- static bool trap_wcr (struct kvm_vcpu * vcpu ,
767- struct sys_reg_params * p ,
768- const struct sys_reg_desc * rd )
708+ static int get_dbg_wb_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
709+ u64 * val )
769710{
770- u64 * dbg_reg = & vcpu -> arch .vcpu_debug_state .dbg_wcr [rd -> CRm ];
771-
772- if (p -> is_write )
773- reg_to_dbg (vcpu , p , rd , dbg_reg );
774- else
775- dbg_to_reg (vcpu , p , rd , dbg_reg );
711+ u64 * reg = demux_wb_reg (vcpu , rd );
776712
777- return true;
778- }
713+ if (! reg )
714+ return - EINVAL ;
779715
780- static int set_wcr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
781- u64 val )
782- {
783- vcpu -> arch .vcpu_debug_state .dbg_wcr [rd -> CRm ] = val ;
716+ * val = * reg ;
784717 return 0 ;
785718}
786719
787- static int get_wcr (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
788- u64 * val )
720+ static u64 reset_dbg_wb_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd )
789721{
790- * val = vcpu -> arch .vcpu_debug_state .dbg_wcr [rd -> CRm ];
791- return 0 ;
792- }
722+ u64 * reg = demux_wb_reg (vcpu , rd );
793723
794- static u64 reset_wcr (struct kvm_vcpu * vcpu ,
795- const struct sys_reg_desc * rd )
796- {
797- vcpu -> arch .vcpu_debug_state .dbg_wcr [rd -> CRm ] = rd -> val ;
724+ /*
725+ * Bail early if we couldn't find storage for the register, the
726+ * KVM_BUG_ON() in demux_wb_reg() will prevent this VM from ever
727+ * being run.
728+ */
729+ if (!reg )
730+ return 0 ;
731+
732+ * reg = rd -> val ;
798733 return rd -> val ;
799734}
800735
@@ -1303,13 +1238,17 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
13031238/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
13041239#define DBG_BCR_BVR_WCR_WVR_EL1 (n ) \
13051240 { SYS_DESC(SYS_DBGBVRn_EL1(n)), \
1306- trap_bvr, reset_bvr, 0, 0, get_bvr, set_bvr }, \
1241+ trap_dbg_wb_reg, reset_dbg_wb_reg, 0, 0, \
1242+ get_dbg_wb_reg, set_dbg_wb_reg }, \
13071243 { SYS_DESC(SYS_DBGBCRn_EL1(n)), \
1308- trap_bcr, reset_bcr, 0, 0, get_bcr, set_bcr }, \
1244+ trap_dbg_wb_reg, reset_dbg_wb_reg, 0, 0, \
1245+ get_dbg_wb_reg, set_dbg_wb_reg }, \
13091246 { SYS_DESC(SYS_DBGWVRn_EL1(n)), \
1310- trap_wvr, reset_wvr, 0, 0, get_wvr, set_wvr }, \
1247+ trap_dbg_wb_reg, reset_dbg_wb_reg, 0, 0, \
1248+ get_dbg_wb_reg, set_dbg_wb_reg }, \
13111249 { SYS_DESC(SYS_DBGWCRn_EL1(n)), \
1312- trap_wcr, reset_wcr, 0, 0, get_wcr, set_wcr }
1250+ trap_dbg_wb_reg, reset_dbg_wb_reg, 0, 0, \
1251+ get_dbg_wb_reg, set_dbg_wb_reg }
13131252
13141253#define PMU_SYS_REG (name ) \
13151254 SYS_DESC(SYS_##name), .reset = reset_pmu_reg, \
@@ -3523,18 +3462,20 @@ static bool trap_dbgdidr(struct kvm_vcpu *vcpu,
35233462 * None of the other registers share their location, so treat them as
35243463 * if they were 64bit.
35253464 */
3526- #define DBG_BCR_BVR_WCR_WVR (n ) \
3527- /* DBGBVRn */ \
3528- { AA32(LO), Op1( 0), CRn( 0), CRm((n)), Op2( 4), trap_bvr, NULL, n }, \
3529- /* DBGBCRn */ \
3530- { Op1 ( 0 ), CRn ( 0 ), CRm ((n )), Op2 ( 5 ), trap_bcr , NULL , n }, \
3531- /* DBGWVRn */ \
3532- { Op1 ( 0 ), CRn ( 0 ), CRm ((n )), Op2 ( 6 ), trap_wvr , NULL , n }, \
3533- /* DBGWCRn */ \
3534- { Op1 ( 0 ), CRn ( 0 ), CRm ((n )), Op2 ( 7 ), trap_wcr , NULL , n }
3535-
3536- #define DBGBXVR (n ) \
3537- { AA32 (HI ), Op1 ( 0 ), CRn ( 1 ), CRm ((n )), Op2 ( 1 ), trap_bvr , NULL , n }
3465+ #define DBG_BCR_BVR_WCR_WVR (n ) \
3466+ /* DBGBVRn */ \
3467+ { AA32(LO), Op1( 0), CRn( 0), CRm((n)), Op2( 4), \
3468+ trap_dbg_wb_reg, NULL, n }, \
3469+ /* DBGBCRn */ \
3470+ { Op1 ( 0 ), CRn ( 0 ), CRm ((n )), Op2 ( 5 ), trap_dbg_wb_reg , NULL , n }, \
3471+ /* DBGWVRn */ \
3472+ { Op1 ( 0 ), CRn ( 0 ), CRm ((n )), Op2 ( 6 ), trap_dbg_wb_reg , NULL , n }, \
3473+ /* DBGWCRn */ \
3474+ { Op1 ( 0 ), CRn ( 0 ), CRm ((n )), Op2 ( 7 ), trap_dbg_wb_reg , NULL , n }
3475+
3476+ #define DBGBXVR (n ) \
3477+ { AA32 (HI ), Op1 ( 0 ), CRn ( 1 ), CRm ((n )), Op2 ( 1 ), \
3478+ trap_dbg_wb_reg , NULL , n }
35383479
35393480/*
35403481 * Trapped cp14 registers. We generally ignore most of the external
0 commit comments