arch: riscv: add pmp support
- Set some helper function to write/clear/print PMP config registers. - Add support for different PMP slot size function to core/board. Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
This commit is contained in:
parent
6340dd7a59
commit
18962e4ab8
7 changed files with 553 additions and 0 deletions
|
@ -25,6 +25,7 @@ menu "RISCV Processor Options"
|
|||
|
||||
config CORE_E31
|
||||
bool "Use E31 core"
|
||||
select RISCV_PMP
|
||||
select ARCH_HAS_USERSPACE
|
||||
select ARCH_HAS_STACK_PROTECTION if PMP_STACK_GUARD
|
||||
default n
|
||||
|
@ -112,6 +113,19 @@ config GEN_IRQ_VECTOR_TABLE
|
|||
config NUM_IRQS
|
||||
int
|
||||
|
||||
menuconfig RISCV_PMP
|
||||
bool "RISC-V PMP Support"
|
||||
default n
|
||||
select THREAD_STACK_INFO
|
||||
select MEMORY_PROTECTION
|
||||
select ARCH_MEM_DOMAIN_SYNCHRONOUS_API if USERSPACE
|
||||
help
|
||||
MCU implements Physical Memory Protection.
|
||||
|
||||
if RISCV_PMP
|
||||
source "arch/riscv/core/pmp/Kconfig"
|
||||
endif #RISCV_PMP
|
||||
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_RISCV_PMP pmp)
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(
|
||||
|
|
14
arch/riscv/core/pmp/CMakeLists.txt
Normal file
14
arch/riscv/core/pmp/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Copyright (c) 2020 BayLibre, SAS
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_RISCV_PMP core_pmp.c)
|
||||
|
||||
zephyr_library_include_directories(
|
||||
.
|
||||
../../include
|
||||
)
|
11
arch/riscv/core/pmp/Kconfig
Normal file
11
arch/riscv/core/pmp/Kconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Physical Memory Protection (PMP) configuration options
|
||||
|
||||
# Copyright (c) 2020 BayLibre, SAS
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config PMP_SLOT
|
||||
int "Number of PMP slot"
|
||||
default 8
|
||||
help
|
||||
Depend of the arch/board. Take care to don't put value higher
|
||||
than the Hardware allow you.
|
221
arch/riscv/core/pmp/core_pmp.c
Normal file
221
arch/riscv/core/pmp/core_pmp.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2020 BayLibre, SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_internal.h>
|
||||
#include "core_pmp.h"
|
||||
#include <arch/riscv/csr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define PMP_SLOT_NUMBER CONFIG_PMP_SLOT
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
extern ulong_t is_user_mode;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CSR_PMPCFG0,
|
||||
CSR_PMPCFG1,
|
||||
CSR_PMPCFG2,
|
||||
CSR_PMPCFG3,
|
||||
CSR_PMPADDR0,
|
||||
CSR_PMPADDR1,
|
||||
CSR_PMPADDR2,
|
||||
CSR_PMPADDR3,
|
||||
CSR_PMPADDR4,
|
||||
CSR_PMPADDR5,
|
||||
CSR_PMPADDR6,
|
||||
CSR_PMPADDR7,
|
||||
CSR_PMPADDR8,
|
||||
CSR_PMPADDR9,
|
||||
CSR_PMPADDR10,
|
||||
CSR_PMPADDR11,
|
||||
CSR_PMPADDR12,
|
||||
CSR_PMPADDR13,
|
||||
CSR_PMPADDR14,
|
||||
CSR_PMPADDR15
|
||||
};
|
||||
|
||||
ulong_t csr_read_enum(int pmp_csr_enum)
|
||||
{
|
||||
ulong_t res = -1;
|
||||
|
||||
switch (pmp_csr_enum) {
|
||||
case CSR_PMPCFG0:
|
||||
res = csr_read(0x3A0); break;
|
||||
case CSR_PMPCFG1:
|
||||
res = csr_read(0x3A1); break;
|
||||
case CSR_PMPCFG2:
|
||||
res = csr_read(0x3A2); break;
|
||||
case CSR_PMPCFG3:
|
||||
res = csr_read(0x3A3); break;
|
||||
case CSR_PMPADDR0:
|
||||
res = csr_read(0x3B0); break;
|
||||
case CSR_PMPADDR1:
|
||||
res = csr_read(0x3B1); break;
|
||||
case CSR_PMPADDR2:
|
||||
res = csr_read(0x3B2); break;
|
||||
case CSR_PMPADDR3:
|
||||
res = csr_read(0x3B3); break;
|
||||
case CSR_PMPADDR4:
|
||||
res = csr_read(0x3B4); break;
|
||||
case CSR_PMPADDR5:
|
||||
res = csr_read(0x3B5); break;
|
||||
case CSR_PMPADDR6:
|
||||
res = csr_read(0x3B6); break;
|
||||
case CSR_PMPADDR7:
|
||||
res = csr_read(0x3B7); break;
|
||||
case CSR_PMPADDR8:
|
||||
res = csr_read(0x3B8); break;
|
||||
case CSR_PMPADDR9:
|
||||
res = csr_read(0x3B9); break;
|
||||
case CSR_PMPADDR10:
|
||||
res = csr_read(0x3BA); break;
|
||||
case CSR_PMPADDR11:
|
||||
res = csr_read(0x3BB); break;
|
||||
case CSR_PMPADDR12:
|
||||
res = csr_read(0x3BC); break;
|
||||
case CSR_PMPADDR13:
|
||||
res = csr_read(0x3BD); break;
|
||||
case CSR_PMPADDR14:
|
||||
res = csr_read(0x3BE); break;
|
||||
case CSR_PMPADDR15:
|
||||
res = csr_read(0x3BF); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void csr_write_enum(int pmp_csr_enum, ulong_t value)
|
||||
{
|
||||
switch (pmp_csr_enum) {
|
||||
case CSR_PMPCFG0:
|
||||
csr_write(0x3A0, value); break;
|
||||
case CSR_PMPCFG1:
|
||||
csr_write(0x3A1, value); break;
|
||||
case CSR_PMPCFG2:
|
||||
csr_write(0x3A2, value); break;
|
||||
case CSR_PMPCFG3:
|
||||
csr_write(0x3A3, value); break;
|
||||
case CSR_PMPADDR0:
|
||||
csr_write(0x3B0, value); break;
|
||||
case CSR_PMPADDR1:
|
||||
csr_write(0x3B1, value); break;
|
||||
case CSR_PMPADDR2:
|
||||
csr_write(0x3B2, value); break;
|
||||
case CSR_PMPADDR3:
|
||||
csr_write(0x3B3, value); break;
|
||||
case CSR_PMPADDR4:
|
||||
csr_write(0x3B4, value); break;
|
||||
case CSR_PMPADDR5:
|
||||
csr_write(0x3B5, value); break;
|
||||
case CSR_PMPADDR6:
|
||||
csr_write(0x3B6, value); break;
|
||||
case CSR_PMPADDR7:
|
||||
csr_write(0x3B7, value); break;
|
||||
case CSR_PMPADDR8:
|
||||
csr_write(0x3B8, value); break;
|
||||
case CSR_PMPADDR9:
|
||||
csr_write(0x3B9, value); break;
|
||||
case CSR_PMPADDR10:
|
||||
csr_write(0x3BA, value); break;
|
||||
case CSR_PMPADDR11:
|
||||
csr_write(0x3BB, value); break;
|
||||
case CSR_PMPADDR12:
|
||||
csr_write(0x3BC, value); break;
|
||||
case CSR_PMPADDR13:
|
||||
csr_write(0x3BD, value); break;
|
||||
case CSR_PMPADDR14:
|
||||
csr_write(0x3BE, value); break;
|
||||
case CSR_PMPADDR15:
|
||||
csr_write(0x3BF, value); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int z_riscv_pmp_set(unsigned int index, ulong_t cfg_val, ulong_t addr_val)
|
||||
{
|
||||
ulong_t reg_val;
|
||||
ulong_t shift, mask;
|
||||
int pmpcfg_csr;
|
||||
int pmpaddr_csr;
|
||||
|
||||
if ((index >= PMP_SLOT_NUMBER) | (index < 0))
|
||||
return -1;
|
||||
|
||||
/* Calculate PMP config/addr register, shift and mask */
|
||||
#ifdef CONFIG_64BIT
|
||||
pmpcfg_csr = CSR_PMPCFG0 + ((index >> 3) << 1);
|
||||
shift = (index & 0x7) << 3;
|
||||
#else
|
||||
pmpcfg_csr = CSR_PMPCFG0 + (index >> 2);
|
||||
shift = (index & 0x3) << 3;
|
||||
#endif /* CONFIG_64BIT */
|
||||
pmpaddr_csr = CSR_PMPADDR0 + index;
|
||||
|
||||
/* Mask = 0x000000FF<<((index%4)*8) */
|
||||
mask = 0x000000FF << shift;
|
||||
|
||||
cfg_val = cfg_val << shift;
|
||||
addr_val = TO_PMP_ADDR(addr_val);
|
||||
|
||||
reg_val = csr_read_enum(pmpcfg_csr);
|
||||
reg_val = reg_val & ~mask;
|
||||
reg_val = reg_val | cfg_val;
|
||||
|
||||
csr_write_enum(pmpaddr_csr, addr_val);
|
||||
csr_write_enum(pmpcfg_csr, reg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pmp_get(unsigned int index, ulong_t *cfg_val, ulong_t *addr_val)
|
||||
{
|
||||
ulong_t shift;
|
||||
int pmpcfg_csr;
|
||||
int pmpaddr_csr;
|
||||
|
||||
if ((index >= PMP_SLOT_NUMBER) | (index < 0))
|
||||
return -1;
|
||||
|
||||
/* Calculate PMP config/addr register and shift */
|
||||
#ifdef CONFIG_64BIT
|
||||
pmpcfg_csr = CSR_PMPCFG0 + (index >> 4);
|
||||
shift = (index & 0x0007) << 3;
|
||||
#else
|
||||
pmpcfg_csr = CSR_PMPCFG0 + (index >> 2);
|
||||
shift = (index & 0x0003) << 3;
|
||||
#endif /* CONFIG_64BIT */
|
||||
pmpaddr_csr = CSR_PMPADDR0 + index;
|
||||
|
||||
*cfg_val = (csr_read_enum(pmpcfg_csr) >> shift) & 0xFF;
|
||||
*addr_val = FROM_PMP_ADDR(csr_read_enum(pmpaddr_csr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void z_riscv_pmp_clear_config(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < RISCV_PMP_CFG_NUM; i++)
|
||||
csr_write_enum(CSR_PMPCFG0 + i, 0);
|
||||
}
|
||||
|
||||
/* Function to help debug */
|
||||
void z_riscv_pmp_print(unsigned int index)
|
||||
{
|
||||
ulong_t cfg_val;
|
||||
ulong_t addr_val;
|
||||
|
||||
if (pmp_get(index, &cfg_val, &addr_val))
|
||||
return;
|
||||
#ifdef CONFIG_64BIT
|
||||
printf("PMP[%d] :\t%02lX %16lX\n", index, cfg_val, addr_val);
|
||||
#else
|
||||
printf("PMP[%d] :\t%02lX %08lX\n", index, cfg_val, addr_val);
|
||||
#endif /* CONFIG_64BIT */
|
||||
}
|
57
arch/riscv/include/core_pmp.h
Normal file
57
arch/riscv/include/core_pmp.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2020 BayLibre, SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef CORE_PMP_H_
|
||||
#define CORE_PMP_H_
|
||||
|
||||
/* Configuration register flags (cfg_val)*/
|
||||
#define PMP_R 0x01 /* Allow read */
|
||||
#define PMP_W 0x02 /* Allow write */
|
||||
#define PMP_X 0x04 /* Allow execute */
|
||||
#define PMP_A 0x18 /* Address-matching mode field */
|
||||
#define PMP_L 0x80 /* PMP entry is locked */
|
||||
#define PMP_OFF 0x00 /* Null region */
|
||||
#define PMP_TOR 0x08 /* Top of range */
|
||||
#define PMP_NA4 0x10 /* Naturally aligned four-byte region */
|
||||
#define PMP_NAPOT 0x18 /* Naturally aligned power-of-two region */
|
||||
|
||||
#define PMP_SHIFT_ADDR 2
|
||||
#define PMP_TYPE_MASK 0x18
|
||||
#define TO_PMP_ADDR(addr) ((addr) >> PMP_SHIFT_ADDR)
|
||||
#define FROM_PMP_ADDR(addr) ((addr) << PMP_SHIFT_ADDR)
|
||||
#define TO_NAPOT_RANGE(size) (((size) - 1) >> 1)
|
||||
#define TO_PMP_NAPOT(addr, size) TO_PMP_ADDR(addr | \
|
||||
TO_NAPOT_RANGE(size))
|
||||
|
||||
#ifdef CONFIG_RISCV_PMP
|
||||
|
||||
/*
|
||||
* @brief Set a Physical Memory Protection slot
|
||||
*
|
||||
* Configure a memory region to be secured by one of the 16 PMP entries.
|
||||
*
|
||||
* @param index Number of the targeted PMP entrie (0 to 15 only).
|
||||
* @param cfg_val Configuration value (cf datasheet or defined flags)
|
||||
* @param addr_val Address register value
|
||||
*
|
||||
* This function shall only be called from Secure state.
|
||||
*
|
||||
* @return -1 if bad argument, 0 otherwise.
|
||||
*/
|
||||
int z_riscv_pmp_set(unsigned int index, ulong_t cfg_val, ulong_t addr_val);
|
||||
|
||||
/*
|
||||
* @brief Reset to 0 all PMP setup registers
|
||||
*/
|
||||
void z_riscv_pmp_clear_config(void);
|
||||
|
||||
/*
|
||||
* @brief Print PMP setup register for info/debug
|
||||
*/
|
||||
void z_riscv_pmp_print(unsigned int index);
|
||||
#endif /* CONFIG_RISCV_PMP */
|
||||
|
||||
#endif /* CORE_PMP_H_ */
|
234
include/arch/riscv/csr.h
Normal file
234
include/arch/riscv/csr.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright (c) 2020 BayLibre, SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef CSR_H_
|
||||
#define CSR_H_
|
||||
|
||||
#define MSTATUS_UIE 0x00000001
|
||||
#define MSTATUS_SIE 0x00000002
|
||||
#define MSTATUS_HIE 0x00000004
|
||||
#define MSTATUS_MIE 0x00000008
|
||||
#define MSTATUS_UPIE 0x00000010
|
||||
#define MSTATUS_SPIE 0x00000020
|
||||
#define MSTATUS_HPIE 0x00000040
|
||||
#define MSTATUS_MPIE 0x00000080
|
||||
#define MSTATUS_SPP 0x00000100
|
||||
#define MSTATUS_HPP 0x00000600
|
||||
#define MSTATUS_MPP 0x00001800
|
||||
#define MSTATUS_FS 0x00006000
|
||||
#define MSTATUS_XS 0x00018000
|
||||
#define MSTATUS_MPRV 0x00020000
|
||||
#define MSTATUS_SUM 0x00040000
|
||||
#define MSTATUS_MXR 0x00080000
|
||||
#define MSTATUS_TVM 0x00100000
|
||||
#define MSTATUS_TW 0x00200000
|
||||
#define MSTATUS_TSR 0x00400000
|
||||
#define MSTATUS32_SD 0x80000000
|
||||
#define MSTATUS_UXL 0x0000000300000000
|
||||
#define MSTATUS_SXL 0x0000000C00000000
|
||||
#define MSTATUS64_SD 0x8000000000000000
|
||||
|
||||
#define SSTATUS_UIE 0x00000001
|
||||
#define SSTATUS_SIE 0x00000002
|
||||
#define SSTATUS_UPIE 0x00000010
|
||||
#define SSTATUS_SPIE 0x00000020
|
||||
#define SSTATUS_SPP 0x00000100
|
||||
#define SSTATUS_FS 0x00006000
|
||||
#define SSTATUS_XS 0x00018000
|
||||
#define SSTATUS_SUM 0x00040000
|
||||
#define SSTATUS_MXR 0x00080000
|
||||
#define SSTATUS32_SD 0x80000000
|
||||
#define SSTATUS_UXL 0x0000000300000000
|
||||
#define SSTATUS64_SD 0x8000000000000000
|
||||
|
||||
#define DCSR_XDEBUGVER (3U<<30)
|
||||
#define DCSR_NDRESET (1<<29)
|
||||
#define DCSR_FULLRESET (1<<28)
|
||||
#define DCSR_EBREAKM (1<<15)
|
||||
#define DCSR_EBREAKH (1<<14)
|
||||
#define DCSR_EBREAKS (1<<13)
|
||||
#define DCSR_EBREAKU (1<<12)
|
||||
#define DCSR_STOPCYCLE (1<<10)
|
||||
#define DCSR_STOPTIME (1<<9)
|
||||
#define DCSR_CAUSE (7<<6)
|
||||
#define DCSR_DEBUGINT (1<<5)
|
||||
#define DCSR_HALT (1<<3)
|
||||
#define DCSR_STEP (1<<2)
|
||||
#define DCSR_PRV (3<<0)
|
||||
|
||||
#define DCSR_CAUSE_NONE 0
|
||||
#define DCSR_CAUSE_SWBP 1
|
||||
#define DCSR_CAUSE_HWBP 2
|
||||
#define DCSR_CAUSE_DEBUGINT 3
|
||||
#define DCSR_CAUSE_STEP 4
|
||||
#define DCSR_CAUSE_HALT 5
|
||||
|
||||
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
|
||||
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
|
||||
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
|
||||
|
||||
#define MCONTROL_SELECT (1<<19)
|
||||
#define MCONTROL_TIMING (1<<18)
|
||||
#define MCONTROL_ACTION (0x3f<<12)
|
||||
#define MCONTROL_CHAIN (1<<11)
|
||||
#define MCONTROL_MATCH (0xf<<7)
|
||||
#define MCONTROL_M (1<<6)
|
||||
#define MCONTROL_H (1<<5)
|
||||
#define MCONTROL_S (1<<4)
|
||||
#define MCONTROL_U (1<<3)
|
||||
#define MCONTROL_EXECUTE (1<<2)
|
||||
#define MCONTROL_STORE (1<<1)
|
||||
#define MCONTROL_LOAD (1<<0)
|
||||
|
||||
#define MCONTROL_TYPE_NONE 0
|
||||
#define MCONTROL_TYPE_MATCH 2
|
||||
|
||||
#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
|
||||
#define MCONTROL_ACTION_DEBUG_MODE 1
|
||||
#define MCONTROL_ACTION_TRACE_START 2
|
||||
#define MCONTROL_ACTION_TRACE_STOP 3
|
||||
#define MCONTROL_ACTION_TRACE_EMIT 4
|
||||
|
||||
#define MCONTROL_MATCH_EQUAL 0
|
||||
#define MCONTROL_MATCH_NAPOT 1
|
||||
#define MCONTROL_MATCH_GE 2
|
||||
#define MCONTROL_MATCH_LT 3
|
||||
#define MCONTROL_MATCH_MASK_LOW 4
|
||||
#define MCONTROL_MATCH_MASK_HIGH 5
|
||||
|
||||
#define MIP_SSIP (1 << IRQ_S_SOFT)
|
||||
#define MIP_HSIP (1 << IRQ_H_SOFT)
|
||||
#define MIP_MSIP (1 << IRQ_M_SOFT)
|
||||
#define MIP_STIP (1 << IRQ_S_TIMER)
|
||||
#define MIP_HTIP (1 << IRQ_H_TIMER)
|
||||
#define MIP_MTIP (1 << IRQ_M_TIMER)
|
||||
#define MIP_SEIP (1 << IRQ_S_EXT)
|
||||
#define MIP_HEIP (1 << IRQ_H_EXT)
|
||||
#define MIP_MEIP (1 << IRQ_M_EXT)
|
||||
|
||||
#define SIP_SSIP MIP_SSIP
|
||||
#define SIP_STIP MIP_STIP
|
||||
|
||||
#define PRV_U 0
|
||||
#define PRV_S 1
|
||||
#define PRV_H 2
|
||||
#define PRV_M 3
|
||||
|
||||
#define SATP32_MODE 0x80000000
|
||||
#define SATP32_ASID 0x7FC00000
|
||||
#define SATP32_PPN 0x003FFFFF
|
||||
#define SATP64_MODE 0xF000000000000000
|
||||
#define SATP64_ASID 0x0FFFF00000000000
|
||||
#define SATP64_PPN 0x00000FFFFFFFFFFF
|
||||
|
||||
#define SATP_MODE_OFF 0
|
||||
#define SATP_MODE_SV32 1
|
||||
#define SATP_MODE_SV39 8
|
||||
#define SATP_MODE_SV48 9
|
||||
#define SATP_MODE_SV57 10
|
||||
#define SATP_MODE_SV64 11
|
||||
|
||||
#define PMP_R 0x01
|
||||
#define PMP_W 0x02
|
||||
#define PMP_X 0x04
|
||||
#define PMP_A 0x18
|
||||
#define PMP_L 0x80
|
||||
#define PMP_SHIFT 2
|
||||
|
||||
#define PMP_TOR 0x08
|
||||
#define PMP_NA4 0x10
|
||||
#define PMP_NAPOT 0x18
|
||||
|
||||
#define IRQ_S_SOFT 1
|
||||
#define IRQ_H_SOFT 2
|
||||
#define IRQ_M_SOFT 3
|
||||
#define IRQ_S_TIMER 5
|
||||
#define IRQ_H_TIMER 6
|
||||
#define IRQ_M_TIMER 7
|
||||
#define IRQ_S_EXT 9
|
||||
#define IRQ_H_EXT 10
|
||||
#define IRQ_M_EXT 11
|
||||
#define IRQ_COP 12
|
||||
#define IRQ_HOST 13
|
||||
|
||||
#define DEFAULT_RSTVEC 0x00001000
|
||||
#define CLINT_BASE 0x02000000
|
||||
#define CLINT_SIZE 0x000c0000
|
||||
#define EXT_IO_BASE 0x40000000
|
||||
#define DRAM_BASE 0x80000000
|
||||
|
||||
/* page table entry (PTE) fields */
|
||||
#define PTE_V 0x001 /* Valid */
|
||||
#define PTE_R 0x002 /* Read */
|
||||
#define PTE_W 0x004 /* Write */
|
||||
#define PTE_X 0x008 /* Execute */
|
||||
#define PTE_U 0x010 /* User */
|
||||
#define PTE_G 0x020 /* Global */
|
||||
#define PTE_A 0x040 /* Accessed */
|
||||
#define PTE_D 0x080 /* Dirty */
|
||||
#define PTE_SOFT 0x300 /* Reserved for Software */
|
||||
|
||||
#define PTE_PPN_SHIFT 10
|
||||
|
||||
#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
|
||||
|
||||
#define INSERT_FIELD(val, which, fieldval) \
|
||||
( \
|
||||
((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))) \
|
||||
) \
|
||||
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __v; \
|
||||
__asm__ volatile ("csrr %0, " #csr \
|
||||
: "=r" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ volatile ("csrw " #csr ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
|
||||
#define csr_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ volatile ("csrrs %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ volatile ("csrs " #csr ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ volatile ("csrrc %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ volatile ("csrc " #csr ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
#endif /* CSR_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue