Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sunsparc / include / ss_common.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: ss_common.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#ifndef _SS_COMMON_H
29#define _SS_COMMON_H
30
31#pragma ident "@(#)ss_common.h 1.54 07/03/07 SMI"
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37#include "basics.h"
38#include "fatal.h"
39#include "allocate.h"
40#include "simcore.h"
41#include "config.h"
42#include "options.h"
43#include "strutil.h"
44#include "fileutil.h"
45#include "lexer.h"
46#include "parser.h"
47#include "strings.h"
48#include "strutil.h"
49#include "createthr.h"
50#include "tsparcv9.h"
51#include "sparcv9regs.h"
52#include "tsparcv9internal.h"
53#include "execinstns.h" /* autogenerated core defined instructions */
54#include "sparcv9decode.h"
55#include "sparcv9instns.h" /* autogenerated sparcv9 instruction definitions */
56#include "xicache.h"
57#include "xdcache.h"
58#include "dumpinfo.h"
59#include "device.h"
60#include "callback.h"
61#include "bswap.h"
62
63
64#if 1 /* { */
65#define RW_lock_t volatile int64_t
66#define RW_rdlock(_l) ss_rdlock(_l)
67#define RW_wrlock(_l) ss_wrlock(_l)
68#define RW_unlock(_l) ss_unlock(_l)
69#define RW_lock_init(_l, _a) do { *(_l) = 0; } while (0)
70extern void ss_rdlock(RW_lock_t *);
71extern void ss_wrlock(RW_lock_t *);
72extern void ss_unlock(RW_lock_t *);
73#elif HAS_POSIX_RW_LOCK /* } { */
74#define RW_lock_t pthread_rwlock_t
75#define RW_rdlock(_l) pthread_rwlock_rdlock(_l)
76#define RW_wrlock(_l) pthread_rwlock_wrlock(_l)
77#define RW_unlock(_l) pthread_rwlock_unlock(_l)
78#define RW_lock_init(_l, _a) pthread_rwlock_init(_l, _a)
79#else /* } { */
80#define RW_lock_t pthread_mutex_t
81#define RW_rdlock(_l) pthread_mutex_lock(_l)
82#define RW_wrlock(_l) pthread_mutex_lock(_l)
83#define RW_unlock(_l) pthread_mutex_unlock(_l)
84#define RW_lock_init(_l, _a) pthread_mutex_init(_l, _a)
85#endif /* } */
86
87 /*
88 * SunSPARC / this file specific definitions
89 */
90
91#ifndef NDEBUG /* { */
92#define DBG_CMP 0x100000000000LL
93#define DBGCMP(_s) do { if (debug_bits & DBG_CMP) { _s; } } while (0)
94#define DBG_TM 0x80000000000LL
95#define DBGTM(_s) do { if (debug_bits & DBG_TM) { _s; } } while (0)
96#define DBG_SCRATCH 0x10000000000LL
97#define DBGSCRATCH(_s) do { if (debug_bits & DBG_SCRATCH) { _s; } } while (0)
98#define DBG_DAE 0x8000000000LL
99#define DBGDAE(_s) do { if (debug_bits & DBG_DAE) { _s; } } while (0)
100#define DBG_LE 0x2000000LL
101#define DBGLE(_s) do { if (debug_bits & DBG_LE) { _s } } while (0) /* debug little endian */
102#define DBG_ALIGN 0x4000000LL
103#define DBGALIGN(_s) do { if (debug_bits & DBG_ALIGN) { _s } } while (0)
104#define DBG_EPM 0x80LL
105#define DBGEPM(_s) do { if (debug_bits & DBG_EPM) { _s } } while (0)
106#define DBG_HCALL 0x8000LL
107#define DBGHC(s) do { if (debug_bits & DBG_HCALL) { s } } while (0) /* debug hcalls */
108#define DBG_PIC 0x10000LL
109#define DBGPIC(s) do { if (debug_bits & DBG_PIC) { s } } while (0) /* debug Perf Cntrs */
110#define DBG_SOFTINT 0x10000000LL
111#define DBGSOFTINT(s) do { if (debug_bits & DBG_SOFTINT) { s } } while (0)
112#define DBG_TICK 0x20000000LL
113#define DBGTICK(s) do { if (debug_bits & DBG_TICK) { s } } while (0)
114#define DBG_TICK_READ 0x4000000000LL
115#define DBGTICKREAD(s) do { if (debug_bits & DBG_TICK_READ) { s } } while (0)
116#define DBG_EXCEPT 0x20000LL
117#define DBGE(s) do { if (debug_bits & DBG_EXCEPT) { s } } while (0) /* debug exceptions */
118#define DBG_HPSTATE 0x40000LL
119#define DBGHPS(s) do { if (debug_bits & DBG_HPSTATE) { s } } while (0) /* debug hpstate changes */
120#define DBG_MMU 0x80000LL
121#define DBGMMU(s) do { if (debug_bits & DBG_MMU) { s } } while (0) /* debug mmu */
122#define DBG_MISS 0x100000LL
123#define DBGMISS(s) do { if (debug_bits & DBG_MISS) { s } } while (0) /* debug mmu miss */
124#define DBG_MC 0x200000LL
125#define DBGMC(s) do { if (debug_bits & DBG_MC) { s } } while (0) /* debug dram controllers */
126#define DBG_TS 0x400000LL
127#define DBGTSTACK(s) do { if (debug_bits & DBG_TS) { s } } while (0) /* debug TSTATE etc. */
128#define DBG_ERR 0x800000LL
129#define DBGERR(s) do { if (debug_bits & DBG_ERR) { s } } while (0) /* debug error injection */
130#define DBG_SSI 0x1000000LL
131#define DBGSSI(s) do { if (debug_bits & DBG_SSI) { s } } while (0) /* debug SSI interrupts */
132#define DBG_MONDO 0x8000000LL
133#define DBGMONDO(s) do { if (debug_bits & DBG_MONDO) { s } } while (0) /* debug mondo interrupts */
134#define DBG_ERR_TRAP 0x200000000LL
135#define DBGERRTRAP(s) do { if (debug_bits & DBG_ERR_TRAP) { s } } while (0) /* debug error trap generation */
136#define DBG_MUL_NODE 0x4000LL
137#define DBGMULNODE(s) do { if (debug_bits & DBG_MUL_NODE) { s } } while (0) /* debug multinode, only VF for now */
138/*
139 * debug_bits values already reserved:
140 *
141 * 0x1 DBG_BASIC
142 * 0x2 DBG_EL
143 * 0x4 DBG_EL_MIN
144 * 0x8 < not reserved >
145 * ...
146 * 0x40 < not reserved >
147 * 0x80 DBG_EPM
148 * 0x100 < not reserved >
149 * ...
150 * 0x2000 < not reserved >
151 * 0x4000 DBG_MUL_NODE
152 * 0x8000 DBG_HCALL
153 * 0x10000 DBG_PIC
154 * 0x20000 DBG_EXCEPT
155 * 0x40000 DBG_HPSTATE
156 * 0x80000 DBG_MMU
157 * 0x100000 DBG_MISS
158 * 0x200000 DBG_MC
159 * 0x400000 DBG_TS
160 * 0x800000 DBG_ERR
161 * 0x1000000 DBG_SSI
162 * 0x2000000 DBG_LE
163 * 0x4000000 DBG_ALIGN
164 * 0x8000000 DBG_MONDO
165 * 0x10000000 DBG_SOFTINT
166 * 0x20000000 DBG_TICK
167 * 0x40000000 DBG_DECODE
168 * 0x80000000 DBG_DEV
169 * 0x100000000 DBG_EXEC_LOOP
170 * 0x200000000 DBG_ERR_TRAP
171 * 0x1000000000 DBG_FSR
172 * 0x2000000000 DBG_FPRS
173 * 0x4000000000 DBG_TICK_READ
174 * 0x8000000000 DBG_DAE
175 * 0x10000000000 DBG_SCRATCH
176 * 0x20000000000 DBG_XCACHE
177 * 0x40000000000 DBG_FP
178 * 0x80000000000 DBG_TM
179 * 0x100000000000 DBG_CMP
180 */
181#else /* } { */
182#define DBGCMP(_s) do { } while (0)
183#define DBGTM(_s) do { } while (0)
184#define DBGSCRATCH(_s) do { } while (0)
185#define DBGDAE(_s) do { } while (0)
186#define DBGLE(_s) do { } while (0) /* debug little endian */
187#define DBGPIC(s) do { } while (0) /* debug Perf Cntrs */
188#define DBGSOFTINT(s) do { } while (0)
189#define DBGTICK(s) do { } while (0)
190#define DBGTICKREAD(s) do { } while (0)
191#define DBGEPM(_s) do { } while (0)
192#define DBGALIGN(_s) do { } while (0)
193#define DBGHC(s) do { } while (0) /* debug exceptions */
194#define DBGE(s) do { } while (0) /* debug exceptions */
195#define DBGHPS(s) do { } while (0) /* debug exceptions */
196#define DBGMMU(s) do { } while (0) /* debug exceptions */
197#define DBGMISS(s) do { } while (0) /* debug exceptions */
198#define DBGMC(s) do { } while (0) /* debug dram controllers */
199#define DBGERR(s) do { } while (0) /* debug error injection */
200#define DBGTSTACK(s) do { } while (0) /* debug TSTATE etc. */
201#define DBGSSI(s) do { } while (0) /* debug SSI interrupts */
202#define DBGMONDO(s) do { } while (0) /* debug mondo interrupts */
203#define DBGERRTRAP(s) do { } while (0) /* debug error trap generation */
204#define DBGMULNODE(s) do { } while (0) /* debug multinode, only VF for now */
205#endif /* } */
206
207typedef enum {
208 TFlag_Not_Poss, TFlag_Priv, TFlag_HypPriv
209} tflag_t;
210
211#define T( _name ) SS_trap_##_name, #_name /* SunSPARC standard trap naming convention */
212#define TN1( _name ) N1_trap_##_name, #_name /* Niagara1 specific trap naming convention */
213#define TN2( _name ) N2_trap_##_name, #_name /* Niagara2 standard trap naming convention */
214#define TRK( _name ) RK_trap_##_name, #_name /* Rock standard trap naming convention */
215#define X TFlag_Not_Poss /* Cant be generated by HW - SW emulated only */
216#define SW TFlag_Not_Poss /* Cant be generated by HW - SW emulated only */
217#define P TFlag_Priv
218#define H TFlag_HypPriv
219#define UH TFlag_HypPriv /* legal, but unexpected by hypervisor (supervisor error) */
220
221#define Pri(_maj, _min) (((_maj)<<16)|(_min))
222
223#define E( _name ) _name, #_name /* Error naming convention */
224#define B( _name, _i ) #_name, ((uint64_t)1 << _i) /* Error field name, bit position in CERER */
225
226/*
227 * macros used for determing the fields of sun4v TTE format
228 */
229#define SUN4V_TTED_V_BIT 63
230#define SUN4V_TTED_V(n) (uint_t)((uint64_t)n >> SUN4V_TTED_V_BIT)
231#define SUN4V_TTED_NFO(n) (uint_t)(((uint64_t)n >> 62) & 0x1)
232#define SUN4V_TTED_IE(n) (uint_t)(((uint64_t)n >> 12) & 0x1)
233#define SUN4V_TTED_E(n) (uint_t)(((uint64_t)n >> 11) & 0x1)
234#define SUN4V_TTED_CP(n) (uint_t)(((uint64_t)n >> 10) & 0x1)
235#define SUN4V_TTED_CV(n) (uint_t)(((uint64_t)n >> 9) & 0x1)
236#define SUN4V_TTED_P(n) (uint_t)(((uint64_t)n >> 8) & 0x1)
237#define SUN4V_TTED_EP(n) (uint_t)(((uint64_t)n >> 7) & 0x1)
238#define SUN4V_TTED_X(n) SUN4V_TTED_EP(n)
239#define SUN4V_TTED_W(n) (uint_t)(((uint64_t)n >> 6) & 0x1)
240#define SUN4V_TTED_PS(n) (uint_t)((uint64_t)n & MASK64(3, 0))
241#define SUN4V_TTET_VA(n) ((uint64_t)n & MASK64(41, 0))
242
243#define SUN4V_TTE_ENTRY_SIZE 16
244
245/* Use global array for this calculation */
246extern uint8_t ss_page_size_shift[];
247#define SUN4V_PAGE_SIZE_SHIFT(ps) ((uint_t)(ss_page_size_shift[(ps)]))
248
249 /*
250 * SunSPARC CPU core structures and typedefs
251 */
252
253/*
254 * Common set of strand core identification fields for use in SS_STRAND
255 * structures:
256 * core: core number
257 * vthread: thread number within the core
258 * vcore_id: the thread number within the chip
259 */
260#define SS_CORE_NUM_FIELDS \
261 uint_t core; \
262 uint_t vthread; \
263 uint64_t vcore_id;
264
265
266/* SSR => Strand Specific Registers */
267typedef enum {
268 SSR_ScratchPad0 = 0,
269 SSR_ScratchPad1,
270 SSR_ScratchPad2,
271 SSR_ScratchPad3,
272 SSR_ScratchPad4, /* hypervisor only (Niagara) */
273 SSR_ScratchPad5, /* hypervisor only (Niagara) */
274 SSR_ScratchPad6,
275 SSR_ScratchPad7,
276
277#ifdef ROCK
278 /* Hypervisor Scratchpad Registers (0x00 to 0x18) */
279 SSR_ScratchPad8,
280 SSR_ScratchPad9,
281 SSR_ScratchPad10,
282 SSR_ScratchPad11,
283#endif
284
285 SSR_Num_Regs
286} ss_strand_regs_t;
287
288typedef struct SS_TLB ss_tlb_t;
289
290typedef struct NA_QUEUE {
291 uint16_t head, tail;
292} na_queue_t;
293
294
295typedef struct SS_MMU ss_mmu_t;
296typedef struct SS_ERROR ss_error_t;
297
298 /* Numbers for the SunSPARC strand interrupt queues */
299typedef enum {
300 NA_Q_mondo = 0,
301 NA_Q_device = 1,
302 NA_Q_resumable = 2,
303 NA_Q_unresumable = 3
304} na_qnum_t;
305
306typedef struct SS_L1_CACHE {
307 RW_lock_t rwlock;
308 uint64_t * tagp;
309 uint64_t * datap;
310 uint64_t bist_ctl; /* asi 0x42 va 0x00 ASI_SPARC_BIST_CTL_REG */
311 uint64_t inst_mask; /* asi 0x42 va 0x08 ASI_INST_MASK_REG */
312 bool_t assocdis; /* asi 0x42 va 0x10 ASI_LSU_DIAG_REG */
313} ss_l1_cache_t;
314
315#define BIT(i) ((uint64_t)1<<i)
316#define BIT_TEST(_val, _bit) (((_val)>>(_bit)) & 0x1)
317
318/*
319 * Context Type Encoding defined by SunSPARC
320 *
321 * N.B. These values are used as defined in the Rock DFSR
322 * so they cannot be changed to arbitrary values other than
323 * the ones listed below.
324 */
325typedef enum {
326 ss_ctx_primary = 0,
327 ss_ctx_secondary = 1,
328 ss_ctx_nucleus = 2,
329 ss_ctx_reserved = 3
330} ss_ctx_t;
331
332
333#if defined(NIAGARA1) || defined(NIAGARA2) /* { */
334
335/* Sparc Error Address Register Fields */
336#define I_SYND(val) ((val & 0xff) << 16)
337#define I_REG_WIN(val) ((val & 0x3) << 9)
338#define I_REG_NUM(val) ((val & 0x1f) << 4)
339#define F_REG_NUM(val) ((val & 0x3f) << 4)
340#define EVEN_SYND(val) ((val & 0x7f) << 24)
341#define ODD_SYND(val) ((val & 0x7f) << 16)
342#define TLB_INDEX(val) ((val & 0x3f) << 4)
343#define MMU_PC(val) (val & 0xfffffffffff0) /* PC:47-4 Rsvd:3-0 */
344#define MMU_VA(val) (val & 0xfffffffffff0) /* VA:47-4 Rsvd:3-0 */
345#define L1_PA(val) (val & 0xfffffffff0) /* PA:39-4 Rsvd:3-0 */
346
347/* ECC Codes section in Appendix A of PRM 1.2 */
348
349#define IREG_FAKE_SYND_SINGLE 0x83 /* single bit error on data bit 0 */
350#define IREG_FAKE_SYND_DOUBLE 0x73 /* uncorrectable double bit error */
351#define FREG_FAKE_SYND_SINGLE 0x43 /* single bit error on bit 0 */
352#define FREG_FAKE_SYND_DOUBLE 0x33 /* uncorrectible double bit error */
353
354 /*
355 * Bitfield definitions for the LSU_CONTROL register
356 */
357
358#if defined(NIAGARA1) /* { */
359#define LSU_CTRL_WATCH_VM MASK64(32,25)
360#define LSU_CTRL_WATCH_VR MASK64(22,22)
361#define LSU_CTRL_WATCH_VW MASK64(21,21)
362#endif /* } */
363#if defined(NIAGARA2) /* { */
364#define LSU_CTRL_WATCH_MODE MASK64(34,33)
365#define LSU_CTRL_WATCH_BM MASK64(32,25)
366#define LSU_CTRL_WATCH_RE MASK64(24,24)
367#define LSU_CTRL_WATCH_WE MASK64(23,23)
368#define LSU_CTRL_SPEC_EN MASK64(4,4)
369#endif /* } */
370#define LSU_CTRL_DMMU_EN MASK64(3,3)
371#define LSU_CTRL_IMMU_EN MASK64(2,2)
372#define LSU_CTRL_DC_EN MASK64(1,1)
373#define LSU_CTRL_IC_EN MASK64(0,0)
374
375#if defined(NIAGARA1) /* { */
376#define LSU_CTRL_REG_MASK (LSU_CTRL_WATCH_VM | LSU_CTRL_WATCH_VR | \
377 LSU_CTRL_WATCH_VW | LSU_CTRL_DMMU_EN | \
378 LSU_CTRL_IMMU_EN | LSU_CTRL_DC_EN | \
379 LSU_CTRL_IC_EN)
380#endif /* } */
381#if defined(NIAGARA2) /* { */
382#define LSU_CTRL_REG_MASK (LSU_CTRL_WATCH_MODE | LSU_CTRL_WATCH_BM | \
383 LSU_CTRL_WATCH_RE | LSU_CTRL_WATCH_WE | \
384 LSU_CTRL_SPEC_EN | LSU_CTRL_DMMU_EN | \
385 LSU_CTRL_IMMU_EN | LSU_CTRL_DC_EN | \
386 LSU_CTRL_IC_EN)
387#endif /* } */
388
389#define LSU_CTRL_INITVAL (0LL)
390
391#endif /* } */
392
393
394
395
396 /*
397 * Functions and definitions for TLB and MMU code
398 */
399
400
401 /* FIXME:
402 * This macro is a place holder for the correct register setup
403 * that is required in order to be able to deliver a particular
404 * fault resulting from a memory reference.
405 */
406#define MEMORY_ACCESS_TRAP() do { } while (0)
407
408
409 /*
410 * SunSPARC CPU TLB structures
411 */
412
413 /*
414 * Each hash table is divided into buckets, based on pfn, context and partid
415 * The chains attached to a bucket are designed to have multiple readers and
416 * only a single writer/modifier at any one time.
417 *
418 * FIXME: However, operations like entry probling and invalidate all etc. don't
419 * use the hash ...
420 * ... I'm going to assume that TLB contention between strands is sufficiently
421 * low that we can get away with a single rw lock for the entire TLB.
422 * This should be enough to get something working - we'll fix the performance
423 * later when we get a chance to profile the running code ....
424 *
425 * Naturally, if we don't share TLBs between strand threads then there is no
426 * need for any locks.
427 *
428 * Otherwise we have to implement a fair multiple-reader, single writer locking
429 * scheme, that is hopefully fast - ish.
430 *
431 * FIXME: we use Solaris' reader/writer locks to get this working, but I suspect
432 * they are tediously slow - quick measurement indicates they take around 400 instructions
433 * to take and release an uncontested lock !! Need to profile this code and see if this is
434 * a performance bottleneck. But for now this is sufficient to get this working.
435 *
436 * NOTE: if this is very low contention, we should probably simply move to a mutex
437 * per bucket, since the performance of Solaris' mutexes is about twice that of the rwlock.
438 * Increasing the number of buckets and better hashing alg would also reduce contention.
439 *
440 */
441#ifdef ROCK /* { */
442typedef uint32_t matchcontext_t;
443#else /* } { */
444typedef uint16_t matchcontext_t;
445#endif /* } */
446#define INVALID_PFN -1LL
447#define SS_TLB_REAL_CONTEXT ((matchcontext_t)-1)
448#define SS_TLB_INVALID_CONTEXT ((matchcontext_t)-2)
449#define SS_TLB_INVALID_PARTID ((uint16_t)-1)
450
451#define SS_NUCLEUS_CONTEXT 0
452
453typedef struct TLB_ENTRY tlb_entry_t;
454
455typedef enum {
456 SS_TLB_FLAG_READ = 0x001, /* niagara doesn't have read bit */
457 SS_TLB_FLAG_WRITE = 0x002, /* writeable */
458 SS_TLB_FLAG_EXEC = 0x004, /* executable */
459 SS_TLB_FLAG_PRIV = 0x008, /* privileged */
460 SS_TLB_FLAG_CP = 0x010, /* cachable in physically-indexed cache */
461 SS_TLB_FLAG_E = 0x020, /* side-effect */
462 SS_TLB_FLAG_NFO = 0x040, /* no-fault-only */
463 SS_TLB_FLAG_IE = 0x080, /* Invert Endian */
464 SS_TLB_FLAG_V = 0x100, /* valid */
465 SS_TLB_FLAG_LOCKED = 0x200 /* locked */
466} tlb_flags_t;
467
468struct TLB_ENTRY {
469 uint64_t tag_pfn;
470 uint64_t pa_offset; /* (i.e. pa-va) */
471 uint64_t data; /* as returned by the data register read */
472 uint8_t match_shift;
473 bool_t is_real; /* true for RA to PA, false for VA to PA translation */
474 tlb_flags_t flags;
475 uint16_t tag_context; /* context value in TLB entry tag field */
476 matchcontext_t match_context; /* context used when matching entries; 0..12 bits */
477 /* -1 if this is a real translation not a virtual one */
478 /* -2 if this is not a valid translation */
479 uint16_t partid;
480 sint16_t hashidx; /* used to help find the entry in the hash for unhooking */
481 /* == -1 if the entry is on the free list */
482 tlb_entry_t * nextp;
483};
484
485 /*
486 * Niagara max page size is 256MB .. this value is used for
487 * the TLB hashing index value
488 */
489
490#define SS_MAX_PAGE_SIZE_BITS 28
491
492#if defined(NIAGARA1) || defined(NIAGARA2) /* { */
493/*
494 * Niagara VA hole
495 */
496#define SS_VA_HOLE_LB 0x0000800000000000
497#define SS_VA_HOLE_UB 0xffff7fffffffffff
498/* Extend 48 bit VA to 64 bits */
499#define VA48(_va) (((int64_t)(_va) << 16) >> 16)
500#define VA48_WARNING(_sp, _va) do {\
501 if ((_va) != VA48(_va))\
502 EXEC_WARNING(("@pc=0x%llx not a 48-bit VA 0x%llx",\
503 sp->pc, (_va)));\
504 } while (0)
505#define VA48_ASSERT(_va) ASSERT((_va) == VA48(_va))
506#endif /* } */
507
508typedef struct {
509 tlb_entry_t * ptr;
510} tlb_hash_bucket_t;
511
512 /*
513 * TLB organisation is independent of the
514 * search hash - and is merely determined by the
515 * behaviour of the insert / demap functions.
516 */
517
518#if defined(NIAGARA1) || defined(NIAGARA2) /* { */
519#define SS_TLB_HASH_ENTRIES 32 /* modest number */
520#endif /* } */
521#ifdef ROCK /* { */
522#define SS_TLB_HASH_ENTRIES 256 /* less modest number */
523#endif /* } */
524#define SS_TLB_HASH_MASK (SS_TLB_HASH_ENTRIES-1)
525 /* define replacement policy when all entries are valid: */
526#define SS_TLB_REPLACE_RROBIN 1
527/* #define SS_TLB_REPLACE_RANDOM 1 */
528
529struct SS_TLB {
530 uint_t nentries;
531 RW_lock_t rwlock;
532 tlb_entry_t * freep;
533 tlb_hash_bucket_t hash[SS_TLB_HASH_ENTRIES];
534 tlb_entry_t * tlb_entryp;
535 bool_t parity;
536 uint_t shares;
537#if SS_TLB_REPLACE_RROBIN /* { */
538 uint_t last_replaced;
539#endif /* } */
540#ifdef ROCK /* { */
541 uint8_t *lru_array;
542#endif /* } */
543};
544
545
546
547typedef struct SS_TLB_SPEC {
548 uint_t nentries;
549 bool_t parity;
550} ss_tlb_spec_t;
551
552
553typedef struct ERROR_PROC {
554 tvaddr_t ldac_addr;
555 tvaddr_t ldau_addr;
556 tvaddr_t dac_addr;
557 tvaddr_t dau_addr;
558} error_proc_t;
559
560 /*
561 * SunSPARC CPU specific info about how a debugger instance is
562 * attached ... handled as a hidden data type from the debugger,
563 * but provides this module info on which strand etc. the debugger
564 * is actually attached to.
565 */
566
567typedef struct {
568 domain_t * domainp;
569 config_proc_t * config_procp;
570
571 uint_t core;
572 uint_t strand;
573
574 sparcv9_cpu_t* strandp;
575} ss_dbgr_t;
576
577typedef enum SS_DEMAP ss_demap_t;
578
579typedef enum {
580 NA_mem_read, NA_mem_write, NA_mem_clear
581} dbgr_mem_op_t;
582
583/*
584 * All memory ASIs bit3=1 if the ASI is Little Endian
585 */
586#define SS_ASI_LE_MASK (1 << 3)
587
588typedef enum {
589 MF_Normal = 0x01, /* if normal access, else alternate address space being used */
590 MF_MMU_Bypass = 0x02, /* if this ld/st should bypass MMU translation */
591 MF_Has_Priv = 0x04, /* if access is from priv or hpriv mode */
592 MF_No_Fault = 0x08, /* No faulting load specified */
593 MF_IO_Access = 0x10, /* Not a cacheable access - e.g. REAL_IO */
594 MF_Blk_Init = 0x20, /* Block Initialize effect */
595 MF_Atomic_Access = 0x40, /* Atomic instruction access (including 128-bit atomic load) */
596 MF_TLB_Real_Ctx = 0x80, /* Search TLB RA->PA mapping (due to ASI_*_real_* access) */
597 MF_Little_Endian = 0x100
598} mem_flags_t;
599
600#if ERROR_INJECTION
601
602typedef enum {
603 IFETCH = 0x01,
604 LD = 0x02,
605 ASI_LD = 0x04,
606 ST = 0x08,
607 ANY_OP = 0xff
608} error_op_t;
609
610typedef uint64_t error_type_t;
611
612#define ss_set_errcheck(npp) do { \
613 npp->error_check = npp->errorp->ldac_addr | \
614 npp->errorp->ldau_addr | npp->errorp->dac_addr | \
615 npp->errorp->dau_addr; \
616 } while (0)
617
618#endif /* ERROR_INJECTION */
619
620/* The processor specific structure. */
621typedef struct SS_PROC ss_proc_t;
622
623 /*
624 * functions defined outside the CPU loadable modules
625 */
626extern void host_atomic_get128be(uint64_t *, uint64_t *, uint64_t *);
627
628 /*
629 * extern definitions used by more than one libsunsparc source file
630 */
631extern void ss_parse(domain_t*, config_proc_t*);
632extern void ss_parse_tlb(ss_tlb_spec_t *);
633extern void ss_init(domain_t*, config_proc_t*);
634extern void ss_dump(domain_t*, config_proc_t*);
635extern bool_t ss_dbgr_regread(void*, uint_t, uint64_t*);
636extern bool_t ss_dbgr_regwrite(void*, uint_t, uint64_t);
637extern void ss_exec_setup(simcpu_t*);
638extern void ss_exec_cleanup(simcpu_t*);
639extern bool_t ss_save_state(simcpu_t*);
640extern void ss_check_async_event(simcpu_t*);
641extern void ss_take_exception(simcpu_t*);
642extern void ss_dump_tlbs(config_proc_t*, bool_t);
643extern void ss_dump_tlbs_nolock(config_proc_t*, bool_t);
644extern void ss_dump_instruction_counts(config_proc_t*);
645extern uint64_t ss_ext_signal(config_proc_t*, ext_sig_t, void*);
646extern bool_t ss_dev_mem_access(config_proc_t *config_procp, tpaddr_t addr,
647 uint8_t *datap, uint64_t size, dev_access_t type);
648extern void * ss_dbgr_attach(domain_t*, config_proc_t*, char*);
649extern void ss_dbgr_detach(void*);
650extern uint64_t ss_dbgr_mem_read(void*, tvaddr_t, bool_t, uint8_t*, uint64_t);
651extern uint64_t ss_dbgr_mem_write(void*, tvaddr_t, bool_t, uint8_t*, uint64_t);
652extern uint64_t ss_dbgr_mem_clear(void*, tvaddr_t, bool_t, uint64_t);
653extern void ss_dbgr_set_break(void*, tvaddr_t);
654extern void ss_dbgr_clear_break(void*, tvaddr_t);
655extern void ss_tlb_unhash(ss_tlb_t*, tlb_entry_t*);
656extern void ss_tlb_unfree(ss_tlb_t*, tlb_entry_t*);
657extern void ss_free_tlb_entry(ss_tlb_t*, tlb_entry_t*);
658extern void ss_tlb_scrub(simcpu_t *, ss_tlb_t*, bool_t);
659extern void ss_xic_miss(simcpu_t*, xicache_line_t*, tvaddr_t);
660extern bool_t ss_tm_chkpt(simcpu_t *, tvaddr_t);
661extern void ss_tm_commit(simcpu_t *);
662extern void ss_tm_fail(simcpu_t *, uint64_t);
663extern uint64_t ss_read_pstate(sparcv9_cpu_t *);
664
665#if ERROR_INJECTION
666extern error_conf_t * new_errconf(error_op_t, error_type_t);
667extern error_conf_t * find_errconf(simcpu_t*, error_op_t, error_type_t);
668extern bool_t remove_errconf(simcpu_t * sp, error_conf_t * rmep);
669extern void dump_errconf(error_conf_t*);
670extern void extract_error_type(error_conf_t * errorconfp);
671extern void update_errflags(simcpu_t * sp);
672extern void clear_errflags(simcpu_t * sp);
673extern void ss_error_condition(simcpu_t*, error_conf_t*);
674extern void tlb_entry_error_match(simcpu_t*, ss_mmu_t*, tlb_entry_t*);
675#endif /* ERROR_INJECTION */
676#if !defined(NDEBUG) /* { */
677extern void ss_tlb_contents(FILE*, ss_tlb_t*, bool_t);
678#endif /* } */
679extern uint64_t ss_cpu_mem(domain_t *, void*, sparcv9_cpu_t*, dbgr_mem_op_t, tvaddr_t, bool_t, uint8_t*, uint_t);
680extern void ss_asi_access( simcpu_t*, maccess_t, uint_t, uint_t, uint64_t, uint64_t, asi_flag_t);
681extern bool_t ss_demap(simcpu_t*, ss_demap_t, ss_mmu_t*, ss_tlb_t*, uint_t, bool_t, uint_t, tvaddr_t);
682extern void ss_tlb_flush_shares(simcpu_t *, ss_tlb_t *, bool_t);
683extern uint64_t ss_read_tick(simcpu_t*);
684extern void ss_write_tick(simcpu_t*, uint64_t);
685extern uint64_t ss_read_stick(simcpu_t*);
686extern void ss_write_stick(simcpu_t*, uint64_t);
687extern void ss_recomp_tick_target(simcpu_t*);
688extern uint64_t ss_tick_cmpr_read(simcpu_t *, tick_compare_t *);
689extern void ss_tick_cmpr_write(simcpu_t *, tick_compare_t *, uint64_t);
690extern void ss_recomp_cycle_target(simcpu_t*);
691extern void ss_memory_asi_access(simcpu_t*, maccess_t, uint64_t*, mem_flags_t, uint_t, uint_t, uint_t, tvaddr_t, tvaddr_t);
692extern void ss_check_interrupts(simcpu_t*);
693extern uint8_t host_ldstub(uint8_t *, uint8_t, uint8_t);
694extern uint32_t host_cas32(uint32_t *, uint32_t, uint32_t);
695extern uint64_t host_cas64(uint64_t *, uint64_t, uint64_t);
696extern uint32_t host_swap(uint32_t *, uint32_t);
697extern void v9_set_fsr_lower(simcpu_t*, uint64_t);
698extern void v9_set_fsr(simcpu_t*, uint64_t);
699extern void v9_set_fsr_fp_op(simcpu_t*, uint64_t);
700extern uint64_t v9_get_fsr(simcpu_t*);
701
702extern void ss_change_exec_state(ss_proc_t *npp, uint64_t running_status);
703
704extern uint64_t xor_bits(uint64_t);
705
706uint_t ss_get_cpuid(simcpu_t *sp);
707void ss_trash_regs(sparcv9_cpu_t * v9p, uint64_t val);
708/*
709 * CPU version macros
710 */
711#define SS_VER_MANUF_OFFSET 48 /* bits 63:48 */
712#define SS_VER_IMPL_OFFSET 32 /* bits 47:32 */
713#define SS_VER_MASK_OFFSET 24 /* bits 31:24 */
714#define SS_VER_MAXGL_OFFSET 16 /* bits 18:16 */
715#define SS_VER_MAXTL_OFFSET 8 /* bits 15:8:0 */
716#define SS_VER_NWINS_OFFSET 0 /* bits 4:0 */
717
718#define SS_MAKE_VER_UPPER40(manuf, impl, mask) \
719 ((manuf<<SS_VER_MANUF_OFFSET)| \
720 (impl<<SS_VER_IMPL_OFFSET)| \
721 (mask<<SS_VER_MASK_OFFSET))
722
723#define SS_MAKE_VER_LOWER24(ngl, maxtl, nwins) \
724 (((ngl-1)<<SS_VER_MAXGL_OFFSET)| \
725 (maxtl<<SS_VER_MAXTL_OFFSET)| \
726 ((nwins-1)<<SS_VER_NWINS_OFFSET))
727
728#define RSVD_MASK(_sp, mask, val, asi, addr) \
729 do { \
730 if ((val) & ~(mask)) { \
731 EXEC_WARNING(("pc=0x%llx : stxa 0x%llx, [0x%x]0x%x: " \
732 "Attempted store to rsvd fields being masked out", \
733 (_sp)->pc, (val), (addr), (asi))); \
734 (val) &= (mask); \
735 } \
736 } while (0)
737
738/*
739 * Identical to above RSVD_MASK macro, but safe for use when _sp pointer may be NULL.
740 * Should be kept in sync with the above macro for any changes.
741 */
742#define ROCK_RSVD_MASK(_sp, mask, val, asi, addr) \
743 do { \
744 if ((val) & ~(mask)) { \
745 if ((_sp) != NULL) { \
746 EXEC_WARNING(("pc=0x%llx : stxa 0x%llx, [0x%x]0x%x: " \
747 "Attempted store to rsvd fields being masked out", \
748 (_sp)->pc, (val), (addr), (asi))); \
749 } else { \
750 EXEC_WARNING(("System controller access : stxa 0x%llx, [0x%x]0x%x: " \
751 "Attempted store to rsvd fields being masked out", \
752 (val), (addr), (asi))); \
753 } \
754 (val) &= (mask); \
755 } \
756 } while (0)
757
758#ifdef __cplusplus
759}
760#endif
761
762#endif /* _SS_COMMON_H */