^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/crash_dump.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <xen/interface/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <xen/hvm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "mmu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #ifdef CONFIG_PROC_VMCORE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This function is used in two contexts:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * - the kdump kernel has to check whether a pfn of the crashed kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * was a ballooned page. vmcore is using this function to decide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * whether to access a pfn of the crashed kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - the kexec kernel has to check whether a pfn was ballooned by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * previous kernel. If the pfn is ballooned, handle it properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Returns 0 if the pfn is not backed by a RAM page, the caller may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * handle the pfn special in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static int xen_oldmem_pfn_is_ram(unsigned long pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct xen_hvm_get_mem_type a = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .domid = DOMID_SELF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .pfn = pfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int ram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) switch (a.mem_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) case HVMMEM_mmio_dm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ram = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case HVMMEM_ram_rw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) case HVMMEM_ram_ro:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ram = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return ram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static void xen_hvm_exit_mmap(struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct xen_hvm_pagetable_dying a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) a.domid = DOMID_SELF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) a.gpa = __pa(mm->pgd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) WARN_ON_ONCE(rc < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int is_pagetable_dying_supported(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct xen_hvm_pagetable_dying a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) a.domid = DOMID_SELF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) a.gpa = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void __init xen_hvm_init_mmu_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (is_pagetable_dying_supported())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pv_ops.mmu.exit_mmap = xen_hvm_exit_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #ifdef CONFIG_PROC_VMCORE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) WARN_ON(register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }