1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright 2013, Michael (Ellerman|Neuling), IBM Corporation.
4 */
5
6#include <asm/asm-offsets.h>
7#include <asm/ppc_asm.h>
8#include <asm/reg.h>
9
10#include "subcore.h"
11
12
13_GLOBAL(split_core_secondary_loop)
14	/*
15	 * r3 = u8 *state, used throughout the routine
16	 * r4 = temp
17	 * r5 = temp
18	 * ..
19	 * r12 = MSR
20	 */
21	mfmsr	r12
22
23	/* Disable interrupts so SRR0/1 don't get trashed */
24	li	r4,0
25	ori	r4,r4,MSR_EE|MSR_SE|MSR_BE|MSR_RI
26	andc	r4,r12,r4
27	sync
28	mtmsrd	r4
29
30	/* Switch to real mode and leave interrupts off */
31	li	r5, MSR_IR|MSR_DR
32	andc	r5, r4, r5
33
34	LOAD_REG_ADDR(r4, real_mode)
35
36	mtspr	SPRN_SRR0,r4
37	mtspr	SPRN_SRR1,r5
38	rfid
39	b	.	/* prevent speculative execution */
40
41real_mode:
42	/* Grab values from unsplit SPRs */
43	mfspr	r6,  SPRN_LDBAR
44	mfspr	r7,  SPRN_PMMAR
45	mfspr	r8,  SPRN_PMCR
46	mfspr	r9,  SPRN_RPR
47	mfspr	r10, SPRN_SDR1
48
49	/* Order reading the SPRs vs telling the primary we are ready to split */
50	sync
51
52	/* Tell thread 0 we are in real mode */
53	li	r4, SYNC_STEP_REAL_MODE
54	stb	r4, 0(r3)
55
56	li	r5, (HID0_POWER8_4LPARMODE | HID0_POWER8_2LPARMODE)@highest
57	sldi	r5, r5, 48
58
59	/* Loop until we see the split happen in HID0 */
601:	mfspr	r4, SPRN_HID0
61	and.	r4, r4, r5
62	beq	1b
63
64	/*
65	 * We only need to initialise the below regs once for each subcore,
66	 * but it's simpler and harmless to do it on each thread.
67	 */
68
69	/* Make sure various SPRS have sane values */
70	li	r4, 0
71	mtspr	SPRN_LPID, r4
72	mtspr	SPRN_PCR, r4
73	mtspr	SPRN_HDEC, r4
74
75	/* Restore SPR values now we are split */
76	mtspr	SPRN_LDBAR, r6
77	mtspr	SPRN_PMMAR, r7
78	mtspr	SPRN_PMCR, r8
79	mtspr	SPRN_RPR, r9
80	mtspr	SPRN_SDR1, r10
81
82	LOAD_REG_ADDR(r5, virtual_mode)
83
84	/* Get out of real mode */
85	mtspr	SPRN_SRR0,r5
86	mtspr	SPRN_SRR1,r12
87	rfid
88	b	.	/* prevent speculative execution */
89
90virtual_mode:
91	blr
92