* [PATCH 1/3] kvmppc: optimize irq delivery path
@ 2008-10-10 10:59 ehrhardt
2008-10-10 18:07 ` Hollis Blanchard
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: ehrhardt @ 2008-10-10 10:59 UTC (permalink / raw)
To: kvm-ppc
From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
In kvmppc_deliver_interrupt is just one case left in the switch and it is a
rare one (less than 8%) when looking at the exit numbers. Therefore we can
at least drop the switch/case and if an if. I inserted an unlikely too, but
that's open for discussion.
In kvmppc_can_deliver_interrupt all frequent cases are in the default case.
I know compilers are smart but we can make it easier for them. By writing
down all options and removing the default case combined with the fact that
ithe values are constants 0..15 should allow the compiler to write an easy
jump table.
Modifying kvmppc_can_deliver_interrupt pointed me to the fact that gcc seems
to be unable to reduce priority_exception[x] to a build time constant.
Therefore I changed the usage of the translation arrays in the interrupt
delivery path completely. It is now using priority without translation to irq
on the full irq delivery path.
To be able to do that ivpr regs are stored by their priority now.
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
---
[diffstat]
arch/powerpc/kvm/booke_guest.c | 144 +++++++++++++++++------------------------
arch/powerpc/kvm/emulate.c | 64 +++++++++---------
arch/powerpc/kvm/powerpc.c | 5 -
include/asm-powerpc/kvm_asm.h | 18 +++++
include/asm-powerpc/kvm_ppc.h | 9 +-
5 files changed, 117 insertions(+), 123 deletions(-)
[diff]
diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke_guest.c
@@ -73,62 +73,42 @@
#endif
static const u32 interrupt_msr_mask[16] = {
- [BOOKE_INTERRUPT_CRITICAL] = MSR_ME,
- [BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
- [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME,
- [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_DEBUG] = MSR_ME,
+ [BOOKE_INTERRUPT_PRIO_CRITICAL] = MSR_ME,
+ [BOOKE_INTERRUPT_PRIO_MACHINE_CHECK] = 0,
+ [BOOKE_INTERRUPT_PRIO_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_PROGRAM] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_SYSCALL] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_FIT] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_WATCHDOG] = MSR_ME,
+ [BOOKE_INTERRUPT_PRIO_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
+ [BOOKE_INTERRUPT_PRIO_DEBUG] = MSR_ME,
};
-const unsigned char exception_priority[] = {
- [BOOKE_INTERRUPT_DATA_STORAGE] = 0,
- [BOOKE_INTERRUPT_INST_STORAGE] = 1,
- [BOOKE_INTERRUPT_ALIGNMENT] = 2,
- [BOOKE_INTERRUPT_PROGRAM] = 3,
- [BOOKE_INTERRUPT_FP_UNAVAIL] = 4,
- [BOOKE_INTERRUPT_SYSCALL] = 5,
- [BOOKE_INTERRUPT_AP_UNAVAIL] = 6,
- [BOOKE_INTERRUPT_DTLB_MISS] = 7,
- [BOOKE_INTERRUPT_ITLB_MISS] = 8,
- [BOOKE_INTERRUPT_MACHINE_CHECK] = 9,
- [BOOKE_INTERRUPT_DEBUG] = 10,
- [BOOKE_INTERRUPT_CRITICAL] = 11,
- [BOOKE_INTERRUPT_WATCHDOG] = 12,
- [BOOKE_INTERRUPT_EXTERNAL] = 13,
- [BOOKE_INTERRUPT_FIT] = 14,
- [BOOKE_INTERRUPT_DECREMENTER] = 15,
+const unsigned int exception_priority[] = {
+ [BOOKE_INTERRUPT_DATA_STORAGE] = BOOKE_INTERRUPT_PRIO_DATA_STORAGE,
+ [BOOKE_INTERRUPT_INST_STORAGE] = BOOKE_INTERRUPT_PRIO_INST_STORAGE,
+ [BOOKE_INTERRUPT_ALIGNMENT] = BOOKE_INTERRUPT_PRIO_ALIGNMENT,
+ [BOOKE_INTERRUPT_PROGRAM] = BOOKE_INTERRUPT_PRIO_PROGRAM,
+ [BOOKE_INTERRUPT_FP_UNAVAIL] = BOOKE_INTERRUPT_PRIO_FP_UNAVAIL,
+ [BOOKE_INTERRUPT_SYSCALL] = BOOKE_INTERRUPT_PRIO_SYSCALL,
+ [BOOKE_INTERRUPT_AP_UNAVAIL] = BOOKE_INTERRUPT_PRIO_AP_UNAVAIL,
+ [BOOKE_INTERRUPT_DTLB_MISS] = BOOKE_INTERRUPT_PRIO_DTLB_MISS,
+ [BOOKE_INTERRUPT_ITLB_MISS] = BOOKE_INTERRUPT_PRIO_ITLB_MISS,
+ [BOOKE_INTERRUPT_MACHINE_CHECK] = BOOKE_INTERRUPT_PRIO_MACHINE_CHECK,
+ [BOOKE_INTERRUPT_DEBUG] = BOOKE_INTERRUPT_PRIO_DEBUG,
+ [BOOKE_INTERRUPT_CRITICAL] = BOOKE_INTERRUPT_PRIO_CRITICAL,
+ [BOOKE_INTERRUPT_WATCHDOG] = BOOKE_INTERRUPT_PRIO_WATCHDOG,
+ [BOOKE_INTERRUPT_EXTERNAL] = BOOKE_INTERRUPT_PRIO_EXTERNAL,
+ [BOOKE_INTERRUPT_FIT] = BOOKE_INTERRUPT_PRIO_FIT,
+ [BOOKE_INTERRUPT_DECREMENTER] = BOOKE_INTERRUPT_PRIO_DECREMENTER,
};
-
-const unsigned char priority_exception[] = {
- BOOKE_INTERRUPT_DATA_STORAGE,
- BOOKE_INTERRUPT_INST_STORAGE,
- BOOKE_INTERRUPT_ALIGNMENT,
- BOOKE_INTERRUPT_PROGRAM,
- BOOKE_INTERRUPT_FP_UNAVAIL,
- BOOKE_INTERRUPT_SYSCALL,
- BOOKE_INTERRUPT_AP_UNAVAIL,
- BOOKE_INTERRUPT_DTLB_MISS,
- BOOKE_INTERRUPT_ITLB_MISS,
- BOOKE_INTERRUPT_MACHINE_CHECK,
- BOOKE_INTERRUPT_DEBUG,
- BOOKE_INTERRUPT_CRITICAL,
- BOOKE_INTERRUPT_WATCHDOG,
- BOOKE_INTERRUPT_EXTERNAL,
- BOOKE_INTERRUPT_FIT,
- BOOKE_INTERRUPT_DECREMENTER,
-};
-
void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
{
@@ -187,46 +167,46 @@
}
/* Check if we are ready to deliver the interrupt */
-static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+static int kvmppc_can_deliver_interrupt_by_prio(struct kvm_vcpu *vcpu,
+ unsigned int priority)
{
- int r;
+ int r = 0;
- switch (interrupt) {
- case BOOKE_INTERRUPT_CRITICAL:
+ switch (priority) {
+ case BOOKE_INTERRUPT_PRIO_PROGRAM:
+ case BOOKE_INTERRUPT_PRIO_DTLB_MISS:
+ case BOOKE_INTERRUPT_PRIO_ITLB_MISS:
+ case BOOKE_INTERRUPT_PRIO_SYSCALL:
+ case BOOKE_INTERRUPT_PRIO_DATA_STORAGE:
+ case BOOKE_INTERRUPT_PRIO_INST_STORAGE:
+ case BOOKE_INTERRUPT_PRIO_FP_UNAVAIL:
+ r = 1;
+ break;
+ case BOOKE_INTERRUPT_PRIO_CRITICAL:
+ case BOOKE_INTERRUPT_PRIO_WATCHDOG:
r = vcpu->arch.msr & MSR_CE;
break;
- case BOOKE_INTERRUPT_MACHINE_CHECK:
+ case BOOKE_INTERRUPT_PRIO_MACHINE_CHECK:
r = vcpu->arch.msr & MSR_ME;
break;
- case BOOKE_INTERRUPT_EXTERNAL:
+ case BOOKE_INTERRUPT_PRIO_EXTERNAL:
+ case BOOKE_INTERRUPT_PRIO_DECREMENTER:
+ case BOOKE_INTERRUPT_PRIO_FIT:
r = vcpu->arch.msr & MSR_EE;
break;
- case BOOKE_INTERRUPT_DECREMENTER:
- r = vcpu->arch.msr & MSR_EE;
- break;
- case BOOKE_INTERRUPT_FIT:
- r = vcpu->arch.msr & MSR_EE;
- break;
- case BOOKE_INTERRUPT_WATCHDOG:
- r = vcpu->arch.msr & MSR_CE;
- break;
- case BOOKE_INTERRUPT_DEBUG:
+ case BOOKE_INTERRUPT_PRIO_DEBUG:
r = vcpu->arch.msr & MSR_DE;
break;
- default:
- r = 1;
}
return r;
}
-static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+static void kvmppc_deliver_interrupt_by_prio(struct kvm_vcpu *vcpu,
+ unsigned int priority)
{
- switch (interrupt) {
- case BOOKE_INTERRUPT_DECREMENTER:
+ if (unlikely(priority = BOOKE_INTERRUPT_PRIO_DECREMENTER))
vcpu->arch.tsr |= TSR_DIS;
- break;
- }
if (kvmppc_has_pvmem(vcpu)) {
kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_SRR0, vcpu->arch.pc);
@@ -239,23 +219,21 @@
vcpu->arch.srr1 = vcpu->arch.msr;
}
- vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt];
- kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]);
+ vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
+ kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[priority]);
}
/* Check pending exceptions and deliver one, if possible. */
void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
{
unsigned long *pending = &vcpu->arch.pending_exceptions;
- unsigned int exception;
unsigned int priority;
priority = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending));
while (priority <= BOOKE_MAX_INTERRUPT) {
- exception = priority_exception[priority];
- if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
- kvmppc_clear_exception(vcpu, exception);
- kvmppc_deliver_interrupt(vcpu, exception);
+ if (kvmppc_can_deliver_interrupt_by_prio(vcpu, priority)) {
+ kvmppc_clear_exception_by_prio(pending, priority);
+ kvmppc_deliver_interrupt_by_prio(vcpu, priority);
break;
}
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -789,37 +789,37 @@
* a trap. */
case SPRN_IVOR0:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_CRITICAL]; break;
case SPRN_IVOR1:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_MACHINE_CHECK]; break;
case SPRN_IVOR2:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DATA_STORAGE]; break;
case SPRN_IVOR3:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_INST_STORAGE]; break;
case SPRN_IVOR4:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_EXTERNAL]; break;
case SPRN_IVOR5:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_ALIGNMENT]; break;
case SPRN_IVOR6:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_PROGRAM]; break;
case SPRN_IVOR7:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_FP_UNAVAIL]; break;
case SPRN_IVOR8:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_SYSCALL]; break;
case SPRN_IVOR9:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_AP_UNAVAIL]; break;
case SPRN_IVOR10:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DECREMENTER]; break;
case SPRN_IVOR11:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_FIT]; break;
case SPRN_IVOR12:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_WATCHDOG]; break;
case SPRN_IVOR13:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DTLB_MISS]; break;
case SPRN_IVOR14:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_ITLB_MISS]; break;
case SPRN_IVOR15:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DEBUG]; break;
default:
printk("mfspr: unknown spr %x\n", sprn);
@@ -955,37 +955,37 @@
case SPRN_IVPR:
vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR0:
- vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_CRITICAL] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR1:
- vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR2:
- vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DATA_STORAGE] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR3:
- vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_INST_STORAGE] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR4:
- vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_EXTERNAL] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR5:
- vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_ALIGNMENT] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR6:
- vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_PROGRAM] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR7:
- vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR8:
- vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_SYSCALL] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR9:
- vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR10:
- vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DECREMENTER] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR11:
- vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_FIT] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR12:
- vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_WATCHDOG] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR13:
- vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DTLB_MISS] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR14:
- vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_ITLB_MISS] = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR15:
- vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_INTERRUPT_PRIO_DEBUG] = vcpu->arch.gpr[rs]; break;
default:
printk("mtspr: unknown spr %x\n", sprn);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -222,9 +222,8 @@
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
- unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
-
- return test_bit(priority, &vcpu->arch.pending_exceptions);
+ return test_bit(BOOKE_INTERRUPT_PRIO_DECREMENTER,
+ &vcpu->arch.pending_exceptions);
}
static void kvmppc_decrementer_func(unsigned long data)
diff --git a/include/asm-powerpc/kvm_asm.h b/include/asm-powerpc/kvm_asm.h
--- a/include/asm-powerpc/kvm_asm.h
+++ b/include/asm-powerpc/kvm_asm.h
@@ -44,6 +44,24 @@
#define BOOKE_INTERRUPT_DEBUG 15
#define BOOKE_MAX_INTERRUPT 15
+/* interrupt priortity ordering */
+#define BOOKE_INTERRUPT_PRIO_DATA_STORAGE 0
+#define BOOKE_INTERRUPT_PRIO_INST_STORAGE 1
+#define BOOKE_INTERRUPT_PRIO_ALIGNMENT 2
+#define BOOKE_INTERRUPT_PRIO_PROGRAM 3
+#define BOOKE_INTERRUPT_PRIO_FP_UNAVAIL 4
+#define BOOKE_INTERRUPT_PRIO_SYSCALL 5
+#define BOOKE_INTERRUPT_PRIO_AP_UNAVAIL 6
+#define BOOKE_INTERRUPT_PRIO_DTLB_MISS 7
+#define BOOKE_INTERRUPT_PRIO_ITLB_MISS 8
+#define BOOKE_INTERRUPT_PRIO_MACHINE_CHECK 9
+#define BOOKE_INTERRUPT_PRIO_DEBUG 10
+#define BOOKE_INTERRUPT_PRIO_CRITICAL 11
+#define BOOKE_INTERRUPT_PRIO_WATCHDOG 12
+#define BOOKE_INTERRUPT_PRIO_EXTERNAL 13
+#define BOOKE_INTERRUPT_PRIO_FIT 14
+#define BOOKE_INTERRUPT_PRIO_DECREMENTER 15
+
#define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */
#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h
--- a/include/asm-powerpc/kvm_ppc.h
+++ b/include/asm-powerpc/kvm_ppc.h
@@ -42,8 +42,7 @@
EMULATE_FAIL, /* can't emulate this instruction */
};
-extern const unsigned char exception_priority[];
-extern const unsigned char priority_exception[];
+extern const unsigned int exception_priority[];
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern char kvmppc_handlers_start[];
@@ -75,10 +74,10 @@
set_bit(priority, &vcpu->arch.pending_exceptions);
}
-static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception)
+static inline void kvmppc_clear_exception_by_prio(unsigned long *pending,
+ unsigned int priority)
{
- unsigned int priority = exception_priority[exception];
- clear_bit(priority, &vcpu->arch.pending_exceptions);
+ clear_bit(priority, pending);
}
/* Helper function for "full" MSR writes. No need to call this if only EE is
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH 1/3] kvmppc: optimize irq delivery path
2008-10-10 10:59 [PATCH 1/3] kvmppc: optimize irq delivery path ehrhardt
@ 2008-10-10 18:07 ` Hollis Blanchard
2008-10-13 6:22 ` Christian Ehrhardt
2008-10-13 12:07 ` ehrhardt
2 siblings, 0 replies; 4+ messages in thread
From: Hollis Blanchard @ 2008-10-10 18:07 UTC (permalink / raw)
To: kvm-ppc
On Fri, 2008-10-10 at 12:59 +0200, ehrhardt@linux.vnet.ibm.com wrote:
> From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
>
> In kvmppc_deliver_interrupt is just one case left in the switch and it is a
> rare one (less than 8%) when looking at the exit numbers. Therefore we can
> at least drop the switch/case and if an if. I inserted an unlikely too, but
> that's open for discussion.
>
> In kvmppc_can_deliver_interrupt all frequent cases are in the default case.
> I know compilers are smart but we can make it easier for them. By writing
> down all options and removing the default case combined with the fact that
> ithe values are constants 0..15 should allow the compiler to write an easy
> jump table.
> Modifying kvmppc_can_deliver_interrupt pointed me to the fact that gcc seems
> to be unable to reduce priority_exception[x] to a build time constant.
> Therefore I changed the usage of the translation arrays in the interrupt
> delivery path completely. It is now using priority without translation to irq
> on the full irq delivery path.
> To be able to do that ivpr regs are stored by their priority now.
I like this, but a few notes:
Why did you convert exception_priority[] to int? AFAICS it still only
holds values 0-15, and using chars would shrink it from 2 32-byte
cachelines (3 unaligned) to half of one.
It looks like you applied this on top of the pvmem patches. I guess the
performance benefit is significant enough to apply those, but I'll have
to find the patches again.
I think the IVOR emulation has gotten wide enough that you can add some
newlines.
AFAICS the *_PRIO constants aren't used in assembly, so do they need to
go into kvm_asm.h?
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/3] kvmppc: optimize irq delivery path
2008-10-10 10:59 [PATCH 1/3] kvmppc: optimize irq delivery path ehrhardt
2008-10-10 18:07 ` Hollis Blanchard
@ 2008-10-13 6:22 ` Christian Ehrhardt
2008-10-13 12:07 ` ehrhardt
2 siblings, 0 replies; 4+ messages in thread
From: Christian Ehrhardt @ 2008-10-13 6:22 UTC (permalink / raw)
To: kvm-ppc
Hollis Blanchard wrote:
> On Fri, 2008-10-10 at 12:59 +0200, ehrhardt@linux.vnet.ibm.com wrote:
>
>> From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
>>
>> In kvmppc_deliver_interrupt is just one case left in the switch and it is a
>> rare one (less than 8%) when looking at the exit numbers. Therefore we can
>> at least drop the switch/case and if an if. I inserted an unlikely too, but
>> that's open for discussion.
>>
>> In kvmppc_can_deliver_interrupt all frequent cases are in the default case.
>> I know compilers are smart but we can make it easier for them. By writing
>> down all options and removing the default case combined with the fact that
>> ithe values are constants 0..15 should allow the compiler to write an easy
>> jump table.
>> Modifying kvmppc_can_deliver_interrupt pointed me to the fact that gcc seems
>> to be unable to reduce priority_exception[x] to a build time constant.
>> Therefore I changed the usage of the translation arrays in the interrupt
>> delivery path completely. It is now using priority without translation to irq
>> on the full irq delivery path.
>> To be able to do that ivpr regs are stored by their priority now.
>>
>
> I like this, but a few notes:
>
> Why did you convert exception_priority[] to int? AFAICS it still only
> holds values 0-15, and using chars would shrink it from 2 32-byte
> cachelines (3 unaligned) to half of one.
>
Your right, I changed it while modifying the code to match the type used
to call functions for a test and forgot to revert it.
Will be changed in v2.
> It looks like you applied this on top of the pvmem patches. I guess the
> performance benefit is significant enough to apply those, but I'll have
> to find the patches again.
>
I can rebase them to bring them in pre pvmem, no need you do that work.
This also fixed the dependencies to e.g. the exit timing patches.
Applying pv patches too would be nice, we can talk this week about that
more in detail (if/when/how to do it).
> I think the IVOR emulation has gotten wide enough that you can add some
> newlines.
>
I need to run checkpatch once more on the current version anyway - I
just wanted to put that out for discussion on friday, thats why I missed
those 80+ lines :-/
> AFAICS the *_PRIO constants aren't used in assembly, so do they need to
> go into kvm_asm.h?
>
I wanted to place them near the non _PRIO irq constants, not needed for
the code but nice to understand the code.
But your right, officially I think they should stay in asm/kvm_ppc.h - I
can relocate them in v2 of the patches.
--
Grüsse / regards,
Christian Ehrhardt
IBM Linux Technology Center, Open Virtualization
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] kvmppc: optimize irq delivery path
2008-10-10 10:59 [PATCH 1/3] kvmppc: optimize irq delivery path ehrhardt
2008-10-10 18:07 ` Hollis Blanchard
2008-10-13 6:22 ` Christian Ehrhardt
@ 2008-10-13 12:07 ` ehrhardt
2 siblings, 0 replies; 4+ messages in thread
From: ehrhardt @ 2008-10-13 12:07 UTC (permalink / raw)
To: kvm-ppc
From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
In kvmppc_deliver_interrupt is just one case left in the switch and it is a
rare one (less than 8%) when looking at the exit numbers. Therefore we can
at least drop the switch/case and if an if. I inserted an unlikely too, but
that's open for discussion.
In kvmppc_can_deliver_interrupt all frequent cases are in the default case.
I know compilers are smart but we can make it easier for them. By writing
down all options and removing the default case combined with the fact that
ithe values are constants 0..15 should allow the compiler to write an easy
jump table.
Modifying kvmppc_can_deliver_interrupt pointed me to the fact that gcc seems
to be unable to reduce priority_exception[x] to a build time constant.
Therefore I changed the usage of the translation arrays in the interrupt
delivery path completely. It is now using priority without translation to irq
on the full irq delivery path.
To be able to do that ivpr regs are stored by their priority now.
Additionally the decision made in kvmppc_can_deliver_interrupt is already
sufficient to get the value of interrupt_msr_mask[x]. Therefore we can replace
the 16x4byte array used here with a single 4byte variable (might still be one
miss, but the chance to find this in cache should be better than the right
entry of the whole array).
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
---
[diffstat]
arch/powerpc/kvm/booke_guest.c | 153 ++++++++++++++++-------------------------
arch/powerpc/kvm/emulate.c | 128 +++++++++++++++++++++++++---------
arch/powerpc/kvm/powerpc.c | 5 -
include/asm-powerpc/kvm_ppc.h | 25 +++++-
4 files changed, 180 insertions(+), 131 deletions(-)
[diff]
diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke_guest.c
@@ -53,63 +53,24 @@
{ NULL }
};
-static const u32 interrupt_msr_mask[16] = {
- [BOOKE_INTERRUPT_CRITICAL] = MSR_ME,
- [BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
- [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME,
- [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_DEBUG] = MSR_ME,
+const unsigned char exception_priority[] = {
+ [BOOKE_INTERRUPT_DATA_STORAGE] = BOOKE_IRQPRIO_DATA_STORAGE,
+ [BOOKE_INTERRUPT_INST_STORAGE] = BOOKE_IRQPRIO_INST_STORAGE,
+ [BOOKE_INTERRUPT_ALIGNMENT] = BOOKE_IRQPRIO_ALIGNMENT,
+ [BOOKE_INTERRUPT_PROGRAM] = BOOKE_IRQPRIO_PROGRAM,
+ [BOOKE_INTERRUPT_FP_UNAVAIL] = BOOKE_IRQPRIO_FP_UNAVAIL,
+ [BOOKE_INTERRUPT_SYSCALL] = BOOKE_IRQPRIO_SYSCALL,
+ [BOOKE_INTERRUPT_AP_UNAVAIL] = BOOKE_IRQPRIO_AP_UNAVAIL,
+ [BOOKE_INTERRUPT_DTLB_MISS] = BOOKE_IRQPRIO_DTLB_MISS,
+ [BOOKE_INTERRUPT_ITLB_MISS] = BOOKE_IRQPRIO_ITLB_MISS,
+ [BOOKE_INTERRUPT_MACHINE_CHECK] = BOOKE_IRQPRIO_MACHINE_CHECK,
+ [BOOKE_INTERRUPT_DEBUG] = BOOKE_IRQPRIO_DEBUG,
+ [BOOKE_INTERRUPT_CRITICAL] = BOOKE_IRQPRIO_CRITICAL,
+ [BOOKE_INTERRUPT_WATCHDOG] = BOOKE_IRQPRIO_WATCHDOG,
+ [BOOKE_INTERRUPT_EXTERNAL] = BOOKE_IRQPRIO_EXTERNAL,
+ [BOOKE_INTERRUPT_FIT] = BOOKE_IRQPRIO_FIT,
+ [BOOKE_INTERRUPT_DECREMENTER] = BOOKE_IRQPRIO_DECREMENTER,
};
-
-const unsigned char exception_priority[] = {
- [BOOKE_INTERRUPT_DATA_STORAGE] = 0,
- [BOOKE_INTERRUPT_INST_STORAGE] = 1,
- [BOOKE_INTERRUPT_ALIGNMENT] = 2,
- [BOOKE_INTERRUPT_PROGRAM] = 3,
- [BOOKE_INTERRUPT_FP_UNAVAIL] = 4,
- [BOOKE_INTERRUPT_SYSCALL] = 5,
- [BOOKE_INTERRUPT_AP_UNAVAIL] = 6,
- [BOOKE_INTERRUPT_DTLB_MISS] = 7,
- [BOOKE_INTERRUPT_ITLB_MISS] = 8,
- [BOOKE_INTERRUPT_MACHINE_CHECK] = 9,
- [BOOKE_INTERRUPT_DEBUG] = 10,
- [BOOKE_INTERRUPT_CRITICAL] = 11,
- [BOOKE_INTERRUPT_WATCHDOG] = 12,
- [BOOKE_INTERRUPT_EXTERNAL] = 13,
- [BOOKE_INTERRUPT_FIT] = 14,
- [BOOKE_INTERRUPT_DECREMENTER] = 15,
-};
-
-const unsigned char priority_exception[] = {
- BOOKE_INTERRUPT_DATA_STORAGE,
- BOOKE_INTERRUPT_INST_STORAGE,
- BOOKE_INTERRUPT_ALIGNMENT,
- BOOKE_INTERRUPT_PROGRAM,
- BOOKE_INTERRUPT_FP_UNAVAIL,
- BOOKE_INTERRUPT_SYSCALL,
- BOOKE_INTERRUPT_AP_UNAVAIL,
- BOOKE_INTERRUPT_DTLB_MISS,
- BOOKE_INTERRUPT_ITLB_MISS,
- BOOKE_INTERRUPT_MACHINE_CHECK,
- BOOKE_INTERRUPT_DEBUG,
- BOOKE_INTERRUPT_CRITICAL,
- BOOKE_INTERRUPT_WATCHDOG,
- BOOKE_INTERRUPT_EXTERNAL,
- BOOKE_INTERRUPT_FIT,
- BOOKE_INTERRUPT_DECREMENTER,
-};
-
void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
{
@@ -158,72 +119,80 @@
}
/* Check if we are ready to deliver the interrupt */
-static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+static inline int kvmppc_can_deliver_interrupt_by_prio(struct kvm_vcpu *vcpu,
+ unsigned int priority,
+ u32 *mask)
{
- int r;
+ int r = 0;
- switch (interrupt) {
- case BOOKE_INTERRUPT_CRITICAL:
+ switch (priority) {
+ case BOOKE_IRQPRIO_PROGRAM:
+ case BOOKE_IRQPRIO_DTLB_MISS:
+ case BOOKE_IRQPRIO_ITLB_MISS:
+ case BOOKE_IRQPRIO_SYSCALL:
+ case BOOKE_IRQPRIO_DATA_STORAGE:
+ case BOOKE_IRQPRIO_INST_STORAGE:
+ case BOOKE_IRQPRIO_FP_UNAVAIL:
+ case BOOKE_IRQPRIO_AP_UNAVAIL:
+ case BOOKE_IRQPRIO_ALIGNMENT:
+ r = 1;
+ *mask = MSR_CE|MSR_ME|MSR_DE;
+ break;
+ case BOOKE_IRQPRIO_CRITICAL:
+ case BOOKE_IRQPRIO_WATCHDOG:
r = vcpu->arch.msr & MSR_CE;
+ *mask = MSR_ME;
break;
- case BOOKE_INTERRUPT_MACHINE_CHECK:
+ case BOOKE_IRQPRIO_MACHINE_CHECK:
r = vcpu->arch.msr & MSR_ME;
+ *mask = 0;
break;
- case BOOKE_INTERRUPT_EXTERNAL:
+ case BOOKE_IRQPRIO_EXTERNAL:
+ case BOOKE_IRQPRIO_DECREMENTER:
+ case BOOKE_IRQPRIO_FIT:
r = vcpu->arch.msr & MSR_EE;
+ *mask = MSR_CE|MSR_ME|MSR_DE;
break;
- case BOOKE_INTERRUPT_DECREMENTER:
- r = vcpu->arch.msr & MSR_EE;
+ case BOOKE_IRQPRIO_DEBUG:
+ r = vcpu->arch.msr & MSR_DE;
+ *mask = MSR_ME;
break;
- case BOOKE_INTERRUPT_FIT:
- r = vcpu->arch.msr & MSR_EE;
- break;
- case BOOKE_INTERRUPT_WATCHDOG:
- r = vcpu->arch.msr & MSR_CE;
- break;
- case BOOKE_INTERRUPT_DEBUG:
- r = vcpu->arch.msr & MSR_DE;
- break;
- default:
- r = 1;
}
return r;
}
-static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+static inline void kvmppc_deliver_interrupt_by_prio(struct kvm_vcpu *vcpu,
+ unsigned int priority,
+ u32 mask)
{
- switch (interrupt) {
- case BOOKE_INTERRUPT_DECREMENTER:
+ if (unlikely(priority = BOOKE_IRQPRIO_DECREMENTER))
vcpu->arch.tsr |= TSR_DIS;
- break;
- }
vcpu->arch.srr0 = vcpu->arch.pc;
vcpu->arch.srr1 = vcpu->arch.msr;
- vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt];
- kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]);
+ vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
+ kvmppc_set_msr(vcpu, vcpu->arch.msr & mask);
}
/* Check pending exceptions and deliver one, if possible. */
void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
{
unsigned long *pending = &vcpu->arch.pending_exceptions;
- unsigned int exception;
- unsigned int priority;
+ unsigned int prio;
+ u32 mask;
- priority = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending));
- while (priority <= BOOKE_MAX_INTERRUPT) {
- exception = priority_exception[priority];
- if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
- kvmppc_clear_exception(vcpu, exception);
- kvmppc_deliver_interrupt(vcpu, exception);
+ prio = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending));
+ while (prio <= BOOKE_MAX_INTERRUPT) {
+ if (kvmppc_can_deliver_interrupt_by_prio(vcpu, prio, &mask)) {
+ kvmppc_clear_exception_by_prio(pending, prio);
+ kvmppc_deliver_interrupt_by_prio(vcpu, prio, mask);
break;
}
- priority = find_next_bit(pending,
- BITS_PER_BYTE * sizeof(*pending),
- priority + 1);
+ prio = find_next_bit(pending,
+ BITS_PER_BYTE * sizeof(*pending),
+ prio + 1);
}
}
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -418,37 +418,69 @@
* a trap. */
case SPRN_IVOR0:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
+ break;
case SPRN_IVOR1:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
+ break;
case SPRN_IVOR2:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
+ break;
case SPRN_IVOR3:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
+ break;
case SPRN_IVOR4:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
+ break;
case SPRN_IVOR5:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
+ break;
case SPRN_IVOR6:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
+ break;
case SPRN_IVOR7:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
+ break;
case SPRN_IVOR8:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
+ break;
case SPRN_IVOR9:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
+ break;
case SPRN_IVOR10:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
+ break;
case SPRN_IVOR11:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
+ break;
case SPRN_IVOR12:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
+ break;
case SPRN_IVOR13:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
+ break;
case SPRN_IVOR14:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
+ break;
case SPRN_IVOR15:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
+ vcpu->arch.gpr[rt] + vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
+ break;
default:
printk("mfspr: unknown spr %x\n", sprn);
@@ -568,37 +600,69 @@
case SPRN_IVPR:
vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break;
case SPRN_IVOR0:
- vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR1:
- vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR2:
- vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR3:
- vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR4:
- vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR5:
- vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR6:
- vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR7:
- vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR8:
- vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR9:
- vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR10:
- vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR11:
- vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR12:
- vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR13:
- vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR14:
- vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] + vcpu->arch.gpr[rs];
+ break;
case SPRN_IVOR15:
- vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] + vcpu->arch.gpr[rs];
+ break;
default:
printk("mtspr: unknown spr %x\n", sprn);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -206,9 +206,8 @@
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
- unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
-
- return test_bit(priority, &vcpu->arch.pending_exceptions);
+ return test_bit(BOOKE_IRQPRIO_DECREMENTER,
+ &vcpu->arch.pending_exceptions);
}
static void kvmppc_decrementer_func(unsigned long data)
diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h
--- a/include/asm-powerpc/kvm_ppc.h
+++ b/include/asm-powerpc/kvm_ppc.h
@@ -29,6 +29,24 @@
#include <linux/kvm_types.h>
#include <linux/kvm_host.h>
+/* interrupt priortity ordering */
+#define BOOKE_IRQPRIO_DATA_STORAGE 0
+#define BOOKE_IRQPRIO_INST_STORAGE 1
+#define BOOKE_IRQPRIO_ALIGNMENT 2
+#define BOOKE_IRQPRIO_PROGRAM 3
+#define BOOKE_IRQPRIO_FP_UNAVAIL 4
+#define BOOKE_IRQPRIO_SYSCALL 5
+#define BOOKE_IRQPRIO_AP_UNAVAIL 6
+#define BOOKE_IRQPRIO_DTLB_MISS 7
+#define BOOKE_IRQPRIO_ITLB_MISS 8
+#define BOOKE_IRQPRIO_MACHINE_CHECK 9
+#define BOOKE_IRQPRIO_DEBUG 10
+#define BOOKE_IRQPRIO_CRITICAL 11
+#define BOOKE_IRQPRIO_WATCHDOG 12
+#define BOOKE_IRQPRIO_EXTERNAL 13
+#define BOOKE_IRQPRIO_FIT 14
+#define BOOKE_IRQPRIO_DECREMENTER 15
+
struct kvm_tlb {
struct tlbe guest_tlb[PPC44x_TLB_SIZE];
struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
@@ -42,7 +60,6 @@
};
extern const unsigned char exception_priority[];
-extern const unsigned char priority_exception[];
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern char kvmppc_handlers_start[];
@@ -74,10 +91,10 @@
set_bit(priority, &vcpu->arch.pending_exceptions);
}
-static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception)
+static inline void kvmppc_clear_exception_by_prio(unsigned long *pending,
+ unsigned int priority)
{
- unsigned int priority = exception_priority[exception];
- clear_bit(priority, &vcpu->arch.pending_exceptions);
+ clear_bit(priority, pending);
}
/* Helper function for "full" MSR writes. No need to call this if only EE is
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-10-13 12:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-10 10:59 [PATCH 1/3] kvmppc: optimize irq delivery path ehrhardt
2008-10-10 18:07 ` Hollis Blanchard
2008-10-13 6:22 ` Christian Ehrhardt
2008-10-13 12:07 ` ehrhardt
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.