| /* |
| * Copyright (c) 2021 Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3. Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef __DEV_AMDGPU_AMDGPU_VM_HH__ |
| #define __DEV_AMDGPU_AMDGPU_VM_HH__ |
| |
| #include <vector> |
| |
| #include "arch/amdgpu/vega/pagetable_walker.hh" |
| #include "base/intmath.hh" |
| #include "dev/amdgpu/amdgpu_defines.hh" |
| #include "mem/packet.hh" |
| #include "mem/translation_gen.hh" |
| #include "sim/serialize.hh" |
| |
| /** |
| * MMIO offsets for graphics register bus manager (GRBM). These values were |
| * taken from linux header files. The header files can be found here: |
| * |
| * https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/ |
| * drivers/gpu/drm/amd/include/ asic_reg/gc/gc_9_0_offset.h |
| * https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/ |
| * drivers/gpu/drm/amd/include/ asic_reg/mmhub/mmhub_1_0_offset.h |
| */ |
| |
| #define mmVM_INVALIDATE_ENG17_ACK 0x08c6 |
| #define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32 0x08eb |
| #define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32 0x08ec |
| #define mmVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32 0x090b |
| #define mmVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32 0x090c |
| #define mmVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32 0x092b |
| #define mmVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32 0x092c |
| |
| #define mmMC_VM_FB_OFFSET 0x096b |
| #define mmMC_VM_FB_LOCATION_BASE 0x0980 |
| #define mmMC_VM_FB_LOCATION_TOP 0x0981 |
| #define mmMC_VM_AGP_TOP 0x0982 |
| #define mmMC_VM_AGP_BOT 0x0983 |
| #define mmMC_VM_AGP_BASE 0x0984 |
| #define mmMC_VM_SYSTEM_APERTURE_LOW_ADDR 0x0985 |
| #define mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x0986 |
| |
| #define mmMMHUB_VM_INVALIDATE_ENG17_SEM 0x06e2 |
| #define mmMMHUB_VM_INVALIDATE_ENG17_REQ 0x06f4 |
| #define mmMMHUB_VM_INVALIDATE_ENG17_ACK 0x0706 |
| #define mmMMHUB_VM_FB_LOCATION_BASE 0x082c |
| #define mmMMHUB_VM_FB_LOCATION_TOP 0x082d |
| |
| // AMD GPUs support 16 different virtual address spaces |
| static constexpr int AMDGPU_VM_COUNT = 16; |
| |
| // These apertures have a fixed page size |
| static constexpr int AMDGPU_AGP_PAGE_SIZE = 4096; |
| static constexpr int AMDGPU_GART_PAGE_SIZE = 4096; |
| static constexpr int AMDGPU_MMHUB_PAGE_SIZE = 4096; |
| |
| // Vega page size can be any power of 2 between 4kB and 1GB. |
| static constexpr int AMDGPU_USER_PAGE_SIZE = 4096; |
| |
| namespace gem5 |
| { |
| |
| class AMDGPUVM : public Serializable |
| { |
| private: |
| typedef struct GEM5_PACKED |
| { |
| // Page table addresses: from (Base + Start) to (End) |
| union |
| { |
| struct |
| { |
| uint32_t ptBaseL; |
| uint32_t ptBaseH; |
| }; |
| Addr ptBase; |
| }; |
| union |
| { |
| struct |
| { |
| uint32_t ptStartL; |
| uint32_t ptStartH; |
| }; |
| Addr ptStart; |
| }; |
| union |
| { |
| struct |
| { |
| uint32_t ptEndL; |
| uint32_t ptEndH; |
| }; |
| Addr ptEnd; |
| }; |
| } AMDGPUVMContext; |
| |
| typedef struct AMDGPUSysVMContext : AMDGPUVMContext |
| { |
| Addr agpBase; |
| Addr agpTop; |
| Addr agpBot; |
| Addr fbBase; |
| Addr fbTop; |
| Addr fbOffset; |
| Addr sysAddrL; |
| Addr sysAddrH; |
| } AMDGPUSysVMContext; |
| |
| AMDGPUSysVMContext vmContext0; |
| std::vector<AMDGPUVMContext> vmContexts; |
| |
| // MMHUB aperture. These addresses mirror the framebuffer, so addresses |
| // can be calculated by subtracting the base address. |
| uint64_t mmhubBase = 0x0; |
| uint64_t mmhubTop = 0x0; |
| |
| /** |
| * List of TLBs associated with the GPU device. This is used for flushing |
| * the TLBs upon a driver request. |
| */ |
| std::vector<VegaISA::GpuTLB *> gpu_tlbs; |
| |
| public: |
| AMDGPUVM(); |
| |
| /** |
| * Return base address of GART table in framebuffer. |
| */ |
| Addr gartBase(); |
| /** |
| * Return size of GART in number of PTEs. |
| */ |
| Addr gartSize(); |
| |
| /** |
| * Copy of GART table. Typically resides in device memory, however we use |
| * a copy in gem5 to simplify the interface. |
| */ |
| std::unordered_map<uint64_t, uint32_t> gartTable; |
| |
| void readMMIO(PacketPtr pkt, Addr offset); |
| void writeMMIO(PacketPtr pkt, Addr offset); |
| |
| /** |
| * Methods for resolving apertures |
| */ |
| bool |
| inAGP(Addr vaddr) |
| { |
| return ((vaddr >= vmContext0.agpBot) && (vaddr <= vmContext0.agpTop)); |
| } |
| |
| Addr getAGPBot() { return vmContext0.agpBot; } |
| Addr getAGPTop() { return vmContext0.agpTop; } |
| Addr getAGPBase() { return vmContext0.agpBase; } |
| |
| bool |
| inMMHUB(Addr vaddr) |
| { |
| return ((vaddr >= getMMHUBBase()) && (vaddr <= getMMHUBTop())); |
| } |
| |
| Addr getMMHUBBase() { return mmhubBase; } |
| Addr getMMHUBTop() { return mmhubTop; } |
| |
| bool |
| inFB(Addr vaddr) |
| { |
| return ((vaddr >= vmContext0.fbBase) && (vaddr <= vmContext0.fbTop)); |
| } |
| |
| Addr getFBBase() { return vmContext0.fbBase; } |
| Addr getFBTop() { return vmContext0.fbTop; } |
| Addr getFBOffset() { return vmContext0.fbOffset; } |
| |
| bool |
| inSys(Addr vaddr) |
| { |
| return ((vaddr >= vmContext0.sysAddrL) && |
| (vaddr <= vmContext0.sysAddrH)); |
| } |
| |
| Addr getSysAddrRangeLow () { return vmContext0.sysAddrL; } |
| Addr getSysAddrRangeHigh () { return vmContext0.sysAddrH; } |
| |
| Addr |
| getMmioAperture(Addr addr) |
| { |
| // Aperture ranges: |
| // NBIO 0x0 - 0x4280 |
| // IH 0x4280 - 0x4980 |
| // SDMA0 0x4980 - 0x5180 |
| // SDMA1 0x5180 - 0x5980 |
| // GRBM 0x8000 - 0xD000 |
| // GFX 0x28000 - 0x3F000 |
| // MMHUB 0x68000 - 0x6a120 |
| |
| if (IH_BASE <= addr && addr < IH_BASE + IH_SIZE) |
| return IH_BASE; |
| else if (SDMA0_BASE <= addr && addr < SDMA0_BASE + SDMA_SIZE) |
| return SDMA0_BASE; |
| else if (SDMA1_BASE <= addr && addr < SDMA1_BASE + SDMA_SIZE) |
| return SDMA1_BASE; |
| else if (GRBM_BASE <= addr && addr < GRBM_BASE + GRBM_SIZE) |
| return GRBM_BASE; |
| else if (GFX_BASE <= addr && addr < GFX_BASE + GFX_SIZE) |
| return GFX_BASE; |
| else if (MMHUB_BASE <= addr && addr < MMHUB_BASE + MMHUB_SIZE) |
| return MMHUB_BASE; |
| else { |
| warn_once("Accessing unsupported MMIO aperture! Assuming NBIO\n"); |
| return NBIO_BASE; |
| } |
| |
| } |
| |
| // Gettig mapped aperture base addresses |
| Addr |
| getFrameAperture(Addr addr) |
| { |
| if (addr < gartBase()) { |
| warn_once("Accessing unsupported frame apperture!\n"); |
| return ~0; |
| } else if (gartBase() <= addr && addr < (gartBase() + gartSize())) { |
| return gartBase(); |
| } else { |
| warn_once("Accessing unsupported frame apperture!\n"); |
| return ~0; |
| } |
| |
| } |
| |
| /** |
| * Page table base/start accessors for user VMIDs. |
| */ |
| void |
| setPageTableBase(uint16_t vmid, Addr ptBase) |
| { |
| vmContexts[vmid].ptBase = ptBase; |
| } |
| |
| Addr |
| getPageTableBase(uint16_t vmid) |
| { |
| assert(vmid > 0 && vmid < vmContexts.size()); |
| return vmContexts[vmid].ptBase; |
| } |
| |
| Addr |
| getPageTableStart(uint16_t vmid) |
| { |
| assert(vmid > 0 && vmid < vmContexts.size()); |
| return vmContexts[vmid].ptStart; |
| } |
| |
| /** |
| * Control methods for TLBs associated with the GPU device. |
| */ |
| void registerTLB(VegaISA::GpuTLB *tlb); |
| void invalidateTLBs(); |
| |
| |
| void serialize(CheckpointOut &cp) const override; |
| void unserialize(CheckpointIn &cp) override; |
| |
| /** |
| * Translation range generators |
| * |
| * AGP - Legacy interface to device memory. Addr range is set via MMIO |
| * GART - Legacy privledged translation table. Table in device memory |
| * MMHUB - Shadow range of VRAM |
| */ |
| class AGPTranslationGen : public TranslationGen |
| { |
| private: |
| AMDGPUVM *vm; |
| |
| void translate(Range &range) const override; |
| |
| public: |
| AGPTranslationGen(AMDGPUVM *_vm, Addr vaddr, Addr size) |
| : TranslationGen(vaddr, size), vm(_vm) |
| {} |
| }; |
| |
| class GARTTranslationGen : public TranslationGen |
| { |
| private: |
| AMDGPUVM *vm; |
| |
| void translate(Range &range) const override; |
| |
| public: |
| GARTTranslationGen(AMDGPUVM *_vm, Addr vaddr, Addr size) |
| : TranslationGen(vaddr, size), vm(_vm) |
| {} |
| }; |
| |
| class MMHUBTranslationGen : public TranslationGen |
| { |
| private: |
| AMDGPUVM *vm; |
| |
| void translate(Range &range) const override; |
| |
| public: |
| MMHUBTranslationGen(AMDGPUVM *_vm, Addr vaddr, Addr size) |
| : TranslationGen(vaddr, size), vm(_vm) |
| {} |
| }; |
| |
| class UserTranslationGen : public TranslationGen |
| { |
| private: |
| AMDGPUVM *vm; |
| VegaISA::Walker *walker; |
| int vmid; |
| |
| void translate(Range &range) const override; |
| |
| public: |
| UserTranslationGen(AMDGPUVM *_vm, VegaISA::Walker *_walker, int _vmid, |
| Addr vaddr, Addr size) |
| : TranslationGen(vaddr, size), vm(_vm), walker(_walker), |
| vmid(_vmid) |
| {} |
| }; |
| }; |
| |
| } // namespace gem5 |
| |
| #endif // __DEV_AMDGPU_AMDGPU_VM_HH__ |