xtensa: add SMP support

This is largely based on SMP code from the xtensa-2.6.29-smp tree by
Piet Delaney, Marc Gauthier, Joe Taylor, Christian Zankel (and possibly
other Tensilica folks).

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
This commit is contained in:
Max Filippov
2013-10-17 02:42:26 +04:00
committed by Chris Zankel
parent 26a8e96a8b
commit f615136c06
24 changed files with 970 additions and 202 deletions

View File

@@ -19,6 +19,7 @@
#include <asm/page.h>
#include <asm/cacheasm.h>
#include <asm/initialize_mmu.h>
#include <asm/mxregs.h>
#include <linux/init.h>
#include <linux/linkage.h>
@@ -54,7 +55,7 @@ ENTRY(_start)
/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
wsr a2, excsave1
_j _SetupMMU
_j _SetupOCD
.align 4
.literal_position
@@ -62,6 +63,23 @@ ENTRY(_start)
.word _startup
.align 4
_SetupOCD:
/*
* Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).
* Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow
* xt-gdb to single step via DEBUG exceptions received directly
* by ocd.
*/
movi a1, 1
movi a0, 0
wsr a1, windowstart
wsr a0, windowbase
rsync
movi a1, LOCKLEVEL
wsr a1, ps
rsync
.global _SetupMMU
_SetupMMU:
Offset = _SetupMMU - _start
@@ -90,19 +108,6 @@ ENDPROC(_start)
ENTRY(_startup)
/* Disable interrupts and exceptions. */
movi a0, LOCKLEVEL
wsr a0, ps
/* Start with a fresh windowbase and windowstart. */
movi a1, 1
movi a0, 0
wsr a1, windowstart
wsr a0, windowbase
rsync
/* Set a0 to 0 for the remaining initialization. */
movi a0, 0
@@ -154,17 +159,6 @@ ENTRY(_startup)
wsr a0, cpenable
#endif
/* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0
*
* Note: PS.EXCM must be cleared before using any loop
* instructions; otherwise, they are silently disabled, and
* at most one iteration of the loop is executed.
*/
movi a1, LOCKLEVEL
wsr a1, ps
rsync
/* Initialize the caches.
* a2, a3 are just working registers (clobbered).
*/
@@ -182,6 +176,37 @@ ENTRY(_startup)
isync
#ifdef CONFIG_HAVE_SMP
movi a2, CCON # MX External Register to Configure Cache
movi a3, 1
wer a3, a2
#endif
/* Setup stack and enable window exceptions (keep irqs disabled) */
movi a1, start_info
l32i a1, a1, 0
movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL
# WOE=1, INTLEVEL=LOCKLEVEL, UM=0
wsr a2, ps # (enable reg-windows; progmode stack)
rsync
/* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
movi a2, debug_exception
wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
#ifdef CONFIG_SMP
/*
* Notice that we assume with SMP that cores have PRID
* supported by the cores.
*/
rsr a2, prid
bnez a2, .Lboot_secondary
#endif /* CONFIG_SMP */
/* Unpack data sections
*
* The linker script used to build the Linux kernel image
@@ -234,24 +259,7 @@ ENTRY(_startup)
___invalidate_icache_all a2 a3
isync
/* Setup stack and enable window exceptions (keep irqs disabled) */
movi a1, init_thread_union
addi a1, a1, KERNEL_STACK_SIZE
movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL
# WOE=1, INTLEVEL=LOCKLEVEL, UM=0
wsr a2, ps # (enable reg-windows; progmode stack)
rsync
/* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
movi a2, debug_exception
wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
/* Set up EXCSAVE[1] to point to the exc_table. */
movi a6, exc_table
movi a6, 0
xsr a6, excsave1
/* init_arch kick-starts the linux kernel */
@@ -265,8 +273,44 @@ ENTRY(_startup)
should_never_return:
j should_never_return
#ifdef CONFIG_SMP
.Lboot_secondary:
movi a2, cpu_start_ccount
1:
l32i a3, a2, 0
beqi a3, 0, 1b
movi a3, 0
s32i a3, a2, 0
memw
1:
l32i a3, a2, 0
beqi a3, 0, 1b
wsr a3, ccount
movi a3, 0
s32i a3, a2, 0
memw
movi a6, 0
wsr a6, excsave1
movi a4, secondary_start_kernel
callx4 a4
j should_never_return
#endif /* CONFIG_SMP */
ENDPROC(_startup)
/*
* DATA section
*/
.section ".data.init.refok"
.align 4
ENTRY(start_info)
.long init_thread_union + KERNEL_STACK_SIZE
/*
* BSS section
*/