mirror of https://gitee.com/openkylin/linux.git
96 lines
2.0 KiB
ArmAsm
96 lines
2.0 KiB
ArmAsm
|
/*
|
||
|
* Copyright 2013, Michael (Ellerman|Neuling), IBM Corporation.
|
||
|
*
|
||
|
* 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/asm-offsets.h>
|
||
|
#include <asm/ppc_asm.h>
|
||
|
#include <asm/reg.h>
|
||
|
|
||
|
#include "subcore.h"
|
||
|
|
||
|
|
||
|
_GLOBAL(split_core_secondary_loop)
|
||
|
/*
|
||
|
* r3 = u8 *state, used throughout the routine
|
||
|
* r4 = temp
|
||
|
* r5 = temp
|
||
|
* ..
|
||
|
* r12 = MSR
|
||
|
*/
|
||
|
mfmsr r12
|
||
|
|
||
|
/* Disable interrupts so SRR0/1 don't get trashed */
|
||
|
li r4,0
|
||
|
ori r4,r4,MSR_EE|MSR_SE|MSR_BE|MSR_RI
|
||
|
andc r4,r12,r4
|
||
|
sync
|
||
|
mtmsrd r4
|
||
|
|
||
|
/* Switch to real mode and leave interrupts off */
|
||
|
li r5, MSR_IR|MSR_DR
|
||
|
andc r5, r4, r5
|
||
|
|
||
|
LOAD_REG_ADDR(r4, real_mode)
|
||
|
|
||
|
mtspr SPRN_SRR0,r4
|
||
|
mtspr SPRN_SRR1,r5
|
||
|
rfid
|
||
|
b . /* prevent speculative execution */
|
||
|
|
||
|
real_mode:
|
||
|
/* Grab values from unsplit SPRs */
|
||
|
mfspr r6, SPRN_LDBAR
|
||
|
mfspr r7, SPRN_PMMAR
|
||
|
mfspr r8, SPRN_PMCR
|
||
|
mfspr r9, SPRN_RPR
|
||
|
mfspr r10, SPRN_SDR1
|
||
|
|
||
|
/* Order reading the SPRs vs telling the primary we are ready to split */
|
||
|
sync
|
||
|
|
||
|
/* Tell thread 0 we are in real mode */
|
||
|
li r4, SYNC_STEP_REAL_MODE
|
||
|
stb r4, 0(r3)
|
||
|
|
||
|
li r5, (HID0_POWER8_4LPARMODE | HID0_POWER8_2LPARMODE)@highest
|
||
|
sldi r5, r5, 48
|
||
|
|
||
|
/* Loop until we see the split happen in HID0 */
|
||
|
1: mfspr r4, SPRN_HID0
|
||
|
and. r4, r4, r5
|
||
|
beq 1b
|
||
|
|
||
|
/*
|
||
|
* We only need to initialise the below regs once for each subcore,
|
||
|
* but it's simpler and harmless to do it on each thread.
|
||
|
*/
|
||
|
|
||
|
/* Make sure various SPRS have sane values */
|
||
|
li r4, 0
|
||
|
mtspr SPRN_LPID, r4
|
||
|
mtspr SPRN_PCR, r4
|
||
|
mtspr SPRN_HDEC, r4
|
||
|
|
||
|
/* Restore SPR values now we are split */
|
||
|
mtspr SPRN_LDBAR, r6
|
||
|
mtspr SPRN_PMMAR, r7
|
||
|
mtspr SPRN_PMCR, r8
|
||
|
mtspr SPRN_RPR, r9
|
||
|
mtspr SPRN_SDR1, r10
|
||
|
|
||
|
LOAD_REG_ADDR(r5, virtual_mode)
|
||
|
|
||
|
/* Get out of real mode */
|
||
|
mtspr SPRN_SRR0,r5
|
||
|
mtspr SPRN_SRR1,r12
|
||
|
rfid
|
||
|
b . /* prevent speculative execution */
|
||
|
|
||
|
virtual_mode:
|
||
|
blr
|