Commit | Line | Data |
---|---|---|
d94d71cb | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
de56a948 | 2 | /* |
de56a948 PM |
3 | * |
4 | * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> | |
5 | * | |
6 | * Derived from book3s_interrupts.S, which is: | |
7 | * Copyright SUSE Linux Products GmbH 2009 | |
8 | * | |
9 | * Authors: Alexander Graf <agraf@suse.de> | |
10 | */ | |
11 | ||
29a011fc | 12 | #include <linux/linkage.h> |
de56a948 PM |
13 | #include <asm/ppc_asm.h> |
14 | #include <asm/kvm_asm.h> | |
15 | #include <asm/reg.h> | |
16 | #include <asm/page.h> | |
17 | #include <asm/asm-offsets.h> | |
18 | #include <asm/exception-64s.h> | |
19 | #include <asm/ppc-opcode.h> | |
ec0c464c | 20 | #include <asm/asm-compat.h> |
2c86cd18 | 21 | #include <asm/feature-fixups.h> |
de56a948 PM |
22 | |
23 | /***************************************************************************** | |
24 | * * | |
25 | * Guest entry / exit code that is in kernel module memory (vmalloc) * | |
26 | * * | |
27 | ****************************************************************************/ | |
28 | ||
29 | /* Registers: | |
e0b7ec05 | 30 | * none |
de56a948 PM |
31 | */ |
32 | _GLOBAL(__kvmppc_vcore_entry) | |
33 | ||
34 | /* Write correct stack frame */ | |
35 | mflr r0 | |
36 | std r0,PPC_LR_STKOFF(r1) | |
37 | ||
38 | /* Save host state to the stack */ | |
39 | stdu r1, -SWITCH_FRAME_SIZE(r1) | |
40 | ||
a5ddea0e | 41 | /* Save non-volatile registers (r14 - r31) and CR */ |
de56a948 | 42 | SAVE_NVGPRS(r1) |
a5ddea0e PM |
43 | mfcr r3 |
44 | std r3, _CCR(r1) | |
de56a948 PM |
45 | |
46 | /* Save host DSCR */ | |
47 | mfspr r3, SPRN_DSCR | |
48 | std r3, HSTATE_DSCR(r13) | |
49 | ||
eee7ff9d | 50 | BEGIN_FTR_SECTION |
de56a948 PM |
51 | /* Save host DABR */ |
52 | mfspr r3, SPRN_DABR | |
53 | std r3, HSTATE_DABR(r13) | |
eee7ff9d | 54 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) |
de56a948 | 55 | |
8943633c | 56 | /* Save host PMU registers */ |
41f4e631 | 57 | bl kvmhv_save_host_pmu |
de56a948 PM |
58 | |
59 | /* | |
60 | * Put whatever is in the decrementer into the | |
61 | * hypervisor decrementer. | |
fae5c9f3 | 62 | * Because of a hardware deviation in P8, |
35dfb43c | 63 | * we need to set LPCR[HDICE] before writing HDEC. |
de56a948 | 64 | */ |
2f272463 PM |
65 | ld r5, HSTATE_KVM_VCORE(r13) |
66 | ld r6, VCORE_KVM(r5) | |
67 | ld r9, KVM_HOST_LPCR(r6) | |
35dfb43c PM |
68 | ori r8, r9, LPCR_HDICE |
69 | mtspr SPRN_LPCR, r8 | |
70 | isync | |
de56a948 PM |
71 | mfspr r8,SPRN_DEC |
72 | mftb r7 | |
de56a948 | 73 | extsw r8,r8 |
fae5c9f3 | 74 | mtspr SPRN_HDEC,r8 |
de56a948 PM |
75 | add r8,r8,r7 |
76 | std r8,HSTATE_DECEXP(r13) | |
77 | ||
78 | /* Jump to partition switch code */ | |
b1576fec | 79 | bl kvmppc_hv_entry_trampoline |
de56a948 PM |
80 | nop |
81 | ||
82 | /* | |
83 | * We return here in virtual mode after the guest exits | |
84 | * with something that we can't handle in real mode. | |
48e70b1c | 85 | * Interrupts are still hard-disabled. |
de56a948 PM |
86 | */ |
87 | ||
de56a948 PM |
88 | /* |
89 | * Register usage at this point: | |
90 | * | |
91 | * R1 = host R1 | |
92 | * R2 = host R2 | |
8b24e69f | 93 | * R3 = trap number on this thread |
de56a948 PM |
94 | * R12 = exit handler id |
95 | * R13 = PACA | |
96 | */ | |
97 | ||
a5ddea0e | 98 | /* Restore non-volatile host registers (r14 - r31) and CR */ |
de56a948 | 99 | REST_NVGPRS(r1) |
a5ddea0e PM |
100 | ld r4, _CCR(r1) |
101 | mtcr r4 | |
de56a948 PM |
102 | |
103 | addi r1, r1, SWITCH_FRAME_SIZE | |
104 | ld r0, PPC_LR_STKOFF(r1) | |
105 | mtlr r0 | |
106 | blr | |
41f4e631 | 107 | |
57dc0eed NP |
108 | /* |
109 | * void kvmhv_save_host_pmu(void) | |
110 | */ | |
29a011fc | 111 | SYM_FUNC_START_LOCAL(kvmhv_save_host_pmu) |
41f4e631 PM |
112 | BEGIN_FTR_SECTION |
113 | /* Work around P8 PMAE bug */ | |
114 | li r3, -1 | |
115 | clrrdi r3, r3, 10 | |
116 | mfspr r8, SPRN_MMCR2 | |
117 | mtspr SPRN_MMCR2, r3 /* freeze all counters using MMCR2 */ | |
118 | isync | |
119 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |
120 | li r3, 1 | |
121 | sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ | |
122 | mfspr r7, SPRN_MMCR0 /* save MMCR0 */ | |
123 | mtspr SPRN_MMCR0, r3 /* freeze all counters, disable interrupts */ | |
124 | mfspr r6, SPRN_MMCRA | |
125 | /* Clear MMCRA in order to disable SDAR updates */ | |
126 | li r5, 0 | |
127 | mtspr SPRN_MMCRA, r5 | |
128 | isync | |
129 | lbz r5, PACA_PMCINUSE(r13) /* is the host using the PMU? */ | |
130 | cmpwi r5, 0 | |
131 | beq 31f /* skip if not */ | |
132 | mfspr r5, SPRN_MMCR1 | |
133 | mfspr r9, SPRN_SIAR | |
134 | mfspr r10, SPRN_SDAR | |
135 | std r7, HSTATE_MMCR0(r13) | |
136 | std r5, HSTATE_MMCR1(r13) | |
137 | std r6, HSTATE_MMCRA(r13) | |
138 | std r9, HSTATE_SIAR(r13) | |
139 | std r10, HSTATE_SDAR(r13) | |
140 | BEGIN_FTR_SECTION | |
141 | mfspr r9, SPRN_SIER | |
142 | std r8, HSTATE_MMCR2(r13) | |
143 | std r9, HSTATE_SIER(r13) | |
144 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |
145 | mfspr r3, SPRN_PMC1 | |
146 | mfspr r5, SPRN_PMC2 | |
147 | mfspr r6, SPRN_PMC3 | |
148 | mfspr r7, SPRN_PMC4 | |
149 | mfspr r8, SPRN_PMC5 | |
150 | mfspr r9, SPRN_PMC6 | |
151 | stw r3, HSTATE_PMC1(r13) | |
152 | stw r5, HSTATE_PMC2(r13) | |
153 | stw r6, HSTATE_PMC3(r13) | |
154 | stw r7, HSTATE_PMC4(r13) | |
155 | stw r8, HSTATE_PMC5(r13) | |
156 | stw r9, HSTATE_PMC6(r13) | |
157 | 31: blr | |
29a011fc | 158 | SYM_FUNC_END(kvmhv_save_host_pmu) |