mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	powerpc/8xx: Inconditionally use task PGDIR in DTLB misses
At the time being, DATA TLB miss handlers use task PGDIR for user addresses and swapper_pg_dir for kernel addresses. Now that kernel part of swapper_pg_dir is copied into task PGDIR at PGD allocation, it is possible to avoid the above logic and always use task PGDIR. But new kernel PGD entries can still be created after init, in which case those PGD entries may miss in task PGDIR. This can be handled in DATA TLB error handler. However, it needs to be done in real mode because the missing entry might be related to the stack. So implement copy of missing PGD entry in the prolog of DATA TLB ERROR handler just after the fixup of DAR. Note that this is feasible because 8xx doesn't implement vmap or ioremap with 8Mbytes pages but only 512kbytes pages which are at PTE level. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://msgid.link/7a76a923d2a111f1d843d8b20b4df0c65d2f4a7b.1724173828.git.christophe.leroy@csgroup.eu
This commit is contained in:
		
							parent
							
								
									33c527522f
								
							
						
					
					
						commit
						ac9f97ff8b
					
				
					 1 changed files with 34 additions and 23 deletions
				
			
		| 
						 | 
				
			
			@ -40,16 +40,6 @@
 | 
			
		|||
 | 
			
		||||
#include "head_32.h"
 | 
			
		||||
 | 
			
		||||
.macro compare_to_kernel_boundary scratch, addr
 | 
			
		||||
#if CONFIG_TASK_SIZE <= 0x80000000 && MODULES_VADDR >= 0x80000000
 | 
			
		||||
/* By simply checking Address >= 0x80000000, we know if its a kernel address */
 | 
			
		||||
	not.	\scratch, \addr
 | 
			
		||||
#else
 | 
			
		||||
	rlwinm	\scratch, \addr, 16, 0xfff8
 | 
			
		||||
	cmpli	cr0, \scratch, TASK_SIZE@h
 | 
			
		||||
#endif
 | 
			
		||||
.endm
 | 
			
		||||
 | 
			
		||||
#define PAGE_SHIFT_512K		19
 | 
			
		||||
#define PAGE_SHIFT_8M		23
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -237,19 +227,12 @@ instruction_counter:
 | 
			
		|||
	START_EXCEPTION(INTERRUPT_DATA_TLB_MISS_8xx, DataStoreTLBMiss)
 | 
			
		||||
	mtspr	SPRN_SPRG_SCRATCH2, r10
 | 
			
		||||
	mtspr	SPRN_M_TW, r11
 | 
			
		||||
	mfcr	r11
 | 
			
		||||
 | 
			
		||||
	/* If we are faulting a kernel address, we have to use the
 | 
			
		||||
	 * kernel page tables.
 | 
			
		||||
	 */
 | 
			
		||||
	mfspr	r10, SPRN_MD_EPN
 | 
			
		||||
	compare_to_kernel_boundary r10, r10
 | 
			
		||||
	mfspr	r10, SPRN_M_TWB	/* Get level 1 table */
 | 
			
		||||
	blt+	3f
 | 
			
		||||
	rlwinm	r10, r10, 0, 20, 31
 | 
			
		||||
	oris	r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
 | 
			
		||||
3:
 | 
			
		||||
	mtcr	r11
 | 
			
		||||
	lwz	r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10)	/* Get level 1 entry */
 | 
			
		||||
 | 
			
		||||
	mtspr	SPRN_MD_TWC, r11
 | 
			
		||||
| 
						 | 
				
			
			@ -321,15 +304,19 @@ instruction_counter:
 | 
			
		|||
	cmpwi	cr1, r11, RPN_PATTERN
 | 
			
		||||
	beq-	cr1, FixupDAR	/* must be a buggy dcbX, icbi insn. */
 | 
			
		||||
DARFixed:/* Return from dcbx instruction bug workaround */
 | 
			
		||||
	mfspr	r11, SPRN_DSISR
 | 
			
		||||
	rlwinm	r11, r11, 0, DSISR_NOHPTE
 | 
			
		||||
	cmpwi	cr1, r11, 0
 | 
			
		||||
	beq+	cr1, .Ldtlbie
 | 
			
		||||
	mfspr	r11, SPRN_DAR
 | 
			
		||||
	tlbie	r11
 | 
			
		||||
	rlwinm	r11, r11, 16, 0xffff
 | 
			
		||||
	cmplwi	cr1, r11, TASK_SIZE@h
 | 
			
		||||
	bge-	cr1, FixupPGD
 | 
			
		||||
.Ldtlbie:
 | 
			
		||||
	EXCEPTION_PROLOG_1
 | 
			
		||||
	/* 0x300 is DataAccess exception, needed by bad_page_fault() */
 | 
			
		||||
	EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataTLBError handle_dar_dsisr=1
 | 
			
		||||
	lwz	r4, _DAR(r11)
 | 
			
		||||
	lwz	r5, _DSISR(r11)
 | 
			
		||||
	andis.	r10,r5,DSISR_NOHPTE@h
 | 
			
		||||
	beq+	.Ldtlbie
 | 
			
		||||
	tlbie	r4
 | 
			
		||||
.Ldtlbie:
 | 
			
		||||
	prepare_transfer_to_handler
 | 
			
		||||
	bl	do_page_fault
 | 
			
		||||
	b	interrupt_return
 | 
			
		||||
| 
						 | 
				
			
			@ -383,6 +370,30 @@ DARFixed:/* Return from dcbx instruction bug workaround */
 | 
			
		|||
	__HEAD
 | 
			
		||||
	. = 0x2000
 | 
			
		||||
 | 
			
		||||
FixupPGD:
 | 
			
		||||
	mtspr	SPRN_M_TW, r10
 | 
			
		||||
	mfspr	r10, SPRN_DAR
 | 
			
		||||
	mtspr	SPRN_MD_EPN, r10
 | 
			
		||||
	mfspr	r11, SPRN_M_TWB	/* Get level 1 table */
 | 
			
		||||
	lwz	r10, (swapper_pg_dir - PAGE_OFFSET)@l(r11)	/* Get the level 1 entry */
 | 
			
		||||
	cmpwi	cr1, r10, 0
 | 
			
		||||
	bne	cr1, 1f
 | 
			
		||||
 | 
			
		||||
	rlwinm	r10, r11, 0, 20, 31
 | 
			
		||||
	oris	r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
 | 
			
		||||
	lwz	r10, (swapper_pg_dir - PAGE_OFFSET)@l(r10)	/* Get the level 1 entry */
 | 
			
		||||
	cmpwi	cr1, r10, 0
 | 
			
		||||
	beq	cr1, 1f
 | 
			
		||||
	stw	r10, (swapper_pg_dir - PAGE_OFFSET)@l(r11)	/* Set the level 1 entry */
 | 
			
		||||
	mfspr	r10, SPRN_M_TW
 | 
			
		||||
	mtcr	r10
 | 
			
		||||
	mfspr	r10, SPRN_SPRG_SCRATCH0
 | 
			
		||||
	mfspr	r11, SPRN_SPRG_SCRATCH1
 | 
			
		||||
	rfi
 | 
			
		||||
1:
 | 
			
		||||
	mfspr	r10, SPRN_M_TW
 | 
			
		||||
	b	.Ldtlbie
 | 
			
		||||
 | 
			
		||||
/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
 | 
			
		||||
 * by decoding the registers used by the dcbx instruction and adding them.
 | 
			
		||||
 * DAR is set to the calculated address.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue