linux/arch/x86/kernel/cpu/mshyperv.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * HyperV  Detection code.
 *
 * Copyright (C) 2010, Novell, Inc.
 * Author : K. Y. Srinivasan <[email protected]>
 */

#include <linux/types.h>
#include <linux/time.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/hardirq.h>
#include <linux/efi.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kexec.h>
#include <linux/random.h>
#include <asm/processor.h>
#include <asm/hypervisor.h>
#include <asm/hyperv-tlfs.h>
#include <asm/mshyperv.h>
#include <asm/desc.h>
#include <asm/idtentry.h>
#include <asm/irq_regs.h>
#include <asm/i8259.h>
#include <asm/apic.h>
#include <asm/timer.h>
#include <asm/reboot.h>
#include <asm/nmi.h>
#include <clocksource/hyperv_timer.h>
#include <asm/numa.h>
#include <asm/svm.h>

/* Is Linux running as the root partition? */
bool hv_root_partition;
/* Is Linux running on nested Microsoft Hypervisor */
bool hv_nested;
struct ms_hyperv_info ms_hyperv;

/* Used in modules via hv_do_hypercall(): see arch/x86/include/asm/mshyperv.h */
bool hyperv_paravisor_present __ro_after_init;
EXPORT_SYMBOL_GPL();

#if IS_ENABLED(CONFIG_HYPERV)
static inline unsigned int hv_get_nested_msr(unsigned int reg)
{}

u64 hv_get_non_nested_msr(unsigned int reg)
{}
EXPORT_SYMBOL_GPL();

void hv_set_non_nested_msr(unsigned int reg, u64 value)
{}
EXPORT_SYMBOL_GPL();

u64 hv_get_msr(unsigned int reg)
{}
EXPORT_SYMBOL_GPL();

void hv_set_msr(unsigned int reg, u64 value)
{}
EXPORT_SYMBOL_GPL();

static void (*vmbus_handler)(void);
static void (*hv_stimer0_handler)(void);
static void (*hv_kexec_handler)(void);
static void (*hv_crash_handler)(struct pt_regs *regs);

DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
{}

void hv_setup_vmbus_handler(void (*handler)(void))
{}

void hv_remove_vmbus_handler(void)
{}

/*
 * Routines to do per-architecture handling of stimer0
 * interrupts when in Direct Mode
 */
DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_stimer0)
{}

/* For x86/x64, override weak placeholders in hyperv_timer.c */
void hv_setup_stimer0_handler(void (*handler)(void))
{}

void hv_remove_stimer0_handler(void)
{}

void hv_setup_kexec_handler(void (*handler)(void))
{}

void hv_remove_kexec_handler(void)
{}

void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
{}

void hv_remove_crash_handler(void)
{}

#ifdef CONFIG_KEXEC_CORE
static void hv_machine_shutdown(void)
{}
#endif /* CONFIG_KEXEC_CORE */

#ifdef CONFIG_CRASH_DUMP
static void hv_machine_crash_shutdown(struct pt_regs *regs)
{}
#endif /* CONFIG_CRASH_DUMP */
#endif /* CONFIG_HYPERV */

static uint32_t  __init ms_hyperv_platform(void)
{}

#ifdef CONFIG_X86_LOCAL_APIC
/*
 * Prior to WS2016 Debug-VM sends NMIs to all CPUs which makes
 * it difficult to process CHANNELMSG_UNLOAD in case of crash. Handle
 * unknown NMI on the first CPU which gets it.
 */
static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
{}
#endif

static unsigned long hv_get_tsc_khz(void)
{}

#if defined(CONFIG_SMP) && IS_ENABLED(CONFIG_HYPERV)
static void __init hv_smp_prepare_boot_cpu(void)
{}

static void __init hv_smp_prepare_cpus(unsigned int max_cpus)
{}
#endif

/*
 * When a fully enlightened TDX VM runs on Hyper-V, the firmware sets the
 * HW_REDUCED flag: refer to acpi_tb_create_local_fadt(). Consequently ttyS0
 * interrupts can't work because request_irq() -> ... -> irq_to_desc() returns
 * NULL for ttyS0. This happens because mp_config_acpi_legacy_irqs() sees a
 * nr_legacy_irqs() of 0, so it doesn't initialize the array 'mp_irqs[]', and
 * later setup_IO_APIC_irqs() -> find_irq_entry() fails to find the legacy irqs
 * from the array and hence doesn't create the necessary irq description info.
 *
 * Clone arch/x86/kernel/acpi/boot.c: acpi_generic_reduced_hw_init() here,
 * except don't change 'legacy_pic', which keeps its default value
 * 'default_legacy_pic'. This way, mp_config_acpi_legacy_irqs() sees a non-zero
 * nr_legacy_irqs() and eventually serial console interrupts works properly.
 */
static void __init reduced_hw_init(void)
{}

int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
{}

static void __init ms_hyperv_init_platform(void)
{}

static bool __init ms_hyperv_x2apic_available(void)
{}

/*
 * If ms_hyperv_msi_ext_dest_id() returns true, hyperv_prepare_irq_remapping()
 * returns -ENODEV and the Hyper-V IOMMU driver is not used; instead, the
 * generic support of the 15-bit APIC ID is used: see __irq_msi_compose_msg().
 *
 * Note: for a VM on Hyper-V, the I/O-APIC is the only device which
 * (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)
{}

#ifdef CONFIG_AMD_MEM_ENCRYPT
static void hv_sev_es_hcall_prepare(struct ghcb *ghcb, struct pt_regs *regs)
{}

static bool hv_sev_es_hcall_finish(struct ghcb *ghcb, struct pt_regs *regs)
{}
#endif

const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv =;