1*527773eeSEric Auger /* 2*527773eeSEric Auger * ARM SMMU Support 3*527773eeSEric Auger * 4*527773eeSEric Auger * Copyright (C) 2015-2016 Broadcom Corporation 5*527773eeSEric Auger * Copyright (c) 2017 Red Hat, Inc. 6*527773eeSEric Auger * Written by Prem Mallappa, Eric Auger 7*527773eeSEric Auger * 8*527773eeSEric Auger * This program is free software; you can redistribute it and/or modify 9*527773eeSEric Auger * it under the terms of the GNU General Public License version 2 as 10*527773eeSEric Auger * published by the Free Software Foundation. 11*527773eeSEric Auger * 12*527773eeSEric Auger * This program is distributed in the hope that it will be useful, 13*527773eeSEric Auger * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*527773eeSEric Auger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*527773eeSEric Auger * GNU General Public License for more details. 16*527773eeSEric Auger * 17*527773eeSEric Auger */ 18*527773eeSEric Auger 19*527773eeSEric Auger #ifndef HW_ARM_SMMU_COMMON_H 20*527773eeSEric Auger #define HW_ARM_SMMU_COMMON_H 21*527773eeSEric Auger 22*527773eeSEric Auger #include "hw/sysbus.h" 23*527773eeSEric Auger #include "hw/pci/pci.h" 24*527773eeSEric Auger 25*527773eeSEric Auger #define SMMU_PCI_BUS_MAX 256 26*527773eeSEric Auger #define SMMU_PCI_DEVFN_MAX 256 27*527773eeSEric Auger 28*527773eeSEric Auger #define SMMU_MAX_VA_BITS 48 29*527773eeSEric Auger 30*527773eeSEric Auger /* 31*527773eeSEric Auger * Page table walk error types 32*527773eeSEric Auger */ 33*527773eeSEric Auger typedef enum { 34*527773eeSEric Auger SMMU_PTW_ERR_NONE, 35*527773eeSEric Auger SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */ 36*527773eeSEric Auger SMMU_PTW_ERR_TRANSLATION, /* Translation fault */ 37*527773eeSEric Auger SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */ 38*527773eeSEric Auger SMMU_PTW_ERR_ACCESS, /* Access fault */ 39*527773eeSEric Auger SMMU_PTW_ERR_PERMISSION, /* Permission fault */ 40*527773eeSEric Auger } SMMUPTWEventType; 41*527773eeSEric Auger 42*527773eeSEric Auger typedef struct SMMUPTWEventInfo { 43*527773eeSEric Auger SMMUPTWEventType type; 44*527773eeSEric Auger dma_addr_t addr; /* fetched address that induced an abort, if any */ 45*527773eeSEric Auger } SMMUPTWEventInfo; 46*527773eeSEric Auger 47*527773eeSEric Auger typedef struct SMMUTransTableInfo { 48*527773eeSEric Auger bool disabled; /* is the translation table disabled? */ 49*527773eeSEric Auger uint64_t ttb; /* TT base address */ 50*527773eeSEric Auger uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ 51*527773eeSEric Auger uint8_t granule_sz; /* granule page shift */ 52*527773eeSEric Auger } SMMUTransTableInfo; 53*527773eeSEric Auger 54*527773eeSEric Auger /* 55*527773eeSEric Auger * Generic structure populated by derived SMMU devices 56*527773eeSEric Auger * after decoding the configuration information and used as 57*527773eeSEric Auger * input to the page table walk 58*527773eeSEric Auger */ 59*527773eeSEric Auger typedef struct SMMUTransCfg { 60*527773eeSEric Auger int stage; /* translation stage */ 61*527773eeSEric Auger bool aa64; /* arch64 or aarch32 translation table */ 62*527773eeSEric Auger bool disabled; /* smmu is disabled */ 63*527773eeSEric Auger bool bypassed; /* translation is bypassed */ 64*527773eeSEric Auger bool aborted; /* translation is aborted */ 65*527773eeSEric Auger uint64_t ttb; /* TT base address */ 66*527773eeSEric Auger uint8_t oas; /* output address width */ 67*527773eeSEric Auger uint8_t tbi; /* Top Byte Ignore */ 68*527773eeSEric Auger uint16_t asid; 69*527773eeSEric Auger SMMUTransTableInfo tt[2]; 70*527773eeSEric Auger } SMMUTransCfg; 71*527773eeSEric Auger 72*527773eeSEric Auger typedef struct SMMUDevice { 73*527773eeSEric Auger void *smmu; 74*527773eeSEric Auger PCIBus *bus; 75*527773eeSEric Auger int devfn; 76*527773eeSEric Auger IOMMUMemoryRegion iommu; 77*527773eeSEric Auger AddressSpace as; 78*527773eeSEric Auger } SMMUDevice; 79*527773eeSEric Auger 80*527773eeSEric Auger typedef struct SMMUNotifierNode { 81*527773eeSEric Auger SMMUDevice *sdev; 82*527773eeSEric Auger QLIST_ENTRY(SMMUNotifierNode) next; 83*527773eeSEric Auger } SMMUNotifierNode; 84*527773eeSEric Auger 85*527773eeSEric Auger typedef struct SMMUPciBus { 86*527773eeSEric Auger PCIBus *bus; 87*527773eeSEric Auger SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */ 88*527773eeSEric Auger } SMMUPciBus; 89*527773eeSEric Auger 90*527773eeSEric Auger typedef struct SMMUState { 91*527773eeSEric Auger /* <private> */ 92*527773eeSEric Auger SysBusDevice dev; 93*527773eeSEric Auger const char *mrtypename; 94*527773eeSEric Auger MemoryRegion iomem; 95*527773eeSEric Auger 96*527773eeSEric Auger GHashTable *smmu_pcibus_by_busptr; 97*527773eeSEric Auger GHashTable *configs; /* cache for configuration data */ 98*527773eeSEric Auger GHashTable *iotlb; 99*527773eeSEric Auger SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX]; 100*527773eeSEric Auger PCIBus *pci_bus; 101*527773eeSEric Auger QLIST_HEAD(, SMMUNotifierNode) notifiers_list; 102*527773eeSEric Auger uint8_t bus_num; 103*527773eeSEric Auger PCIBus *primary_bus; 104*527773eeSEric Auger } SMMUState; 105*527773eeSEric Auger 106*527773eeSEric Auger typedef struct { 107*527773eeSEric Auger /* <private> */ 108*527773eeSEric Auger SysBusDeviceClass parent_class; 109*527773eeSEric Auger 110*527773eeSEric Auger /*< public >*/ 111*527773eeSEric Auger 112*527773eeSEric Auger DeviceRealize parent_realize; 113*527773eeSEric Auger 114*527773eeSEric Auger } SMMUBaseClass; 115*527773eeSEric Auger 116*527773eeSEric Auger #define TYPE_ARM_SMMU "arm-smmu" 117*527773eeSEric Auger #define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU) 118*527773eeSEric Auger #define ARM_SMMU_CLASS(klass) \ 119*527773eeSEric Auger OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU) 120*527773eeSEric Auger #define ARM_SMMU_GET_CLASS(obj) \ 121*527773eeSEric Auger OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU) 122*527773eeSEric Auger 123*527773eeSEric Auger #endif /* HW_ARM_SMMU_COMMON */ 124