i82094aa.cc revision 5653:b87e45d7c585
18112Sgblack@eecs.umich.edu/* 28112Sgblack@eecs.umich.edu * Copyright (c) 2008 The Regents of The University of Michigan 38112Sgblack@eecs.umich.edu * All rights reserved. 48112Sgblack@eecs.umich.edu * 58112Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 68112Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 78112Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 88112Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 98112Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 108112Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 118112Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 128112Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 138112Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 148112Sgblack@eecs.umich.edu * this software without specific prior written permission. 158112Sgblack@eecs.umich.edu * 168112Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 178112Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 188112Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198112Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208112Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 218112Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228112Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238112Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248112Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258112Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 268112Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278112Sgblack@eecs.umich.edu * 288112Sgblack@eecs.umich.edu * Authors: Gabe Black 298113Sgblack@eecs.umich.edu */ 308113Sgblack@eecs.umich.edu 318113Sgblack@eecs.umich.edu#include "arch/x86/intmessage.hh" 328113Sgblack@eecs.umich.edu#include "dev/x86/i82094aa.hh" 338113Sgblack@eecs.umich.edu#include "mem/packet.hh" 348113Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 358113Sgblack@eecs.umich.edu#include "sim/system.hh" 368113Sgblack@eecs.umich.edu 378113Sgblack@eecs.umich.eduX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), 3811320Ssteve.reinhardt@amd.com latency(p->pio_latency), pioAddr(p->pio_addr) 398113Sgblack@eecs.umich.edu{ 408113Sgblack@eecs.umich.edu // This assumes there's only one I/O APIC in the system 418113Sgblack@eecs.umich.edu id = sys->getNumCPUs(); 428113Sgblack@eecs.umich.edu assert(id <= 0xf); 438113Sgblack@eecs.umich.edu arbId = id; 448113Sgblack@eecs.umich.edu regSel = 0; 458113Sgblack@eecs.umich.edu RedirTableEntry entry = 0; 468113Sgblack@eecs.umich.edu entry.mask = 1; 478113Sgblack@eecs.umich.edu for (int i = 0; i < TableSize; i++) { 488113Sgblack@eecs.umich.edu redirTable[i] = entry; 498113Sgblack@eecs.umich.edu } 508113Sgblack@eecs.umich.edu} 518113Sgblack@eecs.umich.edu 528117Sgblack@eecs.umich.eduTick 538113Sgblack@eecs.umich.eduX86ISA::I82094AA::read(PacketPtr pkt) 548113Sgblack@eecs.umich.edu{ 558113Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 568113Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 578113Sgblack@eecs.umich.edu switch(offset) { 588113Sgblack@eecs.umich.edu case 0: 598113Sgblack@eecs.umich.edu pkt->set<uint32_t>(regSel); 608113Sgblack@eecs.umich.edu break; 618113Sgblack@eecs.umich.edu case 16: 628113Sgblack@eecs.umich.edu pkt->set<uint32_t>(readReg(regSel)); 638113Sgblack@eecs.umich.edu break; 648113Sgblack@eecs.umich.edu default: 658113Sgblack@eecs.umich.edu panic("Illegal read from I/O APIC.\n"); 668113Sgblack@eecs.umich.edu } 678113Sgblack@eecs.umich.edu return latency; 68} 69 70Tick 71X86ISA::I82094AA::write(PacketPtr pkt) 72{ 73 assert(pkt->getSize() == 4); 74 Addr offset = pkt->getAddr() - pioAddr; 75 switch(offset) { 76 case 0: 77 regSel = pkt->get<uint32_t>(); 78 break; 79 case 16: 80 writeReg(regSel, pkt->get<uint32_t>()); 81 break; 82 default: 83 panic("Illegal write to I/O APIC.\n"); 84 } 85 return latency; 86} 87 88void 89X86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 90{ 91 if (offset == 0x0) { 92 id = bits(value, 27, 24); 93 } else if (offset == 0x1) { 94 // The IOAPICVER register is read only. 95 } else if (offset == 0x2) { 96 arbId = bits(value, 27, 24); 97 } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 98 int index = (offset - 0x10) / 2; 99 if (offset % 2) { 100 redirTable[index].topDW = value; 101 redirTable[index].topReserved = 0; 102 } else { 103 redirTable[index].bottomDW = value; 104 redirTable[index].bottomReserved = 0; 105 } 106 } else { 107 warn("Access to undefined I/O APIC register %#x.\n", offset); 108 } 109 DPRINTF(I82094AA, 110 "Wrote %#x to I/O APIC register %#x .\n", value, offset); 111} 112 113uint32_t 114X86ISA::I82094AA::readReg(uint8_t offset) 115{ 116 uint32_t result = 0; 117 if (offset == 0x0) { 118 result = id << 24; 119 } else if (offset == 0x1) { 120 result = ((TableSize - 1) << 16) | APICVersion; 121 } else if (offset == 0x2) { 122 result = arbId << 24; 123 } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 124 int index = (offset - 0x10) / 2; 125 if (offset % 2) { 126 result = redirTable[index].topDW; 127 } else { 128 result = redirTable[index].bottomDW; 129 } 130 } else { 131 warn("Access to undefined I/O APIC register %#x.\n", offset); 132 } 133 DPRINTF(I82094AA, 134 "Read %#x from I/O APIC register %#x.\n", result, offset); 135 return result; 136} 137 138void 139X86ISA::I82094AA::signalInterrupt(int line) 140{ 141 DPRINTF(I82094AA, "Received interrupt %d.\n", line); 142 assert(line < TableSize); 143 RedirTableEntry entry = redirTable[line]; 144 if (entry.mask) { 145 DPRINTF(I82094AA, "Entry was masked.\n"); 146 return; 147 } else { 148 if (DTRACE(I82094AA)) { 149 switch(entry.deliveryMode) { 150 case 0: 151 DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); 152 break; 153 case 1: 154 DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); 155 break; 156 case 2: 157 DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); 158 break; 159 case 3: 160 fatal("Tried to use reserved delivery mode " 161 "for IO APIC entry %d.\n", line); 162 break; 163 case 4: 164 DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); 165 break; 166 case 5: 167 DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); 168 break; 169 case 6: 170 fatal("Tried to use reserved delivery mode " 171 "for IO APIC entry %d.\n", line); 172 break; 173 case 7: 174 DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); 175 break; 176 } 177 DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); 178 } 179 180 TriggerIntMessage message; 181 message.destination = entry.dest; 182 message.vector = entry.vector; 183 message.deliveryMode = entry.deliveryMode; 184 message.destMode = entry.destMode; 185 186 if (entry.destMode == 0) { 187 DPRINTF(I82094AA, 188 "Sending interrupt to APIC ID %d.\n", entry.dest); 189 PacketPtr pkt = buildIntRequest(entry.dest, message); 190 if (sys->getMemoryMode() == Enums::timing) 191 intPort->sendMessageTiming(pkt, latency); 192 else if (sys->getMemoryMode() == Enums::atomic) 193 intPort->sendMessageAtomic(pkt); 194 else 195 panic("Unrecognized memory mode.\n"); 196 } else { 197 DPRINTF(I82094AA, "Sending interrupts to APIC IDs:" 198 "%s%s%s%s%s%s%s%s\n", 199 bits((int)entry.dest, 0) ? " 0": "", 200 bits((int)entry.dest, 1) ? " 1": "", 201 bits((int)entry.dest, 2) ? " 2": "", 202 bits((int)entry.dest, 3) ? " 3": "", 203 bits((int)entry.dest, 4) ? " 4": "", 204 bits((int)entry.dest, 5) ? " 5": "", 205 bits((int)entry.dest, 6) ? " 6": "", 206 bits((int)entry.dest, 7) ? " 7": "" 207 ); 208 uint8_t dests = entry.dest; 209 uint8_t id = 0; 210 while(dests) { 211 if (dests & 0x1) { 212 PacketPtr pkt = buildIntRequest(id, message); 213 if (sys->getMemoryMode() == Enums::timing) 214 intPort->sendMessageTiming(pkt, latency); 215 else if (sys->getMemoryMode() == Enums::atomic) 216 intPort->sendMessageAtomic(pkt); 217 else 218 panic("Unrecognized memory mode.\n"); 219 } 220 dests >>= 1; 221 id++; 222 } 223 } 224 } 225} 226 227X86ISA::I82094AA * 228I82094AAParams::create() 229{ 230 return new X86ISA::I82094AA(this); 231} 232