diff options
Diffstat (limited to 'arch/microblaze/kernel/head.S')
-rw-r--r-- | arch/microblaze/kernel/head.S | 165 |
1 files changed, 127 insertions, 38 deletions
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index 14b276406153..eb889ec53a1a 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -30,6 +30,7 @@ #include <linux/init.h> #include <linux/linkage.h> +#include <asm/entry.h> #include <asm/thread_info.h> #include <asm/page.h> #include <linux/of_fdt.h> /* for OF_DT_HEADER */ @@ -38,6 +39,7 @@ #include <asm/setup.h> /* COMMAND_LINE_SIZE */ #include <asm/mmu.h> #include <asm/processor.h> +#include <asm/asm-offsets.h> .section .data .global empty_zero_page @@ -47,7 +49,11 @@ empty_zero_page: .global swapper_pg_dir swapper_pg_dir: .space PAGE_SIZE - +#ifdef CONFIG_SMP +temp_boot_stack: + .space 1024 +#define CURRENT_SAVE CURRENT_SAVE_ADDR +#endif /* CONFIG_SMP */ #endif /* CONFIG_MMU */ .section .rodata @@ -79,6 +85,13 @@ real_start: msrclr r8, 0 /* clear nothing - just read msr for test */ cmpu r8, r8, r1 /* r1 must contain msr reg content */ +#ifdef CONFIG_SMP + /* skip FDT copy if secondary */ + mfs r11, rpvr0 + andi r11, r11, 0xFF + bnei r11, _setup_initial_mmu +#endif /* CONFIG_SMP */ + /* r7 may point to an FDT, or there may be one linked in. if it's in r7, we've got to save it away ASAP. We ensure r7 points to a valid FDT, just in case the bootloader @@ -147,6 +160,7 @@ _copy_bram: #endif /* We have to turn on the MMU right away. */ +_setup_initial_mmu: /* * Set up the initial MMU state so we can do the first level of * kernel initialization. This maps the first 16 MBytes of memory 1:1 @@ -178,50 +192,51 @@ _invalidate: tophys(r4,r3) /* Load the kernel physical address */ /* start to do TLB calculation */ - addik r12, r0, _end + addik r12, r0, _end_tlb_mapping rsub r12, r3, r12 - addik r12, r12, CONFIG_LOWMEM_SIZE >> PTE_SHIFT /* that's the pad */ or r9, r0, r0 /* TLB0 = 0 */ or r10, r0, r0 /* TLB1 = 0 */ - addik r11, r12, -0x1000000 - bgei r11, GT16 /* size is greater than 16MB */ - addik r11, r12, -0x0800000 - bgei r11, GT8 /* size is greater than 8MB */ - addik r11, r12, -0x0400000 - bgei r11, GT4 /* size is greater than 4MB */ - /* size is less than 4MB */ - addik r11, r12, -0x0200000 - bgei r11, GT2 /* size is greater than 2MB */ - addik r9, r0, 0x0100000 /* TLB0 must be 1MB */ - addik r11, r12, -0x0100000 - bgei r11, GT1 /* size is greater than 1MB */ - /* TLB1 is 0 which is setup above */ - bri tlb_end -GT4: /* r11 contains the rest - will be either 1 or 4 */ - ori r9, r0, 0x400000 /* TLB0 is 4MB */ - bri TLB1 -GT16: /* TLB0 is 16MB */ + /* + * Linux is 4MB aligned that's why we can just check certain sizes. + * Add 12MB, 16MB and 8MB on the top of list because that's normal + * sizes which are often used. + */ + addik r11, r12, -0xc00000 /* 12 MB */ + beqi r11, GT12 + addik r11, r12, -0x1000000 /* 16 MB */ + beqi r11, GT16 + addik r11, r12, -0x800000 /* 8 MB */ + beqi r11, GT8 + addik r11, r12, -0x2000000 /* 32 MB */ + beqi r11, GT32 + addik r11, r12, -0x1800000 /* 24 MB */ + beqi r11, GT24 + addik r11, r12, -0x1400000 /* 20 MB */ + beqi r11, GT20 + addik r11, r12, -0x400000 /* 4 MB */ + beqi r11, GT4 + /* if this page doesn't detect it use 32MB mapping */ +GT32: addik r9, r0, 0x1000000 /* means TLB0 is 16MB */ -TLB1: - /* must be used r2 because of subtract if failed */ - addik r2, r11, -0x0400000 - bgei r2, GT20 /* size is greater than 16MB */ - /* size is >16MB and <20MB */ - addik r11, r11, -0x0100000 - bgei r11, GT17 /* size is greater than 17MB */ - /* kernel is >16MB and < 17MB */ -GT1: - addik r10, r0, 0x0100000 /* means TLB1 is 1MB */ - bri tlb_end -GT2: /* TLB0 is 0 and TLB1 will be 4MB */ -GT17: /* TLB1 is 4MB - kernel size <20MB */ - addik r10, r0, 0x0400000 /* means TLB1 is 4MB */ - bri tlb_end -GT8: /* TLB0 is still zero that's why I can use only TLB1 */ -GT20: /* TLB1 is 16MB - kernel size >20MB */ +GT16: addik r10, r0, 0x1000000 /* means TLB1 is 16MB */ + bri tlb_end +GT24: + addik r9, r0, 0x1000000 /* means TLB0 is 16MB */ +GT8: + addik r10, r0, 0x800000 /* means TLB1 is 8MB */ + bri tlb_end +GT20: + addik r9, r0, 0x1000000 /* means TLB0 is 16MB */ +GT4: + addik r10, r0, 0x400000 /* means TLB1 is 4MB */ + bri tlb_end +GT12: + addik r9, r0, 0x800000 /* means TLB0 is 8MB */ + addik r10, r0, 0x400000 /* means TLB1 is 4MB */ + /* NOTE: No need to just to tlb_end here */ tlb_end: /* @@ -322,6 +337,18 @@ jump_over2: */ turn_on_mmu: ori r15,r0,start_here +#ifdef CONFIG_SMP + /* + * Read PVR and mask off all but CPU id bits to use to select + * boot sequence + */ + mfs r4, rpvr0 + andi r4, r4, 0xFF + + beqi r4, finish + ori r15, r0, start_secondary_cpu +finish: +#endif /* CONFIG_SMP */ ori r4,r0,MSR_KERNEL_VMS mts rmsr,r4 nop @@ -340,6 +367,10 @@ start_here: /* Initialize r31 with current task address */ addik r31, r0, init_task +#ifdef CONFIG_MMU + /* save current for CPU 0 */ + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); +#endif addik r11, r0, machine_early_init brald r15, r11 @@ -384,3 +415,61 @@ kernel_load_context: rted r17, 0 /* enable MMU and jump to start_kernel */ nop #endif /* CONFIG_MMU */ + +#ifdef CONFIG_SMP +/* Entry point for secondary processors */ +start_secondary_cpu: + + /* Initialize small data anchors */ + addik r13, r0, _KERNEL_SDA_BASE_ + addik r2, r0, _KERNEL_SDA2_BASE_ + + /* Initialize stack pointer */ + addik r1, r0, temp_boot_stack + 1024 - 4 + + /* + * Initialize the exception table. + */ + addik r11, r0, secondary_machine_init + brald r15, r11 + nop + + lwi r1, r0, secondary_ti + + /* Initialize r31 with current task address */ + lwi CURRENT_TASK, r1, TI_TASK + /* save current for secondary CPU */ + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); + + /* Initialize stack pointer */ + addi r1, r1, THREAD_SIZE - 4 + swi r0, r1, 0 + + /* Initialize MMU */ + ori r11, r0, 0x10000000 + mts rzpr, r11 + + ori r15, r0, TOPHYS(kernel_load_context_secondary) + ori r4, r0, MSR_KERNEL + mts rmsr, r4 + nop + bri 4 + rted r15, 0 + nop + + /* Load up the kernel context */ +kernel_load_context_secondary: + # Keep entry 0 and 1 valid. Entry 3 mapped to LMB can go away. + ori r5, r0, MICROBLAZE_LMB_TLB_ID + mts rtlbx, r5 + nop + mts rtlbhi, r0 + nop + addi r15, r0, machine_halt + ori r17, r0, start_secondary + ori r4, r0, MSR_KERNEL_VMS + mts rmsr, r4 + nop + rted r17, 0 /* enable MMU and jump to start_kernel */ + nop +#endif /* CONFIG_SMP */ |