Commit 9f0e6b98 authored by Radim Krčmář's avatar Radim Krčmář Committed by Anup Patel
Browse files

KVM: RISC-V: remove unnecessary SBI reset state



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: default avatarAndrew Jones <ajones@ventanamicro.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250403112522.1566629-6-rkrcmar@ventanamicro.com


Signed-off-by: default avatarAnup Patel <anup@brainfault.org>
parent a1c66842
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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;

+8 −6
Original line number Diff line number Diff line
@@ -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
+1 −3
Original line number Diff line number Diff line
@@ -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))
+33 −28
Original line number Diff line number Diff line
@@ -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);

+4 −5
Original line number Diff line number Diff line
@@ -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);
}