solo_cp0.c
6.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
* Copyright (C) 1996-1998 by the Board of Trustees
* of Leland Stanford Junior University.
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
/****************************************************************
* solo_cp0.c
*
* $Author: blythe $
* $Date: 2002/05/29 01:09:11 $
*****************************************************************/
#include "mipsy.h"
#include "cp0.h"
#include "sim_error.h"
#include "solo_anl.h"
#include "solo_interface.h"
#include "cpu_interface.h"
#include "solo.h"
#include "solo_interface.h"
#include "solo_page.h"
#include "simtypes.h"
#include "cpu_stats.h"
static int libcOwner = -1;
static int libcWaiters = 0;
Result
TranslateVirtualNoSideeffect(CPUState *P, VA vAddr, PA *pAddr)
{
uint flavor = 0;
void *bdoorAddr = 0;
return TranslateVirtual(P, vAddr, pAddr, &flavor,&bdoorAddr);
}
/*****************************************************************
* TranslateVirtual
*
* Now that we're in solo mipsy, just return the virtual address
*****************************************************************/
Result
TranslateVirtual(CPUState *P, VA vAddr, PA *pAddr, uint *tlbFlavor, void **bdoorAddr)
{
int i, p;
bool icache;
int cpuNum = P->myNum;
SoloPA soloPA;
icache = (bool) TLB_IS_IFETCH(*tlbFlavor);
/* Setting this to 0 means that by this is not a backdoor reference */
*tlbFlavor = 0;
if (((void *)vAddr >= (void*)SOLO_STACK_TOP) &&
((void *)vAddr < (void*)0x90000000)) {
/* WARNING: ALL references above the top of */
/* the application's stack top are backdoor. */
*tlbFlavor = TLB_BDOOR_DATA;
*bdoorAddr = (void *)vAddr;
*pAddr = (PA)vAddr;
} else {
if (icache) {
/* Make sure that only one processor at a time is allowed to */
/* be executing in the libc code. The start of libc is found */
/* by linking in an object file with a single function in it. */
if ((void *)vAddr >= (void *)CommAreaPtr->libcStart) {
if ((libcOwner != P->myNum) && (libcOwner != -1)) {
P->cpuStatus = cpu_libc_blocked;
STATS_SET(cpuNum, libcWaitStart, MipsyReadTime(cpuNum));
libcWaiters++;
return FAILURE;
} else {
libcOwner = P->myNum;
}
} else {
if (libcOwner == P->myNum) {
if (libcWaiters > 0) {
libcWaiters--;
for (i=1; i < TOTAL_CPUS; i++) {
p = (P->myNum + i) % TOTAL_CPUS;
if (PE[p].cpuStatus == cpu_libc_blocked) {
STATS_ADD_INTERVAL(p, libcWaitTime, libcWaitStart);
libcOwner = p;
PE[p].cpuStatus = cpu_running;
break;
}
}
ASSERT(libcOwner != P->myNum);
} else {
libcOwner = -1;
}
}
}
}
if (IS_STACK_REF(vAddr)) {
soloPA = SoloV_to_P(P->myNum, vAddr, P->myNum, TRUE, tlbFlavor);
} else {
soloPA = SoloV_to_P(P->myNum, vAddr, P->myNum, FALSE, tlbFlavor);
}
if ((*tlbFlavor) == TLB_UNCACHED) {
*pAddr = vAddr; /* This will be translated by the memsys command */
} else {
#if 0
/* JH: This is the safe, default version that doesn't provide the lock hack.
In case the lock code crashes for you badly, this is a saving grace you
can use*/
*pAddr = SoloCompressAddr(soloPA);
#else
/* Check for accesses in the lock space, and remap them into the special range*/
if (SOLO_PA_SPACE(soloPA) == 1) {
/* Lock space. Remove space bit, add base in mipsy VA range so */
/* compress maintains hidden notion of this address */
#ifdef DEBUG_PAGE_VERBOSE
CPUPrint("Lock address detected, pAddr = %llx\n",soloPA);
#endif
soloPA += soloLockBase;
/* soloPA &= ~((unsigned long long) 0xe0000000LL); */
soloPA = SOLO_FORM_PA( SOLO_PA_NODE(soloPA), 0LL, /* Space 0! */
SOLO_PA_OFFSET(soloPA));
#ifdef DEBUG_PAGE_VERBOSE
CPUPrint("After address munging, pAddr = %llx\n",soloPA);
/* Remove the space bit. Not strictly necessary, since compress will */
/* throw it away anyway... */
#endif
} else if (SOLO_PA_SPACE(soloPA) == 2) {
/* Check for accesses in the barrier space, and remap them into
the special range*/
/* Lock space. Remove space bit, add base in mipsy VA range so */
/* compress maintains hidden notion of this address */
#ifdef DEBUG_PAGE_VERBOSE
CPUPrint("Barrier address detected, pAddr = %llx\n",soloPA);
#endif
soloPA += soloBarrierBase;
/* soloPA &= ~((unsigned long long) 0xe0000000LL); */
soloPA = SOLO_FORM_PA( SOLO_PA_NODE(soloPA), 0LL, /* Space 0! */
SOLO_PA_OFFSET(soloPA));
#ifdef DEBUG_PAGE_VERBOSE
CPUPrint("After address munging, pAddr = %llx\n",soloPA);
/* Remove the space bit. Not strictly necessary, since compress will */
/* throw it away anyway... */
#endif
}
*pAddr = SoloCompressAddr(soloPA);
#ifdef DEBUG_PAGE_VERBOSE
CPUPrint("Before compression, pAddr = %llx\n",soloPA);
CPUPrint("After compression, pAddr = %x\n",*pAddr);
#endif
#endif
}
}
return SUCCESS;
}
/*****************************************************************
* EXCEPTION
****************************************************************/
void EXCEPTION(CPUState *P, int code)
{
CPUError("EXCEPTION %d occurred on cpu %d @ PC 0x%x\n",
code, P->myNum, P->PC);
}
/*****************************************************************
* ExceptionReturn
****************************************************************/
void
ExceptionReturn(int cpuNum)
{
CPUPrint("RFE - you shouldn't be here\n");
}
void MipsyCheckForInterrupts(CPUState *P)
{
/* SOLO doesn't do interrupts */
}
void UpdateCPUMode(CPUState *P)
{
CPUWarning("SOLO in UpdateCPUMode\n");
}
int
ExecuteC0Instruction(CPUState *P, Inst instr)
{
CPUWarning("WriteC0Reg - you shouldn't be here\n");
return C0_CONTINUE;
}