gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
i82094aa.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 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: Gabe Black
29  */
30 
31 #include "dev/x86/i82094aa.hh"
32 
33 #include "arch/x86/interrupts.hh"
34 #include "arch/x86/intmessage.hh"
35 #include "cpu/base.hh"
36 #include "debug/I82094AA.hh"
37 #include "dev/x86/i8259.hh"
38 #include "mem/packet.hh"
39 #include "mem/packet_access.hh"
40 #include "sim/system.hh"
41 
43  : BasicPioDevice(p, 20), IntDevice(this, p->int_latency),
44  extIntPic(p->external_int_pic), lowestPriorityOffset(0)
45 {
46  // This assumes there's only one I/O APIC in the system and since the apic
47  // id is stored in a 8-bit field with 0xff meaning broadcast, the id must
48  // be less than 0xff
49 
50  assert(p->apic_id < 0xff);
51  initialApicId = id = p->apic_id;
52  arbId = id;
53  regSel = 0;
54  RedirTableEntry entry = 0;
55  entry.mask = 1;
56  for (int i = 0; i < TableSize; i++) {
57  redirTable[i] = entry;
58  pinStates[i] = false;
59  }
60 }
61 
62 void
64 {
65  // The io apic must register its address ranges on both its pio port
66  // via the piodevice init() function and its int port that it inherited
67  // from IntDevice. Note IntDevice is not a SimObject itself.
68 
71 }
72 
74 X86ISA::I82094AA::getMasterPort(const std::string &if_name, PortID idx)
75 {
76  if (if_name == "int_master")
77  return intMasterPort;
78  return BasicPioDevice::getMasterPort(if_name, idx);
79 }
80 
83 {
84  AddrRangeList ranges;
85  ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
86  x86InterruptAddress(initialApicId, 0) +
88  return ranges;
89 }
90 
91 Tick
93 {
94  // Packet instantiated calling sendMessage() in signalInterrupt()
95  delete pkt->req;
96  delete pkt;
97  return 0;
98 }
99 
100 Tick
102 {
103  assert(pkt->getSize() == 4);
104  Addr offset = pkt->getAddr() - pioAddr;
105  switch(offset) {
106  case 0:
107  pkt->set<uint32_t>(regSel);
108  break;
109  case 16:
110  pkt->set<uint32_t>(readReg(regSel));
111  break;
112  default:
113  panic("Illegal read from I/O APIC.\n");
114  }
115  pkt->makeAtomicResponse();
116  return pioDelay;
117 }
118 
119 Tick
121 {
122  assert(pkt->getSize() == 4);
123  Addr offset = pkt->getAddr() - pioAddr;
124  switch(offset) {
125  case 0:
126  regSel = pkt->get<uint32_t>();
127  break;
128  case 16:
129  writeReg(regSel, pkt->get<uint32_t>());
130  break;
131  default:
132  panic("Illegal write to I/O APIC.\n");
133  }
134  pkt->makeAtomicResponse();
135  return pioDelay;
136 }
137 
138 void
139 X86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value)
140 {
141  if (offset == 0x0) {
142  id = bits(value, 31, 24);
143  } else if (offset == 0x1) {
144  // The IOAPICVER register is read only.
145  } else if (offset == 0x2) {
146  arbId = bits(value, 31, 24);
147  } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
148  int index = (offset - 0x10) / 2;
149  if (offset % 2) {
150  redirTable[index].topDW = value;
151  redirTable[index].topReserved = 0;
152  } else {
153  redirTable[index].bottomDW = value;
154  redirTable[index].bottomReserved = 0;
155  }
156  } else {
157  warn("Access to undefined I/O APIC register %#x.\n", offset);
158  }
160  "Wrote %#x to I/O APIC register %#x .\n", value, offset);
161 }
162 
163 uint32_t
165 {
166  uint32_t result = 0;
167  if (offset == 0x0) {
168  result = id << 24;
169  } else if (offset == 0x1) {
170  result = ((TableSize - 1) << 16) | APICVersion;
171  } else if (offset == 0x2) {
172  result = arbId << 24;
173  } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
174  int index = (offset - 0x10) / 2;
175  if (offset % 2) {
176  result = redirTable[index].topDW;
177  } else {
178  result = redirTable[index].bottomDW;
179  }
180  } else {
181  warn("Access to undefined I/O APIC register %#x.\n", offset);
182  }
184  "Read %#x from I/O APIC register %#x.\n", result, offset);
185  return result;
186 }
187 
188 void
190 {
191  DPRINTF(I82094AA, "Received interrupt %d.\n", line);
192  assert(line < TableSize);
193  RedirTableEntry entry = redirTable[line];
194  if (entry.mask) {
195  DPRINTF(I82094AA, "Entry was masked.\n");
196  return;
197  } else {
198  TriggerIntMessage message = 0;
199  message.destination = entry.dest;
200  if (entry.deliveryMode == DeliveryMode::ExtInt) {
201  assert(extIntPic);
202  message.vector = extIntPic->getVector();
203  } else {
204  message.vector = entry.vector;
205  }
206  message.deliveryMode = entry.deliveryMode;
207  message.destMode = entry.destMode;
208  message.level = entry.polarity;
209  message.trigger = entry.trigger;
210  ApicList apics;
211  int numContexts = sys->numContexts();
212  if (message.destMode == 0) {
213  if (message.deliveryMode == DeliveryMode::LowestPriority) {
214  panic("Lowest priority delivery mode from the "
215  "IO APIC aren't supported in physical "
216  "destination mode.\n");
217  }
218  if (message.destination == 0xFF) {
219  for (int i = 0; i < numContexts; i++) {
220  apics.push_back(i);
221  }
222  } else {
223  apics.push_back(message.destination);
224  }
225  } else {
226  for (int i = 0; i < numContexts; i++) {
227  Interrupts *localApic = sys->getThreadContext(i)->
228  getCpuPtr()->getInterruptController(0);
229  if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
230  message.destination) {
231  apics.push_back(localApic->getInitialApicId());
232  }
233  }
234  if (message.deliveryMode == DeliveryMode::LowestPriority &&
235  apics.size()) {
236  // The manual seems to suggest that the chipset just does
237  // something reasonable for these instead of actually using
238  // state from the local APIC. We'll just rotate an offset
239  // through the set of APICs selected above.
240  uint64_t modOffset = lowestPriorityOffset % apics.size();
241  lowestPriorityOffset++;
242  ApicList::iterator apicIt = apics.begin();
243  while (modOffset--) {
244  apicIt++;
245  assert(apicIt != apics.end());
246  }
247  int selected = *apicIt;
248  apics.clear();
249  apics.push_back(selected);
250  }
251  }
252  intMasterPort.sendMessage(apics, message, sys->isTimingMode());
253  }
254 }
255 
256 void
258 {
259  assert(number < TableSize);
260  if (!pinStates[number])
261  signalInterrupt(number);
262  pinStates[number] = true;
263 }
264 
265 void
267 {
268  assert(number < TableSize);
269  pinStates[number] = false;
270 }
271 
272 void
274 {
275  uint64_t* redirTableArray = (uint64_t*)redirTable;
276  SERIALIZE_SCALAR(regSel);
277  SERIALIZE_SCALAR(initialApicId);
278  SERIALIZE_SCALAR(id);
279  SERIALIZE_SCALAR(arbId);
280  SERIALIZE_SCALAR(lowestPriorityOffset);
281  SERIALIZE_ARRAY(redirTableArray, TableSize);
282  SERIALIZE_ARRAY(pinStates, TableSize);
283 }
284 
285 void
287 {
288  uint64_t redirTableArray[TableSize];
289  UNSERIALIZE_SCALAR(regSel);
290  UNSERIALIZE_SCALAR(initialApicId);
291  UNSERIALIZE_SCALAR(id);
292  UNSERIALIZE_SCALAR(arbId);
293  UNSERIALIZE_SCALAR(lowestPriorityOffset);
294  UNSERIALIZE_ARRAY(redirTableArray, TableSize);
295  UNSERIALIZE_ARRAY(pinStates, TableSize);
296  for (int i = 0; i < TableSize; i++) {
297  redirTable[i] = (RedirTableEntry)redirTableArray[i];
298  }
299 }
300 
302 I82094AAParams::create()
303 {
304  return new X86ISA::I82094AA(this);
305 }
#define DPRINTF(x,...)
Definition: trace.hh:212
offset
Definition: misc.hh:977
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
bool pinStates[TableSize]
Definition: i82094aa.hh:82
Bitfield< 5, 3 > index
Definition: types.hh:95
Bitfield< 7 > i
Definition: miscregs.hh:1378
#define panic(...)
Definition: misc.hh:153
void init() override
Definition: i82094aa.cc:63
I82094AA(Params *p)
Definition: i82094aa.cc:42
void lowerInterruptPin(int number) override
Definition: i82094aa.cc:266
uint32_t readReg(ApicRegIndex miscReg)
Definition: interrupts.cc:362
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i82094aa.cc:120
virtual void init()
Definition: intdev.cc:67
PioDeviceParams Params
Definition: io_device.hh:116
BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a master port with a given name and index.
Definition: i82094aa.cc:74
Tick recvResponse(PacketPtr pkt) override
Definition: i82094aa.cc:92
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
#define warn(...)
Definition: misc.hh:219
static const uint8_t TableSize
Definition: i82094aa.hh:76
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i82094aa.cc:273
const Addr PhysAddrAPICRangeSize
Definition: x86_traits.hh:78
void raiseInterruptPin(int number) override
Definition: i82094aa.cc:257
static Addr x86InterruptAddress(const uint8_t id, const uint16_t addr)
Definition: x86_traits.hh:100
uint32_t readReg(uint8_t offset)
Definition: i82094aa.cc:164
void makeAtomicResponse()
Definition: packet.hh:857
uint64_t Tick
Tick count type.
Definition: types.hh:63
uint8_t arbId
Definition: i82094aa.hh:72
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i82094aa.cc:101
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
void writeReg(uint8_t offset, uint32_t value)
Definition: i82094aa.cc:139
uint8_t initialApicId
Definition: i82094aa.hh:70
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
EndBitUnion(RedirTableEntry) protected uint8_t regSel
Definition: i82094aa.hh:64
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
AddrRange RangeEx(Addr start, Addr end)
Definition: addr_range.hh:390
AddrRangeList getIntAddrRange() const override
Definition: i82094aa.cc:82
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:83
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:67
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
Definition: port.hh:115
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i82094aa.cc:286
RedirTableEntry redirTable[TableSize]
Definition: i82094aa.hh:81
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
unsigned getSize() const
Definition: packet.hh:649
void signalInterrupt(int line) override
Definition: i82094aa.cc:189
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
Definition: bitfield.hh:67
Bitfield< 0 > p
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: mem_object.cc:52
Addr getAddr() const
Definition: packet.hh:639

Generated on Fri Jun 9 2017 13:03:47 for gem5 by doxygen 1.8.6