powerpc/mm/32s: add setibat() clearibat() and update_bats()
setibat() and clearibat() allows to manipulate IBATs independently of DBATs. update_bats() allows to update bats after init. This is done with MMU off. Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
		
							parent
							
								
									166d97d961
								
							
						
					
					
						commit
						5e04ae85fb
					
				| @ -92,6 +92,8 @@ typedef struct { | ||||
| 	unsigned long vdso_base; | ||||
| } mm_context_t; | ||||
| 
 | ||||
| void update_bats(void); | ||||
| 
 | ||||
| /* patch sites */ | ||||
| extern s32 patch__hash_page_A0, patch__hash_page_A1, patch__hash_page_A2; | ||||
| extern s32 patch__hash_page_B, patch__hash_page_C; | ||||
|  | ||||
| @ -1096,6 +1096,41 @@ BEGIN_MMU_FTR_SECTION | ||||
| END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) | ||||
| 	blr | ||||
| 
 | ||||
| _ENTRY(update_bats) | ||||
| 	lis	r4, 1f@h
 | ||||
| 	ori	r4, r4, 1f@l
 | ||||
| 	tophys(r4, r4) | ||||
| 	mfmsr	r6 | ||||
| 	mflr	r7 | ||||
| 	li	r3, MSR_KERNEL & ~(MSR_IR | MSR_DR) | ||||
| 	rlwinm	r0, r6, 0, ~MSR_RI | ||||
| 	rlwinm	r0, r0, 0, ~MSR_EE | ||||
| 	mtmsr	r0 | ||||
| 	mtspr	SPRN_SRR0, r4 | ||||
| 	mtspr	SPRN_SRR1, r3 | ||||
| 	SYNC | ||||
| 	RFI | ||||
| 1:	bl	clear_bats | ||||
| 	lis	r3, BATS@ha
 | ||||
| 	addi	r3, r3, BATS@l
 | ||||
| 	tophys(r3, r3) | ||||
| 	LOAD_BAT(0, r3, r4, r5) | ||||
| 	LOAD_BAT(1, r3, r4, r5) | ||||
| 	LOAD_BAT(2, r3, r4, r5) | ||||
| 	LOAD_BAT(3, r3, r4, r5) | ||||
| BEGIN_MMU_FTR_SECTION | ||||
| 	LOAD_BAT(4, r3, r4, r5) | ||||
| 	LOAD_BAT(5, r3, r4, r5) | ||||
| 	LOAD_BAT(6, r3, r4, r5) | ||||
| 	LOAD_BAT(7, r3, r4, r5) | ||||
| END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) | ||||
| 	li	r3, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI) | ||||
| 	mtmsr	r3 | ||||
| 	mtspr	SPRN_SRR0, r7 | ||||
| 	mtspr	SPRN_SRR1, r6 | ||||
| 	SYNC | ||||
| 	RFI | ||||
| 
 | ||||
| flush_tlbs: | ||||
| 	lis	r10, 0x40 | ||||
| 1:	addic.	r10, r10, -0x1000 | ||||
|  | ||||
| @ -106,6 +106,38 @@ static unsigned int block_size(unsigned long base, unsigned long top) | ||||
| 	return min3(max_size, 1U << base_shift, 1U << block_shift); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set up one of the IBAT (block address translation) register pairs. | ||||
|  * The parameters are not checked; in particular size must be a power | ||||
|  * of 2 between 128k and 256M. | ||||
|  * Only for 603+ ... | ||||
|  */ | ||||
| static void setibat(int index, unsigned long virt, phys_addr_t phys, | ||||
| 		    unsigned int size, pgprot_t prot) | ||||
| { | ||||
| 	unsigned int bl = (size >> 17) - 1; | ||||
| 	int wimgxpp; | ||||
| 	struct ppc_bat *bat = BATS[index]; | ||||
| 	unsigned long flags = pgprot_val(prot); | ||||
| 
 | ||||
| 	if (!cpu_has_feature(CPU_FTR_NEED_COHERENT)) | ||||
| 		flags &= ~_PAGE_COHERENT; | ||||
| 
 | ||||
| 	wimgxpp = (flags & _PAGE_COHERENT) | (_PAGE_EXEC ? BPP_RX : BPP_XX); | ||||
| 	bat[0].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ | ||||
| 	bat[0].batl = BAT_PHYS_ADDR(phys) | wimgxpp; | ||||
| 	if (flags & _PAGE_USER) | ||||
| 		bat[0].batu |= 1;	/* Vp = 1 */ | ||||
| } | ||||
| 
 | ||||
| static void clearibat(int index) | ||||
| { | ||||
| 	struct ppc_bat *bat = BATS[index]; | ||||
| 
 | ||||
| 	bat[0].batu = 0; | ||||
| 	bat[0].batl = 0; | ||||
| } | ||||
| 
 | ||||
| unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top) | ||||
| { | ||||
| 	int idx; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user