Commit c5335f17 authored by Alexander Graf's avatar Alexander Graf Committed by Avi Kivity

KVM: PPC: Implement level interrupts for BookE

BookE also wants to support level based interrupts, so let's implement
all the necessary logic there. We need to trick a bit here because the
irqprios are 1:1 assigned to architecture defined values. But since there
is some space left there, we can just pick a random one and move it later
on - it's internal anyways.
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 7b4203e8
...@@ -131,13 +131,19 @@ void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) ...@@ -131,13 +131,19 @@ void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
struct kvm_interrupt *irq) struct kvm_interrupt *irq)
{ {
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_EXTERNAL); unsigned int prio = BOOKE_IRQPRIO_EXTERNAL;
if (irq->irq == KVM_INTERRUPT_SET_LEVEL)
prio = BOOKE_IRQPRIO_EXTERNAL_LEVEL;
kvmppc_booke_queue_irqprio(vcpu, prio);
} }
void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
struct kvm_interrupt *irq) struct kvm_interrupt *irq)
{ {
clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions);
clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
} }
/* Deliver the interrupt of the corresponding priority, if possible. */ /* Deliver the interrupt of the corresponding priority, if possible. */
...@@ -150,6 +156,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, ...@@ -150,6 +156,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
ulong crit_raw = vcpu->arch.shared->critical; ulong crit_raw = vcpu->arch.shared->critical;
ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
bool crit; bool crit;
bool keep_irq = false;
/* Truncate crit indicators in 32 bit mode */ /* Truncate crit indicators in 32 bit mode */
if (!(vcpu->arch.shared->msr & MSR_SF)) { if (!(vcpu->arch.shared->msr & MSR_SF)) {
...@@ -162,6 +169,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, ...@@ -162,6 +169,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
/* ... and we're in supervisor mode */ /* ... and we're in supervisor mode */
crit = crit && !(vcpu->arch.shared->msr & MSR_PR); crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
if (priority == BOOKE_IRQPRIO_EXTERNAL_LEVEL) {
priority = BOOKE_IRQPRIO_EXTERNAL;
keep_irq = true;
}
switch (priority) { switch (priority) {
case BOOKE_IRQPRIO_DTLB_MISS: case BOOKE_IRQPRIO_DTLB_MISS:
case BOOKE_IRQPRIO_DATA_STORAGE: case BOOKE_IRQPRIO_DATA_STORAGE:
...@@ -214,7 +226,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, ...@@ -214,7 +226,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
vcpu->arch.shared->dar = vcpu->arch.queued_dear; vcpu->arch.shared->dar = vcpu->arch.queued_dear;
kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask); kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions); if (!keep_irq)
clear_bit(priority, &vcpu->arch.pending_exceptions);
} }
return allowed; return allowed;
......
...@@ -46,7 +46,9 @@ ...@@ -46,7 +46,9 @@
#define BOOKE_IRQPRIO_FIT 17 #define BOOKE_IRQPRIO_FIT 17
#define BOOKE_IRQPRIO_DECREMENTER 18 #define BOOKE_IRQPRIO_DECREMENTER 18
#define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 #define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19
#define BOOKE_IRQPRIO_MAX 19 /* Internal pseudo-irqprio for level triggered externals */
#define BOOKE_IRQPRIO_EXTERNAL_LEVEL 20
#define BOOKE_IRQPRIO_MAX 20
extern unsigned long kvmppc_booke_handlers; extern unsigned long kvmppc_booke_handlers;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment