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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
/*
* Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
*
* Copyright (C) 2010-2012 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; see the file COPYING. If not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#line 5
#include "arm_defs.h"
#include "platdefx.h"
#include "arm_as_macros.h"
/**
* @file
*
* @brief Save and Load VFP entire VFP state.
*/
.text
/**
* @brief Save VFP context
* @param R0 = save area pointer:
* .long fpexc,fpscr,fpinst,fpinst2,cpacr,fpexc'
* .double d0..d15
* .double d16..d31
* Note: VFP is left in an enable state regardless of initial state.
*/
.align 4
.global SaveVFP
SaveVFP:
/*
* Save registers. GCC does not expect us to preserve R0..R3,R12,LR.
*/
stmdb sp!, {r4-r6}
/*
* Save Coproc Access Control register.
*/
mrc_p15 COPROC_ACCESS_CONTROL, r5
/*
* If CP10/11 are disabled, enable them so we can save VFP state.
* The host (or guest) may have left data in the data registers that
* must be preserved.
*/
orr r2, r5, #CPACR_CP10_CP11_PRIV_ONLY
mcr_p15 COPROC_ACCESS_CONTROL, r2
isb
/*
* Follow procedure on AppxB-22 ARM DDI0406B to save FPINST[2].
* Also enable VFP access with FPEXC_EN.
*/
fmrx r1, fpexc @ get existing FPEXC system register
orr r6, r1, #ARM_VFP_SYSTEM_REG_FPEXC_EX|ARM_VFP_SYSTEM_REG_FPEXC_FP2V|ARM_VFP_SYSTEM_REG_FPEXC_EN
#if !defined(MVP_HOST_CODE_forceon)
fmxr fpexc, r6 @ set FPEXC.EX, .FP2V and .EN
fmrx r6, fpexc @ read them back
tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_EX @ see if either one is valid
beq 1000f @ neither, skip it all
fmrx r3, FPINST @ FPINST is valid, save it
tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_FP2V @ see if FPINST2 is valid
beq 1000f
fmrx r4, FPINST2 @ FPINST2 is valid, save it
1000:
#else
mov r6, r1
#endif
fmrx r2, FPSCR @ always save FPSCR system register
/*
* At this point:
* R1 = original FPEXC
* R2 = FPSCR
* R3 = FPINST
* R4 = FPINST2
* R5 = original CPACR
* R6 = FPEXC readback with FPEXC.EX, .FP2V and .EN set
* telling us whether FPINST/2 are valid
*/
stmia r0!, {r1-r6}
/*
* Save floating point data registers.
*/
vstmia r0!, {d0-d15} @ Save d0 thru d15
/**
* @todo We should probably just read MVFR0 once at boot/initialization
* time and store it in some variable, to save having to do what might
* be expensive coprocessor accesses.
*/
fmrx r1, MVFR0 @ Read Media and VFP Feature Register 0
and r1, r1, #ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK @ A_SIMD field
cmp r1, #2 @ 32 x 64bit registers?
bne 2000f
vstmia r0!, {d16-d31}
2000:
/*
* Restore scratch registers and return.
*/
ldmia sp!, {r4-r6}
mov pc, lr
/**
* @brief Load VFP context
* @param R0 = load area pointer:
* .long fpexc,fpscr,fpinst,fpinst2,cpacr,fpexc'
* .double d0..d15
* .double d16..d31
* @note VFP is assumed to be in an enabled state on entry.
*/
.align 4
.global LoadVFP
LoadVFP:
/*
* Save registers. GCC does not expect us to preserve R0..R3,R12,LR.
*/
stmdb sp!, {r4-r6}
/*
* Get status register contents:
* R1 = original FPEXC
* R2 = FPSCR
* R3 = FPINST
* R4 = FPINST2
* R5 = original CPACR
* R6 = FPEXC readback with FPEXC.EX, .FP2V and .EN set
* telling us whether FPINST/2 are valid
*/
ldmia r0!, {r1-r6}
/*
* Restore some initial FP status registers.
*/
fmxr fpexc, r6 @ with FPEXC.EX, .FP2V and .EN set
fmxr FPSCR, r2 @ always load FPSCR system register
/*
* Follow procedure on AppxB-22 ARM DDI0406B to load FPINST[2].
*/
#if !defined(MVP_HOST_CODE_forceon)
fmrx r6, fpexc @ initial call might have different bits
@ ... because FPEXC.EX, .FP2V and .EN
@ are forced set by init code in
@ mvpd.c SetupMonitor()
tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_EX @ see if either one is valid
beq 1000f @ neither, skip it all
fmxr FPINST, r3 @ FPINST is valid, save it
tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_FP2V @ see if FPINST2 is valid
beq 1000f
fmxr FPINST2, r4 @ FPINST2 is valid, save it
1000:
#endif
/*
* Load floating point data registers.
*/
vldmia r0!, {d0-d15}
/**
* @todo We should probably just read MVFR0 once at boot/initialization
* time and store it in some variable, to save having to do what might
* be expensive coprocessor accesses.
*/
fmrx r3, MVFR0 @ Read Media and VFP Feature Register 0
and r3, r3, #ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK @ A_SIMD field
cmp r3, #2 @ 32 x 64bit registers?
bne 2000f
vldmia r0!, {d16-d31}
2000:
/*
* Now that VFP registers are all loaded, we put the restored values
* back in the registers, possibly disabling the VFP.
*/
fmxr fpexc, r1 @ with original FPEXC.EX, FPEXC.FP2V
@ and FPEXC.EN values
/*
* Load Coproc Access Control CP10/CP11 enable bits, possibly disabling
* VFP access.
*/
mrc_p15 COPROC_ACCESS_CONTROL, r0
bic r0, r0, #CPACR_CP10_CP11_MASK
and r5, r5, #CPACR_CP10_CP11_MASK
orr r0, r0, r5
mcr_p15 COPROC_ACCESS_CONTROL, r0
isb
/*
* Restore scratch registers and return.
*/
ldmia sp!, {r4-r6}
mov pc, lr
.align 4
.global GetFPEXC
GetFPEXC:
fmrx r0, fpexc @ get existing FPEXC system register
mov pc, lr
|