diff options
author | Anup Patel <anup.patel@linaro.org> | 2014-04-29 01:54:21 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2014-04-30 07:18:58 -0400 |
commit | e6bc13c8a70eabc6a39098ccedf6129c734e3db3 (patch) | |
tree | 7e4cc5c675464156243f3e86a58a0fe9bad4f5bc | |
parent | 4b1238269ed340d59ef829fd9c30a39cfb2923a8 (diff) |
ARM/ARM64: KVM: Emulate PSCI v0.2 AFFINITY_INFO
This patch adds emulation of PSCI v0.2 AFFINITY_INFO function call
for KVM ARM/ARM64. This is a VCPU-level function call which will be
used to determine current state of given affinity level.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r-- | arch/arm/kvm/psci.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 59362131b79f..3b6a0cf25c7d 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c | |||
@@ -27,6 +27,16 @@ | |||
27 | * as described in ARM document number ARM DEN 0022A. | 27 | * as described in ARM document number ARM DEN 0022A. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) | ||
31 | |||
32 | static unsigned long psci_affinity_mask(unsigned long affinity_level) | ||
33 | { | ||
34 | if (affinity_level <= 3) | ||
35 | return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level); | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | |||
30 | static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) | 40 | static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) |
31 | { | 41 | { |
32 | vcpu->arch.pause = true; | 42 | vcpu->arch.pause = true; |
@@ -85,6 +95,42 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) | |||
85 | return PSCI_RET_SUCCESS; | 95 | return PSCI_RET_SUCCESS; |
86 | } | 96 | } |
87 | 97 | ||
98 | static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) | ||
99 | { | ||
100 | int i; | ||
101 | unsigned long mpidr; | ||
102 | unsigned long target_affinity; | ||
103 | unsigned long target_affinity_mask; | ||
104 | unsigned long lowest_affinity_level; | ||
105 | struct kvm *kvm = vcpu->kvm; | ||
106 | struct kvm_vcpu *tmp; | ||
107 | |||
108 | target_affinity = *vcpu_reg(vcpu, 1); | ||
109 | lowest_affinity_level = *vcpu_reg(vcpu, 2); | ||
110 | |||
111 | /* Determine target affinity mask */ | ||
112 | target_affinity_mask = psci_affinity_mask(lowest_affinity_level); | ||
113 | if (!target_affinity_mask) | ||
114 | return PSCI_RET_INVALID_PARAMS; | ||
115 | |||
116 | /* Ignore other bits of target affinity */ | ||
117 | target_affinity &= target_affinity_mask; | ||
118 | |||
119 | /* | ||
120 | * If one or more VCPU matching target affinity are running | ||
121 | * then ON else OFF | ||
122 | */ | ||
123 | kvm_for_each_vcpu(i, tmp, kvm) { | ||
124 | mpidr = kvm_vcpu_get_mpidr(tmp); | ||
125 | if (((mpidr & target_affinity_mask) == target_affinity) && | ||
126 | !tmp->arch.pause) { | ||
127 | return PSCI_0_2_AFFINITY_LEVEL_ON; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return PSCI_0_2_AFFINITY_LEVEL_OFF; | ||
132 | } | ||
133 | |||
88 | static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) | 134 | static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) |
89 | { | 135 | { |
90 | memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); | 136 | memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); |
@@ -132,6 +178,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) | |||
132 | case PSCI_0_2_FN64_CPU_ON: | 178 | case PSCI_0_2_FN64_CPU_ON: |
133 | val = kvm_psci_vcpu_on(vcpu); | 179 | val = kvm_psci_vcpu_on(vcpu); |
134 | break; | 180 | break; |
181 | case PSCI_0_2_FN_AFFINITY_INFO: | ||
182 | case PSCI_0_2_FN64_AFFINITY_INFO: | ||
183 | val = kvm_psci_vcpu_affinity_info(vcpu); | ||
184 | break; | ||
135 | case PSCI_0_2_FN_SYSTEM_OFF: | 185 | case PSCI_0_2_FN_SYSTEM_OFF: |
136 | kvm_psci_system_off(vcpu); | 186 | kvm_psci_system_off(vcpu); |
137 | /* | 187 | /* |
@@ -157,12 +207,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) | |||
157 | ret = 0; | 207 | ret = 0; |
158 | break; | 208 | break; |
159 | case PSCI_0_2_FN_CPU_SUSPEND: | 209 | case PSCI_0_2_FN_CPU_SUSPEND: |
160 | case PSCI_0_2_FN_AFFINITY_INFO: | ||
161 | case PSCI_0_2_FN_MIGRATE: | 210 | case PSCI_0_2_FN_MIGRATE: |
162 | case PSCI_0_2_FN_MIGRATE_INFO_TYPE: | 211 | case PSCI_0_2_FN_MIGRATE_INFO_TYPE: |
163 | case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: | 212 | case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: |
164 | case PSCI_0_2_FN64_CPU_SUSPEND: | 213 | case PSCI_0_2_FN64_CPU_SUSPEND: |
165 | case PSCI_0_2_FN64_AFFINITY_INFO: | ||
166 | case PSCI_0_2_FN64_MIGRATE: | 214 | case PSCI_0_2_FN64_MIGRATE: |
167 | case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: | 215 | case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: |
168 | val = PSCI_RET_NOT_SUPPORTED; | 216 | val = PSCI_RET_NOT_SUPPORTED; |