mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'hyperv-next-signed-20251006' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv updates from Wei Liu: - Unify guest entry code for KVM and MSHV (Sean Christopherson) - Switch Hyper-V MSI domain to use msi_create_parent_irq_domain() (Nam Cao) - Add CONFIG_HYPERV_VMBUS and limit the semantics of CONFIG_HYPERV (Mukesh Rathor) - Add kexec/kdump support on Azure CVMs (Vitaly Kuznetsov) - Deprecate hyperv_fb in favor of Hyper-V DRM driver (Prasanna Kumar T S M) - Miscellaneous enhancements, fixes and cleanups (Abhishek Tiwari, Alok Tiwari, Nuno Das Neves, Wei Liu, Roman Kisel, Michael Kelley) * tag 'hyperv-next-signed-20251006' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: hyperv: Remove the spurious null directive line MAINTAINERS: Mark hyperv_fb driver Obsolete fbdev/hyperv_fb: deprecate this in favor of Hyper-V DRM driver Drivers: hv: Make CONFIG_HYPERV bool Drivers: hv: Add CONFIG_HYPERV_VMBUS option Drivers: hv: vmbus: Fix typos in vmbus_drv.c Drivers: hv: vmbus: Fix sysfs output format for ring buffer index Drivers: hv: vmbus: Clean up sscanf format specifier in target_cpu_store() x86/hyperv: Switch to msi_create_parent_irq_domain() mshv: Use common "entry virt" APIs to do work in root before running guest entry: Rename "kvm" entry code assets to "virt" to genericize APIs entry/kvm: KVM: Move KVM details related to signal/-EINTR into KVM proper mshv: Handle NEED_RESCHED_LAZY before transferring to guest x86/hyperv: Add kexec/kdump support on Azure CVMs Drivers: hv: Simplify data structures for VMBus channel close message Drivers: hv: util: Cosmetic changes for hv_utils_transport.c mshv: Add support for a new parent partition configuration clocksource: hyper-v: Skip unnecessary checks for the root partition hyperv: Add missing field to hv_output_map_device_interrupt
This commit is contained in:
+11
-2
@@ -10390,7 +10390,7 @@ L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/entry
|
||||
F: include/linux/entry-common.h
|
||||
F: include/linux/entry-kvm.h
|
||||
F: include/linux/entry-virt.h
|
||||
F: include/linux/irq-entry-common.h
|
||||
F: kernel/entry/
|
||||
|
||||
@@ -11604,7 +11604,6 @@ F: drivers/pci/controller/pci-hyperv-intf.c
|
||||
F: drivers/pci/controller/pci-hyperv.c
|
||||
F: drivers/scsi/storvsc_drv.c
|
||||
F: drivers/uio/uio_hv_generic.c
|
||||
F: drivers/video/fbdev/hyperv_fb.c
|
||||
F: include/asm-generic/mshyperv.h
|
||||
F: include/clocksource/hyperv_timer.h
|
||||
F: include/hyperv/hvgdk.h
|
||||
@@ -11618,6 +11617,16 @@ F: include/uapi/linux/hyperv.h
|
||||
F: net/vmw_vsock/hyperv_transport.c
|
||||
F: tools/hv/
|
||||
|
||||
HYPER-V FRAMEBUFFER DRIVER
|
||||
M: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
M: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
M: Wei Liu <wei.liu@kernel.org>
|
||||
M: Dexuan Cui <decui@microsoft.com>
|
||||
L: linux-hyperv@vger.kernel.org
|
||||
S: Obsolete
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
|
||||
F: drivers/video/fbdev/hyperv_fb.c
|
||||
|
||||
HYPERBUS SUPPORT
|
||||
M: Vignesh Raghavendra <vigneshr@ti.com>
|
||||
R: Tudor Ambarus <tudor.ambarus@linaro.org>
|
||||
|
||||
@@ -25,7 +25,7 @@ menuconfig KVM
|
||||
select HAVE_KVM_CPU_RELAX_INTERCEPT
|
||||
select KVM_MMIO
|
||||
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
|
||||
select KVM_XFER_TO_GUEST_WORK
|
||||
select VIRT_XFER_TO_GUEST_WORK
|
||||
select KVM_VFIO
|
||||
select HAVE_KVM_DIRTY_RING_ACQ_REL
|
||||
select NEED_KVM_DIRTY_RING_WITH_BITMAP
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/entry-kvm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kvm_host.h>
|
||||
@@ -1183,7 +1182,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
||||
/*
|
||||
* Check conditions before entering the guest
|
||||
*/
|
||||
ret = xfer_to_guest_mode_handle_work(vcpu);
|
||||
ret = kvm_xfer_to_guest_mode_handle_work(vcpu);
|
||||
if (!ret)
|
||||
ret = 1;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ config KVM
|
||||
select KVM_GENERIC_HARDWARE_ENABLING
|
||||
select KVM_GENERIC_MMU_NOTIFIER
|
||||
select KVM_MMIO
|
||||
select KVM_XFER_TO_GUEST_WORK
|
||||
select VIRT_XFER_TO_GUEST_WORK
|
||||
select SCHED_INFO
|
||||
select GUEST_PERF_EVENTS if PERF_EVENTS
|
||||
help
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/entry-kvm.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/lbt.h>
|
||||
#include <asm/loongarch.h>
|
||||
@@ -251,7 +250,7 @@ static int kvm_enter_guest_check(struct kvm_vcpu *vcpu)
|
||||
/*
|
||||
* Check conditions before entering the guest
|
||||
*/
|
||||
ret = xfer_to_guest_mode_handle_work(vcpu);
|
||||
ret = kvm_xfer_to_guest_mode_handle_work(vcpu);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ config KVM
|
||||
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
|
||||
select KVM_GENERIC_HARDWARE_ENABLING
|
||||
select KVM_MMIO
|
||||
select KVM_XFER_TO_GUEST_WORK
|
||||
select VIRT_XFER_TO_GUEST_WORK
|
||||
select KVM_GENERIC_MMU_NOTIFIER
|
||||
select SCHED_INFO
|
||||
select GUEST_PERF_EVENTS if PERF_EVENTS
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/entry-kvm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kdebug.h>
|
||||
@@ -911,7 +910,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
||||
run->exit_reason = KVM_EXIT_UNKNOWN;
|
||||
while (ret > 0) {
|
||||
/* Check conditions before entering the guest */
|
||||
ret = xfer_to_guest_mode_handle_work(vcpu);
|
||||
ret = kvm_xfer_to_guest_mode_handle_work(vcpu);
|
||||
if (ret)
|
||||
continue;
|
||||
ret = 1;
|
||||
|
||||
+76
-35
@@ -11,6 +11,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/irqchip/irq-msi-lib.h>
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
static int hv_map_interrupt(union hv_device_id device_id, bool level,
|
||||
@@ -289,59 +290,99 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
|
||||
(void)hv_unmap_msi_interrupt(dev, &old_entry);
|
||||
}
|
||||
|
||||
static void hv_msi_free_irq(struct irq_domain *domain,
|
||||
struct msi_domain_info *info, unsigned int virq)
|
||||
{
|
||||
struct irq_data *irqd = irq_get_irq_data(virq);
|
||||
struct msi_desc *desc;
|
||||
|
||||
if (!irqd)
|
||||
return;
|
||||
|
||||
desc = irq_data_get_msi_desc(irqd);
|
||||
if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev)))
|
||||
return;
|
||||
|
||||
hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd);
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
|
||||
* which implement the MSI or MSI-X Capability Structure.
|
||||
*/
|
||||
static struct irq_chip hv_pci_msi_controller = {
|
||||
.name = "HV-PCI-MSI",
|
||||
.irq_unmask = pci_msi_unmask_irq,
|
||||
.irq_mask = pci_msi_mask_irq,
|
||||
.irq_ack = irq_chip_ack_parent,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_compose_msi_msg = hv_irq_compose_msi_msg,
|
||||
.irq_set_affinity = msi_domain_set_affinity,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED,
|
||||
.irq_set_affinity = irq_chip_set_affinity_parent,
|
||||
};
|
||||
|
||||
static struct msi_domain_ops pci_msi_domain_ops = {
|
||||
.msi_free = hv_msi_free_irq,
|
||||
.msi_prepare = pci_msi_prepare,
|
||||
static bool hv_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
|
||||
struct irq_domain *real_parent, struct msi_domain_info *info)
|
||||
{
|
||||
struct irq_chip *chip = info->chip;
|
||||
|
||||
if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
|
||||
return false;
|
||||
|
||||
chip->flags |= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED;
|
||||
|
||||
info->ops->msi_prepare = pci_msi_prepare;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define HV_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX)
|
||||
#define HV_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS)
|
||||
|
||||
static struct msi_parent_ops hv_msi_parent_ops = {
|
||||
.supported_flags = HV_MSI_FLAGS_SUPPORTED,
|
||||
.required_flags = HV_MSI_FLAGS_REQUIRED,
|
||||
.bus_select_token = DOMAIN_BUS_NEXUS,
|
||||
.bus_select_mask = MATCH_PCI_MSI,
|
||||
.chip_flags = MSI_CHIP_FLAG_SET_ACK,
|
||||
.prefix = "HV-",
|
||||
.init_dev_msi_info = hv_init_dev_msi_info,
|
||||
};
|
||||
|
||||
static struct msi_domain_info hv_pci_msi_domain_info = {
|
||||
.flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
||||
MSI_FLAG_PCI_MSIX,
|
||||
.ops = &pci_msi_domain_ops,
|
||||
.chip = &hv_pci_msi_controller,
|
||||
.handler = handle_edge_irq,
|
||||
.handler_name = "edge",
|
||||
static int hv_msi_domain_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs,
|
||||
void *arg)
|
||||
{
|
||||
/*
|
||||
* TODO: The allocation bits of hv_irq_compose_msi_msg(), i.e. everything except
|
||||
* entry_to_msi_msg() should be in here.
|
||||
*/
|
||||
|
||||
int ret;
|
||||
|
||||
ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (int i = 0; i < nr_irqs; ++i) {
|
||||
irq_domain_set_info(d, virq + i, 0, &hv_pci_msi_controller, NULL,
|
||||
handle_edge_irq, NULL, "edge");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hv_msi_domain_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs)
|
||||
{
|
||||
for (int i = 0; i < nr_irqs; ++i) {
|
||||
struct irq_data *irqd = irq_domain_get_irq_data(d, virq);
|
||||
struct msi_desc *desc;
|
||||
|
||||
desc = irq_data_get_msi_desc(irqd);
|
||||
if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev)))
|
||||
continue;
|
||||
|
||||
hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd);
|
||||
}
|
||||
irq_domain_free_irqs_top(d, virq, nr_irqs);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops hv_msi_domain_ops = {
|
||||
.select = msi_lib_irq_domain_select,
|
||||
.alloc = hv_msi_domain_alloc,
|
||||
.free = hv_msi_domain_free,
|
||||
};
|
||||
|
||||
struct irq_domain * __init hv_create_pci_msi_domain(void)
|
||||
{
|
||||
struct irq_domain *d = NULL;
|
||||
struct fwnode_handle *fn;
|
||||
|
||||
fn = irq_domain_alloc_named_fwnode("HV-PCI-MSI");
|
||||
if (fn)
|
||||
d = pci_msi_create_irq_domain(fn, &hv_pci_msi_domain_info, x86_vector_domain);
|
||||
struct irq_domain_info info = {
|
||||
.fwnode = irq_domain_alloc_named_fwnode("HV-PCI-MSI"),
|
||||
.ops = &hv_msi_domain_ops,
|
||||
.parent = x86_vector_domain,
|
||||
};
|
||||
|
||||
if (info.fwnode)
|
||||
d = msi_create_parent_irq_domain(&info, &hv_msi_parent_ops);
|
||||
|
||||
/* No point in going further if we can't get an irq domain */
|
||||
BUG_ON(!d);
|
||||
|
||||
+210
-1
@@ -462,6 +462,195 @@ void hv_ivm_msr_read(u64 msr, u64 *value)
|
||||
hv_ghcb_msr_read(msr, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep track of the PFN regions which were shared with the host. The access
|
||||
* must be revoked upon kexec/kdump (see hv_ivm_clear_host_access()).
|
||||
*/
|
||||
struct hv_enc_pfn_region {
|
||||
struct list_head list;
|
||||
u64 pfn;
|
||||
int count;
|
||||
};
|
||||
|
||||
static LIST_HEAD(hv_list_enc);
|
||||
static DEFINE_RAW_SPINLOCK(hv_list_enc_lock);
|
||||
|
||||
static int hv_list_enc_add(const u64 *pfn_list, int count)
|
||||
{
|
||||
struct hv_enc_pfn_region *ent;
|
||||
unsigned long flags;
|
||||
u64 pfn;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
pfn = pfn_list[i];
|
||||
|
||||
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||
/* Check if the PFN already exists in some region first */
|
||||
list_for_each_entry(ent, &hv_list_enc, list) {
|
||||
if ((ent->pfn <= pfn) && (ent->pfn + ent->count - 1 >= pfn))
|
||||
/* Nothing to do - pfn is already in the list */
|
||||
goto unlock_done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the PFN is adjacent to an existing region. Growing
|
||||
* a region can make it adjacent to another one but merging is
|
||||
* not (yet) implemented for simplicity. A PFN cannot be added
|
||||
* to two regions to keep the logic in hv_list_enc_remove()
|
||||
* correct.
|
||||
*/
|
||||
list_for_each_entry(ent, &hv_list_enc, list) {
|
||||
if (ent->pfn + ent->count == pfn) {
|
||||
/* Grow existing region up */
|
||||
ent->count++;
|
||||
goto unlock_done;
|
||||
} else if (pfn + 1 == ent->pfn) {
|
||||
/* Grow existing region down */
|
||||
ent->pfn--;
|
||||
ent->count++;
|
||||
goto unlock_done;
|
||||
}
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||
|
||||
/* No adjacent region found -- create a new one */
|
||||
ent = kzalloc(sizeof(struct hv_enc_pfn_region), GFP_KERNEL);
|
||||
if (!ent)
|
||||
return -ENOMEM;
|
||||
|
||||
ent->pfn = pfn;
|
||||
ent->count = 1;
|
||||
|
||||
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||
list_add(&ent->list, &hv_list_enc);
|
||||
|
||||
unlock_done:
|
||||
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hv_list_enc_remove(const u64 *pfn_list, int count)
|
||||
{
|
||||
struct hv_enc_pfn_region *ent, *t;
|
||||
struct hv_enc_pfn_region new_region;
|
||||
unsigned long flags;
|
||||
u64 pfn;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
pfn = pfn_list[i];
|
||||
|
||||
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||
list_for_each_entry_safe(ent, t, &hv_list_enc, list) {
|
||||
if (pfn == ent->pfn + ent->count - 1) {
|
||||
/* Removing tail pfn */
|
||||
ent->count--;
|
||||
if (!ent->count) {
|
||||
list_del(&ent->list);
|
||||
kfree(ent);
|
||||
}
|
||||
goto unlock_done;
|
||||
} else if (pfn == ent->pfn) {
|
||||
/* Removing head pfn */
|
||||
ent->count--;
|
||||
ent->pfn++;
|
||||
if (!ent->count) {
|
||||
list_del(&ent->list);
|
||||
kfree(ent);
|
||||
}
|
||||
goto unlock_done;
|
||||
} else if (pfn > ent->pfn && pfn < ent->pfn + ent->count - 1) {
|
||||
/*
|
||||
* Removing a pfn in the middle. Cut off the tail
|
||||
* of the existing region and create a template for
|
||||
* the new one.
|
||||
*/
|
||||
new_region.pfn = pfn + 1;
|
||||
new_region.count = ent->count - (pfn - ent->pfn + 1);
|
||||
ent->count = pfn - ent->pfn;
|
||||
goto unlock_split;
|
||||
}
|
||||
|
||||
}
|
||||
unlock_done:
|
||||
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||
continue;
|
||||
|
||||
unlock_split:
|
||||
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||
|
||||
ent = kzalloc(sizeof(struct hv_enc_pfn_region), GFP_KERNEL);
|
||||
if (!ent)
|
||||
return -ENOMEM;
|
||||
|
||||
ent->pfn = new_region.pfn;
|
||||
ent->count = new_region.count;
|
||||
|
||||
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||
list_add(&ent->list, &hv_list_enc);
|
||||
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Stop new private<->shared conversions */
|
||||
static void hv_vtom_kexec_begin(void)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Crash kernel reaches here with interrupts disabled: can't wait for
|
||||
* conversions to finish.
|
||||
*
|
||||
* If race happened, just report and proceed.
|
||||
*/
|
||||
if (!set_memory_enc_stop_conversion())
|
||||
pr_warn("Failed to stop shared<->private conversions\n");
|
||||
}
|
||||
|
||||
static void hv_vtom_kexec_finish(void)
|
||||
{
|
||||
struct hv_gpa_range_for_visibility *input;
|
||||
struct hv_enc_pfn_region *ent;
|
||||
unsigned long flags;
|
||||
u64 hv_status;
|
||||
int cur, i;
|
||||
|
||||
local_irq_save(flags);
|
||||
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
|
||||
|
||||
if (unlikely(!input))
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(ent, &hv_list_enc, list) {
|
||||
for (i = 0, cur = 0; i < ent->count; i++) {
|
||||
input->gpa_page_list[cur] = ent->pfn + i;
|
||||
cur++;
|
||||
|
||||
if (cur == HV_MAX_MODIFY_GPA_REP_COUNT || i == ent->count - 1) {
|
||||
input->partition_id = HV_PARTITION_ID_SELF;
|
||||
input->host_visibility = VMBUS_PAGE_NOT_VISIBLE;
|
||||
input->reserved0 = 0;
|
||||
input->reserved1 = 0;
|
||||
hv_status = hv_do_rep_hypercall(
|
||||
HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY,
|
||||
cur, 0, input, NULL);
|
||||
WARN_ON_ONCE(!hv_result_success(hv_status));
|
||||
cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* hv_mark_gpa_visibility - Set pages visible to host via hvcall.
|
||||
*
|
||||
@@ -475,6 +664,7 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
|
||||
struct hv_gpa_range_for_visibility *input;
|
||||
u64 hv_status;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* no-op if partition isolation is not enabled */
|
||||
if (!hv_is_isolation_supported())
|
||||
@@ -486,6 +676,13 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (visibility == VMBUS_PAGE_NOT_VISIBLE)
|
||||
ret = hv_list_enc_remove(pfn, count);
|
||||
else
|
||||
ret = hv_list_enc_add(pfn, count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
local_irq_save(flags);
|
||||
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
|
||||
|
||||
@@ -506,8 +703,18 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
|
||||
|
||||
if (hv_result_success(hv_status))
|
||||
return 0;
|
||||
|
||||
if (visibility == VMBUS_PAGE_NOT_VISIBLE)
|
||||
ret = hv_list_enc_add(pfn, count);
|
||||
else
|
||||
return -EFAULT;
|
||||
ret = hv_list_enc_remove(pfn, count);
|
||||
/*
|
||||
* There's no good way to recover from -ENOMEM here, the accounting is
|
||||
* wrong either way.
|
||||
*/
|
||||
WARN_ON_ONCE(ret);
|
||||
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -669,6 +876,8 @@ void __init hv_vtom_init(void)
|
||||
x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required;
|
||||
x86_platform.guest.enc_status_change_prepare = hv_vtom_clear_present;
|
||||
x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility;
|
||||
x86_platform.guest.enc_kexec_begin = hv_vtom_kexec_begin;
|
||||
x86_platform.guest.enc_kexec_finish = hv_vtom_kexec_finish;
|
||||
|
||||
/* Set WB as the default cache mode. */
|
||||
guest_force_mtrr_state(NULL, 0, MTRR_TYPE_WRBACK);
|
||||
|
||||
@@ -565,6 +565,11 @@ static void __init ms_hyperv_init_platform(void)
|
||||
machine_ops.crash_shutdown = hv_machine_crash_shutdown;
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* HV_ACCESS_TSC_INVARIANT is always zero for the root partition. Root
|
||||
* partition doesn't need to write to synthetic MSR to enable invariant
|
||||
* TSC feature. It sees what the hardware provides.
|
||||
*/
|
||||
if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) {
|
||||
/*
|
||||
* Writing to synthetic MSR 0x40000118 updates/changes the
|
||||
@@ -636,8 +641,12 @@ static void __init ms_hyperv_init_platform(void)
|
||||
* TSC should be marked as unstable only after Hyper-V
|
||||
* clocksource has been initialized. This ensures that the
|
||||
* stability of the sched_clock is not altered.
|
||||
*
|
||||
* HV_ACCESS_TSC_INVARIANT is always zero for the root partition. No
|
||||
* need to check for it.
|
||||
*/
|
||||
if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT))
|
||||
if (!hv_root_partition() &&
|
||||
!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT))
|
||||
mark_tsc_unstable("running on Hyper-V");
|
||||
|
||||
hardlockup_detector_disable();
|
||||
|
||||
@@ -40,7 +40,7 @@ config KVM_X86
|
||||
select HAVE_KVM_MSI
|
||||
select HAVE_KVM_CPU_RELAX_INTERCEPT
|
||||
select HAVE_KVM_NO_POLL
|
||||
select KVM_XFER_TO_GUEST_WORK
|
||||
select VIRT_XFER_TO_GUEST_WORK
|
||||
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
|
||||
select KVM_VFIO
|
||||
select HAVE_KVM_PM_NOTIFIER if PM
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tboot.h>
|
||||
#include <linux/trace_events.h>
|
||||
#include <linux/entry-kvm.h>
|
||||
|
||||
#include <asm/apic.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
+1
-2
@@ -59,7 +59,6 @@
|
||||
#include <linux/sched/stat.h>
|
||||
#include <linux/sched/isolation.h>
|
||||
#include <linux/mem_encrypt.h>
|
||||
#include <linux/entry-kvm.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
@@ -11635,7 +11634,7 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
|
||||
|
||||
if (__xfer_to_guest_mode_work_pending()) {
|
||||
kvm_vcpu_srcu_read_unlock(vcpu);
|
||||
r = xfer_to_guest_mode_handle_work(vcpu);
|
||||
r = kvm_xfer_to_guest_mode_handle_work(vcpu);
|
||||
kvm_vcpu_srcu_read_lock(vcpu);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@ obj-$(CONFIG_SOUNDWIRE) += soundwire/
|
||||
|
||||
# Virtualization drivers
|
||||
obj-$(CONFIG_VIRT_DRIVERS) += virt/
|
||||
obj-$(subst m,y,$(CONFIG_HYPERV)) += hv/
|
||||
obj-$(CONFIG_HYPERV) += hv/
|
||||
|
||||
obj-$(CONFIG_PM_DEVFREQ) += devfreq/
|
||||
obj-$(CONFIG_EXTCON) += extcon/
|
||||
|
||||
@@ -549,14 +549,22 @@ static void __init hv_init_tsc_clocksource(void)
|
||||
union hv_reference_tsc_msr tsc_msr;
|
||||
|
||||
/*
|
||||
* When running as a guest partition:
|
||||
*
|
||||
* If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly
|
||||
* handles frequency and offset changes due to live migration,
|
||||
* pause/resume, and other VM management operations. So lower the
|
||||
* Hyper-V Reference TSC rating, causing the generic TSC to be used.
|
||||
* TSC_INVARIANT is not offered on ARM64, so the Hyper-V Reference
|
||||
* TSC will be preferred over the virtualized ARM64 arch counter.
|
||||
*
|
||||
* When running as the root partition:
|
||||
*
|
||||
* There is no HV_ACCESS_TSC_INVARIANT feature. Always lower the rating
|
||||
* of the Hyper-V Reference TSC.
|
||||
*/
|
||||
if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) {
|
||||
if ((ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) ||
|
||||
hv_root_partition()) {
|
||||
hyperv_cs_tsc.rating = 250;
|
||||
hyperv_cs_msr.rating = 245;
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ source "drivers/gpu/drm/tyr/Kconfig"
|
||||
|
||||
config DRM_HYPERV
|
||||
tristate "DRM Support for Hyper-V synthetic video device"
|
||||
depends on DRM && PCI && HYPERV
|
||||
depends on DRM && PCI && HYPERV_VMBUS
|
||||
select DRM_CLIENT_SELECTION
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_SHMEM_HELPER
|
||||
|
||||
+1
-1
@@ -1171,7 +1171,7 @@ config GREENASIA_FF
|
||||
|
||||
config HID_HYPERV_MOUSE
|
||||
tristate "Microsoft Hyper-V mouse driver"
|
||||
depends on HYPERV
|
||||
depends on HYPERV_VMBUS
|
||||
help
|
||||
Select this option to enable the Hyper-V mouse driver.
|
||||
|
||||
|
||||
+12
-3
@@ -3,13 +3,14 @@
|
||||
menu "Microsoft Hyper-V guest support"
|
||||
|
||||
config HYPERV
|
||||
tristate "Microsoft Hyper-V client drivers"
|
||||
bool "Microsoft Hyper-V core hypervisor support"
|
||||
depends on (X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
|
||||
|| (ARM64 && !CPU_BIG_ENDIAN)
|
||||
select PARAVIRT
|
||||
select X86_HV_CALLBACK_VECTOR if X86
|
||||
select OF_EARLY_FLATTREE if OF
|
||||
select SYSFB if EFI && !HYPERV_VTL_MODE
|
||||
select IRQ_MSI_LIB if X86
|
||||
help
|
||||
Select this option to run Linux as a Hyper-V client operating
|
||||
system.
|
||||
@@ -44,18 +45,25 @@ config HYPERV_TIMER
|
||||
|
||||
config HYPERV_UTILS
|
||||
tristate "Microsoft Hyper-V Utilities driver"
|
||||
depends on HYPERV && CONNECTOR && NLS
|
||||
depends on HYPERV_VMBUS && CONNECTOR && NLS
|
||||
depends on PTP_1588_CLOCK_OPTIONAL
|
||||
help
|
||||
Select this option to enable the Hyper-V Utilities.
|
||||
|
||||
config HYPERV_BALLOON
|
||||
tristate "Microsoft Hyper-V Balloon driver"
|
||||
depends on HYPERV
|
||||
depends on HYPERV_VMBUS
|
||||
select PAGE_REPORTING
|
||||
help
|
||||
Select this option to enable Hyper-V Balloon driver.
|
||||
|
||||
config HYPERV_VMBUS
|
||||
tristate "Microsoft Hyper-V VMBus driver"
|
||||
depends on HYPERV
|
||||
default HYPERV
|
||||
help
|
||||
Select this option to enable Hyper-V Vmbus driver.
|
||||
|
||||
config MSHV_ROOT
|
||||
tristate "Microsoft Hyper-V root partition support"
|
||||
depends on HYPERV && (X86_64 || ARM64)
|
||||
@@ -66,6 +74,7 @@ config MSHV_ROOT
|
||||
# no particular order, making it impossible to reassemble larger pages
|
||||
depends on PAGE_SIZE_4KB
|
||||
select EVENTFD
|
||||
select VIRT_XFER_TO_GUEST_WORK
|
||||
default n
|
||||
help
|
||||
Select this option to enable support for booting and running as root
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_HYPERV) += hv_vmbus.o
|
||||
obj-$(CONFIG_HYPERV_VMBUS) += hv_vmbus.o
|
||||
obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o
|
||||
obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o
|
||||
obj-$(CONFIG_MSHV_ROOT) += mshv_root.o
|
||||
@@ -16,5 +16,5 @@ mshv_root-y := mshv_root_main.o mshv_synic.o mshv_eventfd.o mshv_irq.o \
|
||||
mshv_root_hv_call.o mshv_portid_table.o
|
||||
|
||||
# Code that must be built-in
|
||||
obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o
|
||||
obj-$(CONFIG_HYPERV) += hv_common.o
|
||||
obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o mshv_common.o
|
||||
|
||||
@@ -925,7 +925,7 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
|
||||
|
||||
/* Send a closing message */
|
||||
|
||||
msg = &channel->close_msg.msg;
|
||||
msg = &channel->close_msg;
|
||||
|
||||
msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
|
||||
msg->child_relid = channel->offermsg.child_relid;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user