Skip to content

Commit d86cde6

Browse files
jingzhangosoupton
authored andcommitted
KVM: arm64: Reuse fields of sys_reg_desc for idreg
sys_reg_desc::{reset, val} are presently unused for ID register descriptors. Repurpose these fields to support user-configurable ID registers. Use the ::reset() function pointer to return the sanitised value of a given ID register, optionally with KVM-specific feature sanitisation. Additionally, keep a mask of writable register fields in ::val. Signed-off-by: Jing Zhang <jingzhangos@google.com> Link: https://lore.kernel.org/r/20230609190054.1542113-6-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent f90f936 commit d86cde6

2 files changed

Lines changed: 84 additions & 25 deletions

File tree

arch/arm64/kvm/sys_regs.c

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,11 @@ static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
540540
return 0;
541541
}
542542

543-
static void reset_bvr(struct kvm_vcpu *vcpu,
543+
static u64 reset_bvr(struct kvm_vcpu *vcpu,
544544
const struct sys_reg_desc *rd)
545545
{
546546
vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val;
547+
return rd->val;
547548
}
548549

549550
static bool trap_bcr(struct kvm_vcpu *vcpu,
@@ -576,10 +577,11 @@ static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
576577
return 0;
577578
}
578579

579-
static void reset_bcr(struct kvm_vcpu *vcpu,
580+
static u64 reset_bcr(struct kvm_vcpu *vcpu,
580581
const struct sys_reg_desc *rd)
581582
{
582583
vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val;
584+
return rd->val;
583585
}
584586

585587
static bool trap_wvr(struct kvm_vcpu *vcpu,
@@ -613,10 +615,11 @@ static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
613615
return 0;
614616
}
615617

616-
static void reset_wvr(struct kvm_vcpu *vcpu,
618+
static u64 reset_wvr(struct kvm_vcpu *vcpu,
617619
const struct sys_reg_desc *rd)
618620
{
619621
vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val;
622+
return rd->val;
620623
}
621624

622625
static bool trap_wcr(struct kvm_vcpu *vcpu,
@@ -649,25 +652,28 @@ static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
649652
return 0;
650653
}
651654

652-
static void reset_wcr(struct kvm_vcpu *vcpu,
655+
static u64 reset_wcr(struct kvm_vcpu *vcpu,
653656
const struct sys_reg_desc *rd)
654657
{
655658
vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val;
659+
return rd->val;
656660
}
657661

658-
static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
662+
static u64 reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
659663
{
660664
u64 amair = read_sysreg(amair_el1);
661665
vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1);
666+
return amair;
662667
}
663668

664-
static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
669+
static u64 reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
665670
{
666671
u64 actlr = read_sysreg(actlr_el1);
667672
vcpu_write_sys_reg(vcpu, actlr, ACTLR_EL1);
673+
return actlr;
668674
}
669675

670-
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
676+
static u64 reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
671677
{
672678
u64 mpidr;
673679

@@ -681,7 +687,10 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
681687
mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0);
682688
mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1);
683689
mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2);
684-
vcpu_write_sys_reg(vcpu, (1ULL << 31) | mpidr, MPIDR_EL1);
690+
mpidr |= (1ULL << 31);
691+
vcpu_write_sys_reg(vcpu, mpidr, MPIDR_EL1);
692+
693+
return mpidr;
685694
}
686695

687696
static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu,
@@ -693,13 +702,13 @@ static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu,
693702
return REG_HIDDEN;
694703
}
695704

696-
static void reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
705+
static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
697706
{
698707
u64 n, mask = BIT(ARMV8_PMU_CYCLE_IDX);
699708

700709
/* No PMU available, any PMU reg may UNDEF... */
701710
if (!kvm_arm_support_pmu_v3())
702-
return;
711+
return 0;
703712

704713
n = read_sysreg(pmcr_el0) >> ARMV8_PMU_PMCR_N_SHIFT;
705714
n &= ARMV8_PMU_PMCR_N_MASK;
@@ -708,40 +717,50 @@ static void reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
708717

709718
reset_unknown(vcpu, r);
710719
__vcpu_sys_reg(vcpu, r->reg) &= mask;
720+
721+
return __vcpu_sys_reg(vcpu, r->reg);
711722
}
712723

713-
static void reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
724+
static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
714725
{
715726
reset_unknown(vcpu, r);
716727
__vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0);
728+
729+
return __vcpu_sys_reg(vcpu, r->reg);
717730
}
718731

719-
static void reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
732+
static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
720733
{
721734
reset_unknown(vcpu, r);
722735
__vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_EVTYPE_MASK;
736+
737+
return __vcpu_sys_reg(vcpu, r->reg);
723738
}
724739

725-
static void reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
740+
static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
726741
{
727742
reset_unknown(vcpu, r);
728743
__vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_COUNTER_MASK;
744+
745+
return __vcpu_sys_reg(vcpu, r->reg);
729746
}
730747

731-
static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
748+
static u64 reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
732749
{
733750
u64 pmcr;
734751

735752
/* No PMU available, PMCR_EL0 may UNDEF... */
736753
if (!kvm_arm_support_pmu_v3())
737-
return;
754+
return 0;
738755

739756
/* Only preserve PMCR_EL0.N, and reset the rest to 0 */
740757
pmcr = read_sysreg(pmcr_el0) & (ARMV8_PMU_PMCR_N_MASK << ARMV8_PMU_PMCR_N_SHIFT);
741758
if (!kvm_supports_32bit_el0())
742759
pmcr |= ARMV8_PMU_PMCR_LC;
743760

744761
__vcpu_sys_reg(vcpu, r->reg) = pmcr;
762+
763+
return __vcpu_sys_reg(vcpu, r->reg);
745764
}
746765

747766
static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
@@ -1209,7 +1228,8 @@ static u8 pmuver_to_perfmon(u8 pmuver)
12091228
}
12101229

12111230
/* Read a sanitised cpufeature ID register by sys_reg_desc */
1212-
static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r)
1231+
static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
1232+
const struct sys_reg_desc *r)
12131233
{
12141234
u32 id = reg_to_encoding(r);
12151235
u64 val;
@@ -1280,6 +1300,17 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r
12801300
return val;
12811301
}
12821302

1303+
static u64 kvm_read_sanitised_id_reg(struct kvm_vcpu *vcpu,
1304+
const struct sys_reg_desc *r)
1305+
{
1306+
return __kvm_read_sanitised_id_reg(vcpu, r);
1307+
}
1308+
1309+
static u64 read_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
1310+
{
1311+
return __kvm_read_sanitised_id_reg(vcpu, r);
1312+
}
1313+
12831314
static unsigned int id_visibility(const struct kvm_vcpu *vcpu,
12841315
const struct sys_reg_desc *r)
12851316
{
@@ -1530,7 +1561,7 @@ static bool access_clidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
15301561
* Fabricate a CLIDR_EL1 value instead of using the real value, which can vary
15311562
* by the physical CPU which the vcpu currently resides in.
15321563
*/
1533-
static void reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
1564+
static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
15341565
{
15351566
u64 ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0);
15361567
u64 clidr;
@@ -1578,6 +1609,8 @@ static void reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
15781609
clidr |= 2 << CLIDR_TTYPE_SHIFT(loc);
15791610

15801611
__vcpu_sys_reg(vcpu, r->reg) = clidr;
1612+
1613+
return __vcpu_sys_reg(vcpu, r->reg);
15811614
}
15821615

15831616
static int set_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
@@ -1677,13 +1710,26 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
16771710
.visibility = elx2_visibility, \
16781711
}
16791712

1713+
/*
1714+
* Since reset() callback and field val are not used for idregs, they will be
1715+
* used for specific purposes for idregs.
1716+
* The reset() would return KVM sanitised register value. The value would be the
1717+
* same as the host kernel sanitised value if there is no KVM sanitisation.
1718+
* The val would be used as a mask indicating writable fields for the idreg.
1719+
* Only bits with 1 are writable from userspace. This mask might not be
1720+
* necessary in the future whenever all ID registers are enabled as writable
1721+
* from userspace.
1722+
*/
1723+
16801724
/* sys_reg_desc initialiser for known cpufeature ID registers */
16811725
#define ID_SANITISED(name) { \
16821726
SYS_DESC(SYS_##name), \
16831727
.access = access_id_reg, \
16841728
.get_user = get_id_reg, \
16851729
.set_user = set_id_reg, \
16861730
.visibility = id_visibility, \
1731+
.reset = kvm_read_sanitised_id_reg, \
1732+
.val = 0, \
16871733
}
16881734

16891735
/* sys_reg_desc initialiser for known cpufeature ID registers */
@@ -1693,6 +1739,8 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
16931739
.get_user = get_id_reg, \
16941740
.set_user = set_id_reg, \
16951741
.visibility = aa32_id_visibility, \
1742+
.reset = kvm_read_sanitised_id_reg, \
1743+
.val = 0, \
16961744
}
16971745

16981746
/*
@@ -1705,7 +1753,9 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
17051753
.access = access_id_reg, \
17061754
.get_user = get_id_reg, \
17071755
.set_user = set_id_reg, \
1708-
.visibility = raz_visibility \
1756+
.visibility = raz_visibility, \
1757+
.reset = kvm_read_sanitised_id_reg, \
1758+
.val = 0, \
17091759
}
17101760

17111761
/*
@@ -1719,6 +1769,8 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
17191769
.get_user = get_id_reg, \
17201770
.set_user = set_id_reg, \
17211771
.visibility = raz_visibility, \
1772+
.reset = kvm_read_sanitised_id_reg, \
1773+
.val = 0, \
17221774
}
17231775

17241776
static bool access_sp_el1(struct kvm_vcpu *vcpu,
@@ -3055,19 +3107,21 @@ id_to_sys_reg_desc(struct kvm_vcpu *vcpu, u64 id,
30553107
*/
30563108

30573109
#define FUNCTION_INVARIANT(reg) \
3058-
static void get_##reg(struct kvm_vcpu *v, \
3110+
static u64 get_##reg(struct kvm_vcpu *v, \
30593111
const struct sys_reg_desc *r) \
30603112
{ \
30613113
((struct sys_reg_desc *)r)->val = read_sysreg(reg); \
3114+
return ((struct sys_reg_desc *)r)->val; \
30623115
}
30633116

30643117
FUNCTION_INVARIANT(midr_el1)
30653118
FUNCTION_INVARIANT(revidr_el1)
30663119
FUNCTION_INVARIANT(aidr_el1)
30673120

3068-
static void get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
3121+
static u64 get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
30693122
{
30703123
((struct sys_reg_desc *)r)->val = read_sanitised_ftr_reg(SYS_CTR_EL0);
3124+
return ((struct sys_reg_desc *)r)->val;
30713125
}
30723126

30733127
/* ->val is filled in by kvm_sys_reg_table_init() */

arch/arm64/kvm/sys_regs.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,16 @@ struct sys_reg_desc {
6464
struct sys_reg_params *,
6565
const struct sys_reg_desc *);
6666

67-
/* Initialization for vcpu. */
68-
void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
67+
/*
68+
* Initialization for vcpu. Return initialized value, or KVM
69+
* sanitized value for ID registers.
70+
*/
71+
u64 (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
6972

7073
/* Index into sys_reg[], or 0 if we don't need to save it. */
7174
int reg;
7275

73-
/* Value (usually reset value) */
76+
/* Value (usually reset value), or write mask for idregs */
7477
u64 val;
7578

7679
/* Custom get/set_user functions, fallback to generic if NULL */
@@ -123,19 +126,21 @@ static inline bool read_zero(struct kvm_vcpu *vcpu,
123126
}
124127

125128
/* Reset functions */
126-
static inline void reset_unknown(struct kvm_vcpu *vcpu,
129+
static inline u64 reset_unknown(struct kvm_vcpu *vcpu,
127130
const struct sys_reg_desc *r)
128131
{
129132
BUG_ON(!r->reg);
130133
BUG_ON(r->reg >= NR_SYS_REGS);
131134
__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
135+
return __vcpu_sys_reg(vcpu, r->reg);
132136
}
133137

134-
static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
138+
static inline u64 reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
135139
{
136140
BUG_ON(!r->reg);
137141
BUG_ON(r->reg >= NR_SYS_REGS);
138142
__vcpu_sys_reg(vcpu, r->reg) = r->val;
143+
return __vcpu_sys_reg(vcpu, r->reg);
139144
}
140145

141146
static inline unsigned int sysreg_visibility(const struct kvm_vcpu *vcpu,

0 commit comments

Comments
 (0)