intel_iommu.c (e85c0d14014514a2f0faeae5b4c23fab5b234de4) intel_iommu.c (8991c460be5a0811194fd4d2b49ba7146a23526b)
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

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

1445
1446 default:
1447 trace_vtd_err("IOTLB flush: invalid granularity.");
1448 iaig = 0;
1449 }
1450 return iaig;
1451}
1452
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

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

1445
1446 default:
1447 trace_vtd_err("IOTLB flush: invalid granularity.");
1448 iaig = 0;
1449 }
1450 return iaig;
1451}
1452
1453static inline bool vtd_queued_inv_enable_check(IntelIOMMUState *s)
1454{
1455 return s->iq_tail == 0;
1456}
1453static void vtd_fetch_inv_desc(IntelIOMMUState *s);
1457
1458static inline bool vtd_queued_inv_disable_check(IntelIOMMUState *s)
1459{
1460 return s->qi_enabled && (s->iq_tail == s->iq_head) &&
1461 (s->iq_last_desc_type == VTD_INV_DESC_WAIT);
1462}
1463
1464static void vtd_handle_gcmd_qie(IntelIOMMUState *s, bool en)
1465{
1466 uint64_t iqa_val = vtd_get_quad_raw(s, DMAR_IQA_REG);
1467
1468 trace_vtd_inv_qi_enable(en);
1469
1470 if (en) {
1454
1455static inline bool vtd_queued_inv_disable_check(IntelIOMMUState *s)
1456{
1457 return s->qi_enabled && (s->iq_tail == s->iq_head) &&
1458 (s->iq_last_desc_type == VTD_INV_DESC_WAIT);
1459}
1460
1461static void vtd_handle_gcmd_qie(IntelIOMMUState *s, bool en)
1462{
1463 uint64_t iqa_val = vtd_get_quad_raw(s, DMAR_IQA_REG);
1464
1465 trace_vtd_inv_qi_enable(en);
1466
1467 if (en) {
1471 if (vtd_queued_inv_enable_check(s)) {
1472 s->iq = iqa_val & VTD_IQA_IQA_MASK;
1473 /* 2^(x+8) entries */
1474 s->iq_size = 1UL << ((iqa_val & VTD_IQA_QS) + 8);
1475 s->qi_enabled = true;
1476 trace_vtd_inv_qi_setup(s->iq, s->iq_size);
1477 /* Ok - report back to driver */
1478 vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_QIES);
1479 } else {
1480 trace_vtd_err_qi_enable(s->iq_tail);
1468 s->iq = iqa_val & VTD_IQA_IQA_MASK;
1469 /* 2^(x+8) entries */
1470 s->iq_size = 1UL << ((iqa_val & VTD_IQA_QS) + 8);
1471 s->qi_enabled = true;
1472 trace_vtd_inv_qi_setup(s->iq, s->iq_size);
1473 /* Ok - report back to driver */
1474 vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_QIES);
1475
1476 if (s->iq_tail != 0) {
1477 /*
1478 * This is a spec violation but Windows guests are known to set up
1479 * Queued Invalidation this way so we allow the write and process
1480 * Invalidation Descriptors right away.
1481 */
1482 trace_vtd_warn_invalid_qi_tail(s->iq_tail);
1483 if (!(vtd_get_long_raw(s, DMAR_FSTS_REG) & VTD_FSTS_IQE)) {
1484 vtd_fetch_inv_desc(s);
1485 }
1481 }
1482 } else {
1483 if (vtd_queued_inv_disable_check(s)) {
1484 /* disable Queued Invalidation */
1485 vtd_set_quad_raw(s, DMAR_IQH_REG, 0);
1486 s->iq_head = 0;
1487 s->qi_enabled = false;
1488 /* Ok - report back to driver */

--- 1573 unchanged lines hidden ---
1486 }
1487 } else {
1488 if (vtd_queued_inv_disable_check(s)) {
1489 /* disable Queued Invalidation */
1490 vtd_set_quad_raw(s, DMAR_IQH_REG, 0);
1491 s->iq_head = 0;
1492 s->qi_enabled = false;
1493 /* Ok - report back to driver */

--- 1573 unchanged lines hidden ---