iob.cc (4918:3214e3694fb2) iob.cc (5103:391933804192)
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 <cstring>
39
40#include "arch/sparc/isa_traits.hh"
41#include "arch/sparc/faults.hh"
42#include "base/trace.hh"
43#include "cpu/intr_control.hh"
44#include "dev/sparc/iob.hh"
45#include "dev/platform.hh"
46#include "mem/port.hh"
47#include "mem/packet_access.hh"
48#include "sim/faults.hh"
49#include "sim/system.hh"
50
51Iob::Iob(const Params *p)
52 : PioDevice(p), ic(p->platform->intrctrl)
53{
54 iobManAddr = ULL(0x9800000000);
55 iobManSize = ULL(0x0100000000);
56 iobJBusAddr = ULL(0x9F00000000);
57 iobJBusSize = ULL(0x0100000000);
58 assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
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 <cstring>
39
40#include "arch/sparc/isa_traits.hh"
41#include "arch/sparc/faults.hh"
42#include "base/trace.hh"
43#include "cpu/intr_control.hh"
44#include "dev/sparc/iob.hh"
45#include "dev/platform.hh"
46#include "mem/port.hh"
47#include "mem/packet_access.hh"
48#include "sim/faults.hh"
49#include "sim/system.hh"
50
51Iob::Iob(const Params *p)
52 : PioDevice(p), ic(p->platform->intrctrl)
53{
54 iobManAddr = ULL(0x9800000000);
55 iobManSize = ULL(0x0100000000);
56 iobJBusAddr = ULL(0x9F00000000);
57 iobJBusSize = ULL(0x0100000000);
58 assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
59
60 pioDelay = p->pio_latency;
61
59 // Get the interrupt controller from the platform
60 ic = platform->intrctrl;
61
62 for (int x = 0; x < NumDeviceIds; ++x) {
63 intMan[x].cpu = 0;
64 intMan[x].vector = 0;
65 intCtl[x].mask = true;
66 intCtl[x].pend = false;
67 }
68
69}
70
71Tick
72Iob::read(PacketPtr pkt)
73{
74
75 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
76 readIob(pkt);
77 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
78 readJBus(pkt);
79 else
80 panic("Invalid address reached Iob\n");
81
82 pkt->makeAtomicResponse();
83 return pioDelay;
84}
85
86void
87Iob::readIob(PacketPtr pkt)
88{
89 Addr accessAddr = pkt->getAddr() - iobManAddr;
90 int index;
91 uint64_t data;
92
93 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
94 index = (accessAddr - IntManAddr) >> 3;
95 data = intMan[index].cpu << 8 | intMan[index].vector << 0;
96 pkt->set(data);
97 return;
98 }
99
100 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
101 index = (accessAddr - IntManAddr) >> 3;
102 data = intCtl[index].mask ? 1 << 2 : 0 |
103 intCtl[index].pend ? 1 << 0 : 0;
104 pkt->set(data);
105 return;
106 }
107
108 if (accessAddr == JIntVecAddr) {
109 pkt->set(jIntVec);
110 return;
111 }
112
113 panic("Read to unknown IOB offset 0x%x\n", accessAddr);
114}
115
116void
117Iob::readJBus(PacketPtr pkt)
118{
119 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
120 int cpuid = pkt->req->getCpuNum();
121 int index;
122 uint64_t data;
123
124
125
126
127 if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
128 index = (accessAddr - JIntData0Addr) >> 3;
129 pkt->set(jBusData0[index]);
130 return;
131 }
132
133 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
134 index = (accessAddr - JIntData1Addr) >> 3;
135 pkt->set(jBusData1[index]);
136 return;
137 }
138
139 if (accessAddr == JIntDataA0Addr) {
140 pkt->set(jBusData0[cpuid]);
141 return;
142 }
143
144 if (accessAddr == JIntDataA1Addr) {
145 pkt->set(jBusData1[cpuid]);
146 return;
147 }
148
149 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
150 index = (accessAddr - JIntBusyAddr) >> 3;
151 data = jIntBusy[index].busy ? 1 << 5 : 0 |
152 jIntBusy[index].source;
153 pkt->set(data);
154 return;
155 }
156 if (accessAddr == JIntABusyAddr) {
157 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
158 jIntBusy[cpuid].source;
159 pkt->set(data);
160 return;
161 };
162
163 panic("Read to unknown JBus offset 0x%x\n", accessAddr);
164}
165
166Tick
167Iob::write(PacketPtr pkt)
168{
169 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
170 writeIob(pkt);
171 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
172 writeJBus(pkt);
173 else
174 panic("Invalid address reached Iob\n");
175
176
177 pkt->makeAtomicResponse();
178 return pioDelay;
179}
180
181void
182Iob::writeIob(PacketPtr pkt)
183{
184 Addr accessAddr = pkt->getAddr() - iobManAddr;
185 int index;
186 uint64_t data;
187
188 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
189 index = (accessAddr - IntManAddr) >> 3;
190 data = pkt->get<uint64_t>();
191 intMan[index].cpu = bits(data,12,8);
192 intMan[index].vector = bits(data,5,0);
193 DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
194 intMan[index].cpu, intMan[index].vector);
195 return;
196 }
197
198 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
199 index = (accessAddr - IntManAddr) >> 3;
200 data = pkt->get<uint64_t>();
201 intCtl[index].mask = bits(data,2,2);
202 if (bits(data,1,1))
203 intCtl[index].pend = false;
204 DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
205 intCtl[index].pend, bits(data,2,2));
206 return;
207 }
208
209 if (accessAddr == JIntVecAddr) {
210 jIntVec = bits(pkt->get<uint64_t>(), 5,0);
211 DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
212 return;
213 }
214
215 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
216 Type type;
217 int cpu_id;
218 int vector;
219 index = (accessAddr - IntManAddr) >> 3;
220 data = pkt->get<uint64_t>();
221 type = (Type)bits(data,17,16);
222 cpu_id = bits(data, 12,8);
223 vector = bits(data,5,0);
224 generateIpi(type,cpu_id, vector);
225 return;
226 }
227
228 panic("Write to unknown IOB offset 0x%x\n", accessAddr);
229}
230
231void
232Iob::writeJBus(PacketPtr pkt)
233{
234 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
235 int cpuid = pkt->req->getCpuNum();
236 int index;
237 uint64_t data;
238
239 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
240 index = (accessAddr - JIntBusyAddr) >> 3;
241 data = pkt->get<uint64_t>();
242 jIntBusy[index].busy = bits(data,5,5);
243 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
244 jIntBusy[index].busy);
245 return;
246 }
247 if (accessAddr == JIntABusyAddr) {
248 data = pkt->get<uint64_t>();
249 jIntBusy[cpuid].busy = bits(data,5,5);
250 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
251 jIntBusy[cpuid].busy);
252 return;
253 };
254
255 panic("Write to unknown JBus offset 0x%x\n", accessAddr);
256}
257
258void
259Iob::receiveDeviceInterrupt(DeviceId devid)
260{
261 assert(devid < NumDeviceIds);
262 if (intCtl[devid].mask)
263 return;
264 intCtl[devid].mask = true;
265 intCtl[devid].pend = true;
266 DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
267 devid, intMan[devid].cpu, intMan[devid].vector);
268 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
269}
270
271
272void
273Iob::generateIpi(Type type, int cpu_id, int vector)
274{
275 SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
276 if (cpu_id >= sys->getNumCPUs())
277 return;
278
279 switch (type) {
280 case 0: // interrupt
281 DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n",
282 cpu_id, vector);
283 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
284 break;
285 case 1: // reset
286 warn("Sending reset to CPU: %d\n", cpu_id);
287 if (vector != por->trapType())
288 panic("Don't know how to set non-POR reset to cpu\n");
289 por->invoke(sys->threadContexts[cpu_id]);
290 sys->threadContexts[cpu_id]->activate();
291 break;
292 case 2: // idle -- this means stop executing and don't wake on interrupts
293 DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
294 sys->threadContexts[cpu_id]->halt();
295 break;
296 case 3: // resume
297 DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
298 sys->threadContexts[cpu_id]->activate();
299 break;
300 default:
301 panic("Invalid type to generate ipi\n");
302 }
303}
304
305bool
306Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
307{
308 // If we are already dealing with an interrupt for that cpu we can't deal
309 // with another one right now... come back later
310 if (jIntBusy[cpu_id].busy)
311 return false;
312
313 DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
314 source, cpu_id, jIntVec);
315
316 jIntBusy[cpu_id].busy = true;
317 jIntBusy[cpu_id].source = source;
318 jBusData0[cpu_id] = d0;
319 jBusData1[cpu_id] = d1;
320
321 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
322 return true;
323}
324
325void
326Iob::addressRanges(AddrRangeList &range_list)
327{
328 range_list.clear();
329 range_list.push_back(RangeSize(iobManAddr, iobManSize));
330 range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
331}
332
333
334void
335Iob::serialize(std::ostream &os)
336{
337
338 SERIALIZE_SCALAR(jIntVec);
339 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
340 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
341 for (int x = 0; x < NumDeviceIds; x++) {
342 nameOut(os, csprintf("%s.Int%d", name(), x));
343 paramOut(os, "cpu", intMan[x].cpu);
344 paramOut(os, "vector", intMan[x].vector);
345 paramOut(os, "mask", intCtl[x].mask);
346 paramOut(os, "pend", intCtl[x].pend);
347 };
348 for (int x = 0; x < MaxNiagaraProcs; x++) {
349 nameOut(os, csprintf("%s.jIntBusy%d", name(), x));
350 paramOut(os, "busy", jIntBusy[x].busy);
351 paramOut(os, "source", jIntBusy[x].source);
352 };
353}
354
355void
356Iob::unserialize(Checkpoint *cp, const std::string &section)
357{
358 UNSERIALIZE_SCALAR(jIntVec);
359 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
360 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
361 for (int x = 0; x < NumDeviceIds; x++) {
362 paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu);
363 paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector);
364 paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask);
365 paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend);
366 };
367 for (int x = 0; x < MaxNiagaraProcs; x++) {
368 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy);
369 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source);
370 };
371}
372
373Iob *
374IobParams::create()
375{
376 return new Iob(this);
377}
62 // Get the interrupt controller from the platform
63 ic = platform->intrctrl;
64
65 for (int x = 0; x < NumDeviceIds; ++x) {
66 intMan[x].cpu = 0;
67 intMan[x].vector = 0;
68 intCtl[x].mask = true;
69 intCtl[x].pend = false;
70 }
71
72}
73
74Tick
75Iob::read(PacketPtr pkt)
76{
77
78 if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
79 readIob(pkt);
80 else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
81 readJBus(pkt);
82 else
83 panic("Invalid address reached Iob\n");
84
85 pkt->makeAtomicResponse();
86 return pioDelay;
87}
88
89void
90Iob::readIob(PacketPtr pkt)
91{
92 Addr accessAddr = pkt->getAddr() - iobManAddr;
93 int index;
94 uint64_t data;
95
96 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
97 index = (accessAddr - IntManAddr) >> 3;
98 data = intMan[index].cpu << 8 | intMan[index].vector << 0;
99 pkt->set(data);
100 return;
101 }
102
103 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
104 index = (accessAddr - IntManAddr) >> 3;
105 data = intCtl[index].mask ? 1 << 2 : 0 |
106 intCtl[index].pend ? 1 << 0 : 0;
107 pkt->set(data);
108 return;
109 }
110
111 if (accessAddr == JIntVecAddr) {
112 pkt->set(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 int cpuid = pkt->req->getCpuNum();
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]);
133 return;
134 }
135
136 if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
137 index = (accessAddr - JIntData1Addr) >> 3;
138 pkt->set(jBusData1[index]);
139 return;
140 }
141
142 if (accessAddr == JIntDataA0Addr) {
143 pkt->set(jBusData0[cpuid]);
144 return;
145 }
146
147 if (accessAddr == JIntDataA1Addr) {
148 pkt->set(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;
156 pkt->set(data);
157 return;
158 }
159 if (accessAddr == JIntABusyAddr) {
160 data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
161 jIntBusy[cpuid].source;
162 pkt->set(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 if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
192 index = (accessAddr - IntManAddr) >> 3;
193 data = pkt->get<uint64_t>();
194 intMan[index].cpu = bits(data,12,8);
195 intMan[index].vector = bits(data,5,0);
196 DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
197 intMan[index].cpu, intMan[index].vector);
198 return;
199 }
200
201 if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
202 index = (accessAddr - IntManAddr) >> 3;
203 data = pkt->get<uint64_t>();
204 intCtl[index].mask = bits(data,2,2);
205 if (bits(data,1,1))
206 intCtl[index].pend = false;
207 DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
208 intCtl[index].pend, bits(data,2,2));
209 return;
210 }
211
212 if (accessAddr == JIntVecAddr) {
213 jIntVec = bits(pkt->get<uint64_t>(), 5,0);
214 DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
215 return;
216 }
217
218 if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
219 Type type;
220 int cpu_id;
221 int vector;
222 index = (accessAddr - IntManAddr) >> 3;
223 data = pkt->get<uint64_t>();
224 type = (Type)bits(data,17,16);
225 cpu_id = bits(data, 12,8);
226 vector = bits(data,5,0);
227 generateIpi(type,cpu_id, vector);
228 return;
229 }
230
231 panic("Write to unknown IOB offset 0x%x\n", accessAddr);
232}
233
234void
235Iob::writeJBus(PacketPtr pkt)
236{
237 Addr accessAddr = pkt->getAddr() - iobJBusAddr;
238 int cpuid = pkt->req->getCpuNum();
239 int index;
240 uint64_t data;
241
242 if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
243 index = (accessAddr - JIntBusyAddr) >> 3;
244 data = pkt->get<uint64_t>();
245 jIntBusy[index].busy = bits(data,5,5);
246 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
247 jIntBusy[index].busy);
248 return;
249 }
250 if (accessAddr == JIntABusyAddr) {
251 data = pkt->get<uint64_t>();
252 jIntBusy[cpuid].busy = bits(data,5,5);
253 DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
254 jIntBusy[cpuid].busy);
255 return;
256 };
257
258 panic("Write to unknown JBus offset 0x%x\n", accessAddr);
259}
260
261void
262Iob::receiveDeviceInterrupt(DeviceId devid)
263{
264 assert(devid < NumDeviceIds);
265 if (intCtl[devid].mask)
266 return;
267 intCtl[devid].mask = true;
268 intCtl[devid].pend = true;
269 DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
270 devid, intMan[devid].cpu, intMan[devid].vector);
271 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
272}
273
274
275void
276Iob::generateIpi(Type type, int cpu_id, int vector)
277{
278 SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
279 if (cpu_id >= sys->getNumCPUs())
280 return;
281
282 switch (type) {
283 case 0: // interrupt
284 DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n",
285 cpu_id, vector);
286 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
287 break;
288 case 1: // reset
289 warn("Sending reset to CPU: %d\n", cpu_id);
290 if (vector != por->trapType())
291 panic("Don't know how to set non-POR reset to cpu\n");
292 por->invoke(sys->threadContexts[cpu_id]);
293 sys->threadContexts[cpu_id]->activate();
294 break;
295 case 2: // idle -- this means stop executing and don't wake on interrupts
296 DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
297 sys->threadContexts[cpu_id]->halt();
298 break;
299 case 3: // resume
300 DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
301 sys->threadContexts[cpu_id]->activate();
302 break;
303 default:
304 panic("Invalid type to generate ipi\n");
305 }
306}
307
308bool
309Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
310{
311 // If we are already dealing with an interrupt for that cpu we can't deal
312 // with another one right now... come back later
313 if (jIntBusy[cpu_id].busy)
314 return false;
315
316 DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
317 source, cpu_id, jIntVec);
318
319 jIntBusy[cpu_id].busy = true;
320 jIntBusy[cpu_id].source = source;
321 jBusData0[cpu_id] = d0;
322 jBusData1[cpu_id] = d1;
323
324 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
325 return true;
326}
327
328void
329Iob::addressRanges(AddrRangeList &range_list)
330{
331 range_list.clear();
332 range_list.push_back(RangeSize(iobManAddr, iobManSize));
333 range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
334}
335
336
337void
338Iob::serialize(std::ostream &os)
339{
340
341 SERIALIZE_SCALAR(jIntVec);
342 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
343 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
344 for (int x = 0; x < NumDeviceIds; x++) {
345 nameOut(os, csprintf("%s.Int%d", name(), x));
346 paramOut(os, "cpu", intMan[x].cpu);
347 paramOut(os, "vector", intMan[x].vector);
348 paramOut(os, "mask", intCtl[x].mask);
349 paramOut(os, "pend", intCtl[x].pend);
350 };
351 for (int x = 0; x < MaxNiagaraProcs; x++) {
352 nameOut(os, csprintf("%s.jIntBusy%d", name(), x));
353 paramOut(os, "busy", jIntBusy[x].busy);
354 paramOut(os, "source", jIntBusy[x].source);
355 };
356}
357
358void
359Iob::unserialize(Checkpoint *cp, const std::string &section)
360{
361 UNSERIALIZE_SCALAR(jIntVec);
362 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
363 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
364 for (int x = 0; x < NumDeviceIds; x++) {
365 paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu);
366 paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector);
367 paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask);
368 paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend);
369 };
370 for (int x = 0; x < MaxNiagaraProcs; x++) {
371 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy);
372 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source);
373 };
374}
375
376Iob *
377IobParams::create()
378{
379 return new Iob(this);
380}