From: Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx> This adds the host portion of the hypercall infrastructure which receives the guest calls - no specific hcall function is implemented in this patch. Hypercall ABI is beat style using sycall+arg. A new kvm exit stat counter for hypercalls is added too. Signed-off-by: Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx> --- [diffstat] arch/powerpc/kvm/booke_guest.c | 11 +++++++++-- arch/powerpc/kvm/booke_interrupts.S | 9 +++++++++ arch/powerpc/kvm/emulate.c | 16 ++++++++++++++++ include/asm-powerpc/kvm_host.h | 1 + include/asm-powerpc/kvm_para.h | 4 ++++ 5 files changed, 39 insertions(+), 2 deletions(-) [diff] diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/fs.h> +#include <linux/kvm_para.h> #include <asm/cputable.h> #include <asm/uaccess.h> #include <asm/kvm_ppc.h> @@ -44,6 +45,7 @@ { "dtlb_r", VCPU_STAT(dtlb_real_miss_exits) }, { "dtlb_v", VCPU_STAT(dtlb_virt_miss_exits) }, { "sysc", VCPU_STAT(syscall_exits) }, + { "hcall", VCPU_STAT(hcall_exits) }, { "isi", VCPU_STAT(isi_exits) }, { "dsi", VCPU_STAT(dsi_exits) }, { "inst_emu", VCPU_STAT(emulated_inst_exits) }, @@ -327,8 +329,13 @@ break; case BOOKE_INTERRUPT_SYSCALL: - kvmppc_queue_exception(vcpu, exit_nr); - vcpu->stat.syscall_exits++; + if (vcpu->arch.last_inst == KVM_HYPERCALL_BIN) { + kvmppc_do_hypercall(vcpu); + vcpu->stat.hcall_exits++; + } else { + kvmppc_queue_exception(vcpu, exit_nr); + vcpu->stat.syscall_exits++; + } r = RESUME_GUEST; break; diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -43,7 +43,10 @@ #define NEED_INST_MASK ((1<<BOOKE_INTERRUPT_PROGRAM) | \ (1<<BOOKE_INTERRUPT_DTLB_MISS) | \ + (1<<BOOKE_INTERRUPT_SYSCALL) | \ (1<<BOOKE_INTERRUPT_DEBUG)) + +#define NEED_PRE_INST_MASK (1<<BOOKE_INTERRUPT_SYSCALL) #define NEED_DEAR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \ (1<<BOOKE_INTERRUPT_DTLB_MISS)) @@ -114,6 +117,12 @@ mfmsr r8 ori r7, r8, MSR_DS mtmsr r7 + + andi. r7, r6, NEED_PRE_INST_MASK + beq ..skip_syscall_srr0pc + subi r9, r9, 4 + +..skip_syscall_srr0pc: isync lwz r9, 0(r9) mtmsr r8 diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -22,6 +22,7 @@ #include <linux/types.h> #include <linux/string.h> #include <linux/kvm_host.h> +#include <linux/kvm_para.h> #include <asm/dcr.h> #include <asm/dcr-regs.h> @@ -201,6 +202,21 @@ { vcpu->arch.pc = vcpu->arch.srr0; kvmppc_set_msr(vcpu, vcpu->arch.srr1); +} + +int kvmppc_do_hypercall(struct kvm_vcpu *vcpu) +{ + u32 ret = 0; + + switch (vcpu->arch.gpr[11]) { + default: + printk(KERN_ERR "unknown hypercall %d\n", vcpu->arch.gpr[11]); + kvmppc_dump_vcpu(vcpu); + ret = -ENOSYS; + } + + vcpu->arch.gpr[3] = ret; + return ret; } /* XXX to do: diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h --- a/include/asm-powerpc/kvm_host.h +++ b/include/asm-powerpc/kvm_host.h @@ -56,6 +56,7 @@ u32 dtlb_real_miss_exits; u32 dtlb_virt_miss_exits; u32 syscall_exits; + u32 hcall_exits; u32 isi_exits; u32 dsi_exits; u32 emulated_inst_exits; diff --git a/include/asm-powerpc/kvm_para.h b/include/asm-powerpc/kvm_para.h --- a/include/asm-powerpc/kvm_para.h +++ b/include/asm-powerpc/kvm_para.h @@ -22,6 +22,8 @@ #ifdef __KERNEL__ +#define KVM_HYPERCALL_BIN 0x44000022 + static inline int kvm_para_available(void) { return 0; @@ -32,6 +34,8 @@ return 0; } +extern int kvmppc_do_hypercall(struct kvm_vcpu *vcpu); + #endif /* __KERNEL__ */ #endif /* __POWERPC_KVM_PARA_H__ */ -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html