Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'kvm-riscv-6.19-1' of https://github.com/kvm-riscv/linux into HEAD

KVM/riscv changes for 6.19

- SBI MPXY support for KVM guest
- New KVM_EXIT_FAIL_ENTRY_NO_VSFILE for the case when in-kernel
AIA virtualization fails to allocate IMSIC VS-file
- Support enabling dirty log gradually in small chunks
- Fix guest page fault within HLV* instructions
- Flush VS-stage TLB after VCPU migration for Andes cores

+138 -94
+1 -1
Documentation/virt/kvm/api.rst
··· 8028 8028 dirty logging can be enabled gradually in small chunks on the first call 8029 8029 to KVM_CLEAR_DIRTY_LOG. KVM_DIRTY_LOG_INITIALLY_SET depends on 8030 8030 KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (it is also only available on 8031 - x86 and arm64 for now). 8031 + x86, arm64 and riscv for now). 8032 8032 8033 8033 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name 8034 8034 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make
+6
arch/riscv/include/asm/kvm_host.h
··· 59 59 BIT(IRQ_VS_TIMER) | \ 60 60 BIT(IRQ_VS_EXT)) 61 61 62 + #define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ 63 + KVM_DIRTY_LOG_INITIALLY_SET) 64 + 62 65 struct kvm_vm_stat { 63 66 struct kvm_vm_stat_generic generic; 64 67 }; ··· 329 326 bool kvm_riscv_vcpu_stopped(struct kvm_vcpu *vcpu); 330 327 331 328 void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu); 329 + 330 + /* Flags representing implementation specific details */ 331 + DECLARE_STATIC_KEY_FALSE(kvm_riscv_vsstage_tlb_no_gpa); 332 332 333 333 #endif /* __RISCV_KVM_HOST_H__ */
+1
arch/riscv/include/asm/kvm_tlb.h
··· 49 49 unsigned long gva, unsigned long gvsz, 50 50 unsigned long order); 51 51 void kvm_riscv_local_hfence_vvma_all(unsigned long vmid); 52 + void kvm_riscv_local_tlb_sanitize(struct kvm_vcpu *vcpu); 52 53 53 54 void kvm_riscv_tlb_flush_process(struct kvm_vcpu *vcpu); 54 55
+4 -1
arch/riscv/include/asm/kvm_vcpu_sbi.h
··· 69 69 unsigned long reg_size, const void *reg_val); 70 70 }; 71 71 72 - void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run); 72 + int kvm_riscv_vcpu_sbi_forward_handler(struct kvm_vcpu *vcpu, 73 + struct kvm_run *run, 74 + struct kvm_vcpu_sbi_return *retdata); 73 75 void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu, 74 76 struct kvm_run *run, 75 77 u32 type, u64 flags); ··· 107 105 extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp; 108 106 extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_sta; 109 107 extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_fwft; 108 + extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_mpxy; 110 109 extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental; 111 110 extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor; 112 111
-1
arch/riscv/include/asm/kvm_vmid.h
··· 22 22 int kvm_riscv_gstage_vmid_init(struct kvm *kvm); 23 23 bool kvm_riscv_gstage_vmid_ver_changed(struct kvm_vmid *vmid); 24 24 void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu); 25 - void kvm_riscv_gstage_vmid_sanitize(struct kvm_vcpu *vcpu); 26 25 27 26 #endif
+3
arch/riscv/include/uapi/asm/kvm.h
··· 23 23 #define KVM_INTERRUPT_SET -1U 24 24 #define KVM_INTERRUPT_UNSET -2U 25 25 26 + #define KVM_EXIT_FAIL_ENTRY_NO_VSFILE (1ULL << 0) 27 + 26 28 /* for KVM_GET_REGS and KVM_SET_REGS */ 27 29 struct kvm_regs { 28 30 }; ··· 213 211 KVM_RISCV_SBI_EXT_STA, 214 212 KVM_RISCV_SBI_EXT_SUSP, 215 213 KVM_RISCV_SBI_EXT_FWFT, 214 + KVM_RISCV_SBI_EXT_MPXY, 216 215 KVM_RISCV_SBI_EXT_MAX, 217 216 }; 218 217
+1
arch/riscv/kvm/Makefile
··· 27 27 kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o 28 28 kvm-y += vcpu_sbi.o 29 29 kvm-y += vcpu_sbi_base.o 30 + kvm-y += vcpu_sbi_forward.o 30 31 kvm-y += vcpu_sbi_fwft.o 31 32 kvm-y += vcpu_sbi_hsm.o 32 33 kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_sbi_pmu.o
+1 -1
arch/riscv/kvm/aia_imsic.c
··· 814 814 /* For HW acceleration mode, we can't continue */ 815 815 if (kvm->arch.aia.mode == KVM_DEV_RISCV_AIA_MODE_HWACCEL) { 816 816 run->fail_entry.hardware_entry_failure_reason = 817 - CSR_HSTATUS; 817 + KVM_EXIT_FAIL_ENTRY_NO_VSFILE; 818 818 run->fail_entry.cpu = vcpu->cpu; 819 819 run->exit_reason = KVM_EXIT_FAIL_ENTRY; 820 820 return 0;
+14
arch/riscv/kvm/main.c
··· 15 15 #include <asm/kvm_nacl.h> 16 16 #include <asm/sbi.h> 17 17 18 + DEFINE_STATIC_KEY_FALSE(kvm_riscv_vsstage_tlb_no_gpa); 19 + 20 + static void kvm_riscv_setup_vendor_features(void) 21 + { 22 + /* Andes AX66: split two-stage TLBs */ 23 + if (riscv_cached_mvendorid(0) == ANDES_VENDOR_ID && 24 + (riscv_cached_marchid(0) & 0xFFFF) == 0x8A66) { 25 + static_branch_enable(&kvm_riscv_vsstage_tlb_no_gpa); 26 + kvm_info("VS-stage TLB does not cache guest physical address and VMID\n"); 27 + } 28 + } 29 + 18 30 long kvm_arch_dev_ioctl(struct file *filp, 19 31 unsigned int ioctl, unsigned long arg) 20 32 { ··· 171 159 if (kvm_riscv_aia_available()) 172 160 kvm_info("AIA available with %d guest external interrupts\n", 173 161 kvm_riscv_aia_nr_hgei); 162 + 163 + kvm_riscv_setup_vendor_features(); 174 164 175 165 kvm_register_perf_callbacks(NULL); 176 166
+4 -1
arch/riscv/kvm/mmu.c
··· 161 161 * allocated dirty_bitmap[], dirty pages will be tracked while 162 162 * the memory slot is write protected. 163 163 */ 164 - if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) 164 + if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) { 165 + if (kvm_dirty_log_manual_protect_and_init_set(kvm)) 166 + return; 165 167 mmu_wp_memory_region(kvm, new->id); 168 + } 166 169 } 167 170 168 171 int kvm_arch_prepare_memory_region(struct kvm *kvm,
+30
arch/riscv/kvm/tlb.c
··· 158 158 csr_write(CSR_HGATP, hgatp); 159 159 } 160 160 161 + void kvm_riscv_local_tlb_sanitize(struct kvm_vcpu *vcpu) 162 + { 163 + unsigned long vmid; 164 + 165 + if (!kvm_riscv_gstage_vmid_bits() || 166 + vcpu->arch.last_exit_cpu == vcpu->cpu) 167 + return; 168 + 169 + /* 170 + * On RISC-V platforms with hardware VMID support, we share same 171 + * VMID for all VCPUs of a particular Guest/VM. This means we might 172 + * have stale G-stage TLB entries on the current Host CPU due to 173 + * some other VCPU of the same Guest which ran previously on the 174 + * current Host CPU. 175 + * 176 + * To cleanup stale TLB entries, we simply flush all G-stage TLB 177 + * entries by VMID whenever underlying Host CPU changes for a VCPU. 178 + */ 179 + 180 + vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); 181 + kvm_riscv_local_hfence_gvma_vmid_all(vmid); 182 + 183 + /* 184 + * Flush VS-stage TLB entries for implementation where VS-stage 185 + * TLB does not cahce guest physical address and VMID. 186 + */ 187 + if (static_branch_unlikely(&kvm_riscv_vsstage_tlb_no_gpa)) 188 + kvm_riscv_local_hfence_vvma_all(vmid); 189 + } 190 + 161 191 void kvm_riscv_fence_i_process(struct kvm_vcpu *vcpu) 162 192 { 163 193 kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_RCVD);
+1 -1
arch/riscv/kvm/vcpu.c
··· 968 968 * Note: This should be done after G-stage VMID has been 969 969 * updated using kvm_riscv_gstage_vmid_ver_changed() 970 970 */ 971 - kvm_riscv_gstage_vmid_sanitize(vcpu); 971 + kvm_riscv_local_tlb_sanitize(vcpu); 972 972 973 973 trace_kvm_entry(vcpu); 974 974
+22
arch/riscv/kvm/vcpu_insn.c
··· 298 298 return (rc <= 0) ? rc : 1; 299 299 } 300 300 301 + static bool is_load_guest_page_fault(unsigned long scause) 302 + { 303 + /** 304 + * If a g-stage page fault occurs, the direct approach 305 + * is to let the g-stage page fault handler handle it 306 + * naturally, however, calling the g-stage page fault 307 + * handler here seems rather strange. 308 + * Considering this is a corner case, we can directly 309 + * return to the guest and re-execute the same PC, this 310 + * will trigger a g-stage page fault again and then the 311 + * regular g-stage page fault handler will populate 312 + * g-stage page table. 313 + */ 314 + return (scause == EXC_LOAD_GUEST_PAGE_FAULT); 315 + } 316 + 301 317 /** 302 318 * kvm_riscv_vcpu_virtual_insn -- Handle virtual instruction trap 303 319 * ··· 339 323 ct->sepc, 340 324 &utrap); 341 325 if (utrap.scause) { 326 + if (is_load_guest_page_fault(utrap.scause)) 327 + return 1; 342 328 utrap.sepc = ct->sepc; 343 329 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); 344 330 return 1; ··· 396 378 insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, ct->sepc, 397 379 &utrap); 398 380 if (utrap.scause) { 381 + if (is_load_guest_page_fault(utrap.scause)) 382 + return 1; 399 383 /* Redirect trap if we failed to read instruction */ 400 384 utrap.sepc = ct->sepc; 401 385 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); ··· 524 504 insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, ct->sepc, 525 505 &utrap); 526 506 if (utrap.scause) { 507 + if (is_load_guest_page_fault(utrap.scause)) 508 + return 1; 527 509 /* Redirect trap if we failed to read instruction */ 528 510 utrap.sepc = ct->sepc; 529 511 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap);
+9 -1
arch/riscv/kvm/vcpu_sbi.c
··· 83 83 .ext_ptr = &vcpu_sbi_ext_fwft, 84 84 }, 85 85 { 86 + .ext_idx = KVM_RISCV_SBI_EXT_MPXY, 87 + .ext_ptr = &vcpu_sbi_ext_mpxy, 88 + }, 89 + { 86 90 .ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL, 87 91 .ext_ptr = &vcpu_sbi_ext_experimental, 88 92 }, ··· 124 120 return sext && scontext->ext_status[sext->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE; 125 121 } 126 122 127 - void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run) 123 + int kvm_riscv_vcpu_sbi_forward_handler(struct kvm_vcpu *vcpu, 124 + struct kvm_run *run, 125 + struct kvm_vcpu_sbi_return *retdata) 128 126 { 129 127 struct kvm_cpu_context *cp = &vcpu->arch.guest_context; 130 128 ··· 143 137 run->riscv_sbi.args[5] = cp->a5; 144 138 run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED; 145 139 run->riscv_sbi.ret[1] = 0; 140 + retdata->uexit = true; 141 + return 0; 146 142 } 147 143 148 144 void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
+1 -27
arch/riscv/kvm/vcpu_sbi_base.c
··· 41 41 * For experimental/vendor extensions 42 42 * forward it to the userspace 43 43 */ 44 - kvm_riscv_vcpu_sbi_forward(vcpu, run); 45 - retdata->uexit = true; 44 + return kvm_riscv_vcpu_sbi_forward_handler(vcpu, run, retdata); 46 45 } else { 47 46 sbi_ext = kvm_vcpu_sbi_find_ext(vcpu, cp->a0); 48 47 *out_val = sbi_ext && sbi_ext->probe ? ··· 69 70 .extid_start = SBI_EXT_BASE, 70 71 .extid_end = SBI_EXT_BASE, 71 72 .handler = kvm_sbi_ext_base_handler, 72 - }; 73 - 74 - static int kvm_sbi_ext_forward_handler(struct kvm_vcpu *vcpu, 75 - struct kvm_run *run, 76 - struct kvm_vcpu_sbi_return *retdata) 77 - { 78 - /* 79 - * Both SBI experimental and vendor extensions are 80 - * unconditionally forwarded to userspace. 81 - */ 82 - kvm_riscv_vcpu_sbi_forward(vcpu, run); 83 - retdata->uexit = true; 84 - return 0; 85 - } 86 - 87 - const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental = { 88 - .extid_start = SBI_EXT_EXPERIMENTAL_START, 89 - .extid_end = SBI_EXT_EXPERIMENTAL_END, 90 - .handler = kvm_sbi_ext_forward_handler, 91 - }; 92 - 93 - const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor = { 94 - .extid_start = SBI_EXT_VENDOR_START, 95 - .extid_end = SBI_EXT_VENDOR_END, 96 - .handler = kvm_sbi_ext_forward_handler, 97 73 };
+34
arch/riscv/kvm/vcpu_sbi_forward.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2025 Ventana Micro Systems Inc. 4 + */ 5 + 6 + #include <linux/kvm_host.h> 7 + #include <asm/kvm_vcpu_sbi.h> 8 + #include <asm/sbi.h> 9 + 10 + const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental = { 11 + .extid_start = SBI_EXT_EXPERIMENTAL_START, 12 + .extid_end = SBI_EXT_EXPERIMENTAL_END, 13 + .handler = kvm_riscv_vcpu_sbi_forward_handler, 14 + }; 15 + 16 + const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor = { 17 + .extid_start = SBI_EXT_VENDOR_START, 18 + .extid_end = SBI_EXT_VENDOR_END, 19 + .handler = kvm_riscv_vcpu_sbi_forward_handler, 20 + }; 21 + 22 + const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn = { 23 + .extid_start = SBI_EXT_DBCN, 24 + .extid_end = SBI_EXT_DBCN, 25 + .default_disabled = true, 26 + .handler = kvm_riscv_vcpu_sbi_forward_handler, 27 + }; 28 + 29 + const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_mpxy = { 30 + .extid_start = SBI_EXT_MPXY, 31 + .extid_end = SBI_EXT_MPXY, 32 + .default_disabled = true, 33 + .handler = kvm_riscv_vcpu_sbi_forward_handler, 34 + };
-32
arch/riscv/kvm/vcpu_sbi_replace.c
··· 185 185 .extid_end = SBI_EXT_SRST, 186 186 .handler = kvm_sbi_ext_srst_handler, 187 187 }; 188 - 189 - static int kvm_sbi_ext_dbcn_handler(struct kvm_vcpu *vcpu, 190 - struct kvm_run *run, 191 - struct kvm_vcpu_sbi_return *retdata) 192 - { 193 - struct kvm_cpu_context *cp = &vcpu->arch.guest_context; 194 - unsigned long funcid = cp->a6; 195 - 196 - switch (funcid) { 197 - case SBI_EXT_DBCN_CONSOLE_WRITE: 198 - case SBI_EXT_DBCN_CONSOLE_READ: 199 - case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: 200 - /* 201 - * The SBI debug console functions are unconditionally 202 - * forwarded to the userspace. 203 - */ 204 - kvm_riscv_vcpu_sbi_forward(vcpu, run); 205 - retdata->uexit = true; 206 - break; 207 - default: 208 - retdata->err_val = SBI_ERR_NOT_SUPPORTED; 209 - } 210 - 211 - return 0; 212 - } 213 - 214 - const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn = { 215 - .extid_start = SBI_EXT_DBCN, 216 - .extid_end = SBI_EXT_DBCN, 217 - .default_disabled = true, 218 - .handler = kvm_sbi_ext_dbcn_handler, 219 - };
+1 -3
arch/riscv/kvm/vcpu_sbi_system.c
··· 47 47 kvm_riscv_vcpu_sbi_request_reset(vcpu, cp->a1, cp->a2); 48 48 49 49 /* userspace provides the suspend implementation */ 50 - kvm_riscv_vcpu_sbi_forward(vcpu, run); 51 - retdata->uexit = true; 52 - break; 50 + return kvm_riscv_vcpu_sbi_forward_handler(vcpu, run, retdata); 53 51 default: 54 52 retdata->err_val = SBI_ERR_NOT_SUPPORTED; 55 53 break;
+1 -2
arch/riscv/kvm/vcpu_sbi_v01.c
··· 32 32 * The CONSOLE_GETCHAR/CONSOLE_PUTCHAR SBI calls cannot be 33 33 * handled in kernel so we forward these to user-space 34 34 */ 35 - kvm_riscv_vcpu_sbi_forward(vcpu, run); 36 - retdata->uexit = true; 35 + ret = kvm_riscv_vcpu_sbi_forward_handler(vcpu, run, retdata); 37 36 break; 38 37 case SBI_EXT_0_1_SET_TIMER: 39 38 #if __riscv_xlen == 32
-23
arch/riscv/kvm/vmid.c
··· 122 122 kvm_for_each_vcpu(i, v, vcpu->kvm) 123 123 kvm_make_request(KVM_REQ_UPDATE_HGATP, v); 124 124 } 125 - 126 - void kvm_riscv_gstage_vmid_sanitize(struct kvm_vcpu *vcpu) 127 - { 128 - unsigned long vmid; 129 - 130 - if (!kvm_riscv_gstage_vmid_bits() || 131 - vcpu->arch.last_exit_cpu == vcpu->cpu) 132 - return; 133 - 134 - /* 135 - * On RISC-V platforms with hardware VMID support, we share same 136 - * VMID for all VCPUs of a particular Guest/VM. This means we might 137 - * have stale G-stage TLB entries on the current Host CPU due to 138 - * some other VCPU of the same Guest which ran previously on the 139 - * current Host CPU. 140 - * 141 - * To cleanup stale TLB entries, we simply flush all G-stage TLB 142 - * entries by VMID whenever underlying Host CPU changes for a VCPU. 143 - */ 144 - 145 - vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); 146 - kvm_riscv_local_hfence_gvma_vmid_all(vmid); 147 - }
+4
tools/testing/selftests/kvm/riscv/get-reg-list.c
··· 133 133 case KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_SUSP: 134 134 case KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_STA: 135 135 case KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT: 136 + case KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_MPXY: 136 137 case KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_EXPERIMENTAL: 137 138 case KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_VENDOR: 138 139 return true; ··· 640 639 KVM_SBI_EXT_ARR(KVM_RISCV_SBI_EXT_SUSP), 641 640 KVM_SBI_EXT_ARR(KVM_RISCV_SBI_EXT_STA), 642 641 KVM_SBI_EXT_ARR(KVM_RISCV_SBI_EXT_FWFT), 642 + KVM_SBI_EXT_ARR(KVM_RISCV_SBI_EXT_MPXY), 643 643 KVM_SBI_EXT_ARR(KVM_RISCV_SBI_EXT_EXPERIMENTAL), 644 644 KVM_SBI_EXT_ARR(KVM_RISCV_SBI_EXT_VENDOR), 645 645 }; ··· 1144 1142 KVM_SBI_EXT_SIMPLE_CONFIG(pmu, PMU); 1145 1143 KVM_SBI_EXT_SIMPLE_CONFIG(dbcn, DBCN); 1146 1144 KVM_SBI_EXT_SIMPLE_CONFIG(susp, SUSP); 1145 + KVM_SBI_EXT_SIMPLE_CONFIG(mpxy, MPXY); 1147 1146 KVM_SBI_EXT_SUBLIST_CONFIG(fwft, FWFT); 1148 1147 1149 1148 KVM_ISA_EXT_SUBLIST_CONFIG(aia, AIA); ··· 1225 1222 &config_sbi_pmu, 1226 1223 &config_sbi_dbcn, 1227 1224 &config_sbi_susp, 1225 + &config_sbi_mpxy, 1228 1226 &config_sbi_fwft, 1229 1227 &config_aia, 1230 1228 &config_fp_f,