blob: 40e738f7422967f8eed378bb3c3fc7a5b9cae12a [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_EPMP_STATE_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_EPMP_STATE_H_
#include <stdint.h>
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/silicon_creator/lib/epmp_defs.h"
#include "sw/device/silicon_creator/lib/error.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* Silicon creator ePMP library.
*
* This library provides functions to create and manage an in-memory copy of the
* ePMP configuration. To update the hardware configuration please use either
* assembly or the CSR library directly as needed.
*/
enum {
/**
* The number of PMP entries supported by the hardware.
*/
kEpmpNumRegions = 16,
};
/**
* PMP configuration permission settings.
*
* May be combined with `epmp_mode_t` values to form complete configurations.
*
* Bit | Index
* ----+------
* L | 7
* R | 0
* W | 1
* X | 2
*
* Combinations not exposed by this enum should not be used. The 'unlocked'
* zero value should only be used for entries that are configured as OFF.
*/
typedef enum epmp_perm {
kEpmpPermUnlocked = 0,
kEpmpPermLockedNoAccess = EPMP_CFG_L,
kEpmpPermLockedReadOnly = EPMP_CFG_LR,
kEpmpPermLockedReadWrite = EPMP_CFG_LRW,
kEpmpPermLockedReadExecute = EPMP_CFG_LRX,
kEpmpPermLockedReadWriteExecute = EPMP_CFG_LRWX,
} epmp_perm_t;
/**
* PMP configuration addressing mode fields.
*
* May be combined with `epmp_perm_t` values to form complete configurations.
*/
typedef enum epmp_mode {
kEpmpModeOff = EPMP_CFG_A_OFF,
kEpmpModeTor = EPMP_CFG_A_TOR,
kEpmpModeNa4 = EPMP_CFG_A_NA4,
kEpmpModeNapot = EPMP_CFG_A_NAPOT,
} epmp_mode_t;
/**
* ePMP region specification.
*
* Provides the unencoded start and end addresses of a particular region.
*
* The `start` address is inclusive and the `end` address is exclusive.
*/
typedef struct epmp_region {
uintptr_t start;
uintptr_t end;
} epmp_region_t;
/**
* In-memory copy of the ePMP register state.
*/
typedef struct epmp_state {
/**
* PMP configuration values (pmpcfg0 - pmpcfg3).
*
* The 8-bit configuration values (pmp0cfg - pmp15cfg) are packed into these
* registers in little-endian byte order.
*
* Each 8-bit configuration value is encoded as follows:
*
* Layout:
*
* +---+-------+-------+---+---+---+
* | L | 0 | A | X | W | R |
* +---+-------+-------+---+---+---+
* 8 7 6 5 4 3 2 1 0
*
* Key:
*
* L = Locked
* A = Address-matching Mode (OFF=0, TOR=1, NA4=2, NAPOT=3)
* X = Executable
* W = Writeable
* R = Readable
*
* Note: the interpretation of these configuration bits depends on
* whether Machine Mode Lockdown (mseccfg.MML) is enabled or not.
* See the PMP Enhancements specification for more details.
*/
uint32_t pmpcfg[kEpmpNumRegions / 4];
/**
* PMP address registers (pmpaddr0 - pmpaddr15).
*
* The way that address register values are interpreted differs
* depending on the address-matching mode (A) in the relevant pmpcfg
* register(s).
*/
uint32_t pmpaddr[kEpmpNumRegions];
/**
* Machine Security Configuration register (mseccfg).
*
* +---...---+------+------+------+
* | 0 | RLB | MMWP | MML |
* +---...---+------+------+------+
* 63 3 2 1 0
*
* Key:
*
* RLB = Rule Locking Bypass
* MMWP = Machine Mode Whitelist Policy
* MML = Machine Mode Lockdown
*
* See the PMP Enhancements specification for more details.
*
* Note: these are the low 32 bits of mseccfg only. The high 32 bits
* are set to 0.
*/
uint32_t mseccfg;
} epmp_state_t;
extern epmp_state_t epmp_state;
/**
* Configure the given PMP entry in state using the Top-Of-Range addressing
* mode.
*
* @param state The ePMP state to update.
* @param entry The index of the entry to update.
* @param region The memory region to encode in the address registers.
* @param perm The permissions to set for the entry.
*/
inline void epmp_state_configure_tor(uint32_t entry, epmp_region_t region,
epmp_perm_t perm) {
// Set address registers.
if (entry > 0) {
epmp_state.pmpaddr[entry - 1] = region.start >> 2;
}
epmp_state.pmpaddr[entry] = region.end >> 2;
// Set configuration register.
bitfield_field32_t field = {.mask = 0xff, .index = (entry % 4) * 8};
epmp_state.pmpcfg[entry / 4] = bitfield_field32_write(
epmp_state.pmpcfg[entry / 4], field, kEpmpModeTor | perm);
}
/**
* Configure the given PMP entry in state using the Naturally-Aligned-4-byte
* addressing mode.
*
* @param state The ePMP state to update.
* @param entry The index of the entry to update.
* @param region The memory region to encode in the address registers.
* @param perm The permissions to set for the entry.
*/
inline void epmp_state_configure_na4(uint32_t entry, epmp_region_t region,
epmp_perm_t perm) {
// Set address register.
epmp_state.pmpaddr[entry] = region.start >> 2;
// Set configuration register.
bitfield_field32_t field = {.mask = 0xff, .index = (entry % 4) * 8};
epmp_state.pmpcfg[entry / 4] = bitfield_field32_write(
epmp_state.pmpcfg[entry / 4], field, kEpmpModeNa4 | perm);
}
/**
* Configure the given PMP entry in state using the
* Naturally-Aligned-Power-Of-Two addressing mode.
*
* @param state The ePMP state to update.
* @param entry The index of the entry to update.
* @param region The memory region to encode in the address registers.
* @param perm The permissions to set for the entry.
*/
inline void epmp_state_configure_napot(uint32_t entry, epmp_region_t region,
epmp_perm_t perm) {
// Set address register.
uint32_t len = (region.end - region.start - 1) >> 3;
epmp_state.pmpaddr[entry] = (region.start >> 2) | len;
// Set configuration register.
bitfield_field32_t field = {.mask = 0xff, .index = (entry % 4) * 8};
epmp_state.pmpcfg[entry / 4] = bitfield_field32_write(
epmp_state.pmpcfg[entry / 4], field, kEpmpModeNapot | perm);
}
/**
* Report whether the given state matches the current hardware ePMP
* configuration.
*
* @param state Expected values of the ePMP CSRs.
* @return Whether the check succeeded.
*/
rom_error_t epmp_state_check(void);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_EPMP_STATE_H_