Skip to content

Commit d570142

Browse files
author
Gleb Natapov
committed
Merge tag 'kvm-arm-for-3.13-1' of git://git.linaro.org/people/cdall/linux-kvm-arm into next
Updates for KVM/ARM including cpu=host and Cortex-A7 support
2 parents f2e1066 + a7265fb commit d570142

File tree

16 files changed

+270
-134
lines changed

16 files changed

+270
-134
lines changed

Documentation/virtual/kvm/api.txt

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,7 +2304,31 @@ Possible features:
23042304
Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
23052305

23062306

2307-
4.83 KVM_GET_REG_LIST
2307+
4.83 KVM_ARM_PREFERRED_TARGET
2308+
2309+
Capability: basic
2310+
Architectures: arm, arm64
2311+
Type: vm ioctl
2312+
Parameters: struct struct kvm_vcpu_init (out)
2313+
Returns: 0 on success; -1 on error
2314+
Errors:
2315+
ENODEV: no preferred target available for the host
2316+
2317+
This queries KVM for preferred CPU target type which can be emulated
2318+
by KVM on underlying host.
2319+
2320+
The ioctl returns struct kvm_vcpu_init instance containing information
2321+
about preferred CPU target type and recommended features for it. The
2322+
kvm_vcpu_init->features bitmap returned will have feature bits set if
2323+
the preferred target recommends setting these features, but this is
2324+
not mandatory.
2325+
2326+
The information returned by this ioctl can be used to prepare an instance
2327+
of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
2328+
in VCPU matching underlying host.
2329+
2330+
2331+
4.84 KVM_GET_REG_LIST
23082332

23092333
Capability: basic
23102334
Architectures: arm, arm64
@@ -2323,8 +2347,7 @@ struct kvm_reg_list {
23232347
This ioctl returns the guest registers that are supported for the
23242348
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
23252349

2326-
2327-
4.84 KVM_ARM_SET_DEVICE_ADDR
2350+
4.85 KVM_ARM_SET_DEVICE_ADDR
23282351

23292352
Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
23302353
Architectures: arm, arm64
@@ -2362,7 +2385,7 @@ must be called after calling KVM_CREATE_IRQCHIP, but before calling
23622385
KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the
23632386
base addresses will return -EEXIST.
23642387

2365-
4.85 KVM_PPC_RTAS_DEFINE_TOKEN
2388+
4.86 KVM_PPC_RTAS_DEFINE_TOKEN
23662389

23672390
Capability: KVM_CAP_PPC_RTAS
23682391
Architectures: ppc

arch/arm/include/asm/kvm_arm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@
9595
#define TTBCR_IRGN1 (3 << 24)
9696
#define TTBCR_EPD1 (1 << 23)
9797
#define TTBCR_A1 (1 << 22)
98-
#define TTBCR_T1SZ (3 << 16)
98+
#define TTBCR_T1SZ (7 << 16)
9999
#define TTBCR_SH0 (3 << 12)
100100
#define TTBCR_ORGN0 (3 << 10)
101101
#define TTBCR_IRGN0 (3 << 8)
102102
#define TTBCR_EPD0 (1 << 7)
103-
#define TTBCR_T0SZ 3
103+
#define TTBCR_T0SZ (7 << 0)
104104
#define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
105105

106106
/* Hyp System Trap Register */

arch/arm/include/asm/kvm_asm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#define c6_IFAR 17 /* Instruction Fault Address Register */
4040
#define c7_PAR 18 /* Physical Address Register */
4141
#define c7_PAR_high 19 /* PAR top 32 bits */
42-
#define c9_L2CTLR 20 /* Cortex A15 L2 Control Register */
42+
#define c9_L2CTLR 20 /* Cortex A15/A7 L2 Control Register */
4343
#define c10_PRRR 21 /* Primary Region Remap Register */
4444
#define c10_NMRR 22 /* Normal Memory Remap Register */
4545
#define c12_VBAR 23 /* Vector Base Address Register */

arch/arm/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ struct kvm_vcpu_stat {
149149
struct kvm_vcpu_init;
150150
int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
151151
const struct kvm_vcpu_init *init);
152+
int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
152153
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
153154
int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
154155
struct kvm_one_reg;

arch/arm/include/uapi/asm/kvm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ struct kvm_regs {
6363

6464
/* Supported Processor Types */
6565
#define KVM_ARM_TARGET_CORTEX_A15 0
66-
#define KVM_ARM_NUM_TARGETS 1
66+
#define KVM_ARM_TARGET_CORTEX_A7 1
67+
#define KVM_ARM_NUM_TARGETS 2
6768

6869
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
6970
#define KVM_ARM_DEVICE_TYPE_SHIFT 0

arch/arm/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
1919

2020
obj-y += kvm-arm.o init.o interrupts.o
2121
obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
22-
obj-y += coproc.o coproc_a15.o mmio.o psci.o perf.o
22+
obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
2323
obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
2424
obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o

arch/arm/kvm/arm.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,19 @@ long kvm_arch_vm_ioctl(struct file *filp,
797797
return -EFAULT;
798798
return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr);
799799
}
800+
case KVM_ARM_PREFERRED_TARGET: {
801+
int err;
802+
struct kvm_vcpu_init init;
803+
804+
err = kvm_vcpu_preferred_target(&init);
805+
if (err)
806+
return err;
807+
808+
if (copy_to_user(argp, &init, sizeof(init)))
809+
return -EFAULT;
810+
811+
return 0;
812+
}
800813
default:
801814
return -EINVAL;
802815
}

arch/arm/kvm/coproc.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,92 @@ int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
7171
return 1;
7272
}
7373

74+
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
75+
{
76+
/*
77+
* Compute guest MPIDR. No need to mess around with different clusters
78+
* but we read the 'U' bit from the underlying hardware directly.
79+
*/
80+
vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & MPIDR_SMP_BITMASK)
81+
| vcpu->vcpu_id;
82+
}
83+
84+
/* TRM entries A7:4.3.31 A15:4.3.28 - RO WI */
85+
static bool access_actlr(struct kvm_vcpu *vcpu,
86+
const struct coproc_params *p,
87+
const struct coproc_reg *r)
88+
{
89+
if (p->is_write)
90+
return ignore_write(vcpu, p);
91+
92+
*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR];
93+
return true;
94+
}
95+
96+
/* TRM entries A7:4.3.56, A15:4.3.60 - R/O. */
97+
static bool access_cbar(struct kvm_vcpu *vcpu,
98+
const struct coproc_params *p,
99+
const struct coproc_reg *r)
100+
{
101+
if (p->is_write)
102+
return write_to_read_only(vcpu, p);
103+
return read_zero(vcpu, p);
104+
}
105+
106+
/* TRM entries A7:4.3.49, A15:4.3.48 - R/O WI */
107+
static bool access_l2ctlr(struct kvm_vcpu *vcpu,
108+
const struct coproc_params *p,
109+
const struct coproc_reg *r)
110+
{
111+
if (p->is_write)
112+
return ignore_write(vcpu, p);
113+
114+
*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR];
115+
return true;
116+
}
117+
118+
static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
119+
{
120+
u32 l2ctlr, ncores;
121+
122+
asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
123+
l2ctlr &= ~(3 << 24);
124+
ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
125+
l2ctlr |= (ncores & 3) << 24;
126+
127+
vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
128+
}
129+
130+
static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
131+
{
132+
u32 actlr;
133+
134+
/* ACTLR contains SMP bit: make sure you create all cpus first! */
135+
asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
136+
/* Make the SMP bit consistent with the guest configuration */
137+
if (atomic_read(&vcpu->kvm->online_vcpus) > 1)
138+
actlr |= 1U << 6;
139+
else
140+
actlr &= ~(1U << 6);
141+
142+
vcpu->arch.cp15[c1_ACTLR] = actlr;
143+
}
144+
145+
/*
146+
* TRM entries: A7:4.3.50, A15:4.3.49
147+
* R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored).
148+
*/
149+
static bool access_l2ectlr(struct kvm_vcpu *vcpu,
150+
const struct coproc_params *p,
151+
const struct coproc_reg *r)
152+
{
153+
if (p->is_write)
154+
return ignore_write(vcpu, p);
155+
156+
*vcpu_reg(vcpu, p->Rt1) = 0;
157+
return true;
158+
}
159+
74160
/* See note at ARM ARM B1.14.4 */
75161
static bool access_dcsw(struct kvm_vcpu *vcpu,
76162
const struct coproc_params *p,
@@ -153,10 +239,22 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
153239
* registers preceding 32-bit ones.
154240
*/
155241
static const struct coproc_reg cp15_regs[] = {
242+
/* MPIDR: we use VMPIDR for guest access. */
243+
{ CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
244+
NULL, reset_mpidr, c0_MPIDR },
245+
156246
/* CSSELR: swapped by interrupt.S. */
157247
{ CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32,
158248
NULL, reset_unknown, c0_CSSELR },
159249

250+
/* ACTLR: trapped by HCR.TAC bit. */
251+
{ CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32,
252+
access_actlr, reset_actlr, c1_ACTLR },
253+
254+
/* CPACR: swapped by interrupt.S. */
255+
{ CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
256+
NULL, reset_val, c1_CPACR, 0x00000000 },
257+
160258
/* TTBR0/TTBR1: swapped by interrupt.S. */
161259
{ CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
162260
{ CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
@@ -194,6 +292,13 @@ static const struct coproc_reg cp15_regs[] = {
194292
{ CRn( 7), CRm( 6), Op1( 0), Op2( 2), is32, access_dcsw},
195293
{ CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw},
196294
{ CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw},
295+
/*
296+
* L2CTLR access (guest wants to know #CPUs).
297+
*/
298+
{ CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32,
299+
access_l2ctlr, reset_l2ctlr, c9_L2CTLR },
300+
{ CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr},
301+
197302
/*
198303
* Dummy performance monitor implementation.
199304
*/
@@ -234,13 +339,22 @@ static const struct coproc_reg cp15_regs[] = {
234339
/* CNTKCTL: swapped by interrupt.S. */
235340
{ CRn(14), CRm( 1), Op1( 0), Op2( 0), is32,
236341
NULL, reset_val, c14_CNTKCTL, 0x00000000 },
342+
343+
/* The Configuration Base Address Register. */
344+
{ CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
237345
};
238346

239347
/* Target specific emulation tables */
240348
static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS];
241349

242350
void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table)
243351
{
352+
unsigned int i;
353+
354+
for (i = 1; i < table->num; i++)
355+
BUG_ON(cmp_reg(&table->table[i-1],
356+
&table->table[i]) >= 0);
357+
244358
target_tables[table->target] = table;
245359
}
246360

0 commit comments

Comments
 (0)