mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
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: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
7b4203e8cb
commit
c5335f1765
2 changed files with 18 additions and 3 deletions
|
@ -131,13 +131,19 @@ void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
|
|||
void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
|
||||
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,
|
||||
struct kvm_interrupt *irq)
|
||||
{
|
||||
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. */
|
||||
|
@ -150,6 +156,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
|||
ulong crit_raw = vcpu->arch.shared->critical;
|
||||
ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
|
||||
bool crit;
|
||||
bool keep_irq = false;
|
||||
|
||||
/* Truncate crit indicators in 32 bit mode */
|
||||
if (!(vcpu->arch.shared->msr & MSR_SF)) {
|
||||
|
@ -162,6 +169,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
|||
/* ... and we're in supervisor mode */
|
||||
crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
|
||||
|
||||
if (priority == BOOKE_IRQPRIO_EXTERNAL_LEVEL) {
|
||||
priority = BOOKE_IRQPRIO_EXTERNAL;
|
||||
keep_irq = true;
|
||||
}
|
||||
|
||||
switch (priority) {
|
||||
case BOOKE_IRQPRIO_DTLB_MISS:
|
||||
case BOOKE_IRQPRIO_DATA_STORAGE:
|
||||
|
@ -214,7 +226,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
|||
vcpu->arch.shared->dar = vcpu->arch.queued_dear;
|
||||
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;
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
#define BOOKE_IRQPRIO_FIT 17
|
||||
#define BOOKE_IRQPRIO_DECREMENTER 18
|
||||
#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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue