* Re: [PATCH v7 2/7] Drivers: hv: Centralize guest memory region destruction
From: Anirudh Rayabharam @ 2025-12-01 11:12 UTC (permalink / raw)
To: Stanislav Kinsburskii
Cc: kys, haiyangz, wei.liu, decui, linux-hyperv, linux-kernel
In-Reply-To: <176412293764.447063.2221992979416155779.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net>
On Wed, Nov 26, 2025 at 02:08:57AM +0000, Stanislav Kinsburskii wrote:
> Centralize guest memory region destruction to prevent resource leaks and
> inconsistent cleanup across unmap and partition destruction paths.
>
> Unify region removal, encrypted partition access recovery, and region
> invalidation to improve maintainability and reliability. Reduce code
> duplication and make future updates less error-prone by encapsulating
> cleanup logic in a single helper.
>
> Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> Reviewed-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> ---
> drivers/hv/mshv_root_main.c | 65 ++++++++++++++++++++++---------------------
> 1 file changed, 34 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index fec82619684a..ec18984c3f2d 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -1356,13 +1356,42 @@ mshv_map_user_memory(struct mshv_partition *partition,
> return ret;
> }
>
> +static void mshv_partition_destroy_region(struct mshv_mem_region *region)
> +{
> + struct mshv_partition *partition = region->partition;
> + u32 unmap_flags = 0;
> + int ret;
> +
> + hlist_del(®ion->hnode);
> +
> + if (mshv_partition_encrypted(partition)) {
> + ret = mshv_partition_region_share(region);
> + if (ret) {
> + pt_err(partition,
> + "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n",
> + ret);
> + return;
> + }
> + }
> +
> + if (region->flags.large_pages)
> + unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE;
> +
> + /* ignore unmap failures and continue as process may be exiting */
> + hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn,
> + region->nr_pages, unmap_flags);
> +
> + mshv_region_invalidate(region);
> +
> + vfree(region);
> +}
> +
> /* Called for unmapping both the guest ram and the mmio space */
> static long
> mshv_unmap_user_memory(struct mshv_partition *partition,
> struct mshv_user_mem_region mem)
> {
> struct mshv_mem_region *region;
> - u32 unmap_flags = 0;
>
> if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
> return -EINVAL;
> @@ -1377,18 +1406,8 @@ mshv_unmap_user_memory(struct mshv_partition *partition,
> region->nr_pages != HVPFN_DOWN(mem.size))
> return -EINVAL;
>
> - hlist_del(®ion->hnode);
> + mshv_partition_destroy_region(region);
>
> - if (region->flags.large_pages)
> - unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE;
> -
> - /* ignore unmap failures and continue as process may be exiting */
> - hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn,
> - region->nr_pages, unmap_flags);
> -
> - mshv_region_invalidate(region);
> -
> - vfree(region);
> return 0;
> }
>
> @@ -1724,8 +1743,8 @@ static void destroy_partition(struct mshv_partition *partition)
> {
> struct mshv_vp *vp;
> struct mshv_mem_region *region;
> - int i, ret;
> struct hlist_node *n;
> + int i;
>
> if (refcount_read(&partition->pt_ref_count)) {
> pt_err(partition,
> @@ -1789,25 +1808,9 @@ static void destroy_partition(struct mshv_partition *partition)
>
> remove_partition(partition);
>
> - /* Remove regions, regain access to the memory and unpin the pages */
> hlist_for_each_entry_safe(region, n, &partition->pt_mem_regions,
> - hnode) {
> - hlist_del(®ion->hnode);
> -
> - if (mshv_partition_encrypted(partition)) {
> - ret = mshv_partition_region_share(region);
> - if (ret) {
> - pt_err(partition,
> - "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n",
> - ret);
> - return;
> - }
> - }
> -
> - mshv_region_invalidate(region);
> -
> - vfree(region);
> - }
> + hnode)
> + mshv_partition_destroy_region(region);
>
> /* Withdraw and free all pages we deposited */
> hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id);
>
>
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply
* Re: [PATCH v7 3/7] Drivers: hv: Move region management to mshv_regions.c
From: Anirudh Rayabharam @ 2025-12-01 11:06 UTC (permalink / raw)
To: Stanislav Kinsburskii
Cc: kys, haiyangz, wei.liu, decui, linux-hyperv, linux-kernel
In-Reply-To: <176412294544.447063.14863746685758881018.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net>
On Wed, Nov 26, 2025 at 02:09:05AM +0000, Stanislav Kinsburskii wrote:
> Refactor memory region management functions from mshv_root_main.c into
> mshv_regions.c for better modularity and code organization.
>
> Adjust function calls and headers to use the new implementation. Improve
> maintainability and separation of concerns in the mshv_root module.
>
> Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> ---
> drivers/hv/Makefile | 2
> drivers/hv/mshv_regions.c | 175 +++++++++++++++++++++++++++++++++++++++++++
> drivers/hv/mshv_root.h | 10 ++
> drivers/hv/mshv_root_main.c | 176 +++----------------------------------------
> 4 files changed, 198 insertions(+), 165 deletions(-)
> create mode 100644 drivers/hv/mshv_regions.c
>
> diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
> index 58b8d07639f3..46d4f4f1b252 100644
> --- a/drivers/hv/Makefile
> +++ b/drivers/hv/Makefile
> @@ -14,7 +14,7 @@ hv_vmbus-y := vmbus_drv.o \
> hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o
> hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o
> 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
> + mshv_root_hv_call.o mshv_portid_table.o mshv_regions.o
> mshv_vtl-y := mshv_vtl_main.o
>
> # Code that must be built-in
> diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
> new file mode 100644
> index 000000000000..35b866670840
> --- /dev/null
> +++ b/drivers/hv/mshv_regions.c
How about mshv_mem_regions.c?
Nevertheless:
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply
* RE: [PATCH v6 0/3] Add support for clean shutdown with MSHV
From: Michael Kelley @ 2025-11-29 6:48 UTC (permalink / raw)
To: Praveen K Paladugu, kys@microsoft.com, haiyangz@microsoft.com,
wei.liu@kernel.org, decui@microsoft.com, tglx@linutronix.de,
mingo@redhat.com, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org, bp@alien8.de,
dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
arnd@arndb.de
Cc: anbelski@linux.microsoft.com,
easwar.hariharan@linux.microsoft.com,
nunodasneves@linux.microsoft.com,
skinsburskii@linux.microsoft.com
In-Reply-To: <20251126215013.11549-1-prapal@linux.microsoft.com>
From: Praveen K Paladugu <prapal@linux.microsoft.com> Sent: Wednesday, November 26, 2025 1:50 PM
>
> Add support for clean shutdown of the root partition when running on
> MSHV Hypervisor.
>
> v6:
> - Fixed build errors, by adding CONFIG_X86_64 guard
Adding the CONFIG_X86_64 guard seems like the right solution, and it does
make the build errors go away. However note that as coded in drivers/hv/Makefile,
the code under the new guard won't be built at all unless CONFIG_MSHV_ROOT
is set (ignoring the VTL case for now), which can only happen in the X86_64 or
ARM64 cases. So it was nagging at me as to why the guard is needed for an
x86 32-bit build failure reported by the kernel test robot.
It turns out there's an underlying bug in drivers/hv/Makefile causing
mshv_common.o to be built in cases when it shouldn't be, such as the x86
32-bit case. The build failures reported by the kernel test robot were on these
cases when it shouldn't be built in the first place. The bug is in this Makefile line:
ifneq ($(CONFIG_MSHV_ROOT) $(CONFIG_MSHV_VTL),)
which should be
ifneq ($(CONFIG_MSHV_ROOT)$(CONFIG_MSHV_VTL),)
The buggy version has a spurious "space" character before the start of
$(CONFIG_MSHV_VTL) such that the result is always "not equal" and
mshv_common.o is always built.
If the Makefile is fixed, then the X86_64 guards you added in
mshv_common.c are not needed. Furthermore, the stubs for
hv_sleep_notifiers_register() and hv_machine_power_off() in
arch/x86/include/asm/mshyperv.h for the !CONFIG_X86_64 case aren't
needed. And the declarations for hv_sleep_notifiers_register() and
hv_machine_power_off() can be moved out from under the #ifdef
CONFIG_X86_64. The bottom line is that nothing in this patch set needs
to be guarded by CONFIG_X86_64.
Here's a quick diff of what I changed on top of your v6 patch set
(including the fix to drivers/hv/Makefile). I tested the build process
on both x86/64 and arm64, with and without CONFIG_MSHV_ROOT
selected.
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 4c22f3257368..01d192e70211 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -178,16 +178,15 @@ int hyperv_fill_flush_guest_mapping_list(
struct hv_guest_mapping_flush_list *flush,
u64 start_gfn, u64 end_gfn);
+void hv_sleep_notifiers_register(void);
+void hv_machine_power_off(void);
+
#ifdef CONFIG_X86_64
void hv_apic_init(void);
void __init hv_init_spinlocks(void);
bool hv_vcpu_is_preempted(int vcpu);
-void hv_sleep_notifiers_register(void);
-void hv_machine_power_off(void);
#else
static inline void hv_apic_init(void) {}
-static inline void hv_sleep_notifiers_register(void) {};
-static inline void hv_machine_power_off(void) {};
#endif
struct irq_domain *hv_create_pci_msi_domain(void);
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index 58b8d07639f3..6d929fb0e13d 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile
@@ -20,6 +20,6 @@ mshv_vtl-y := mshv_vtl_main.o
# Code that must be built-in
obj-$(CONFIG_HYPERV) += hv_common.o
obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o
-ifneq ($(CONFIG_MSHV_ROOT) $(CONFIG_MSHV_VTL),)
+ifneq ($(CONFIG_MSHV_ROOT)$(CONFIG_MSHV_VTL),)
obj-y += mshv_common.o
endif
diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
index 28905e3ed9c0..73505cbdc324 100644
--- a/drivers/hv/mshv_common.c
+++ b/drivers/hv/mshv_common.c
@@ -142,7 +142,6 @@ int hv_call_get_partition_property(u64 partition_id,
}
EXPORT_SYMBOL_GPL(hv_call_get_partition_property);
-#ifdef CONFIG_X86_64
/*
* Corresponding sleep states have to be initialized in order for a subsequent
* HVCALL_ENTER_SLEEP_STATE call to succeed. Currently only S5 state as per
@@ -235,4 +234,3 @@ void hv_machine_power_off(void)
local_irq_restore(flags);
}
-#endif
The Makefile fix needs to be a separate patch.
I think I got all this correct, but please double-check my work! :-)
Michael
> - Moved machine_ops hook definition to ms_hyperv_init_platform
> - Addressed review comments in v5
>
> v5:
> - Fixed build errors
> - Padded struct hv_input_set_system_property for alignment
> - Dropped CONFIG_ACPI stub
>
> v4:
> - Adopted machine_ops to order invoking HV_ENTER_SLEEP_STATE as the
> last step in shutdown sequence.
> - This ensures rest of the cleanups are done before powering off
>
> v3:
> - Dropped acpi_sleep handlers as they are not used on mshv
> - Applied ordering for hv_reboot_notifier
> - Fixed build issues on i386, arm64 architectures
>
> v2:
> - Addressed review comments from v1.
> - Moved all sleep state handling methods under CONFIG_ACPI stub
> - - This fixes build issues on non-x86 architectures.
>
>
> Praveen K Paladugu (3):
> hyperv: Add definitions for MSHV sleep state configuration
> hyperv: Use reboot notifier to configure sleep state
> hyperv: Cleanly shutdown root partition with MSHV
>
> arch/x86/hyperv/hv_init.c | 1 +
> arch/x86/include/asm/mshyperv.h | 4 ++
> arch/x86/kernel/cpu/mshyperv.c | 2 +
> drivers/hv/mshv_common.c | 98 +++++++++++++++++++++++++++++++++
> include/hyperv/hvgdk_mini.h | 4 +-
> include/hyperv/hvhdk_mini.h | 40 ++++++++++++++
> 6 files changed, 148 insertions(+), 1 deletion(-)
>
> --
> 2.51.0
>
^ permalink raw reply related
* RE: [RFC PATCH] Drivers: hv: Confidential VMBus exernal memory support
From: Michael Kelley @ 2025-11-28 17:47 UTC (permalink / raw)
To: Tianyu Lan, kys@microsoft.com, haiyangz@microsoft.com,
wei.liu@kernel.org, decui@microsoft.com, longli@microsoft.com,
vdso@hexbites.dev
Cc: Tianyu Lan, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20251124182920.9365-1-tiala@microsoft.com>
From: Tianyu Lan <ltykernel@gmail.com> Sent: Monday, November 24, 2025 10:29 AM
>
> In CVM(Confidential VM), system memory is encrypted
> by default. Device drivers typically use the swiotlb
> bounce buffer for DMA memory, which is decrypted
> and shared between the guest and host. Confidential
> Vmbus, however, supports a confidential channel
s/Vmbus/VMBus/ [and elsewhere in this commit msg]
> that employs encrypted memory for the Vmbus ring
> buffer and external DMA memory. The support for
> the confidential ring buffer has already been
> integrated.
>
> In CVM, device drivers usually employ the standard
> DMA API to map DMA memory with the bounce buffer,
> which remains transparent to the device driver.
> For external DMA memory support,
The "external memory" terminology is not at all clear in the context
of Linux. Presumably the terminology came from Hyper-V or the
paravisor, but I never understood what the "external" refers to. Maybe
it is memory that is "external" with respect to the hypervisor, and therefore
not shared between the hypervisor and guest? But that meaning won't be
evident to other reviewers in the Linux kernel community. In any case, some
explanation of "external memory" is needed. And even consider changing the
field names in the code to be something that makes more sense to Linux.
> Hyper-V specific
> DMA operations are introduced, bypassing the bounce
> buffer when the confidential external memory flag
> is set.
This commit message never explains why it is important to not do bounce
buffering. There's the obvious but unstated reason of improving performance,
but that's not the main reason. The main reason is a confidentiality leak.
When available, Confidential VMBus would be used because it keeps the
DMA data private (i.e., encrypted) and confidential to the guest. Bounce
buffering copies the data to shared (i.e., decrypted) swiotlb memory, where
it is exposed to the hypervisor. That's a confidentiality leak, and is the
primary reason the bounce buffering must be eliminated. This requirement
was pointed out by Robin Murphy in the discussion of Roman Kisel's
original code to eliminate the bounce buffering.
Separately, I have major qualms about using an approach with Hyper-V specific
DMA operations. As implemented here, these DMA operations bypass all
the kernel DMA layer logic when the VMBus synthetic device indicates
"external memory". In that case, the supplied physical address is just used
as the DMA address and everything else is bypassed. While this actually works
for VMBus synthetic devices because of their simple requirements, it also
is implicitly making some assumptions. These assumptions are true today
(as far as I know) but won't necessarily be true in the future. The assumptions
include:
* There's no vIOMMU in the guest VM. IOMMUs in CoCo VMs have their
own issues to work out, but an implementation that bypasses any IOMMU
logic in the DMA layer is very short-term thinking.
* There are no PCI pass-thru devices in the guest. Since the implementation
changes the global dma_ops, the drivers for such PCI pass-thru devices would
use the same global dma_ops, and would fail.
The code also has some other problems that I point out further down.
In any case, an approach with Hyper-V specific DMA operations seems like
a very temporary fix (hack?) at best. Further down, I'll proposed at alternate
approach that preserves all the existing DMA layer functionality.
> These DMA operations might also be reused
> for TDISP devices in the future, which also support
> DMA operations with encrypted memory.
>
> The DMA operations used are global architecture
> DMA operations (for details, see get_arch_dma_ops()
> and get_dma_ops()), and there is no need to set up
> for each device individually.
>
> Signed-off-by: Tianyu Lan <tiala@microsoft.com>
> ---
> drivers/hv/vmbus_drv.c | 90 +++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 89 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 0dc4692b411a..ca31231b2c32 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -39,6 +39,9 @@
> #include <clocksource/hyperv_timer.h>
> #include <asm/mshyperv.h>
> #include "hyperv_vmbus.h"
> +#include "../../kernel/dma/direct.h"
> +
> +extern const struct dma_map_ops *dma_ops;
>
> struct vmbus_dynid {
> struct list_head node;
> @@ -1429,6 +1432,88 @@ static int vmbus_alloc_synic_and_connect(void)
> return -ENOMEM;
> }
>
> +
> +static bool hyperv_private_memory_dma(struct device *dev)
> +{
> + struct hv_device *hv_dev = device_to_hv_device(dev);
device_to_hv_device() works only when "dev" is for a VMBus device. As noted above,
if a CoCo VM were ever to have a PCI pass-thru device doing DMA, "dev" would
be some PCI device, and device_to_hv_device() would return garbage.
> +
> + if (hv_dev && hv_dev->channel && hv_dev->channel->co_external_memory)
> + return true;
> + else
> + return false;
> +}
> +
> +static dma_addr_t hyperv_dma_map_page(struct device *dev, struct page *page,
> + unsigned long offset, size_t size,
> + enum dma_data_direction dir,
> + unsigned long attrs)
> +{
> + phys_addr_t phys = page_to_phys(page) + offset;
> +
> + if (hyperv_private_memory_dma(dev))
> + return __phys_to_dma(dev, phys);
> + else
> + return dma_direct_map_phys(dev, phys, size, dir, attrs);
This code won't build when the VMBus driver is built as a module.
dma_direct_map_phys() is in inline function that references several other
DMA functions that aren't exported because they aren't intended to be
used by drivers. Same problems occur with dma_direct_unmap_phys()
and similar functions used below.
> +}
> +
> +static void hyperv_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
> + size_t size, enum dma_data_direction dir, unsigned long attrs)
> +{
> + if (!hyperv_private_memory_dma(dev))
> + dma_direct_unmap_phys(dev, dma_handle, size, dir, attrs);
> +}
> +
> +static int hyperv_dma_map_sg(struct device *dev, struct scatterlist *sgl,
> + int nelems, enum dma_data_direction dir,
> + unsigned long attrs)
> +{
> + struct scatterlist *sg;
> + dma_addr_t dma_addr;
> + int i;
> +
> + if (hyperv_private_memory_dma(dev)) {
> + for_each_sg(sgl, sg, nelems, i) {
> + dma_addr = __phys_to_dma(dev, sg_phys(sg));
> + sg_dma_address(sg) = dma_addr;
> + sg_dma_len(sg) = sg->length;
> + }
> +
> + return nelems;
> + } else {
> + return dma_direct_map_sg(dev, sgl, nelems, dir, attrs);
> + }
> +}
> +
> +static void hyperv_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
> + int nelems, enum dma_data_direction dir, unsigned long attrs)
> +{
> + if (!hyperv_private_memory_dma(dev))
> + dma_direct_unmap_sg(dev, sgl, nelems, dir, attrs);
> +}
> +
> +static int hyperv_dma_supported(struct device *dev, u64 mask)
> +{
> + dev->coherent_dma_mask = mask;
> + return 1;
> +}
> +
> +static size_t hyperv_dma_max_mapping_size(struct device *dev)
> +{
> + if (hyperv_private_memory_dma(dev))
> + return SIZE_MAX;
> + else
> + return swiotlb_max_mapping_size(dev);
> +}
> +
> +const struct dma_map_ops hyperv_dma_ops = {
> + .map_page = hyperv_dma_map_page,
> + .unmap_page = hyperv_dma_unmap_page,
> + .map_sg = hyperv_dma_map_sg,
> + .unmap_sg = hyperv_dma_unmap_sg,
> + .dma_supported = hyperv_dma_supported,
> + .max_mapping_size = hyperv_dma_max_mapping_size,
> +};
> +
> /*
> * vmbus_bus_init -Main vmbus driver initialization routine.
> *
> @@ -1479,8 +1564,11 @@ static int vmbus_bus_init(void)
> * doing that on each VP while initializing SynIC's wastes time.
> */
> is_confidential = ms_hyperv.confidential_vmbus_available;
> - if (is_confidential)
> + if (is_confidential) {
> + dma_ops = &hyperv_dma_ops;
arm64 doesn't have the global variable dma_ops, so this patch
won't build on arm64, even if Confidential VMBus isn't yet available
for arm64.
> pr_info("Establishing connection to the confidential VMBus\n");
> + }
> +
> hv_para_set_sint_proxy(!is_confidential);
> ret = vmbus_alloc_synic_and_connect();
> if (ret)
> --
> 2.50.1
>
Here's my idea for an alternate approach. The goal is to allow use of the
swiotlb to be disabled on a per-device basis. A device is initialized for swiotlb
usage by swiotlb_dev_init(), which sets dev->dma_io_tlb_mem to point to the
default swiotlb memory. For VMBus devices, the calling sequence is
vmbus_device_register() -> device_register() -> device_initialize() ->
swiotlb_dev_init(). But if vmbus_device_register() could override the
dev->dma_io_tlb_mem value and put it back to NULL, swiotlb operations
would be disabled on the device. Furthermore, is_swiotlb_force_bounce()
would return "false", and the normal DMA functions would not force the
use of bounce buffers. The entire code change looks like this:
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -2133,11 +2133,15 @@ int vmbus_device_register(struct hv_device *child_device_obj)
child_device_obj->device.dma_mask = &child_device_obj->dma_mask;
dma_set_mask(&child_device_obj->device, DMA_BIT_MASK(64));
+ device_initialize(&child_device_obj->device);
+ if (child_device_obj->channel->co_external_memory)
+ child_device_obj->device.dma_io_tlb_mem = NULL;
+
/*
* Register with the LDM. This will kick off the driver/device
* binding...which will eventually call vmbus_match() and vmbus_probe()
*/
- ret = device_register(&child_device_obj->device);
+ ret = device_add(&child_device_obj->device);
if (ret) {
pr_err("Unable to register child device\n");
put_device(&child_device_obj->device);
I've only compile tested the above since I don't have an environment where
I can test Confidential VMBus. You would need to verify whether my thinking
is correct and this produces the intended result.
Directly setting dma_io_tlb_mem to NULL isn't great. It would be better
to add an exported function swiotlb_dev_disable() to swiotlb code that sets
dma_io_tlb_mem to NULL, but you get the idea.
Other reviewers may still see this approach as a bit of a hack, but it's a lot
less of a hack than introducing Hyper-V specific DMA functions.
swiotlb_dev_disable() is conceptually needed for TDISP devices, as TDISP
devices must similarly protect confidentiality by not allowing use of the swiotlb.
So adding swiotlb_dev_disable() is a step in the right direction, even if the
eventual TDISP code does it slightly differently. Doing the disable on a
per-device basis is also the right thing in the long run.
Michael
^ permalink raw reply
* Re: [RESEND PATCH] Drivers: hv: adjust interrupt control structure for ARM64
From: Wei Liu @ 2025-11-28 7:17 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
linux-hyperv, linux-kernel
In-Reply-To: <20251124142600.2112608-1-anirudh@anirudhrb.com>
On Mon, Nov 24, 2025 at 02:25:59PM +0000, Anirudh Rayabharam wrote:
> From: Jinank Jain <jinankjain@microsoft.com>
>
> Interrupt control structure (union hv_interupt_control) has different
> fields when it comes to x86 vs ARM64. Bring in the correct structure
> from HyperV header files and adjust the existing interrupt routing
> code accordingly.
>
> Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
> Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
Applied.
^ permalink raw reply
* Re: [PATCH 1/1] Drivers: hv: use kmalloc_array() instead of kmalloc()
From: Wei Liu @ 2025-11-28 7:15 UTC (permalink / raw)
To: Gongwei Li
Cc: kys, haiyangz, wei.liu, decui, linux-hyperv, linux-kernel,
Gongwei Li
In-Reply-To: <20251121031041.56619-1-13875017792@163.com>
On Fri, Nov 21, 2025 at 11:10:41AM +0800, Gongwei Li wrote:
> From: Gongwei Li <ligongwei@kylinos.cn>
>
> Replace kmalloc() with kmalloc_array() to prevent potential
> overflow, as recommended in Documentation/process/deprecated.rst.
>
> Signed-off-by: Gongwei Li <ligongwei@kylinos.cn>
Applied to hyperv-next. Thanks.
> ---
> drivers/hv/hv_util.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
> index 36ee89c0358b..7e9c8e169c66 100644
> --- a/drivers/hv/hv_util.c
> +++ b/drivers/hv/hv_util.c
> @@ -586,7 +586,7 @@ static int util_probe(struct hv_device *dev,
> (struct hv_util_service *)dev_id->driver_data;
> int ret;
>
> - srv->recv_buffer = kmalloc(HV_HYP_PAGE_SIZE * 4, GFP_KERNEL);
> + srv->recv_buffer = kmalloc_array(4, HV_HYP_PAGE_SIZE, GFP_KERNEL);
> if (!srv->recv_buffer)
> return -ENOMEM;
> srv->channel = dev->channel;
> --
> 2.25.1
>
^ permalink raw reply
* [linux-next:master] [syscore] a97fbc3ee3: will-it-scale.per_process_ops 3.2% regression
From: kernel test robot @ 2025-11-28 6:35 UTC (permalink / raw)
To: Thierry Reding
Cc: oe-lkp, lkp, Rafael J. Wysocki, linux-arm-kernel,
linux-samsung-soc, loongarch, linux-mips, linuxppc-dev, linux-sh,
linux-perf-users, linux-kernel, linux-hyperv, linux-edac, kvm,
linux-pci, linux-acpi, imx, linux-rockchip, linux-tegra, linux-pm,
linux-gpio, iommu, linux-mediatek, linux-riscv, linux-sunxi,
linux-leds, xen-devel, oliver.sang
Hello,
kernel test robot noticed a 3.2% regression of will-it-scale.per_process_ops on:
commit: a97fbc3ee3e2a536fafaff04f21f45472db71769 ("syscore: Pass context data to callbacks")
https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git master
[still regression on linux-next/master ef68bf704646690aba5e81c2f7be8d6ef13d7ad8]
testcase: will-it-scale
config: x86_64-rhel-9.4
compiler: gcc-14
test machine: 64 threads 2 sockets Intel(R) Xeon(R) Gold 6346 CPU @ 3.10GHz (Ice Lake) with 256G memory
parameters:
nr_task: 100%
mode: process
test: signal1
cpufreq_governor: performance
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202511281432.47ac7e38-lkp@intel.com
Details are as below:
-------------------------------------------------------------------------------------------------->
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20251128/202511281432.47ac7e38-lkp@intel.com
=========================================================================================
compiler/cpufreq_governor/kconfig/mode/nr_task/rootfs/tbox_group/test/testcase:
gcc-14/performance/x86_64-rhel-9.4/process/100%/debian-13-x86_64-20250902.cgz/lkp-icl-2sp7/signal1/will-it-scale
commit:
v6.18-rc1
a97fbc3ee3 ("syscore: Pass context data to callbacks")
v6.18-rc1 a97fbc3ee3e2a536fafaff04f21
---------------- ---------------------------
%stddev %change %stddev
\ | \
71066 ±105% +119.1% 155709 ± 64% numa-meminfo.node1.AnonHugePages
34.80 ±105% +118.6% 76.08 ± 64% numa-vmstat.node1.nr_anon_transparent_hugepages
0.34 +0.2 0.52 ± 25% mpstat.cpu.all.idle%
0.01 +0.0 0.01 ± 3% mpstat.cpu.all.soft%
142.02 ± 5% +20.2% 170.65 ± 9% sched_debug.cfs_rq:/.runnable_avg.stddev
7.16 ± 5% +52.9% 10.94 ± 8% sched_debug.cpu.clock.stddev
1233 ± 4% -22.2% 960.17 ± 8% perf-c2c.DRAM.remote
2429 ± 3% -18.0% 1993 perf-c2c.HITM.local
1010 ± 5% -29.8% 709.00 ± 2% perf-c2c.HITM.remote
8382642 -3.2% 8118230 will-it-scale.64.processes
130978 -3.2% 126846 will-it-scale.per_process_ops
8382642 -3.2% 8118230 will-it-scale.workload
285565 -1.6% 280908 proc-vmstat.nr_active_anon
28063 +4.4% 29306 proc-vmstat.nr_mapped
117169 -3.9% 112656 proc-vmstat.nr_shmem
285565 -1.6% 280908 proc-vmstat.nr_zone_active_anon
38231 ± 33% -48.6% 19647 ± 35% proc-vmstat.numa_hint_faults
19706 ± 75% -65.5% 6790 ± 15% proc-vmstat.numa_hint_faults_local
9.391e+09 -3.1% 9.102e+09 perf-stat.i.branch-instructions
0.48 -0.0 0.45 perf-stat.i.branch-miss-rate%
45545162 -10.7% 40674481 perf-stat.i.branch-misses
11.08 ± 8% -2.3 8.81 ± 12% perf-stat.i.cache-miss-rate%
1811 +6.2% 1922 perf-stat.i.context-switches
5.09 +3.2% 5.26 perf-stat.i.cpi
117.53 -2.1% 115.06 perf-stat.i.cpu-migrations
216404 ± 2% +86.7% 404107 ± 4% perf-stat.i.cycles-between-cache-misses
3.87e+10 -3.1% 3.752e+10 perf-stat.i.instructions
0.20 -3.1% 0.19 perf-stat.i.ipc
0.49 -0.0 0.45 perf-stat.overall.branch-miss-rate%
5.10 +3.2% 5.26 perf-stat.overall.cpi
0.20 -3.1% 0.19 perf-stat.overall.ipc
9.361e+09 -3.1% 9.068e+09 perf-stat.ps.branch-instructions
45428240 -10.7% 40562730 perf-stat.ps.branch-misses
1806 +6.2% 1917 perf-stat.ps.context-switches
117.13 -2.1% 114.62 perf-stat.ps.cpu-migrations
3.858e+10 -3.1% 3.738e+10 perf-stat.ps.instructions
1.166e+13 -3.0% 1.131e+13 perf-stat.total.instructions
32.30 -6.5 25.85 perf-profile.calltrace.cycles-pp.get_signal.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe
31.42 -6.4 25.04 perf-profile.calltrace.cycles-pp.dequeue_signal.get_signal.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64
30.28 -6.3 23.98 perf-profile.calltrace.cycles-pp.dec_rlimit_put_ucounts.__sigqueue_free.dequeue_signal.get_signal.arch_do_signal_or_restart
30.32 -6.3 24.02 perf-profile.calltrace.cycles-pp.__sigqueue_free.dequeue_signal.get_signal.arch_do_signal_or_restart.exit_to_user_mode_loop
37.60 -6.0 31.57 perf-profile.calltrace.cycles-pp.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe
37.68 -6.0 31.66 perf-profile.calltrace.cycles-pp.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe
90.92 -0.5 90.43 perf-profile.calltrace.cycles-pp.entry_SYSCALL_64_after_hwframe
90.63 -0.5 90.14 perf-profile.calltrace.cycles-pp.do_syscall_64.entry_SYSCALL_64_after_hwframe
0.62 +0.0 0.65 perf-profile.calltrace.cycles-pp.check_xstate_in_sigframe.__fpu_restore_sig.fpu__restore_sig.restore_sigcontext.__x64_sys_rt_sigreturn
0.72 ± 2% +0.0 0.75 perf-profile.calltrace.cycles-pp.kmem_cache_alloc_noprof.__send_signal_locked.do_send_sig_info.do_send_specific.__x64_sys_tgkill
0.67 +0.0 0.70 perf-profile.calltrace.cycles-pp.__fpu_restore_sig.fpu__restore_sig.restore_sigcontext.__x64_sys_rt_sigreturn.do_syscall_64
2.54 +0.0 2.58 perf-profile.calltrace.cycles-pp.fpu__restore_sig.restore_sigcontext.__x64_sys_rt_sigreturn.do_syscall_64.entry_SYSCALL_64_after_hwframe
1.15 +0.0 1.19 perf-profile.calltrace.cycles-pp.fpu__clear_user_states.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe
1.78 +0.0 1.83 perf-profile.calltrace.cycles-pp.clear_bhb_loop
0.56 +0.1 0.61 perf-profile.calltrace.cycles-pp.rseq_ip_fixup.__rseq_handle_notify_resume.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64
1.46 +0.1 1.51 perf-profile.calltrace.cycles-pp.__restore_fpregs_from_user.restore_fpregs_from_user.fpu__restore_sig.restore_sigcontext.__x64_sys_rt_sigreturn
1.62 +0.1 1.68 perf-profile.calltrace.cycles-pp.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe.handler
3.06 +0.1 3.11 perf-profile.calltrace.cycles-pp.restore_sigcontext.__x64_sys_rt_sigreturn.do_syscall_64.entry_SYSCALL_64_after_hwframe
1.69 +0.1 1.75 perf-profile.calltrace.cycles-pp.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe.handler
1.91 +0.1 1.98 perf-profile.calltrace.cycles-pp.entry_SYSCALL_64_after_hwframe.handler
1.88 +0.1 1.96 perf-profile.calltrace.cycles-pp.do_syscall_64.entry_SYSCALL_64_after_hwframe.handler
0.96 +0.1 1.04 perf-profile.calltrace.cycles-pp.save_xstate_epilog.get_sigframe.x64_setup_rt_frame.arch_do_signal_or_restart.exit_to_user_mode_loop
0.93 +0.1 1.02 perf-profile.calltrace.cycles-pp.__rseq_handle_notify_resume.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe
4.46 +0.1 4.57 perf-profile.calltrace.cycles-pp.__x64_sys_rt_sigreturn.do_syscall_64.entry_SYSCALL_64_after_hwframe
2.18 +0.2 2.35 perf-profile.calltrace.cycles-pp.copy_fpstate_to_sigframe.get_sigframe.x64_setup_rt_frame.arch_do_signal_or_restart.exit_to_user_mode_loop
4.88 +0.3 5.14 perf-profile.calltrace.cycles-pp.handler
3.66 +0.3 3.95 perf-profile.calltrace.cycles-pp.get_sigframe.x64_setup_rt_frame.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64
4.16 +0.3 4.50 perf-profile.calltrace.cycles-pp.x64_setup_rt_frame.arch_do_signal_or_restart.exit_to_user_mode_loop.do_syscall_64.entry_SYSCALL_64_after_hwframe
0.00 +0.5 0.51 perf-profile.calltrace.cycles-pp.restore_altstack.__x64_sys_rt_sigreturn.do_syscall_64.entry_SYSCALL_64_after_hwframe
0.00 +0.5 0.52 perf-profile.calltrace.cycles-pp.__get_user_nocheck_8.__x64_sys_rt_sigreturn.do_syscall_64.entry_SYSCALL_64_after_hwframe
45.91 +5.3 51.19 perf-profile.calltrace.cycles-pp.do_send_sig_info.do_send_specific.__x64_sys_tgkill.do_syscall_64.entry_SYSCALL_64_after_hwframe
46.73 +5.3 52.02 perf-profile.calltrace.cycles-pp.do_send_specific.__x64_sys_tgkill.do_syscall_64.entry_SYSCALL_64_after_hwframe
47.27 +5.3 52.57 perf-profile.calltrace.cycles-pp.__x64_sys_tgkill.do_syscall_64.entry_SYSCALL_64_after_hwframe
45.10 +5.3 50.43 perf-profile.calltrace.cycles-pp.__send_signal_locked.do_send_sig_info.do_send_specific.__x64_sys_tgkill.do_syscall_64
43.31 +5.3 48.65 perf-profile.calltrace.cycles-pp.inc_rlimit_get_ucounts.sig_get_ucounts.__send_signal_locked.do_send_sig_info.do_send_specific
43.39 +5.3 48.73 perf-profile.calltrace.cycles-pp.sig_get_ucounts.__send_signal_locked.do_send_sig_info.do_send_specific.__x64_sys_tgkill
32.36 -6.5 25.90 perf-profile.children.cycles-pp.get_signal
31.44 -6.4 25.06 perf-profile.children.cycles-pp.dequeue_signal
30.29 -6.3 23.99 perf-profile.children.cycles-pp.dec_rlimit_put_ucounts
30.33 -6.3 24.03 perf-profile.children.cycles-pp.__sigqueue_free
39.26 -6.0 33.30 perf-profile.children.cycles-pp.arch_do_signal_or_restart
39.38 -5.9 33.43 perf-profile.children.cycles-pp.exit_to_user_mode_loop
93.64 -0.3 93.30 perf-profile.children.cycles-pp.entry_SYSCALL_64_after_hwframe
93.28 -0.3 92.95 perf-profile.children.cycles-pp.do_syscall_64
0.36 ± 11% -0.1 0.25 perf-profile.children.cycles-pp.recalc_sigpending
0.61 ± 11% -0.1 0.50 ± 6% perf-profile.children.cycles-pp._raw_spin_lock_irq
0.43 -0.1 0.38 perf-profile.children.cycles-pp.fpregs_mark_activate
0.44 -0.0 0.40 perf-profile.children.cycles-pp.complete_signal
0.27 ± 5% -0.0 0.23 ± 3% perf-profile.children.cycles-pp.sysvec_apic_timer_interrupt
0.25 ± 6% -0.0 0.22 ± 5% perf-profile.children.cycles-pp.__sysvec_apic_timer_interrupt
0.25 ± 6% -0.0 0.22 ± 5% perf-profile.children.cycles-pp.hrtimer_interrupt
0.25 -0.0 0.22 ± 5% perf-profile.children.cycles-pp._raw_spin_lock_irqsave
0.29 ± 5% -0.0 0.26 ± 3% perf-profile.children.cycles-pp.asm_sysvec_apic_timer_interrupt
0.31 ± 2% -0.0 0.28 perf-profile.children.cycles-pp.set_current_blocked
0.05 +0.0 0.06 perf-profile.children.cycles-pp.fpu__alloc_mathframe
0.06 +0.0 0.07 perf-profile.children.cycles-pp.__cond_resched
0.20 +0.0 0.21 perf-profile.children.cycles-pp.syscall_return_via_sysret
0.24 +0.0 0.25 perf-profile.children.cycles-pp.__get_user_nocheck_4
0.39 +0.0 0.40 perf-profile.children.cycles-pp.entry_SYSCALL_64_safe_stack
0.72 +0.0 0.74 perf-profile.children.cycles-pp.entry_SYSRETQ_unsafe_stack
0.20 +0.0 0.22 perf-profile.children.cycles-pp.__get_user_8
0.22 ± 2% +0.0 0.24 perf-profile.children.cycles-pp.__put_user_8
0.46 ± 3% +0.0 0.48 perf-profile.children.cycles-pp.__memcg_slab_post_alloc_hook
0.69 +0.0 0.71 perf-profile.children.cycles-pp.__fpu_restore_sig
0.27 +0.0 0.30 perf-profile.children.cycles-pp.rseq_get_rseq_cs
0.63 +0.0 0.66 perf-profile.children.cycles-pp.check_xstate_in_sigframe
0.74 +0.0 0.77 perf-profile.children.cycles-pp.kmem_cache_alloc_noprof
0.50 +0.0 0.53 perf-profile.children.cycles-pp.restore_altstack
0.32 +0.0 0.35 perf-profile.children.cycles-pp.rseq_update_cpu_node_id
0.36 +0.0 0.39 perf-profile.children.cycles-pp.__put_user_nocheck_4
0.69 +0.0 0.73 perf-profile.children.cycles-pp.arch_exit_to_user_mode_prepare
0.37 +0.0 0.40 perf-profile.children.cycles-pp.__put_user_nocheck_8
2.06 +0.0 2.10 perf-profile.children.cycles-pp.__getpid
0.66 +0.0 0.70 perf-profile.children.cycles-pp._copy_from_user
2.55 +0.0 2.59 perf-profile.children.cycles-pp.fpu__restore_sig
0.87 +0.0 0.91 perf-profile.children.cycles-pp.its_return_thunk
1.21 +0.0 1.25 perf-profile.children.cycles-pp.fpu__clear_user_states
1.48 +0.0 1.52 perf-profile.children.cycles-pp.__restore_fpregs_from_user
2.39 +0.1 2.44 perf-profile.children.cycles-pp.clear_bhb_loop
0.09 ± 4% +0.1 0.14 ± 4% perf-profile.children.cycles-pp.shmem_file_write_iter
0.08 +0.1 0.14 ± 5% perf-profile.children.cycles-pp.generic_perform_write
0.00 +0.1 0.06 ± 8% perf-profile.children.cycles-pp.shmem_get_folio_gfp
0.10 ± 3% +0.1 0.16 ± 3% perf-profile.children.cycles-pp.perf_mmap__push
0.00 +0.1 0.06 ± 6% perf-profile.children.cycles-pp.shmem_write_begin
0.58 +0.1 0.64 perf-profile.children.cycles-pp.rseq_ip_fixup
3.08 +0.1 3.13 perf-profile.children.cycles-pp.restore_sigcontext
0.10 ± 3% +0.1 0.16 ± 4% perf-profile.children.cycles-pp.record__mmap_read_evlist
0.09 ± 5% +0.1 0.15 ± 4% perf-profile.children.cycles-pp.record__pushfn
0.12 ± 4% +0.1 0.18 ± 4% perf-profile.children.cycles-pp.handle_internal_command
0.12 ± 4% +0.1 0.18 ± 4% perf-profile.children.cycles-pp.main
0.12 ± 4% +0.1 0.18 ± 4% perf-profile.children.cycles-pp.run_builtin
0.11 ± 6% +0.1 0.17 ± 5% perf-profile.children.cycles-pp.cmd_record
0.98 +0.1 1.06 perf-profile.children.cycles-pp.__get_user_nocheck_8
1.36 +0.1 1.45 perf-profile.children.cycles-pp.native_irq_return_iret
1.00 +0.1 1.09 perf-profile.children.cycles-pp.save_xstate_epilog
0.95 +0.1 1.04 perf-profile.children.cycles-pp.__rseq_handle_notify_resume
4.52 +0.1 4.64 perf-profile.children.cycles-pp.__x64_sys_rt_sigreturn
2.27 +0.2 2.45 perf-profile.children.cycles-pp.copy_fpstate_to_sigframe
3.68 +0.2 3.86 perf-profile.children.cycles-pp.handler
3.68 +0.3 3.98 perf-profile.children.cycles-pp.get_sigframe
4.21 +0.3 4.55 perf-profile.children.cycles-pp.x64_setup_rt_frame
45.96 +5.3 51.25 perf-profile.children.cycles-pp.do_send_sig_info
46.77 +5.3 52.07 perf-profile.children.cycles-pp.do_send_specific
47.30 +5.3 52.60 perf-profile.children.cycles-pp.__x64_sys_tgkill
45.18 +5.3 50.51 perf-profile.children.cycles-pp.__send_signal_locked
43.40 +5.3 48.74 perf-profile.children.cycles-pp.sig_get_ucounts
43.32 +5.3 48.66 perf-profile.children.cycles-pp.inc_rlimit_get_ucounts
30.28 -6.3 23.98 perf-profile.self.cycles-pp.dec_rlimit_put_ucounts
0.34 ± 12% -0.1 0.23 ± 2% perf-profile.self.cycles-pp.recalc_sigpending
0.58 ± 12% -0.1 0.48 ± 6% perf-profile.self.cycles-pp._raw_spin_lock_irq
0.31 -0.1 0.25 ± 2% perf-profile.self.cycles-pp.complete_signal
0.36 -0.1 0.31 perf-profile.self.cycles-pp.fpregs_mark_activate
0.23 ± 2% -0.0 0.20 ± 3% perf-profile.self.cycles-pp._raw_spin_lock_irqsave
0.20 +0.0 0.21 perf-profile.self.cycles-pp.arch_do_signal_or_restart
0.07 +0.0 0.08 perf-profile.self.cycles-pp.collect_signal
0.40 +0.0 0.41 perf-profile.self.cycles-pp.__getpid
0.20 +0.0 0.21 perf-profile.self.cycles-pp.syscall_return_via_sysret
0.23 +0.0 0.24 ± 2% perf-profile.self.cycles-pp.__get_user_nocheck_4
0.15 ± 2% +0.0 0.16 ± 2% perf-profile.self.cycles-pp.__x64_sys_rt_sigreturn
0.26 +0.0 0.28 perf-profile.self.cycles-pp.kmem_cache_free
0.10 +0.0 0.11 ± 4% perf-profile.self.cycles-pp.signal_setup_done
0.70 +0.0 0.72 perf-profile.self.cycles-pp.entry_SYSRETQ_unsafe_stack
0.18 ± 2% +0.0 0.20 perf-profile.self.cycles-pp.__get_user_8
0.21 ± 3% +0.0 0.23 perf-profile.self.cycles-pp.__put_user_8
0.25 ± 3% +0.0 0.27 ± 2% perf-profile.self.cycles-pp.__memcg_slab_post_alloc_hook
0.47 +0.0 0.49 perf-profile.self.cycles-pp.get_signal
0.52 +0.0 0.55 perf-profile.self.cycles-pp.its_return_thunk
0.37 +0.0 0.40 perf-profile.self.cycles-pp.get_sigframe
0.34 +0.0 0.37 perf-profile.self.cycles-pp.__put_user_nocheck_4
0.31 +0.0 0.34 perf-profile.self.cycles-pp.rseq_update_cpu_node_id
0.34 +0.0 0.38 perf-profile.self.cycles-pp.__put_user_nocheck_8
0.37 ± 2% +0.0 0.41 perf-profile.self.cycles-pp.save_xstate_epilog
0.64 +0.0 0.68 perf-profile.self.cycles-pp.arch_exit_to_user_mode_prepare
0.64 +0.0 0.68 perf-profile.self.cycles-pp._copy_from_user
0.53 +0.0 0.57 perf-profile.self.cycles-pp.x64_setup_rt_frame
1.46 +0.0 1.51 perf-profile.self.cycles-pp.__restore_fpregs_from_user
2.36 +0.1 2.41 perf-profile.self.cycles-pp.clear_bhb_loop
1.00 +0.1 1.06 perf-profile.self.cycles-pp.fpu__clear_user_states
0.94 +0.1 1.01 perf-profile.self.cycles-pp.__get_user_nocheck_8
1.36 +0.1 1.45 perf-profile.self.cycles-pp.native_irq_return_iret
1.45 +0.1 1.55 perf-profile.self.cycles-pp.copy_fpstate_to_sigframe
43.32 +5.3 48.66 perf-profile.self.cycles-pp.inc_rlimit_get_ucounts
Disclaimer:
Results have been estimated based on internal Intel analysis and are provided
for informational purposes only. Any difference in system hardware or software
design or configuration may affect actual performance.
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH net-next v12 02/12] vsock: add netns to vsock core
From: Bobby Eshleman @ 2025-11-27 16:33 UTC (permalink / raw)
To: Stefano Garzarella
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan, linux-kernel,
virtualization, netdev, kvm, linux-hyperv, linux-kselftest,
berrange, Sargun Dhillon, Bobby Eshleman
In-Reply-To: <hgz3rtpb3lvxzbygye6ziobfujfsl2yefh5t3ghrbbbknr6eis@ypifkm24ygja>
On Thu, Nov 27, 2025 at 03:25:32PM +0100, Stefano Garzarella wrote:
> On Wed, Nov 26, 2025 at 11:47:31PM -0800, Bobby Eshleman wrote:
> > From: Bobby Eshleman <bobbyeshleman@meta.com>
> >
> > Add netns logic to vsock core. Additionally, modify transport hook
> > prototypes to be used by later transport-specific patches (e.g.,
> > *_seqpacket_allow()).
> >
> > Namespaces are supported primarily by changing socket lookup functions
> > (e.g., vsock_find_connected_socket()) to take into account the socket
> > namespace and the namespace mode before considering a candidate socket a
> > "match".
> >
> > This patch also introduces the sysctl /proc/sys/net/vsock/ns_mode that
> > accepts the "global" or "local" mode strings.
> >
> > Add netns functionality (initialization, passing to transports, procfs,
> > etc...) to the af_vsock socket layer. Later patches that add netns
> > support to transports depend on this patch.
> >
> > dgram_allow(), stream_allow(), and seqpacket_allow() callbacks are
> > modified to take a vsk in order to perform logic on namespace modes. In
> > future patches, the net and net_mode will also be used for socket
> > lookups in these functions.
> >
> > Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
> > ---
> > Changes in v12:
> > - return true in dgram_allow(), stream_allow(), and seqpacket_allow()
> > only if net_mode == VSOCK_NET_MODE_GLOBAL (Stefano)
> > - document bind(VMADDR_CID_ANY) case in af_vsock.c (Stefano)
> > - change order of stream_allow() call in vmci so we can pass vsk
> > to it
> >
> > Changes in v10:
> > - add file-level comment about what happens to sockets/devices
> > when the namespace mode changes (Stefano)
> > - change the 'if (write)' boolean in vsock_net_mode_string() to
> > if (!write), this simplifies a later patch which adds "goto"
> > for mutex unlocking on function exit.
> >
> > Changes in v9:
> > - remove virtio_vsock_alloc_rx_skb() (Stefano)
> > - remove vsock_global_dummy_net, not needed as net=NULL +
> > net_mode=VSOCK_NET_MODE_GLOBAL achieves identical result
> >
> > Changes in v7:
> > - hv_sock: fix hyperv build error
> > - explain why vhost does not use the dummy
> > - explain usage of __vsock_global_dummy_net
> > - explain why VSOCK_NET_MODE_STR_MAX is 8 characters
> > - use switch-case in vsock_net_mode_string()
> > - avoid changing transports as much as possible
> > - add vsock_find_{bound,connected}_socket_net()
> > - rename `vsock_hdr` to `sysctl_hdr`
> > - add virtio_vsock_alloc_linear_skb() wrapper for setting dummy net and
> > global mode for virtio-vsock, move skb->cb zero-ing into wrapper
> > - explain seqpacket_allow() change
> > - move net setting to __vsock_create() instead of vsock_create() so
> > that child sockets also have their net assigned upon accept()
> >
> > Changes in v6:
> > - unregister sysctl ops in vsock_exit()
> > - af_vsock: clarify description of CID behavior
> > - af_vsock: fix buf vs buffer naming, and length checking
> > - af_vsock: fix length checking w/ correct ctl_table->maxlen
> >
> > Changes in v5:
> > - vsock_global_net() -> vsock_global_dummy_net()
> > - update comments for new uAPI
> > - use /proc/sys/net/vsock/ns_mode instead of /proc/net/vsock_ns_mode
> > - add prototype changes so patch remains compilable
> > ---
> > drivers/vhost/vsock.c | 9 +-
> > include/linux/virtio_vsock.h | 4 +-
> > include/net/af_vsock.h | 13 +-
> > net/vmw_vsock/af_vsock.c | 272 +++++++++++++++++++++++++++++---
> > net/vmw_vsock/hyperv_transport.c | 7 +-
> > net/vmw_vsock/virtio_transport.c | 9 +-
> > net/vmw_vsock/virtio_transport_common.c | 6 +-
> > net/vmw_vsock/vmci_transport.c | 26 ++-
> > net/vmw_vsock/vsock_loopback.c | 8 +-
> > 9 files changed, 310 insertions(+), 44 deletions(-)
> >
> > diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
> > index ae01457ea2cd..83937e1d63fa 100644
> > --- a/drivers/vhost/vsock.c
> > +++ b/drivers/vhost/vsock.c
> > @@ -404,7 +404,8 @@ static bool vhost_transport_msgzerocopy_allow(void)
> > return true;
> > }
> >
> > -static bool vhost_transport_seqpacket_allow(u32 remote_cid);
> > +static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk,
> > + u32 remote_cid);
> >
> > static struct virtio_transport vhost_transport = {
> > .transport = {
> > @@ -460,11 +461,15 @@ static struct virtio_transport vhost_transport = {
> > .send_pkt = vhost_transport_send_pkt,
> > };
> >
> > -static bool vhost_transport_seqpacket_allow(u32 remote_cid)
> > +static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk,
> > + u32 remote_cid)
> > {
> > struct vhost_vsock *vsock;
> > bool seqpacket_allow = false;
> >
> > + if (vsk->net_mode != VSOCK_NET_MODE_GLOBAL)
> > + return false;
> > +
> > rcu_read_lock();
> > vsock = vhost_vsock_get(remote_cid);
> >
> > diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
> > index 0c67543a45c8..1845e8d4f78d 100644
> > --- a/include/linux/virtio_vsock.h
> > +++ b/include/linux/virtio_vsock.h
> > @@ -256,10 +256,10 @@ void virtio_transport_notify_buffer_size(struct vsock_sock *vsk, u64 *val);
> >
> > u64 virtio_transport_stream_rcvhiwat(struct vsock_sock *vsk);
> > bool virtio_transport_stream_is_active(struct vsock_sock *vsk);
> > -bool virtio_transport_stream_allow(u32 cid, u32 port);
> > +bool virtio_transport_stream_allow(struct vsock_sock *vsk, u32 cid, u32 port);
> > int virtio_transport_dgram_bind(struct vsock_sock *vsk,
> > struct sockaddr_vm *addr);
> > -bool virtio_transport_dgram_allow(u32 cid, u32 port);
> > +bool virtio_transport_dgram_allow(struct vsock_sock *vsk, u32 cid, u32 port);
> >
> > int virtio_transport_connect(struct vsock_sock *vsk);
> >
> > diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
> > index 9b5bdd083b6f..d10e73cd7413 100644
> > --- a/include/net/af_vsock.h
> > +++ b/include/net/af_vsock.h
> > @@ -126,7 +126,7 @@ struct vsock_transport {
> > size_t len, int flags);
> > int (*dgram_enqueue)(struct vsock_sock *, struct sockaddr_vm *,
> > struct msghdr *, size_t len);
> > - bool (*dgram_allow)(u32 cid, u32 port);
> > + bool (*dgram_allow)(struct vsock_sock *vsk, u32 cid, u32 port);
> >
> > /* STREAM. */
> > /* TODO: stream_bind() */
> > @@ -138,14 +138,14 @@ struct vsock_transport {
> > s64 (*stream_has_space)(struct vsock_sock *);
> > u64 (*stream_rcvhiwat)(struct vsock_sock *);
> > bool (*stream_is_active)(struct vsock_sock *);
> > - bool (*stream_allow)(u32 cid, u32 port);
> > + bool (*stream_allow)(struct vsock_sock *vsk, u32 cid, u32 port);
> >
> > /* SEQ_PACKET. */
> > ssize_t (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,
> > int flags);
> > int (*seqpacket_enqueue)(struct vsock_sock *vsk, struct msghdr *msg,
> > size_t len);
> > - bool (*seqpacket_allow)(u32 remote_cid);
> > + bool (*seqpacket_allow)(struct vsock_sock *vsk, u32 remote_cid);
> > u32 (*seqpacket_has_data)(struct vsock_sock *vsk);
> >
> > /* Notification. */
> > @@ -218,6 +218,13 @@ void vsock_remove_connected(struct vsock_sock *vsk);
> > struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
> > struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
> > struct sockaddr_vm *dst);
> > +struct sock *vsock_find_bound_socket_net(struct sockaddr_vm *addr,
> > + struct net *net,
> > + enum vsock_net_mode net_mode);
> > +struct sock *vsock_find_connected_socket_net(struct sockaddr_vm *src,
> > + struct sockaddr_vm *dst,
> > + struct net *net,
> > + enum vsock_net_mode net_mode);
> > void vsock_remove_sock(struct vsock_sock *vsk);
> > void vsock_for_each_connected_socket(struct vsock_transport *transport,
> > void (*fn)(struct sock *sk));
> > diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> > index adcba1b7bf74..6113c22db8dc 100644
> > --- a/net/vmw_vsock/af_vsock.c
> > +++ b/net/vmw_vsock/af_vsock.c
> > @@ -83,6 +83,46 @@
> > * TCP_ESTABLISHED - connected
> > * TCP_CLOSING - disconnecting
> > * TCP_LISTEN - listening
> > + *
> > + * - Namespaces in vsock support two different modes configured
> > + * through /proc/sys/net/vsock/ns_mode. The modes are "local" and "global".
> > + * Each mode defines how the namespace interacts with CIDs.
> > + * /proc/sys/net/vsock/ns_mode is write-once, so that it may be configured
> > + * and locked down by a namespace manager. The default is "global". The mode
> > + * is set per-namespace.
> > + *
> > + * The modes affect the allocation and accessibility of CIDs as follows:
> > + *
> > + * - global - access and allocation are all system-wide
>
> nit: maybe we should mention that this mode is primarily for backward
> compatibility, since it's the way how vsock worked before netns support.
>
> (We can fix later eventually with a followup patch)
>
> > + * - all CID allocation from global namespaces draw from the same
> > + * system-wide pool.
> > + * - if one global namespace has already allocated some CID, another
> > + * global namespace will not be able to allocate the same CID.
> > + * - global mode AF_VSOCK sockets can reach any VM or socket in any global
> > + * namespace, they are not contained to only their own namespace.
> > + * - AF_VSOCK sockets in a global mode namespace cannot reach VMs or
> > + * sockets in any local mode namespace.
> > + * - local - access and allocation are contained within the namespace
> > + * - CID allocation draws only from a private pool local only to the
> > + * namespace, and does not affect the CIDs available for allocation in any
> > + * other namespace (global or local).
> > + * - VMs in a local namespace do not collide with CIDs in any other local
> > + * namespace or any global namespace. For example, if a VM in a local mode
> > + * namespace is given CID 10, then CID 10 is still available for
> > + * allocation in any other namespace, but not in the same namespace.
> > + * - AF_VSOCK sockets in a local mode namespace can connect only to VMs or
> > + * other sockets within their own namespace.
> > + * - sockets bound to VMADDR_CID_ANY in local namespaces will never resolve
> > + * to any transport that is not compatible with local mode. There is no
> > + * error that propagates to the user (as there is for connection attempts)
> > + * because it is possible for some packet to reach this socket from
> > + * a different transport that *does* support local mode. For
> > + * example, virtio-vsock may not support local mode, but the socket
> > + * may still accept a connection from vhost-vsock which does.
> > + *
> > + * - when a socket or device is initialized in a namespace with mode
> > + * global, it will stay in global mode even if the namespace later
> > + * changes to local.
> > */
> >
> > #include <linux/compat.h>
> > @@ -100,6 +140,7 @@
> > #include <linux/module.h>
> > #include <linux/mutex.h>
> > #include <linux/net.h>
> > +#include <linux/proc_fs.h>
> > #include <linux/poll.h>
> > #include <linux/random.h>
> > #include <linux/skbuff.h>
> > @@ -111,9 +152,18 @@
> > #include <linux/workqueue.h>
> > #include <net/sock.h>
> > #include <net/af_vsock.h>
> > +#include <net/netns/vsock.h>
> > #include <uapi/linux/vm_sockets.h>
> > #include <uapi/asm-generic/ioctls.h>
> >
> > +#define VSOCK_NET_MODE_STR_GLOBAL "global"
> > +#define VSOCK_NET_MODE_STR_LOCAL "local"
> > +
> > +/* 6 chars for "global", 1 for null-terminator, and 1 more for '\n'.
> > + * The newline is added by proc_dostring() for read operations.
> > + */
> > +#define VSOCK_NET_MODE_STR_MAX 8
> > +
> > static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
> > static void vsock_sk_destruct(struct sock *sk);
> > static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
> > @@ -235,33 +285,47 @@ static void __vsock_remove_connected(struct vsock_sock *vsk)
> > sock_put(&vsk->sk);
> > }
> >
> > -static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
> > +static struct sock *__vsock_find_bound_socket_net(struct sockaddr_vm *addr,
> > + struct net *net,
> > + enum vsock_net_mode net_mode)
> > {
> > struct vsock_sock *vsk;
> >
> > list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table) {
> > - if (vsock_addr_equals_addr(addr, &vsk->local_addr))
> > - return sk_vsock(vsk);
> > + struct sock *sk = sk_vsock(vsk);
> > +
> > + if (vsock_addr_equals_addr(addr, &vsk->local_addr) &&
> > + vsock_net_check_mode(sock_net(sk), vsk->net_mode, net,
> > + net_mode))
> > + return sk;
> >
> > if (addr->svm_port == vsk->local_addr.svm_port &&
> > (vsk->local_addr.svm_cid == VMADDR_CID_ANY ||
> > - addr->svm_cid == VMADDR_CID_ANY))
> > - return sk_vsock(vsk);
> > + addr->svm_cid == VMADDR_CID_ANY) &&
> > + vsock_net_check_mode(sock_net(sk), vsk->net_mode, net,
> > + net_mode))
> > + return sk;
> > }
> >
> > return NULL;
> > }
> >
> > -static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
> > - struct sockaddr_vm *dst)
> > +static struct sock *
> > +__vsock_find_connected_socket_net(struct sockaddr_vm *src,
> > + struct sockaddr_vm *dst, struct net *net,
> > + enum vsock_net_mode net_mode)
> > {
> > struct vsock_sock *vsk;
> >
> > list_for_each_entry(vsk, vsock_connected_s)ckets(src, dst),
> > connected_table) {
> > + struct sock *sk = sk_vsock(vsk);
> > +
> > if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
> > - dst->svm_port == vsk->local_addr.svm_port) {
> > - return sk_vsock(vsk);
> > + dst->svm_port == vsk->local_addr.svm_port &&
> > + vsock_net_check_mode(sock_net(sk), vsk->net_mode, net,
> > + net_mode)) {
> > + return sk;
> > }
> > }
> >
> > @@ -304,12 +368,14 @@ void vsock_remove_connected(struct vsock_sock *vsk)
> > }
> > EXPORT_SYMBOL_GPL(vsock_remove_connected);
> >
> > -struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr)
> > +struct sock *vsock_find_bound_socket_net(struct sockaddr_vm *addr,
> > + struct net *net,
> > + enum vsock_net_mode net_mode)
> > {
> > struct sock *sk;
> >
> > spin_lock_bh(&vsock_table_lock);
> > - sk = __vsock_find_bound_socket(addr);
> > + sk = __vsock_find_bound_socket_net(addr, net, net_mode);
> > if (sk)
> > sock_hold(sk);
> >
> > @@ -317,15 +383,23 @@ struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr)
> >
> > return sk;
> > }
> > +EXPORT_SYMBOL_GPL(vsock_find_bound_socket_net);
> > +
> > +struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr)
> > +{
> > + return vsock_find_bound_socket_net(addr, NULL, VSOCK_NET_MODE_GLOBAL);
>
> The patch LGTM, my last doubt now is if here (and in
> vsock_find_connected_socket() ) we should use `init_net`.
>
> In practice, this is the namespace (NULL) and mode (GLOBAL) used by
> transports that do not support namespaces.
>
> So here we are making them belong to no namespace, so they can only reach
> global ones. When any namespace, including `init_net`, switches to local, it
> can no longer be reached by transports that do not support local namespaces,
> because in practice we still do not have a way to associate a device (in the
> case of drivers) with a specific namespace. Right?
Right.
>
> If I get it right, it can makes sense, but I'd like an ack from net
> maintainers to be sure we are doing the right things.
>
> Also I think we should have a comment on top of this function to make it
> clear that should be used only by transport that doesn't support namespace,
> and the reason why we used NULL and GLOBAL. Plus a comment on top of this
> file (near where we described local vs global) to clarify the status of
> this.
>
> That said, if next week net-next will close, I think we can send a follow-up
> patch just for those comments, so:
Sounds good, I'll wait for further feedback before sending anything!
>
> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
>
> > +}
> > EXPORT_SYMBOL_GPL(vsock_find_bound_socket);
> >
> > -struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
> > - struct sockaddr_vm *dst)
> > +struct sock *vsock_find_connected_socket_net(struct sockaddr_vm *src,
> > + struct sockaddr_vm *dst,
> > + struct net *net,
> > + enum vsock_net_mode net_mode)
> > {
> > struct sock *sk;
> >
> > spin_lock_bh(&vsock_table_lock);
> > - sk = __vsock_find_connected_socket(src, dst);
> > + sk = __vsock_find_connected_socket_net(src, dst, net, net_mode);
> > if (sk)
> > sock_hold(sk);
> >
> > @@ -333,6 +407,14 @@ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
> >
> > return sk;
> > }
> > +EXPORT_SYMBOL_GPL(vsock_find_connected_socket_net);
> > +
> > +struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
> > + struct sockaddr_vm *dst)
> > +{
> > + return vsock_find_connected_socket_net(src, dst,
> > + NULL, VSOCK_NET_MODE_GLOBAL);
> > +}
> > EXPORT_SYMBOL_GPL(vsock_find_connected_socket);
>
^ permalink raw reply
* Re: [PATCH net-next v12 00/12] vsock: add namespace support to vhost-vsock and loopback
From: Stefano Garzarella @ 2025-11-27 15:17 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman
Cc: Bobby Eshleman, Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan, linux-kernel,
virtualization, netdev, kvm, linux-hyperv, linux-kselftest,
berrange, Sargun Dhillon, Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-0-257ee21cd5de@meta.com>
On Wed, Nov 26, 2025 at 11:47:29PM -0800, Bobby Eshleman wrote:
>This series adds namespace support to vhost-vsock and loopback. It does
>not add namespaces to any of the other guest transports (virtio-vsock,
>hyperv, or vmci).
Jakub, Paolo, and other net maintainers, I left my R-b on all the
patches in this series and I think it's ready to go.
I just have one doubt about the second patch. From my point of view, I
think it makes sense, but I would like your opinion regarding the netns:
https://lore.kernel.org/netdev/hgz3rtpb3lvxzbygye6ziobfujfsl2yefh5t3ghrbbbknr6eis@ypifkm24ygja/
Thanks,
Stefano
>
>The current revision supports two modes: local and global. Local
>mode is complete isolation of namespaces, while global mode is complete
>sharing between namespaces of CIDs (the original behavior).
>
>The mode is set using /proc/sys/net/vsock/ns_mode.
>
>Modes are per-netns and write-once. This allows a system to configure
>namespaces independently (some may share CIDs, others are completely
>isolated). This also supports future possible mixed use cases, where
>there may be namespaces in global mode spinning up VMs while there are
>mixed mode namespaces that provide services to the VMs, but are not
>allowed to allocate from the global CID pool (this mode is not
>implemented in this series).
>
>If a socket or VM is created when a namespace is global but the
>namespace changes to local, the socket or VM will continue working
>normally. That is, the socket or VM assumes the mode behavior of the
>namespace at the time the socket/VM was created. The original mode is
>captured in vsock_create() and so occurs at the time of socket(2) and
>accept(2) for sockets and open(2) on /dev/vhost-vsock for VMs. This
>prevents a socket/VM connection from suddenly breaking due to a
>namespace mode change. Any new sockets/VMs created after the mode change
>will adopt the new mode's behavior.
>
>Additionally, added tests for the new namespace features:
>
>tools/testing/selftests/vsock/vmtest.sh
>1..28
>ok 1 vm_server_host_client
>ok 2 vm_client_host_server
>ok 3 vm_loopback
>ok 4 ns_host_vsock_ns_mode_ok
>ok 5 ns_host_vsock_ns_mode_write_once_ok
>ok 6 ns_global_same_cid_fails
>ok 7 ns_local_same_cid_ok
>ok 8 ns_global_local_same_cid_ok
>ok 9 ns_local_global_same_cid_ok
>ok 10 ns_diff_global_host_connect_to_global_vm_ok
>ok 11 ns_diff_global_host_connect_to_local_vm_fails
>ok 12 ns_diff_global_vm_connect_to_global_host_ok
>ok 13 ns_diff_global_vm_connect_to_local_host_fails
>ok 14 ns_diff_local_host_connect_to_local_vm_fails
>ok 15 ns_diff_local_vm_connect_to_local_host_fails
>ok 16 ns_diff_global_to_local_loopback_local_fails
>ok 17 ns_diff_local_to_global_loopback_fails
>ok 18 ns_diff_local_to_local_loopback_fails
>ok 19 ns_diff_global_to_global_loopback_ok
>ok 20 ns_same_local_loopback_ok
>ok 21 ns_same_local_host_connect_to_local_vm_ok
>ok 22 ns_same_local_vm_connect_to_local_host_ok
>ok 23 ns_mode_change_connection_continue_vm_ok
>ok 24 ns_mode_change_connection_continue_host_ok
>ok 25 ns_mode_change_connection_continue_both_ok
>ok 26 ns_delete_vm_ok
>ok 27 ns_delete_host_ok
>ok 28 ns_delete_both_ok
>SUMMARY: PASS=28 SKIP=0 FAIL=0
>
>Dependent on series:
>https://lore.kernel.org/all/20251108-vsock-selftests-fixes-and-improvements-v4-0-d5e8d6c87289@meta.com/
>
>Thanks again for everyone's help and reviews!
>
>Suggested-by: Sargun Dhillon <sargun@sargun.me>
>Signed-off-by: Bobby Eshleman <bobbyeshleman@gmail.com>
>
>Changes in v12:
>- add ns mode checking to _allow() callbacks to reject local mode for
> incompatible transports (Stefano)
>- flip vhost/loopback to return true for stream_allow() and
> seqpacket_allow() in "vsock: add netns support to virtio transports"
> (Stefano)
>- add VMADDR_CID_ANY + local mode documentation in af_vsock.c (Stefano)
>- change "selftests/vsock: add tests for host <-> vm connectivity with
> namespaces" to skip test 29 in vsock_test for namespace local
> vsock_test calls in a host local-mode namespace. There is a
> false-positive edge case for that test encountered with the
> ->stream_allow() approach. More details in that patch.
>- updated cover letter with new test output
>- Link to v11: https://lore.kernel.org/r/20251120-vsock-vmtest-v11-0-55cbc80249a7@meta.com
>
>Changes in v11:
>- vmtest: add a patch to use ss in wait_for_listener functions and
> support vsock, tcp, and unix. Change all patches to use the new
> functions.
>- vmtest: add a patch to re-use vm dmesg / warn counting functions
>- Link to v10: https://lore.kernel.org/r/20251117-vsock-vmtest-v10-0-df08f165bf3e@meta.com
>
>Changes in v10:
>- Combine virtio common patches into one (Stefano)
>- Resolve vsock_loopback virtio_transport_reset_no_sock() issue
> with info->vsk setting. This eliminates the need for skb->cb,
> so remove skb->cb patches.
>- many line width 80 fixes
>- Link to v9: https://lore.kernel.org/all/20251111-vsock-vmtest-v9-0-852787a37bed@meta.com
>
>Changes in v9:
>- reorder loopback patch after patch for virtio transport common code
>- remove module ordering tests patch because loopback no longer depends
> on pernet ops
>- major simplifications in vsock_loopback
>- added a new patch for blocking local mode for guests, added test case
> to check
>- add net ref tracking to vsock_loopback patch
>- Link to v8: https://lore.kernel.org/r/20251023-vsock-vmtest-v8-0-dea984d02bb0@meta.com
>
>Changes in v8:
>- Break generic cleanup/refactoring patches into standalone series,
> remove those from this series
>- Link to dependency: https://lore.kernel.org/all/20251022-vsock-selftests-fixes-and-improvements-v1-0-edeb179d6463@meta.com/
>- Link to v7: https://lore.kernel.org/r/20251021-vsock-vmtest-v7-0-0661b7b6f081@meta.com
>
>Changes in v7:
>- fix hv_sock build
>- break out vmtest patches into distinct, more well-scoped patches
>- change `orig_net_mode` to `net_mode`
>- many fixes and style changes in per-patch change sets (see individual
> patches for specific changes)
>- optimize `virtio_vsock_skb_cb` layout
>- update commit messages with more useful descriptions
>- vsock_loopback: use orig_net_mode instead of current net mode
>- add tests for edge cases (ns deletion, mode changing, loopback module
> load ordering)
>- Link to v6: https://lore.kernel.org/r/20250916-vsock-vmtest-v6-0-064d2eb0c89d@meta.com
>
>Changes in v6:
>- define behavior when mode changes to local while socket/VM is alive
>- af_vsock: clarify description of CID behavior
>- af_vsock: use stronger langauge around CID rules (dont use "may")
>- af_vsock: improve naming of buf/buffer
>- af_vsock: improve string length checking on proc writes
>- vsock_loopback: add space in struct to clarify lock protection
>- vsock_loopback: do proper cleanup/unregister on vsock_loopback_exit()
>- vsock_loopback: use virtio_vsock_skb_net() instead of sock_net()
>- vsock_loopback: set loopback to NULL after kfree()
>- vsock_loopback: use pernet_operations and remove callback mechanism
>- vsock_loopback: add macros for "global" and "local"
>- vsock_loopback: fix length checking
>- vmtest.sh: check for namespace support in vmtest.sh
>- Link to v5: https://lore.kernel.org/r/20250827-vsock-vmtest-v5-0-0ba580bede5b@meta.com
>
>Changes in v5:
>- /proc/net/vsock_ns_mode -> /proc/sys/net/vsock/ns_mode
>- vsock_global_net -> vsock_global_dummy_net
>- fix netns lookup in vhost_vsock to respect pid namespaces
>- add callbacks for vsock_loopback to avoid circular dependency
>- vmtest.sh loads vsock_loopback module
>- remove vsock_net_mode_can_set()
>- change vsock_net_write_mode() to return true/false based on success
>- make vsock_net_mode enum instead of u8
>- Link to v4: https://lore.kernel.org/r/20250805-vsock-vmtest-v4-0-059ec51ab111@meta.com
>
>Changes in v4:
>- removed RFC tag
>- implemented loopback support
>- renamed new tests to better reflect behavior
>- completed suite of tests with permutations of ns modes and vsock_test
> as guest/host
>- simplified socat bridging with unix socket instead of tcp + veth
>- only use vsock_test for success case, socat for failure case (context
> in commit message)
>- lots of cleanup
>
>Changes in v3:
>- add notion of "modes"
>- add procfs /proc/net/vsock_ns_mode
>- local and global modes only
>- no /dev/vhost-vsock-netns
>- vmtest.sh already merged, so new patch just adds new tests for NS
>- Link to v2:
> https://lore.kernel.org/kvm/20250312-vsock-netns-v2-0-84bffa1aa97a@gmail.com
>
>Changes in v2:
>- only support vhost-vsock namespaces
>- all g2h namespaces retain old behavior, only common API changes
> impacted by vhost-vsock changes
>- add /dev/vhost-vsock-netns for "opt-in"
>- leave /dev/vhost-vsock to old behavior
>- removed netns module param
>- Link to v1:
> https://lore.kernel.org/r/20200116172428.311437-1-sgarzare@redhat.com
>
>Changes in v1:
>- added 'netns' module param to vsock.ko to enable the
> network namespace support (disabled by default)
>- added 'vsock_net_eq()' to check the "net" assigned to a socket
> only when 'netns' support is enabled
>- Link to RFC: https://patchwork.ozlabs.org/cover/1202235/
>
>---
>Bobby Eshleman (12):
> vsock: a per-net vsock NS mode state
> vsock: add netns to vsock core
> virtio: set skb owner of virtio_transport_reset_no_sock() reply
> vsock: add netns support to virtio transports
> selftests/vsock: add namespace helpers to vmtest.sh
> selftests/vsock: prepare vm management helpers for namespaces
> selftests/vsock: add vm_dmesg_{warn,oops}_count() helpers
> selftests/vsock: use ss to wait for listeners instead of /proc/net
> selftests/vsock: add tests for proc sys vsock ns_mode
> selftests/vsock: add namespace tests for CID collisions
> selftests/vsock: add tests for host <-> vm connectivity with namespaces
> selftests/vsock: add tests for namespace deletion and mode changes
>
> MAINTAINERS | 1 +
> drivers/vhost/vsock.c | 59 +-
> include/linux/virtio_vsock.h | 12 +-
> include/net/af_vsock.h | 57 +-
> include/net/net_namespace.h | 4 +
> include/net/netns/vsock.h | 17 +
> net/vmw_vsock/af_vsock.c | 272 +++++++-
> net/vmw_vsock/hyperv_transport.c | 7 +-
> net/vmw_vsock/virtio_transport.c | 19 +-
> net/vmw_vsock/virtio_transport_common.c | 75 ++-
> net/vmw_vsock/vmci_transport.c | 26 +-
> net/vmw_vsock/vsock_loopback.c | 23 +-
> tools/testing/selftests/vsock/vmtest.sh | 1077 +++++++++++++++++++++++++++++--
> 13 files changed, 1522 insertions(+), 127 deletions(-)
>---
>base-commit: 962ac5ca99a5c3e7469215bf47572440402dfd59
>change-id: 20250325-vsock-vmtest-b3a21d2102c2
>prerequisite-message-id: <20251022-vsock-selftests-fixes-and-improvements-v1-0-edeb179d6463@meta.com>
>prerequisite-patch-id: a2eecc3851f2509ed40009a7cab6990c6d7cfff5
>prerequisite-patch-id: 501db2100636b9c8fcb3b64b8b1df797ccbede85
>prerequisite-patch-id: ba1a2f07398a035bc48ef72edda41888614be449
>prerequisite-patch-id: fd5cc5445aca9355ce678e6d2bfa89fab8a57e61
>prerequisite-patch-id: 795ab4432ffb0843e22b580374782e7e0d99b909
>prerequisite-patch-id: 1499d263dc933e75366c09e045d2125ca39f7ddd
>prerequisite-patch-id: f92d99bb1d35d99b063f818a19dcda999152d74c
>prerequisite-patch-id: e3296f38cdba6d903e061cff2bbb3e7615e8e671
>prerequisite-patch-id: bc4662b4710d302d4893f58708820fc2a0624325
>prerequisite-patch-id: f8991f2e98c2661a706183fde6b35e2b8d9aedcf
>prerequisite-patch-id: 44bf9ed69353586d284e5ee63d6fffa30439a698
>prerequisite-patch-id: d50621bc630eeaf608bbaf260370c8dabf6326df
>
>Best regards,
>--
>Bobby Eshleman <bobbyeshleman@meta.com>
>
^ permalink raw reply
* Re: [PATCH net-next v12 11/12] selftests/vsock: add tests for host <-> vm connectivity with namespaces
From: Stefano Garzarella @ 2025-11-27 14:49 UTC (permalink / raw)
To: Bobby Eshleman
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan, linux-kernel,
virtualization, netdev, kvm, linux-hyperv, linux-kselftest,
berrange, Sargun Dhillon, Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-11-257ee21cd5de@meta.com>
On Wed, Nov 26, 2025 at 11:47:40PM -0800, Bobby Eshleman wrote:
>From: Bobby Eshleman <bobbyeshleman@meta.com>
>
>Add tests to validate namespace correctness using vsock_test and socat.
>The vsock_test tool is used to validate expected success tests, but
>socat is used for expected failure tests. socat is used to ensure that
>connections are rejected outright instead of failing due to some other
>socket behavior (as tested in vsock_test). Additionally, socat is
>already required for tunneling TCP traffic from vsock_test. Using only
>one of the vsock_test tests like 'test_stream_client_close_client' would
>have yielded a similar result, but doing so wouldn't remove the socat
>dependency.
>
>Additionally, check for the dependency socat. socat needs special
>handling beyond just checking if it is on the path because it must be
>compiled with support for both vsock and unix. The function
>check_socat() checks that this support exists.
>
>Add more padding to test name printf strings because the tests added in
>this patch would otherwise overflow.
>
>Add vm_dmesg_* helpers to encapsulate checking dmesg
>for oops and warnings.
>
>Add ability to pass extra args to host-side vsock_test so that tests
>that cause false positives may be skipped with arg --skip.
>
>Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
>---
>Changes in v12:
>- add test skip (vsock_test test 29) when host_vsock_test() uses client
> mode in a local namespace. Test 29 causes a false positive to trigger.
I see, LGTM and thanks for adding a comment with the reason!
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
>
>Changes in v11:
>- add 'sleep "${WAIT_PERIOD}"' after any non-TCP socat LISTEN cmd
> (Stefano)
>- add host_wait_for_listener() after any socat TCP-LISTEN (Stefano)
>- reuse vm_dmesg_{oops,warn}_count() inside vm_dmesg_check()
>- fix copy-paste in test_ns_same_local_vm_connect_to_local_host_ok()
> (Stefano)
>
>Changes in v10:
>- add vm_dmesg_start() and vm_dmesg_check()
>
>Changes in v9:
>- consistent variable quoting
>---
> tools/testing/selftests/vsock/vmtest.sh | 572 +++++++++++++++++++++++++++++++-
> 1 file changed, 568 insertions(+), 4 deletions(-)
>
>diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
>index ec18eb5b4ccd..da9198dc8ab5 100755
>--- a/tools/testing/selftests/vsock/vmtest.sh
>+++ b/tools/testing/selftests/vsock/vmtest.sh
>@@ -7,6 +7,7 @@
> # * virtme-ng
> # * busybox-static (used by virtme-ng)
> # * qemu (used by virtme-ng)
>+# * socat
> #
> # shellcheck disable=SC2317,SC2119
>
>@@ -54,6 +55,19 @@ readonly TEST_NAMES=(
> ns_local_same_cid_ok
> ns_global_local_same_cid_ok
> ns_local_global_same_cid_ok
>+ ns_diff_global_host_connect_to_global_vm_ok
>+ ns_diff_global_host_connect_to_local_vm_fails
>+ ns_diff_global_vm_connect_to_global_host_ok
>+ ns_diff_global_vm_connect_to_local_host_fails
>+ ns_diff_local_host_connect_to_local_vm_fails
>+ ns_diff_local_vm_connect_to_local_host_fails
>+ ns_diff_global_to_local_loopback_local_fails
>+ ns_diff_local_to_global_loopback_fails
>+ ns_diff_local_to_local_loopback_fails
>+ ns_diff_global_to_global_loopback_ok
>+ ns_same_local_loopback_ok
>+ ns_same_local_host_connect_to_local_vm_ok
>+ ns_same_local_vm_connect_to_local_host_ok
> )
> readonly TEST_DESCS=(
> # vm_server_host_client
>@@ -82,6 +96,45 @@ readonly TEST_DESCS=(
>
> # ns_local_global_same_cid_ok
> "Check QEMU successfully starts one VM in a local ns and then another VM in a global ns with the same CID."
>+
>+ # ns_diff_global_host_connect_to_global_vm_ok
>+ "Run vsock_test client in global ns with server in VM in another global ns."
>+
>+ # ns_diff_global_host_connect_to_local_vm_fails
>+ "Run socat to test a process in a global ns fails to connect to a VM in a local ns."
>+
>+ # ns_diff_global_vm_connect_to_global_host_ok
>+ "Run vsock_test client in VM in a global ns with server in another global ns."
>+
>+ # ns_diff_global_vm_connect_to_local_host_fails
>+ "Run socat to test a VM in a global ns fails to connect to a host process in a local ns."
>+
>+ # ns_diff_local_host_connect_to_local_vm_fails
>+ "Run socat to test a host process in a local ns fails to connect to a VM in another local ns."
>+
>+ # ns_diff_local_vm_connect_to_local_host_fails
>+ "Run socat to test a VM in a local ns fails to connect to a host process in another local ns."
>+
>+ # ns_diff_global_to_local_loopback_local_fails
>+ "Run socat to test a loopback vsock in a global ns fails to connect to a vsock in a local ns."
>+
>+ # ns_diff_local_to_global_loopback_fails
>+ "Run socat to test a loopback vsock in a local ns fails to connect to a vsock in a global ns."
>+
>+ # ns_diff_local_to_local_loopback_fails
>+ "Run socat to test a loopback vsock in a local ns fails to connect to a vsock in another local ns."
>+
>+ # ns_diff_global_to_global_loopback_ok
>+ "Run socat to test a loopback vsock in a global ns successfully connects to a vsock in another global ns."
>+
>+ # ns_same_local_loopback_ok
>+ "Run socat to test a loopback vsock in a local ns successfully connects to a vsock in the same ns."
>+
>+ # ns_same_local_host_connect_to_local_vm_ok
>+ "Run vsock_test client in a local ns with server in VM in same ns."
>+
>+ # ns_same_local_vm_connect_to_local_host_ok
>+ "Run vsock_test client in VM in a local ns with server in same ns."
> )
>
> readonly USE_SHARED_VM=(
>@@ -112,7 +165,7 @@ usage() {
> for ((i = 0; i < ${#TEST_NAMES[@]}; i++)); do
> name=${TEST_NAMES[${i}]}
> desc=${TEST_DESCS[${i}]}
>- printf "\t%-35s%-35s\n" "${name}" "${desc}"
>+ printf "\t%-55s%-35s\n" "${name}" "${desc}"
> done
> echo
>
>@@ -231,7 +284,7 @@ check_args() {
> }
>
> check_deps() {
>- for dep in vng ${QEMU} busybox pkill ssh ss; do
>+ for dep in vng ${QEMU} busybox pkill ssh ss socat; do
> if [[ ! -x $(command -v "${dep}") ]]; then
> echo -e "skip: dependency ${dep} not found!\n"
> exit "${KSFT_SKIP}"
>@@ -282,6 +335,20 @@ check_vng() {
> fi
> }
>
>+check_socat() {
>+ local support_string
>+
>+ support_string="$(socat -V)"
>+
>+ if [[ "${support_string}" != *"WITH_VSOCK 1"* ]]; then
>+ die "err: socat is missing vsock support"
>+ fi
>+
>+ if [[ "${support_string}" != *"WITH_UNIX 1"* ]]; then
>+ die "err: socat is missing unix support"
>+ fi
>+}
>+
> handle_build() {
> if [[ ! "${BUILD}" -eq 1 ]]; then
> return
>@@ -330,6 +397,14 @@ terminate_pidfiles() {
> done
> }
>
>+terminate_pids() {
>+ local pid
>+
>+ for pid in "$@"; do
>+ kill -SIGTERM "${pid}" &>/dev/null || :
>+ done
>+}
>+
> vm_start() {
> local pidfile=$1
> local ns=$2
>@@ -468,6 +543,28 @@ vm_dmesg_warn_count() {
> vm_ssh "${ns}" -- dmesg --level=warn 2>/dev/null | grep -c -i 'vsock'
> }
>
>+vm_dmesg_check() {
>+ local pidfile=$1
>+ local ns=$2
>+ local oops_before=$3
>+ local warn_before=$4
>+ local oops_after warn_after
>+
>+ oops_after=$(vm_dmesg_oops_count "${ns}")
>+ if [[ "${oops_after}" -gt "${oops_before}" ]]; then
>+ echo "FAIL: kernel oops detected on vm in ns ${ns}" | log_host
>+ return 1
>+ fi
>+
>+ warn_after=$(vm_dmesg_warn_count "${ns}")
>+ if [[ "${warn_after}" -gt "${warn_before}" ]]; then
>+ echo "FAIL: kernel warning detected on vm in ns ${ns}" | log_host
>+ return 1
>+ fi
>+
>+ return 0
>+}
>+
> vm_vsock_test() {
> local ns=$1
> local host=$2
>@@ -511,6 +608,8 @@ host_vsock_test() {
> local host=$2
> local cid=$3
> local port=$4
>+ shift 4
>+ local extra_args=("$@")
> local rc
>
> local cmd="${VSOCK_TEST}"
>@@ -525,13 +624,15 @@ host_vsock_test() {
> --mode=client \
> --peer-cid="${cid}" \
> --control-host="${host}" \
>- --control-port="${port}" 2>&1 | log_host
>+ --control-port="${port}" \
>+ "${extra_args[@]}" 2>&1 | log_host
> rc=$?
> else
> ${cmd} \
> --mode=server \
> --peer-cid="${cid}" \
>- --control-port="${port}" 2>&1 | log_host &
>+ --control-port="${port}" \
>+ "${extra_args[@]}" 2>&1 | log_host &
> rc=$?
>
> if [[ $rc -ne 0 ]]; then
>@@ -592,6 +693,468 @@ test_ns_host_vsock_ns_mode_ok() {
> return "${KSFT_PASS}"
> }
>
>+test_ns_diff_global_host_connect_to_global_vm_ok() {
>+ local oops_before warn_before
>+ local pids pid pidfile
>+ local ns0 ns1 port
>+ declare -a pids
>+ local unixfile
>+ ns0="global0"
>+ ns1="global1"
>+ port=1234
>+ local rc
>+
>+ init_namespaces
>+
>+ pidfile="$(create_pidfile)"
>+
>+ if ! vm_start "${pidfile}" "${ns0}"; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns0}"
>+ oops_before=$(vm_dmesg_oops_count "${ns0}")
>+ warn_before=$(vm_dmesg_warn_count "${ns0}")
>+
>+ unixfile=$(mktemp -u /tmp/XXXX.sock)
>+ ip netns exec "${ns1}" \
>+ socat TCP-LISTEN:"${TEST_HOST_PORT}",fork \
>+ UNIX-CONNECT:"${unixfile}" &
>+ pids+=($!)
>+ host_wait_for_listener "${ns1}" "${TEST_HOST_PORT}" "tcp"
>+
>+ ip netns exec "${ns0}" socat UNIX-LISTEN:"${unixfile}",fork \
>+ TCP-CONNECT:localhost:"${TEST_HOST_PORT}" &
>+ pids+=($!)
>+ host_wait_for_listener "${ns0}" "${unixfile}" "unix"
>+
>+ vm_vsock_test "${ns0}" "server" 2 "${TEST_GUEST_PORT}"
>+ vm_wait_for_listener "${ns0}" "${TEST_GUEST_PORT}" "tcp"
>+ host_vsock_test "${ns1}" "127.0.0.1" "${VSOCK_CID}" "${TEST_HOST_PORT}"
>+ rc=$?
>+
>+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pids "${pids[@]}"
>+ terminate_pidfiles "${pidfile}"
>+
>+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ return "${KSFT_PASS}"
>+}
>+
>+test_ns_diff_global_host_connect_to_local_vm_fails() {
>+ local oops_before warn_before
>+ local ns0="global0"
>+ local ns1="local0"
>+ local port=12345
>+ local dmesg_rc
>+ local pidfile
>+ local result
>+ local pid
>+
>+ init_namespaces
>+
>+ outfile=$(mktemp)
>+
>+ pidfile="$(create_pidfile)"
>+ if ! vm_start "${pidfile}" "${ns1}"; then
>+ log_host "failed to start vm (cid=${VSOCK_CID}, ns=${ns0})"
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns1}"
>+ oops_before=$(vm_dmesg_oops_count "${ns1}")
>+ warn_before=$(vm_dmesg_warn_count "${ns1}")
>+
>+ vm_ssh "${ns1}" -- socat VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" &
>+ vm_wait_for_listener "${ns1}" "${port}" "vsock"
>+ echo TEST | ip netns exec "${ns0}" \
>+ socat STDIN VSOCK-CONNECT:"${VSOCK_CID}":"${port}" 2>/dev/null
>+
>+ vm_dmesg_check "${pidfile}" "${ns1}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+ result=$(cat "${outfile}")
>+ rm -f "${outfile}"
>+
>+ if [[ "${result}" == "TEST" ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ return "${KSFT_PASS}"
>+}
>+
>+test_ns_diff_global_vm_connect_to_global_host_ok() {
>+ local oops_before warn_before
>+ local ns0="global0"
>+ local ns1="global1"
>+ local port=12345
>+ local unixfile
>+ local dmesg_rc
>+ local pidfile
>+ local pids
>+ local rc
>+
>+ init_namespaces
>+
>+ declare -a pids
>+
>+ log_host "Setup socat bridge from ns ${ns0} to ns ${ns1} over port ${port}"
>+
>+ unixfile=$(mktemp -u /tmp/XXXX.sock)
>+
>+ ip netns exec "${ns0}" \
>+ socat TCP-LISTEN:"${port}" UNIX-CONNECT:"${unixfile}" &
>+ pids+=($!)
>+ host_wait_for_listener "${ns0}" "${port}" "tcp"
>+
>+ ip netns exec "${ns1}" \
>+ socat UNIX-LISTEN:"${unixfile}" TCP-CONNECT:127.0.0.1:"${port}" &
>+ pids+=($!)
>+ host_wait_for_listener "${ns1}" "${unixfile}" "unix"
>+
>+ log_host "Launching ${VSOCK_TEST} in ns ${ns1}"
>+ host_vsock_test "${ns1}" "server" "${VSOCK_CID}" "${port}"
>+
>+ pidfile="$(create_pidfile)"
>+ if ! vm_start "${pidfile}" "${ns0}"; then
>+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
>+ terminate_pids "${pids[@]}"
>+ rm -f "${unixfile}"
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns0}"
>+
>+ oops_before=$(vm_dmesg_oops_count "${ns0}")
>+ warn_before=$(vm_dmesg_warn_count "${ns0}")
>+
>+ vm_vsock_test "${ns0}" "10.0.2.2" 2 "${port}"
>+ rc=$?
>+
>+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+ terminate_pids "${pids[@]}"
>+ rm -f "${unixfile}"
>+
>+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ return "${KSFT_PASS}"
>+
>+}
>+
>+test_ns_diff_global_vm_connect_to_local_host_fails() {
>+ local ns0="global0"
>+ local ns1="local0"
>+ local port=12345
>+ local oops_before warn_before
>+ local dmesg_rc
>+ local pidfile
>+ local result
>+ local pid
>+
>+ init_namespaces
>+
>+ log_host "Launching socat in ns ${ns1}"
>+ outfile=$(mktemp)
>+
>+ ip netns exec "${ns1}" socat VSOCK-LISTEN:"${port}" STDOUT &> "${outfile}" &
>+ pid=$!
>+ host_wait_for_listener "${ns1}" "${port}" "vsock"
>+
>+ pidfile="$(create_pidfile)"
>+ if ! vm_start "${pidfile}" "${ns0}"; then
>+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
>+ terminate_pids "${pid}"
>+ rm -f "${outfile}"
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns0}"
>+
>+ oops_before=$(vm_dmesg_oops_count "${ns0}")
>+ warn_before=$(vm_dmesg_warn_count "${ns0}")
>+
>+ vm_ssh "${ns0}" -- \
>+ bash -c "echo TEST | socat STDIN VSOCK-CONNECT:2:${port}" 2>&1 | log_guest
>+
>+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+ terminate_pids "${pid}"
>+
>+ result=$(cat "${outfile}")
>+ rm -f "${outfile}"
>+
>+ if [[ "${result}" != TEST ]] && [[ "${dmesg_rc}" -eq 0 ]]; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_diff_local_host_connect_to_local_vm_fails() {
>+ local ns0="local0"
>+ local ns1="local1"
>+ local port=12345
>+ local oops_before warn_before
>+ local dmesg_rc
>+ local pidfile
>+ local result
>+ local pid
>+
>+ init_namespaces
>+
>+ outfile=$(mktemp)
>+
>+ pidfile="$(create_pidfile)"
>+ if ! vm_start "${pidfile}" "${ns1}"; then
>+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns1}"
>+ oops_before=$(vm_dmesg_oops_count "${ns1}")
>+ warn_before=$(vm_dmesg_warn_count "${ns1}")
>+
>+ vm_ssh "${ns1}" -- socat VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" &
>+ vm_wait_for_listener "${ns1}" "${port}" "vsock"
>+
>+ echo TEST | ip netns exec "${ns0}" \
>+ socat STDIN VSOCK-CONNECT:"${VSOCK_CID}":"${port}" 2>/dev/null
>+
>+ vm_dmesg_check "${pidfile}" "${ns1}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+
>+ result=$(cat "${outfile}")
>+ rm -f "${outfile}"
>+
>+ if [[ "${result}" != TEST ]] && [[ "${dmesg_rc}" -eq 0 ]]; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_diff_local_vm_connect_to_local_host_fails() {
>+ local oops_before warn_before
>+ local ns0="local0"
>+ local ns1="local1"
>+ local port=12345
>+ local dmesg_rc
>+ local pidfile
>+ local result
>+ local pid
>+
>+ init_namespaces
>+
>+ log_host "Launching socat in ns ${ns1}"
>+ outfile=$(mktemp)
>+ ip netns exec "${ns1}" socat VSOCK-LISTEN:"${port}" STDOUT &> "${outfile}" &
>+ pid=$!
>+ host_wait_for_listener "${ns1}" "${port}" "vsock"
>+
>+ pidfile="$(create_pidfile)"
>+ if ! vm_start "${pidfile}" "${ns0}"; then
>+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
>+ rm -f "${outfile}"
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns0}"
>+ oops_before=$(vm_dmesg_oops_count "${ns0}")
>+ warn_before=$(vm_dmesg_warn_count "${ns0}")
>+
>+ vm_ssh "${ns0}" -- \
>+ bash -c "echo TEST | socat STDIN VSOCK-CONNECT:2:${port}" 2>&1 | log_guest
>+
>+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+ terminate_pids "${pid}"
>+
>+ result=$(cat "${outfile}")
>+ rm -f "${outfile}"
>+
>+ if [[ "${result}" != TEST ]] && [[ "${dmesg_rc}" -eq 0 ]]; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+__test_loopback_two_netns() {
>+ local ns0=$1
>+ local ns1=$2
>+ local port=12345
>+ local result
>+ local pid
>+
>+ modprobe vsock_loopback &> /dev/null || :
>+
>+ log_host "Launching socat in ns ${ns1}"
>+ outfile=$(mktemp)
>+
>+ ip netns exec "${ns1}" socat VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" 2>/dev/null &
>+ pid=$!
>+ host_wait_for_listener "${ns1}" "${port}" "vsock"
>+
>+ log_host "Launching socat in ns ${ns0}"
>+ echo TEST | ip netns exec "${ns0}" socat STDIN VSOCK-CONNECT:1:"${port}" 2>/dev/null
>+ terminate_pids "${pid}"
>+
>+ result=$(cat "${outfile}")
>+ rm -f "${outfile}"
>+
>+ if [[ "${result}" == TEST ]]; then
>+ return 0
>+ fi
>+
>+ return 1
>+}
>+
>+test_ns_diff_global_to_local_loopback_local_fails() {
>+ init_namespaces
>+
>+ if ! __test_loopback_two_netns "global0" "local0"; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_diff_local_to_global_loopback_fails() {
>+ init_namespaces
>+
>+ if ! __test_loopback_two_netns "local0" "global0"; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_diff_local_to_local_loopback_fails() {
>+ init_namespaces
>+
>+ if ! __test_loopback_two_netns "local0" "local1"; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_diff_global_to_global_loopback_ok() {
>+ init_namespaces
>+
>+ if __test_loopback_two_netns "global0" "global1"; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_same_local_loopback_ok() {
>+ init_namespaces
>+
>+ if __test_loopback_two_netns "local0" "local0"; then
>+ return "${KSFT_PASS}"
>+ fi
>+
>+ return "${KSFT_FAIL}"
>+}
>+
>+test_ns_same_local_host_connect_to_local_vm_ok() {
>+ local oops_before warn_before
>+ local ns="local0"
>+ local port=1234
>+ local dmesg_rc
>+ local pidfile
>+ local rc
>+
>+ init_namespaces
>+
>+ pidfile="$(create_pidfile)"
>+
>+ if ! vm_start "${pidfile}" "${ns}"; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns}"
>+ oops_before=$(vm_dmesg_oops_count "${ns}")
>+ warn_before=$(vm_dmesg_warn_count "${ns}")
>+
>+ vm_vsock_test "${ns}" "server" 2 "${TEST_GUEST_PORT}"
>+
>+ # Skip test 29 (transport release use-after-free): This test attempts
>+ # binding both G2H and H2G CIDs. Because virtio-vsock (G2H) doesn't
>+ # support local namespaces the test will fail when
>+ # transport_g2h->stream_allow() returns false. This edge case only
>+ # happens for vsock_test in client mode on the host in a local
>+ # namespace. This is a false positive.
>+ host_vsock_test "${ns}" "127.0.0.1" "${VSOCK_CID}" "${TEST_HOST_PORT}" --skip=29
>+ rc=$?
>+
>+ vm_dmesg_check "${pidfile}" "${ns}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+
>+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ return "${KSFT_PASS}"
>+}
>+
>+test_ns_same_local_vm_connect_to_local_host_ok() {
>+ local oops_before warn_before
>+ local ns="local0"
>+ local port=1234
>+ local dmesg_rc
>+ local pidfile
>+ local rc
>+
>+ init_namespaces
>+
>+ pidfile="$(create_pidfile)"
>+
>+ if ! vm_start "${pidfile}" "${ns}"; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ vm_wait_for_ssh "${ns}"
>+ oops_before=$(vm_dmesg_oops_count "${ns}")
>+ warn_before=$(vm_dmesg_warn_count "${ns}")
>+
>+ host_vsock_test "${ns}" "server" "${VSOCK_CID}" "${port}"
>+ vm_vsock_test "${ns}" "10.0.2.2" 2 "${port}"
>+ rc=$?
>+
>+ vm_dmesg_check "${pidfile}" "${ns}" "${oops_before}" "${warn_before}"
>+ dmesg_rc=$?
>+
>+ terminate_pidfiles "${pidfile}"
>+
>+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
>+ return "${KSFT_FAIL}"
>+ fi
>+
>+ return "${KSFT_PASS}"
>+}
>+
> namespaces_can_boot_same_cid() {
> local ns0=$1
> local ns1=$2
>@@ -869,6 +1432,7 @@ fi
> check_args "${ARGS[@]}"
> check_deps
> check_vng
>+check_socat
> handle_build
>
> echo "1..${#ARGS[@]}"
>
>--
>2.47.3
>
^ permalink raw reply
* Re: [PATCH net-next v12 04/12] vsock: add netns support to virtio transports
From: Stefano Garzarella @ 2025-11-27 14:44 UTC (permalink / raw)
To: Bobby Eshleman
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan, linux-kernel,
virtualization, netdev, kvm, linux-hyperv, linux-kselftest,
berrange, Sargun Dhillon, Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-4-257ee21cd5de@meta.com>
On Wed, Nov 26, 2025 at 11:47:33PM -0800, Bobby Eshleman wrote:
>From: Bobby Eshleman <bobbyeshleman@meta.com>
>
>Add netns support to loopback and vhost. Keep netns disabled for
>virtio-vsock, but add necessary changes to comply with common API
>updates.
>
>This is the patch in the series when vhost-vsock namespaces actually
>come online. Hence, vhost_transport_supports_local_mode() is switched
>to return true.
>
>Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
>---
>Changes in v12:
>- change seqpacket_allow() and stream_allow() to return true for
> loopback and vhost (Stefano)
>
>Changes in v11:
>- reorder with the skb ownership patch for loopback (Stefano)
>- toggle vhost_transport_supports_local_mode() to true
>
>Changes in v10:
>- Splitting patches complicates the series with meaningless placeholder
> values that eventually get replaced anyway, so to avoid that this
> patch combines into one. Links to previous patches here:
> - Link: https://lore.kernel.org/all/20251111-vsock-vmtest-v9-3-852787a37bed@meta.com/
> - Link: https://lore.kernel.org/all/20251111-vsock-vmtest-v9-6-852787a37bed@meta.com/
> - Link: https://lore.kernel.org/all/20251111-vsock-vmtest-v9-7-852787a37bed@meta.com/
>- remove placeholder values (Stefano)
>- update comment describe net/net_mode for
> virtio_transport_reset_no_sock()
>---
> drivers/vhost/vsock.c | 56 +++++++++++++++++++++--------
> include/linux/virtio_vsock.h | 8 +++--
> net/vmw_vsock/virtio_transport.c | 10 ++++--
> net/vmw_vsock/virtio_transport_common.c | 63 ++++++++++++++++++++++++---------
> net/vmw_vsock/vsock_loopback.c | 19 +++++++---
> 5 files changed, 118 insertions(+), 38 deletions(-)
>
>diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
>index 83937e1d63fa..82cb9ec09e78 100644
>--- a/drivers/vhost/vsock.c
>+++ b/drivers/vhost/vsock.c
>@@ -46,6 +46,11 @@ static DEFINE_READ_MOSTLY_HASHTABLE(vhost_vsock_hash, 8);
> struct vhost_vsock {
> struct vhost_dev dev;
> struct vhost_virtqueue vqs[2];
>+ struct net *net;
>+ netns_tracker ns_tracker;
>+
>+ /* The ns mode at the time vhost_vsock was created */
>+ enum vsock_net_mode net_mode;
>
> /* Link to global vhost_vsock_hash, writes use vhost_vsock_mutex */
> struct hlist_node hash;
>@@ -67,7 +72,8 @@ static u32 vhost_transport_get_local_cid(void)
> /* Callers that dereference the return value must hold vhost_vsock_mutex or the
> * RCU read lock.
> */
>-static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
>+static struct vhost_vsock *vhost_vsock_get(u32 guest_cid, struct net *net,
>+ enum vsock_net_mode mode)
> {
> struct vhost_vsock *vsock;
>
>@@ -78,9 +84,10 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
> if (other_cid == 0)
> continue;
>
>- if (other_cid == guest_cid)
>+ if (other_cid == guest_cid &&
>+ vsock_net_check_mode(net, mode, vsock->net,
>+ vsock->net_mode))
> return vsock;
>-
> }
>
> return NULL;
>@@ -269,7 +276,8 @@ static void vhost_transport_send_pkt_work(struct vhost_work *work)
> }
>
> static int
>-vhost_transport_send_pkt(struct sk_buff *skb)
>+vhost_transport_send_pkt(struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
> struct vhost_vsock *vsock;
>@@ -278,7 +286,7 @@ vhost_transport_send_pkt(struct sk_buff *skb)
> rcu_read_lock();
>
> /* Find the vhost_vsock according to guest context id */
>- vsock = vhost_vsock_get(le64_to_cpu(hdr->dst_cid));
>+ vsock = vhost_vsock_get(le64_to_cpu(hdr->dst_cid), net, net_mode);
> if (!vsock) {
> rcu_read_unlock();
> kfree_skb(skb);
>@@ -305,7 +313,8 @@ vhost_transport_cancel_pkt(struct vsock_sock *vsk)
> rcu_read_lock();
>
> /* Find the vhost_vsock according to guest context id */
>- vsock = vhost_vsock_get(vsk->remote_addr.svm_cid);
>+ vsock = vhost_vsock_get(vsk->remote_addr.svm_cid,
>+ sock_net(sk_vsock(vsk)), vsk->net_mode);
> if (!vsock)
> goto out;
>
>@@ -407,6 +416,12 @@ static bool vhost_transport_msgzerocopy_allow(void)
> static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk,
> u32 remote_cid);
>
>+static bool
>+vhost_transport_stream_allow(struct vsock_sock *vsk, u32 cid, u32 port)
>+{
>+ return true;
>+}
>+
> static struct virtio_transport vhost_transport = {
> .transport = {
> .module = THIS_MODULE,
>@@ -431,7 +446,7 @@ static struct virtio_transport vhost_transport = {
> .stream_has_space = virtio_transport_stream_has_space,
> .stream_rcvhiwat = virtio_transport_stream_rcvhiwat,
> .stream_is_active = virtio_transport_stream_is_active,
>- .stream_allow = virtio_transport_stream_allow,
>+ .stream_allow = vhost_transport_stream_allow,
>
> .seqpacket_dequeue = virtio_transport_seqpacket_dequeue,
> .seqpacket_enqueue = virtio_transport_seqpacket_enqueue,
>@@ -464,14 +479,12 @@ static struct virtio_transport vhost_transport = {
> static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk,
> u32 remote_cid)
> {
>+ struct net *net = sock_net(sk_vsock(vsk));
> struct vhost_vsock *vsock;
> bool seqpacket_allow = false;
>
>- if (vsk->net_mode != VSOCK_NET_MODE_GLOBAL)
>- return false;
>-
> rcu_read_lock();
>- vsock = vhost_vsock_get(remote_cid);
>+ vsock = vhost_vsock_get(remote_cid, net, vsk->net_mode);
>
> if (vsock)
> seqpacket_allow = vsock->seqpacket_allow;
>@@ -542,7 +555,8 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
> if (le64_to_cpu(hdr->src_cid) == vsock->guest_cid &&
> le64_to_cpu(hdr->dst_cid) ==
> vhost_transport_get_local_cid())
>- virtio_transport_recv_pkt(&vhost_transport, skb);
>+ virtio_transport_recv_pkt(&vhost_transport, skb,
>+ vsock->net, vsock->net_mode);
> else
> kfree_skb(skb);
>
>@@ -659,6 +673,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
> {
> struct vhost_virtqueue **vqs;
> struct vhost_vsock *vsock;
>+ struct net *net;
> int ret;
>
> /* This struct is large and allocation could fail, fall back to vmalloc
>@@ -674,6 +689,17 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
> goto out;
> }
>
>+ net = current->nsproxy->net_ns;
>+ vsock->net = get_net_track(net, &vsock->ns_tracker, GFP_KERNEL);
>+
>+ /* Store the mode of the namespace at the time of creation. If this
>+ * namespace later changes from "global" to "local", we want this vsock
>+ * to continue operating normally and not suddenly break. For that
>+ * reason, we save the mode here and later use it when performing
>+ * socket lookups with vsock_net_check_mode() (see vhost_vsock_get()).
>+ */
>+ vsock->net_mode = vsock_net_mode(net);
>+
> vsock->guest_cid = 0; /* no CID assigned yet */
> vsock->seqpacket_allow = false;
>
>@@ -713,7 +739,8 @@ static void vhost_vsock_reset_orphans(struct sock *sk)
> */
>
> /* If the peer is still valid, no need to reset connection */
>- if (vhost_vsock_get(vsk->remote_addr.svm_cid))
>+ if (vhost_vsock_get(vsk->remote_addr.svm_cid, sock_net(sk),
>+ vsk->net_mode))
> return;
>
> /* If the close timeout is pending, let it expire. This avoids races
>@@ -758,6 +785,7 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
> virtio_vsock_skb_queue_purge(&vsock->send_pkt_queue);
>
> vhost_dev_cleanup(&vsock->dev);
>+ put_net_track(vsock->net, &vsock->ns_tracker);
> kfree(vsock->dev.vqs);
> vhost_vsock_free(vsock);
> return 0;
>@@ -784,7 +812,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
>
> /* Refuse if CID is already in use */
> mutex_lock(&vhost_vsock_mutex);
>- other = vhost_vsock_get(guest_cid);
>+ other = vhost_vsock_get(guest_cid, vsock->net, vsock->net_mode);
> if (other && other != vsock) {
> mutex_unlock(&vhost_vsock_mutex);
> return -EADDRINUSE;
>diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
>index 1845e8d4f78d..7ea264dcfff7 100644
>--- a/include/linux/virtio_vsock.h
>+++ b/include/linux/virtio_vsock.h
>@@ -173,6 +173,8 @@ struct virtio_vsock_pkt_info {
> u32 remote_cid, remote_port;
> struct vsock_sock *vsk;
> struct msghdr *msg;
>+ struct net *net;
>+ enum vsock_net_mode net_mode;
> u32 pkt_len;
> u16 type;
> u16 op;
>@@ -185,7 +187,8 @@ struct virtio_transport {
> struct vsock_transport transport;
>
> /* Takes ownership of the packet */
>- int (*send_pkt)(struct sk_buff *skb);
>+ int (*send_pkt)(struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode);
>
> /* Used in MSG_ZEROCOPY mode. Checks, that provided data
> * (number of buffers) could be transmitted with zerocopy
>@@ -280,7 +283,8 @@ virtio_transport_dgram_enqueue(struct vsock_sock *vsk,
> void virtio_transport_destruct(struct vsock_sock *vsk);
>
> void virtio_transport_recv_pkt(struct virtio_transport *t,
>- struct sk_buff *skb);
>+ struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode);
> void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct sk_buff *skb);
> u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 wanted);
> void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit);
>diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
>index f5123810192d..3ff695740108 100644
>--- a/net/vmw_vsock/virtio_transport.c
>+++ b/net/vmw_vsock/virtio_transport.c
>@@ -231,7 +231,8 @@ static int virtio_transport_send_skb_fast_path(struct virtio_vsock *vsock, struc
> }
>
> static int
>-virtio_transport_send_pkt(struct sk_buff *skb)
>+virtio_transport_send_pkt(struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct virtio_vsock_hdr *hdr;
> struct virtio_vsock *vsock;
>@@ -665,7 +666,12 @@ static void virtio_transport_rx_work(struct work_struct *work)
> virtio_vsock_skb_put(skb, payload_len);
>
> virtio_transport_deliver_tap_pkt(skb);
>- virtio_transport_recv_pkt(&virtio_transport, skb);
>+
>+ /* Force virtio-transport into global mode since it
>+ * does not yet support local-mode namespacing.
>+ */
>+ virtio_transport_recv_pkt(&virtio_transport, skb,
>+ NULL, VSOCK_NET_MODE_GLOBAL);
This is related to the discussion of the previous patch I guess.
So if I get it right, it LGTM!
> }
> } while (!virtqueue_enable_cb(vq));
>
>diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
>index de71e2b3f77e..a818152d8b79 100644
>--- a/net/vmw_vsock/virtio_transport_common.c
>+++ b/net/vmw_vsock/virtio_transport_common.c
>@@ -413,7 +413,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
>
> virtio_transport_inc_tx_pkt(vvs, skb);
>
>- ret = t_ops->send_pkt(skb);
>+ ret = t_ops->send_pkt(skb, info->net, info->net_mode);
> if (ret < 0)
> break;
>
>@@ -527,6 +527,8 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk)
> struct virtio_vsock_pkt_info info = {
> .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE,
> .vsk = vsk,
>+ .net = sock_net(sk_vsock(vsk)),
>+ .net_mode = vsk->net_mode,
> };
>
> return virtio_transport_send_pkt_info(vsk, &info);
>@@ -1067,6 +1069,8 @@ int virtio_transport_connect(struct vsock_sock *vsk)
> struct virtio_vsock_pkt_info info = {
> .op = VIRTIO_VSOCK_OP_REQUEST,
> .vsk = vsk,
>+ .net = sock_net(sk_vsock(vsk)),
>+ .net_mode = vsk->net_mode,
> };
>
> return virtio_transport_send_pkt_info(vsk, &info);
>@@ -1082,6 +1086,8 @@ int virtio_transport_shutdown(struct vsock_sock *vsk, int mode)
> (mode & SEND_SHUTDOWN ?
> VIRTIO_VSOCK_SHUTDOWN_SEND : 0),
> .vsk = vsk,
>+ .net = sock_net(sk_vsock(vsk)),
>+ .net_mode = vsk->net_mode,
> };
>
> return virtio_transport_send_pkt_info(vsk, &info);
>@@ -1108,6 +1114,8 @@ virtio_transport_stream_enqueue(struct vsock_sock *vsk,
> .msg = msg,
> .pkt_len = len,
> .vsk = vsk,
>+ .net = sock_net(sk_vsock(vsk)),
>+ .net_mode = vsk->net_mode,
> };
>
> return virtio_transport_send_pkt_info(vsk, &info);
>@@ -1145,6 +1153,8 @@ static int virtio_transport_reset(struct vsock_sock *vsk,
> .op = VIRTIO_VSOCK_OP_RST,
> .reply = !!skb,
> .vsk = vsk,
>+ .net = sock_net(sk_vsock(vsk)),
>+ .net_mode = vsk->net_mode,
> };
>
> /* Send RST only if the original pkt is not a RST pkt */
>@@ -1156,9 +1166,14 @@ static int virtio_transport_reset(struct vsock_sock *vsk,
>
> /* Normally packets are associated with a socket. There may be no socket if an
> * attempt was made to connect to a socket that does not exist.
>+ *
>+ * net and net_mode refer to the namespace of whoever sent the invalid message.
>+ * For loopback, this is the namespace of the socket. For vhost, this is the
>+ * namespace of the VM (i.e., vhost_vsock).
> */
> static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
>- struct sk_buff *skb)
>+ struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
> struct virtio_vsock_pkt_info info = {
>@@ -1171,6 +1186,13 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
> * sock_net(sk) until the reply skb is freed.
> */
> .vsk = vsock_sk(skb->sk),
>+
>+ /* net or net_mode are not defined here because we pass
>+ * net and net_mode directly to t->send_pkt(), instead of
>+ * relying on virtio_transport_send_pkt_info() to pass them to
>+ * t->send_pkt(). They are not needed by
>+ * virtio_transport_alloc_skb().
>+ */
> };
> struct sk_buff *reply;
>
>@@ -1189,7 +1211,7 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
> if (!reply)
> return -ENOMEM;
>
>- return t->send_pkt(reply);
>+ return t->send_pkt(reply, net, net_mode);
> }
>
> /* This function should be called with sk_lock held and SOCK_DONE set */
>@@ -1471,6 +1493,8 @@ virtio_transport_send_response(struct vsock_sock *vsk,
> .remote_port = le32_to_cpu(hdr->src_port),
> .reply = true,
> .vsk = vsk,
>+ .net = sock_net(sk_vsock(vsk)),
>+ .net_mode = vsk->net_mode,
> };
>
> return virtio_transport_send_pkt_info(vsk, &info);
>@@ -1513,12 +1537,14 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb,
> int ret;
>
> if (le16_to_cpu(hdr->op) != VIRTIO_VSOCK_OP_REQUEST) {
>- virtio_transport_reset_no_sock(t, skb);
>+ virtio_transport_reset_no_sock(t, skb, sock_net(sk),
>+ vsk->net_mode);
> return -EINVAL;
> }
>
> if (sk_acceptq_is_full(sk)) {
>- virtio_transport_reset_no_sock(t, skb);
>+ virtio_transport_reset_no_sock(t, skb, sock_net(sk),
>+ vsk->net_mode);
> return -ENOMEM;
> }
>
>@@ -1526,13 +1552,15 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb,
> * Subsequent enqueues would lead to a memory leak.
> */
> if (sk->sk_shutdown == SHUTDOWN_MASK) {
>- virtio_transport_reset_no_sock(t, skb);
>+ virtio_transport_reset_no_sock(t, skb, sock_net(sk),
>+ vsk->net_mode);
> return -ESHUTDOWN;
> }
>
> child = vsock_create_connected(sk);
> if (!child) {
>- virtio_transport_reset_no_sock(t, skb);
>+ virtio_transport_reset_no_sock(t, skb, sock_net(sk),
>+ vsk->net_mode);
> return -ENOMEM;
> }
>
>@@ -1554,7 +1582,8 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb,
> */
> if (ret || vchild->transport != &t->transport) {
> release_sock(child);
>- virtio_transport_reset_no_sock(t, skb);
>+ virtio_transport_reset_no_sock(t, skb, sock_net(sk),
>+ vsk->net_mode);
> sock_put(child);
> return ret;
> }
>@@ -1582,7 +1611,8 @@ static bool virtio_transport_valid_type(u16 type)
> * lock.
> */
> void virtio_transport_recv_pkt(struct virtio_transport *t,
>- struct sk_buff *skb)
>+ struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
> struct sockaddr_vm src, dst;
>@@ -1605,24 +1635,25 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
> le32_to_cpu(hdr->fwd_cnt));
>
> if (!virtio_transport_valid_type(le16_to_cpu(hdr->type))) {
>- (void)virtio_transport_reset_no_sock(t, skb);
>+ (void)virtio_transport_reset_no_sock(t, skb, net, net_mode);
> goto free_pkt;
> }
>
> /* The socket must be in connected or bound table
> * otherwise send reset back
> */
>- sk = vsock_find_connected_socket(&src, &dst);
>+ sk = vsock_find_connected_socket_net(&src, &dst, net, net_mode);
> if (!sk) {
>- sk = vsock_find_bound_socket(&dst);
>+ sk = vsock_find_bound_socket_net(&dst, net, net_mode);
> if (!sk) {
>- (void)virtio_transport_reset_no_sock(t, skb);
>+ (void)virtio_transport_reset_no_sock(t, skb, net,
>+ net_mode);
> goto free_pkt;
> }
> }
>
> if (virtio_transport_get_type(sk) != le16_to_cpu(hdr->type)) {
>- (void)virtio_transport_reset_no_sock(t, skb);
>+ (void)virtio_transport_reset_no_sock(t, skb, net, net_mode);
> sock_put(sk);
> goto free_pkt;
> }
>@@ -1641,7 +1672,7 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
> */
> if (sock_flag(sk, SOCK_DONE) ||
> (sk->sk_state != TCP_LISTEN && vsk->transport != &t->transport)) {
>- (void)virtio_transport_reset_no_sock(t, skb);
>+ (void)virtio_transport_reset_no_sock(t, skb, net, net_mode);
> release_sock(sk);
> sock_put(sk);
> goto free_pkt;
>@@ -1673,7 +1704,7 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
> kfree_skb(skb);
> break;
> default:
>- (void)virtio_transport_reset_no_sock(t, skb);
>+ (void)virtio_transport_reset_no_sock(t, skb, net, net_mode);
> kfree_skb(skb);
> break;
> }
>diff --git a/net/vmw_vsock/vsock_loopback.c b/net/vmw_vsock/vsock_loopback.c
>index afad27cf533a..aef44d1631c3 100644
>--- a/net/vmw_vsock/vsock_loopback.c
>+++ b/net/vmw_vsock/vsock_loopback.c
>@@ -26,7 +26,8 @@ static u32 vsock_loopback_get_local_cid(void)
> return VMADDR_CID_LOCAL;
> }
>
>-static int vsock_loopback_send_pkt(struct sk_buff *skb)
>+static int vsock_loopback_send_pkt(struct sk_buff *skb, struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct vsock_loopback *vsock = &the_vsock_loopback;
> int len = skb->len;
>@@ -48,6 +49,13 @@ static int vsock_loopback_cancel_pkt(struct vsock_sock *vsk)
>
> static bool vsock_loopback_seqpacket_allow(struct vsock_sock *vsk,
> u32 remote_cid);
>+
>+static bool vsock_loopback_stream_allow(struct vsock_sock *vsk, u32 cid,
>+ u32 port)
>+{
>+ return true;
>+}
>+
> static bool vsock_loopback_msgzerocopy_allow(void)
> {
> return true;
>@@ -77,7 +85,7 @@ static struct virtio_transport loopback_transport = {
> .stream_has_space = virtio_transport_stream_has_space,
> .stream_rcvhiwat = virtio_transport_stream_rcvhiwat,
> .stream_is_active = virtio_transport_stream_is_active,
>- .stream_allow = virtio_transport_stream_allow,
>+ .stream_allow = vsock_loopback_stream_allow,
So after this change, there is only virtio_transport.c using the
virtio_transport_stream_allow() defined in virtio_transport_common.c
right?
At that point, we should move it in virtio_transport.c IMO.
That said, we can do it with a follow-up patch, since the behaviour is
unchanged, so:
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
>
> .seqpacket_dequeue = virtio_transport_seqpacket_dequeue,
> .seqpacket_enqueue = virtio_transport_seqpacket_enqueue,
>@@ -110,7 +118,7 @@ static struct virtio_transport loopback_transport = {
> static bool
> vsock_loopback_seqpacket_allow(struct vsock_sock *vsk, u32 remote_cid)
> {
>- return vsk->net_mode == VSOCK_NET_MODE_GLOBAL;
>+ return true;
> }
>
> static void vsock_loopback_work(struct work_struct *work)
>@@ -132,7 +140,10 @@ static void vsock_loopback_work(struct work_struct *work)
> */
> virtio_transport_consume_skb_sent(skb, false);
> virtio_transport_deliver_tap_pkt(skb);
>- virtio_transport_recv_pkt(&loopback_transport, skb);
>+
>+ virtio_transport_recv_pkt(&loopback_transport, skb,
>+ sock_net(skb->sk),
>+ vsock_sk(skb->sk)->net_mode);
> }
> }
>
>
>--
>2.47.3
>
^ permalink raw reply
* Re: [PATCH net-next v12 02/12] vsock: add netns to vsock core
From: Stefano Garzarella @ 2025-11-27 14:25 UTC (permalink / raw)
To: Bobby Eshleman
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang,
Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan, linux-kernel,
virtualization, netdev, kvm, linux-hyperv, linux-kselftest,
berrange, Sargun Dhillon, Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-2-257ee21cd5de@meta.com>
On Wed, Nov 26, 2025 at 11:47:31PM -0800, Bobby Eshleman wrote:
>From: Bobby Eshleman <bobbyeshleman@meta.com>
>
>Add netns logic to vsock core. Additionally, modify transport hook
>prototypes to be used by later transport-specific patches (e.g.,
>*_seqpacket_allow()).
>
>Namespaces are supported primarily by changing socket lookup functions
>(e.g., vsock_find_connected_socket()) to take into account the socket
>namespace and the namespace mode before considering a candidate socket a
>"match".
>
>This patch also introduces the sysctl /proc/sys/net/vsock/ns_mode that
>accepts the "global" or "local" mode strings.
>
>Add netns functionality (initialization, passing to transports, procfs,
>etc...) to the af_vsock socket layer. Later patches that add netns
>support to transports depend on this patch.
>
>dgram_allow(), stream_allow(), and seqpacket_allow() callbacks are
>modified to take a vsk in order to perform logic on namespace modes. In
>future patches, the net and net_mode will also be used for socket
>lookups in these functions.
>
>Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
>---
>Changes in v12:
>- return true in dgram_allow(), stream_allow(), and seqpacket_allow()
> only if net_mode == VSOCK_NET_MODE_GLOBAL (Stefano)
>- document bind(VMADDR_CID_ANY) case in af_vsock.c (Stefano)
>- change order of stream_allow() call in vmci so we can pass vsk
> to it
>
>Changes in v10:
>- add file-level comment about what happens to sockets/devices
> when the namespace mode changes (Stefano)
>- change the 'if (write)' boolean in vsock_net_mode_string() to
> if (!write), this simplifies a later patch which adds "goto"
> for mutex unlocking on function exit.
>
>Changes in v9:
>- remove virtio_vsock_alloc_rx_skb() (Stefano)
>- remove vsock_global_dummy_net, not needed as net=NULL +
> net_mode=VSOCK_NET_MODE_GLOBAL achieves identical result
>
>Changes in v7:
>- hv_sock: fix hyperv build error
>- explain why vhost does not use the dummy
>- explain usage of __vsock_global_dummy_net
>- explain why VSOCK_NET_MODE_STR_MAX is 8 characters
>- use switch-case in vsock_net_mode_string()
>- avoid changing transports as much as possible
>- add vsock_find_{bound,connected}_socket_net()
>- rename `vsock_hdr` to `sysctl_hdr`
>- add virtio_vsock_alloc_linear_skb() wrapper for setting dummy net and
> global mode for virtio-vsock, move skb->cb zero-ing into wrapper
>- explain seqpacket_allow() change
>- move net setting to __vsock_create() instead of vsock_create() so
> that child sockets also have their net assigned upon accept()
>
>Changes in v6:
>- unregister sysctl ops in vsock_exit()
>- af_vsock: clarify description of CID behavior
>- af_vsock: fix buf vs buffer naming, and length checking
>- af_vsock: fix length checking w/ correct ctl_table->maxlen
>
>Changes in v5:
>- vsock_global_net() -> vsock_global_dummy_net()
>- update comments for new uAPI
>- use /proc/sys/net/vsock/ns_mode instead of /proc/net/vsock_ns_mode
>- add prototype changes so patch remains compilable
>---
> drivers/vhost/vsock.c | 9 +-
> include/linux/virtio_vsock.h | 4 +-
> include/net/af_vsock.h | 13 +-
> net/vmw_vsock/af_vsock.c | 272 +++++++++++++++++++++++++++++---
> net/vmw_vsock/hyperv_transport.c | 7 +-
> net/vmw_vsock/virtio_transport.c | 9 +-
> net/vmw_vsock/virtio_transport_common.c | 6 +-
> net/vmw_vsock/vmci_transport.c | 26 ++-
> net/vmw_vsock/vsock_loopback.c | 8 +-
> 9 files changed, 310 insertions(+), 44 deletions(-)
>
>diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
>index ae01457ea2cd..83937e1d63fa 100644
>--- a/drivers/vhost/vsock.c
>+++ b/drivers/vhost/vsock.c
>@@ -404,7 +404,8 @@ static bool vhost_transport_msgzerocopy_allow(void)
> return true;
> }
>
>-static bool vhost_transport_seqpacket_allow(u32 remote_cid);
>+static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk,
>+ u32 remote_cid);
>
> static struct virtio_transport vhost_transport = {
> .transport = {
>@@ -460,11 +461,15 @@ static struct virtio_transport vhost_transport = {
> .send_pkt = vhost_transport_send_pkt,
> };
>
>-static bool vhost_transport_seqpacket_allow(u32 remote_cid)
>+static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk,
>+ u32 remote_cid)
> {
> struct vhost_vsock *vsock;
> bool seqpacket_allow = false;
>
>+ if (vsk->net_mode != VSOCK_NET_MODE_GLOBAL)
>+ return false;
>+
> rcu_read_lock();
> vsock = vhost_vsock_get(remote_cid);
>
>diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
>index 0c67543a45c8..1845e8d4f78d 100644
>--- a/include/linux/virtio_vsock.h
>+++ b/include/linux/virtio_vsock.h
>@@ -256,10 +256,10 @@ void virtio_transport_notify_buffer_size(struct vsock_sock *vsk, u64 *val);
>
> u64 virtio_transport_stream_rcvhiwat(struct vsock_sock *vsk);
> bool virtio_transport_stream_is_active(struct vsock_sock *vsk);
>-bool virtio_transport_stream_allow(u32 cid, u32 port);
>+bool virtio_transport_stream_allow(struct vsock_sock *vsk, u32 cid, u32 port);
> int virtio_transport_dgram_bind(struct vsock_sock *vsk,
> struct sockaddr_vm *addr);
>-bool virtio_transport_dgram_allow(u32 cid, u32 port);
>+bool virtio_transport_dgram_allow(struct vsock_sock *vsk, u32 cid, u32 port);
>
> int virtio_transport_connect(struct vsock_sock *vsk);
>
>diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
>index 9b5bdd083b6f..d10e73cd7413 100644
>--- a/include/net/af_vsock.h
>+++ b/include/net/af_vsock.h
>@@ -126,7 +126,7 @@ struct vsock_transport {
> size_t len, int flags);
> int (*dgram_enqueue)(struct vsock_sock *, struct sockaddr_vm *,
> struct msghdr *, size_t len);
>- bool (*dgram_allow)(u32 cid, u32 port);
>+ bool (*dgram_allow)(struct vsock_sock *vsk, u32 cid, u32 port);
>
> /* STREAM. */
> /* TODO: stream_bind() */
>@@ -138,14 +138,14 @@ struct vsock_transport {
> s64 (*stream_has_space)(struct vsock_sock *);
> u64 (*stream_rcvhiwat)(struct vsock_sock *);
> bool (*stream_is_active)(struct vsock_sock *);
>- bool (*stream_allow)(u32 cid, u32 port);
>+ bool (*stream_allow)(struct vsock_sock *vsk, u32 cid, u32 port);
>
> /* SEQ_PACKET. */
> ssize_t (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,
> int flags);
> int (*seqpacket_enqueue)(struct vsock_sock *vsk, struct msghdr *msg,
> size_t len);
>- bool (*seqpacket_allow)(u32 remote_cid);
>+ bool (*seqpacket_allow)(struct vsock_sock *vsk, u32 remote_cid);
> u32 (*seqpacket_has_data)(struct vsock_sock *vsk);
>
> /* Notification. */
>@@ -218,6 +218,13 @@ void vsock_remove_connected(struct vsock_sock *vsk);
> struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
> struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
> struct sockaddr_vm *dst);
>+struct sock *vsock_find_bound_socket_net(struct sockaddr_vm *addr,
>+ struct net *net,
>+ enum vsock_net_mode net_mode);
>+struct sock *vsock_find_connected_socket_net(struct sockaddr_vm *src,
>+ struct sockaddr_vm *dst,
>+ struct net *net,
>+ enum vsock_net_mode net_mode);
> void vsock_remove_sock(struct vsock_sock *vsk);
> void vsock_for_each_connected_socket(struct vsock_transport *transport,
> void (*fn)(struct sock *sk));
>diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
>index adcba1b7bf74..6113c22db8dc 100644
>--- a/net/vmw_vsock/af_vsock.c
>+++ b/net/vmw_vsock/af_vsock.c
>@@ -83,6 +83,46 @@
> * TCP_ESTABLISHED - connected
> * TCP_CLOSING - disconnecting
> * TCP_LISTEN - listening
>+ *
>+ * - Namespaces in vsock support two different modes configured
>+ * through /proc/sys/net/vsock/ns_mode. The modes are "local" and "global".
>+ * Each mode defines how the namespace interacts with CIDs.
>+ * /proc/sys/net/vsock/ns_mode is write-once, so that it may be configured
>+ * and locked down by a namespace manager. The default is "global". The mode
>+ * is set per-namespace.
>+ *
>+ * The modes affect the allocation and accessibility of CIDs as follows:
>+ *
>+ * - global - access and allocation are all system-wide
nit: maybe we should mention that this mode is primarily for backward
compatibility, since it's the way how vsock worked before netns support.
(We can fix later eventually with a followup patch)
>+ * - all CID allocation from global namespaces draw from the same
>+ * system-wide pool.
>+ * - if one global namespace has already allocated some CID, another
>+ * global namespace will not be able to allocate the same CID.
>+ * - global mode AF_VSOCK sockets can reach any VM or socket in any global
>+ * namespace, they are not contained to only their own namespace.
>+ * - AF_VSOCK sockets in a global mode namespace cannot reach VMs or
>+ * sockets in any local mode namespace.
>+ * - local - access and allocation are contained within the namespace
>+ * - CID allocation draws only from a private pool local only to the
>+ * namespace, and does not affect the CIDs available for allocation in any
>+ * other namespace (global or local).
>+ * - VMs in a local namespace do not collide with CIDs in any other local
>+ * namespace or any global namespace. For example, if a VM in a local mode
>+ * namespace is given CID 10, then CID 10 is still available for
>+ * allocation in any other namespace, but not in the same namespace.
>+ * - AF_VSOCK sockets in a local mode namespace can connect only to VMs or
>+ * other sockets within their own namespace.
>+ * - sockets bound to VMADDR_CID_ANY in local namespaces will never resolve
>+ * to any transport that is not compatible with local mode. There is no
>+ * error that propagates to the user (as there is for connection attempts)
>+ * because it is possible for some packet to reach this socket from
>+ * a different transport that *does* support local mode. For
>+ * example, virtio-vsock may not support local mode, but the socket
>+ * may still accept a connection from vhost-vsock which does.
>+ *
>+ * - when a socket or device is initialized in a namespace with mode
>+ * global, it will stay in global mode even if the namespace later
>+ * changes to local.
> */
>
> #include <linux/compat.h>
>@@ -100,6 +140,7 @@
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/net.h>
>+#include <linux/proc_fs.h>
> #include <linux/poll.h>
> #include <linux/random.h>
> #include <linux/skbuff.h>
>@@ -111,9 +152,18 @@
> #include <linux/workqueue.h>
> #include <net/sock.h>
> #include <net/af_vsock.h>
>+#include <net/netns/vsock.h>
> #include <uapi/linux/vm_sockets.h>
> #include <uapi/asm-generic/ioctls.h>
>
>+#define VSOCK_NET_MODE_STR_GLOBAL "global"
>+#define VSOCK_NET_MODE_STR_LOCAL "local"
>+
>+/* 6 chars for "global", 1 for null-terminator, and 1 more for '\n'.
>+ * The newline is added by proc_dostring() for read operations.
>+ */
>+#define VSOCK_NET_MODE_STR_MAX 8
>+
> static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
> static void vsock_sk_destruct(struct sock *sk);
> static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
>@@ -235,33 +285,47 @@ static void __vsock_remove_connected(struct vsock_sock *vsk)
> sock_put(&vsk->sk);
> }
>
>-static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
>+static struct sock *__vsock_find_bound_socket_net(struct sockaddr_vm *addr,
>+ struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct vsock_sock *vsk;
>
> list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table) {
>- if (vsock_addr_equals_addr(addr, &vsk->local_addr))
>- return sk_vsock(vsk);
>+ struct sock *sk = sk_vsock(vsk);
>+
>+ if (vsock_addr_equals_addr(addr, &vsk->local_addr) &&
>+ vsock_net_check_mode(sock_net(sk), vsk->net_mode, net,
>+ net_mode))
>+ return sk;
>
> if (addr->svm_port == vsk->local_addr.svm_port &&
> (vsk->local_addr.svm_cid == VMADDR_CID_ANY ||
>- addr->svm_cid == VMADDR_CID_ANY))
>- return sk_vsock(vsk);
>+ addr->svm_cid == VMADDR_CID_ANY) &&
>+ vsock_net_check_mode(sock_net(sk), vsk->net_mode, net,
>+ net_mode))
>+ return sk;
> }
>
> return NULL;
> }
>
>-static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
>- struct sockaddr_vm *dst)
>+static struct sock *
>+__vsock_find_connected_socket_net(struct sockaddr_vm *src,
>+ struct sockaddr_vm *dst, struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct vsock_sock *vsk;
>
> list_for_each_entry(vsk, vsock_connected_s)ckets(src, dst),
> connected_table) {
>+ struct sock *sk = sk_vsock(vsk);
>+
> if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
>- dst->svm_port == vsk->local_addr.svm_port) {
>- return sk_vsock(vsk);
>+ dst->svm_port == vsk->local_addr.svm_port &&
>+ vsock_net_check_mode(sock_net(sk), vsk->net_mode, net,
>+ net_mode)) {
>+ return sk;
> }
> }
>
>@@ -304,12 +368,14 @@ void vsock_remove_connected(struct vsock_sock *vsk)
> }
> EXPORT_SYMBOL_GPL(vsock_remove_connected);
>
>-struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr)
>+struct sock *vsock_find_bound_socket_net(struct sockaddr_vm *addr,
>+ struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct sock *sk;
>
> spin_lock_bh(&vsock_table_lock);
>- sk = __vsock_find_bound_socket(addr);
>+ sk = __vsock_find_bound_socket_net(addr, net, net_mode);
> if (sk)
> sock_hold(sk);
>
>@@ -317,15 +383,23 @@ struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr)
>
> return sk;
> }
>+EXPORT_SYMBOL_GPL(vsock_find_bound_socket_net);
>+
>+struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr)
>+{
>+ return vsock_find_bound_socket_net(addr, NULL, VSOCK_NET_MODE_GLOBAL);
The patch LGTM, my last doubt now is if here (and in
vsock_find_connected_socket() ) we should use `init_net`.
In practice, this is the namespace (NULL) and mode (GLOBAL) used by
transports that do not support namespaces.
So here we are making them belong to no namespace, so they can only
reach global ones. When any namespace, including `init_net`, switches to
local, it can no longer be reached by transports that do not support
local namespaces, because in practice we still do not have a way to
associate a device (in the case of drivers) with a specific namespace.
Right?
If I get it right, it can makes sense, but I'd like an ack from net
maintainers to be sure we are doing the right things.
Also I think we should have a comment on top of this function to make it
clear that should be used only by transport that doesn't support
namespace, and the reason why we used NULL and GLOBAL. Plus a comment on
top of this file (near where we described local vs global) to clarify
the status of this.
That said, if next week net-next will close, I think we can send a
follow-up patch just for those comments, so:
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
>+}
> EXPORT_SYMBOL_GPL(vsock_find_bound_socket);
>
>-struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
>- struct sockaddr_vm *dst)
>+struct sock *vsock_find_connected_socket_net(struct sockaddr_vm *src,
>+ struct sockaddr_vm *dst,
>+ struct net *net,
>+ enum vsock_net_mode net_mode)
> {
> struct sock *sk;
>
> spin_lock_bh(&vsock_table_lock);
>- sk = __vsock_find_connected_socket(src, dst);
>+ sk = __vsock_find_connected_socket_net(src, dst, net, net_mode);
> if (sk)
> sock_hold(sk);
>
>@@ -333,6 +407,14 @@ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
>
> return sk;
> }
>+EXPORT_SYMBOL_GPL(vsock_find_connected_socket_net);
>+
>+struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
>+ struct sockaddr_vm *dst)
>+{
>+ return vsock_find_connected_socket_net(src, dst,
>+ NULL, VSOCK_NET_MODE_GLOBAL);
>+}
> EXPORT_SYMBOL_GPL(vsock_find_connected_socket);
^ permalink raw reply
* [PATCH net-next, v5] net: mana: Implement ndo_tx_timeout and serialize queue resets per port.
From: Dipayaan Roy @ 2025-11-27 13:58 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, longli, kotaranov, horms, shradhagupta, ssengar,
ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, dipayanroy
Implement .ndo_tx_timeout for MANA so any stalled TX queue can be detected
and a device-controlled port reset for all queues can be scheduled to a
ordered workqueue. The reset for all queues on stall detection is
recommended by hardware team.
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
Changes in v5:
-Fixed commit message, used 'create_singlethread_workqueue' and fixed
cleanup part.
Changes in v4:
-Fixed commit message, work initialization before registering netdev,
fixed potential null pointer de-reference bug.
Changes in v3:
-Fixed commit meesage, removed rtnl_trylock and added
disable_work_sync, fixed mana_queue_reset_work, and few
cosmetics.
Changes in v2:
-Fixed cosmetic changes.
---
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 77 ++++++++++++++++++-
include/net/mana/gdma.h | 7 +-
include/net/mana/mana.h | 8 +-
3 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 1ad154f9db1a..d8451f550db4 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -299,6 +299,42 @@ static int mana_get_gso_hs(struct sk_buff *skb)
return gso_hs;
}
+static void mana_per_port_queue_reset_work_handler(struct work_struct *work)
+{
+ struct mana_queue_reset_work *reset_queue_work =
+ container_of(work, struct mana_queue_reset_work, work);
+
+ struct mana_port_context *apc = container_of(reset_queue_work,
+ struct mana_port_context,
+ queue_reset_work);
+ struct net_device *ndev = apc->ndev;
+ int err;
+
+ rtnl_lock();
+
+ /* Pre-allocate buffers to prevent failure in mana_attach later */
+ err = mana_pre_alloc_rxbufs(apc, ndev->mtu, apc->num_queues);
+ if (err) {
+ netdev_err(ndev, "Insufficient memory for reset post tx stall detection\n");
+ goto out;
+ }
+
+ err = mana_detach(ndev, false);
+ if (err) {
+ netdev_err(ndev, "mana_detach failed: %d\n", err);
+ goto dealloc_pre_rxbufs;
+ }
+
+ err = mana_attach(ndev);
+ if (err)
+ netdev_err(ndev, "mana_attach failed: %d\n", err);
+
+dealloc_pre_rxbufs:
+ mana_pre_dealloc_rxbufs(apc);
+out:
+ rtnl_unlock();
+}
+
netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT;
@@ -839,6 +875,23 @@ static int mana_change_mtu(struct net_device *ndev, int new_mtu)
return err;
}
+static void mana_tx_timeout(struct net_device *netdev, unsigned int txqueue)
+{
+ struct mana_port_context *apc = netdev_priv(netdev);
+ struct mana_context *ac = apc->ac;
+ struct gdma_context *gc = ac->gdma_dev->gdma_context;
+
+ /* Already in service, hence tx queue reset is not required.*/
+ if (gc->in_service)
+ return;
+
+ /* Note: If there are pending queue reset work for this port(apc),
+ * subsequent request queued up from here are ignored. This is because
+ * we are using the same work instance per port(apc).
+ */
+ queue_work(ac->per_port_queue_reset_wq, &apc->queue_reset_work.work);
+}
+
static int mana_shaper_set(struct net_shaper_binding *binding,
const struct net_shaper *shaper,
struct netlink_ext_ack *extack)
@@ -924,6 +977,7 @@ static const struct net_device_ops mana_devops = {
.ndo_bpf = mana_bpf,
.ndo_xdp_xmit = mana_xdp_xmit,
.ndo_change_mtu = mana_change_mtu,
+ .ndo_tx_timeout = mana_tx_timeout,
.net_shaper_ops = &mana_shaper_ops,
};
@@ -3287,6 +3341,8 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
ndev->min_mtu = ETH_MIN_MTU;
ndev->needed_headroom = MANA_HEADROOM;
ndev->dev_port = port_idx;
+ /* Recommended timeout based on HW FPGA re-config scenario. */
+ ndev->watchdog_timeo = 15 * HZ;
SET_NETDEV_DEV(ndev, gc->dev);
netif_set_tso_max_size(ndev, GSO_MAX_SIZE);
@@ -3303,6 +3359,10 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
if (err)
goto reset_apc;
+ /* Initialize the per port queue reset work.*/
+ INIT_WORK(&apc->queue_reset_work.work,
+ mana_per_port_queue_reset_work_handler);
+
netdev_lockdep_set_classes(ndev);
ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
@@ -3549,6 +3609,14 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
if (ac->num_ports > MAX_PORTS_IN_MANA_DEV)
ac->num_ports = MAX_PORTS_IN_MANA_DEV;
+ ac->per_port_queue_reset_wq =
+ create_singlethread_workqueue("mana_per_port_queue_reset_wq");
+ if (!ac->per_port_queue_reset_wq) {
+ dev_err(dev, "Failed to allocate per port queue reset workqueue\n");
+ err = -ENOMEM;
+ goto out;
+ }
+
if (!resuming) {
for (i = 0; i < ac->num_ports; i++) {
err = mana_probe_port(ac, i, &ac->ports[i]);
@@ -3616,13 +3684,15 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
for (i = 0; i < ac->num_ports; i++) {
ndev = ac->ports[i];
- apc = netdev_priv(ndev);
if (!ndev) {
if (i == 0)
dev_err(dev, "No net device to remove\n");
goto out;
}
+ apc = netdev_priv(ndev);
+ disable_work_sync(&apc->queue_reset_work.work);
+
/* All cleanup actions should stay after rtnl_lock(), otherwise
* other functions may access partially cleaned up data.
*/
@@ -3649,6 +3719,11 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
mana_destroy_eq(ac);
out:
+ if (ac->per_port_queue_reset_wq) {
+ destroy_workqueue(ac->per_port_queue_reset_wq);
+ ac->per_port_queue_reset_wq = NULL;
+ }
+
mana_gd_deregister_device(gd);
if (suspending)
diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
index a4cf307859f8..808622ae5ccc 100644
--- a/include/net/mana/gdma.h
+++ b/include/net/mana/gdma.h
@@ -592,6 +592,10 @@ enum {
/* Driver can self reset on FPGA Reconfig EQE notification */
#define GDMA_DRV_CAP_FLAG_1_HANDLE_RECONFIG_EQE BIT(17)
+
+/* Driver detects stalled send queues and recovers them */
+#define GDMA_DRV_CAP_FLAG_1_HANDLE_STALL_SQ_RECOVERY BIT(18)
+
#define GDMA_DRV_CAP_FLAG_1_HW_VPORT_LINK_AWARE BIT(6)
/* Driver supports linearizing the skb when num_sge exceeds hardware limit */
@@ -611,7 +615,8 @@ enum {
GDMA_DRV_CAP_FLAG_1_HANDLE_RECONFIG_EQE | \
GDMA_DRV_CAP_FLAG_1_HW_VPORT_LINK_AWARE | \
GDMA_DRV_CAP_FLAG_1_PERIODIC_STATS_QUERY | \
- GDMA_DRV_CAP_FLAG_1_SKB_LINEARIZE)
+ GDMA_DRV_CAP_FLAG_1_SKB_LINEARIZE | \
+ GDMA_DRV_CAP_FLAG_1_HANDLE_STALL_SQ_RECOVERY)
#define GDMA_DRV_CAP_FLAGS2 0
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index d7e089c6b694..cef78a871c7c 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -480,7 +480,7 @@ struct mana_context {
struct mana_ethtool_hc_stats hc_stats;
struct mana_eq *eqs;
struct dentry *mana_eqs_debugfs;
-
+ struct workqueue_struct *per_port_queue_reset_wq;
/* Workqueue for querying hardware stats */
struct delayed_work gf_stats_work;
bool hwc_timeout_occurred;
@@ -492,9 +492,15 @@ struct mana_context {
u32 link_event;
};
+struct mana_queue_reset_work {
+ /* Work structure */
+ struct work_struct work;
+};
+
struct mana_port_context {
struct mana_context *ac;
struct net_device *ndev;
+ struct mana_queue_reset_work queue_reset_work;
u8 mac_addr[ETH_ALEN];
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next, v4] net: mana: Implement ndo_tx_timeout and serialize queue resets per port.
From: Dipayaan Roy @ 2025-11-27 12:29 UTC (permalink / raw)
To: Jakub Kicinski
Cc: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
pabeni, longli, kotaranov, horms, shradhagupta, ssengar, ernis,
shirazsaleem, linux-hyperv, netdev, linux-kernel, linux-rdma,
dipayanroy
In-Reply-To: <20251126200541.00e5270f@kernel.org>
Hi Jakub,
On Wed, Nov 26, 2025 at 08:05:41PM -0800, Jakub Kicinski wrote:
> On Sun, 23 Nov 2025 10:08:18 -0800 Dipayaan Roy wrote:
> > Implement .ndo_tx_timeout for MANA so any stalled TX queue can be detected
> > and a device-controlled port reset for all queues can be scheduled to a
> > ordered workqueue. The reset for all queues on stall detection is
> > recomended by hardware team.
> >
> > The change introduces a single ordered workqueue
> > "mana_per_port_queue_reset_wq" queuing one work_struct per port,
> > using WQ_UNBOUND | WQ_MEM_RECLAIM so stalled queue reset work can
> > run on any CPU and still make forward progress under memory
> > pressure.
>
> And we need to be able to reset the NIC queue under memory pressure
> because.. ? I could be wrong but I still find this unusual / defensive
> programming, if you could point me at some existing drivers that'd help.
>
I found these existing drivers using 'create_singlethread_workqueue',
drivers/net/ethernet/mellanox/mlx4/en_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
'create_singlethread_workqueue' in turn uses WQ_MEM_RECLAIM
as in below macros
#define alloc_ordered_workqueue(fmt, flags, args...) \
alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1,
##args)
...
#define create_singlethread_workqueue(name) \
alloc_ordered_workqueue("%s", __WQ_LEGACY | WQ_MEM_RECLAIM,
name)
I will switch to directly using create_singlethread_workqueue instead
of explicitly mentioning the flags in the next version.
> > @@ -3287,6 +3341,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
> > ndev->min_mtu = ETH_MIN_MTU;
> > ndev->needed_headroom = MANA_HEADROOM;
> > ndev->dev_port = port_idx;
> > + ndev->watchdog_timeo = 15 * HZ;
>
> 5 sec is typical, off the top of my head
>
As per our internal discussion, 15 second timeout recommended by HW team based on the FPGA reconfig
scenario.
> > @@ -3647,6 +3717,11 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
> > free_netdev(ndev);
> > }
> >
> > + if (ac->per_port_queue_reset_wq) {
> > + destroy_workqueue(ac->per_port_queue_reset_wq);
> > + ac->per_port_queue_reset_wq = NULL;
> > + }
>
> I think you're missing this cleanup in the failure path of mana_probe
Right, if all the ports fail to probe the clean up will get skipped from
mana_remove. I will fix this in the v5.
> --
> pw-bot: cr
Thank you for the comments, I will work on it in v5.
Regards
^ permalink raw reply
* Re: [PATCH v7 4/7] Drivers: hv: Fix huge page handling in memory region traversal
From: kernel test robot @ 2025-11-27 10:59 UTC (permalink / raw)
To: Stanislav Kinsburskii, kys, haiyangz, wei.liu, decui
Cc: llvm, oe-kbuild-all, linux-hyperv, linux-kernel
In-Reply-To: <176412295155.447063.16512843211428609586.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net>
Hi Stanislav,
kernel test robot noticed the following build warnings:
[auto build test WARNING on next-20251125]
[cannot apply to linus/master v6.18-rc7 v6.18-rc6 v6.18-rc5 v6.18-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Stanislav-Kinsburskii/Drivers-hv-Refactor-and-rename-memory-region-handling-functions/20251126-101138
base: next-20251125
patch link: https://lore.kernel.org/r/176412295155.447063.16512843211428609586.stgit%40skinsburskii-cloud-desktop.internal.cloudapp.net
patch subject: [PATCH v7 4/7] Drivers: hv: Fix huge page handling in memory region traversal
config: x86_64-randconfig-076-20251127 (https://download.01.org/0day-ci/archive/20251127/202511271830.nH1cbyQI-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271830.nH1cbyQI-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511271830.nH1cbyQI-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/hv/mshv_regions.c:288:12: warning: parameter 'flags' set but not used [-Wunused-but-set-parameter]
288 | u32 flags,
| ^
1 warning generated.
vim +/flags +288 drivers/hv/mshv_regions.c
286
287 static int mshv_region_chunk_unmap(struct mshv_mem_region *region,
> 288 u32 flags,
289 u64 page_offset, u64 page_count)
290 {
291 if (PageTransCompound(region->pages[page_offset]))
292 flags |= HV_UNMAP_GPA_LARGE_PAGE;
293
294 return hv_call_unmap_gpa_pages(region->partition->pt_id,
295 region->start_gfn + page_offset,
296 page_count, 0);
297 }
298
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH 2/3] irqchip/gic-v3: allocate one SGI for MSHV
From: kernel test robot @ 2025-11-27 10:36 UTC (permalink / raw)
To: Anirudh Raybharam, kys, haiyangz, wei.liu, decui, longli,
catalin.marinas, will, maz, tglx, Arnd Bergmann, akpm, agordeev,
guoweikang.kernel, osandov, bsz, linux-hyperv, linux-arm-kernel,
linux-kernel, linux-arch
Cc: llvm, oe-kbuild-all
In-Reply-To: <20251125170124.2443340-3-anirudh@anirudhrb.com>
Hi Anirudh,
kernel test robot noticed the following build errors:
[auto build test ERROR on next-20251125]
[also build test ERROR on v6.18-rc7]
[cannot apply to arm64/for-next/core tip/irq/core arnd-asm-generic/master linus/master v6.18-rc7 v6.18-rc6 v6.18-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Anirudh-Raybharam/arm64-hyperv-move-hyperv-detection-earlier-in-boot/20251126-011057
base: next-20251125
patch link: https://lore.kernel.org/r/20251125170124.2443340-3-anirudh%40anirudhrb.com
patch subject: [PATCH 2/3] irqchip/gic-v3: allocate one SGI for MSHV
config: arm-randconfig-002-20251127 (https://download.01.org/0day-ci/archive/20251127/202511271745.71G6M2De-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project b3428bb966f1de8aa48375ffee0eba04ede133b7)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271745.71G6M2De-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511271745.71G6M2De-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/irqchip/irq-gic-v3.c:37:10: fatal error: 'asm/mshyperv.h' file not found
37 | #include <asm/mshyperv.h>
| ^~~~~~~~~~~~~~~~
1 error generated.
vim +37 drivers/irqchip/irq-gic-v3.c
32
33 #include <asm/cputype.h>
34 #include <asm/exception.h>
35 #include <asm/smp_plat.h>
36 #include <asm/virt.h>
> 37 #include <asm/mshyperv.h>
38
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH 1/3] arm64: hyperv: move hyperv detection earlier in boot
From: kernel test robot @ 2025-11-27 10:36 UTC (permalink / raw)
To: Anirudh Raybharam, kys, haiyangz, wei.liu, decui, longli,
catalin.marinas, will, maz, tglx, Arnd Bergmann, akpm, agordeev,
guoweikang.kernel, osandov, bsz, linux-hyperv, linux-arm-kernel,
linux-kernel, linux-arch
Cc: oe-kbuild-all
In-Reply-To: <20251125170124.2443340-2-anirudh@anirudhrb.com>
Hi Anirudh,
kernel test robot noticed the following build warnings:
[auto build test WARNING on next-20251125]
[also build test WARNING on v6.18-rc7]
[cannot apply to arm64/for-next/core tip/irq/core arnd-asm-generic/master linus/master v6.18-rc7 v6.18-rc6 v6.18-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Anirudh-Raybharam/arm64-hyperv-move-hyperv-detection-earlier-in-boot/20251126-011057
base: next-20251125
patch link: https://lore.kernel.org/r/20251125170124.2443340-2-anirudh%40anirudhrb.com
patch subject: [PATCH 1/3] arm64: hyperv: move hyperv detection earlier in boot
config: arm64-randconfig-003-20251127 (https://download.01.org/0day-ci/archive/20251127/202511271709.lBS024jA-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 9.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271709.lBS024jA-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511271709.lBS024jA-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from arch/arm64/include/asm/mshyperv.h:66,
from arch/arm64/kernel/setup.c:57:
include/asm-generic/mshyperv.h:326:38: error: return type is an incomplete type
326 | static inline enum hv_isolation_type hv_get_isolation_type(void)
| ^~~~~~~~~~~~~~~~~~~~~
include/asm-generic/mshyperv.h: In function 'hv_get_isolation_type':
include/asm-generic/mshyperv.h:328:9: error: 'HV_ISOLATION_TYPE_NONE' undeclared (first use in this function)
328 | return HV_ISOLATION_TYPE_NONE;
| ^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/mshyperv.h:328:9: note: each undeclared identifier is reported only once for each function it appears in
>> include/asm-generic/mshyperv.h:328:9: warning: 'return' with a value, in function returning void [-Wreturn-type]
include/asm-generic/mshyperv.h:326:38: note: declared here
326 | static inline enum hv_isolation_type hv_get_isolation_type(void)
| ^~~~~~~~~~~~~~~~~~~~~
vim +/return +328 include/asm-generic/mshyperv.h
7ad9bb9d0f357d Wei Liu 2021-09-10 289
3817854ba89201 Nuno Das Neves 2025-03-14 290 #define _hv_status_fmt(fmt) "%s: Hyper-V status: %#x = %s: " fmt
3817854ba89201 Nuno Das Neves 2025-03-14 291 #define hv_status_printk(level, status, fmt, ...) \
3817854ba89201 Nuno Das Neves 2025-03-14 292 do { \
3817854ba89201 Nuno Das Neves 2025-03-14 293 u64 __status = (status); \
3817854ba89201 Nuno Das Neves 2025-03-14 294 pr_##level(_hv_status_fmt(fmt), __func__, hv_result(__status), \
3817854ba89201 Nuno Das Neves 2025-03-14 295 hv_result_to_string(__status), ##__VA_ARGS__); \
3817854ba89201 Nuno Das Neves 2025-03-14 296 } while (0)
3817854ba89201 Nuno Das Neves 2025-03-14 297 #define hv_status_err(status, fmt, ...) \
3817854ba89201 Nuno Das Neves 2025-03-14 298 hv_status_printk(err, status, fmt, ##__VA_ARGS__)
3817854ba89201 Nuno Das Neves 2025-03-14 299 #define hv_status_debug(status, fmt, ...) \
3817854ba89201 Nuno Das Neves 2025-03-14 300 hv_status_printk(debug, status, fmt, ##__VA_ARGS__)
3817854ba89201 Nuno Das Neves 2025-03-14 301
3817854ba89201 Nuno Das Neves 2025-03-14 302 const char *hv_result_to_string(u64 hv_status);
9d8731a1757bef Nuno Das Neves 2025-02-21 303 int hv_result_to_errno(u64 status);
f3a99e761efa61 Tianyu Lan 2020-04-06 304 void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
765e33f5211ab6 Michael Kelley 2019-05-30 305 bool hv_is_hyperv_initialized(void);
b96f86534fa310 Dexuan Cui 2019-11-19 306 bool hv_is_hibernation_supported(void);
a6c76bb08dc7f7 Andrea Parri (Microsoft 2021-02-01 307) enum hv_isolation_type hv_get_isolation_type(void);
a6c76bb08dc7f7 Andrea Parri (Microsoft 2021-02-01 308) bool hv_is_isolation_supported(void);
0cc4f6d9f0b9f2 Tianyu Lan 2021-10-25 309 bool hv_isolation_type_snp(void);
20c89a559e00df Tianyu Lan 2021-10-25 310 u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
d6e0228d265f29 Dexuan Cui 2023-08-24 311 u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2);
3e1b611515d286 Tianyu Lan 2025-09-18 312 void hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set);
a156ad8c508209 Roman Kisel 2025-10-08 313 void hv_para_set_sint_proxy(bool enable);
e6eeb3c782739c Roman Kisel 2025-10-08 314 u64 hv_para_get_synic_register(unsigned int reg);
e6eeb3c782739c Roman Kisel 2025-10-08 315 void hv_para_set_synic_register(unsigned int reg, u64 val);
765e33f5211ab6 Michael Kelley 2019-05-30 316 void hyperv_cleanup(void);
6dc2a774cb4fdb Sunil Muthuswamy 2021-03-23 317 bool hv_query_ext_cap(u64 cap_query);
37200078ed6aa2 Michael Kelley 2022-03-24 318 void hv_setup_dma_ops(struct device *dev, bool coherent);
765e33f5211ab6 Michael Kelley 2019-05-30 319 #else /* CONFIG_HYPERV */
db912b8954c23a Nuno Das Neves 2025-02-21 320 static inline void hv_identify_partition_type(void) {}
765e33f5211ab6 Michael Kelley 2019-05-30 321 static inline bool hv_is_hyperv_initialized(void) { return false; }
b96f86534fa310 Dexuan Cui 2019-11-19 322 static inline bool hv_is_hibernation_supported(void) { return false; }
765e33f5211ab6 Michael Kelley 2019-05-30 323 static inline void hyperv_cleanup(void) {}
f2580a907e5c0e Michael Kelley 2024-03-18 324 static inline void ms_hyperv_late_init(void) {}
0cc4f6d9f0b9f2 Tianyu Lan 2021-10-25 325 static inline bool hv_is_isolation_supported(void) { return false; }
0cc4f6d9f0b9f2 Tianyu Lan 2021-10-25 326 static inline enum hv_isolation_type hv_get_isolation_type(void)
0cc4f6d9f0b9f2 Tianyu Lan 2021-10-25 327 {
0cc4f6d9f0b9f2 Tianyu Lan 2021-10-25 @328 return HV_ISOLATION_TYPE_NONE;
0cc4f6d9f0b9f2 Tianyu Lan 2021-10-25 329 }
765e33f5211ab6 Michael Kelley 2019-05-30 330 #endif /* CONFIG_HYPERV */
765e33f5211ab6 Michael Kelley 2019-05-30 331
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v4 21/21] x86/pvlocks: Move paravirt spinlock functions into own header
From: kernel test robot @ 2025-11-27 9:24 UTC (permalink / raw)
To: Juergen Gross, linux-kernel, x86, linux-hyperv, virtualization,
kvm
Cc: oe-kbuild-all, Juergen Gross, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, Ajay Kaher,
Alexey Makhalov, Broadcom internal kernel review list,
Paolo Bonzini, Vitaly Kuznetsov, Boris Ostrovsky, Josh Poimboeuf,
Peter Zijlstra, xen-devel
In-Reply-To: <20251127070844.21919-22-jgross@suse.com>
Hi Juergen,
kernel test robot noticed the following build errors:
[auto build test ERROR on tip/x86/core]
[also build test ERROR on tip/sched/core kvm/queue kvm/next linus/master v6.18-rc7]
[cannot apply to kvm/linux-next next-20251127]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-Remove-not-needed-includes-of-paravirt-h/20251127-152054
base: tip/x86/core
patch link: https://lore.kernel.org/r/20251127070844.21919-22-jgross%40suse.com
patch subject: [PATCH v4 21/21] x86/pvlocks: Move paravirt spinlock functions into own header
config: i386-allnoconfig (https://download.01.org/0day-ci/archive/20251127/202511271704.MdDOB4pB-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271704.MdDOB4pB-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511271704.MdDOB4pB-lkp@intel.com/
All errors (new ones prefixed by >>):
arch/x86/kernel/alternative.c: In function 'alternative_instructions':
>> arch/x86/kernel/alternative.c:2373:9: error: implicit declaration of function 'paravirt_set_cap'; did you mean 'paravirt_ret0'? [-Wimplicit-function-declaration]
2373 | paravirt_set_cap();
| ^~~~~~~~~~~~~~~~
| paravirt_ret0
vim +2373 arch/x86/kernel/alternative.c
270a69c4485d7d0 arch/x86/kernel/alternative.c Peter Zijlstra 2023-02-08 2344
9a0b5817ad97bb7 arch/i386/kernel/alternative.c Gerd Hoffmann 2006-03-23 2345 void __init alternative_instructions(void)
9a0b5817ad97bb7 arch/i386/kernel/alternative.c Gerd Hoffmann 2006-03-23 2346 {
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2347 u64 ibt;
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2348
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2349 int3_selftest();
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2350
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2351 /*
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2352 * The patching is not fully atomic, so try to avoid local
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2353 * interruptions that might execute the to be patched code.
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2354 * Other CPUs are not running.
7457c0da024b181 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2355 */
8f4e956b313dccc arch/i386/kernel/alternative.c Andi Kleen 2007-07-22 2356 stop_nmi();
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2357
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2358 /*
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2359 * Don't stop machine check exceptions while patching.
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2360 * MCEs only happen when something got corrupted and in this
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2361 * case we must do something about the corruption.
32b1cbe380417f2 arch/x86/kernel/alternative.c Marco Ammon 2019-09-02 2362 * Ignoring it is worse than an unlikely patching race.
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2363 * Also machine checks tend to be broadcast and if one CPU
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2364 * goes into machine check the others follow quickly, so we don't
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2365 * expect a machine check to cause undue problems during to code
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2366 * patching.
123aa76ec0cab5d arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2367 */
8f4e956b313dccc arch/i386/kernel/alternative.c Andi Kleen 2007-07-22 2368
4e6292114c74122 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 2369 /*
f7af6977621a416 arch/x86/kernel/alternative.c Juergen Gross 2023-12-10 2370 * Make sure to set (artificial) features depending on used paravirt
f7af6977621a416 arch/x86/kernel/alternative.c Juergen Gross 2023-12-10 2371 * functions which can later influence alternative patching.
4e6292114c74122 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 2372 */
4e6292114c74122 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 @2373 paravirt_set_cap();
4e6292114c74122 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 2374
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2375 /* Keep CET-IBT disabled until caller/callee are patched */
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2376 ibt = ibt_save(/*disable*/ true);
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2377
931ab63664f02b1 arch/x86/kernel/alternative.c Peter Zijlstra 2022-10-27 2378 __apply_fineibt(__retpoline_sites, __retpoline_sites_end,
1d7e707af446134 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2379) __cfi_sites, __cfi_sites_end, true);
026211c40b05548 arch/x86/kernel/alternative.c Kees Cook 2025-09-03 2380 cfi_debug = false;
931ab63664f02b1 arch/x86/kernel/alternative.c Peter Zijlstra 2022-10-27 2381
7508500900814d1 arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2382 /*
7508500900814d1 arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2383 * Rewrite the retpolines, must be done before alternatives since
7508500900814d1 arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2384 * those can rewrite the retpoline thunks.
7508500900814d1 arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2385 */
1d7e707af446134 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2386) apply_retpolines(__retpoline_sites, __retpoline_sites_end);
1d7e707af446134 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2387) apply_returns(__return_sites, __return_sites_end);
7508500900814d1 arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2388
a82b26451de126a arch/x86/kernel/alternative.c Peter Zijlstra (Intel 2025-06-03 2389) its_fini_core();
a82b26451de126a arch/x86/kernel/alternative.c Peter Zijlstra (Intel 2025-06-03 2390)
e81dc127ef69887 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2391 /*
ab9fea59487d8b5 arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2392 * Adjust all CALL instructions to point to func()-10, including
ab9fea59487d8b5 arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2393 * those in .altinstr_replacement.
e81dc127ef69887 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2394 */
e81dc127ef69887 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2395 callthunks_patch_builtin_calls();
e81dc127ef69887 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2396
ab9fea59487d8b5 arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2397 apply_alternatives(__alt_instructions, __alt_instructions_end);
ab9fea59487d8b5 arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2398
be0fffa5ca894a9 arch/x86/kernel/alternative.c Peter Zijlstra 2023-06-22 2399 /*
be0fffa5ca894a9 arch/x86/kernel/alternative.c Peter Zijlstra 2023-06-22 2400 * Seal all functions that do not have their address taken.
be0fffa5ca894a9 arch/x86/kernel/alternative.c Peter Zijlstra 2023-06-22 2401 */
1d7e707af446134 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2402) apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
ed53a0d971926e4 arch/x86/kernel/alternative.c Peter Zijlstra 2022-03-08 2403
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2404 ibt_restore(ibt);
ebebe30794d38c5 arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2405
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v4 21/21] x86/pvlocks: Move paravirt spinlock functions into own header
From: kernel test robot @ 2025-11-27 9:24 UTC (permalink / raw)
To: Juergen Gross, linux-kernel, x86, linux-hyperv, virtualization,
kvm
Cc: llvm, oe-kbuild-all, Juergen Gross, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, Ajay Kaher,
Alexey Makhalov, Broadcom internal kernel review list,
Paolo Bonzini, Vitaly Kuznetsov, Boris Ostrovsky, Josh Poimboeuf,
Peter Zijlstra, xen-devel
In-Reply-To: <20251127070844.21919-22-jgross@suse.com>
Hi Juergen,
kernel test robot noticed the following build errors:
[auto build test ERROR on tip/x86/core]
[also build test ERROR on tip/sched/core kvm/queue kvm/next linus/master v6.18-rc7]
[cannot apply to kvm/linux-next next-20251127]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-paravirt-Remove-not-needed-includes-of-paravirt-h/20251127-152054
base: tip/x86/core
patch link: https://lore.kernel.org/r/20251127070844.21919-22-jgross%40suse.com
patch subject: [PATCH v4 21/21] x86/pvlocks: Move paravirt spinlock functions into own header
config: x86_64-allnoconfig (https://download.01.org/0day-ci/archive/20251127/202511271747.smpLdjsz-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271747.smpLdjsz-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511271747.smpLdjsz-lkp@intel.com/
All errors (new ones prefixed by >>):
>> arch/x86/kernel/alternative.c:2373:2: error: call to undeclared function 'paravirt_set_cap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
2373 | paravirt_set_cap();
| ^
arch/x86/kernel/alternative.c:2373:2: note: did you mean 'paravirt_ret0'?
arch/x86/include/asm/paravirt-base.h:23:15: note: 'paravirt_ret0' declared here
23 | unsigned long paravirt_ret0(void);
| ^
1 error generated.
vim +/paravirt_set_cap +2373 arch/x86/kernel/alternative.c
270a69c4485d7d arch/x86/kernel/alternative.c Peter Zijlstra 2023-02-08 2344
9a0b5817ad97bb arch/i386/kernel/alternative.c Gerd Hoffmann 2006-03-23 2345 void __init alternative_instructions(void)
9a0b5817ad97bb arch/i386/kernel/alternative.c Gerd Hoffmann 2006-03-23 2346 {
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2347 u64 ibt;
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2348
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2349 int3_selftest();
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2350
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2351 /*
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2352 * The patching is not fully atomic, so try to avoid local
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2353 * interruptions that might execute the to be patched code.
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2354 * Other CPUs are not running.
7457c0da024b18 arch/x86/kernel/alternative.c Peter Zijlstra 2019-05-03 2355 */
8f4e956b313dcc arch/i386/kernel/alternative.c Andi Kleen 2007-07-22 2356 stop_nmi();
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2357
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2358 /*
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2359 * Don't stop machine check exceptions while patching.
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2360 * MCEs only happen when something got corrupted and in this
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2361 * case we must do something about the corruption.
32b1cbe380417f arch/x86/kernel/alternative.c Marco Ammon 2019-09-02 2362 * Ignoring it is worse than an unlikely patching race.
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2363 * Also machine checks tend to be broadcast and if one CPU
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2364 * goes into machine check the others follow quickly, so we don't
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2365 * expect a machine check to cause undue problems during to code
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2366 * patching.
123aa76ec0cab5 arch/x86/kernel/alternative.c Andi Kleen 2009-02-12 2367 */
8f4e956b313dcc arch/i386/kernel/alternative.c Andi Kleen 2007-07-22 2368
4e6292114c7412 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 2369 /*
f7af6977621a41 arch/x86/kernel/alternative.c Juergen Gross 2023-12-10 2370 * Make sure to set (artificial) features depending on used paravirt
f7af6977621a41 arch/x86/kernel/alternative.c Juergen Gross 2023-12-10 2371 * functions which can later influence alternative patching.
4e6292114c7412 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 2372 */
4e6292114c7412 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 @2373 paravirt_set_cap();
4e6292114c7412 arch/x86/kernel/alternative.c Juergen Gross 2021-03-11 2374
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2375 /* Keep CET-IBT disabled until caller/callee are patched */
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2376 ibt = ibt_save(/*disable*/ true);
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2377
931ab63664f02b arch/x86/kernel/alternative.c Peter Zijlstra 2022-10-27 2378 __apply_fineibt(__retpoline_sites, __retpoline_sites_end,
1d7e707af44613 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2379) __cfi_sites, __cfi_sites_end, true);
026211c40b0554 arch/x86/kernel/alternative.c Kees Cook 2025-09-03 2380 cfi_debug = false;
931ab63664f02b arch/x86/kernel/alternative.c Peter Zijlstra 2022-10-27 2381
7508500900814d arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2382 /*
7508500900814d arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2383 * Rewrite the retpolines, must be done before alternatives since
7508500900814d arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2384 * those can rewrite the retpoline thunks.
7508500900814d arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2385 */
1d7e707af44613 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2386) apply_retpolines(__retpoline_sites, __retpoline_sites_end);
1d7e707af44613 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2387) apply_returns(__return_sites, __return_sites_end);
7508500900814d arch/x86/kernel/alternative.c Peter Zijlstra 2021-10-26 2388
a82b26451de126 arch/x86/kernel/alternative.c Peter Zijlstra (Intel 2025-06-03 2389) its_fini_core();
a82b26451de126 arch/x86/kernel/alternative.c Peter Zijlstra (Intel 2025-06-03 2390)
e81dc127ef6988 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2391 /*
ab9fea59487d8b arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2392 * Adjust all CALL instructions to point to func()-10, including
ab9fea59487d8b arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2393 * those in .altinstr_replacement.
e81dc127ef6988 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2394 */
e81dc127ef6988 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2395 callthunks_patch_builtin_calls();
e81dc127ef6988 arch/x86/kernel/alternative.c Thomas Gleixner 2022-09-15 2396
ab9fea59487d8b arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2397 apply_alternatives(__alt_instructions, __alt_instructions_end);
ab9fea59487d8b arch/x86/kernel/alternative.c Peter Zijlstra 2025-02-07 2398
be0fffa5ca894a arch/x86/kernel/alternative.c Peter Zijlstra 2023-06-22 2399 /*
be0fffa5ca894a arch/x86/kernel/alternative.c Peter Zijlstra 2023-06-22 2400 * Seal all functions that do not have their address taken.
be0fffa5ca894a arch/x86/kernel/alternative.c Peter Zijlstra 2023-06-22 2401 */
1d7e707af44613 arch/x86/kernel/alternative.c Mike Rapoport (Microsoft 2025-01-26 2402) apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
ed53a0d971926e arch/x86/kernel/alternative.c Peter Zijlstra 2022-03-08 2403
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2404 ibt_restore(ibt);
ebebe30794d38c arch/x86/kernel/alternative.c Pawan Gupta 2025-05-03 2405
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [RFC PATCH] Drivers: hv: Confidential VMBus exernal memory support
From: Tianyu Lan @ 2025-11-27 9:16 UTC (permalink / raw)
To: vdso
Cc: decui, haiyangz, kys, linux-hyperv, linux-kernel, longli, tiala,
wei.liu
In-Reply-To: <20251127051559.60238-1-vdso@hexbites.dev>
On Thu, Nov 27, 2025 at 1:16 PM <vdso@hexbites.dev> wrote:
>
> From: Roman Kisel <vdso@hexbites.dev>
>
> Tianyu Lan wrote:
>
> > In CVM(Confidential VM), system memory is encrypted
> > by default. Device drivers typically use the swiotlb
> > bounce buffer for DMA memory, which is decrypted
> > and shared between the guest and host. Confidential
> > Vmbus, however, supports a confidential channel
> > that employs encrypted memory for the Vmbus ring
> > buffer and external DMA memory. The support for
> > the confidential ring buffer has already been
> > integrated.
> >
> > In CVM, device drivers usually employ the standard
> > DMA API to map DMA memory with the bounce buffer,
> > which remains transparent to the device driver.
> > For external DMA memory support, Hyper-V specific
> > DMA operations are introduced, bypassing the bounce
> > buffer when the confidential external memory flag
> > is set. These DMA operations might also be reused
> > for TDISP devices in the future, which also support
> > DMA operations with encrypted memory.
> >
> > The DMA operations used are global architecture
> > DMA operations (for details, see get_arch_dma_ops()
> > and get_dma_ops()), and there is no need to set up
> > for each device individually.
> >
> > Signed-off-by: Tianyu Lan <tiala@microsoft.com>
>
> Tinayu,
>
> Looks great to me!
>
> Reviewed-by: Roman Kisel <vdso@hexbites.dev>
>
> P.S. For the inclined reader, here is how the old, only for
> storage and not satisfactory in other ways my attempt to solve this:
>
> https://lore.kernel.org/linux-hyperv/20250409000835.285105-6-romank@linux.microsoft.com/
> https://lore.kernel.org/linux-hyperv/20250409000835.285105-7-romank@linux.microsoft.com/
>
> Maybe it'd be a good idea to CC folks who provided feedback back then.
>
Hi Roman:
Thanks for your review. I will follow your suggestion.
Thanks
> > ---
> > drivers/hv/vmbus_drv.c | 90 +++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 89 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> > index 0dc4692b411a..ca31231b2c32 100644
> > --- a/drivers/hv/vmbus_drv.c
> > +++ b/drivers/hv/vmbus_drv.c
> > @@ -39,6 +39,9 @@
> > #include <clocksource/hyperv_timer.h>
> > #include <asm/mshyperv.h>
> > #include "hyperv_vmbus.h"
> > +#include "../../kernel/dma/direct.h"
> > +
> > +extern const struct dma_map_ops *dma_ops;
> >
> > struct vmbus_dynid {
> > struct list_head node;
> > @@ -1429,6 +1432,88 @@ static int vmbus_alloc_synic_and_connect(void)
> > return -ENOMEM;
> > }
> >
> > +
> > +static bool hyperv_private_memory_dma(struct device *dev)
> > +{
> > + struct hv_device *hv_dev = device_to_hv_device(dev);
> > +
> > + if (hv_dev && hv_dev->channel && hv_dev->channel->co_external_memory)
> > + return true;
> > + else
> > + return false;
> > +}
> > +
> > +static dma_addr_t hyperv_dma_map_page(struct device *dev, struct page *page,
> > + unsigned long offset, size_t size,
> > + enum dma_data_direction dir,
> > + unsigned long attrs)
> > +{
> > + phys_addr_t phys = page_to_phys(page) + offset;
> > +
> > + if (hyperv_private_memory_dma(dev))
> > + return __phys_to_dma(dev, phys);
> > + else
> > + return dma_direct_map_phys(dev, phys, size, dir, attrs);
> > +}
> > +
> > +static void hyperv_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
> > + size_t size, enum dma_data_direction dir, unsigned long attrs)
> > +{
> > + if (!hyperv_private_memory_dma(dev))
> > + dma_direct_unmap_phys(dev, dma_handle, size, dir, attrs);
> > +}
> > +
> > +static int hyperv_dma_map_sg(struct device *dev, struct scatterlist *sgl,
> > + int nelems, enum dma_data_direction dir,
> > + unsigned long attrs)
> > +{
> > + struct scatterlist *sg;
> > + dma_addr_t dma_addr;
> > + int i;
> > +
> > + if (hyperv_private_memory_dma(dev)) {
> > + for_each_sg(sgl, sg, nelems, i) {
> > + dma_addr = __phys_to_dma(dev, sg_phys(sg));
> > + sg_dma_address(sg) = dma_addr;
> > + sg_dma_len(sg) = sg->length;
> > + }
> > +
> > + return nelems;
> > + } else {
> > + return dma_direct_map_sg(dev, sgl, nelems, dir, attrs);
> > + }
> > +}
> > +
> > +static void hyperv_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
> > + int nelems, enum dma_data_direction dir, unsigned long attrs)
> > +{
> > + if (!hyperv_private_memory_dma(dev))
> > + dma_direct_unmap_sg(dev, sgl, nelems, dir, attrs);
> > +}
> > +
> > +static int hyperv_dma_supported(struct device *dev, u64 mask)
> > +{
> > + dev->coherent_dma_mask = mask;
> > + return 1;
> > +}
> > +
> > +static size_t hyperv_dma_max_mapping_size(struct device *dev)
> > +{
> > + if (hyperv_private_memory_dma(dev))
> > + return SIZE_MAX;
> > + else
> > + return swiotlb_max_mapping_size(dev);
> > +}
> > +
> > +const struct dma_map_ops hyperv_dma_ops = {
> > + .map_page = hyperv_dma_map_page,
> > + .unmap_page = hyperv_dma_unmap_page,
> > + .map_sg = hyperv_dma_map_sg,
> > + .unmap_sg = hyperv_dma_unmap_sg,
> > + .dma_supported = hyperv_dma_supported,
> > + .max_mapping_size = hyperv_dma_max_mapping_size,
> > +};
> > +
> > /*
> > * vmbus_bus_init -Main vmbus driver initialization routine.
> > *
> > @@ -1479,8 +1564,11 @@ static int vmbus_bus_init(void)
> > * doing that on each VP while initializing SynIC's wastes time.
> > */
> > is_confidential = ms_hyperv.confidential_vmbus_available;
> > - if (is_confidential)
> > + if (is_confidential) {
> > + dma_ops = &hyperv_dma_ops;
> > pr_info("Establishing connection to the confidential VMBus\n");
> > + }
> > +
> > hv_para_set_sint_proxy(!is_confidential);
> > ret = vmbus_alloc_synic_and_connect();
> > if (ret)
> > --
> > 2.50.1
--
Thanks
Tianyu Lan
^ permalink raw reply
* [PATCH net-next v12 11/12] selftests/vsock: add tests for host <-> vm connectivity with namespaces
From: Bobby Eshleman @ 2025-11-27 7:47 UTC (permalink / raw)
To: Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan
Cc: linux-kernel, virtualization, netdev, kvm, linux-hyperv,
linux-kselftest, berrange, Sargun Dhillon, Bobby Eshleman,
Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-0-257ee21cd5de@meta.com>
From: Bobby Eshleman <bobbyeshleman@meta.com>
Add tests to validate namespace correctness using vsock_test and socat.
The vsock_test tool is used to validate expected success tests, but
socat is used for expected failure tests. socat is used to ensure that
connections are rejected outright instead of failing due to some other
socket behavior (as tested in vsock_test). Additionally, socat is
already required for tunneling TCP traffic from vsock_test. Using only
one of the vsock_test tests like 'test_stream_client_close_client' would
have yielded a similar result, but doing so wouldn't remove the socat
dependency.
Additionally, check for the dependency socat. socat needs special
handling beyond just checking if it is on the path because it must be
compiled with support for both vsock and unix. The function
check_socat() checks that this support exists.
Add more padding to test name printf strings because the tests added in
this patch would otherwise overflow.
Add vm_dmesg_* helpers to encapsulate checking dmesg
for oops and warnings.
Add ability to pass extra args to host-side vsock_test so that tests
that cause false positives may be skipped with arg --skip.
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Changes in v12:
- add test skip (vsock_test test 29) when host_vsock_test() uses client
mode in a local namespace. Test 29 causes a false positive to trigger.
Changes in v11:
- add 'sleep "${WAIT_PERIOD}"' after any non-TCP socat LISTEN cmd
(Stefano)
- add host_wait_for_listener() after any socat TCP-LISTEN (Stefano)
- reuse vm_dmesg_{oops,warn}_count() inside vm_dmesg_check()
- fix copy-paste in test_ns_same_local_vm_connect_to_local_host_ok()
(Stefano)
Changes in v10:
- add vm_dmesg_start() and vm_dmesg_check()
Changes in v9:
- consistent variable quoting
---
tools/testing/selftests/vsock/vmtest.sh | 572 +++++++++++++++++++++++++++++++-
1 file changed, 568 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
index ec18eb5b4ccd..da9198dc8ab5 100755
--- a/tools/testing/selftests/vsock/vmtest.sh
+++ b/tools/testing/selftests/vsock/vmtest.sh
@@ -7,6 +7,7 @@
# * virtme-ng
# * busybox-static (used by virtme-ng)
# * qemu (used by virtme-ng)
+# * socat
#
# shellcheck disable=SC2317,SC2119
@@ -54,6 +55,19 @@ readonly TEST_NAMES=(
ns_local_same_cid_ok
ns_global_local_same_cid_ok
ns_local_global_same_cid_ok
+ ns_diff_global_host_connect_to_global_vm_ok
+ ns_diff_global_host_connect_to_local_vm_fails
+ ns_diff_global_vm_connect_to_global_host_ok
+ ns_diff_global_vm_connect_to_local_host_fails
+ ns_diff_local_host_connect_to_local_vm_fails
+ ns_diff_local_vm_connect_to_local_host_fails
+ ns_diff_global_to_local_loopback_local_fails
+ ns_diff_local_to_global_loopback_fails
+ ns_diff_local_to_local_loopback_fails
+ ns_diff_global_to_global_loopback_ok
+ ns_same_local_loopback_ok
+ ns_same_local_host_connect_to_local_vm_ok
+ ns_same_local_vm_connect_to_local_host_ok
)
readonly TEST_DESCS=(
# vm_server_host_client
@@ -82,6 +96,45 @@ readonly TEST_DESCS=(
# ns_local_global_same_cid_ok
"Check QEMU successfully starts one VM in a local ns and then another VM in a global ns with the same CID."
+
+ # ns_diff_global_host_connect_to_global_vm_ok
+ "Run vsock_test client in global ns with server in VM in another global ns."
+
+ # ns_diff_global_host_connect_to_local_vm_fails
+ "Run socat to test a process in a global ns fails to connect to a VM in a local ns."
+
+ # ns_diff_global_vm_connect_to_global_host_ok
+ "Run vsock_test client in VM in a global ns with server in another global ns."
+
+ # ns_diff_global_vm_connect_to_local_host_fails
+ "Run socat to test a VM in a global ns fails to connect to a host process in a local ns."
+
+ # ns_diff_local_host_connect_to_local_vm_fails
+ "Run socat to test a host process in a local ns fails to connect to a VM in another local ns."
+
+ # ns_diff_local_vm_connect_to_local_host_fails
+ "Run socat to test a VM in a local ns fails to connect to a host process in another local ns."
+
+ # ns_diff_global_to_local_loopback_local_fails
+ "Run socat to test a loopback vsock in a global ns fails to connect to a vsock in a local ns."
+
+ # ns_diff_local_to_global_loopback_fails
+ "Run socat to test a loopback vsock in a local ns fails to connect to a vsock in a global ns."
+
+ # ns_diff_local_to_local_loopback_fails
+ "Run socat to test a loopback vsock in a local ns fails to connect to a vsock in another local ns."
+
+ # ns_diff_global_to_global_loopback_ok
+ "Run socat to test a loopback vsock in a global ns successfully connects to a vsock in another global ns."
+
+ # ns_same_local_loopback_ok
+ "Run socat to test a loopback vsock in a local ns successfully connects to a vsock in the same ns."
+
+ # ns_same_local_host_connect_to_local_vm_ok
+ "Run vsock_test client in a local ns with server in VM in same ns."
+
+ # ns_same_local_vm_connect_to_local_host_ok
+ "Run vsock_test client in VM in a local ns with server in same ns."
)
readonly USE_SHARED_VM=(
@@ -112,7 +165,7 @@ usage() {
for ((i = 0; i < ${#TEST_NAMES[@]}; i++)); do
name=${TEST_NAMES[${i}]}
desc=${TEST_DESCS[${i}]}
- printf "\t%-35s%-35s\n" "${name}" "${desc}"
+ printf "\t%-55s%-35s\n" "${name}" "${desc}"
done
echo
@@ -231,7 +284,7 @@ check_args() {
}
check_deps() {
- for dep in vng ${QEMU} busybox pkill ssh ss; do
+ for dep in vng ${QEMU} busybox pkill ssh ss socat; do
if [[ ! -x $(command -v "${dep}") ]]; then
echo -e "skip: dependency ${dep} not found!\n"
exit "${KSFT_SKIP}"
@@ -282,6 +335,20 @@ check_vng() {
fi
}
+check_socat() {
+ local support_string
+
+ support_string="$(socat -V)"
+
+ if [[ "${support_string}" != *"WITH_VSOCK 1"* ]]; then
+ die "err: socat is missing vsock support"
+ fi
+
+ if [[ "${support_string}" != *"WITH_UNIX 1"* ]]; then
+ die "err: socat is missing unix support"
+ fi
+}
+
handle_build() {
if [[ ! "${BUILD}" -eq 1 ]]; then
return
@@ -330,6 +397,14 @@ terminate_pidfiles() {
done
}
+terminate_pids() {
+ local pid
+
+ for pid in "$@"; do
+ kill -SIGTERM "${pid}" &>/dev/null || :
+ done
+}
+
vm_start() {
local pidfile=$1
local ns=$2
@@ -468,6 +543,28 @@ vm_dmesg_warn_count() {
vm_ssh "${ns}" -- dmesg --level=warn 2>/dev/null | grep -c -i 'vsock'
}
+vm_dmesg_check() {
+ local pidfile=$1
+ local ns=$2
+ local oops_before=$3
+ local warn_before=$4
+ local oops_after warn_after
+
+ oops_after=$(vm_dmesg_oops_count "${ns}")
+ if [[ "${oops_after}" -gt "${oops_before}" ]]; then
+ echo "FAIL: kernel oops detected on vm in ns ${ns}" | log_host
+ return 1
+ fi
+
+ warn_after=$(vm_dmesg_warn_count "${ns}")
+ if [[ "${warn_after}" -gt "${warn_before}" ]]; then
+ echo "FAIL: kernel warning detected on vm in ns ${ns}" | log_host
+ return 1
+ fi
+
+ return 0
+}
+
vm_vsock_test() {
local ns=$1
local host=$2
@@ -511,6 +608,8 @@ host_vsock_test() {
local host=$2
local cid=$3
local port=$4
+ shift 4
+ local extra_args=("$@")
local rc
local cmd="${VSOCK_TEST}"
@@ -525,13 +624,15 @@ host_vsock_test() {
--mode=client \
--peer-cid="${cid}" \
--control-host="${host}" \
- --control-port="${port}" 2>&1 | log_host
+ --control-port="${port}" \
+ "${extra_args[@]}" 2>&1 | log_host
rc=$?
else
${cmd} \
--mode=server \
--peer-cid="${cid}" \
- --control-port="${port}" 2>&1 | log_host &
+ --control-port="${port}" \
+ "${extra_args[@]}" 2>&1 | log_host &
rc=$?
if [[ $rc -ne 0 ]]; then
@@ -592,6 +693,468 @@ test_ns_host_vsock_ns_mode_ok() {
return "${KSFT_PASS}"
}
+test_ns_diff_global_host_connect_to_global_vm_ok() {
+ local oops_before warn_before
+ local pids pid pidfile
+ local ns0 ns1 port
+ declare -a pids
+ local unixfile
+ ns0="global0"
+ ns1="global1"
+ port=1234
+ local rc
+
+ init_namespaces
+
+ pidfile="$(create_pidfile)"
+
+ if ! vm_start "${pidfile}" "${ns0}"; then
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns0}"
+ oops_before=$(vm_dmesg_oops_count "${ns0}")
+ warn_before=$(vm_dmesg_warn_count "${ns0}")
+
+ unixfile=$(mktemp -u /tmp/XXXX.sock)
+ ip netns exec "${ns1}" \
+ socat TCP-LISTEN:"${TEST_HOST_PORT}",fork \
+ UNIX-CONNECT:"${unixfile}" &
+ pids+=($!)
+ host_wait_for_listener "${ns1}" "${TEST_HOST_PORT}" "tcp"
+
+ ip netns exec "${ns0}" socat UNIX-LISTEN:"${unixfile}",fork \
+ TCP-CONNECT:localhost:"${TEST_HOST_PORT}" &
+ pids+=($!)
+ host_wait_for_listener "${ns0}" "${unixfile}" "unix"
+
+ vm_vsock_test "${ns0}" "server" 2 "${TEST_GUEST_PORT}"
+ vm_wait_for_listener "${ns0}" "${TEST_GUEST_PORT}" "tcp"
+ host_vsock_test "${ns1}" "127.0.0.1" "${VSOCK_CID}" "${TEST_HOST_PORT}"
+ rc=$?
+
+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pids "${pids[@]}"
+ terminate_pidfiles "${pidfile}"
+
+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
+ return "${KSFT_FAIL}"
+ fi
+
+ return "${KSFT_PASS}"
+}
+
+test_ns_diff_global_host_connect_to_local_vm_fails() {
+ local oops_before warn_before
+ local ns0="global0"
+ local ns1="local0"
+ local port=12345
+ local dmesg_rc
+ local pidfile
+ local result
+ local pid
+
+ init_namespaces
+
+ outfile=$(mktemp)
+
+ pidfile="$(create_pidfile)"
+ if ! vm_start "${pidfile}" "${ns1}"; then
+ log_host "failed to start vm (cid=${VSOCK_CID}, ns=${ns0})"
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns1}"
+ oops_before=$(vm_dmesg_oops_count "${ns1}")
+ warn_before=$(vm_dmesg_warn_count "${ns1}")
+
+ vm_ssh "${ns1}" -- socat VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" &
+ vm_wait_for_listener "${ns1}" "${port}" "vsock"
+ echo TEST | ip netns exec "${ns0}" \
+ socat STDIN VSOCK-CONNECT:"${VSOCK_CID}":"${port}" 2>/dev/null
+
+ vm_dmesg_check "${pidfile}" "${ns1}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+ result=$(cat "${outfile}")
+ rm -f "${outfile}"
+
+ if [[ "${result}" == "TEST" ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
+ return "${KSFT_FAIL}"
+ fi
+
+ return "${KSFT_PASS}"
+}
+
+test_ns_diff_global_vm_connect_to_global_host_ok() {
+ local oops_before warn_before
+ local ns0="global0"
+ local ns1="global1"
+ local port=12345
+ local unixfile
+ local dmesg_rc
+ local pidfile
+ local pids
+ local rc
+
+ init_namespaces
+
+ declare -a pids
+
+ log_host "Setup socat bridge from ns ${ns0} to ns ${ns1} over port ${port}"
+
+ unixfile=$(mktemp -u /tmp/XXXX.sock)
+
+ ip netns exec "${ns0}" \
+ socat TCP-LISTEN:"${port}" UNIX-CONNECT:"${unixfile}" &
+ pids+=($!)
+ host_wait_for_listener "${ns0}" "${port}" "tcp"
+
+ ip netns exec "${ns1}" \
+ socat UNIX-LISTEN:"${unixfile}" TCP-CONNECT:127.0.0.1:"${port}" &
+ pids+=($!)
+ host_wait_for_listener "${ns1}" "${unixfile}" "unix"
+
+ log_host "Launching ${VSOCK_TEST} in ns ${ns1}"
+ host_vsock_test "${ns1}" "server" "${VSOCK_CID}" "${port}"
+
+ pidfile="$(create_pidfile)"
+ if ! vm_start "${pidfile}" "${ns0}"; then
+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
+ terminate_pids "${pids[@]}"
+ rm -f "${unixfile}"
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns0}"
+
+ oops_before=$(vm_dmesg_oops_count "${ns0}")
+ warn_before=$(vm_dmesg_warn_count "${ns0}")
+
+ vm_vsock_test "${ns0}" "10.0.2.2" 2 "${port}"
+ rc=$?
+
+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+ terminate_pids "${pids[@]}"
+ rm -f "${unixfile}"
+
+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
+ return "${KSFT_FAIL}"
+ fi
+
+ return "${KSFT_PASS}"
+
+}
+
+test_ns_diff_global_vm_connect_to_local_host_fails() {
+ local ns0="global0"
+ local ns1="local0"
+ local port=12345
+ local oops_before warn_before
+ local dmesg_rc
+ local pidfile
+ local result
+ local pid
+
+ init_namespaces
+
+ log_host "Launching socat in ns ${ns1}"
+ outfile=$(mktemp)
+
+ ip netns exec "${ns1}" socat VSOCK-LISTEN:"${port}" STDOUT &> "${outfile}" &
+ pid=$!
+ host_wait_for_listener "${ns1}" "${port}" "vsock"
+
+ pidfile="$(create_pidfile)"
+ if ! vm_start "${pidfile}" "${ns0}"; then
+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
+ terminate_pids "${pid}"
+ rm -f "${outfile}"
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns0}"
+
+ oops_before=$(vm_dmesg_oops_count "${ns0}")
+ warn_before=$(vm_dmesg_warn_count "${ns0}")
+
+ vm_ssh "${ns0}" -- \
+ bash -c "echo TEST | socat STDIN VSOCK-CONNECT:2:${port}" 2>&1 | log_guest
+
+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+ terminate_pids "${pid}"
+
+ result=$(cat "${outfile}")
+ rm -f "${outfile}"
+
+ if [[ "${result}" != TEST ]] && [[ "${dmesg_rc}" -eq 0 ]]; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_diff_local_host_connect_to_local_vm_fails() {
+ local ns0="local0"
+ local ns1="local1"
+ local port=12345
+ local oops_before warn_before
+ local dmesg_rc
+ local pidfile
+ local result
+ local pid
+
+ init_namespaces
+
+ outfile=$(mktemp)
+
+ pidfile="$(create_pidfile)"
+ if ! vm_start "${pidfile}" "${ns1}"; then
+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns1}"
+ oops_before=$(vm_dmesg_oops_count "${ns1}")
+ warn_before=$(vm_dmesg_warn_count "${ns1}")
+
+ vm_ssh "${ns1}" -- socat VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" &
+ vm_wait_for_listener "${ns1}" "${port}" "vsock"
+
+ echo TEST | ip netns exec "${ns0}" \
+ socat STDIN VSOCK-CONNECT:"${VSOCK_CID}":"${port}" 2>/dev/null
+
+ vm_dmesg_check "${pidfile}" "${ns1}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+
+ result=$(cat "${outfile}")
+ rm -f "${outfile}"
+
+ if [[ "${result}" != TEST ]] && [[ "${dmesg_rc}" -eq 0 ]]; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_diff_local_vm_connect_to_local_host_fails() {
+ local oops_before warn_before
+ local ns0="local0"
+ local ns1="local1"
+ local port=12345
+ local dmesg_rc
+ local pidfile
+ local result
+ local pid
+
+ init_namespaces
+
+ log_host "Launching socat in ns ${ns1}"
+ outfile=$(mktemp)
+ ip netns exec "${ns1}" socat VSOCK-LISTEN:"${port}" STDOUT &> "${outfile}" &
+ pid=$!
+ host_wait_for_listener "${ns1}" "${port}" "vsock"
+
+ pidfile="$(create_pidfile)"
+ if ! vm_start "${pidfile}" "${ns0}"; then
+ log_host "failed to start vm (cid=${cid}, ns=${ns0})"
+ rm -f "${outfile}"
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns0}"
+ oops_before=$(vm_dmesg_oops_count "${ns0}")
+ warn_before=$(vm_dmesg_warn_count "${ns0}")
+
+ vm_ssh "${ns0}" -- \
+ bash -c "echo TEST | socat STDIN VSOCK-CONNECT:2:${port}" 2>&1 | log_guest
+
+ vm_dmesg_check "${pidfile}" "${ns0}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+ terminate_pids "${pid}"
+
+ result=$(cat "${outfile}")
+ rm -f "${outfile}"
+
+ if [[ "${result}" != TEST ]] && [[ "${dmesg_rc}" -eq 0 ]]; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+__test_loopback_two_netns() {
+ local ns0=$1
+ local ns1=$2
+ local port=12345
+ local result
+ local pid
+
+ modprobe vsock_loopback &> /dev/null || :
+
+ log_host "Launching socat in ns ${ns1}"
+ outfile=$(mktemp)
+
+ ip netns exec "${ns1}" socat VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" 2>/dev/null &
+ pid=$!
+ host_wait_for_listener "${ns1}" "${port}" "vsock"
+
+ log_host "Launching socat in ns ${ns0}"
+ echo TEST | ip netns exec "${ns0}" socat STDIN VSOCK-CONNECT:1:"${port}" 2>/dev/null
+ terminate_pids "${pid}"
+
+ result=$(cat "${outfile}")
+ rm -f "${outfile}"
+
+ if [[ "${result}" == TEST ]]; then
+ return 0
+ fi
+
+ return 1
+}
+
+test_ns_diff_global_to_local_loopback_local_fails() {
+ init_namespaces
+
+ if ! __test_loopback_two_netns "global0" "local0"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_diff_local_to_global_loopback_fails() {
+ init_namespaces
+
+ if ! __test_loopback_two_netns "local0" "global0"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_diff_local_to_local_loopback_fails() {
+ init_namespaces
+
+ if ! __test_loopback_two_netns "local0" "local1"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_diff_global_to_global_loopback_ok() {
+ init_namespaces
+
+ if __test_loopback_two_netns "global0" "global1"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_same_local_loopback_ok() {
+ init_namespaces
+
+ if __test_loopback_two_netns "local0" "local0"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_same_local_host_connect_to_local_vm_ok() {
+ local oops_before warn_before
+ local ns="local0"
+ local port=1234
+ local dmesg_rc
+ local pidfile
+ local rc
+
+ init_namespaces
+
+ pidfile="$(create_pidfile)"
+
+ if ! vm_start "${pidfile}" "${ns}"; then
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns}"
+ oops_before=$(vm_dmesg_oops_count "${ns}")
+ warn_before=$(vm_dmesg_warn_count "${ns}")
+
+ vm_vsock_test "${ns}" "server" 2 "${TEST_GUEST_PORT}"
+
+ # Skip test 29 (transport release use-after-free): This test attempts
+ # binding both G2H and H2G CIDs. Because virtio-vsock (G2H) doesn't
+ # support local namespaces the test will fail when
+ # transport_g2h->stream_allow() returns false. This edge case only
+ # happens for vsock_test in client mode on the host in a local
+ # namespace. This is a false positive.
+ host_vsock_test "${ns}" "127.0.0.1" "${VSOCK_CID}" "${TEST_HOST_PORT}" --skip=29
+ rc=$?
+
+ vm_dmesg_check "${pidfile}" "${ns}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+
+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
+ return "${KSFT_FAIL}"
+ fi
+
+ return "${KSFT_PASS}"
+}
+
+test_ns_same_local_vm_connect_to_local_host_ok() {
+ local oops_before warn_before
+ local ns="local0"
+ local port=1234
+ local dmesg_rc
+ local pidfile
+ local rc
+
+ init_namespaces
+
+ pidfile="$(create_pidfile)"
+
+ if ! vm_start "${pidfile}" "${ns}"; then
+ return "${KSFT_FAIL}"
+ fi
+
+ vm_wait_for_ssh "${ns}"
+ oops_before=$(vm_dmesg_oops_count "${ns}")
+ warn_before=$(vm_dmesg_warn_count "${ns}")
+
+ host_vsock_test "${ns}" "server" "${VSOCK_CID}" "${port}"
+ vm_vsock_test "${ns}" "10.0.2.2" 2 "${port}"
+ rc=$?
+
+ vm_dmesg_check "${pidfile}" "${ns}" "${oops_before}" "${warn_before}"
+ dmesg_rc=$?
+
+ terminate_pidfiles "${pidfile}"
+
+ if [[ "${rc}" -ne 0 ]] || [[ "${dmesg_rc}" -ne 0 ]]; then
+ return "${KSFT_FAIL}"
+ fi
+
+ return "${KSFT_PASS}"
+}
+
namespaces_can_boot_same_cid() {
local ns0=$1
local ns1=$2
@@ -869,6 +1432,7 @@ fi
check_args "${ARGS[@]}"
check_deps
check_vng
+check_socat
handle_build
echo "1..${#ARGS[@]}"
--
2.47.3
^ permalink raw reply related
* [PATCH net-next v12 12/12] selftests/vsock: add tests for namespace deletion and mode changes
From: Bobby Eshleman @ 2025-11-27 7:47 UTC (permalink / raw)
To: Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan
Cc: linux-kernel, virtualization, netdev, kvm, linux-hyperv,
linux-kselftest, berrange, Sargun Dhillon, Bobby Eshleman,
Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-0-257ee21cd5de@meta.com>
From: Bobby Eshleman <bobbyeshleman@meta.com>
Add tests that validate vsock sockets are resilient to deleting
namespaces or changing namespace modes from global to local. The vsock
sockets should still function normally.
The function check_ns_changes_dont_break_connection() is added to re-use
the step-by-step logic of 1) setup connections, 2) do something that
would maybe break the connections, 3) check that the connections are
still ok.
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Changes in v11:
- remove pipefile (Stefano)
Changes in v9:
- more consistent shell style
- clarify -u usage comment for pipefile
---
tools/testing/selftests/vsock/vmtest.sh | 119 ++++++++++++++++++++++++++++++++
1 file changed, 119 insertions(+)
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
index da9198dc8ab5..a903a0bf66c4 100755
--- a/tools/testing/selftests/vsock/vmtest.sh
+++ b/tools/testing/selftests/vsock/vmtest.sh
@@ -68,6 +68,12 @@ readonly TEST_NAMES=(
ns_same_local_loopback_ok
ns_same_local_host_connect_to_local_vm_ok
ns_same_local_vm_connect_to_local_host_ok
+ ns_mode_change_connection_continue_vm_ok
+ ns_mode_change_connection_continue_host_ok
+ ns_mode_change_connection_continue_both_ok
+ ns_delete_vm_ok
+ ns_delete_host_ok
+ ns_delete_both_ok
)
readonly TEST_DESCS=(
# vm_server_host_client
@@ -135,6 +141,24 @@ readonly TEST_DESCS=(
# ns_same_local_vm_connect_to_local_host_ok
"Run vsock_test client in VM in a local ns with server in same ns."
+
+ # ns_mode_change_connection_continue_vm_ok
+ "Check that changing NS mode of VM namespace from global to local after a connection is established doesn't break the connection"
+
+ # ns_mode_change_connection_continue_host_ok
+ "Check that changing NS mode of host namespace from global to local after a connection is established doesn't break the connection"
+
+ # ns_mode_change_connection_continue_both_ok
+ "Check that changing NS mode of host and VM namespaces from global to local after a connection is established doesn't break the connection"
+
+ # ns_delete_vm_ok
+ "Check that deleting the VM's namespace does not break the socket connection"
+
+ # ns_delete_host_ok
+ "Check that deleting the host's namespace does not break the socket connection"
+
+ # ns_delete_both_ok
+ "Check that deleting the VM and host's namespaces does not break the socket connection"
)
readonly USE_SHARED_VM=(
@@ -1274,6 +1298,101 @@ test_vm_loopback() {
return "${KSFT_PASS}"
}
+check_ns_changes_dont_break_connection() {
+ local pipefile pidfile outfile
+ local ns0="global0"
+ local ns1="global1"
+ local port=12345
+ local pids=()
+ local rc=0
+
+ init_namespaces
+
+ pidfile="$(create_pidfile)"
+ if ! vm_start "${pidfile}" "${ns0}"; then
+ return "${KSFT_FAIL}"
+ fi
+ vm_wait_for_ssh "${ns0}"
+
+ outfile=$(mktemp)
+ vm_ssh "${ns0}" -- \
+ socat VSOCK-LISTEN:"${port}",fork STDOUT > "${outfile}" 2>/dev/null &
+ pids+=($!)
+ vm_wait_for_listener "${ns0}" "${port}" "vsock"
+
+ # We use a pipe here so that we can echo into the pipe instead of using
+ # socat and a unix socket file. We just need a name for the pipe (not a
+ # regular file) so use -u.
+ pipefile=$(mktemp -u /tmp/vmtest_pipe_XXXX)
+ ip netns exec "${ns1}" \
+ socat PIPE:"${pipefile}" VSOCK-CONNECT:"${VSOCK_CID}":"${port}" &
+ pids+=($!)
+
+ timeout "${WAIT_PERIOD}" \
+ bash -c 'while [[ ! -e '"${pipefile}"' ]]; do sleep 1; done; exit 0'
+
+ if [[ $2 == "delete" ]]; then
+ if [[ "$1" == "vm" ]]; then
+ ip netns del "${ns0}"
+ elif [[ "$1" == "host" ]]; then
+ ip netns del "${ns1}"
+ elif [[ "$1" == "both" ]]; then
+ ip netns del "${ns0}"
+ ip netns del "${ns1}"
+ fi
+ elif [[ $2 == "change_mode" ]]; then
+ if [[ "$1" == "vm" ]]; then
+ ns_set_mode "${ns0}" "local"
+ elif [[ "$1" == "host" ]]; then
+ ns_set_mode "${ns1}" "local"
+ elif [[ "$1" == "both" ]]; then
+ ns_set_mode "${ns0}" "local"
+ ns_set_mode "${ns1}" "local"
+ fi
+ fi
+
+ echo "TEST" > "${pipefile}"
+
+ timeout "${WAIT_PERIOD}" \
+ bash -c 'while [[ ! -s '"${outfile}"' ]]; do sleep 1; done; exit 0'
+
+ if grep -q "TEST" "${outfile}"; then
+ rc="${KSFT_PASS}"
+ else
+ rc="${KSFT_FAIL}"
+ fi
+
+ terminate_pidfiles "${pidfile}"
+ terminate_pids "${pids[@]}"
+ rm -f "${outfile}" "${pipefile}"
+
+ return "${rc}"
+}
+
+test_ns_mode_change_connection_continue_vm_ok() {
+ check_ns_changes_dont_break_connection "vm" "change_mode"
+}
+
+test_ns_mode_change_connection_continue_host_ok() {
+ check_ns_changes_dont_break_connection "host" "change_mode"
+}
+
+test_ns_mode_change_connection_continue_both_ok() {
+ check_ns_changes_dont_break_connection "both" "change_mode"
+}
+
+test_ns_delete_vm_ok() {
+ check_ns_changes_dont_break_connection "vm" "delete"
+}
+
+test_ns_delete_host_ok() {
+ check_ns_changes_dont_break_connection "host" "delete"
+}
+
+test_ns_delete_both_ok() {
+ check_ns_changes_dont_break_connection "both" "delete"
+}
+
shared_vm_test() {
local tname
--
2.47.3
^ permalink raw reply related
* [PATCH net-next v12 10/12] selftests/vsock: add namespace tests for CID collisions
From: Bobby Eshleman @ 2025-11-27 7:47 UTC (permalink / raw)
To: Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan
Cc: linux-kernel, virtualization, netdev, kvm, linux-hyperv,
linux-kselftest, berrange, Sargun Dhillon, Bobby Eshleman,
Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-0-257ee21cd5de@meta.com>
From: Bobby Eshleman <bobbyeshleman@meta.com>
Add tests to verify CID collision rules across different vsock namespace
modes.
1. Two VMs with the same CID cannot start in different global namespaces
(ns_global_same_cid_fails)
2. Two VMs with the same CID can start in different local namespaces
(ns_local_same_cid_ok)
3. VMs with the same CID can coexist when one is in a global namespace
and another is in a local namespace (ns_global_local_same_cid_ok and
ns_local_global_same_cid_ok)
The tests ns_global_local_same_cid_ok and ns_local_global_same_cid_ok
make sure that ordering does not matter.
The tests use a shared helper function namespaces_can_boot_same_cid()
that attempts to start two VMs with identical CIDs in the specified
namespaces and verifies whether VM initialization failed or succeeded.
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Changes in v11:
- check vm_start() rc in namespaces_can_boot_same_cid() (Stefano)
- fix ns_local_same_cid_ok() to use local0 and local1 instead of reusing
local0 twice. This check should pass, ensuring local namespaces do not
collide (Stefano)
---
tools/testing/selftests/vsock/vmtest.sh | 78 +++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
index 28b91b906cdc..ec18eb5b4ccd 100755
--- a/tools/testing/selftests/vsock/vmtest.sh
+++ b/tools/testing/selftests/vsock/vmtest.sh
@@ -50,6 +50,10 @@ readonly TEST_NAMES=(
vm_loopback
ns_host_vsock_ns_mode_ok
ns_host_vsock_ns_mode_write_once_ok
+ ns_global_same_cid_fails
+ ns_local_same_cid_ok
+ ns_global_local_same_cid_ok
+ ns_local_global_same_cid_ok
)
readonly TEST_DESCS=(
# vm_server_host_client
@@ -66,6 +70,18 @@ readonly TEST_DESCS=(
# ns_host_vsock_ns_mode_write_once_ok
"Check /proc/sys/net/vsock/ns_mode is write-once on the host."
+
+ # ns_global_same_cid_fails
+ "Check QEMU fails to start two VMs with same CID in two different global namespaces."
+
+ # ns_local_same_cid_ok
+ "Check QEMU successfully starts two VMs with same CID in two different local namespaces."
+
+ # ns_global_local_same_cid_ok
+ "Check QEMU successfully starts one VM in a global ns and then another VM in a local ns with the same CID."
+
+ # ns_local_global_same_cid_ok
+ "Check QEMU successfully starts one VM in a local ns and then another VM in a global ns with the same CID."
)
readonly USE_SHARED_VM=(
@@ -576,6 +592,68 @@ test_ns_host_vsock_ns_mode_ok() {
return "${KSFT_PASS}"
}
+namespaces_can_boot_same_cid() {
+ local ns0=$1
+ local ns1=$2
+ local pidfile1 pidfile2
+ local rc
+
+ pidfile1="$(create_pidfile)"
+
+ # The first VM should be able to start. If it can't then we have
+ # problems and need to return non-zero.
+ if ! vm_start "${pidfile1}" "${ns0}"; then
+ return 1
+ fi
+
+ pidfile2="$(create_pidfile)"
+ vm_start "${pidfile2}" "${ns1}"
+ rc=$?
+ terminate_pidfiles "${pidfile1}" "${pidfile2}"
+
+ return "${rc}"
+}
+
+test_ns_global_same_cid_fails() {
+ init_namespaces
+
+ if namespaces_can_boot_same_cid "global0" "global1"; then
+ return "${KSFT_FAIL}"
+ fi
+
+ return "${KSFT_PASS}"
+}
+
+test_ns_local_global_same_cid_ok() {
+ init_namespaces
+
+ if namespaces_can_boot_same_cid "local0" "global0"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_global_local_same_cid_ok() {
+ init_namespaces
+
+ if namespaces_can_boot_same_cid "global0" "local0"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
+test_ns_local_same_cid_ok() {
+ init_namespaces
+
+ if namespaces_can_boot_same_cid "local0" "local1"; then
+ return "${KSFT_PASS}"
+ fi
+
+ return "${KSFT_FAIL}"
+}
+
test_ns_host_vsock_ns_mode_write_once_ok() {
for mode in "${NS_MODES[@]}"; do
local ns="${mode}0"
--
2.47.3
^ permalink raw reply related
* [PATCH net-next v12 09/12] selftests/vsock: add tests for proc sys vsock ns_mode
From: Bobby Eshleman @ 2025-11-27 7:47 UTC (permalink / raw)
To: Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan
Cc: linux-kernel, virtualization, netdev, kvm, linux-hyperv,
linux-kselftest, berrange, Sargun Dhillon, Bobby Eshleman,
Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-0-257ee21cd5de@meta.com>
From: Bobby Eshleman <bobbyeshleman@meta.com>
Add tests for the /proc/sys/net/vsock/ns_mode interface. Namely,
that it accepts "global" and "local" strings and enforces a write-once
policy.
Start a convention of commenting the test name over the test
description. Add test name comments over test descriptions that existed
before this convention.
Add a check_netns() function that checks if the test requires namespaces
and if the current kernel supports namespaces. Skip tests that require
namespaces if the system does not have namespace support.
Add a test to verify that guest VMs with an active G2H transport
(virtio-vsock) cannot set namespace mode to 'local'. This validates
the mutual exclusion between G2H transports and LOCAL mode.
This patch is the first to add tests that do *not* re-use the same
shared VM. For that reason, it adds a run_tests() function to run these
tests and filter out the shared VM tests.
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Changes in v12:
- remove ns_vm_local_mode_rejected test, due to dropping that constraint
Changes in v11:
- Document ns_ prefix above TEST_NAMES (Stefano)
Changes in v10:
- Remove extraneous add_namespaces/del_namespaces calls.
- Rename run_tests() to run_ns_tests() since it is designed to only
run ns tests.
Changes in v9:
- add test ns_vm_local_mode_rejected to check that guests cannot use
local mode
---
tools/testing/selftests/vsock/vmtest.sh | 118 +++++++++++++++++++++++++++++++-
1 file changed, 116 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
index e32997db322d..28b91b906cdc 100755
--- a/tools/testing/selftests/vsock/vmtest.sh
+++ b/tools/testing/selftests/vsock/vmtest.sh
@@ -41,14 +41,38 @@ readonly KERNEL_CMDLINE="\
virtme.ssh virtme_ssh_channel=tcp virtme_ssh_user=$USER \
"
readonly LOG=$(mktemp /tmp/vsock_vmtest_XXXX.log)
-readonly TEST_NAMES=(vm_server_host_client vm_client_host_server vm_loopback)
+
+# Namespace tests must use the ns_ prefix. This is checked in check_netns() and
+# is used to determine if a test needs namespace setup before test execution.
+readonly TEST_NAMES=(
+ vm_server_host_client
+ vm_client_host_server
+ vm_loopback
+ ns_host_vsock_ns_mode_ok
+ ns_host_vsock_ns_mode_write_once_ok
+)
readonly TEST_DESCS=(
+ # vm_server_host_client
"Run vsock_test in server mode on the VM and in client mode on the host."
+
+ # vm_client_host_server
"Run vsock_test in client mode on the VM and in server mode on the host."
+
+ # vm_loopback
"Run vsock_test using the loopback transport in the VM."
+
+ # ns_host_vsock_ns_mode_ok
+ "Check /proc/sys/net/vsock/ns_mode strings on the host."
+
+ # ns_host_vsock_ns_mode_write_once_ok
+ "Check /proc/sys/net/vsock/ns_mode is write-once on the host."
)
-readonly USE_SHARED_VM=(vm_server_host_client vm_client_host_server vm_loopback)
+readonly USE_SHARED_VM=(
+ vm_server_host_client
+ vm_client_host_server
+ vm_loopback
+)
readonly NS_MODES=("local" "global")
VERBOSE=0
@@ -205,6 +229,20 @@ check_deps() {
fi
}
+check_netns() {
+ local tname=$1
+
+ # If the test requires NS support, check if NS support exists
+ # using /proc/self/ns
+ if [[ "${tname}" =~ ^ns_ ]] &&
+ [[ ! -e /proc/self/ns ]]; then
+ log_host "No NS support detected for test ${tname}"
+ return 1
+ fi
+
+ return 0
+}
+
check_vng() {
local tested_versions
local version
@@ -528,6 +566,32 @@ log_guest() {
LOG_PREFIX=guest log "$@"
}
+test_ns_host_vsock_ns_mode_ok() {
+ for mode in "${NS_MODES[@]}"; do
+ if ! ns_set_mode "${mode}0" "${mode}"; then
+ return "${KSFT_FAIL}"
+ fi
+ done
+
+ return "${KSFT_PASS}"
+}
+
+test_ns_host_vsock_ns_mode_write_once_ok() {
+ for mode in "${NS_MODES[@]}"; do
+ local ns="${mode}0"
+ if ! ns_set_mode "${ns}" "${mode}"; then
+ return "${KSFT_FAIL}"
+ fi
+
+ # try writing again and expect failure
+ if ns_set_mode "${ns}" "${mode}"; then
+ return "${KSFT_FAIL}"
+ fi
+ done
+
+ return "${KSFT_PASS}"
+}
+
test_vm_server_host_client() {
if ! vm_vsock_test "init_ns" "server" 2 "${TEST_GUEST_PORT}"; then
return "${KSFT_FAIL}"
@@ -601,6 +665,11 @@ run_shared_vm_tests() {
continue
fi
+ if ! check_netns "${arg}"; then
+ check_result "${KSFT_SKIP}" "${arg}"
+ continue
+ fi
+
run_shared_vm_test "${arg}"
check_result "$?" "${arg}"
done
@@ -654,6 +723,49 @@ run_shared_vm_test() {
return "${rc}"
}
+run_ns_tests() {
+ for arg in "${ARGS[@]}"; do
+ if shared_vm_test "${arg}"; then
+ continue
+ fi
+
+ if ! check_netns "${arg}"; then
+ check_result "${KSFT_SKIP}" "${arg}"
+ continue
+ fi
+
+ add_namespaces
+
+ name=$(echo "${arg}" | awk '{ print $1 }')
+ log_host "Executing test_${name}"
+
+ host_oops_before=$(dmesg 2>/dev/null | grep -c -i 'Oops')
+ host_warn_before=$(dmesg --level=warn 2>/dev/null | grep -c -i 'vsock')
+ eval test_"${name}"
+ rc=$?
+
+ host_oops_after=$(dmesg 2>/dev/null | grep -c -i 'Oops')
+ if [[ "${host_oops_after}" -gt "${host_oops_before}" ]]; then
+ echo "FAIL: kernel oops detected on host" | log_host
+ check_result "${KSFT_FAIL}" "${name}"
+ del_namespaces
+ continue
+ fi
+
+ host_warn_after=$(dmesg --level=warn 2>/dev/null | grep -c -i 'vsock')
+ if [[ "${host_warn_after}" -gt "${host_warn_before}" ]]; then
+ echo "FAIL: kernel warning detected on host" | log_host
+ check_result "${KSFT_FAIL}" "${name}"
+ del_namespaces
+ continue
+ fi
+
+ check_result "${rc}" "${name}"
+
+ del_namespaces
+ done
+}
+
BUILD=0
QEMU="qemu-system-$(uname -m)"
@@ -699,6 +811,8 @@ if shared_vm_tests_requested "${ARGS[@]}"; then
terminate_pidfiles "${pidfile}"
fi
+run_ns_tests "${ARGS[@]}"
+
echo "SUMMARY: PASS=${cnt_pass} SKIP=${cnt_skip} FAIL=${cnt_fail}"
echo "Log: ${LOG}"
--
2.47.3
^ permalink raw reply related
* [PATCH net-next v12 08/12] selftests/vsock: use ss to wait for listeners instead of /proc/net
From: Bobby Eshleman @ 2025-11-27 7:47 UTC (permalink / raw)
To: Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Michael S. Tsirkin,
Jason Wang, Eugenio Pérez, Xuan Zhuo, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Bryan Tan, Vishnu Dasa,
Broadcom internal kernel review list, Shuah Khan
Cc: linux-kernel, virtualization, netdev, kvm, linux-hyperv,
linux-kselftest, berrange, Sargun Dhillon, Bobby Eshleman,
Bobby Eshleman
In-Reply-To: <20251126-vsock-vmtest-v12-0-257ee21cd5de@meta.com>
From: Bobby Eshleman <bobbyeshleman@meta.com>
Replace /proc/net parsing with ss(8) for detecting listening sockets in
wait_for_listener() functions and add support for TCP, VSOCK, and Unix
socket protocols.
The previous implementation parsed /proc/net/tcp using awk to detect
listening sockets, but this approach could not support vsock because
vsock does not export socket information to /proc/net/.
Instead, use ss so that we can detect listeners on tcp, vsock, and unix.
The protocol parameter is now required for all wait_for_listener family
functions (wait_for_listener, vm_wait_for_listener,
host_wait_for_listener) to explicitly specify which socket type to wait
for.
ss is added to the dependency check in check_deps().
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
tools/testing/selftests/vsock/vmtest.sh | 47 +++++++++++++++++++++------------
1 file changed, 30 insertions(+), 17 deletions(-)
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
index 1623e4da15e2..e32997db322d 100755
--- a/tools/testing/selftests/vsock/vmtest.sh
+++ b/tools/testing/selftests/vsock/vmtest.sh
@@ -191,7 +191,7 @@ check_args() {
}
check_deps() {
- for dep in vng ${QEMU} busybox pkill ssh; do
+ for dep in vng ${QEMU} busybox pkill ssh ss; do
if [[ ! -x $(command -v "${dep}") ]]; then
echo -e "skip: dependency ${dep} not found!\n"
exit "${KSFT_SKIP}"
@@ -346,21 +346,32 @@ wait_for_listener()
local port=$1
local interval=$2
local max_intervals=$3
- local protocol=tcp
- local pattern
+ local protocol=$4
local i
- pattern=":$(printf "%04X" "${port}") "
-
- # for tcp protocol additionally check the socket state
- [ "${protocol}" = "tcp" ] && pattern="${pattern}0A"
-
for i in $(seq "${max_intervals}"); do
- if awk -v pattern="${pattern}" \
- 'BEGIN {rc=1} $2" "$4 ~ pattern {rc=0} END {exit rc}' \
- /proc/net/"${protocol}"*; then
+ case "${protocol}" in
+ tcp)
+ if ss --listening --tcp --numeric | grep -q ":${port} "; then
+ break
+ fi
+ ;;
+ vsock)
+ if ss --listening --vsock --numeric | grep -q ":${port} "; then
+ break
+ fi
+ ;;
+ unix)
+ # For unix sockets, port is actually the socket path
+ if ss --listening --unix | grep -q "${port}"; then
+ break
+ fi
+ ;;
+ *)
+ echo "Unknown protocol: ${protocol}" >&2
break
- fi
+ ;;
+ esac
sleep "${interval}"
done
}
@@ -368,23 +379,25 @@ wait_for_listener()
vm_wait_for_listener() {
local ns=$1
local port=$2
+ local protocol=$3
vm_ssh "${ns}" <<EOF
$(declare -f wait_for_listener)
-wait_for_listener ${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX}
+wait_for_listener ${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX} ${protocol}
EOF
}
host_wait_for_listener() {
local ns=$1
local port=$2
+ local protocol=$3
if [[ "${ns}" == "init_ns" ]]; then
- wait_for_listener "${port}" "${WAIT_PERIOD}" "${WAIT_PERIOD_MAX}"
+ wait_for_listener "${port}" "${WAIT_PERIOD}" "${WAIT_PERIOD_MAX}" "${protocol}"
else
ip netns exec "${ns}" bash <<-EOF
$(declare -f wait_for_listener)
- wait_for_listener ${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX}
+ wait_for_listener ${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX} ${protocol}
EOF
fi
}
@@ -431,7 +444,7 @@ vm_vsock_test() {
return $rc
fi
- vm_wait_for_listener "${ns}" "${port}"
+ vm_wait_for_listener "${ns}" "${port}" "tcp"
rc=$?
fi
set +o pipefail
@@ -472,7 +485,7 @@ host_vsock_test() {
return $rc
fi
- host_wait_for_listener "${ns}" "${port}"
+ host_wait_for_listener "${ns}" "${port}" "tcp"
rc=$?
fi
set +o pipefail
--
2.47.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox