diff options
author | Gleb Natapov <gleb@redhat.com> | 2013-10-16 08:30:32 -0400 |
---|---|---|
committer | Gleb Natapov <gleb@redhat.com> | 2013-10-16 08:30:32 -0400 |
commit | d570142674890fe10b3d7d86aa105e3dfce1ddfa (patch) | |
tree | 8a681c3cd9e21400773e24b32f8849d0f25cf4e7 | |
parent | f2e106692d5189303997ad7b96de8d8123aa5613 (diff) | |
parent | a7265fb1751ffbfad553afc7f592a6dac6be48de (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.txt | 31 | ||||
-rw-r--r-- | arch/arm/include/asm/kvm_arm.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/kvm_asm.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/arm/include/uapi/asm/kvm.h | 3 | ||||
-rw-r--r-- | arch/arm/kvm/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 13 | ||||
-rw-r--r-- | arch/arm/kvm/coproc.c | 114 | ||||
-rw-r--r-- | arch/arm/kvm/coproc_a15.c | 117 | ||||
-rw-r--r-- | arch/arm/kvm/coproc_a7.c | 54 | ||||
-rw-r--r-- | arch/arm/kvm/emulate.c | 2 | ||||
-rw-r--r-- | arch/arm/kvm/guest.c | 24 | ||||
-rw-r--r-- | arch/arm/kvm/reset.c | 15 | ||||
-rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/arm64/kvm/guest.c | 20 | ||||
-rw-r--r-- | include/uapi/linux/kvm.h | 1 |
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 | ||
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 | ||
2308 | 2332 | ||
2309 | Capability: basic | 2333 | Capability: basic |
2310 | Architectures: arm, arm64 | 2334 | Architectures: arm, arm64 |
@@ -2323,8 +2347,7 @@ struct kvm_reg_list { | |||
2323 | This ioctl returns the guest registers that are supported for the | 2347 | This ioctl returns the guest registers that are supported for the |
2324 | KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. | 2348 | KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. |
2325 | 2349 | ||
2326 | 2350 | 4.85 KVM_ARM_SET_DEVICE_ADDR | |
2327 | 4.84 KVM_ARM_SET_DEVICE_ADDR | ||
2328 | 2351 | ||
2329 | Capability: KVM_CAP_ARM_SET_DEVICE_ADDR | 2352 | Capability: KVM_CAP_ARM_SET_DEVICE_ADDR |
2330 | Architectures: arm, arm64 | 2353 | Architectures: arm, arm64 |
@@ -2362,7 +2385,7 @@ must be called after calling KVM_CREATE_IRQCHIP, but before calling | |||
2362 | KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the | 2385 | KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the |
2363 | base addresses will return -EEXIST. | 2386 | base addresses will return -EEXIST. |
2364 | 2387 | ||
2365 | 4.85 KVM_PPC_RTAS_DEFINE_TOKEN | 2388 | 4.86 KVM_PPC_RTAS_DEFINE_TOKEN |
2366 | 2389 | ||
2367 | Capability: KVM_CAP_PPC_RTAS | 2390 | Capability: KVM_CAP_PPC_RTAS |
2368 | Architectures: ppc | 2391 | Architectures: 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 { | |||
149 | struct kvm_vcpu_init; | 149 | struct kvm_vcpu_init; |
150 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | 150 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, |
151 | const struct kvm_vcpu_init *init); | 151 | const struct kvm_vcpu_init *init); |
152 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); | ||
152 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); | 153 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); |
153 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); | 154 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); |
154 | struct kvm_one_reg; | 155 | struct 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 | ||
20 | obj-y += kvm-arm.o init.o interrupts.o | 20 | obj-y += kvm-arm.o init.o interrupts.o |
21 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o | 21 | 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 |
23 | obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o | 23 | obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o |
24 | obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o | 24 | obj-$(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 | ||
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 | |||
74 | /* See note at ARM ARM B1.14.4 */ | 160 | /* See note at ARM ARM B1.14.4 */ |
75 | static bool access_dcsw(struct kvm_vcpu *vcpu, | 161 | static 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 | */ |
155 | static const struct coproc_reg cp15_regs[] = { | 241 | 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 | |||
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 | ||
242 | void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table) | 350 | void 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 | ||
27 | static 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 */ | ||
43 | static 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. */ | ||
55 | static 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. */ | ||
65 | static 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 | |||
76 | static 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 | |||
88 | static 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). */ | ||
104 | static 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 | */ |
123 | static const struct coproc_reg a15_regs[] = { | 34 | static 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 | ||
149 | static struct kvm_coproc_target_table a15_target_table = { | 40 | static struct kvm_coproc_target_table a15_target_table = { |
@@ -154,12 +45,6 @@ static struct kvm_coproc_target_table a15_target_table = { | |||
154 | 45 | ||
155 | static int __init coproc_a15_init(void) | 46 | static 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 | */ | ||
37 | static 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 | |||
43 | static 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 | |||
49 | static int __init coproc_a7_init(void) | ||
50 | { | ||
51 | kvm_register_target_coproc_table(&a7_target_table); | ||
52 | return 0; | ||
53 | } | ||
54 | late_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 | ||
227 | int 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 | |||
225 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 247 | int 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 | ||
36 | static const int a15_max_cpu_idx = 3; | 36 | static const int cortexa_max_cpu_idx = 3; |
37 | 37 | ||
38 | static struct kvm_regs a15_regs_reset = { | 38 | static 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 | ||
42 | static const struct kvm_irq_level a15_vtimer_irq = { | 42 | static 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 { | |||
146 | struct kvm_vcpu_init; | 146 | struct kvm_vcpu_init; |
147 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | 147 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, |
148 | const struct kvm_vcpu_init *init); | 148 | const struct kvm_vcpu_init *init); |
149 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); | ||
149 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); | 150 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); |
150 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); | 151 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); |
151 | struct kvm_one_reg; | 152 | struct 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 | ||
251 | int 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 | |||
251 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 271 | int 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) |