diff options
author | Alexander Graf <agraf@suse.de> | 2010-08-30 08:03:24 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:52:20 -0400 |
commit | c5335f17651de5075313524ccc3881527268966f (patch) | |
tree | d81c88bb7ab6af6940d116d0fc31189f2576e21e /arch/powerpc | |
parent | 7b4203e8cb5c5d9bc49da62b7a6fa4ba876a1b3f (diff) |
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kvm/booke.c | 17 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.h | 4 |
2 files changed, 18 insertions, 3 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 835f6d0e4f20..77575d08c818 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -131,13 +131,19 @@ void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) | |||
131 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 131 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, |
132 | struct kvm_interrupt *irq) | 132 | struct kvm_interrupt *irq) |
133 | { | 133 | { |
134 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_EXTERNAL); | 134 | unsigned int prio = BOOKE_IRQPRIO_EXTERNAL; |
135 | |||
136 | if (irq->irq == KVM_INTERRUPT_SET_LEVEL) | ||
137 | prio = BOOKE_IRQPRIO_EXTERNAL_LEVEL; | ||
138 | |||
139 | kvmppc_booke_queue_irqprio(vcpu, prio); | ||
135 | } | 140 | } |
136 | 141 | ||
137 | void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, | 142 | void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, |
138 | struct kvm_interrupt *irq) | 143 | struct kvm_interrupt *irq) |
139 | { | 144 | { |
140 | clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); | 145 | clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); |
146 | clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions); | ||
141 | } | 147 | } |
142 | 148 | ||
143 | /* Deliver the interrupt of the corresponding priority, if possible. */ | 149 | /* Deliver the interrupt of the corresponding priority, if possible. */ |
@@ -150,6 +156,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
150 | ulong crit_raw = vcpu->arch.shared->critical; | 156 | ulong crit_raw = vcpu->arch.shared->critical; |
151 | ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); | 157 | ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); |
152 | bool crit; | 158 | bool crit; |
159 | bool keep_irq = false; | ||
153 | 160 | ||
154 | /* Truncate crit indicators in 32 bit mode */ | 161 | /* Truncate crit indicators in 32 bit mode */ |
155 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | 162 | if (!(vcpu->arch.shared->msr & MSR_SF)) { |
@@ -162,6 +169,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
162 | /* ... and we're in supervisor mode */ | 169 | /* ... and we're in supervisor mode */ |
163 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); | 170 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); |
164 | 171 | ||
172 | if (priority == BOOKE_IRQPRIO_EXTERNAL_LEVEL) { | ||
173 | priority = BOOKE_IRQPRIO_EXTERNAL; | ||
174 | keep_irq = true; | ||
175 | } | ||
176 | |||
165 | switch (priority) { | 177 | switch (priority) { |
166 | case BOOKE_IRQPRIO_DTLB_MISS: | 178 | case BOOKE_IRQPRIO_DTLB_MISS: |
167 | case BOOKE_IRQPRIO_DATA_STORAGE: | 179 | case BOOKE_IRQPRIO_DATA_STORAGE: |
@@ -214,7 +226,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
214 | vcpu->arch.shared->dar = vcpu->arch.queued_dear; | 226 | vcpu->arch.shared->dar = vcpu->arch.queued_dear; |
215 | kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask); | 227 | kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask); |
216 | 228 | ||
217 | clear_bit(priority, &vcpu->arch.pending_exceptions); | 229 | if (!keep_irq) |
230 | clear_bit(priority, &vcpu->arch.pending_exceptions); | ||
218 | } | 231 | } |
219 | 232 | ||
220 | return allowed; | 233 | return allowed; |
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 88258acc98fa..492bb7030358 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h | |||
@@ -46,7 +46,9 @@ | |||
46 | #define BOOKE_IRQPRIO_FIT 17 | 46 | #define BOOKE_IRQPRIO_FIT 17 |
47 | #define BOOKE_IRQPRIO_DECREMENTER 18 | 47 | #define BOOKE_IRQPRIO_DECREMENTER 18 |
48 | #define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 | 48 | #define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 |
49 | #define BOOKE_IRQPRIO_MAX 19 | 49 | /* Internal pseudo-irqprio for level triggered externals */ |
50 | #define BOOKE_IRQPRIO_EXTERNAL_LEVEL 20 | ||
51 | #define BOOKE_IRQPRIO_MAX 20 | ||
50 | 52 | ||
51 | extern unsigned long kvmppc_booke_handlers; | 53 | extern unsigned long kvmppc_booke_handlers; |
52 | 54 | ||