Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e04ae85 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

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: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 166d97d9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
+35 −0
Original line number Diff line number Diff line
@@ -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
+32 −0
Original line number Diff line number Diff line
@@ -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;