mcu_hi3321_watch/kernel/freertos/FreeRTOS/Arch/RISC-V/include/pmp.h
2025-05-26 20:15:20 +08:00

414 lines
10 KiB
C

/*
* Copyright (c) CompanyNameMagicTag 2021-2022. All rights reserved.
*/
#ifndef _ARCH_PMP_H
#define _ARCH_PMP_H
#include "stdint.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup pmp
* Locking PMP entry.
*/
#define PMP_RGN_LOCK 0x80
#define PMP_MAX_SUPPORT 16
#define PMP_MIN_ADDRESS 0x00000000UL
#define PMP_MAX_ADDRESS 0xFFFFFFFFUL
/**
* @ingroup pmp
* Address Matching.
*/
#define PMP_RGN_ADDR_MATCH_OFF 0 /* Null region (disabled) */
#define PMP_RGN_ADDR_MATCH_TOR 0x8 /* Top of range */
#define PMP_RGN_ADDR_MATCH_NA4 0x10 /* Naturally aligned four-byte region */
#define PMP_RGN_ADDR_MATCH_NAPOT 0x18 /* Naturally aligned power-of-two region, >= 8 bytes */
#define PMP_RGN_ADDR_MATCH_MASK 0x18
/**
* @ingroup pmp
* Access permission.
*/
#define PMPCFG_R_BIT 0
#define PMPCFG_W_BIT 1
#define PMPCFG_X_BIT 2
/* risc-v pmp register config */
#define MEMATTRL 0x7D8
#define MEMATTRH 0x7D9
#define SECTL 0x7DA
#ifndef __ASSEMBLER__
enum MemReadAcc {
E_MEM_RD_ACC_NON_RD = 0,
E_MEM_RD_ACC_RD = 1,
};
enum MemWriteReadAcc {
E_MEM_WR_ACC_NON_WR = 0,
E_MEM_WR_ACC_WR = 1,
};
enum MemExecuteAcc {
E_MEM_EX_ACC_NON_EX = 0,
E_MEM_EX_ACC_EX = 1,
};
typedef struct {
enum MemReadAcc readAcc;
enum MemWriteReadAcc writeAcc;
enum MemExecuteAcc excuteAcc;
} PmpAccInfo;
/**
* @ingroup pmp
* memory attribute.
*/
typedef enum {
MEM_ATTR_DEV_NON_BUF = 0, /* 4b0000, device non-bufferable */
MEM_ATTR_NORM_NON_CA_NON_BUF = 2, /* 4b0010, normal non-cacheable non-bufferable */
MEM_ATTR_NORM_NON_CA_BUF = 3, /* 4b0011, normal non-cacheable bufferable */
MEM_ATTR_WB_RD_ALLOC = 7, /* 4b0111, write-back read-only allocate */
MEM_ATTR_WB_WR_ALLOC = 11, /* 4b1011, write-back write-only allocate */
MEM_ATTR_WB_RW_ALLOC = 15, /* 4b1111, write-back write and read allocate */
} PmpMemAttrInfo;
typedef enum {
SEC_CONTRLO_SECURE_NOMMU = 0, /* secure and disable SoC IOMMU */
SEC_CONTRLO_NOSECURE_NOMMU = 1, /* no-secure and disable SoC IOMMU */
SEC_CONTRLO_SECURE_MMU = 2, /* secure and enable SoC IOMMU */
SEC_CONTRLO_NOSECURE_MMU = 3, /* no-secure and enable SoC IOMMU */
} PmpSeControlInfo;
/**
* @ingroup pmp
* PMP entry info
* uwBaseAddress must be in the range of RAM, and
* uwRegionSize granularity must be the multiple of cache line size
* if addrress matching mode equals to NPAOT, the base address and size should match the type and size
* uwAccessPermission is not arbitrary input
*/
typedef struct {
/* Index of PMP entry */
uint8_t ucNumber;
/* whether lock, Works in any supported mode */
BaseType_t bLocked;
/*
* Address matching mode of PMP configuration,
* Currently supported modes: PMP_RGN_ADDR_MATCH_OFF,
* PMP_RGN_ADDR_MATCH_TOR and PMP_RGN_ADDR_MATCH_NAPOT.
*/
uint8_t ucAddressMatch;
/*
* access permission of read, write and instruction execution.
* The changed member is not valid in PMP_RGN_ADDR_MATCH_OFF mode.
*/
PmpAccInfo accPermission;
/*
* set the base address of the protected region,
* the base address must be in the range of RAM.
* It should be cache line aligned under the cache.
*/
uint32_t uwBaseAddress;
/*
* PMP entry region size: It is valid only in PMP_RGN_ADDR_MATCH_NAPOT mode,
* requiring >= 8byte and aligned power-of-2 byte.
* It should be cache line aligned under the cache.
*/
uint32_t uwRegionSize;
/*
* PMP memory attribute register information:
* The changed member is not valid in PMP_RGN_ADDR_MATCH_OFF mode.
*/
PmpMemAttrInfo memAttr;
/*
* Security control register information:
* The changed member is not valid in PMP_RGN_ADDR_MATCH_OFF mode.
*/
PmpSeControlInfo seCtl;
} PMP_ENTRY_INFO;
/**
* @ingroup pmp
* PMP error code: The pointer to an input parameter is NULL.
*
* Value: 0x00
*
* Solution: Check whether the pointer to the input parameter is usable.
*/
#define errPMP_PTR_NULL 0x00
/**
* @ingroup pmp
* PMP error code: The base address is not aligned to the boundary of the region capacity.
*
* Value: 0x01
*
* Solution: Check base address.
*/
#define errPMP_INVALID_BASE_ADDRESS 0x01
/**
* @ingroup pmp
* PMP error code: Capacity less than cacheline bytes.
* The PMP entry size granularity must be the multiple of cache line size.
*
* Value: 0x02
*
* Solution: Guaranteed that the capacity is greater than or equal to cacheline, supporting cacheline granularity.
*/
#define errPMP_INVALID_CAPACITY 0x02
/**
* @ingroup pmp
* PMP error code: Type extension that given is invalid.
*
* Value: 0x03
*
* Solution: memory attribute configuration only support 0000,0010,0011,0111,,1011,1111
*/
#define errPMP_ATTR_INVALID 0x03
/**
* @ingroup pmp
* PMP error code: Invalid number.
*
* Value: 0x04
*
* Solution: Enter a valid number.
*/
#define errPMP_INVALID_NUMBER 0x04
/**
* @ingroup pmp
* PMP error code: The next PMP is TOR mode, current pmpcfg match is error.
*
* Value: 0x05
*
* Solution: The next PMP is TOR mode, and when modifying the current pmpcfg,
* When modifying the current config, if the current pmpcfg original match is
* PMP_RGN_ADDR_MATCH_TOR or PMP_RGN_ADDR_MATCH_OFF, the modified match must
* be PMP_RGN_ADDR_MATCH_TOR or PMP_RGN_ADDR_MATCH_OFF.
*/
#define errPMP_TOR_INVALID_MATCH_MODE 0x05
/**
* @ingroup pmp
* PMP error code: The next PMP is TOR mode, current pmpcfg match is error.
*
* Value: 0x06
*
* Solution: The next PMP is TOR mode, and when modifying the current pmpcfg,
* When modifying the current config, if the current pmpcfg original match is
* PMP_RGN_ADDR_MATCH_NAPOT, the modified match must be PMP_RGN_ADDR_MATCH_NAPOT.
*/
#define errPMP_NAPOT_INVALID_MATCH_MODE 0x06
/**
* @ingroup pmp
* PMP error code: Invalid access.
*
* Value: 0x07
*
* Solution: Checking whether the access is correct.
*/
#define errPMP_REGION_INVALID_ACCESS 0x07
/**
* @ingroup pmp
* PMP error code: Base address is not in range.
*
* Value: 0x08
*
* Solution: Checking base address
*/
#define errPMP_BASE_ADDRESS_NOT_IN_RANGE 0x08
/**
* @ingroup pmp
* PMP error code: According to the current base address, the size of the application is too big.
*
* Value: 0x09
*
* Solution: baseAddress + regionSize must not exceed RAM Max address
*/
#define errPMP_REGION_SIZE_IS_TOO_BIG 0x09
/**
* @ingroup pmp
* PMP error code: According to the current configuration, the PMP entry is locked.
*
* Value: 0x0a
*
* Solution: if PMP entry is locked, then write configuration and address register will be ignored,
* you should reset the system.
*/
#define errPMP_ENTRY_IS_LOCKED 0x0a
/**
* @ingroup pmp
* PMP error code: PMP_RGN_ADDR_MATCH_NA4 is Unsupported patterns.
*
* Value: 0x0b
*
* Solution: PMP_RGN_ADDR_MATCH_NA4 is not support now.
*/
#define errPMP_INVALID_MATCH 0x0b
/**
* @ingroup pmp
* PMP error code: According to the current configuration,
* the NAPOT type and size is not matched in NAPOT range encoding.
*
* Value: 0x0c
*
* Solution: baseAddress + regionSize must obey the NAPOT range encoding rules.
*/
#define errPMP_NAPOT_ENCODING_NON_MATCHED 0x0c
/**
* @ingroup pmp
* PMP error code: According to the current configuration, if pmp(i + 1)cfg.A is set to TOR,
* writes to pmpaddr(i) are ignored.
*
* Value: 0x0d
*
* Solution: check if the lower bound of region is locked of this region when setting address matching mode to TOR.
*/
#define errPMP_TOR_LOWER_BOUND_LOCKED 0x0d
/**
* @ingroup pmp
* PMP error code: According to the current configuration, check whether the lower bound of TOR region equals to
* the pre-region end address
*
* Value: 0x0e
*
* Solution: set the lower bound of TOR i-th region to the pre-region, i.e. (i-1)'th region end address
*/
#define errPMP_TOR_LOWER_BOUND_NONMATCHED 0x0e
/**
* @ingroup pmp
* PMP error code: Type extension that given is invalid.
*
* Value: 0xf
*
* Solution: memory sectl configuration only support 00,01,10,11
*/
#define errPMP_SECTL_INVALID 0xf
/**
* pmp.h
* <pre>
* uint32_t ulArchProtectionUnitInit(uint64_t minAddr, uint64_t maxAddr);
* </pre>
*
* pmp region init
*
* @param minAddr Minimum protected address.
*
* @param maxAddr Maximum protected address
*
* @return pdPASS.
*
* \defgroup ulArchProtectionUnitInit ulArchProtectionUnitInit
* \ingroup pmp
*/
uint32_t ulArchProtectionUnitInit(uint64_t minAddr, uint64_t maxAddr);
/**
* pmp.h
* <pre>
* uint32_t ulArchGetSectl( void );
* </pre>
*
* pmp Sectl region get.
*
* @param none.
*
* @return Sectl register value is returned.
*
* \defgroup ulArchGetSectl ulArchGetSectl
* \ingroup pmp
*/
uint32_t ulArchGetSectl(void);
/**
* pmp.h
* <pre>
* uint32_t ulArchRegionDisable(uint8_t number);
* </pre>
*
* pmp region disable.
*
* @param number The pmp entry number.
*
* @return pdPASS, error information.
*
* \defgroup ulArchRegionDisable ulArchRegionDisable
* \ingroup pmp
*/
uint32_t ulArchRegionDisable(uint8_t number);
/**
* pmp.h
* <pre>
* uint32_t ulArchProtectionRegionSet(PMP_ENTRY_INFO *pmpInfo);
* </pre>
*
* Set protection memory region.
*
* @param pmpInfo Set the related configuration information for the protected area,
* @param pmpInfo->bLocked Lock region in machine mode. if 1, lock region, validating access permission in
* machine mode, otherwise, disable it.
*
* @return pdPASS or the index of pmpInfo which set up failed.
*
* \defgroup ulArchProtectionRegionSet ulArchProtectionRegionSet
* \ingroup pmp
*/
uint32_t ulArchProtectionRegionSet(PMP_ENTRY_INFO *pmpInfo);
/**
* pmp.h
* <pre>
* void vArchPmpAddrWrite(uint8_t pmpAddrIdx, uint32_t pmpAddrVal);
* </pre>
*
* Set pmp addr.
*
* @param pmpAddrIdx pmp addr index.
* @param pmpAddrVal pmp addr value.
*
* @return none.
*
* \defgroup ulArchProtectionRegionSet ulArchProtectionRegionSet
* \ingroup pmp
*/
void vArchPmpAddrWrite(uint8_t pmpAddrIdx, uint32_t pmpAddrVal);
#endif /* __ASSEMBLER__ */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _ARCH_PMP_H */