Linux Documentation
 help / color / mirror / Atom feed
* Re: [PATCH v5 04/21] nfsd: allow nfsd to get a dir lease with an ignore mask
From: Chuck Lever @ 2026-06-08 16:29 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-4-542cddfad576@kernel.org>


On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> When requesting a directory lease, enable the FL_IGN_DIR_* bits that
> correspond to the requested notification types.

> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 67e163ee13a2..2a34ba457b74 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c

> @@ -9642,12 +9657,11 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
>  		dp->dl_stid.sc_export =
>  			exp_get(cstate->current_fh.fh_export);
> 
> -	fl = nfs4_alloc_init_lease(dp);
> +	fl = nfs4_alloc_init_lease(dp, gdd->gddr_notification[0]);

Both Sashiko and my own gpt-5.5 review noted the use of a response field
here rather than a request field, but that is a false positive finding.
The commit message needs to explain why the use of gddr_notification[0]
is correct.


>  	if (!fl)
>  		goto out_put_stid;
> 
> -	status = kernel_setlease(nf->nf_file,
> -				 fl->c.flc_type, &fl, NULL);
> +	status = kernel_setlease(nf->nf_file, fl->c.flc_type, &fl, NULL);
>  	if (fl)
>  		locks_free_lease(fl);
>  	if (status)

This last edit appears to be a clean-up that is unrelated to the purpose
of the patch.


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH mm-unstable v19 11/14] mm/khugepaged: Introduce mTHP collapse support
From: Lance Yang @ 2026-06-08 16:26 UTC (permalink / raw)
  To: david
  Cc: lance.yang, npache, linux-doc, linux-kernel, linux-mm,
	linux-trace-kernel, aarcange, akpm, anshuman.khandual, apopple,
	baohua, baolin.wang, byungchul, catalin.marinas, cl, corbet,
	dave.hansen, dev.jain, gourry, hannes, hughd, jack, jackmanb,
	jannh, jglisse, joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers,
	matthew.brost, mhiramat, mhocko, peterx, pfalcato, rakie.kim,
	raquini, rdunlap, richard.weiyang, rientjes, rostedt, rppt,
	ryan.roberts, shivankg, sunnanyong, surenb, thomas.hellstrom,
	tiwai, usamaarif642, vbabka, vishal.moola, wangkefeng.wang, will,
	willy, yang, ying.huang, ziy, zokeefe
In-Reply-To: <2553caae-9e0e-42a7-8b61-d1216f1e81fa@kernel.org>


On Mon, Jun 08, 2026 at 04:56:37PM +0200, David Hildenbrand (Arm) wrote:
>On 6/6/26 12:28, Lance Yang wrote:
>> 
>> On Fri, Jun 05, 2026 at 10:14:18AM -0600, Nico Pache wrote:
>>> Enable khugepaged to collapse to mTHP orders. This patch implements the
>>> main scanning logic using a bitmap to track occupied pages and the
>>> algorithm to find optimal collapse sizes.
>>>
>>> Previous to this patch, PMD collapse had 3 main phases, a light weight
>>> scanning phase (mmap_read_lock) that determines a potential PMD
>>> collapse, an alloc phase (mmap unlocked), then finally heavier collapse
>>> phase (mmap_write_lock).
>>>
>>> To enabled mTHP collapse we make the following changes:
>>>
>>> During PMD scan phase, track occupied pages in a bitmap. When mTHP
>>> orders are enabled, we remove the restriction of max_ptes_none during the
>>> scan phase to avoid missing potential mTHP collapse candidates. Once we
>>> have scanned the full PMD range and updated the bitmap to track occupied
>>> pages, we use the bitmap to find the optimal mTHP size.
>>>
>>> Implement mthp_collapse() to walk forward through the bitmap and
>>> determine the best eligible order for each naturally-aligned region. The
>>> algorithm starts at the beginning of the PMD range and, for each offset,
>>> tries the highest order that fits the alignment. If the number of
>>> occupied PTEs in that region satisfies the max_ptes_none threshold for
>>> that order, a collapse is attempted. On failure, the order is
>>> decremented and the same offset is retried at the next smaller size. Once
>>> the smallest enabled order is exhausted (or a collapse succeeds), the
>>> offset advances past the region just processed, and the next attempt
>>> starts at the highest order permitted by the new offset's natural
>>> alignment.
>>>
>>> The algorithm works as follows:
>>>    1) set offset=0 and order=HPAGE_PMD_ORDER
>>>    2) if the order is not enabled, go to step (5)
>>>    3) count occupied PTEs in the (offset, order) range using
>>>       bitmap_weight_from()
>>>    4) if the count satisfies the max_ptes_none threshold, attempt
>>>       collapse; on success, advance to step (6)
>>>    5) if a smaller enabled order exists, decrement order and retry
>>>       from step (2) at the same offset
>>>    6) advance offset past the current region and compute the next
>>>       order from the new offset's natural alignment via __ffs(offset),
>>>       capped at HPAGE_PMD_ORDER
>>>    7) repeat from step (2) until the full PMD range is covered
>>>
>>> mTHP collapses reject regions containing swapped out or shared pages.
>>> This is because adding new entries can lead to new none pages, and these
>>> may lead to constant promotion into a higher order mTHP. A similar
>>> issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
>>> introducing at least 2x the number of pages, and on a future scan will
>>> satisfy the promotion condition once again. This issue is prevented via
>>> the collapse_max_ptes_none() function which imposes the max_ptes_none
>>> restrictions above.
>>>
>>> We currently only support mTHP collapse for max_ptes_none values of 0
>>> and HPAGE_PMD_NR - 1. resulting in the following behavior:
>>>
>>>    - max_ptes_none=0: Never introduce new empty pages during collapse
>>>    - max_ptes_none=HPAGE_PMD_NR-1: Always try collapse to the highest
>>>      available mTHP order
>>>
>>> Any other max_ptes_none value will emit a warning and default mTHP
>>> collapse to max_ptes_none=0. There should be no behavior change for PMD
>>> collapse.
>>>
>>> Once we determine what mTHP sizes fits best in that PMD range a collapse
>>> is attempted. A minimum collapse order of 2 is used as this is the lowest
>>> order supported by anon memory as defined by THP_ORDERS_ALL_ANON.
>>>
>>> Currently madv_collapse is not supported and will only attempt PMD
>>> collapse.
>>>
>>> We can also remove the check for is_khugepaged inside the PMD scan as
>>> the collapse_max_ptes_none() function handles this logic now.
>>>
>>> Signed-off-by: Nico Pache <npache@redhat.com>
>>> ---
>>> mm/khugepaged.c | 146 +++++++++++++++++++++++++++++++++++++++++++++---
>>> 1 file changed, 138 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>> index ec886a031952..430047316f43 100644
>>> --- a/mm/khugepaged.c
>>> +++ b/mm/khugepaged.c
>>> @@ -99,6 +99,8 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
>>>
>>> static struct kmem_cache *mm_slot_cache __ro_after_init;
>>>
>>> +#define KHUGEPAGED_MIN_MTHP_ORDER	2
>>> +
>>> struct collapse_control {
>>> 	bool is_khugepaged;
>>>
>>> @@ -110,6 +112,9 @@ struct collapse_control {
>>>
>>> 	/* nodemask for allocation fallback */
>>> 	nodemask_t alloc_nmask;
>>> +
>>> +	/* Each bit represents a single occupied (!none/zero) page. */
>>> +	DECLARE_BITMAP(mthp_present_ptes, MAX_PTRS_PER_PTE);
>>> };
>>>
>>> /**
>>> @@ -1440,20 +1445,130 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long s
>>> 	return result;
>>> }
>>>
>>> +/* Return the highest naturally aligned order that fits at @offset within a PMD. */
>>> +static unsigned int max_order_from_offset(unsigned int offset)
>>> +{
>>> +	if (offset == 0)
>>> +		return HPAGE_PMD_ORDER;
>>> +
>>> +	return min_t(unsigned int, __ffs(offset), HPAGE_PMD_ORDER);
>>> +}
>>> +
>>> +/*
>>> + * mthp_collapse() consumes the bitmap that is generated during
>>> + * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
>>> + *
>>> + * Each bit in cc->mthp_present_ptes represents a single occupied (!none/zero)
>>> + * page. We start at the PMD order and check if it is eligible for collapse;
>>> + * if not, we check the left and right halves of the PTE page table we are
>>> + * examining at a lower order.
>>> + *
>>> + * For each of these, we determine how many PTE entries are occupied in the
>>> + * range of PTE entries we propose to collapse, then we compare this to a
>>> + * threshold number of PTE entries which would need to be occupied for a
>>> + * collapse to be permitted at that order (accounting for max_ptes_none).
>>> + *
>>> + * If a collapse is permitted, we attempt to collapse the PTE range into a
>>> + * mTHP.
>>> + */
>>> +static enum scan_result mthp_collapse(struct mm_struct *mm,
>>> +		unsigned long address, int referenced, int unmapped,
>>> +		struct collapse_control *cc, unsigned long enabled_orders)
>>> +{
>>> +	unsigned int nr_occupied_ptes, nr_ptes, max_ptes_none;
>>> +	enum scan_result last_result = SCAN_FAIL;
>>> +	int collapsed = 0;
>>> +	bool alloc_failed = false;
>>> +	unsigned long collapse_address;
>>> +	unsigned int offset = 0;
>>> +	unsigned int order = HPAGE_PMD_ORDER;
>>> +
>>> +	while (offset < HPAGE_PMD_NR) {
>>> +		nr_ptes = 1UL << order;
>>> +
>>> +		if (!test_bit(order, &enabled_orders))
>>> +			goto next_order;
>>> +
>>> +		max_ptes_none = collapse_max_ptes_none(cc, NULL, order);
>>> +		nr_occupied_ptes = bitmap_weight_from(cc->mthp_present_ptes, offset,
>>> +						      offset + nr_ptes);
>>> +
>>> +		if (nr_occupied_ptes >= nr_ptes - max_ptes_none) {
>> 
>> Looks broken for swap PTEs in PMD collapse ...
>> 
>> collapse_scan_pmd() allows them up to max_ptes_swap and record them in
>> unmapped, but they don't get a bit in mthp_present_ptes. And then
>> mthp_collapse() does the check above:
>
>Right. I assumed this is implicitly handled by the optimization in collapse_scan_pmd:
>
>	if (enabled_orders != BIT(HPAGE_PMD_ORDER))
>		max_ptes_none = KHUGEPAGED_MAX_PTES_LIMIT;
>
>But we perform the check a second time.

Note that once lower orders are enabled, the scan *relaxes* max_ptes_none
only so it can cover the whole PMD and build the bitmap ...

>> 
>> nr_occupied_ptes >= nr_ptes - max_ptes_none
>> 
>> So max_ptes_none=0 + 511 present PTEs + one allowed swap PTE won't even
>> call collapse_huge_page() for PMD order.
>> 
>> Shouldn't we account for them in the PMD-order check? Something like:
>> 
>> if (is_pmd_order(order))
>> 	nr_occupied_ptes += unmapped;
>As an alternative, we could either 1) skip the check there for
>pmd order (as the check was already done); or 2) introduce+maintain

Yeah, skipping the check would do the trick, since isolate will check
max_ptes_none again later :)

>a bitmap that tracks non-present PTEs.
>
>@@ -1475,7 +1477,9 @@ static enum scan_result mthp_collapse(struct mm_struct *mm,
>                nr_occupied_ptes = bitmap_weight_from(cc->mthp_present_ptes, offset,
>                                                      offset + nr_ptes);
> 
>-               if (nr_occupied_ptes >= nr_ptes - max_ptes_none) {
>+               /* Check was already done in the caller. */

This check is not quite redundant for PMD order, though. It avoids
entering collapse_huge_page() for a range that already exceeds
max_ptes_none for that order.

>+               if (is_pmd_order(order) ||
>+                   nr_occupied_ptes >= nr_ptes - max_ptes_none) {
>                        enum scan_result ret;
> 
>                        collapse_address = address + offset * PAGE_SIZE;
>
>2) would probably be cleanest long-term.

Yeah, Agreed.

^ permalink raw reply

* Re: [PATCH v4 03/21] nfs_common: add new NOTIFY4_* flags proposed in RFC8881bis
From: Chuck Lever @ 2026-06-08 16:23 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker
  Cc: Alexander Aring, Amir Goldstein, Jan Kara, Alexander Viro,
	Christian Brauner, Calum Mackay, linux-kernel, linux-doc,
	linux-nfs
In-Reply-To: <20260522-dir-deleg-v4-3-2acb883ac6bc@kernel.org>

Unfortunately, reviewing this series slipped off my radar. I'm just now
getting to it. I'm going to do this in order and some of the earlier
reviews are cosmetic. But there are some significant changes needed
later on, so I expect we'll need to redrive this series and punt it to
v7.3.

One thing you might update before you repost is to remove the "Acked-by:
Chuck Lever" throughout the series.


Nit: the Subject: prefix should be "nfsd:" not "nfs_common:"


On Fri, May 22, 2026, at 8:28 AM, Jeff Layton wrote:
> RFC8881bis adds some new flags to GET_DIR_DELEGATION that we very much
> need to support.

Nit: Let's say: "RFC8881bis adds new flags to GET_DIR_DELEGATION
that later patches consume."

One recent private comment to me was a question about whether we can
trust the stability of the specification, which is still a WG document
and has been for years. This patch's commit message should address
that.


> diff --git a/Documentation/sunrpc/xdr/nfs4_1.x 
> b/Documentation/sunrpc/xdr/nfs4_1.x
> index 632f5b579c39..aa14b590b524 100644
> --- a/Documentation/sunrpc/xdr/nfs4_1.x
> +++ b/Documentation/sunrpc/xdr/nfs4_1.x
> @@ -416,7 +416,21 @@ enum notify_type4 {
>          NOTIFY4_REMOVE_ENTRY = 2,
>          NOTIFY4_ADD_ENTRY = 3,
>          NOTIFY4_RENAME_ENTRY = 4,
> -        NOTIFY4_CHANGE_COOKIE_VERIFIER = 5
> +        NOTIFY4_CHANGE_COOKIE_VERIFIER = 5,
> +        /*
> +         * Added in NFSv4.1 bis document
> +         */

I clarified this comment: "/* Proposed in RFC8881bis */"

I rebuilt the generated source to confirm that it hasn't been altered
by recent changes to xdrgen or this comment change. The only thing
that changed in the output was the header's timestamp.


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Nhat Pham @ 2026-06-08 16:23 UTC (permalink / raw)
  To: Hao Jia
  Cc: Yosry Ahmed, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <90730fa7-62e7-d5f4-b638-23b22a8509f2@gmail.com>

On Mon, Jun 8, 2026 at 5:50 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
> On 2026/6/5 01:23, Nhat Pham wrote:
> >
>
> Thanks for the suggestion!
>
> I ran some tests and found that neither the per-memcg cursor nor
> different batch sizes have a significant impact on proactive writeback
> performance. However, exactly as we suspected, without the per-memcg
> cursor, the writeback distribution among child memcgs is highly unfair.
>
> Test Setup:
>
>    zswap config: 18G capacity, LZ4 compression.
>    cgroup hierarchy: 1 parent test memcg with 10 child memcgs.
>    Allocation: Allocated 1600MB of anonymous pages in each child memcg.
> To ensure compressibility, the first half of each page was filled with
> random data and the second half with zeros.
>    Force to zswap: Ran echo "1600M" > memory.reclaim on each child memcg
> to squeeze all their memory into zswap.
>    Trigger writeback: Ran echo "<size> zswap_writeback_only" >
> memory.reclaim on the parent cgroup 200 times, with a 2-second interval
> between each run.
>    Metric: Monitored the zswpwb_proactive metric in memory.stat to
> observe the writeback volume.
>    **Note**: The size here refers to the uncompressed memory size. Also,
> since the second-chance algorithm would cause many writebacks to fall
> short of the target size, I **bypassed** it during these tests to avoid
> interference.
>
> Without cursor (size: 1M, batch: 32)
>    child        wb_pages        wb_MB     share%
>    child0           6368        24.88      12.50
>    child1           6368        24.88      12.50
>    child2           6368        24.88      12.50
>    child3           6368        24.88      12.50
>    child4           6368        24.88      12.50
>    child5           6368        24.88      12.50
>    child6           6368        24.88      12.50
>    child7           6368        24.88      12.50
>    child8              0         0.00       0.00
>    child9              0         0.00       0.00
> Without cursor (size: 1M, batch: 128)
>    child        wb_pages        wb_MB     share%
>    child0          25472        99.50      50.00
>    child1          25472        99.50      50.00
>    child2              0         0.00       0.00
>    child3              0         0.00       0.00
>    child4              0         0.00       0.00
>    child5              0         0.00       0.00
>    child6              0         0.00       0.00
>    child7              0         0.00       0.00
>    child8              0         0.00       0.00
>    child9              0         0.00       0.00
> Without cursor (size: 6M, batch: 128)
>    child        wb_pages        wb_MB     share%
>    child0          51200       200.00      16.67
>    child1          51200       200.00      16.67
>    child2          25600       100.00       8.33
>    child3          25600       100.00       8.33
>    child4          25600       100.00       8.33
>    child5          25600       100.00       8.33
>    child6          25600       100.00       8.33
>    child7          25600       100.00       8.33
>    child8          25600       100.00       8.33
>    child9          25600       100.00       8.33
>
>
> With cursor (size: 1M, batch: 32)
>    child        wb_pages        wb_MB     share%
>    child0           5120        20.00      10.00
>    child1           5120        20.00      10.00
>    child2           5120        20.00      10.00
>    child3           5120        20.00      10.00
>    child4           5120        20.00      10.00
>    child5           5120        20.00      10.00
>    child6           5120        20.00      10.00
>    child7           5120        20.00      10.00
>    child8           5120        20.00      10.00
>    child9           5120        20.00      10.00
> With cursor (size: 1M, batch: 128)
>    child        wb_pages        wb_MB     share%
>    child0           5120        20.00      10.00
>    child1           5120        20.00      10.00
>    child2           5120        20.00      10.00
>    child3           5120        20.00      10.00
>    child4           5120        20.00      10.00
>    child5           5120        20.00      10.00
>    child6           5120        20.00      10.00
>    child7           5120        20.00      10.00
>    child8           5120        20.00      10.00
>    child9           5120        20.00      10.00
>

Yeah OTOH, we don't really make fairness an API contract here. When
you set up a proactive reclaim scheme, if you decide to target a
cgroup (and not its children separately), everything underneath it is
fair game to the kernel in any split that we fancy. If you want true
fairness or a desired split, you have to treat them as independent
memory domains and set up proactive reclaim to hit each child cgroup
separately (i.e one "echo > memory.reclaim" for each of them). This is
necessary for example if each child represents a separate, isolated
service/container/tenant. And maybe this is actually what you really
want - hit the ancestor cgroup very lightly for the stuff it owns, but
then dedidcate most of the reclaim effort at the leaf cgroups
independently?

But OTOH, this does seem like a recipe for inefficient reclaim. We
might exhaust hotter memory of a cgroup while sparing colder memory of
another cgroup... But maybe if they're all cold anyway, then who
cares, and eventually you'll get to the cold stuff of other child?

Yosry, what's the concern here? Is it space overhead, or overall code
complexity?

^ permalink raw reply

* Re: [PATCH v7 00/12] ima: Exporting and deleting IMA measurement records from kernel memory
From: Roberto Sassu @ 2026-06-08 16:22 UTC (permalink / raw)
  To: Mimi Zohar, corbet, skhan, dmitry.kasatkin, eric.snowberg, paul,
	jmorris, serge
  Cc: linux-doc, linux-kernel, linux-integrity, linux-security-module,
	gregorylumen, chenste, nramas, Roberto Sassu
In-Reply-To: <22debae414a07a3cbdb62e723dfb737d6d4bd693.camel@linux.ibm.com>

On Mon, 2026-06-08 at 12:21 -0400, Mimi Zohar wrote:
> On Fri, 2026-06-05 at 19:22 +0200, Roberto Sassu wrote:
> > From: Roberto Sassu <roberto.sassu@huawei.com>
> > 
> > Introduction
> > ============
> > 
> > The IMA measurements list is currently stored in the kernel memory.
> > Memory occupation grows linearly with the number of records, and can
> > become a problem especially in environments with reduced resources.
> > 
> > While there is an advantage in keeping the IMA measurements list in
> > kernel memory, so that it is always available for reading from the
> > securityfs interfaces, storing it elsewhere would make it possible to
> > free precious memory for other kernel usage.
> > 
> > The IMA measurements list needs to be retained and safely stored for new
> > attestation servers to validate it. Assuming the IMA measurements list
> > is properly saved, storing it outside the kernel does not introduce
> > security issues, since its integrity is anyway protected by the TPM.
> > 
> > Hence, the new IMA staging mechanism is introduced to export IMA
> > measurements to user space and delete them from kernel space.
> > 
> > Staging consists in atomically moving the current measurements list to a
> > temporary list, so that measurements can be deleted afterwards. The
> > staging operation locks the hot path (racing with addition of new
> > measurements) for a very short time, only for swapping the list
> > pointers. Deletion of the measurements instead is done locklessly, away
> > from the hot path.
> > 
> > There are two flavors of the staging mechanism. In the staging with
> > prompt, all current measurements are staged, read and deleted upon
> > confirmation. In the staging and deleting flavor, N measurements are
> > staged from the beginning of the current measurements list and
> > immediately deleted without confirmation.
> > 
> > 
> > Usage
> > =====
> > 
> > The IMA staging mechanism can be enabled from the kernel configuration
> > with the CONFIG_IMA_STAGING option. This option prevents inadvertently
> > removing the IMA measurement list on systems which do not properly save
> > it.
> > 
> > If the option is enabled, IMA duplicates the current securityfs
> > measurements interfaces (both binary and ASCII), by adding the _staged
> > file suffix. Both the original and the staging interfaces gain the write
> > permission for the root user and group, but require the process to have
> > CAP_SYS_ADMIN set.
> > 
> > The staging mechanism supports two flavors.
> > 
> > Staging with prompt
> > ~~~~~~~~~~~~~~~~~~~
> > 
> > The current measurement list is moved to a temporary staging area,
> > allowing it to be saved to external storage, before being deleted upon
> > confirmation.
> > 
> > This staging process is achieved with the following steps.
> > 
> >   1.  echo A > <_staged interface>: the user requests IMA to stage the
> >       entire measurements list;
> >   2.  cat <_staged interface>: the user reads the staged measurements;
> >   3.  echo D > <_staged interface>: the user requests IMA to delete
> >       staged measurements.
> > 
> > Staging and deleting
> > ~~~~~~~~~~~~~~~~~~~~
> > 
> > N measurements are staged to a temporary staging area, and immediately
> > deleted without further confirmation.
> > 
> > This staging process is achieved with the following steps.
> > 
> >   1.  cat <original interface>: the user reads the current measurements
> >       list and determines what the value N for staging should be;
> >   2.  echo N > <original interface>: the user requests IMA to delete N
> >       measurements from the current measurements list.
> > 
> > 
> > Management of Staged Measurements
> > =================================
> > 
> > Since with the staging mechanism measurement records are removed from
> > the kernel, the staged measurements need to be saved in a storage and
> > concatenated together, so that they can be presented during remote
> > attestation as if staging was never done. This task can be accomplished
> > by a remote attestation agent modified to support staging, or a system
> > service.
> > 
> > 
> > Patch set content
> > =================
> > 
> > Patches 1-8 are preparatory patches to quickly replace the hash table,
> > maintain separate counters for the different measurements list types,
> > mediate access to the measurements list interface, and simplify the staging
> > patches.
> > 
> > Patch 9 introduces the staging with prompt flavor. Patch 10 makes it
> > possible to flush the hash table when deleting all the staged measurements.
> > Patch 11 introduces the staging and deleting flavor. Patch 12 adds the
> > documentation of the staging mechanism.
> > 
> > 
> > Changelog
> > =========
> > 
> > v6:
> >  - Make ima_extend_list_mutex as static since it is not needed anymore by
> >    ima_dump_measurement_list() (suggested by Mimi)
> >  - Export ima_flush_htable in patch 11 instead of 10 (suggested by Mimi)
> >  - Add clarification in the documentation regarding a proactive remote
> >    attestation agent, and storing all the measurements in the storage
> >    (suggested by Mimi)
> 
> Roberto, thank you for making these and all the other changes.  The patch set is
> now queued in next-integrity.

Perfect, thank you!

Roberto


^ permalink raw reply

* Re: [PATCH v7 00/12] ima: Exporting and deleting IMA measurement records from kernel memory
From: Mimi Zohar @ 2026-06-08 16:21 UTC (permalink / raw)
  To: Roberto Sassu, corbet, skhan, dmitry.kasatkin, eric.snowberg,
	paul, jmorris, serge
  Cc: linux-doc, linux-kernel, linux-integrity, linux-security-module,
	gregorylumen, chenste, nramas, Roberto Sassu
In-Reply-To: <20260605172236.2042045-1-roberto.sassu@huaweicloud.com>

On Fri, 2026-06-05 at 19:22 +0200, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> Introduction
> ============
> 
> The IMA measurements list is currently stored in the kernel memory.
> Memory occupation grows linearly with the number of records, and can
> become a problem especially in environments with reduced resources.
> 
> While there is an advantage in keeping the IMA measurements list in
> kernel memory, so that it is always available for reading from the
> securityfs interfaces, storing it elsewhere would make it possible to
> free precious memory for other kernel usage.
> 
> The IMA measurements list needs to be retained and safely stored for new
> attestation servers to validate it. Assuming the IMA measurements list
> is properly saved, storing it outside the kernel does not introduce
> security issues, since its integrity is anyway protected by the TPM.
> 
> Hence, the new IMA staging mechanism is introduced to export IMA
> measurements to user space and delete them from kernel space.
> 
> Staging consists in atomically moving the current measurements list to a
> temporary list, so that measurements can be deleted afterwards. The
> staging operation locks the hot path (racing with addition of new
> measurements) for a very short time, only for swapping the list
> pointers. Deletion of the measurements instead is done locklessly, away
> from the hot path.
> 
> There are two flavors of the staging mechanism. In the staging with
> prompt, all current measurements are staged, read and deleted upon
> confirmation. In the staging and deleting flavor, N measurements are
> staged from the beginning of the current measurements list and
> immediately deleted without confirmation.
> 
> 
> Usage
> =====
> 
> The IMA staging mechanism can be enabled from the kernel configuration
> with the CONFIG_IMA_STAGING option. This option prevents inadvertently
> removing the IMA measurement list on systems which do not properly save
> it.
> 
> If the option is enabled, IMA duplicates the current securityfs
> measurements interfaces (both binary and ASCII), by adding the _staged
> file suffix. Both the original and the staging interfaces gain the write
> permission for the root user and group, but require the process to have
> CAP_SYS_ADMIN set.
> 
> The staging mechanism supports two flavors.
> 
> Staging with prompt
> ~~~~~~~~~~~~~~~~~~~
> 
> The current measurement list is moved to a temporary staging area,
> allowing it to be saved to external storage, before being deleted upon
> confirmation.
> 
> This staging process is achieved with the following steps.
> 
>   1.  echo A > <_staged interface>: the user requests IMA to stage the
>       entire measurements list;
>   2.  cat <_staged interface>: the user reads the staged measurements;
>   3.  echo D > <_staged interface>: the user requests IMA to delete
>       staged measurements.
> 
> Staging and deleting
> ~~~~~~~~~~~~~~~~~~~~
> 
> N measurements are staged to a temporary staging area, and immediately
> deleted without further confirmation.
> 
> This staging process is achieved with the following steps.
> 
>   1.  cat <original interface>: the user reads the current measurements
>       list and determines what the value N for staging should be;
>   2.  echo N > <original interface>: the user requests IMA to delete N
>       measurements from the current measurements list.
> 
> 
> Management of Staged Measurements
> =================================
> 
> Since with the staging mechanism measurement records are removed from
> the kernel, the staged measurements need to be saved in a storage and
> concatenated together, so that they can be presented during remote
> attestation as if staging was never done. This task can be accomplished
> by a remote attestation agent modified to support staging, or a system
> service.
> 
> 
> Patch set content
> =================
> 
> Patches 1-8 are preparatory patches to quickly replace the hash table,
> maintain separate counters for the different measurements list types,
> mediate access to the measurements list interface, and simplify the staging
> patches.
> 
> Patch 9 introduces the staging with prompt flavor. Patch 10 makes it
> possible to flush the hash table when deleting all the staged measurements.
> Patch 11 introduces the staging and deleting flavor. Patch 12 adds the
> documentation of the staging mechanism.
> 
> 
> Changelog
> =========
> 
> v6:
>  - Make ima_extend_list_mutex as static since it is not needed anymore by
>    ima_dump_measurement_list() (suggested by Mimi)
>  - Export ima_flush_htable in patch 11 instead of 10 (suggested by Mimi)
>  - Add clarification in the documentation regarding a proactive remote
>    attestation agent, and storing all the measurements in the storage
>    (suggested by Mimi)

Roberto, thank you for making these and all the other changes.  The patch set is
now queued in next-integrity.

Mimi

^ permalink raw reply

* Re: [RFC v1 0/9] kho: granular compatibility and header decoupling
From: Pasha Tatashin @ 2026-06-08 16:12 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Pasha Tatashin, linux-kselftest, shuah, akpm, linux-mm, skhan,
	linux-doc, jasonmiu, linux-kernel, corbet, ran.xiaokai, kexec,
	pratyush, graf
In-Reply-To: <178091437240.1648214.10761111570005003901.b4-reply@b4>

On 06-08 13:26, Mike Rapoport wrote:
> On 2026-06-07 13:43:09+00:00, Pasha Tatashin wrote:
> > On 06-07 14:58, Mike Rapoport wrote:
> > 
> > > On Fri, 05 Jun 2026 03:32:26 +0000, Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> > > 
> > > Hi,
> > > 
> > > 
> > > I'd keep vmalloc where it is, it's more of a memory preservation primitive
> > > rather than a data structure of it's own. The data structure it uses is an
> > > implementation detail.
> > 
> > kho vmalloc is absolutely a data structure. KHO core only provides the
> > basic handover mechanism (FDT nodes, physical memory ranges). vmalloc
> > is a structured representation on top of KHO, and should provide its own
> > versioned ABI.
> 
> kho_preserve_vmalloc() has the same semantics as kho_preserve_folio().
> It's not intended to be used as a data structure. The data structure is
> an implementation detail unlike with kho_block and kho_radix_tree that
> are intended to be used as data structures and expose clear data
> structure APIs.
> 
> Yes, vmalloc should have versioning, but that does not mean it must move
> to different files.

Core KHO preserves contiguous ranges of unmovable physical memory, that 
is it. Preserving physical addresses and folios falls into that 
category, and everything else is built on top of it.

The underlying implementation is where the ABI contract is defined. 
Unlike kho_preserve_pages(), which just tracks raw physical ranges, 
kho_preserve_vmalloc() must serialize non-contiguous virtual memory. To 
do this, it passes metadata kho_vmalloc, kho_vmalloc_hdr, linked list of 
PFN arrays.

I do not understand why you are so against the modularization of 
higher-level implementations on top of KHO. Moving them to dedicated 
files makes the codebase cleaner and easier to maintain. For instance, 
at some point we might support sparse or partially filled vmalloc areas 
where VA size > PA size, or areas that have holes.

Keeping all of that in a single KHO file is the wrong approach and goes 
against how other logically separated subsystems in Linux are organized 
(e.g., mm/vmap.c, mm/vmalloc.c, etc.). Yes, there are some messier 
places in the kernel as well, but keeping this in its own dedicated 
kho_vmalloc.c file makes complete sense to me.

> 
> And, btw, moving KHOSER_PTR() infra along with vmalloc is wrong. It was
> my oversight that I didn't insist on using it for most of the
> serializeable pointers instead of open coded
> virt_to_phys()/phys_to_virt(). We need to fix it.

The only reason it was moved to vmalloc.h in this series is because kho 
vmalloc is currently the only user of DECLARE_KHOSER_PTR / 
KHOSER_STORE_PTR in the tree. I can move it to the newly introduced 
compat.h to keep it in a shared place.

However, overall enforcing the use of KHOSER is unrelated to this work. 
I have my own thoughts on this, and perhaps with proper versioning, 
using KHOSER_PTR everywhere would be appropriate, but let's keep that as 
a separate work.

> > If we change any of the vmalloc serialized structures (like kho_vmalloc,
> > kho_vmalloc_chunk, or kho_vmalloc_hdr), then vmalloc won't work and
> > compatibility will break.
> > 
> > Core KHO does not need vmalloc; nothing in kexec_handover.c uses it.
> > 
> > Instead, vmalloc has external customers:
> > - memfd (uses it to preserve serialized folio metadata)
> > - KHO test suite in lib/test_kho.c (uses it to preserve physical address arrays)
> 
> Following this logic, kho_presrve_folio() should be moved out because
> it's not used by KHO but has external customers. And radix tree should
> forever remain in kexec_handover.c because KHO uses it ;-)
> 
> > > Let's minimize the churn where possible for the sake of git blame and
> > > backports.
> > 
> > It is much better to do the right cleanups now while KHO is young. Once more
> > subsystems are added, this refactoring will be twice as hard. Modularizing the
> > code now guarantees a simpler, safer, and scalable design. Placing each data
> > structure in its own file gives us code that is easier to maintain, review, and
> > less prone to bugs.
> 
> dependencies
> > > that justify small headers for each two functions and netiher
> > > linux/kexec_handover.h nor linux/kho/abi/kexec_handover.h are that long
> > > to start splitting them.
> > 
> > External users only need to include the headers they actually use. For
> > example, LUO shouldn't have to pull vmalloc or radix tree KHO
> > declarations, and memfd does not need block.
> > 
> > From a maintenance point of view, it is much easier to catch ABI
> > changes when the file with the appropriate version has been changed,
> > and most likely the version of that file should be updated. If a single
> > header contains compatibility versions for several different data
> > structures, it is easier to miss the correct version update.
> 
> No matter in what files the definition lives, someone can forget to
> update version and we may miss it during review.
> 
> Would be better to spend this time and energy to add kho-specific prompt
> to LLM review to catch such issues ;-)

LLMs are great, and we should absolutely rely on them. Spending time 
defining LLM rules and helps in the long term, but none of that is an 
excuse for keeping the codebase messier than necessary. Having the 
codebase logically separated and modularized is still the right 
approach; ease of human review should always be prioritized, even with 
LLM assistants.

Localized context is incredibly powerful for preventing human error. 
When a developer modifies a structure in vmalloc.h, the corresponding 
compatibility version is right there in front of them in the same file, 
making it far more obvious that a version bump is required. In a 
monolithic header, it's easy to modify a structure on line 100 and 
completely overlook a global version defined on line 10.

Modular files drastically reduce noise in git history and diffs. If a 
reviewer sees a patch touching include/linux/kho/abi/vmalloc.h, it is an 
immediate, high-signal flag that a specific ABI is being altered.

Even LLMs behave much better when the context window is smaller. An LLM 
can read a focused file and understand the interactions much more 
accurately, compared to polluting its context with a unrelated 
subsystems.

> > Since we are splitting the source files (like kho_radix.c and
> > kho_vmalloc.c), the headers should logically follow the same
> > modularity.
>  
> They could. Doesn't mean they have to.

This is not a logical argument, nothing is have to... Keeping headers 
aligned 1:1 with their implementation files provides clean 
encapsulation, prevents transitive dependency pollution, and ensures 
that ABI changes are tightly localized.

> > > I agree that we should decouple versioning of these components from the
> > > global KHO versioning.
> > > Can't say I agree with the way you propose to do it.
> > > 
> > > I don't like that each user of a KHO component should include that
> > > component version in its own version string (or whatever it may become
> > > later).
> > > 
> > > It requires ABI headers update each time a user decides to add a new
> > > data structure and worse when there is a change to that data structure.
> > > It creates coupling of the data structure user with its particular
> > > version and just looks ugly IMHO.
> > 
> > It is actually the opposite.
> > 
> > If a user adds a new data structure, that new data structure will have
> > its own compatibility version. Instead of the current approach where
> > the global version string needs to be updated, only the new version
> > string would be added.
> > 
> > Also, if someone updates their code to use the new data structure, their
> > compatibility string is going to be updated anyway, as part of using
> > the data structure requires including the dependency in their
> > compatibility.
> 
> Sorry I wasn't clear. I agree that kho_vmalloc, block and radix tree
> should have their own versioning rather than rely on global KHO version.
> 
> What I don't like in your proposal is mixing versioning of a component
> with its dependencies.
> 
> I think that versioning should be completely local to each component.
> LUO should not care about kho_block "on wire" layout. This should be
> encapsulated in kho_block.

That is a fair point.

As I mentioned in my previous reply, we can definitely look into making 
the version checking more modular. For example, each component could 
implement a standard compatibility-checking interface.

These checks could run early in boot to determine whether each component 
is capable of accepting the incoming preserved data format.

Whenever the component is later used by LUO, memfd, etc., we can query 
that cached status. This achieves four key benefits:

1. It avoids delaying the compatibility check to the actual time of data 
retrieval, which is too late to safely abort.

2. It prevents a local incompatibility from triggering a global kernel 
panic, allowing us to handle failures gracefully for just that specific 
component or session.

3. It keeps the local version local, as you suggested, so it is checked 
only by the consumers of that specific component.

4. It provides a clean path for backward compatibility, as components 
can individually decide whether they understand the incoming data 
format.

> > Backward compatibility is not in scope at the moment, but we can make
> > the version parsing more granular in the future.

100% Agreed.

> > Instead of a simple strncmp(), we can introduce a standard callback
> > interface for data structures. Each data structure implementation would
> > implement this interface, and we would pass the parsed version string
> > to the data-structure-specific version check.
> 
> Backward compatibility will be in scope sooner or later and string
> parsing is surely not the way to deal with multiple versions.
> 
> How do you suggest to represent support for multiple versions?
> "luo-v2;luo-v3;block-v2;block-v3;block-v4"?
> 
> > > Or, say, we add support to kmalloc() and use it in kho_block.
> > > Then we'd have to add kmalloc() versioning to all kho_block users, right?
> > 
> > I was thinking about this. Since we don't have examples of data
> > structures depending on each other right now, I simply made sure
> > there are no duplicates in the compatibility strings.
> > 
> > If data structures have interdependencies in the future, we can easily
> > remove this uniqueness restriction. The users of block will still
> > include the block compatibility string (which automatically includes
> > kmalloc), and if user also depends on kmalloc, they will include it
> > as well.
> > 
> > > I think the versioning of each component should be handled by ->restore()
> > > of that component. If it sees an incompatible version in the preserved
> > > data, it returns an error. The versions can be stored e.g. in the base KHO
> > > fdt.
> > 
> > Hm, I think, checking compatibility inside ->restore() of each component may be
> > too late in the boot sequence.
> >
> > By checking the composite compatibility strings upfront (before invoking
> > the actual restore/retrieve callbacks), we can guarantee that the entire
> > state configuration is fully compatible. If any mismatch is found, we
> > can cleanly abort the live update.
> 
> If a ->restore() returned an error (for any reason) we anyway need to
> reboot, don't we? 
> 
> What do we do if memfd discovered incompatibility, but, say hugetlb
> global state was already restored?
> 
> If you really want to run the compatibility check upfront, we need a
> mechanism for that. And that should probably happen even before
> kho_mem_init().
> 
> > Additionally, keeping the versioning managed via composite strings on the
> > serialized data and registered handlers keeps the KHO core completely
> > decoupled from individual component ABIs, avoiding the need to bloat the
> > base KHO FDT with subsystem-specific versions.
> 
> Actually FDT "compatible" handles versioning nicer than composite strings
> You can have
> 
> 	compatible="kho-v4", "vmalloc-v1", "radix-v1", "block-v2";
> 
> and check fdt_node_check_compatible("vmalloc-v1") for vmalloc and
> fdt_node_check_compatible("block-v2") for block.

That is actually very similar to what I am proposing—individual version 
tokens (which in my current series are concatenated into a composite 
compatibility string separated by ';').

But let's not get too fixated on the composite string formatting. I 
actually really like what you are proposing: using integers for versions 
and having each registered component carry its own "NAME" and version 
number in the KHO FDT.

> And we wouldn't need to reimplement string parsing ;-)
> 
> But yeah, I do see value of making components versioning and KHO global
> versioning independent. I just don't like composite strings and I don't
> like mixing versioning with dependencies.
> 
> Since we are moving from FDT for the most things, version should become
> a number rather than a string and version compatibility should be

AFAIK, for everything but KHO itself is going to be FDT free. I would 
like to be strict about that going forward :-)

> independently verified by each component.
> Then dependencies between components will remain at API level rather
> than brought into the ABI.
> 
> If you think ->restore() is too late for compatibility check, we should
> work on a mechanism for upfront compatibility verification.

+1.

Pasha

^ permalink raw reply

* Re: [PATCH v16 00/10] arm64/riscv: Add support for crashkernel CMA reservation
From: Andrew Morton @ 2026-06-08 16:10 UTC (permalink / raw)
  To: Jinjie Ruan
  Cc: corbet, skhan, catalin.marinas, will, chenhuacai, kernel, maddy,
	mpe, npiggin, chleroy, pjw, palmer, aou, alex, tglx, mingo, bp,
	dave.hansen, hpa, robh, saravanak, bhe, rppt, pasha.tatashin,
	pratyush, ruirui.yang, rdunlap, peterz, feng.tang, dapeng1.mi,
	kees, elver, kuba, lirongqing, ebiggers, paulmck, leitao, coxu,
	Liam.Howlett, ryan.roberts, osandov, jbohac, cfsworks,
	tangyouling, sourabhjain, ritesh.list, adityag, liaoyuanhong,
	seanjc, fuqiang.wang, ardb, chenjiahao16, guoren, x86, linux-doc,
	linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
	linux-riscv, devicetree, kexec
In-Reply-To: <20260608073459.3119290-1-ruanjinjie@huawei.com>

On Mon, 8 Jun 2026 15:34:49 +0800 Jinjie Ruan <ruanjinjie@huawei.com> wrote:

> The crash memory allocation, and the exclude of crashk_res, crashk_low_res
> and crashk_cma memory are almost identical across different architectures,
> This patch set handle them in crash core in a general way, which eliminate
> a lot of duplication code.
> 
> And add support for crashkernel CMA reservation for arm64 and riscv.

fyi, AI review might have found a bunch of issues in arch-specific
code, all of them pre-existing.

	https://sashiko.dev/#/patchset/20260608073459.3119290-1-ruanjinjie@huawei.com

^ permalink raw reply

* Re: [PATCH RFC 4/4] Documentation/kernel-parameters: add/update printk_delay/boot_delay
From: Petr Mladek @ 2026-06-08 15:26 UTC (permalink / raw)
  To: Andrew Murray
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Steven Rostedt, John Ogness, Sergey Senozhatsky, Andrew Morton,
	Sebastian Andrzej Siewior, Clark Williams, Randy Dunlap,
	Linus Torvalds, linux-doc, linux-kernel, linux-arm-kernel,
	linux-rpi-kernel, linux-rt-devel
In-Reply-To: <20260601-deprecate_boot_delay-v1-4-c34c187142a6@thegoodpenguin.co.uk>

On Mon 2026-06-01 00:17:40, Andrew Murray wrote:
> boot_delay has been deprecated in favour of an extended printk_delay,
> let's update kernel-parameters to reflect the addition of printk_delay
> and the deprecation of boot_delay.
> 
> Signed-off-by: Andrew Murray <amurray@thegoodpenguin.co.uk>

LGTM:

Reviewed-by: Petr Mladek <pmladek@suse.com>

Best Regards,
Petr

^ permalink raw reply

* Re: [PATCH RFC 3/4] printk: nbcon: move printk_delay to console emiting code
From: Petr Mladek @ 2026-06-08 15:25 UTC (permalink / raw)
  To: Andrew Murray
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Steven Rostedt, John Ogness, Sergey Senozhatsky, Andrew Morton,
	Sebastian Andrzej Siewior, Clark Williams, Randy Dunlap,
	Linus Torvalds, linux-doc, linux-kernel, linux-arm-kernel,
	linux-rpi-kernel, linux-rt-devel
In-Reply-To: <20260601-deprecate_boot_delay-v1-3-c34c187142a6@thegoodpenguin.co.uk>

On Mon 2026-06-01 00:17:39, Andrew Murray wrote:
> The printk_delay and boot_delay features are helpful for debugging
> as kernel output can be slowed down during boot allowing messages to
> be seen before scrolling off the screen, or to correlate timing between
> some physical event and console output.
> 
> However, since the introduction of nbcon and the legacy printer thread
> for PREEMPT_RT kernels, printk records are now emited to the console
> asynchronously to the caller of printk. Thus, any printk delay added by
> boot_delay/printk_delay continues to slow down the calling process but
> may not have any impact to the rate in which records are emited to the
> console.
> 
> Let's address this by moving the printk delay from the calling code
> to the console emiting code instead. Whilst this ensures that delays
> are still observed (especially for slower consoles), it doesn't improve
> the use-case of using boot_delay/printk_delay to correlate timings
> between physical events and console output.
> 
> --- a/include/linux/printk.h
> +++ b/include/linux/printk.h

The declaration is needed just inside kernel/printk/ directory.
It should better be done via kernel/printk/internal.h

> @@ -209,6 +209,7 @@ extern bool nbcon_device_try_acquire(struct console *con);
>  extern void nbcon_device_release(struct console *con);
>  void nbcon_atomic_flush_unsafe(void);
>  bool pr_flush(int timeout_ms, bool reset_on_progress);
> +void printk_delay(bool use_atomic);
>  #else
>  static inline __printf(1, 0)
>  int vprintk(const char *s, va_list args)
> @@ -326,6 +327,9 @@ static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
>  {
>  	return true;
>  }
> +static inline void printk_delay(bool use_atomic)
> +{
> +}
>  
>  #endif
>  
> diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
> index d7044a7a214bdd4537a5e20d876d99bc3ffe8b3a..a507a2fed5bf4366e24330f763b842a698ecf6f7 100644
> --- a/kernel/printk/nbcon.c
> +++ b/kernel/printk/nbcon.c
> @@ -1267,11 +1267,16 @@ static int nbcon_kthread_func(void *__console)
>  
>  		con_flags = console_srcu_read_flags(con);
>  
> +		wctxt.len = 0;
> +
>  		if (console_is_usable(con, con_flags, false))
>  			backlog = nbcon_emit_one(&wctxt, false);
>  
>  		console_srcu_read_unlock(cookie);
>  
> +		if (backlog && wctxt.len > 0)

Heh, this is tricky. It might probably work but it is not guarantted
by design.

The "backlog" name is a bit misleading. The value is basically
wctxt.ctxt.backlog. The real meaning is that printk_get_next_message()
was able to read a message. It means that there _was_ a backlog.
But it is not clear whether there are still pending messages or not.

Also it is not clear that whether the message was pushed to the
console or not. It might have been supressed in which case
(wctxt.len == 0). But it might also be emitted only partially
when a higher priority context took over the console context
ownership.

I would prefer to explicitely set some flag when
nbcon_emit_next_record() really called con->write*().
See below.

> +			printk_delay(false);
> +
>  		cond_resched();
>  
>  	} while (backlog);
> @@ -1525,6 +1530,8 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover,
>  	}
>  
>  	progress = nbcon_emit_one(&wctxt, use_atomic);
> +	if (progress && wctxt.len > 0)

Same here.

> +		printk_delay(use_atomic);
>  
>  	if (use_atomic) {
>  		start_critical_timings();
> @@ -1584,6 +1591,8 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
>  			if (!nbcon_context_try_acquire(ctxt, false))
>  				return -EPERM;
>  
> +			wctxt.len = 0;
> +
>  			/*
>  			 * nbcon_emit_next_record() returns false when
>  			 * the console was handed over or taken over.
> @@ -1595,7 +1604,9 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
>  			nbcon_context_release(ctxt);
>  		}
>  
> -		if (!ctxt->backlog) {
> +		if (ctxt->backlog && wctxt.len > 0) {
> +			printk_delay(true);
> +		} else {

This changes the semantic. The original code call this when
no message was read. The new code would call this path also
when the output was suppressed. It would probably work.
But still.

>  			/* Are there reserved but not yet finalized records? */
>  			if (nbcon_seq_read(con) < stop_seq)
>  				err = -ENOENT;


As mentioned above, I would add a flag which would be set when
con->write*() was called.

It modifies the type of unsafe_takeover in struct nbcon_write_context.
But it actually makes it more compatible with struct nbcon_state.

My proposal (on top of this patch):

diff --git a/include/linux/console.h b/include/linux/console.h
index 5520e4477ad7..5a86942e55ef 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -290,6 +290,7 @@ struct nbcon_context {
  * @outbuf:		Pointer to the text buffer for output
  * @len:		Length to write
  * @unsafe_takeover:	If a hostile takeover in an unsafe state has occurred
+ * @emitted:		The write context tried to emit the message. Might be incomplete.
  * @cpu:		CPU on which the message was generated
  * @pid:		PID of the task that generated the message
  * @comm:		Name of the task that generated the message
@@ -298,7 +299,8 @@ struct nbcon_write_context {
 	struct nbcon_context	__private ctxt;
 	char			*outbuf;
 	unsigned int		len;
-	bool			unsafe_takeover;
+	unsigned char		unsafe_takeover	:  1;
+	unsigned char		emitted : 1
 #ifdef CONFIG_PRINTK_EXECUTION_CTX
 	int			cpu;
 	pid_t			pid;
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index a507a2fed5bf..060534becefc 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -1069,6 +1069,9 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt, bool use_a
 	else
 		con->write_thread(con, wctxt);
 
+	/* Tried to emit something. Might be incomplete. */
+	wctxt.emitted = 1;
+
 	if (!wctxt->outbuf) {
 		/*
 		 * Ownership was lost and reacquired by the driver. Handle it
@@ -1267,14 +1270,14 @@ static int nbcon_kthread_func(void *__console)
 
 		con_flags = console_srcu_read_flags(con);
 
-		wctxt.len = 0;
+		wctxt.emitted = 0;
 
 		if (console_is_usable(con, con_flags, false))
 			backlog = nbcon_emit_one(&wctxt, false);
 
 		console_srcu_read_unlock(cookie);
 
-		if (backlog && wctxt.len > 0)
+		if (wctxt.emitted)
 			printk_delay(false);
 
 		cond_resched();
@@ -1530,7 +1533,7 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover,
 	}
 
 	progress = nbcon_emit_one(&wctxt, use_atomic);
-	if (progress && wctxt.len > 0)
+	if (wctxt.emitted)
 		printk_delay(use_atomic);
 
 	if (use_atomic) {
@@ -1591,7 +1594,7 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
 			if (!nbcon_context_try_acquire(ctxt, false))
 				return -EPERM;
 
-			wctxt.len = 0;
+			wctxt.emitted = 0;
 
 			/*
 			 * nbcon_emit_next_record() returns false when
@@ -1604,9 +1607,10 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
 			nbcon_context_release(ctxt);
 		}
 
-		if (ctxt->backlog && wctxt.len > 0) {
+		if (wctxt.emitted)
 			printk_delay(true);
-		} else {
+
+		if (!ctxt->backlog) {
 			/* Are there reserved but not yet finalized records? */
 			if (nbcon_seq_read(con) < stop_seq)
 				err = -ENOENT;

^ permalink raw reply related

* RE: [Intel-wired-lan] [PATCH iwl-next v8 08/15] idpf: refactor idpf to use libie_pci APIs
From: Loktionov, Aleksandr @ 2026-06-08 15:16 UTC (permalink / raw)
  To: Zaremba, Larysa, intel-wired-lan@lists.osuosl.org,
	Nguyen, Anthony L
  Cc: Lobakin, Aleksander, Samudrala, Sridhar, Michal Swiatkowski,
	Zaremba, Larysa, Fijalkowski, Maciej, Tantilov, Emil S,
	Chittim, Madhu, Hay, Joshua A, Keller, Jacob E,
	Shanmugam, Jayaprakash, Jiri Pirko, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
	Richard Cochran, Kitszel, Przemyslaw, Andrew Lunn,
	netdev@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, Salin, Samuel
In-Reply-To: <20260608144127.2751230-9-larysa.zaremba@intel.com>



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Larysa Zaremba
> Sent: Monday, June 8, 2026 4:41 PM
> To: intel-wired-lan@lists.osuosl.org; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>
> Cc: Lobakin, Aleksander <aleksander.lobakin@intel.com>; Samudrala,
> Sridhar <sridhar.samudrala@intel.com>; Michal Swiatkowski
> <michal.swiatkowski@linux.intel.com>; Zaremba, Larysa
> <larysa.zaremba@intel.com>; Fijalkowski, Maciej
> <maciej.fijalkowski@intel.com>; Tantilov, Emil S
> <emil.s.tantilov@intel.com>; Chittim, Madhu <madhu.chittim@intel.com>;
> Hay, Joshua A <joshua.a.hay@intel.com>; Keller, Jacob E
> <jacob.e.keller@intel.com>; Shanmugam, Jayaprakash
> <jayaprakash.shanmugam@intel.com>; Jiri Pirko <jiri@resnulli.us>;
> David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>; Simon Horman <horms@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Richard Cochran <richardcochran@gmail.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; netdev@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; Salin, Samuel
> <samuel.salin@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next v8 08/15] idpf: refactor
> idpf to use libie_pci APIs
> 
> From: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> 
> Use libie_pci init and MMIO APIs where possible, struct idpf_hw cannot
> be deleted for now as it also houses control queues that will be
> refactored later. Use libie_cp header for libie_ctlq_ctx that contains
> mmio info from the start in order to not increase the diff later.
> 
> Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
> Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
> Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> Tested-by: Samuel Salin <Samuel.salin@intel.com>
> Co-developed-by: Larysa Zaremba <larysa.zaremba@intel.com>
> Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
> ---
>  drivers/net/ethernet/intel/idpf/Kconfig       |   1 +
>  drivers/net/ethernet/intel/idpf/idpf.h        |  70 +-------
>  .../net/ethernet/intel/idpf/idpf_controlq.c   |  26 ++-
>  .../net/ethernet/intel/idpf/idpf_controlq.h   |   2 -
>  drivers/net/ethernet/intel/idpf/idpf_dev.c    |  61 ++++---
>  drivers/net/ethernet/intel/idpf/idpf_idc.c    |  38 ++--
>  drivers/net/ethernet/intel/idpf/idpf_lib.c    |   7 +-
>  drivers/net/ethernet/intel/idpf/idpf_main.c   | 114 ++++++------
>  drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  57 +++---
>  .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 169 +++++++++--------
> -
>  .../ethernet/intel/idpf/idpf_virtchnl_ptp.c   |  58 +++---
>  11 files changed, 288 insertions(+), 315 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/idpf/Kconfig
> b/drivers/net/ethernet/intel/idpf/Kconfig
> index adab2154125b..586df3a4afe9 100644
> --- a/drivers/net/ethernet/intel/idpf/Kconfig
> +++ b/drivers/net/ethernet/intel/idpf/Kconfig
> @@ -6,6 +6,7 @@ config IDPF
>  	depends on PCI_MSI
>  	depends on PTP_1588_CLOCK_OPTIONAL
>  	select DIMLIB

...

> +56,14 @@ static void idpf_ctlq_reg_init(struct idpf_adapter *adapter,
>   */
>  static void idpf_mb_intr_reg_init(struct idpf_adapter *adapter)  {
> +	struct libie_mmio_info *mmio = &adapter->ctlq_ctx.mmio_info;
>  	struct idpf_intr_reg *intr = &adapter->mb_vector.intr_reg;
>  	u32 dyn_ctl = le32_to_cpu(adapter->caps.mailbox_dyn_ctl);
> 
> -	intr->dyn_ctl = idpf_get_reg_addr(adapter, dyn_ctl);
> +	intr->dyn_ctl = libie_pci_get_mmio_addr(mmio, dyn_ctl);
Probable NULL dereference: libie_pci_get_mmio_addr(mmio, dyn_ctl) can return NULL.
It looks like no checks were made.

>  	intr->dyn_ctl_intena_m = PF_GLINT_DYN_CTL_INTENA_M;
>  	intr->dyn_ctl_itridx_m = PF_GLINT_DYN_CTL_ITR_INDX_M;

...

> 
>  	return 0;
>  }
> --
> 2.47.0


^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next v8 07/15] idpf: remove unused code for getting RSS info from device
From: Loktionov, Aleksandr @ 2026-06-08 15:10 UTC (permalink / raw)
  To: Zaremba, Larysa, intel-wired-lan@lists.osuosl.org,
	Nguyen, Anthony L
  Cc: Lobakin, Aleksander, Samudrala, Sridhar, Michal Swiatkowski,
	Zaremba, Larysa, Fijalkowski, Maciej, Tantilov, Emil S,
	Chittim, Madhu, Hay, Joshua A, Keller, Jacob E,
	Shanmugam, Jayaprakash, Jiri Pirko, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
	Richard Cochran, Kitszel, Przemyslaw, Andrew Lunn,
	netdev@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <20260608144127.2751230-8-larysa.zaremba@intel.com>



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Larysa Zaremba
> Sent: Monday, June 8, 2026 4:41 PM
> To: intel-wired-lan@lists.osuosl.org; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>
> Cc: Lobakin, Aleksander <aleksander.lobakin@intel.com>; Samudrala,
> Sridhar <sridhar.samudrala@intel.com>; Michal Swiatkowski
> <michal.swiatkowski@linux.intel.com>; Zaremba, Larysa
> <larysa.zaremba@intel.com>; Fijalkowski, Maciej
> <maciej.fijalkowski@intel.com>; Tantilov, Emil S
> <emil.s.tantilov@intel.com>; Chittim, Madhu <madhu.chittim@intel.com>;
> Hay, Joshua A <joshua.a.hay@intel.com>; Keller, Jacob E
> <jacob.e.keller@intel.com>; Shanmugam, Jayaprakash
> <jayaprakash.shanmugam@intel.com>; Jiri Pirko <jiri@resnulli.us>;
> David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>; Simon Horman <horms@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Richard Cochran <richardcochran@gmail.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; netdev@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [Intel-wired-lan] [PATCH iwl-next v8 07/15] idpf: remove
> unused code for getting RSS info from device
> 
> idpf_send_get_set_rss_lut_msg() and idpf_send_get_set_rss_key_msg() do
> not handle the get=true path properly. Response validation is
> insufficient, memcpy size is wrong, LE-to-CPU conversion is missing.
> Fortunately, those functions are never used with get=true. Given how
> broken this dead code is, it is unlikely to be useful in the future.
> 
> Rename idpf_send_get_set_rss_lut_msg() to idpf_send_set_rss_lut_msg(),
> idpf_send_get_set_rss_key_msg() to idpf_send_set_rss_key_msg(), remove
> the get parameter and remove all get=true cases from the function.
> 
> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
> Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
> ---
>  drivers/net/ethernet/intel/idpf/idpf_txrx.c   |   4 +-
>  .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 107 +++--------------
> -
>  .../net/ethernet/intel/idpf/idpf_virtchnl.h   |  10 +-
>  3 files changed, 22 insertions(+), 99 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> index f6b3b15364ff..d744db0efd3f 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> @@ -4679,11 +4679,11 @@ int idpf_config_rss(struct idpf_vport *vport,
> struct idpf_rss_data *rss_data)
>  	u32 vport_id = vport->vport_id;
>  	int err;
> 

...

> vport_id);
>  void idpf_vc_xn_shutdown(struct idpf_vc_xn_manager *vcxn_mngr);  int
> idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
>  			       u8 *send_msg, u16 msg_size,
> --
> 2.47.0


Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next v8 06/15] idpf: remove 'vport_params_reqd' field
From: Loktionov, Aleksandr @ 2026-06-08 15:09 UTC (permalink / raw)
  To: Zaremba, Larysa, intel-wired-lan@lists.osuosl.org,
	Nguyen, Anthony L
  Cc: Lobakin, Aleksander, Samudrala, Sridhar, Michal Swiatkowski,
	Zaremba, Larysa, Fijalkowski, Maciej, Tantilov, Emil S,
	Chittim, Madhu, Hay, Joshua A, Keller, Jacob E,
	Shanmugam, Jayaprakash, Jiri Pirko, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
	Richard Cochran, Kitszel, Przemyslaw, Andrew Lunn,
	netdev@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, Salin, Samuel
In-Reply-To: <20260608144127.2751230-7-larysa.zaremba@intel.com>



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Larysa Zaremba
> Sent: Monday, June 8, 2026 4:41 PM
> To: intel-wired-lan@lists.osuosl.org; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>
> Cc: Lobakin, Aleksander <aleksander.lobakin@intel.com>; Samudrala,
> Sridhar <sridhar.samudrala@intel.com>; Michal Swiatkowski
> <michal.swiatkowski@linux.intel.com>; Zaremba, Larysa
> <larysa.zaremba@intel.com>; Fijalkowski, Maciej
> <maciej.fijalkowski@intel.com>; Tantilov, Emil S
> <emil.s.tantilov@intel.com>; Chittim, Madhu <madhu.chittim@intel.com>;
> Hay, Joshua A <joshua.a.hay@intel.com>; Keller, Jacob E
> <jacob.e.keller@intel.com>; Shanmugam, Jayaprakash
> <jayaprakash.shanmugam@intel.com>; Jiri Pirko <jiri@resnulli.us>;
> David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>; Simon Horman <horms@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Richard Cochran <richardcochran@gmail.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; netdev@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; Salin, Samuel
> <samuel.salin@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next v8 06/15] idpf: remove
> 'vport_params_reqd' field
> 
> From: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> 
> While sending a create vport message to the device control plane, a
> create vport virtchnl message is prepared with all the required info
> to initialize the vport. This info is stored in the adapter struct but
> never used thereafter. So, remove the said field.
> 
> Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
> Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
> Tested-by: Samuel Salin <Samuel.salin@intel.com>
> Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
> ---
>  drivers/net/ethernet/intel/idpf/idpf.h        |  2 --
>  drivers/net/ethernet/intel/idpf/idpf_lib.c    |  2 --
>  .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 30 +++++++-----------
> -
>  3 files changed, 10 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/idpf/idpf.h
> b/drivers/net/ethernet/intel/idpf/idpf.h
> index 984944bab28b..c5e47e79a641 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf.h
> +++ b/drivers/net/ethernet/intel/idpf/idpf.h
> @@ -638,7 +638,6 @@ struct idpf_vc_xn_manager;
>   * @avail_queues: Device given queue limits
>   * @vports: Array to store vports created by the driver
>   * @netdevs: Associated Vport netdevs

...

> 
>  	adapter->vport_ids = kcalloc(num_max_vports, sizeof(u32),
> GFP_KERNEL);
>  	if (!adapter->vport_ids)
> --
> 2.47.0


Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next v8 03/15] libeth: allow to create fill queues without NAPI
From: Loktionov, Aleksandr @ 2026-06-08 15:09 UTC (permalink / raw)
  To: Zaremba, Larysa, intel-wired-lan@lists.osuosl.org,
	Nguyen, Anthony L
  Cc: Lobakin, Aleksander, Samudrala, Sridhar, Michal Swiatkowski,
	Zaremba, Larysa, Fijalkowski, Maciej, Tantilov, Emil S,
	Chittim, Madhu, Hay, Joshua A, Keller, Jacob E,
	Shanmugam, Jayaprakash, Jiri Pirko, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
	Richard Cochran, Kitszel, Przemyslaw, Andrew Lunn,
	netdev@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, R, Bharath, Salin, Samuel
In-Reply-To: <20260608144127.2751230-4-larysa.zaremba@intel.com>



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Larysa Zaremba
> Sent: Monday, June 8, 2026 4:41 PM
> To: intel-wired-lan@lists.osuosl.org; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>
> Cc: Lobakin, Aleksander <aleksander.lobakin@intel.com>; Samudrala,
> Sridhar <sridhar.samudrala@intel.com>; Michal Swiatkowski
> <michal.swiatkowski@linux.intel.com>; Zaremba, Larysa
> <larysa.zaremba@intel.com>; Fijalkowski, Maciej
> <maciej.fijalkowski@intel.com>; Tantilov, Emil S
> <emil.s.tantilov@intel.com>; Chittim, Madhu <madhu.chittim@intel.com>;
> Hay, Joshua A <joshua.a.hay@intel.com>; Keller, Jacob E
> <jacob.e.keller@intel.com>; Shanmugam, Jayaprakash
> <jayaprakash.shanmugam@intel.com>; Jiri Pirko <jiri@resnulli.us>;
> David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>; Simon Horman <horms@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Richard Cochran <richardcochran@gmail.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; netdev@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; R, Bharath
> <bharath.r@intel.com>; Salin, Samuel <samuel.salin@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next v8 03/15] libeth: allow to
> create fill queues without NAPI
> 
> From: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> 
> Control queues can utilize libeth_rx fill queues, despite working
> outside of NAPI context. The only problem is standard fill queues
> requiring NAPI that provides them with the device pointer.
> 
> Introduce a way to provide the device directly without using NAPI.
> 
> Suggested-by: Alexander Lobakin <aleksander.lobakin@intel.com>
> Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
> Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> Tested-by: Bharath R <bharath.r@intel.com>
> Tested-by: Samuel Salin <Samuel.salin@intel.com>
> Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
> ---
>  drivers/net/ethernet/intel/libeth/rx.c | 12 ++++++++----
>  include/net/libeth/rx.h                |  4 +++-
>  2 files changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/libeth/rx.c
> b/drivers/net/ethernet/intel/libeth/rx.c
> index 62521a1f4ec9..0c1a565a1b3a 100644
> --- a/drivers/net/ethernet/intel/libeth/rx.c
> +++ b/drivers/net/ethernet/intel/libeth/rx.c
> @@ -145,25 +145,29 @@ static bool libeth_rx_page_pool_params_zc(struct
> libeth_fq *fq,
>  /**
>   * libeth_rx_fq_create - create a PP with the default libeth settings
>   * @fq: buffer queue struct to fill
> - * @napi: &napi_struct covering this PP (no usage outside its poll
> loops)
> + * @napi_dev: &napi_struct for NAPI (data) queues, &device for others
>   *
>   * Return: %0 on success, -%errno on failure.
>   */
> -int libeth_rx_fq_create(struct libeth_fq *fq, struct napi_struct
> *napi)
> +int libeth_rx_fq_create(struct libeth_fq *fq, void *napi_dev)
>  {
> +	struct napi_struct *napi = fq->no_napi ? NULL : napi_dev;
>  	struct page_pool_params pp = {
>  		.flags		= PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
>  		.order		= LIBETH_RX_PAGE_ORDER,
>  		.pool_size	= fq->count,
>  		.nid		= fq->nid,
> -		.dev		= napi->dev->dev.parent,
> -		.netdev		= napi->dev,
> +		.dev		= napi ? napi->dev->dev.parent : napi_dev,
> +		.netdev		= napi ? napi->dev : NULL,
>  		.napi		= napi,
>  	};
>  	struct libeth_fqe *fqes;
>  	struct page_pool *pool;
>  	int ret;
> 
> +	if (!pp.netdev && fq->type == LIBETH_FQE_MTU)
> +		return -EINVAL;
> +
>  	pp.dma_dir = fq->xdp ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
> 
>  	if (!fq->hsplit)
> diff --git a/include/net/libeth/rx.h b/include/net/libeth/rx.h index
> 5d991404845e..0e736846c5e8 100644
> --- a/include/net/libeth/rx.h
> +++ b/include/net/libeth/rx.h
> @@ -69,6 +69,7 @@ enum libeth_fqe_type {
>   * @type: type of the buffers this queue has
>   * @hsplit: flag whether header split is enabled
>   * @xdp: flag indicating whether XDP is enabled
> + * @no_napi: the queue is not a data queue and does not have NAPI
>   * @buf_len: HW-writeable length per each buffer
>   * @nid: ID of the closest NUMA node with memory
>   */
> @@ -85,12 +86,13 @@ struct libeth_fq {
>  	enum libeth_fqe_type	type:2;
>  	bool			hsplit:1;
>  	bool			xdp:1;
> +	bool			no_napi:1;
> 
>  	u32			buf_len;
>  	int			nid;
>  };
> 
> -int libeth_rx_fq_create(struct libeth_fq *fq, struct napi_struct
> *napi);
> +int libeth_rx_fq_create(struct libeth_fq *fq, void *napi_dev);
>  void libeth_rx_fq_destroy(struct libeth_fq *fq);
> 
>  /**
> --
> 2.47.0

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>


^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next v8 01/15] virtchnl: move virtchnl and virtchnl2 headers to 'include/linux/net/intel'
From: Loktionov, Aleksandr @ 2026-06-08 15:08 UTC (permalink / raw)
  To: Zaremba, Larysa, intel-wired-lan@lists.osuosl.org,
	Nguyen, Anthony L
  Cc: Lobakin, Aleksander, Samudrala, Sridhar, Michal Swiatkowski,
	Zaremba, Larysa, Fijalkowski, Maciej, Tantilov, Emil S,
	Chittim, Madhu, Hay, Joshua A, Keller, Jacob E,
	Shanmugam, Jayaprakash, Jiri Pirko, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
	Richard Cochran, Kitszel, Przemyslaw, Andrew Lunn,
	netdev@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, Salin, Samuel
In-Reply-To: <20260608144127.2751230-2-larysa.zaremba@intel.com>



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Larysa Zaremba
> Sent: Monday, June 8, 2026 4:41 PM
> To: intel-wired-lan@lists.osuosl.org; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>
> Cc: Lobakin, Aleksander <aleksander.lobakin@intel.com>; Samudrala,
> Sridhar <sridhar.samudrala@intel.com>; Michal Swiatkowski
> <michal.swiatkowski@linux.intel.com>; Zaremba, Larysa
> <larysa.zaremba@intel.com>; Fijalkowski, Maciej
> <maciej.fijalkowski@intel.com>; Tantilov, Emil S
> <emil.s.tantilov@intel.com>; Chittim, Madhu <madhu.chittim@intel.com>;
> Hay, Joshua A <joshua.a.hay@intel.com>; Keller, Jacob E
> <jacob.e.keller@intel.com>; Shanmugam, Jayaprakash
> <jayaprakash.shanmugam@intel.com>; Jiri Pirko <jiri@resnulli.us>;
> David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>; Simon Horman <horms@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Richard Cochran <richardcochran@gmail.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; Andrew Lunn
> <andrew+netdev@lunn.ch>; netdev@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; Salin, Samuel
> <samuel.salin@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next v8 01/15] virtchnl: move
> virtchnl and virtchnl2 headers to 'include/linux/net/intel'
> 
> From: Victor Raj <victor.raj@intel.com>
> 
> virtchnl2 headers will be used by both idpf and ixd drivers, so they
> have to be moved to an include directory. On top of that, it would be
> useful to place all iavf headers together with other intel networking
> headers.
> 
> Move abovementioned intel header files into 'include/linux/net/intel'.
> 
> Suggested-by: Alexander Lobakin <aleksander.lobakin@intel.com>
> Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
> Signed-off-by: Victor Raj <victor.raj@intel.com>
> Tested-by: Samuel Salin <Samuel.salin@intel.com>
> Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
> ---
>  MAINTAINERS                                                   | 1 -
>  drivers/net/ethernet/intel/i40e/i40e.h                        | 2 +-
>  drivers/net/ethernet/intel/i40e/i40e_common.c                 | 2 +-
>  drivers/net/ethernet/intel/i40e/i40e_prototype.h              | 2 +-
>  drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h            | 2 +-
>  drivers/net/ethernet/intel/iavf/iavf.h                        | 2 +-
>  drivers/net/ethernet/intel/iavf/iavf_common.c                 | 2 +-
>  drivers/net/ethernet/intel/iavf/iavf_prototype.h              | 3 ++-
>  drivers/net/ethernet/intel/iavf/iavf_types.h                  | 4 +--
> -
>  drivers/net/ethernet/intel/ice/ice.h                          | 2 +-
>  drivers/net/ethernet/intel/ice/ice_common.h                   | 2 +-
>  drivers/net/ethernet/intel/ice/ice_vf_lib.h                   | 2 +-
>  drivers/net/ethernet/intel/ice/virt/virtchnl.h                | 2 +-
>  drivers/net/ethernet/intel/idpf/idpf.h                        | 2 +-
>  drivers/net/ethernet/intel/idpf/idpf_txrx.h                   | 2 +-
>  drivers/net/ethernet/intel/idpf/idpf_virtchnl.h               | 2 +-
>  include/linux/{avf => net/intel}/virtchnl.h                   | 0
>  .../intel/idpf => include/linux/net/intel}/virtchnl2.h        | 0
>  .../idpf => include/linux/net/intel}/virtchnl2_lan_desc.h     | 0
>  19 files changed, 16 insertions(+), 18 deletions(-)  rename
> include/linux/{avf => net/intel}/virtchnl.h (100%)  rename
> {drivers/net/ethernet/intel/idpf =>
> include/linux/net/intel}/virtchnl2.h (100%)  rename
> {drivers/net/ethernet/intel/idpf =>
> include/linux/net/intel}/virtchnl2_lan_desc.h (100%)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index eb8cdcc76324..952f09b40711 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12917,7 +12917,6 @@ T:	git
> git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git
>  F:	Documentation/networking/device_drivers/ethernet/intel/
>  F:	drivers/net/ethernet/intel/
>  F:	drivers/net/ethernet/intel/*/

...

> 
>  #define IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC	(60 * 1000)
>  #define IDPF_VC_XN_IDX_M		GENMASK(7, 0)
> diff --git a/include/linux/avf/virtchnl.h
> b/include/linux/net/intel/virtchnl.h
> similarity index 100%
> rename from include/linux/avf/virtchnl.h rename to
> include/linux/net/intel/virtchnl.h
> diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h
> b/include/linux/net/intel/virtchnl2.h
> similarity index 100%
> rename from drivers/net/ethernet/intel/idpf/virtchnl2.h
> rename to include/linux/net/intel/virtchnl2.h
> diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2_lan_desc.h
> b/include/linux/net/intel/virtchnl2_lan_desc.h
> similarity index 100%
> rename from drivers/net/ethernet/intel/idpf/virtchnl2_lan_desc.h
> rename to include/linux/net/intel/virtchnl2_lan_desc.h
> --
> 2.47.0


Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>

^ permalink raw reply

* Re: [RFC PATCH v1 00/13] exec: add spawn templates for repeated executable startup
From: Jann Horn @ 2026-06-08 15:02 UTC (permalink / raw)
  To: Mateusz Guzik, Christian Brauner
  Cc: Li Chen, Kees Cook, Alexander Viro, linux-fsdevel, linux-api,
	linux-kernel, linux-mm, linux-arch, linux-doc, linux-kselftest,
	x86, Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Jan Kara,
	Jonathan Corbet, Shuah Khan
In-Reply-To: <vealb52tv5suireenkke4lul2l3wbnaul2rp3ea545ly5wa5ty@yk3aksvp7skt>

On Thu, May 28, 2026 at 2:55 PM Mateusz Guzik <mjguzik@gmail.com> wrote:
> This problem is dear to my heart and I have been pondering it on and off
> for some time now. The entire fork + exec idiom is terrible and needs to
> be retired.

It seems to me like vfork+exec is a decent UAPI building block, on
which you can build nice-looking userspace APIs, though I agree that
this is not an ideal direct interface for application code.

> Additionally there is a known problem where transiently copied file
> descriptors on fork + exec cause a headache in multithreaded programs
> doing something like this in parallel. I only did cursory reading, it
> seems your patchset keeps the same problem in place.

I think we almost have UAPI that would let you avoid this issue?
You can use clone() with CLONE_FILES, then unshare the FD table with
close_range(3, UINT_MAX, CLOSE_RANGE_UNSHARE). That is not currently
implemented to be atomic with stuff that happens on other threads, but
if we changed that, and it doesn't provide a good way to carry some
FDs across, but it feels to me like this could be fixed with a variant
of close_range() that removes O_CLOEXEC FDs except ones listed in an
array.

> There are numerous impactful ways to speed up execs both in terms of
> single-threaded cost and their multicore scalability, most of which
> would be immediately usable by all programs without an opt-in. imo these
> needs to be exhausted before something like a "template" can be
> considered.

(I think probably a large part of this would be stuff that happens in
userspace, like dynamic linking.)

> Per the above, the primary win would stem from *NOT* messing with mm.

As you write below, I think we have that with CLONE_MM? The C function
vfork() is kind of a terrible API because of its returns-twice
behavior, but I think if process cloning with CLONE_VM|CLONE_VFORK was
wrapped by libc in a way similar to clone() (with the child executing
a separate handler function), or if it was used in the implementation
of some higher-level process-spawning API, it would be a perfectly
fine API?

Or am I misunderstanding what you mean by "messing with mm"?

> As in, whatever the interface, it needs to create an "empty" target
> process (for lack of a better term).
>
> In terms of userspace-visible APIs, a clean solution escapes me.

I think we already have relatively good API for this - you can use
clone() to create something that initially shares almost all the state
that a thread would, and then incrementally unshare resources and go
through execve().

^ permalink raw reply

* Re: [PATCH mm-unstable v19 11/14] mm/khugepaged: Introduce mTHP collapse support
From: David Hildenbrand (Arm) @ 2026-06-08 14:56 UTC (permalink / raw)
  To: Lance Yang, npache
  Cc: linux-doc, linux-kernel, linux-mm, linux-trace-kernel, aarcange,
	akpm, anshuman.khandual, apopple, baohua, baolin.wang, byungchul,
	catalin.marinas, cl, corbet, dave.hansen, dev.jain, gourry,
	hannes, hughd, jack, jackmanb, jannh, jglisse, joshua.hahnjy, kas,
	liam, ljs, mathieu.desnoyers, matthew.brost, mhiramat, mhocko,
	peterx, pfalcato, rakie.kim, raquini, rdunlap, richard.weiyang,
	rientjes, rostedt, rppt, ryan.roberts, shivankg, sunnanyong,
	surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
	vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
	zokeefe
In-Reply-To: <20260606102800.26940-1-lance.yang@linux.dev>

On 6/6/26 12:28, Lance Yang wrote:
> 
> On Fri, Jun 05, 2026 at 10:14:18AM -0600, Nico Pache wrote:
>> Enable khugepaged to collapse to mTHP orders. This patch implements the
>> main scanning logic using a bitmap to track occupied pages and the
>> algorithm to find optimal collapse sizes.
>>
>> Previous to this patch, PMD collapse had 3 main phases, a light weight
>> scanning phase (mmap_read_lock) that determines a potential PMD
>> collapse, an alloc phase (mmap unlocked), then finally heavier collapse
>> phase (mmap_write_lock).
>>
>> To enabled mTHP collapse we make the following changes:
>>
>> During PMD scan phase, track occupied pages in a bitmap. When mTHP
>> orders are enabled, we remove the restriction of max_ptes_none during the
>> scan phase to avoid missing potential mTHP collapse candidates. Once we
>> have scanned the full PMD range and updated the bitmap to track occupied
>> pages, we use the bitmap to find the optimal mTHP size.
>>
>> Implement mthp_collapse() to walk forward through the bitmap and
>> determine the best eligible order for each naturally-aligned region. The
>> algorithm starts at the beginning of the PMD range and, for each offset,
>> tries the highest order that fits the alignment. If the number of
>> occupied PTEs in that region satisfies the max_ptes_none threshold for
>> that order, a collapse is attempted. On failure, the order is
>> decremented and the same offset is retried at the next smaller size. Once
>> the smallest enabled order is exhausted (or a collapse succeeds), the
>> offset advances past the region just processed, and the next attempt
>> starts at the highest order permitted by the new offset's natural
>> alignment.
>>
>> The algorithm works as follows:
>>    1) set offset=0 and order=HPAGE_PMD_ORDER
>>    2) if the order is not enabled, go to step (5)
>>    3) count occupied PTEs in the (offset, order) range using
>>       bitmap_weight_from()
>>    4) if the count satisfies the max_ptes_none threshold, attempt
>>       collapse; on success, advance to step (6)
>>    5) if a smaller enabled order exists, decrement order and retry
>>       from step (2) at the same offset
>>    6) advance offset past the current region and compute the next
>>       order from the new offset's natural alignment via __ffs(offset),
>>       capped at HPAGE_PMD_ORDER
>>    7) repeat from step (2) until the full PMD range is covered
>>
>> mTHP collapses reject regions containing swapped out or shared pages.
>> This is because adding new entries can lead to new none pages, and these
>> may lead to constant promotion into a higher order mTHP. A similar
>> issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
>> introducing at least 2x the number of pages, and on a future scan will
>> satisfy the promotion condition once again. This issue is prevented via
>> the collapse_max_ptes_none() function which imposes the max_ptes_none
>> restrictions above.
>>
>> We currently only support mTHP collapse for max_ptes_none values of 0
>> and HPAGE_PMD_NR - 1. resulting in the following behavior:
>>
>>    - max_ptes_none=0: Never introduce new empty pages during collapse
>>    - max_ptes_none=HPAGE_PMD_NR-1: Always try collapse to the highest
>>      available mTHP order
>>
>> Any other max_ptes_none value will emit a warning and default mTHP
>> collapse to max_ptes_none=0. There should be no behavior change for PMD
>> collapse.
>>
>> Once we determine what mTHP sizes fits best in that PMD range a collapse
>> is attempted. A minimum collapse order of 2 is used as this is the lowest
>> order supported by anon memory as defined by THP_ORDERS_ALL_ANON.
>>
>> Currently madv_collapse is not supported and will only attempt PMD
>> collapse.
>>
>> We can also remove the check for is_khugepaged inside the PMD scan as
>> the collapse_max_ptes_none() function handles this logic now.
>>
>> Signed-off-by: Nico Pache <npache@redhat.com>
>> ---
>> mm/khugepaged.c | 146 +++++++++++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 138 insertions(+), 8 deletions(-)
>>
>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>> index ec886a031952..430047316f43 100644
>> --- a/mm/khugepaged.c
>> +++ b/mm/khugepaged.c
>> @@ -99,6 +99,8 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
>>
>> static struct kmem_cache *mm_slot_cache __ro_after_init;
>>
>> +#define KHUGEPAGED_MIN_MTHP_ORDER	2
>> +
>> struct collapse_control {
>> 	bool is_khugepaged;
>>
>> @@ -110,6 +112,9 @@ struct collapse_control {
>>
>> 	/* nodemask for allocation fallback */
>> 	nodemask_t alloc_nmask;
>> +
>> +	/* Each bit represents a single occupied (!none/zero) page. */
>> +	DECLARE_BITMAP(mthp_present_ptes, MAX_PTRS_PER_PTE);
>> };
>>
>> /**
>> @@ -1440,20 +1445,130 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long s
>> 	return result;
>> }
>>
>> +/* Return the highest naturally aligned order that fits at @offset within a PMD. */
>> +static unsigned int max_order_from_offset(unsigned int offset)
>> +{
>> +	if (offset == 0)
>> +		return HPAGE_PMD_ORDER;
>> +
>> +	return min_t(unsigned int, __ffs(offset), HPAGE_PMD_ORDER);
>> +}
>> +
>> +/*
>> + * mthp_collapse() consumes the bitmap that is generated during
>> + * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
>> + *
>> + * Each bit in cc->mthp_present_ptes represents a single occupied (!none/zero)
>> + * page. We start at the PMD order and check if it is eligible for collapse;
>> + * if not, we check the left and right halves of the PTE page table we are
>> + * examining at a lower order.
>> + *
>> + * For each of these, we determine how many PTE entries are occupied in the
>> + * range of PTE entries we propose to collapse, then we compare this to a
>> + * threshold number of PTE entries which would need to be occupied for a
>> + * collapse to be permitted at that order (accounting for max_ptes_none).
>> + *
>> + * If a collapse is permitted, we attempt to collapse the PTE range into a
>> + * mTHP.
>> + */
>> +static enum scan_result mthp_collapse(struct mm_struct *mm,
>> +		unsigned long address, int referenced, int unmapped,
>> +		struct collapse_control *cc, unsigned long enabled_orders)
>> +{
>> +	unsigned int nr_occupied_ptes, nr_ptes, max_ptes_none;
>> +	enum scan_result last_result = SCAN_FAIL;
>> +	int collapsed = 0;
>> +	bool alloc_failed = false;
>> +	unsigned long collapse_address;
>> +	unsigned int offset = 0;
>> +	unsigned int order = HPAGE_PMD_ORDER;
>> +
>> +	while (offset < HPAGE_PMD_NR) {
>> +		nr_ptes = 1UL << order;
>> +
>> +		if (!test_bit(order, &enabled_orders))
>> +			goto next_order;
>> +
>> +		max_ptes_none = collapse_max_ptes_none(cc, NULL, order);
>> +		nr_occupied_ptes = bitmap_weight_from(cc->mthp_present_ptes, offset,
>> +						      offset + nr_ptes);
>> +
>> +		if (nr_occupied_ptes >= nr_ptes - max_ptes_none) {
> 
> Looks broken for swap PTEs in PMD collapse ...
> 
> collapse_scan_pmd() allows them up to max_ptes_swap and record them in
> unmapped, but they don't get a bit in mthp_present_ptes. And then
> mthp_collapse() does the check above:

Right. I assumed this is implicitly handled by the optimization in collapse_scan_pmd:

	if (enabled_orders != BIT(HPAGE_PMD_ORDER))
		max_ptes_none = KHUGEPAGED_MAX_PTES_LIMIT;

But we perform the check a second time.

> 
> nr_occupied_ptes >= nr_ptes - max_ptes_none
> 
> So max_ptes_none=0 + 511 present PTEs + one allowed swap PTE won't even
> call collapse_huge_page() for PMD order.
> 
> Shouldn't we account for them in the PMD-order check? Something like:
> 
> if (is_pmd_order(order))
> 	nr_occupied_ptes += unmapped;
As an alternative, we could either 1) skip the check there for
pmd order (as the check was already done); or 2) introduce+maintain
a bitmap that tracks non-present PTEs.

@@ -1475,7 +1477,9 @@ static enum scan_result mthp_collapse(struct mm_struct *mm,
                nr_occupied_ptes = bitmap_weight_from(cc->mthp_present_ptes, offset,
                                                      offset + nr_ptes);
 
-               if (nr_occupied_ptes >= nr_ptes - max_ptes_none) {
+               /* Check was already done in the caller. */
+               if (is_pmd_order(order) ||
+                   nr_occupied_ptes >= nr_ptes - max_ptes_none) {
                        enum scan_result ret;
 
                        collapse_address = address + offset * PAGE_SIZE;

2) would probably be cleanest long-term.

-- 
Cheers,

David

^ permalink raw reply

* Re: [RFC v1 1/9] kho: split out radix tree tracker into kho_radix.c
From: Pasha Tatashin @ 2026-06-08 14:56 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Pasha Tatashin, linux-kselftest, shuah, akpm, linux-mm, skhan,
	linux-doc, jasonmiu, linux-kernel, corbet, ran.xiaokai, kexec,
	pratyush, graf
In-Reply-To: <178085518028.1648214.13339471022594901667.b4-reply@b4>

On 06-07 20:59, Mike Rapoport wrote:
> On 2026-06-07 16:20:50+00:00, Pasha Tatashin wrote:
> > On 06-07 14:58, Mike Rapoport wrote:
> > 
> > > On Fri, 05 Jun 2026 03:32:27 +0000, Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> > > 
> > > It's radix tree data structure implementation, kho memory tracker is it's
> > > user. Please rephrase to keep the semantics clear.
> > 
> > Yeap, I will update it.
> > 
> > > I don't see much value in moving kexec_handover.o to a separate line,
> > > btw, the same is true for luo_core.o, but it's not important enough to
> > > change.
> > 
> > This is purely for consistency. I wanted to use the exact same style in 
> > the Makefile instead of having two different ways of declaring the 
> > object lists.
> > 
> > This:
> >     luo-y :=                                \
> >             luo_core.o                      \
> >             luo_file.o                      \
> >             luo_flb.o                       \
> >             luo_session.o
> > 
> >     kho-y :=                                \
> >             kexec_handover.o                \
> >             kho_radix.o                     \
> >             kho_block.o                     \
> >             kho_vmalloc.o
>  
> I mean this:
> 
> luo-y := luo_core.o		\
> 	luo_file.o		\
> 	luo_flb.o		\
> 	luo_session.o
>  
> kho-y := kexec_handover.o	\
> 	kho_radix.o		\
> 	kho_block.o		\
> 	kho_vmalloc.o

Got it, I thought you were against making the consistent :-)

> 
> 

^ permalink raw reply

* [PATCH v5 00/34] Cleaning up the KVM clock mess
From: David Woodhouse @ 2026-06-08 14:47 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest

This is v5 of the series to clean up the KVM clock, rebased onto
tip/timers/ptp (which now includes Thomas's ktime snapshot series and
the read_snapshot patches for hyperv, kvmclock, and vmclock).

The KVM clock has historically suffered from three problems:

 1. Imprecision: get_kvmclock_ns() computed the clock from the *host*
    TSC without applying guest TSC scaling, causing systemic drift from
    the values the guest computes from its own TSC.

 2. Unnecessary discontinuities: gratuitous KVM_REQ_MASTERCLOCK_UPDATE
    requests caused the master clock reference point to be re-snapshotted,
    yanking the guest's clock due to arithmetic precision differences.

 3. No precise migration API: the existing KVM_[GS]ET_CLOCK only allows
    setting the clock at a given UTC reference time, which is necessarily
    imprecise. There was no way to preserve the exact arithmetic
    relationship between guest TSC and KVM clock across live migration.

This series addresses all three, and adds new APIs for precise clock 
migration and TSC frequency reporting. As an added bonus, it now rips 
out the whole pvclock_gtod_data hack which was shadowing the kernel's 
timekeeping, and uses ktime snapshots as $DEITY (well, Thomas) intended.

Changes since v4:
 - Rebased onto tip/timers/ptp (includes ktime snapshot infrastructure)
 - Dropped "WARN if kvm_get_walltime_and_clockread() fails" — the WARN
   was spurious during clocksource transitions
 - Dropped guest-side "Obtain TSC frequency from CPUID" patches (adopted
   by Sean for a separate series)
 - Dropped KVM_VCPU_TSC_EFFECTIVE_FREQ
 - Fixed false re-enabling of master clock when a single vCPU syncs
   multiple times at a mismatched frequency: introduced per-vCPU
   cur_tsc_freq_generation counter so each vCPU is counted exactly once
 - Unified nr_vcpus_matched_tsc and nr_vcpus_matched_freq to use the
   same counting convention (1-based, >= online_vcpus threshold)
 - "Avoid gratuitous global clock updates": kept global update in
   non-master-clock mode on vCPU load (CLOCK_MONOTONIC_RAW means no NTP
   drift but preserving the existing safety); only optimize master clock
 - "Xen runstate negative time": refined to update state but not account
   time on backwards clock, always update last_steal and guest shared page
 - Added "Activate master clock immediately on vCPU creation" to avoid
   unnecessary non-master-clock window during VM setup
 - New final patches: use ktime_get_snapshot_id() for master clock
   reference, then remove pvclock_gtod_data entirely (replaced by direct
   ktime_get_raw() + offs_boot computation)
 - Added masterclock_offset_test selftest (verifies kvmclock consistency
   across vCPUs with different TSC offsets)
 - Added xen_cpuid_timing_test selftest
 - Added pvclock_migration_test selftest
 - Addressed AI reviewer (Sashiko) feedback throughout:
   - get_kvmclock(): goto fallback on clock read failure instead of
     using uninitialized data; single #ifdef CONFIG_X86_64 block
   - kvm_synchronize_tsc(): changed ns to s64 to match function
     signature; moved time reads inside tsc_write_lock
   - Kill last_tsc fields: use kvm_scale_tsc() subtraction for
     backwards TSC instead of zeroing cur_tsc_write
   - KVM_[GS]ET_CLOCK_GUEST: validate padding fields, bounds-check
     tsc_shift
   - pvclock selftest: seqcount loop for torn-read safety, per-vCPU
     pvclock addresses, graceful skip when caps unavailable
   - KVM_VCPU_TSC_SCALE: return -ENXIO when !has_tsc_control
   - UAPI pvclock-abi: added -D__KERNEL__ to xen-hypercalls.sh
   - VMX: also clear SECONDARY_EXEC_TSC_SCALING from vmcs_config

David Woodhouse (31):
  KVM: x86/xen: Do not corrupt KVM clock in kvm_xen_shared_info_init()
  KVM: x86: Improve accuracy of KVM clock when TSC scaling is in force
  KVM: x86: Explicitly disable TSC scaling without CONSTANT_TSC
  KVM: x86: Activate master clock immediately on vCPU creation
  KVM: x86: Add KVM_VCPU_TSC_SCALE and fix the documentation on TSC migration
  KVM: x86: Avoid NTP frequency skew for KVM clock on 32-bit host
  KVM: x86: Fold __get_kvmclock() into get_kvmclock()
  KVM: x86: Restructure get_kvmclock()
  KVM: x86: Fix KVM clock precision in get_kvmclock() with TSC scaling
  KVM: x86: Use get_kvmclock() in kvm_get_wall_clock_epoch()
  KVM: x86: Fix compute_guest_tsc() to handle negative time deltas
  KVM: x86: Restructure kvm_guest_time_update() for TSC upscaling
  KVM: x86: Simplify and comment kvm_get_time_scale()
  KVM: x86: Remove implicit rdtsc() from kvm_compute_l1_tsc_offset()
  KVM: x86: Improve synchronization in kvm_synchronize_tsc()
  KVM: x86: Kill last_tsc_{nsec,write,offset} fields
  KVM: x86: Replace nr_vcpus_matched_tsc count with all_vcpus_matched_tsc bool
  KVM: x86: Allow KVM master clock mode when TSCs are offset from each other
  KVM: x86: Factor out kvm_use_master_clock()
  KVM: x86: Avoid gratuitous global clock updates
  KVM: x86/xen: Prevent runstate times from becoming negative
  KVM: x86: Avoid redundant masterclock updates from multiple vCPUs
  KVM: x86: Remove runtime Xen TSC frequency CPUID update
  KVM: x86: Re-synchronize TSC after KVM_SET_TSC_KHZ
  KVM: x86: Use ktime_get_snapshot_id() for master clock
  KVM: x86: Compute kvmclock base without pvclock_gtod_data
  KVM: x86: Replace pvclock_gtod_data vclock_mode with boolean
  KVM: x86: Remove pvclock_gtod_data and private timekeeping code
  KVM: selftests: Add master clock offset test
  KVM: selftests: Add Xen/generic CPUID timing leaf test
  KVM: selftests: Add Xen runstate migration test

Jack Allister (3):
  UAPI: x86: Move pvclock-abi to UAPI for x86 platforms
  KVM: x86: Add KVM_[GS]ET_CLOCK_GUEST for accurate KVM clock migration
  KVM: selftests: Add KVM/PV clock selftest to prove timer correction

 Documentation/virt/kvm/api.rst                     |   37 +
 Documentation/virt/kvm/devices/vcpu.rst            |  119 ++-
 MAINTAINERS                                        |    4 +-
 arch/x86/include/asm/kvm_host.h                    |   16 +-
 arch/x86/include/uapi/asm/kvm.h                    |    6 +
 arch/x86/include/{ => uapi}/asm/pvclock-abi.h      |   27 +-
 arch/x86/kvm/cpuid.c                               |   16 -
 arch/x86/kvm/svm/svm.c                             |    3 +-
 arch/x86/kvm/vmx/vmx.c                             |    4 +-
 arch/x86/kvm/x86.c                                 | 1039 ++++++++++++--------
 arch/x86/kvm/xen.c                                 |   30 +-
 arch/x86/kvm/xen.h                                 |   13 -
 include/uapi/linux/kvm.h                           |    3 +
 scripts/xen-hypercalls.sh                          |    2 +-
 tools/testing/selftests/kvm/Makefile.kvm           |    4 +
 .../selftests/kvm/x86/masterclock_offset_test.c    |  180 ++++
 .../selftests/kvm/x86/pvclock_migration_test.c     |  382 +++++++
 tools/testing/selftests/kvm/x86/pvclock_test.c     |  441 +++++++++
 .../selftests/kvm/x86/xen_cpuid_timing_test.c      |  230 +++++
 .../testing/selftests/kvm/x86/xen_migration_test.c |  194 ++++
 20 files changed, 2263 insertions(+), 487 deletions(-)

base-commit: bc484a5096732cd858771cccd3164ec985bdc03d


^ permalink raw reply

* [PATCH v5 16/34] KVM: x86: Simplify and comment kvm_get_time_scale()
From: David Woodhouse @ 2026-06-08 14:47 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <20260608145455.89187-1-dwmw2@infradead.org>

From: David Woodhouse <dwmw@amazon.co.uk>

The kvm_get_time_scale() function was entirely opaque. Add comments
explaining what it does: compute a fixed-point multiplier and shift for
converting TSC ticks to nanoseconds via pvclock_scale_delta().

Rename the local variables from the cryptic tps64/tps32/scaled64 to
base_hz_u64/base32/scaled_hz_u64 to make the code self-documenting.
The "tps32" name stood for "Ticks Per Second" but was misleading since
it held the shifted base frequency, not a tick count.

No functional change.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Paul Durrant <paul@xen.org>
---
 arch/x86/kvm/x86.c | 55 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 92e32d720523..a6c31a0d9955 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2472,32 +2472,57 @@ static uint32_t div_frac(uint32_t dividend, uint32_t divisor)
 	return dividend;
 }
 
-static void kvm_get_time_scale(uint64_t scaled_hz, uint64_t base_hz,
+static void kvm_get_time_scale(u64 scaled_hz, u64 base_hz,
 			       s8 *pshift, u32 *pmultiplier)
 {
-	uint64_t scaled64;
-	int32_t  shift = 0;
-	uint64_t tps64;
-	uint32_t tps32;
+	u64 scaled_hz_u64 = scaled_hz;
+	s32 shift = 0;
+	u64 base_hz_u64;
+	u32 base32;
 
-	tps64 = base_hz;
-	scaled64 = scaled_hz;
-	while (tps64 > scaled64*2 || tps64 & 0xffffffff00000000ULL) {
-		tps64 >>= 1;
+	/*
+	 * This function calculates a fixed-point multiplier and shift such
+	 * that:
+	 *   time_ns = (tsc_cycles << shift) * multiplier >> 32
+	 *
+	 * Where tsc_cycles tick at base_hz, and time_ns should count at
+	 * scaled_hz (typically NSEC_PER_SEC for a TSC→nanoseconds conversion).
+	 *
+	 * The multiplier is: (scaled_hz << 32) / base_hz, adjusted by shift
+	 * to keep everything in range.
+	 */
+
+	base_hz_u64 = base_hz;
+
+	/*
+	 * Start by shifting base_hz right until it fits in 32 bits, and
+	 * is lower than double the target rate. This introduces a negative
+	 * shift value which would result in pvclock_scale_delta() shifting
+	 * the actual tick count right before performing the multiplication.
+	 */
+	while (base_hz_u64 > scaled_hz_u64 * 2 || base_hz_u64 >> 32) {
+		base_hz_u64 >>= 1;
 		shift--;
 	}
 
-	tps32 = (uint32_t)tps64;
-	while (tps32 <= scaled64 || scaled64 & 0xffffffff00000000ULL) {
-		if (scaled64 & 0xffffffff00000000ULL || tps32 & 0x80000000)
-			scaled64 >>= 1;
+	/* Now the shifted base_hz fits in 32 bits. */
+	base32 = (u32)base_hz_u64;
+
+	/*
+	 * Next, shift scaled_hz right until it fits in 32 bits, and ensure
+	 * that the shifted base_hz is strictly larger (so that the result of the
+	 * final division also fits in 32 bits).
+	 */
+	while (base32 <= scaled_hz_u64 || scaled_hz_u64 >> 32) {
+		if (scaled_hz_u64 >> 32 || base32 & BIT(31))
+			scaled_hz_u64 >>= 1;
 		else
-			tps32 <<= 1;
+			base32 <<= 1;
 		shift++;
 	}
 
 	*pshift = shift;
-	*pmultiplier = div_frac(scaled64, tps32);
+	*pmultiplier = div_frac(scaled_hz_u64, base32);
 }
 
 #ifdef CONFIG_X86_64
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 32/34] KVM: x86: Compute kvmclock base without pvclock_gtod_data
From: David Woodhouse @ 2026-06-08 14:48 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <20260608145455.89187-1-dwmw2@infradead.org>

From: David Woodhouse <dwmw@amazon.co.uk>

get_kvmclock_base_ns() needs CLOCK_MONOTONIC_RAW + offs_boot. Compute
this directly rather than reading offs_boot from the pvclock_gtod_data
private copy. offs_boot only changes at suspend/resume so does not
need to be atomically paired with the raw clock read.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Assisted-by: Kiro:claude-opus-4.6-1m
---
 arch/x86/kvm/x86.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2713aebb96ae..c18947c5b63f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2402,7 +2402,7 @@ static void update_pvclock_gtod(struct timekeeper *tk)
 static s64 get_kvmclock_base_ns(void)
 {
 	/* Count up from boot time, but with the frequency of the raw clock.  */
-	return ktime_to_ns(ktime_add(ktime_get_raw(), pvclock_gtod_data.offs_boot));
+	return ktime_to_ns(ktime_mono_to_any(ktime_get_raw(), TK_OFFS_BOOT));
 }
 
 static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_ofs)
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 23/34] KVM: x86: Factor out kvm_use_master_clock()
From: David Woodhouse @ 2026-06-08 14:48 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <20260608145455.89187-1-dwmw2@infradead.org>

From: David Woodhouse <dwmw@amazon.co.uk>

Both kvm_track_tsc_matching() and pvclock_update_vm_gtod_copy() make a
decision about whether the KVM clock should be in master clock mode.
They used *different* criteria for the decision though. This isn't
really a problem; it only has the potential to cause unnecessary
invocations of KVM_REQ_MASTERCLOCK_UPDATE if the masterclock was
disabled due to TSC going backwards, or the guest using the old MSR.
But it isn't pretty.

Factor the decision out to a single function. And document the
historical reason why it's disabled for guests that use the old
MSR_KVM_SYSTEM_TIME.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Paul Durrant <paul@xen.org>
---
 arch/x86/kvm/x86.c | 40 ++++++++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 86c30be4c5d2..72fb4620a5ba 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2638,11 +2638,30 @@ static inline bool gtod_is_based_on_tsc(int mode)
 {
 	return mode == VDSO_CLOCKMODE_TSC || mode == VDSO_CLOCKMODE_HVCLOCK;
 }
-#endif
+
+static bool kvm_use_master_clock(struct kvm *kvm)
+{
+	struct kvm_arch *ka = &kvm->arch;
+
+	/*
+	 * The 'old kvmclock' check is a workaround (from 2015) for a
+	 * SUSE 2.6.16 kernel that didn't boot if the system_time in
+	 * its kvmclock was too far behind the current time. So the
+	 * mode of just setting the reference point and allowing time
+	 * to proceed linearly from there makes it fail to boot.
+	 * Despite that being kind of the *point* of the way the clock
+	 * is exposed to the guest. By coincidence, the offending
+	 * kernels used the old MSR_KVM_SYSTEM_TIME, which was moved
+	 * only because it resided in the wrong number range. So the
+	 * workaround is activated for *all* guests using the old MSR.
+	 */
+	return ka->all_vcpus_matched_freq &&
+		!ka->backwards_tsc_observed &&
+		!ka->boot_vcpu_runs_old_kvmclock;
+}
 
 static void kvm_track_tsc_matching(struct kvm_vcpu *vcpu, bool new_generation)
 {
-#ifdef CONFIG_X86_64
 	struct kvm_arch *ka = &vcpu->kvm->arch;
 	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
 
@@ -2677,7 +2696,7 @@ static void kvm_track_tsc_matching(struct kvm_vcpu *vcpu, bool new_generation)
 	 * are fine — each vCPU's pvclock has its own tsc_timestamp that
 	 * accounts for its offset.
 	 */
-	bool use_master_clock = ka->all_vcpus_matched_freq &&
+	bool use_master_clock = kvm_use_master_clock(vcpu->kvm) &&
 				gtod_is_based_on_tsc(gtod->clock.vclock_mode);
 
 	/*
@@ -2693,8 +2712,11 @@ static void kvm_track_tsc_matching(struct kvm_vcpu *vcpu, bool new_generation)
 	trace_kvm_track_tsc(vcpu->vcpu_id, ka->nr_vcpus_matched_tsc,
 			    atomic_read(&vcpu->kvm->online_vcpus),
 		            ka->use_master_clock, gtod->clock.vclock_mode);
-#endif
 }
+#else
+static inline void kvm_track_tsc_matching(struct kvm_vcpu *vcpu,
+					  bool new_generation) {}
+#endif
 
 /*
  * Multiply tsc by a fixed point number represented by ratio.
@@ -3216,10 +3238,9 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm)
 #ifdef CONFIG_X86_64
 	struct kvm_arch *ka = &kvm->arch;
 	int vclock_mode;
-	bool host_tsc_clocksource, vcpus_matched;
+	bool host_tsc_clocksource;
 
 	lockdep_assert_held(&kvm->arch.tsc_write_lock);
-	vcpus_matched = ka->all_vcpus_matched_freq;
 
 	/*
 	 * If the host uses TSC clock, then passthrough TSC as stable
@@ -3229,9 +3250,8 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm)
 					&ka->master_kernel_ns,
 					&ka->master_cycle_now);
 
-	ka->use_master_clock = host_tsc_clocksource && vcpus_matched
-				&& !ka->backwards_tsc_observed
-				&& !ka->boot_vcpu_runs_old_kvmclock;
+	ka->use_master_clock = host_tsc_clocksource &&
+				kvm_use_master_clock(kvm);
 
 	if (ka->use_master_clock) {
 		u64 tsc_hz;
@@ -3259,7 +3279,7 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm)
 
 	vclock_mode = pvclock_gtod_data.clock.vclock_mode;
 	trace_kvm_update_master_clock(ka->use_master_clock, vclock_mode,
-					vcpus_matched);
+					ka->all_vcpus_matched_freq);
 #endif
 }
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 18/34] KVM: x86: Improve synchronization in kvm_synchronize_tsc()
From: David Woodhouse @ 2026-06-08 14:47 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <20260608145455.89187-1-dwmw2@infradead.org>

From: David Woodhouse <dwmw@amazon.co.uk>

When synchronizing to an existing TSC (either by explicitly writing
zero, or the legacy hack where the TSC is written within one second's
worth of the previously written TSC), the last_tsc_write and
last_tsc_nsec values were being misrecorded by __kvm_synchronize_tsc().
The *unsynchronized* value of the TSC (perhaps even zero) was being
recorded, along with the current time at which kvm_synchronize_tsc()
was called. This could cause *subsequent* writes to fail to synchronize
correctly.

Fix that by resetting {data, ns} to the previous values before passing
them to __kvm_synchronize_tsc() when synchronization is detected.
Except in the case where the TSC is unstable and *has* to be synthesised
from the host clock, in which case attempt to create a nsec/tsc pair
which is on the correct line.

Furthermore, there were *three* different TSC reads used for calculating
the "current" time, all slightly different from each other. Fix that by
using kvm_get_time_and_clockread() where possible and using the same
host_tsc value in all cases.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Paul Durrant <paul@xen.org>
---
 arch/x86/kvm/x86.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bce4c7a6a6fe..c8c0633263fb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -203,6 +203,9 @@ module_param(mitigate_smt_rsb, bool, 0444);
  * usermode, e.g. SYSCALL MSRs and TSC_AUX, can be deferred until the CPU
  * returns to userspace, i.e. the kernel can run with the guest's value.
  */
+#ifdef CONFIG_X86_64
+static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp);
+#endif
 #define KVM_MAX_NR_USER_RETURN_MSRS 16
 
 struct kvm_user_return_msrs {
@@ -2854,14 +2857,23 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 *user_value)
 {
 	u64 data = user_value ? *user_value : 0;
 	struct kvm *kvm = vcpu->kvm;
-	u64 offset, ns, elapsed;
+	u64 offset, host_tsc, elapsed;
+	s64 ns;
 	unsigned long flags;
 	bool matched = false;
 	bool synchronizing = false;
 
 	raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
-	offset = kvm_compute_l1_tsc_offset(vcpu, rdtsc(), data);
-	ns = get_kvmclock_base_ns();
+
+#ifdef CONFIG_X86_64
+	if (!kvm_get_time_and_clockread(&ns, &host_tsc))
+#endif
+	{
+		host_tsc = rdtsc();
+		ns = get_kvmclock_base_ns();
+	}
+
+	offset = kvm_compute_l1_tsc_offset(vcpu, host_tsc, data);
 	elapsed = ns - kvm->arch.last_tsc_nsec;
 
 	if (vcpu->arch.virtual_tsc_khz) {
@@ -2904,12 +2916,25 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 *user_value)
          */
 	if (synchronizing &&
 	    vcpu->arch.virtual_tsc_khz == kvm->arch.last_tsc_khz) {
+		/*
+		 * If synchronizing, the "last written" TSC value/time
+		 * recorded by __kvm_synchronize_tsc() should not change
+		 * (i.e. should be precisely the same as the existing
+		 * generation).
+		 */
+		data = kvm->arch.last_tsc_write;
+
 		if (!kvm_check_tsc_unstable()) {
 			offset = kvm->arch.cur_tsc_offset;
+			ns = kvm->arch.cur_tsc_nsec;
 		} else {
+			/*
+			 * ...unless the TSC is unstable and has to be
+			 * synthesised from the host clock in nanoseconds.
+			 */
 			u64 delta = nsec_to_cycles(vcpu, elapsed);
 			data += delta;
-			offset = kvm_compute_l1_tsc_offset(vcpu, rdtsc(), data);
+			offset = kvm_compute_l1_tsc_offset(vcpu, host_tsc, data);
 		}
 		matched = true;
 	}
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 03/34] UAPI: x86: Move pvclock-abi to UAPI for x86 platforms
From: David Woodhouse @ 2026-06-08 14:47 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <20260608145455.89187-1-dwmw2@infradead.org>

From: Jack Allister <jalliste@amazon.com>

A subsequent commit will provide a new KVM interface for performing a
fixup/correction of the KVM clock against the reference TSC. The
KVM_[GS]ET_CLOCK_GUEST API requires a pvclock_vcpu_time_info, as such
the caller must know about this definition.

Move the definition to the UAPI folder so that it is exported to
usermode and also change the type definitions to use the standard for
UAPI exports.

Signed-off-by: Jack Allister <jalliste@amazon.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Paul Durrant <paul@xen.org>
---
 MAINTAINERS                                   |  4 +--
 arch/x86/include/{ => uapi}/asm/pvclock-abi.h | 27 ++++++++++---------
 scripts/xen-hypercalls.sh                     |  2 +-
 3 files changed, 18 insertions(+), 15 deletions(-)
 rename arch/x86/include/{ => uapi}/asm/pvclock-abi.h (82%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 882214b0e7db..dc0f6516beb4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14402,7 +14402,7 @@ S:	Supported
 T:	git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
 F:	arch/um/include/asm/kvm_para.h
 F:	arch/x86/include/asm/kvm_para.h
-F:	arch/x86/include/asm/pvclock-abi.h
+F:	arch/x86/include/uapi/asm/pvclock-abi.h
 F:	arch/x86/include/uapi/asm/kvm_para.h
 F:	arch/x86/kernel/kvm.c
 F:	arch/x86/kernel/kvmclock.c
@@ -29081,7 +29081,7 @@ R:	Boris Ostrovsky <boris.ostrovsky@oracle.com>
 L:	xen-devel@lists.xenproject.org (moderated for non-subscribers)
 S:	Supported
 F:	arch/x86/configs/xen.config
-F:	arch/x86/include/asm/pvclock-abi.h
+F:	arch/x86/include/uapi/asm/pvclock-abi.h
 F:	arch/x86/include/asm/xen/
 F:	arch/x86/platform/pvh/
 F:	arch/x86/xen/
diff --git a/arch/x86/include/asm/pvclock-abi.h b/arch/x86/include/uapi/asm/pvclock-abi.h
similarity index 82%
rename from arch/x86/include/asm/pvclock-abi.h
rename to arch/x86/include/uapi/asm/pvclock-abi.h
index b9fece5fc96d..6d70cf640362 100644
--- a/arch/x86/include/asm/pvclock-abi.h
+++ b/arch/x86/include/uapi/asm/pvclock-abi.h
@@ -1,6 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_X86_PVCLOCK_ABI_H
 #define _ASM_X86_PVCLOCK_ABI_H
+
+#include <linux/types.h>
+
 #ifndef __ASSEMBLER__
 
 /*
@@ -24,20 +27,20 @@
  */
 
 struct pvclock_vcpu_time_info {
-	u32   version;
-	u32   pad0;
-	u64   tsc_timestamp;
-	u64   system_time;
-	u32   tsc_to_system_mul;
-	s8    tsc_shift;
-	u8    flags;
-	u8    pad[2];
+	__u32   version;
+	__u32   pad0;
+	__u64   tsc_timestamp;
+	__u64   system_time;
+	__u32   tsc_to_system_mul;
+	__s8    tsc_shift;
+	__u8    flags;
+	__u8    pad[2];
 } __attribute__((__packed__)); /* 32 bytes */
 
 struct pvclock_wall_clock {
-	u32   version;
-	u32   sec;
-	u32   nsec;
+	__u32   version;
+	__u32   sec;
+	__u32   nsec;
 } __attribute__((__packed__));
 
 #define PVCLOCK_TSC_STABLE_BIT	(1 << 0)
diff --git a/scripts/xen-hypercalls.sh b/scripts/xen-hypercalls.sh
index f18b00843df3..51a722198997 100755
--- a/scripts/xen-hypercalls.sh
+++ b/scripts/xen-hypercalls.sh
@@ -5,7 +5,7 @@ shift
 in="$@"
 
 for i in $in; do
-	eval $CPP $LINUXINCLUDE -dD -imacros "$i" -x c /dev/null
+	eval $CPP -D__KERNEL__ $LINUXINCLUDE -dD -imacros "$i" -x c /dev/null
 done | \
 awk '$1 == "#define" && $2 ~ /__HYPERVISOR_[a-z][a-z_0-9]*/ { v[$3] = $2 }
 	END {   print "/* auto-generated by scripts/xen-hypercall.sh */"
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 10/34] KVM: x86: Fold __get_kvmclock() into get_kvmclock()
From: David Woodhouse @ 2026-06-08 14:47 UTC (permalink / raw)
  To: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky,
	David Woodhouse, Paul Durrant, Jonathan Cameron, Sascha Bischoff,
	Marc Zyngier, Joey Gouly, Jack Allister, Dongli Zhang, joe.jin,
	kvm, linux-doc, linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <20260608145455.89187-1-dwmw2@infradead.org>

From: David Woodhouse <dwmw@amazon.co.uk>

There is no need for the separate __get_kvmclock() helper; just inline
its body into get_kvmclock() within the seqcount retry loop.

No functional change.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 arch/x86/kvm/x86.c | 63 +++++++++++++++++++++-------------------------
 1 file changed, 28 insertions(+), 35 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 50bd2871b051..fce898811fe7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3200,50 +3200,43 @@ static unsigned long get_cpu_tsc_khz(void)
 		return __this_cpu_read(cpu_tsc_khz);
 }
 
-/* Called within read_seqcount_begin/retry for kvm->pvclock_sc.  */
-static void __get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data)
+static void get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data)
 {
 	struct kvm_arch *ka = &kvm->arch;
 	struct pvclock_vcpu_time_info hv_clock;
+	unsigned int seq;
 
-	/* both __this_cpu_read() and rdtsc() should be on the same cpu */
-	get_cpu();
+	do {
+		seq = read_seqcount_begin(&ka->pvclock_sc);
 
-	data->flags = 0;
-	if (ka->use_master_clock &&
-	    (static_cpu_has(X86_FEATURE_CONSTANT_TSC) || __this_cpu_read(cpu_tsc_khz))) {
+		/* both __this_cpu_read() and rdtsc() should be on the same cpu */
+		get_cpu();
+
+		data->flags = 0;
+		if (ka->use_master_clock &&
+		    (static_cpu_has(X86_FEATURE_CONSTANT_TSC) || __this_cpu_read(cpu_tsc_khz))) {
 #ifdef CONFIG_X86_64
-		struct timespec64 ts;
+			struct timespec64 ts;
 
-		if (kvm_get_walltime_and_clockread(&ts, &data->host_tsc)) {
-			data->realtime = ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec;
-			data->flags |= KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC;
-		} else
+			if (kvm_get_walltime_and_clockread(&ts, &data->host_tsc)) {
+				data->realtime = ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec;
+				data->flags |= KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC;
+			} else
 #endif
-		data->host_tsc = rdtsc();
-
-		data->flags |= KVM_CLOCK_TSC_STABLE;
-		hv_clock.tsc_timestamp = ka->master_cycle_now;
-		hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
-		kvm_get_time_scale(NSEC_PER_SEC, get_cpu_tsc_khz() * 1000LL,
-				   &hv_clock.tsc_shift,
-				   &hv_clock.tsc_to_system_mul);
-		data->clock = __pvclock_read_cycles(&hv_clock, data->host_tsc);
-	} else {
-		data->clock = get_kvmclock_base_ns() + ka->kvmclock_offset;
-	}
-
-	put_cpu();
-}
-
-static void get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data)
-{
-	struct kvm_arch *ka = &kvm->arch;
-	unsigned seq;
+			data->host_tsc = rdtsc();
+
+			data->flags |= KVM_CLOCK_TSC_STABLE;
+			hv_clock.tsc_timestamp = ka->master_cycle_now;
+			hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
+			kvm_get_time_scale(NSEC_PER_SEC, get_cpu_tsc_khz() * 1000LL,
+					   &hv_clock.tsc_shift,
+					   &hv_clock.tsc_to_system_mul);
+			data->clock = __pvclock_read_cycles(&hv_clock, data->host_tsc);
+		} else {
+			data->clock = get_kvmclock_base_ns() + ka->kvmclock_offset;
+		}
 
-	do {
-		seq = read_seqcount_begin(&ka->pvclock_sc);
-		__get_kvmclock(kvm, data);
+		put_cpu();
 	} while (read_seqcount_retry(&ka->pvclock_sc, seq));
 }
 
-- 
2.54.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox