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 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull kvm fixes from Paolo Bonzini:
"ARM:

- Clear the pending exception state from a vcpu coming out of reset,
as it could otherwise affect the first instruction executed in the
guest

- Fix pointer arithmetic in address translation emulation, so that
the Hardware Access bit is set on the correct PTE instead of some
other location

s390:

- Fix deadlock in new memory management

- Properly handle kernel faults on donated memory

- Fix bounds checking for irq routing, with selftest

- Fix invalid machine checks and log all of them"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: arm64: Fix the descriptor address in __kvm_at_swap_desc()
KVM: s390: vsie: Avoid injecting machine check on signal
KVM: s390: log machine checks more aggressively
KVM: s390: selftests: Add IRQ routing address offset tests
KVM: s390: Limit adapter indicator access to mapped page
s390/mm: Add missing secure storage access fixups for donated memory
KVM: arm64: Discard PC update state on vcpu reset
KVM: s390: Fix a deadlock

+144 -22
+1 -1
arch/arm64/kvm/at.c
··· 1753 1753 if (!writable) 1754 1754 return -EPERM; 1755 1755 1756 - ptep = (u64 __user *)hva + offset; 1756 + ptep = (void __user *)hva + offset; 1757 1757 if (cpus_have_final_cap(ARM64_HAS_LSE_ATOMICS)) 1758 1758 r = __lse_swap_desc(ptep, old, new); 1759 1759 else
+14
arch/arm64/kvm/reset.c
··· 247 247 kvm_vcpu_set_be(vcpu); 248 248 249 249 *vcpu_pc(vcpu) = target_pc; 250 + 251 + /* 252 + * We may come from a state where either a PC update was 253 + * pending (SMC call resulting in PC being increpented to 254 + * skip the SMC) or a pending exception. Make sure we get 255 + * rid of all that, as this cannot be valid out of reset. 256 + * 257 + * Note that clearing the exception mask also clears PC 258 + * updates, but that's an implementation detail, and we 259 + * really want to make it explicit. 260 + */ 261 + vcpu_clear_flag(vcpu, PENDING_EXCEPTION); 262 + vcpu_clear_flag(vcpu, EXCEPT_MASK); 263 + vcpu_clear_flag(vcpu, INCREMENT_PC); 250 264 vcpu_set_reg(vcpu, 0, reset_state.r0); 251 265 } 252 266
+3
arch/s390/include/asm/kvm_host.h
··· 710 710 void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm, 711 711 unsigned long *aqm, unsigned long *adm); 712 712 713 + #define SIE64_RETURN_NORMAL 0 714 + #define SIE64_RETURN_MCCK 1 715 + 713 716 int __sie64a(phys_addr_t sie_block_phys, struct kvm_s390_sie_block *sie_block, u64 *rsa, 714 717 unsigned long gasce); 715 718
+1 -1
arch/s390/include/asm/stacktrace.h
··· 62 62 struct { 63 63 unsigned long sie_control_block; 64 64 unsigned long sie_savearea; 65 - unsigned long sie_reason; 65 + unsigned long sie_return; 66 66 unsigned long sie_flags; 67 67 unsigned long sie_control_block_phys; 68 68 unsigned long sie_guest_asce;
+1 -1
arch/s390/kernel/asm-offsets.c
··· 63 63 OFFSET(__SF_EMPTY, stack_frame, empty[0]); 64 64 OFFSET(__SF_SIE_CONTROL, stack_frame, sie_control_block); 65 65 OFFSET(__SF_SIE_SAVEAREA, stack_frame, sie_savearea); 66 - OFFSET(__SF_SIE_REASON, stack_frame, sie_reason); 66 + OFFSET(__SF_SIE_RETURN, stack_frame, sie_return); 67 67 OFFSET(__SF_SIE_FLAGS, stack_frame, sie_flags); 68 68 OFFSET(__SF_SIE_CONTROL_PHYS, stack_frame, sie_control_block_phys); 69 69 OFFSET(__SF_SIE_GUEST_ASCE, stack_frame, sie_guest_asce);
+2 -2
arch/s390/kernel/entry.S
··· 200 200 stg %r3,__SF_SIE_CONTROL(%r15) # ...and virtual addresses 201 201 stg %r4,__SF_SIE_SAVEAREA(%r15) # save guest register save area 202 202 stg %r5,__SF_SIE_GUEST_ASCE(%r15) # save guest asce 203 - xc __SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0 203 + xc __SF_SIE_RETURN(8,%r15),__SF_SIE_RETURN(%r15) # return code = 0 204 204 mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r14) # copy thread flags 205 205 lmg %r0,%r13,0(%r4) # load guest gprs 0-13 206 206 mvi __TI_sie(%r14),1 ··· 237 237 xgr %r4,%r4 238 238 xgr %r5,%r5 239 239 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers 240 - lg %r2,__SF_SIE_REASON(%r15) # return exit reason code 240 + lg %r2,__SF_SIE_RETURN(%r15) # return sie return code 241 241 BR_EX %r14 242 242 SYM_FUNC_END(__sie64a) 243 243 EXPORT_SYMBOL(__sie64a)
+2 -2
arch/s390/kernel/nmi.c
··· 487 487 mcck_dam_code = (mci.val & MCIC_SUBCLASS_MASK); 488 488 if (test_cpu_flag(CIF_MCCK_GUEST) && 489 489 (mcck_dam_code & MCCK_CODE_NO_GUEST) != mcck_dam_code) { 490 - /* Set exit reason code for host's later handling */ 491 - *((long *)(regs->gprs[15] + __SF_SIE_REASON)) = -EINTR; 490 + /* Set sie return code for host's later handling */ 491 + ((struct stack_frame *)regs->gprs[15])->sie_return = SIE64_RETURN_MCCK; 492 492 } 493 493 clear_cpu_flag(CIF_MCCK_GUEST); 494 494
+4 -2
arch/s390/kvm/gaccess.c
··· 1434 1434 if (rc) 1435 1435 return rc; 1436 1436 1437 - pgste = pgste_get_lock(ptep_h); 1437 + if (!pgste_get_trylock(ptep_h, &pgste)) 1438 + return -EAGAIN; 1438 1439 newpte = _pte(f->pfn, f->writable, !p, 0); 1439 1440 newpte.s.d |= ptep->s.d; 1440 1441 newpte.s.sd |= ptep->s.sd; ··· 1445 1444 pgste_set_unlock(ptep_h, pgste); 1446 1445 1447 1446 newpte = _pte(f->pfn, 0, !p, 0); 1448 - pgste = pgste_get_lock(ptep); 1447 + if (!pgste_get_trylock(ptep, &pgste)) 1448 + return -EAGAIN; 1449 1449 pgste = __dat_ptep_xchg(ptep, pgste, newpte, gpa_to_gfn(raddr), sg->asce, uses_skeys(sg)); 1450 1450 pgste_set_unlock(ptep, pgste); 1451 1451
+18
arch/s390/kvm/interrupt.c
··· 2724 2724 2725 2725 bit = bit_nr + (addr % PAGE_SIZE) * 8; 2726 2726 2727 + /* kvm_set_routing_entry() should never allow this to happen */ 2728 + WARN_ON_ONCE(bit > (PAGE_SIZE * BITS_PER_BYTE - 1)); 2729 + 2727 2730 return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit; 2728 2731 } 2729 2732 ··· 2827 2824 int rc; 2828 2825 2829 2826 mci.val = mcck_info->mcic; 2827 + 2828 + /* log machine checks being reinjected on all debugs */ 2829 + VCPU_EVENT(vcpu, 2, "guest machine check %lx", mci.val); 2830 + KVM_EVENT(2, "guest machine check %lx", mci.val); 2831 + pr_info("guest machine check pid %d: %lx", current->pid, mci.val); 2832 + 2830 2833 if (mci.sr) 2831 2834 cr14 |= CR14_RECOVERY_SUBMASK; 2832 2835 if (mci.dg) ··· 2861 2852 struct kvm_kernel_irq_routing_entry *e, 2862 2853 const struct kvm_irq_routing_entry *ue) 2863 2854 { 2855 + const struct kvm_irq_routing_s390_adapter *adapter; 2864 2856 u64 uaddr_s, uaddr_i; 2865 2857 int idx; 2866 2858 ··· 2871 2861 if (kvm_is_ucontrol(kvm)) 2872 2862 return -EINVAL; 2873 2863 e->set = set_adapter_int; 2864 + 2865 + adapter = &ue->u.adapter; 2866 + if (adapter->summary_addr + (adapter->summary_offset / 8) >= 2867 + (adapter->summary_addr & PAGE_MASK) + PAGE_SIZE) 2868 + return -EINVAL; 2869 + if (adapter->ind_addr + (adapter->ind_offset / 8) >= 2870 + (adapter->ind_addr & PAGE_MASK) + PAGE_SIZE) 2871 + return -EINVAL; 2874 2872 2875 2873 idx = srcu_read_lock(&kvm->srcu); 2876 2874 uaddr_s = gpa_to_hva(kvm, ue->u.adapter.summary_addr);
+8 -8
arch/s390/kvm/kvm-s390.c
··· 4617 4617 return 0; 4618 4618 } 4619 4619 4620 - static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) 4620 + static int vcpu_post_run(struct kvm_vcpu *vcpu, int sie_return) 4621 4621 { 4622 4622 struct mcck_volatile_info *mcck_info; 4623 4623 struct sie_page *sie_page; ··· 4633 4633 vcpu->run->s.regs.gprs[14] = vcpu->arch.sie_block->gg14; 4634 4634 vcpu->run->s.regs.gprs[15] = vcpu->arch.sie_block->gg15; 4635 4635 4636 - if (exit_reason == -EINTR) { 4637 - VCPU_EVENT(vcpu, 3, "%s", "machine check"); 4636 + if (sie_return == SIE64_RETURN_MCCK) { 4638 4637 sie_page = container_of(vcpu->arch.sie_block, 4639 4638 struct sie_page, sie_block); 4640 4639 mcck_info = &sie_page->mcck_info; 4641 4640 kvm_s390_reinject_machine_check(vcpu, mcck_info); 4642 4641 return 0; 4643 4642 } 4643 + WARN_ON_ONCE(sie_return != SIE64_RETURN_NORMAL); 4644 4644 4645 4645 if (vcpu->arch.sie_block->icptcode > 0) { 4646 4646 rc = kvm_handle_sie_intercept(vcpu); ··· 4679 4679 #define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK) 4680 4680 static int __vcpu_run(struct kvm_vcpu *vcpu) 4681 4681 { 4682 - int rc, exit_reason; 4682 + int rc, sie_return; 4683 4683 struct sie_page *sie_page = (struct sie_page *)vcpu->arch.sie_block; 4684 4684 4685 4685 /* ··· 4719 4719 guest_timing_enter_irqoff(); 4720 4720 __disable_cpu_timer_accounting(vcpu); 4721 4721 4722 - exit_reason = kvm_s390_enter_exit_sie(vcpu->arch.sie_block, 4723 - vcpu->run->s.regs.gprs, 4724 - vcpu->arch.gmap->asce.val); 4722 + sie_return = kvm_s390_enter_exit_sie(vcpu->arch.sie_block, 4723 + vcpu->run->s.regs.gprs, 4724 + vcpu->arch.gmap->asce.val); 4725 4725 4726 4726 __enable_cpu_timer_accounting(vcpu); 4727 4727 guest_timing_exit_irqoff(); ··· 4744 4744 } 4745 4745 kvm_vcpu_srcu_read_lock(vcpu); 4746 4746 4747 - rc = vcpu_post_run(vcpu, exit_reason); 4747 + rc = vcpu_post_run(vcpu, sie_return); 4748 4748 if (rc || guestdbg_exit_pending(vcpu)) { 4749 4749 kvm_vcpu_srcu_read_unlock(vcpu); 4750 4750 break;
+5 -3
arch/s390/kvm/vsie.c
··· 1122 1122 { 1123 1123 struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; 1124 1124 struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; 1125 + unsigned long sie_return = SIE64_RETURN_NORMAL; 1125 1126 int guest_bp_isolation; 1126 1127 int rc = 0; 1127 1128 ··· 1164 1163 goto xfer_to_guest_mode_check; 1165 1164 } 1166 1165 guest_timing_enter_irqoff(); 1167 - rc = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, sg->asce.val); 1166 + sie_return = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, sg->asce.val); 1168 1167 guest_timing_exit_irqoff(); 1169 1168 local_irq_enable(); 1170 1169 } ··· 1179 1178 1180 1179 kvm_vcpu_srcu_read_lock(vcpu); 1181 1180 1182 - if (rc == -EINTR) { 1183 - VCPU_EVENT(vcpu, 3, "%s", "machine check"); 1181 + if (sie_return == SIE64_RETURN_MCCK) { 1184 1182 kvm_s390_reinject_machine_check(vcpu, &vsie_page->mcck_info); 1185 1183 return 0; 1186 1184 } 1185 + 1186 + WARN_ON_ONCE(sie_return != SIE64_RETURN_NORMAL); 1187 1187 1188 1188 if (rc > 0) 1189 1189 rc = 0; /* we could still have an icpt */
+9 -2
arch/s390/mm/fault.c
··· 441 441 folio = phys_to_folio(addr); 442 442 if (unlikely(!folio_try_get(folio))) 443 443 return; 444 - rc = arch_make_folio_accessible(folio); 444 + rc = uv_convert_from_secure(folio_to_phys(folio)); 445 + if (!rc) 446 + clear_bit(PG_arch_1, &folio->flags.f); 445 447 folio_put(folio); 448 + /* 449 + * There are some valid fixup types for kernel 450 + * accesses to donated secure memory. zeropad is one 451 + * of them. 452 + */ 446 453 if (rc) 447 - BUG(); 454 + return handle_fault_error_nolock(regs, 0); 448 455 } else { 449 456 if (faulthandler_disabled()) 450 457 return handle_fault_error_nolock(regs, 0);
+1
tools/testing/selftests/kvm/Makefile.kvm
··· 206 206 TEST_GEN_PROGS_s390 += s390/user_operexec 207 207 TEST_GEN_PROGS_s390 += s390/keyop 208 208 TEST_GEN_PROGS_s390 += rseq_test 209 + TEST_GEN_PROGS_s390 += s390/irq_routing 209 210 210 211 TEST_GEN_PROGS_riscv = $(TEST_GEN_PROGS_COMMON) 211 212 TEST_GEN_PROGS_riscv += riscv/sbi_pmu_test
+75
tools/testing/selftests/kvm/s390/irq_routing.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * IRQ routing offset tests. 4 + * 5 + * Copyright IBM Corp. 2026 6 + * 7 + * Authors: 8 + * Janosch Frank <frankja@linux.ibm.com> 9 + */ 10 + #include <stdio.h> 11 + #include <stdlib.h> 12 + #include <string.h> 13 + #include <sys/ioctl.h> 14 + 15 + #include "test_util.h" 16 + #include "kvm_util.h" 17 + #include "kselftest.h" 18 + #include "ucall_common.h" 19 + 20 + extern char guest_code[]; 21 + asm("guest_code:\n" 22 + "diag %r0,%r0,0\n" 23 + "j .\n"); 24 + 25 + static void test(void) 26 + { 27 + struct kvm_irq_routing *routing; 28 + struct kvm_vcpu *vcpu; 29 + struct kvm_vm *vm; 30 + vm_paddr_t mem; 31 + int ret; 32 + 33 + struct kvm_irq_routing_entry ue = { 34 + .type = KVM_IRQ_ROUTING_S390_ADAPTER, 35 + .gsi = 1, 36 + }; 37 + 38 + vm = vm_create_with_one_vcpu(&vcpu, guest_code); 39 + mem = vm_phy_pages_alloc(vm, 2, 4096 * 42, 0); 40 + 41 + routing = kvm_gsi_routing_create(); 42 + routing->nr = 1; 43 + routing->entries[0] = ue; 44 + routing->entries[0].u.adapter.summary_addr = (uintptr_t)mem; 45 + routing->entries[0].u.adapter.ind_addr = (uintptr_t)mem; 46 + 47 + routing->entries[0].u.adapter.summary_offset = 4096 * 8; 48 + ret = __vm_ioctl(vm, KVM_SET_GSI_ROUTING, routing); 49 + ksft_test_result(ret == -1 && errno == EINVAL, "summary offset outside of page\n"); 50 + 51 + routing->entries[0].u.adapter.summary_offset -= 4; 52 + ret = __vm_ioctl(vm, KVM_SET_GSI_ROUTING, routing); 53 + ksft_test_result(ret == 0, "summary offset inside of page\n"); 54 + 55 + routing->entries[0].u.adapter.ind_offset = 4096 * 8; 56 + ret = __vm_ioctl(vm, KVM_SET_GSI_ROUTING, routing); 57 + ksft_test_result(ret == -1 && errno == EINVAL, "ind offset outside of page\n"); 58 + 59 + routing->entries[0].u.adapter.ind_offset -= 4; 60 + ret = __vm_ioctl(vm, KVM_SET_GSI_ROUTING, routing); 61 + ksft_test_result(ret == 0, "ind offset inside of page\n"); 62 + 63 + kvm_vm_free(vm); 64 + } 65 + 66 + int main(int argc, char *argv[]) 67 + { 68 + TEST_REQUIRE(kvm_has_cap(KVM_CAP_IRQ_ROUTING)); 69 + 70 + ksft_print_header(); 71 + ksft_set_plan(4); 72 + test(); 73 + 74 + ksft_finished(); /* Print results and exit() accordingly */ 75 + }