mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-23 09:56:00 +00:00
powerpc: Add code to handle soft-disabled doorbells on server
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>
This commit is contained in:
parent
919ca8681f
commit
fe9e1d54e3
arch/powerpc/kernel
@ -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:
|
||||
|
@ -528,10 +528,12 @@ 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: \
|
||||
@ -539,13 +541,15 @@ masked_##_H##interrupt: \
|
||||
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; \
|
||||
@ -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
|
||||
@ -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
|
||||
/*
|
||||
|
@ -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
|
||||
@ -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 ! */
|
||||
|
Loading…
Reference in New Issue
Block a user