10c54acb8STomasz Jeznach /* 20c54acb8STomasz Jeznach * QEMU emulation of an RISC-V IOMMU 30c54acb8STomasz Jeznach * 40c54acb8STomasz Jeznach * Copyright (C) 2022-2023 Rivos Inc. 50c54acb8STomasz Jeznach * 60c54acb8STomasz Jeznach * This program is free software; you can redistribute it and/or modify it 70c54acb8STomasz Jeznach * under the terms and conditions of the GNU General Public License, 80c54acb8STomasz Jeznach * version 2 or later, as published by the Free Software Foundation. 90c54acb8STomasz Jeznach * 100c54acb8STomasz Jeznach * This program is distributed in the hope that it will be useful, 110c54acb8STomasz Jeznach * but WITHOUT ANY WARRANTY; without even the implied warranty of 120c54acb8STomasz Jeznach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 130c54acb8STomasz Jeznach * GNU General Public License for more details. 140c54acb8STomasz Jeznach * 150c54acb8STomasz Jeznach * You should have received a copy of the GNU General Public License along 160c54acb8STomasz Jeznach * with this program; if not, see <http://www.gnu.org/licenses/>. 170c54acb8STomasz Jeznach */ 180c54acb8STomasz Jeznach 190c54acb8STomasz Jeznach #ifndef HW_RISCV_IOMMU_STATE_H 200c54acb8STomasz Jeznach #define HW_RISCV_IOMMU_STATE_H 210c54acb8STomasz Jeznach 220c54acb8STomasz Jeznach #include "qom/object.h" 230c54acb8STomasz Jeznach #include "hw/riscv/iommu.h" 240c54acb8STomasz Jeznach 250c54acb8STomasz Jeznach struct RISCVIOMMUState { 260c54acb8STomasz Jeznach /*< private >*/ 270c54acb8STomasz Jeznach DeviceState parent_obj; 280c54acb8STomasz Jeznach 290c54acb8STomasz Jeznach /*< public >*/ 300c54acb8STomasz Jeznach uint32_t version; /* Reported interface version number */ 310c54acb8STomasz Jeznach uint32_t pid_bits; /* process identifier width */ 320c54acb8STomasz Jeznach uint32_t bus; /* PCI bus mapping for non-root endpoints */ 330c54acb8STomasz Jeznach 340c54acb8STomasz Jeznach uint64_t cap; /* IOMMU supported capabilities */ 350c54acb8STomasz Jeznach uint64_t fctl; /* IOMMU enabled features */ 360c54acb8STomasz Jeznach uint64_t icvec_avail_vectors; /* Available interrupt vectors in ICVEC */ 370c54acb8STomasz Jeznach 380c54acb8STomasz Jeznach bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */ 390c54acb8STomasz Jeznach bool enable_msi; /* Enable MSI remapping */ 400c54acb8STomasz Jeznach bool enable_s_stage; /* Enable S/VS-Stage translation */ 410c54acb8STomasz Jeznach bool enable_g_stage; /* Enable G-Stage translation */ 420c54acb8STomasz Jeznach 430c54acb8STomasz Jeznach /* IOMMU Internal State */ 440c54acb8STomasz Jeznach uint64_t ddtp; /* Validated Device Directory Tree Root Pointer */ 450c54acb8STomasz Jeznach 460c54acb8STomasz Jeznach dma_addr_t cq_addr; /* Command queue base physical address */ 470c54acb8STomasz Jeznach dma_addr_t fq_addr; /* Fault/event queue base physical address */ 480c54acb8STomasz Jeznach dma_addr_t pq_addr; /* Page request queue base physical address */ 490c54acb8STomasz Jeznach 500c54acb8STomasz Jeznach uint32_t cq_mask; /* Command queue index bit mask */ 510c54acb8STomasz Jeznach uint32_t fq_mask; /* Fault/event queue index bit mask */ 520c54acb8STomasz Jeznach uint32_t pq_mask; /* Page request queue index bit mask */ 530c54acb8STomasz Jeznach 540c54acb8STomasz Jeznach /* interrupt notifier */ 550c54acb8STomasz Jeznach void (*notify)(RISCVIOMMUState *iommu, unsigned vector); 560c54acb8STomasz Jeznach 570c54acb8STomasz Jeznach /* IOMMU State Machine */ 580c54acb8STomasz Jeznach QemuThread core_proc; /* Background processing thread */ 590c54acb8STomasz Jeznach QemuCond core_cond; /* Background processing wake up signal */ 600c54acb8STomasz Jeznach unsigned core_exec; /* Processing thread execution actions */ 610c54acb8STomasz Jeznach 620c54acb8STomasz Jeznach /* IOMMU target address space */ 630c54acb8STomasz Jeznach AddressSpace *target_as; 640c54acb8STomasz Jeznach MemoryRegion *target_mr; 650c54acb8STomasz Jeznach 660c54acb8STomasz Jeznach /* MSI / MRIF access trap */ 670c54acb8STomasz Jeznach AddressSpace trap_as; 680c54acb8STomasz Jeznach MemoryRegion trap_mr; 690c54acb8STomasz Jeznach 700c54acb8STomasz Jeznach GHashTable *ctx_cache; /* Device translation Context Cache */ 710c54acb8STomasz Jeznach 72*9d085a1cSTomasz Jeznach GHashTable *iot_cache; /* IO Translated Address Cache */ 73*9d085a1cSTomasz Jeznach unsigned iot_limit; /* IO Translation Cache size limit */ 74*9d085a1cSTomasz Jeznach 750c54acb8STomasz Jeznach /* MMIO Hardware Interface */ 760c54acb8STomasz Jeznach MemoryRegion regs_mr; 770c54acb8STomasz Jeznach uint8_t *regs_rw; /* register state (user write) */ 780c54acb8STomasz Jeznach uint8_t *regs_wc; /* write-1-to-clear mask */ 790c54acb8STomasz Jeznach uint8_t *regs_ro; /* read-only mask */ 800c54acb8STomasz Jeznach 810c54acb8STomasz Jeznach QLIST_ENTRY(RISCVIOMMUState) iommus; 820c54acb8STomasz Jeznach QLIST_HEAD(, RISCVIOMMUSpace) spaces; 830c54acb8STomasz Jeznach }; 840c54acb8STomasz Jeznach 850c54acb8STomasz Jeznach void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus, 860c54acb8STomasz Jeznach Error **errp); 870c54acb8STomasz Jeznach 880c54acb8STomasz Jeznach /* private helpers */ 890c54acb8STomasz Jeznach 900c54acb8STomasz Jeznach /* Register helper functions */ 910c54acb8STomasz Jeznach static inline uint32_t riscv_iommu_reg_mod32(RISCVIOMMUState *s, 920c54acb8STomasz Jeznach unsigned idx, uint32_t set, uint32_t clr) 930c54acb8STomasz Jeznach { 940c54acb8STomasz Jeznach uint32_t val = ldl_le_p(s->regs_rw + idx); 950c54acb8STomasz Jeznach stl_le_p(s->regs_rw + idx, (val & ~clr) | set); 960c54acb8STomasz Jeznach return val; 970c54acb8STomasz Jeznach } 980c54acb8STomasz Jeznach 990c54acb8STomasz Jeznach static inline void riscv_iommu_reg_set32(RISCVIOMMUState *s, unsigned idx, 1000c54acb8STomasz Jeznach uint32_t set) 1010c54acb8STomasz Jeznach { 1020c54acb8STomasz Jeznach stl_le_p(s->regs_rw + idx, set); 1030c54acb8STomasz Jeznach } 1040c54acb8STomasz Jeznach 1050c54acb8STomasz Jeznach static inline uint32_t riscv_iommu_reg_get32(RISCVIOMMUState *s, unsigned idx) 1060c54acb8STomasz Jeznach { 1070c54acb8STomasz Jeznach return ldl_le_p(s->regs_rw + idx); 1080c54acb8STomasz Jeznach } 1090c54acb8STomasz Jeznach 1100c54acb8STomasz Jeznach static inline uint64_t riscv_iommu_reg_mod64(RISCVIOMMUState *s, unsigned idx, 1110c54acb8STomasz Jeznach uint64_t set, uint64_t clr) 1120c54acb8STomasz Jeznach { 1130c54acb8STomasz Jeznach uint64_t val = ldq_le_p(s->regs_rw + idx); 1140c54acb8STomasz Jeznach stq_le_p(s->regs_rw + idx, (val & ~clr) | set); 1150c54acb8STomasz Jeznach return val; 1160c54acb8STomasz Jeznach } 1170c54acb8STomasz Jeznach 1180c54acb8STomasz Jeznach static inline void riscv_iommu_reg_set64(RISCVIOMMUState *s, unsigned idx, 1190c54acb8STomasz Jeznach uint64_t set) 1200c54acb8STomasz Jeznach { 1210c54acb8STomasz Jeznach stq_le_p(s->regs_rw + idx, set); 1220c54acb8STomasz Jeznach } 1230c54acb8STomasz Jeznach 1240c54acb8STomasz Jeznach static inline uint64_t riscv_iommu_reg_get64(RISCVIOMMUState *s, 1250c54acb8STomasz Jeznach unsigned idx) 1260c54acb8STomasz Jeznach { 1270c54acb8STomasz Jeznach return ldq_le_p(s->regs_rw + idx); 1280c54acb8STomasz Jeznach } 1290c54acb8STomasz Jeznach #endif 130