Commit 7d621599 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hyperv-next-signed-20221208' of...

Merge tag 'hyperv-next-signed-20221208' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv updates from Wei Liu:

 - Drop unregister syscore from hyperv_cleanup to avoid hang (Gaurav
   Kohli)

 - Clean up panic path for Hyper-V framebuffer (Guilherme G. Piccoli)

 - Allow IRQ remapping to work without x2apic (Nuno Das Neves)

 - Fix comments (Olaf Hering)

 - Expand hv_vp_assist_page definition (Saurabh Sengar)

 - Improvement to page reporting (Shradha Gupta)

 - Make sure TSC clocksource works when Linux runs as the root partition
   (Stanislav Kinsburskiy)

* tag 'hyperv-next-signed-20221208' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
  x86/hyperv: Remove unregister syscore call from Hyper-V cleanup
  iommu/hyper-v: Allow hyperv irq remapping without x2apic
  clocksource: hyper-v: Add TSC page support for root partition
  clocksource: hyper-v: Use TSC PFN getter to map vvar page
  clocksource: hyper-v: Introduce TSC PFN getter
  clocksource: hyper-v: Introduce a pointer to TSC page
  x86/hyperv: Expand definition of struct hv_vp_assist_page
  PCI: hv: update comment in x86 specific hv_arch_irq_unmask
  hv: fix comment typo in vmbus_channel/low_latency
  drivers: hv, hyperv_fb: Untangle and refactor Hyper-V panic notifiers
  video: hyperv_fb: Avoid taking busy spinlock on panic path
  hv_balloon: Add support for configurable order free page reporting
  mm/page_reporting: Add checks for page_reporting_order param
parents 43686598 32c97d98
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -210,11 +210,10 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
					pgprot_decrypted(vma->vm_page_prot));
		}
	} else if (sym_offset == image->sym_hvclock_page) {
		struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page();
		pfn = hv_get_tsc_pfn();

		if (tsc_pg && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
			return vmf_insert_pfn(vma, vmf->address,
					virt_to_phys(tsc_pg) >> PAGE_SHIFT);
		if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
			return vmf_insert_pfn(vma, vmf->address, pfn);
	} else if (sym_offset == image->sym_timens_page) {
		struct page *timens_page = find_timens_vvar_page(vma);

+2 −2
Original line number Diff line number Diff line
@@ -462,6 +462,8 @@ void __init hyperv_init(void)
		BUG_ON(!src);
		memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE);
		memunmap(src);

		hv_remap_tsc_clocksource();
	} else {
		hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
@@ -535,8 +537,6 @@ void hyperv_cleanup(void)
	union hv_x64_msr_hypercall_contents hypercall_msr;
	union hv_reference_tsc_msr tsc_msr;

	unregister_syscore_ops(&hv_syscore_ops);

	/* Reset our OS id */
	wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
	hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
+10 −1
Original line number Diff line number Diff line
@@ -374,11 +374,20 @@ struct hv_nested_enlightenments_control {
struct hv_vp_assist_page {
	__u32 apic_assist;
	__u32 reserved1;
	__u64 vtl_control[3];
	__u32 vtl_entry_reason;
	__u32 vtl_reserved;
	__u64 vtl_ret_x64rax;
	__u64 vtl_ret_x64rcx;
	struct hv_nested_enlightenments_control nested_control;
	__u8 enlighten_vmentry;
	__u8 reserved2[7];
	__u64 current_nested_vmcs;
	__u8 synthetic_time_unhalted_timer_expired;
	__u8 reserved3[7];
	__u8 virtualization_fault_information[40];
	__u8 reserved4[8];
	__u8 intercept_message[256];
	__u8 vtl_ret_actions[256];
} __packed;

struct hv_enlightened_vmcs {
+6 −0
Original line number Diff line number Diff line
@@ -475,6 +475,12 @@ static bool __init ms_hyperv_x2apic_available(void)
 * (logically) generates MSIs directly to the system APIC irq domain.
 * There is no HPET, and PCI MSI/MSI-X interrupts are remapped by the
 * pci-hyperv host bridge.
 *
 * Note: for a Hyper-V root partition, this will always return false.
 * The hypervisor doesn't expose these HYPERV_CPUID_VIRT_STACK_* cpuids by
 * default, they are implemented as intercepts by the Windows Hyper-V stack.
 * Even a nested root partition (L2 root) will not get them because the
 * nested (L1) hypervisor filters them out.
 */
static bool __init ms_hyperv_msi_ext_dest_id(void)
{
+47 −14
Original line number Diff line number Diff line
@@ -367,9 +367,18 @@ static union {
	u8 reserved[PAGE_SIZE];
} tsc_pg __aligned(PAGE_SIZE);

static struct ms_hyperv_tsc_page *tsc_page = &tsc_pg.page;
static unsigned long tsc_pfn;

unsigned long hv_get_tsc_pfn(void)
{
	return tsc_pfn;
}
EXPORT_SYMBOL_GPL(hv_get_tsc_pfn);

struct ms_hyperv_tsc_page *hv_get_tsc_page(void)
{
	return &tsc_pg.page;
	return tsc_page;
}
EXPORT_SYMBOL_GPL(hv_get_tsc_page);

@@ -407,13 +416,12 @@ static void suspend_hv_clock_tsc(struct clocksource *arg)

static void resume_hv_clock_tsc(struct clocksource *arg)
{
	phys_addr_t phys_addr = virt_to_phys(&tsc_pg);
	union hv_reference_tsc_msr tsc_msr;

	/* Re-enable the TSC page */
	tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
	tsc_msr.enable = 1;
	tsc_msr.pfn = HVPFN_DOWN(phys_addr);
	tsc_msr.pfn = tsc_pfn;
	hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
}

@@ -497,14 +505,10 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
static bool __init hv_init_tsc_clocksource(void)
{
	union hv_reference_tsc_msr tsc_msr;
	phys_addr_t	phys_addr;

	if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
		return false;

	if (hv_root_partition)
		return false;

	/*
	 * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly
	 * handles frequency and offset changes due to live migration,
@@ -522,18 +526,30 @@ static bool __init hv_init_tsc_clocksource(void)
	}

	hv_read_reference_counter = read_hv_clock_tsc;
	phys_addr = virt_to_phys(hv_get_tsc_page());

	/*
	 * The Hyper-V TLFS specifies to preserve the value of reserved
	 * bits in registers. So read the existing value, preserve the
	 * low order 12 bits, and add in the guest physical address
	 * (which already has at least the low 12 bits set to zero since
	 * it is page aligned). Also set the "enable" bit, which is bit 0.
	 * TSC page mapping works differently in root compared to guest.
	 * - In guest partition the guest PFN has to be passed to the
	 *   hypervisor.
	 * - In root partition it's other way around: it has to map the PFN
	 *   provided by the hypervisor.
	 *   But it can't be mapped right here as it's too early and MMU isn't
	 *   ready yet. So, we only set the enable bit here and will remap the
	 *   page later in hv_remap_tsc_clocksource().
	 *
	 * It worth mentioning, that TSC clocksource read function
	 * (read_hv_clock_tsc) has a MSR-based fallback mechanism, used when
	 * TSC page is zeroed (which is the case until the PFN is remapped) and
	 * thus TSC clocksource will work even without the real TSC page
	 * mapped.
	 */
	tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
	if (hv_root_partition)
		tsc_pfn = tsc_msr.pfn;
	else
		tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page));
	tsc_msr.enable = 1;
	tsc_msr.pfn = HVPFN_DOWN(phys_addr);
	tsc_msr.pfn = tsc_pfn;
	hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);

	clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
@@ -566,3 +582,20 @@ void __init hv_init_clocksource(void)
	hv_sched_clock_offset = hv_read_reference_counter();
	hv_setup_sched_clock(read_hv_sched_clock_msr);
}

void __init hv_remap_tsc_clocksource(void)
{
	if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
		return;

	if (!hv_root_partition) {
		WARN(1, "%s: attempt to remap TSC page in guest partition\n",
		     __func__);
		return;
	}

	tsc_page = memremap(tsc_pfn << HV_HYP_PAGE_SHIFT, sizeof(tsc_pg),
			    MEMREMAP_WB);
	if (!tsc_page)
		pr_err("Failed to remap Hyper-V TSC page.\n");
}
Loading