RISC-V: Clear HSTATUS.HU on CPU initialization

The RISC-V privileged specification does not mandate HSTATUS reset
values, leaving the HU bit potentially set after hardware reset.
When HU=1, hypervisor instructions (HLV/HLVX/HSV) can execute in
U-mode to access guest memory, which may cause unintended behavior
if not explicitly controlled.

Clear HSTATUS.HU during CPU initialization to ensure hypervisor
instructions are only available in HS-mode, preventing unexpected
guest memory access from U-mode code.

Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://patch.msgid.link/20260924-hstatus_hu-v2-1-7e970f5f1d8d@sifive.com
Cc: stable@vger.kernel.org
[pjw@kernel.org: capitalized RISCV_ISA_EXT_h to fix build; added stable cc]
Signed-off-by: Paul Walmsley <pjw@kernel.org>
This commit is contained in:
Yong-Xuan Wang 2026-10-05 19:02:38 -06:00 committed by Paul Walmsley
parent 148ab873d8
commit 6694612317
5 changed files with 20 additions and 0 deletions

View File

@ -40,6 +40,8 @@ extern u32 thead_vlenb_of;
void __init riscv_user_isa_enable(void);
void riscv_clear_hypervisor_csr(void);
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
.name = #_name, \
.property = #_name, \

View File

@ -1233,6 +1233,18 @@ void __init riscv_user_isa_enable(void)
pr_warn("Zicbop disabled as it is unavailable on some harts\n");
}
void riscv_clear_hypervisor_csr(void)
{
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_H))
return;
/*
* Clear HSTATUS.HU to restrict hypervisor instructions to HS-mode.
* This prevents user-mode from executing HLV/HSV instructions.
*/
csr_clear(CSR_HSTATUS, HSTATUS_HU);
}
#ifdef CONFIG_RISCV_ALTERNATIVE
/*
* Alternative patch sites consider 48 bits when determining when to patch

View File

@ -366,6 +366,8 @@ void __init setup_arch(char **cmdline_p)
if (!IS_ENABLED(CONFIG_RISCV_ISA_ZBB) || !riscv_isa_extension_available(NULL, ZBB))
static_branch_disable(&efficient_ffs_key);
riscv_clear_hypervisor_csr();
}
bool arch_cpu_is_hotpluggable(int cpu)

View File

@ -244,6 +244,8 @@ asmlinkage __visible void smp_callin(void)
numa_add_cpu(curr_cpuid);
riscv_clear_hypervisor_csr();
pr_debug("CPU%u: Booted secondary hartid %lu\n", curr_cpuid,
cpuid_to_hartid_map(curr_cpuid));

View File

@ -43,6 +43,8 @@ void suspend_save_csrs(struct suspend_context *context)
void suspend_restore_csrs(struct suspend_context *context)
{
riscv_clear_hypervisor_csr();
csr_write(CSR_SCRATCH, 0);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_XLINUXENVCFG))
csr_write(CSR_ENVCFG, context->envcfg);