Linux needs hwcap-list to enable crypto instructions, but only sun4v firmware provides it.
When the CPU has crypto, pass the list through fw_cfg for OpenBIOS to copy onto the cpu node. Include the capabilities linux-user reports, since Linux trusts the list instead of guessing. Without crypto, nothing changes. Signed-off-by: Stian Halseth <[email protected]> --- Based-on: <[email protected]> This exposes the crypto hwcap to guests, so it should land after the block-init series, which glibc's memset needs. The OpenBIOS side, which copies the file onto the cpu node, is on the OpenBIOS list as "SPARC64: set hwcap-list on the cpu node from fw_cfg". The kernel change to read the property on sun4u goes to sparclinux. hw/sparc64/sun4u.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index a348096aee..7e38a55102 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -121,6 +121,51 @@ static void fw_cfg_boot_set(void *opaque, const char *boot_device, fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); } +/* + * OpenBIOS copies this list to the cpu node's hwcap-list property + * for Linux, which gets it from the machine description on sun4v. + */ +static void fw_cfg_build_hwcap_list(FWCfgState *fw_cfg, SPARCCPU *cpu) +{ + static const struct { + uint32_t mask; + const char *name; + } capabilities[] = { + { 0, "popc" }, + { CPU_FEATURE_FSMULD, "fsmuld" }, + { CPU_FEATURE_VIS1, "vis" }, + { CPU_FEATURE_VIS2, "vis2" }, + { CPU_FEATURE_FMAF, "fmaf" }, + { CPU_FEATURE_VIS3, "vis3" }, + { CPU_FEATURE_IMA, "ima" }, + { CPU_FEATURE_CRYPTO, "aes" }, + { CPU_FEATURE_CRYPTO, "sha1" }, + { CPU_FEATURE_CRYPTO, "sha256" }, + { CPU_FEATURE_CRYPTO, "sha512" }, + { CPU_FEATURE_CRYPTO, "crc32c" }, + }; + uint32_t features = cpu->env.def.features; + GByteArray *array; + size_t len; + + if (!(features & CPU_FEATURE_CRYPTO)) { + return; + } + + array = g_byte_array_new(); + for (size_t i = 0; i < ARRAY_SIZE(capabilities); i++) { + if ((features & capabilities[i].mask) == capabilities[i].mask) { + const char *name = capabilities[i].name; + + g_byte_array_append(array, (const guint8 *)name, strlen(name) + 1); + } + } + + len = array->len; + fw_cfg_add_file(fw_cfg, "etc/sparc64/hwcap-list", + g_byte_array_free(array, FALSE), len); +} + static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_t NVRAM_size, const char *arch, ram_addr_t RAM_size, const char *boot_devices, @@ -717,6 +762,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth); + fw_cfg_build_hwcap_list(fw_cfg, cpu); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); -- 2.43.0
