Skip to content

Commit

Permalink
RISC-V: KVM: Implement VCPU create, init and destroy functions
Browse files Browse the repository at this point in the history
This patch implements VCPU create, init and destroy functions
required by generic KVM module. We don't have much dynamic
resources in struct kvm_vcpu_arch so these functions are quite
simple for KVM RISC-V.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Alexander Graf <graf@amazon.com>
Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
  • Loading branch information
avpatel committed Oct 4, 2021
1 parent 99cdc6c commit a33c72f
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 9 deletions.
69 changes: 69 additions & 0 deletions arch/riscv/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,76 @@ struct kvm_cpu_trap {
unsigned long htinst;
};

struct kvm_cpu_context {
unsigned long zero;
unsigned long ra;
unsigned long sp;
unsigned long gp;
unsigned long tp;
unsigned long t0;
unsigned long t1;
unsigned long t2;
unsigned long s0;
unsigned long s1;
unsigned long a0;
unsigned long a1;
unsigned long a2;
unsigned long a3;
unsigned long a4;
unsigned long a5;
unsigned long a6;
unsigned long a7;
unsigned long s2;
unsigned long s3;
unsigned long s4;
unsigned long s5;
unsigned long s6;
unsigned long s7;
unsigned long s8;
unsigned long s9;
unsigned long s10;
unsigned long s11;
unsigned long t3;
unsigned long t4;
unsigned long t5;
unsigned long t6;
unsigned long sepc;
unsigned long sstatus;
unsigned long hstatus;
};

struct kvm_vcpu_csr {
unsigned long vsstatus;
unsigned long vsie;
unsigned long vstvec;
unsigned long vsscratch;
unsigned long vsepc;
unsigned long vscause;
unsigned long vstval;
unsigned long hvip;
unsigned long vsatp;
unsigned long scounteren;
};

struct kvm_vcpu_arch {
/* VCPU ran at least once */
bool ran_atleast_once;

/* ISA feature bits (similar to MISA) */
unsigned long isa;

/* CPU context of Guest VCPU */
struct kvm_cpu_context guest_context;

/* CPU CSR context of Guest VCPU */
struct kvm_vcpu_csr guest_csr;

/* CPU context upon Guest VCPU reset */
struct kvm_cpu_context guest_reset_context;

/* CPU CSR context upon Guest VCPU reset */
struct kvm_vcpu_csr guest_reset_csr;

/* Don't run the VCPU (blocked) */
bool pause;

Expand Down
55 changes: 46 additions & 9 deletions arch/riscv/kvm/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,64 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
sizeof(kvm_vcpu_stats_desc),
};

#define KVM_RISCV_ISA_ALLOWED (riscv_isa_extension_mask(a) | \
riscv_isa_extension_mask(c) | \
riscv_isa_extension_mask(d) | \
riscv_isa_extension_mask(f) | \
riscv_isa_extension_mask(i) | \
riscv_isa_extension_mask(m) | \
riscv_isa_extension_mask(s) | \
riscv_isa_extension_mask(u))

static void kvm_riscv_reset_vcpu(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;

memcpy(csr, reset_csr, sizeof(*csr));

memcpy(cntx, reset_cntx, sizeof(*cntx));
}

int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
{
return 0;
}

int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{
/* TODO: */
struct kvm_cpu_context *cntx;

/* Mark this VCPU never ran */
vcpu->arch.ran_atleast_once = false;

/* Setup ISA features available to VCPU */
vcpu->arch.isa = riscv_isa_extension_base(NULL) & KVM_RISCV_ISA_ALLOWED;

/* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
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;

/* Reset VCPU */
kvm_riscv_reset_vcpu(vcpu);

return 0;
}

void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
{
}

int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
{
/* TODO: */
return 0;
}

void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
/* TODO: */
/* Flush the pages pre-allocated for Stage2 page table mappings */
kvm_riscv_stage2_flush_cache(vcpu);
}

int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
Expand Down Expand Up @@ -197,6 +231,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
struct kvm_cpu_trap trap;
struct kvm_run *run = vcpu->run;

/* Mark this VCPU ran at least once */
vcpu->arch.ran_atleast_once = true;

vcpu->arch.srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);

/* Process MMIO value returned from user-space */
Expand Down Expand Up @@ -270,7 +307,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
* get an interrupt between __kvm_riscv_switch_to() and
* local_irq_enable() which can potentially change CSRs.
*/
trap.sepc = 0;
trap.sepc = vcpu->arch.guest_context.sepc;
trap.scause = csr_read(CSR_SCAUSE);
trap.stval = csr_read(CSR_STVAL);
trap.htval = csr_read(CSR_HTVAL);
Expand Down

0 comments on commit a33c72f

Please sign in to comment.