qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

smmu-common.h (5789B)


      1 /*
      2  * ARM SMMU Support
      3  *
      4  * Copyright (C) 2015-2016 Broadcom Corporation
      5  * Copyright (c) 2017 Red Hat, Inc.
      6  * Written by Prem Mallappa, Eric Auger
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License version 2 as
     10  * published by the Free Software Foundation.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  */
     18 
     19 #ifndef HW_ARM_SMMU_COMMON_H
     20 #define HW_ARM_SMMU_COMMON_H
     21 
     22 #include "hw/sysbus.h"
     23 #include "hw/pci/pci.h"
     24 #include "qom/object.h"
     25 
     26 #define SMMU_PCI_BUS_MAX      256
     27 #define SMMU_PCI_DEVFN_MAX    256
     28 #define SMMU_PCI_DEVFN(sid)   (sid & 0xFF)
     29 
     30 #define SMMU_MAX_VA_BITS      48
     31 
     32 /*
     33  * Page table walk error types
     34  */
     35 typedef enum {
     36     SMMU_PTW_ERR_NONE,
     37     SMMU_PTW_ERR_WALK_EABT,   /* Translation walk external abort */
     38     SMMU_PTW_ERR_TRANSLATION, /* Translation fault */
     39     SMMU_PTW_ERR_ADDR_SIZE,   /* Address Size fault */
     40     SMMU_PTW_ERR_ACCESS,      /* Access fault */
     41     SMMU_PTW_ERR_PERMISSION,  /* Permission fault */
     42 } SMMUPTWEventType;
     43 
     44 typedef struct SMMUPTWEventInfo {
     45     SMMUPTWEventType type;
     46     dma_addr_t addr; /* fetched address that induced an abort, if any */
     47 } SMMUPTWEventInfo;
     48 
     49 typedef struct SMMUTransTableInfo {
     50     bool disabled;             /* is the translation table disabled? */
     51     uint64_t ttb;              /* TT base address */
     52     uint8_t tsz;               /* input range, ie. 2^(64 -tsz)*/
     53     uint8_t granule_sz;        /* granule page shift */
     54     bool had;                  /* hierarchical attribute disable */
     55 } SMMUTransTableInfo;
     56 
     57 typedef struct SMMUTLBEntry {
     58     IOMMUTLBEntry entry;
     59     uint8_t level;
     60     uint8_t granule;
     61 } SMMUTLBEntry;
     62 
     63 /*
     64  * Generic structure populated by derived SMMU devices
     65  * after decoding the configuration information and used as
     66  * input to the page table walk
     67  */
     68 typedef struct SMMUTransCfg {
     69     int stage;                 /* translation stage */
     70     bool aa64;                 /* arch64 or aarch32 translation table */
     71     bool disabled;             /* smmu is disabled */
     72     bool bypassed;             /* translation is bypassed */
     73     bool aborted;              /* translation is aborted */
     74     bool record_faults;        /* record fault events */
     75     uint64_t ttb;              /* TT base address */
     76     uint8_t oas;               /* output address width */
     77     uint8_t tbi;               /* Top Byte Ignore */
     78     uint16_t asid;
     79     SMMUTransTableInfo tt[2];
     80     uint32_t iotlb_hits;       /* counts IOTLB hits for this asid */
     81     uint32_t iotlb_misses;     /* counts IOTLB misses for this asid */
     82 } SMMUTransCfg;
     83 
     84 typedef struct SMMUDevice {
     85     void               *smmu;
     86     PCIBus             *bus;
     87     int                devfn;
     88     IOMMUMemoryRegion  iommu;
     89     AddressSpace       as;
     90     uint32_t           cfg_cache_hits;
     91     uint32_t           cfg_cache_misses;
     92     QLIST_ENTRY(SMMUDevice) next;
     93 } SMMUDevice;
     94 
     95 typedef struct SMMUPciBus {
     96     PCIBus       *bus;
     97     SMMUDevice   *pbdev[]; /* Parent array is sparse, so dynamically alloc */
     98 } SMMUPciBus;
     99 
    100 typedef struct SMMUIOTLBKey {
    101     uint64_t iova;
    102     uint16_t asid;
    103     uint8_t tg;
    104     uint8_t level;
    105 } SMMUIOTLBKey;
    106 
    107 struct SMMUState {
    108     /* <private> */
    109     SysBusDevice  dev;
    110     const char *mrtypename;
    111     MemoryRegion iomem;
    112 
    113     GHashTable *smmu_pcibus_by_busptr;
    114     GHashTable *configs; /* cache for configuration data */
    115     GHashTable *iotlb;
    116     SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
    117     PCIBus *pci_bus;
    118     QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
    119     uint8_t bus_num;
    120     PCIBus *primary_bus;
    121 };
    122 
    123 struct SMMUBaseClass {
    124     /* <private> */
    125     SysBusDeviceClass parent_class;
    126 
    127     /*< public >*/
    128 
    129     DeviceRealize parent_realize;
    130 
    131 };
    132 
    133 #define TYPE_ARM_SMMU "arm-smmu"
    134 OBJECT_DECLARE_TYPE(SMMUState, SMMUBaseClass, ARM_SMMU)
    135 
    136 /* Return the SMMUPciBus handle associated to a PCI bus number */
    137 SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
    138 
    139 /* Return the stream ID of an SMMU device */
    140 static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
    141 {
    142     return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
    143 }
    144 
    145 /**
    146  * smmu_ptw - Perform the page table walk for a given iova / access flags
    147  * pair, according to @cfg translation config
    148  */
    149 int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
    150              SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
    151 
    152 /**
    153  * select_tt - compute which translation table shall be used according to
    154  * the input iova and translation config and return the TT specific info
    155  */
    156 SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
    157 
    158 /* Return the iommu mr associated to @sid, or NULL if none */
    159 IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
    160 
    161 #define SMMU_IOTLB_MAX_SIZE 256
    162 
    163 SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
    164                                 SMMUTransTableInfo *tt, hwaddr iova);
    165 void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry);
    166 SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
    167                                 uint8_t tg, uint8_t level);
    168 void smmu_iotlb_inv_all(SMMUState *s);
    169 void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
    170 void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
    171                          uint8_t tg, uint64_t num_pages, uint8_t ttl);
    172 
    173 /* Unmap the range of all the notifiers registered to any IOMMU mr */
    174 void smmu_inv_notifiers_all(SMMUState *s);
    175 
    176 /* Unmap the range of all the notifiers registered to @mr */
    177 void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr);
    178 
    179 #endif /* HW_ARM_SMMU_COMMON_H */