Skip to content

Commit

Permalink
powerpc: Add code to handle soft-disabled doorbells on server
Browse files Browse the repository at this point in the history
This patch adds the logic to properly handle doorbells that come in when
interrupts have been soft disabled and to replay them when interrupts
are re-enabled:

- masked_##_H##interrupt is modified to leave interrupts enabled when a
  doorbell has come in since doorbells are edge sensitive and as such
  won't be automatically re-raised.

- __check_irq_replay now tests if a doorbell happened on book3s, and
  returns either 0xe80 or 0xa00 depending on whether we are the
  hypervisor or not.

- restore_check_irq_replay now tests for the two possible server
  doorbell vector numbers to replay.

- __replay_interrupt also adds tests for the two server doorbell vector
  numbers, and is modified to use a compare instruction rather than an
  andi. on the single bit difference between 0x500 and 0x900.

The last two use a CPU feature section to avoid needlessly testing
against the hypervisor vector if it is not the hypervisor, and vice
versa.

Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Ian Munsie authored and Benjamin Herrenschmidt committed Jan 10, 2013
1 parent 919ca86 commit fe9e1d5
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 16 deletions.
13 changes: 11 additions & 2 deletions arch/powerpc/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -836,13 +836,22 @@ restore_check_irq_replay:
addi r3,r1,STACK_FRAME_OVERHEAD;
bl .timer_interrupt
b .ret_from_except
#ifdef CONFIG_PPC_DOORBELL
1:
#ifdef CONFIG_PPC_BOOK3E
1: cmpwi cr0,r3,0x280
cmpwi cr0,r3,0x280
#else
BEGIN_FTR_SECTION
cmpwi cr0,r3,0xe80
FTR_SECTION_ELSE
cmpwi cr0,r3,0xa00
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
#endif /* CONFIG_PPC_BOOK3E */
bne 1f
addi r3,r1,STACK_FRAME_OVERHEAD;
bl .doorbell_exception
b .ret_from_except
#endif /* CONFIG_PPC_BOOK3E */
#endif /* CONFIG_PPC_DOORBELL */
1: b .ret_from_except /* What else to do here ? */

unrecov_restore:
Expand Down
37 changes: 25 additions & 12 deletions arch/powerpc/kernel/exceptions-64s.S
Original file line number Diff line number Diff line change
Expand Up @@ -528,24 +528,28 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206)
KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)

/*
* An interrupt came in while soft-disabled. We set paca->irq_happened,
* then, if it was a decrementer interrupt, we bump the dec to max and
* and return, else we hard disable and return. This is called with
* r10 containing the value to OR to the paca field.
* An interrupt came in while soft-disabled. We set paca->irq_happened, then:
* - If it was a decrementer interrupt, we bump the dec to max and and return.
* - If it was a doorbell we return immediately since doorbells are edge
* triggered and won't automatically refire.
* - else we hard disable and return.
* This is called with r10 containing the value to OR to the paca field.
*/
#define MASKED_INTERRUPT(_H) \
masked_##_H##interrupt: \
std r11,PACA_EXGEN+EX_R11(r13); \
lbz r11,PACAIRQHAPPENED(r13); \
or r11,r11,r10; \
stb r11,PACAIRQHAPPENED(r13); \
andi. r10,r10,PACA_IRQ_DEC; \
beq 1f; \
cmpwi r10,PACA_IRQ_DEC; \
bne 1f; \
lis r10,0x7fff; \
ori r10,r10,0xffff; \
mtspr SPRN_DEC,r10; \
b 2f; \
1: mfspr r10,SPRN_##_H##SRR1; \
1: cmpwi r10,PACA_IRQ_DBELL; \
beq 2f; \
mfspr r10,SPRN_##_H##SRR1; \
rldicl r10,r10,48,1; /* clear MSR_EE */ \
rotldi r10,r10,16; \
mtspr SPRN_##_H##SRR1,r10; \
Expand All @@ -562,8 +566,8 @@ masked_##_H##interrupt: \

/*
* Called from arch_local_irq_enable when an interrupt needs
* to be resent. r3 contains 0x500 or 0x900 to indicate which
* kind of interrupt. MSR:EE is already off. We generate a
* to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate
* which kind of interrupt. MSR:EE is already off. We generate a
* stackframe like if a real interrupt had happened.
*
* Note: While MSR:EE is off, we need to make sure that _MSR
Expand All @@ -579,9 +583,18 @@ _GLOBAL(__replay_interrupt)
mflr r11
mfcr r9
ori r12,r12,MSR_EE
andi. r3,r3,0x0800
bne decrementer_common
b hardware_interrupt_common
cmpwi r3,0x900
beq decrementer_common
cmpwi r3,0x500
beq hardware_interrupt_common
BEGIN_FTR_SECTION
cmpwi r3,0xe80
beq h_doorbell_common
FTR_SECTION_ELSE
cmpwi r3,0xa00
beq doorbell_super_common
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
blr

#ifdef CONFIG_PPC_PSERIES
/*
Expand Down
11 changes: 9 additions & 2 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ static inline notrace int decrementer_check_overflow(void)
}

/* This is called whenever we are re-enabling interrupts
* and returns either 0 (nothing to do) or 500/900 if there's
* either an EE or a DEC to generate.
* and returns either 0 (nothing to do) or 500/900/280/a00/e80 if
* there's an EE, DEC or DBELL to generate.
*
* This is called in two contexts: From arch_local_irq_restore()
* before soft-enabling interrupts, and from the exception exit
Expand Down Expand Up @@ -182,6 +182,13 @@ notrace unsigned int __check_irq_replay(void)
local_paca->irq_happened &= ~PACA_IRQ_DBELL;
if (happened & PACA_IRQ_DBELL)
return 0x280;
#else
local_paca->irq_happened &= ~PACA_IRQ_DBELL;
if (happened & PACA_IRQ_DBELL) {
if (cpu_has_feature(CPU_FTR_HVMODE))
return 0xe80;
return 0xa00;
}
#endif /* CONFIG_PPC_BOOK3E */

/* There should be nothing left ! */
Expand Down

0 comments on commit fe9e1d5

Please sign in to comment.