| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 | | /* 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 | 
 |