mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/riscv: implement vcpu_csr_init()
Introduce vcpu_csr_init() to initialise hypervisor CSRs that control vCPU execution and virtualization behaviour before the vCPU is first scheduled. The function configures trap and interrupt delegation to VS-mode by setting the appropriate bits in the hedeleg and hideleg registers, initializes hstatus so that execution enters VS-mode when control is passed to the guest, and restricts guest access to hardware performance counters by initializing hcounteren, as unrestricted access would require additional handling in Xen. When the Smstateen and SSAIA extensions are available, access to AIA CSRs and IMSIC guest interrupt files is enabled by setting the corresponding bits in hstateen0, avoiding unnecessary traps into Xen (note that SVSLCT(Supervisor Virtual Select) name is used intead of CSRIND as OpenSBI uses such name and riscv_encoding.h is mostly based on it). If the Svpbmt extension is supported, the PBMTE bit is set in henvcfg to allow its use for VS-stage address translation. Guest access to the ENVCFG CSR is also enabled by setting ENVCFG bit in hstateen0, as a guest may need to control certain characteristics of the U-mode (VU-mode when V=1) execution environment. For CSRs that may contain read-only bits (e.g. hedeleg, hideleg, hstateen0), to the written value a correspondent mask is applied to avoid divergence between the software state and the actual CSR contents. As hstatus is not part of struct arch_vcpu (it already resides in struct cpu_user_regs), introduce vcpu_guest_cpu_user_regs() to provide a uniform way to access hstatus and other guest CPU user registers. This establishes a consistent and well-defined initial CSR state for vCPUs prior to their first context switch. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
8149f72c0c
commit
02b3a1b0e5
4 files changed
+73
No files matched your search
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/riscv_encoding.h>
|
||||
|
||||
struct csr_masks {
|
||||
register_t hedeleg;
|
||||
@@ -20,6 +21,21 @@ struct csr_masks {
|
||||
} ro_one;
|
||||
};
|
||||
|
||||
#define HEDELEG_DEFAULT (BIT(CAUSE_MISALIGNED_FETCH, U) | \
|
||||
BIT(CAUSE_FETCH_ACCESS, U) | \
|
||||
BIT(CAUSE_ILLEGAL_INSTRUCTION, U) | \
|
||||
BIT(CAUSE_BREAKPOINT, U) | \
|
||||
BIT(CAUSE_MISALIGNED_LOAD, U) | \
|
||||
BIT(CAUSE_LOAD_ACCESS, U) | \
|
||||
BIT(CAUSE_MISALIGNED_STORE, U) | \
|
||||
BIT(CAUSE_STORE_ACCESS, U) | \
|
||||
BIT(CAUSE_USER_ECALL, U) | \
|
||||
BIT(CAUSE_FETCH_PAGE_FAULT, U) | \
|
||||
BIT(CAUSE_LOAD_PAGE_FAULT, U) | \
|
||||
BIT(CAUSE_STORE_PAGE_FAULT, U))
|
||||
|
||||
#define HIDELEG_DEFAULT (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
|
||||
|
||||
static struct csr_masks __ro_after_init csr_masks;
|
||||
|
||||
#define HEDELEG_AVAIL_MASK ULONG_MAX
|
||||
@@ -62,6 +78,51 @@ void __init init_csr_masks(void)
|
||||
#undef INIT_RO_ONE_MASK
|
||||
}
|
||||
|
||||
static void vcpu_csr_init(struct vcpu *v)
|
||||
{
|
||||
v->arch.hedeleg = HEDELEG_DEFAULT & csr_masks.hedeleg;
|
||||
|
||||
vcpu_guest_cpu_user_regs(v)->hstatus = HSTATUS_SPV | HSTATUS_SPVP;
|
||||
|
||||
v->arch.hideleg = HIDELEG_DEFAULT & csr_masks.hideleg;
|
||||
|
||||
/*
|
||||
* VS should access only the time counter directly.
|
||||
* Everything else should trap.
|
||||
*/
|
||||
v->arch.hcounteren = HCOUNTEREN_TM;
|
||||
|
||||
if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_svpbmt) )
|
||||
v->arch.henvcfg = ENVCFG_PBMTE & csr_masks.henvcfg;
|
||||
|
||||
if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) )
|
||||
{
|
||||
/* Allow guest to access CSR_SENVCFG */
|
||||
register_t hstateen0 = SMSTATEEN0_HSENVCFG;
|
||||
|
||||
if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_ssaia) )
|
||||
/*
|
||||
* If the hypervisor extension is implemented, the same three
|
||||
* bits are defined also in hypervisor CSR hstateen0 but concern
|
||||
* only the state potentially accessible to a virtual machine
|
||||
* executing in privilege modes VS and VU:
|
||||
* bit 60 CSRs siselect and sireg (really vsiselect and
|
||||
* vsireg)
|
||||
* bit 59 CSRs siph and sieh (RV32 only) and stopi (really
|
||||
* vsiph, vsieh, and vstopi)
|
||||
* bit 58 all state of IMSIC guest interrupt files, including
|
||||
* CSR stopei (really vstopei)
|
||||
* If one of these bits is zero in hstateen0, and the same bit is
|
||||
* one in mstateen0, then an attempt to access the corresponding
|
||||
* state from VS or VU-mode raises a virtual instruction exception.
|
||||
*/
|
||||
hstateen0 |= SMSTATEEN0_AIA | SMSTATEEN0_IMSIC | SMSTATEEN0_SVSLCT;
|
||||
|
||||
v->arch.hstateen0 = (hstateen0 & csr_masks.hstateen0) |
|
||||
csr_masks.ro_one.hstateen0;
|
||||
}
|
||||
}
|
||||
|
||||
static void continue_new_vcpu(struct vcpu *prev)
|
||||
{
|
||||
BUG_ON("unimplemented\n");
|
||||
@@ -84,6 +145,8 @@ int arch_vcpu_create(struct vcpu *v)
|
||||
if ( is_idle_vcpu(v) )
|
||||
return 0;
|
||||
|
||||
vcpu_csr_init(v);
|
||||
|
||||
/*
|
||||
* As the vtimer and interrupt controller (IC) are not yet implemented,
|
||||
* return an error.
|
||||
|
||||
@@ -48,6 +48,8 @@ DECLARE_PER_CPU(struct vcpu *, curr_vcpu);
|
||||
#define get_cpu_current(cpu) per_cpu(curr_vcpu, cpu)
|
||||
|
||||
#define guest_cpu_user_regs() ({ BUG_ON("unimplemented"); NULL; })
|
||||
#define vcpu_guest_cpu_user_regs(vcpu) \
|
||||
(&(vcpu)->arch.cpu_info->guest_cpu_user_regs)
|
||||
|
||||
#define switch_stack_and_jump(stack, fn) do { \
|
||||
asm volatile ( \
|
||||
|
||||
@@ -49,6 +49,12 @@ struct arch_vcpu {
|
||||
|
||||
struct cpu_info *cpu_info;
|
||||
|
||||
register_t hcounteren;
|
||||
register_t hedeleg;
|
||||
register_t hideleg;
|
||||
register_t henvcfg;
|
||||
register_t hstateen0;
|
||||
|
||||
register_t vsatp;
|
||||
};
|
||||
|
||||
|
||||
@@ -228,6 +228,8 @@
|
||||
#define ENVCFG_CBIE_INV _UL(0x3)
|
||||
#define ENVCFG_FIOM _UL(0x1)
|
||||
|
||||
#define HCOUNTEREN_TM BIT(1, U)
|
||||
|
||||
/* ===== User-level CSRs ===== */
|
||||
|
||||
/* User Trap Setup (N-extension) */
|
||||
|
||||