Skip to content

Commit c9dc950

Browse files
author
Marc Zyngier
committed
Merge branch 'kvm-arm64/target-table-no-more' into kvmarm-master/next-WIP
Signed-off-by: Marc Zyngier <[email protected]>
2 parents fc27932 + 750ed56 commit c9dc950

File tree

4 files changed

+56
-227
lines changed

4 files changed

+56
-227
lines changed

arch/arm64/include/asm/kvm_coproc.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ struct kvm_sys_reg_table {
1919
size_t num;
2020
};
2121

22-
struct kvm_sys_reg_target_table {
23-
struct kvm_sys_reg_table table64;
24-
struct kvm_sys_reg_table table32;
25-
};
26-
27-
void kvm_register_target_sys_reg_table(unsigned int target,
28-
struct kvm_sys_reg_target_table *table);
29-
3022
int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
3123
int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
3224
int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);

arch/arm64/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
1414
$(KVM)/vfio.o $(KVM)/irqchip.o \
1515
arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
1616
inject_fault.o regmap.o va_layout.o hyp.o handle_exit.o \
17-
guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o \
17+
guest.o debug.o reset.o sys_regs.o \
1818
vgic-sys-reg-v3.o fpsimd.o pmu.o \
1919
aarch32.o arch_timer.o \
2020
vgic/vgic.o vgic/vgic-init.o \

arch/arm64/kvm/sys_regs.c

Lines changed: 55 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,25 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
244244
return true;
245245
}
246246

247+
static bool access_actlr(struct kvm_vcpu *vcpu,
248+
struct sys_reg_params *p,
249+
const struct sys_reg_desc *r)
250+
{
251+
if (p->is_write)
252+
return ignore_write(vcpu, p);
253+
254+
p->regval = vcpu_read_sys_reg(vcpu, ACTLR_EL1);
255+
256+
if (p->is_aarch32) {
257+
if (r->Op2 & 2)
258+
p->regval = upper_32_bits(p->regval);
259+
else
260+
p->regval = lower_32_bits(p->regval);
261+
}
262+
263+
return true;
264+
}
265+
247266
/*
248267
* Trap handler for the GICv3 SGI generation system register.
249268
* Forward the request to the VGIC emulation.
@@ -617,6 +636,12 @@ static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
617636
vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1);
618637
}
619638

639+
static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
640+
{
641+
u64 actlr = read_sysreg(actlr_el1);
642+
vcpu_write_sys_reg(vcpu, actlr, ACTLR_EL1);
643+
}
644+
620645
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
621646
{
622647
u64 mpidr;
@@ -1520,6 +1545,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
15201545
ID_UNALLOCATED(7,7),
15211546

15221547
{ SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
1548+
{ SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
15231549
{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
15241550
{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
15251551
{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
@@ -1959,6 +1985,8 @@ static const struct sys_reg_desc cp14_64_regs[] = {
19591985
static const struct sys_reg_desc cp15_regs[] = {
19601986
{ Op1( 0), CRn( 0), CRm( 0), Op2( 1), access_ctr },
19611987
{ Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_vm_reg, NULL, c1_SCTLR },
1988+
{ Op1( 0), CRn( 1), CRm( 0), Op2( 1), access_actlr },
1989+
{ Op1( 0), CRn( 1), CRm( 0), Op2( 3), access_actlr },
19621990
{ Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
19631991
{ Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
19641992
{ Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR },
@@ -2111,36 +2139,6 @@ static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
21112139
return 0;
21122140
}
21132141

2114-
/* Target specific emulation tables */
2115-
static struct kvm_sys_reg_target_table *target_tables[KVM_ARM_NUM_TARGETS];
2116-
2117-
void kvm_register_target_sys_reg_table(unsigned int target,
2118-
struct kvm_sys_reg_target_table *table)
2119-
{
2120-
if (check_sysreg_table(table->table64.table, table->table64.num, false) ||
2121-
check_sysreg_table(table->table32.table, table->table32.num, true))
2122-
return;
2123-
2124-
target_tables[target] = table;
2125-
}
2126-
2127-
/* Get specific register table for this target. */
2128-
static const struct sys_reg_desc *get_target_table(unsigned target,
2129-
bool mode_is_64,
2130-
size_t *num)
2131-
{
2132-
struct kvm_sys_reg_target_table *table;
2133-
2134-
table = target_tables[target];
2135-
if (mode_is_64) {
2136-
*num = table->table64.num;
2137-
return table->table64.table;
2138-
} else {
2139-
*num = table->table32.num;
2140-
return table->table32.table;
2141-
}
2142-
}
2143-
21442142
static int match_sys_reg(const void *key, const void *elt)
21452143
{
21462144
const unsigned long pval = (unsigned long)key;
@@ -2251,9 +2249,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
22512249
*/
22522250
static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
22532251
const struct sys_reg_desc *global,
2254-
size_t nr_global,
2255-
const struct sys_reg_desc *target_specific,
2256-
size_t nr_specific)
2252+
size_t nr_global)
22572253
{
22582254
struct sys_reg_params params;
22592255
u32 hsr = kvm_vcpu_get_hsr(vcpu);
@@ -2280,14 +2276,11 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
22802276
}
22812277

22822278
/*
2283-
* Try to emulate the coprocessor access using the target
2284-
* specific table first, and using the global table afterwards.
2285-
* If either of the tables contains a handler, handle the
2279+
* If the table contains a handler, handle the
22862280
* potential register operation in the case of a read and return
22872281
* with success.
22882282
*/
2289-
if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
2290-
!emulate_cp(vcpu, &params, global, nr_global)) {
2283+
if (!emulate_cp(vcpu, &params, global, nr_global)) {
22912284
/* Split up the value between registers for the read side */
22922285
if (!params.is_write) {
22932286
vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval));
@@ -2308,9 +2301,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
23082301
*/
23092302
static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
23102303
const struct sys_reg_desc *global,
2311-
size_t nr_global,
2312-
const struct sys_reg_desc *target_specific,
2313-
size_t nr_specific)
2304+
size_t nr_global)
23142305
{
23152306
struct sys_reg_params params;
23162307
u32 hsr = kvm_vcpu_get_hsr(vcpu);
@@ -2326,8 +2317,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
23262317
params.Op1 = (hsr >> 14) & 0x7;
23272318
params.Op2 = (hsr >> 17) & 0x7;
23282319

2329-
if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
2330-
!emulate_cp(vcpu, &params, global, nr_global)) {
2320+
if (!emulate_cp(vcpu, &params, global, nr_global)) {
23312321
if (!params.is_write)
23322322
vcpu_set_reg(vcpu, Rt, params.regval);
23332323
return 1;
@@ -2339,38 +2329,22 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
23392329

23402330
int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
23412331
{
2342-
const struct sys_reg_desc *target_specific;
2343-
size_t num;
2344-
2345-
target_specific = get_target_table(vcpu->arch.target, false, &num);
2346-
return kvm_handle_cp_64(vcpu,
2347-
cp15_64_regs, ARRAY_SIZE(cp15_64_regs),
2348-
target_specific, num);
2332+
return kvm_handle_cp_64(vcpu, cp15_64_regs, ARRAY_SIZE(cp15_64_regs));
23492333
}
23502334

23512335
int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
23522336
{
2353-
const struct sys_reg_desc *target_specific;
2354-
size_t num;
2355-
2356-
target_specific = get_target_table(vcpu->arch.target, false, &num);
2357-
return kvm_handle_cp_32(vcpu,
2358-
cp15_regs, ARRAY_SIZE(cp15_regs),
2359-
target_specific, num);
2337+
return kvm_handle_cp_32(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
23602338
}
23612339

23622340
int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
23632341
{
2364-
return kvm_handle_cp_64(vcpu,
2365-
cp14_64_regs, ARRAY_SIZE(cp14_64_regs),
2366-
NULL, 0);
2342+
return kvm_handle_cp_64(vcpu, cp14_64_regs, ARRAY_SIZE(cp14_64_regs));
23672343
}
23682344

23692345
int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
23702346
{
2371-
return kvm_handle_cp_32(vcpu,
2372-
cp14_regs, ARRAY_SIZE(cp14_regs),
2373-
NULL, 0);
2347+
return kvm_handle_cp_32(vcpu, cp14_regs, ARRAY_SIZE(cp14_regs));
23742348
}
23752349

23762350
static bool is_imp_def_sys_reg(struct sys_reg_params *params)
@@ -2382,15 +2356,9 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params)
23822356
static int emulate_sys_reg(struct kvm_vcpu *vcpu,
23832357
struct sys_reg_params *params)
23842358
{
2385-
size_t num;
2386-
const struct sys_reg_desc *table, *r;
2387-
2388-
table = get_target_table(vcpu->arch.target, true, &num);
2359+
const struct sys_reg_desc *r;
23892360

2390-
/* Search target-specific then generic table. */
2391-
r = find_reg(params, table, num);
2392-
if (!r)
2393-
r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
2361+
r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
23942362

23952363
if (likely(r)) {
23962364
perform_access(vcpu, params, r);
@@ -2405,14 +2373,20 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
24052373
return 1;
24062374
}
24072375

2408-
static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
2409-
const struct sys_reg_desc *table, size_t num)
2376+
/**
2377+
* kvm_reset_sys_regs - sets system registers to reset value
2378+
* @vcpu: The VCPU pointer
2379+
*
2380+
* This function finds the right table above and sets the registers on the
2381+
* virtual CPU struct to their architecturally defined reset values.
2382+
*/
2383+
void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
24102384
{
24112385
unsigned long i;
24122386

2413-
for (i = 0; i < num; i++)
2414-
if (table[i].reset)
2415-
table[i].reset(vcpu, &table[i]);
2387+
for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++)
2388+
if (sys_reg_descs[i].reset)
2389+
sys_reg_descs[i].reset(vcpu, &sys_reg_descs[i]);
24162390
}
24172391

24182392
/**
@@ -2494,8 +2468,7 @@ const struct sys_reg_desc *find_reg_by_id(u64 id,
24942468
static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
24952469
u64 id)
24962470
{
2497-
size_t num;
2498-
const struct sys_reg_desc *table, *r;
2471+
const struct sys_reg_desc *r;
24992472
struct sys_reg_params params;
25002473

25012474
/* We only do sys_reg for now. */
@@ -2505,10 +2478,7 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
25052478
if (!index_to_params(id, &params))
25062479
return NULL;
25072480

2508-
table = get_target_table(vcpu->arch.target, true, &num);
2509-
r = find_reg(&params, table, num);
2510-
if (!r)
2511-
r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
2481+
r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
25122482

25132483
/* Not saved in the sys_reg array and not otherwise accessible? */
25142484
if (r && !(r->reg || r->get_user))
@@ -2808,35 +2778,17 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
28082778
/* Assumed ordered tables, see kvm_sys_reg_table_init. */
28092779
static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
28102780
{
2811-
const struct sys_reg_desc *i1, *i2, *end1, *end2;
2781+
const struct sys_reg_desc *i2, *end2;
28122782
unsigned int total = 0;
2813-
size_t num;
28142783
int err;
28152784

2816-
/* We check for duplicates here, to allow arch-specific overrides. */
2817-
i1 = get_target_table(vcpu->arch.target, true, &num);
2818-
end1 = i1 + num;
28192785
i2 = sys_reg_descs;
28202786
end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs);
28212787

2822-
BUG_ON(i1 == end1 || i2 == end2);
2823-
2824-
/* Walk carefully, as both tables may refer to the same register. */
2825-
while (i1 || i2) {
2826-
int cmp = cmp_sys_reg(i1, i2);
2827-
/* target-specific overrides generic entry. */
2828-
if (cmp <= 0)
2829-
err = walk_one_sys_reg(vcpu, i1, &uind, &total);
2830-
else
2831-
err = walk_one_sys_reg(vcpu, i2, &uind, &total);
2832-
2788+
while (i2 != end2) {
2789+
err = walk_one_sys_reg(vcpu, i2++, &uind, &total);
28332790
if (err)
28342791
return err;
2835-
2836-
if (cmp <= 0 && ++i1 == end1)
2837-
i1 = NULL;
2838-
if (cmp >= 0 && ++i2 == end2)
2839-
i2 = NULL;
28402792
}
28412793
return total;
28422794
}
@@ -2903,22 +2855,3 @@ void kvm_sys_reg_table_init(void)
29032855
/* Clear all higher bits. */
29042856
cache_levels &= (1 << (i*3))-1;
29052857
}
2906-
2907-
/**
2908-
* kvm_reset_sys_regs - sets system registers to reset value
2909-
* @vcpu: The VCPU pointer
2910-
*
2911-
* This function finds the right table above and sets the registers on the
2912-
* virtual CPU struct to their architecturally defined reset values.
2913-
*/
2914-
void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
2915-
{
2916-
size_t num;
2917-
const struct sys_reg_desc *table;
2918-
2919-
/* Generic chip reset first (so target could override). */
2920-
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
2921-
2922-
table = get_target_table(vcpu->arch.target, true, &num);
2923-
reset_sys_reg_descs(vcpu, table, num);
2924-
}

0 commit comments

Comments
 (0)