/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2026 SiFive Inc. */ #include #include #include /* * Instead of allocating individual PMP entries for each M-mode * MMIO driver, configure SMEPMP regions to grant R/W permission * to peripheral and system ports for all privilege modes. * Finer-grained access control is enforced by wgChecker rules. */ static int sifive_smepmp_setup(void) { struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); int rc; if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMEPMP)) return 0; /* Peripheral port region: 0 to 2GiB */ rc = sbi_domain_root_add_memrange(0x0, 0x80000000, 0x80000000, SBI_DOMAIN_MEMREGION_MMIO | SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW); if (rc) return rc; #if __riscv_xlen > 32 /* System port region: 512GiB to 1TiB */ rc = sbi_domain_root_add_memrange(0x8000000000ULL, 0x8000000000ULL, 0x8000000000ULL, SBI_DOMAIN_MEMREGION_MMIO | SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW); if (rc) return rc; #endif return 0; } static int sifive_early_init(bool cold_boot) { int rc; if (cold_boot) { rc = sifive_smepmp_setup(); if (rc) return rc; } return generic_early_init(cold_boot); } static int sifive_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match) { generic_platform_ops.early_init = sifive_early_init; return 0; } static const struct fdt_match sifive_dev_platform_match[] = { { .compatible = "sifive-dev" }, { }, }; const struct fdt_driver sifive_dev_platform = { .match_table = sifive_dev_platform_match, .init = sifive_platform_init, };