diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-01-21 09:42:58 +0300 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-01-21 09:42:58 +0300 |
commit | 2023b843d7b62d99e7356b872e99abc7d6667e49 (patch) | |
tree | 74e17b43ed1316c6c02055457b4291c1b050f48e /arch/sh/kernel/head_32.S | |
parent | 77c2019fc1b4495ce483ef2af9cb12bae23e353b (diff) | |
download | linux-2023b843d7b62d99e7356b872e99abc7d6667e49.tar.xz |
sh: Rework P2 to only include kernel text.
This effectively neutralizes P2 by getting rid of P1 identity mapping
for all available memory and instead only establishes a single unbuffered
PMB entry (16MB -- the smallest available) that covers the kernel.
As using segmentation for abusing caching attributes in drivers is no
longer supported (and there are no drivers that can be enabled in 32-bit
mode that do this), this provides us with all of the uncached access
needs by the kernel itself.
Drivers and their ilk need to specify their caching attributes when
remapping through page tables, as usual.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/head_32.S')
-rw-r--r-- | arch/sh/kernel/head_32.S | 169 |
1 files changed, 92 insertions, 77 deletions
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index ee954d1b8cc6..e93320135cda 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S @@ -86,7 +86,96 @@ ENTRY(_stext) #endif #if defined(CONFIG_PMB) && !defined(CONFIG_PMB_LEGACY) +/* + * Reconfigure the initial PMB mappings setup by the hardware. + * + * When we boot in 32-bit MMU mode there are 2 PMB entries already + * setup for us. + * + * Entry VPN PPN V SZ C UB WT + * --------------------------------------------------------------- + * 0 0x80000000 0x00000000 1 512MB 1 0 1 + * 1 0xA0000000 0x00000000 1 512MB 0 0 0 + * + * But we reprogram them here because we want complete control over + * our address space and the initial mappings may not map PAGE_OFFSET + * to __MEMORY_START (or even map all of our RAM). + * + * Once we've setup cached and uncached mappings we clear the rest of the + * PMB entries. This clearing also deals with the fact that PMB entries + * can persist across reboots. The PMB could have been left in any state + * when the reboot occurred, so to be safe we clear all entries and start + * with with a clean slate. + * + * The uncached mapping is constructed using the smallest possible + * mapping with a single unbufferable page. Only the kernel text needs to + * be covered via the uncached mapping so that certain functions can be + * run uncached. + * + * Drivers and the like that have previously abused the 1:1 identity + * mapping are unsupported in 32-bit mode and must specify their caching + * preference when page tables are constructed. + * + * This frees up the P2 space for more nefarious purposes. + * + * Register utilization is as follows: + * + * r0 = PMB_DATA data field + * r1 = PMB_DATA address field + * r2 = PMB_ADDR data field + * r3 = PMB_ADDR address field + * r4 = PMB_E_SHIFT + * r5 = remaining amount of RAM to map + * r6 = PMB mapping size we're trying to use + * r7 = cached_to_uncached + * r8 = scratch register + * r9 = scratch register + * r10 = number of PMB entries we've setup + */ + + mov.l .LMMUCR, r1 /* Flush the TLB */ + mov.l @r1, r0 + or #MMUCR_TI, r0 + mov.l r0, @r1 + + mov.l .LMEMORY_SIZE, r5 + mov r5, r7 + + mov #PMB_E_SHIFT, r0 + mov #0x1, r4 + shld r0, r4 + mov.l .LFIRST_DATA_ENTRY, r0 + mov.l .LPMB_DATA, r1 + mov.l .LFIRST_ADDR_ENTRY, r2 + mov.l .LPMB_ADDR, r3 + + mov #0, r10 + + /* + * Uncached mapping + */ + mov #(PMB_SZ_16M >> 2), r9 + shll2 r9 + + mov #(PMB_UB >> 8), r8 + shll8 r8 + + or r0, r8 + or r9, r8 + mov.l r8, @r1 + mov r2, r8 + add r7, r8 + mov.l r8, @r3 + + add r4, r1 + add r4, r3 + add #1, r10 + +/* + * Iterate over all of the available sizes from largest to + * smallest for constructing the cached mapping. + */ #define __PMB_ITER_BY_SIZE(size) \ .L##size: \ mov #(size >> 4), r6; \ @@ -115,26 +204,6 @@ ENTRY(_stext) /* Increment number of PMB entries */ \ add #1, r10; \ \ - /* \ - * Uncached mapping \ - */ \ - mov #(PMB_UB >> 8), r8; \ - shll8 r8; \ - \ - or r0, r8; \ - or r9, r8; \ - mov.l r8, @r1; \ - mov r2, r8; \ - add r7, r8; \ - mov.l r8, @r3; \ - \ - /* Increment to the next PMB_DATA entry */ \ - add r4, r1; \ - /* Increment to the next PMB_ADDR entry */ \ - add r4, r3; \ - /* Increment number of PMB entries */ \ - add #1, r10; \ - \ sub r6, r5; \ add r6, r0; \ add r6, r2; \ @@ -142,68 +211,14 @@ ENTRY(_stext) bra .L##size; \ 9999: - /* - * Reconfigure the initial PMB mappings setup by the hardware. - * - * When we boot in 32-bit MMU mode there are 2 PMB entries already - * setup for us. - * - * Entry VPN PPN V SZ C UB WT - * --------------------------------------------------------------- - * 0 0x80000000 0x00000000 1 512MB 1 0 1 - * 1 0xA0000000 0x00000000 1 512MB 0 0 0 - * - * But we reprogram them here because we want complete control over - * our address space and the initial mappings may not map PAGE_OFFSET - * to __MEMORY_START (or even map all of our RAM). - * - * Once we've setup cached and uncached mappings for all of RAM we - * clear the rest of the PMB entries. - * - * This clearing also deals with the fact that PMB entries can persist - * across reboots. The PMB could have been left in any state when the - * reboot occurred, so to be safe we clear all entries and start with - * with a clean slate. - */ - - mov.l .LMMUCR, r1 /* Flush the TLB */ - mov.l @r1, r0 - or #MMUCR_TI, r0 - mov.l r0, @r1 - - mov.l .LMEMORY_SIZE, r5 - mov r5, r7 - - mov #PMB_E_SHIFT, r0 - mov #0x1, r4 - shld r0, r4 - - mov.l .LFIRST_DATA_ENTRY, r0 - mov.l .LPMB_DATA, r1 - mov.l .LFIRST_ADDR_ENTRY, r2 - mov.l .LPMB_ADDR, r3 - - mov #0, r10 - - /* - * r0 = PMB_DATA data field - * r1 = PMB_DATA address field - * r2 = PMB_ADDR data field - * r3 = PMB_ADDR address field - * r4 = PMB_E_SHIFT - * r5 = remaining amount of RAM to map - * r6 = PMB mapping size we're trying to use - * r7 = cached_to_uncached - * r8 = scratch register - * r9 = scratch register - * r10 = number of PMB entries we've setup - */ __PMB_ITER_BY_SIZE(512) __PMB_ITER_BY_SIZE(128) __PMB_ITER_BY_SIZE(64) __PMB_ITER_BY_SIZE(16) - /* Update cached_to_uncached */ + /* + * Now that we can access it, update cached_to_uncached. + */ mov.l .Lcached_to_uncached, r0 mov.l r7, @r0 |