| /* | |
| * Copyright (c) 2021 The Regents of the University of California | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * 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; | |
| * neither the name of the copyright holders 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 | |
| * OWNER 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 __ARCH_RISCV_PMP_HH__ | |
| #define __ARCH_RISCV_PMP_HH__ | |
| #include "arch/generic/tlb.hh" | |
| #include "arch/riscv/isa.hh" | |
| #include "base/addr_range.hh" | |
| #include "base/types.hh" | |
| #include "mem/packet.hh" | |
| #include "params/PMP.hh" | |
| #include "sim/sim_object.hh" | |
| /** | |
| * @file | |
| * PMP header file. | |
| */ | |
| namespace gem5 | |
| { | |
| /** | |
| * This class helps to implement RISCV's physical memory | |
| * protection (pmp) primitive. | |
| * @todo Add statistics and debug prints. | |
| */ | |
| class PMP : public SimObject | |
| { | |
| public: | |
| PARAMS(PMP); | |
| PMP(const Params ¶ms); | |
| private: | |
| /** maximum number of entries in the pmp table */ | |
| int pmpEntries; | |
| /** This enum is used for encoding of address matching mode of | |
| * pmp address register, which is present in bits 3-4 (A) of | |
| * pmpcfg register for a pmp entry. | |
| * PMP_OFF = null region (pmp disabled) | |
| * MP_TOR = top of range mode | |
| * PMP_NA4 = naturally aligned four byte region | |
| * PMP_NAPOT = naturally aligned power of two region, >= 8 bytes | |
| */ | |
| enum pmpAmatch | |
| { | |
| PMP_OFF, | |
| PMP_TOR, | |
| PMP_NA4, | |
| PMP_NAPOT | |
| }; | |
| /** pmpcfg address range read permission mask */ | |
| const uint8_t PMP_READ = 1 << 0; | |
| /** pmpcfg address range write permission mask */ | |
| const uint8_t PMP_WRITE = 1 << 1; | |
| /** pmpcfg address range execute permission mask */ | |
| const uint8_t PMP_EXEC = 1 << 2; | |
| /** pmpcfg address range locked mask */ | |
| const uint8_t PMP_LOCK = 1 << 7; | |
| /** variable to keep track of active number of rules any time */ | |
| int numRules; | |
| /** single pmp entry struct*/ | |
| struct PmpEntry | |
| { | |
| /** addr range corresponding to a single pmp entry */ | |
| AddrRange pmpAddr = AddrRange(0, 0); | |
| /** raw addr in pmpaddr register for a pmp entry */ | |
| Addr rawAddr; | |
| /** pmpcfg reg value for a pmp entry */ | |
| uint8_t pmpCfg = 0; | |
| }; | |
| /** a table of pmp entries */ | |
| std::vector<PmpEntry> pmpTable; | |
| public: | |
| /** | |
| * pmpCheck checks if a particular memory access | |
| * is allowed based on the pmp rules. | |
| * @param req memory request. | |
| * @param mode mode of request (read, write, execute). | |
| * @param pmode current privilege mode of execution (U, S, M). | |
| * @param tc thread context. | |
| * @param vaddr optional parameter to pass vaddr of original | |
| * request for which a page table walk is consulted by pmp unit | |
| * @return Fault. | |
| */ | |
| Fault pmpCheck(const RequestPtr &req, BaseMMU::Mode mode, | |
| RiscvISA::PrivilegeMode pmode, ThreadContext *tc, | |
| Addr vaddr = 0); | |
| /** | |
| * pmpUpdateCfg updates the pmpcfg for a pmp | |
| * entry and calls pmpUpdateRule to update the | |
| * rule of corresponding pmp entry. | |
| * @param pmp_index pmp entry index. | |
| * @param this_cfg value to be written to pmpcfg. | |
| */ | |
| void pmpUpdateCfg(uint32_t pmp_index, uint8_t this_cfg); | |
| /** | |
| * pmpUpdateAddr updates the pmpaddr for a pmp | |
| * entry and calls pmpUpdateRule to update the | |
| * rule of corresponding pmp entry. | |
| * @param pmp_index pmp entry index. | |
| * @param this_addr value to be written to pmpaddr. | |
| */ | |
| void pmpUpdateAddr(uint32_t pmp_index, Addr this_addr); | |
| private: | |
| /** | |
| * This function is called during a memory | |
| * access to determine if the pmp table | |
| * should be consulted for this access. | |
| * @param pmode current privilege mode of execution (U, S, M). | |
| * @param mode mode of request (read, write, execute). | |
| * @param tc thread context. | |
| * @return true or false. | |
| */ | |
| bool shouldCheckPMP(RiscvISA::PrivilegeMode pmode, | |
| BaseMMU::Mode mode, ThreadContext *tc); | |
| /** | |
| * createAddrfault creates an address fault | |
| * if the pmp checks fail to pass for a given | |
| * access. This function is used by pmpCheck(). | |
| * given pmp entry depending on the value | |
| * of pmpaddr and pmpcfg for that entry. | |
| * @param vaddr virtual address of the access. | |
| * @param mode mode of access(read, write, execute). | |
| * @return Fault. | |
| */ | |
| Fault createAddrfault(Addr vaddr, BaseMMU::Mode mode); | |
| /** | |
| * pmpUpdateRule updates the pmp rule for a | |
| * given pmp entry depending on the value | |
| * of pmpaddr and pmpcfg for that entry. | |
| * @param pmp_index pmp entry index. | |
| */ | |
| void pmpUpdateRule(uint32_t pmp_index); | |
| /** | |
| * pmpGetAField extracts the A field (address matching mode) | |
| * from an input pmpcfg register | |
| * @param cfg pmpcfg register value. | |
| * @return The A field. | |
| */ | |
| inline uint8_t pmpGetAField(uint8_t cfg); | |
| /** | |
| * This function decodes a pmpaddr register value | |
| * into an address range when A field of pmpcfg | |
| * register is set to NAPOT mode (naturally aligned | |
| * power of two region). | |
| * @param pmpaddr input address from a pmp entry. | |
| * @return an address range. | |
| */ | |
| inline AddrRange pmpDecodeNapot(Addr pmpaddr); | |
| }; | |
| } // namespace gem5 | |
| #endif // __ARCH_RISCV_PMP_HH__ |