 0ee958e102
			
		
	
	
	0ee958e102
	
	
	
		
			
			This patch introduces a new SMP implementation for systems implementing the MIPS Coherent Processing System architecture. The kernel will make use of the Coherence Manager, Cluster Power Controller & Global Interrupt Controller in order to detect, bring up & make use of other cores in the system. SMTC is not supported, so only a single TC per VPE in the system is used. That is, this option enables an SMVP style setup but across multiple cores. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6362/ Patchwork: https://patchwork.linux-mips.org/patch/6611/ Patchwork: https://patchwork.linux-mips.org/patch/6651/ Patchwork: https://patchwork.linux-mips.org/patch/6652/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
		
			
				
	
	
		
			191 lines
		
	
	
	
		
			3.7 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			191 lines
		
	
	
	
		
			3.7 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2013 Imagination Technologies
 | |
|  * Author: Paul Burton <paul.burton@imgtec.com>
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms of the GNU General Public License as published by the
 | |
|  * Free Software Foundation;  either version 2 of the  License, or (at your
 | |
|  * option) any later version.
 | |
|  */
 | |
| 
 | |
| #include <asm/addrspace.h>
 | |
| #include <asm/asm.h>
 | |
| #include <asm/asm-offsets.h>
 | |
| #include <asm/asmmacro.h>
 | |
| #include <asm/cacheops.h>
 | |
| #include <asm/mipsregs.h>
 | |
| 
 | |
| #define GCR_CL_COHERENCE_OFS 0x2008
 | |
| 
 | |
| .section .text.cps-vec
 | |
| .balign 0x1000
 | |
| .set noreorder
 | |
| 
 | |
| LEAF(mips_cps_core_entry)
 | |
| 	/*
 | |
| 	 * These first 8 bytes will be patched by cps_smp_setup to load the
 | |
| 	 * base address of the CM GCRs into register v1.
 | |
| 	 */
 | |
| 	.quad	0
 | |
| 
 | |
| 	/* Check whether we're here due to an NMI */
 | |
| 	mfc0	k0, CP0_STATUS
 | |
| 	and	k0, k0, ST0_NMI
 | |
| 	beqz	k0, not_nmi
 | |
| 	 nop
 | |
| 
 | |
| 	/* This is an NMI */
 | |
| 	la	k0, nmi_handler
 | |
| 	jr	k0
 | |
| 	 nop
 | |
| 
 | |
| not_nmi:
 | |
| 	/* Setup Cause */
 | |
| 	li	t0, CAUSEF_IV
 | |
| 	mtc0	t0, CP0_CAUSE
 | |
| 
 | |
| 	/* Setup Status */
 | |
| 	li	t0, ST0_CU1 | ST0_CU0
 | |
| 	mtc0	t0, CP0_STATUS
 | |
| 
 | |
| 	/*
 | |
| 	 * Clear the bits used to index the caches. Note that the architecture
 | |
| 	 * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
 | |
| 	 * be valid for all MIPS32 CPUs, even those for which said writes are
 | |
| 	 * unnecessary.
 | |
| 	 */
 | |
| 	mtc0	zero, CP0_TAGLO, 0
 | |
| 	mtc0	zero, CP0_TAGHI, 0
 | |
| 	mtc0	zero, CP0_TAGLO, 2
 | |
| 	mtc0	zero, CP0_TAGHI, 2
 | |
| 	ehb
 | |
| 
 | |
| 	/* Primary cache configuration is indicated by Config1 */
 | |
| 	mfc0	v0, CP0_CONFIG, 1
 | |
| 
 | |
| 	/* Detect I-cache line size */
 | |
| 	_EXT	t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
 | |
| 	beqz	t0, icache_done
 | |
| 	 li	t1, 2
 | |
| 	sllv	t0, t1, t0
 | |
| 
 | |
| 	/* Detect I-cache size */
 | |
| 	_EXT	t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
 | |
| 	xori	t2, t1, 0x7
 | |
| 	beqz	t2, 1f
 | |
| 	 li	t3, 32
 | |
| 	addi	t1, t1, 1
 | |
| 	sllv	t1, t3, t1
 | |
| 1:	/* At this point t1 == I-cache sets per way */
 | |
| 	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
 | |
| 	addi	t2, t2, 1
 | |
| 	mul	t1, t1, t0
 | |
| 	mul	t1, t1, t2
 | |
| 
 | |
| 	li	a0, KSEG0
 | |
| 	add	a1, a0, t1
 | |
| 1:	cache	Index_Store_Tag_I, 0(a0)
 | |
| 	add	a0, a0, t0
 | |
| 	bne	a0, a1, 1b
 | |
| 	 nop
 | |
| icache_done:
 | |
| 
 | |
| 	/* Detect D-cache line size */
 | |
| 	_EXT	t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
 | |
| 	beqz	t0, dcache_done
 | |
| 	 li	t1, 2
 | |
| 	sllv	t0, t1, t0
 | |
| 
 | |
| 	/* Detect D-cache size */
 | |
| 	_EXT	t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
 | |
| 	xori	t2, t1, 0x7
 | |
| 	beqz	t2, 1f
 | |
| 	 li	t3, 32
 | |
| 	addi	t1, t1, 1
 | |
| 	sllv	t1, t3, t1
 | |
| 1:	/* At this point t1 == D-cache sets per way */
 | |
| 	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
 | |
| 	addi	t2, t2, 1
 | |
| 	mul	t1, t1, t0
 | |
| 	mul	t1, t1, t2
 | |
| 
 | |
| 	li	a0, KSEG0
 | |
| 	addu	a1, a0, t1
 | |
| 	subu	a1, a1, t0
 | |
| 1:	cache	Index_Store_Tag_D, 0(a0)
 | |
| 	bne	a0, a1, 1b
 | |
| 	 add	a0, a0, t0
 | |
| dcache_done:
 | |
| 
 | |
| 	/* Set Kseg0 cacheable, coherent, write-back, write-allocate */
 | |
| 	mfc0	t0, CP0_CONFIG
 | |
| 	ori	t0, 0x7
 | |
| 	xori	t0, 0x2
 | |
| 	mtc0	t0, CP0_CONFIG
 | |
| 	ehb
 | |
| 
 | |
| 	/* Enter the coherent domain */
 | |
| 	li	t0, 0xff
 | |
| 	sw	t0, GCR_CL_COHERENCE_OFS(v1)
 | |
| 	ehb
 | |
| 
 | |
| 	/* Jump to kseg0 */
 | |
| 	la	t0, 1f
 | |
| 	jr	t0
 | |
| 	 nop
 | |
| 
 | |
| 1:	/* We're up, cached & coherent */
 | |
| 
 | |
| 	/*
 | |
| 	 * TODO: We should check the VPE number we intended to boot here, and
 | |
| 	 *       if non-zero we should start that VPE and stop this one. For
 | |
| 	 *       the moment this doesn't matter since CPUs are brought up
 | |
| 	 *       sequentially and in order, but once hotplug is implemented
 | |
| 	 *       this will need revisiting.
 | |
| 	 */
 | |
| 
 | |
| 	/* Off we go! */
 | |
| 	la	t0, mips_cps_bootcfg
 | |
| 	lw	t1, BOOTCFG_PC(t0)
 | |
| 	lw	gp, BOOTCFG_GP(t0)
 | |
| 	lw	sp, BOOTCFG_SP(t0)
 | |
| 	jr	t1
 | |
| 	 nop
 | |
| 	END(mips_cps_core_entry)
 | |
| 
 | |
| .org 0x200
 | |
| LEAF(excep_tlbfill)
 | |
| 	b	.
 | |
| 	 nop
 | |
| 	END(excep_tlbfill)
 | |
| 
 | |
| .org 0x280
 | |
| LEAF(excep_xtlbfill)
 | |
| 	b	.
 | |
| 	 nop
 | |
| 	END(excep_xtlbfill)
 | |
| 
 | |
| .org 0x300
 | |
| LEAF(excep_cache)
 | |
| 	b	.
 | |
| 	 nop
 | |
| 	END(excep_cache)
 | |
| 
 | |
| .org 0x380
 | |
| LEAF(excep_genex)
 | |
| 	b	.
 | |
| 	 nop
 | |
| 	END(excep_genex)
 | |
| 
 | |
| .org 0x400
 | |
| LEAF(excep_intex)
 | |
| 	b	.
 | |
| 	 nop
 | |
| 	END(excep_intex)
 | |
| 
 | |
| .org 0x480
 | |
| LEAF(excep_ejtag)
 | |
| 	la	k0, ejtag_debug_handler
 | |
| 	jr	k0
 | |
| 	 nop
 | |
| 	END(excep_ejtag)
 |