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; } }
static void sendIOSpace(uint32_t pci_request_id) { uint32_t vtd_root_index; uint32_t vtd_context_index; vtd_rte_t* vtd_root_slot; vtd_cte_t* vtd_context; vtd_cte_t* vtd_context_slot; vtd_root_index = get_pci_bus(pci_request_id); vtd_root_slot = x86KSvtdRootTable + vtd_root_index; vtd_context = (vtd_cte_t*)paddr_to_pptr(vtd_rte_ptr_get_ctp(vtd_root_slot)); vtd_context_index = (get_pci_dev(pci_request_id) << 3) | get_pci_fun(pci_request_id); vtd_context_slot = &vtd_context[vtd_context_index]; if (vtd_cte_ptr_get_present(vtd_context_slot)) { sendWord(vtd_cte_ptr_get_asr(vtd_context_slot)); } else { sendWord(0); } }