hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *
 * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
 *
 * Derived from book3s_interrupts.S, which is:
 * Copyright SUSE Linux Products GmbH 2009
 *
 * Authors: Alexander Graf <agraf@suse.de>
 */
 
#include <asm/ppc_asm.h>
#include <asm/kvm_asm.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/asm-offsets.h>
#include <asm/exception-64s.h>
#include <asm/ppc-opcode.h>
#include <asm/asm-compat.h>
#include <asm/feature-fixups.h>
 
/*****************************************************************************
 *                                                                           *
 *     Guest entry / exit code that is in kernel module memory (vmalloc)     *
 *                                                                           *
 ****************************************************************************/
 
/* Registers:
 *  none
 */
_GLOBAL(__kvmppc_vcore_entry)
 
   /* Write correct stack frame */
   mflr    r0
   std    r0,PPC_LR_STKOFF(r1)
 
   /* Save host state to the stack */
   stdu    r1, -SWITCH_FRAME_SIZE(r1)
 
   /* Save non-volatile registers (r14 - r31) and CR */
   SAVE_NVGPRS(r1)
   mfcr    r3
   std    r3, _CCR(r1)
 
   /* Save host DSCR */
   mfspr    r3, SPRN_DSCR
   std    r3, HSTATE_DSCR(r13)
 
BEGIN_FTR_SECTION
   /* Save host DABR */
   mfspr    r3, SPRN_DABR
   std    r3, HSTATE_DABR(r13)
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 
   /* Save host PMU registers */
   bl    kvmhv_save_host_pmu
 
   /*
    * Put whatever is in the decrementer into the
    * hypervisor decrementer.
    * Because of a hardware deviation in P8 and P9,
    * we need to set LPCR[HDICE] before writing HDEC.
    */
   ld    r5, HSTATE_KVM_VCORE(r13)
   ld    r6, VCORE_KVM(r5)
   ld    r9, KVM_HOST_LPCR(r6)
   ori    r8, r9, LPCR_HDICE
   mtspr    SPRN_LPCR, r8
   isync
   andis.    r0, r9, LPCR_LD@h
   mfspr    r8,SPRN_DEC
   mftb    r7
BEGIN_FTR_SECTION
   /* On POWER9, don't sign-extend if host LPCR[LD] bit is set */
   bne    32f
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
   extsw    r8,r8
32:    mtspr    SPRN_HDEC,r8
   add    r8,r8,r7
   std    r8,HSTATE_DECEXP(r13)
 
   /* Jump to partition switch code */
   bl    kvmppc_hv_entry_trampoline
   nop
 
/*
 * We return here in virtual mode after the guest exits
 * with something that we can't handle in real mode.
 * Interrupts are still hard-disabled.
 */
 
   /*
    * Register usage at this point:
    *
    * R1       = host R1
    * R2       = host R2
    * R3       = trap number on this thread
    * R12      = exit handler id
    * R13      = PACA
    */
 
   /* Restore non-volatile host registers (r14 - r31) and CR */
   REST_NVGPRS(r1)
   ld    r4, _CCR(r1)
   mtcr    r4
 
   addi    r1, r1, SWITCH_FRAME_SIZE
   ld    r0, PPC_LR_STKOFF(r1)
   mtlr    r0
   blr
 
_GLOBAL(kvmhv_save_host_pmu)
BEGIN_FTR_SECTION
   /* Work around P8 PMAE bug */
   li    r3, -1
   clrrdi    r3, r3, 10
   mfspr    r8, SPRN_MMCR2
   mtspr    SPRN_MMCR2, r3        /* freeze all counters using MMCR2 */
   isync
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
   li    r3, 1
   sldi    r3, r3, 31        /* MMCR0_FC (freeze counters) bit */
   mfspr    r7, SPRN_MMCR0        /* save MMCR0 */
   mtspr    SPRN_MMCR0, r3        /* freeze all counters, disable interrupts */
   mfspr    r6, SPRN_MMCRA
   /* Clear MMCRA in order to disable SDAR updates */
   li    r5, 0
   mtspr    SPRN_MMCRA, r5
   isync
   lbz    r5, PACA_PMCINUSE(r13)    /* is the host using the PMU? */
   cmpwi    r5, 0
   beq    31f            /* skip if not */
   mfspr    r5, SPRN_MMCR1
   mfspr    r9, SPRN_SIAR
   mfspr    r10, SPRN_SDAR
   std    r7, HSTATE_MMCR0(r13)
   std    r5, HSTATE_MMCR1(r13)
   std    r6, HSTATE_MMCRA(r13)
   std    r9, HSTATE_SIAR(r13)
   std    r10, HSTATE_SDAR(r13)
BEGIN_FTR_SECTION
   mfspr    r9, SPRN_SIER
   std    r8, HSTATE_MMCR2(r13)
   std    r9, HSTATE_SIER(r13)
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
BEGIN_FTR_SECTION
   mfspr    r5, SPRN_MMCR3
   mfspr    r6, SPRN_SIER2
   mfspr    r7, SPRN_SIER3
   std    r5, HSTATE_MMCR3(r13)
   std    r6, HSTATE_SIER2(r13)
   std    r7, HSTATE_SIER3(r13)
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_31)
   mfspr    r3, SPRN_PMC1
   mfspr    r5, SPRN_PMC2
   mfspr    r6, SPRN_PMC3
   mfspr    r7, SPRN_PMC4
   mfspr    r8, SPRN_PMC5
   mfspr    r9, SPRN_PMC6
   stw    r3, HSTATE_PMC1(r13)
   stw    r5, HSTATE_PMC2(r13)
   stw    r6, HSTATE_PMC3(r13)
   stw    r7, HSTATE_PMC4(r13)
   stw    r8, HSTATE_PMC5(r13)
   stw    r9, HSTATE_PMC6(r13)
31:    blr