summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-07 10:29:54 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-07 10:29:54 -0700
commit86782c16a81f8232c13c1509fd3295bd97d185b0 (patch)
tree7c705761a7a6ae08fb0741adc703dec6bed1de7d
parent66d64899eae85dc9b96c5433933787cdcd9b21e4 (diff)
parent16cbec24897624051b324aa3a85859c38ca65fde (diff)
Merge tag 'hyperv-fixes-signed-20260406' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull Hyper-V fixes from Wei Liu: - Two fixes for Hyper-V PCI driver (Long Li, Sahil Chandna) - Fix an infinite loop issue in MSHV driver (Stanislav Kinsburskii) * tag 'hyperv-fixes-signed-20260406' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: mshv: Fix infinite fault loop on permission-denied GPA intercepts PCI: hv: Fix double ida_free in hv_pci_probe error path PCI: hv: Set default NUMA node to 0 for devices without affinity info
-rw-r--r--drivers/hv/mshv_root_main.c15
-rw-r--r--drivers/pci/controller/pci-hyperv.c12
-rw-r--r--include/hyperv/hvgdk_mini.h6
-rw-r--r--include/hyperv/hvhdk.h4
4 files changed, 29 insertions, 8 deletions
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 6f42423f7faa..c8e5523a52b6 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -630,7 +630,7 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
{
struct mshv_partition *p = vp->vp_partition;
struct mshv_mem_region *region;
- bool ret;
+ bool ret = false;
u64 gfn;
#if defined(CONFIG_X86_64)
struct hv_x64_memory_intercept_message *msg =
@@ -641,6 +641,8 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
(struct hv_arm64_memory_intercept_message *)
vp->vp_intercept_msg_page->u.payload;
#endif
+ enum hv_intercept_access_type access_type =
+ msg->header.intercept_access_type;
gfn = HVPFN_DOWN(msg->guest_physical_address);
@@ -648,12 +650,19 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
if (!region)
return false;
+ if (access_type == HV_INTERCEPT_ACCESS_WRITE &&
+ !(region->hv_map_flags & HV_MAP_GPA_WRITABLE))
+ goto put_region;
+
+ if (access_type == HV_INTERCEPT_ACCESS_EXECUTE &&
+ !(region->hv_map_flags & HV_MAP_GPA_EXECUTABLE))
+ goto put_region;
+
/* Only movable memory ranges are supported for GPA intercepts */
if (region->mreg_type == MSHV_REGION_TYPE_MEM_MOVABLE)
ret = mshv_region_handle_gfn_fault(region, gfn);
- else
- ret = false;
+put_region:
mshv_region_put(region);
return ret;
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 2c7a406b4ba8..49c0a2d51162 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -2485,6 +2485,14 @@ static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
if (!hv_dev)
continue;
+ /*
+ * If the Hyper-V host doesn't provide a NUMA node for the
+ * device, default to node 0. With NUMA_NO_NODE the kernel
+ * may spread work across NUMA nodes, which degrades
+ * performance on Hyper-V.
+ */
+ set_dev_node(&dev->dev, 0);
+
if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY &&
hv_dev->desc.virtual_numa_node < num_possible_nodes())
/*
@@ -3778,7 +3786,7 @@ static int hv_pci_probe(struct hv_device *hdev,
hbus->bridge->domain_nr);
if (!hbus->wq) {
ret = -ENOMEM;
- goto free_dom;
+ goto free_bus;
}
hdev->channel->next_request_id_callback = vmbus_next_request_id;
@@ -3874,8 +3882,6 @@ close:
vmbus_close(hdev->channel);
destroy_wq:
destroy_workqueue(hbus->wq);
-free_dom:
- pci_bus_release_emul_domain_nr(hbus->bridge->domain_nr);
free_bus:
kfree(hbus);
return ret;
diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
index 1823a290a7b7..f9600f87186a 100644
--- a/include/hyperv/hvgdk_mini.h
+++ b/include/hyperv/hvgdk_mini.h
@@ -1533,4 +1533,10 @@ struct hv_mmio_write_input {
u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH];
} __packed;
+enum hv_intercept_access_type {
+ HV_INTERCEPT_ACCESS_READ = 0,
+ HV_INTERCEPT_ACCESS_WRITE = 1,
+ HV_INTERCEPT_ACCESS_EXECUTE = 2
+};
+
#endif /* _HV_HVGDK_MINI_H */
diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
index 245f3db53bf1..5e83d3714966 100644
--- a/include/hyperv/hvhdk.h
+++ b/include/hyperv/hvhdk.h
@@ -779,7 +779,7 @@ struct hv_x64_intercept_message_header {
u32 vp_index;
u8 instruction_length:4;
u8 cr8:4; /* Only set for exo partitions */
- u8 intercept_access_type;
+ u8 intercept_access_type; /* enum hv_intercept_access_type */
union hv_x64_vp_execution_state execution_state;
struct hv_x64_segment_register cs_segment;
u64 rip;
@@ -825,7 +825,7 @@ union hv_arm64_vp_execution_state {
struct hv_arm64_intercept_message_header {
u32 vp_index;
u8 instruction_length;
- u8 intercept_access_type;
+ u8 intercept_access_type; /* enum hv_intercept_access_type */
union hv_arm64_vp_execution_state execution_state;
u64 pc;
u64 cpsr;