Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: ev_idle hcall support for e500 guests

Signed-off-by: Liu Yu <yu.liu@freescale.com>
[varun: 64-bit changes]
Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>

authored by

Liu Yu-B13201 and committed by
Alexander Graf
2f979de8 9202e076

+44 -6
+6 -5
arch/powerpc/include/asm/epapr_hcalls.h
··· 50 50 #ifndef _EPAPR_HCALLS_H 51 51 #define _EPAPR_HCALLS_H 52 52 53 - #include <linux/types.h> 54 - #include <linux/errno.h> 55 - #include <asm/byteorder.h> 56 - 57 53 #define EV_BYTE_CHANNEL_SEND 1 58 54 #define EV_BYTE_CHANNEL_RECEIVE 2 59 55 #define EV_BYTE_CHANNEL_POLL 3 ··· 104 108 #define EV_INVALID_STATE 11 /* The object is in an invalid state */ 105 109 #define EV_UNIMPLEMENTED 12 /* Unimplemented hypercall */ 106 110 #define EV_BUFFER_OVERFLOW 13 /* Caller-supplied buffer too small */ 111 + 112 + #ifndef __ASSEMBLY__ 113 + #include <linux/types.h> 114 + #include <linux/errno.h> 115 + #include <asm/byteorder.h> 107 116 108 117 /* 109 118 * Hypercall register clobber list ··· 507 506 508 507 return r3; 509 508 } 510 - 509 + #endif /* !__ASSEMBLY__ */ 511 510 #endif
+28
arch/powerpc/kernel/epapr_hcalls.S
··· 8 8 */ 9 9 10 10 #include <linux/threads.h> 11 + #include <asm/epapr_hcalls.h> 11 12 #include <asm/reg.h> 12 13 #include <asm/page.h> 13 14 #include <asm/cputable.h> 14 15 #include <asm/thread_info.h> 15 16 #include <asm/ppc_asm.h> 17 + #include <asm/asm-compat.h> 16 18 #include <asm/asm-offsets.h> 19 + 20 + /* epapr_ev_idle() was derived from e500_idle() */ 21 + _GLOBAL(epapr_ev_idle) 22 + CURRENT_THREAD_INFO(r3, r1) 23 + PPC_LL r4, TI_LOCAL_FLAGS(r3) /* set napping bit */ 24 + ori r4, r4,_TLF_NAPPING /* so when we take an exception */ 25 + PPC_STL r4, TI_LOCAL_FLAGS(r3) /* it will return to our caller */ 26 + 27 + wrteei 1 28 + 29 + idle_loop: 30 + LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE)) 31 + 32 + .global epapr_ev_idle_start 33 + epapr_ev_idle_start: 34 + li r3, -1 35 + nop 36 + nop 37 + nop 38 + 39 + /* 40 + * Guard against spurious wakeups from a hypervisor -- 41 + * only interrupt will cause us to return to LR due to 42 + * _TLF_NAPPING. 43 + */ 44 + b idle_loop 17 45 18 46 /* Hypercall entry point. Will be patched with device tree instructions. */ 19 47 .global epapr_hypercall_start
+10 -1
arch/powerpc/kernel/epapr_paravirt.c
··· 21 21 #include <asm/epapr_hcalls.h> 22 22 #include <asm/cacheflush.h> 23 23 #include <asm/code-patching.h> 24 + #include <asm/machdep.h> 25 + 26 + extern void epapr_ev_idle(void); 27 + extern u32 epapr_ev_idle_start[]; 24 28 25 29 bool epapr_paravirt_enabled; 26 30 ··· 45 41 if (len % 4 || len > (4 * 4)) 46 42 return -ENODEV; 47 43 48 - for (i = 0; i < (len / 4); i++) 44 + for (i = 0; i < (len / 4); i++) { 49 45 patch_instruction(epapr_hypercall_start + i, insts[i]); 46 + patch_instruction(epapr_ev_idle_start + i, insts[i]); 47 + } 48 + 49 + if (of_get_property(hyper_node, "has-idle", NULL)) 50 + ppc_md.power_save = epapr_ev_idle; 50 51 51 52 epapr_paravirt_enabled = true; 52 53