intel_iommu.c (892721d91d9deb2affe4e61334b1dd1b43728f92) intel_iommu.c (07f7b73398de3b60f28301a9af2a2338710105c7)
1/*
2 * QEMU emulation of an Intel IOMMU (VT-d)
3 * (DMA Remapping device)
4 *
5 * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com>
6 * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify

--- 223 unchanged lines hidden (view full) ---

232 }
233
234out:
235 return entry;
236}
237
238static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id,
239 uint16_t domain_id, hwaddr addr, uint64_t slpte,
1/*
2 * QEMU emulation of an Intel IOMMU (VT-d)
3 * (DMA Remapping device)
4 *
5 * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com>
6 * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify

--- 223 unchanged lines hidden (view full) ---

232 }
233
234out:
235 return entry;
236}
237
238static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id,
239 uint16_t domain_id, hwaddr addr, uint64_t slpte,
240 bool read_flags, bool write_flags,
241 uint32_t level)
240 uint8_t access_flags, uint32_t level)
242{
243 VTDIOTLBEntry *entry = g_malloc(sizeof(*entry));
244 uint64_t *key = g_malloc(sizeof(*key));
245 uint64_t gfn = vtd_get_iotlb_gfn(addr, level);
246
247 trace_vtd_iotlb_page_update(source_id, addr, slpte, domain_id);
248 if (g_hash_table_size(s->iotlb) >= VTD_IOTLB_MAX_SIZE) {
249 trace_vtd_iotlb_reset("iotlb exceeds size limit");
250 vtd_reset_iotlb(s);
251 }
252
253 entry->gfn = gfn;
254 entry->domain_id = domain_id;
255 entry->slpte = slpte;
241{
242 VTDIOTLBEntry *entry = g_malloc(sizeof(*entry));
243 uint64_t *key = g_malloc(sizeof(*key));
244 uint64_t gfn = vtd_get_iotlb_gfn(addr, level);
245
246 trace_vtd_iotlb_page_update(source_id, addr, slpte, domain_id);
247 if (g_hash_table_size(s->iotlb) >= VTD_IOTLB_MAX_SIZE) {
248 trace_vtd_iotlb_reset("iotlb exceeds size limit");
249 vtd_reset_iotlb(s);
250 }
251
252 entry->gfn = gfn;
253 entry->domain_id = domain_id;
254 entry->slpte = slpte;
256 entry->read_flags = read_flags;
257 entry->write_flags = write_flags;
255 entry->access_flags = access_flags;
258 entry->mask = vtd_slpt_level_page_mask(level);
259 *key = vtd_get_iotlb_key(gfn, source_id, level);
260 g_hash_table_replace(s->iotlb, key, entry);
261}
262
263/* Given the reg addr of both the message data and address, generate an
264 * interrupt via MSI.
265 */

--- 816 unchanged lines hidden (view full) ---

1082 VTDContextCacheEntry *cc_entry = &vtd_as->context_cache_entry;
1083 uint64_t slpte, page_mask;
1084 uint32_t level;
1085 uint16_t source_id = vtd_make_source_id(bus_num, devfn);
1086 int ret_fr;
1087 bool is_fpd_set = false;
1088 bool reads = true;
1089 bool writes = true;
256 entry->mask = vtd_slpt_level_page_mask(level);
257 *key = vtd_get_iotlb_key(gfn, source_id, level);
258 g_hash_table_replace(s->iotlb, key, entry);
259}
260
261/* Given the reg addr of both the message data and address, generate an
262 * interrupt via MSI.
263 */

--- 816 unchanged lines hidden (view full) ---

1080 VTDContextCacheEntry *cc_entry = &vtd_as->context_cache_entry;
1081 uint64_t slpte, page_mask;
1082 uint32_t level;
1083 uint16_t source_id = vtd_make_source_id(bus_num, devfn);
1084 int ret_fr;
1085 bool is_fpd_set = false;
1086 bool reads = true;
1087 bool writes = true;
1088 uint8_t access_flags;
1090 VTDIOTLBEntry *iotlb_entry;
1091
1092 /*
1093 * We have standalone memory region for interrupt addresses, we
1094 * should never receive translation requests in this region.
1095 */
1096 assert(!vtd_is_interrupt_addr(addr));
1097
1098 /* Try to fetch slpte form IOTLB */
1099 iotlb_entry = vtd_lookup_iotlb(s, source_id, addr);
1100 if (iotlb_entry) {
1101 trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->slpte,
1102 iotlb_entry->domain_id);
1103 slpte = iotlb_entry->slpte;
1089 VTDIOTLBEntry *iotlb_entry;
1090
1091 /*
1092 * We have standalone memory region for interrupt addresses, we
1093 * should never receive translation requests in this region.
1094 */
1095 assert(!vtd_is_interrupt_addr(addr));
1096
1097 /* Try to fetch slpte form IOTLB */
1098 iotlb_entry = vtd_lookup_iotlb(s, source_id, addr);
1099 if (iotlb_entry) {
1100 trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->slpte,
1101 iotlb_entry->domain_id);
1102 slpte = iotlb_entry->slpte;
1104 reads = iotlb_entry->read_flags;
1105 writes = iotlb_entry->write_flags;
1103 access_flags = iotlb_entry->access_flags;
1106 page_mask = iotlb_entry->mask;
1107 goto out;
1108 }
1109
1110 /* Try to fetch context-entry from cache first */
1111 if (cc_entry->context_cache_gen == s->context_cache_gen) {
1112 trace_vtd_iotlb_cc_hit(bus_num, devfn, cc_entry->context_entry.hi,
1113 cc_entry->context_entry.lo,

--- 53 unchanged lines hidden (view full) ---

1167 trace_vtd_fault_disabled();
1168 } else {
1169 vtd_report_dmar_fault(s, source_id, addr, ret_fr, is_write);
1170 }
1171 goto error;
1172 }
1173
1174 page_mask = vtd_slpt_level_page_mask(level);
1104 page_mask = iotlb_entry->mask;
1105 goto out;
1106 }
1107
1108 /* Try to fetch context-entry from cache first */
1109 if (cc_entry->context_cache_gen == s->context_cache_gen) {
1110 trace_vtd_iotlb_cc_hit(bus_num, devfn, cc_entry->context_entry.hi,
1111 cc_entry->context_entry.lo,

--- 53 unchanged lines hidden (view full) ---

1165 trace_vtd_fault_disabled();
1166 } else {
1167 vtd_report_dmar_fault(s, source_id, addr, ret_fr, is_write);
1168 }
1169 goto error;
1170 }
1171
1172 page_mask = vtd_slpt_level_page_mask(level);
1173 access_flags = IOMMU_ACCESS_FLAG(reads, writes);
1175 vtd_update_iotlb(s, source_id, VTD_CONTEXT_ENTRY_DID(ce.hi), addr, slpte,
1174 vtd_update_iotlb(s, source_id, VTD_CONTEXT_ENTRY_DID(ce.hi), addr, slpte,
1176 reads, writes, level);
1175 access_flags, level);
1177out:
1178 entry->iova = addr & page_mask;
1179 entry->translated_addr = vtd_get_slpte_addr(slpte) & page_mask;
1180 entry->addr_mask = ~page_mask;
1176out:
1177 entry->iova = addr & page_mask;
1178 entry->translated_addr = vtd_get_slpte_addr(slpte) & page_mask;
1179 entry->addr_mask = ~page_mask;
1181 entry->perm = IOMMU_ACCESS_FLAG(reads, writes);
1180 entry->perm = access_flags;
1182 return true;
1183
1184error:
1185 entry->iova = 0;
1186 entry->translated_addr = 0;
1187 entry->addr_mask = 0;
1188 entry->perm = IOMMU_NONE;
1189 return false;

--- 1908 unchanged lines hidden ---
1181 return true;
1182
1183error:
1184 entry->iova = 0;
1185 entry->translated_addr = 0;
1186 entry->addr_mask = 0;
1187 entry->perm = IOMMU_NONE;
1188 return false;

--- 1908 unchanged lines hidden ---