aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-08-30 08:03:24 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:52:20 -0400
commitc5335f17651de5075313524ccc3881527268966f (patch)
treed81c88bb7ab6af6940d116d0fc31189f2576e21e /arch/powerpc
parent7b4203e8cb5c5d9bc49da62b7a6fa4ba876a1b3f (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.c17
-rw-r--r--arch/powerpc/kvm/booke.h4
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)
131void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, 131void 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
137void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, 142void 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
51extern unsigned long kvmppc_booke_handlers; 53extern unsigned long kvmppc_booke_handlers;
52 54