Skip to content

Commit c259d76

Browse files
author
Marc Zyngier
committed
KVM: arm64: Account for RES1 bits in DECLARE_FEAT_MAP() and co
None of the registers we manage in the feature dependency infrastructure so far has any RES1 bit. This is about to change, as VTCR_EL2 has its bit 31 being RES1. In order to not fail the consistency checks by not describing a bit, add RES1 bits to the set of immutable bits. This requires some extra surgery for the FGT handling, as we now need to track RES1 bits there as well. There are no RES1 FGT bits *yet*. Watch this space. Reviewed-by: Fuad Tabba <tabba@google.com> Tested-by: Sascha Bischoff <sascha.bischoff@arm.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Tested-by: Fuad Tabba <tabba@google.com> Link: https://patch.msgid.link/20251210173024.561160-5-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent a035001 commit c259d76

3 files changed

Lines changed: 45 additions & 36 deletions

File tree

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ struct fgt_masks {
638638
u64 mask;
639639
u64 nmask;
640640
u64 res0;
641+
u64 res1;
641642
};
642643

643644
extern struct fgt_masks hfgrtr_masks;

arch/arm64/kvm/config.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
*/
1717
struct reg_bits_to_feat_map {
1818
union {
19-
u64 bits;
20-
u64 *res0p;
19+
u64 bits;
20+
struct fgt_masks *masks;
2121
};
2222

2323
#define NEVER_FGU BIT(0) /* Can trap, but never UNDEF */
2424
#define CALL_FUNC BIT(1) /* Needs to evaluate tons of crap */
2525
#define FIXED_VALUE BIT(2) /* RAZ/WI or RAO/WI in KVM */
26-
#define RES0_POINTER BIT(3) /* Pointer to RES0 value instead of bits */
26+
#define MASKS_POINTER BIT(3) /* Pointer to fgt_masks struct instead of bits */
2727

2828
unsigned long flags;
2929

@@ -92,8 +92,8 @@ struct reg_feat_map_desc {
9292
#define NEEDS_FEAT_FIXED(m, ...) \
9393
__NEEDS_FEAT_FLAG(m, FIXED_VALUE, bits, __VA_ARGS__, 0)
9494

95-
#define NEEDS_FEAT_RES0(p, ...) \
96-
__NEEDS_FEAT_FLAG(p, RES0_POINTER, res0p, __VA_ARGS__)
95+
#define NEEDS_FEAT_MASKS(p, ...) \
96+
__NEEDS_FEAT_FLAG(p, MASKS_POINTER, masks, __VA_ARGS__)
9797

9898
/*
9999
* Declare the dependency between a set of bits and a set of features,
@@ -109,19 +109,20 @@ struct reg_feat_map_desc {
109109
#define DECLARE_FEAT_MAP(n, r, m, f) \
110110
struct reg_feat_map_desc n = { \
111111
.name = #r, \
112-
.feat_map = NEEDS_FEAT(~r##_RES0, f), \
112+
.feat_map = NEEDS_FEAT(~(r##_RES0 | \
113+
r##_RES1), f), \
113114
.bit_feat_map = m, \
114115
.bit_feat_map_sz = ARRAY_SIZE(m), \
115116
}
116117

117118
/*
118119
* Specialised version of the above for FGT registers that have their
119-
* RES0 masks described as struct fgt_masks.
120+
* RESx masks described as struct fgt_masks.
120121
*/
121122
#define DECLARE_FEAT_MAP_FGT(n, msk, m, f) \
122123
struct reg_feat_map_desc n = { \
123124
.name = #msk, \
124-
.feat_map = NEEDS_FEAT_RES0(&msk.res0, f),\
125+
.feat_map = NEEDS_FEAT_MASKS(&msk, f), \
125126
.bit_feat_map = m, \
126127
.bit_feat_map_sz = ARRAY_SIZE(m), \
127128
}
@@ -1168,21 +1169,21 @@ static const DECLARE_FEAT_MAP(mdcr_el2_desc, MDCR_EL2,
11681169
mdcr_el2_feat_map, FEAT_AA64EL2);
11691170

11701171
static void __init check_feat_map(const struct reg_bits_to_feat_map *map,
1171-
int map_size, u64 res0, const char *str)
1172+
int map_size, u64 resx, const char *str)
11721173
{
11731174
u64 mask = 0;
11741175

11751176
for (int i = 0; i < map_size; i++)
11761177
mask |= map[i].bits;
11771178

1178-
if (mask != ~res0)
1179+
if (mask != ~resx)
11791180
kvm_err("Undefined %s behaviour, bits %016llx\n",
1180-
str, mask ^ ~res0);
1181+
str, mask ^ ~resx);
11811182
}
11821183

11831184
static u64 reg_feat_map_bits(const struct reg_bits_to_feat_map *map)
11841185
{
1185-
return map->flags & RES0_POINTER ? ~(*map->res0p) : map->bits;
1186+
return map->flags & MASKS_POINTER ? (map->masks->mask | map->masks->nmask) : map->bits;
11861187
}
11871188

11881189
static void __init check_reg_desc(const struct reg_feat_map_desc *r)

arch/arm64/kvm/emulate-nested.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,23 +2105,24 @@ static u32 encoding_next(u32 encoding)
21052105
}
21062106

21072107
#define FGT_MASKS(__n, __m) \
2108-
struct fgt_masks __n = { .str = #__m, .res0 = __m, }
2109-
2110-
FGT_MASKS(hfgrtr_masks, HFGRTR_EL2_RES0);
2111-
FGT_MASKS(hfgwtr_masks, HFGWTR_EL2_RES0);
2112-
FGT_MASKS(hfgitr_masks, HFGITR_EL2_RES0);
2113-
FGT_MASKS(hdfgrtr_masks, HDFGRTR_EL2_RES0);
2114-
FGT_MASKS(hdfgwtr_masks, HDFGWTR_EL2_RES0);
2115-
FGT_MASKS(hafgrtr_masks, HAFGRTR_EL2_RES0);
2116-
FGT_MASKS(hfgrtr2_masks, HFGRTR2_EL2_RES0);
2117-
FGT_MASKS(hfgwtr2_masks, HFGWTR2_EL2_RES0);
2118-
FGT_MASKS(hfgitr2_masks, HFGITR2_EL2_RES0);
2119-
FGT_MASKS(hdfgrtr2_masks, HDFGRTR2_EL2_RES0);
2120-
FGT_MASKS(hdfgwtr2_masks, HDFGWTR2_EL2_RES0);
2108+
struct fgt_masks __n = { .str = #__m, .res0 = __m ## _RES0, .res1 = __m ## _RES1 }
2109+
2110+
FGT_MASKS(hfgrtr_masks, HFGRTR_EL2);
2111+
FGT_MASKS(hfgwtr_masks, HFGWTR_EL2);
2112+
FGT_MASKS(hfgitr_masks, HFGITR_EL2);
2113+
FGT_MASKS(hdfgrtr_masks, HDFGRTR_EL2);
2114+
FGT_MASKS(hdfgwtr_masks, HDFGWTR_EL2);
2115+
FGT_MASKS(hafgrtr_masks, HAFGRTR_EL2);
2116+
FGT_MASKS(hfgrtr2_masks, HFGRTR2_EL2);
2117+
FGT_MASKS(hfgwtr2_masks, HFGWTR2_EL2);
2118+
FGT_MASKS(hfgitr2_masks, HFGITR2_EL2);
2119+
FGT_MASKS(hdfgrtr2_masks, HDFGRTR2_EL2);
2120+
FGT_MASKS(hdfgwtr2_masks, HDFGWTR2_EL2);
21212121

21222122
static __init bool aggregate_fgt(union trap_config tc)
21232123
{
21242124
struct fgt_masks *rmasks, *wmasks;
2125+
u64 rresx, wresx;
21252126

21262127
switch (tc.fgt) {
21272128
case HFGRTR_GROUP:
@@ -2154,24 +2155,27 @@ static __init bool aggregate_fgt(union trap_config tc)
21542155
break;
21552156
}
21562157

2158+
rresx = rmasks->res0 | rmasks->res1;
2159+
if (wmasks)
2160+
wresx = wmasks->res0 | wmasks->res1;
2161+
21572162
/*
21582163
* A bit can be reserved in either the R or W register, but
21592164
* not both.
21602165
*/
2161-
if ((BIT(tc.bit) & rmasks->res0) &&
2162-
(!wmasks || (BIT(tc.bit) & wmasks->res0)))
2166+
if ((BIT(tc.bit) & rresx) && (!wmasks || (BIT(tc.bit) & wresx)))
21632167
return false;
21642168

21652169
if (tc.pol)
2166-
rmasks->mask |= BIT(tc.bit) & ~rmasks->res0;
2170+
rmasks->mask |= BIT(tc.bit) & ~rresx;
21672171
else
2168-
rmasks->nmask |= BIT(tc.bit) & ~rmasks->res0;
2172+
rmasks->nmask |= BIT(tc.bit) & ~rresx;
21692173

21702174
if (wmasks) {
21712175
if (tc.pol)
2172-
wmasks->mask |= BIT(tc.bit) & ~wmasks->res0;
2176+
wmasks->mask |= BIT(tc.bit) & ~wresx;
21732177
else
2174-
wmasks->nmask |= BIT(tc.bit) & ~wmasks->res0;
2178+
wmasks->nmask |= BIT(tc.bit) & ~wresx;
21752179
}
21762180

21772181
return true;
@@ -2180,7 +2184,6 @@ static __init bool aggregate_fgt(union trap_config tc)
21802184
static __init int check_fgt_masks(struct fgt_masks *masks)
21812185
{
21822186
unsigned long duplicate = masks->mask & masks->nmask;
2183-
u64 res0 = masks->res0;
21842187
int ret = 0;
21852188

21862189
if (duplicate) {
@@ -2194,10 +2197,14 @@ static __init int check_fgt_masks(struct fgt_masks *masks)
21942197
ret = -EINVAL;
21952198
}
21962199

2197-
masks->res0 = ~(masks->mask | masks->nmask);
2198-
if (masks->res0 != res0)
2199-
kvm_info("Implicit %s = %016llx, expecting %016llx\n",
2200-
masks->str, masks->res0, res0);
2200+
if ((masks->res0 | masks->res1 | masks->mask | masks->nmask) != GENMASK(63, 0) ||
2201+
(masks->res0 & masks->res1) || (masks->res0 & masks->mask) ||
2202+
(masks->res0 & masks->nmask) || (masks->res1 & masks->mask) ||
2203+
(masks->res1 & masks->nmask) || (masks->mask & masks->nmask)) {
2204+
kvm_info("Inconsistent masks for %s (%016llx, %016llx, %016llx, %016llx)\n",
2205+
masks->str, masks->res0, masks->res1, masks->mask, masks->nmask);
2206+
masks->res0 = ~(masks->res1 | masks->mask | masks->nmask);
2207+
}
22012208

22022209
return ret;
22032210
}

0 commit comments

Comments
 (0)