iob.cc (11793:ef606668d247) iob.cc (13231:c6c133f9e007)
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31/** @file
32 * This device implemetns the niagara I/O bridge chip. It manages incomming
33 * interrupts and posts them to the CPU when needed. It holds mask registers and
34 * various status registers for CPUs to check what interrupts are pending as
35 * well as facilities to send IPIs to other cpus.
36 */
37
38#include "dev/sparc/iob.hh"
39
40#include <cstring>
41
42#include "arch/sparc/faults.hh"
43#include "arch/sparc/isa_traits.hh"
44#include "base/bitfield.hh"
45#include "base/trace.hh"
46#include "cpu/intr_control.hh"
47#include "cpu/thread_context.hh"
48#include "debug/Iob.hh"
49#include "dev/platform.hh"
50#include "mem/packet_access.hh"
51#include "mem/port.hh"
52#include "sim/faults.hh"
53#include "sim/system.hh"
54
55Iob::Iob(const Params *p)
56 : PioDevice(p), ic(p->platform->intrctrl)
57{
58 iobManAddr = ULL(0x9800000000);
59 iobManSize = ULL(0x0100000000);
60 iobJBusAddr = ULL(0x9F00000000);
61 iobJBusSize = ULL(0x0100000000);
62 assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
63
64 pioDelay = p->pio_latency;
65
66 for (int x = 0; x < NumDeviceIds; ++x) {
67 intMan[x].cpu = 0;
68 intMan[x].vector = 0;
69 intCtl[x].mask = true;
70 intCtl[x].pend = false;
71 }
72
73}
74
75Tick
76Iob::read(PacketPtr pkt)
77{
78
79 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
80 readIob(pkt);
81 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
82 readJBus(pkt);
83 else
84 panic("Invalid address reached Iob\n");
85
86 pkt->makeAtomicResponse();
87 return pioDelay;
88}
89
90void
91Iob::readIob(PacketPtr pkt)
92{
93 Addr accessAddr = pkt->getAddr() - iobManAddr;
94
95 assert(IntManAddr == 0);
96 if (accessAddr < IntManAddr + IntManSize) {
97 int index = (accessAddr - IntManAddr) >> 3;
98 uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0;
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31/** @file
32 * This device implemetns the niagara I/O bridge chip. It manages incomming
33 * interrupts and posts them to the CPU when needed. It holds mask registers and
34 * various status registers for CPUs to check what interrupts are pending as
35 * well as facilities to send IPIs to other cpus.
36 */
37
38#include "dev/sparc/iob.hh"
39
40#include <cstring>
41
42#include "arch/sparc/faults.hh"
43#include "arch/sparc/isa_traits.hh"
44#include "base/bitfield.hh"
45#include "base/trace.hh"
46#include "cpu/intr_control.hh"
47#include "cpu/thread_context.hh"
48#include "debug/Iob.hh"
49#include "dev/platform.hh"
50#include "mem/packet_access.hh"
51#include "mem/port.hh"
52#include "sim/faults.hh"
53#include "sim/system.hh"
54
55Iob::Iob(const Params *p)
56 : PioDevice(p), ic(p->platform->intrctrl)
57{
58 iobManAddr = ULL(0x9800000000);
59 iobManSize = ULL(0x0100000000);
60 iobJBusAddr = ULL(0x9F00000000);
61 iobJBusSize = ULL(0x0100000000);
62 assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
63
64 pioDelay = p->pio_latency;
65
66 for (int x = 0; x < NumDeviceIds; ++x) {
67 intMan[x].cpu = 0;
68 intMan[x].vector = 0;
69 intCtl[x].mask = true;
70 intCtl[x].pend = false;
71 }
72
73}
74
75Tick
76Iob::read(PacketPtr pkt)
77{
78
79 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
80 readIob(pkt);
81 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
82 readJBus(pkt);
83 else
84 panic("Invalid address reached Iob\n");
85
86 pkt->makeAtomicResponse();
87 return pioDelay;
88}
89
90void
91Iob::readIob(PacketPtr pkt)
92{
93 Addr accessAddr = pkt->getAddr() - iobManAddr;
94
95 assert(IntManAddr == 0);
96 if (accessAddr < IntManAddr + IntManSize) {
97 int index = (accessAddr - IntManAddr) >> 3;
98 uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0;
99 pkt->set(data);
99 pkt->setBE(data);
100 return;
101 }
102
103 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
104 int index = (accessAddr - IntCtlAddr) >> 3;
105 uint64_t data = intCtl[index].mask ? 1 << 2 : 0 |
106 intCtl[index].pend ? 1 << 0 : 0;
100 return;
101 }
102
103 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
104 int index = (accessAddr - IntCtlAddr) >> 3;
105 uint64_t data = intCtl[index].mask ? 1 << 2 : 0 |
106 intCtl[index].pend ? 1 << 0 : 0;
107 pkt->set(data);
107 pkt->setBE(data);
108 return;
109 }
110
111 if (accessAddr == JIntVecAddr) {
108 return;
109 }
110
111 if (accessAddr == JIntVecAddr) {
112 pkt->set(jIntVec);
112 pkt->setBE(jIntVec);
113 return;
114 }
115
116 panic("Read to unknown IOB offset 0x%x\n", accessAddr);
117}
118
119void
120Iob::readJBus(PacketPtr pkt)
121{
122 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
123 ContextID cpuid = pkt->req->contextId();
124 int index;
125 uint64_t data;
126
127
128
129
130 if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
131 index = (accessAddr - JIntData0Addr) >> 3;
113 return;
114 }
115
116 panic("Read to unknown IOB offset 0x%x\n", accessAddr);
117}
118
119void
120Iob::readJBus(PacketPtr pkt)
121{
122 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
123 ContextID cpuid = pkt->req->contextId();
124 int index;
125 uint64_t data;
126
127
128
129
130 if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
131 index = (accessAddr - JIntData0Addr) >> 3;
132 pkt->set(jBusData0[index]);
132 pkt->setBE(jBusData0[index]);
133 return;
134 }
135
136 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
137 index = (accessAddr - JIntData1Addr) >> 3;
133 return;
134 }
135
136 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
137 index = (accessAddr - JIntData1Addr) >> 3;
138 pkt->set(jBusData1[index]);
138 pkt->setBE(jBusData1[index]);
139 return;
140 }
141
142 if (accessAddr == JIntDataA0Addr) {
139 return;
140 }
141
142 if (accessAddr == JIntDataA0Addr) {
143 pkt->set(jBusData0[cpuid]);
143 pkt->setBE(jBusData0[cpuid]);
144 return;
145 }
146
147 if (accessAddr == JIntDataA1Addr) {
144 return;
145 }
146
147 if (accessAddr == JIntDataA1Addr) {
148 pkt->set(jBusData1[cpuid]);
148 pkt->setBE(jBusData1[cpuid]);
149 return;
150 }
151
152 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
153 index = (accessAddr - JIntBusyAddr) >> 3;
154 data = jIntBusy[index].busy ? 1 << 5 : 0 |
155 jIntBusy[index].source;
149 return;
150 }
151
152 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
153 index = (accessAddr - JIntBusyAddr) >> 3;
154 data = jIntBusy[index].busy ? 1 << 5 : 0 |
155 jIntBusy[index].source;
156 pkt->set(data);
156 pkt->setBE(data);
157 return;
158 }
159 if (accessAddr == JIntABusyAddr) {
160 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
161 jIntBusy[cpuid].source;
157 return;
158 }
159 if (accessAddr == JIntABusyAddr) {
160 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
161 jIntBusy[cpuid].source;
162 pkt->set(data);
162 pkt->setBE(data);
163 return;
164 };
165
166 panic("Read to unknown JBus offset 0x%x\n", accessAddr);
167}
168
169Tick
170Iob::write(PacketPtr pkt)
171{
172 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
173 writeIob(pkt);
174 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
175 writeJBus(pkt);
176 else
177 panic("Invalid address reached Iob\n");
178
179
180 pkt->makeAtomicResponse();
181 return pioDelay;
182}
183
184void
185Iob::writeIob(PacketPtr pkt)
186{
187 Addr accessAddr = pkt->getAddr() - iobManAddr;
188 int index;
189 uint64_t data;
190
191 assert(IntManAddr == 0);
192 if (accessAddr < IntManAddr + IntManSize) {
193 index = (accessAddr - IntManAddr) >> 3;
163 return;
164 };
165
166 panic("Read to unknown JBus offset 0x%x\n", accessAddr);
167}
168
169Tick
170Iob::write(PacketPtr pkt)
171{
172 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
173 writeIob(pkt);
174 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
175 writeJBus(pkt);
176 else
177 panic("Invalid address reached Iob\n");
178
179
180 pkt->makeAtomicResponse();
181 return pioDelay;
182}
183
184void
185Iob::writeIob(PacketPtr pkt)
186{
187 Addr accessAddr = pkt->getAddr() - iobManAddr;
188 int index;
189 uint64_t data;
190
191 assert(IntManAddr == 0);
192 if (accessAddr < IntManAddr + IntManSize) {
193 index = (accessAddr - IntManAddr) >> 3;
194 data = pkt->get();
194 data = pkt->getBE<uint64_t>();
195 intMan[index].cpu = bits(data,12,8);
196 intMan[index].vector = bits(data,5,0);
197 DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
198 intMan[index].cpu, intMan[index].vector);
199 return;
200 }
201
202 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
203 index = (accessAddr - IntCtlAddr) >> 3;
195 intMan[index].cpu = bits(data,12,8);
196 intMan[index].vector = bits(data,5,0);
197 DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
198 intMan[index].cpu, intMan[index].vector);
199 return;
200 }
201
202 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
203 index = (accessAddr - IntCtlAddr) >> 3;
204 data = pkt->get();
204 data = pkt->getBE<uint64_t>();
205 intCtl[index].mask = bits(data,2,2);
206 if (bits(data,1,1))
207 intCtl[index].pend = false;
208 DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
209 intCtl[index].pend, bits(data,2,2));
210 return;
211 }
212
213 if (accessAddr == JIntVecAddr) {
205 intCtl[index].mask = bits(data,2,2);
206 if (bits(data,1,1))
207 intCtl[index].pend = false;
208 DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
209 intCtl[index].pend, bits(data,2,2));
210 return;
211 }
212
213 if (accessAddr == JIntVecAddr) {
214 jIntVec = bits(pkt->get(), 5,0);
214 jIntVec = bits(pkt->getBE<uint64_t>(), 5,0);
215 DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
216 return;
217 }
218
219 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
220 Type type;
221 int cpu_id;
222 int vector;
223 index = (accessAddr - IntManAddr) >> 3;
215 DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
216 return;
217 }
218
219 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
220 Type type;
221 int cpu_id;
222 int vector;
223 index = (accessAddr - IntManAddr) >> 3;
224 data = pkt->get();
224 data = pkt->getBE<uint64_t>();
225 type = (Type)bits(data,17,16);
226 cpu_id = bits(data, 12,8);
227 vector = bits(data,5,0);
228 generateIpi(type,cpu_id, vector);
229 return;
230 }
231
232 panic("Write to unknown IOB offset 0x%x\n", accessAddr);
233}
234
235void
236Iob::writeJBus(PacketPtr pkt)
237{
238 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
239 ContextID cpuid = pkt->req->contextId();
240 int index;
241 uint64_t data;
242
243 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
244 index = (accessAddr - JIntBusyAddr) >> 3;
225 type = (Type)bits(data,17,16);
226 cpu_id = bits(data, 12,8);
227 vector = bits(data,5,0);
228 generateIpi(type,cpu_id, vector);
229 return;
230 }
231
232 panic("Write to unknown IOB offset 0x%x\n", accessAddr);
233}
234
235void
236Iob::writeJBus(PacketPtr pkt)
237{
238 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
239 ContextID cpuid = pkt->req->contextId();
240 int index;
241 uint64_t data;
242
243 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
244 index = (accessAddr - JIntBusyAddr) >> 3;
245 data = pkt->get();
245 data = pkt->getBE<uint64_t>();
246 jIntBusy[index].busy = bits(data,5,5);
247 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
248 jIntBusy[index].busy);
249 return;
250 }
251 if (accessAddr == JIntABusyAddr) {
246 jIntBusy[index].busy = bits(data,5,5);
247 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
248 jIntBusy[index].busy);
249 return;
250 }
251 if (accessAddr == JIntABusyAddr) {
252 data = pkt->get();
252 data = pkt->getBE<uint64_t>();
253 jIntBusy[cpuid].busy = bits(data,5,5);
254 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
255 jIntBusy[cpuid].busy);
256 return;
257 };
258
259 panic("Write to unknown JBus offset 0x%x\n", accessAddr);
260}
261
262void
263Iob::receiveDeviceInterrupt(DeviceId devid)
264{
265 assert(devid < NumDeviceIds);
266 if (intCtl[devid].mask)
267 return;
268 intCtl[devid].mask = true;
269 intCtl[devid].pend = true;
270 DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
271 devid, intMan[devid].cpu, intMan[devid].vector);
272 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
273}
274
275
276void
277Iob::generateIpi(Type type, int cpu_id, int vector)
278{
279 SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
280 if (cpu_id >= sys->numContexts())
281 return;
282
283 switch (type) {
284 case 0: // interrupt
285 DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n",
286 cpu_id, vector);
287 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
288 break;
289 case 1: // reset
290 warn("Sending reset to CPU: %d\n", cpu_id);
291 if (vector != por->trapType())
292 panic("Don't know how to set non-POR reset to cpu\n");
293 por->invoke(sys->threadContexts[cpu_id]);
294 sys->threadContexts[cpu_id]->activate();
295 break;
296 case 2: // idle -- this means stop executing and don't wake on interrupts
297 DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
298 sys->threadContexts[cpu_id]->halt();
299 break;
300 case 3: // resume
301 DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
302 sys->threadContexts[cpu_id]->activate();
303 break;
304 default:
305 panic("Invalid type to generate ipi\n");
306 }
307}
308
309bool
310Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
311{
312 // If we are already dealing with an interrupt for that cpu we can't deal
313 // with another one right now... come back later
314 if (jIntBusy[cpu_id].busy)
315 return false;
316
317 DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
318 source, cpu_id, jIntVec);
319
320 jIntBusy[cpu_id].busy = true;
321 jIntBusy[cpu_id].source = source;
322 jBusData0[cpu_id] = d0;
323 jBusData1[cpu_id] = d1;
324
325 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
326 return true;
327}
328
329AddrRangeList
330Iob::getAddrRanges() const
331{
332 AddrRangeList ranges;
333 ranges.push_back(RangeSize(iobManAddr, iobManSize));
334 ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
335 return ranges;
336}
337
338
339void
340Iob::serialize(CheckpointOut &cp) const
341{
342
343 SERIALIZE_SCALAR(jIntVec);
344 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
345 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
346 for (int x = 0; x < NumDeviceIds; x++) {
347 ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
348 paramOut(cp, "cpu", intMan[x].cpu);
349 paramOut(cp, "vector", intMan[x].vector);
350 paramOut(cp, "mask", intCtl[x].mask);
351 paramOut(cp, "pend", intCtl[x].pend);
352 };
353 for (int x = 0; x < MaxNiagaraProcs; x++) {
354 ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
355 paramOut(cp, "busy", jIntBusy[x].busy);
356 paramOut(cp, "source", jIntBusy[x].source);
357 };
358}
359
360void
361Iob::unserialize(CheckpointIn &cp)
362{
363 UNSERIALIZE_SCALAR(jIntVec);
364 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
365 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
366 for (int x = 0; x < NumDeviceIds; x++) {
367 ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
368 paramIn(cp, "cpu", intMan[x].cpu);
369 paramIn(cp, "vector", intMan[x].vector);
370 paramIn(cp, "mask", intCtl[x].mask);
371 paramIn(cp, "pend", intCtl[x].pend);
372 };
373 for (int x = 0; x < MaxNiagaraProcs; x++) {
374 ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
375 paramIn(cp, "busy", jIntBusy[x].busy);
376 paramIn(cp, "source", jIntBusy[x].source);
377 };
378}
379
380Iob *
381IobParams::create()
382{
383 return new Iob(this);
384}
253 jIntBusy[cpuid].busy = bits(data,5,5);
254 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
255 jIntBusy[cpuid].busy);
256 return;
257 };
258
259 panic("Write to unknown JBus offset 0x%x\n", accessAddr);
260}
261
262void
263Iob::receiveDeviceInterrupt(DeviceId devid)
264{
265 assert(devid < NumDeviceIds);
266 if (intCtl[devid].mask)
267 return;
268 intCtl[devid].mask = true;
269 intCtl[devid].pend = true;
270 DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
271 devid, intMan[devid].cpu, intMan[devid].vector);
272 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
273}
274
275
276void
277Iob::generateIpi(Type type, int cpu_id, int vector)
278{
279 SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
280 if (cpu_id >= sys->numContexts())
281 return;
282
283 switch (type) {
284 case 0: // interrupt
285 DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n",
286 cpu_id, vector);
287 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
288 break;
289 case 1: // reset
290 warn("Sending reset to CPU: %d\n", cpu_id);
291 if (vector != por->trapType())
292 panic("Don't know how to set non-POR reset to cpu\n");
293 por->invoke(sys->threadContexts[cpu_id]);
294 sys->threadContexts[cpu_id]->activate();
295 break;
296 case 2: // idle -- this means stop executing and don't wake on interrupts
297 DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
298 sys->threadContexts[cpu_id]->halt();
299 break;
300 case 3: // resume
301 DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
302 sys->threadContexts[cpu_id]->activate();
303 break;
304 default:
305 panic("Invalid type to generate ipi\n");
306 }
307}
308
309bool
310Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
311{
312 // If we are already dealing with an interrupt for that cpu we can't deal
313 // with another one right now... come back later
314 if (jIntBusy[cpu_id].busy)
315 return false;
316
317 DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
318 source, cpu_id, jIntVec);
319
320 jIntBusy[cpu_id].busy = true;
321 jIntBusy[cpu_id].source = source;
322 jBusData0[cpu_id] = d0;
323 jBusData1[cpu_id] = d1;
324
325 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
326 return true;
327}
328
329AddrRangeList
330Iob::getAddrRanges() const
331{
332 AddrRangeList ranges;
333 ranges.push_back(RangeSize(iobManAddr, iobManSize));
334 ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
335 return ranges;
336}
337
338
339void
340Iob::serialize(CheckpointOut &cp) const
341{
342
343 SERIALIZE_SCALAR(jIntVec);
344 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
345 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
346 for (int x = 0; x < NumDeviceIds; x++) {
347 ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
348 paramOut(cp, "cpu", intMan[x].cpu);
349 paramOut(cp, "vector", intMan[x].vector);
350 paramOut(cp, "mask", intCtl[x].mask);
351 paramOut(cp, "pend", intCtl[x].pend);
352 };
353 for (int x = 0; x < MaxNiagaraProcs; x++) {
354 ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
355 paramOut(cp, "busy", jIntBusy[x].busy);
356 paramOut(cp, "source", jIntBusy[x].source);
357 };
358}
359
360void
361Iob::unserialize(CheckpointIn &cp)
362{
363 UNSERIALIZE_SCALAR(jIntVec);
364 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
365 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
366 for (int x = 0; x < NumDeviceIds; x++) {
367 ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
368 paramIn(cp, "cpu", intMan[x].cpu);
369 paramIn(cp, "vector", intMan[x].vector);
370 paramIn(cp, "mask", intCtl[x].mask);
371 paramIn(cp, "pend", intCtl[x].pend);
372 };
373 for (int x = 0; x < MaxNiagaraProcs; x++) {
374 ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
375 paramIn(cp, "busy", jIntBusy[x].busy);
376 paramIn(cp, "source", jIntBusy[x].source);
377 };
378}
379
380Iob *
381IobParams::create()
382{
383 return new Iob(this);
384}