1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
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 | |
12 | #include <linux/linkage.h> |
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> |
20 | #include <asm/asm-compat.h> |
21 | #include <asm/feature-fixups.h> |
22 | |
23 | /***************************************************************************** |
24 | * * |
25 | * Guest entry / exit code that is in kernel module memory (vmalloc) * |
26 | * * |
27 | ****************************************************************************/ |
28 | |
29 | /* Registers: |
30 | * none |
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 | |
41 | /* Save non-volatile registers (r14 - r31) and CR */ |
42 | SAVE_NVGPRS(r1) |
43 | mfcr r3 |
44 | std r3, _CCR(r1) |
45 | |
46 | /* Save host DSCR */ |
47 | mfspr r3, SPRN_DSCR |
48 | std r3, HSTATE_DSCR(r13) |
49 | |
50 | BEGIN_FTR_SECTION |
51 | /* Save host DABR */ |
52 | mfspr r3, SPRN_DABR |
53 | std r3, HSTATE_DABR(r13) |
54 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) |
55 | |
56 | /* Save host PMU registers */ |
57 | bl kvmhv_save_host_pmu |
58 | |
59 | /* |
60 | * Put whatever is in the decrementer into the |
61 | * hypervisor decrementer. |
62 | * Because of a hardware deviation in P8, |
63 | * we need to set LPCR[HDICE] before writing HDEC. |
64 | */ |
65 | ld r5, HSTATE_KVM_VCORE(r13) |
66 | ld r6, VCORE_KVM(r5) |
67 | ld r9, KVM_HOST_LPCR(r6) |
68 | ori r8, r9, LPCR_HDICE |
69 | mtspr SPRN_LPCR, r8 |
70 | isync |
71 | mfspr r8,SPRN_DEC |
72 | mftb r7 |
73 | extsw r8,r8 |
74 | mtspr SPRN_HDEC,r8 |
75 | add r8,r8,r7 |
76 | std r8,HSTATE_DECEXP(r13) |
77 | |
78 | /* Jump to partition switch code */ |
79 | bl kvmppc_hv_entry_trampoline |
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. |
85 | * Interrupts are still hard-disabled. |
86 | */ |
87 | |
88 | /* |
89 | * Register usage at this point: |
90 | * |
91 | * R1 = host R1 |
92 | * R2 = host R2 |
93 | * R3 = trap number on this thread |
94 | * R12 = exit handler id |
95 | * R13 = PACA |
96 | */ |
97 | |
98 | /* Restore non-volatile host registers (r14 - r31) and CR */ |
99 | REST_NVGPRS(r1) |
100 | ld r4, _CCR(r1) |
101 | mtcr r4 |
102 | |
103 | addi r1, r1, SWITCH_FRAME_SIZE |
104 | ld r0, PPC_LR_STKOFF(r1) |
105 | mtlr r0 |
106 | blr |
107 | |
108 | /* |
109 | * void kvmhv_save_host_pmu(void) |
110 | */ |
111 | SYM_FUNC_START_LOCAL(kvmhv_save_host_pmu) |
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 |
158 | SYM_FUNC_END(kvmhv_save_host_pmu) |
159 | |