Skip to content

Commit f0f558b

Browse files
paulusmackmpe
authored andcommitted
powerpc/mm: Preserve CFAR value on SLB miss caused by access to bogus address
Currently, if userspace or the kernel accesses a completely bogus address, for example with any of bits 46-59 set, we first take an SLB miss interrupt, install a corresponding SLB entry with VSID 0, retry the instruction, then take a DSI/ISI interrupt because there is no HPT entry mapping the address. However, by the time of the second interrupt, the Come-From Address Register (CFAR) has been overwritten by the rfid instruction at the end of the SLB miss interrupt handler. Since bogus accesses can often be caused by a function return after the stack has been overwritten, the CFAR value would be very useful as it could indicate which function it was whose return had led to the bogus address. This patch adds code to create a full exception frame in the SLB miss handler in the case of a bogus address, rather than inserting an SLB entry with a zero VSID field. Then we call a new slb_miss_bad_addr() function in C code, which delivers a signal for a user access or creates an oops for a kernel access. In the latter case the oops message will show the CFAR value at the time of the access. In the case of the radix MMU, a segment miss interrupt indicates an access outside the ranges mapped by the page tables. Previously this was handled by the code for an unrecoverable SLB miss (one with MSR[RI] = 0), which is not really correct. With this patch, we now handle these interrupts with slb_miss_bad_addr(), which is much more consistent. Signed-off-by: Paul Mackerras <[email protected]> Reviewed-by: Aneesh Kumar K.V <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent b42d902 commit f0f558b

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ data_access_slb_pSeries:
175175
std r3,PACA_EXSLB+EX_R3(r13)
176176
mfspr r3,SPRN_DAR
177177
mfspr r12,SPRN_SRR1
178+
crset 4*cr6+eq
178179
#ifndef CONFIG_RELOCATABLE
179180
b slb_miss_realmode
180181
#else
@@ -201,6 +202,7 @@ instruction_access_slb_pSeries:
201202
std r3,PACA_EXSLB+EX_R3(r13)
202203
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
203204
mfspr r12,SPRN_SRR1
205+
crclr 4*cr6+eq
204206
#ifndef CONFIG_RELOCATABLE
205207
b slb_miss_realmode
206208
#else
@@ -783,6 +785,7 @@ data_access_slb_relon_pSeries:
783785
std r3,PACA_EXSLB+EX_R3(r13)
784786
mfspr r3,SPRN_DAR
785787
mfspr r12,SPRN_SRR1
788+
crset 4*cr6+eq
786789
#ifndef CONFIG_RELOCATABLE
787790
b slb_miss_realmode
788791
#else
@@ -808,6 +811,7 @@ instruction_access_slb_relon_pSeries:
808811
std r3,PACA_EXSLB+EX_R3(r13)
809812
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
810813
mfspr r12,SPRN_SRR1
814+
crclr 4*cr6+eq
811815
#ifndef CONFIG_RELOCATABLE
812816
b slb_miss_realmode
813817
#else
@@ -1408,6 +1412,7 @@ unrecover_mce:
14081412
* r3 has the faulting address
14091413
* r9 - r13 are saved in paca->exslb.
14101414
* r3 is saved in paca->slb_r3
1415+
* cr6.eq is set for a D-SLB miss, clear for a I-SLB miss
14111416
* We assume we aren't going to take any exceptions during this procedure.
14121417
*/
14131418
slb_miss_realmode:
@@ -1418,29 +1423,31 @@ slb_miss_realmode:
14181423

14191424
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
14201425
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
1426+
std r3,PACA_EXSLB+EX_DAR(r13)
14211427

1428+
crset 4*cr0+eq
14221429
#ifdef CONFIG_PPC_STD_MMU_64
14231430
BEGIN_MMU_FTR_SECTION
14241431
bl slb_allocate_realmode
14251432
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
14261433
#endif
1427-
/* All done -- return from exception. */
14281434

14291435
ld r10,PACA_EXSLB+EX_LR(r13)
14301436
ld r3,PACA_EXSLB+EX_R3(r13)
14311437
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
1432-
14331438
mtlr r10
1439+
1440+
beq 8f /* if bad address, make full stack frame */
1441+
14341442
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
1435-
BEGIN_MMU_FTR_SECTION
14361443
beq- 2f
1437-
FTR_SECTION_ELSE
1438-
b 2f
1439-
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
1444+
1445+
/* All done -- return from exception. */
14401446

14411447
.machine push
14421448
.machine "power4"
14431449
mtcrf 0x80,r9
1450+
mtcrf 0x02,r9 /* I/D indication is in cr6 */
14441451
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
14451452
.machine pop
14461453

@@ -1470,6 +1477,27 @@ unrecov_slb:
14701477
bl unrecoverable_exception
14711478
b 1b
14721479

1480+
8: mfspr r11,SPRN_SRR0
1481+
ld r10,PACAKBASE(r13)
1482+
LOAD_HANDLER(r10,bad_addr_slb)
1483+
mtspr SPRN_SRR0,r10
1484+
ld r10,PACAKMSR(r13)
1485+
mtspr SPRN_SRR1,r10
1486+
rfid
1487+
b .
1488+
1489+
bad_addr_slb:
1490+
EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB)
1491+
RECONCILE_IRQ_STATE(r10, r11)
1492+
ld r3, PACA_EXSLB+EX_DAR(r13)
1493+
std r3, _DAR(r1)
1494+
beq cr6, 2f
1495+
li r10, 0x480 /* fix trap number for I-SLB miss */
1496+
std r10, _TRAP(r1)
1497+
2: bl save_nvgprs
1498+
addi r3, r1, STACK_FRAME_OVERHEAD
1499+
bl slb_miss_bad_addr
1500+
b ret_from_except
14731501

14741502
#ifdef CONFIG_PPC_970_NAP
14751503
power4_fixup_nap:

arch/powerpc/kernel/traps.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,18 @@ void alignment_exception(struct pt_regs *regs)
13101310
exception_exit(prev_state);
13111311
}
13121312

1313+
void slb_miss_bad_addr(struct pt_regs *regs)
1314+
{
1315+
enum ctx_state prev_state = exception_enter();
1316+
1317+
if (user_mode(regs))
1318+
_exception(SIGSEGV, regs, SEGV_BNDERR, regs->dar);
1319+
else
1320+
bad_page_fault(regs, regs->dar, SIGSEGV);
1321+
1322+
exception_exit(prev_state);
1323+
}
1324+
13131325
void StackOverflow(struct pt_regs *regs)
13141326
{
13151327
printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",

arch/powerpc/mm/slb_low.S

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,9 @@ BEGIN_FTR_SECTION
173173
END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
174174
b slb_finish_load
175175

176-
8: /* invalid EA */
177-
li r10,0 /* BAD_VSID */
178-
li r9,0 /* BAD_VSID */
179-
li r11,SLB_VSID_USER /* flags don't much matter */
180-
b slb_finish_load
176+
8: /* invalid EA - return an error indication */
177+
crset 4*cr0+eq /* indicate failure */
178+
blr
181179

182180
/*
183181
* Finish loading of an SLB entry and return

0 commit comments

Comments
 (0)