kernel/source/devices/pc/apic/ioapic.cpp
// returns false if the system does not have an APIC!
returns false if the system does not have an APIC!
returns false if the system does not have an APIC!
bool init()
	{
		if(IoApics.empty())
		{
			scheduler::registerCPU(true, 0, 0, 0);
			return false;
		}
		array<VirtAddr> mappedBases;
		for(auto& _ioa : IoApics)
		{
			auto ioa = &_ioa;
			auto alignedBase = VirtAddr(ioa->baseAddr).pageAligned();
			if(mappedBases.find(alignedBase) == mappedBases.end())
			{
				if(vmm::allocateSpecific(alignedBase, 1).isZero())
					abort("ioapic: failed to map base address {p}", ioa->baseAddr);
				vmm::mapAddress(alignedBase, alignedBase.physIdentity(), 1, vmm::PAGE_PRESENT | vmm::PAGE_WRITE);
				mappedBases.append(alignedBase);
			}
			int id = (readIOAPIC(ioa, IOAPIC_REG_ID) & 0xF000000) >> 24;
			if(id != ioa->id)
			{
				warn("ioapic", "mismatch in ioapic id! MADT reported {}, actual value is {}", ioa->id, id);
			}
			{
				uint32_t reg = readIOAPIC(ioa, IOAPIC_REG_VERSION);
				ioa->maxRedirections = (reg & 0xFF0000) >> 16;
				log("ioapic", "[{}]: ver {x}, {} intrs, gsi {}", ioa->id, reg & 0xFF, ioa->maxRedirections, ioa->gsiBase);
			}
		}
		return true;
	}
bool init ( ) { if ( IoApics . empty ( ) ) { scheduler :: registerCPU ( true , 0 , 0 , 0 ) ; return false ; } array < VirtAddr > mappedBases ; for ( auto & _ioa : IoApics ) { auto ioa = & _ioa ; auto alignedBase = VirtAddr ( ioa -> baseAddr ) . pageAligned ( ) ; if ( mappedBases . find ( alignedBase ) == mappedBases . end ( ) ) { if ( vmm :: allocateSpecific ( alignedBase , 1 ) . isZero ( ) ) abort ( " " , ioa -> baseAddr ) ; vmm :: mapAddress ( alignedBase , alignedBase . physIdentity ( ) , 1 , vmm :: PAGE_PRESENT | vmm :: PAGE_WRITE ) ; mappedBases . append ( alignedBase ) ; } int id = ( readIOAPIC ( ioa , IOAPIC_REG_ID ) & 0xF000000 ) >> 24 ; if ( id != ioa -> id ) { warn ( " " , " " , ioa -> id , id ) ; } { uint32_t reg = readIOAPIC ( ioa , IOAPIC_REG_VERSION ) ; ioa -> maxRedirections = ( reg & 0xFF0000 ) >> 16 ; log ( " " , " " , ioa -> id , reg & 0xFF , ioa -> maxRedirections , ioa -> gsiBase ) ; } } return true ; }
returns false if the system does not have an APIC!
returns false if the system does not have an APIC!
// if we do not have ioapics, then we do not have lapics or whatever. // so, we return false -- falling back to the normal 8259 pic. // but first, we need to setup a fake processor. // initialise all ioapics // reference: https://pdos.csail.mit.edu/6.828/2006/readings/ia32/ioapic.pdf // for the ioapic base address, the specs say FEC0 xy00h, where x is 0-F. // so, there are 16 possible pages we need to map (if the system has a fuckload of ioapics) // but, because there can be more than one ioapic in one page, and there's no guarantee that // we get them in any sorted order (eg. in increasing base address), we keep track of the physical // pages that we have already mapped, so we do not double map them (because we can't!) // note: "we can't" above refers to the fact that we need to allocate the virtual address space in the lower 4GB, // so if we've already allocated it then we can't allocate it again! (duh) // sanity check. // under normal circumstances I would make this an error, BUT the virtualbox people aren't very smart // they set the IOAPIC's id in the MADT to the number of cpus in the system!!! // which wouldn't be so bad if the id register of the IOAPIC matched, but it doesn't!! // https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Devices/PC/DevACPI.cpp#L2993 // get the number of interrupts this guy handles.