Merge existing fixes from asoc/for-5.10
[linux-2.6-microblaze.git] / arch / powerpc / kvm / book3s_hv_interrupts.S
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 <asm/ppc_asm.h>
13 #include <asm/kvm_asm.h>
14 #include <asm/reg.h>
15 #include <asm/page.h>
16 #include <asm/asm-offsets.h>
17 #include <asm/exception-64s.h>
18 #include <asm/ppc-opcode.h>
19 #include <asm/asm-compat.h>
20 #include <asm/feature-fixups.h>
21
22 /*****************************************************************************
23  *                                                                           *
24  *     Guest entry / exit code that is in kernel module memory (vmalloc)     *
25  *                                                                           *
26  ****************************************************************************/
27
28 /* Registers:
29  *  none
30  */
31 _GLOBAL(__kvmppc_vcore_entry)
32
33         /* Write correct stack frame */
34         mflr    r0
35         std     r0,PPC_LR_STKOFF(r1)
36
37         /* Save host state to the stack */
38         stdu    r1, -SWITCH_FRAME_SIZE(r1)
39
40         /* Save non-volatile registers (r14 - r31) and CR */
41         SAVE_NVGPRS(r1)
42         mfcr    r3
43         std     r3, _CCR(r1)
44
45         /* Save host DSCR */
46         mfspr   r3, SPRN_DSCR
47         std     r3, HSTATE_DSCR(r13)
48
49 BEGIN_FTR_SECTION
50         /* Save host DABR */
51         mfspr   r3, SPRN_DABR
52         std     r3, HSTATE_DABR(r13)
53 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
54
55         /* Save host PMU registers */
56         bl      kvmhv_save_host_pmu
57
58         /*
59          * Put whatever is in the decrementer into the
60          * hypervisor decrementer.
61          * Because of a hardware deviation in P8 and P9,
62          * we need to set LPCR[HDICE] before writing HDEC.
63          */
64         ld      r5, HSTATE_KVM_VCORE(r13)
65         ld      r6, VCORE_KVM(r5)
66         ld      r9, KVM_HOST_LPCR(r6)
67         ori     r8, r9, LPCR_HDICE
68         mtspr   SPRN_LPCR, r8
69         isync
70         andis.  r0, r9, LPCR_LD@h
71         mfspr   r8,SPRN_DEC
72         mftb    r7
73 BEGIN_FTR_SECTION
74         /* On POWER9, don't sign-extend if host LPCR[LD] bit is set */
75         bne     32f
76 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
77         extsw   r8,r8
78 32:     mtspr   SPRN_HDEC,r8
79         add     r8,r8,r7
80         std     r8,HSTATE_DECEXP(r13)
81
82         /* Jump to partition switch code */
83         bl      kvmppc_hv_entry_trampoline
84         nop
85
86 /*
87  * We return here in virtual mode after the guest exits
88  * with something that we can't handle in real mode.
89  * Interrupts are still hard-disabled.
90  */
91
92         /*
93          * Register usage at this point:
94          *
95          * R1       = host R1
96          * R2       = host R2
97          * R3       = trap number on this thread
98          * R12      = exit handler id
99          * R13      = PACA
100          */
101
102         /* Restore non-volatile host registers (r14 - r31) and CR */
103         REST_NVGPRS(r1)
104         ld      r4, _CCR(r1)
105         mtcr    r4
106
107         addi    r1, r1, SWITCH_FRAME_SIZE
108         ld      r0, PPC_LR_STKOFF(r1)
109         mtlr    r0
110         blr
111
112 _GLOBAL(kvmhv_save_host_pmu)
113 BEGIN_FTR_SECTION
114         /* Work around P8 PMAE bug */
115         li      r3, -1
116         clrrdi  r3, r3, 10
117         mfspr   r8, SPRN_MMCR2
118         mtspr   SPRN_MMCR2, r3          /* freeze all counters using MMCR2 */
119         isync
120 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
121         li      r3, 1
122         sldi    r3, r3, 31              /* MMCR0_FC (freeze counters) bit */
123         mfspr   r7, SPRN_MMCR0          /* save MMCR0 */
124         mtspr   SPRN_MMCR0, r3          /* freeze all counters, disable interrupts */
125         mfspr   r6, SPRN_MMCRA
126         /* Clear MMCRA in order to disable SDAR updates */
127         li      r5, 0
128         mtspr   SPRN_MMCRA, r5
129         isync
130         lbz     r5, PACA_PMCINUSE(r13)  /* is the host using the PMU? */
131         cmpwi   r5, 0
132         beq     31f                     /* skip if not */
133         mfspr   r5, SPRN_MMCR1
134         mfspr   r9, SPRN_SIAR
135         mfspr   r10, SPRN_SDAR
136         std     r7, HSTATE_MMCR0(r13)
137         std     r5, HSTATE_MMCR1(r13)
138         std     r6, HSTATE_MMCRA(r13)
139         std     r9, HSTATE_SIAR(r13)
140         std     r10, HSTATE_SDAR(r13)
141 BEGIN_FTR_SECTION
142         mfspr   r9, SPRN_SIER
143         std     r8, HSTATE_MMCR2(r13)
144         std     r9, HSTATE_SIER(r13)
145 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
146 BEGIN_FTR_SECTION
147         mfspr   r5, SPRN_MMCR3
148         mfspr   r6, SPRN_SIER2
149         mfspr   r7, SPRN_SIER3
150         std     r5, HSTATE_MMCR3(r13)
151         std     r6, HSTATE_SIER2(r13)
152         std     r7, HSTATE_SIER3(r13)
153 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_31)
154         mfspr   r3, SPRN_PMC1
155         mfspr   r5, SPRN_PMC2
156         mfspr   r6, SPRN_PMC3
157         mfspr   r7, SPRN_PMC4
158         mfspr   r8, SPRN_PMC5
159         mfspr   r9, SPRN_PMC6
160         stw     r3, HSTATE_PMC1(r13)
161         stw     r5, HSTATE_PMC2(r13)
162         stw     r6, HSTATE_PMC3(r13)
163         stw     r7, HSTATE_PMC4(r13)
164         stw     r8, HSTATE_PMC5(r13)
165         stw     r9, HSTATE_PMC6(r13)
166 31:     blr