| 
 | 1 | +/*  | 
 | 2 | + * Copyright (c) 2025 Google LLC  | 
 | 3 | + *  | 
 | 4 | + * SPDX-License-Identifier: Apache-2.0  | 
 | 5 | + */  | 
 | 6 | + | 
 | 7 | +#include <kernel_internal.h>  | 
 | 8 | +#include <zephyr/mem_mgmt/mem_attr.h>  | 
 | 9 | +#include <zephyr/tc_util.h>  | 
 | 10 | +#include <zephyr/ztest.h>  | 
 | 11 | + | 
 | 12 | +void z_riscv_pmp_read_config(unsigned long *pmp_cfg, size_t pmp_cfg_size);  | 
 | 13 | +void z_riscv_pmp_read_addr(unsigned long *pmp_addr, size_t pmp_addr_size);  | 
 | 14 | + | 
 | 15 | +/**  | 
 | 16 | + * @brief Verifies the RISC-V PMP entries configured via Device Tree (zephyr,memattr).  | 
 | 17 | + *  | 
 | 18 | + * @details Reads the PMP configuration (pmpcfg) and address (pmpaddr) registers  | 
 | 19 | + * and asserts that the entries programmed by the CONFIG_MEM_ATTR process match  | 
 | 20 | + * the expected values for the Device Tree-defined memory regions.  | 
 | 21 | + */  | 
 | 22 | +ZTEST(riscv_pmp_memattr_entries, test_pmp_devicetree_memattr_config)  | 
 | 23 | +{  | 
 | 24 | +	const size_t num_pmpcfg_regs = CONFIG_PMP_SLOTS / sizeof(unsigned long);  | 
 | 25 | +	const size_t num_pmpaddr_regs = CONFIG_PMP_SLOTS;  | 
 | 26 | + | 
 | 27 | +	unsigned long current_pmpcfg_regs[num_pmpcfg_regs];  | 
 | 28 | +	unsigned long current_pmpaddr_regs[num_pmpaddr_regs];  | 
 | 29 | + | 
 | 30 | +	/* Read the current PMP configuration from the control registers */  | 
 | 31 | +	z_riscv_pmp_read_config(current_pmpcfg_regs, num_pmpcfg_regs);  | 
 | 32 | +	z_riscv_pmp_read_addr(current_pmpaddr_regs, num_pmpaddr_regs);  | 
 | 33 | + | 
 | 34 | +	const uint8_t *const current_pmp_cfg_entries = (const uint8_t *)current_pmpcfg_regs;  | 
 | 35 | + | 
 | 36 | +	const unsigned long expected_pmp_addr[3] = {0x20003fff, 0x20000000, 0x2000c000};  | 
 | 37 | +	const uint8_t expected_pmp_cfg_entries[3] = {0x1f, 0x00, 0x0f};  | 
 | 38 | + | 
 | 39 | +	size_t found_idx = -1;  | 
 | 40 | +	bool found_sequence = false;  | 
 | 41 | +	const size_t expected_len = ARRAY_SIZE(expected_pmp_addr);  | 
 | 42 | + | 
 | 43 | +	for (size_t i = 0; i <= CONFIG_PMP_SLOTS - expected_len; ++i) {  | 
 | 44 | +		if (memcmp(¤t_pmpaddr_regs[i], expected_pmp_addr,  | 
 | 45 | +			   expected_len * sizeof(unsigned long)) == 0) {  | 
 | 46 | + | 
 | 47 | +			if (memcmp(¤t_pmp_cfg_entries[i], expected_pmp_cfg_entries,  | 
 | 48 | +				   expected_len * sizeof(uint8_t)) == 0) {  | 
 | 49 | +				found_sequence = true;  | 
 | 50 | +				found_idx = i;  | 
 | 51 | +				break;  | 
 | 52 | +			}  | 
 | 53 | +		}  | 
 | 54 | +	}  | 
 | 55 | + | 
 | 56 | +	zassert_true(found_sequence,  | 
 | 57 | +		     "Expected PMP sequence (Addrs: 0x%lx, Cfg: 0x%x, ...) was not found in any "  | 
 | 58 | +		     "slot. Last checked slot: %zu",  | 
 | 59 | +		     expected_pmp_addr[0], expected_pmp_cfg_entries[0], found_idx);  | 
 | 60 | +}  | 
 | 61 | + | 
 | 62 | +ZTEST(riscv_pmp_memattr_entries, test_dt_pmp_perm_conversion)  | 
 | 63 | +{  | 
 | 64 | +	uint8_t result;  | 
 | 65 | + | 
 | 66 | +	result = DT_MEM_RISCV_TO_PMP_PERM(0);  | 
 | 67 | +	zassert_equal(result, 0, "Expected 0, got 0x%x", result);  | 
 | 68 | + | 
 | 69 | +	result = DT_MEM_RISCV_TO_PMP_PERM(DT_MEM_RISCV_TYPE_IO_R);  | 
 | 70 | +	zassert_equal(result, PMP_R, "Expected PMP_R (0x%x), got 0x%x", PMP_R, result);  | 
 | 71 | + | 
 | 72 | +	result = DT_MEM_RISCV_TO_PMP_PERM(DT_MEM_RISCV_TYPE_IO_W);  | 
 | 73 | +	zassert_equal(result, PMP_W, "Expected PMP_W (0x%x), got 0x%x", PMP_W, result);  | 
 | 74 | + | 
 | 75 | +	result = DT_MEM_RISCV_TO_PMP_PERM(DT_MEM_RISCV_TYPE_IO_X);  | 
 | 76 | +	zassert_equal(result, PMP_X, "Expected PMP_X (0x%x), got 0x%x", PMP_X, result);  | 
 | 77 | + | 
 | 78 | +	result = DT_MEM_RISCV_TO_PMP_PERM(DT_MEM_RISCV_TYPE_IO_R | DT_MEM_RISCV_TYPE_IO_W);  | 
 | 79 | +	zassert_equal(result, PMP_R | PMP_W, "Expected R|W (0x%x), got 0x%x", PMP_R | PMP_W,  | 
 | 80 | +		      result);  | 
 | 81 | + | 
 | 82 | +	result = DT_MEM_RISCV_TO_PMP_PERM(DT_MEM_RISCV_TYPE_IO_R | DT_MEM_RISCV_TYPE_IO_W |  | 
 | 83 | +					  DT_MEM_RISCV_TYPE_IO_X);  | 
 | 84 | +	zassert_equal(result, PMP_R | PMP_W | PMP_X, "Expected R|W|X (0x%x), got 0x%x",  | 
 | 85 | +		      PMP_R | PMP_W | PMP_X, result);  | 
 | 86 | +}  | 
 | 87 | + | 
 | 88 | +ZTEST_SUITE(riscv_pmp_memattr_entries, NULL, NULL, NULL, NULL, NULL);  | 
0 commit comments