The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/vmm/amd/amdvi_priv.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2016 Anish Gupta (anish@freebsd.org)
    5  * Copyright (c) 2021 The FreeBSD Foundation
    6  *
    7  * Portions of this software were developed by Ka Ho Ng
    8  * under sponsorship from the FreeBSD Foundation.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice unmodified, this list of conditions, and the following
   15  *    disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * $FreeBSD$
   32  */
   33 
   34 #ifndef _AMDVI_PRIV_H_
   35 #define _AMDVI_PRIV_H_
   36 
   37 #include <contrib/dev/acpica/include/acpi.h>
   38 
   39 #define BIT(n)                  (1ULL << (n))
   40 /* Return value of bits[n:m] where n and (n >= ) m are bit positions. */
   41 #define REG_BITS(x, n, m)       (((x) >> (m)) &                 \
   42                                 ((1 << (((n) - (m)) + 1)) - 1))
   43 
   44 /*
   45  * IOMMU PCI capability.
   46  */
   47 #define AMDVI_PCI_CAP_IOTLB     BIT(0)  /* IOTLB is supported. */
   48 #define AMDVI_PCI_CAP_HT        BIT(1)  /* HyperTransport tunnel support. */
   49 #define AMDVI_PCI_CAP_NPCACHE   BIT(2)  /* Not present page cached. */
   50 #define AMDVI_PCI_CAP_EFR       BIT(3)  /* Extended features. */
   51 #define AMDVI_PCI_CAP_EXT       BIT(4)  /* Miscellaneous information reg. */
   52 
   53 /*
   54  * IOMMU extended features.
   55  */
   56 #define AMDVI_EX_FEA_PREFSUP    BIT(0)  /* Prefetch command support. */
   57 #define AMDVI_EX_FEA_PPRSUP     BIT(1)  /* PPR support */
   58 #define AMDVI_EX_FEA_XTSUP      BIT(2)  /* Reserved */
   59 #define AMDVI_EX_FEA_NXSUP      BIT(3)  /* No-execute. */
   60 #define AMDVI_EX_FEA_GTSUP      BIT(4)  /* Guest translation support. */
   61 #define AMDVI_EX_FEA_EFRW       BIT(5)  /* Reserved */
   62 #define AMDVI_EX_FEA_IASUP      BIT(6)  /* Invalidate all command supp. */
   63 #define AMDVI_EX_FEA_GASUP      BIT(7)  /* Guest APIC or AVIC support. */
   64 #define AMDVI_EX_FEA_HESUP      BIT(8)  /* Hardware Error. */
   65 #define AMDVI_EX_FEA_PCSUP      BIT(9)  /* Performance counters support. */
   66 /* XXX: add more EFER bits. */
   67 
   68 /*
   69  * Device table entry or DTE
   70  * NOTE: Must be 256-bits/32 bytes aligned.
   71  */
   72 struct amdvi_dte {
   73         uint32_t dt_valid:1;            /* Device Table valid. */
   74         uint32_t pt_valid:1;            /* Page translation valid. */
   75         uint16_t :7;                    /* Reserved[8:2] */
   76         uint8_t  pt_level:3;            /* Paging level, 0 to disable. */
   77         uint64_t pt_base:40;            /* Page table root pointer. */
   78         uint8_t  :3;                    /* Reserved[54:52] */
   79         uint8_t  gv_valid:1;            /* Revision 2, GVA to SPA. */
   80         uint8_t  gv_level:2;            /* Revision 2, GLX level. */
   81         uint8_t  gv_cr3_lsb:3;          /* Revision 2, GCR3[14:12] */
   82         uint8_t  read_allow:1;          /* I/O read enabled. */
   83         uint8_t  write_allow:1;         /* I/O write enabled. */
   84         uint8_t  :1;                    /* Reserved[63] */
   85         uint16_t domain_id:16;          /* Domain ID */
   86         uint16_t gv_cr3_lsb2:16;        /* Revision 2, GCR3[30:15] */
   87         uint8_t  iotlb_enable:1;        /* Device support IOTLB */
   88         uint8_t  sup_second_io_fault:1; /* Suppress subsequent I/O faults. */
   89         uint8_t  sup_all_io_fault:1;    /* Suppress all I/O page faults. */
   90         uint8_t  IOctl:2;               /* Port I/O control. */
   91         uint8_t  iotlb_cache_disable:1; /* IOTLB cache hints. */
   92         uint8_t  snoop_disable:1;       /* Snoop disable. */
   93         uint8_t  allow_ex:1;            /* Allow exclusion. */
   94         uint8_t  sysmgmt:2;             /* System management message.*/
   95         uint8_t  :1;                    /* Reserved[106] */
   96         uint32_t gv_cr3_msb:21;         /* Revision 2, GCR3[51:31] */
   97         uint8_t  intmap_valid:1;        /* Interrupt map valid. */
   98         uint8_t  intmap_len:4;          /* Interrupt map table length. */
   99         uint8_t  intmap_ign:1;          /* Ignore unmapped interrupts. */
  100         uint64_t intmap_base:46;        /* IntMap base. */
  101         uint8_t  :4;                    /* Reserved[183:180] */
  102         uint8_t  init_pass:1;           /* INIT pass through or PT */
  103         uint8_t  extintr_pass:1;        /* External Interrupt PT */
  104         uint8_t  nmi_pass:1;            /* NMI PT */
  105         uint8_t  :1;                    /* Reserved[187] */
  106         uint8_t  intr_ctrl:2;           /* Interrupt control */
  107         uint8_t  lint0_pass:1;          /* LINT0 PT */
  108         uint8_t  lint1_pass:1;          /* LINT1 PT */
  109         uint64_t :64;                   /* Reserved[255:192] */
  110 } __attribute__((__packed__));
  111 CTASSERT(sizeof(struct amdvi_dte) == 32);
  112 
  113 /*
  114  * IOMMU command entry.
  115  */
  116 struct amdvi_cmd {
  117         uint32_t        word0;
  118         uint32_t        word1:28;
  119         uint8_t         opcode:4;
  120         uint64_t        addr;
  121 } __attribute__((__packed__));
  122 
  123 /* Command opcodes. */
  124 #define AMDVI_CMP_WAIT_OPCODE   0x1     /* Completion wait. */
  125 #define AMDVI_INVD_DTE_OPCODE   0x2     /* Invalidate device table entry. */
  126 #define AMDVI_INVD_PAGE_OPCODE  0x3     /* Invalidate pages. */
  127 #define AMDVI_INVD_IOTLB_OPCODE 0x4     /* Invalidate IOTLB pages. */
  128 #define AMDVI_INVD_INTR_OPCODE  0x5     /* Invalidate Interrupt table. */
  129 #define AMDVI_PREFETCH_PAGES_OPCODE     0x6     /* Prefetch IOMMU pages. */
  130 #define AMDVI_COMP_PPR_OPCODE   0x7     /* Complete PPR request. */
  131 #define AMDVI_INV_ALL_OPCODE    0x8     /* Invalidate all. */
  132 
  133 /* Completion wait attributes. */
  134 #define AMDVI_CMP_WAIT_STORE    BIT(0)  /* Write back data. */
  135 #define AMDVI_CMP_WAIT_INTR     BIT(1)  /* Completion wait interrupt. */
  136 #define AMDVI_CMP_WAIT_FLUSH    BIT(2)  /* Flush queue. */
  137 
  138 /* Invalidate page. */
  139 #define AMDVI_INVD_PAGE_S       BIT(0)  /* Invalidation size. */
  140 #define AMDVI_INVD_PAGE_PDE     BIT(1)  /* Invalidate PDE. */
  141 #define AMDVI_INVD_PAGE_GN_GVA  BIT(2)  /* GPA or GVA. */
  142 
  143 #define AMDVI_INVD_PAGE_ALL_ADDR        (0x7FFFFFFFFFFFFULL << 12)
  144 
  145 /* Invalidate IOTLB. */
  146 #define AMDVI_INVD_IOTLB_S      BIT(0)  /* Invalidation size 4k or addr */
  147 #define AMDVI_INVD_IOTLB_GN_GVA BIT(2)  /* GPA or GVA. */
  148 
  149 #define AMDVI_INVD_IOTLB_ALL_ADDR       (0x7FFFFFFFFFFFFULL << 12)
  150 /* XXX: add more command entries. */
  151 
  152 /*
  153  * IOMMU event entry.
  154  */
  155 struct amdvi_event {
  156         uint16_t        devid;
  157         uint16_t        pasid_hi;
  158         uint16_t        pasid_domid;    /* PASID low or DomainID */
  159         uint16_t        flag:12;
  160         uint8_t         opcode:4;
  161         uint64_t        addr;
  162 } __attribute__((__packed__));
  163 CTASSERT(sizeof(struct amdvi_event) == 16);
  164 
  165 /* Various event types. */
  166 #define AMDVI_EVENT_INVALID_DTE         0x1
  167 #define AMDVI_EVENT_PFAULT              0x2
  168 #define AMDVI_EVENT_DTE_HW_ERROR        0x3
  169 #define AMDVI_EVENT_PAGE_HW_ERROR       0x4
  170 #define AMDVI_EVENT_ILLEGAL_CMD         0x5
  171 #define AMDVI_EVENT_CMD_HW_ERROR        0x6
  172 #define AMDVI_EVENT_IOTLB_TIMEOUT       0x7
  173 #define AMDVI_EVENT_INVALID_DTE_REQ     0x8
  174 #define AMDVI_EVENT_INVALID_PPR_REQ     0x9
  175 #define AMDVI_EVENT_COUNTER_ZERO        0xA
  176 
  177 #define AMDVI_EVENT_FLAG_MASK           0x1FF   /* Mask for event flags. */
  178 #define AMDVI_EVENT_FLAG_TYPE(x)        (((x) >> 9) & 0x3)
  179 
  180 /*
  181  * IOMMU control block.
  182  */
  183 struct amdvi_ctrl {
  184         struct {
  185                 uint16_t size:9;
  186                 uint16_t :3;
  187                 uint64_t base:40;       /* Devtable register base. */
  188                 uint16_t :12;
  189         } dte;
  190         struct {
  191                 uint16_t :12;
  192                 uint64_t base:40;
  193                 uint8_t  :4;
  194                 uint8_t  len:4;
  195                 uint8_t  :4;
  196         } cmd;
  197         struct {
  198                 uint16_t :12;
  199                 uint64_t base:40;
  200                 uint8_t  :4;
  201                 uint8_t  len:4;
  202                 uint8_t  :4;
  203         } event;
  204         uint16_t control :13;
  205         uint64_t         :51;
  206         struct {
  207                 uint8_t  enable:1;
  208                 uint8_t  allow:1;
  209                 uint16_t :10;
  210                 uint64_t base:40;
  211                 uint16_t :12;
  212                 uint16_t :12;
  213                 uint64_t limit:40;
  214                 uint16_t :12;
  215         } excl;
  216         /* 
  217          * Revision 2 only. 
  218          */
  219         uint64_t ex_feature;
  220         struct {
  221                 uint16_t :12;
  222                 uint64_t base:40;
  223                 uint8_t  :4;
  224                 uint8_t  len:4;
  225                 uint8_t  :4;
  226         } ppr;
  227         uint64_t first_event;
  228         uint64_t second_event;
  229         uint64_t event_status;
  230         /* Revision 2 only, end. */
  231         uint8_t  pad1[0x1FA8];          /* Padding. */
  232         uint32_t cmd_head:19;
  233         uint64_t :45;
  234         uint32_t cmd_tail:19;
  235         uint64_t :45;
  236         uint32_t evt_head:19;
  237         uint64_t :45;
  238         uint32_t evt_tail:19;
  239         uint64_t :45;
  240         uint32_t status:19;
  241         uint64_t :45;
  242         uint64_t pad2;
  243         uint8_t  :4;
  244         uint16_t ppr_head:15;
  245         uint64_t :45;
  246         uint8_t  :4;
  247         uint16_t ppr_tail:15;
  248         uint64_t :45;
  249         uint8_t  pad3[0x1FC0];          /* Padding. */
  250 
  251         /* XXX: More for rev2. */
  252 } __attribute__((__packed__));
  253 CTASSERT(offsetof(struct amdvi_ctrl, pad1)== 0x58);
  254 CTASSERT(offsetof(struct amdvi_ctrl, pad2)== 0x2028);
  255 CTASSERT(offsetof(struct amdvi_ctrl, pad3)== 0x2040);
  256 
  257 #define AMDVI_MMIO_V1_SIZE      (4 * PAGE_SIZE) /* v1 size */
  258 /* 
  259  * AMF IOMMU v2 size including event counters 
  260  */
  261 #define AMDVI_MMIO_V2_SIZE      (8 * PAGE_SIZE)
  262 
  263 CTASSERT(sizeof(struct amdvi_ctrl) == 0x4000);
  264 CTASSERT(sizeof(struct amdvi_ctrl) == AMDVI_MMIO_V1_SIZE);
  265 
  266 /* IVHD flag */
  267 #define IVHD_FLAG_HTT           BIT(0)  /* Hypertransport Tunnel. */
  268 #define IVHD_FLAG_PPW           BIT(1)  /* Pass posted write. */
  269 #define IVHD_FLAG_RPPW          BIT(2)  /* Response pass posted write. */
  270 #define IVHD_FLAG_ISOC          BIT(3)  /* Isoc support. */
  271 #define IVHD_FLAG_IOTLB         BIT(4)  /* IOTLB support. */
  272 #define IVHD_FLAG_COH           BIT(5)  /* Coherent control, default 1 */
  273 #define IVHD_FLAG_PFS           BIT(6)  /* Prefetch IOMMU pages. */
  274 #define IVHD_FLAG_PPRS          BIT(7)  /* Peripheral page support. */
  275 
  276 /* IVHD device entry data setting. */
  277 #define IVHD_DEV_LINT0_PASS     BIT(6)  /* LINT0 interrupts. */
  278 #define IVHD_DEV_LINT1_PASS     BIT(7)  /* LINT1 interrupts. */
  279 
  280 /* Bit[5:4] for System Mgmt. Bit3 is reserved. */
  281 #define IVHD_DEV_INIT_PASS      BIT(0)  /* INIT */
  282 #define IVHD_DEV_EXTINTR_PASS   BIT(1)  /* ExtInt */
  283 #define IVHD_DEV_NMI_PASS       BIT(2)  /* NMI */
  284 
  285 /* IVHD 8-byte extended data settings. */
  286 #define IVHD_DEV_EXT_ATS_DISABLE        BIT(31) /* Disable ATS */
  287 
  288 /* IOMMU control register. */
  289 #define AMDVI_CTRL_EN           BIT(0)  /* IOMMU enable. */
  290 #define AMDVI_CTRL_HTT          BIT(1)  /* Hypertransport tunnel enable. */
  291 #define AMDVI_CTRL_ELOG         BIT(2)  /* Event log enable. */
  292 #define AMDVI_CTRL_ELOGINT      BIT(3)  /* Event log interrupt. */
  293 #define AMDVI_CTRL_COMINT       BIT(4)  /* Completion wait interrupt. */
  294 #define AMDVI_CTRL_PPW          BIT(8)
  295 #define AMDVI_CTRL_RPPW         BIT(9)
  296 #define AMDVI_CTRL_COH          BIT(10)
  297 #define AMDVI_CTRL_ISOC         BIT(11)
  298 #define AMDVI_CTRL_CMD          BIT(12) /* Command buffer enable. */
  299 #define AMDVI_CTRL_PPRLOG       BIT(13)
  300 #define AMDVI_CTRL_PPRINT       BIT(14)
  301 #define AMDVI_CTRL_PPREN        BIT(15)
  302 #define AMDVI_CTRL_GTE          BIT(16) /* Guest translation enable. */
  303 #define AMDVI_CTRL_GAE          BIT(17) /* Guest APIC enable. */
  304 
  305 /* Invalidation timeout. */
  306 #define AMDVI_CTRL_INV_NO_TO    0       /* No timeout. */
  307 #define AMDVI_CTRL_INV_TO_1ms   1       /* 1 ms */
  308 #define AMDVI_CTRL_INV_TO_10ms  2       /* 10 ms */
  309 #define AMDVI_CTRL_INV_TO_100ms 3       /* 100 ms */
  310 #define AMDVI_CTRL_INV_TO_1S    4       /* 1 second */
  311 #define AMDVI_CTRL_INV_TO_10S   5       /* 10 second */
  312 #define AMDVI_CTRL_INV_TO_100S  6       /* 100 second */
  313 
  314 /*
  315  * Max number of PCI devices.
  316  * 256 bus x 32 slot/devices x 8 functions.
  317  */
  318 #define PCI_NUM_DEV_MAX         0x10000
  319 
  320 /* Maximum number of domains supported by IOMMU. */
  321 #define AMDVI_MAX_DOMAIN        (BIT(16) - 1)
  322 
  323 /*
  324  * IOMMU Page Table attributes.
  325  */
  326 #define AMDVI_PT_PRESENT        BIT(0)
  327 #define AMDVI_PT_COHERENT       BIT(60)
  328 #define AMDVI_PT_READ           BIT(61)
  329 #define AMDVI_PT_WRITE          BIT(62)
  330 
  331 #define AMDVI_PT_RW             (AMDVI_PT_READ | AMDVI_PT_WRITE)
  332 #define AMDVI_PT_MASK           0xFFFFFFFFFF000UL /* Only [51:12] for PA */
  333 
  334 #define AMDVI_PD_LEVEL_SHIFT    9
  335 #define AMDVI_PD_SUPER(x)       (((x) >> AMDVI_PD_LEVEL_SHIFT) == 7)
  336 /*
  337  * IOMMU Status, offset 0x2020
  338  */
  339 #define AMDVI_STATUS_EV_OF              BIT(0)  /* Event overflow. */
  340 #define AMDVI_STATUS_EV_INTR            BIT(1)  /* Event interrupt. */
  341 /* Completion wait command completed. */
  342 #define AMDVI_STATUS_CMP                BIT(2)
  343 
  344 #define IVRS_CTRL_RID                   1       /* MMIO RID */
  345 
  346 /* ACPI IVHD */
  347 struct ivhd_dev_cfg {
  348         uint32_t start_id;
  349         uint32_t end_id;
  350         uint8_t  data;                  /* Device configuration. */
  351         bool     enable_ats;            /* ATS enabled for the device. */
  352         int      ats_qlen;              /* ATS invalidation queue depth. */
  353 };
  354 
  355 struct amdvi_domain {
  356         uint64_t *ptp;                  /* Highest level page table */
  357         int     ptp_level;              /* Level of page tables */
  358         u_int   id;                     /* Domain id */
  359         SLIST_ENTRY (amdvi_domain) next;
  360 };
  361 
  362 /*
  363  * Different type of IVHD.
  364  * XXX: Use AcpiIvrsType once new IVHD types are available.
  365 */
  366 enum IvrsType
  367 {
  368         IVRS_TYPE_HARDWARE_LEGACY = ACPI_IVRS_TYPE_HARDWARE1,
  369                                         /* Legacy without EFRi support. */
  370         IVRS_TYPE_HARDWARE_EFR    = ACPI_IVRS_TYPE_HARDWARE2,
  371                                                 /* With EFR support. */
  372         IVRS_TYPE_HARDWARE_MIXED  = 0x40, /* Mixed with EFR support. */
  373 };
  374 
  375 /*
  376  * AMD IOMMU softc.
  377  */
  378 struct amdvi_softc {
  379         struct amdvi_ctrl *ctrl;        /* Control area. */
  380         device_t        dev;            /* IOMMU device. */
  381         device_t        pci_dev;        /* IOMMU PCI function device. */
  382         enum IvrsType   ivhd_type;      /* IOMMU IVHD type. */
  383         bool            iotlb;          /* IOTLB supported by IOMMU */
  384         struct amdvi_cmd *cmd;          /* Command descriptor area. */
  385         int             cmd_max;        /* Max number of commands. */
  386         uint64_t        cmp_data;       /* Command completion write back. */
  387         struct amdvi_event *event;      /* Event descriptor area. */
  388         int             event_max;      /* Max number of events. */
  389         /* ACPI various flags. */
  390         uint32_t        ivhd_flag;      /* ACPI IVHD flag. */
  391         uint32_t        ivhd_feature;   /* ACPI v1 Reserved or v2 attribute. */
  392         uint64_t        ext_feature;    /* IVHD EFR */
  393         /* PCI related. */
  394         uint16_t        cap_off;        /* PCI Capability offset. */
  395         uint8_t         pci_cap;        /* PCI capability. */
  396         uint16_t        pci_seg;        /* IOMMU PCI domain/segment. */
  397         uint16_t        pci_rid;        /* PCI BDF of IOMMU */
  398 
  399         /* ACPI device configuration for end points. */
  400         struct          ivhd_dev_cfg *dev_cfg;
  401         int             dev_cfg_cnt;
  402         int             dev_cfg_cap;
  403 
  404         /* Software statistics. */
  405         uint64_t        event_intr_cnt; /* Total event INTR count. */
  406         uint64_t        total_cmd;      /* Total number of commands. */
  407 };
  408 
  409 int     amdvi_setup_hw(struct amdvi_softc *softc);
  410 int     amdvi_teardown_hw(struct amdvi_softc *softc);
  411 #endif /* _AMDVI_PRIV_H_ */

Cache object: 059f9c1c1437b97b3bc3019d04934d33


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.