Lines Matching full:wr

13 static void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool s1ptw)  in fail_s1_walk()  argument
15 wr->fst = fst; in fail_s1_walk()
16 wr->ptw = s1ptw; in fail_s1_walk()
17 wr->s2 = s1ptw; in fail_s1_walk()
18 wr->failed = true; in fail_s1_walk()
139 struct s1_walk_result *wr, u64 va) in setup_s1_walk() argument
249 wr->level = S1_MMU_DISABLED; in setup_s1_walk()
256 wr->level = S1_MMU_DISABLED; in setup_s1_walk()
260 if (wr->level == S1_MMU_DISABLED) { in setup_s1_walk()
264 wr->pa = va; in setup_s1_walk()
356 fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(0), false); in setup_s1_walk()
361 fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(wi->sl), false); in setup_s1_walk()
366 struct s1_walk_result *wr, u64 va) in walk_s1() argument
390 fail_s1_walk(wr, in walk_s1()
397 fail_s1_walk(wr, ESR_ELx_FSC_PERM_L(level), in walk_s1()
419 fail_s1_walk(wr, ESR_ELx_FSC_SEA_TTW(level), false); in walk_s1()
442 wr->APTable |= FIELD_GET(S1_TABLE_AP, desc); in walk_s1()
443 wr->UXNTable |= FIELD_GET(PMD_TABLE_UXN, desc); in walk_s1()
444 wr->PXNTable |= FIELD_GET(PMD_TABLE_PXN, desc); in walk_s1()
481 fail_s1_walk(wr, ESR_ELx_FSC_ACCESS_L(level), false); in walk_s1()
487 wr->failed = false; in walk_s1()
488 wr->level = level; in walk_s1()
489 wr->desc = desc; in walk_s1()
490 wr->pa = baddr & GENMASK(52, va_bottom); in walk_s1()
491 wr->pa |= va & GENMASK_ULL(va_bottom - 1, 0); in walk_s1()
493 wr->nG = (wi->regime != TR_EL2) && (desc & PTE_NG); in walk_s1()
494 if (wr->nG) { in walk_s1()
514 wr->asid = FIELD_GET(TTBR_ASID_MASK, asid_ttbr); in walk_s1()
517 wr->asid &= GENMASK(7, 0); in walk_s1()
523 fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(level), false); in walk_s1()
526 fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(level), false); in walk_s1()
731 static u8 compute_s1_sh(struct s1_walk_info *wi, struct s1_walk_result *wr, in compute_s1_sh() argument
742 sh = FIELD_GET(KVM_PTE_LEAF_ATTR_LO_S1_SH, wr->desc); in compute_s1_sh()
847 struct s1_walk_result *wr) in compute_par_s1() argument
851 if (wr->failed) { in compute_par_s1()
854 par |= FIELD_PREP(SYS_PAR_EL1_FST, wr->fst); in compute_par_s1()
855 par |= wr->ptw ? SYS_PAR_EL1_PTW : 0; in compute_par_s1()
856 par |= wr->s2 ? SYS_PAR_EL1_S : 0; in compute_par_s1()
857 } else if (wr->level == S1_MMU_DISABLED) { in compute_par_s1()
860 par |= wr->pa & SYS_PAR_EL1_PA; in compute_par_s1()
881 mair >>= FIELD_GET(PTE_ATTRINDX_MASK, wr->desc) * 8; in compute_par_s1()
893 par |= wr->pa & SYS_PAR_EL1_PA; in compute_par_s1()
895 sh = compute_s1_sh(wi, wr, mair); in compute_par_s1()
922 struct s1_walk_result *wr) in compute_s1_direct_permissions() argument
928 switch (FIELD_GET(PTE_USER | PTE_RDONLY, wr->desc)) { in compute_s1_direct_permissions()
930 wr->pr = wr->pw = true; in compute_s1_direct_permissions()
931 wr->ur = wr->uw = false; in compute_s1_direct_permissions()
934 wr->pr = wr->pw = wr->ur = wr->uw = true; in compute_s1_direct_permissions()
937 wr->pr = true; in compute_s1_direct_permissions()
938 wr->pw = wr->ur = wr->uw = false; in compute_s1_direct_permissions()
941 wr->pr = wr->ur = true; in compute_s1_direct_permissions()
942 wr->pw = wr->uw = false; in compute_s1_direct_permissions()
947 wr->px = !((wr->desc & PTE_PXN) || wr->uw); in compute_s1_direct_permissions()
948 wr->ux = !(wr->desc & PTE_UXN); in compute_s1_direct_permissions()
950 wr->ur = wr->uw = wr->ux = false; in compute_s1_direct_permissions()
952 if (!(wr->desc & PTE_RDONLY)) { in compute_s1_direct_permissions()
953 wr->pr = wr->pw = true; in compute_s1_direct_permissions()
955 wr->pr = true; in compute_s1_direct_permissions()
956 wr->pw = false; in compute_s1_direct_permissions()
960 wr->px = !(wr->desc & PTE_UXN); in compute_s1_direct_permissions()
973 wr->pwxn = wr->uwxn = wxn; in compute_s1_direct_permissions()
974 wr->pov = wi->poe; in compute_s1_direct_permissions()
975 wr->uov = wi->e0poe; in compute_s1_direct_permissions()
980 struct s1_walk_result *wr) in compute_s1_hierarchical_permissions() argument
984 switch (wr->APTable) { in compute_s1_hierarchical_permissions()
988 wr->ur = wr->uw = false; in compute_s1_hierarchical_permissions()
991 wr->pw = wr->uw = false; in compute_s1_hierarchical_permissions()
994 wr->pw = wr->ur = wr->uw = false; in compute_s1_hierarchical_permissions()
998 wr->px &= !wr->PXNTable; in compute_s1_hierarchical_permissions()
999 wr->ux &= !wr->UXNTable; in compute_s1_hierarchical_permissions()
1001 if (wr->APTable & BIT(1)) in compute_s1_hierarchical_permissions()
1002 wr->pw = false; in compute_s1_hierarchical_permissions()
1005 wr->px &= !wr->UXNTable; in compute_s1_hierarchical_permissions()
1011 #define set_priv_perms(wr, r, w, x) \ argument
1013 (wr)->pr = (r); \
1014 (wr)->pw = (w); \
1015 (wr)->px = (x); \
1018 #define set_unpriv_perms(wr, r, w, x) \ argument
1020 (wr)->ur = (r); \
1021 (wr)->uw = (w); \
1022 (wr)->ux = (x); \
1025 #define set_priv_wxn(wr, v) \ argument
1027 (wr)->pwxn = (v); \
1030 #define set_unpriv_wxn(wr, v) \ argument
1032 (wr)->uwxn = (v); \
1036 #define set_perms(w, wr, ip) \ argument
1041 set_ ## w ## _perms((wr), false, false, false); \
1044 set_ ## w ## _perms((wr), true , false, false); \
1047 set_ ## w ## _perms((wr), false, false, true ); \
1050 set_ ## w ## _perms((wr), true , false, true ); \
1053 set_ ## w ## _perms((wr), false, false, false); \
1056 set_ ## w ## _perms((wr), true , true , false); \
1059 set_ ## w ## _perms((wr), true , true , true ); \
1062 set_ ## w ## _perms((wr), true , true , true ); \
1065 set_ ## w ## _perms((wr), true , false, false); \
1068 set_ ## w ## _perms((wr), true , false, false); \
1071 set_ ## w ## _perms((wr), true , false, true ); \
1074 set_ ## w ## _perms((wr), false, false, false); \
1077 set_ ## w ## _perms((wr), true , true , false); \
1080 set_ ## w ## _perms((wr), false, false, false); \
1083 set_ ## w ## _perms((wr), true , true , true ); \
1086 set_ ## w ## _perms((wr), false, false, false); \
1091 set_ ## w ## _wxn((wr), ((ip) == 0b0110)); \
1097 struct s1_walk_result *wr) in compute_s1_indirect_permissions() argument
1101 idx = pte_pi_index(wr->desc); in compute_s1_indirect_permissions()
1118 set_perms(priv, wr, pp); in compute_s1_indirect_permissions()
1121 set_perms(unpriv, wr, up); in compute_s1_indirect_permissions()
1123 set_unpriv_perms(wr, false, false, false); in compute_s1_indirect_permissions()
1125 wr->pov = wi->poe && !(pp & BIT(3)); in compute_s1_indirect_permissions()
1126 wr->uov = wi->e0poe && !(up & BIT(3)); in compute_s1_indirect_permissions()
1129 if (wr->px && wr->uw) { in compute_s1_indirect_permissions()
1130 set_priv_perms(wr, false, false, false); in compute_s1_indirect_permissions()
1131 set_unpriv_perms(wr, false, false, false); in compute_s1_indirect_permissions()
1137 struct s1_walk_result *wr) in compute_s1_overlay_permissions() argument
1141 idx = FIELD_GET(PTE_PO_IDX_MASK, wr->desc); in compute_s1_overlay_permissions()
1143 if (wr->pov) { in compute_s1_overlay_permissions()
1160 if (wr->pwxn && (pov_perms & POE_X)) in compute_s1_overlay_permissions()
1163 wr->pr &= pov_perms & POE_R; in compute_s1_overlay_permissions()
1164 wr->pw &= pov_perms & POE_W; in compute_s1_overlay_permissions()
1165 wr->px &= pov_perms & POE_X; in compute_s1_overlay_permissions()
1168 if (wr->uov) { in compute_s1_overlay_permissions()
1185 if (wr->uwxn && (uov_perms & POE_X)) in compute_s1_overlay_permissions()
1188 wr->ur &= uov_perms & POE_R; in compute_s1_overlay_permissions()
1189 wr->uw &= uov_perms & POE_W; in compute_s1_overlay_permissions()
1190 wr->ux &= uov_perms & POE_X; in compute_s1_overlay_permissions()
1196 struct s1_walk_result *wr) in compute_s1_permissions() argument
1201 compute_s1_direct_permissions(vcpu, wi, wr); in compute_s1_permissions()
1203 compute_s1_indirect_permissions(vcpu, wi, wr); in compute_s1_permissions()
1206 compute_s1_hierarchical_permissions(vcpu, wi, wr); in compute_s1_permissions()
1208 compute_s1_overlay_permissions(vcpu, wi, wr); in compute_s1_permissions()
1211 if (!wr->pov) in compute_s1_permissions()
1212 wr->px &= !(wr->pwxn && wr->pw); in compute_s1_permissions()
1215 if (!wr->uov) in compute_s1_permissions()
1216 wr->ux &= !(wr->uwxn && wr->uw); in compute_s1_permissions()
1218 pan = wi->pan && (wr->ur || wr->uw || in compute_s1_permissions()
1219 (pan3_enabled(vcpu, wi->regime) && wr->ux)); in compute_s1_permissions()
1220 wr->pw &= !pan; in compute_s1_permissions()
1221 wr->pr &= !pan; in compute_s1_permissions()
1226 struct s1_walk_result wr = {}; in handle_at_slow() local
1236 ret = setup_s1_walk(vcpu, &wi, &wr, vaddr); in handle_at_slow()
1240 if (wr.level == S1_MMU_DISABLED) in handle_at_slow()
1245 ret = walk_s1(vcpu, &wi, &wr, vaddr); in handle_at_slow()
1252 compute_s1_permissions(vcpu, &wi, &wr); in handle_at_slow()
1258 perm_fail = !wr.pr; in handle_at_slow()
1263 perm_fail = !wr.pw; in handle_at_slow()
1266 perm_fail = !wr.ur; in handle_at_slow()
1269 perm_fail = !wr.uw; in handle_at_slow()
1279 fail_s1_walk(&wr, ESR_ELx_FSC_PERM_L(wr.level), false); in handle_at_slow()
1282 return compute_par_s1(vcpu, &wi, &wr); in handle_at_slow()
1547 * set. The rest of the wi and wr should be 0-initialised.
1550 struct s1_walk_result *wr, u64 va) in __kvm_translate_va() argument
1554 ret = setup_s1_walk(vcpu, wi, wr, va); in __kvm_translate_va()
1558 if (wr->level == S1_MMU_DISABLED) { in __kvm_translate_va()
1559 wr->ur = wr->uw = wr->ux = true; in __kvm_translate_va()
1560 wr->pr = wr->pw = wr->px = true; in __kvm_translate_va()
1562 ret = walk_s1(vcpu, wi, wr, va); in __kvm_translate_va()
1566 compute_s1_permissions(vcpu, wi, wr); in __kvm_translate_va()
1607 struct s1_walk_result wr = {}; in __kvm_find_s1_desc_level() local
1615 ret = setup_s1_walk(vcpu, &wi, &wr, va); in __kvm_find_s1_desc_level()
1620 if (WARN_ON_ONCE(wr.level == S1_MMU_DISABLED)) { in __kvm_find_s1_desc_level()
1626 ret = walk_s1(vcpu, &wi, &wr, va); in __kvm_find_s1_desc_level()