aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv_builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv_builtin.c')
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 275425142bb7..c42aa55b885f 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -22,6 +22,7 @@
22#include <asm/kvm_ppc.h> 22#include <asm/kvm_ppc.h>
23#include <asm/kvm_book3s.h> 23#include <asm/kvm_book3s.h>
24#include <asm/archrandom.h> 24#include <asm/archrandom.h>
25#include <asm/xics.h>
25 26
26#define KVM_CMA_CHUNK_ORDER 18 27#define KVM_CMA_CHUNK_ORDER 18
27 28
@@ -184,3 +185,65 @@ long kvmppc_h_random(struct kvm_vcpu *vcpu)
184 185
185 return H_HARDWARE; 186 return H_HARDWARE;
186} 187}
188
189static inline void rm_writeb(unsigned long paddr, u8 val)
190{
191 __asm__ __volatile__("stbcix %0,0,%1"
192 : : "r" (val), "r" (paddr) : "memory");
193}
194
195/*
196 * Send an interrupt to another CPU.
197 * This can only be called in real mode.
198 * The caller needs to include any barrier needed to order writes
199 * to memory vs. the IPI/message.
200 */
201void kvmhv_rm_send_ipi(int cpu)
202{
203 unsigned long xics_phys;
204
205 /* Poke the target */
206 xics_phys = paca[cpu].kvm_hstate.xics_phys;
207 rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY);
208}
209
210/*
211 * The following functions are called from the assembly code
212 * in book3s_hv_rmhandlers.S.
213 */
214static void kvmhv_interrupt_vcore(struct kvmppc_vcore *vc, int active)
215{
216 int cpu = vc->pcpu;
217
218 /* Order setting of exit map vs. msgsnd/IPI */
219 smp_mb();
220 for (; active; active >>= 1, ++cpu)
221 if (active & 1)
222 kvmhv_rm_send_ipi(cpu);
223}
224
225void kvmhv_commence_exit(int trap)
226{
227 struct kvmppc_vcore *vc = local_paca->kvm_hstate.kvm_vcore;
228 int ptid = local_paca->kvm_hstate.ptid;
229 int me, ee;
230
231 /* Set our bit in the threads-exiting-guest map in the 0xff00
232 bits of vcore->entry_exit_map */
233 me = 0x100 << ptid;
234 do {
235 ee = vc->entry_exit_map;
236 } while (cmpxchg(&vc->entry_exit_map, ee, ee | me) != ee);
237
238 /* Are we the first here? */
239 if ((ee >> 8) != 0)
240 return;
241
242 /*
243 * Trigger the other threads in this vcore to exit the guest.
244 * If this is a hypervisor decrementer interrupt then they
245 * will be already on their way out of the guest.
246 */
247 if (trap != BOOK3S_INTERRUPT_HV_DECREMENTER)
248 kvmhv_interrupt_vcore(vc, ee & ~(1 << ptid));
249}