aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2013-10-16 08:30:32 -0400
committerGleb Natapov <gleb@redhat.com>2013-10-16 08:30:32 -0400
commitd570142674890fe10b3d7d86aa105e3dfce1ddfa (patch)
tree8a681c3cd9e21400773e24b32f8849d0f25cf4e7
parentf2e106692d5189303997ad7b96de8d8123aa5613 (diff)
parenta7265fb1751ffbfad553afc7f592a6dac6be48de (diff)
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
-rw-r--r--Documentation/virtual/kvm/api.txt31
-rw-r--r--arch/arm/include/asm/kvm_arm.h4
-rw-r--r--arch/arm/include/asm/kvm_asm.h2
-rw-r--r--arch/arm/include/asm/kvm_host.h1
-rw-r--r--arch/arm/include/uapi/asm/kvm.h3
-rw-r--r--arch/arm/kvm/Makefile2
-rw-r--r--arch/arm/kvm/arm.c13
-rw-r--r--arch/arm/kvm/coproc.c114
-rw-r--r--arch/arm/kvm/coproc_a15.c117
-rw-r--r--arch/arm/kvm/coproc_a7.c54
-rw-r--r--arch/arm/kvm/emulate.c2
-rw-r--r--arch/arm/kvm/guest.c24
-rw-r--r--arch/arm/kvm/reset.c15
-rw-r--r--arch/arm64/include/asm/kvm_host.h1
-rw-r--r--arch/arm64/kvm/guest.c20
-rw-r--r--include/uapi/linux/kvm.h1
16 files changed, 270 insertions, 134 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 858aecf21db2..a89a5ee0b940 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2304,7 +2304,31 @@ Possible features:
2304 Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). 2304 Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
2305 2305
2306 2306
23074.83 KVM_GET_REG_LIST 23074.83 KVM_ARM_PREFERRED_TARGET
2308
2309Capability: basic
2310Architectures: arm, arm64
2311Type: vm ioctl
2312Parameters: struct struct kvm_vcpu_init (out)
2313Returns: 0 on success; -1 on error
2314Errors:
2315 ENODEV: no preferred target available for the host
2316
2317This queries KVM for preferred CPU target type which can be emulated
2318by KVM on underlying host.
2319
2320The ioctl returns struct kvm_vcpu_init instance containing information
2321about preferred CPU target type and recommended features for it. The
2322kvm_vcpu_init->features bitmap returned will have feature bits set if
2323the preferred target recommends setting these features, but this is
2324not mandatory.
2325
2326The information returned by this ioctl can be used to prepare an instance
2327of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
2328in VCPU matching underlying host.
2329
2330
23314.84 KVM_GET_REG_LIST
2308 2332
2309Capability: basic 2333Capability: basic
2310Architectures: arm, arm64 2334Architectures: arm, arm64
@@ -2323,8 +2347,7 @@ struct kvm_reg_list {
2323This ioctl returns the guest registers that are supported for the 2347This ioctl returns the guest registers that are supported for the
2324KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 2348KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
2325 2349
2326 23504.85 KVM_ARM_SET_DEVICE_ADDR
23274.84 KVM_ARM_SET_DEVICE_ADDR
2328 2351
2329Capability: KVM_CAP_ARM_SET_DEVICE_ADDR 2352Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
2330Architectures: arm, arm64 2353Architectures: arm, arm64
@@ -2362,7 +2385,7 @@ must be called after calling KVM_CREATE_IRQCHIP, but before calling
2362KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the 2385KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the
2363base addresses will return -EEXIST. 2386base addresses will return -EEXIST.
2364 2387
23654.85 KVM_PPC_RTAS_DEFINE_TOKEN 23884.86 KVM_PPC_RTAS_DEFINE_TOKEN
2366 2389
2367Capability: KVM_CAP_PPC_RTAS 2390Capability: KVM_CAP_PPC_RTAS
2368Architectures: ppc 2391Architectures: ppc
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 64e96960de29..d556f03bca17 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -95,12 +95,12 @@
95#define TTBCR_IRGN1 (3 << 24) 95#define TTBCR_IRGN1 (3 << 24)
96#define TTBCR_EPD1 (1 << 23) 96#define TTBCR_EPD1 (1 << 23)
97#define TTBCR_A1 (1 << 22) 97#define TTBCR_A1 (1 << 22)
98#define TTBCR_T1SZ (3 << 16) 98#define TTBCR_T1SZ (7 << 16)
99#define TTBCR_SH0 (3 << 12) 99#define TTBCR_SH0 (3 << 12)
100#define TTBCR_ORGN0 (3 << 10) 100#define TTBCR_ORGN0 (3 << 10)
101#define TTBCR_IRGN0 (3 << 8) 101#define TTBCR_IRGN0 (3 << 8)
102#define TTBCR_EPD0 (1 << 7) 102#define TTBCR_EPD0 (1 << 7)
103#define TTBCR_T0SZ 3 103#define TTBCR_T0SZ (7 << 0)
104#define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0) 104#define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
105 105
106/* Hyp System Trap Register */ 106/* Hyp System Trap Register */
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index a2f43ddcc300..661da11f76f4 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -39,7 +39,7 @@
39#define c6_IFAR 17 /* Instruction Fault Address Register */ 39#define c6_IFAR 17 /* Instruction Fault Address Register */
40#define c7_PAR 18 /* Physical Address Register */ 40#define c7_PAR 18 /* Physical Address Register */
41#define c7_PAR_high 19 /* PAR top 32 bits */ 41#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 */
43#define c10_PRRR 21 /* Primary Region Remap Register */ 43#define c10_PRRR 21 /* Primary Region Remap Register */
44#define c10_NMRR 22 /* Normal Memory Remap Register */ 44#define c10_NMRR 22 /* Normal Memory Remap Register */
45#define c12_VBAR 23 /* Vector Base Address Register */ 45#define c12_VBAR 23 /* Vector Base Address Register */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index e45a74b62ac1..8a6f6db14ee4 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -149,6 +149,7 @@ struct kvm_vcpu_stat {
149struct kvm_vcpu_init; 149struct kvm_vcpu_init;
150int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, 150int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
151 const struct kvm_vcpu_init *init); 151 const struct kvm_vcpu_init *init);
152int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
152unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); 153unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
153int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); 154int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
154struct kvm_one_reg; 155struct kvm_one_reg;
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index c1ee007523d7..c498b60c0505 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -63,7 +63,8 @@ struct kvm_regs {
63 63
64/* Supported Processor Types */ 64/* Supported Processor Types */
65#define KVM_ARM_TARGET_CORTEX_A15 0 65#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
67 68
68/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */ 69/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
69#define KVM_ARM_DEVICE_TYPE_SHIFT 0 70#define KVM_ARM_DEVICE_TYPE_SHIFT 0
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index d99bee4950e5..789bca9e64a7 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -19,6 +19,6 @@ kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
19 19
20obj-y += kvm-arm.o init.o interrupts.o 20obj-y += kvm-arm.o init.o interrupts.o
21obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o 21obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
22obj-y += coproc.o coproc_a15.o mmio.o psci.o perf.o 22obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
23obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o 23obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
24obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o 24obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9c697db2787e..cc5adb9349ef 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -797,6 +797,19 @@ long kvm_arch_vm_ioctl(struct file *filp,
797 return -EFAULT; 797 return -EFAULT;
798 return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); 798 return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr);
799 } 799 }
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 }
800 default: 813 default:
801 return -EINVAL; 814 return -EINVAL;
802 } 815 }
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index db9cf692d4dd..a629f2c1d0f9 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -71,6 +71,92 @@ int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
71 return 1; 71 return 1;
72} 72}
73 73
74static 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 */
85static 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. */
97static 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 */
107static 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
118static 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
130static 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 */
149static 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
74/* See note at ARM ARM B1.14.4 */ 160/* See note at ARM ARM B1.14.4 */
75static bool access_dcsw(struct kvm_vcpu *vcpu, 161static bool access_dcsw(struct kvm_vcpu *vcpu,
76 const struct coproc_params *p, 162 const struct coproc_params *p,
@@ -153,10 +239,22 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
153 * registers preceding 32-bit ones. 239 * registers preceding 32-bit ones.
154 */ 240 */
155static const struct coproc_reg cp15_regs[] = { 241static 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
156 /* CSSELR: swapped by interrupt.S. */ 246 /* CSSELR: swapped by interrupt.S. */
157 { CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32, 247 { CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32,
158 NULL, reset_unknown, c0_CSSELR }, 248 NULL, reset_unknown, c0_CSSELR },
159 249
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
160 /* TTBR0/TTBR1: swapped by interrupt.S. */ 258 /* TTBR0/TTBR1: swapped by interrupt.S. */
161 { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, 259 { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
162 { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, 260 { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
@@ -195,6 +293,13 @@ static const struct coproc_reg cp15_regs[] = {
195 { CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw}, 293 { CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw},
196 { CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw}, 294 { CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw},
197 /* 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
302 /*
198 * Dummy performance monitor implementation. 303 * Dummy performance monitor implementation.
199 */ 304 */
200 { CRn( 9), CRm(12), Op1( 0), Op2( 0), is32, access_pmcr}, 305 { CRn( 9), CRm(12), Op1( 0), Op2( 0), is32, access_pmcr},
@@ -234,6 +339,9 @@ static const struct coproc_reg cp15_regs[] = {
234 /* CNTKCTL: swapped by interrupt.S. */ 339 /* CNTKCTL: swapped by interrupt.S. */
235 { CRn(14), CRm( 1), Op1( 0), Op2( 0), is32, 340 { CRn(14), CRm( 1), Op1( 0), Op2( 0), is32,
236 NULL, reset_val, c14_CNTKCTL, 0x00000000 }, 341 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},
237}; 345};
238 346
239/* Target specific emulation tables */ 347/* Target specific emulation tables */
@@ -241,6 +349,12 @@ static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS];
241 349
242void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table) 350void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table)
243{ 351{
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
244 target_tables[table->target] = table; 358 target_tables[table->target] = table;
245} 359}
246 360
diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c
index cf93472b9dd6..bb0cac1410cc 100644
--- a/arch/arm/kvm/coproc_a15.c
+++ b/arch/arm/kvm/coproc_a15.c
@@ -17,101 +17,12 @@
17 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */ 18 */
19#include <linux/kvm_host.h> 19#include <linux/kvm_host.h>
20#include <asm/cputype.h>
21#include <asm/kvm_arm.h>
22#include <asm/kvm_host.h>
23#include <asm/kvm_emulate.h>
24#include <asm/kvm_coproc.h> 20#include <asm/kvm_coproc.h>
21#include <asm/kvm_emulate.h>
25#include <linux/init.h> 22#include <linux/init.h>
26 23
27static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
28{
29 /*
30 * Compute guest MPIDR:
31 * (Even if we present only one VCPU to the guest on an SMP
32 * host we don't set the U bit in the MPIDR, or vice versa, as
33 * revealing the underlying hardware properties is likely to
34 * be the best choice).
35 */
36 vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & ~MPIDR_LEVEL_MASK)
37 | (vcpu->vcpu_id & MPIDR_LEVEL_MASK);
38}
39
40#include "coproc.h" 24#include "coproc.h"
41 25
42/* A15 TRM 4.3.28: RO WI */
43static bool access_actlr(struct kvm_vcpu *vcpu,
44 const struct coproc_params *p,
45 const struct coproc_reg *r)
46{
47 if (p->is_write)
48 return ignore_write(vcpu, p);
49
50 *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR];
51 return true;
52}
53
54/* A15 TRM 4.3.60: R/O. */
55static bool access_cbar(struct kvm_vcpu *vcpu,
56 const struct coproc_params *p,
57 const struct coproc_reg *r)
58{
59 if (p->is_write)
60 return write_to_read_only(vcpu, p);
61 return read_zero(vcpu, p);
62}
63
64/* A15 TRM 4.3.48: R/O WI. */
65static bool access_l2ctlr(struct kvm_vcpu *vcpu,
66 const struct coproc_params *p,
67 const struct coproc_reg *r)
68{
69 if (p->is_write)
70 return ignore_write(vcpu, p);
71
72 *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR];
73 return true;
74}
75
76static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
77{
78 u32 l2ctlr, ncores;
79
80 asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
81 l2ctlr &= ~(3 << 24);
82 ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
83 l2ctlr |= (ncores & 3) << 24;
84
85 vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
86}
87
88static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
89{
90 u32 actlr;
91
92 /* ACTLR contains SMP bit: make sure you create all cpus first! */
93 asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
94 /* Make the SMP bit consistent with the guest configuration */
95 if (atomic_read(&vcpu->kvm->online_vcpus) > 1)
96 actlr |= 1U << 6;
97 else
98 actlr &= ~(1U << 6);
99
100 vcpu->arch.cp15[c1_ACTLR] = actlr;
101}
102
103/* A15 TRM 4.3.49: R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored). */
104static bool access_l2ectlr(struct kvm_vcpu *vcpu,
105 const struct coproc_params *p,
106 const struct coproc_reg *r)
107{
108 if (p->is_write)
109 return ignore_write(vcpu, p);
110
111 *vcpu_reg(vcpu, p->Rt1) = 0;
112 return true;
113}
114
115/* 26/*
116 * A15-specific CP15 registers. 27 * A15-specific CP15 registers.
117 * CRn denotes the primary register number, but is copied to the CRm in the 28 * CRn denotes the primary register number, but is copied to the CRm in the
@@ -121,29 +32,9 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
121 * registers preceding 32-bit ones. 32 * registers preceding 32-bit ones.
122 */ 33 */
123static const struct coproc_reg a15_regs[] = { 34static const struct coproc_reg a15_regs[] = {
124 /* MPIDR: we use VMPIDR for guest access. */
125 { CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
126 NULL, reset_mpidr, c0_MPIDR },
127
128 /* SCTLR: swapped by interrupt.S. */ 35 /* SCTLR: swapped by interrupt.S. */
129 { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, 36 { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
130 NULL, reset_val, c1_SCTLR, 0x00C50078 }, 37 NULL, reset_val, c1_SCTLR, 0x00C50078 },
131 /* ACTLR: trapped by HCR.TAC bit. */
132 { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32,
133 access_actlr, reset_actlr, c1_ACTLR },
134 /* CPACR: swapped by interrupt.S. */
135 { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
136 NULL, reset_val, c1_CPACR, 0x00000000 },
137
138 /*
139 * L2CTLR access (guest wants to know #CPUs).
140 */
141 { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32,
142 access_l2ctlr, reset_l2ctlr, c9_L2CTLR },
143 { CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr},
144
145 /* The Configuration Base Address Register. */
146 { CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
147}; 38};
148 39
149static struct kvm_coproc_target_table a15_target_table = { 40static struct kvm_coproc_target_table a15_target_table = {
@@ -154,12 +45,6 @@ static struct kvm_coproc_target_table a15_target_table = {
154 45
155static int __init coproc_a15_init(void) 46static int __init coproc_a15_init(void)
156{ 47{
157 unsigned int i;
158
159 for (i = 1; i < ARRAY_SIZE(a15_regs); i++)
160 BUG_ON(cmp_reg(&a15_regs[i-1],
161 &a15_regs[i]) >= 0);
162
163 kvm_register_target_coproc_table(&a15_target_table); 48 kvm_register_target_coproc_table(&a15_target_table);
164 return 0; 49 return 0;
165} 50}
diff --git a/arch/arm/kvm/coproc_a7.c b/arch/arm/kvm/coproc_a7.c
new file mode 100644
index 000000000000..1df767331588
--- /dev/null
+++ b/arch/arm/kvm/coproc_a7.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Copyright (C) 2013 - ARM Ltd
4 *
5 * Authors: Rusty Russell <rusty@rustcorp.au>
6 * Christoffer Dall <c.dall@virtualopensystems.com>
7 * Jonathan Austin <jonathan.austin@arm.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22#include <linux/kvm_host.h>
23#include <asm/kvm_coproc.h>
24#include <asm/kvm_emulate.h>
25#include <linux/init.h>
26
27#include "coproc.h"
28
29/*
30 * Cortex-A7 specific CP15 registers.
31 * CRn denotes the primary register number, but is copied to the CRm in the
32 * user space API for 64-bit register access in line with the terminology used
33 * in the ARM ARM.
34 * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
35 * registers preceding 32-bit ones.
36 */
37static const struct coproc_reg a7_regs[] = {
38 /* SCTLR: swapped by interrupt.S. */
39 { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
40 NULL, reset_val, c1_SCTLR, 0x00C50878 },
41};
42
43static struct kvm_coproc_target_table a7_target_table = {
44 .target = KVM_ARM_TARGET_CORTEX_A7,
45 .table = a7_regs,
46 .num = ARRAY_SIZE(a7_regs),
47};
48
49static int __init coproc_a7_init(void)
50{
51 kvm_register_target_coproc_table(&a7_target_table);
52 return 0;
53}
54late_initcall(coproc_a7_init);
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index bdede9e7da51..d6c005283678 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -354,7 +354,7 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
354 *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; 354 *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
355 355
356 if (is_pabt) { 356 if (is_pabt) {
357 /* Set DFAR and DFSR */ 357 /* Set IFAR and IFSR */
358 vcpu->arch.cp15[c6_IFAR] = addr; 358 vcpu->arch.cp15[c6_IFAR] = addr;
359 is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31); 359 is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31);
360 /* Always give debug fault for now - should give guest a clue */ 360 /* Always give debug fault for now - should give guest a clue */
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 152d03612181..20f8d97904af 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -190,6 +190,8 @@ int __attribute_const__ kvm_target_cpu(void)
190 return -EINVAL; 190 return -EINVAL;
191 191
192 switch (part_number) { 192 switch (part_number) {
193 case ARM_CPU_PART_CORTEX_A7:
194 return KVM_ARM_TARGET_CORTEX_A7;
193 case ARM_CPU_PART_CORTEX_A15: 195 case ARM_CPU_PART_CORTEX_A15:
194 return KVM_ARM_TARGET_CORTEX_A15; 196 return KVM_ARM_TARGET_CORTEX_A15;
195 default: 197 default:
@@ -202,7 +204,7 @@ int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
202{ 204{
203 unsigned int i; 205 unsigned int i;
204 206
205 /* We can only do a cortex A15 for now. */ 207 /* We can only cope with guest==host and only on A15/A7 (for now). */
206 if (init->target != kvm_target_cpu()) 208 if (init->target != kvm_target_cpu())
207 return -EINVAL; 209 return -EINVAL;
208 210
@@ -222,6 +224,26 @@ int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
222 return kvm_reset_vcpu(vcpu); 224 return kvm_reset_vcpu(vcpu);
223} 225}
224 226
227int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init)
228{
229 int target = kvm_target_cpu();
230
231 if (target < 0)
232 return -ENODEV;
233
234 memset(init, 0, sizeof(*init));
235
236 /*
237 * For now, we don't return any features.
238 * In future, we might use features to return target
239 * specific features available for the preferred
240 * target type.
241 */
242 init->target = (__u32)target;
243
244 return 0;
245}
246
225int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 247int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
226{ 248{
227 return -EINVAL; 249 return -EINVAL;
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index 71e08baee209..d9bbd834f188 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -30,16 +30,16 @@
30#include <kvm/arm_arch_timer.h> 30#include <kvm/arm_arch_timer.h>
31 31
32/****************************************************************************** 32/******************************************************************************
33 * Cortex-A15 Reset Values 33 * Cortex-A15 and Cortex-A7 Reset Values
34 */ 34 */
35 35
36static const int a15_max_cpu_idx = 3; 36static const int cortexa_max_cpu_idx = 3;
37 37
38static struct kvm_regs a15_regs_reset = { 38static struct kvm_regs cortexa_regs_reset = {
39 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT, 39 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
40}; 40};
41 41
42static const struct kvm_irq_level a15_vtimer_irq = { 42static const struct kvm_irq_level cortexa_vtimer_irq = {
43 { .irq = 27 }, 43 { .irq = 27 },
44 .level = 1, 44 .level = 1,
45}; 45};
@@ -62,12 +62,13 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
62 const struct kvm_irq_level *cpu_vtimer_irq; 62 const struct kvm_irq_level *cpu_vtimer_irq;
63 63
64 switch (vcpu->arch.target) { 64 switch (vcpu->arch.target) {
65 case KVM_ARM_TARGET_CORTEX_A7:
65 case KVM_ARM_TARGET_CORTEX_A15: 66 case KVM_ARM_TARGET_CORTEX_A15:
66 if (vcpu->vcpu_id > a15_max_cpu_idx) 67 if (vcpu->vcpu_id > cortexa_max_cpu_idx)
67 return -EINVAL; 68 return -EINVAL;
68 cpu_reset = &a15_regs_reset; 69 cpu_reset = &cortexa_regs_reset;
69 vcpu->arch.midr = read_cpuid_id(); 70 vcpu->arch.midr = read_cpuid_id();
70 cpu_vtimer_irq = &a15_vtimer_irq; 71 cpu_vtimer_irq = &cortexa_vtimer_irq;
71 break; 72 break;
72 default: 73 default:
73 return -ENODEV; 74 return -ENODEV;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 54c064f622aa..5d85a02d1231 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -146,6 +146,7 @@ struct kvm_vcpu_stat {
146struct kvm_vcpu_init; 146struct kvm_vcpu_init;
147int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, 147int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
148 const struct kvm_vcpu_init *init); 148 const struct kvm_vcpu_init *init);
149int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
149unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); 150unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
150int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); 151int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
151struct kvm_one_reg; 152struct kvm_one_reg;
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 2c3ff67a8ecb..3f0731e53274 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -248,6 +248,26 @@ int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
248 return kvm_reset_vcpu(vcpu); 248 return kvm_reset_vcpu(vcpu);
249} 249}
250 250
251int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init)
252{
253 int target = kvm_target_cpu();
254
255 if (target < 0)
256 return -ENODEV;
257
258 memset(init, 0, sizeof(*init));
259
260 /*
261 * For now, we don't return any features.
262 * In future, we might use features to return target
263 * specific features available for the preferred
264 * target type.
265 */
266 init->target = (__u32)target;
267
268 return 0;
269}
270
251int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 271int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
252{ 272{
253 return -EINVAL; 273 return -EINVAL;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 99c25338ede8..e32e776f20c0 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1012,6 +1012,7 @@ struct kvm_s390_ucas_mapping {
1012/* VM is being stopped by host */ 1012/* VM is being stopped by host */
1013#define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad) 1013#define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad)
1014#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init) 1014#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init)
1015#define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init)
1015#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list) 1016#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
1016 1017
1017#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) 1018#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)