1 /* $Id: sparc.h,v 1.3 2010/06/05 19:37:56 fredette Exp $ */
2 
3 /* tme/ic/sparc.h - public header file for SPARC emulation */
4 
5 /*
6  * Copyright (c) 2005 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 #ifndef _TME_IC_SPARC_H
37 #define _TME_IC_SPARC_H
38 
39 #include <tme/common.h>
40 _TME_RCSID("$Id: sparc.h,v 1.3 2010/06/05 19:37:56 fredette Exp $");
41 
42 /* includes: */
43 #include <tme/element.h>
44 #include <tme/generic/bus.h>
45 
46 /* macros: */
47 
48 /* the sparc32 address spaces: */
49 #define TME_SPARC32_ASI_UI			(0x08)
50 #define TME_SPARC32_ASI_SI			(0x09)
51 #define TME_SPARC32_ASI_UD			(0x0A)
52 #define TME_SPARC32_ASI_SD			(0x0B)
53 
54 /* common sparc64 address space identifier flags: */
55 #define TME_SPARC64_ASI_FLAG_SECONDARY		(0x01)
56 #define TME_SPARC64_ASI_FLAG_NO_FAULT		(0x02)
57 #define TME_SPARC64_ASI_FLAG_LITTLE		(0x08)
58 #define TME_SPARC64_ASI_FLAG_UNRESTRICTED	(0x80)
59 
60 /* the sparc address space masks: */
61 /* bits 24 through 31 must be zero - except when
62    TME_SPARC_ASI_MASK_FLAG_UNDEF is set, which is what makes an ASI
63    mask undefined.
64 
65    bits 16 through 23 are the original ASI.
66 
67    ASIs are divided into two categories: special and normal.  an
68    address space mask from a special ASI never matches an address
69    space mask from a normal ASI, and vice-versa.
70 
71    if bit 15 is set, the ASI is special.  an address space mask from a
72    special ASI never matches an address space mask from a different
73    ASI.
74 
75    if bit 15 is clear, the ASI is normal.  an address space mask from
76    a normal ASI may match address space masks from different normal
77    ASIs.
78 
79    each of the bits eight through 14 identifies an address
80    translation.  an address translation is usually the combination of
81    an address space with privilege.
82 
83    an address space mask generated by a memory instruction has exactly
84    one of these bits set, since the instruction's ASI+privilege
85    combination can translate addresses in only one way.  an address
86    space mask generated from an MMU mapping has at least one of these
87    bits set, for the ASI+privilege from the instruction that caused
88    the mapping lookup.  if the same mapping is also valid for other
89    ASI+privilege combinations that can be added to the address space
90    mask, the bits for their address translations can also be set.
91 
92    the meanings of the address translation bits must be consistent
93    across all normal ASIs, since these bits are the only ones that are
94    significant when address masks from two normal ASIs are compared.
95    since an address mask from a special ASI can never match an address
96    mask from a different ASI, the address translation bits for a
97    special ASI are effectively unique to that ASI, and so there are
98    only two of them - privileged and nonprivileged.
99 
100    bits zero through seven are available for ASI-specific use, and
101    they never affect ASI mask comparison: */
102 #define TME_SPARC_ASI_MASK_FLAG_SPECIAL				TME_BIT(15)
103 #define TME_SPARC_ASI_MASK_FLAG_UNDEF				TME_BIT(24)
104 #define TME_SPARC_ASI_MASK_RAW(asi)				\
105   (((tme_uint32_t) (asi))					\
106    * (TME_SPARC_ASI_MASK_FLAG_SPECIAL * 2))
107 #define TME_SPARC_ASI_MASK(asi, xlat)				\
108   (TME_SPARC_ASI_MASK_RAW(asi)					\
109    + TME_BIT(8 + (xlat)))
110 #define TME_SPARC_ASI_MASK_SPECIAL(asi, priv)			\
111   (TME_SPARC_ASI_MASK(asi, (priv) != 0)				\
112    + TME_SPARC_ASI_MASK_FLAG_SPECIAL)
113 #define TME_SPARC_ASI_MASK_WHICH(asi_mask)			\
114   ((asi_mask)							\
115    / (TME_SPARC_ASI_MASK_FLAG_SPECIAL * 2))
116 #define TME_SPARC_ASI_MASK_FLAGS_AVAIL				\
117   (TME_SPARC_ASI_MASK(0, 0) - 1)
118 
119 /* this evaluates to nonzero iff the two ASI masks overlap: */
120 /* NB: asi_mask0 must be a single ASI mask from a memory instruction
121    (in other words, it must have exactly one address translation bit
122    set), and it may also have TME_SPARC_ASI_MASK_FLAG_UNDEF set.  .
123    if asi_mask1 is a binary-OR of multiple ASI masks, either all of
124    them must be for normal ASIs, or all of them must be for the same
125    special ASI.  asi_mask1 must not have TME_SPARC_ASI_MASK_FLAG_UNDEF
126    set: */
127 #define TME_SPARC_ASI_MASK_OVERLAP(asi_mask0, asi_mask1)	\
128   ((((asi_mask0)						\
129      ^ (asi_mask1))						\
130     & ((((tme_uint32_t)						\
131 	 (tme_int32_t)						\
132 	 (tme_int16_t)						\
133 	 (asi_mask0))						\
134 	| TME_SPARC_ASI_MASK_FLAG_SPECIAL			\
135 	| TME_SPARC_ASI_MASK_FLAG_UNDEF)			\
136        & (0 - TME_SPARC_ASI_MASK(0, 0)))) == 0)
137 
138 /* this evaluates to nonzero iff this TLB entry allows access to an
139    ASI, given by mask: */
140 #define TME_SPARC_TLB_ASI_MASK_OK(tlb, asi_mask)		\
141   TME_SPARC_ASI_MASK_OVERLAP(asi_mask, (tlb)->tme_sparc_tlb_asi_mask)
142 
143 /* sparc32 has four required address translations, corresponding to
144    the four required ASIs: supervisor data, supervisor instruction,
145    user data, user instruction.  all normal ASIs must use one of these
146    address translations, and so you must specify one of the required
147    ASIs to build an address space mask for a normal ASI: */
148 /* NB: this assumes that the four required ASIs are dense, and start
149    with TME_SPARC32_ASI_UI: */
150 #define TME_SPARC32_ASI_MASK(asi, asi_required)			\
151   TME_SPARC_ASI_MASK(asi, (asi_required) - TME_SPARC32_ASI_UI)
152 
153 /* sparc32 address space mask flags: */
154 #define TME_SPARC32_ASI_MASK_FLAG_SPECIAL		(0x01)
155 
156 /* for convenience we also provide the address space masks for the
157    sparc32 required ASIs here: */
158 #define TME_SPARC32_ASI_MASK_UI		TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_UI, TME_SPARC32_ASI_UI)
159 #define TME_SPARC32_ASI_MASK_SI		TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_SI, TME_SPARC32_ASI_SI)
160 #define TME_SPARC32_ASI_MASK_UD		TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_UD, TME_SPARC32_ASI_UD)
161 #define TME_SPARC32_ASI_MASK_SD		TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_SD, TME_SPARC32_ASI_SD)
162 
163 /* sparc64 address space masks use the common sparc64 address space
164    identifier flags for address space mask flags, plus these other
165    address space mask flags.  these other flags can't conflict with
166    the common flags (which are essentially architected), and the same
167    flag value (common or other) may have different names and meanings
168    in an ASI mask from an instruction and one from a TLB entry: */
169 #define TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS		(0x04)
170 #define TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER	(0x10)
171 #define TME_SPARC64_ASI_MASK_FLAG_SPECIAL		(0x20)
172 #define TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS	(0x40)
173 #define TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE	(TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS)
174 
175 /* sparc64 has five architected address translations: privileged
176    primary, privileged secondary, nonprivileged primary, nonprivileged
177    secondary, and nucleus.  all of these are required, except for
178    nucleus.  all normal ASIs must use one of these translations.
179 
180    however, note that sparc64 address translation, by itself, doesn't
181    depend on privilege - the architected mapping from ASI to context
182    doesn't consider it.  only address protection depends on privilege.
183    (this isn't necessarily true on sparc32 - a sparc32 without a
184    reference MMU could translate addresses completely differently for
185    its different architected ASIs.)
186 
187    this means that a sparc64 normal ASI's address translation check
188    will be done completely by the context comparison, leaving only
189    privilege to be represented as generic sparc address space mask
190    address translations: */
191 #define TME_SPARC64_ASI_MASK_USER			TME_SPARC_ASI_MASK(0 /* asi */, 0)
192 #define TME_SPARC64_ASI_MASK_PRIV			TME_SPARC_ASI_MASK(0 /* asi */, 1)
193 #define TME_SPARC64_ASI_MASK(asi, asi_mask_flags)		\
194   ((asi_mask_flags)						\
195    + TME_SPARC_ASI_MASK(asi,					\
196                         (((asi_mask_flags)			\
197 			  & TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) == 0)))
198 
199 /* for convenience, we provide macros to build address space masks for
200    the architected ASIs given ASI mask flags here: */
201 #define TME_SPARC64_ASI_MASK_NUCLEUS(asi_flag_little)			\
202   TME_SPARC64_ASI_MASK(0x04 + (asi_flag_little),			\
203 		       (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS + (asi_flag_little)))
204 #define TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(asi_flags)		\
205   TME_SPARC64_ASI_MASK(TME_SPARC64_ASI_FLAG_UNRESTRICTED		\
206 		       + ((asi_flags)					\
207 			  & (TME_SPARC64_ASI_FLAG_SECONDARY		\
208 			     + TME_SPARC64_ASI_FLAG_NO_FAULT		\
209 			     + TME_SPARC64_ASI_FLAG_LITTLE)),		\
210 		       asi_flags)
211 
212 /* these busy and unbusy a TLB entry: */
213 #define tme_sparc_tlb_busy(tlb)					\
214   tme_bus_tlb_busy(&(tlb)->tme_sparc_tlb_bus_tlb)
215 #define tme_sparc_tlb_unbusy(tlb)				\
216   tme_bus_tlb_unbusy(&(tlb)->tme_sparc_tlb_bus_tlb)
217 
218 /* the minimum and maximum IPL levels: */
219 #define TME_SPARC_IPL_NONE	(0)
220 #define TME_SPARC_IPL_MIN	(1)
221 #define TME_SPARC_IPL_MAX	(15)
222 #define TME_SPARC_IPL_NMI	(15)
223 
224 /* this indexes an sparc bus router array for an sparc with a port size
225    of 8 * (2 ^ siz_lg2) bits: */
226 #define TME_SPARC_BUS_ROUTER_INDEX(siz_lg2, cycle_size, address)\
227 (((								\
228    /* by the maximum cycle size: */				\
229    ((cycle_size) - 1)						\
230 								\
231    /* by the address alignment: */				\
232    << siz_lg2)							\
233   + ((address) & ((1 << (siz_lg2)) - 1)))			\
234 								\
235  /* factor in the size of the generic bus router array: */	\
236  * TME_BUS_ROUTER_SIZE(siz_lg2))
237 
238 /* this gives the number of entries that must be in a generic bus
239    router array for a device with a bus size of 8 * (2 ^ siz_lg2)
240    bits: */
241 #define TME_SPARC_BUS_ROUTER_SIZE(siz_lg2)			\
242   TME_SPARC_BUS_ROUTER_INDEX(siz_lg2, (1 << (siz_lg2)) + 1, 0)
243 
244 /* structures: */
245 
246 /* an sparc TLB entry: */
247 struct tme_sparc_tlb {
248 
249   /* the generic bus TLB associated with this TLB entry: */
250   struct tme_bus_tlb tme_sparc_tlb_bus_tlb;
251 #define tme_sparc_tlb_addr_first tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_first
252 #define tme_sparc_tlb_addr_last tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_last
253 #define tme_sparc_tlb_bus_rwlock tme_sparc_tlb_bus_tlb.tme_bus_tlb_rwlock
254 #define tme_sparc_tlb_cycles_ok tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycles_ok
255 #define tme_sparc_tlb_addr_offset tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_offset
256 #define tme_sparc_tlb_addr_shift tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_shift
257 #define tme_sparc_tlb_emulator_off_read tme_sparc_tlb_bus_tlb.tme_bus_tlb_emulator_off_read
258 #define tme_sparc_tlb_emulator_off_write tme_sparc_tlb_bus_tlb.tme_bus_tlb_emulator_off_write
259 
260   /* any link for this TLB entry: */
261   tme_uint32_t tme_sparc_tlb_link;
262 
263   /* the context for this TLB entry: */
264   tme_bus_context_t tme_sparc_tlb_context;
265 
266   /* an ASI mask: */
267   tme_uint32_t tme_sparc_tlb_asi_mask;
268 };
269 
270 /* an sparc bus connection: */
271 struct tme_sparc_bus_connection {
272 
273   /* a generic bus connection: */
274   struct tme_bus_connection tme_sparc_bus_connection;
275 
276   /* the sparc interrupt function: */
277   int (*tme_sparc_bus_interrupt) _TME_P((struct tme_sparc_bus_connection *, unsigned int));
278 
279   /* the sparc TLB entry filler: */
280   int (*tme_sparc_bus_tlb_fill) _TME_P((struct tme_sparc_bus_connection *, struct tme_sparc_tlb *,
281 					tme_uint32_t, tme_bus_addr_t, unsigned int));
282 
283   /* the sparc FPU strict-compliance enabler: */
284   void (*tme_sparc_bus_fpu_strict) _TME_P((struct tme_sparc_bus_connection *, unsigned int));
285 };
286 
287 /* globals: */
288 extern _tme_const tme_bus_lane_t tme_sparc_router_32[];
289 
290 #endif /* !_TME_IC_SPARC_H */
291