From c399283c71e310e1573e8d27f9cb9d27a4ea3376 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Mon, 20 Dec 2021 13:42:15 +0000 Subject: [PATCH] Add an loader command on arm64 to sync the cache On boot we don't need to perform any CPU cache management when the IDC and DIC fields in the ctr_el0 register are set. Add a command to tell loader to ignore these fields. This could be useful, for example, if the hardware is misreporting the values and we are missing a quirk to enable it. It is not expected this will be needed, but is only intended as a workaround to ensure the kernel can still boot. Sponsored by: The FreeBSD Foundation --- stand/arm64/libarm64/cache.c | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/stand/arm64/libarm64/cache.c b/stand/arm64/libarm64/cache.c index ff52572399ac..105e08cb4257 100644 --- a/stand/arm64/libarm64/cache.c +++ b/stand/arm64/libarm64/cache.c @@ -37,17 +37,30 @@ __FBSDID("$FreeBSD$"); #include #include +#include "bootstrap.h" #include "cache.h" +static long cache_flags; +#define CACHE_FLAG_DIC_OFF (1<<0) +#define CACHE_FLAG_IDC_OFF (1<<1) + static bool get_cache_dic(uint64_t ctr) { + if ((cache_flags & CACHE_FLAG_DIC_OFF) != 0) { + return (false); + } + return (CTR_DIC_VAL(ctr) != 0); } static bool get_cache_idc(uint64_t ctr) { + if ((cache_flags & CACHE_FLAG_IDC_OFF) != 0) { + return (false); + } + return (CTR_IDC_VAL(ctr) != 0); } @@ -112,3 +125,28 @@ cpu_inval_icache(void) : : : "memory"); } } + +static int +command_cache_flags(int argc, char *argv[]) +{ + char *cp; + long new_flags; + + if (argc == 3) { + if (strcmp(argv[1], "set") == 0) { + new_flags = strtol(argv[2], &cp, 0); + if (cp[0] != '\0') { + printf("Invalid flags\n"); + } else { + printf("Setting cache flags to %#lx\n", + new_flags); + cache_flags = new_flags; + return (CMD_OK); + } + } + } + + printf("usage: cache_flags set \n"); + return (CMD_ERROR); +} +COMMAND_SET(cache_flags, "cache_flags", "Set cache flags", command_cache_flags);