powerpc/kvm/book3s: Add support for H_IPOLL and H_XIRR_X in XICS emulation
authorPaul Mackerras <paulus@samba.org>
Thu, 23 May 2013 15:42:21 +0000 (15:42 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 31 May 2013 22:29:27 +0000 (08:29 +1000)
This adds the remaining two hypercalls defined by PAPR for manipulating
the XICS interrupt controller, H_IPOLL and H_XIRR_X.  H_IPOLL returns
information about the priority and pending interrupts for a virtual
cpu, without changing any state.  H_XIRR_X is like H_XIRR in that it
reads and acknowledges the highest-priority pending interrupt, but it
also returns the timestamp (timebase register value) from when the
interrupt was first received by the hypervisor.  Currently we just
return the current time, since we don't do any software queueing of
virtual interrupts inside the XICS emulation code.

These hcalls are not currently used by Linux guests, but may be in
future.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/hvcall.h
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/book3s_xics.c

index cf4df8e2139af0a1a0c083ba3ad2618b2efc57c4..0c7f2bfcf1348100fb10c4cd6f74dcee34e42756 100644 (file)
 #define H_GET_MPP              0x2D4
 #define H_HOME_NODE_ASSOCIATIVITY 0x2EC
 #define H_BEST_ENERGY          0x2F4
+#define H_XIRR_X               0x2FC
 #define H_RANDOM               0x300
 #define H_COP                  0x304
 #define H_GET_MPP_X            0x314
index 9de24f8e03c71b44e0407b65bbe137c3506650e3..550f5928b394f6cb4c1da71978031a1ce1f96b79 100644 (file)
@@ -562,6 +562,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        case H_CPPR:
        case H_EOI:
        case H_IPI:
+       case H_IPOLL:
+       case H_XIRR_X:
                if (kvmppc_xics_enabled(vcpu)) {
                        ret = kvmppc_xics_hcall(vcpu, req);
                        break;
index b24309c6c2d507d3f2c008358c3c0728d450a7cd..da0e0bc268bd4bce1322b696dd25972c24bc740e 100644 (file)
@@ -257,6 +257,8 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
        case H_CPPR:
        case H_EOI:
        case H_IPI:
+       case H_IPOLL:
+       case H_XIRR_X:
                if (kvmppc_xics_enabled(vcpu))
                        return kvmppc_h_pr_xics_hcall(vcpu, cmd);
                break;
index f7a103756618e530014d0dc03508a91ff00ded2b..94c1dd46b83d54e98a96c6af3b2e682072f027e6 100644 (file)
@@ -650,6 +650,23 @@ static noinline int kvmppc_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
        return H_SUCCESS;
 }
 
+static int kvmppc_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server)
+{
+       union kvmppc_icp_state state;
+       struct kvmppc_icp *icp;
+
+       icp = vcpu->arch.icp;
+       if (icp->server_num != server) {
+               icp = kvmppc_xics_find_server(vcpu->kvm, server);
+               if (!icp)
+                       return H_PARAMETER;
+       }
+       state = ACCESS_ONCE(icp->state);
+       kvmppc_set_gpr(vcpu, 4, ((u32)state.cppr << 24) | state.xisr);
+       kvmppc_set_gpr(vcpu, 5, state.mfrr);
+       return H_SUCCESS;
+}
+
 static noinline void kvmppc_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
 {
        union kvmppc_icp_state old_state, new_state;
@@ -787,6 +804,18 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
        if (!xics || !vcpu->arch.icp)
                return H_HARDWARE;
 
+       /* These requests don't have real-mode implementations at present */
+       switch (req) {
+       case H_XIRR_X:
+               res = kvmppc_h_xirr(vcpu);
+               kvmppc_set_gpr(vcpu, 4, res);
+               kvmppc_set_gpr(vcpu, 5, get_tb());
+               return rc;
+       case H_IPOLL:
+               rc = kvmppc_h_ipoll(vcpu, kvmppc_get_gpr(vcpu, 4));
+               return rc;
+       }
+
        /* Check for real mode returning too hard */
        if (xics->real_mode)
                return kvmppc_xics_rm_complete(vcpu, req);