Skip to content

Commit 1c6801d

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: Handle WXN attribute
Until now, we didn't really care about WXN as it didn't have an effect on the R/W permissions (only the execution could be droppped), and therefore not of interest for AT. However, with S1POE, WXN can revoke the Write permission if an overlay is active and that execution is allowed. This *is* relevant to AT. Add full handling of WXN so that we correctly handle this case. Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent e39ce70 commit 1c6801d

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

arch/arm64/kvm/at.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ struct s1_walk_result {
4040
u8 APTable;
4141
bool UXNTable;
4242
bool PXNTable;
43+
bool uwxn;
4344
bool uov;
4445
bool ur;
4546
bool uw;
4647
bool ux;
48+
bool pwxn;
4749
bool pov;
4850
bool pr;
4951
bool pw;
@@ -847,6 +849,8 @@ static void compute_s1_direct_permissions(struct kvm_vcpu *vcpu,
847849
struct s1_walk_info *wi,
848850
struct s1_walk_result *wr)
849851
{
852+
bool wxn;
853+
850854
/* Non-hierarchical part of AArch64.S1DirectBasePermissions() */
851855
if (wi->regime != TR_EL2) {
852856
switch (FIELD_GET(PTE_USER | PTE_RDONLY, wr->desc)) {
@@ -884,6 +888,17 @@ static void compute_s1_direct_permissions(struct kvm_vcpu *vcpu,
884888
wr->px = !(wr->desc & PTE_UXN);
885889
}
886890

891+
switch (wi->regime) {
892+
case TR_EL2:
893+
case TR_EL20:
894+
wxn = (vcpu_read_sys_reg(vcpu, SCTLR_EL2) & SCTLR_ELx_WXN);
895+
break;
896+
case TR_EL10:
897+
wxn = (__vcpu_sys_reg(vcpu, SCTLR_EL1) & SCTLR_ELx_WXN);
898+
break;
899+
}
900+
901+
wr->pwxn = wr->uwxn = wxn;
887902
wr->pov = wi->poe;
888903
wr->uov = wi->e0poe;
889904
}
@@ -935,6 +950,16 @@ static void compute_s1_hierarchical_permissions(struct kvm_vcpu *vcpu,
935950
(wr)->ux = (x); \
936951
} while (0)
937952

953+
#define set_priv_wxn(wr, v) \
954+
do { \
955+
(wr)->pwxn = (v); \
956+
} while (0)
957+
958+
#define set_unpriv_wxn(wr, v) \
959+
do { \
960+
(wr)->uwxn = (v); \
961+
} while (0)
962+
938963
/* Similar to AArch64.S1IndirectBasePermissions(), without GCS */
939964
#define set_perms(w, wr, ip) \
940965
do { \
@@ -989,6 +1014,10 @@ static void compute_s1_hierarchical_permissions(struct kvm_vcpu *vcpu,
9891014
set_ ## w ## _perms((wr), false, false, false); \
9901015
break; \
9911016
} \
1017+
\
1018+
/* R_HJYGR */ \
1019+
set_ ## w ## _wxn((wr), ((ip) == 0b0110)); \
1020+
\
9921021
} while (0)
9931022

9941023
static void compute_s1_indirect_permissions(struct kvm_vcpu *vcpu,
@@ -1090,6 +1119,22 @@ static void compute_s1_permissions(struct kvm_vcpu *vcpu,
10901119
if (wi->poe || wi->e0poe)
10911120
compute_s1_overlay_permissions(vcpu, wi, wr);
10921121

1122+
/* R_QXXPC */
1123+
if (wr->pwxn) {
1124+
if (!wr->pov && wr->pw)
1125+
wr->px = false;
1126+
if (wr->pov && wr->px)
1127+
wr->pw = false;
1128+
}
1129+
1130+
/* R_NPBXC */
1131+
if (wr->uwxn) {
1132+
if (!wr->uov && wr->uw)
1133+
wr->ux = false;
1134+
if (wr->uov && wr->ux)
1135+
wr->uw = false;
1136+
}
1137+
10931138
pan = wi->pan && (wr->ur || wr->uw ||
10941139
(pan3_enabled(vcpu, wi->regime) && wr->ux));
10951140
wr->pw &= !pan;

0 commit comments

Comments
 (0)