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 §ion) 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 §ion) 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}
|