KVM: PPC: Book3S: Add support for ibm,int-on/off RTAS calls
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>
This commit is contained in:
parent
4619ac88b7
commit
d19bd86204
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -123,6 +123,28 @@ 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;
|
||||
|
@ -130,7 +152,6 @@ int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority)
|
|||
struct kvmppc_ics *ics;
|
||||
struct ics_irq_state *state;
|
||||
u16 src;
|
||||
bool deliver;
|
||||
|
||||
if (!xics)
|
||||
return -ENODEV;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue