/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright 2013, Michael (Ellerman|Neuling), IBM Corporation. */ #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