Skip to content

Commit 2e2e911

Browse files
committed
Merge tag 'kvm-riscv-5.20-1' of https://github.com/kvm-riscv/linux into HEAD
KVM/riscv changes for 5.20 * Track ISA extensions used by Guest using bitmap * Added system instruction emulation framework * Added CSR emulation framework * Added gfp_custom flag in struct kvm_mmu_memory_cache * Added G-stage ioremap() and iounmap() functions * Added support for Svpbmt inside Guest
2 parents e0dccc3 + 6bb2e00 commit 2e2e911

17 files changed

Lines changed: 1028 additions & 599 deletions

File tree

arch/riscv/include/asm/csr.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@
156156
(_AC(1, UL) << IRQ_S_TIMER) | \
157157
(_AC(1, UL) << IRQ_S_EXT))
158158

159+
/* xENVCFG flags */
160+
#define ENVCFG_STCE (_AC(1, ULL) << 63)
161+
#define ENVCFG_PBMTE (_AC(1, ULL) << 62)
162+
#define ENVCFG_CBZE (_AC(1, UL) << 7)
163+
#define ENVCFG_CBCFE (_AC(1, UL) << 6)
164+
#define ENVCFG_CBIE_SHIFT 4
165+
#define ENVCFG_CBIE (_AC(0x3, UL) << ENVCFG_CBIE_SHIFT)
166+
#define ENVCFG_CBIE_ILL _AC(0x0, UL)
167+
#define ENVCFG_CBIE_FLUSH _AC(0x1, UL)
168+
#define ENVCFG_CBIE_INV _AC(0x3, UL)
169+
#define ENVCFG_FIOM _AC(0x1, UL)
170+
159171
/* symbolic CSR names: */
160172
#define CSR_CYCLE 0xc00
161173
#define CSR_TIME 0xc01
@@ -252,7 +264,9 @@
252264
#define CSR_HTIMEDELTA 0x605
253265
#define CSR_HCOUNTEREN 0x606
254266
#define CSR_HGEIE 0x607
267+
#define CSR_HENVCFG 0x60a
255268
#define CSR_HTIMEDELTAH 0x615
269+
#define CSR_HENVCFGH 0x61a
256270
#define CSR_HTVAL 0x643
257271
#define CSR_HIP 0x644
258272
#define CSR_HVIP 0x645
@@ -264,6 +278,8 @@
264278
#define CSR_MISA 0x301
265279
#define CSR_MIE 0x304
266280
#define CSR_MTVEC 0x305
281+
#define CSR_MENVCFG 0x30a
282+
#define CSR_MENVCFGH 0x31a
267283
#define CSR_MSCRATCH 0x340
268284
#define CSR_MEPC 0x341
269285
#define CSR_MCAUSE 0x342

arch/riscv/include/asm/kvm_host.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#include <linux/kvm_types.h>
1515
#include <linux/spinlock.h>
1616
#include <asm/csr.h>
17+
#include <asm/hwcap.h>
1718
#include <asm/kvm_vcpu_fp.h>
19+
#include <asm/kvm_vcpu_insn.h>
1820
#include <asm/kvm_vcpu_timer.h>
1921

2022
#define KVM_MAX_VCPUS 1024
@@ -63,6 +65,8 @@ struct kvm_vcpu_stat {
6365
u64 wfi_exit_stat;
6466
u64 mmio_exit_user;
6567
u64 mmio_exit_kernel;
68+
u64 csr_exit_user;
69+
u64 csr_exit_kernel;
6670
u64 exits;
6771
};
6872

@@ -90,14 +94,6 @@ struct kvm_arch {
9094
struct kvm_guest_timer timer;
9195
};
9296

93-
struct kvm_mmio_decode {
94-
unsigned long insn;
95-
int insn_len;
96-
int len;
97-
int shift;
98-
int return_handled;
99-
};
100-
10197
struct kvm_sbi_context {
10298
int return_handled;
10399
};
@@ -170,7 +166,7 @@ struct kvm_vcpu_arch {
170166
int last_exit_cpu;
171167

172168
/* ISA feature bits (similar to MISA) */
173-
unsigned long isa;
169+
DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX);
174170

175171
/* SSCRATCH, STVEC, and SCOUNTEREN of Host */
176172
unsigned long host_sscratch;
@@ -216,6 +212,9 @@ struct kvm_vcpu_arch {
216212
/* MMIO instruction details */
217213
struct kvm_mmio_decode mmio_decode;
218214

215+
/* CSR instruction details */
216+
struct kvm_csr_decode csr_decode;
217+
219218
/* SBI context */
220219
struct kvm_sbi_context sbi_context;
221220

@@ -285,6 +284,11 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm,
285284
void kvm_riscv_hfence_vvma_all(struct kvm *kvm,
286285
unsigned long hbase, unsigned long hmask);
287286

287+
int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa,
288+
phys_addr_t hpa, unsigned long size,
289+
bool writable, bool in_atomic);
290+
void kvm_riscv_gstage_iounmap(struct kvm *kvm, gpa_t gpa,
291+
unsigned long size);
288292
int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
289293
struct kvm_memory_slot *memslot,
290294
gpa_t gpa, unsigned long hva, bool is_write);
@@ -303,14 +307,12 @@ void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu);
303307

304308
void __kvm_riscv_unpriv_trap(void);
305309

306-
void kvm_riscv_vcpu_wfi(struct kvm_vcpu *vcpu);
307310
unsigned long kvm_riscv_vcpu_unpriv_read(struct kvm_vcpu *vcpu,
308311
bool read_insn,
309312
unsigned long guest_addr,
310313
struct kvm_cpu_trap *trap);
311314
void kvm_riscv_vcpu_trap_redirect(struct kvm_vcpu *vcpu,
312315
struct kvm_cpu_trap *trap);
313-
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
314316
int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
315317
struct kvm_cpu_trap *trap);
316318

arch/riscv/include/asm/kvm_vcpu_fp.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,22 @@ void __kvm_riscv_fp_d_restore(struct kvm_cpu_context *context);
2222

2323
void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu);
2424
void kvm_riscv_vcpu_guest_fp_save(struct kvm_cpu_context *cntx,
25-
unsigned long isa);
25+
const unsigned long *isa);
2626
void kvm_riscv_vcpu_guest_fp_restore(struct kvm_cpu_context *cntx,
27-
unsigned long isa);
27+
const unsigned long *isa);
2828
void kvm_riscv_vcpu_host_fp_save(struct kvm_cpu_context *cntx);
2929
void kvm_riscv_vcpu_host_fp_restore(struct kvm_cpu_context *cntx);
3030
#else
3131
static inline void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu)
3232
{
3333
}
3434
static inline void kvm_riscv_vcpu_guest_fp_save(struct kvm_cpu_context *cntx,
35-
unsigned long isa)
35+
const unsigned long *isa)
3636
{
3737
}
3838
static inline void kvm_riscv_vcpu_guest_fp_restore(
3939
struct kvm_cpu_context *cntx,
40-
unsigned long isa)
40+
const unsigned long *isa)
4141
{
4242
}
4343
static inline void kvm_riscv_vcpu_host_fp_save(struct kvm_cpu_context *cntx)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (c) 2022 Ventana Micro Systems Inc.
4+
*/
5+
6+
#ifndef __KVM_VCPU_RISCV_INSN_H
7+
#define __KVM_VCPU_RISCV_INSN_H
8+
9+
struct kvm_vcpu;
10+
struct kvm_run;
11+
struct kvm_cpu_trap;
12+
13+
struct kvm_mmio_decode {
14+
unsigned long insn;
15+
int insn_len;
16+
int len;
17+
int shift;
18+
int return_handled;
19+
};
20+
21+
struct kvm_csr_decode {
22+
unsigned long insn;
23+
int return_handled;
24+
};
25+
26+
/* Return values used by function emulating a particular instruction */
27+
enum kvm_insn_return {
28+
KVM_INSN_EXIT_TO_USER_SPACE = 0,
29+
KVM_INSN_CONTINUE_NEXT_SEPC,
30+
KVM_INSN_CONTINUE_SAME_SEPC,
31+
KVM_INSN_ILLEGAL_TRAP,
32+
KVM_INSN_VIRTUAL_TRAP
33+
};
34+
35+
void kvm_riscv_vcpu_wfi(struct kvm_vcpu *vcpu);
36+
int kvm_riscv_vcpu_csr_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
37+
int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
38+
struct kvm_cpu_trap *trap);
39+
40+
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
41+
unsigned long fault_addr,
42+
unsigned long htinst);
43+
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
44+
unsigned long fault_addr,
45+
unsigned long htinst);
46+
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
47+
48+
#endif

arch/riscv/include/asm/kvm_vcpu_timer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ int kvm_riscv_vcpu_timer_init(struct kvm_vcpu *vcpu);
3939
int kvm_riscv_vcpu_timer_deinit(struct kvm_vcpu *vcpu);
4040
int kvm_riscv_vcpu_timer_reset(struct kvm_vcpu *vcpu);
4141
void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu);
42-
int kvm_riscv_guest_timer_init(struct kvm *kvm);
42+
void kvm_riscv_guest_timer_init(struct kvm *kvm);
4343

4444
#endif

arch/riscv/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ enum KVM_RISCV_ISA_EXT_ID {
9696
KVM_RISCV_ISA_EXT_H,
9797
KVM_RISCV_ISA_EXT_I,
9898
KVM_RISCV_ISA_EXT_M,
99+
KVM_RISCV_ISA_EXT_SVPBMT,
99100
KVM_RISCV_ISA_EXT_MAX,
100101
};
101102

arch/riscv/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ kvm-y += mmu.o
1717
kvm-y += vcpu.o
1818
kvm-y += vcpu_exit.o
1919
kvm-y += vcpu_fp.o
20+
kvm-y += vcpu_insn.o
2021
kvm-y += vcpu_switch.o
2122
kvm-y += vcpu_sbi.o
2223
kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o

arch/riscv/kvm/mmu.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,9 @@ static void gstage_wp_memory_region(struct kvm *kvm, int slot)
343343
kvm_flush_remote_tlbs(kvm);
344344
}
345345

346-
static int gstage_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa,
347-
unsigned long size, bool writable)
346+
int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa,
347+
phys_addr_t hpa, unsigned long size,
348+
bool writable, bool in_atomic)
348349
{
349350
pte_t pte;
350351
int ret = 0;
@@ -353,13 +354,14 @@ static int gstage_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa,
353354
struct kvm_mmu_memory_cache pcache;
354355

355356
memset(&pcache, 0, sizeof(pcache));
357+
pcache.gfp_custom = (in_atomic) ? GFP_ATOMIC | __GFP_ACCOUNT : 0;
356358
pcache.gfp_zero = __GFP_ZERO;
357359

358360
end = (gpa + size + PAGE_SIZE - 1) & PAGE_MASK;
359361
pfn = __phys_to_pfn(hpa);
360362

361363
for (addr = gpa; addr < end; addr += PAGE_SIZE) {
362-
pte = pfn_pte(pfn, PAGE_KERNEL);
364+
pte = pfn_pte(pfn, PAGE_KERNEL_IO);
363365

364366
if (!writable)
365367
pte = pte_wrprotect(pte);
@@ -382,6 +384,13 @@ static int gstage_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa,
382384
return ret;
383385
}
384386

387+
void kvm_riscv_gstage_iounmap(struct kvm *kvm, gpa_t gpa, unsigned long size)
388+
{
389+
spin_lock(&kvm->mmu_lock);
390+
gstage_unmap_range(kvm, gpa, size, false);
391+
spin_unlock(&kvm->mmu_lock);
392+
}
393+
385394
void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
386395
struct kvm_memory_slot *slot,
387396
gfn_t gfn_offset,
@@ -517,8 +526,9 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
517526
goto out;
518527
}
519528

520-
ret = gstage_ioremap(kvm, gpa, pa,
521-
vm_end - vm_start, writable);
529+
ret = kvm_riscv_gstage_ioremap(kvm, gpa, pa,
530+
vm_end - vm_start,
531+
writable, false);
522532
if (ret)
523533
break;
524534
}
@@ -611,7 +621,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
611621
{
612622
int ret;
613623
kvm_pfn_t hfn;
614-
bool writeable;
624+
bool writable;
615625
short vma_pageshift;
616626
gfn_t gfn = gpa >> PAGE_SHIFT;
617627
struct vm_area_struct *vma;
@@ -659,7 +669,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
659669

660670
mmu_seq = kvm->mmu_notifier_seq;
661671

662-
hfn = gfn_to_pfn_prot(kvm, gfn, is_write, &writeable);
672+
hfn = gfn_to_pfn_prot(kvm, gfn, is_write, &writable);
663673
if (hfn == KVM_PFN_ERR_HWPOISON) {
664674
send_sig_mceerr(BUS_MCEERR_AR, (void __user *)hva,
665675
vma_pageshift, current);
@@ -673,14 +683,14 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
673683
* for write faults.
674684
*/
675685
if (logging && !is_write)
676-
writeable = false;
686+
writable = false;
677687

678688
spin_lock(&kvm->mmu_lock);
679689

680690
if (mmu_notifier_retry(kvm, mmu_seq))
681691
goto out_unlock;
682692

683-
if (writeable) {
693+
if (writable) {
684694
kvm_set_pfn_dirty(hfn);
685695
mark_page_dirty(kvm, gfn);
686696
ret = gstage_map_page(kvm, pcache, gpa, hfn << PAGE_SHIFT,

0 commit comments

Comments
 (0)