@@ -1047,34 +1047,51 @@ static void compute_s1_overlay_permissions(struct kvm_vcpu *vcpu,
10471047
10481048 idx = FIELD_GET (PTE_PO_IDX_MASK , wr -> desc );
10491049
1050- switch (wi -> regime ) {
1051- case TR_EL10 :
1052- pov_perms = perm_idx (vcpu , POR_EL1 , idx );
1053- uov_perms = perm_idx (vcpu , POR_EL0 , idx );
1054- break ;
1055- case TR_EL20 :
1056- pov_perms = perm_idx (vcpu , POR_EL2 , idx );
1057- uov_perms = perm_idx (vcpu , POR_EL0 , idx );
1058- break ;
1059- case TR_EL2 :
1060- pov_perms = perm_idx (vcpu , POR_EL2 , idx );
1061- uov_perms = 0 ;
1062- break ;
1063- }
1050+ if (wr -> pov ) {
1051+ switch (wi -> regime ) {
1052+ case TR_EL10 :
1053+ pov_perms = perm_idx (vcpu , POR_EL1 , idx );
1054+ break ;
1055+ case TR_EL20 :
1056+ pov_perms = perm_idx (vcpu , POR_EL2 , idx );
1057+ break ;
1058+ case TR_EL2 :
1059+ pov_perms = perm_idx (vcpu , POR_EL2 , idx );
1060+ break ;
1061+ }
1062+
1063+ if (pov_perms & ~POE_RWX )
1064+ pov_perms = POE_NONE ;
10641065
1065- if (pov_perms & ~POE_RWX )
1066- pov_perms = POE_NONE ;
1066+ /* R_QXXPC, S1PrivOverflow enabled */
1067+ if (wr -> pwxn && (pov_perms & POE_X ))
1068+ pov_perms &= ~POE_W ;
10671069
1068- if (wi -> poe && wr -> pov ) {
10691070 wr -> pr &= pov_perms & POE_R ;
10701071 wr -> pw &= pov_perms & POE_W ;
10711072 wr -> px &= pov_perms & POE_X ;
10721073 }
10731074
1074- if (uov_perms & ~POE_RWX )
1075- uov_perms = POE_NONE ;
1075+ if (wr -> uov ) {
1076+ switch (wi -> regime ) {
1077+ case TR_EL10 :
1078+ uov_perms = perm_idx (vcpu , POR_EL0 , idx );
1079+ break ;
1080+ case TR_EL20 :
1081+ uov_perms = perm_idx (vcpu , POR_EL0 , idx );
1082+ break ;
1083+ case TR_EL2 :
1084+ uov_perms = 0 ;
1085+ break ;
1086+ }
1087+
1088+ if (uov_perms & ~POE_RWX )
1089+ uov_perms = POE_NONE ;
1090+
1091+ /* R_NPBXC, S1UnprivOverlay enabled */
1092+ if (wr -> uwxn && (uov_perms & POE_X ))
1093+ uov_perms &= ~POE_W ;
10761094
1077- if (wi -> e0poe && wr -> uov ) {
10781095 wr -> ur &= uov_perms & POE_R ;
10791096 wr -> uw &= uov_perms & POE_W ;
10801097 wr -> ux &= uov_perms & POE_X ;
@@ -1095,24 +1112,15 @@ static void compute_s1_permissions(struct kvm_vcpu *vcpu,
10951112 if (!wi -> hpd )
10961113 compute_s1_hierarchical_permissions (vcpu , wi , wr );
10971114
1098- if (wi -> poe || wi -> e0poe )
1099- compute_s1_overlay_permissions (vcpu , wi , wr );
1115+ compute_s1_overlay_permissions (vcpu , wi , wr );
11001116
1101- /* R_QXXPC */
1102- if (wr -> pwxn ) {
1103- if (!wr -> pov && wr -> pw )
1104- wr -> px = false;
1105- if (wr -> pov && wr -> px )
1106- wr -> pw = false;
1107- }
1117+ /* R_QXXPC, S1PrivOverlay disabled */
1118+ if (!wr -> pov )
1119+ wr -> px &= !(wr -> pwxn && wr -> pw );
11081120
1109- /* R_NPBXC */
1110- if (wr -> uwxn ) {
1111- if (!wr -> uov && wr -> uw )
1112- wr -> ux = false;
1113- if (wr -> uov && wr -> ux )
1114- wr -> uw = false;
1115- }
1121+ /* R_NPBXC, S1UnprivOverlay disabled */
1122+ if (!wr -> uov )
1123+ wr -> ux &= !(wr -> uwxn && wr -> uw );
11161124
11171125 pan = wi -> pan && (wr -> ur || wr -> uw ||
11181126 (pan3_enabled (vcpu , wi -> regime ) && wr -> ux ));
0 commit comments