aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-11-11 05:56:07 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2013-11-11 06:02:27 -0500
commit6da8ae556c11bb3b832dcc0bd077c2d563f5583f (patch)
treea66ef36fe683e8d2c7507cbf62d18e0a6f175193 /arch/arm/kvm
parent1b2ca42267fe8c4e909312f2b83dfef882cf6234 (diff)
parent79c648806f9034abf54332b78043bb242189d953 (diff)
Merge tag 'kvm-arm-for-3.13-3' of git://git.linaro.org/people/cdall/linux-kvm-arm into kvm-next
Updates for KVM/ARM, take 3 supporting more than 4 CPUs. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Conflicts: arch/arm/kvm/reset.c [cpu_reset->reset_regs change; context only]
Diffstat (limited to 'arch/arm/kvm')
-rw-r--r--arch/arm/kvm/coproc.c14
-rw-r--r--arch/arm/kvm/psci.c17
-rw-r--r--arch/arm/kvm/reset.c4
3 files changed, 23 insertions, 12 deletions
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index a629f2c1d0f9..78c0885d6501 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -74,11 +74,13 @@ int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
74static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) 74static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
75{ 75{
76 /* 76 /*
77 * Compute guest MPIDR. No need to mess around with different clusters 77 * Compute guest MPIDR. We build a virtual cluster out of the
78 * but we read the 'U' bit from the underlying hardware directly. 78 * vcpu_id, but we read the 'U' bit from the underlying
79 * hardware directly.
79 */ 80 */
80 vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & MPIDR_SMP_BITMASK) 81 vcpu->arch.cp15[c0_MPIDR] = ((read_cpuid_mpidr() & MPIDR_SMP_BITMASK) |
81 | vcpu->vcpu_id; 82 ((vcpu->vcpu_id >> 2) << MPIDR_LEVEL_BITS) |
83 (vcpu->vcpu_id & 3));
82} 84}
83 85
84/* TRM entries A7:4.3.31 A15:4.3.28 - RO WI */ 86/* TRM entries A7:4.3.31 A15:4.3.28 - RO WI */
@@ -122,6 +124,10 @@ static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
122 asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); 124 asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
123 l2ctlr &= ~(3 << 24); 125 l2ctlr &= ~(3 << 24);
124 ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1; 126 ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
127 /* How many cores in the current cluster and the next ones */
128 ncores -= (vcpu->vcpu_id & ~3);
129 /* Cap it to the maximum number of cores in a single cluster */
130 ncores = min(ncores, 3U);
125 l2ctlr |= (ncores & 3) << 24; 131 l2ctlr |= (ncores & 3) << 24;
126 132
127 vcpu->arch.cp15[c9_L2CTLR] = l2ctlr; 133 vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 86a693a02ba3..311263124acf 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -18,6 +18,7 @@
18#include <linux/kvm_host.h> 18#include <linux/kvm_host.h>
19#include <linux/wait.h> 19#include <linux/wait.h>
20 20
21#include <asm/cputype.h>
21#include <asm/kvm_emulate.h> 22#include <asm/kvm_emulate.h>
22#include <asm/kvm_psci.h> 23#include <asm/kvm_psci.h>
23 24
@@ -34,22 +35,30 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
34static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) 35static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
35{ 36{
36 struct kvm *kvm = source_vcpu->kvm; 37 struct kvm *kvm = source_vcpu->kvm;
37 struct kvm_vcpu *vcpu; 38 struct kvm_vcpu *vcpu = NULL, *tmp;
38 wait_queue_head_t *wq; 39 wait_queue_head_t *wq;
39 unsigned long cpu_id; 40 unsigned long cpu_id;
41 unsigned long mpidr;
40 phys_addr_t target_pc; 42 phys_addr_t target_pc;
43 int i;
41 44
42 cpu_id = *vcpu_reg(source_vcpu, 1); 45 cpu_id = *vcpu_reg(source_vcpu, 1);
43 if (vcpu_mode_is_32bit(source_vcpu)) 46 if (vcpu_mode_is_32bit(source_vcpu))
44 cpu_id &= ~((u32) 0); 47 cpu_id &= ~((u32) 0);
45 48
46 if (cpu_id >= atomic_read(&kvm->online_vcpus)) 49 kvm_for_each_vcpu(i, tmp, kvm) {
50 mpidr = kvm_vcpu_get_mpidr(tmp);
51 if ((mpidr & MPIDR_HWID_BITMASK) == (cpu_id & MPIDR_HWID_BITMASK)) {
52 vcpu = tmp;
53 break;
54 }
55 }
56
57 if (!vcpu)
47 return KVM_PSCI_RET_INVAL; 58 return KVM_PSCI_RET_INVAL;
48 59
49 target_pc = *vcpu_reg(source_vcpu, 2); 60 target_pc = *vcpu_reg(source_vcpu, 2);
50 61
51 vcpu = kvm_get_vcpu(kvm, cpu_id);
52
53 wq = kvm_arch_vcpu_wq(vcpu); 62 wq = kvm_arch_vcpu_wq(vcpu);
54 if (!waitqueue_active(wq)) 63 if (!waitqueue_active(wq))
55 return KVM_PSCI_RET_INVAL; 64 return KVM_PSCI_RET_INVAL;
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index d153e64d1255..f558c073c023 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -33,8 +33,6 @@
33 * Cortex-A15 and Cortex-A7 Reset Values 33 * Cortex-A15 and Cortex-A7 Reset Values
34 */ 34 */
35 35
36static const int cortexa_max_cpu_idx = 3;
37
38static struct kvm_regs cortexa_regs_reset = { 36static struct kvm_regs cortexa_regs_reset = {
39 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT, 37 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
40}; 38};
@@ -64,8 +62,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
64 switch (vcpu->arch.target) { 62 switch (vcpu->arch.target) {
65 case KVM_ARM_TARGET_CORTEX_A7: 63 case KVM_ARM_TARGET_CORTEX_A7:
66 case KVM_ARM_TARGET_CORTEX_A15: 64 case KVM_ARM_TARGET_CORTEX_A15:
67 if (vcpu->vcpu_id > cortexa_max_cpu_idx)
68 return -EINVAL;
69 reset_regs = &cortexa_regs_reset; 65 reset_regs = &cortexa_regs_reset;
70 vcpu->arch.midr = read_cpuid_id(); 66 vcpu->arch.midr = read_cpuid_id();
71 cpu_vtimer_irq = &cortexa_vtimer_irq; 67 cpu_vtimer_irq = &cortexa_vtimer_irq;