mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 02:53:36 +02:00
KVM: arm64: Add reg_feat_map_desc to describe full register dependency
struct reg_bits_to_feat_map is great to describe bit-to-feature dependency, but not so much to describe register-to-feature dependency. Yet both need to exist. Add a new reg_feat_map_desc structure to describe this. Extra complexity is added by the need to source the RES0 bits from the runtime-computed FGT masks, for which we need an extra flag and extra complexity. Oh well. Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
c3b3bbd160
commit
559442afea
|
|
@ -7,12 +7,22 @@
|
|||
#include <linux/kvm_host.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
/*
|
||||
* Describes the dependencies between a set of bits (or the negation
|
||||
* of a set of RES0 bits) and a feature. The flags indicate how the
|
||||
* data is interpreted.
|
||||
*/
|
||||
struct reg_bits_to_feat_map {
|
||||
u64 bits;
|
||||
union {
|
||||
u64 bits;
|
||||
u64 *res0p;
|
||||
};
|
||||
|
||||
#define NEVER_FGU BIT(0) /* Can trap, but never UNDEF */
|
||||
#define CALL_FUNC BIT(1) /* Needs to evaluate tons of crap */
|
||||
#define FIXED_VALUE BIT(2) /* RAZ/WI or RAO/WI in KVM */
|
||||
#define RES0_POINTER BIT(3) /* Pointer to RES0 value instead of bits */
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
union {
|
||||
|
|
@ -28,9 +38,27 @@ struct reg_bits_to_feat_map {
|
|||
};
|
||||
};
|
||||
|
||||
#define __NEEDS_FEAT_3(m, f, id, fld, lim) \
|
||||
/*
|
||||
* Describes the dependencies for a given register:
|
||||
*
|
||||
* @feat_map describes the dependency for the whole register. If the
|
||||
* features the register depends on are not present, the whole
|
||||
* register is effectively RES0.
|
||||
*
|
||||
* @bit_feat_map describes the dependencies for a set of bits in that
|
||||
* register. If the features these bits depend on are not present, the
|
||||
* bits are effectively RES0.
|
||||
*/
|
||||
struct reg_feat_map_desc {
|
||||
const char *name;
|
||||
const struct reg_bits_to_feat_map feat_map;
|
||||
const struct reg_bits_to_feat_map *bit_feat_map;
|
||||
const unsigned int bit_feat_map_sz;
|
||||
};
|
||||
|
||||
#define __NEEDS_FEAT_3(m, f, w, id, fld, lim) \
|
||||
{ \
|
||||
.bits = (m), \
|
||||
.w = (m), \
|
||||
.flags = (f), \
|
||||
.regidx = IDREG_IDX(SYS_ ## id), \
|
||||
.shift = id ##_## fld ## _SHIFT, \
|
||||
|
|
@ -39,28 +67,63 @@ struct reg_bits_to_feat_map {
|
|||
.lo_lim = id ##_## fld ##_## lim \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_2(m, f, fun, dummy) \
|
||||
#define __NEEDS_FEAT_2(m, f, w, fun, dummy) \
|
||||
{ \
|
||||
.bits = (m), \
|
||||
.w = (m), \
|
||||
.flags = (f) | CALL_FUNC, \
|
||||
.fval = (fun), \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_1(m, f, fun) \
|
||||
#define __NEEDS_FEAT_1(m, f, w, fun) \
|
||||
{ \
|
||||
.bits = (m), \
|
||||
.w = (m), \
|
||||
.flags = (f) | CALL_FUNC, \
|
||||
.match = (fun), \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_FLAG(m, f, w, ...) \
|
||||
CONCATENATE(__NEEDS_FEAT_, COUNT_ARGS(__VA_ARGS__))(m, f, w, __VA_ARGS__)
|
||||
|
||||
#define NEEDS_FEAT_FLAG(m, f, ...) \
|
||||
CONCATENATE(__NEEDS_FEAT_, COUNT_ARGS(__VA_ARGS__))(m, f, __VA_ARGS__)
|
||||
__NEEDS_FEAT_FLAG(m, f, bits, __VA_ARGS__)
|
||||
|
||||
#define NEEDS_FEAT_FIXED(m, ...) \
|
||||
NEEDS_FEAT_FLAG(m, FIXED_VALUE, __VA_ARGS__, 0)
|
||||
__NEEDS_FEAT_FLAG(m, FIXED_VALUE, bits, __VA_ARGS__, 0)
|
||||
|
||||
#define NEEDS_FEAT_RES0(p, ...) \
|
||||
__NEEDS_FEAT_FLAG(p, RES0_POINTER, res0p, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Declare the dependency between a set of bits and a set of features,
|
||||
* generating a struct reg_bit_to_feat_map.
|
||||
*/
|
||||
#define NEEDS_FEAT(m, ...) NEEDS_FEAT_FLAG(m, 0, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Declare the dependency between a non-FGT register, a set of
|
||||
* feature, and the set of individual bits it contains. This generates
|
||||
* a struct reg_feat_map_desc.
|
||||
*/
|
||||
#define DECLARE_FEAT_MAP(n, r, m, f) \
|
||||
struct reg_feat_map_desc n = { \
|
||||
.name = #r, \
|
||||
.feat_map = NEEDS_FEAT(~r##_RES0, f), \
|
||||
.bit_feat_map = m, \
|
||||
.bit_feat_map_sz = ARRAY_SIZE(m), \
|
||||
}
|
||||
|
||||
/*
|
||||
* Specialised version of the above for FGT registers that have their
|
||||
* RES0 masks described as struct fgt_masks.
|
||||
*/
|
||||
#define DECLARE_FEAT_MAP_FGT(n, msk, m, f) \
|
||||
struct reg_feat_map_desc n = { \
|
||||
.name = #msk, \
|
||||
.feat_map = NEEDS_FEAT_RES0(&msk.res0, f),\
|
||||
.bit_feat_map = m, \
|
||||
.bit_feat_map_sz = ARRAY_SIZE(m), \
|
||||
}
|
||||
|
||||
#define FEAT_SPE ID_AA64DFR0_EL1, PMSVer, IMP
|
||||
#define FEAT_SPE_FnE ID_AA64DFR0_EL1, PMSVer, V1P2
|
||||
#define FEAT_BRBE ID_AA64DFR0_EL1, BRBE, IMP
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user