diff options
author | Alexander Graf <agraf@suse.de> | 2014-05-22 11:25:14 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-05-30 08:26:26 -0400 |
commit | aae6559651dd9d779da79f30de02033557fe263b (patch) | |
tree | e20739fdfd363f9322c89f4730ae5b22034f4ead /arch/powerpc/kvm | |
parent | 42188365f92c2d6bc89c9441a5e9305c1354e8a6 (diff) |
KVM: PPC: MPIC: Reset IRQ source private members
When we reset the in-kernel MPIC controller, we forget to reset some hidden
state such as destmask and output. This state is usually set when the guest
writes to the IDR register for a specific IRQ line.
To make sure we stay in sync and don't forget hidden state, treat reset of
the IDR register as a simple write of the IDR register. That automatically
updates all the hidden state as well.
Reported-by: Paul Janzen <pcj@pauljanzen.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r-- | arch/powerpc/kvm/mpic.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c index efbd9962a209..b68d0dc9479a 100644 --- a/arch/powerpc/kvm/mpic.c +++ b/arch/powerpc/kvm/mpic.c | |||
@@ -126,6 +126,8 @@ static int openpic_cpu_write_internal(void *opaque, gpa_t addr, | |||
126 | u32 val, int idx); | 126 | u32 val, int idx); |
127 | static int openpic_cpu_read_internal(void *opaque, gpa_t addr, | 127 | static int openpic_cpu_read_internal(void *opaque, gpa_t addr, |
128 | u32 *ptr, int idx); | 128 | u32 *ptr, int idx); |
129 | static inline void write_IRQreg_idr(struct openpic *opp, int n_IRQ, | ||
130 | uint32_t val); | ||
129 | 131 | ||
130 | enum irq_type { | 132 | enum irq_type { |
131 | IRQ_TYPE_NORMAL = 0, | 133 | IRQ_TYPE_NORMAL = 0, |
@@ -528,7 +530,6 @@ static void openpic_reset(struct openpic *opp) | |||
528 | /* Initialise IRQ sources */ | 530 | /* Initialise IRQ sources */ |
529 | for (i = 0; i < opp->max_irq; i++) { | 531 | for (i = 0; i < opp->max_irq; i++) { |
530 | opp->src[i].ivpr = opp->ivpr_reset; | 532 | opp->src[i].ivpr = opp->ivpr_reset; |
531 | opp->src[i].idr = opp->idr_reset; | ||
532 | 533 | ||
533 | switch (opp->src[i].type) { | 534 | switch (opp->src[i].type) { |
534 | case IRQ_TYPE_NORMAL: | 535 | case IRQ_TYPE_NORMAL: |
@@ -543,6 +544,8 @@ static void openpic_reset(struct openpic *opp) | |||
543 | case IRQ_TYPE_FSLSPECIAL: | 544 | case IRQ_TYPE_FSLSPECIAL: |
544 | break; | 545 | break; |
545 | } | 546 | } |
547 | |||
548 | write_IRQreg_idr(opp, i, opp->idr_reset); | ||
546 | } | 549 | } |
547 | /* Initialise IRQ destinations */ | 550 | /* Initialise IRQ destinations */ |
548 | for (i = 0; i < MAX_CPU; i++) { | 551 | for (i = 0; i < MAX_CPU; i++) { |