11c7955c4SPeter Xu /* 21c7955c4SPeter Xu * Common IOMMU interface for X86 platform 31c7955c4SPeter Xu * 41c7955c4SPeter Xu * Copyright (C) 2016 Peter Xu, Red Hat <peterx@redhat.com> 51c7955c4SPeter Xu * 61c7955c4SPeter Xu * This program is free software; you can redistribute it and/or modify 71c7955c4SPeter Xu * it under the terms of the GNU General Public License as published by 81c7955c4SPeter Xu * the Free Software Foundation; either version 2 of the License, or 91c7955c4SPeter Xu * (at your option) any later version. 101c7955c4SPeter Xu 111c7955c4SPeter Xu * This program is distributed in the hope that it will be useful, 121c7955c4SPeter Xu * but WITHOUT ANY WARRANTY; without even the implied warranty of 131c7955c4SPeter Xu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141c7955c4SPeter Xu * GNU General Public License for more details. 151c7955c4SPeter Xu 161c7955c4SPeter Xu * You should have received a copy of the GNU General Public License along 171c7955c4SPeter Xu * with this program; if not, see <http://www.gnu.org/licenses/>. 181c7955c4SPeter Xu */ 191c7955c4SPeter Xu 2058ea30f5SMarkus Armbruster #ifndef HW_I386_X86_IOMMU_H 2158ea30f5SMarkus Armbruster #define HW_I386_X86_IOMMU_H 221c7955c4SPeter Xu 231c7955c4SPeter Xu #include "hw/sysbus.h" 2435c24501SSingh, Brijesh #include "hw/pci/msi.h" 25db1015e9SEduardo Habkost #include "qom/object.h" 261c7955c4SPeter Xu 271c7955c4SPeter Xu #define TYPE_X86_IOMMU_DEVICE ("x86-iommu") 28a489d195SEduardo Habkost OBJECT_DECLARE_TYPE(X86IOMMUState, X86IOMMUClass, X86_IOMMU_DEVICE) 291c7955c4SPeter Xu 308b5ed7dfSPeter Xu #define X86_IOMMU_SID_INVALID (0xffff) 3104af0e18SPeter Xu 3235c24501SSingh, Brijesh typedef struct X86IOMMUIrq X86IOMMUIrq; 3335c24501SSingh, Brijesh typedef struct X86IOMMU_MSIMessage X86IOMMU_MSIMessage; 341c7955c4SPeter Xu 351c7955c4SPeter Xu struct X86IOMMUClass { 361c7955c4SPeter Xu SysBusDeviceClass parent; 371c7955c4SPeter Xu /* Intel/AMD specific realize() hook */ 381c7955c4SPeter Xu DeviceRealize realize; 398b5ed7dfSPeter Xu /* MSI-based interrupt remapping */ 408b5ed7dfSPeter Xu int (*int_remap)(X86IOMMUState *iommu, MSIMessage *src, 418b5ed7dfSPeter Xu MSIMessage *dst, uint16_t sid); 421c7955c4SPeter Xu }; 431c7955c4SPeter Xu 4402a2cbc8SPeter Xu /** 4502a2cbc8SPeter Xu * iec_notify_fn - IEC (Interrupt Entry Cache) notifier hook, 4602a2cbc8SPeter Xu * triggered when IR invalidation happens. 4702a2cbc8SPeter Xu * @private: private data 4802a2cbc8SPeter Xu * @global: whether this is a global IEC invalidation 4902a2cbc8SPeter Xu * @index: IRTE index to invalidate (start from) 5002a2cbc8SPeter Xu * @mask: invalidation mask 5102a2cbc8SPeter Xu */ 5202a2cbc8SPeter Xu typedef void (*iec_notify_fn)(void *private, bool global, 5302a2cbc8SPeter Xu uint32_t index, uint32_t mask); 5402a2cbc8SPeter Xu 5502a2cbc8SPeter Xu struct IEC_Notifier { 5602a2cbc8SPeter Xu iec_notify_fn iec_notify; 5702a2cbc8SPeter Xu void *private; 5802a2cbc8SPeter Xu QLIST_ENTRY(IEC_Notifier) list; 5902a2cbc8SPeter Xu }; 6002a2cbc8SPeter Xu typedef struct IEC_Notifier IEC_Notifier; 6102a2cbc8SPeter Xu 621c7955c4SPeter Xu struct X86IOMMUState { 631c7955c4SPeter Xu SysBusDevice busdev; 64a924b3d8SPeter Xu OnOffAuto intr_supported; /* Whether vIOMMU supports IR */ 65554f5e16SJason Wang bool dt_supported; /* Whether vIOMMU supports DT */ 66dbaabb25SPeter Xu bool pt_supported; /* Whether vIOMMU supports pass-through */ 6702a2cbc8SPeter Xu QLIST_HEAD(, IEC_Notifier) iec_notifiers; /* IEC notify list */ 681c7955c4SPeter Xu }; 691c7955c4SPeter Xu 70a924b3d8SPeter Xu bool x86_iommu_ir_supported(X86IOMMUState *s); 71a924b3d8SPeter Xu 7235c24501SSingh, Brijesh /* Generic IRQ entry information when interrupt remapping is enabled */ 7335c24501SSingh, Brijesh struct X86IOMMUIrq { 7435c24501SSingh, Brijesh /* Used by both IOAPIC/MSI interrupt remapping */ 7535c24501SSingh, Brijesh uint8_t trigger_mode; 7635c24501SSingh, Brijesh uint8_t vector; 7735c24501SSingh, Brijesh uint8_t delivery_mode; 7835c24501SSingh, Brijesh uint32_t dest; 7935c24501SSingh, Brijesh uint8_t dest_mode; 8035c24501SSingh, Brijesh 8135c24501SSingh, Brijesh /* only used by MSI interrupt remapping */ 8235c24501SSingh, Brijesh uint8_t redir_hint; 8335c24501SSingh, Brijesh uint8_t msi_addr_last_bits; 8435c24501SSingh, Brijesh }; 8535c24501SSingh, Brijesh 8635c24501SSingh, Brijesh struct X86IOMMU_MSIMessage { 8735c24501SSingh, Brijesh union { 8835c24501SSingh, Brijesh struct { 89e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 90*e1e56c07SThomas Huth uint64_t __addr_hi:32; 91*e1e56c07SThomas Huth uint64_t __addr_head:12; /* 0xfee */ 92*e1e56c07SThomas Huth uint64_t dest:8; 93*e1e56c07SThomas Huth uint64_t __reserved:8; 94*e1e56c07SThomas Huth uint64_t redir_hint:1; 95*e1e56c07SThomas Huth uint64_t dest_mode:1; 96*e1e56c07SThomas Huth uint64_t __not_used:2; 9735c24501SSingh, Brijesh #else 98*e1e56c07SThomas Huth uint64_t __not_used:2; 99*e1e56c07SThomas Huth uint64_t dest_mode:1; 100*e1e56c07SThomas Huth uint64_t redir_hint:1; 101*e1e56c07SThomas Huth uint64_t __reserved:8; 102*e1e56c07SThomas Huth uint64_t dest:8; 103*e1e56c07SThomas Huth uint64_t __addr_head:12; /* 0xfee */ 104*e1e56c07SThomas Huth uint64_t __addr_hi:32; 10535c24501SSingh, Brijesh #endif 10635c24501SSingh, Brijesh } QEMU_PACKED; 10735c24501SSingh, Brijesh uint64_t msi_addr; 10835c24501SSingh, Brijesh }; 10935c24501SSingh, Brijesh union { 11035c24501SSingh, Brijesh struct { 111e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 112*e1e56c07SThomas Huth uint32_t __resved1:16; 113*e1e56c07SThomas Huth uint32_t trigger_mode:1; 114*e1e56c07SThomas Huth uint32_t level:1; 115*e1e56c07SThomas Huth uint32_t __resved:3; 116*e1e56c07SThomas Huth uint32_t delivery_mode:3; 117*e1e56c07SThomas Huth uint32_t vector:8; 11835c24501SSingh, Brijesh #else 119*e1e56c07SThomas Huth uint32_t vector:8; 120*e1e56c07SThomas Huth uint32_t delivery_mode:3; 121*e1e56c07SThomas Huth uint32_t __resved:3; 122*e1e56c07SThomas Huth uint32_t level:1; 123*e1e56c07SThomas Huth uint32_t trigger_mode:1; 124*e1e56c07SThomas Huth uint32_t __resved1:16; 12535c24501SSingh, Brijesh #endif 12635c24501SSingh, Brijesh } QEMU_PACKED; 12735c24501SSingh, Brijesh uint32_t msi_data; 12835c24501SSingh, Brijesh }; 12935c24501SSingh, Brijesh }; 13035c24501SSingh, Brijesh 1311cf5fd57SPeter Xu /** 1321cf5fd57SPeter Xu * x86_iommu_get_default - get default IOMMU device 1331cf5fd57SPeter Xu * @return: pointer to default IOMMU device 1341cf5fd57SPeter Xu */ 1351cf5fd57SPeter Xu X86IOMMUState *x86_iommu_get_default(void); 1361cf5fd57SPeter Xu 13702a2cbc8SPeter Xu /** 13802a2cbc8SPeter Xu * x86_iommu_iec_register_notifier - register IEC (Interrupt Entry 13902a2cbc8SPeter Xu * Cache) notifiers 14002a2cbc8SPeter Xu * @iommu: IOMMU device to register 14102a2cbc8SPeter Xu * @fn: IEC notifier hook function 14202a2cbc8SPeter Xu * @data: notifier private data 14302a2cbc8SPeter Xu */ 14402a2cbc8SPeter Xu void x86_iommu_iec_register_notifier(X86IOMMUState *iommu, 14502a2cbc8SPeter Xu iec_notify_fn fn, void *data); 14602a2cbc8SPeter Xu 14702a2cbc8SPeter Xu /** 14802a2cbc8SPeter Xu * x86_iommu_iec_notify_all - Notify IEC invalidations 14902a2cbc8SPeter Xu * @iommu: IOMMU device that sends the notification 15002a2cbc8SPeter Xu * @global: whether this is a global invalidation. If true, @index 15102a2cbc8SPeter Xu * and @mask are undefined. 15202a2cbc8SPeter Xu * @index: starting index of interrupt entry to invalidate 15302a2cbc8SPeter Xu * @mask: index mask for the invalidation 15402a2cbc8SPeter Xu */ 15502a2cbc8SPeter Xu void x86_iommu_iec_notify_all(X86IOMMUState *iommu, bool global, 15602a2cbc8SPeter Xu uint32_t index, uint32_t mask); 15702a2cbc8SPeter Xu 15835c24501SSingh, Brijesh /** 15935c24501SSingh, Brijesh * x86_iommu_irq_to_msi_message - Populate one MSIMessage from X86IOMMUIrq 16035c24501SSingh, Brijesh * @X86IOMMUIrq: The IRQ information 16135c24501SSingh, Brijesh * @out: Output MSI message 16235c24501SSingh, Brijesh */ 16335c24501SSingh, Brijesh void x86_iommu_irq_to_msi_message(X86IOMMUIrq *irq, MSIMessage *out); 1641c7955c4SPeter Xu #endif 165