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 's390-6.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Alexander Gordeev:

- Do not create PT_LOAD program header for the kenel image when the
virtual memory informaton in OS_INFO data is not available. That
fixes stand-alone dump failures against kernels that do not provide
the virtual memory informaton

- Add KVM s390 shared zeropage selftest

* tag 's390-6.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
KVM: s390x: selftests: Add shared zeropage test
s390/crash: Do not use VM info if os_info does not have it

+142 -24
+30 -24
arch/s390/kernel/crash_dump.c
··· 451 451 /* 452 452 * Initialize ELF header (new kernel) 453 453 */ 454 - static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt) 454 + static void *ehdr_init(Elf64_Ehdr *ehdr, int phdr_count) 455 455 { 456 456 memset(ehdr, 0, sizeof(*ehdr)); 457 457 memcpy(ehdr->e_ident, ELFMAG, SELFMAG); ··· 465 465 ehdr->e_phoff = sizeof(Elf64_Ehdr); 466 466 ehdr->e_ehsize = sizeof(Elf64_Ehdr); 467 467 ehdr->e_phentsize = sizeof(Elf64_Phdr); 468 - /* 469 - * Number of memory chunk PT_LOAD program headers plus one kernel 470 - * image PT_LOAD program header plus one PT_NOTE program header. 471 - */ 472 - ehdr->e_phnum = mem_chunk_cnt + 1 + 1; 468 + /* Number of PT_LOAD program headers plus PT_NOTE program header */ 469 + ehdr->e_phnum = phdr_count + 1; 473 470 return ehdr + 1; 474 471 } 475 472 ··· 500 503 /* 501 504 * Initialize ELF loads (new kernel) 502 505 */ 503 - static void loads_init(Elf64_Phdr *phdr) 506 + static void loads_init(Elf64_Phdr *phdr, bool os_info_has_vm) 504 507 { 505 - unsigned long old_identity_base = os_info_old_value(OS_INFO_IDENTITY_BASE); 508 + unsigned long old_identity_base = 0; 506 509 phys_addr_t start, end; 507 510 u64 idx; 508 511 512 + if (os_info_has_vm) 513 + old_identity_base = os_info_old_value(OS_INFO_IDENTITY_BASE); 509 514 for_each_physmem_range(idx, &oldmem_type, &start, &end) { 510 515 phdr->p_type = PT_LOAD; 511 516 phdr->p_vaddr = old_identity_base + start; ··· 519 520 phdr->p_align = PAGE_SIZE; 520 521 phdr++; 521 522 } 523 + } 524 + 525 + static bool os_info_has_vm(void) 526 + { 527 + return os_info_old_value(OS_INFO_KASLR_OFFSET); 522 528 } 523 529 524 530 /* ··· 570 566 return ptr; 571 567 } 572 568 573 - static size_t get_elfcorehdr_size(int mem_chunk_cnt) 569 + static size_t get_elfcorehdr_size(int phdr_count) 574 570 { 575 571 size_t size; 576 572 ··· 585 581 size += nt_vmcoreinfo_size(); 586 582 /* nt_final */ 587 583 size += sizeof(Elf64_Nhdr); 588 - /* PT_LOAD type program header for kernel text region */ 589 - size += sizeof(Elf64_Phdr); 590 584 /* PT_LOADS */ 591 - size += mem_chunk_cnt * sizeof(Elf64_Phdr); 585 + size += phdr_count * sizeof(Elf64_Phdr); 592 586 593 587 return size; 594 588 } ··· 597 595 int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) 598 596 { 599 597 Elf64_Phdr *phdr_notes, *phdr_loads, *phdr_text; 598 + int mem_chunk_cnt, phdr_text_cnt; 600 599 size_t alloc_size; 601 - int mem_chunk_cnt; 602 600 void *ptr, *hdr; 603 601 u64 hdr_off; 604 602 ··· 617 615 } 618 616 619 617 mem_chunk_cnt = get_mem_chunk_cnt(); 618 + phdr_text_cnt = os_info_has_vm() ? 1 : 0; 620 619 621 - alloc_size = get_elfcorehdr_size(mem_chunk_cnt); 620 + alloc_size = get_elfcorehdr_size(mem_chunk_cnt + phdr_text_cnt); 622 621 623 622 hdr = kzalloc(alloc_size, GFP_KERNEL); 624 623 625 - /* Without elfcorehdr /proc/vmcore cannot be created. Thus creating 624 + /* 625 + * Without elfcorehdr /proc/vmcore cannot be created. Thus creating 626 626 * a dump with this crash kernel will fail. Panic now to allow other 627 627 * dump mechanisms to take over. 628 628 */ ··· 632 628 panic("s390 kdump allocating elfcorehdr failed"); 633 629 634 630 /* Init elf header */ 635 - ptr = ehdr_init(hdr, mem_chunk_cnt); 631 + phdr_notes = ehdr_init(hdr, mem_chunk_cnt + phdr_text_cnt); 636 632 /* Init program headers */ 637 - phdr_notes = ptr; 638 - ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr)); 639 - phdr_text = ptr; 640 - ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr)); 641 - phdr_loads = ptr; 642 - ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt); 633 + if (phdr_text_cnt) { 634 + phdr_text = phdr_notes + 1; 635 + phdr_loads = phdr_text + 1; 636 + } else { 637 + phdr_loads = phdr_notes + 1; 638 + } 639 + ptr = PTR_ADD(phdr_loads, sizeof(Elf64_Phdr) * mem_chunk_cnt); 643 640 /* Init notes */ 644 641 hdr_off = PTR_DIFF(ptr, hdr); 645 642 ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off); 646 643 /* Init kernel text program header */ 647 - text_init(phdr_text); 644 + if (phdr_text_cnt) 645 + text_init(phdr_text); 648 646 /* Init loads */ 649 - loads_init(phdr_loads); 647 + loads_init(phdr_loads, phdr_text_cnt); 650 648 /* Finalize program headers */ 651 649 hdr_off = PTR_DIFF(ptr, hdr); 652 650 *addr = (unsigned long long) hdr;
+1
tools/testing/selftests/kvm/Makefile
··· 183 183 TEST_GEN_PROGS_s390x += s390x/tprot 184 184 TEST_GEN_PROGS_s390x += s390x/cmma_test 185 185 TEST_GEN_PROGS_s390x += s390x/debug_test 186 + TEST_GEN_PROGS_s390x += s390x/shared_zeropage_test 186 187 TEST_GEN_PROGS_s390x += demand_paging_test 187 188 TEST_GEN_PROGS_s390x += dirty_log_test 188 189 TEST_GEN_PROGS_s390x += guest_print_test
+111
tools/testing/selftests/kvm/s390x/shared_zeropage_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Test shared zeropage handling (with/without storage keys) 4 + * 5 + * Copyright (C) 2024, Red Hat, Inc. 6 + */ 7 + #include <sys/mman.h> 8 + 9 + #include <linux/fs.h> 10 + 11 + #include "test_util.h" 12 + #include "kvm_util.h" 13 + #include "kselftest.h" 14 + #include "ucall_common.h" 15 + 16 + static void set_storage_key(void *addr, uint8_t skey) 17 + { 18 + asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); 19 + } 20 + 21 + static void guest_code(void) 22 + { 23 + /* Issue some storage key instruction. */ 24 + set_storage_key((void *)0, 0x98); 25 + GUEST_DONE(); 26 + } 27 + 28 + /* 29 + * Returns 1 if the shared zeropage is mapped, 0 if something else is mapped. 30 + * Returns < 0 on error or if nothing is mapped. 31 + */ 32 + static int maps_shared_zeropage(int pagemap_fd, void *addr) 33 + { 34 + struct page_region region; 35 + struct pm_scan_arg arg = { 36 + .start = (uintptr_t)addr, 37 + .end = (uintptr_t)addr + 4096, 38 + .vec = (uintptr_t)&region, 39 + .vec_len = 1, 40 + .size = sizeof(struct pm_scan_arg), 41 + .category_mask = PAGE_IS_PFNZERO, 42 + .category_anyof_mask = PAGE_IS_PRESENT, 43 + .return_mask = PAGE_IS_PFNZERO, 44 + }; 45 + return ioctl(pagemap_fd, PAGEMAP_SCAN, &arg); 46 + } 47 + 48 + int main(int argc, char *argv[]) 49 + { 50 + char *mem, *page0, *page1, *page2, tmp; 51 + const size_t pagesize = getpagesize(); 52 + struct kvm_vcpu *vcpu; 53 + struct kvm_vm *vm; 54 + struct ucall uc; 55 + int pagemap_fd; 56 + 57 + ksft_print_header(); 58 + ksft_set_plan(3); 59 + 60 + /* 61 + * We'll use memory that is not mapped into the VM for simplicity. 62 + * Shared zeropages are enabled/disabled per-process. 63 + */ 64 + mem = mmap(0, 3 * pagesize, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); 65 + TEST_ASSERT(mem != MAP_FAILED, "mmap() failed"); 66 + 67 + /* Disable THP. Ignore errors on older kernels. */ 68 + madvise(mem, 3 * pagesize, MADV_NOHUGEPAGE); 69 + 70 + page0 = mem; 71 + page1 = page0 + pagesize; 72 + page2 = page1 + pagesize; 73 + 74 + /* Can we even detect shared zeropages? */ 75 + pagemap_fd = open("/proc/self/pagemap", O_RDONLY); 76 + TEST_REQUIRE(pagemap_fd >= 0); 77 + 78 + tmp = *page0; 79 + asm volatile("" : "+r" (tmp)); 80 + TEST_REQUIRE(maps_shared_zeropage(pagemap_fd, page0) == 1); 81 + 82 + vm = vm_create_with_one_vcpu(&vcpu, guest_code); 83 + 84 + /* Verify that we get the shared zeropage after VM creation. */ 85 + tmp = *page1; 86 + asm volatile("" : "+r" (tmp)); 87 + ksft_test_result(maps_shared_zeropage(pagemap_fd, page1) == 1, 88 + "Shared zeropages should be enabled\n"); 89 + 90 + /* 91 + * Let our VM execute a storage key instruction that should 92 + * unshare all shared zeropages. 93 + */ 94 + vcpu_run(vcpu); 95 + get_ucall(vcpu, &uc); 96 + TEST_ASSERT_EQ(uc.cmd, UCALL_DONE); 97 + 98 + /* Verify that we don't have a shared zeropage anymore. */ 99 + ksft_test_result(!maps_shared_zeropage(pagemap_fd, page1), 100 + "Shared zeropage should be gone\n"); 101 + 102 + /* Verify that we don't get any new shared zeropages. */ 103 + tmp = *page2; 104 + asm volatile("" : "+r" (tmp)); 105 + ksft_test_result(!maps_shared_zeropage(pagemap_fd, page2), 106 + "Shared zeropages should be disabled\n"); 107 + 108 + kvm_vm_free(vm); 109 + 110 + ksft_finished(); 111 + }