Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: instr_emul.s | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
46 | * Use is subject to license terms. | |
47 | */ | |
48 | ||
49 | #pragma ident "@(#)instr_emul.s 1.2 07/07/17 SMI" | |
50 | ||
51 | /* | |
52 | * Niagara II unimplemented instruction emulation | |
53 | */ | |
54 | #include <sys/asm_linkage.h> | |
55 | #include <sys/stack.h> | |
56 | #include <hypervisor.h> | |
57 | #include <hprivregs.h> | |
58 | #include <sparcv9/asi.h> | |
59 | #include <asi.h> | |
60 | #include <mmu.h> | |
61 | #include <traps.h> | |
62 | #include <sun4v/traps.h> | |
63 | #include <sun4v/mmu.h> | |
64 | #include <sun4v/asi.h> | |
65 | #include <sun4v/instr.h> | |
66 | #include <sparcv9/misc.h> | |
67 | ||
68 | #include <offsets.h> | |
69 | #include <traptable.h> | |
70 | #include <util.h> | |
71 | #include <guest.h> | |
72 | #include <segments.h> | |
73 | #include <debug.h> | |
74 | #include <abort.h> | |
75 | ||
76 | /* | |
77 | * Illegal access to non-cacheable page | |
78 | * | |
79 | * Emulate VIS LDBLOCKF instruction. | |
80 | * | |
81 | * %g1 TPC | |
82 | * %g2 VA from D-SFAR (sign-extended) | |
83 | * %g3 LSUCR | |
84 | */ | |
85 | ENTRY(dae_nc_page) | |
86 | ||
87 | /* | |
88 | * Decode the instruction to determine whether it's a VIS block load | |
89 | * instruction. | |
90 | * | |
91 | * Note: We know that we will never use these instructions in | |
92 | * hyper-privileged mode so we could ignore that possibility and | |
93 | * save a few instructions. Leave the test in for debug. | |
94 | */ | |
95 | #ifdef DEBUG | |
96 | rdhpr %htstate, %g4 | |
97 | btst HTSTATE_HPRIV, %g4 | |
98 | bnz,a,pn %xcc, hvabort | |
99 | rd %pc, %g1 | |
100 | #endif | |
101 | ||
102 | /* | |
103 | * Ascertain what the MMU is doing for instruction translation by | |
104 | * checking LSUCR.im | |
105 | */ | |
106 | btst LSUCR_IM, %g3 | |
107 | bz,pn %xcc, .dae_nc_page_tpc_ra | |
108 | nop | |
109 | ||
110 | /* | |
111 | * Check if we are in nucleus ctx or not. If we | |
112 | * are (ie, we took the trap the trap at TL == 0), | |
113 | * we need to zero the primary ctx regs | |
114 | * before using ASI_ITLB_PROBE. | |
115 | */ | |
116 | rdpr %tl, %g3 | |
117 | dec %g3 | |
118 | brz %g3, 1f | |
119 | .empty | |
120 | ||
121 | mov MMU_PCONTEXT0, %g5 | |
122 | ldxa [%g5]ASI_MMU, %g4 | |
123 | stxa %g0, [%g5]ASI_MMU | |
124 | STRAND_PUSH(%g4, %g6, %g7) | |
125 | ||
126 | mov MMU_PCONTEXT1, %g5 | |
127 | ldxa [%g5]ASI_MMU, %g4 | |
128 | stxa %g0, [%g5]ASI_MMU | |
129 | STRAND_PUSH(%g4, %g6, %g7) | |
130 | 1: | |
131 | /* | |
132 | * LSUCR.im == 1, virtual address translation is enabled | |
133 | * %g1 contains VA of instruction, clear VA[12:0] | |
134 | */ | |
135 | srlx %g1, 13, %g6 | |
136 | sllx %g6, 13, %g6 | |
137 | ||
138 | /* | |
139 | * VA[39:5] for ASI_ITLB_PROBE is VA[47:13] | |
140 | */ | |
141 | srlx %g6, 13 - 5, %g6 | |
142 | ldxa [%g6]ASI_ITLB_PROBE, %g7 | |
143 | brlz,a,pt %g7, 2f ! valid PA ? (bit 63 == 1 ?) | |
144 | nop | |
145 | ||
146 | ! not a valid PA, look for RA->PA translation | |
147 | or %g6, (1 << 4), %g6 | |
148 | ldxa [%g6]ASI_ITLB_PROBE, %g7 | |
149 | 2: | |
150 | ! if needed, restore MMU contexts | |
151 | brz %g3, 3f | |
152 | nop | |
153 | ||
154 | STRAND_POP(%g4, %g5) | |
155 | mov MMU_PCONTEXT0, %g5 | |
156 | stxa %g4, [%g5]ASI_MMU | |
157 | STRAND_POP(%g4, %g5) | |
158 | mov MMU_PCONTEXT1, %g5 | |
159 | stxa %g4, [%g5]ASI_MMU | |
160 | ||
161 | 3: | |
162 | ! valid PA ? (bit 63 is Valid bit) | |
163 | brlz,a,pt %g7, .dae_nc_page_va | |
164 | sllx %g7, 1, %g6 ! %g6 bit 62 after ITLB_PROBE, | |
165 | ! multi-hit | |
166 | ||
167 | /* | |
168 | * nope, retry the instruction and hope for better luck next time | |
169 | * | |
170 | * Note: We are introducing a possible infinite retry/trap loop | |
171 | * here. This needs to be carefully considered. | |
172 | */ | |
173 | retry | |
174 | ||
175 | .dae_nc_page_va: | |
176 | /* | |
177 | * valid instruction address found with ASI_ITLB_PROBE | |
178 | * better avoid multi-hits and parity errors | |
179 | * | |
180 | * %g1 instruction VA | |
181 | * %g7 Valid PA[39:13], (need to clear bit 63) | |
182 | */ | |
183 | brlz,pn %g6, .dae_nc_page_dmmu_err ! %g6 bit 62 << 1 | |
184 | sllx %g6, 1, %g6 ! %g6 bit 61 after ITLB_PROBE, | |
185 | ! parity | |
186 | brlz,pn %g6, .dae_nc_page_dmmu_err ! %g6 bit 61 << 1 | |
187 | ||
188 | sllx %g7, 1, %g7 | |
189 | srlx %g7, 1, %g7 | |
190 | ||
191 | ! VA[12:0] -> PA[12:0] | |
192 | set 0x1fff, %g6 | |
193 | and %g1, %g6, %g5 ! %g5 VA[12:0] | |
194 | or %g7, %g5, %g7 ! %g7 PA of instruction | |
195 | ba .dae_nc_page_decode_instr | |
196 | ld [%g7], %g5 ! %g5 instruction | |
197 | ||
198 | .dae_nc_page_tpc_ra: | |
199 | ||
200 | /* | |
201 | * TPC contains RA | |
202 | * %g1 contains RA of instruction | |
203 | */ | |
204 | GUEST_STRUCT(%g4) | |
205 | RA2PA_CONV(%g4, %g1, %g5, %g6) ! %g5 PA | |
206 | ld [%g5], %g5 ! %g5 instruction | |
207 | ||
208 | .dae_nc_page_decode_instr: | |
209 | /* | |
210 | * %g1 TPC | |
211 | * %g2 VA from D-SFAR (sign-extended) | |
212 | * %g5 instruction to decode | |
213 | */ | |
214 | srlx %g5, LDBLOCKF_OP_SHIFT, %g7 ! op | |
215 | cmp %g7, LDBLOCKF_OP | |
216 | bne,pn %xcc, .dae_nc_page_dmmu_err | |
217 | set LDBLOCKF_OP3_MASK, %g7 | |
218 | and %g5, %g7, %g7 | |
219 | srlx %g7, LDBLOCKF_OP3_SHIFT, %g7 | |
220 | cmp %g7, LDBLOCKF_OP3 ! block load | |
221 | bne,pn %xcc, .dae_nc_page_dmmu_err | |
222 | ||
223 | /* | |
224 | * Block load/store, check the ASI from the instruction if instr.i = 0, | |
225 | * from TSTATE.ASI if instr.i = 1. | |
226 | * | |
227 | * %g5 instruction | |
228 | */ | |
229 | srlx %g5, LDBLOCKF_I_SHIFT, %g4 | |
230 | btst 1, %g4 | |
231 | bnz,pn %xcc, 1f ! i = 1 | |
232 | nop | |
233 | ||
234 | set LDBLOCKF_ASI_MASK, %g4 | |
235 | and %g4, %g5, %g4 | |
236 | ba,pt %xcc, 2f | |
237 | srlx %g4, LDBLOCKF_ASI_SHIFT, %g4 ! %g4 instr.imm_asi | |
238 | 1: | |
239 | rdpr %tstate, %g4 | |
240 | srlx %g4, TSTATE_ASI_SHIFT, %g4 | |
241 | and %g4, TSTATE_ASI_MASK, %g4 | |
242 | 2: | |
243 | ||
244 | /* | |
245 | * If the ASI is not for a block load/store, no emulation | |
246 | * The following ASIs are for use with LDDFA and STDFA instructions | |
247 | * as Block Load (LDBLOCKF) and Block Store (STBLOCKF) operations. | |
248 | * | |
249 | * The block load ASI is mapped as :- | |
250 | * | |
251 | * ASI_BLK_AIUP -> ASI_AIUP | |
252 | * ASI_BLK_AIUS -> ASI_AIUS | |
253 | * ASI_BLK_AIUP_LE -> ASI_AIUP_LE | |
254 | * ASI_BLK_AIUS_LE -> ASI_AIUS_LE | |
255 | * ASI_BLK_P -> ASI_AIUP | |
256 | * ASI_BLK_S -> ASI_AIUS | |
257 | * ASI_BLK_PL -> ASI_AIUP_LE | |
258 | * ASI_BLK_SL -> ASI_AIUS_LE | |
259 | * | |
260 | * Note: Is there a possible TLB/TSB miss here which would cause | |
261 | * a guest trap at TL > 1 but with a user VA ? We are entering | |
262 | * dangerous territor here. | |
263 | * | |
264 | * %g4 ASI | |
265 | */ | |
266 | cmp %g4, ASI_BLK_P | |
267 | be,pn %xcc, .dae_nc_page_asi_ok | |
268 | mov ASI_AIUP, %g7 | |
269 | cmp %g4, ASI_BLK_S | |
270 | be,pn %xcc, .dae_nc_page_asi_ok | |
271 | mov ASI_AIUS, %g7 | |
272 | cmp %g4, ASI_BLK_PL | |
273 | be,pn %xcc, .dae_nc_page_asi_ok | |
274 | mov ASI_AIUP_LE, %g7 | |
275 | cmp %g4, ASI_BLK_SL | |
276 | be,pn %xcc, .dae_nc_page_asi_ok | |
277 | mov ASI_AIUS_LE, %g7 | |
278 | cmp %g4, ASI_BLK_AIUP | |
279 | be,pn %xcc, .dae_nc_page_asi_ok | |
280 | mov ASI_AIUP, %g7 | |
281 | cmp %g4, ASI_BLK_AIUS | |
282 | be,pn %xcc, .dae_nc_page_asi_ok | |
283 | mov ASI_AIUS, %g7 | |
284 | cmp %g4, ASI_BLK_AIUP_LE | |
285 | be,pn %xcc, .dae_nc_page_asi_ok | |
286 | mov ASI_AIUP_LE, %g7 | |
287 | cmp %g4, ASI_BLK_AIUS_LE | |
288 | be,pn %xcc, .dae_nc_page_asi_ok | |
289 | mov ASI_AIUS_LE, %g7 | |
290 | ||
291 | /* | |
292 | * Not a block load/store ASI, so treat this as any other | |
293 | * MMU DAE_nc_page error | |
294 | */ | |
295 | ba,a,pt %xcc, .dae_nc_page_dmmu_err | |
296 | .empty | |
297 | ||
298 | .dae_nc_page_asi_ok: | |
299 | /* | |
300 | * Valid LDBLOCKF VIS instruction, emulate | |
301 | * | |
302 | * %g2 VA from D-SFAR (sign-extended) | |
303 | * %g5 instruction | |
304 | * %g7 ASI | |
305 | */ | |
306 | ||
307 | /* | |
308 | * Get the target register, verify that it is a double-precision | |
309 | * FP register aligned on an eight-double-precision register boundary. | |
310 | */ | |
311 | set LDBLOCKF_RD_MASK, %g3 | |
312 | and %g5, %g3, %g3 | |
313 | srlx %g3, LDBLOCKF_RD_SHIFT, %g3 ! %g3 target FP register | |
314 | btst 1, %g3 ! if odd-numbered fp reg, it | |
315 | ! is for fp32 and up | |
316 | ||
317 | bnz,a,pt %xcc, 0f ! it is for fp32 and up | |
318 | add %g3, 31, %g3 ! only 5 bits available for | |
319 | ! dest reg in instr | |
320 | 0: | |
321 | #if 0 | |
322 | /* | |
323 | * illegal_inst trap has priority, no need to check for aligned fp reg | |
324 | * save a couple of instructions here | |
325 | */ | |
326 | btst 0xf, %g3 | |
327 | bnz,pn %xcc, .dae_nc_page_dmmu_err | |
328 | nop | |
329 | #endif | |
330 | ||
331 | wr %g7, %asi ! set target ASI | |
332 | ||
333 | /* | |
334 | * we know this was a valid FP block load operation, | |
335 | * as the fp_disabled trap has priority, so FPRS.fef | |
336 | * must have been set. Set it again now for the hypervisor | |
337 | * without checking/storing FPRS, save a few instructions. | |
338 | * The DAE_nc_page trap will have enabled PSTATE.PEF. | |
339 | */ | |
340 | wr %g0, FPRS_FEF, %fprs | |
341 | ||
342 | .dae_nc_page_ldblockf: | |
343 | ||
344 | #define LD_FP_SIZE (SZ_INSTR * 9) | |
345 | ||
346 | /* | |
347 | * get address of 'load table' below | |
348 | * | |
349 | * %g2 PA | |
350 | * %g3 target register | |
351 | */ | |
352 | ba 1f | |
353 | rd %pc, %g5 | |
354 | ||
355 | .dae_nc_page_load_fp0: | |
356 | ldda [%g2 + 0]%asi, %f0 | |
357 | ldda [%g2 + 8]%asi, %f2 | |
358 | ldda [%g2 + 16]%asi, %f4 | |
359 | ldda [%g2 + 24]%asi, %f6 | |
360 | ldda [%g2 + 32]%asi, %f8 | |
361 | ldda [%g2 + 40]%asi, %f10 | |
362 | ldda [%g2 + 48]%asi, %f12 | |
363 | ldda [%g2 + 56]%asi, %f14 | |
364 | done | |
365 | ||
366 | .dae_nc_page_load_fp16: | |
367 | ldda [%g2 + 0]%asi, %f16 | |
368 | ldda [%g2 + 8]%asi, %f18 | |
369 | ldda [%g2 + 16]%asi, %f20 | |
370 | ldda [%g2 + 24]%asi, %f22 | |
371 | ldda [%g2 + 32]%asi, %f24 | |
372 | ldda [%g2 + 40]%asi, %f26 | |
373 | ldda [%g2 + 48]%asi, %f28 | |
374 | ldda [%g2 + 56]%asi, %f30 | |
375 | done | |
376 | ||
377 | .dae_nc_page_load_fp32: | |
378 | ldda [%g2 + 0]%asi, %f32 | |
379 | ldda [%g2 + 8]%asi, %f34 | |
380 | ldda [%g2 + 16]%asi, %f36 | |
381 | ldda [%g2 + 24]%asi, %f38 | |
382 | ldda [%g2 + 32]%asi, %f40 | |
383 | ldda [%g2 + 40]%asi, %f42 | |
384 | ldda [%g2 + 48]%asi, %f44 | |
385 | ldda [%g2 + 56]%asi, %f46 | |
386 | done | |
387 | ||
388 | .dae_nc_page_load_fp48: | |
389 | ldda [%g2 + 0]%asi, %f48 | |
390 | ldda [%g2 + 8]%asi, %f50 | |
391 | ldda [%g2 + 16]%asi, %f52 | |
392 | ldda [%g2 + 24]%asi, %f54 | |
393 | ldda [%g2 + 32]%asi, %f56 | |
394 | ldda [%g2 + 40]%asi, %f58 | |
395 | ldda [%g2 + 48]%asi, %f60 | |
396 | ldda [%g2 + 56]%asi, %f62 | |
397 | done | |
398 | ||
399 | 1: | |
400 | ||
401 | /* | |
402 | * Jump into the load table, load the FP registers from the | |
403 | * source address and return to TNPC. | |
404 | * | |
405 | * target register must be 8 double-aligned, (% 16 == 0) | |
406 | * | |
407 | * %g2 PA for load | |
408 | * %g3 target register | |
409 | * %g5 &.dae_nc_page_load_fp0 | |
410 | */ | |
411 | srlx %g3, 4, %g3 ! fpreg / 16 | |
412 | mulx %g3, LD_FP_SIZE, %g3 | |
413 | add %g3, %g5, %g3 | |
414 | jmp %g3 + SZ_INSTR | |
415 | nop | |
416 | ||
417 | .dae_nc_page_dmmu_err: | |
418 | /* | |
419 | * Emulation not supported for this instruction, treat as | |
420 | * DMMU DAE_nc_page error | |
421 | */ | |
422 | DMMU_ERR_RV(MMU_FT_NCATOMIC) | |
423 | ||
424 | /* NOTREACHED */ | |
425 | ||
426 | SET_SIZE(dae_nc_page) |