diff options
author | Andrew Turner <andrew@FreeBSD.org> | 2021-12-20 13:42:15 +0000 |
---|---|---|
committer | Andrew Turner <andrew@FreeBSD.org> | 2021-12-20 13:58:36 +0000 |
commit | c399283c71e310e1573e8d27f9cb9d27a4ea3376 (patch) | |
tree | ffe6377e1ccd817bf4c0811859bf4656902da08f /stand/arm64 | |
parent | c1381f07f61a66979f1569995f37f2a0413c0413 (diff) | |
download | src-c399283c71e310e1573e8d27f9cb9d27a4ea3376.tar.gz src-c399283c71e310e1573e8d27f9cb9d27a4ea3376.zip |
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
Diffstat (limited to 'stand/arm64')
-rw-r--r-- | stand/arm64/libarm64/cache.c | 38 |
1 files changed, 38 insertions, 0 deletions
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 <stand.h> #include <efi.h> +#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 <value>\n"); + return (CMD_ERROR); +} +COMMAND_SET(cache_flags, "cache_flags", "Set cache flags", command_cache_flags); |