|
|
1.1 root 1: /* $Id: stp103x.c,v 1.5 2010/06/05 18:57:04 fredette Exp $ */
2:
3: /* ic/sparc/stp103x.c - implementation of UltraSPARC I (STP1030) and II (STP1031) emulation: */
4:
5: /*
6: * Copyright (c) 2008 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
37: _TME_RCSID("$Id: stp103x.c,v 1.5 2010/06/05 18:57:04 fredette Exp $");
38:
39: /* includes: */
40: #include "sparc-impl.h"
41:
42: /* macros: */
43:
44: /* the PSTATE extensions: */
45: #define TME_STP103X_PSTATE_IG TME_BIT(11)
46: #define TME_STP103X_PSTATE_MG TME_BIT(10)
47:
48: /* the load/store unit control register: */
49: #define TME_STP103X_LSU_IC TME_BIT(0)
50: #define TME_STP103X_LSU_DC TME_BIT(1)
51: #define TME_STP103X_LSU_IM TME_BIT(2)
52: #define TME_STP103X_LSU_DM TME_BIT(3)
53: #define TME_STP103X_LSU_FM (TME_BIT(20) - TME_BIT(4))
54: #define TME_STP103X_LSU_VW TME_BIT(21)
55: #define TME_STP103X_LSU_VR TME_BIT(22)
56: #define TME_STP103X_LSU_PW TME_BIT(23)
57: #define TME_STP103X_LSU_PR TME_BIT(24)
58:
59: /* the E-Cache (E-state) error enable register: */
60: #define TME_STP103X_ESTATE_ERROR_ENABLE_CEEN TME_BIT(0)
61: #define TME_STP103X_ESTATE_ERROR_ENABLE_NCEEN TME_BIT(1)
62: #define TME_STP103X_ESTATE_ERROR_ENABLE_ISAPEN TME_BIT(2)
63:
64: /* the start of the virtual address hole: */
65: #define TME_STP103X_VA_HOLE_START (((tme_uint64_t) 1) << 43)
66:
67: /* the size of the physical address space: */
68: #define TME_STP103X_PA_SIZE (((tme_uint64_t) 1) << 41)
69:
70: /* the maximum context number: */
71: #define TME_STP103X_CONTEXT_MAX (8191)
72:
73: /* the different page sizes: */
74: #define TME_STP103X_PAGE_SIZE_8KB (8 * 1024)
75: #define TME_STP103X_PAGE_SIZE_64KB (64 * 1024)
76: #define TME_STP103X_PAGE_SIZE_512KB (512 * 1024)
77: #define TME_STP103X_PAGE_SIZE_4MB (4 * 1024 * 1024)
78:
79: /* because we often deal with the tme_uint64_t TLB/TTE entry tag and
80: data as tme_uint32_t halves for performance, we need to easily
81: generate the right bitfield masks for both types. this macro
82: converts the constant x to the type of e, and then shifts it by
83: (shift mod (8 * sizeof(e))). e is only typed, never evaluated: */
84: #define _TME_STP103X_TLB_X(e, x, shift) ((1 ? (x) : (e)) << ((shift) % (8 * sizeof(e))))
85:
86: /* TLB/TTE data: */
87: #define TME_STP103X_TLB_DATA_V(e) _TME_STP103X_TLB_X(e, 1, 63)
88: #define TME_STP103X_TLB_DATA_SIZE_MASK(e) _TME_STP103X_TLB_X(e, 0x3, 61)
89: #define TME_STP103X_TLB_DATA_SIZE_8KB(e) _TME_STP103X_TLB_X(e, 0x0, 61)
90: #define TME_STP103X_TLB_DATA_SIZE_64KB(e) _TME_STP103X_TLB_X(e, 0x1, 61)
91: #define TME_STP103X_TLB_DATA_SIZE_512KB(e) _TME_STP103X_TLB_X(e, 0x2, 61)
92: #define TME_STP103X_TLB_DATA_SIZE_4MB(e) _TME_STP103X_TLB_X(e, 0x3, 61)
93: #define TME_STP103X_TLB_DATA_NFO(e) _TME_STP103X_TLB_X(e, 1, 60)
94: #define TME_STP103X_TLB_DATA_IE(e) _TME_STP103X_TLB_X(e, 1, 59)
95: #define TME_STP103X_TLB_DATA_SOFT2(e) _TME_STP103X_TLB_X(e, 0x1ff, 50)
96: #define TME_STP103X_TLB_DATA_SIZE_CAM_MASK(e) _TME_STP103X_TLB_X(e, 0x7, 45)
97: #define TME_STP103X_TLB_DATA_SIZE_CAM_8KB(e) _TME_STP103X_TLB_X(e, 0x0, 45)
98: #define TME_STP103X_TLB_DATA_SIZE_CAM_64KB(e) _TME_STP103X_TLB_X(e, 0x1, 45)
99: #define TME_STP103X_TLB_DATA_SIZE_CAM_512KB(e) _TME_STP103X_TLB_X(e, 0x3, 45)
100: #define TME_STP103X_TLB_DATA_SIZE_CAM_4MB(e) _TME_STP103X_TLB_X(e, 0x7, 45)
101: #define TME_STP103X_TLB_DATA_SIZE_RAM_MASK(e) _TME_STP103X_TLB_X(e, 0x7, 42)
102: #define TME_STP103X_TLB_DATA_SIZE_RAM_8KB(e) _TME_STP103X_TLB_X(e, 0x0, 42)
103: #define TME_STP103X_TLB_DATA_SIZE_RAM_64KB(e) _TME_STP103X_TLB_X(e, 0x1, 42)
104: #define TME_STP103X_TLB_DATA_SIZE_RAM_512KB(e) _TME_STP103X_TLB_X(e, 0x3, 42)
105: #define TME_STP103X_TLB_DATA_SIZE_RAM_4MB(e) _TME_STP103X_TLB_X(e, 0x7, 42)
106: #define TME_STP103X_TLB_DATA_DIAG_USED(e) _TME_STP103X_TLB_X(e, 1, 41)
107: #define TME_STP103X_TLB_DATA_PA ((((tme_uint64_t) 1) << 41) - (1 << 13))
108: #define TME_STP103X_TLB_DATA_SOFT(e) _TME_STP103X_TLB_X(e, 0x3f, 7)
109: #define TME_STP103X_TLB_DATA_L(e) _TME_STP103X_TLB_X(e, 1, 6)
110: #define TME_STP103X_TLB_DATA_CP(e) _TME_STP103X_TLB_X(e, 1, 5)
111: #define TME_STP103X_TLB_DATA_CV(e) _TME_STP103X_TLB_X(e, 1, 4)
112: #define TME_STP103X_TLB_DATA_E(e) _TME_STP103X_TLB_X(e, 1, 3)
113: #define TME_STP103X_TLB_DATA_P(e) _TME_STP103X_TLB_X(e, 1, 2)
114: #define TME_STP103X_TLB_DATA_W(e) _TME_STP103X_TLB_X(e, 1, 1)
115: #define TME_STP103X_TLB_DATA_G(e) _TME_STP103X_TLB_X(e, 1, 0)
116:
117: /* the DMMU and IMMU SFSR: */
118: #define TME_STP103X_SFSR_ASI (0xff << 16)
119: #define TME_STP103X_SFSR_FT_PRIVILEGE (0x01 << 7)
120: #define TME_STP103X_SFSR_FT_SIDE_EFFECTS (0x02 << 7)
121: #define TME_STP103X_SFSR_FT_UNCACHEABLE (0x04 << 7)
122: #define TME_STP103X_SFSR_FT_ILLEGAL (0x08 << 7)
123: #define TME_STP103X_SFSR_FT_NO_FAULT_FAULT (0x10 << 7)
124: #define TME_STP103X_SFSR_FT_VA_RANGE (0x20 << 7)
125: #define TME_STP103X_SFSR_FT_VA_RANGE_NNPC (0x40 << 7)
126: #define TME_STP103X_SFSR_E TME_BIT(6)
127: #define TME_STP103X_SFSR_CT_PRIMARY (0x0 << 4)
128: #define TME_STP103X_SFSR_CT_SECONDARY (0x1 << 4)
129: #define TME_STP103X_SFSR_CT_NUCLEUS (0x2 << 4)
130: #define TME_STP103X_SFSR_CT_RESERVED (0x3 << 4)
131: #define TME_STP103X_SFSR_PR TME_BIT(3)
132: #define TME_STP103X_SFSR_W TME_BIT(2)
133: #define TME_STP103X_SFSR_OW TME_BIT(1)
134: #define TME_STP103X_SFSR_FV TME_BIT(0)
135:
136: /* the AFSR: */
137: #define TME_STP103X_AFSR_ME (((tme_uint64_t) 1) << 32)
138: #define TME_STP103X_AFSR_PRIV TME_BIT(31)
139: #define TME_STP103X_AFSR_TO TME_BIT(27)
140:
141: /* a TSB register: */
142: #define TME_STP103X_TSB_SIZE (0x7)
143: #define TME_STP103X_TSB_SPLIT TME_BIT(12)
144:
145: /* specific traps: */
146: #define TME_STP103X_TRAP_MG _TME_SPARC_TRAP_IMPDEP(0)
147: #define TME_STP103X_TRAP_IG _TME_SPARC_TRAP_IMPDEP(1)
148: #define TME_STP103X_TRAP_interrupt_vector \
149: (TME_STP103X_TRAP_IG | _TME_SPARC_TRAP(16, 0x060))
150: #define TME_STP103X_TRAP_fast_instruction_access_MMU_miss \
151: (TME_STP103X_TRAP_MG | _TME_SPARC_TRAP(2, 0x064))
152: #define TME_STP103X_TRAP_fast_data_access_MMU_miss \
153: (TME_STP103X_TRAP_MG | _TME_SPARC_TRAP(12, 0x068))
154: #define TME_STP103X_TRAP_fast_data_access_protection \
155: (TME_STP103X_TRAP_MG | _TME_SPARC_TRAP(12, 0x06c))
156:
157: /* specific ASIs and flags: */
158: #define TME_STP103X_ASI_LSU_CONTROL_REG (0x45)
159: #define TME_STP103X_ASI_DCACHE_DATA (0x46)
160: #define TME_STP103X_ASI_DCACHE_TAG (0x47)
161: #define TME_STP103X_ASI_INTR_DISPATCH_STATUS (0x48)
162: #define TME_STP103X_ASI_INTR_RECEIVE (0x49)
163: #define TME_STP103X_ASI_UPA_CONFIG_REG (0x4a)
164: #define TME_STP103X_ASI_ESTATE_ERROR_EN_REG (0x4b)
165: #define TME_STP103X_ASI_AFSR (0x4c)
166: #define TME_STP103X_ASI_AFAR (0x4d)
167: #define TME_STP103X_ASI_ECACHE_TAG_DATA (0x4e)
168: #define TME_STP103X_ASI_IMMU (0x50)
169: #define TME_STP103X_ASI_DMMU (0x58)
170: #define TME_STP103X_ASI_FLAG_TSB_8KB_PTR (0x1)
171: #define TME_STP103X_ASI_FLAG_TSB_64KB_PTR (0x2)
172: #define TME_STP103X_ASI_BLK_COMMIT (0xe0)
173:
174: /* the size of the IMMU and DMMU TLBs: */
175: #define TME_STP103X_TLB_SIZE (64)
176:
177: /* the size of the E-Cache: */
178: #define TME_STP103X_ECACHE_SIZE (512 * 1024)
179:
180: /* the block size of the I-Cache: */
181: #define TME_STP103X_ICACHE_BLOCK_SIZE (32)
182:
183: /* the TICK_compare register: */
184: #define TME_STP103X_TCR_INT_DIS (((tme_uint64_t) 1) << 63)
185: #define TME_STP103X_TCR_TICK_CMPR (TME_STP103X_TCR_INT_DIS - 1)
186:
187: /* the SIR: */
188: #define TME_STP103X_SIR_SOFTINT(x) (1 << (x))
189: #define TME_STP103X_SIR_TICK_INT (1 << 0)
190:
191: /* ASI_INTR_RECEIVE: */
192: #define TME_STP103X_INTR_RECEIVE_BUSY (1 << 5)
193:
194: /* the block load and store sizes: */
195: #define TME_STP103X_BLOCK_SIZE (64)
196: #define TME_STP103X_BLOCK_FPREGS_DOUBLE (TME_STP103X_BLOCK_SIZE / sizeof(tme_uint64_t))
197:
198: /* other constants: */
199: #define TME_STP103X_MAXTL (5)
200:
201: /* the UPA configuration register: */
202: /* NB: this is a partial list: */
203: #define TME_STP1030_UPA_CONFIG_PCON ((2 << 29) - (1 << 22))
204: #define TME_STP1031_UPA_CONFIG_PCON ((((tme_uint64_t) 2) << 32) - (1 << 22))
205: #define TME_STP1031_UPA_CONFIG_ELIM ((((tme_uint64_t) 2) << 35) - (((tme_uint64_t) 1) << 33))
206:
207: /* the UPA queue depths and capabilities: */
208: #define TME_STP103X_UPA_PINT_RDQ (1)
209: #define TME_STP103X_UPA_PREQ_DQ (0)
210: #define TME_STP103X_UPA_PREQ_RQ (1)
211: #define TME_STP103X_UPA_UPACAP \
212: (TME_UPA_UPACAP_HANDLERSLAVE \
213: | TME_UPA_UPACAP_INTERRUPTMASTER \
214: | !TME_UPA_UPACAP_SLAVE_INT_L \
215: | TME_UPA_UPACAP_CACHEMASTER \
216: | TME_UPA_UPACAP_MASTER)
217:
218: /* fixed characteristics of the stp103x: */
219: #undef TME_SPARC_VERSION
220: #define TME_SPARC_VERSION(ic) (9)
221: #undef TME_SPARC_NWINDOWS
222: #define TME_SPARC_NWINDOWS(ic) (8)
223: #undef TME_SPARC_MEMORY_FLAGS
224: #define TME_SPARC_MEMORY_FLAGS(ic) \
225: (TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS \
226: + TME_SPARC_MEMORY_FLAG_HAS_INVERT_ENDIAN \
227: + !TME_SPARC_MEMORY_FLAG_HAS_LDDF_STDF_32)
228:
229: /* this recovers the stp103x state from the generic sparc state: */
230: #define TME_STP103X(ic) ((struct tme_stp103x *) (TRUE ? (ic) : (struct tme_sparc *) 0))
231:
232: /* this evaluates to nonzero if an ASI mask from an ASI_DMMU* or
233: ASI_IMMU* ASI is from an ASI_DMMU* ASI: */
234: #if (TME_STP103X_ASI_DMMU <= TME_STP103X_ASI_IMMU) || ((TME_STP103X_ASI_DMMU ^ TME_STP103X_ASI_IMMU) & ((TME_STP103X_ASI_DMMU ^ TME_STP103X_ASI_IMMU) - 1)) != 0
235: #error "TME_STP103X_ASI_DMMU or TME_STP103X_ASI_IMMU changed"
236: #endif
237: #define TME_STP103X_ASI_MMU_MASK_IS_DMMU(asi_mask) \
238: ((asi_mask) \
239: & TME_SPARC_ASI_MASK_RAW(TME_STP103X_ASI_DMMU \
240: ^ TME_STP103X_ASI_IMMU))
241:
242: /* specific load/store information: */
243: #define TME_STP103X_LSINFO_ASSERT_NO_FAULTS _TME_SPARC_LSINFO_X(0)
244:
245: /* specific load/store faults: */
246: #define TME_STP103X_LS_FAULT_MMU_MISS _TME_SPARC64_LS_FAULT_X(0)
247: #define TME_STP103X_LS_FAULT_PRIVILEGE _TME_SPARC64_LS_FAULT_X(1)
248: #define TME_STP103X_LS_FAULT_PROTECTION _TME_SPARC64_LS_FAULT_X(2)
249: #define TME_STP103X_LS_FAULT_ILLEGAL _TME_SPARC64_LS_FAULT_X(3)
250:
251: /* update flags: */
252: #define TME_STP103X_UPDATE_NONE (0)
253: #define TME_STP103X_UPDATE_DMMU TME_BIT(0)
254: #define TME_STP103X_UPDATE_IMMU (0)
255: #define TME_STP103X_UPDATE_MMU_TAG_ACCESS TME_BIT(1)
256: #define TME_STP103X_UPDATE_MMU_SFSR TME_BIT(2)
257: #define TME_STP103X_UPDATE_DMMU_SFAR TME_BIT(3)
258:
259: /* the first IMMU and DMMU TLB entry parts: */
260: #define TME_STP103X_TLB_PART_0_DMMU (TME_STP103X_TLB_SIZE * 2 * 0)
261: #define TME_STP103X_TLB_PART_0_IMMU (TME_STP103X_TLB_SIZE * 2 * 1)
262:
263: /* this returns nonzero if this is an stp1030: */
264: #define TME_STP103X_IS_1030(ic) (TME_STP103X(ic)->tme_stp103x_is_1030)
265:
266: /* types: */
267:
268: /* the stp103x DMMU and IMMU common state: */
269: struct tme_stp103x_mmu {
270:
271: /* the DMMU or IMMU synchronous fault status register: */
272: tme_uint64_t tme_stp103x_mmu_sfsr;
273:
274: /* the DMMU or IMMU tag access register: */
275: tme_uint64_t tme_stp103x_mmu_tag_access;
276:
277: /* the DMMU or IMMU translation storage buffer register: */
278: tme_uint64_t tme_stp103x_mmu_tsb;
279: };
280:
281: /* the stp103x state: */
282: struct tme_stp103x {
283:
284: /* the generic sparc state: */
285: struct tme_sparc tme_stp103x_sparc;
286:
287: /* the tick comparison register: */
288: tme_uint64_t tme_stp103x_tcr;
289:
290: /* the softint register: */
291: tme_uint16_t tme_stp103x_sir;
292: tme_memory_atomic_flag_t tme_stp103x_sir_tick_int;
293:
294: /* the dispatch control register: */
295: tme_uint8_t tme_stp103x_dcr;
296:
297: /* this is nonzero if this is an stp1030: */
298: tme_uint8_t tme_stp103x_is_1030;
299:
300: /* the performance control register: */
301: tme_uint16_t tme_stp103x_pcr;
302:
303: /* the performance instrumentation counters: */
304: union tme_value64 tme_stp103x_pic;
305:
306: /* the UPA configuration register: */
307: tme_uint64_t tme_stp103x_upa_config;
308:
309: /* the load/store unit control register: */
310: tme_uint64_t tme_stp103x_lsu;
311:
312: /* the estate error enable register: */
313: tme_uint32_t tme_stp103x_estate_error_enable;
314:
315: /* the ecache tag data register: */
316: tme_uint32_t tme_stp103x_ecache_tag_data;
317:
318: /* the ecache probe line: */
319: tme_uint64_t tme_stp103x_ecache_data_probe;
320:
321: /* the transmit and receive interrupt vector data: */
322: tme_uint64_t tme_stp103x_udb_intr_transmit[3];
323: tme_shared tme_uint64_t tme_stp103x_udb_intr_receive[3];
324: tme_shared tme_uint8_t tme_stp103x_intr_receive_mid;
325: tme_memory_atomic_flag_t tme_stp103x_intr_receive_busy;
326:
327: /* the tick compare condition and time: */
328: tme_cond_t tme_stp103x_tick_compare_cond;
329: struct timeval tme_stp103x_tick_compare_time;
330:
331: /* the UDB low and high control registers: */
332: tme_uint16_t tme_stp103x_udb_control[2];
333:
334: /* the asynchronous fault address and status registers: */
335: tme_uint64_t tme_stp103x_afar;
336: tme_uint64_t tme_stp103x_afsr;
337:
338: /* the DMMU and IMMU common state: */
339: struct tme_stp103x_mmu tme_stp103x_immu;
340: struct tme_stp103x_mmu tme_stp103x_dmmu;
341:
342: /* the DMMU synchronous fault address register: */
343: tme_uint64_t tme_stp103x_dmmu_sfar;
344:
345: /* this is nonzero if the last fast_data_access_protection trap was
346: for a 64KB page: */
347: tme_uint8_t tme_stp103x_dmmu_direct_64KB;
348:
349: /* the DMMU and IMMU TLB: */
350: /* NB: this single array is half IMMU TLB, half DMMU TLB, and each
351: entry has two parts: tag and data: */
352: union {
353: tme_uint64_t _tme_stp103x_tlb_u_64s[2 * 2 * TME_STP103X_TLB_SIZE];
354: #define tme_stp103x_tlb_64s(x) _tme_stp103x_tlb_u._tme_stp103x_tlb_u_64s[x]
355: tme_uint32_t _tme_stp103x_tlb_u_32s[2 * 4 * TME_STP103X_TLB_SIZE];
356: #if (TME_ENDIAN_NATIVE != TME_ENDIAN_BIG) && (TME_ENDIAN_NATIVE != TME_ENDIAN_LITTLE)
357: #error "only big- and little-endian hosts are supported"
358: #endif
359: #define tme_stp103x_tlb_32s(x, y) _tme_stp103x_tlb_u._tme_stp103x_tlb_u_32s[((x) * 2) + ((y) ^ (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG))]
360: } _tme_stp103x_tlb_u;
361: };
362:
363: /* globals: */
364:
365: /* the cacheable access bus router: */
366: static const tme_bus_lane_t _tme_stp103x_bus_router_cacheable[1 << TME_BUS128_LOG2][1 << TME_BUS128_LOG2] = {
367: /* a byte access: */
368: {
369: TME_BUS_LANE_ROUTE(0),
370: TME_BUS_LANE_UNDEF,
371: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
372: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
373: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
374: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF
375: },
376: /* a word access: */
377: {
378: TME_BUS_LANE_ROUTE(1),
379: TME_BUS_LANE_ROUTE(0),
380: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
381: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
382: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
383: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF
384: },
385: /* a doubleword access: */
386: {
387: TME_BUS_LANE_ROUTE(3),
388: TME_BUS_LANE_ROUTE(2),
389: TME_BUS_LANE_ROUTE(1),
390: TME_BUS_LANE_ROUTE(0),
391: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
392: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
393: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF
394: },
395: /* an extended word access: */
396: {
397: TME_BUS_LANE_ROUTE(7),
398: TME_BUS_LANE_ROUTE(6),
399: TME_BUS_LANE_ROUTE(5),
400: TME_BUS_LANE_ROUTE(4),
401: TME_BUS_LANE_ROUTE(3),
402: TME_BUS_LANE_ROUTE(2),
403: TME_BUS_LANE_ROUTE(1),
404: TME_BUS_LANE_ROUTE(0),
405: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF,
406: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF
407: },
408: /* a quadword access: */
409: {
410: TME_BUS_LANE_ROUTE(15),
411: TME_BUS_LANE_ROUTE(14),
412: TME_BUS_LANE_ROUTE(13),
413: TME_BUS_LANE_ROUTE(12),
414: TME_BUS_LANE_ROUTE(11),
415: TME_BUS_LANE_ROUTE(10),
416: TME_BUS_LANE_ROUTE(9),
417: TME_BUS_LANE_ROUTE(8),
418: TME_BUS_LANE_ROUTE(7),
419: TME_BUS_LANE_ROUTE(6),
420: TME_BUS_LANE_ROUTE(5),
421: TME_BUS_LANE_ROUTE(4),
422: TME_BUS_LANE_ROUTE(3),
423: TME_BUS_LANE_ROUTE(2),
424: TME_BUS_LANE_ROUTE(1),
425: TME_BUS_LANE_ROUTE(0),
426: }
427: };
428:
429: /* this maps a virtual address: */
430: static void _tme_stp103x_ls_address_map _TME_P((struct tme_sparc *, struct tme_sparc_ls *));
431:
432: /* this makes a never struct timeval: */
433: static inline void
434: tme_misc_timeval_never(struct timeval *tv)
435: {
436: tv->tv_sec = 0;
437: tv->tv_sec--;
438: if (tv->tv_sec < 1) {
439: tv->tv_sec = 1;
440: tv->tv_sec <<= ((8 * sizeof(tv->tv_sec)) - 2);
441: tv->tv_sec += (tv->tv_sec - 1);
442: }
443: tv->tv_usec = 999999;
444: }
445:
446: /* this does an interrupt check: */
447: /* NB: this may do a preinstruction trap: */
448: static void
449: _tme_stp103x_interrupt_check(struct tme_sparc *ic,
450: int flags)
451: {
452: tme_uint32_t sir;
453: tme_uint32_t ipl;
454: tme_uint32_t trap;
455:
456: /* if we're replaying instructions, return now: */
457: if (tme_sparc_recode_verify_replay_last_pc(ic) != 0) {
458: return;
459: }
460:
461: /* if PSTATE.IE is clear, return now: */
462: if ((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_IE) == 0) {
463: return;
464: }
465:
466: /* if the incoming interrupt vector data is busy: */
467: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy)) {
468:
469: /* start interrupt vector trap processing: */
470: trap = TME_STP103X_TRAP_interrupt_vector;
471: }
472:
473: /* otherwise, the incoming interrupt vector data is not busy: */
474: else {
475:
476: /* if no SOFTINT bits greater than PIL are set, return now: */
477: sir = TME_STP103X(ic)->tme_stp103x_sir;
478: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int)) {
479: sir |= TME_STP103X_SIR_SOFTINT(14);
480: }
481: ipl = ic->tme_sparc64_ireg_pil + 1;
482: sir >>= ipl;
483: if (sir == 0) {
484: return;
485: }
486:
487: /* get the greatest SOFTINT bit greater than PIL that is set: */
488: for (; sir != 1; sir >>= 1, ipl++);
489:
490: /* start interrupt trap processing: */
491: trap = TME_SPARC64_TRAP_interrupt_level(ipl);
492: }
493:
494: /* start trap processing: */
495: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) {
496: tme_mutex_unlock(&ic->tme_sparc_external_mutex);
497: }
498: if (flags & TME_SPARC_EXTERNAL_CHECK_PCS_UPDATED) {
499: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT);
500: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC);
501: #ifdef _TME_SPARC_RECODE_VERIFY
502: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) = TME_SPARC_RECODE_VERIFY_PC_NONE;
503: #endif /* _TME_SPARC_RECODE_VERIFY */
504: }
505: tme_sparc64_trap_preinstruction(ic, trap);
506: }
507:
508: /* this updates the SIR: */
509: /* NB: this may do a preinstruction trap: */
510: static void
511: _tme_stp103x_update_sir(struct tme_sparc *ic,
512: tme_uint32_t sir_andn,
513: tme_uint32_t sir_or)
514: {
515:
516: /* if we're clearing SIR.TICK_INT: */
517: if (sir_andn & TME_STP103X_SIR_TICK_INT) {
518:
519: /* do an interrupt check: */
520: _tme_stp103x_interrupt_check(ic, TME_SPARC_EXTERNAL_CHECK_PCS_UPDATED);
521:
522: /* clear the tick interrupt atomic flag: */
523: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, FALSE);
524: }
525:
526: /* if we're setting SIR.TICK_INT: */
527: if (sir_or & TME_STP103X_SIR_TICK_INT) {
528:
529: /* set the tick interrupt atomic flag: */
530: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, TRUE);
531:
532: /* we won't set SIR.TICK_INT in the normal SIR image: */
533: sir_or ^= TME_STP103X_SIR_TICK_INT;
534: }
535:
536: /* update all other bits in SIR: */
537: TME_STP103X(ic)->tme_stp103x_sir
538: = ((TME_STP103X(ic)->tme_stp103x_sir
539: & ~sir_andn)
540: | sir_or);
541:
542: /* do an interrupt check: */
543: _tme_stp103x_interrupt_check(ic, TME_SPARC_EXTERNAL_CHECK_NULL);
544: }
545:
546: /* this updates the LSU control register: */
547: static void
548: _tme_stp103x_update_lsu(struct tme_sparc *ic, tme_uint64_t lsu_new)
549: {
550: tme_uint64_t lsu_xor;
551: struct tme_sparc_tlb *tlb;
552:
553: /* get a change mask: */
554: lsu_xor = lsu_new ^ TME_STP103X(ic)->tme_stp103x_lsu;
555:
556: /* if LSU.IC or LSU.DC are changing: */
557: if (lsu_xor
558: & (TME_STP103X_LSU_IC
559: | TME_STP103X_LSU_DC)) {
560:
561: /* nothing to do, since we don't emulate the caches: */
562: }
563:
564: /* if LSU.IM or LSU.DM are changing: */
565: if (lsu_xor
566: & (TME_STP103X_LSU_IM
567: | TME_STP103X_LSU_DM)) {
568:
569: /* invalidate all of the sparc TLB entries: */
570: tlb = &ic->tme_sparc_tlbs[0];
571: do {
572: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token);
573: } while (++tlb <= &ic->tme_sparc_tlbs[TME_ARRAY_ELS(ic->tme_sparc_tlbs) - 1]);
574: }
575:
576: /* if LSU.FM is changing: */
577: if (lsu_xor & TME_STP103X_LSU_FM) {
578: /* XXX FIXME WRITEME: */
579: abort();
580: }
581:
582: /* if any of LSU.VR, LSU.VW, LSU.PR, LSU.PW are changing: */
583: if (lsu_xor
584: & (TME_STP103X_LSU_VR
585: | TME_STP103X_LSU_VW
586: | TME_STP103X_LSU_PR
587: | TME_STP103X_LSU_PW)) {
588: /* XXX FIXME WRITEME: */
589: abort();
590: }
591:
592: /* update the register: */
593: TME_STP103X(ic)->tme_stp103x_lsu = lsu_new;
594: }
595:
596: /* this updates the UPA configuration register: */
597: static void
598: _tme_stp103x_update_upa_config(struct tme_sparc *ic, tme_uint64_t upa_config)
599: {
600:
601: /* if this is an STP1030: */
602: if (TME_STP103X_IS_1030(ic)) {
603:
604: /* only the PCON field is writable: */
605: upa_config &= TME_STP1030_UPA_CONFIG_PCON;
606: }
607:
608: /* otherwise, this is an STP1031: */
609: else {
610:
611: /* only the PCON and ELIM fields are writable: */
612: upa_config
613: &= (TME_STP1031_UPA_CONFIG_PCON
614: | TME_STP1031_UPA_CONFIG_ELIM);
615:
616: /* all read-only STP1031-specific fields are hardwired to zero: */
617: }
618:
619: /* add the MID: */
620: upa_config += (ic->_tme_upa_bus_connection->tme_upa_bus_connection_mid << 17);
621:
622: /* add the PCAP fields: */
623: upa_config
624: += ((TME_STP103X_UPA_PINT_RDQ << 15)
625: + (TME_STP103X_UPA_PREQ_DQ << 9)
626: + (TME_STP103X_UPA_PREQ_RQ << 5)
627: + (TME_STP103X_UPA_UPACAP << 0));
628:
629: /* set the UPA configuration register: */
630: TME_STP103X(ic)->tme_stp103x_upa_config = upa_config;
631: }
632:
633: /* this handles a PSTATE update: */
634: /* NB: this may do a preinstruction trap: */
635: static void
636: _tme_stp103x_update_pstate(struct tme_sparc *ic,
637: tme_uint32_t pstate,
638: tme_uint32_t trap)
639: {
640: tme_uint64_t lsu_new;
641: tme_uint32_t pstate_xor;
642: tme_uint64_t address_mask;
643:
644: /* if we are in RED_state: */
645: if (pstate & TME_SPARC64_PSTATE_RED) {
646:
647: /* traps that enter RED_state, and traps in RED_state, always
648: clear the LSU_Control_Register. a write of one to PSTATE.RED
649: only clears LSU.IM: */
650: lsu_new
651: = (trap != TME_SPARC_TRAP_none
652: ? 0
653: : (TME_STP103X(ic)->tme_stp103x_lsu
654: & ~ (tme_uint64_t) TME_STP103X_LSU_IM));
655: _tme_stp103x_update_lsu(ic, lsu_new);
656:
657: /* if this is a power-on reset: */
658: if (trap == TME_SPARC64_TRAP_power_on_reset) {
659:
660: /* a POR clears the E-Cache (E-State) error enable register: */
661: TME_STP103X(ic)->tme_stp103x_estate_error_enable = 0;
662:
663: /* a POR zeroes the writable fields in the UPA configuration
664: register: */
665: _tme_stp103x_update_upa_config(ic, 0);
666: }
667: }
668:
669: /* if this is a trap that uses the MMU globals: */
670: if (trap & TME_STP103X_TRAP_MG) {
671: assert (trap != TME_SPARC_TRAP_none);
672: pstate
673: = ((pstate
674: & ~(TME_SPARC64_PSTATE_AG
675: + TME_STP103X_PSTATE_MG
676: + TME_STP103X_PSTATE_IG))
677: + TME_STP103X_PSTATE_MG);
678: }
679:
680: /* otherwise, if this is a trap that uses the interrupt globals: */
681: else if (trap & TME_STP103X_TRAP_IG) {
682: assert (trap != TME_SPARC_TRAP_none);
683: pstate
684: = ((pstate
685: & ~(TME_SPARC64_PSTATE_AG
686: + TME_STP103X_PSTATE_MG
687: + TME_STP103X_PSTATE_IG))
688: + TME_STP103X_PSTATE_IG);
689: }
690:
691: /* otherwise, if this is another trap: */
692: else if (trap != TME_SPARC_TRAP_none) {
693: pstate
694: &= ~(TME_STP103X_PSTATE_IG
695: + TME_STP103X_PSTATE_MG);
696: assert (pstate & TME_SPARC64_PSTATE_AG);
697: }
698:
699: /* the global register selection can't be reserved: */
700: assert ((((pstate & TME_SPARC64_PSTATE_AG) != 0)
701: + ((pstate & TME_STP103X_PSTATE_MG) != 0)
702: + ((pstate & TME_STP103X_PSTATE_IG) != 0)) < 2);
703:
704: /* update the global register offset: */
705: ic->tme_sparc_reg8_offset[0]
706: = ((pstate & TME_SPARC64_PSTATE_AG)
707: #if (TME_SPARC64_IREG_AG_G0 % 8)
708: #error "TME_SPARC64_IREG_AG_G0 must be a multiple of eight"
709: #endif
710: ? (TME_SPARC64_IREG_AG_G0 / 8)
711: : (pstate & TME_STP103X_PSTATE_MG)
712: #if (TME_SPARC64_IREG_MG_G0 % 8)
713: #error "TME_SPARC64_IREG_MG_G0 must be a multiple of eight"
714: #endif
715: ? (TME_SPARC64_IREG_MG_G0 / 8)
716: : (pstate & TME_STP103X_PSTATE_IG)
717: #if (TME_SPARC64_IREG_IG_G0 % 8)
718: #error "TME_SPARC64_IREG_IG_G0 must be a multiple of eight"
719: #endif
720: ? (TME_SPARC64_IREG_IG_G0 / 8)
721: #if (TME_SPARC_IREG_G0 % 8)
722: #error "TME_SPARC_IREG_G0 must be a multiple of eight"
723: #endif
724: : (TME_SPARC_IREG_G0 / 8));
725: _TME_SPARC_RECODE_CWP_UPDATE(ic, tme_uint64_t);
726:
727: /* make sure that %g0 is zero in the normal global register set and
728: the current global register set. recode instructions thunks
729: always refer to %g0 in the normal global register set: */
730: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_G0) = 0;
731: ic->tme_sparc_ireg_uint64(TME_SPARC_G0_OFFSET(ic) + TME_SPARC_IREG_G0) = 0;
732:
733: /* get the changing bits in PSTATE: */
734: pstate_xor = ic->tme_sparc64_ireg_pstate ^ pstate;
735:
736: #if TME_HAVE_RECODE && TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32
737:
738: /* if PSTATE.AM and/or PSTATE.CLE are changing: */
739: if (__tme_predict_false(pstate_xor
740: & (TME_SPARC64_PSTATE_AM
741: | TME_SPARC64_PSTATE_CLE
742: ))) {
743:
744: /* clear the return address stack, since chaining doesn't check that
745: PSTATE matches instructions thunks: */
746: tme_recode_chain_ras_clear(ic->tme_sparc_recode_ic,
747: &ic->tme_sparc_ic);
748: }
749:
750: #endif /* TME_HAVE_RECODE && TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */
751:
752: /* set PSTATE: */
753: ic->tme_sparc64_ireg_pstate = pstate;
754:
755: /* update the address mask: */
756: address_mask
757: = ((0 - (tme_uint64_t) ((~pstate / TME_SPARC64_PSTATE_AM) & 1))
758: | (tme_uint32_t) (0 - (tme_uint32_t) 1));
759: ic->tme_sparc_address_mask = address_mask;
760:
761: /* mask the PCs: */
762: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT) &= address_mask;
763: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) &= address_mask;
764:
765: /* if interrupts are enabled, we can't be trapping, because
766: _tme_stp103x_interrupt_check() might trap with an interrupt,
767: discarding the initial trap: */
768: assert ((pstate & TME_SPARC64_PSTATE_IE) == 0
769: || trap == TME_SPARC_TRAP_none);
770:
771: /* do an interrupt check: */
772: _tme_stp103x_interrupt_check(ic, TME_SPARC_EXTERNAL_CHECK_NULL);
773: }
774:
775: /* this updates the AFSR: */
776: static void
777: _tme_stp103x_update_afsr(struct tme_sparc *ic, tme_uint64_t afsr_reset)
778: {
779:
780: /* one bits in positions 20..32 clear those bits in the AFSR: */
781: TME_STP103X(ic)->tme_stp103x_afsr
782: &= ~(afsr_reset
783: & ((((tme_uint64_t) 1) << (32 + 1)) - (1 << 20)));
784: }
785:
786: /* this updates the interrupt vector receive: */
787: static void
788: _tme_stp103x_update_intr_receive(struct tme_sparc *ic, tme_uint64_t intr_receive)
789: {
790: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy,
791: (intr_receive & TME_STP103X_INTR_RECEIVE_BUSY) != 0);
792: }
793:
794: /* the stp103x rdasr: */
795: static
796: TME_SPARC_FORMAT3(_tme_stp103x_rdasr, tme_uint64_t)
797: {
798: unsigned int reg_rs1;
799: tme_uint64_t value;
800:
801: /* if this is an implementation-specific ASR: */
802: if (TME_SPARC_INSN & (0x10 << 14)) {
803:
804: /* get rs1: */
805: reg_rs1 = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RS1);
806:
807: /* if this is an undefined implementation-specific ASR: */
808: if (__tme_predict_false(reg_rs1 >= 0x18)) {
809: TME_SPARC_INSN_ILL(ic);
810: }
811:
812: /* if this is a read of GSR: */
813: if (reg_rs1 == 0x13) {
814: if (__tme_predict_false((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0
815: || (ic->tme_sparc64_ireg_fprs & TME_SPARC64_FPRS_FEF) == 0)) {
816: tme_sparc64_trap(ic, TME_SPARC64_TRAP_fp_disabled);
817: }
818: value = ic->tme_sparc_vis_gsr;
819: }
820:
821: /* otherwise, this is not a read of GSR: */
822: else {
823:
824: /* if this is a nonprivileged read: */
825: if (__tme_predict_false(!TME_SPARC_PRIV(ic))) {
826:
827: /* if this is not a read of PIC, or if PCR.PRIV is set: */
828: if (reg_rs1 != 0x11
829: || (TME_STP103X(ic)->tme_stp103x_pcr & TME_BIT(0))) {
830: tme_sparc64_trap(ic, TME_SPARC64_TRAP_privileged_opcode);
831: }
832: }
833:
834: /* dispatch on rs1: */
835: switch (reg_rs1) {
836: default: TME_SPARC_INSN_ILL(ic);
837: case 0x10: value = TME_STP103X(ic)->tme_stp103x_pcr; break;
838: case 0x11: value = TME_STP103X(ic)->tme_stp103x_pic.tme_value64_uint; break;
839: case 0x12: value = TME_STP103X(ic)->tme_stp103x_dcr; break;
840: case 0x16:
841: value = TME_STP103X(ic)->tme_stp103x_sir;
842: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int)) {
843: value += TME_STP103X_SIR_TICK_INT;
844: }
845: break;
846: case 0x17: value = TME_STP103X(ic)->tme_stp103x_tcr; break;
847: }
848: }
849: TME_SPARC_FORMAT3_RD = value;
850: TME_SPARC_INSN_OK;
851: }
852: tme_sparc64_rdasr(ic, _rs1, _rs2, _rd);
853: }
854:
855: /* the stp103x rdpr: */
856: static
857: TME_SPARC_FORMAT3(_tme_stp103x_rdpr, tme_uint64_t)
858: {
859: unsigned long offset_in_insns;
860: tme_uint32_t delay_factor;
861: tme_uint32_t insn;
862: const struct tme_sparc_tlb *itlb_current;
863:
864: /* the PROM (at least, SUNW,501-3082-update7.bin) calculates a delay
865: factor by waiting for a timer interrupt while running these two
866: instructions:
867:
868: f0055720: 10 80 00 00 b 0xf0055720
869: f0055724: a4 04 a0 01 inc %l2
870:
871: the PROM then does a delay by running these two instructions:
872:
873: f00557e0: 14 68 00 00 bg %xcc, 0xf00557e0
874: f00557e4: a2 a4 60 01 deccc %l1
875:
876: unfortunately, in the stp103x emulation, a deccc is more
877: expensive than an inc, because it must update the condition
878: codes. the difference is significant enough to cause what
879: should be a brief delay between these two PROM messages:
880:
881: Probing Memory Bank #3 0 + 0 : 0 Megabytes
882: Probing /sbus@1f,0 at 0,0 Nothing there
883:
884: to be very, very long. the cost difference appears to be even
885: worse when recode is on, and the extreme delay gives the user the
886: impression that the emulator is stuck.
887:
888: there's a chance that there's a cost difference between inc and
889: deccc even on a real stp103x; "1000 ms" on the PROM on a real
890: Ultra-1 delays noticeably longer than one second.
891:
892: this function is a gross hack that attempts to reduce the delay.
893: it modifies the original loop that calculates the delay factor to
894: use (for the "best" factor) an inccc instruction instead of a
895: inc, to make it more symmetric with the delay loop.
896:
897: it detects the original loop by this instruction that precedes it:
898:
899: f0055708: a7 51 00 00 rdpr %tick, %l3
900: */
901:
902: /* if this is a "rdpr %tick, %l3" instruction: */
903: if (__tme_predict_false(TME_SPARC_INSN == 0xa7510000)) {
904:
905: /* get the offset, in units of instructions, to the next PC that
906: is I-Cache block aligned: */
907: offset_in_insns = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC);
908: offset_in_insns = ~offset_in_insns;
909: offset_in_insns %= TME_STP103X_ICACHE_BLOCK_SIZE;
910: offset_in_insns = (offset_in_insns + 1) / sizeof(TME_SPARC_INSN);
911:
912: /* if the CPU is in privileged mode, and the first two
913: instructions at that PC are "b ." and "inc %l2": */
914: if (TME_SPARC_PRIV(ic)
915: && tme_sparc_fetch_nearby(ic, offset_in_insns + 0) == 0x10800000
916: && tme_sparc_fetch_nearby(ic, offset_in_insns + 1) == 0xa404a001) {
917:
918: /* if the PROM delay factor is to be corrected: */
919: delay_factor = ic->tme_sparc_prom_delay_factor;
920: if (delay_factor != TME_SPARC_PROM_DELAY_FACTOR_UNCORRECTED) {
921:
922: /* if the PROM delay factor correction is "min": */
923: if (delay_factor == TME_SPARC_PROM_DELAY_FACTOR_MIN) {
924:
925: /* the delay factor is calculated by running the loop for
926: 64ms and then dividing the count by 64, so a raw count of
927: 64 will get the minimum delay: */
928: delay_factor = 64;
929: }
930:
931: /* if the PROM delay factor correction is "best": */
932: if (delay_factor == TME_SPARC_PROM_DELAY_FACTOR_BEST) {
933:
934: /* modify the "inc %l2" to be "inccc %l2": */
935: insn = 0xa484a001;
936: }
937:
938: /* otherwise, the PROM delay factor is given directly: */
939: else {
940:
941: /* modify the "inc %l2" to be "or %g0, simm13, %l2": */
942: insn = 0xa4102000 + TME_MIN(delay_factor, 0xfff);
943: }
944:
945: /* get the current instruction TLB entry: */
946: /* NB: we don't repeat the assert()s or the address-covering
947: checks of tme_sparc_fetch_nearby(): */
948: itlb_current = tme_sparc_itlb_current(ic);
949:
950: /* modify the "inc %l2": */
951: /* NB: we break const here: */
952: ((tme_shared tme_uint32_t *)
953: (unsigned long)
954: (itlb_current->tme_sparc_tlb_emulator_off_read
955: + ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)))
956: [offset_in_insns + 1] = tme_htobe_u32(insn);
957:
958: /* NB: we don't invalidate the memory page that we just modified
959: (in the tme_sparc_recode_cacheable_valids sense), because we
960: assume that the loop that calculates the delay factor hasn't
961: been recoded yet, and we assume that no other CPUs or other
962: bus masters care about the modification: */
963: }
964: }
965: }
966:
967: /* do the normal rdpr: */
968: tme_sparc64_rdpr(ic, _rs1, _rs2, _rd);
969: }
970:
971: /* the stp103x wrasr: */
972: static
973: TME_SPARC_FORMAT3(_tme_stp103x_wrasr, tme_uint64_t)
974: {
975: tme_uint64_t value_xor;
976: unsigned int reg_rd;
977: tme_uint64_t tick;
978: struct timeval tick_compare_time;
979: tme_uint64_t cycles_scaled;
980: tme_uint64_t usec64;
981: tme_uint32_t usec32;
982:
983: /* if this is an implementation-specific ASR: */
984: if (TME_SPARC_INSN & (0x10 << 25)) {
985:
986: /* get the value to write: */
987: value_xor = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2;
988:
989: /* get rd: */
990: reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
991:
992: /* if this is an undefined implementation-specific ASR: */
993: if (__tme_predict_false(reg_rd >= 0x18)) {
994: TME_SPARC_INSN_ILL(ic);
995: }
996:
997: /* if this is an write to GSR: */
998: if (reg_rd == 0x13) {
999: if (__tme_predict_false((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0
1000: || (ic->tme_sparc64_ireg_fprs & TME_SPARC64_FPRS_FEF) == 0)) {
1001: tme_sparc64_trap(ic, TME_SPARC64_TRAP_fp_disabled);
1002: }
1003: ic->tme_sparc_vis_gsr = value_xor;
1004: }
1005:
1006: /* otherwise, this is not a write to GSR: */
1007: else {
1008:
1009: /* if this is a nonprivileged write: */
1010: if (__tme_predict_false(!TME_SPARC_PRIV(ic))) {
1011:
1012: /* if this is not a write to PIC, or if PCR.PRIV is set: */
1013: if (reg_rd != 0x11
1014: || (TME_STP103X(ic)->tme_stp103x_pcr & TME_BIT(0))) {
1015: tme_sparc64_trap(ic, TME_SPARC64_TRAP_privileged_action);
1016: }
1017: }
1018:
1019: /* dispatch on rd: */
1020: switch (reg_rd) {
1021: default: assert (FALSE);
1022: case 0x10: TME_STP103X(ic)->tme_stp103x_pcr = value_xor; break;
1023: case 0x11: TME_STP103X(ic)->tme_stp103x_pic.tme_value64_uint = value_xor; break;
1024: case 0x12: TME_STP103X(ic)->tme_stp103x_dcr = value_xor; break;
1025: case 0x14: _tme_stp103x_update_sir(ic, 0, value_xor); break;
1026: case 0x15: _tme_stp103x_update_sir(ic, value_xor, 0); break;
1027: case 0x16: _tme_stp103x_update_sir(ic, 0xffff, value_xor); break;
1028:
1029: case 0x17:
1030: TME_STP103X(ic)->tme_stp103x_tcr = value_xor;
1031:
1032: /* if we're not replaying instructions: */
1033: if (tme_sparc_recode_verify_replay_last_pc(ic) == 0) {
1034:
1035: /* if INT_DIS is set: */
1036: if (__tme_predict_false(value_xor & TME_STP103X_TCR_INT_DIS)) {
1037:
1038: /* the tick compare time is never: */
1039: tme_misc_timeval_never(&tick_compare_time);
1040: }
1041:
1042: /* otherwise, INT_DIS is clear: */
1043: else {
1044:
1045: /* get the current value of TICK.counter: */
1046: tick = tme_misc_cycles_scaled(&ic->tme_sparc_cycles_scaling, 0).tme_value64_uint;
1047: tick += ic->tme_sparc64_ireg_tick_offset;
1048: tick &= TME_SPARC64_TICK_COUNTER;
1049:
1050: /* get the current time: */
1051: gettimeofday(&tick_compare_time, NULL);
1052:
1053: /* get the number of cycles until the compare value is
1054: reached: */
1055: cycles_scaled = TME_STP103X(ic)->tme_stp103x_tcr - tick;
1056: cycles_scaled &= TME_SPARC64_TICK_COUNTER;
1057:
1058: /* if the number of cycles doesn't fit in 32 bits: */
1059: if (__tme_predict_false(cycles_scaled > (tme_uint32_t) (0 - (tme_uint32_t) 1))) {
1060:
1061: /* convert cycles into microseconds: */
1062: usec64 = cycles_scaled / ic->tme_sparc_cycles_scaled_per_usec;
1063:
1064: /* add in the whole seconds: */
1065: tick_compare_time.tv_sec += (usec64 / 1000000);
1066:
1067: /* get the remaining microseconds: */
1068: usec32 = (usec64 % 1000000);
1069: }
1070:
1071: /* otherwise, the number of cycles fits in 32 bits: */
1072: else {
1073:
1074: /* convert cycles into microseconds: */
1075: usec32 = ((tme_uint32_t) cycles_scaled) / ic->tme_sparc_cycles_scaled_per_usec;
1076:
1077: /* if there is at least one whole second: */
1078: if (__tme_predict_false(usec32 >= 1000000)) {
1079:
1080: /* add in the whole seconds: */
1081: tick_compare_time.tv_sec += (usec32 / 1000000);
1082:
1083: /* get the remaining microseconds: */
1084: usec32 %= 1000000;
1085: }
1086: }
1087:
1088: /* add in the microseconds: */
1089: usec32 += tick_compare_time.tv_usec;
1090: if (usec32 >= 1000000) {
1091: tick_compare_time.tv_sec++;
1092: usec32 -= 1000000;
1093: }
1094: tick_compare_time.tv_usec = usec32;
1095: }
1096:
1097: /* lock the external mutex: */
1098: tme_mutex_lock(&ic->tme_sparc_external_mutex);
1099:
1100: /* set the tick compare time: */
1101: TME_STP103X(ic)->tme_stp103x_tick_compare_time = tick_compare_time;
1102:
1103: /* notify the tick compare thread: */
1104: tme_cond_notify(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond, FALSE);
1105:
1106: /* unlock the external mutex: */
1107: tme_mutex_unlock(&ic->tme_sparc_external_mutex);
1108: }
1109: break;
1110: }
1111: }
1112: TME_SPARC_INSN_OK;
1113: }
1114: tme_sparc64_wrasr(ic, _rs1, _rs2, _rd);
1115: }
1116:
1117: /* the stp103x impdep1: */
1118: static
1119: TME_SPARC_FORMAT3(_tme_stp103x_impdep1, tme_uint64_t)
1120: {
1121: tme_uint32_t opf;
1122: tme_uint64_t rd;
1123: unsigned int alignaddr_off;
1124:
1125: /* extract the opf field: */
1126: opf = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1ff << 5));
1127:
1128: /* if this is a shutdown instruction: */
1129: if (opf == 0x80) {
1130: TME_SPARC_INSN_PRIV;
1131:
1132: /* XXX WRITEME: */
1133: abort();
1134: }
1135:
1136: /* if this is the VIS alignaddr instruction: */
1137: if ((opf | TME_BIT(1)) == 0x1a) {
1138:
1139: /* add the two registers into an address: */
1140: rd = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;
1141:
1142: /* store the alignaddr offset: */
1143: alignaddr_off
1144: = (((opf & TME_BIT(1))
1145: ? (sizeof(tme_uint64_t) - 1)
1146: : 0)
1147: ^ rd);
1148: TME_FIELD_MASK_DEPOSITU(ic->tme_sparc_vis_gsr,
1149: TME_SPARC_VIS_GSR_ALIGNADDR_OFF,
1150: alignaddr_off);
1151:
1152: /* truncate the address: */
1153: TME_SPARC_FORMAT3_RD = rd & (0 - (tme_uint64_t) sizeof(tme_uint64_t));
1154:
1155: TME_SPARC_INSN_OK;
1156: }
1157:
1158: /* otherwise, assume that this is some other VIS instruction: */
1159: tme_sparc_vis(ic);
1160: TME_SPARC_INSN_OK;
1161: }
1162:
1163: /* the stp103x impdep2: */
1164: static
1165: TME_SPARC_FORMAT3(_tme_stp103x_impdep2, tme_uint64_t)
1166: {
1167: TME_SPARC_INSN_ILL(ic);
1168: }
1169:
1170: /* the stp103x flush: */
1171: static
1172: TME_SPARC_FORMAT3(_tme_stp103x_flush, tme_uint64_t)
1173: {
1174: tme_uint64_t address;
1175: tme_uint32_t context;
1176: struct tme_sparc_tlb *dtlb;
1177: tme_uint64_t rd;
1178:
1179: /* if we're replaying instructions, return now: */
1180: if (tme_sparc_recode_verify_replay_last_pc(ic) != 0) {
1181: TME_SPARC_INSN_OK;
1182: }
1183:
1184: /* get the address: */
1185: address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;
1186: address &= ic->tme_sparc_address_mask;
1187:
1188: /* get the context: */
1189: context = ic->tme_sparc_memory_context_default;
1190:
1191: /* get and busy the DTLB entry: */
1192: dtlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, address))];
1193: tme_sparc_tlb_busy(dtlb);
1194:
1195: /* a flush instruction behaves like a non-faulting load: */
1196: tme_sparc64_ls(ic,
1197: address,
1198: &rd,
1199: (TME_SPARC_LSINFO_OP_LD
1200: + TME_SPARC_LSINFO_ASI_FLAGS(TME_SPARC64_ASI_FLAG_NO_FAULT)
1201: + sizeof(tme_uint8_t)));
1202:
1203: /* unbusy the DTLB entry: */
1204: tme_sparc_tlb_unbusy(dtlb);
1205:
1206: TME_SPARC_INSN_OK;
1207: }
1208:
1209: /* the format three opcode map: */
1210: #define _TME_SPARC_EXECUTE_OPMAP tme_sparc_opcodes_stp103x
1211: static const _tme_sparc64_format3 _TME_SPARC_EXECUTE_OPMAP[] = {
1212:
1213: /* op=2: arithmetic, logical, shift, and remaining: */
1214:
1215: /* 000000 */ tme_sparc64_add,
1216: /* 000001 */ tme_sparc64_and,
1217: /* 000010 */ tme_sparc64_or,
1218: /* 000011 */ tme_sparc64_xor,
1219: /* 000100 */ tme_sparc64_sub,
1220: /* 000101 */ tme_sparc64_andn,
1221: /* 000110 */ tme_sparc64_orn,
1222: /* 000111 */ tme_sparc64_xnor,
1223: /* 001000 */ tme_sparc64_addx,
1224: /* 001001 */ tme_sparc64_mulx,
1225: /* 001010 */ tme_sparc64_umul,
1226: /* 001011 */ tme_sparc64_smul,
1227: /* 001100 */ tme_sparc64_subx,
1228: /* 001101 */ tme_sparc64_udivx,
1229: /* 001110 */ tme_sparc64_udiv,
1230: /* 001111 */ tme_sparc64_sdiv,
1231: /* 010000 */ tme_sparc64_addcc,
1232: /* 010001 */ tme_sparc64_andcc,
1233: /* 010010 */ tme_sparc64_orcc,
1234: /* 010011 */ tme_sparc64_xorcc,
1235: /* 010100 */ tme_sparc64_subcc,
1236: /* 010101 */ tme_sparc64_andncc,
1237: /* 010110 */ tme_sparc64_orncc,
1238: /* 010111 */ tme_sparc64_xnorcc,
1239: /* 011000 */ tme_sparc64_addxcc,
1240: /* 011001 */ NULL,
1241: /* 011010 */ tme_sparc64_umulcc,
1242: /* 011011 */ tme_sparc64_smulcc,
1243: /* 011100 */ tme_sparc64_subxcc,
1244: /* 011101 */ NULL,
1245: /* 011110 */ tme_sparc64_udivcc,
1246: /* 011111 */ tme_sparc64_sdivcc,
1247: /* 100000 */ tme_sparc64_taddcc,
1248: /* 100001 */ tme_sparc64_tsubcc,
1249: /* 100010 */ tme_sparc64_taddcctv,
1250: /* 100011 */ tme_sparc64_tsubcctv,
1251: /* 100100 */ tme_sparc64_mulscc,
1252: /* 100101 */ tme_sparc64_sll,
1253: /* 100110 */ tme_sparc64_srl,
1254: /* 100111 */ tme_sparc64_sra,
1255: /* 101000 */ _tme_stp103x_rdasr,
1256: /* 101001 */ NULL,
1257: /* 101010 */ _tme_stp103x_rdpr,
1258: /* 101011 */ tme_sparc64_flushw,
1259: /* 101100 */ tme_sparc64_movcc,
1260: /* 101101 */ tme_sparc64_sdivx,
1261: /* 101110 */ NULL,
1262: /* 101111 */ tme_sparc64_movr,
1263: /* 110000 */ _tme_stp103x_wrasr,
1264: /* 110001 */ tme_sparc64_saved_restored,
1265: /* 110010 */ tme_sparc64_wrpr,
1266: /* 110011 */ NULL,
1267: /* 110100 */ tme_sparc64_fpop1,
1268: /* 110101 */ tme_sparc64_fpop2,
1269: /* 110110 */ _tme_stp103x_impdep1,
1270: /* 110111 */ _tme_stp103x_impdep2,
1271: /* 111000 */ tme_sparc64_jmpl,
1272: /* 111001 */ tme_sparc64_return,
1273: /* 111010 */ tme_sparc64_tcc,
1274: /* 111011 */ _tme_stp103x_flush,
1275: /* 111100 */ tme_sparc64_save_restore,
1276: /* 111101 */ tme_sparc64_save_restore,
1277: /* 111110 */ tme_sparc64_done_retry,
1278: /* 111111 */ NULL,
1279:
1280: /* op=3: memory instructions: */
1281:
1282: /* 000000 */ tme_sparc64_ld,
1283: /* 000001 */ tme_sparc64_ldb,
1284: /* 000010 */ tme_sparc64_ldh,
1285: /* 000011 */ tme_sparc64_ldd,
1286: /* 000100 */ tme_sparc64_st,
1287: /* 000101 */ tme_sparc64_stb,
1288: /* 000110 */ tme_sparc64_sth,
1289: /* 000111 */ tme_sparc64_std,
1290: /* 001000 */ tme_sparc64_ld,
1291: /* 001001 */ tme_sparc64_ldb,
1292: /* 001010 */ tme_sparc64_ldh,
1293: /* 001011 */ tme_sparc64_ldx,
1294: /* 001100 */ NULL,
1295: /* 001101 */ tme_sparc64_ldstub,
1296: /* 001110 */ tme_sparc64_stx,
1297: /* 001111 */ tme_sparc64_swap,
1298: /* 010000 */ tme_sparc64_lda,
1299: /* 010001 */ tme_sparc64_ldba,
1300: /* 010010 */ tme_sparc64_ldha,
1301: /* 010011 */ tme_sparc64_ldda,
1302: /* 010100 */ tme_sparc64_sta,
1303: /* 010101 */ tme_sparc64_stba,
1304: /* 010110 */ tme_sparc64_stha,
1305: /* 010111 */ tme_sparc64_stda,
1306: /* 011000 */ tme_sparc64_lda,
1307: /* 011001 */ tme_sparc64_ldba,
1308: /* 011010 */ tme_sparc64_ldha,
1309: /* 011011 */ tme_sparc64_ldxa,
1310: /* 011100 */ NULL,
1311: /* 011101 */ tme_sparc64_ldstuba,
1312: /* 011110 */ tme_sparc64_stxa,
1313: /* 011111 */ tme_sparc64_swapa,
1314: /* 100000 */ tme_sparc64_ldf,
1315: /* 100001 */ tme_sparc64_ldfsr,
1316: /* 100010 */ tme_sparc64_illegal_instruction, /* ldqf */
1317: /* 100011 */ tme_sparc64_lddf,
1318: /* 100100 */ tme_sparc64_stf,
1319: /* 100101 */ tme_sparc64_stfsr,
1320: /* 100110 */ tme_sparc64_illegal_instruction, /* stqf */
1321: /* 100111 */ tme_sparc64_stdf,
1322: /* 101000 */ NULL,
1323: /* 101001 */ NULL,
1324: /* 101010 */ NULL,
1325: /* 101011 */ NULL,
1326: /* 101100 */ NULL,
1327: /* 101101 */ tme_sparc64_prefetch,
1328: /* 101110 */ NULL,
1329: /* 101111 */ NULL,
1330: /* 110000 */ tme_sparc64_ldfa,
1331: /* 110001 */ NULL,
1332: /* 110010 */ tme_sparc64_illegal_instruction, /* ldqfa */
1333: /* 110011 */ tme_sparc64_lddfa,
1334: /* 110100 */ tme_sparc64_stfa,
1335: /* 110101 */ NULL,
1336: /* 110110 */ tme_sparc64_illegal_instruction, /* stqfa */
1337: /* 110111 */ tme_sparc64_stdfa,
1338: /* 111000 */ NULL,
1339: /* 111001 */ NULL,
1340: /* 111010 */ NULL,
1341: /* 111011 */ NULL,
1342: /* 111100 */ tme_sparc64_casa,
1343: /* 111101 */ tme_sparc64_prefetch,
1344: /* 111110 */ tme_sparc64_casxa,
1345: /* 111111 */ NULL,
1346: };
1347:
1348: /* make the executor for the STP103x: */
1349: #define _TME_SPARC_EXECUTE_NAME _tme_sparc_execute_stp103x
1350: #include "sparc-execute.c"
1351:
1352: /* this invalidates a specific valid stp103x TLB entry: */
1353: static void
1354: _tme_stp103x_tlb_invalidate(struct tme_sparc *ic,
1355: signed long tlb_part_i)
1356: {
1357: tme_uint32_t tlb_data_32_63;
1358: struct tme_sparc_tlb *tlb;
1359: tme_uint32_t tlb_count;
1360: tme_uint32_t size;
1361: tme_uint64_t address;
1362: tme_uint32_t context;
1363:
1364: /* load bits 32..63 of the TLB entry's data: */
1365: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1);
1366:
1367: /* this TLB entry must be valid: */
1368: assert (tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63));
1369:
1370: /* this TLB entry is now invalid: */
1371: tlb_data_32_63 &= ~TME_STP103X_TLB_DATA_V(tlb_data_32_63);
1372: TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1) = tlb_data_32_63;
1373:
1374: /* if this TLB entry is global: */
1375: if (TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0)
1376: & TME_STP103X_TLB_DATA_G((tme_uint32_t) 0)) {
1377:
1378: /* assume that this is an stp103x DTLB entry, and we need to
1379: invalidate sparc DTLB entries: */
1380: tlb = &ic->tme_sparc_tlbs[0];
1381: tlb_count = _TME_SPARC_DTLB_HASH_SIZE;
1382:
1383: /* if this is an stp103x ITLB entry: */
1384: #if TME_STP103X_TLB_PART_0_DMMU >= TME_STP103X_TLB_PART_0_IMMU
1385: #error "TME_STP103X_TLB_PART_0_DMMU or TME_STP103X_TLB_PART_0_IMMU changed"
1386: #endif
1387: if (tlb_part_i >= TME_STP103X_TLB_PART_0_IMMU) {
1388:
1389: /* we need to invalidate sparc ITLB entries: */
1390: tlb += _TME_SPARC_DTLB_HASH_SIZE;
1391: tlb_count = _TME_SPARC_ITLB_HASH_SIZE;
1392: }
1393:
1394: /* invalidate all of the sparc TLB entries linked to this stp103x
1395: TLB entry: */
1396: do {
1397: if (tlb->tme_sparc_tlb_link == tlb_part_i) {
1398: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token);
1399: }
1400: tlb++;
1401: } while (--tlb_count);
1402: }
1403:
1404: /* otherwise, this TLB entry isn't global: */
1405: else {
1406:
1407: /* get the size of this mapping: */
1408: size
1409: = (TME_STP103X_PAGE_SIZE_8KB
1410: << (3 * TME_FIELD_MASK_EXTRACTU(tlb_data_32_63,
1411: TME_STP103X_TLB_DATA_SIZE_MASK(tlb_data_32_63))));
1412:
1413: /* get the tag, and divide it into context and address: */
1414: address = TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0);
1415: context = address;
1416: context &= TME_STP103X_CONTEXT_MAX;
1417: address &= (0 - (tme_uint64_t) size);
1418:
1419: /* we assume that a stride of 8KB will find all sparc TLB entries
1420: for this stp103x TLB entry: */
1421: assert ((1 << ic->tme_sparc_tlb_page_size_log2) == TME_STP103X_PAGE_SIZE_8KB);
1422:
1423: /* if this is an stp103x DTLB entry: */
1424: #if TME_STP103X_TLB_PART_0_DMMU >= TME_STP103X_TLB_PART_0_IMMU
1425: #error "TME_STP103X_TLB_PART_0_DMMU or TME_STP103X_TLB_PART_0_IMMU changed"
1426: #endif
1427: if (tlb_part_i < TME_STP103X_TLB_PART_0_IMMU) {
1428:
1429: /* invalidate all of the sparc DTLB entries linked to this
1430: stp103x DTLB entry: */
1431: do {
1432: tlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, address))];
1433: if (tlb->tme_sparc_tlb_link == tlb_part_i) {
1434: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token);
1435: }
1436: address += TME_STP103X_PAGE_SIZE_8KB;
1437: } while ((size -= TME_STP103X_PAGE_SIZE_8KB) > 0);
1438: }
1439:
1440: /* otherwise, this is an stp103x ITLB entry: */
1441: else {
1442:
1443: /* invalidate all of the sparc ITLB entries linked to this
1444: stp103x ITLB entry: */
1445: do {
1446: tlb = &ic->tme_sparc_tlbs[TME_SPARC_ITLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, address))];
1447: if (tlb->tme_sparc_tlb_link == tlb_part_i) {
1448: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token);
1449: }
1450: address += TME_STP103X_PAGE_SIZE_8KB;
1451: } while ((size -= TME_STP103X_PAGE_SIZE_8KB) > 0);
1452: }
1453: }
1454: }
1455:
1456: /* this handles a load/store trap: */
1457: static void
1458: _tme_stp103x_ls_trap(struct tme_sparc *ic,
1459: struct tme_sparc_ls *ls)
1460: {
1461: tme_uint32_t lsinfo;
1462: tme_uint32_t sfsr;
1463: tme_uint32_t ls_faults;
1464: tme_uint32_t trap;
1465: tme_uint32_t updates;
1466: tme_uint32_t insn;
1467: tme_uint64_t afsr;
1468: tme_uint64_t address;
1469: tme_uint32_t asi_mask;
1470: struct tme_stp103x_mmu *mmu;
1471:
1472: /* get the information about this load/store: */
1473: lsinfo = ls->tme_sparc_ls_lsinfo;
1474:
1475: /* check that we weren't supposed to fault: */
1476: assert ((lsinfo & TME_STP103X_LSINFO_ASSERT_NO_FAULTS) == 0);
1477:
1478: /* if we're supposed to ignore faults: */
1479: if (__tme_predict_false(lsinfo & TME_SPARC_LSINFO_NO_FAULT)) {
1480:
1481: /* clear all faults and complete the load/store: */
1482: ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;
1483: ls->tme_sparc_ls_size = 0;
1484: return;
1485: }
1486:
1487: /* start an SFSR value: */
1488: sfsr = 0;
1489:
1490: /* get the list of faults from this load/store: */
1491: ls_faults = ls->tme_sparc_ls_faults;
1492:
1493: /* there must be at least one fault: */
1494: assert (ls_faults != TME_SPARC_LS_FAULT_NONE);
1495:
1496: /* we don't support generic bus faults: */
1497: assert ((ls_faults
1498: & (TME_SPARC_LS_FAULT_BUS_FAULT)) == 0);
1499:
1500: /* if this is an IMMU miss, this must be the only fault. we rely on
1501: this to honor trap priorities, since we handle IMMU misses and
1502: DMMU misses as if they have the same priority, even though they
1503: don't: */
1504: assert ((ls_faults & TME_STP103X_LS_FAULT_MMU_MISS) == 0
1505: || (lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0
1506: || ls_faults == TME_STP103X_LS_FAULT_MMU_MISS);
1507:
1508: /* if this is a instruction access error, it must happen alone. we
1509: rely on this to honor trap priorities, since we handle
1510: instruction access errors and data access errors as if they have
1511: the same priority, even though they don't: */
1512: assert ((ls_faults & TME_SPARC_LS_FAULT_BUS_ERROR) == 0
1513: || (lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0
1514: || ls_faults == TME_SPARC_LS_FAULT_BUS_ERROR);
1515:
1516: /* if this is an instruction access exception, it either happens
1517: alone (because of a privilege violation), or it's because of a
1518: jmpl/return target address out-of-range. we rely on this to
1519: honor trap priorities, since we handle privilege violation
1520: instruction access exceptions and data access exceptions as if
1521: they have the same priority, even though they don't. (a
1522: jmpl/return target instruction access exception explicitly has
1523: the same priority as a data access exception): */
1524: assert ((ls_faults
1525: & (TME_STP103X_LS_FAULT_PRIVILEGE
1526: | TME_SPARC64_LS_FAULT_SIDE_EFFECTS
1527: | TME_SPARC64_LS_FAULT_UNCACHEABLE
1528: | TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD
1529: | TME_STP103X_LS_FAULT_ILLEGAL
1530: | TME_SPARC64_LS_FAULT_NO_FAULT_FAULT
1531: | TME_SPARC64_LS_FAULT_VA_RANGE
1532: | TME_SPARC64_LS_FAULT_VA_RANGE_NNPC)) == 0
1533: || (lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0
1534: || ls_faults == TME_STP103X_LS_FAULT_PRIVILEGE
1535: || ls_faults == TME_SPARC64_LS_FAULT_VA_RANGE_NNPC);
1536:
1537: /* these traps are sorted by priority, most important first: */
1538:
1539: /* if this was an illegal instruction: */
1540: if (ls_faults
1541: & (TME_SPARC_LS_FAULT_LDD_STD_RD_ODD)) {
1542:
1543: /* make an illegal_instruction trap, which doesn't update any MMU
1544: registers: */
1545: trap = TME_SPARC64_TRAP_illegal_instruction;
1546: updates = TME_STP103X_UPDATE_NONE;
1547: }
1548:
1549: /* otherwise, if the address isn't aligned: */
1550: else if (ls_faults & TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED) {
1551:
1552: /* assume that this is not an lddf or stdf instruction, or that
1553: the address is not even 32-bit aligned, and make the normal
1554: mem_address_not_aligned trap: */
1555: trap = TME_SPARC64_TRAP_mem_address_not_aligned;
1556:
1557: /* if this is an lddf or stdf instruction: */
1558: insn = ic->_tme_sparc_insn;
1559: if ((insn
1560: & (0x3b << 19))
1561: == (0x23 << 19)) {
1562:
1563: /* if the address is 32-bit aligned, but not 64-bit aligned: */
1564: if ((ls->tme_sparc_ls_address64 % sizeof(tme_uint64_t))
1565: == sizeof(tme_uint32_t)) {
1566:
1567: /* make the LDDF_mem_address_not_aligned or
1568: STDF_mem_address_not_aligned trap: */
1569: trap
1570: = ((insn & (4 << 19))
1571: ? TME_SPARC64_TRAP_STDF_mem_address_not_aligned
1572: : TME_SPARC64_TRAP_LDDF_mem_address_not_aligned);
1573: }
1574: }
1575:
1576: /* these traps update the DMMU SFSR and SFAR: */
1577: updates
1578: = (TME_STP103X_UPDATE_DMMU
1579: + TME_STP103X_UPDATE_MMU_SFSR
1580: + TME_STP103X_UPDATE_DMMU_SFAR);
1581: }
1582:
1583: /* otherwise, if the ASI is privileged: */
1584: else if (ls_faults & TME_SPARC64_LS_FAULT_PRIVILEGED_ASI) {
1585:
1586: /* make a privileged_action trap, which updates the DMMU SFSR and
1587: SFAR: */
1588: trap = TME_SPARC64_TRAP_privileged_action;
1589: updates
1590: = (TME_STP103X_UPDATE_DMMU
1591: + TME_STP103X_UPDATE_MMU_SFSR
1592: + TME_STP103X_UPDATE_DMMU_SFAR);
1593: }
1594:
1595: /* otherwise, if this is an access exception: */
1596: else if (ls_faults
1597: & (TME_STP103X_LS_FAULT_PRIVILEGE
1598: | TME_SPARC64_LS_FAULT_SIDE_EFFECTS
1599: | TME_SPARC64_LS_FAULT_UNCACHEABLE
1600: | TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD
1601: | TME_STP103X_LS_FAULT_ILLEGAL
1602: | TME_SPARC64_LS_FAULT_NO_FAULT_FAULT
1603: | TME_SPARC64_LS_FAULT_VA_RANGE
1604: | TME_SPARC64_LS_FAULT_VA_RANGE_NNPC)) {
1605:
1606: /* make the SFSR FT field: */
1607: if (ls_faults & TME_STP103X_LS_FAULT_PRIVILEGE) {
1608: sfsr += TME_STP103X_SFSR_FT_PRIVILEGE;
1609: }
1610: if (ls_faults & TME_SPARC64_LS_FAULT_SIDE_EFFECTS) {
1611: sfsr += TME_STP103X_SFSR_FT_SIDE_EFFECTS;
1612: }
1613: if (ls_faults & TME_SPARC64_LS_FAULT_UNCACHEABLE) {
1614: /* XXX FIXME WRITEME table 6-11 hints that it's possible to do a
1615: casxa to DTLB_DATA_ACCESS_REG, and that a fault while doing
1616: so will set this bit: */
1617: sfsr += TME_STP103X_SFSR_FT_UNCACHEABLE;
1618: }
1619: if (ls_faults &
1620: (TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD
1621: | TME_STP103X_LS_FAULT_ILLEGAL)) {
1622: sfsr += TME_STP103X_SFSR_FT_ILLEGAL;
1623: }
1624: if (ls_faults & TME_SPARC64_LS_FAULT_NO_FAULT_FAULT) {
1625: sfsr += TME_STP103X_SFSR_FT_NO_FAULT_FAULT;
1626: }
1627: if (ls_faults & TME_SPARC64_LS_FAULT_VA_RANGE) {
1628: sfsr += TME_STP103X_SFSR_FT_VA_RANGE;
1629: }
1630: if (ls_faults & TME_SPARC64_LS_FAULT_VA_RANGE_NNPC) {
1631: sfsr += TME_STP103X_SFSR_FT_VA_RANGE_NNPC;
1632: }
1633:
1634: /* if this is an instruction fetch: */
1635: if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) {
1636:
1637: /* the IMMU SFSR FT field must have exactly one of the privilege
1638: and VA range bits set: */
1639: assert (sfsr != 0
1640: && (sfsr
1641: & ~(TME_STP103X_SFSR_FT_PRIVILEGE
1642: | TME_STP103X_SFSR_FT_VA_RANGE
1643: | TME_STP103X_SFSR_FT_VA_RANGE_NNPC)) == 0
1644: && (sfsr & (sfsr - 1)) == 0);
1645:
1646: /* make an instruction_access_exception trap, which updates the
1647: IMMU SFSR and tag access register: */
1648: trap = (TME_STP103X_TRAP_MG | TME_SPARC64_TRAP_instruction_access_exception);
1649: updates
1650: = (TME_STP103X_UPDATE_IMMU
1651: + TME_STP103X_UPDATE_MMU_SFSR
1652: + TME_STP103X_UPDATE_MMU_TAG_ACCESS);
1653: }
1654:
1655: /* otherwise, this is not an instruction fetch: */
1656: else {
1657:
1658: /* make a data_access_exception trap, which updates the DMMU
1659: SFSR, SFAR, and tag access register: */
1660: trap = (TME_STP103X_TRAP_MG | TME_SPARC64_TRAP_data_access_exception);
1661: updates
1662: = (TME_STP103X_UPDATE_DMMU
1663: + TME_STP103X_UPDATE_MMU_SFSR
1664: + TME_STP103X_UPDATE_DMMU_SFAR
1665: + TME_STP103X_UPDATE_MMU_TAG_ACCESS);
1666: }
1667: }
1668:
1669: /* otherwise, if this is an MMU miss: */
1670: else if (ls_faults & TME_STP103X_LS_FAULT_MMU_MISS) {
1671:
1672: /* if this is an instruction fetch: */
1673: if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) {
1674:
1675: /* make an instruction_access_MMU_miss trap, which updates the
1676: IMMU tag access register: */
1677: trap = TME_STP103X_TRAP_fast_instruction_access_MMU_miss;
1678: updates
1679: = (TME_STP103X_UPDATE_IMMU
1680: + TME_STP103X_UPDATE_MMU_TAG_ACCESS);
1681: }
1682:
1683: /* otherwise, this is not an instruction fetch: */
1684: else {
1685:
1686: /* make a data_access_MMU_miss trap, which updates the DMMU tag
1687: access: */
1688: trap = TME_STP103X_TRAP_fast_data_access_MMU_miss;
1689: updates
1690: = (TME_STP103X_UPDATE_DMMU
1691: + TME_STP103X_UPDATE_MMU_TAG_ACCESS);
1692: }
1693: }
1694:
1695: /* otherwise, if this is a data access protection fault: */
1696: else if (ls_faults & TME_STP103X_LS_FAULT_PROTECTION) {
1697:
1698: /* make a fast_data_access_protection trap, which updates the
1699: DMMU SFSR, SFAR, and tag access register: */
1700: trap = TME_STP103X_TRAP_fast_data_access_protection;
1701: updates
1702: = (TME_STP103X_UPDATE_DMMU
1703: + TME_STP103X_UPDATE_MMU_SFSR
1704: + TME_STP103X_UPDATE_DMMU_SFAR
1705: + TME_STP103X_UPDATE_MMU_TAG_ACCESS);
1706: }
1707:
1708: /* otherwise, this must be an access error fault: */
1709: else {
1710: assert (ls_faults & TME_SPARC_LS_FAULT_BUS_ERROR);
1711:
1712: /* get the asynchronous fault status register bit for this
1713: fault: */
1714: /* NB: we assume that all bus errors are timeouts: */
1715: afsr = TME_STP103X_AFSR_TO;
1716:
1717: /* if no same or higher-priority asynchronous fault has already
1718: happened: */
1719: if ((TME_STP103X(ic)->tme_stp103x_afsr
1720: & (TME_STP103X_AFSR_ME - afsr)) == 0) {
1721:
1722: /* update the asynchronous fault address register: */
1723: assert (ls->tme_sparc_ls_tlb->tme_sparc_tlb_addr_shift == 0);
1724: TME_STP103X(ic)->tme_stp103x_afar
1725: = ((ls->tme_sparc_ls_address64
1726: + (tme_uint64_t) ls->tme_sparc_ls_tlb->tme_sparc_tlb_addr_offset)
1727: & (0 - (tme_uint64_t) (1 << 4)));
1728: }
1729:
1730: /* update the asynchronous fault status register: */
1731: TME_STP103X(ic)->tme_stp103x_afsr
1732: |= (((TME_STP103X(ic)->tme_stp103x_afsr
1733: & afsr)
1734: ? TME_STP103X_AFSR_ME
1735: : !TME_STP103X_AFSR_ME)
1736: + (TME_SPARC_PRIV(ic)
1737: ? TME_STP103X_AFSR_PRIV
1738: : !TME_STP103X_AFSR_PRIV));
1739:
1740: /* if noncacheable errors are not enabled: */
1741: if ((TME_STP103X(ic)->tme_stp103x_estate_error_enable & TME_STP103X_ESTATE_ERROR_ENABLE_NCEEN) == 0) {
1742:
1743: /* clear the fault: */
1744: ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;
1745:
1746: /* if this is a load: */
1747: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) {
1748:
1749: /* force all bytes read to be all-bits-one by filling the
1750: entire memory buffer with all-bits-one: */
1751: /* NB: we do this even though earlier parts of the load may
1752: have succeeded, to keep things simple. we assume that
1753: nothing depends on partially successful loads: */
1754: memset (ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s,
1755: 0xff,
1756: sizeof(ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s));
1757: }
1758:
1759: /* stop this load or store: */
1760: /* NB: we do this even though later parts of the load or store
1761: may succeed, to keep things simple. we assume that nothing
1762: depends on partially successful loads or stores: */
1763: /* NB: we don't set TME_SPARC_LSINFO_LD_COMPLETED because we are
1764: only stopping the load or store here, not completing it. we
1765: still let the original load instruction function complete the
1766: load from the memory buffer: */
1767: ls->tme_sparc_ls_size = 0;
1768:
1769: /* make no trap: */
1770: trap = TME_SPARC_TRAP_none;
1771: }
1772:
1773: /* otherwise, if this is an instruction fetch: */
1774: else if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) {
1775:
1776: /* make an instruction_access_error trap: */
1777: trap = TME_SPARC64_TRAP_instruction_access_error;
1778: }
1779:
1780: /* otherwise, this is not an instruction fetch: */
1781: else {
1782:
1783: /* make a data_access_error trap: */
1784: trap = TME_SPARC64_TRAP_data_access_error;
1785: }
1786:
1787: /* this trap doesn't update any other state: */
1788: updates = TME_STP103X_UPDATE_NONE;
1789: }
1790:
1791: /* get the virtual address, forced to be in range: */
1792: address = ls->tme_sparc_ls_address64;
1793: address |= (0 - (TME_STP103X_VA_HOLE_START * 2));
1794: address = (address ^ TME_STP103X_VA_HOLE_START) + TME_STP103X_VA_HOLE_START;
1795:
1796: /* if this trap updates the DMMU SFAR: */
1797: if (updates & TME_STP103X_UPDATE_DMMU_SFAR) {
1798: TME_STP103X(ic)->tme_stp103x_dmmu_sfar = address;
1799: }
1800:
1801: /* assume that this trap updates the IMMU: */
1802: mmu = &TME_STP103X(ic)->tme_stp103x_immu;
1803:
1804: /* if this trap updates the DMMU: */
1805: if ((updates
1806: & (TME_STP103X_UPDATE_DMMU
1807: | TME_STP103X_UPDATE_IMMU))
1808: != TME_STP103X_UPDATE_IMMU) {
1809:
1810: /* assume that this trap updates the DMMU SFSR and define
1811: SFSR.E: */
1812: if (ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask
1813: & TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS) {
1814: sfsr += TME_STP103X_SFSR_E;
1815: }
1816:
1817: /* update the common DMMU state: */
1818: mmu = &TME_STP103X(ic)->tme_stp103x_dmmu;
1819: }
1820:
1821: /* get the ASI mask from the instruction: */
1822: asi_mask = ls->tme_sparc_ls_asi_mask;
1823:
1824: /* if this trap updates the DMMU or IMMU tag access register: */
1825: if (updates & TME_STP103X_UPDATE_MMU_TAG_ACCESS) {
1826:
1827: /* update the tag access: */
1828: mmu->tme_stp103x_mmu_tag_access
1829: = ((address
1830: & (0 - (tme_uint64_t) (TME_STP103X_CONTEXT_MAX + 1)))
1831: + ((asi_mask & TME_SPARC64_ASI_MASK_FLAG_SPECIAL)
1832: ? 0
1833: : ls->tme_sparc_ls_context));
1834: }
1835:
1836: /* if this trap updates the DMMU or IMMU SFSR: */
1837: if (updates & TME_STP103X_UPDATE_MMU_SFSR) {
1838:
1839: /* define SFSR.ASI: */
1840: TME_FIELD_MASK_DEPOSITU(sfsr,
1841: TME_STP103X_SFSR_ASI,
1842: TME_SPARC_ASI_MASK_WHICH(asi_mask));
1843:
1844: /* define SFSR.CT: */
1845: sfsr
1846: += ((asi_mask & TME_SPARC64_ASI_MASK_FLAG_SPECIAL)
1847: ? TME_STP103X_SFSR_CT_RESERVED
1848: : (asi_mask & TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS)
1849: ? TME_STP103X_SFSR_CT_NUCLEUS
1850: : (asi_mask & TME_SPARC64_ASI_FLAG_SECONDARY)
1851: ? TME_STP103X_SFSR_CT_SECONDARY
1852: : TME_STP103X_SFSR_CT_PRIMARY);
1853:
1854: /* define SFSR.PR: */
1855: if (TME_SPARC_PRIV(ic)) {
1856: sfsr += TME_STP103X_SFSR_PR;
1857: }
1858:
1859: /* define SFSR.W: */
1860: if (lsinfo
1861: & (TME_SPARC_LSINFO_OP_ST
1862: | TME_SPARC_LSINFO_OP_ATOMIC)) {
1863: sfsr += TME_STP103X_SFSR_W;
1864: }
1865:
1866: /* define SFSR.FV: */
1867: sfsr += TME_STP103X_SFSR_FV;
1868:
1869: /* define SFSR.OW: */
1870: if (mmu->tme_stp103x_mmu_sfsr & TME_STP103X_SFSR_FV) {
1871: sfsr += TME_STP103X_SFSR_OW;
1872: }
1873:
1874: /* update the DMMU or IMMU SFSR: */
1875: mmu->tme_stp103x_mmu_sfsr = sfsr;
1876: }
1877:
1878: /* if there is a trap: */
1879: if (__tme_predict_true(trap != TME_SPARC_TRAP_none)) {
1880:
1881: /* trap: */
1882: tme_sparc64_trap(ic, trap);
1883: }
1884: }
1885:
1886: /* this checks that the virtual address of a load/store is in range.
1887: if it is out of range and ic is non-NULL, it traps immediately: */
1888: static tme_uint64_t
1889: _tme_stp103x_ls_address_check(struct tme_sparc *ic,
1890: struct tme_sparc_ls *ls)
1891: {
1892: tme_uint64_t address;
1893: tme_uint32_t address_32_63;
1894:
1895: /* get bits 32..63 of the address: */
1896: address = ls->tme_sparc_ls_address64;
1897: address_32_63 = address >> 32;
1898:
1899: /* if this address is in the address space hole: */
1900: if (__tme_predict_false((address_32_63 + (tme_uint32_t) (TME_STP103X_VA_HOLE_START >> 32))
1901: >= (tme_uint32_t) ((TME_STP103X_VA_HOLE_START * 2) >> 32))) {
1902:
1903: /* note the fault: */
1904: ls->tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_VA_RANGE;
1905:
1906: /* if we can, trap now: */
1907: if (ic != NULL) {
1908: _tme_stp103x_ls_trap(ic, ls);
1909: abort();
1910: /* NOTREACHED */
1911: }
1912: }
1913:
1914: /* return the address: */
1915: return (address);
1916: }
1917:
1918: /* this maps a virtual address directly into a physical address: */
1919: static void
1920: _tme_stp103x_ls_address_map_phys(struct tme_sparc *ic,
1921: struct tme_sparc_ls *ls)
1922: {
1923: tme_uint64_t address;
1924: tme_uint32_t asi;
1925: tme_uint32_t asi_mask;
1926:
1927: /* check the address: */
1928: address = _tme_stp103x_ls_address_check(ic, ls);
1929:
1930: /* get the original ASI: */
1931: asi = TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask);
1932:
1933: /* all of the bypass ASIs behave as if the P bit were clear: */
1934: asi_mask
1935: = (TME_SPARC64_ASI_MASK_PRIV
1936: + TME_SPARC64_ASI_MASK_USER);
1937:
1938: /* ASIs 0x15 and 0x1d behave as if the E bit were set and the CP bit
1939: were clear: */
1940: if (asi & 1) {
1941: asi_mask
1942: += (TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS
1943: + TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE);
1944: }
1945:
1946: /* update the flags on the TLB entry: */
1947: ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask
1948: |= asi_mask;
1949:
1950: /* do the truncating mapping: */
1951: address &= (0 - (tme_uint64_t) TME_STP103X_PAGE_SIZE_8KB);
1952: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = address;
1953: address |= (TME_STP103X_PAGE_SIZE_8KB - 1);
1954: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = address;
1955: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE);
1956: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset
1957: = ((address % TME_STP103X_PA_SIZE)
1958: - address);
1959: }
1960:
1961: /* this maps a virtual address: */
1962: static void
1963: _tme_stp103x_ls_address_map(struct tme_sparc *ic,
1964: struct tme_sparc_ls *ls)
1965: {
1966: tme_uint64_t address;
1967: tme_uint32_t lsu_0_31;
1968: signed long tlb_part_i;
1969: tme_uint32_t tlb_tag_match_0_31;
1970: tme_uint32_t tlb_tag_match_32_63;
1971: tme_uint32_t tlb_tag_xor_0_31;
1972: tme_uint32_t tlb_data_32_63;
1973: tme_uint32_t size;
1974: tme_uint32_t tlb_data_0_31;
1975: struct tme_sparc_tlb *tlb;
1976: tme_uint32_t asi_mask;
1977: tme_uint32_t cycles_ok;
1978:
1979: /* check the address: */
1980: address = _tme_stp103x_ls_address_check(ic, ls);
1981:
1982: /* get bits 0..31 of the load/store unit control register: */
1983: lsu_0_31 = TME_STP103X(ic)->tme_stp103x_lsu;
1984:
1985: /* assume that this is not an instruction fetch, and start at the
1986: beginning of the DMMU TLB entries: */
1987: tlb_part_i = TME_STP103X_TLB_PART_0_DMMU;
1988:
1989: /* if this is an instruction fetch: */
1990: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_FETCH) {
1991:
1992: /* assume that LSU.IM is set, and set LSU.DM to indicate an
1993: enabled IMMU (!): */
1994: lsu_0_31 |= TME_STP103X_LSU_DM;
1995:
1996: /* if the IMMU is disabled, or if the CPU is in RED_state: */
1997: if (__tme_predict_false((lsu_0_31 & TME_STP103X_LSU_IM) == 0
1998: || (ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_RED))) {
1999:
2000: /* clear LSU.DM, to indicate a disabled IMMU (!): */
2001: lsu_0_31 &= ~TME_STP103X_LSU_DM;
2002: }
2003:
2004: /* start at the beginning of the IMMU TLB entries: */
2005: tlb_part_i = TME_STP103X_TLB_PART_0_IMMU;
2006: }
2007:
2008: /* if the MMU is disabled: */
2009: if (__tme_predict_false((lsu_0_31 & TME_STP103X_LSU_DM) == 0)) {
2010:
2011: /* a disabled MMU behaves as if the E bit were set, and the P and
2012: CP bits were clear: */
2013: ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask
2014: |= (TME_SPARC64_ASI_MASK_PRIV
2015: + TME_SPARC64_ASI_MASK_USER
2016: + TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS
2017: + TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE);
2018:
2019: /* do the truncating mapping: */
2020: address &= (0 - (tme_uint64_t) TME_STP103X_PAGE_SIZE_8KB);
2021: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = address;
2022: address |= (TME_STP103X_PAGE_SIZE_8KB - 1);
2023: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = address;
2024: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE);
2025: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset
2026: = ((address % TME_STP103X_PA_SIZE)
2027: - address);
2028: return;
2029: }
2030:
2031: /* make the tag to match: */
2032: tlb_tag_match_32_63 = (address >> 32);
2033: tlb_tag_match_0_31 = address;
2034: tlb_tag_match_0_31 &= ~TME_STP103X_CONTEXT_MAX;
2035: tlb_tag_match_0_31 += ls->tme_sparc_ls_context;
2036:
2037: /* loop over TLB entries: */
2038: do {
2039:
2040: /* if bits 32..63 of the tag match: */
2041: if (TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 1) == tlb_tag_match_32_63) {
2042:
2043: /* if bits 22..31 of the tag match: */
2044: tlb_tag_xor_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 0) ^ tlb_tag_match_0_31;
2045: if (tlb_tag_xor_0_31 < TME_STP103X_PAGE_SIZE_4MB) {
2046:
2047: /* load bits 32..63 of the data: */
2048: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1);
2049:
2050: /* if the data is valid: */
2051: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)) {
2052:
2053: /* get the size of this mapping: */
2054: size
2055: = (TME_STP103X_PAGE_SIZE_8KB
2056: << (3 * TME_FIELD_MASK_EXTRACTU(tlb_data_32_63,
2057: TME_STP103X_TLB_DATA_SIZE_MASK(tlb_data_32_63))));
2058:
2059: /* load bits 0..31 of the data: */
2060: tlb_data_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0);
2061:
2062: /* if bits 0..31 of the tag match: */
2063: if ((tlb_tag_xor_0_31
2064: & ((0 - size)
2065: + ((tlb_data_0_31
2066: & TME_STP103X_TLB_DATA_G(tlb_data_0_31))
2067: ? 0
2068: : TME_STP103X_CONTEXT_MAX))) == 0) {
2069:
2070: /* set the used bit: */
2071: tlb_data_32_63 |= TME_STP103X_TLB_DATA_DIAG_USED(tlb_data_32_63);
2072: TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1) = tlb_data_32_63;
2073:
2074: /* get the sparc TLB entry: */
2075: tlb = ls->tme_sparc_ls_tlb;
2076:
2077: /* if this is a global mapping, update the TLB context: */
2078: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_G(tlb_data_0_31)) {
2079: tlb->tme_sparc_tlb_context = TME_STP103X_CONTEXT_MAX + 1;
2080: }
2081:
2082: /* link the TLB entries: */
2083: tlb->tme_sparc_tlb_link = tlb_part_i;
2084:
2085: /* start the address offset for this mapping: */
2086: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset
2087: = ((tlb_data_0_31
2088: & (tme_uint32_t) TME_STP103X_TLB_DATA_PA)
2089: + (((tme_uint64_t)
2090: (tlb_data_32_63
2091: & (tme_uint32_t) (TME_STP103X_TLB_DATA_PA >> 32)))
2092: << 32));
2093:
2094: /* copy the E, !CP, IE, and NFO bits into the TLB entry's
2095: ASI mask. we predict for the common case, which has CP
2096: set and all of the other bits clear: */
2097: /* NB: we ignore the CV bit, because it's always zero in
2098: the IMMU, and in the DMMU it doesn't count as
2099: uncacheable as far as atomic instructions are
2100: concerned: */
2101: if (__tme_predict_false((tlb_data_0_31
2102: & (TME_STP103X_TLB_DATA_E(tlb_data_0_31)
2103: | TME_STP103X_TLB_DATA_CP(tlb_data_0_31)))
2104: != TME_STP103X_TLB_DATA_CP(tlb_data_0_31))) {
2105: asi_mask = 0;
2106: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_E(tlb_data_0_31)) {
2107: asi_mask += TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS;
2108: }
2109: if ((tlb_data_0_31 & TME_STP103X_TLB_DATA_CP(tlb_data_0_31)) == 0) {
2110: asi_mask += TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE;
2111: }
2112: }
2113: else {
2114: asi_mask = 0;
2115: }
2116: if (__tme_predict_false(tlb_data_32_63
2117: & (TME_STP103X_TLB_DATA_NFO(tlb_data_32_63)
2118: | TME_STP103X_TLB_DATA_IE(tlb_data_32_63)))) {
2119: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_NFO(tlb_data_32_63)) {
2120: asi_mask += TME_SPARC64_ASI_FLAG_NO_FAULT;
2121: }
2122: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_IE(tlb_data_32_63)) {
2123: asi_mask += TME_SPARC64_ASI_FLAG_LITTLE;
2124: }
2125: }
2126:
2127: /* if this mapping is privileged: */
2128: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_P(tlb_data_0_31)) {
2129:
2130: /* if this access is not privileged: */
2131: if (__tme_predict_false(!TME_SPARC_PRIV(ic))) {
2132:
2133: /* trap: */
2134: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_PRIVILEGE;
2135: _tme_stp103x_ls_trap(ic, ls);
2136: assert (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_NO_FAULT);
2137: return;
2138: }
2139: }
2140:
2141: /* otherwise, this mapping is not privileged: */
2142: else {
2143:
2144: /* this TLB entry can be used for privileged and nonprivileged
2145: accesses: */
2146: asi_mask
2147: += (TME_SPARC64_ASI_MASK_PRIV
2148: + TME_SPARC64_ASI_MASK_USER);
2149: }
2150:
2151: /* update the TLB entry's ASI mask: */
2152: ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask |= asi_mask;
2153:
2154: /* if this page is writable: */
2155: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_W(tlb_data_0_31)) {
2156:
2157: /* this mapping can be read and written: */
2158: cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
2159: }
2160:
2161: /* otherwise, this page is not writable: */
2162: else {
2163:
2164: /* if this is a store or an atomic: */
2165: if (__tme_predict_false(ls->tme_sparc_ls_lsinfo
2166: & (TME_SPARC_LSINFO_OP_ST
2167: | TME_SPARC_LSINFO_OP_ATOMIC))) {
2168:
2169: /* remember if this is a 64KB page: */
2170: TME_STP103X(ic)->tme_stp103x_dmmu_direct_64KB = (size == TME_STP103X_PAGE_SIZE_64KB);
2171:
2172: /* trap: */
2173: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_PROTECTION;
2174: _tme_stp103x_ls_trap(ic, ls);
2175: abort();
2176: /* NOTREACHED */
2177: }
2178:
2179: /* this mapping can only be read: */
2180: cycles_ok = TME_BUS_CYCLE_READ;
2181: }
2182:
2183: /* set the cycles for this mapping: */
2184: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = cycles_ok;
2185:
2186: /* set the first and last addresses for this mapping: */
2187: address = ls->tme_sparc_ls_address64;
2188: address |= (size - 1);
2189: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = address;
2190: address &= (0 - (tme_uint64_t) size);
2191: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = address;
2192:
2193: /* finish the address offset for this mapping: */
2194: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset -= address;
2195:
2196: return;
2197: }
2198: }
2199: }
2200: }
2201:
2202: tlb_part_i += 2;
2203: } while (tlb_part_i % (2 * TME_STP103X_TLB_SIZE));
2204:
2205: /* this is a miss: */
2206: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_MMU_MISS;
2207: _tme_stp103x_ls_trap(ic, ls);
2208: assert (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_NO_FAULT);
2209: }
2210:
2211: /* the ASI handler for ASI_PHYS_USE_EC*, ASI_PHYS_BYPASS_EC_WITH_EBIT*: */
2212: static void
2213: _tme_stp103x_ls_asi_phys(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2214: {
2215:
2216: /* override the address map function: */
2217: ls->tme_sparc_ls_address_map = _tme_stp103x_ls_address_map_phys;
2218: }
2219:
2220: /* the cycle handler for ASI_NUCLEUS_QUAD_LDD*: */
2221: static void
2222: _tme_stp103x_ls_cycle_quad(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2223: {
2224: struct tme_sparc_tlb *tlb;
2225: tme_uint32_t asi_mask;
2226: _tme_const tme_shared tme_uint8_t *memory;
2227: #if !TME_THREADS_COOPERATIVE
2228: #ifdef tme_memory_atomic_read128
2229: tme_uint128_t quad;
2230: #endif /* tme_memory_atomic_read128 */
2231: #endif /* !TME_THREADS_COOPERATIVE */
2232: tme_uint64_t quad_64lo;
2233: tme_uint64_t quad_64hi;
2234: tme_uint64_t *_rd;
2235:
2236: /* get the TLB entry: */
2237: tlb = ls->tme_sparc_ls_tlb;
2238:
2239: /* get the ASI mask: */
2240: asi_mask = tlb->tme_sparc_tlb_asi_mask;
2241:
2242: /* this TLB entry must be for cacheable memory: */
2243: if (__tme_predict_false(asi_mask
2244: & TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE)) {
2245:
2246: /* we must have caught this on the first cycle: */
2247: assert (ls->tme_sparc_ls_buffer_offset == 0);
2248:
2249: /* fault: */
2250: ls->tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_UNCACHEABLE;
2251: return;
2252: }
2253:
2254: /* assume that we can't do a fast transfer: */
2255: memory = TME_EMULATOR_OFF_UNDEF;
2256:
2257: /* if this is the first cycle: */
2258: if (ls->tme_sparc_ls_buffer_offset == 0) {
2259:
2260: /* if this TLB entry allows fast transfer of all of the addresses: */
2261: if (__tme_predict_true((((tme_bus_addr64_t) tlb->tme_sparc_tlb_addr_last)
2262: - ls->tme_sparc_ls_address64)
2263: >= ((sizeof(tme_uint64_t) * 2) - 1))) {
2264:
2265: /* we may be able do a fast transfer: */
2266: memory = tlb->tme_sparc_tlb_emulator_off_read;
2267: }
2268: }
2269:
2270: /* if we can't do a fast transfer: */
2271: if (__tme_predict_false(memory == TME_EMULATOR_OFF_UNDEF)) {
2272:
2273: /* do a slow cycle: */
2274: tme_sparc64_load(ic, ls);
2275:
2276: /* if this was not the last cycle, return now: */
2277: if (ls->tme_sparc_ls_size != 0) {
2278: return;
2279: }
2280:
2281: /* fake a fast transfer from the memory buffer: */
2282: memory = &ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s[0];
2283: memory -= ls->tme_sparc_ls_address64;
2284: }
2285:
2286: /* finish the memory address: */
2287: memory += ls->tme_sparc_ls_address64;
2288:
2289: /* if threads are cooperative: */
2290: #if TME_THREADS_COOPERATIVE
2291:
2292: /* do two 64-bit loads: */
2293: quad_64lo
2294: = tme_memory_bus_read64(((_tme_const tme_shared tme_uint64_t *) memory) + 0,
2295: tlb->tme_sparc_tlb_bus_rwlock,
2296: (sizeof(tme_uint64_t) * 2),
2297: sizeof(tme_uint64_t));
2298: quad_64hi
2299: = tme_memory_bus_read64(((_tme_const tme_shared tme_uint64_t *) memory) + 1,
2300: tlb->tme_sparc_tlb_bus_rwlock,
2301: (sizeof(tme_uint64_t) * 1),
2302: sizeof(tme_uint64_t));
2303:
2304: /* otherwise, threads are not cooperative: */
2305: #else /* !TME_THREADS_COOPERATIVE */
2306:
2307: /* if host supports an atomic 128-bit read: */
2308: #ifdef tme_memory_atomic_read128
2309:
2310: /* do the atomic 128-bit read: */
2311: quad
2312: = tme_memory_atomic_read128((_tme_const tme_shared tme_uint128_t *) memory,
2313: tlb->tme_sparc_tlb_bus_rwlock,
2314: sizeof(tme_uint128_t));
2315:
2316: /* get the two parts of the load: */
2317: #if TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
2318: quad_64lo = quad >> 64;
2319: quad_64hi = quad;
2320: #elif TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
2321: quad_64lo = quad;
2322: quad_64hi = quad >> 64;
2323: #endif
2324: #else /* !tme_memory_atomic_read128 */
2325: #error "non-cooperative threads requires an atomic 128-bit read"
2326: #endif /* !tme_memory_atomic_read128 */
2327: #endif /* !TME_THREADS_COOPERATIVE */
2328:
2329: /* swap the two 64-bit values as needed: */
2330: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE) {
2331: quad_64lo = tme_letoh_u64(quad_64lo);
2332: quad_64hi = tme_letoh_u64(quad_64hi);
2333: }
2334: else {
2335: quad_64lo = tme_betoh_u64(quad_64lo);
2336: quad_64hi = tme_betoh_u64(quad_64hi);
2337: }
2338:
2339: /* complete the load: */
2340: ls->tme_sparc_ls_size = 0;
2341: _rd = ls->tme_sparc_ls_rd64;
2342: TME_SPARC_FORMAT3_RD = quad_64lo;
2343: TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint64) = quad_64hi;
2344: }
2345:
2346: /* the ASI handler for ASI_NUCLEUS_QUAD_LDD*: */
2347: static void
2348: _tme_stp103x_ls_asi_quad(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2349: {
2350:
2351: /* we need to do the complete load: */
2352: ls->tme_sparc_ls_size = sizeof(tme_uint64_t) * 2;
2353: ls->tme_sparc_ls_buffer_offset = 0;
2354: ls->tme_sparc_ls_lsinfo
2355: |= (TME_SPARC_LSINFO_SLOW_CYCLES
2356: + TME_SPARC_LSINFO_LD_COMPLETED);
2357: ls->tme_sparc_ls_cycle = _tme_stp103x_ls_cycle_quad;
2358:
2359: /* an instruction other than ldda is illegal: */
2360: if (__tme_predict_false((ic->_tme_sparc_insn
2361: & (0x3f << 19))
2362: != (0x13 << 19))) {
2363: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
2364: }
2365:
2366: /* the address must be 128-bit aligned: */
2367: if (__tme_predict_false(((tme_uint32_t) ls->tme_sparc_ls_address64)
2368: % (sizeof(tme_uint64_t) * 2))) {
2369: ls->tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;
2370: }
2371: }
2372:
2373: /* the ASI handler for various infrequently-used ASIs: */
2374: static void
2375: _tme_stp103x_ls_asi_slow(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2376: {
2377: tme_uint32_t lsinfo_ops;
2378: int size_ok;
2379: int address_ok;
2380: tme_uint64_t value_mask;
2381: void (*update_write) _TME_P((struct tme_sparc *, tme_uint64_t));
2382: int redispatch;
2383: tme_uint64_t *_value64;
2384: tme_uint32_t *_value32;
2385: tme_uint64_t value;
2386: tme_uint64_t value_now;
2387:
2388: /* assume that this ASI allows reads and writes: */
2389: lsinfo_ops
2390: = (TME_SPARC_LSINFO_OP_LD
2391: | TME_SPARC_LSINFO_OP_ST);
2392:
2393: /* assume that this ASI allows only 64-bit accesses: */
2394: size_ok = (ls->tme_sparc_ls_size == sizeof(tme_uint64_t));
2395:
2396: /* assume that this ASI allows only accesses to address zero: */
2397: address_ok = (ls->tme_sparc_ls_address64 == 0);
2398:
2399: /* assume that this ASI doesn't mask values written: */
2400: value_mask = 0 - (tme_uint64_t) 1;
2401:
2402: /* assume that this ASI has no write side-effects: */
2403: update_write = NULL;
2404:
2405: /* assume that a write won't need a redispatch: */
2406: redispatch = FALSE;
2407:
2408: /* assume that the access is invalid: */
2409: _value64 = NULL;
2410: _value32 = NULL;
2411:
2412: /* dispatch on the ASI: */
2413: switch (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)) {
2414:
2415: /* all unknown ASIs: */
2416: default:
2417: address_ok = FALSE;
2418: break;
2419:
2420: case TME_STP103X_ASI_LSU_CONTROL_REG:
2421: _value64 = &TME_STP103X(ic)->tme_stp103x_lsu;
2422: update_write = _tme_stp103x_update_lsu;
2423: break;
2424:
2425: case TME_STP103X_ASI_INTR_DISPATCH_STATUS:
2426: lsinfo_ops = TME_SPARC_LSINFO_OP_LD;
2427: /* XXX FIXME WRITEME: */
2428: abort();
2429: break;
2430:
2431: case TME_STP103X_ASI_INTR_RECEIVE:
2432: value_now
2433: = ((tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy)
2434: ? TME_STP103X_INTR_RECEIVE_BUSY
2435: : 0)
2436: + TME_STP103X(ic)->tme_stp103x_intr_receive_mid);
2437: _value64 = &value_now;
2438: update_write = _tme_stp103x_update_intr_receive;
2439: break;
2440:
2441: case TME_STP103X_ASI_UPA_CONFIG_REG:
2442: _value64 = &TME_STP103X(ic)->tme_stp103x_upa_config;
2443: update_write = _tme_stp103x_update_upa_config;
2444: break;
2445:
2446: case TME_STP103X_ASI_ESTATE_ERROR_EN_REG:
2447: _value32 = &TME_STP103X(ic)->tme_stp103x_estate_error_enable;
2448: value_mask
2449: = (TME_STP103X_ESTATE_ERROR_ENABLE_CEEN
2450: | TME_STP103X_ESTATE_ERROR_ENABLE_NCEEN
2451: | TME_STP103X_ESTATE_ERROR_ENABLE_ISAPEN);
2452: break;
2453:
2454: case TME_STP103X_ASI_AFSR:
2455: _value64 = &TME_STP103X(ic)->tme_stp103x_afsr;
2456: update_write = _tme_stp103x_update_afsr;
2457: break;
2458:
2459: case TME_STP103X_ASI_AFAR:
2460: _value64 = &TME_STP103X(ic)->tme_stp103x_afar;
2461: value_mask = TME_STP103X_PA_SIZE - (1 << 4);
2462: break;
2463:
2464: case TME_STP103X_ASI_ECACHE_TAG_DATA:
2465: _value32 = &TME_STP103X(ic)->tme_stp103x_ecache_tag_data;
2466: break;
2467: }
2468:
2469: /* check the access: */
2470: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo & lsinfo_ops) == 0
2471: || !size_ok
2472: || !address_ok)) {
2473: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
2474: }
2475:
2476: /* if there are any faults: */
2477: if (__tme_predict_false(ls->tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_NONE)) {
2478: return;
2479: }
2480:
2481: /* get the raw value to read or write: */
2482: value
2483: = ((ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST)
2484: ? *ls->tme_sparc_ls_rd64
2485: : _value64 != NULL
2486: ? *_value64
2487: : *_value32);
2488:
2489: /* mask the value: */
2490: value &= value_mask;
2491:
2492: /* complete the load or store: */
2493: ls->tme_sparc_ls_size = 0;
2494:
2495: /* if this is a load: */
2496: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) {
2497:
2498: /* complete the load: */
2499: *ls->tme_sparc_ls_rd64 = value;
2500: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
2501: }
2502:
2503: /* otherwise, this is a store: */
2504: else {
2505:
2506: /* if this value has write side-effects: */
2507: if (update_write != NULL) {
2508:
2509: /* do the write side-effects: */
2510: (*update_write)(ic, value);
2511: }
2512:
2513: /* otherwise, this value has no write side-effects: */
2514: else {
2515:
2516: /* complete the store: */
2517: if (_value64 != NULL) {
2518: *_value64 = value;
2519: }
2520: else {
2521: *_value32 = value;
2522: }
2523: }
2524:
2525: /* if this store needs a redispatch: */
2526: if (redispatch) {
2527: tme_bus_tlb_unbusy(&ic->tme_sparc_tlbs[ls->tme_sparc_ls_tlb_i].tme_sparc_tlb_bus_tlb);
2528: tme_sparc_redispatch(ic);
2529: }
2530: }
2531: }
2532:
2533: /* the ASI handler for ASI_DMMU and ASI_IMMU: */
2534: static void
2535: _tme_stp103x_ls_asi_mmu(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2536: {
2537: tme_uint64_t address;
2538: tme_uint32_t address_0_31;
2539: struct tme_stp103x_mmu *mmu;
2540: tme_uint32_t lsinfo;
2541: tme_uint64_t tag_target;
2542: tme_uint32_t context;
2543: tme_uint64_t *_value64;
2544: tme_uint32_t *_value32;
2545: int value_has_va;
2546: tme_uint64_t value_mask;
2547: tme_uint32_t lsinfo_ops;
2548: int redispatch;
2549: tme_uint64_t value;
2550:
2551: /* if this is a 64-bit access that hasn't faulted yet: */
2552: if (__tme_predict_true(ls->tme_sparc_ls_size == sizeof(tme_uint64_t)
2553: && ls->tme_sparc_ls_faults == TME_SPARC_LS_FAULT_NONE)) {
2554:
2555: /* get the address: */
2556: address = ls->tme_sparc_ls_address64;
2557:
2558: /* if the address fits into 32 bits: */
2559: if (__tme_predict_true((address & (0 - (((tme_uint64_t) 1) << 32))) == 0)) {
2560:
2561: /* truncate the address to 32 bits: */
2562: address_0_31 = address;
2563:
2564: /* get the MMU state: */
2565: mmu
2566: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)
2567: ? &TME_STP103X(ic)->tme_stp103x_dmmu
2568: : &TME_STP103X(ic)->tme_stp103x_immu);
2569:
2570: /* get the load/store information: */
2571: lsinfo = ls->tme_sparc_ls_lsinfo;
2572:
2573: /* address 0x0 is the tag target register: */
2574: if (address_0_31 == 0) {
2575:
2576: /* if this is a load: */
2577: if (lsinfo & TME_SPARC_LSINFO_OP_LD) {
2578:
2579: /* make the value for the tag target register: */
2580: tag_target = mmu->tme_stp103x_mmu_tag_access;
2581: context = ((tme_uint32_t) tag_target) & TME_STP103X_CONTEXT_MAX;
2582: tag_target >>= 22;
2583: tag_target |= ((tme_uint64_t) (context << (48 - 32))) << 32;
2584:
2585: /* complete the load: */
2586: *ls->tme_sparc_ls_rd64 = tag_target;
2587: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
2588: ls->tme_sparc_ls_size = 0;
2589: return;
2590: }
2591: }
2592:
2593: else {
2594:
2595: /* assume that the register is invalid: */
2596: _value64 = NULL;
2597: _value32 = NULL;
2598:
2599: /* assume that values for this register aren't virtual
2600: addresses, and don't have any masked bits: */
2601: value_has_va = FALSE;
2602: value_mask = 0 - (tme_uint64_t) 1;
2603:
2604: /* assume that this register allows reads and writes: */
2605: lsinfo_ops
2606: = (TME_SPARC_LSINFO_OP_LD
2607: | TME_SPARC_LSINFO_OP_ST);
2608:
2609: /* assume that a write to this register won't need a redispatch: */
2610: redispatch = FALSE;
2611:
2612: /* address 0x18 is the synchronous fault status register: */
2613: if (address_0_31 == 0x18) {
2614: _value64 = &mmu->tme_stp103x_mmu_sfsr;
2615: }
2616:
2617: /* address 0x28 is the TSB register: */
2618: else if (address_0_31 == 0x28) {
2619: _value64 = &mmu->tme_stp103x_mmu_tsb;
2620: value_has_va = TRUE;
2621: }
2622:
2623: /* address 0x30 is the tag access register: */
2624: else if (address_0_31 == 0x30) {
2625: _value64 = &mmu->tme_stp103x_mmu_tag_access;
2626: value_has_va = TRUE;
2627: }
2628:
2629: /* if this is ASI_DMMU: */
2630: else if (mmu == &TME_STP103X(ic)->tme_stp103x_dmmu) {
2631:
2632: /* address 0x8 is the primary context register: */
2633: if (address_0_31 == 0x8) {
2634: _value32 = &ic->tme_sparc_memory_context_primary;
2635: value_mask = TME_STP103X_CONTEXT_MAX;
2636: redispatch = TRUE;
2637: }
2638:
2639: /* address 0x10 is the secondary context register: */
2640: else if (address_0_31 == 0x10) {
2641: _value32 = &ic->tme_sparc_memory_context_secondary;
2642: value_mask = TME_STP103X_CONTEXT_MAX;
2643: }
2644:
2645: /* address 0x20 is the synchronous fault address register: */
2646: else if (address_0_31 == 0x20) {
2647: _value64 = &TME_STP103X(ic)->tme_stp103x_dmmu_sfar;
2648: lsinfo_ops = TME_SPARC_LSINFO_OP_LD;
2649: }
2650:
2651: /* address 0x38 is the VA Data Watchpoint register: */
2652: else if (address_0_31 == 0x38) {
2653: abort();
2654: }
2655:
2656: /* address 0x40 is the PA Data Watchpoint register: */
2657: else if (address_0_31 == 0x38) {
2658: abort();
2659: }
2660: }
2661:
2662: /* if the register valid and supports this access: */
2663: if (__tme_predict_true((_value64 != NULL
2664: || _value32 != NULL)
2665: && (lsinfo & lsinfo_ops) != 0)) {
2666:
2667: /* get the raw value to read or write: */
2668: value
2669: = (lsinfo & TME_SPARC_LSINFO_OP_ST
2670: ? *ls->tme_sparc_ls_rd64
2671: : _value64 != NULL
2672: ? *_value64
2673: : *_value32);
2674:
2675: /* if this value has a virtual address: */
2676: if (value_has_va) {
2677:
2678: /* force the virtual address to be in range: */
2679: value |= (0 - (TME_STP103X_VA_HOLE_START * 2));
2680: value = (value ^ TME_STP103X_VA_HOLE_START) + TME_STP103X_VA_HOLE_START;
2681: }
2682:
2683: /* mask the value: */
2684: value &= value_mask;
2685:
2686: /* if this is a load: */
2687: if (lsinfo & TME_SPARC_LSINFO_OP_LD) {
2688:
2689: /* complete the load: */
2690: *ls->tme_sparc_ls_rd64 = value;
2691: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
2692: }
2693:
2694: /* otherwise, this is a store: */
2695: else {
2696:
2697: /* complete the store: */
2698: if (_value64 != NULL) {
2699: *_value64 = value;
2700: }
2701: else {
2702: *_value32 = value;
2703: }
2704:
2705: /* if this store needs a redispatch: */
2706: if (redispatch) {
2707: tme_bus_tlb_unbusy(&ic->tme_sparc_tlbs[ls->tme_sparc_ls_tlb_i].tme_sparc_tlb_bus_tlb);
2708: tme_sparc_redispatch(ic);
2709: }
2710: }
2711:
2712: /* complete the load or store: */
2713: ls->tme_sparc_ls_size = 0;
2714: return;
2715: }
2716: }
2717: }
2718: }
2719:
2720: /* this is an illegal access: */
2721: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
2722: }
2723:
2724: /* the ASI handler for:
2725: ASI_DMMU_TSB_8KB_PTR_REG, ASI_DMMU_TSB_64KB_PTR_REG,
2726: ASI_IMMU_TSB_8KB_PTR_REG, ASI_IMMU_TSB_64KB_PTR_REG,
2727: ASI_DMMU_TSB_DIRECT_PTR_REG: */
2728: static void
2729: _tme_stp103x_ls_asi_tsb_ptr(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2730: {
2731: tme_uint32_t asi_mask;
2732: struct tme_stp103x_mmu *mmu;
2733: tme_uint32_t pointer_0_31;
2734: tme_uint32_t size_64KB;
2735: tme_uint32_t tsb_0_31;
2736: tme_uint32_t tsb_size;
2737:
2738: /* if this is not a 64-bit load of address zero: */
2739: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
2740: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) == 0
2741: || ls->tme_sparc_ls_address64 != 0)) {
2742:
2743: /* this is an illegal access: */
2744: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
2745: }
2746:
2747: /* if this access has faulted: */
2748: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
2749: return;
2750: }
2751:
2752: /* get the ASI mask from the instruction: */
2753: asi_mask = ls->tme_sparc_ls_asi_mask;
2754:
2755: /* get the common MMU state: */
2756: mmu
2757: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(asi_mask)
2758: ? &TME_STP103X(ic)->tme_stp103x_dmmu
2759: : &TME_STP103X(ic)->tme_stp103x_immu);
2760:
2761: /* start the TSB pointer with the tag access register: */
2762: pointer_0_31 = mmu->tme_stp103x_mmu_tag_access;
2763:
2764: /* if this might be a 64KB page: */
2765: size_64KB = asi_mask & TME_SPARC_ASI_MASK_RAW(TME_STP103X_ASI_FLAG_TSB_64KB_PTR);
2766: if (size_64KB) {
2767:
2768: /* if this is ASI_DMMU_TSB_DIRECT_PTR_REG: */
2769: if (asi_mask & TME_SPARC_ASI_MASK_RAW(TME_STP103X_ASI_FLAG_TSB_8KB_PTR)) {
2770:
2771: /* this is a 64KB page if the last fast_data_access_protection
2772: trap was for a 64KB page: */
2773: size_64KB = TME_STP103X(ic)->tme_stp103x_dmmu_direct_64KB;
2774: }
2775:
2776: /* if this is a 64KB page, shift the TSB pointer: */
2777: if (size_64KB) {
2778: pointer_0_31 /= (TME_STP103X_PAGE_SIZE_64KB / TME_STP103X_PAGE_SIZE_8KB);
2779: }
2780: }
2781:
2782: /* shift the tag access register in the TSB pointer down to index a
2783: 16-byte TSB entry: */
2784: pointer_0_31 = (pointer_0_31 / (TME_STP103X_PAGE_SIZE_8KB / 16)) & (0 - (tme_uint32_t) 16);
2785:
2786: /* get bits 0..31 of the TSB register: */
2787: tsb_0_31 = mmu->tme_stp103x_mmu_tsb;
2788:
2789: /* get the size of (one half of) the TSB: */
2790: tsb_size = TME_STP103X_PAGE_SIZE_8KB;
2791: tsb_size <<= (tsb_0_31 & TME_STP103X_TSB_SIZE);
2792:
2793: /* finish the offset of the entry in (one half of) the TSB: */
2794: pointer_0_31 &= (tsb_size - 1);
2795:
2796: /* if this is a split TSB: */
2797: if (tsb_0_31 & TME_STP103X_TSB_SPLIT) {
2798:
2799: /* if this is a 64KB page, select the other half of the TSB: */
2800: if (size_64KB) {
2801: pointer_0_31 += tsb_size;
2802: }
2803:
2804: /* the TSB is actually two halves: */
2805: tsb_size *= 2;
2806: }
2807:
2808: /* finish bits 0..31 of the TSB pointer: */
2809: pointer_0_31 += (tsb_0_31 & (0 - tsb_size));
2810:
2811: /* complete the load: */
2812: *ls->tme_sparc_ls_rd64
2813: = ((mmu->tme_stp103x_mmu_tsb
2814: & (0 - (((tme_uint64_t) 1) << 32)))
2815: | pointer_0_31);
2816: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
2817: ls->tme_sparc_ls_size = 0;
2818: }
2819:
2820: /* the ASI handler for ASI_ITLB_DATA_IN_REG, ASI_DTLB_DATA_IN_REG: */
2821: static void
2822: _tme_stp103x_ls_asi_tlb_data_in(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2823: {
2824: signed long tlb_part_i;
2825: signed long tlb_part_i_invalid;
2826: signed long tlb_part_i_unlocked;
2827: signed long tlb_part_i_unlocked_unused;
2828: tme_uint32_t tlb_data_32_63;
2829:
2830: /* if this is not a 64-bit store of address zero: */
2831: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
2832: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) == 0
2833: || ls->tme_sparc_ls_address64 != 0)) {
2834:
2835: /* this is an illegal access: */
2836: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
2837: }
2838:
2839: /* if this access has faulted: */
2840: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
2841: return;
2842: }
2843:
2844: /* if this is ASI_DTLB_DATA_IN_REG, start at the last entry of the
2845: DTLB, otherwise start at the last entry of the ITLB: */
2846: tlb_part_i
2847: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)
2848: ? TME_STP103X_TLB_PART_0_DMMU + (TME_STP103X_TLB_SIZE * 2) - 2
2849: : TME_STP103X_TLB_PART_0_IMMU + (TME_STP103X_TLB_SIZE * 2) - 2);
2850:
2851: /* search for invalid, unlocked, and unlocked+unused TLB entries: */
2852: tlb_part_i_invalid = -1;
2853: tlb_part_i_unlocked = -1;
2854: tlb_part_i_unlocked_unused = -1;
2855: for (;;) {
2856:
2857: /* load bits 32..63 of the TLB entry's data: */
2858: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1);
2859:
2860: /* if this TLB entry is invalid: */
2861: if ((tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)) == 0) {
2862:
2863: /* track the lowest-numbered invalid TLB entry: */
2864: tlb_part_i_invalid = tlb_part_i;
2865: }
2866:
2867: /* if this TLB entry is not locked: */
2868: if ((TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0)
2869: & TME_STP103X_TLB_DATA_L((tme_uint32_t) 0)) == 0) {
2870:
2871: /* track the lowest-numbered unlocked TLB entry: */
2872: tlb_part_i_unlocked = tlb_part_i;
2873:
2874: /* if the TLB entry's used bit is clear: */
2875: if ((tlb_data_32_63 & TME_STP103X_TLB_DATA_DIAG_USED(tlb_data_32_63)) == 0) {
2876:
2877: /* track the lowest-numbered unlocked and unused TLB entry: */
2878: tlb_part_i_unlocked_unused = tlb_part_i;
2879: }
2880: }
2881:
2882: /* if we have not exhausted the TLB: */
2883: if (tlb_part_i % (TME_STP103X_TLB_SIZE * 2)) {
2884: tlb_part_i -= 2;
2885: continue;
2886: }
2887:
2888: /* if there is an invalid TLB entry: */
2889: if (tlb_part_i_invalid >= 0) {
2890: tlb_part_i = tlb_part_i_invalid;
2891: break;
2892: }
2893:
2894: /* otherwise, if there is an unlocked and unused TLB entry: */
2895: if (tlb_part_i_unlocked_unused >= 0) {
2896: tlb_part_i = tlb_part_i_unlocked_unused;
2897: }
2898:
2899: /* otherwise, there is no invalid TLB entry and no unlocked and
2900: unused TLB entry: */
2901: else {
2902:
2903: /* clear the used bits on all TLB entries: */
2904: do {
2905: TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1)
2906: &= ~TME_STP103X_TLB_DATA_DIAG_USED(tlb_data_32_63);
2907: tlb_part_i += 2;
2908: } while (tlb_part_i % (TME_STP103X_TLB_SIZE * 2));
2909:
2910: /* there must be an unlocked TLB entry: */
2911: assert (tlb_part_i_unlocked >= 0);
2912: tlb_part_i = tlb_part_i_unlocked;
2913: }
2914:
2915: /* invalidate this TLB entry: */
2916: _tme_stp103x_tlb_invalidate(ic, tlb_part_i);
2917: break;
2918: }
2919:
2920: /* complete the store: */
2921: #if TME_STP103X_TLB_PART_0_DMMU >= TME_STP103X_TLB_PART_0_IMMU
2922: #error "TME_STP103X_TLB_PART_0_DMMU or TME_STP103X_TLB_PART_0_IMMU changed"
2923: #endif
2924: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0)
2925: = (tlb_part_i < TME_STP103X_TLB_PART_0_IMMU
2926: ? &TME_STP103X(ic)->tme_stp103x_dmmu
2927: : &TME_STP103X(ic)->tme_stp103x_immu)->tme_stp103x_mmu_tag_access;
2928: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 1) = *ls->tme_sparc_ls_rd64;
2929: ls->tme_sparc_ls_size = 0;
2930: }
2931:
2932: /* ASI_ITLB_DATA_ACCESS_REG, ASI_DTLB_DATA_ACCESS_REG: */
2933: static void
2934: _tme_stp103x_ls_asi_tlb_data_access(struct tme_sparc *ic, struct tme_sparc_ls *ls)
2935: {
2936: unsigned long tlb_part_i;
2937: tme_uint64_t *_tag_access;
2938:
2939: /* XXX FIXME WRITEME table 6-11 hints that it's possible to do a
2940: casxa to DTLB_DATA_ACCESS_REG. also see the WRITEME in
2941: _tme_stp103x_ls_trap(): */
2942: assert ((ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ATOMIC) == 0);
2943:
2944: /* if this is not a 64-bit load or store: */
2945: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
2946: || (ls->tme_sparc_ls_lsinfo
2947: & (TME_SPARC_LSINFO_OP_LD
2948: | TME_SPARC_LSINFO_OP_ST)) == 0)) {
2949:
2950: /* this is an illegal access: */
2951: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
2952: }
2953:
2954: /* if this access has faulted: */
2955: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
2956: return;
2957: }
2958:
2959: /* get the addressed TLB entry and common MMU state: */
2960: tlb_part_i = ls->tme_sparc_ls_address64;
2961: tlb_part_i %= TME_STP103X_TLB_SIZE * sizeof(tme_uint64_t);
2962: tlb_part_i /= (sizeof(tme_uint64_t) / 2);
2963: tlb_part_i += TME_STP103X_TLB_PART_0_DMMU;
2964: _tag_access = &TME_STP103X(ic)->tme_stp103x_dmmu.tme_stp103x_mmu_tag_access;
2965: if (!TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)) {
2966: tlb_part_i = (tlb_part_i - TME_STP103X_TLB_PART_0_DMMU) + TME_STP103X_TLB_PART_0_IMMU;
2967: _tag_access = &TME_STP103X(ic)->tme_stp103x_immu.tme_stp103x_mmu_tag_access;
2968: }
2969:
2970: /* if this is a load: */
2971: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) {
2972:
2973: /* complete the load: */
2974: *ls->tme_sparc_ls_rd64 = TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 1);
2975: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
2976: }
2977:
2978: /* otherwise, this is a store: */
2979: else {
2980:
2981: /* if the TLB entry is valid: */
2982: if (TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1)
2983: & TME_STP103X_TLB_DATA_V((tme_uint32_t) 0)) {
2984:
2985: /* invalidate this TLB entry: */
2986: _tme_stp103x_tlb_invalidate(ic,
2987: tlb_part_i);
2988: }
2989:
2990: /* complete the store: */
2991: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0) = *_tag_access;
2992: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 1) = *ls->tme_sparc_ls_rd64;
2993: }
2994:
2995: /* we completed the load or store: */
2996: ls->tme_sparc_ls_size = 0;
2997: }
2998:
2999: /* the ASI handler for ASI_ITLB_TAG_READ_REG, ASI_DTLB_TAG_READ_REG: */
3000: static void
3001: _tme_stp103x_ls_asi_tlb_tag_read(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3002: {
3003: unsigned long tlb_part_i;
3004:
3005: /* if this is not a 64-bit load: */
3006: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
3007: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) == 0)) {
3008:
3009: /* this is an illegal access: */
3010: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3011: }
3012:
3013: /* if this access has faulted: */
3014: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
3015: return;
3016: }
3017:
3018: /* get the addressed TLB entry and common MMU state: */
3019: tlb_part_i = ls->tme_sparc_ls_address64;
3020: tlb_part_i %= TME_STP103X_TLB_SIZE * sizeof(tme_uint64_t);
3021: tlb_part_i /= (sizeof(tme_uint64_t) / 2);
3022: tlb_part_i += TME_STP103X_TLB_PART_0_DMMU;
3023: if (!TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)) {
3024: tlb_part_i = (tlb_part_i - TME_STP103X_TLB_PART_0_DMMU) + TME_STP103X_TLB_PART_0_IMMU;
3025: }
3026:
3027: /* complete the load: */
3028: *ls->tme_sparc_ls_rd64 = TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0);
3029: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
3030: ls->tme_sparc_ls_size = 0;
3031: }
3032:
3033: /* the ASI handler for ASI_IMMU_DEMAP, ASI_DMMU_DEMAP: */
3034: static void
3035: _tme_stp103x_ls_asi_mmu_demap(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3036: {
3037: tme_uint64_t address;
3038: tme_uint32_t tlb_tag_match_32_63;
3039: tme_uint32_t tlb_tag_match_0_31;
3040: tme_uint32_t context;
3041: tme_uint32_t tlb_tag_mask32;
3042: unsigned long tlb_part_i;
3043: tme_uint32_t tlb_tag_xor_32_63;
3044: tme_uint32_t tlb_data_0_31;
3045: tme_uint32_t tlb_tag_xor_0_31;
3046: tme_uint32_t tlb_data_32_63;
3047: tme_uint32_t size;
3048:
3049: /* if this is not a 64-bit store: */
3050: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
3051: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) == 0)) {
3052:
3053: /* this is an illegal access: */
3054: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3055: }
3056:
3057: /* check the address: */
3058: address = _tme_stp103x_ls_address_check(NULL, ls);
3059: tlb_tag_match_32_63 = address >> 32;
3060: tlb_tag_match_0_31 = address;
3061:
3062: /* if this access has faulted: */
3063: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
3064: return;
3065: }
3066:
3067: /* we will complete this store: */
3068: ls->tme_sparc_ls_size = 0;
3069:
3070: /* assume that this demap uses the primary context: */
3071: context = ic->tme_sparc_memory_context_primary;
3072:
3073: /* if this demap might use the secondary context: */
3074: if (tlb_tag_match_0_31 & TME_BIT(4)) {
3075: context = ic->tme_sparc_memory_context_secondary;
3076: }
3077:
3078: /* if this demap uses the nucleus context: */
3079: if (tlb_tag_match_0_31 & TME_BIT(5)) {
3080: context = 0;
3081:
3082: /* "Use of the reserved value causes the demap to be ignored" */
3083: if (tlb_tag_match_0_31 & TME_BIT(4)) {
3084: return;
3085: }
3086: }
3087:
3088: /* if this is a demap page, we must match the VA part of a tag. if
3089: this is a demap context, we must ignore the VA part of a tag: */
3090: tlb_tag_mask32 = 0 - (tme_uint32_t) ((tlb_tag_match_0_31 & TME_BIT(6)) == 0);
3091:
3092: /* finish the tag to match: */
3093: tlb_tag_match_0_31 &= ~TME_STP103X_CONTEXT_MAX;
3094: tlb_tag_match_0_31 += context;
3095:
3096: /* if this is ASI_DMMU_DEMAP, start at the first entry of the DTLB,
3097: otherwise start at the first entry of the ITLB: */
3098: tlb_part_i
3099: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)
3100: ? TME_STP103X_TLB_PART_0_DMMU
3101: : TME_STP103X_TLB_PART_0_IMMU);
3102:
3103: /* loop over the TLB entries: */
3104: do {
3105:
3106: /* if bits 32..63 of the tag match: */
3107: tlb_tag_xor_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 1) ^ tlb_tag_match_32_63;
3108: if ((tlb_tag_xor_32_63 & tlb_tag_mask32) == 0) {
3109:
3110: /* load bits 0..31 of the data: */
3111: tlb_data_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0);
3112:
3113: /* exclusive-OR bits 0..31 of the tag with bits 0..31 of the tag
3114: to match: */
3115: tlb_tag_xor_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 0) ^ tlb_tag_match_0_31;
3116:
3117: /* if this is a global entry: */
3118: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_G(tlb_data_0_31)) {
3119:
3120: /* assume that this is a demap page, which can match a global
3121: page, and force a match of the context field of the tag: */
3122: tlb_tag_xor_0_31 &= ~TME_STP103X_CONTEXT_MAX;
3123:
3124: /* if this a demap context: */
3125: if (tlb_tag_mask32 == 0) {
3126:
3127: /* a demap context never matches a global page. force a
3128: mismatch of the context field of the tag: */
3129: tlb_tag_xor_0_31 += 1;
3130: }
3131: }
3132:
3133: /* load bits 32..63 of the data: */
3134: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1);
3135:
3136: /* if this TLB entry is valid: */
3137: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)) {
3138:
3139: /* get the size of this mapping: */
3140: size
3141: = (TME_STP103X_PAGE_SIZE_8KB
3142: << (3 * TME_FIELD_MASK_EXTRACTU(tlb_data_32_63,
3143: TME_STP103X_TLB_DATA_SIZE_MASK(tlb_data_32_63))));
3144:
3145: /* if bits 0..31 of the tag match: */
3146: if ((tlb_tag_xor_0_31
3147: & (((0 - size)
3148: & tlb_tag_mask32)
3149: + TME_STP103X_CONTEXT_MAX)) == 0) {
3150:
3151: /* invalidate this TLB entry: */
3152: _tme_stp103x_tlb_invalidate(ic, tlb_part_i);
3153: }
3154: }
3155: }
3156:
3157: tlb_part_i += 2;
3158: } while (tlb_part_i % (2 * TME_STP103X_TLB_SIZE));
3159: }
3160:
3161: /* the ASI handler for ASI_ECACHE_W and ASI_ECACHE_R: */
3162: static void
3163: _tme_stp103x_ls_asi_ecache(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3164: {
3165: tme_uint64_t address;
3166: tme_uint32_t address_0_31;
3167: tme_uint32_t address_32_63;
3168: unsigned int ecache_what;
3169: int is_write;
3170:
3171: /* get the address: */
3172: address = ls->tme_sparc_ls_address64;
3173: address_32_63 = (address >> 32);
3174: address_0_31 = address;
3175:
3176: /* see if this is an E-Cache data access, or a tag/state/parity
3177: access: */
3178: ecache_what = (address_32_63 >> (39 - 32)) & 0x3;
3179:
3180: /* truncate the E-Cache address to the cache size, and 64-bit align
3181: it: */
3182: address_0_31 &= (TME_STP103X_ECACHE_SIZE - sizeof(tme_uint64_t));
3183:
3184: /* see if this is ASI_ECACHE_W or ASI_ECACHE_R: */
3185: is_write = (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x76);
3186: assert (is_write || TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x7e);
3187:
3188: /* check the access: */
3189: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo
3190: & (is_write
3191: ? TME_SPARC_LSINFO_OP_ST
3192: : TME_SPARC_LSINFO_OP_LD)) == 0
3193: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
3194: || (ecache_what != 0x1
3195: && ecache_what != 0x2))) {
3196: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3197: }
3198:
3199: /* if the access has faulted: */
3200: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
3201: return;
3202: }
3203:
3204: /* if this is a data access: */
3205: if (ecache_what == 0x1) {
3206:
3207: /* the PROM probes the size of the E-Cache by writing power-of-two
3208: sizes to those same addresses in the E-Cache, from high sizes
3209: to low sizes. then it reads address zero to see the last size
3210: that got truncated to address zero. we don't emulate the
3211: E-Cache, but we do emulate a single line at address zero, so we
3212: appear to the probe as having the smallest E-Cache size
3213: (512KB): */
3214: #if TME_STP103X_ECACHE_SIZE != (512 * 1024)
3215: #error "TME_STP103X_ECACHE_SIZE changed"
3216: #endif
3217: if (address_0_31 == 0) {
3218: if (is_write) {
3219: TME_STP103X(ic)->tme_stp103x_ecache_data_probe = *ls->tme_sparc_ls_rd64;
3220: }
3221: else {
3222: *ls->tme_sparc_ls_rd64 = TME_STP103X(ic)->tme_stp103x_ecache_data_probe;
3223: }
3224: }
3225: else {
3226: abort();
3227: }
3228: }
3229:
3230: /* otherwise, this must be a tag access: */
3231: else {
3232: assert (ecache_what == 0x2);
3233:
3234: /* the PROM initializes all tags in the E-Cache. we don't emulate
3235: the E-Cache, but we do support initializing any tag: */
3236: if (is_write
3237: && ((TME_STP103X(ic)->tme_stp103x_ecache_tag_data % (2 << 28))
3238: == (0x00000 /* a EC_tag of zero */
3239: + (0x0 << 22) /* an EC_state of Invalid */
3240: + (0xf << 25)))) { /* correct odd EC_parity */
3241: /* nothing to do */
3242: }
3243: else {
3244: abort();
3245: }
3246: }
3247:
3248: /* complete the load or store: */
3249: if (!is_write) {
3250: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
3251: }
3252: ls->tme_sparc_ls_size = 0;
3253: }
3254:
3255: /* the ASI handler for ASI_DCACHE_DATA and ASI_DCACHE_TAG: */
3256: static void
3257: _tme_stp103x_ls_asi_dcache(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3258: {
3259: tme_uint32_t address_0_31;
3260: tme_uint64_t value;
3261:
3262: /* get the address: */
3263: address_0_31 = ls->tme_sparc_ls_address64 % (16 * 1024);
3264:
3265: /* check the access: */
3266: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo
3267: & (TME_SPARC_LSINFO_OP_ST
3268: | TME_SPARC_LSINFO_OP_LD)) == 0
3269: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t))) {
3270: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3271: }
3272:
3273: /* if the access has faulted: */
3274: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
3275: return;
3276: }
3277:
3278: /* if this is a store: */
3279: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) {
3280:
3281: /* get the value being stored: */
3282: value = *ls->tme_sparc_ls_rd64;
3283:
3284: /* we support writing zeros to tags - the PROM does this to
3285: initialize all tags in the D-cache, and kernels do this to
3286: flush the D-cache: */
3287: if (__tme_predict_true(TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == TME_STP103X_ASI_DCACHE_TAG
3288: && value == 0)) {
3289:
3290: /* complete this store: */
3291: ls->tme_sparc_ls_size = 0;
3292: return;
3293: }
3294:
3295: /* soon after POR, the PROM writes 0xdeadbeef to address zero in
3296: both ASI_DCACHE_DATA and ASI_DCACHE_TAG. we support these
3297: writes: */
3298: if (address_0_31 == 0
3299: && value == 0xdeadbeef) {
3300:
3301: /* complete this store: */
3302: ls->tme_sparc_ls_size = 0;
3303: return;
3304: }
3305: }
3306:
3307: /* otherwise, this is a load: */
3308: else {
3309:
3310: /* we support reading tags, which always read as zeroes. kernels
3311: may read tags when flushing the D-cache: */
3312: if (__tme_predict_true(TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == TME_STP103X_ASI_DCACHE_TAG)) {
3313:
3314: /* complete this load: */
3315: *ls->tme_sparc_ls_rd64 = 0;
3316: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
3317: ls->tme_sparc_ls_size = 0;
3318: return;
3319: }
3320: }
3321:
3322: /* XXX FIXME WRITEME: */
3323: abort();
3324: }
3325:
3326: /* the ASI handler for ASI_ICACHE_INSTR, ASI_ICACHE_TAG,
3327: ASI_ICACHE_PRE_DECODE, ASI_ICACHE_NEXT_FIELD: */
3328: static void
3329: _tme_stp103x_ls_asi_icache(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3330: {
3331: tme_uint32_t address_0_31;
3332: tme_uint64_t value;
3333:
3334: /* get the address: */
3335: address_0_31 = ls->tme_sparc_ls_address64 % (16 * 1024);
3336:
3337: /* check the access: */
3338: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo
3339: & (TME_SPARC_LSINFO_OP_ST
3340: | TME_SPARC_LSINFO_OP_LD)) == 0
3341: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t))) {
3342: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3343: }
3344:
3345: /* if the access has faulted: */
3346: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
3347: return;
3348: }
3349:
3350: /* if this is a store: */
3351: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) {
3352:
3353: /* get the value being stored: */
3354: value = *ls->tme_sparc_ls_rd64;
3355:
3356: /* soon after POR, the PROM writes 0xdeadbeef to address zero in
3357: both ASI_ICACHE_DATA and ASI_ICACHE_TAG. later, the PROM
3358: initializes all tags in the I-cache. we don't emulate the
3359: I-cache, but we do support these writes: */
3360: if ((address_0_31 == 0
3361: && value == 0xdeadbeef)
3362: || (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x67
3363: && value == 0)) {
3364:
3365: /* complete this store: */
3366: ls->tme_sparc_ls_size = 0;
3367: return;
3368: }
3369: }
3370:
3371: /* XXX FIXME WRITEME: */
3372: abort();
3373: }
3374:
3375: /* this swaps double-precision floating-point register values in the
3376: memory buffer for the block transfer ASIs: */
3377: static void
3378: _tme_stp103x_block_buffer_bswap(struct tme_sparc *ic,
3379: const struct tme_sparc_ls *ls)
3380: {
3381: const struct tme_sparc_tlb *tlb;
3382: tme_uint32_t endian_little;
3383: signed int value_i;
3384:
3385: /* get the TLB entry: */
3386: tlb = ls->tme_sparc_ls_tlb;
3387:
3388: /* get the byte order of the memory: */
3389: endian_little = ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE;
3390:
3391: /* if the host and memory byte orders don't match: */
3392: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
3393: ? !endian_little
3394: : TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
3395: ? endian_little
3396: : TRUE) {
3397:
3398: /* if the host is big- or little-endian: */
3399: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
3400: || TME_ENDIAN_NATIVE == TME_ENDIAN_BIG) {
3401:
3402: /* swap the values in the memory buffer: */
3403: value_i = TME_STP103X_BLOCK_FPREGS_DOUBLE - 1;
3404: do {
3405: ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[value_i]
3406: = tme_bswap_u64(ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[value_i]);
3407: } while (--value_i >= 0);
3408: }
3409:
3410: /* otherwise, the host has an unusual byte order: */
3411: else {
3412: abort();
3413: }
3414: }
3415: }
3416:
3417: /* the cycle handler for loads with ASI_BLOCK_AS_IF_USER*,
3418: ASI_BLK_COMMIT*, and ASI_BLOCK*: */
3419: static void
3420: _tme_stp103x_ls_cycle_block_ld(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3421: {
3422: unsigned int fpreg_number;
3423:
3424: /* do a load cycle: */
3425: tme_sparc64_load(ic, ls);
3426:
3427: /* if this was not the last cycle, return now: */
3428: if (ls->tme_sparc_ls_size != 0) {
3429: return;
3430: }
3431:
3432: /* swap the memory buffer: */
3433: _tme_stp103x_block_buffer_bswap(ic, ls);
3434:
3435: /* save the block load for verification: */
3436: tme_sparc_recode_verify_mem_block(ic, TME_SPARC_RECODE_VERIFY_MEM_LOAD);
3437:
3438: /* decode rd: */
3439: fpreg_number
3440: = tme_sparc_fpu_fpreg_decode(ic,
3441: TME_FIELD_MASK_EXTRACTU(ic->_tme_sparc_insn,
3442: TME_SPARC_FORMAT3_MASK_RD),
3443: TME_IEEE754_FPREG_FORMAT_DOUBLE);
3444:
3445: /* loop over a block's worth of double-precision floating-point
3446: registers: */
3447: do {
3448:
3449: /* make sure the floating-point register is double-precision: */
3450: tme_sparc_fpu_fpreg_format(ic,
3451: fpreg_number,
3452: (TME_IEEE754_FPREG_FORMAT_DOUBLE
3453: | TME_IEEE754_FPREG_FORMAT_BUILTIN));
3454:
3455: /* copy the double-precision value from the memory buffer: */
3456: ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
3457: ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint
3458: = (ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s
3459: [(fpreg_number / 2)
3460: % TME_STP103X_BLOCK_FPREGS_DOUBLE]);
3461:
3462: /* NB: tme_sparc64_lddfa() will eventually use
3463: TME_SPARC_FPU_DIRTY() to mark the right half of the FPU
3464: dirty: */
3465:
3466: /* log the value loaded, except for the first, which will be
3467: logged eventually by tme_sparc64_ldxa(): */
3468: if (((fpreg_number / 2) % TME_STP103X_BLOCK_FPREGS_DOUBLE) != 0) {
3469: tme_sparc_log(ic, 1000, TME_OK,
3470: (TME_SPARC_LOG_HANDLE(ic),
3471: _("ldxa 0x%02x:0x%016" TME_PRIx64 ": 0x%016" TME_PRIx64),
3472: TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask),
3473: ((ls->tme_sparc_ls_address64
3474: - TME_STP103X_BLOCK_SIZE)
3475: + (sizeof(tme_uint64_t)
3476: * ((fpreg_number / 2)
3477: % TME_STP103X_BLOCK_FPREGS_DOUBLE))),
3478: ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint));
3479: }
3480:
3481: } while ((fpreg_number += 2)
3482: % (TME_STP103X_BLOCK_FPREGS_DOUBLE * 2));
3483:
3484: /* complete this load for the lddfa function: */
3485: assert (ls->tme_sparc_ls_rd64
3486: == &ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX));
3487: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX)
3488: = ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[0];
3489: }
3490:
3491: /* the cycle handler for stores with ASI_BLOCK_AS_IF_USER*,
3492: ASI_BLK_COMMIT*, and ASI_BLOCK*: */
3493: static void
3494: _tme_stp103x_ls_cycle_block_st(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3495: {
3496: unsigned int fpreg_number;
3497: union tme_value64 value_double_buffer;
3498:
3499: /* this must be the first cycle: */
3500: assert (ls->tme_sparc_ls_buffer_offset == 0);
3501:
3502: /* decode rd: */
3503: fpreg_number
3504: = tme_sparc_fpu_fpreg_decode(ic,
3505: TME_FIELD_MASK_EXTRACTU(ic->_tme_sparc_insn,
3506: TME_SPARC_FORMAT3_MASK_RD),
3507: TME_IEEE754_FPREG_FORMAT_DOUBLE);
3508:
3509: /* loop over a block's worth of double-precision floating-point
3510: registers: */
3511: do {
3512:
3513: /* make sure the floating-point register is double-precision: */
3514: tme_sparc_fpu_fpreg_format(ic,
3515: fpreg_number,
3516: (TME_IEEE754_FPREG_FORMAT_DOUBLE
3517: | TME_IEEE754_FPREG_FORMAT_BUILTIN));
3518:
3519: /* copy the double-precision value into the memory buffer: */
3520: ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s
3521: [(fpreg_number / 2)
3522: % TME_STP103X_BLOCK_FPREGS_DOUBLE]
3523: = (tme_ieee754_double_value_get(&ic->tme_sparc_fpu_fpregs[fpreg_number],
3524: &value_double_buffer)
3525: ->tme_value64_uint);
3526:
3527: /* log the value stored, except for the first, which was already
3528: logged by tme_sparc64_stxa(): */
3529: if (((fpreg_number / 2) % TME_STP103X_BLOCK_FPREGS_DOUBLE) != 0) {
3530: tme_sparc_log(ic, 1000, TME_OK,
3531: (TME_SPARC_LOG_HANDLE(ic),
3532: _("stxa 0x%02x:0x%016" TME_PRIx64 ": 0x%016" TME_PRIx64),
3533: TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask),
3534: (ls->tme_sparc_ls_address64
3535: + (sizeof(tme_uint64_t)
3536: * ((fpreg_number / 2)
3537: % TME_STP103X_BLOCK_FPREGS_DOUBLE))),
3538: ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s
3539: [(fpreg_number / 2)
3540: % TME_STP103X_BLOCK_FPREGS_DOUBLE]));
3541: }
3542:
3543: } while ((fpreg_number += 2)
3544: % (TME_STP103X_BLOCK_FPREGS_DOUBLE * 2));
3545:
3546: /* save the block store for verification: */
3547: tme_sparc_recode_verify_mem_block(ic, TME_SPARC_RECODE_VERIFY_MEM_STORE);
3548:
3549: /* swap the memory buffer: */
3550: _tme_stp103x_block_buffer_bswap(ic, ls);
3551:
3552: /* do any leftover store cycles directly: */
3553: ls->tme_sparc_ls_cycle = tme_sparc64_store;
3554:
3555: /* do a store cycle: */
3556: tme_sparc64_store(ic, ls);
3557: }
3558:
3559: /* the ASI handler for ASI_BLOCK_AS_IF_USER*, ASI_BLK_COMMIT*, and
3560: ASI_BLOCK*: */
3561: static void
3562: _tme_stp103x_ls_asi_block(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3563: {
3564: tme_uint32_t insn;
3565:
3566: /* NB: tme_sparc64_lddfa() or tme_sparc64_stdfa() has already done
3567: an TME_SPARC_INSN_FPU: */
3568:
3569: /* we need to do the complete transfer: */
3570: /* NB: even if this is an stdfa, the TME_SPARC_LSINFO_LD_COMPLETED
3571: won't cause any problems: */
3572: assert (sizeof(ic->tme_sparc_memory_buffer) >= TME_STP103X_BLOCK_SIZE);
3573: ls->tme_sparc_ls_size = TME_STP103X_BLOCK_SIZE;
3574: ls->tme_sparc_ls_buffer_offset = 0;
3575: ls->tme_sparc_ls_lsinfo
3576: |= (TME_SPARC_LSINFO_SLOW_CYCLES
3577: | TME_SPARC_LSINFO_LD_COMPLETED);
3578:
3579: /* an instruction other than lddfa or stdfa, or an lddfa with an
3580: ASI_BLK_COMMIT*, or with an rd that isn't a multiple of 16 is
3581: illegal: */
3582: insn = ic->_tme_sparc_insn;
3583: /* NB: we flip the stdfa op3 bits, and check that the whole op3
3584: field becomes zero (for ASI_BLK_COMMIT*) or that all op3 bits
3585: except the one that differentiates stdfa from lddfa become zero
3586: (for all other ASIs): */
3587: /* NB: we only need to test bits 1, 2, and 3 in the double-precision
3588: encoded rd, since bit 0 is the encoded bit 5: */
3589: insn ^= (0x37 << 19);
3590: if (__tme_predict_false((insn
3591: & ((((TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)
3592: ^ TME_STP103X_ASI_BLK_COMMIT)
3593: & ~TME_SPARC64_ASI_FLAG_SECONDARY)
3594: ? (0x3b << 19)
3595: : (0x3f << 19))
3596: | TME_BIT(3 + 25)
3597: | TME_BIT(2 + 25)
3598: | TME_BIT(1 + 25))))) {
3599: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3600: }
3601:
3602: /* the address must be block-aligned: */
3603: else if (__tme_predict_false(((tme_uint32_t) ls->tme_sparc_ls_address64)
3604: % TME_STP103X_BLOCK_SIZE)) {
3605: ls->tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;
3606: }
3607:
3608: /* set the cycle function: */
3609: /* NB: we flipped the stdfa op3 bits in insn above, so bit two of
3610: op3 is now set for an lddfa, and clear for an stdfa: */
3611: ls->tme_sparc_ls_cycle
3612: = ((insn & (4 << 19))
3613: ? _tme_stp103x_ls_cycle_block_ld
3614: : _tme_stp103x_ls_cycle_block_st);
3615: }
3616:
3617: /* the ASI handler for the UDB registers: */
3618: static void
3619: _tme_stp103x_ls_asi_udb(struct tme_sparc *ic, struct tme_sparc_ls *ls)
3620: {
3621: tme_uint32_t address_0_31;
3622: int is_write;
3623: tme_uint16_t value16;
3624: unsigned int intr_reg;
3625:
3626: /* get the address: */
3627: address_0_31 = ls->tme_sparc_ls_address64;
3628:
3629: /* see if this is should be a write or a read: */
3630: is_write = (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x77);
3631: assert (is_write || TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x7f);
3632:
3633: /* check the access type and size, and that the address fits in 32
3634: bits: */
3635: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo
3636: & (is_write
3637: ? TME_SPARC_LSINFO_OP_ST
3638: : TME_SPARC_LSINFO_OP_LD)) == 0
3639: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t)
3640: || ls->tme_sparc_ls_address64 > (tme_uint32_t) (0 - (tme_uint32_t) 1))) {
3641: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3642: }
3643:
3644: /* if the access hasn't faulted yet: */
3645: if (__tme_predict_true(ls->tme_sparc_ls_faults == TME_SPARC_LS_FAULT_NONE)) {
3646:
3647: /* dispatch on the address: */
3648: switch (address_0_31) {
3649:
3650: /* the low and high UDB error registers: */
3651: case 0x00:
3652: case 0x18:
3653: /* we never generate ECC errors, so these registers
3654: always read as zero, and writes are ignored: */
3655: if (!is_write) {
3656: *ls->tme_sparc_ls_rd64 = 0;
3657: }
3658: break;
3659:
3660: /* the low and high UDB control registers: */
3661: case 0x20:
3662: case 0x38:
3663: if (is_write) {
3664: value16 = *ls->tme_sparc_ls_rd64;
3665: if (value16 & TME_BIT(8)) { /* F_MODE */
3666: abort();
3667: }
3668: TME_STP103X(ic)->tme_stp103x_udb_control[(address_0_31 & 8) == 0] = value16;
3669: }
3670: else {
3671: *ls->tme_sparc_ls_rd64
3672: = ((0x00 << 9) /* UDB version number */
3673: + (TME_STP103X(ic)->tme_stp103x_udb_control[(address_0_31 & 8) == 0]
3674: % (2 << 8))); /* F_MODE, FCBV */
3675: }
3676: break;
3677:
3678: /* the UDB transmit and receive interrupt vector data: */
3679: case 0x40:
3680: case 0x50:
3681: case 0x60:
3682: intr_reg = (address_0_31 - 0x40) / sizeof(tme_uint64_t);
3683: if (is_write) {
3684: TME_STP103X(ic)->tme_stp103x_udb_intr_transmit[intr_reg]
3685: = *ls->tme_sparc_ls_rd64;
3686: }
3687: else {
3688: *ls->tme_sparc_ls_rd64
3689: = TME_STP103X(ic)->tme_stp103x_udb_intr_receive[intr_reg];
3690: }
3691: break;
3692:
3693: default:
3694:
3695: /* if this isn't a write of the UDB interrupt vector dispatch: */
3696: if (!is_write
3697: || (address_0_31 & ~((2 << 18) - (1 << 14))) != 0x70) {
3698:
3699: /* this is an illegal access: */
3700: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL;
3701: break;
3702: }
3703:
3704: abort();
3705: break;
3706: }
3707: }
3708:
3709: /* if the access has faulted: */
3710: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {
3711: return;
3712: }
3713:
3714: /* complete the load or store: */
3715: if (!is_write) {
3716: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED;
3717: }
3718: ls->tme_sparc_ls_size = 0;
3719: }
3720:
3721: /* the ASI handlers: */
3722: static const _tme_sparc_ls_asi_handler _tme_stp103x_ls_asi_handlers[] = {
3723: NULL,
3724: _tme_stp103x_ls_asi_mmu,
3725: _tme_stp103x_ls_asi_tsb_ptr,
3726: _tme_stp103x_ls_asi_quad,
3727: _tme_stp103x_ls_asi_tlb_data_in,
3728: _tme_stp103x_ls_asi_mmu_demap,
3729: _tme_stp103x_ls_asi_slow,
3730: _tme_stp103x_ls_asi_phys,
3731: _tme_stp103x_ls_asi_dcache,
3732: _tme_stp103x_ls_asi_ecache,
3733: _tme_stp103x_ls_asi_tlb_data_access,
3734: _tme_stp103x_ls_asi_tlb_tag_read,
3735: _tme_stp103x_ls_asi_icache,
3736: _tme_stp103x_ls_asi_block,
3737: _tme_stp103x_ls_asi_udb,
3738: tme_sparc64_vis_ls_asi_pst,
3739: tme_sparc64_vis_ls_asi_fl,
3740: };
3741:
3742: /* the tick compare register thread: */
3743: static void
3744: _tme_stp103x_tick_compare_th(void *_ic)
3745: {
3746: struct tme_sparc *ic;
3747: struct timeval now;
3748: unsigned long now_tv_sec;
3749: unsigned long now_tv_usec;
3750: unsigned long tick_compare_time_tv_sec;
3751: unsigned long tick_compare_time_tv_usec;
3752: struct timeval sleep;
3753:
3754: /* recover our data structure: */
3755: ic = (struct tme_sparc *) _ic;
3756:
3757: /* lock the external mutex: */
3758: tme_mutex_lock(&ic->tme_sparc_external_mutex);
3759:
3760: /* loop forever: */
3761: for (;;) {
3762:
3763: /* get the current time: */
3764: tme_gettimeofday(&now);
3765:
3766: /* if the current time is greater than or equal to the tick compare time: */
3767: now_tv_sec = now.tv_sec;
3768: now_tv_usec = now.tv_usec;
3769: tick_compare_time_tv_sec = TME_STP103X(ic)->tme_stp103x_tick_compare_time.tv_sec;
3770: tick_compare_time_tv_usec = TME_STP103X(ic)->tme_stp103x_tick_compare_time.tv_usec;
3771: if (now_tv_sec > tick_compare_time_tv_sec
3772: || (now_tv_sec == tick_compare_time_tv_sec
3773: && now_tv_usec >= tick_compare_time_tv_usec)) {
3774:
3775: /* set the tick interrupt atomic flag: */
3776: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, TRUE);
3777:
3778: /* set the external flag: */
3779: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, TRUE);
3780:
3781: /* notify any thread waiting on the external condition: */
3782: tme_cond_notify(&ic->tme_sparc_external_cond, FALSE);
3783:
3784: /* wait on the tick compare condition: */
3785: tme_cond_wait_yield(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond,
3786: &ic->tme_sparc_external_mutex);
3787: }
3788:
3789: /* otherwise, the current time is less than the tick compare
3790: time: */
3791: else {
3792:
3793: /* make the sleep time, but don't sleep more than a minute at a time: */
3794: if (tick_compare_time_tv_usec < now_tv_usec) {
3795: tick_compare_time_tv_sec--;
3796: tick_compare_time_tv_usec += 1000000;
3797: }
3798: sleep.tv_sec = TME_MIN(tick_compare_time_tv_sec - now_tv_sec, 60);
3799: sleep.tv_usec = tick_compare_time_tv_usec - now_tv_usec;
3800:
3801: /* sleep on the tick compare condition: */
3802: tme_cond_sleep_yield(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond,
3803: &ic->tme_sparc_external_mutex,
3804: &sleep);
3805: }
3806: }
3807: /* NOTREACHED */
3808: }
3809:
3810: /* this checks for external signals: */
3811: /* NB: this may do a preinstruction trap: */
3812: static void
3813: _tme_stp103x_external_check(struct tme_sparc *ic,
3814: int flags)
3815: {
3816:
3817: /* if RESET_L has been negated since the last check: */
3818: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_reset_negated))) {
3819:
3820: /* clear the XIR and RESET_L asserted flags, then clear the
3821: RESET_L negated flag: */
3822: tme_memory_atomic_write_flag(&ic->tme_sparc_external_halt_asserted, FALSE);
3823: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_asserted, FALSE);
3824: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
3825: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_negated, FALSE);
3826:
3827: /* start POR trap processing: */
3828: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) {
3829: tme_mutex_unlock(&ic->tme_sparc_external_mutex);
3830: }
3831: tme_sparc64_trap_preinstruction(ic, TME_SPARC64_TRAP_power_on_reset);
3832: }
3833:
3834: /* if RESET_L is asserted: */
3835: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_reset_asserted))) {
3836:
3837: /* halt: */
3838: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) {
3839: tme_mutex_unlock(&ic->tme_sparc_external_mutex);
3840: }
3841: ic->_tme_sparc_mode = TME_SPARC_MODE_HALT;
3842: tme_sparc_redispatch(ic);
3843: }
3844:
3845: /* if XIR has been asserted since the last check: */
3846: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_halt_asserted))) {
3847:
3848: /* clear the XIR asserted flag: */
3849: tme_memory_atomic_write_flag(&ic->tme_sparc_external_halt_asserted, FALSE);
3850:
3851: /* start XIR trap processing: */
3852: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) {
3853: tme_mutex_unlock(&ic->tme_sparc_external_mutex);
3854: }
3855: tme_sparc64_trap_preinstruction(ic, TME_SPARC64_TRAP_externally_initiated_reset);
3856: }
3857:
3858: /* do an interrupt check: */
3859: _tme_stp103x_interrupt_check(ic, flags);
3860: }
3861:
3862: /* the bus cycle function: */
3863: static void
3864: _tme_stp103x_ls_bus_cycle(const struct tme_sparc *ic,
3865: struct tme_sparc_ls *ls)
3866: {
3867: tme_uint32_t asi_mask;
3868: unsigned int cycle_size_log2;
3869:
3870: /* NB: we provide the old sparc32 bus routing information when
3871: emulating stp103x noncached read and write transactions on the
3872: UPA bus.
3873:
3874: this is a bad hack that we do only to save duplicating that same
3875: information in the stp2220 emulation, which needs it for cycles
3876: that pass through it onto its SBus.
3877:
3878: since the old sparc32 bus routing information doesn't have
3879: anything to do with how the UPA bus works, we assume that all TLB
3880: fills for noncacheable accesses that don't allow fast transfers
3881: will either end up at another CPU (which will know about the
3882: disagreement and ignore the bus routing information), or end up
3883: at an I/O bridge, which will either rely on the sparc32 bus
3884: routing information (stp2220), or replace it with its own bus
3885: routing information (stp2222), before running the cycle on its
3886: I/O bus. if the cycle is for an I/O bridge's internal registers,
3887: like a CPU it will know about the disagreement and ignore the bus
3888: routing information.
3889:
3890: we assume that all TLB fills for cacheable accesses target main
3891: memory, which we assume will tolerate any bus routing: */
3892:
3893: /* get the ASI mask for this TLB entry: */
3894: asi_mask = ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask;
3895:
3896: /* if the TLB entry is for noncacheable accesses: */
3897: if (asi_mask & TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE) {
3898:
3899: /* call the default sparc32 bus cycle function: */
3900: tme_sparc32_ls_bus_cycle(ic, ls);
3901: return;
3902: }
3903:
3904: /* provide a simple bus routing for cacheable accesses: */
3905: cycle_size_log2 = TME_BUS8_LOG2;
3906: for (; (1 << cycle_size_log2) != ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size; ) {
3907: assert (cycle_size_log2 < TME_BUS128_LOG2);
3908: cycle_size_log2++;
3909: }
3910: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS128_LOG2);
3911: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_lane_routing
3912: = (&(_tme_stp103x_bus_router_cacheable
3913: [cycle_size_log2]
3914: [0])
3915: - TME_BUS_ROUTER_INDEX(TME_BUS128_LOG2, TME_BUS128_LOG2, 0));
3916: }
3917:
3918: /* this fills a TLB for the CPU: */
3919: static int
3920: _tme_stp103x_tlb_fill(struct tme_bus_connection *conn_bus,
3921: struct tme_bus_tlb *tlb,
3922: tme_bus_addr_t address,
3923: unsigned int cycle_type)
3924: {
3925: abort();
3926: }
3927:
3928: /* this handles an interrupt: */
3929: static void
3930: _tme_stp103x_interrupt(struct tme_upa_bus_connection *conn_upa,
3931: tme_uint32_t master_mid,
3932: const tme_uint64_t *data,
3933: struct tme_completion *completion)
3934: {
3935: struct tme_sparc *ic;
3936:
3937: /* recover our data structure: */
3938: ic = conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
3939:
3940: /* if the receive interrupt vector data is already busy: */
3941: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy)) {
3942:
3943: /* NACK this interrupt: */
3944: completion->tme_completion_error = EAGAIN;
3945: tme_memory_barrier(completion, sizeof(*completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
3946: }
3947:
3948: /* otherwise, the incoming data isn't busy: */
3949: else {
3950:
3951: /* save the interrupt data and ACK this interrupt: */
3952: /* NB: the interrupt data is an array of eight big-endian
3953: tme_uint64_t, since an interrupt packet is four 128-bit values.
3954: the even indices are the least-significant halves of the
3955: 128-bit values: */
3956: TME_STP103X(ic)->tme_stp103x_intr_receive_mid = master_mid;
3957: TME_STP103X(ic)->tme_stp103x_udb_intr_receive[0] = tme_betoh_u64(data[2 * 0]);
3958: TME_STP103X(ic)->tme_stp103x_udb_intr_receive[1] = tme_betoh_u64(data[2 * 1]);
3959: TME_STP103X(ic)->tme_stp103x_udb_intr_receive[2] = tme_betoh_u64(data[2 * 2]);
3960: completion->tme_completion_error = TME_OK;
3961: tme_memory_barrier(0, 0, TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
3962: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy, 1);
3963: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
3964: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, 1);
3965: tme_cond_notify(&ic->tme_sparc_external_cond, FALSE);
3966: }
3967:
3968: /* validate this completion: */
3969: tme_completion_validate(completion);
3970: }
3971:
3972: /* this returns the version of an FPU for an stp103x: */
3973: static tme_uint32_t
3974: _tme_sparc_fpu_ver_stp103x(struct tme_sparc *ic, const char *fpu_name, char **_output)
3975: {
3976: tme_uint32_t ver;
3977:
3978: /* if we're returning a usage: */
3979: if (_output != NULL) {
3980: tme_output_append_error(_output,
3981: "builtin");
3982: return (TME_SPARC_FSR_VER_missing);
3983: }
3984:
3985: if (TME_ARG_IS(fpu_name, "builtin")) {
3986: /* XXX FIXME - the stp1030 has an FSR_version of zero. we assume
3987: that the stp1031 does too: */
3988: ver = 0;
3989: }
3990: else {
3991: return (TME_SPARC_FSR_VER_missing);
3992: }
3993:
3994: ic->tme_sparc_fpu_flags
3995: = (!TME_SPARC_FPU_FLAG_OK_REG_MISALIGNED);
3996: return (ver * _TME_FIELD_MASK_FACTOR(TME_SPARC_FSR_VER));
3997: }
3998:
3999: /* this creates and returns a new stp103x: */
4000: static int
4001: _tme_stp103x_new(struct tme_element *element,
4002: const char * const *args,
4003: const void *extra,
4004: char **_output,
4005: int is_1030)
4006: {
4007: struct tme_sparc *ic;
4008: tme_uint32_t psr;
4009: tme_uint32_t asi;
4010: tme_uint32_t asi_mask_flags;
4011: void (*handler) _TME_P((struct tme_sparc *, struct tme_sparc_ls *));
4012: tme_uint32_t handler_i;
4013:
4014: /* allocate the stp103x structure: */
4015: ic = &tme_new0(struct tme_stp103x, 1)->tme_stp103x_sparc;
4016: ic->tme_sparc_element = element;
4017:
4018: /* set the type: */
4019: is_1030 = !!is_1030;
4020: TME_STP103X(ic)->tme_stp103x_is_1030 = is_1030;
4021: if (TME_STP103X_IS_1030(ic) != is_1030) {
4022: tme_free(ic);
4023: return (ENXIO);
4024: }
4025:
4026: /* initialize the synchronization parts of the structure: */
4027: tme_sparc_sync_init(ic);
4028:
4029: /* initialize the stp103x private structure: */
4030: TME_STP103X(ic)->tme_stp103x_tcr = TME_STP103X_TCR_INT_DIS;
4031: tme_cond_init(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond);
4032: tme_misc_timeval_never(&TME_STP103X(ic)->tme_stp103x_tick_compare_time);
4033: tme_memory_atomic_init_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, FALSE);
4034: tme_memory_atomic_init_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy, FALSE);
4035:
4036: /* start the tick compare thread: */
4037: tme_thread_create((tme_thread_t) _tme_stp103x_tick_compare_th, ic);
4038:
4039: /* fill in the stp103x-specific parts of the structure: */
4040: psr = 0;
4041: TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_IMPL, 1);
4042: TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_VER, 1);
4043: ic->tme_sparc32_ireg_psr = psr;
4044: ic->tme_sparc_version = TME_SPARC_VERSION(ic);
4045: ic->tme_sparc_nwindows = TME_SPARC_NWINDOWS(ic);
4046: ic->tme_sparc_memory_flags = TME_SPARC_MEMORY_FLAGS(ic);
4047: ic->tme_sparc64_maxtl = TME_STP103X_MAXTL;
4048: ic->tme_sparc_tlb_page_size_log2 = 13; /* log2(TME_STP103X_PAGE_SIZE_8KB) */
4049: ic->tme_sparc_memory_context_max = TME_STP103X_CONTEXT_MAX;
4050: ic->_tme_sparc64_execute_opmap = _TME_SPARC_EXECUTE_OPMAP;
4051: ic->tme_sparc64_rstvaddr = 0 - (tme_uint64_t) (1 << 28);
4052: ic->tme_sparc64_ireg_va_hole_start = TME_STP103X_VA_HOLE_START;
4053: ic->tme_sparc64_ireg_ver
4054: = ((0x0017 * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MANUF))
4055: + (0x0010 * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_IMPL))
4056: + (0x40 * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MASK))
4057: + (ic->tme_sparc64_maxtl * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MAXTL))
4058: + ((TME_SPARC_NWINDOWS(ic) - 1) * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MAXWIN)));
4059: ic->tme_sparc64_ireg_winstates_mask
4060: = (TME_SPARC64_WINSTATES_CWP(TME_SPARC_NWINDOWS(ic) - 1)
4061: + TME_SPARC64_WINSTATES_CANRESTORE(TME_SPARC_NWINDOWS(ic) - 1)
4062: + TME_SPARC64_WINSTATES_CANSAVE(TME_SPARC_NWINDOWS(ic) - 1)
4063: + TME_SPARC64_WINSTATES_OTHERWIN(TME_SPARC_NWINDOWS(ic) - 1));
4064: ic->_tme_sparc_execute = _tme_sparc_execute_stp103x;
4065: ic->_tme_sparc_fpu_ver = _tme_sparc_fpu_ver_stp103x;
4066: ic->_tme_sparc_external_check = _tme_stp103x_external_check;
4067: ic->_tme_sparc_tlb_fill = _tme_stp103x_tlb_fill;
4068: ic->_tme_sparc_upa_interrupt = _tme_stp103x_interrupt;
4069: ic->_tme_sparc_ls_asi_misaligned = tme_sparc64_vis_ls_asi_misaligned;
4070: ic->_tme_sparc_ls_asi_handlers = _tme_stp103x_ls_asi_handlers;
4071: ic->_tme_sparc_ls_address_map = _tme_stp103x_ls_address_map;
4072: ic->_tme_sparc_ls_bus_cycle = _tme_stp103x_ls_bus_cycle;
4073: ic->_tme_sparc_ls_bus_fault = tme_sparc_ls_bus_fault;
4074: ic->_tme_sparc_ls_trap = _tme_stp103x_ls_trap;
4075: ic->_tme_sparc64_update_pstate = _tme_stp103x_update_pstate;
4076: ic->tme_sparc_vis_ls_fault_illegal = TME_STP103X_LS_FAULT_ILLEGAL;
4077: ic->tme_sparc_timing_loop_cycles_each = 1;
4078: #ifdef _TME_SPARC_RECODE_VERIFY
4079: /* NB: struct tme_stp103x has been deliberately laid out to have all
4080: of the verifiable contents first, followed by everything that
4081: isn't verifiable (basically, anything that is accessed using
4082: loads and stores, since replay only simulates them): */
4083: ic->tme_sparc_recode_verify_ic_size
4084: = (((char *) &((struct tme_stp103x *) 0)->tme_stp103x_upa_config)
4085: - (char *) ((struct tme_stp103x *) 0));
4086: ic->tme_sparc_recode_verify_ic_size_total = sizeof(struct tme_stp103x);
4087: #endif /* _TME_SPARC_RECODE_VERIFY */
4088:
4089: /* initialize the ASIs: */
4090: for (asi = 0; asi < TME_ARRAY_ELS(ic->tme_sparc_asis); asi++) {
4091:
4092: /* dispatch on this ASI: */
4093: switch (asi) {
4094:
4095: /* ASI_PHYS_USE_EC*, ASI_PHYS_BYPASS_EC_WITH_EBIT*: */
4096: case (0x14):
4097: case (0x14
4098: + TME_SPARC64_ASI_FLAG_LITTLE):
4099: case (0x15):
4100: case (0x15
4101: + TME_SPARC64_ASI_FLAG_LITTLE):
4102: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4103: handler = _tme_stp103x_ls_asi_phys;
4104: break;
4105:
4106: /* ASI_NUCLEUS_QUAD_LDD*: */
4107: case (0x24):
4108: case (0x24
4109: + TME_SPARC64_ASI_FLAG_LITTLE):
4110: asi_mask_flags
4111: = (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS
4112: + (asi
4113: & TME_SPARC64_ASI_FLAG_LITTLE));
4114: handler = _tme_stp103x_ls_asi_quad;
4115: break;
4116:
4117: /* ASI_DCACHE_DATA, ASI_DCACHE_TAG: */
4118: case TME_STP103X_ASI_DCACHE_DATA:
4119: case TME_STP103X_ASI_DCACHE_TAG:
4120: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4121: handler = _tme_stp103x_ls_asi_dcache;
4122: break;
4123:
4124: /* ASI_ECACHE_W, ASI_ECACHE_R: */
4125: case 0x76:
4126: case 0x7e:
4127: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4128: handler = _tme_stp103x_ls_asi_ecache;
4129: break;
4130:
4131: /* ASI_IMMU, ASI_DMMU: */
4132: case TME_STP103X_ASI_IMMU:
4133: case TME_STP103X_ASI_DMMU:
4134: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4135: handler = _tme_stp103x_ls_asi_mmu;
4136: break;
4137:
4138: /* ASI_IMMU_TSB_8KB_PTR_REG, ASI_IMMU_TSB_64KB_PTR_REG,
4139: ASI_DMMU_TSB_8KB_PTR_REG, ASI_DMMU_TSB_64KB_PTR_REG,
4140: ASI_DMMU_TSB_DIRECT_PTR_REG: */
4141: case (TME_STP103X_ASI_IMMU
4142: + TME_STP103X_ASI_FLAG_TSB_8KB_PTR):
4143: case (TME_STP103X_ASI_IMMU
4144: + TME_STP103X_ASI_FLAG_TSB_64KB_PTR):
4145: case (TME_STP103X_ASI_DMMU
4146: + TME_STP103X_ASI_FLAG_TSB_8KB_PTR):
4147: case (TME_STP103X_ASI_DMMU
4148: + TME_STP103X_ASI_FLAG_TSB_64KB_PTR):
4149: case (TME_STP103X_ASI_DMMU
4150: + (TME_STP103X_ASI_FLAG_TSB_8KB_PTR
4151: | TME_STP103X_ASI_FLAG_TSB_64KB_PTR)):
4152: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4153: handler = _tme_stp103x_ls_asi_tsb_ptr;
4154: break;
4155:
4156: /* ASI_ITLB_DATA_IN_REG, ASI_DTLB_DATA_IN_REG: */
4157: case (TME_STP103X_ASI_IMMU + 0x4):
4158: case (TME_STP103X_ASI_DMMU + 0x4):
4159: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4160: handler = _tme_stp103x_ls_asi_tlb_data_in;
4161: break;
4162:
4163: /* ASI_ITLB_DATA_ACCESS_REG, ASI_DTLB_DATA_ACCESS_REG: */
4164: case (TME_STP103X_ASI_IMMU + 0x5):
4165: case (TME_STP103X_ASI_DMMU + 0x5):
4166: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4167: handler = _tme_stp103x_ls_asi_tlb_data_access;
4168: break;
4169:
4170: /* ASI_ITLB_TAG_READ_REG, ASI_DTLB_TAG_READ_REG: */
4171: case (TME_STP103X_ASI_IMMU + 0x6):
4172: case (TME_STP103X_ASI_DMMU + 0x6):
4173: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4174: handler = _tme_stp103x_ls_asi_tlb_tag_read;
4175: break;
4176:
4177: /* ASI_IMMU_DEMAP, ASI_DMMU_DEMAP: */
4178: case (TME_STP103X_ASI_IMMU + 0x7):
4179: case (TME_STP103X_ASI_DMMU + 0x7):
4180: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4181: handler = _tme_stp103x_ls_asi_mmu_demap;
4182: break;
4183:
4184: /* ASI_ICACHE_INSTR: */
4185: /* ASI_ICACHE_TAG: */
4186: /* ASI_ICACHE_PRE_DECODE: */
4187: /* ASI_ICACHE_NEXT_FIELD: */
4188: case 0x66:
4189: case 0x67:
4190: case 0x6e:
4191: case 0x6f:
4192: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4193: handler = _tme_stp103x_ls_asi_icache;
4194: break;
4195:
4196: /* ASI_BLOCK_AS_IF_USER*: */
4197: case (0x70):
4198: case (0x70
4199: + TME_SPARC64_ASI_FLAG_SECONDARY):
4200: case (0x70
4201: + TME_SPARC64_ASI_FLAG_LITTLE):
4202: case (0x70
4203: + TME_SPARC64_ASI_FLAG_SECONDARY
4204: + TME_SPARC64_ASI_FLAG_LITTLE):
4205: asi_mask_flags
4206: = (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER
4207: + (asi
4208: & (TME_SPARC64_ASI_FLAG_SECONDARY
4209: | TME_SPARC64_ASI_FLAG_LITTLE)));
4210: handler = _tme_stp103x_ls_asi_block;
4211: break;
4212:
4213: /* ASI_UDB*: */
4214: case 0x77:
4215: case 0x7f:
4216: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4217: handler = _tme_stp103x_ls_asi_udb;
4218: break;
4219:
4220: /* the mandatory v9 ASIs: */
4221: #if TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS != 4
4222: #error "TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS changed"
4223: #endif
4224: case (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS):
4225: case (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS
4226: + TME_SPARC64_ASI_FLAG_LITTLE):
4227: #if TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER != 0x10
4228: #error "TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER changed"
4229: #endif
4230: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER):
4231: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER
4232: + TME_SPARC64_ASI_FLAG_SECONDARY):
4233: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER
4234: + TME_SPARC64_ASI_FLAG_LITTLE):
4235: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER
4236: + TME_SPARC64_ASI_FLAG_SECONDARY
4237: + TME_SPARC64_ASI_FLAG_LITTLE):
4238: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED):
4239: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4240: + TME_SPARC64_ASI_FLAG_SECONDARY):
4241: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4242: + TME_SPARC64_ASI_FLAG_NO_FAULT):
4243: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4244: + TME_SPARC64_ASI_FLAG_SECONDARY
4245: + TME_SPARC64_ASI_FLAG_NO_FAULT):
4246: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4247: + TME_SPARC64_ASI_FLAG_LITTLE):
4248: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4249: + TME_SPARC64_ASI_FLAG_SECONDARY
4250: + TME_SPARC64_ASI_FLAG_LITTLE):
4251: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4252: + TME_SPARC64_ASI_FLAG_NO_FAULT
4253: + TME_SPARC64_ASI_FLAG_LITTLE):
4254: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED
4255: + TME_SPARC64_ASI_FLAG_SECONDARY
4256: + TME_SPARC64_ASI_FLAG_NO_FAULT
4257: + TME_SPARC64_ASI_FLAG_LITTLE):
4258:
4259: /* the mandatory v9 ASIs are all normal and have no handlers: */
4260: asi_mask_flags = asi;
4261: handler = NULL;
4262: assert ((asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_SPECIAL) == 0);
4263: assert (_tme_stp103x_ls_asi_handlers[0] == handler);
4264: break;
4265:
4266: /* ASI_PST*: */
4267: case (TME_SPARC_VIS_ASI_PST8):
4268: case (TME_SPARC_VIS_ASI_PST8
4269: + TME_SPARC64_ASI_FLAG_SECONDARY):
4270: case (TME_SPARC_VIS_ASI_PST8
4271: + TME_SPARC64_ASI_FLAG_LITTLE):
4272: case (TME_SPARC_VIS_ASI_PST8
4273: + TME_SPARC64_ASI_FLAG_SECONDARY
4274: + TME_SPARC64_ASI_FLAG_LITTLE):
4275: case (TME_SPARC_VIS_ASI_PST16):
4276: case (TME_SPARC_VIS_ASI_PST16
4277: + TME_SPARC64_ASI_FLAG_SECONDARY):
4278: case (TME_SPARC_VIS_ASI_PST16
4279: + TME_SPARC64_ASI_FLAG_LITTLE):
4280: case (TME_SPARC_VIS_ASI_PST16
4281: + TME_SPARC64_ASI_FLAG_SECONDARY
4282: + TME_SPARC64_ASI_FLAG_LITTLE):
4283: case (TME_SPARC_VIS_ASI_PST32):
4284: case (TME_SPARC_VIS_ASI_PST32
4285: + TME_SPARC64_ASI_FLAG_SECONDARY):
4286: case (TME_SPARC_VIS_ASI_PST32
4287: + TME_SPARC64_ASI_FLAG_LITTLE):
4288: case (TME_SPARC_VIS_ASI_PST32
4289: + TME_SPARC64_ASI_FLAG_SECONDARY
4290: + TME_SPARC64_ASI_FLAG_LITTLE):
4291: asi_mask_flags
4292: = (asi
4293: & (TME_SPARC64_ASI_FLAG_SECONDARY
4294: | TME_SPARC64_ASI_FLAG_LITTLE));
4295: handler = tme_sparc64_vis_ls_asi_pst;
4296: break;
4297:
4298: /* ASI_FL*: */
4299: case (TME_SPARC_VIS_ASI_FL8):
4300: case (TME_SPARC_VIS_ASI_FL8
4301: + TME_SPARC64_ASI_FLAG_SECONDARY):
4302: case (TME_SPARC_VIS_ASI_FL8
4303: + TME_SPARC64_ASI_FLAG_LITTLE):
4304: case (TME_SPARC_VIS_ASI_FL8
4305: + TME_SPARC64_ASI_FLAG_SECONDARY
4306: + TME_SPARC64_ASI_FLAG_LITTLE):
4307: case (TME_SPARC_VIS_ASI_FL16):
4308: case (TME_SPARC_VIS_ASI_FL16
4309: + TME_SPARC64_ASI_FLAG_SECONDARY):
4310: case (TME_SPARC_VIS_ASI_FL16
4311: + TME_SPARC64_ASI_FLAG_LITTLE):
4312: case (TME_SPARC_VIS_ASI_FL16
4313: + TME_SPARC64_ASI_FLAG_SECONDARY
4314: + TME_SPARC64_ASI_FLAG_LITTLE):
4315: asi_mask_flags
4316: = (asi
4317: & (TME_SPARC64_ASI_FLAG_SECONDARY
4318: | TME_SPARC64_ASI_FLAG_LITTLE));
4319: handler = tme_sparc64_vis_ls_asi_fl;
4320: break;
4321:
4322: /* ASI_BLK_COMMIT*: */
4323: case (TME_STP103X_ASI_BLK_COMMIT):
4324: case (TME_STP103X_ASI_BLK_COMMIT
4325: + TME_SPARC64_ASI_FLAG_SECONDARY):
4326: asi_mask_flags
4327: = (asi
4328: & (TME_SPARC64_ASI_FLAG_SECONDARY));
4329: handler = _tme_stp103x_ls_asi_block;
4330: break;
4331:
4332: /* ASI_BLOCK*: */
4333: case (0xf0):
4334: case (0xf0
4335: + TME_SPARC64_ASI_FLAG_SECONDARY):
4336: case (0xf0
4337: + TME_SPARC64_ASI_FLAG_LITTLE):
4338: case (0xf0
4339: + TME_SPARC64_ASI_FLAG_SECONDARY
4340: + TME_SPARC64_ASI_FLAG_LITTLE):
4341: asi_mask_flags
4342: = (asi
4343: & (TME_SPARC64_ASI_FLAG_SECONDARY
4344: | TME_SPARC64_ASI_FLAG_LITTLE));
4345: handler = _tme_stp103x_ls_asi_block;
4346: break;
4347:
4348: case TME_STP103X_ASI_LSU_CONTROL_REG:
4349: case TME_STP103X_ASI_INTR_DISPATCH_STATUS:
4350: case TME_STP103X_ASI_INTR_RECEIVE:
4351: case TME_STP103X_ASI_UPA_CONFIG_REG:
4352: case TME_STP103X_ASI_ESTATE_ERROR_EN_REG:
4353: case TME_STP103X_ASI_AFSR:
4354: case TME_STP103X_ASI_AFAR:
4355: case TME_STP103X_ASI_ECACHE_TAG_DATA:
4356: default:
4357: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL;
4358: handler = _tme_stp103x_ls_asi_slow;
4359: break;
4360: }
4361:
4362: /* get any ASI handler index: */
4363: for (handler_i = 0; _tme_stp103x_ls_asi_handlers[handler_i] != handler; handler_i++) {
4364: assert (handler_i < (TME_ARRAY_ELS(_tme_stp103x_ls_asi_handlers) - 1));
4365: }
4366:
4367: /* initialize this ASI: */
4368: ic->tme_sparc_asis[asi].tme_sparc_asi_mask_flags = asi_mask_flags;
4369: ic->tme_sparc_asis[asi].tme_sparc_asi_handler = handler_i;
4370: }
4371:
4372: /* call the common sparc new function: */
4373: return (tme_sparc_new(ic, args, extra, _output));
4374: }
4375:
4376: /* this creates and returns a new stp1030: */
4377: TME_ELEMENT_X_NEW_DECL(tme_ic_,sparc,stp1030) {
4378: return (_tme_stp103x_new(element, args, extra, _output, TRUE));
4379: }
4380:
4381: #undef TME_SPARC_VERSION
4382: #define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic)
4383: #undef TME_SPARC_NWINDOWS
4384: #define TME_SPARC_NWINDOWS(ic) _TME_SPARC_NWINDOWS(ic)
4385: #undef _TME_SPARC_EXECUTE_NAME
4386: #undef _TME_SPARC_EXECUTE_OPMAP
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.