diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 0c5f30ee..2ded1d2d 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -374,6 +374,12 @@ static unsigned int sbi_hart_get_smepmp_flags(struct sbi_scratch *scratch, pmp_flags |= PMP_W; if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE) pmp_flags |= PMP_X; + } else if (reg->flags & SBI_DOMAIN_MEMREGION_ENF_PERMISSIONS) { + /* + * If permissions are to be enforced for all modes on + * this region, the lock bit should be set. + */ + pmp_flags |= PMP_L; } return pmp_flags; diff --git a/platform/generic/include/xuantie/xuantie_pmp_ext.h b/platform/generic/include/xuantie/xuantie_pmp_ext.h new file mode 100644 index 00000000..d2adc827 --- /dev/null +++ b/platform/generic/include/xuantie/xuantie_pmp_ext.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __RISCV_XUANTIE_PMP_EXT_H__ +#define __RISCV_XUANTIE_PMP_EXT_H__ + +#include + +int xuantie_pmp_ext_cfg(void); + +#endif /* __RISCV_XUANTIE_PMP_EXT_H__ */ diff --git a/platform/generic/include/xuantie/xuantie_quirk.h b/platform/generic/include/xuantie/xuantie_quirk.h index b18f2965..0eaf1fe9 100644 --- a/platform/generic/include/xuantie/xuantie_quirk.h +++ b/platform/generic/include/xuantie/xuantie_quirk.h @@ -5,8 +5,9 @@ #ifndef __RISCV_XUANTIE_QUIRK_H__ #define __RISCV_XUANTIE_QUIRK_H__ -#define QUIRK_XUANTIE_PMC BIT(0) -#define QUIRK_XUANTIE_LINK BIT(1) +#define QUIRK_XUANTIE_PMC BIT(0) +#define QUIRK_XUANTIE_LINK BIT(1) +#define QUIRK_XUANTIE_PMP_EXT BIT(2) struct xuantie_generic_quirks { u32 quirk; diff --git a/platform/generic/xuantie/objects.mk b/platform/generic/xuantie/objects.mk index 73439760..6132dddf 100644 --- a/platform/generic/xuantie/objects.mk +++ b/platform/generic/xuantie/objects.mk @@ -3,4 +3,4 @@ # carray-platform_override_modules-$(CONFIG_PLATFORM_XUANTIE) += xuantie_dummy -platform-objs-$(CONFIG_PLATFORM_XUANTIE) += xuantie/xuantie_dummy.o xuantie/xuantie_pmc.o xuantie/xuantie_link.o +platform-objs-$(CONFIG_PLATFORM_XUANTIE) += xuantie/xuantie_dummy.o xuantie/xuantie_pmc.o xuantie/xuantie_link.o xuantie/xuantie_pmp_ext.o diff --git a/platform/generic/xuantie/xuantie_dummy.c b/platform/generic/xuantie/xuantie_dummy.c index 7f284e27..00d536c0 100644 --- a/platform/generic/xuantie/xuantie_dummy.c +++ b/platform/generic/xuantie/xuantie_dummy.c @@ -13,9 +13,20 @@ #include #include #include +#include static u32 gquirk = 0; +int xuantie_early_init(bool cold_boot) +{ + if (cold_boot) { + if (gquirk & QUIRK_XUANTIE_PMP_EXT) + xuantie_pmp_ext_cfg(); + } + + return generic_early_init(cold_boot); +} + int xuantie_final_init(bool cold_boot) { if (cold_boot) { @@ -34,13 +45,14 @@ static int xuantie_dummy_platform_init(const void *fdt, int nodeoff, const struct xuantie_generic_quirks *data = match->data; gquirk = data->quirk; + generic_platform_ops.early_init = xuantie_early_init; generic_platform_ops.final_init = xuantie_final_init; return 0; } static const struct xuantie_generic_quirks xuantie_quirks = { - .quirk = QUIRK_XUANTIE_PMC | QUIRK_XUANTIE_LINK, + .quirk = QUIRK_XUANTIE_PMC | QUIRK_XUANTIE_LINK | QUIRK_XUANTIE_PMP_EXT, }; static const struct xuantie_generic_quirks xuantie_pmc_quirks = { @@ -51,10 +63,15 @@ static const struct xuantie_generic_quirks xuantie_link_quirks = { .quirk = QUIRK_XUANTIE_LINK, }; +static const struct xuantie_generic_quirks xuantie_pmp_ext_quirks = { + .quirk = QUIRK_XUANTIE_PMP_EXT, +}; + static const struct fdt_match xuantie_dummy_match[] = { { .compatible = "xuantie,dummy", .data = &xuantie_quirks }, { .compatible = "xuantie,pmc", .data = &xuantie_pmc_quirks }, { .compatible = "xuantie,link", .data = &xuantie_link_quirks }, + { .compatible = "riscv-virtio", .data = &xuantie_pmp_ext_quirks }, // qemu debug { }, }; diff --git a/platform/generic/xuantie/xuantie_pmp_ext.c b/platform/generic/xuantie/xuantie_pmp_ext.c new file mode 100644 index 00000000..7d7519e9 --- /dev/null +++ b/platform/generic/xuantie/xuantie_pmp_ext.c @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* +sbi_domain_root_add_memrange needs to be called before sbi_domain_finalize, +because sbi_domain_finalize sets domain_finalized = true, causing subsequent +additions to fail. +*/ +int xuantie_pmp_ext_cfg(void) +{ + int nodeoffset, rc; + uint64_t addr, size; + void *fdt = fdt_get_address_rw(); + + nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,pmp_ext"); + if (nodeoffset < 0) + return nodeoffset; + + rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, &addr, &size); + if (rc) + return SBI_ENODEV; + + rc = sbi_domain_root_add_memrange(addr, size, size & (-size), + SBI_DOMAIN_MEMREGION_ENF_PERMISSIONS); + return rc; +}