Skip to content

Commit bb44a8d

Browse files
author
Marc Zyngier
committed
KVM: arm64: Move sysreg reset check to boot time
Our sysreg reset check has become a bit silly, as it only checks whether a reset callback actually exists for a given sysreg entry, and apply the method if available. Doing the check at each vcpu reset is pretty dumb, as the tables never change. It is thus perfectly possible to do the same checks at boot time. This also allows us to introduce a sparse sys_regs[] array, something that will be required with ARMv8.4-NV. Signed-off-by: Marc Zyngier <[email protected]>
1 parent 7ccadf2 commit bb44a8d

File tree

1 file changed

+35
-37
lines changed

1 file changed

+35
-37
lines changed

arch/arm64/kvm/sys_regs.c

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,12 +2087,37 @@ static const struct sys_reg_desc cp15_64_regs[] = {
20872087
{ SYS_DESC(SYS_AARCH32_CNTP_CVAL), access_arch_timer },
20882088
};
20892089

2090+
static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
2091+
bool is_32)
2092+
{
2093+
unsigned int i;
2094+
2095+
for (i = 0; i < n; i++) {
2096+
if (!is_32 && table[i].reg && !table[i].reset) {
2097+
kvm_err("sys_reg table %p entry %d has lacks reset\n",
2098+
table, i);
2099+
return 1;
2100+
}
2101+
2102+
if (i && cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
2103+
kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1);
2104+
return 1;
2105+
}
2106+
}
2107+
2108+
return 0;
2109+
}
2110+
20902111
/* Target specific emulation tables */
20912112
static struct kvm_sys_reg_target_table *target_tables[KVM_ARM_NUM_TARGETS];
20922113

20932114
void kvm_register_target_sys_reg_table(unsigned int target,
20942115
struct kvm_sys_reg_target_table *table)
20952116
{
2117+
if (check_sysreg_table(table->table64.table, table->table64.num, false) ||
2118+
check_sysreg_table(table->table32.table, table->table32.num, true))
2119+
return;
2120+
20962121
target_tables[target] = table;
20972122
}
20982123

@@ -2378,19 +2403,13 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
23782403
}
23792404

23802405
static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
2381-
const struct sys_reg_desc *table, size_t num,
2382-
unsigned long *bmap)
2406+
const struct sys_reg_desc *table, size_t num)
23832407
{
23842408
unsigned long i;
23852409

23862410
for (i = 0; i < num; i++)
2387-
if (table[i].reset) {
2388-
int reg = table[i].reg;
2389-
2411+
if (table[i].reset)
23902412
table[i].reset(vcpu, &table[i]);
2391-
if (reg > 0 && reg < NR_SYS_REGS)
2392-
set_bit(reg, bmap);
2393-
}
23942413
}
23952414

23962415
/**
@@ -2846,32 +2865,18 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
28462865
return write_demux_regids(uindices);
28472866
}
28482867

2849-
static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n)
2850-
{
2851-
unsigned int i;
2852-
2853-
for (i = 1; i < n; i++) {
2854-
if (cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
2855-
kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1);
2856-
return 1;
2857-
}
2858-
}
2859-
2860-
return 0;
2861-
}
2862-
28632868
void kvm_sys_reg_table_init(void)
28642869
{
28652870
unsigned int i;
28662871
struct sys_reg_desc clidr;
28672872

28682873
/* Make sure tables are unique and in order. */
2869-
BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs)));
2870-
BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs)));
2871-
BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs)));
2872-
BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs)));
2873-
BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs)));
2874-
BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs)));
2874+
BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs), false));
2875+
BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs), true));
2876+
BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs), true));
2877+
BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs), true));
2878+
BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs), true));
2879+
BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs), false));
28752880

28762881
/* We abuse the reset function to overwrite the table itself. */
28772882
for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
@@ -2907,17 +2912,10 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
29072912
{
29082913
size_t num;
29092914
const struct sys_reg_desc *table;
2910-
DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
29112915

29122916
/* Generic chip reset first (so target could override). */
2913-
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
2917+
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
29142918

29152919
table = get_target_table(vcpu->arch.target, true, &num);
2916-
reset_sys_reg_descs(vcpu, table, num, bmap);
2917-
2918-
for (num = 1; num < NR_SYS_REGS; num++) {
2919-
if (WARN(!test_bit(num, bmap),
2920-
"Didn't reset __vcpu_sys_reg(%zi)\n", num))
2921-
break;
2922-
}
2920+
reset_sys_reg_descs(vcpu, table, num);
29232921
}

0 commit comments

Comments
 (0)