Mapped kernel support for Broadcom XLP
cover Mapped kernel support for Broadcom XLP
This patchset adds support for loading a XLR/XLP kernel compiled with a CKSEG2 load address.
The changes are to:
- move the existing MAPPED_KERNEL option from sgi-ip27 to common config
- Add a plat_mem_fixup function to arch_mem_init which will allow the platform to calculate the kernel wired TLB entries and save them so that all the CPUs can set them up at boot.
- Update PAGE_OFFSET, MAP_BASE and MODULE_START when mapped kernel is enabled.
- Update compressed kernel code to generate the final executable in KSEG0 and map the load address of the embedded kernel before loading it.
- Use wired entries of sizes 256M/1G/4G to map the available memory on XLP9xx and XLP2xx
Comments and suggestions welcome.
JC.
Ashok Kumar (1):
MIPS: Netlogic: Mapped kernel support
Jayachandran C (4):
MIPS: Make MAPPED_KERNEL config option common
MIPS: Add platform function to fixup memory
MIPS: Compress MAPPED kernels
MIPS: Netlogic: Map kernel with 1G/4G pages on XLPII
arch/mips/Kconfig | 7 + arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 9 + arch/mips/boot/compressed/decompress.c | 6 +- arch/mips/boot/compressed/head.S | 5 + .../include/asm/mach-netlogic/kernel-entry-init.h | 50 ++++ arch/mips/include/asm/mach-netlogic/spaces.h | 25 ++ arch/mips/include/asm/netlogic/common.h | 15 ++ arch/mips/include/asm/pgtable-64.h | 4 + arch/mips/kernel/setup.c | 4 + arch/mips/mm/tlb-r4k.c | 2 + arch/mips/netlogic/Platform | 5 + arch/mips/netlogic/common/Makefile | 1 + arch/mips/netlogic/common/memory.c | 247 ++++++++++++++++++++ arch/mips/netlogic/common/reset.S | 40 ++++ arch/mips/netlogic/common/smpboot.S | 16 +- arch/mips/netlogic/xlp/setup.c | 14 -- arch/mips/netlogic/xlr/setup.c | 3 +- arch/mips/netlogic/xlr/wakeup.c | 7 +- arch/mips/sgi-ip27/Kconfig | 8 - 19 files changed, 440 insertions(+), 28 deletions(-) create mode 100644 arch/mips/include/asm/mach-netlogic/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-netlogic/spaces.h create mode 100644 arch/mips/netlogic/common/memory.c
Signature · 1 line
1.7.9.5
PATCH 1/4 MIPS: Add platform function to fixup memory
Provide a function plat_mem_fixup() that is called after memory command line args are parsed. This can be used to fixup memory regions including those passed thru device tree and command line.
In XLR/XLP, use this to reduce the size of the memory segments so that prefetch will not access illegal addresses.
--- arch/mips/kernel/setup.c | 4 +++ arch/mips/netlogic/common/Makefile | 1 + arch/mips/netlogic/common/memory.c | 53 ++++++++++++++++++++++++++++++++++++ arch/mips/netlogic/xlp/setup.c | 14 ---------- arch/mips/netlogic/xlr/setup.c | 3 +- 5 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 arch/mips/netlogic/common/memory.c
arch/mips/kernel/setup.c +4 -0
@@ -610,6 +610,7 @@ static void __init request_crashkernel(struct resource *res)static void __init arch_mem_init (char **cmdline_p) {extern void plat_mem_setup (void ); +extern void plat_mem_fixup (void );/* call board setup routine */ plat_mem_setup ();
@@ -653,6 +654,9 @@ static void __init arch_mem_init(char **cmdline_p)pr_info ("User-defined physical RAM map:\n" );print_memory_map (); } +#if defined(CONFIG_CPU_XLP ) || defined(CONFIG_CPU_XLR ) +plat_mem_fixup (); +#endif bootmem_init ();#ifdef CONFIG_PROC_VMCORE
arch/mips/netlogic/common/Makefile +1 -0
@@ -1,5 +1,6 @@ obj-y += irq.o time.o obj-y += nlm-dma.o obj-y += reset.o +obj-y += memory.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_EARLY_PRINTK) += earlycons.o
arch/mips/netlogic/common/memory.c new file +53 -0
53 lines not on this page · raw message
arch/mips/netlogic/xlp/setup.c +0 -14
@@ -65,18 +65,6 @@ static void nlm_linux_exit(void)cpu_wait (); } -static void nlm_fixup_mem (void ) -{ -const int pref_backup =512 ; -int i; - -for (i =0 ; i < boot_mem_map.nr_map; i++) { -if (boot_mem_map.map[i].type !=BOOT_MEM_RAM ) -continue ; - boot_mem_map.map[i].size -= pref_backup; - } -} -static void __init xlp_init_mem_from_bars (void ) {uint64_t map[16 ];
@@ -115,8 +103,6 @@ void __init plat_mem_setup(void)pr_info ("Using DRAM BARs for memory map.\n" );xlp_init_mem_from_bars (); } -/* Calculate and setup wired entries for mapped kernel */ -nlm_fixup_mem (); }const char *get_system_type (void )
arch/mips/netlogic/xlr/setup.c +1 -2
@@ -144,7 +144,6 @@ static void prom_add_memory(void) {struct nlm_boot_mem_map *bootm;u64 start, size; -u64 pref_backup =512 ;/* avoid pref walking beyond end */ int i; bootm = (void *)(long )nlm_prom_info.psb_mem_map;
@@ -158,7 +157,7 @@ static void prom_add_memory(void)if (i ==0 && start ==0 && size ==0x0c000000 ) size =0x0ff00000 ; -add_memory_region (start, size - pref_backup,BOOT_MEM_RAM ); +add_memory_region (start, size,BOOT_MEM_RAM ); } }
Signature · 1 line
1.7.9.5
PATCH 2/4 MIPS: Netlogic: Mapped kernel support
In reply to Jayachandran CFrom: Ashok Kumar <[email protected]>
Add support for loading kernel compiled for CKSEG2. This is done by adding wired TLB entries for the CKSEG2 at boot up and slave CPU init.
In 64-bit we will map the whole physical memory to mapped area starting at XKSEG and move the MAP_OFFSET higher to accomodate this.
[[email protected]: Updated to add support 32-bit, and to add XLR
support. Also made some code cleanups and style fixes.]
--- arch/mips/Kconfig | 9 +- .../include/asm/mach-netlogic/kernel-entry-init.h | 50 +++++++++ arch/mips/include/asm/mach-netlogic/spaces.h | 25 +++++ arch/mips/include/asm/netlogic/common.h | 14 +++ arch/mips/include/asm/pgtable-64.h | 4 + arch/mips/mm/tlb-r4k.c | 2 + arch/mips/netlogic/Platform | 5 + arch/mips/netlogic/common/memory.c | 113 ++++++++++++++++++++ arch/mips/netlogic/common/reset.S | 40 +++++++ arch/mips/netlogic/common/smpboot.S | 16 ++- arch/mips/netlogic/xlr/wakeup.c | 7 +- 11 files changed, 277 insertions(+), 8 deletions(-) create mode 100644 arch/mips/include/asm/mach-netlogic/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-netlogic/spaces.h
arch/mips/Kconfig +4 -5
@@ -2095,12 +2095,11 @@ config SB1_PASS_2_1_WORKAROUNDS config MAPPED_KERNEL bool "Mapped kernel support" - depends on SGI_IP27 + depends on SGI_IP27 || CPU_XLP || CPU_XLR help - Change the way a Linux kernel is loaded into memory on a MIPS64 - machine. This is required in order to support text replication on - NUMA. If you need to understand it, read the source code. - + Enable compiling and loading the Linux kernel compiled to + run in the KSEG2/CKSEG2. Wired TLB entries are used to map + the available DRAM into either XKSEG or KSEG2. config 64BIT_PHYS_ADDR bool
arch/mips/include/asm/mach-netlogic/kernel-entry-init.h new file +50 -0
50 lines not on this page · raw message
arch/mips/include/asm/mach-netlogic/spaces.h new file +25 -0
@@ -0,0 +1,25 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle +* Copyright (C) 2000, 2002 Maciej W. Rozycki +* Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. +*/ +#ifndef _ASM_NETLOGIC_SPACES_H +#define _ASM_NETLOGIC_SPACES_H + +#if defined(CONFIG_MAPPED_KERNEL ) +#ifdef CONFIG_32BIT +#define PAGE_OFFSET CKSEG2 +#define MAP_BASE CKSEG3 +#else +#define PAGE_OFFSET _AC(0xc000000000000000, UL) +#define MAP_BASE _AC(0xd000000000000000, UL) +#endif +#endif /* CONFIG_MAPPED_KERNEL */ + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_NETLOGIC_SPACES_H */
arch/mips/include/asm/netlogic/common.h +14 -0
@@ -47,6 +47,17 @@#define BOOT_NMI_LOCK 4#define BOOT_NMI_HANDLER 8 +/* TLB entry save area for mapped kernel */ +#define BOOT_NTLBS 64 +#define BOOT_TLBS_START 72 +#define BOOT_TLB_SIZE 32 + +/* four u64 entries per TLB */ +#define BOOT_TLB_ENTRYHI 0 +#define BOOT_TLB_ENTRYLO0 1 +#define BOOT_TLB_ENTRYLO1 2 +#define BOOT_TLB_PAGEMASK 3 +/* CPU ready flags for each CPU */ #define BOOT_CPU_READY 2048
@@ -90,6 +101,9 @@ extern char nlm_reset_entry[], nlm_reset_entry_end[];/* SWIOTLB */ extern struct dma_map_ops nlm_swiotlb_dma_ops; +/* mapped kernel */ +void nlm_setup_wired_tlbs (void ); +extern unsigned int nlm_threads_per_core;extern cpumask_t nlm_cpumask;
arch/mips/include/asm/pgtable-64.h +4 -0
@@ -135,7 +135,11 @@#if defined(CONFIG_MODULES ) && defined(KBUILD_64BIT_SYM32 ) && \VMALLOC_START !=CKSSEG /* Load modules into 32bit-compatible segment. */ +#ifdef CONFIG_MAPPED_KERNEL +#define MODULE_START CKSEG3/* don't overlap with mapped kernel */ +#else #define MODULE_START CKSSEG +#endif #define MODULE_END (FIXADDR_START-2*PAGE_SIZE)#endif
arch/mips/mm/tlb-r4k.c +2 -0
@@ -431,7 +431,9 @@ void tlb_init(void)* be set to fixed-size pages. */ write_c0_pagemask (PM_DEFAULT_MASK ); +#ifndef CONFIG_MAPPED_KERNEL write_c0_wired (0 ); +#endif if (current_cpu_type () ==CPU_R10000 ||current_cpu_type () ==CPU_R12000 ||current_cpu_type () ==CPU_R14000 )
arch/mips/netlogic/Platform +5 -0
@@ -14,4 +14,9 @@ cflags-$(CONFIG_CPU_XLP) += $(call cc-option,-march=xlp,-march=mips64r2) # NETLOGIC processor support # platform-$(CONFIG_NLM_COMMON) += netlogic/ + +ifdef CONFIG_MAPPED_KERNEL +load-$(CONFIG_NLM_COMMON) += 0xffffffffc0100000 +else load-$(CONFIG_NLM_COMMON) += 0xffffffff80100000 +endif
arch/mips/netlogic/common/memory.c +113 -0
127 lines not on this page · raw message
arch/mips/netlogic/common/reset.S +40 -0
@@ -43,6 +43,7 @@ #include <asm/asmmacro.h> #include <asm/addrspace.h> +#include <kernel-entry-init.h> #include <asm/netlogic/common.h> #include <asm/netlogic/xlp-hal/iomap.h>
@@ -254,6 +255,10 @@ EXPORT(nlm_boot_siblings) PTR_ADDU t1, v1 li t2, 1 sw t2, 0(t1) + + /* mapped first wired TLB for mapped kernel */ + kernel_entry_setup + /* Wait until NMI hits */ 3: wait b 3b
@@ -278,3 +283,38 @@ LEAF(nlm_init_boot_cpu) jr ra nop END(nlm_init_boot_cpu) + +LEAF(nlm_setup_wired_tlbs) +#ifdef CONFIG_MAPPED_KERNEL + li t0, CKSEG1ADDR(RESET_DATA_PHYS) + lw t3, BOOT_NTLBS(t0) + ADDIU t0, t0, BOOT_TLBS_START + li t1, 1 /* entry 0 is wired at boot, start at 1 */ + addiu t3, 1 /* final number of wired entries */ + +1: sltu v1, t1, t3 + beqz v1, 2f + nop + ld a0, (8 * BOOT_TLB_ENTRYLO0)(t0) + dmtc0 a0, CP0_ENTRYLO0 + ld a1, (8 * BOOT_TLB_ENTRYLO1)(t0) + dmtc0 a1, CP0_ENTRYLO1 + ld a2, (8 * BOOT_TLB_ENTRYHI)(t0) + dmtc0 a2, CP0_ENTRYHI + ld a2, (8 * BOOT_TLB_PAGEMASK)(t0) + dmtc0 a2, CP0_PAGEMASK + mtc0 t1, CP0_INDEX + _ehb + tlbwi + ADDIU t0, BOOT_TLB_SIZE + addiu t1, 1 + b 1b + nop +2: + mtc0 t3, CP0_WIRED + JRHB ra +#else + jr ra +#endif + nop +END(nlm_setup_wired_tlbs)
arch/mips/netlogic/common/smpboot.S +14 -2
@@ -41,6 +41,7 @@ #include <asm/asmmacro.h> #include <asm/addrspace.h> +#include <kernel-entry-init.h> #include <asm/netlogic/common.h> #include <asm/netlogic/xlp-hal/iomap.h>
@@ -80,6 +81,13 @@ NESTED(nlm_boot_secondary_cpus, 16, sp) ori t1, ST0_KX #endif mtc0 t1, CP0_STATUS + +#ifdef CONFIG_64BIT + /* set the full wired TLBs needed for mapped kernel */ + jal nlm_setup_wired_tlbs + nop +#endif + PTR_LA t1, nlm_next_sp PTR_L sp, 0(t1) PTR_LA t1, nlm_next_gp
@@ -136,8 +144,12 @@ NESTED(nlm_rmiboot_preboot, 16, sp) or t1, t2, v1 /* put in new value */ mtcr t1, t0 /* update core control */ +1: + /* mapped first wired TLB for mapped kernel */ + kernel_entry_setup + /* wait for NMI to hit */ -1: wait - b 1b +2: wait + b 2b nop END(nlm_rmiboot_preboot)
arch/mips/netlogic/xlr/wakeup.c +6 -1
@@ -53,6 +53,7 @@ int xlr_wakeup_secondary_cpus(void)struct nlm_soc_info *nodep;unsigned int i, j, boot_cpu;volatile u32 *cpu_ready =nlm_get_boot_data (BOOT_CPU_READY ); +void *handler;/* * In case of RMI boot, hit with NMI to get the cores
@@ -60,7 +61,11 @@ int xlr_wakeup_secondary_cpus(void)*/ nodep =nlm_get_node (0 ); boot_cpu =hard_smp_processor_id (); -nlm_set_nmi_handler (nlm_rmiboot_preboot); + handler = nlm_rmiboot_preboot; +#ifdef CONFIG_MAPPED_KERNEL + handler = (void *)CKSEG0ADDR ((long )handler); +#endif +nlm_set_nmi_handler (handler);for (i =0 ; i <NR_CPUS ; i++) {if (i == boot_cpu || !cpumask_test_cpu (i, &nlm_cpumask))continue ;
Signature · 1 line
1.7.9.5
PATCH 3/4 MIPS: Compress MAPPED kernels
In reply to Jayachandran CAdd code to build the wrapper in KSEG0, which in turn loads the mapped kernel.
--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 9 +++++++++ arch/mips/boot/compressed/decompress.c | 6 +++++- arch/mips/boot/compressed/head.S | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-)
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +9 -0
@@ -51,6 +51,15 @@ int main(int argc, char *argv[]) vmlinuz_load_addr += (16 - vmlinux_size %16 ); +/* handle 32/64 bit mapped addresses */ +if (vmlinuz_load_addr >=0xffffffffc0000000ULL ) + vmlinuz_load_addr =0xffffffff80000000ull | + (vmlinuz_load_addr &0x1fffffff ); +if (vmlinuz_load_addr >=0xc0000000ULL && + vmlinuz_load_addr <0xffffffffULL ) + vmlinuz_load_addr =0x80000000ull | + (vmlinuz_load_addr &0x1fffffff ); +printf ("0x%llx\n" , vmlinuz_load_addr);return EXIT_SUCCESS ;
arch/mips/boot/compressed/decompress.c +5 -1
@@ -70,6 +70,7 @@ void error(char *x)void decompress_kernel (unsigned long boot_heap_start) {unsigned long zimage_start, zimage_size; +unsigned long long loadaddr =VMLINUX_LOAD_ADDRESS_ULL ; zimage_start = (unsigned long )(&__image_begin); zimage_size = (unsigned long)(&__image_end) -
@@ -90,9 +91,12 @@ void decompress_kernel(unsigned long boot_heap_start)puthex (VMLINUX_LOAD_ADDRESS_ULL );puts ("\n" ); +#ifdef CONFIG_MAPPED_KERNEL + loadaddr =CKSEG0ADDR (loadaddr); +#endif /* Decompress the kernel with according algorithm */ decompress ((char *)zimage_start, zimage_size,0 ,0 , - (void *)VMLINUX_LOAD_ADDRESS_ULL ,0 , error); + (void *)(unsigned long )loadaddr,0 , error);/* FIXME: should we flush cache here? */ puts ("Now, booting the kernel...\n" );
arch/mips/boot/compressed/head.S +5 -0
@@ -14,6 +14,7 @@ #include <asm/asm.h> #include <asm/regdef.h> +#include <asm/addrspace.h> .set noreorder .cprestore
@@ -44,7 +45,11 @@ start: move a1, s1 move a2, s2 move a3, s3 +#ifdef CONFIG_MAPPED_KERNEL + PTR_LI k0, CKSEG0ADDR(KERNEL_ENTRY) +#else PTR_LI k0, KERNEL_ENTRY +#endif jr k0 nop 3:
Signature · 1 line
1.7.9.5
PATCH 4/4 MIPS: Netlogic: Map kernel with 1G/4G pages on XLPII
In reply to Jayachandran CXLP2XX and XLP9XX support 1G and 4G pages. Use this for mapping physical memory in Mapped Kernel support.
Reduces the number of WIRED entries in systems with more RAM.
--- arch/mips/netlogic/common/memory.c | 237 ++++++++++++++++++++++++------------ 1 file changed, 159 insertions(+), 78 deletions(-)
arch/mips/netlogic/common/memory.c +159 -78
@@ -34,6 +34,7 @@#include <linux/kernel.h> #include <linux/types.h> +#include <linux/sizes.h> #include <asm/bootinfo.h> #include <asm/pgtable.h>
@@ -41,100 +42,187 @@#include <asm/tlb.h> #include <asm/netlogic/common.h> +#include <asm/netlogic/xlp-hal/xlp.h> -#define TLBSZ (256 * 1024 * 1024) -#define PM_TLBSZ PM_256M -#define PTE_MAPKERN (pa) (((pa >> 12) << 6) | 0x2f) +#define SZ_4G (4ull * 1024 * 1024 * 1024) +#define PM_4G 0x1ffffe000 +#define MINPGSZ SZ_256M + +#define PTE_MAPKERN (pa) ((((pa) >> 12) << 6) | 0x2f)#define TLB_MAXWIRED 28static const int prefetch_backup =512 ;#if defined(CONFIG_MAPPED_KERNEL ) && defined(CONFIG_64BIT ) -static void nlm_tlb_align (struct boot_mem_map_entry *map) + +/* To track the allocated area of a boot_mem_map segment */ +struct alloc_entry { +/* Start and end of the va mapped */ +unsigned long long start; +unsigned long long end; + +/* When just one of lo0/lo1 is used, the valid area is half of above */ +unsigned long long astart; +unsigned long long aend; +} alloc_map[32 ]; + +static inline int addtlb (phys_addr_t pa,u64 pgsz,u64 pmask, +unsigned int validmask,struct alloc_entry *ae) { -phys_t astart, aend, start, end; +phys_addr_t endpa; +u64 *t; +u32 *tlbcount; +int ntlb; + + tlbcount = (u32 *)nlm_get_boot_data (BOOT_NTLBS ); + ntlb = *tlbcount; + endpa = pa +2 * pgsz; - start = map->addr; - end = start + map->size; +pr_debug ("%2d - pa0 %llx pa1 %llx pgsz %llx valid %x\n" , + ntlb, pa, endpa, pgsz, validmask); +if (ntlb ==TLB_MAXWIRED ) { +pr_err ("Ran out of TLB entries pa %llx pgsz %llx\n" , pa, pgsz); +return -1 ; + } -/* fudge first entry for now */ -if (start <0x10000000 ) { - start =0 ; - end =0x10000000 ; + t =nlm_get_boot_data (BOOT_TLBS_START ); + t += ntlb * (BOOT_TLB_SIZE /sizeof (t[0 ])); + t[BOOT_TLB_ENTRYHI ] = pa +PAGE_OFFSET ; + t[BOOT_TLB_ENTRYLO0 ] = (validmask &0x1 ) ?PTE_MAPKERN (pa) :1 ; + t[BOOT_TLB_ENTRYLO1 ] = (validmask &0x2 ) ?PTE_MAPKERN (pa + pgsz) :1 ; + t[BOOT_TLB_PAGEMASK ] = pmask; + +if (pa < ae->start) { + ae->astart = ae->start = pa; +if ((validmask &0x1 ) ==0 ) + ae->astart += pgsz; } - astart =round_up (start,TLBSZ ); - aend =round_down (end,TLBSZ ); -if (aend <= astart) { -pr_info ("Boot mem map: discard seg %lx-%lx\n" , - (unsigned long )start, (unsigned long )end); - map->size =0 ; -return ; +if (endpa > ae->end) { + ae->aend = ae->end = endpa; +if ((validmask &0x2 ) ==0 ) + ae->aend -= pgsz; } -if (astart != start || aend != end) { -if (start !=0 ) { - map->addr = astart; - map->size = aend - astart; - } -pr_info ("Boot mem map: %lx - %lx -> %lx-%lx\n" , - (unsigned long )start, (unsigned long )end, - (unsigned long )astart, (unsigned long )aend); - }else -pr_info ("Boot mem map: added %lx - %lx\n" , - (unsigned long )astart, (unsigned long )aend); + *tlbcount = ntlb +1 ; +return 0 ; } +/* +* Calculate the TLB entries needed to wire dowm the memory map +* +* Tries to use the largest pagesizes possible, discards memory which +* cannot be mapped +*/ static void nlm_calc_wired_tlbs (void ) { -u64 *tlbarr; -u32 *tlbcount; -u64 lo0, lo1, vaddr; -phys_addr_t astart, aend, p; -unsigned long bootdata =CKSEG1ADDR (RESET_DATA_PHYS ); -int i, pos; +u64 pgsz, pgmask, p; +phys_addr_t astart, aend, pend, nstart; +phys_addr_t tstart, tend, mstart, mend; +struct boot_mem_map_entry *bmap; +int i, nr_map; + + nr_map = boot_mem_map.nr_map; + bmap = boot_mem_map.map; + +for (i =0 ; i < nr_map; i++) { + alloc_map[i].start = alloc_map[i].astart = ~0ull ; + alloc_map[i].end = alloc_map[i].aend =0 ; + } - tlbarr = (u64 *)(bootdata +BOOT_TLBS_START ); - tlbcount = (u32 *)(bootdata +BOOT_NTLBS ); +/* force the first entry with one 256M lo0 page */ +addtlb (0 ,0x10000000 ,PM_256M ,0x1 , &alloc_map[0 ]); - pos =0 ; -for (i =0 ; i < boot_mem_map.nr_map; i++) { -if (boot_mem_map.map[i].type !=BOOT_MEM_RAM ) -continue ; - astart = boot_mem_map.map[i].addr; - aend = astart + boot_mem_map.map[i].size; +/* starting page size and page mask */ +if (cpu_is_xlpii ()) { + pgsz =SZ_4G ; + pgmask =PM_4G ; + }else { + pgsz =SZ_256M ; + pgmask =PM_256M ; + } -/* fudge first entry for now */ -if (astart <0x10000000 ) { - astart =0 ; - aend =0x10000000 ; - } -for (p =round_down (astart,2 *TLBSZ ); - p <round_up (aend,2 *TLBSZ );) { - vaddr =PAGE_OFFSET + p; - lo0 = (p >= astart) ?PTE_MAPKERN (p) :1 ; - p +=TLBSZ ; - lo1 = (p < aend) ?PTE_MAPKERN (p) :1 ; - p +=TLBSZ ; - - tlbarr[BOOT_TLB_ENTRYHI ] = vaddr; - tlbarr[BOOT_TLB_ENTRYLO0 ] = lo0; - tlbarr[BOOT_TLB_ENTRYLO1 ] = lo1; - tlbarr[BOOT_TLB_PAGEMASK ] =PM_TLBSZ ; - tlbarr += (BOOT_TLB_SIZE /sizeof (tlbarr[0 ])); - -if (++pos >=TLB_MAXWIRED ) { -pr_err ("Ran out of TLBs at %llx, " , - (unsigned long long )p); -pr_err ("Discarding rest of memory!\n" ); - boot_mem_map.nr_map = i +1 ; - boot_mem_map.map[i].size = p - - boot_mem_map.map[i].addr; +/* do multiple passes with successively smaller page sizes */ +for (; pgsz >=MINPGSZ ; pgsz /=4 , pgmask = (pgmask >>2 ) ^0x1800 ) { +for (i =0 ; i < nr_map; i++) { +if (bmap[i].type !=BOOT_MEM_RAM ) +continue ; + +/* previous mapping end and next mapping start */ + pend = alloc_map[i -1 ].end; + nstart = (i == nr_map -1 ) ? ~0ull : bmap[i +1 ].addr; + +/* mem block start and end */ + mstart =round_up (bmap[i].addr,MINPGSZ ); + mend =round_down (bmap[i].addr + bmap[i].size,MINPGSZ ); + +/* allocated area in the memory block, start and end */ + astart = alloc_map[i].start; + aend = alloc_map[i].end; + +/* skip fully mapped blocks */ +if (mstart >= astart && mend <= aend) +continue ; + +/* boundaries aligned to the current page size */ + tstart =round_up (mstart,2 * pgsz); + tend =round_down (mend,2 * pgsz); +if (tstart > tend) +continue ; + +/* use LO1 of a TLB entry */ +if (mstart + pgsz == tstart && pend <= mstart - pgsz) +if (addtlb (mstart - pgsz, pgsz, + pgmask,0x2 , &alloc_map[i])) goto out; + +for (p = tstart; p < tend;) { +if (astart < aend && p == astart) { + p = aend; +continue ; } +if (addtlb (p, pgsz, pgmask,0x3 , &alloc_map[i])) + goto out; + p +=2 * pgsz; + } + +/* use LO0 of a TLB entry */ +if (tend + pgsz == mend && nstart >= mend + pgsz) +if (addtlb (tend, pgsz, + pgmask,0x1 , &alloc_map[i])) + goto out; } } out: - *tlbcount = pos; -pr_info ("%d TLB entires used for mapped kernel.\n" , pos); +for (i =0 ; i < nr_map; i++) { + mstart = bmap[i].addr; + mend = bmap[i].addr + bmap[i].size; + astart = alloc_map[i].astart; + aend = alloc_map[i].aend; + +pr_info ("%2d alloc: %10llx %10llx mem %10llx %10llx\n" , i, + astart, aend, bmap[i].addr, + bmap[i].addr + bmap[i].size); +if (astart >= aend) { + bmap[i].size =0 ; +pr_info ("%2d: Discarded %#10llx - %#10llx\n" , i, + (unsigned long long )mstart, + (unsigned long long )mend); +continue ; + } +if (bmap[i].addr < astart) { + bmap[i].addr = astart; +pr_info ("%2d: Discarded %#10llx - %#10llx\n" , i, + (unsigned long long )bmap[i].addr, + (unsigned long long )astart); + } +if (mend > aend) { + bmap[i].size = aend - bmap[i].addr; +pr_info ("%2d: Discarded %#10llx - %#10llx\n" , i, + (unsigned long long )aend, + (unsigned long long )mend); + } + } +pr_info ("%d TLB entires used for mapped kernel.\n" , + *(u32 *)nlm_get_boot_data (BOOT_NTLBS )); }#endif
@@ -143,13 +231,6 @@ void __init plat_mem_fixup(void)int i;#if defined(CONFIG_MAPPED_KERNEL ) && defined(CONFIG_64BIT ) -/* trim memory regions to PM_TLBSZ boundaries */ -for (i =0 ; i < boot_mem_map.nr_map; i++) { -if (boot_mem_map.map[i].type !=BOOT_MEM_RAM ) -continue ; -nlm_tlb_align (&boot_mem_map.map[i]); - } -/* calculate and save wired TLB entries */ nlm_calc_wired_tlbs ();
Signature · 1 line
1.7.9.5
Quoted 16 lines · Jayachandran C
This patchset adds support for loading a XLR/XLP kernel compiled with a CKSEG2 load address.
The changes are to:
- move the existingMAPPED_KERNELoption from sgi-ip27 to common config
- Add aplat_mem_fixupfunction toarch_mem_initwhich will allow the platform to calculate the kernel wired TLB entries and save them so that all the CPUs can set them up at boot.
- UpdatePAGE_OFFSET,MAP_BASEandMODULE_STARTwhen mapped kernel is enabled.
- Update compressed kernel code to generate the final executable in KSEG0 and map the load address of the embedded kernel before loading it.
- Use wired entries of sizes 256M/1G/4G to map the available memory on XLP9xx and XLP2xx
Quoted 1 line
Comments and suggestions welcome.
Looks like I missed a patch while sending this out. Will send the full patchset again (and fix it up in patchwork).
JC.
PATCH 1/5 MIPS: Make MAPPED_KERNEL config option common
In reply to Jayachandran CThis will be needed for the mapped kernel patches for Netlogic XLP.
--- arch/mips/Kconfig | 8 ++++++++ arch/mips/sgi-ip27/Kconfig | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-)
arch/mips/Kconfig +8 -0
@@ -2093,6 +2093,14 @@ config SB1_PASS_2_1_WORKAROUNDS depends on CPU_SB1 && CPU_SB1_PASS_2 default y +config MAPPED_KERNEL + bool "Mapped kernel support" + depends on SGI_IP27 + help + Change the way a Linux kernel is loaded into memory on a MIPS64 + machine. This is required in order to support text replication on + NUMA. If you need to understand it, read the source code. + config 64BIT_PHYS_ADDR bool
arch/mips/sgi-ip27/Kconfig +0 -8
@@ -21,14 +21,6 @@ config SGI_SN_N_MODE endchoice -config MAPPED_KERNEL - bool "Mapped kernel support" - depends on SGI_IP27 - help - Change the way a Linux kernel is loaded into memory on a MIPS64 - machine. This is required in order to support text replication on - NUMA. If you need to understand it, read the source code. - config REPLICATE_KTEXT bool "Kernel text replication support" depends on SGI_IP27
Signature · 1 line
1.7.9.5
PATCH 2/5 MIPS: Add platform function to fixup memory
Provide a function plat_mem_fixup() that is called after memory command line args are parsed. This can be used to fixup memory regions including those passed thru device tree and command line.
In XLR/XLP, use this to reduce the size of the memory segments so that prefetch will not access illegal addresses.
--- arch/mips/kernel/setup.c | 4 +++ arch/mips/netlogic/common/Makefile | 1 + arch/mips/netlogic/common/memory.c | 53 ++++++++++++++++++++++++++++++++++++ arch/mips/netlogic/xlp/setup.c | 14 ---------- arch/mips/netlogic/xlr/setup.c | 3 +- 5 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 arch/mips/netlogic/common/memory.c
arch/mips/kernel/setup.c +4 -0
@@ -610,6 +610,7 @@ static void __init request_crashkernel(struct resource *res)static void __init arch_mem_init (char **cmdline_p) {extern void plat_mem_setup (void ); +extern void plat_mem_fixup (void );/* call board setup routine */ plat_mem_setup ();
@@ -653,6 +654,9 @@ static void __init arch_mem_init(char **cmdline_p)pr_info ("User-defined physical RAM map:\n" );print_memory_map (); } +#if defined(CONFIG_CPU_XLP ) || defined(CONFIG_CPU_XLR ) +plat_mem_fixup (); +#endif bootmem_init ();#ifdef CONFIG_PROC_VMCORE
arch/mips/netlogic/common/Makefile +1 -0
@@ -1,5 +1,6 @@ obj-y += irq.o time.o obj-y += nlm-dma.o obj-y += reset.o +obj-y += memory.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_EARLY_PRINTK) += earlycons.o
arch/mips/netlogic/common/memory.c new file +53 -0
53 lines not on this page · raw message
arch/mips/netlogic/xlp/setup.c +0 -14
@@ -65,18 +65,6 @@ static void nlm_linux_exit(void)cpu_wait (); } -static void nlm_fixup_mem (void ) -{ -const int pref_backup =512 ; -int i; - -for (i =0 ; i < boot_mem_map.nr_map; i++) { -if (boot_mem_map.map[i].type !=BOOT_MEM_RAM ) -continue ; - boot_mem_map.map[i].size -= pref_backup; - } -} -static void __init xlp_init_mem_from_bars (void ) {uint64_t map[16 ];
@@ -115,8 +103,6 @@ void __init plat_mem_setup(void)pr_info ("Using DRAM BARs for memory map.\n" );xlp_init_mem_from_bars (); } -/* Calculate and setup wired entries for mapped kernel */ -nlm_fixup_mem (); }const char *get_system_type (void )
arch/mips/netlogic/xlr/setup.c +1 -2
@@ -144,7 +144,6 @@ static void prom_add_memory(void) {struct nlm_boot_mem_map *bootm;u64 start, size; -u64 pref_backup =512 ;/* avoid pref walking beyond end */ int i; bootm = (void *)(long )nlm_prom_info.psb_mem_map;
@@ -158,7 +157,7 @@ static void prom_add_memory(void)if (i ==0 && start ==0 && size ==0x0c000000 ) size =0x0ff00000 ; -add_memory_region (start, size - pref_backup,BOOT_MEM_RAM ); +add_memory_region (start, size,BOOT_MEM_RAM ); } }
Signature · 1 line
1.7.9.5
PATCH 3/5 MIPS: Netlogic: Mapped kernel support
In reply to Jayachandran CFrom: Ashok Kumar <[email protected]>
Add support for loading kernel compiled for CKSEG2. This is done by adding wired TLB entries for the CKSEG2 at boot up and slave CPU init.
In 64-bit we will map the whole physical memory to mapped area starting at XKSEG and move the MAP_OFFSET higher to accomodate this.
[[email protected]: Updated to add support 32-bit, and to add XLR
support. Also made some code cleanups and style fixes.]
--- arch/mips/Kconfig | 9 +- .../include/asm/mach-netlogic/kernel-entry-init.h | 50 +++++++++ arch/mips/include/asm/mach-netlogic/spaces.h | 25 +++++ arch/mips/include/asm/netlogic/common.h | 14 +++ arch/mips/include/asm/pgtable-64.h | 4 + arch/mips/mm/tlb-r4k.c | 2 + arch/mips/netlogic/Platform | 5 + arch/mips/netlogic/common/memory.c | 113 ++++++++++++++++++++ arch/mips/netlogic/common/reset.S | 40 +++++++ arch/mips/netlogic/common/smpboot.S | 16 ++- arch/mips/netlogic/xlr/wakeup.c | 7 +- 11 files changed, 277 insertions(+), 8 deletions(-) create mode 100644 arch/mips/include/asm/mach-netlogic/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-netlogic/spaces.h
arch/mips/Kconfig +4 -5
@@ -2095,12 +2095,11 @@ config SB1_PASS_2_1_WORKAROUNDS config MAPPED_KERNEL bool "Mapped kernel support" - depends on SGI_IP27 + depends on SGI_IP27 || CPU_XLP || CPU_XLR help - Change the way a Linux kernel is loaded into memory on a MIPS64 - machine. This is required in order to support text replication on - NUMA. If you need to understand it, read the source code. - + Enable compiling and loading the Linux kernel compiled to + run in the KSEG2/CKSEG2. Wired TLB entries are used to map + the available DRAM into either XKSEG or KSEG2. config 64BIT_PHYS_ADDR bool
arch/mips/include/asm/mach-netlogic/kernel-entry-init.h new file +50 -0
50 lines not on this page · raw message
arch/mips/include/asm/mach-netlogic/spaces.h new file +25 -0
@@ -0,0 +1,25 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle +* Copyright (C) 2000, 2002 Maciej W. Rozycki +* Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. +*/ +#ifndef _ASM_NETLOGIC_SPACES_H +#define _ASM_NETLOGIC_SPACES_H + +#if defined(CONFIG_MAPPED_KERNEL ) +#ifdef CONFIG_32BIT +#define PAGE_OFFSET CKSEG2 +#define MAP_BASE CKSEG3 +#else +#define PAGE_OFFSET _AC(0xc000000000000000, UL) +#define MAP_BASE _AC(0xd000000000000000, UL) +#endif +#endif /* CONFIG_MAPPED_KERNEL */ + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_NETLOGIC_SPACES_H */
arch/mips/include/asm/netlogic/common.h +14 -0
@@ -47,6 +47,17 @@#define BOOT_NMI_LOCK 4#define BOOT_NMI_HANDLER 8 +/* TLB entry save area for mapped kernel */ +#define BOOT_NTLBS 64 +#define BOOT_TLBS_START 72 +#define BOOT_TLB_SIZE 32 + +/* four u64 entries per TLB */ +#define BOOT_TLB_ENTRYHI 0 +#define BOOT_TLB_ENTRYLO0 1 +#define BOOT_TLB_ENTRYLO1 2 +#define BOOT_TLB_PAGEMASK 3 +/* CPU ready flags for each CPU */ #define BOOT_CPU_READY 2048
@@ -90,6 +101,9 @@ extern char nlm_reset_entry[], nlm_reset_entry_end[];/* SWIOTLB */ extern struct dma_map_ops nlm_swiotlb_dma_ops; +/* mapped kernel */ +void nlm_setup_wired_tlbs (void ); +extern unsigned int nlm_threads_per_core;extern cpumask_t nlm_cpumask;
arch/mips/include/asm/pgtable-64.h +4 -0
@@ -135,7 +135,11 @@#if defined(CONFIG_MODULES ) && defined(KBUILD_64BIT_SYM32 ) && \VMALLOC_START !=CKSSEG /* Load modules into 32bit-compatible segment. */ +#ifdef CONFIG_MAPPED_KERNEL +#define MODULE_START CKSEG3/* don't overlap with mapped kernel */ +#else #define MODULE_START CKSSEG +#endif #define MODULE_END (FIXADDR_START-2*PAGE_SIZE)#endif
arch/mips/mm/tlb-r4k.c +2 -0
@@ -431,7 +431,9 @@ void tlb_init(void)* be set to fixed-size pages. */ write_c0_pagemask (PM_DEFAULT_MASK ); +#ifndef CONFIG_MAPPED_KERNEL write_c0_wired (0 ); +#endif if (current_cpu_type () ==CPU_R10000 ||current_cpu_type () ==CPU_R12000 ||current_cpu_type () ==CPU_R14000 )
arch/mips/netlogic/Platform +5 -0
@@ -14,4 +14,9 @@ cflags-$(CONFIG_CPU_XLP) += $(call cc-option,-march=xlp,-march=mips64r2) # NETLOGIC processor support # platform-$(CONFIG_NLM_COMMON) += netlogic/ + +ifdef CONFIG_MAPPED_KERNEL +load-$(CONFIG_NLM_COMMON) += 0xffffffffc0100000 +else load-$(CONFIG_NLM_COMMON) += 0xffffffff80100000 +endif
arch/mips/netlogic/common/memory.c +113 -0
127 lines not on this page · raw message
arch/mips/netlogic/common/reset.S +40 -0
@@ -43,6 +43,7 @@ #include <asm/asmmacro.h> #include <asm/addrspace.h> +#include <kernel-entry-init.h> #include <asm/netlogic/common.h> #include <asm/netlogic/xlp-hal/iomap.h>
@@ -254,6 +255,10 @@ EXPORT(nlm_boot_siblings) PTR_ADDU t1, v1 li t2, 1 sw t2, 0(t1) + + /* mapped first wired TLB for mapped kernel */ + kernel_entry_setup + /* Wait until NMI hits */ 3: wait b 3b
@@ -278,3 +283,38 @@ LEAF(nlm_init_boot_cpu) jr ra nop END(nlm_init_boot_cpu) + +LEAF(nlm_setup_wired_tlbs) +#ifdef CONFIG_MAPPED_KERNEL + li t0, CKSEG1ADDR(RESET_DATA_PHYS) + lw t3, BOOT_NTLBS(t0) + ADDIU t0, t0, BOOT_TLBS_START + li t1, 1 /* entry 0 is wired at boot, start at 1 */ + addiu t3, 1 /* final number of wired entries */ + +1: sltu v1, t1, t3 + beqz v1, 2f + nop + ld a0, (8 * BOOT_TLB_ENTRYLO0)(t0) + dmtc0 a0, CP0_ENTRYLO0 + ld a1, (8 * BOOT_TLB_ENTRYLO1)(t0) + dmtc0 a1, CP0_ENTRYLO1 + ld a2, (8 * BOOT_TLB_ENTRYHI)(t0) + dmtc0 a2, CP0_ENTRYHI + ld a2, (8 * BOOT_TLB_PAGEMASK)(t0) + dmtc0 a2, CP0_PAGEMASK + mtc0 t1, CP0_INDEX + _ehb + tlbwi + ADDIU t0, BOOT_TLB_SIZE + addiu t1, 1 + b 1b + nop +2: + mtc0 t3, CP0_WIRED + JRHB ra +#else + jr ra +#endif + nop +END(nlm_setup_wired_tlbs)
arch/mips/netlogic/common/smpboot.S +14 -2
@@ -41,6 +41,7 @@ #include <asm/asmmacro.h> #include <asm/addrspace.h> +#include <kernel-entry-init.h> #include <asm/netlogic/common.h> #include <asm/netlogic/xlp-hal/iomap.h>
@@ -80,6 +81,13 @@ NESTED(nlm_boot_secondary_cpus, 16, sp) ori t1, ST0_KX #endif mtc0 t1, CP0_STATUS + +#ifdef CONFIG_64BIT + /* set the full wired TLBs needed for mapped kernel */ + jal nlm_setup_wired_tlbs + nop +#endif + PTR_LA t1, nlm_next_sp PTR_L sp, 0(t1) PTR_LA t1, nlm_next_gp
@@ -136,8 +144,12 @@ NESTED(nlm_rmiboot_preboot, 16, sp) or t1, t2, v1 /* put in new value */ mtcr t1, t0 /* update core control */ +1: + /* mapped first wired TLB for mapped kernel */ + kernel_entry_setup + /* wait for NMI to hit */ -1: wait - b 1b +2: wait + b 2b nop END(nlm_rmiboot_preboot)
arch/mips/netlogic/xlr/wakeup.c +6 -1
@@ -53,6 +53,7 @@ int xlr_wakeup_secondary_cpus(void)struct nlm_soc_info *nodep;unsigned int i, j, boot_cpu;volatile u32 *cpu_ready =nlm_get_boot_data (BOOT_CPU_READY ); +void *handler;/* * In case of RMI boot, hit with NMI to get the cores
@@ -60,7 +61,11 @@ int xlr_wakeup_secondary_cpus(void)*/ nodep =nlm_get_node (0 ); boot_cpu =hard_smp_processor_id (); -nlm_set_nmi_handler (nlm_rmiboot_preboot); + handler = nlm_rmiboot_preboot; +#ifdef CONFIG_MAPPED_KERNEL + handler = (void *)CKSEG0ADDR ((long )handler); +#endif +nlm_set_nmi_handler (handler);for (i =0 ; i <NR_CPUS ; i++) {if (i == boot_cpu || !cpumask_test_cpu (i, &nlm_cpumask))continue ;
Signature · 1 line
1.7.9.5
PATCH 4/5 MIPS: Compress MAPPED kernels
In reply to Jayachandran CAdd code to build the wrapper in KSEG0, which in turn loads the mapped kernel.
--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 9 +++++++++ arch/mips/boot/compressed/decompress.c | 6 +++++- arch/mips/boot/compressed/head.S | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-)
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +9 -0
@@ -51,6 +51,15 @@ int main(int argc, char *argv[]) vmlinuz_load_addr += (16 - vmlinux_size %16 ); +/* handle 32/64 bit mapped addresses */ +if (vmlinuz_load_addr >=0xffffffffc0000000ULL ) + vmlinuz_load_addr =0xffffffff80000000ull | + (vmlinuz_load_addr &0x1fffffff ); +if (vmlinuz_load_addr >=0xc0000000ULL && + vmlinuz_load_addr <0xffffffffULL ) + vmlinuz_load_addr =0x80000000ull | + (vmlinuz_load_addr &0x1fffffff ); +printf ("0x%llx\n" , vmlinuz_load_addr);return EXIT_SUCCESS ;
arch/mips/boot/compressed/decompress.c +5 -1
@@ -70,6 +70,7 @@ void error(char *x)void decompress_kernel (unsigned long boot_heap_start) {unsigned long zimage_start, zimage_size; +unsigned long long loadaddr =VMLINUX_LOAD_ADDRESS_ULL ; zimage_start = (unsigned long )(&__image_begin); zimage_size = (unsigned long)(&__image_end) -
@@ -90,9 +91,12 @@ void decompress_kernel(unsigned long boot_heap_start)puthex (VMLINUX_LOAD_ADDRESS_ULL );puts ("\n" ); +#ifdef CONFIG_MAPPED_KERNEL + loadaddr =CKSEG0ADDR (loadaddr); +#endif /* Decompress the kernel with according algorithm */ decompress ((char *)zimage_start, zimage_size,0 ,0 , - (void *)VMLINUX_LOAD_ADDRESS_ULL ,0 , error); + (void *)(unsigned long )loadaddr,0 , error);/* FIXME: should we flush cache here? */ puts ("Now, booting the kernel...\n" );
arch/mips/boot/compressed/head.S +5 -0
@@ -14,6 +14,7 @@ #include <asm/asm.h> #include <asm/regdef.h> +#include <asm/addrspace.h> .set noreorder .cprestore
@@ -44,7 +45,11 @@ start: move a1, s1 move a2, s2 move a3, s3 +#ifdef CONFIG_MAPPED_KERNEL + PTR_LI k0, CKSEG0ADDR(KERNEL_ENTRY) +#else PTR_LI k0, KERNEL_ENTRY +#endif jr k0 nop 3:
Signature · 1 line
1.7.9.5
PATCH 5/5 MIPS: Netlogic: Map kernel with 1G/4G pages on XLPII
In reply to Jayachandran CXLP2XX and XLP9XX support 1G and 4G pages. Use this for mapping physical memory in Mapped Kernel support.
Reduces the number of WIRED entries in systems with more RAM.
--- arch/mips/netlogic/common/memory.c | 237 ++++++++++++++++++++++++------------ 1 file changed, 159 insertions(+), 78 deletions(-)
arch/mips/netlogic/common/memory.c +159 -78
@@ -34,6 +34,7 @@#include <linux/kernel.h> #include <linux/types.h> +#include <linux/sizes.h> #include <asm/bootinfo.h> #include <asm/pgtable.h>
@@ -41,100 +42,187 @@#include <asm/tlb.h> #include <asm/netlogic/common.h> +#include <asm/netlogic/xlp-hal/xlp.h> -#define TLBSZ (256 * 1024 * 1024) -#define PM_TLBSZ PM_256M -#define PTE_MAPKERN (pa) (((pa >> 12) << 6) | 0x2f) +#define SZ_4G (4ull * 1024 * 1024 * 1024) +#define PM_4G 0x1ffffe000 +#define MINPGSZ SZ_256M + +#define PTE_MAPKERN (pa) ((((pa) >> 12) << 6) | 0x2f)#define TLB_MAXWIRED 28static const int prefetch_backup =512 ;#if defined(CONFIG_MAPPED_KERNEL ) && defined(CONFIG_64BIT ) -static void nlm_tlb_align (struct boot_mem_map_entry *map) + +/* To track the allocated area of a boot_mem_map segment */ +struct alloc_entry { +/* Start and end of the va mapped */ +unsigned long long start; +unsigned long long end; + +/* When just one of lo0/lo1 is used, the valid area is half of above */ +unsigned long long astart; +unsigned long long aend; +} alloc_map[32 ]; + +static inline int addtlb (phys_addr_t pa,u64 pgsz,u64 pmask, +unsigned int validmask,struct alloc_entry *ae) { -phys_t astart, aend, start, end; +phys_addr_t endpa; +u64 *t; +u32 *tlbcount; +int ntlb; + + tlbcount = (u32 *)nlm_get_boot_data (BOOT_NTLBS ); + ntlb = *tlbcount; + endpa = pa +2 * pgsz; - start = map->addr; - end = start + map->size; +pr_debug ("%2d - pa0 %llx pa1 %llx pgsz %llx valid %x\n" , + ntlb, pa, endpa, pgsz, validmask); +if (ntlb ==TLB_MAXWIRED ) { +pr_err ("Ran out of TLB entries pa %llx pgsz %llx\n" , pa, pgsz); +return -1 ; + } -/* fudge first entry for now */ -if (start <0x10000000 ) { - start =0 ; - end =0x10000000 ; + t =nlm_get_boot_data (BOOT_TLBS_START ); + t += ntlb * (BOOT_TLB_SIZE /sizeof (t[0 ])); + t[BOOT_TLB_ENTRYHI ] = pa +PAGE_OFFSET ; + t[BOOT_TLB_ENTRYLO0 ] = (validmask &0x1 ) ?PTE_MAPKERN (pa) :1 ; + t[BOOT_TLB_ENTRYLO1 ] = (validmask &0x2 ) ?PTE_MAPKERN (pa + pgsz) :1 ; + t[BOOT_TLB_PAGEMASK ] = pmask; + +if (pa < ae->start) { + ae->astart = ae->start = pa; +if ((validmask &0x1 ) ==0 ) + ae->astart += pgsz; } - astart =round_up (start,TLBSZ ); - aend =round_down (end,TLBSZ ); -if (aend <= astart) { -pr_info ("Boot mem map: discard seg %lx-%lx\n" , - (unsigned long )start, (unsigned long )end); - map->size =0 ; -return ; +if (endpa > ae->end) { + ae->aend = ae->end = endpa; +if ((validmask &0x2 ) ==0 ) + ae->aend -= pgsz; } -if (astart != start || aend != end) { -if (start !=0 ) { - map->addr = astart; - map->size = aend - astart; - } -pr_info ("Boot mem map: %lx - %lx -> %lx-%lx\n" , - (unsigned long )start, (unsigned long )end, - (unsigned long )astart, (unsigned long )aend); - }else -pr_info ("Boot mem map: added %lx - %lx\n" , - (unsigned long )astart, (unsigned long )aend); + *tlbcount = ntlb +1 ; +return 0 ; } +/* +* Calculate the TLB entries needed to wire dowm the memory map +* +* Tries to use the largest pagesizes possible, discards memory which +* cannot be mapped +*/ static void nlm_calc_wired_tlbs (void ) { -u64 *tlbarr; -u32 *tlbcount; -u64 lo0, lo1, vaddr; -phys_addr_t astart, aend, p; -unsigned long bootdata =CKSEG1ADDR (RESET_DATA_PHYS ); -int i, pos; +u64 pgsz, pgmask, p; +phys_addr_t astart, aend, pend, nstart; +phys_addr_t tstart, tend, mstart, mend; +struct boot_mem_map_entry *bmap; +int i, nr_map; + + nr_map = boot_mem_map.nr_map; + bmap = boot_mem_map.map; + +for (i =0 ; i < nr_map; i++) { + alloc_map[i].start = alloc_map[i].astart = ~0ull ; + alloc_map[i].end = alloc_map[i].aend =0 ; + } - tlbarr = (u64 *)(bootdata +BOOT_TLBS_START ); - tlbcount = (u32 *)(bootdata +BOOT_NTLBS ); +/* force the first entry with one 256M lo0 page */ +addtlb (0 ,0x10000000 ,PM_256M ,0x1 , &alloc_map[0 ]); - pos =0 ; -for (i =0 ; i < boot_mem_map.nr_map; i++) { -if (boot_mem_map.map[i].type !=BOOT_MEM_RAM ) -continue ; - astart = boot_mem_map.map[i].addr; - aend = astart + boot_mem_map.map[i].size; +/* starting page size and page mask */ +if (cpu_is_xlpii ()) { + pgsz =SZ_4G ; + pgmask =PM_4G ; + }else { + pgsz =SZ_256M ; + pgmask =PM_256M ; + } -/* fudge first entry for now */ -if (astart <0x10000000 ) { - astart =0 ; - aend =0x10000000 ; - } -for (p =round_down (astart,2 *TLBSZ ); - p <round_up (aend,2 *TLBSZ );) { - vaddr =PAGE_OFFSET + p; - lo0 = (p >= astart) ?PTE_MAPKERN (p) :1 ; - p +=TLBSZ ; - lo1 = (p < aend) ?PTE_MAPKERN (p) :1 ; - p +=TLBSZ ; - - tlbarr[BOOT_TLB_ENTRYHI ] = vaddr; - tlbarr[BOOT_TLB_ENTRYLO0 ] = lo0; - tlbarr[BOOT_TLB_ENTRYLO1 ] = lo1; - tlbarr[BOOT_TLB_PAGEMASK ] =PM_TLBSZ ; - tlbarr += (BOOT_TLB_SIZE /sizeof (tlbarr[0 ])); - -if (++pos >=TLB_MAXWIRED ) { -pr_err ("Ran out of TLBs at %llx, " , - (unsigned long long )p); -pr_err ("Discarding rest of memory!\n" ); - boot_mem_map.nr_map = i +1 ; - boot_mem_map.map[i].size = p - - boot_mem_map.map[i].addr; +/* do multiple passes with successively smaller page sizes */ +for (; pgsz >=MINPGSZ ; pgsz /=4 , pgmask = (pgmask >>2 ) ^0x1800 ) { +for (i =0 ; i < nr_map; i++) { +if (bmap[i].type !=BOOT_MEM_RAM ) +continue ; + +/* previous mapping end and next mapping start */ + pend = alloc_map[i -1 ].end; + nstart = (i == nr_map -1 ) ? ~0ull : bmap[i +1 ].addr; + +/* mem block start and end */ + mstart =round_up (bmap[i].addr,MINPGSZ ); + mend =round_down (bmap[i].addr + bmap[i].size,MINPGSZ ); + +/* allocated area in the memory block, start and end */ + astart = alloc_map[i].start; + aend = alloc_map[i].end; + +/* skip fully mapped blocks */ +if (mstart >= astart && mend <= aend) +continue ; + +/* boundaries aligned to the current page size */ + tstart =round_up (mstart,2 * pgsz); + tend =round_down (mend,2 * pgsz); +if (tstart > tend) +continue ; + +/* use LO1 of a TLB entry */ +if (mstart + pgsz == tstart && pend <= mstart - pgsz) +if (addtlb (mstart - pgsz, pgsz, + pgmask,0x2 , &alloc_map[i])) goto out; + +for (p = tstart; p < tend;) { +if (astart < aend && p == astart) { + p = aend; +continue ; } +if (addtlb (p, pgsz, pgmask,0x3 , &alloc_map[i])) + goto out; + p +=2 * pgsz; + } + +/* use LO0 of a TLB entry */ +if (tend + pgsz == mend && nstart >= mend + pgsz) +if (addtlb (tend, pgsz, + pgmask,0x1 , &alloc_map[i])) + goto out; } } out: - *tlbcount = pos; -pr_info ("%d TLB entires used for mapped kernel.\n" , pos); +for (i =0 ; i < nr_map; i++) { + mstart = bmap[i].addr; + mend = bmap[i].addr + bmap[i].size; + astart = alloc_map[i].astart; + aend = alloc_map[i].aend; + +pr_info ("%2d alloc: %10llx %10llx mem %10llx %10llx\n" , i, + astart, aend, bmap[i].addr, + bmap[i].addr + bmap[i].size); +if (astart >= aend) { + bmap[i].size =0 ; +pr_info ("%2d: Discarded %#10llx - %#10llx\n" , i, + (unsigned long long )mstart, + (unsigned long long )mend); +continue ; + } +if (bmap[i].addr < astart) { + bmap[i].addr = astart; +pr_info ("%2d: Discarded %#10llx - %#10llx\n" , i, + (unsigned long long )bmap[i].addr, + (unsigned long long )astart); + } +if (mend > aend) { + bmap[i].size = aend - bmap[i].addr; +pr_info ("%2d: Discarded %#10llx - %#10llx\n" , i, + (unsigned long long )aend, + (unsigned long long )mend); + } + } +pr_info ("%d TLB entires used for mapped kernel.\n" , + *(u32 *)nlm_get_boot_data (BOOT_NTLBS )); }#endif
@@ -143,13 +231,6 @@ void __init plat_mem_fixup(void)int i;#if defined(CONFIG_MAPPED_KERNEL ) && defined(CONFIG_64BIT ) -/* trim memory regions to PM_TLBSZ boundaries */ -for (i =0 ; i < boot_mem_map.nr_map; i++) { -if (boot_mem_map.map[i].type !=BOOT_MEM_RAM ) -continue ; -nlm_tlb_align (&boot_mem_map.map[i]); - } -/* calculate and save wired TLB entries */ nlm_calc_wired_tlbs ();
Signature · 1 line
1.7.9.5