KVM: RISC-V: remove unnecessary SBI reset state
authorRadim Krčmář <rkrcmar@ventanamicro.com>
Thu, 3 Apr 2025 11:25:22 +0000 (13:25 +0200)
committerAnup Patel <anup@brainfault.org>
Wed, 21 May 2025 04:04:52 +0000 (09:34 +0530)
The SBI reset state has only two variables -- pc and a1.
The rest is known, so keep only the necessary information.

The reset structures make sense if we want userspace to control the
reset state (which we do), but I'd still remove them now and reintroduce
with the userspace interface later -- we could probably have just a
single reset state per VM, instead of a reset state for each VCPU.

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250403112522.1566629-6-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
arch/riscv/include/asm/kvm_aia.h
arch/riscv/include/asm/kvm_host.h
arch/riscv/kvm/aia_device.c
arch/riscv/kvm/vcpu.c
arch/riscv/kvm/vcpu_sbi.c

index 1f37b60..3b643b9 100644 (file)
@@ -63,9 +63,6 @@ struct kvm_vcpu_aia {
        /* CPU AIA CSR context of Guest VCPU */
        struct kvm_vcpu_aia_csr guest_csr;
 
-       /* CPU AIA CSR context upon Guest VCPU reset */
-       struct kvm_vcpu_aia_csr guest_reset_csr;
-
        /* Guest physical address of IMSIC for this VCPU */
        gpa_t           imsic_addr;
 
index 0e9c2fa..f673ebf 100644 (file)
@@ -193,6 +193,12 @@ struct kvm_vcpu_smstateen_csr {
        unsigned long sstateen0;
 };
 
+struct kvm_vcpu_reset_state {
+       spinlock_t lock;
+       unsigned long pc;
+       unsigned long a1;
+};
+
 struct kvm_vcpu_arch {
        /* VCPU ran at least once */
        bool ran_atleast_once;
@@ -227,12 +233,8 @@ struct kvm_vcpu_arch {
        /* CPU Smstateen CSR context of Guest VCPU */
        struct kvm_vcpu_smstateen_csr smstateen_csr;
 
-       /* CPU context upon Guest VCPU reset */
-       struct kvm_cpu_context guest_reset_context;
-       spinlock_t reset_cntx_lock;
-
-       /* CPU CSR context upon Guest VCPU reset */
-       struct kvm_vcpu_csr guest_reset_csr;
+       /* CPU reset state of Guest VCPU */
+       struct kvm_vcpu_reset_state reset_state;
 
        /*
         * VCPU interrupts
index 39cd26a..43e472f 100644 (file)
@@ -526,12 +526,10 @@ int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu)
 void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu)
 {
        struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
-       struct kvm_vcpu_aia_csr *reset_csr =
-                               &vcpu->arch.aia_context.guest_reset_csr;
 
        if (!kvm_riscv_aia_available())
                return;
-       memcpy(csr, reset_csr, sizeof(*csr));
+       memset(csr, 0, sizeof(*csr));
 
        /* Proceed only if AIA was initialized successfully */
        if (!kvm_riscv_aia_initialized(vcpu->kvm))
index 11b0df6..a78f9ec 100644 (file)
@@ -51,13 +51,41 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
                       sizeof(kvm_vcpu_stats_desc),
 };
 
-static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
+static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu)
 {
        struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
-       struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
        struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
-       struct kvm_cpu_context *reset_cntx = &vcpu->arch.guest_reset_context;
+       struct kvm_vcpu_reset_state *reset_state = &vcpu->arch.reset_state;
        void *vector_datap = cntx->vector.datap;
+
+       memset(cntx, 0, sizeof(*cntx));
+       memset(csr, 0, sizeof(*csr));
+       memset(&vcpu->arch.smstateen_csr, 0, sizeof(vcpu->arch.smstateen_csr));
+
+       /* Restore datap as it's not a part of the guest context. */
+       cntx->vector.datap = vector_datap;
+
+       /* Load SBI reset values */
+       cntx->a0 = vcpu->vcpu_id;
+
+       spin_lock(&reset_state->lock);
+       cntx->sepc = reset_state->pc;
+       cntx->a1 = reset_state->a1;
+       spin_unlock(&reset_state->lock);
+
+       /* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
+       cntx->sstatus = SR_SPP | SR_SPIE;
+
+       cntx->hstatus |= HSTATUS_VTW;
+       cntx->hstatus |= HSTATUS_SPVP;
+       cntx->hstatus |= HSTATUS_SPV;
+
+       /* By default, make CY, TM, and IR counters accessible in VU mode */
+       csr->scounteren = 0x7;
+}
+
+static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
+{
        bool loaded;
 
        /**
@@ -72,18 +100,10 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
 
        vcpu->arch.last_exit_cpu = -1;
 
-       memcpy(csr, reset_csr, sizeof(*csr));
-
-       spin_lock(&vcpu->arch.reset_cntx_lock);
-       memcpy(cntx, reset_cntx, sizeof(*cntx));
-       spin_unlock(&vcpu->arch.reset_cntx_lock);
-
-       memset(&vcpu->arch.smstateen_csr, 0, sizeof(vcpu->arch.smstateen_csr));
+       kvm_riscv_vcpu_context_reset(vcpu);
 
        kvm_riscv_vcpu_fp_reset(vcpu);
 
-       /* Restore datap as it's not a part of the guest context. */
-       cntx->vector.datap = vector_datap;
        kvm_riscv_vcpu_vector_reset(vcpu);
 
        kvm_riscv_vcpu_timer_reset(vcpu);
@@ -115,8 +135,6 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
 int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 {
        int rc;
-       struct kvm_cpu_context *cntx;
-       struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
 
        spin_lock_init(&vcpu->arch.mp_state_lock);
 
@@ -136,24 +154,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
        /* Setup VCPU hfence queue */
        spin_lock_init(&vcpu->arch.hfence_lock);
 
-       /* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
-       spin_lock_init(&vcpu->arch.reset_cntx_lock);
-
-       spin_lock(&vcpu->arch.reset_cntx_lock);
-       cntx = &vcpu->arch.guest_reset_context;
-       cntx->sstatus = SR_SPP | SR_SPIE;
-       cntx->hstatus = 0;
-       cntx->hstatus |= HSTATUS_VTW;
-       cntx->hstatus |= HSTATUS_SPVP;
-       cntx->hstatus |= HSTATUS_SPV;
-       spin_unlock(&vcpu->arch.reset_cntx_lock);
+       spin_lock_init(&vcpu->arch.reset_state.lock);
 
        if (kvm_riscv_vcpu_alloc_vector_context(vcpu))
                return -ENOMEM;
 
-       /* By default, make CY, TM, and IR counters accessible in VU mode */
-       reset_csr->scounteren = 0x7;
-
        /* Setup VCPU timer */
        kvm_riscv_vcpu_timer_init(vcpu);
 
index c63fed7..0afef0b 100644 (file)
@@ -159,11 +159,10 @@ void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
 void kvm_riscv_vcpu_sbi_request_reset(struct kvm_vcpu *vcpu,
                                      unsigned long pc, unsigned long a1)
 {
-       spin_lock(&vcpu->arch.reset_cntx_lock);
-       vcpu->arch.guest_reset_context.sepc = pc;
-       vcpu->arch.guest_reset_context.a0 = vcpu->vcpu_id;
-       vcpu->arch.guest_reset_context.a1 = a1;
-       spin_unlock(&vcpu->arch.reset_cntx_lock);
+       spin_lock(&vcpu->arch.reset_state.lock);
+       vcpu->arch.reset_state.pc = pc;
+       vcpu->arch.reset_state.a1 = a1;
+       spin_unlock(&vcpu->arch.reset_state.lock);
 
        kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
 }