Commit b327e1b3 authored by Paul Mackerras's avatar Paul Mackerras

PPC32: Use non-pinned large-page TLB entries for kernel RAM mapping.

parent f348ef4e
......@@ -555,33 +555,40 @@ label:
4:
tophys(r11, r11)
rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
lwz r11, 0(r11) /* Get L1 entry */
rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
lwz r12, 0(r11) /* Get L1 entry */
andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
beq 2f /* Bail if no table */
rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
lwz r11, 0(r12) /* Get Linux PTE */
andi. r9, r11, _PAGE_PRESENT
beq 2f
beq 5f
ori r11, r11, _PAGE_ACCESSED
stw r11, 0(r12)
/* Most of the Linux PTE is ready to load into the TLB LO.
* We set ZSEL, where only the LS-bit determines user access.
* We set execute, because we don't have the granularity to
* properly set this at the page level (Linux problem).
* If shared is set, we cause a zero PID->TID load.
* Many of these bits are software only. Bits we don't set
* here we (properly should) assume have the appropriate value.
*/
li r12, 0x0ce2
andc r11, r11, r12 /* Make sure 20, 21 are zero */
/* Create TLB tag. This is the faulting address plus a static
* set of bits. These are size, valid, E, U0.
*/
li r12, 0x00c0
rlwimi r10, r12, 0, 20, 31
b finish_tlb_load
2: /* Check for possible large-page pmd entry */
rlwinm. r9, r12, 2, 22, 24
beq 5f
2:
/* Create TLB tag. This is the faulting address, plus a static
* set of bits (valid, E, U0) plus the size from the PMD.
*/
ori r9, r9, 0x40
rlwimi r10, r9, 0, 20, 31
mr r11, r12
b finish_tlb_load
5:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
......@@ -647,55 +654,40 @@ label:
4:
tophys(r11, r11)
rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
lwz r11, 0(r11) /* Get L1 entry */
rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
lwz r12, 0(r11) /* Get L1 entry */
andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
beq 2f /* Bail if no table */
rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
lwz r11, 0(r12) /* Get Linux PTE */
andi. r9, r11, _PAGE_PRESENT
beq 2f
beq 5f
ori r11, r11, _PAGE_ACCESSED
stw r11, 0(r12)
/* Most of the Linux PTE is ready to load into the TLB LO.
* We set ZSEL, where only the LS-bit determines user access.
* We set execute, because we don't have the granularity to
* properly set this at the page level (Linux problem).
* If shared is set, we cause a zero PID->TID load.
* Many of these bits are software only. Bits we don't set
* here we (properly should) assume have the appropriate value.
*/
li r12, 0x0ce2
andc r11, r11, r12 /* Make sure 20, 21 are zero */
/* Create TLB tag. This is the faulting address plus a static
* set of bits. These are size, valid, E, U0.
*/
li r12, 0x00c0
rlwimi r10, r12, 0, 20, 31
b finish_tlb_load
/* Done...restore registers and get out of here.
*/
#ifdef CONFIG_403GCX
lwz r12, 12(r0)
lwz r11, 8(r0)
mtspr SPRN_PID, r12
mtcr r11
lwz r9, 4(r0)
lwz r12, 0(r0)
#else
mfspr r12, SPRG6
mfspr r11, SPRG7
mtspr SPRN_PID, r12
mtcr r11
mfspr r9, SPRG5
mfspr r12, SPRG4
#endif
mfspr r11, SPRG1
mfspr r10, SPRG0
PPC405_ERR77_SYNC
rfi /* Should sync shadow TLBs */
b . /* prevent prefetch past rfi */
2: /* Check for possible large-page pmd entry */
rlwinm. r9, r12, 2, 22, 24
beq 5f
2:
/* Create TLB tag. This is the faulting address, plus a static
* set of bits (valid, E, U0) plus the size from the PMD.
*/
ori r9, r9, 0x40
rlwimi r10, r9, 0, 20, 31
mr r11, r12
b finish_tlb_load
5:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
......@@ -818,8 +810,8 @@ check_single_step_in_exception:
/* Damn, I came up one instruction too many to fit into the
* exception space :-). Both the instruction and data TLB
* miss get to this point to load the TLB.
* r10 - EA of fault
* r11 - TLB LO (info from Linux PTE)
* r10 - TLB_TAG value
* r11 - Linux PTE
* r12, r9 - avilable to use
* PID - loaded with proper value when we get here
* Upon exit, we reload everything and RFI.
......@@ -833,21 +825,19 @@ finish_tlb_load:
*/
lwz r9, tlb_4xx_index@l(0)
addi r9, r9, 1
cmpwi 0, r9, 61 /* reserve entries 62, 63 for kernel */
ble 7f
li r9, 0
7:
andi. r9, r9, (PPC4XX_TLB_SIZE-1)
stw r9, tlb_4xx_index@l(0)
6:
tlbwe r11, r9, TLB_DATA /* Load TLB LO */
/* Create EPN. This is the faulting address plus a static
* set of bits. These are size, valid, E, U0, and ensure
* bits 20 and 21 are zero.
/*
* Clear out the software-only bits in the PTE to generate the
* TLB_DATA value. These are the bottom 2 bits of the RPM, the
* top 3 bits of the zone field, and M.
*/
li r12, 0x00c0
rlwimi r10, r12, 0, 20, 31
li r12, 0x0ce2
andc r11, r11, r12
tlbwe r11, r9, TLB_DATA /* Load TLB LO */
tlbwe r10, r9, TLB_TAG /* Load TLB HI */
/* Done...restore registers and get out of here.
......@@ -929,7 +919,9 @@ start_here:
/* Load up the kernel context */
2:
SYNC /* Force all PTE updates to finish */
sync /* Flush to memory before changing TLB */
tlbia
isync /* Flush shadow TLBs */
/* set up the PTE pointers for the Abatron bdiGDB.
*/
......@@ -956,7 +948,7 @@ start_here:
*/
initial_mmu:
tlbia /* Invalidate all TLB entries */
sync
isync
/* We should still be executing code at physical address 0x0000xxxx
* at this point. However, start_here is at virtual address
......@@ -985,18 +977,30 @@ initial_mmu:
clrrwi r3,r3,10 /* Mask off the effective page number */
ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
li r0,62 /* TLB slot 62 */
li r0,63 /* TLB slot 63 */
tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */
tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */
addis r4, r4, 0x0100 /* Map next 16 M entries */
addis r3, r3, 0x0100
#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(SERIAL_DEBUG_IO_BASE)
/* Load a TLB entry for the UART, so that ppc4xx_progress() can use
* the UARTs nice and early. We use a 4k real==virtual mapping. */
li r0,63 /* TLB slot 63 */
lis r3,SERIAL_DEBUG_IO_BASE@h
ori r3,r3,SERIAL_DEBUG_IO_BASE@l
mr r4,r3
clrrwi r4,r4,12
ori r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G)
clrrwi r3,r3,12
ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
li r0,0 /* TLB slot 0 */
tlbwe r4,r0,TLB_DATA
tlbwe r3,r0,TLB_TAG
#endif /* CONFIG_SERIAL_DEBUG_TEXT && SERIAL_DEBUG_IO_BASE */
isync
/* Establish the exception vector base
......
......@@ -348,18 +348,9 @@ _GLOBAL(_nmask_and_or_msr)
*/
_GLOBAL(_tlbia)
#if defined(CONFIG_40x)
/* This needs to be coordinated with other pinning functions since
* we don't keep a memory location of number of entries to reduce
* cache pollution during these operations.
*/
lis r3, 0
sync
1:
tlbwe r3, r3, TLB_TAG /* just ensure V is clear */
addi r3, r3, 1 /* so r3 works fine for that */
cmpwi 0, r3, 61 /* reserve last two entries */
ble 1b
isync
sync /* Flush to memory before changing mapping */
tlbia
isync /* Flush shadow TLB */
#else /* ! defined(CONFIG_40x) */
#if defined(CONFIG_SMP)
rlwinm r8,r1,0,0,18
......
......@@ -50,6 +50,7 @@
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/setup.h>
#include "mmu_decl.h"
/*
* MMU_init_hw does the chip-specific initialization of the MMU hardware.
......@@ -88,3 +89,49 @@ void __init MMU_init_hw(void)
mtspr(SPRN_DCCR, 0xF0000000); /* 512 MB of data space at 0x0. */
mtspr(SPRN_ICCR, 0xF0000000); /* 512 MB of instr. space at 0x0. */
}
#define LARGE_PAGE_SIZE_16M (1<<24)
#define LARGE_PAGE_SIZE_4M (1<<22)
unsigned long __init mmu_mapin_ram(void)
{
unsigned long v, s;
phys_addr_t p;
v = KERNELBASE;
p = PPC_MEMSTART;
s = 0;
while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
spin_lock(&init_mm.page_table_lock);
pmdp = pmd_offset(pgd_offset_k(v), v);
pmd_val(*pmdp++) = val;
pmd_val(*pmdp++) = val;
pmd_val(*pmdp++) = val;
pmd_val(*pmdp++) = val;
spin_unlock(&init_mm.page_table_lock);
v += LARGE_PAGE_SIZE_16M;
p += LARGE_PAGE_SIZE_16M;
s += LARGE_PAGE_SIZE_16M;
}
while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
spin_lock(&init_mm.page_table_lock);
pmdp = pmd_offset(pgd_offset_k(v), v);
pmd_val(*pmdp) = val;
spin_unlock(&init_mm.page_table_lock);
v += LARGE_PAGE_SIZE_4M;
p += LARGE_PAGE_SIZE_4M;
s += LARGE_PAGE_SIZE_4M;
}
return s;
}
......@@ -50,7 +50,7 @@ extern unsigned long Hash_size, Hash_mask;
#elif defined(CONFIG_4xx)
#define flush_HPTE(X, va, pg) _tlbie(va)
extern void MMU_init_hw(void);
#define mmu_mapin_ram() (0UL)
extern unsigned long mmu_mapin_ram(void);
#else
/* anything except 4xx or 8xx */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment