cap_t CONST Arch_updateCapData(bool_t preserve, word_t data, cap_t cap) { switch (cap_get_capType(cap)) { #ifdef CONFIG_IOMMU case cap_io_space_cap: { io_space_capdata_t w = { { data } }; uint16_t PCIDevice = io_space_capdata_get_PCIDevice(w); uint16_t domainID = io_space_capdata_get_domainID(w); vtd_cte_t *vtd_context_table = (vtd_cte_t*)vtd_rte_get_ctp(ia32KSvtdRootTable[get_pci_bus(data)]); if (!preserve && cap_io_space_cap_get_capPCIDevice(cap) == 0 && vtd_rte_get_present(ia32KSvtdRootTable[get_pci_bus(data)]) && (!vtd_cte_get_present(vtd_context_table[PCIDevice & 0xff]) || vtd_cte_get_translation_type(vtd_context_table[PCIDevice & 0xff]) != 2) && domainID <= MASK(ia32KSnumIODomainIDBits)) { return cap_io_space_cap_new(domainID, PCIDevice); } else { return cap_null_cap_new(); } } #endif case cap_io_port_cap: { io_port_capdata_t w = { .words = { data } }; uint16_t firstPort = io_port_capdata_get_firstPort(w); uint16_t lastPort = io_port_capdata_get_lastPort(w); uint16_t capFirstPort = cap_io_port_cap_get_capIOPortFirstPort(cap); uint16_t capLastPort = cap_io_port_cap_get_capIOPortLastPort(cap); assert(capFirstPort <= capLastPort); /* Ensure input data is ordered correctly. */ if (firstPort > lastPort) { return cap_null_cap_new(); } /* Allow the update if the new cap has range no larger than the old * cap. */ if ((firstPort >= capFirstPort) && (lastPort <= capLastPort)) { return cap_io_port_cap_new(firstPort, lastPort); } else { return cap_null_cap_new(); } } default: return cap; } }
exception_t invokeSetIOPort(vcpu_t *vcpu, cap_t cap) { uint32_t high, low; vcpu->io_port = cap; low = cap_io_port_cap_get_capIOPortFirstPort(cap); high = cap_io_port_cap_get_capIOPortLastPort(cap) + 1; // Set the range vcpu->io_min = low; vcpu->io_max = high; // Clear the IO ports /* There is no point clearing the IO ports as we have no * security model anyway, so might as well let multiple * io ports be set to allow different ranges to be * masked */ // memset(vcpu->io, ~0, 8192); return EXCEPTION_NONE; }