Skip to content

Commit

Permalink
KVM: PPC: Book3S: Add support for ibm,int-on/off RTAS calls
Browse files Browse the repository at this point in the history
This adds support for the ibm,int-on and ibm,int-off RTAS calls to the
in-kernel XICS emulation and corrects the handling of the saved
priority by the ibm,set-xive RTAS call.  With this, ibm,int-off sets
the specified interrupt's priority in its saved_priority field and
sets the priority to 0xff (the least favoured value).  ibm,int-on
restores the saved_priority to the priority field, and ibm,set-xive
sets both the priority and the saved_priority to the specified
priority value.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
  • Loading branch information
Paul Mackerras authored and Alexander Graf committed Apr 26, 2013
1 parent 4619ac8 commit d19bd86
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 15 deletions.
2 changes: 2 additions & 0 deletions arch/powerpc/include/asm/kvm_ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ extern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server,
u32 priority);
extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server,
u32 *priority);
extern int kvmppc_xics_int_on(struct kvm *kvm, u32 irq);
extern int kvmppc_xics_int_off(struct kvm *kvm, u32 irq);

/*
* Cuts out inst bits with ordering according to spec.
Expand Down
40 changes: 40 additions & 0 deletions arch/powerpc/kvm/book3s_rtas.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,44 @@ static void kvm_rtas_get_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
out:
args->rets[0] = rc;
}

static void kvm_rtas_int_off(struct kvm_vcpu *vcpu, struct rtas_args *args)
{
u32 irq;
int rc;

if (args->nargs != 1 || args->nret != 1) {
rc = -3;
goto out;
}

irq = args->args[0];

rc = kvmppc_xics_int_off(vcpu->kvm, irq);
if (rc)
rc = -3;
out:
args->rets[0] = rc;
}

static void kvm_rtas_int_on(struct kvm_vcpu *vcpu, struct rtas_args *args)
{
u32 irq;
int rc;

if (args->nargs != 1 || args->nret != 1) {
rc = -3;
goto out;
}

irq = args->args[0];

rc = kvmppc_xics_int_on(vcpu->kvm, irq);
if (rc)
rc = -3;
out:
args->rets[0] = rc;
}
#endif /* CONFIG_KVM_XICS */

struct rtas_handler {
Expand All @@ -74,6 +112,8 @@ static struct rtas_handler rtas_handlers[] = {
#ifdef CONFIG_KVM_XICS
{ .name = "ibm,set-xive", .handler = kvm_rtas_set_xive },
{ .name = "ibm,get-xive", .handler = kvm_rtas_get_xive },
{ .name = "ibm,int-off", .handler = kvm_rtas_int_off },
{ .name = "ibm,int-on", .handler = kvm_rtas_int_on },
#endif
};

Expand Down
84 changes: 70 additions & 14 deletions arch/powerpc/kvm/book3s_xics.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,35 @@ static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
mutex_unlock(&ics->lock);
}

static bool write_xive(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
struct ics_irq_state *state,
u32 server, u32 priority, u32 saved_priority)
{
bool deliver;

mutex_lock(&ics->lock);

state->server = server;
state->priority = priority;
state->saved_priority = saved_priority;
deliver = false;
if ((state->masked_pending || state->resend) && priority != MASKED) {
state->masked_pending = 0;
deliver = true;
}

mutex_unlock(&ics->lock);

return deliver;
}

int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority)
{
struct kvmppc_xics *xics = kvm->arch.xics;
struct kvmppc_icp *icp;
struct kvmppc_ics *ics;
struct ics_irq_state *state;
u16 src;
bool deliver;

if (!xics)
return -ENODEV;
Expand All @@ -144,23 +165,11 @@ int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority)
if (!icp)
return -EINVAL;

mutex_lock(&ics->lock);

XICS_DBG("set_xive %#x server %#x prio %#x MP:%d RS:%d\n",
irq, server, priority,
state->masked_pending, state->resend);

state->server = server;
state->priority = priority;
deliver = false;
if ((state->masked_pending || state->resend) && priority != MASKED) {
state->masked_pending = 0;
deliver = true;
}

mutex_unlock(&ics->lock);

if (deliver)
if (write_xive(xics, ics, state, server, priority, priority))
icp_deliver_irq(xics, icp, irq);

return 0;
Expand Down Expand Up @@ -189,6 +198,53 @@ int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server, u32 *priority)
return 0;
}

int kvmppc_xics_int_on(struct kvm *kvm, u32 irq)
{
struct kvmppc_xics *xics = kvm->arch.xics;
struct kvmppc_icp *icp;
struct kvmppc_ics *ics;
struct ics_irq_state *state;
u16 src;

if (!xics)
return -ENODEV;

ics = kvmppc_xics_find_ics(xics, irq, &src);
if (!ics)
return -EINVAL;
state = &ics->irq_state[src];

icp = kvmppc_xics_find_server(kvm, state->server);
if (!icp)
return -EINVAL;

if (write_xive(xics, ics, state, state->server, state->saved_priority,
state->saved_priority))
icp_deliver_irq(xics, icp, irq);

return 0;
}

int kvmppc_xics_int_off(struct kvm *kvm, u32 irq)
{
struct kvmppc_xics *xics = kvm->arch.xics;
struct kvmppc_ics *ics;
struct ics_irq_state *state;
u16 src;

if (!xics)
return -ENODEV;

ics = kvmppc_xics_find_ics(xics, irq, &src);
if (!ics)
return -EINVAL;
state = &ics->irq_state[src];

write_xive(xics, ics, state, state->server, MASKED, state->priority);

return 0;
}

/* -- ICP routines, including hcalls -- */

static inline bool icp_try_update(struct kvmppc_icp *icp,
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kvm/book3s_xics.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct ics_irq_state {
u32 number;
u32 server;
u8 priority;
u8 saved_priority; /* currently unused */
u8 saved_priority;
u8 resend;
u8 masked_pending;
u8 asserted; /* Only for LSI */
Expand Down

0 comments on commit d19bd86

Please sign in to comment.