| /* | |
| * 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 |