* Re: [PATCH] mshv: Use PMD_ORDER instead of HPAGE_PMD_ORDER when processing regions
From: Anirudh Rayabharam @ 2025-12-17 5:03 UTC (permalink / raw)
To: Stanislav Kinsburskii
Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel
In-Reply-To: <176529822862.17729.14849117117197568731.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net>
On Tue, Dec 09, 2025 at 04:37:20PM +0000, Stanislav Kinsburskii wrote:
> Fix page order determination logic when CONFIG_PGTABLE_HAS_HUGE_LEAVES
> is undefined, as HPAGE_PMD_SHIFT is defined as BUILD_BUG in that case.
>
> Fixes: abceb4297bf8 ("mshv: Fix huge page handling in memory region
> traversal")
> Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> ---
> drivers/hv/mshv_regions.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
> index 202b9d551e39..dc2d7044fb91 100644
> --- a/drivers/hv/mshv_regions.c
> +++ b/drivers/hv/mshv_regions.c
> @@ -58,7 +58,7 @@ static long mshv_region_process_chunk(struct mshv_mem_region *region,
>
> page_order = folio_order(page_folio(page));
> /* The hypervisor only supports 4K and 2M page sizes */
> - if (page_order && page_order != HPAGE_PMD_ORDER)
> + if (page_order && page_order != PMD_ORDER)
> return -EINVAL;
>
> stride = 1 << page_order;
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply
* Re: [PATCH v7 4/7] Drivers: hv: Fix huge page handling in memory region traversal
From: Stanislav Kinsburskii @ 2025-12-17 0:54 UTC (permalink / raw)
To: Michael Kelley
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <SN6PR02MB4157978DFAA6C2584D0678E1D4A1A@SN6PR02MB4157.namprd02.prod.outlook.com>
On Thu, Dec 11, 2025 at 05:37:26PM +0000, Michael Kelley wrote:
> From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Thursday, December 4, 2025 1:09 PM
<snip>
> I've been playing around with mmu notifiers and 2 Meg pages. At least in my
> experiment, there's a case where the .invalidate callback is invoked on a
> range *before* the 2 Meg page is split. The kernel code that does this is
> in zap_page_range_single_batched(). Early on this function calls
> mmu_notifier_invalidate_range_start(), which invokes the .invalidate
> callback on the initial range. Later on, unmap_single_vma() is called, which
> does the split and eventually makes a second .invalidate callback for the
> entire 2 Meg page.
>
> Details: My experiment is a user space program that does the following:
>
> 1. Allocates 16 Megs of memory on a 16 Meg boundary using
> posix_memalign(). So this is private anonymous memory. Transparent
> huge pages are enabled.
>
> 2. Writes to a byte in each 4K page so they are all populated.
> /proc/meminfo shows eight 2 Meg pages have been allocated.
>
> 3. Creates an mmu notifier for the allocated 16 Megs, using an ioctl
> hacked into the kernel for experimentation purposes.
>
> 4. Uses madvise() with the DONTNEED option to free 32 Kbytes on a 4K
> page boundary somewhere in the 16 Meg allocation. This results in an mmu
> notifier invalidate callback for that 32 Kbytes. Then there's a second invalidate
> callback covering the entire 2 Meg page that contains the 32 Kbyte range.
> Kernel stack traces for the two invalidate callbacks show them originating
> in zap_page_range_single_batched().
>
> 5. Sleeps for 60 seconds. During that time, khugepaged wakes up and does
> hpage_collapse_scan_pmd() -> collapse_huge_page(), which generates a third
> .invalidate callback for the 2 Meg page. I'm haven't investigated what this is
> all about.
>
> 6. Interestingly, if Step 4 above does a slightly different operation using
> mprotect() with PROT_READ instead of madvise(), the 2 Meg page is split first.
> The .invalidate callback for the full 2 Meg happens before the .invalidate
> callback for the specified range.
>
> The root partition probably isn't doing madvise() with DONTNEED for memory
> allocated for guests. But regardless of what user space does or doesn't do, MSHV's
> invalidate callback path should be made safe for this case. Maybe that's just
> detecting it and returning an error (and maybe a WARN_ON) if user space
> doesn't need it to work.
>
> Michael
>
The issue is addressed by "mshv: Align huge page stride with guest
mapping" patch.
Thanks a lot once again for your help in identifying it,
Stanislav
^ permalink raw reply
* Re: [PATCH] mshv: hide x86-specific functions on arm64
From: Stanislav Kinsburskii @ 2025-12-17 0:45 UTC (permalink / raw)
To: Wei Liu
Cc: Arnd Bergmann, K. Y. Srinivasan, Haiyang Zhang, Dexuan Cui,
Long Li, Stansialv Kinsburskii, Nuno Das Neves,
Praveen K Paladugu, Easwar Hariharan, Anatol Belski,
Arnd Bergmann, Sean Christopherson, Naman Jain, linux-hyperv,
linux-kernel
In-Reply-To: <20251216222129.GA1300707@liuwe-devbox-debian-v2.local>
On Tue, Dec 16, 2025 at 10:21:29PM +0000, Wei Liu wrote:
> On Tue, Dec 16, 2025 at 10:36:12PM +0100, Arnd Bergmann wrote:
> > From: Arnd Bergmann <arnd@arndb.de>
> >
> > The hv_sleep_notifiers_register() and hv_machine_power_off() functions are
> > only called and declared on x86, but cause a warning on arm64:
> >
> > drivers/hv/mshv_common.c:210:6: error: no previous prototype for 'hv_sleep_notifiers_register' [-Werror=missing-prototypes]
> > 210 | void hv_sleep_notifiers_register(void)
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> > drivers/hv/mshv_common.c:224:6: error: no previous prototype for 'hv_machine_power_off' [-Werror=missing-prototypes]
> > 224 | void hv_machine_power_off(void)
> > | ^~~~~~~~~~~~~~~~~~~~
> >
> > Hide both inside of an #ifdef block.
> >
> > Fixes: f0be2600ac55 ("mshv: Use reboot notifier to configure sleep state")
> > Fixes: 615a6e7d83f9 ("mshv: Cleanly shutdown root partition with MSHV")
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> Thanks Arnd. I have a queued up a patch which make available the
> declarations to arm64. Let me think about whether to use your patch
> instead.
>
> Anyway, this issue will be fixed one way or the other once I send a PR
> to Linus.
>
The whole idea of mshv_common.c is to have common code for all archs.
It would be nice to keep this file as it is.
Thanks,
Stanislav
> Wei
>
> > ---
> > drivers/hv/mshv_common.c | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
> > index 58027b23c206..63f09bb5136e 100644
> > --- a/drivers/hv/mshv_common.c
> > +++ b/drivers/hv/mshv_common.c
> > @@ -142,6 +142,7 @@ int hv_call_get_partition_property(u64 partition_id,
> > }
> > EXPORT_SYMBOL_GPL(hv_call_get_partition_property);
> >
> > +#ifdef CONFIG_X86
> > /*
> > * 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
> > @@ -237,3 +238,4 @@ void hv_machine_power_off(void)
> > BUG();
> >
> > }
> > +#endif
> > --
> > 2.39.5
> >
^ permalink raw reply
* [PATCH] mshv: Align huge page stride with guest mapping
From: Stanislav Kinsburskii @ 2025-12-17 0:41 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli; +Cc: linux-hyperv, linux-kernel
Ensure that a stride larger than 1 (huge page) is only used when both
the guest frame number (gfn) and the operation size (page_count) are
aligned to the huge page size (PTRS_PER_PMD). This matches the
hypervisor requirement that map/unmap operations for huge pages must be
guest-aligned and cover a full huge page.
Add mshv_chunk_stride() to encapsulate this alignment and page-order
validation, and plumb a huge_page flag into the region chunk handlers.
This prevents issuing large-page map/unmap/share operations that the
hypervisor would reject due to misaligned guest mappings.
Fixes: abceb4297bf8 ("mshv: Fix huge page handling in memory region traversal")
Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
---
drivers/hv/mshv_regions.c | 94 ++++++++++++++++++++++++++++++---------------
1 file changed, 63 insertions(+), 31 deletions(-)
diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
index 30bacba6aec3..29776019bcde 100644
--- a/drivers/hv/mshv_regions.c
+++ b/drivers/hv/mshv_regions.c
@@ -19,6 +19,42 @@
#define MSHV_MAP_FAULT_IN_PAGES PTRS_PER_PMD
+/**
+ * mshv_chunk_stride - Compute stride for mapping guest memory
+ * @page : The page to check for huge page backing
+ * @gfn : Guest frame number for the mapping
+ * @page_count: Total number of pages in the mapping
+ *
+ * Determines the appropriate stride (in pages) for mapping guest memory.
+ * Uses huge page stride if the backing page is huge and the guest mapping
+ * is properly aligned; otherwise falls back to single page stride.
+ *
+ * Return: Stride in pages, or -EINVAL if page order is unsupported.
+ */
+static int mshv_chunk_stride(struct page *page,
+ u64 gfn, u64 page_count)
+{
+ unsigned int page_order;
+
+ page_order = folio_order(page_folio(page));
+ /* The hypervisor only supports 4K and 2M page sizes */
+ if (page_order && page_order != PMD_ORDER)
+ return -EINVAL;
+
+ /*
+ * Default to a single page stride. If page_order is set and both
+ * the guest frame number (gfn) and page_count are huge-page
+ * aligned (PTRS_PER_PMD), use a larger stride so the mapping can
+ * be backed by a huge page in both guest and hypervisor.
+ */
+ if (page_order &&
+ IS_ALIGNED(gfn, PTRS_PER_PMD) &&
+ IS_ALIGNED(page_count, PTRS_PER_PMD))
+ return 1 << page_order;
+
+ return 1;
+}
+
/**
* mshv_region_process_chunk - Processes a contiguous chunk of memory pages
* in a region.
@@ -45,25 +81,23 @@ static long mshv_region_process_chunk(struct mshv_mem_region *region,
int (*handler)(struct mshv_mem_region *region,
u32 flags,
u64 page_offset,
- u64 page_count))
+ u64 page_count,
+ bool huge_page))
{
- u64 count, stride;
- unsigned int page_order;
+ u64 gfn = region->start_gfn + page_offset;
+ u64 count;
struct page *page;
- int ret;
+ int stride, ret;
page = region->pages[page_offset];
if (!page)
return -EINVAL;
- page_order = folio_order(page_folio(page));
- /* The hypervisor only supports 4K and 2M page sizes */
- if (page_order && page_order != PMD_ORDER)
- return -EINVAL;
-
- stride = 1 << page_order;
+ stride = mshv_chunk_stride(page, gfn, page_count);
+ if (stride < 0)
+ return stride;
- /* Start at stride since the first page is validated */
+ /* Start at stride since the first stride is validated */
for (count = stride; count < page_count; count += stride) {
page = region->pages[page_offset + count];
@@ -71,12 +105,13 @@ static long mshv_region_process_chunk(struct mshv_mem_region *region,
if (!page)
break;
- /* Break if page size changes */
- if (page_order != folio_order(page_folio(page)))
+ /* Break if stride size changes */
+ if (stride != mshv_chunk_stride(page, gfn + count,
+ page_count - count))
break;
}
- ret = handler(region, flags, page_offset, count);
+ ret = handler(region, flags, page_offset, count, stride > 1);
if (ret)
return ret;
@@ -108,7 +143,8 @@ static int mshv_region_process_range(struct mshv_mem_region *region,
int (*handler)(struct mshv_mem_region *region,
u32 flags,
u64 page_offset,
- u64 page_count))
+ u64 page_count,
+ bool huge_page))
{
long ret;
@@ -162,11 +198,10 @@ struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages,
static int mshv_region_chunk_share(struct mshv_mem_region *region,
u32 flags,
- u64 page_offset, u64 page_count)
+ u64 page_offset, u64 page_count,
+ bool huge_page)
{
- struct page *page = region->pages[page_offset];
-
- if (PageHuge(page) || PageTransCompound(page))
+ if (huge_page)
flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE;
return hv_call_modify_spa_host_access(region->partition->pt_id,
@@ -188,11 +223,10 @@ int mshv_region_share(struct mshv_mem_region *region)
static int mshv_region_chunk_unshare(struct mshv_mem_region *region,
u32 flags,
- u64 page_offset, u64 page_count)
+ u64 page_offset, u64 page_count,
+ bool huge_page)
{
- struct page *page = region->pages[page_offset];
-
- if (PageHuge(page) || PageTransCompound(page))
+ if (huge_page)
flags |= HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE;
return hv_call_modify_spa_host_access(region->partition->pt_id,
@@ -212,11 +246,10 @@ int mshv_region_unshare(struct mshv_mem_region *region)
static int mshv_region_chunk_remap(struct mshv_mem_region *region,
u32 flags,
- u64 page_offset, u64 page_count)
+ u64 page_offset, u64 page_count,
+ bool huge_page)
{
- struct page *page = region->pages[page_offset];
-
- if (PageHuge(page) || PageTransCompound(page))
+ if (huge_page)
flags |= HV_MAP_GPA_LARGE_PAGE;
return hv_call_map_gpa_pages(region->partition->pt_id,
@@ -295,11 +328,10 @@ int mshv_region_pin(struct mshv_mem_region *region)
static int mshv_region_chunk_unmap(struct mshv_mem_region *region,
u32 flags,
- u64 page_offset, u64 page_count)
+ u64 page_offset, u64 page_count,
+ bool huge_page)
{
- struct page *page = region->pages[page_offset];
-
- if (PageHuge(page) || PageTransCompound(page))
+ if (huge_page)
flags |= HV_UNMAP_GPA_LARGE_PAGE;
return hv_call_unmap_gpa_pages(region->partition->pt_id,
^ permalink raw reply related
* Re: [PATCH] mshv: hide x86-specific functions on arm64
From: Wei Liu @ 2025-12-16 22:21 UTC (permalink / raw)
To: Arnd Bergmann
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Stansialv Kinsburskii, Nuno Das Neves, Praveen K Paladugu,
Easwar Hariharan, Anatol Belski, Stanislav Kinsburskii,
Arnd Bergmann, Sean Christopherson, Naman Jain, linux-hyperv,
linux-kernel
In-Reply-To: <20251216213619.115259-1-arnd@kernel.org>
On Tue, Dec 16, 2025 at 10:36:12PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> The hv_sleep_notifiers_register() and hv_machine_power_off() functions are
> only called and declared on x86, but cause a warning on arm64:
>
> drivers/hv/mshv_common.c:210:6: error: no previous prototype for 'hv_sleep_notifiers_register' [-Werror=missing-prototypes]
> 210 | void hv_sleep_notifiers_register(void)
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/hv/mshv_common.c:224:6: error: no previous prototype for 'hv_machine_power_off' [-Werror=missing-prototypes]
> 224 | void hv_machine_power_off(void)
> | ^~~~~~~~~~~~~~~~~~~~
>
> Hide both inside of an #ifdef block.
>
> Fixes: f0be2600ac55 ("mshv: Use reboot notifier to configure sleep state")
> Fixes: 615a6e7d83f9 ("mshv: Cleanly shutdown root partition with MSHV")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Thanks Arnd. I have a queued up a patch which make available the
declarations to arm64. Let me think about whether to use your patch
instead.
Anyway, this issue will be fixed one way or the other once I send a PR
to Linus.
Wei
> ---
> drivers/hv/mshv_common.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
> index 58027b23c206..63f09bb5136e 100644
> --- a/drivers/hv/mshv_common.c
> +++ b/drivers/hv/mshv_common.c
> @@ -142,6 +142,7 @@ int hv_call_get_partition_property(u64 partition_id,
> }
> EXPORT_SYMBOL_GPL(hv_call_get_partition_property);
>
> +#ifdef CONFIG_X86
> /*
> * 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
> @@ -237,3 +238,4 @@ void hv_machine_power_off(void)
> BUG();
>
> }
> +#endif
> --
> 2.39.5
>
^ permalink raw reply
* [PATCH] mshv: hide x86-specific functions on arm64
From: Arnd Bergmann @ 2025-12-16 21:36 UTC (permalink / raw)
To: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Stansialv Kinsburskii, Nuno Das Neves, Praveen K Paladugu,
Easwar Hariharan, Anatol Belski, Stanislav Kinsburskii
Cc: Arnd Bergmann, Sean Christopherson, Naman Jain, linux-hyperv,
linux-kernel
From: Arnd Bergmann <arnd@arndb.de>
The hv_sleep_notifiers_register() and hv_machine_power_off() functions are
only called and declared on x86, but cause a warning on arm64:
drivers/hv/mshv_common.c:210:6: error: no previous prototype for 'hv_sleep_notifiers_register' [-Werror=missing-prototypes]
210 | void hv_sleep_notifiers_register(void)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/hv/mshv_common.c:224:6: error: no previous prototype for 'hv_machine_power_off' [-Werror=missing-prototypes]
224 | void hv_machine_power_off(void)
| ^~~~~~~~~~~~~~~~~~~~
Hide both inside of an #ifdef block.
Fixes: f0be2600ac55 ("mshv: Use reboot notifier to configure sleep state")
Fixes: 615a6e7d83f9 ("mshv: Cleanly shutdown root partition with MSHV")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/hv/mshv_common.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
index 58027b23c206..63f09bb5136e 100644
--- a/drivers/hv/mshv_common.c
+++ b/drivers/hv/mshv_common.c
@@ -142,6 +142,7 @@ int hv_call_get_partition_property(u64 partition_id,
}
EXPORT_SYMBOL_GPL(hv_call_get_partition_property);
+#ifdef CONFIG_X86
/*
* 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
@@ -237,3 +238,4 @@ void hv_machine_power_off(void)
BUG();
}
+#endif
--
2.39.5
^ permalink raw reply related
* RE: [EXTERNAL] Re: [PATCH net-next] net: mana: Fix use-after-free in reset service rescan path
From: Long Li @ 2025-12-16 17:48 UTC (permalink / raw)
To: Simon Horman, Dipayaan Roy
Cc: KY Srinivasan, Haiyang Zhang, wei.liu@kernel.org, Dexuan Cui,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, Konstantin Taranov,
shradhagupta@linux.microsoft.com, ssengar@linux.microsoft.com,
ernis@linux.microsoft.com, Shiraz Saleem,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
Dipayaan Roy
In-Reply-To: <aUFOl4euBSyPtA5F@horms.kernel.org>
> On Tue, Dec 16, 2025 at 02:55:08AM -0800, Dipayaan Roy wrote:
> > When mana_serv_reset() encounters -ETIMEDOUT or -EPROTO from
> > mana_gd_resume(), it performs a PCI rescan via mana_serv_rescan().
> >
> > mana_serv_rescan() calls pci_stop_and_remove_bus_device(), which can
> > invoke the driver's remove path and free the gdma_context associated
> > with the device. After returning, mana_serv_reset() currently jumps to
> > the out label and attempts to clear gc->in_service, dereferencing a
> > freed gdma_context.
> >
> > The issue was observed with the following call logs:
> > [ 698.942636] BUG: unable to handle page fault for address:
> > ff6c2b638088508d [ 698.943121] #PF: supervisor write access in kernel
> > mode [ 698.943423] #PF: error_code(0x0002) - not-present page [S[
> > 698.943793] Pat Dec 6 07:GD5 100000067 P4D 1002f7067 PUD
> 1002f8067
> > PMD 101bef067 PTE 0
> > 0:56 2025] hv_[n e 698.944283] Oops: Oops: 0002 [#1] SMP NOPTI tvsc
> > f8615163-00[ 698.944611] CPU: 28 UID: 0 PID: 249 Comm: kworker/28:1
> > ...
> > [Sat Dec 6 07:50:56 2025] R10: [ 699.121594] mana 7870:00:00.0
> > enP30832s1: Configured vPort 0 PD 18 DB 16 000000000000001b R11:
> > 0000000000000000 R12: ff44cf3f40270000 [Sat Dec 6 07:50:56 2025]
> R13:
> > 0000000000000001 R14: ff44cf3f402700c8 R15: ff44cf3f4021b405 [Sat
> Dec
> > 6 07:50:56 2025] FS: 0000000000000000(0000)
> GS:ff44cf7e9fcf9000(0000)
> > knlGS:0000000000000000 [Sat Dec 6 07:50:56 2025] CS: 0010 DS: 0000
> > ES: 0000 CR0: 0000000080050033 [Sat Dec 6 07:50:56 2025] CR2:
> ff6c2b638088508d CR3: 000000011fe43001 CR4: 0000000000b73ef0 [Sat
> Dec 6 07:50:56 2025] Call Trace:
> > [Sat Dec 6 07:50:56 2025] <TASK>
> > [Sat Dec 6 07:50:56 2025] mana_serv_func+0x24/0x50 [mana] [Sat Dec
> > 6 07:50:56 2025] process_one_work+0x190/0x350 [Sat Dec 6 07:50:56
> > 2025] worker_thread+0x2b7/0x3d0 [Sat Dec 6 07:50:56 2025]
> > kthread+0xf3/0x200 [Sat Dec 6 07:50:56 2025] ?
> > __pfx_worker_thread+0x10/0x10 [Sat Dec 6 07:50:56 2025] ?
> > __pfx_kthread+0x10/0x10 [Sat Dec 6 07:50:56 2025]
> > ret_from_fork+0x21a/0x250 [Sat Dec 6 07:50:56 2025] ?
> > __pfx_kthread+0x10/0x10 [Sat Dec 6 07:50:56 2025]
> > ret_from_fork_asm+0x1a/0x30 [Sat Dec 6 07:50:56 2025] </TASK>
> >
> > Fix this by returning immediately after mana_serv_rescan() to avoid
> > accessing GC state that may no longer be valid.
> >
> > Fixes: 9bf66036d686 ("net: mana: Handle hardware recovery events when
> > probing the device")
> >
>
> nit: no blank line here please - tags should all appear in one block
>
> > Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
>
> I see that this patch is targeted at net-next.
> But this is a fix for a patch present in net.
> So it should be targeted at net instead
>
> Subject: [PATCH net] ...
>
> Probably it is not necessary to repost in order to address the minor feedback
> I've provided above. But if you do, please be sure to observe the 24h rule and
> wait that long between posting revisions of that patch.
>
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs
> .kernel.org%2Fprocess%2Fmaintainer-
> netdev.html&data=05%7C02%7Clongli%40microsoft.com%7C4c2a8e5358f9
> 426996e808de3c9d8a30%7C72f988bf86f141af91ab2d7cd011db47%7C1%
> 7C0%7C639014844545711953%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0
> eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpb
> CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=NboWX%2F1bx47kxnm95
> BiopW87UR8pG%2BuOqatiMYaUCyo%3D&reserved=0
>
> The above not withstanding, this patch looks good to me.
>
> Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Long Li <longli@microsoft.com>
^ permalink raw reply
* Re: [PATCH 3/3] mshv: release mutex on region invalidation failure
From: Stanislav Kinsburskii @ 2025-12-16 16:18 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel
In-Reply-To: <20251216142030.4095527-4-anirudh@anirudhrb.com>
On Tue, Dec 16, 2025 at 02:20:30PM +0000, Anirudh Rayabharam wrote:
> From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
>
> In the region invalidation failure path in
> mshv_region_interval_invalidate(), the region mutex is not released. Fix
> it by releasing the mutex in the failure path.
>
Please, add the corresponding "Fixes" tag.
Acked-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
> ---
> drivers/hv/mshv_regions.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
> index 8abf80129f9b..30bacba6aec3 100644
> --- a/drivers/hv/mshv_regions.c
> +++ b/drivers/hv/mshv_regions.c
> @@ -511,7 +511,7 @@ static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni,
> ret = mshv_region_remap_pages(region, HV_MAP_GPA_NO_ACCESS,
> page_offset, page_count);
> if (ret)
> - goto out_fail;
> + goto out_unlock;
>
> mshv_region_invalidate_pages(region, page_offset, page_count);
>
> @@ -519,6 +519,8 @@ static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni,
>
> return true;
>
> +out_unlock:
> + mutex_unlock(®ion->mutex);
> out_fail:
> WARN_ONCE(ret,
> "Failed to invalidate region %#llx-%#llx (range %#lx-%#lx, event: %u, pages %#llx-%#llx, mm: %#llx): %d\n",
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH 2/3] mshv: handle gpa intercepts for arm64
From: Stanislav Kinsburskii @ 2025-12-16 16:11 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel
In-Reply-To: <20251216142030.4095527-3-anirudh@anirudhrb.com>
On Tue, Dec 16, 2025 at 02:20:29PM +0000, Anirudh Rayabharam wrote:
> From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
>
> The mshv driver now uses movable pages for guests. For arm64 guests
> to be functional, handle gpa intercepts for arm64 too (the current
> code implements handling only for x86). Without this, arm64 guests are
> broken.
>
> Move some arch-agnostic functions out of #ifdefs so that they can be
> re-used.
>
> Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
> ---
> drivers/hv/mshv_root_main.c | 38 ++++++++++++++++++++++++++++---------
> 1 file changed, 29 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index 9cf28a3f12fe..882605349664 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -608,7 +608,6 @@ mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn)
> return NULL;
> }
>
> -#ifdef CONFIG_X86_64
> static struct mshv_mem_region *
> mshv_partition_region_by_gfn_get(struct mshv_partition *p, u64 gfn)
> {
> @@ -625,6 +624,34 @@ mshv_partition_region_by_gfn_get(struct mshv_partition *p, u64 gfn)
> return region;
> }
>
> +#ifdef CONFIG_X86_64
> +static u64 mshv_get_gpa_intercept_gfn(struct mshv_vp *vp)
> +{
> + struct hv_x64_memory_intercept_message *msg;
> + u64 gfn;
> +
> + msg = (struct hv_x64_memory_intercept_message *)
> + vp->vp_intercept_msg_page->u.payload;
> +
> + gfn = HVPFN_DOWN(msg->guest_physical_address);
> +
> + return gfn;
> +}
> +#else /* CONFIG_X86_64 */
It's better to explicitly branch for ARM64 here for clarity as
hv_arm64_memory_intercept_message is defined only for ARM64.
> +static u64 mshv_get_gpa_intercept_gfn(struct mshv_vp *vp)
> +{
> + struct hv_arm64_memory_intercept_message *msg;
> + u64 gfn;
> +
> + msg = (struct hv_arm64_memory_intercept_message *)
> + vp->vp_intercept_msg_page->u.payload;
> +
> + gfn = HVPFN_DOWN(msg->guest_physical_address);
> +
> + return gfn;
> +}
> +#endif /* CONFIG_X86_64 */
> +
Are these functions really needed?
It would be clearer (and shorter) to branch directly in
mshv_handle_gpa_intercept.
Thanks,
Stanislav
> /**
> * mshv_handle_gpa_intercept - Handle GPA (Guest Physical Address) intercepts.
> * @vp: Pointer to the virtual processor structure.
> @@ -640,14 +667,10 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
> {
> struct mshv_partition *p = vp->vp_partition;
> struct mshv_mem_region *region;
> - struct hv_x64_memory_intercept_message *msg;
> bool ret;
> u64 gfn;
>
> - msg = (struct hv_x64_memory_intercept_message *)
> - vp->vp_intercept_msg_page->u.payload;
> -
> - gfn = HVPFN_DOWN(msg->guest_physical_address);
> + gfn = mshv_get_gpa_intercept_gfn(vp);
>
> region = mshv_partition_region_by_gfn_get(p, gfn);
> if (!region)
> @@ -663,9 +686,6 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
>
> return ret;
> }
> -#else /* CONFIG_X86_64 */
> -static bool mshv_handle_gpa_intercept(struct mshv_vp *vp) { return false; }
> -#endif /* CONFIG_X86_64 */
>
> static bool mshv_vp_handle_intercept(struct mshv_vp *vp)
> {
> --
> 2.34.1
>
^ permalink raw reply
* [PATCH RFC 2/2] net: mana: Add ethtool counters for RX CQEs in coalesced type
From: Haiyang Zhang @ 2025-12-16 15:57 UTC (permalink / raw)
To: linux-hyperv, netdev, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Long Li, Konstantin Taranov,
Simon Horman, Erni Sri Satya Vennela, Shradha Gupta,
Saurabh Sengar, Aditya Garg, Dipayaan Roy, Shiraz Saleem,
linux-kernel, linux-rdma
Cc: paulros
In-Reply-To: <1765900682-22114-1-git-send-email-haiyangz@linux.microsoft.com>
From: Haiyang Zhang <haiyangz@microsoft.com>
For RX CQEs with type CQE_RX_COALESCED_4, to measure the coalescing
efficiency, add counters to count how many CQEs contain 2, 3, 4 packets
respectively.
Also, add a counter for the error case of first packet with lenth == 0.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 25 +++++++++++++++++--
.../ethernet/microsoft/mana/mana_ethtool.c | 17 ++++++++++---
include/net/mana/mana.h | 10 +++++---
3 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index a46a1adf83bc..78824567d80b 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2083,8 +2083,22 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
nextpkt:
pktlen = oob->ppi[i].pkt_len;
- if (pktlen == 0)
+ if (pktlen == 0) {
+ /* Collect coalesced CQE count based on packets processed.
+ * Coalesced CQEs have at least 2 packets, so index is i - 2.
+ */
+ if (i > 1) {
+ u64_stats_update_begin(&rxq->stats.syncp);
+ rxq->stats.coalesced_cqe[i - 2]++;
+ u64_stats_update_end(&rxq->stats.syncp);
+ } else if (i == 0) {
+ /* Error case stat */
+ u64_stats_update_begin(&rxq->stats.syncp);
+ rxq->stats.pkt_len0_err++;
+ u64_stats_update_end(&rxq->stats.syncp);
+ }
return;
+ }
curr = rxq->buf_index;
rxbuf_oob = &rxq->rx_oobs[curr];
@@ -2102,8 +2116,15 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
mana_post_pkt_rxq(rxq);
- if (coalesced && (++i < MANA_RXCOMP_OOB_NUM_PPI))
+ if (!coalesced)
+ return;
+
+ if (++i < MANA_RXCOMP_OOB_NUM_PPI)
goto nextpkt;
+
+ u64_stats_update_begin(&rxq->stats.syncp);
+ rxq->stats.coalesced_cqe[MANA_RXCOMP_OOB_NUM_PPI - 2]++;
+ u64_stats_update_end(&rxq->stats.syncp);
}
static void mana_poll_rx_cq(struct mana_cq *cq)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 1b9ed5c9bbff..773f50b1a4f4 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -20,8 +20,6 @@ static const struct mana_stats_desc mana_eth_stats[] = {
tx_cqe_unknown_type)},
{"tx_linear_pkt_cnt", offsetof(struct mana_ethtool_stats,
tx_linear_pkt_cnt)},
- {"rx_coalesced_err", offsetof(struct mana_ethtool_stats,
- rx_coalesced_err)},
{"rx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
rx_cqe_unknown_type)},
};
@@ -151,7 +149,7 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct mana_port_context *apc = netdev_priv(ndev);
unsigned int num_queues = apc->num_queues;
- int i;
+ int i, j;
if (stringset != ETH_SS_STATS)
return;
@@ -170,6 +168,9 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
+ ethtool_sprintf(&data, "rx_%d_pkt_len0_err", i);
+ for (j = 0; j < MANA_RXCOMP_OOB_NUM_PPI - 1; j++)
+ ethtool_sprintf(&data, "rx_%d_coalesced_cqe_%d", i, j + 2);
}
for (i = 0; i < num_queues; i++) {
@@ -203,6 +204,8 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
u64 xdp_xmit;
u64 xdp_drop;
u64 xdp_tx;
+ u64 pkt_len0_err;
+ u64 coalesced_cqe[MANA_RXCOMP_OOB_NUM_PPI - 1];
u64 tso_packets;
u64 tso_bytes;
u64 tso_inner_packets;
@@ -211,7 +214,7 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
u64 short_pkt_fmt;
u64 csum_partial;
u64 mana_map_err;
- int q, i = 0;
+ int q, i = 0, j;
if (!apc->port_is_up)
return;
@@ -241,6 +244,9 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
xdp_drop = rx_stats->xdp_drop;
xdp_tx = rx_stats->xdp_tx;
xdp_redirect = rx_stats->xdp_redirect;
+ pkt_len0_err = rx_stats->pkt_len0_err;
+ for (j = 0; j < MANA_RXCOMP_OOB_NUM_PPI - 1; j++)
+ coalesced_cqe[j] = rx_stats->coalesced_cqe[j];
} while (u64_stats_fetch_retry(&rx_stats->syncp, start));
data[i++] = packets;
@@ -248,6 +254,9 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
data[i++] = xdp_drop;
data[i++] = xdp_tx;
data[i++] = xdp_redirect;
+ data[i++] = pkt_len0_err;
+ for (j = 0; j < MANA_RXCOMP_OOB_NUM_PPI - 1; j++)
+ data[i++] = coalesced_cqe[j];
}
for (q = 0; q < num_queues; q++) {
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 51d26ebeff6c..f8dd19860103 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -61,8 +61,11 @@ enum TRI_STATE {
#define MAX_PORTS_IN_MANA_DEV 256
+/* Maximum number of packets per coalesced CQE */
+#define MANA_RXCOMP_OOB_NUM_PPI 4
+
/* Update this count whenever the respective structures are changed */
-#define MANA_STATS_RX_COUNT 5
+#define MANA_STATS_RX_COUNT (6 + MANA_RXCOMP_OOB_NUM_PPI - 1)
#define MANA_STATS_TX_COUNT 11
#define MANA_RX_FRAG_ALIGNMENT 64
@@ -73,6 +76,8 @@ struct mana_stats_rx {
u64 xdp_drop;
u64 xdp_tx;
u64 xdp_redirect;
+ u64 pkt_len0_err;
+ u64 coalesced_cqe[MANA_RXCOMP_OOB_NUM_PPI - 1];
struct u64_stats_sync syncp;
};
@@ -227,8 +232,6 @@ struct mana_rxcomp_perpkt_info {
u32 pkt_hash;
}; /* HW DATA */
-#define MANA_RXCOMP_OOB_NUM_PPI 4
-
/* Receive completion OOB */
struct mana_rxcomp_oob {
struct mana_cqe_header cqe_hdr;
@@ -378,7 +381,6 @@ struct mana_ethtool_stats {
u64 tx_cqe_err;
u64 tx_cqe_unknown_type;
u64 tx_linear_pkt_cnt;
- u64 rx_coalesced_err;
u64 rx_cqe_unknown_type;
};
--
2.34.1
^ permalink raw reply related
* [PATCH RFC 1/2] net: mana: Add support for coalesced RX packets on CQE
From: Haiyang Zhang @ 2025-12-16 15:57 UTC (permalink / raw)
To: linux-hyperv, netdev, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Long Li, Konstantin Taranov,
Simon Horman, Erni Sri Satya Vennela, Shradha Gupta,
Saurabh Sengar, Aditya Garg, Dipayaan Roy, Shiraz Saleem,
linux-kernel, linux-rdma
Cc: paulros
From: Haiyang Zhang <haiyangz@microsoft.com>
Our NIC can have up to 4 RX packets on 1 CQE. To support this feature,
check and process the type CQE_RX_COALESCED_4. The default setting is
disabled, to avoid possible regression on latency.
And add ethtool handler to switch this feature. To turn it on, run:
ethtool -C <nic> rx-frames 4
To turn it off:
ethtool -C <nic> rx-frames 1
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 32 ++++++-----
.../ethernet/microsoft/mana/mana_ethtool.c | 55 +++++++++++++++++++
include/net/mana/mana.h | 2 +
3 files changed, 74 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 1ad154f9db1a..a46a1adf83bc 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1330,7 +1330,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
req->update_hashkey = update_key;
req->update_indir_tab = update_tab;
req->default_rxobj = apc->default_rxobj;
- req->cqe_coalescing_enable = 0;
+ req->cqe_coalescing_enable = apc->cqe_coalescing_enable;
if (update_key)
memcpy(&req->hashkey, apc->hashkey, MANA_HASH_KEY_SIZE);
@@ -1864,11 +1864,12 @@ static struct sk_buff *mana_build_skb(struct mana_rxq *rxq, void *buf_va,
}
static void mana_rx_skb(void *buf_va, bool from_pool,
- struct mana_rxcomp_oob *cqe, struct mana_rxq *rxq)
+ struct mana_rxcomp_oob *cqe, struct mana_rxq *rxq,
+ int i)
{
struct mana_stats_rx *rx_stats = &rxq->stats;
struct net_device *ndev = rxq->ndev;
- uint pkt_len = cqe->ppi[0].pkt_len;
+ uint pkt_len = cqe->ppi[i].pkt_len;
u16 rxq_idx = rxq->rxq_idx;
struct napi_struct *napi;
struct xdp_buff xdp = {};
@@ -1912,7 +1913,7 @@ static void mana_rx_skb(void *buf_va, bool from_pool,
}
if (cqe->rx_hashtype != 0 && (ndev->features & NETIF_F_RXHASH)) {
- hash_value = cqe->ppi[0].pkt_hash;
+ hash_value = cqe->ppi[i].pkt_hash;
if (cqe->rx_hashtype & MANA_HASH_L4)
skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L4);
@@ -2047,9 +2048,11 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
struct mana_recv_buf_oob *rxbuf_oob;
struct mana_port_context *apc;
struct device *dev = gc->dev;
+ bool coalesced = false;
void *old_buf = NULL;
u32 curr, pktlen;
bool old_fp;
+ int i = 0;
apc = netdev_priv(ndev);
@@ -2064,9 +2067,8 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
goto drop;
case CQE_RX_COALESCED_4:
- netdev_err(ndev, "RX coalescing is unsupported\n");
- apc->eth_stats.rx_coalesced_err++;
- return;
+ coalesced = true;
+ break;
case CQE_RX_OBJECT_FENCE:
complete(&rxq->fence_event);
@@ -2079,14 +2081,10 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
return;
}
- pktlen = oob->ppi[0].pkt_len;
-
- if (pktlen == 0) {
- /* data packets should never have packetlength of zero */
- netdev_err(ndev, "RX pkt len=0, rq=%u, cq=%u, rxobj=0x%llx\n",
- rxq->gdma_id, cq->gdma_id, rxq->rxobj);
+nextpkt:
+ pktlen = oob->ppi[i].pkt_len;
+ if (pktlen == 0)
return;
- }
curr = rxq->buf_index;
rxbuf_oob = &rxq->rx_oobs[curr];
@@ -2097,12 +2095,15 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
/* Unsuccessful refill will have old_buf == NULL.
* In this case, mana_rx_skb() will drop the packet.
*/
- mana_rx_skb(old_buf, old_fp, oob, rxq);
+ mana_rx_skb(old_buf, old_fp, oob, rxq, i);
drop:
mana_move_wq_tail(rxq->gdma_rq, rxbuf_oob->wqe_inf.wqe_size_in_bu);
mana_post_pkt_rxq(rxq);
+
+ if (coalesced && (++i < MANA_RXCOMP_OOB_NUM_PPI))
+ goto nextpkt;
}
static void mana_poll_rx_cq(struct mana_cq *cq)
@@ -3276,6 +3277,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
apc->port_handle = INVALID_MANA_HANDLE;
apc->pf_filter_handle = INVALID_MANA_HANDLE;
apc->port_idx = port_idx;
+ apc->cqe_coalescing_enable = 0;
mutex_init(&apc->vport_mutex);
apc->vport_use_count = 0;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 0e2f4343ac67..1b9ed5c9bbff 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -397,6 +397,58 @@ static void mana_get_channels(struct net_device *ndev,
channel->combined_count = apc->num_queues;
}
+static int mana_get_coalesce(struct net_device *ndev,
+ struct ethtool_coalesce *ec,
+ struct kernel_ethtool_coalesce *kernel_coal,
+ struct netlink_ext_ack *extack)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+
+ ec->rx_max_coalesced_frames =
+ apc->cqe_coalescing_enable ? MANA_RXCOMP_OOB_NUM_PPI : 1;
+
+ return 0;
+}
+
+static int mana_set_coalesce(struct net_device *ndev,
+ struct ethtool_coalesce *ec,
+ struct kernel_ethtool_coalesce *kernel_coal,
+ struct netlink_ext_ack *extack)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+ u8 saved_cqe_coalescing_enable;
+ int err;
+
+ if (ec->rx_max_coalesced_frames != 1 &&
+ ec->rx_max_coalesced_frames != MANA_RXCOMP_OOB_NUM_PPI) {
+ NL_SET_ERR_MSG_FMT(extack,
+ "rx-frames must be 1 or %u, got %u",
+ MANA_RXCOMP_OOB_NUM_PPI,
+ ec->rx_max_coalesced_frames);
+ return -EINVAL;
+ }
+
+ saved_cqe_coalescing_enable = apc->cqe_coalescing_enable;
+ apc->cqe_coalescing_enable =
+ ec->rx_max_coalesced_frames == MANA_RXCOMP_OOB_NUM_PPI;
+
+ if (!apc->port_is_up)
+ return 0;
+
+ err = mana_config_rss(apc, TRI_STATE_TRUE, false, false);
+
+ if (err) {
+ netdev_err(ndev, "Set rx-frames to %u failed:%d\n",
+ ec->rx_max_coalesced_frames, err);
+ NL_SET_ERR_MSG_FMT(extack, "Set rx-frames to %u failed:%d\n",
+ ec->rx_max_coalesced_frames, err);
+
+ apc->cqe_coalescing_enable = saved_cqe_coalescing_enable;
+ }
+
+ return err;
+}
+
static int mana_set_channels(struct net_device *ndev,
struct ethtool_channels *channels)
{
@@ -517,6 +569,7 @@ static int mana_get_link_ksettings(struct net_device *ndev,
}
const struct ethtool_ops mana_ethtool_ops = {
+ .supported_coalesce_params = ETHTOOL_COALESCE_RX_MAX_FRAMES,
.get_ethtool_stats = mana_get_ethtool_stats,
.get_sset_count = mana_get_sset_count,
.get_strings = mana_get_strings,
@@ -527,6 +580,8 @@ const struct ethtool_ops mana_ethtool_ops = {
.set_rxfh = mana_set_rxfh,
.get_channels = mana_get_channels,
.set_channels = mana_set_channels,
+ .get_coalesce = mana_get_coalesce,
+ .set_coalesce = mana_set_coalesce,
.get_ringparam = mana_get_ringparam,
.set_ringparam = mana_set_ringparam,
.get_link_ksettings = mana_get_link_ksettings,
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index d7e089c6b694..51d26ebeff6c 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -556,6 +556,8 @@ struct mana_port_context {
bool port_is_up;
bool port_st_save; /* Saved port state */
+ u8 cqe_coalescing_enable;
+
struct mana_ethtool_stats eth_stats;
struct mana_ethtool_phy_stats phy_stats;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 3/3] mshv: release mutex on region invalidation failure
From: vdso @ 2025-12-16 15:14 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: kys, haiyangz, longli, decui, wei.liu, linux-hyperv, linux-kernel
In-Reply-To: <20251216142030.4095527-4-anirudh@anirudhrb.com>
> On 12/16/2025 6:20 AM Anirudh Rayabharam <anirudh@anirudhrb.com> wrote:
>
>
> From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
>
> In the region invalidation failure path in
> mshv_region_interval_invalidate(), the region mutex is not released. Fix
> it by releasing the mutex in the failure path.
>
> Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
Reviewed-by: Roman Kisel <vdso@mailbox.org>
> ---
> drivers/hv/mshv_regions.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
> index 8abf80129f9b..30bacba6aec3 100644
> --- a/drivers/hv/mshv_regions.c
> +++ b/drivers/hv/mshv_regions.c
> @@ -511,7 +511,7 @@ static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni,
> ret = mshv_region_remap_pages(region, HV_MAP_GPA_NO_ACCESS,
> page_offset, page_count);
> if (ret)
> - goto out_fail;
> + goto out_unlock;
>
> mshv_region_invalidate_pages(region, page_offset, page_count);
>
> @@ -519,6 +519,8 @@ static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni,
>
> return true;
>
> +out_unlock:
> + mutex_unlock(®ion->mutex);
> out_fail:
> WARN_ONCE(ret,
> "Failed to invalidate region %#llx-%#llx (range %#lx-%#lx, event: %u, pages %#llx-%#llx, mm: %#llx): %d\n",
> --
> 2.34.1
^ permalink raw reply
* Re: [PATCH 1/3] hyperv: add definitions for arm64 gpa intercepts
From: vdso @ 2025-12-16 15:07 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: kys, decui, haiyangz, linux-kernel, longli, wei.liu, linux-hyperv
In-Reply-To: <20251216142030.4095527-2-anirudh@anirudhrb.com>
> On 12/16/2025 6:20 AM Anirudh Rayabharam <anirudh@anirudhrb.com> wrote:
[...]
> +#if IS_ENABLED(CONFIG_ARM64)
> +union hv_arm64_vp_execution_state {
> + u16 as_uint16;
> + struct {
> + u16 cpl:2;
That looks oddly x86(-64)-specific (Current Priviledge Level).
Unless I'm mistaken, CPL doesn't belong here, and the bitfield isn't
used on ARM64. Provided the layout of the struct is correct, the
bitfield can have a better name of `reserved0` or something like that.
> + u16 debug_active:1;
> + u16 interruption_pending:1;
> + u16 vtl:4;
> + u16 virtualization_fault_active:1;
> + u16 reserved:7;
> + } __packed;
^ permalink raw reply
* [PATCH 3/3] mshv: release mutex on region invalidation failure
From: Anirudh Rayabharam @ 2025-12-16 14:20 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh
In-Reply-To: <20251216142030.4095527-1-anirudh@anirudhrb.com>
From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
In the region invalidation failure path in
mshv_region_interval_invalidate(), the region mutex is not released. Fix
it by releasing the mutex in the failure path.
Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
---
drivers/hv/mshv_regions.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
index 8abf80129f9b..30bacba6aec3 100644
--- a/drivers/hv/mshv_regions.c
+++ b/drivers/hv/mshv_regions.c
@@ -511,7 +511,7 @@ static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni,
ret = mshv_region_remap_pages(region, HV_MAP_GPA_NO_ACCESS,
page_offset, page_count);
if (ret)
- goto out_fail;
+ goto out_unlock;
mshv_region_invalidate_pages(region, page_offset, page_count);
@@ -519,6 +519,8 @@ static bool mshv_region_interval_invalidate(struct mmu_interval_notifier *mni,
return true;
+out_unlock:
+ mutex_unlock(®ion->mutex);
out_fail:
WARN_ONCE(ret,
"Failed to invalidate region %#llx-%#llx (range %#lx-%#lx, event: %u, pages %#llx-%#llx, mm: %#llx): %d\n",
--
2.34.1
^ permalink raw reply related
* [PATCH 2/3] mshv: handle gpa intercepts for arm64
From: Anirudh Rayabharam @ 2025-12-16 14:20 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh
In-Reply-To: <20251216142030.4095527-1-anirudh@anirudhrb.com>
From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
The mshv driver now uses movable pages for guests. For arm64 guests
to be functional, handle gpa intercepts for arm64 too (the current
code implements handling only for x86). Without this, arm64 guests are
broken.
Move some arch-agnostic functions out of #ifdefs so that they can be
re-used.
Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
---
drivers/hv/mshv_root_main.c | 38 ++++++++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 9cf28a3f12fe..882605349664 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -608,7 +608,6 @@ mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn)
return NULL;
}
-#ifdef CONFIG_X86_64
static struct mshv_mem_region *
mshv_partition_region_by_gfn_get(struct mshv_partition *p, u64 gfn)
{
@@ -625,6 +624,34 @@ mshv_partition_region_by_gfn_get(struct mshv_partition *p, u64 gfn)
return region;
}
+#ifdef CONFIG_X86_64
+static u64 mshv_get_gpa_intercept_gfn(struct mshv_vp *vp)
+{
+ struct hv_x64_memory_intercept_message *msg;
+ u64 gfn;
+
+ msg = (struct hv_x64_memory_intercept_message *)
+ vp->vp_intercept_msg_page->u.payload;
+
+ gfn = HVPFN_DOWN(msg->guest_physical_address);
+
+ return gfn;
+}
+#else /* CONFIG_X86_64 */
+static u64 mshv_get_gpa_intercept_gfn(struct mshv_vp *vp)
+{
+ struct hv_arm64_memory_intercept_message *msg;
+ u64 gfn;
+
+ msg = (struct hv_arm64_memory_intercept_message *)
+ vp->vp_intercept_msg_page->u.payload;
+
+ gfn = HVPFN_DOWN(msg->guest_physical_address);
+
+ return gfn;
+}
+#endif /* CONFIG_X86_64 */
+
/**
* mshv_handle_gpa_intercept - Handle GPA (Guest Physical Address) intercepts.
* @vp: Pointer to the virtual processor structure.
@@ -640,14 +667,10 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
{
struct mshv_partition *p = vp->vp_partition;
struct mshv_mem_region *region;
- struct hv_x64_memory_intercept_message *msg;
bool ret;
u64 gfn;
- msg = (struct hv_x64_memory_intercept_message *)
- vp->vp_intercept_msg_page->u.payload;
-
- gfn = HVPFN_DOWN(msg->guest_physical_address);
+ gfn = mshv_get_gpa_intercept_gfn(vp);
region = mshv_partition_region_by_gfn_get(p, gfn);
if (!region)
@@ -663,9 +686,6 @@ static bool mshv_handle_gpa_intercept(struct mshv_vp *vp)
return ret;
}
-#else /* CONFIG_X86_64 */
-static bool mshv_handle_gpa_intercept(struct mshv_vp *vp) { return false; }
-#endif /* CONFIG_X86_64 */
static bool mshv_vp_handle_intercept(struct mshv_vp *vp)
{
--
2.34.1
^ permalink raw reply related
* [PATCH 1/3] hyperv: add definitions for arm64 gpa intercepts
From: Anirudh Rayabharam @ 2025-12-16 14:20 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh
In-Reply-To: <20251216142030.4095527-1-anirudh@anirudhrb.com>
From: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
Add definitions required for handling GPA intercepts on arm64.
Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
---
include/hyperv/hvhdk.h | 47 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
index 469186df7826..a286f75f0afa 100644
--- a/include/hyperv/hvhdk.h
+++ b/include/hyperv/hvhdk.h
@@ -800,6 +800,53 @@ struct hv_x64_memory_intercept_message {
u8 instruction_bytes[16];
} __packed;
+#if IS_ENABLED(CONFIG_ARM64)
+union hv_arm64_vp_execution_state {
+ u16 as_uint16;
+ struct {
+ u16 cpl:2;
+ u16 debug_active:1;
+ u16 interruption_pending:1;
+ u16 vtl:4;
+ u16 virtualization_fault_active:1;
+ u16 reserved:7;
+ } __packed;
+};
+
+struct hv_arm64_intercept_message_header {
+ u32 vp_index;
+ u8 instruction_length;
+ u8 intercept_access_type;
+ union hv_arm64_vp_execution_state execution_state;
+ u64 pc;
+ u64 cpsr;
+} __packed;
+
+union hv_arm64_memory_access_info {
+ u8 as_uint8;
+ struct {
+ u8 gva_valid:1;
+ u8 gva_gpa_valid:1;
+ u8 hypercall_output_pending:1;
+ u8 reserved:5;
+ } __packed;
+};
+
+struct hv_arm64_memory_intercept_message {
+ struct hv_arm64_intercept_message_header header;
+ u32 cache_type; /* enum hv_cache_type */
+ u8 instruction_byte_count;
+ union hv_arm64_memory_access_info memory_access_info;
+ u16 reserved1;
+ u8 instruction_bytes[4];
+ u32 reserved2;
+ u64 guest_virtual_address;
+ u64 guest_physical_address;
+ u64 syndrome;
+} __packed;
+
+#endif /* CONFIG_ARM64 */
+
/*
* Dispatch state for the VP communicated by the hypervisor to the
* VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP.
--
2.34.1
^ permalink raw reply related
* [PATCH 0/3] Fixes for movable pages
From: Anirudh Rayabharam @ 2025-12-16 14:20 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel; +Cc: anirudh
From: "Anirudh Rayabharam (Microsoft)" <anirudh@anirudhrb.com>
Fix movable pages for arm64 guests by implementing a GPA intercept
handler.
Fix an improper cleanup issue in the region invalidation failure path.
Anirudh Rayabharam (Microsoft) (3):
hyperv: add definitions for arm64 gpa intercepts
mshv: handle gpa intercepts for arm64
mshv: release mutex on region invalidation failure
drivers/hv/mshv_regions.c | 4 +++-
drivers/hv/mshv_root_main.c | 38 +++++++++++++++++++++++-------
include/hyperv/hvhdk.h | 47 +++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 10 deletions(-)
--
2.34.1
^ permalink raw reply
* Re: [PATCH v3 7/9] efi: Refactor init_primary_display() helpers
From: Ard Biesheuvel @ 2025-12-16 13:40 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: javierm, arnd, richard.lyu, helgaas, x86, linux-arm-kernel,
linux-kernel, linux-efi, loongarch, linux-riscv, dri-devel,
linux-hyperv, linux-pci, linux-fbdev
In-Reply-To: <20251126160854.553077-8-tzimmermann@suse.de>
On Wed, 26 Nov 2025 at 17:09, Thomas Zimmermann <tzimmermann@suse.de> wrote:
>
> Rework the kernel's init_primary_display() helpers to allow for later
> support of additional config-table entries and EDID information. No
> functional changes.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
> arch/loongarch/kernel/efi.c | 22 +++++++++++-----------
> drivers/firmware/efi/efi-init.c | 19 ++++++++++---------
> 2 files changed, 21 insertions(+), 20 deletions(-)
>
This patch seems unnecessary now that we've replace one table with another.
I've dropped it for now - let me know if you really want to keep it.
> diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c
> index 638a392d2cd2..1ef38036e8ae 100644
> --- a/arch/loongarch/kernel/efi.c
> +++ b/arch/loongarch/kernel/efi.c
> @@ -81,19 +81,19 @@ EXPORT_SYMBOL_GPL(sysfb_primary_display);
>
> static void __init init_primary_display(void)
> {
> - struct screen_info *si;
> -
> - if (screen_info_table == EFI_INVALID_TABLE_ADDR)
> - return;
> -
> - si = early_memremap(screen_info_table, sizeof(*si));
> - if (!si) {
> - pr_err("Could not map screen_info config table\n");
> + if (screen_info_table == EFI_INVALID_TABLE_ADDR) {
> + struct screen_info *si = early_memremap(screen_info_table, sizeof(*si));
> +
> + if (!si) {
> + pr_err("Could not map screen_info config table\n");
> + return;
> + }
> + sysfb_primary_display.screen = *si;
> + memset(si, 0, sizeof(*si));
> + early_memunmap(si, sizeof(*si));
> + } else {
> return;
> }
> - sysfb_primary_display.screen = *si;
> - memset(si, 0, sizeof(*si));
> - early_memunmap(si, sizeof(*si));
>
> memblock_reserve(__screen_info_lfb_base(&sysfb_primary_display.screen),
> sysfb_primary_display.screen.lfb_size);
> diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
> index d1d418a34407..ca697d485116 100644
> --- a/drivers/firmware/efi/efi-init.c
> +++ b/drivers/firmware/efi/efi-init.c
> @@ -67,10 +67,9 @@ EXPORT_SYMBOL_GPL(sysfb_primary_display);
>
> static void __init init_primary_display(void)
> {
> - struct screen_info *si;
> -
> if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
> - si = early_memremap(screen_info_table, sizeof(*si));
> + struct screen_info *si = early_memremap(screen_info_table, sizeof(*si));
> +
> if (!si) {
> pr_err("Could not map screen_info config table\n");
> return;
> @@ -78,14 +77,16 @@ static void __init init_primary_display(void)
> sysfb_primary_display.screen = *si;
> memset(si, 0, sizeof(*si));
> early_memunmap(si, sizeof(*si));
> + } else {
> + return;
> + }
>
> - if (memblock_is_map_memory(sysfb_primary_display.screen.lfb_base))
> - memblock_mark_nomap(sysfb_primary_display.screen.lfb_base,
> - sysfb_primary_display.screen.lfb_size);
> + if (memblock_is_map_memory(sysfb_primary_display.screen.lfb_base))
> + memblock_mark_nomap(sysfb_primary_display.screen.lfb_base,
> + sysfb_primary_display.screen.lfb_size);
>
> - if (IS_ENABLED(CONFIG_EFI_EARLYCON))
> - efi_earlycon_reprobe();
> - }
> + if (IS_ENABLED(CONFIG_EFI_EARLYCON))
> + efi_earlycon_reprobe();
> }
>
> static int __init uefi_init(u64 efi_system_table)
> --
> 2.51.1
>
^ permalink raw reply
* Re: [PATCH v3 9/9] efi: libstub: Simplify interfaces for primary_display
From: Ard Biesheuvel @ 2025-12-16 13:23 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: javierm, arnd, richard.lyu, helgaas, x86, linux-arm-kernel,
linux-kernel, linux-efi, loongarch, linux-riscv, dri-devel,
linux-hyperv, linux-pci, linux-fbdev
In-Reply-To: <20251126160854.553077-10-tzimmermann@suse.de>
Hi Thomas
On Wed, 26 Nov 2025 at 17:09, Thomas Zimmermann <tzimmermann@suse.de> wrote:
>
> Rename alloc_primary_display() and __alloc_primary_display(), clarify
> free semantics to make interfaces easier to understand.
>
> Rename alloc_primary_display() to lookup_primary_display() as it
> does not necessarily allocate. Then rename __alloc_primary_display()
> to the new alloc_primary_display(). The helper belongs to
> free_primary_display), so it should be named without underscores.
>
> The lookup helper does not necessarily allocate, so the output
> parameter needs_free to indicate when free should be called.
I don't understand why we need this. Whether or not the helper
allocates is a compile time decision, and in builds where it doesn't,
the free helper doesn't do anything.
I'm all for making things simpler, but I don't think this patch
achieves that tbh.
I've queued up this series now up until this patch - once we converge
on the simplification, I'm happy to apply it on top.
Thanks,
> Pass
> an argument through the calls to track this state. Put the free
> handling into release_primary_display() for simplificy.
>
> Also move the comment fro primary_display.c to efi-stub-entry.c,
> where it now describes lookup_primary_display().
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
> drivers/firmware/efi/libstub/efi-stub-entry.c | 23 +++++++++++++++++--
> drivers/firmware/efi/libstub/efi-stub.c | 22 ++++++++++++------
> drivers/firmware/efi/libstub/efistub.h | 2 +-
> .../firmware/efi/libstub/primary_display.c | 17 +-------------
> drivers/firmware/efi/libstub/zboot.c | 6 +++--
> 5 files changed, 42 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
> index aa85e910fe59..3077b51fe0b2 100644
> --- a/drivers/firmware/efi/libstub/efi-stub-entry.c
> +++ b/drivers/firmware/efi/libstub/efi-stub-entry.c
> @@ -14,10 +14,29 @@ static void *kernel_image_addr(void *addr)
> return addr + kernel_image_offset;
> }
>
> -struct sysfb_display_info *alloc_primary_display(void)
> +/*
> + * There are two ways of populating the core kernel's sysfb_primary_display
> + * via the stub:
> + *
> + * - using a configuration table, which relies on the EFI init code to
> + * locate the table and copy the contents; or
> + *
> + * - by linking directly to the core kernel's copy of the global symbol.
> + *
> + * The latter is preferred because it makes the EFIFB earlycon available very
> + * early, but it only works if the EFI stub is part of the core kernel image
> + * itself. The zboot decompressor can only use the configuration table
> + * approach.
> + */
> +
> +struct sysfb_display_info *lookup_primary_display(bool *needs_free)
> {
> + *needs_free = true;
> +
> if (IS_ENABLED(CONFIG_ARM))
> - return __alloc_primary_display();
> + return alloc_primary_display();
> +
> + *needs_free = false;
>
> if (IS_ENABLED(CONFIG_X86) ||
> IS_ENABLED(CONFIG_EFI_EARLYCON) ||
> diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
> index 42d6073bcd06..dc545f62c62b 100644
> --- a/drivers/firmware/efi/libstub/efi-stub.c
> +++ b/drivers/firmware/efi/libstub/efi-stub.c
> @@ -51,14 +51,14 @@ static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
> void __weak free_primary_display(struct sysfb_display_info *dpy)
> { }
>
> -static struct sysfb_display_info *setup_primary_display(void)
> +static struct sysfb_display_info *setup_primary_display(bool *dpy_needs_free)
> {
> struct sysfb_display_info *dpy;
> struct screen_info *screen = NULL;
> struct edid_info *edid = NULL;
> efi_status_t status;
>
> - dpy = alloc_primary_display();
> + dpy = lookup_primary_display(dpy_needs_free);
> if (!dpy)
> return NULL;
> screen = &dpy->screen;
> @@ -68,15 +68,22 @@ static struct sysfb_display_info *setup_primary_display(void)
>
> status = efi_setup_graphics(screen, edid);
> if (status != EFI_SUCCESS)
> - goto err_free_primary_display;
> + goto err___free_primary_display;
>
> return dpy;
>
> -err_free_primary_display:
> - free_primary_display(dpy);
> +err___free_primary_display:
> + if (*dpy_needs_free)
> + free_primary_display(dpy);
> return NULL;
> }
>
> +static void release_primary_display(struct sysfb_display_info *dpy, bool dpy_needs_free)
> +{
> + if (dpy && dpy_needs_free)
> + free_primary_display(dpy);
> +}
> +
> static void install_memreserve_table(void)
> {
> struct linux_efi_memreserve *rsv;
> @@ -156,13 +163,14 @@ efi_status_t efi_stub_common(efi_handle_t handle,
> char *cmdline_ptr)
> {
> struct sysfb_display_info *dpy;
> + bool dpy_needs_free;
> efi_status_t status;
>
> status = check_platform_features();
> if (status != EFI_SUCCESS)
> return status;
>
> - dpy = setup_primary_display();
> + dpy = setup_primary_display(&dpy_needs_free);
>
> efi_retrieve_eventlog();
>
> @@ -182,7 +190,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,
>
> status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
>
> - free_primary_display(dpy);
> + release_primary_display(dpy, dpy_needs_free);
>
> return status;
> }
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index 979a21818cc1..1503ffb82903 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -1176,8 +1176,8 @@ efi_enable_reset_attack_mitigation(void) { }
>
> void efi_retrieve_eventlog(void);
>
> +struct sysfb_display_info *lookup_primary_display(bool *needs_free);
> struct sysfb_display_info *alloc_primary_display(void);
> -struct sysfb_display_info *__alloc_primary_display(void);
> void free_primary_display(struct sysfb_display_info *dpy);
>
> void efi_cache_sync_image(unsigned long image_base,
> diff --git a/drivers/firmware/efi/libstub/primary_display.c b/drivers/firmware/efi/libstub/primary_display.c
> index cdaebab26514..34c54ac1e02a 100644
> --- a/drivers/firmware/efi/libstub/primary_display.c
> +++ b/drivers/firmware/efi/libstub/primary_display.c
> @@ -7,24 +7,9 @@
>
> #include "efistub.h"
>
> -/*
> - * There are two ways of populating the core kernel's sysfb_primary_display
> - * via the stub:
> - *
> - * - using a configuration table, which relies on the EFI init code to
> - * locate the table and copy the contents; or
> - *
> - * - by linking directly to the core kernel's copy of the global symbol.
> - *
> - * The latter is preferred because it makes the EFIFB earlycon available very
> - * early, but it only works if the EFI stub is part of the core kernel image
> - * itself. The zboot decompressor can only use the configuration table
> - * approach.
> - */
> -
> static efi_guid_t primary_display_guid = LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID;
>
> -struct sysfb_display_info *__alloc_primary_display(void)
> +struct sysfb_display_info *alloc_primary_display(void)
> {
> struct sysfb_display_info *dpy;
> efi_status_t status;
> diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
> index 4b76f74c56da..c1fd1fdbcb08 100644
> --- a/drivers/firmware/efi/libstub/zboot.c
> +++ b/drivers/firmware/efi/libstub/zboot.c
> @@ -26,9 +26,11 @@ void __weak efi_cache_sync_image(unsigned long image_base,
> // executable code loaded into memory to be safe for execution.
> }
>
> -struct sysfb_display_info *alloc_primary_display(void)
> +struct sysfb_display_info *lookup_primary_display(bool *needs_free)
> {
> - return __alloc_primary_display();
> + *needs_free = true;
> +
> + return alloc_primary_display();
> }
>
> asmlinkage efi_status_t __efiapi
> --
> 2.51.1
>
^ permalink raw reply
* Re: [PATCH net-next] net: mana: Fix use-after-free in reset service rescan path
From: Simon Horman @ 2025-12-16 12:20 UTC (permalink / raw)
To: Dipayaan Roy
Cc: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, longli, kotaranov, shradhagupta, ssengar, ernis,
shirazsaleem, linux-hyperv, netdev, linux-kernel, linux-rdma,
dipayanroy
In-Reply-To: <20251216105508.GA13584@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>
On Tue, Dec 16, 2025 at 02:55:08AM -0800, Dipayaan Roy wrote:
> When mana_serv_reset() encounters -ETIMEDOUT or -EPROTO from
> mana_gd_resume(), it performs a PCI rescan via mana_serv_rescan().
>
> mana_serv_rescan() calls pci_stop_and_remove_bus_device(), which can
> invoke the driver's remove path and free the gdma_context associated
> with the device. After returning, mana_serv_reset() currently jumps to
> the out label and attempts to clear gc->in_service, dereferencing a
> freed gdma_context.
>
> The issue was observed with the following call logs:
> [ 698.942636] BUG: unable to handle page fault for address: ff6c2b638088508d
> [ 698.943121] #PF: supervisor write access in kernel mode
> [ 698.943423] #PF: error_code(0x0002) - not-present page
> [S[ 698.943793] Pat Dec 6 07:GD5 100000067 P4D 1002f7067 PUD 1002f8067 PMD 101bef067 PTE 0
> 0:56 2025] hv_[n e 698.944283] Oops: Oops: 0002 [#1] SMP NOPTI
> tvsc f8615163-00[ 698.944611] CPU: 28 UID: 0 PID: 249 Comm: kworker/28:1
> ...
> [Sat Dec 6 07:50:56 2025] R10: [ 699.121594] mana 7870:00:00.0 enP30832s1: Configured vPort 0 PD 18 DB 16
> 000000000000001b R11: 0000000000000000 R12: ff44cf3f40270000
> [Sat Dec 6 07:50:56 2025] R13: 0000000000000001 R14: ff44cf3f402700c8 R15: ff44cf3f4021b405
> [Sat Dec 6 07:50:56 2025] FS: 0000000000000000(0000) GS:ff44cf7e9fcf9000(0000) knlGS:0000000000000000
> [Sat Dec 6 07:50:56 2025] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [Sat Dec 6 07:50:56 2025] CR2: ff6c2b638088508d CR3: 000000011fe43001 CR4: 0000000000b73ef0
> [Sat Dec 6 07:50:56 2025] Call Trace:
> [Sat Dec 6 07:50:56 2025] <TASK>
> [Sat Dec 6 07:50:56 2025] mana_serv_func+0x24/0x50 [mana]
> [Sat Dec 6 07:50:56 2025] process_one_work+0x190/0x350
> [Sat Dec 6 07:50:56 2025] worker_thread+0x2b7/0x3d0
> [Sat Dec 6 07:50:56 2025] kthread+0xf3/0x200
> [Sat Dec 6 07:50:56 2025] ? __pfx_worker_thread+0x10/0x10
> [Sat Dec 6 07:50:56 2025] ? __pfx_kthread+0x10/0x10
> [Sat Dec 6 07:50:56 2025] ret_from_fork+0x21a/0x250
> [Sat Dec 6 07:50:56 2025] ? __pfx_kthread+0x10/0x10
> [Sat Dec 6 07:50:56 2025] ret_from_fork_asm+0x1a/0x30
> [Sat Dec 6 07:50:56 2025] </TASK>
>
> Fix this by returning immediately after mana_serv_rescan() to avoid
> accessing GC state that may no longer be valid.
>
> Fixes: 9bf66036d686 ("net: mana: Handle hardware recovery events when probing the device")
>
nit: no blank line here please - tags should all appear in one block
> Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
I see that this patch is targeted at net-next.
But this is a fix for a patch present in net.
So it should be targeted at net instead
Subject: [PATCH net] ...
Probably it is not necessary to repost in order to address the minor
feedback I've provided above. But if you do, please be sure to observe
the 24h rule and wait that long between posting revisions of that patch.
https://docs.kernel.org/process/maintainer-netdev.html
The above not withstanding, this patch looks good to me.
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* [PATCH net-next] net: mana: Fix use-after-free in reset service rescan path
From: Dipayaan Roy @ 2025-12-16 10:55 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
When mana_serv_reset() encounters -ETIMEDOUT or -EPROTO from
mana_gd_resume(), it performs a PCI rescan via mana_serv_rescan().
mana_serv_rescan() calls pci_stop_and_remove_bus_device(), which can
invoke the driver's remove path and free the gdma_context associated
with the device. After returning, mana_serv_reset() currently jumps to
the out label and attempts to clear gc->in_service, dereferencing a
freed gdma_context.
The issue was observed with the following call logs:
[ 698.942636] BUG: unable to handle page fault for address: ff6c2b638088508d
[ 698.943121] #PF: supervisor write access in kernel mode
[ 698.943423] #PF: error_code(0x0002) - not-present page
[S[ 698.943793] Pat Dec 6 07:GD5 100000067 P4D 1002f7067 PUD 1002f8067 PMD 101bef067 PTE 0
0:56 2025] hv_[n e 698.944283] Oops: Oops: 0002 [#1] SMP NOPTI
tvsc f8615163-00[ 698.944611] CPU: 28 UID: 0 PID: 249 Comm: kworker/28:1
...
[Sat Dec 6 07:50:56 2025] R10: [ 699.121594] mana 7870:00:00.0 enP30832s1: Configured vPort 0 PD 18 DB 16
000000000000001b R11: 0000000000000000 R12: ff44cf3f40270000
[Sat Dec 6 07:50:56 2025] R13: 0000000000000001 R14: ff44cf3f402700c8 R15: ff44cf3f4021b405
[Sat Dec 6 07:50:56 2025] FS: 0000000000000000(0000) GS:ff44cf7e9fcf9000(0000) knlGS:0000000000000000
[Sat Dec 6 07:50:56 2025] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[Sat Dec 6 07:50:56 2025] CR2: ff6c2b638088508d CR3: 000000011fe43001 CR4: 0000000000b73ef0
[Sat Dec 6 07:50:56 2025] Call Trace:
[Sat Dec 6 07:50:56 2025] <TASK>
[Sat Dec 6 07:50:56 2025] mana_serv_func+0x24/0x50 [mana]
[Sat Dec 6 07:50:56 2025] process_one_work+0x190/0x350
[Sat Dec 6 07:50:56 2025] worker_thread+0x2b7/0x3d0
[Sat Dec 6 07:50:56 2025] kthread+0xf3/0x200
[Sat Dec 6 07:50:56 2025] ? __pfx_worker_thread+0x10/0x10
[Sat Dec 6 07:50:56 2025] ? __pfx_kthread+0x10/0x10
[Sat Dec 6 07:50:56 2025] ret_from_fork+0x21a/0x250
[Sat Dec 6 07:50:56 2025] ? __pfx_kthread+0x10/0x10
[Sat Dec 6 07:50:56 2025] ret_from_fork_asm+0x1a/0x30
[Sat Dec 6 07:50:56 2025] </TASK>
Fix this by returning immediately after mana_serv_rescan() to avoid
accessing GC state that may no longer be valid.
Fixes: 9bf66036d686 ("net: mana: Handle hardware recovery events when probing the device")
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index efb4e412ec7e..0055c231acf6 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -481,7 +481,7 @@ static void mana_serv_reset(struct pci_dev *pdev)
/* Perform PCI rescan on device if we failed on HWC */
dev_err(&pdev->dev, "MANA service: resume failed, rescanning\n");
mana_serv_rescan(pdev);
- goto out;
+ return;
}
if (ret)
--
2.34.1
^ permalink raw reply related
* Re: [PATCH][next] hyperv: Avoid -Wflex-array-member-not-at-end warning
From: Gustavo A. R. Silva @ 2025-12-16 2:59 UTC (permalink / raw)
To: Wei Liu, Gustavo A. R. Silva
Cc: K. Y. Srinivasan, Haiyang Zhang, Dexuan Cui, Long Li,
linux-hyperv, linux-kernel, linux-hardening
In-Reply-To: <20251215184759.GA654575@liuwe-devbox-debian-v2.local>
On 12/16/25 03:47, Wei Liu wrote:
> On Fri, Dec 12, 2025 at 03:44:50PM +0900, Gustavo A. R. Silva wrote:
>> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
>> getting ready to enable it, globally.
>>
>> Use the new __TRAILING_OVERLAP() helper to fix the following warning:
>>
>> include/hyperv/hvgdk_mini.h:581:25: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>>
>> This helper creates a union between a flexible-array member (FAM) and a
>> set of MEMBERS that would otherwise follow it.
>>
>> This overlays the trailing MEMBER u64 gva_list[]; onto the FAM
>> struct hv_tlb_flush_ex::hv_vp_set.bank_contents[], while keeping
>> the FAM and the start of MEMBER aligned.
>>
>> The static_assert() ensures this alignment remains, and it's
>> intentionally placed inmediately after the related structure --no
>> blank line in between.
>>
>> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
>
> Gustavo, what is your build command? I would like to incorporate that
> into my own build tests.
I'm using the following patch (which is the one I'll actually submit
upstream once all these warnings are fixed).
diff --git a/Makefile b/Makefile
index e404e4767944..0d6a0d8f791b 100644
--- a/Makefile
+++ b/Makefile
@@ -1086,6 +1086,8 @@ KBUILD_CFLAGS += $(call cc-option, -fstrict-flex-arrays=3)
# Allow including a tagged struct or union anonymously in another struct/union.
KBUILD_CFLAGS += -fms-extensions
+KBUILD_CFLAGS += $(call cc-option, -Wflex-array-member-not-at-end)
+
# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += -fno-strict-overflow
Thanks
-Gustavo
>
> Thanks,
> Wei
>
>> ---
>> include/hyperv/hvgdk_mini.h | 7 +++++--
>> 1 file changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
>> index 04b18d0e37af..30fbbde81c5c 100644
>> --- a/include/hyperv/hvgdk_mini.h
>> +++ b/include/hyperv/hvgdk_mini.h
>> @@ -578,9 +578,12 @@ struct hv_tlb_flush { /* HV_INPUT_FLUSH_VIRTUAL_ADDRESS_LIST */
>> struct hv_tlb_flush_ex {
>> u64 address_space;
>> u64 flags;
>> - struct hv_vpset hv_vp_set;
>> - u64 gva_list[];
>> + __TRAILING_OVERLAP(struct hv_vpset, hv_vp_set, bank_contents, __packed,
>> + u64 gva_list[];
>> + );
>> } __packed;
>> +static_assert(offsetof(struct hv_tlb_flush_ex, hv_vp_set.bank_contents) ==
>> + offsetof(struct hv_tlb_flush_ex, gva_list));
>>
>> struct ms_hyperv_tsc_page { /* HV_REFERENCE_TSC_PAGE */
>> volatile u32 tsc_sequence;
>> --
>> 2.43.0
>>
^ permalink raw reply related
* Re: [PATCH net-next v12 04/12] vsock: add netns support to virtio transports
From: Bobby Eshleman @ 2025-12-16 1:22 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
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: <uidarlot7opjsuozylevyrlgdpjd32tsi7mwll2lsvce226v24@75sq4jdo5tgv>
On Mon, Dec 15, 2025 at 03:11:22PM +0100, Stefano Garzarella wrote:
> On Fri, Dec 12, 2025 at 07:26:15AM -0800, Bobby Eshleman wrote:
> > On Tue, Dec 02, 2025 at 02:01:04PM -0800, Bobby Eshleman wrote:
> > > On Tue, Dec 02, 2025 at 09:47:19PM +0100, Paolo Abeni wrote:
> > > > On 12/2/25 6:56 PM, Bobby Eshleman wrote:
> > > > > On Tue, Dec 02, 2025 at 11:18:14AM +0100, Paolo Abeni wrote:
> > > > >> On 11/27/25 8:47 AM, Bobby Eshleman wrote:
> > > > >>> @@ -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);
> > > > >>
> > > > >> I'm sorry for the very late feedback. I think that at very least the
> > > > >> user-space needs a way to query if the given transport is in local or
> > > > >> global mode, as AFAICS there is no way to tell that when socket creation
> > > > >> races with mode change.
> > > > >
> > > > > Are you thinking something along the lines of sockopt?
> > > >
> > > > I'd like to see a way for the user-space to query the socket 'namespace
> > > > mode'.
> > > >
> > > > sockopt could be an option; a possibly better one could be sock_diag. Or
> > > > you could do both using dumping the info with a shared helper invoked by
> > > > both code paths, alike what TCP is doing.
> > > > >> Also I'm a bit uneasy with the model implemented here, as 'local' socket
> > > > >> may cross netns boundaris and connect to 'local' socket in other netns
> > > > >> (if I read correctly patch 2/12). That in turns AFAICS break the netns
> > > > >> isolation.
> > > > >
> > > > > Local mode sockets are unable to communicate with local mode (and global
> > > > > mode too) sockets that are in other namespaces. The key piece of code
> > > > > for that is vsock_net_check_mode(), where if either modes is local the
> > > > > namespaces must be the same.
> > > >
> > > > Sorry, I likely misread the large comment in patch 2:
> > > >
> > > > https://lore.kernel.org/netdev/20251126-vsock-vmtest-v12-2-257ee21cd5de@meta.com/
> > > >
> > > > >> Have you considered instead a slightly different model, where the
> > > > >> local/global model is set in stone at netns creation time - alike what
> > > > >> /proc/sys/net/ipv4/tcp_child_ehash_entries is doing[1] - and
> > > > >> inter-netns connectivity is explicitly granted by the admin (I guess
> > > > >> you will need new transport operations for that)?
> > > > >>
> > > > >> /P
> > > > >>
> > > > >> [1] tcp allows using per-netns established socket lookup tables - as
> > > > >> opposed to the default global lookup table (even if match always takes
> > > > >> in account the netns obviously). The mentioned sysctl specify such
> > > > >> configuration for the children namespaces, if any.
> > > > >
> > > > > I'll save this discussion if the above doesn't resolve your concerns.
> > > > I still have some concern WRT the dynamic mode change after netns
> > > > creation. I fear some 'unsolvable' (or very hard to solve) race I can't
> > > > see now. A tcp_child_ehash_entries-like model will avoid completely the
> > > > issue, but I understand it would be a significant change over the
> > > > current status.
> > > >
> > > > "Luckily" the merge window is on us and we have some time to discuss. Do
> > > > you have a specific use-case for the ability to change the netns >
> > > mode
> > > > after creation?
> > > >
> > > > /P
> > >
> > > I don't think there is a hard requirement that the mode be change-able
> > > after creation. Though I'd love to avoid such a big change... or at
> > > least leave unchanged as much of what we've already reviewed as
> > > possible.
> > >
> > > In the scheme of defining the mode at creation and following the
> > > tcp_child_ehash_entries-ish model, what I'm imagining is:
> > > - /proc/sys/net/vsock/child_ns_mode can be set to "local" or "global"
> > > - /proc/sys/net/vsock/child_ns_mode is not immutable, can change any
> > > number of times
> > >
> > > - when a netns is created, the new netns mode is inherited from
> > > child_ns_mode, being assigned using something like:
> > >
> > > net->vsock.ns_mode =
> > > get_net_ns_by_pid(current->pid)->child_ns_mode
> > >
> > > - /proc/sys/net/vsock/ns_mode queries the current mode, returning
> > > "local" or "global", returning value of net->vsock.ns_mode
> > > - /proc/sys/net/vsock/ns_mode and net->vsock.ns_mode are immutable and
> > > reject writes
> > >
> > > Does that align with what you have in mind?
> >
> > Hey Paolo, I just wanted to sync up on this one. Does the above align
> > with what you envision?
>
> Hi Bobby, AFAIK Paolo was at LPC, so there could be some delay.
>
> FYI I'll be off from Dec 25 to Jan 6, so if we want to do an RFC in the
> middle, I'll do my best to take a look before my time off.
>
> Thanks,
> Stefano
>
Sounds like a plan, thanks!
Best,
Bobby
^ permalink raw reply
* Re: [PATCH v7 4/7] Drivers: hv: Fix huge page handling in memory region traversal
From: Stanislav Kinsburskii @ 2025-12-15 20:12 UTC (permalink / raw)
To: Michael Kelley
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <SN6PR02MB4157978DFAA6C2584D0678E1D4A1A@SN6PR02MB4157.namprd02.prod.outlook.com>
On Thu, Dec 11, 2025 at 05:37:26PM +0000, Michael Kelley wrote:
> From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Thursday, December 4, 2025 1:09 PM
> >
> > On Thu, Dec 04, 2025 at 04:03:26PM +0000, Michael Kelley wrote:
> > > From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Tuesday, November 25, 2025 6:09 PM
> > > >
>
> [snip]
>
<snip>
> > > > +
> > > > + stride = 1 << page_order;
> > > > +
> > > > + /* Start at stride since the first page is validated */
> > > > + for (count = stride; count < page_count; count += stride) {
> > >
> > > This striding doesn't work properly in the general case. Suppose the
> > > page_offset value puts the start of the chunk in the middle of a 2 Meg
> > > page, and that 2 Meg page is then followed by a bunch of single pages.
> > > (Presumably the mmu notifier "invalidate" callback could do this.)
> > > The use of the full stride here jumps over the remaining portion of the
> > > 2 Meg page plus some number of the single pages, which isn't what you
> > > want. For the striding to work, it must figure out how much remains in the
> > > initial large page, and then once the striding is aligned to the large page
> > > boundaries, the full stride length works.
> > >
> > > Also, what do the hypercalls in the handler functions do if a chunk starts
> > > in the middle of a 2 Meg page? It looks like the handler functions will set
> > > the *_LARGE_PAGE flag to the hypercall but then the hv_call_* function
> > > will fail if the page_count isn't 2 Meg aligned.
> > >
> >
> > This situation you described is not possible, because invalidation
> > callback simply can't invalidate a part of the huge page even in THP
> > case (leave aside hugetlb case) without splitting it beforehand, and
> > splitting a huge page requires invalidation of the whole huge page
> > first.
>
> I've been playing around with mmu notifiers and 2 Meg pages. At least in my
> experiment, there's a case where the .invalidate callback is invoked on a
> range *before* the 2 Meg page is split. The kernel code that does this is
> in zap_page_range_single_batched(). Early on this function calls
> mmu_notifier_invalidate_range_start(), which invokes the .invalidate
> callback on the initial range. Later on, unmap_single_vma() is called, which
> does the split and eventually makes a second .invalidate callback for the
> entire 2 Meg page.
>
> Details: My experiment is a user space program that does the following:
>
> 1. Allocates 16 Megs of memory on a 16 Meg boundary using
> posix_memalign(). So this is private anonymous memory. Transparent
> huge pages are enabled.
>
> 2. Writes to a byte in each 4K page so they are all populated.
> /proc/meminfo shows eight 2 Meg pages have been allocated.
>
> 3. Creates an mmu notifier for the allocated 16 Megs, using an ioctl
> hacked into the kernel for experimentation purposes.
>
> 4. Uses madvise() with the DONTNEED option to free 32 Kbytes on a 4K
> page boundary somewhere in the 16 Meg allocation. This results in an mmu
> notifier invalidate callback for that 32 Kbytes. Then there's a second invalidate
> callback covering the entire 2 Meg page that contains the 32 Kbyte range.
> Kernel stack traces for the two invalidate callbacks show them originating
> in zap_page_range_single_batched().
>
> 5. Sleeps for 60 seconds. During that time, khugepaged wakes up and does
> hpage_collapse_scan_pmd() -> collapse_huge_page(), which generates a third
> .invalidate callback for the 2 Meg page. I'm haven't investigated what this is
> all about.
>
> 6. Interestingly, if Step 4 above does a slightly different operation using
> mprotect() with PROT_READ instead of madvise(), the 2 Meg page is split first.
> The .invalidate callback for the full 2 Meg happens before the .invalidate
> callback for the specified range.
>
> The root partition probably isn't doing madvise() with DONTNEED for memory
> allocated for guests. But regardless of what user space does or doesn't do, MSHV's
> invalidate callback path should be made safe for this case. Maybe that's just
> detecting it and returning an error (and maybe a WARN_ON) if user space
> doesn't need it to work.
>
This is a deep research, Michael. Thanks a lot for you effort.
I'll think more about it and will likely follow up.
Thank you,
Stanislav
> Michael
>
^ permalink raw reply
* Re: [PATCH][next] hyperv: Avoid -Wflex-array-member-not-at-end warning
From: Wei Liu @ 2025-12-15 18:47 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
linux-hyperv, linux-kernel, linux-hardening
In-Reply-To: <aTu54qH2iHLKScRW@kspp>
On Fri, Dec 12, 2025 at 03:44:50PM +0900, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
>
> Use the new __TRAILING_OVERLAP() helper to fix the following warning:
>
> include/hyperv/hvgdk_mini.h:581:25: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>
> This helper creates a union between a flexible-array member (FAM) and a
> set of MEMBERS that would otherwise follow it.
>
> This overlays the trailing MEMBER u64 gva_list[]; onto the FAM
> struct hv_tlb_flush_ex::hv_vp_set.bank_contents[], while keeping
> the FAM and the start of MEMBER aligned.
>
> The static_assert() ensures this alignment remains, and it's
> intentionally placed inmediately after the related structure --no
> blank line in between.
>
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Gustavo, what is your build command? I would like to incorporate that
into my own build tests.
Thanks,
Wei
> ---
> include/hyperv/hvgdk_mini.h | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
> index 04b18d0e37af..30fbbde81c5c 100644
> --- a/include/hyperv/hvgdk_mini.h
> +++ b/include/hyperv/hvgdk_mini.h
> @@ -578,9 +578,12 @@ struct hv_tlb_flush { /* HV_INPUT_FLUSH_VIRTUAL_ADDRESS_LIST */
> struct hv_tlb_flush_ex {
> u64 address_space;
> u64 flags;
> - struct hv_vpset hv_vp_set;
> - u64 gva_list[];
> + __TRAILING_OVERLAP(struct hv_vpset, hv_vp_set, bank_contents, __packed,
> + u64 gva_list[];
> + );
> } __packed;
> +static_assert(offsetof(struct hv_tlb_flush_ex, hv_vp_set.bank_contents) ==
> + offsetof(struct hv_tlb_flush_ex, gva_list));
>
> struct ms_hyperv_tsc_page { /* HV_REFERENCE_TSC_PAGE */
> volatile u32 tsc_sequence;
> --
> 2.43.0
>
^ permalink raw reply
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