* Re: [PATCH 10/13] mm/vma: convert miscellaneous uses of VMA flags in core mm
From: Lance Yang @ 2026-07-02 13:12 UTC (permalink / raw)
To: ljs
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, lance.yang, hughd, vbabka,
rppt, surenb, mhocko, jannh, pfalcato, kees, perex, tiwai,
linux-mips, linux-kernel, linuxppc-dev, dri-devel, etnaviv,
linux-arm-kernel, linux-samsung-soc, intel-gfx, linux-arm-msm,
freedreno, nouveau, linux-rockchip, linux-tegra, virtualization,
intel-xe, xen-devel, linux-fbdev, linux-aio, linux-fsdevel,
linux-mm, linux-sound
In-Reply-To: <1e7d834c887b6a65627d730addcff13d458c6268.1782760670.git.ljs@kernel.org>
On Mon, Jun 29, 2026 at 08:25:33PM +0100, Lorenzo Stoakes wrote:
>Update various uses of legacy flags in vma.c and mmap.c to the new
>vma_flags_t type, updating comments alongside them to be consistent.
>
>Also update __install_special_mapping() to rearrange things slightly to
>accommodate the changes.
>
>Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>---
[...]
>diff --git a/mm/vma.c b/mm/vma.c
>index b81c05e67a61..ab2ef0f04420 100644
>--- a/mm/vma.c
>+++ b/mm/vma.c
>@@ -3417,23 +3417,27 @@ struct vm_area_struct *__install_special_mapping(
> vm_flags_t vm_flags, void *priv,
> const struct vm_operations_struct *ops)
> {
>- int ret;
>+ vma_flags_t vma_flags = legacy_to_vma_flags(vm_flags);
> struct vm_area_struct *vma;
>+ int ret;
>
> vma = vm_area_alloc(mm);
>- if (unlikely(vma == NULL))
>+ if (unlikely(!vma))
> return ERR_PTR(-ENOMEM);
>
>- vma_set_range(vma, addr, addr + len, 0);
>- vm_flags |= vma_flags_to_legacy(mm->def_vma_flags) | VM_DONTEXPAND;
>+ vma_flags_set_mask(&vma_flags, mm->def_vma_flags);
>+ vma_flags_set(&vma_flags, VMA_DONTEXPAND_BIT);
> if (pgtable_supports_soft_dirty())
>- vm_flags |= VM_SOFTDIRTY;
>- vm_flags_init(vma, vm_flags & ~VM_LOCKED_MASK);
>+ vma_flags_set(&vma_flags, VMA_SOFTDIRTY_BIT);
>+ vma_flags_clear_mask(&vma_flags, VMA_LOCKED_MASK);
>+ vma->flags = vma_flags;
Maybe worth a vma_flags_init() helper here to mirror vm_flags_init()?
With this open-coded, we lose the soft-dirty WARN_ON_ONCE sanity check.
Might be nicer to keep that check in one place ;)
[...]
^ permalink raw reply
* Re: [PATCH 11/13] mm/mlock: convert mlock code to use vma_flags_t
From: Lance Yang @ 2026-07-02 13:21 UTC (permalink / raw)
To: ljs
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, lance.yang, hughd, vbabka,
rppt, surenb, mhocko, jannh, pfalcato, kees, perex, tiwai,
linux-mips, linux-kernel, linuxppc-dev, dri-devel, etnaviv,
linux-arm-kernel, linux-samsung-soc, intel-gfx, linux-arm-msm,
freedreno, nouveau, linux-rockchip, linux-tegra, virtualization,
intel-xe, xen-devel, linux-fbdev, linux-aio, linux-fsdevel,
linux-mm, linux-sound
In-Reply-To: <2db16db81538355ca65f778c246d2381c673cad4.1782760670.git.ljs@kernel.org>
On Mon, Jun 29, 2026 at 08:25:34PM +0100, Lorenzo Stoakes wrote:
>Replace use of the legacy vm_flags_t flags with vma_flags_t values
>throughout the mlock logic.
>
>Additionally update comments to reflect the changes to be consistent.
>
>No functional change intended.
>
>Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>---
Nothing scary jumped out at me. Just one tiny nit below ;)
[...]
>@@ -466,24 +466,23 @@ static void mlock_vma_pages_range(struct vm_area_struct *vma,
> */
> static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma,
> struct vm_area_struct **prev, unsigned long start,
>- unsigned long end, vm_flags_t newflags)
>+ unsigned long end, vma_flags_t *new_vma_flags)
> {
>- vma_flags_t new_vma_flags = legacy_to_vma_flags(newflags);
> const vma_flags_t old_vma_flags = vma->flags;
> struct mm_struct *mm = vma->vm_mm;
> int nr_pages;
> int ret = 0;
>
>- if (vma_flags_same_pair(&old_vma_flags, &new_vma_flags) ||
>+ if (vma_flags_same_pair(&old_vma_flags, new_vma_flags) ||
> vma_is_secretmem(vma) || !vma_supports_mlock(vma)) {
> /*
>- * Don't set VM_LOCKED or VM_LOCKONFAULT and don't count.
>+ * Don't set VMA_LOCKED_BIT or VM_LOCKONFAULT and don't count.
s/VM_LOCKONFAULT/VMA_LOCKONFAULT_BIT/
Otherwise LGTM. Feel free to add:
Reviewed-by: Lance Yang <lance.yang@linux.dev>
> * For secretmem, don't allow the memory to be unlocked.
> */
> goto out;
> }
>
>- vma = vma_modify_flags(vmi, *prev, vma, start, end, &new_vma_flags);
>+ vma = vma_modify_flags(vmi, *prev, vma, start, end, new_vma_flags);
> if (IS_ERR(vma)) {
> ret = PTR_ERR(vma);
> goto out;
[...]
^ permalink raw reply
* Re: [PATCH 13/13] mm/mremap: convert mremap code to use vma_flags_t
From: Lance Yang @ 2026-07-02 13:49 UTC (permalink / raw)
To: ljs
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, lance.yang, hughd, vbabka,
rppt, surenb, mhocko, jannh, pfalcato, kees, perex, tiwai,
linux-mips, linux-kernel, linuxppc-dev, dri-devel, etnaviv,
linux-arm-kernel, linux-samsung-soc, intel-gfx, linux-arm-msm,
freedreno, nouveau, linux-rockchip, linux-tegra, virtualization,
intel-xe, xen-devel, linux-fbdev, linux-aio, linux-fsdevel,
linux-mm, linux-sound
In-Reply-To: <380f761d35a3faa4370f8b3f92e3d4af3d4c7110.1782760670.git.ljs@kernel.org>
On Mon, Jun 29, 2026 at 08:25:36PM +0100, Lorenzo Stoakes wrote:
>Replace use of the legacy vm_flags_t flags with vma_flags_t values
>throughout the mremap logic.
>
>Additionally update comments to reflect the changes to be consistent.
>
>No functional change intended.
>
>Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>---
The vm_flags_set() cases below spell out vma_start_write(), but the
vm_flags_clear() cases don't?
Thanks, Lance
> mm/mremap.c | 38 ++++++++++++++++++++------------------
> 1 file changed, 20 insertions(+), 18 deletions(-)
>
>diff --git a/mm/mremap.c b/mm/mremap.c
>index 079a0ba0c4a7..0ea43302b7ed 100644
>--- a/mm/mremap.c
>+++ b/mm/mremap.c
>@@ -68,7 +68,7 @@ struct vma_remap_struct {
> bool populate_expand; /* mlock()'d expanded, must populate. */
> enum mremap_type remap_type; /* expand, shrink, etc. */
> bool mmap_locked; /* Is mm currently write-locked? */
>- unsigned long charged; /* If VM_ACCOUNT, # pages to account. */
>+ unsigned long charged; /* If VMA_ACCOUNT_BIT, # pgs to account */
> bool vmi_needs_invalidate; /* Is the VMA iterator invalidated? */
> };
>
>@@ -954,7 +954,7 @@ static unsigned long vrm_set_new_addr(struct vma_remap_struct *vrm)
>
> if (vrm->flags & MREMAP_FIXED)
> map_flags |= MAP_FIXED;
>- if (vma->vm_flags & VM_MAYSHARE)
>+ if (vma_test(vma, VMA_MAYSHARE_BIT))
> map_flags |= MAP_SHARED;
>
> res = get_unmapped_area(vma->vm_file, new_addr, vrm->new_len, pgoff,
>@@ -976,7 +976,7 @@ static bool vrm_calc_charge(struct vma_remap_struct *vrm)
> {
> unsigned long charged;
>
>- if (!(vrm->vma->vm_flags & VM_ACCOUNT))
>+ if (!vma_test(vrm->vma, VMA_ACCOUNT_BIT))
> return true;
>
> /*
>@@ -1003,7 +1003,7 @@ static bool vrm_calc_charge(struct vma_remap_struct *vrm)
> */
> static void vrm_uncharge(struct vma_remap_struct *vrm)
> {
>- if (!(vrm->vma->vm_flags & VM_ACCOUNT))
>+ if (!vma_test(vrm->vma, VMA_ACCOUNT_BIT))
> return;
>
> vm_unacct_memory(vrm->charged);
>@@ -1023,7 +1023,7 @@ static void vrm_stat_account(struct vma_remap_struct *vrm,
> struct vm_area_struct *vma = vrm->vma;
>
> vm_stat_account(mm, vma->vm_flags, pages);
>- if (vma->vm_flags & VM_LOCKED)
>+ if (vma_test(vma, VMA_LOCKED_BIT))
> mm->locked_vm += pages;
> }
>
>@@ -1167,7 +1167,7 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> * arose, in which case we _do_ wish to unmap the _new_ VMA, which means
> * we actually _do_ want it be unaccounted.
> */
>- bool accountable_move = (vma->vm_flags & VM_ACCOUNT) &&
>+ bool accountable_move = vma_test(vma, VMA_ACCOUNT_BIT) &&
> !(vrm->flags & MREMAP_DONTUNMAP);
>
> /*
>@@ -1186,7 +1186,7 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> * portions of the original VMA that remain.
> */
> if (accountable_move) {
>- vm_flags_clear(vma, VM_ACCOUNT);
>+ vma_clear_flags(vma, VMA_ACCOUNT_BIT);
> /* We are about to split vma, so store the start/end. */
> vm_start = vma->vm_start;
> vm_end = vma->vm_end;
>@@ -1211,8 +1211,8 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> * | |
> * |-------------|
> *
>- * Having cleared VM_ACCOUNT from the whole VMA, after we unmap above
>- * we'll end up with:
>+ * Having cleared VMA_ACCOUNT_BIT from the whole VMA, after we unmap
>+ * above we'll end up with:
> *
> * addr end
> * | |
>@@ -1232,13 +1232,15 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> if (vm_start < addr) {
> struct vm_area_struct *prev = vma_prev(&vmi);
>
>- vm_flags_set(prev, VM_ACCOUNT); /* Acquires VMA lock. */
>+ vma_start_write(prev);
>+ vma_set_flags(prev, VMA_ACCOUNT_BIT);
> }
>
> if (vm_end > end) {
> struct vm_area_struct *next = vma_next(&vmi);
>
>- vm_flags_set(next, VM_ACCOUNT); /* Acquires VMA lock. */
>+ vma_start_write(next);
>+ vma_set_flags(next, VMA_ACCOUNT_BIT);
> }
> }
> }
>@@ -1321,8 +1323,8 @@ static void dontunmap_complete(struct vma_remap_struct *vrm,
> unsigned long old_start = vrm->vma->vm_start;
> unsigned long old_end = vrm->vma->vm_end;
>
>- /* We always clear VM_LOCKED[ONFAULT] on the old VMA. */
>- vm_flags_clear(vrm->vma, VM_LOCKED_MASK);
>+ /* We always clear VMA_LOCKED[ONFAULT]_BIT on the old VMA. */
>+ vma_clear_flags_mask(vrm->vma, VMA_LOCKED_MASK);
>
> /*
> * anon_vma links of the old vma is no longer needed after its page
>@@ -1758,14 +1760,14 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
> * based on the original. There are no known use cases for this
> * behavior. As a result, fail such attempts.
> */
>- if (!old_len && !(vma->vm_flags & (VM_SHARED | VM_MAYSHARE))) {
>+ if (!old_len && !vma_test_any(vma, VMA_SHARED_BIT, VMA_MAYSHARE_BIT)) {
> pr_warn_once("%s (%d): attempted to duplicate a private mapping with mremap. This is not supported.\n",
> current->comm, current->pid);
> return -EINVAL;
> }
>
> if ((vrm->flags & MREMAP_DONTUNMAP) &&
>- (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)))
>+ vma_test_any(vma, VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT))
> return -EINVAL;
>
> /*
>@@ -1795,7 +1797,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
> return 0;
>
> /* We are expanding and the VMA is mlock()'d so we need to populate. */
>- if (vma->vm_flags & VM_LOCKED)
>+ if (vma_test(vma, VMA_LOCKED_BIT))
> vrm->populate_expand = true;
>
> /* Need to be careful about a growing mapping */
>@@ -1803,10 +1805,10 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
> if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
> return -EINVAL;
>
>- if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
>+ if (vma_test_any(vma, VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT))
> return -EFAULT;
>
>- if (!mlock_future_ok(mm, vma->vm_flags & VM_LOCKED, vrm->delta))
>+ if (!mlock_future_ok(mm, vma_test(vma, VMA_LOCKED_BIT), vrm->delta))
> return -EAGAIN;
>
> if (!may_expand_vm(mm, &vma->flags, vrm->delta >> PAGE_SHIFT))
>--
>2.54.0
>
>
^ permalink raw reply
* Re: [PATCH 02/13] mm/vma: update do_mmap() to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-02 14:16 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702111531.64883-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 07:15:31PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:25PM +0100, Lorenzo Stoakes wrote:
> >The core do_mmap() function accepts a vm_flags_t parameter which it then
> >manipulates before passing to mmap_region() to do the heavy lifting of the
> >memory mapping.
> >
> >Update do_mmap() to instead accept a vma_flags_t parameter, and adjust all
> >the logic within do_mmap() to manipulate this instead.
> >
> >This is as part of the ongoing effort to convert VMA flags from a system
> >word size to a bitmap type which allows us to unrestrict the number of VMA
> >flags, as well as gain control over how VMA flag manipulation occurs.
> >
> >We do not cascade these changes to all functions which accept vm_flags_t,
> >but rather use vma_flags_to_legacy() where necessary, specifically
> >deferring converting calc_vm_prot_bits(), calc_vm_flag_bits() and
> >__get_unmapped_area() to vma_flags_t.
> >
> >Also utilise the new vma_flags_can_grow() predicate which correctly handles
> >the case of architectures without upward growing stacks.
> >
> >As part of this change, introduce VMA_SHADOW_STACK so we can correctly
> >handle the case of the shadow stack not being defined.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
>
> Not exactly a small one :) I stared at this patch for a while, hopefully
> don't miss anythig ...
Yeah sorry maybe I could have broken this down more!
>
> Just one tiny nit below. Overall, LGTM, feel free to add:
>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
Thanks!
>
> [...]
> >diff --git a/mm/mmap.c b/mm/mmap.c
> >index 46174e706bbe..547352183214 100644
> >--- a/mm/mmap.c
> >+++ b/mm/mmap.c
> [...]
> >@@ -488,23 +496,27 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
> > * Check to see if we are violating any seals and update VMA
> > * flags if necessary to avoid future seal violations.
> > */
> >- err = memfd_check_seals_mmap(file, &vm_flags);
> >+ err = memfd_check_seals_mmap(file, &vma_flags);
> > if (err)
> > return (unsigned long)err;
> > } else {
> > switch (flags & MAP_TYPE) {
> > case MAP_SHARED:
> >- if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
> >+ if (vma_flags_can_grow(&vma_flags))
> > return -EINVAL;
> > /*
> > * Ignore pgoff.
> > */
> > pgoff = 0;
> >- vm_flags |= VM_SHARED | VM_MAYSHARE;
> >+ vma_flags_set(&vma_flags, VMA_SHARED_BIT, VMA_MAYSHARE_BIT);
> > break;
> >- case MAP_DROPPABLE:
> >- if (VM_DROPPABLE == VM_NONE)
> >+ case MAP_DROPPABLE: {
> >+ vma_flags_t droppable = VMA_DROPPABLE;
> >+
> >+ if (vma_flags_empty(&droppable))
> > return -EOPNOTSUPP;
> >+ vma_flags_set_mask(&vma_flags, droppable);
> >+
> > /*
> > * A locked or stack area makes no sense to be droppable.
> > *
> >@@ -515,23 +527,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
> > */
> > if (flags & (MAP_LOCKED | MAP_HUGETLB))
> > return -EINVAL;
> >- if (vm_flags & (VM_GROWSDOWN | VM_GROWSUP))
> >+ if (vma_flags_can_grow(&vma_flags))
> > return -EINVAL;
> >
> >- vm_flags |= VM_DROPPABLE;
>
> Old code checked VM_GROWSDOWN|VM_GROWSUP before seting VM_DROPPABLE. New
> code flips that around. Hmm, shouldn't master, just made me look twice ;)
>
> Maybe keep old order?
I guess I feared that defining droppable above then referencing it below would
be less clear?
Can move if you feel strongly about it, and sorry for making the move at the
same time as the general vm_flags_t -> vma_flags_t refactor as it does make that
less clear...
>
> Cheers, Lance
>
> >-
> > /*
> > * If the pages can be dropped, then it doesn't make
> > * sense to reserve them.
> > */
> >- vm_flags |= VM_NORESERVE;
> >+ vma_flags_set(&vma_flags, VMA_NORESERVE_BIT);
> >
> > /*
> > * Likewise, they're volatile enough that they
> > * shouldn't survive forks or coredumps.
> > */
> >- vm_flags |= VM_WIPEONFORK | VM_DONTDUMP;
> >+ vma_flags_set(&vma_flags, VMA_WIPEONFORK_BIT,
> >+ VMA_DONTDUMP_BIT);
> >+
> > fallthrough;
> >+ }
> > case MAP_PRIVATE:
> > /*
> > * Set pgoff according to addr for anon_vma.
> [...]
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH 02/13] mm/vma: update do_mmap() to use vma_flags_t
From: Lance Yang @ 2026-07-02 15:08 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <akZwsS-_cywsXSjL@lucifer>
On 2026/7/2 22:16, Lorenzo Stoakes wrote:
> On Thu, Jul 02, 2026 at 07:15:31PM +0800, Lance Yang wrote:
[...]
>>
>> [...]
>>> diff --git a/mm/mmap.c b/mm/mmap.c
>>> index 46174e706bbe..547352183214 100644
>>> --- a/mm/mmap.c
>>> +++ b/mm/mmap.c
>> [...]
>>> @@ -488,23 +496,27 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
>>> * Check to see if we are violating any seals and update VMA
>>> * flags if necessary to avoid future seal violations.
>>> */
>>> - err = memfd_check_seals_mmap(file, &vm_flags);
>>> + err = memfd_check_seals_mmap(file, &vma_flags);
>>> if (err)
>>> return (unsigned long)err;
>>> } else {
>>> switch (flags & MAP_TYPE) {
>>> case MAP_SHARED:
>>> - if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
>>> + if (vma_flags_can_grow(&vma_flags))
>>> return -EINVAL;
>>> /*
>>> * Ignore pgoff.
>>> */
>>> pgoff = 0;
>>> - vm_flags |= VM_SHARED | VM_MAYSHARE;
>>> + vma_flags_set(&vma_flags, VMA_SHARED_BIT, VMA_MAYSHARE_BIT);
>>> break;
>>> - case MAP_DROPPABLE:
>>> - if (VM_DROPPABLE == VM_NONE)
>>> + case MAP_DROPPABLE: {
>>> + vma_flags_t droppable = VMA_DROPPABLE;
>>> +
>>> + if (vma_flags_empty(&droppable))
>>> return -EOPNOTSUPP;
>>> + vma_flags_set_mask(&vma_flags, droppable);
>>> +
>>> /*
>>> * A locked or stack area makes no sense to be droppable.
>>> *
>>> @@ -515,23 +527,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
>>> */
>>> if (flags & (MAP_LOCKED | MAP_HUGETLB))
>>> return -EINVAL;
>>> - if (vm_flags & (VM_GROWSDOWN | VM_GROWSUP))
>>> + if (vma_flags_can_grow(&vma_flags))
>>> return -EINVAL;
>>>
>>> - vm_flags |= VM_DROPPABLE;
>>
>> Old code checked VM_GROWSDOWN|VM_GROWSUP before seting VM_DROPPABLE. New
>> code flips that around. Hmm, shouldn't master, just made me look twice ;)
>>
>> Maybe keep old order?
>
> I guess I feared that defining droppable above then referencing it below would
> be less clear?
>
> Can move if you feel strongly about it, and sorry for making the move at the
> same time as the general vm_flags_t -> vma_flags_t refactor as it does make that
> less clear...
No need to churn just for me. Thanks :)
^ permalink raw reply
* Re: [PATCH 05/13] mm: prefer mm->def_vma_flags in mm logic
From: Lorenzo Stoakes @ 2026-07-02 15:24 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702121022.49113-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 08:10:22PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:28PM +0100, Lorenzo Stoakes wrote:
> >Currently mm->def_flags (of type vm_flags_t) is union'd with
> >mm->def_vma_flags (of type vma_flags_t).
> >
> >As part of the effort to convert vm_flags_t usage to vma_flags_t (in order
> >to no longer be arbitrarily limited to a system word size for VMA flags),
> >prefer mm->def_vma_flags to mm->def_flags throughout the mm logic.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
> > mm/debug.c | 2 +-
> > mm/mlock.c | 13 +++++++------
> > mm/mmap.c | 11 ++++++-----
> > mm/vma.c | 4 ++--
> > 4 files changed, 16 insertions(+), 14 deletions(-)
> >
> >diff --git a/mm/debug.c b/mm/debug.c
> >index 497654b36f1a..f0a354a9496a 100644
> >--- a/mm/debug.c
> >+++ b/mm/debug.c
> >@@ -226,7 +226,7 @@ void dump_mm(const struct mm_struct *mm)
> > mm->numa_next_scan, mm->numa_scan_offset, mm->numa_scan_seq,
> > #endif
> > atomic_read(&mm->tlb_flush_pending),
> >- mm->def_flags, &mm->def_flags
> >+ vma_flags_to_legacy(mm->def_vma_flags), &mm->def_vma_flags
> > );
>
> While at it, one thing for later: dump_mm() still assumes one-world VMA
> flags. That works today since vma_flags_t is one word. Maybe worth a
> BUILD_BUG_ON() here, before that stops being true?
Ah yeah that could actually be pretty straightforward, if you see
https://www.kernel.org/doc/Documentation/printk-formats.txt there is a bitmap
format that could be used.
Can do that on a respin!
>
> Not a big deal though. Feel free to add:
>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
>
> > }
> > EXPORT_SYMBOL(dump_mm);
> [...]
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH 06/13] mm/vma: convert vm_pgprot_modify() to use vma_flags_t and rename
From: Lorenzo Stoakes @ 2026-07-02 15:29 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702122116.65642-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 08:21:16PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:29PM +0100, Lorenzo Stoakes wrote:
> >Update vm_pgprot_modify() to use the new VMA flags type vma_flags_t, and
> >rename to vma_pgprot_modify() accordingly.
> >
> >This is part of the ongoing work to convert vm_flags_t to vma_flags_t, in
> >order to eliminate the arbitrary limit of the number of bits in a system
> >word on available VMA flags.
> >
> >Update VMA userland tests accordingly, updating vma_set_page_prot() to no
> >longer inline vma_pgprot_modify(), rather we can simply define
> >vma_pgprot_modify() as a static inline function and the tests will pick it
> >up from vma.h.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
> [...]
> >diff --git a/mm/vma.h b/mm/vma.h
> >index bcf0c2773449..6a8abb8ae937 100644
> >--- a/mm/vma.h
> >+++ b/mm/vma.h
> >@@ -522,9 +522,11 @@ static inline bool vma_wants_manual_pte_write_upgrade(struct vm_area_struct *vma
> > }
> >
> > #ifdef CONFIG_MMU
> >-static inline pgprot_t vm_pgprot_modify(pgprot_t oldprot, vm_flags_t vm_flags)
> >+static inline pgprot_t vma_pgprot_modify(pgprot_t oldprot, vma_flags_t vma_flags)
> > {
> >- return pgprot_modify(oldprot, vm_get_page_prot(vm_flags));
> >+ const pgprot_t prot = vma_get_page_prot(vma_flags);
> >+
> >+ return pgprot_modify(oldprot, prot);
>
> Nit: could this just stay as a single return? something like:
>
> return pgprot_modify(oldprot, vma_get_page_prot(vma_flags));
I feel it's a bit clearer this way, separating out the two, I know it's a super
tiny difference but anyway :P
>
> Otherwise, LGTM, feel free to add:
>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
Thanks!
>
> [...]
Cheers, Lorenzo
^ permalink raw reply
* [PATCH v2] drm/vblank: Don't arm vblank timer with invalid frame duration
From: Roman Ilin @ 2026-07-02 15:23 UTC (permalink / raw)
To: Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard, David Airlie,
Simona Vetter
Cc: Louis Chauvet, Javier Martinez Canillas, Dmitry Osipenko,
dri-devel, virtualization, linux-kernel, Ville Syrjälä,
Thorsten Leemhuis, Peter Arnesen, Roman Ilin
In-Reply-To: <20260613224434.96501-1-me@romanilin.is>
When a CRTC's display mode carries a too small pixel clock,
drm_calc_timestamping_constants() computes a frame duration that exceeds
INT_MAX. drm_vblank_crtc.framedur_ns becomes negative.
drm_crtc_vblank_start_timer() then arms the vblank hrtimer with this
interval, after which vblank events are no longer delivered. Pending
page flips never complete and the display appears frozen.
This could be triggered on virtio-gpu guests that have dynamic
resolution enabled: when the SPICE agent or the X server resizes the
output, it submits a mode whose pixel clock is off by a factor of 1000,
e.g.:
clock = 406 kHz, htotal = 3152, vtotal = 2148
framedur_ns = 3152 * 2148 * 1000000 / 406 = 16675852216 ns (~16.7 s)
16675852216 does not fit into an int and wraps to roughly -504000000.
ns_to_ktime() then yields a negative interval and the timer stops
working.
Found by bisection, which pointed at commit a036f5fceedb ("drm/virtgpu:
Use vblank timer"). That commit merely made virtio-gpu use the vblank
timer and thereby exposed the pre-existing problem in the timer setup
added by commit 74afeb812850 ("drm/vblank: Add vblank timer").
To fix this, modify drm_calc_timestamping_constants() to use u64 for
calculations, check for INT_MAX overflows, and return an error code.
drm_crtc_vblank_start_timer() will then propagate the error, enabling
the driver to fall back to immediate vblank events. Valid modes are
unaffected, and the timer self-heals on the next mode with a sane clock.
Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Roman Ilin <me@romanilin.is>
---
Changes in v2:
- Moved the bounds check directly into drm_calc_timestamping_constants()
- Changed the helper's return type to int to propagate errors
- Used u64 for intermediate duration calculations to prevent overflows
- Added drm_WARN_ON_ONCE() when durations exceed INT_MAX
- Dropped virtio-gpu specific workarounds to keep the bugfix contained
to DRM core
Notes:
Tested on 7.2.0-rc1.
drivers/gpu/drm/drm_vblank.c | 67 +++++++++++++++++++++---------------
include/drm/drm_vblank.h | 4 +--
2 files changed, 42 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index f90fb2d13..b6a342e48 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -631,44 +631,51 @@ EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
* drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from
* CRTC's true scanout timing, so they take things like panel scaling or
* other adjustments into account.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
*/
-void drm_calc_timestamping_constants(struct drm_crtc *crtc,
- const struct drm_display_mode *mode)
+int drm_calc_timestamping_constants(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
{
struct drm_device *dev = crtc->dev;
unsigned int pipe = drm_crtc_index(crtc);
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
- int linedur_ns = 0, framedur_ns = 0;
+ u64 linedur_ns, framedur_ns;
int dotclock = mode->crtc_clock;
+ unsigned int frame_size;
if (!drm_dev_has_vblank(dev))
- return;
+ return 0;
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
- return;
+ return -EINVAL;
- /* Valid dotclock? */
- if (dotclock > 0) {
- int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
-
- /*
- * Convert scanline length in pixels and video
- * dot clock to line duration and frame duration
- * in nanoseconds:
- */
- linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
- framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
-
- /*
- * Fields of interlaced scanout modes are only half a frame duration.
- */
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- framedur_ns /= 2;
- } else {
- drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
- crtc->base.id);
+ if (dotclock <= 0) {
+ drm_err(dev, "crtc %u: Can't calculate constants, dotclock = %d!\n",
+ crtc->base.id, dotclock);
+ return -EINVAL;
}
+ frame_size = (unsigned int)mode->crtc_htotal * (unsigned int)mode->crtc_vtotal;
+
+ /*
+ * Convert scanline length in pixels and video dot clock to line duration
+ * and frame duration in nanoseconds.
+ */
+ linedur_ns = div_u64((u64)mode->crtc_htotal * 1000000, dotclock);
+ framedur_ns = div_u64((u64)frame_size * 1000000, dotclock);
+
+ /*
+ * Fields of interlaced scanout modes are only half a frame duration.
+ */
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ framedur_ns /= 2;
+
+ if (drm_WARN_ON_ONCE(dev, linedur_ns > INT_MAX) ||
+ drm_WARN_ON_ONCE(dev, framedur_ns > INT_MAX))
+ return -EINVAL;
+
vblank->linedur_ns = linedur_ns;
vblank->framedur_ns = framedur_ns;
drm_mode_copy(&vblank->hwmode, mode);
@@ -678,7 +685,10 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
crtc->base.id, mode->crtc_htotal,
mode->crtc_vtotal, mode->crtc_vdisplay);
drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
- crtc->base.id, dotclock, framedur_ns, linedur_ns);
+ crtc->base.id, dotclock,
+ vblank->framedur_ns, vblank->linedur_ns);
+
+ return 0;
}
EXPORT_SYMBOL(drm_calc_timestamping_constants);
@@ -2221,6 +2231,7 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
unsigned long flags;
+ int ret;
if (!vtimer->crtc) {
/*
@@ -2239,7 +2250,9 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
hrtimer_try_to_cancel(&vtimer->timer);
}
- drm_calc_timestamping_constants(crtc, &crtc->mode);
+ ret = drm_calc_timestamping_constants(crtc, &crtc->mode);
+ if (ret)
+ return ret;
spin_lock_irqsave(&vtimer->interval_lock, flags);
vtimer->interval = ns_to_ktime(vblank->framedur_ns);
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 2fcef9c0f..d99772dfa 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -311,8 +311,8 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc);
u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
void drm_crtc_vblank_restore(struct drm_crtc *crtc);
-void drm_calc_timestamping_constants(struct drm_crtc *crtc,
- const struct drm_display_mode *mode);
+int drm_calc_timestamping_constants(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode);
wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
u32 max_vblank_count);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 08/13] mm: introduce vma_get_page_prot() and use it
From: Lorenzo Stoakes @ 2026-07-02 15:40 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702123845.95316-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 08:38:45PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:31PM +0100, Lorenzo Stoakes wrote:
> >There's a large number of vm_get_page_prot(vma->vm_flags) invocations. Make
> >life easier by introducing vma_get_page_prot() parameterised by the VMA.
> >
> >This also makes converting vm_get_page_prot() to vma_flags_t easier.
> >
> >Also update the userland VMA tests to reflect the change.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
> > drivers/gpu/drm/drm_gem.c | 2 +-
> > drivers/gpu/drm/drm_gem_dma_helper.c | 2 +-
> > drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +-
> > drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +-
> > drivers/gpu/drm/exynos/exynos_drm_gem.c | 6 +++---
> > drivers/gpu/drm/i915/gem/i915_gem_mman.c | 12 ++++++------
> > drivers/gpu/drm/msm/msm_gem.c | 2 +-
> > drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +-
> > drivers/gpu/drm/omapdrm/omap_fbdev.c | 2 +-
> > drivers/gpu/drm/omapdrm/omap_gem.c | 6 +++---
> > drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 2 +-
> > drivers/gpu/drm/tegra/gem.c | 2 +-
> > drivers/gpu/drm/virtio/virtgpu_vram.c | 2 +-
> > drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c | 2 +-
> > drivers/gpu/drm/xe/xe_device.c | 2 +-
> > drivers/gpu/drm/xe/xe_mmio_gem.c | 2 +-
> > drivers/gpu/drm/xen/xen_drm_front_gem.c | 2 +-
> > drivers/video/fbdev/core/fb_io_fops.c | 2 +-
>
> One missed?
>
> drivers/gpu/drm/panthor/panthor_gem.c still has:
>
> vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
>
> Can use vma_get_page_prot(vma) too.
Oops! Will respin and update. Good spot!
>
> [...]
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH 10/13] mm/vma: convert miscellaneous uses of VMA flags in core mm
From: Lorenzo Stoakes @ 2026-07-02 15:46 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702131233.59026-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 09:12:33PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:33PM +0100, Lorenzo Stoakes wrote:
> >Update various uses of legacy flags in vma.c and mmap.c to the new
> >vma_flags_t type, updating comments alongside them to be consistent.
> >
> >Also update __install_special_mapping() to rearrange things slightly to
> >accommodate the changes.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
> [...]
> >diff --git a/mm/vma.c b/mm/vma.c
> >index b81c05e67a61..ab2ef0f04420 100644
> >--- a/mm/vma.c
> >+++ b/mm/vma.c
> >@@ -3417,23 +3417,27 @@ struct vm_area_struct *__install_special_mapping(
> > vm_flags_t vm_flags, void *priv,
> > const struct vm_operations_struct *ops)
> > {
> >- int ret;
> >+ vma_flags_t vma_flags = legacy_to_vma_flags(vm_flags);
> > struct vm_area_struct *vma;
> >+ int ret;
> >
> > vma = vm_area_alloc(mm);
> >- if (unlikely(vma == NULL))
> >+ if (unlikely(!vma))
> > return ERR_PTR(-ENOMEM);
> >
> >- vma_set_range(vma, addr, addr + len, 0);
> >- vm_flags |= vma_flags_to_legacy(mm->def_vma_flags) | VM_DONTEXPAND;
> >+ vma_flags_set_mask(&vma_flags, mm->def_vma_flags);
> >+ vma_flags_set(&vma_flags, VMA_DONTEXPAND_BIT);
> > if (pgtable_supports_soft_dirty())
> >- vm_flags |= VM_SOFTDIRTY;
> >- vm_flags_init(vma, vm_flags & ~VM_LOCKED_MASK);
> >+ vma_flags_set(&vma_flags, VMA_SOFTDIRTY_BIT);
> >+ vma_flags_clear_mask(&vma_flags, VMA_LOCKED_MASK);
> >+ vma->flags = vma_flags;
>
> Maybe worth a vma_flags_init() helper here to mirror vm_flags_init()?
> With this open-coded, we lose the soft-dirty WARN_ON_ONCE sanity check.
>
> Might be nicer to keep that check in one place ;)
I really hate all the VMA flag accessors, they conflate things horribly - we
should be explicitly taking VMA write locks when we need to (and often killable
ones actually) not assuming that a VMA flags accessor does (they should at most
assert).
This case is even more terribly egregious - you are setting flags at an
arbitrary time, why are we asserting something about softdirty?
You may update them as part of initialisation, maybe not. It's far from a
guarantee and feels like a lazy place to put it.
BUT obviously it's an oversight not to open code that here, so I'll update the
patch to do that!
I want VMA flags to be a clean stateless thing, other than the flags
themselves. Implicit, unrelated, asserts or lock acquisitions in general should
be done separately IMO.
>
> [...]
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH 11/13] mm/mlock: convert mlock code to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-02 15:47 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702132107.73727-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 09:21:07PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:34PM +0100, Lorenzo Stoakes wrote:
> >Replace use of the legacy vm_flags_t flags with vma_flags_t values
> >throughout the mlock logic.
> >
> >Additionally update comments to reflect the changes to be consistent.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
>
> Nothing scary jumped out at me. Just one tiny nit below ;)
>
> [...]
> >@@ -466,24 +466,23 @@ static void mlock_vma_pages_range(struct vm_area_struct *vma,
> > */
> > static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma,
> > struct vm_area_struct **prev, unsigned long start,
> >- unsigned long end, vm_flags_t newflags)
> >+ unsigned long end, vma_flags_t *new_vma_flags)
> > {
> >- vma_flags_t new_vma_flags = legacy_to_vma_flags(newflags);
> > const vma_flags_t old_vma_flags = vma->flags;
> > struct mm_struct *mm = vma->vm_mm;
> > int nr_pages;
> > int ret = 0;
> >
> >- if (vma_flags_same_pair(&old_vma_flags, &new_vma_flags) ||
> >+ if (vma_flags_same_pair(&old_vma_flags, new_vma_flags) ||
> > vma_is_secretmem(vma) || !vma_supports_mlock(vma)) {
> > /*
> >- * Don't set VM_LOCKED or VM_LOCKONFAULT and don't count.
> >+ * Don't set VMA_LOCKED_BIT or VM_LOCKONFAULT and don't count.
>
> s/VM_LOCKONFAULT/VMA_LOCKONFAULT_BIT/
Ah yeah oops, will fix and respin! Good spot [and claude missed it ugh] :)
>
> Otherwise LGTM. Feel free to add:
>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
>
> > * For secretmem, don't allow the memory to be unlocked.
> > */
> > goto out;
> > }
> >
> >- vma = vma_modify_flags(vmi, *prev, vma, start, end, &new_vma_flags);
> >+ vma = vma_modify_flags(vmi, *prev, vma, start, end, new_vma_flags);
> > if (IS_ERR(vma)) {
> > ret = PTR_ERR(vma);
> > goto out;
> [...]
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH 12/13] mm/mprotect: convert mprotect code to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-02 15:53 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260701160917.91435-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 12:09:17AM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:35PM +0100, Lorenzo Stoakes wrote:
> >Replace use of the legacy vm_flags_t flags with vma_flags_t values
> >throughout the mprotect logic.
> >
> >Note that we retain the legacy vm_flags_t bit shifting code in
> >do_mprotect_key(), deferring a vma_flags_t approach to this for the time
> >being.
> >
> >Additionally update comments to reflect the changes to be consistent.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
> > mm/mprotect.c | 16 ++++++++--------
> > 1 file changed, 8 insertions(+), 8 deletions(-)
> >
> >diff --git a/mm/mprotect.c b/mm/mprotect.c
> >index 9cbf932b028c..c9504b2a2525 100644
> >--- a/mm/mprotect.c
> >+++ b/mm/mprotect.c
> >@@ -40,7 +40,7 @@
> >
> > static bool maybe_change_pte_writable(struct vm_area_struct *vma, pte_t pte)
> > {
> >- if (WARN_ON_ONCE(!(vma->vm_flags & VM_WRITE)))
> >+ if (WARN_ON_ONCE(!vma_test(vma, VMA_WRITE_BIT)))
> > return false;
> >
> > /* Don't touch entries that are not even readable. */
> >@@ -97,7 +97,7 @@ static bool can_change_shared_pte_writable(struct vm_area_struct *vma,
> > bool can_change_pte_writable(struct vm_area_struct *vma, unsigned long addr,
> > pte_t pte)
> > {
> >- if (!(vma->vm_flags & VM_SHARED))
> >+ if (!vma_test(vma, VMA_SHARED_BIT))
> > return can_change_private_pte_writable(vma, addr, pte);
> >
> > return can_change_shared_pte_writable(vma, pte);
> >@@ -194,7 +194,7 @@ static __always_inline void set_write_prot_commit_flush_ptes(struct vm_area_stru
> > {
> > bool set_write;
> >
> >- if (vma->vm_flags & VM_SHARED) {
> >+ if (vma_test(vma, VMA_SHARED_BIT)) {
> > set_write = can_change_shared_pte_writable(vma, ptent);
> > prot_commit_flush_ptes(vma, addr, ptep, oldpte, ptent, nr_ptes,
> > /* idx = */ 0, set_write, tlb);
> >@@ -811,8 +811,8 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb,
> > vm_unacct_memory(nrpages);
> >
> > /*
> >- * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major
> >- * fault on access.
> >+ * Private VMA_LOCKED_BIT VMA becoming writable: trigger COW to avoid
> >+ * major fault on access.
> > */
> > if (vma_flags_test(&new_vma_flags, VMA_WRITE_BIT) &&
> > vma_flags_test(&old_vma_flags, VMA_LOCKED_BIT) &&
> >@@ -886,7 +886,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> > goto out;
> > start = vma->vm_start;
> > error = -EINVAL;
> >- if (!(vma->vm_flags & VM_GROWSDOWN))
> >+ if (!vma_test(vma, VMA_GROWSDOWN_BIT))
> > goto out;
> > } else {
> > if (vma->vm_start > start)
> >@@ -894,7 +894,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> > if (unlikely(grows & PROT_GROWSUP)) {
> > end = vma->vm_end;
> > error = -EINVAL;
> >- if (!(vma->vm_flags & VM_GROWSUP))
> >+ if (!vma_test(vma, VMA_GROWSUP_BIT))
>
> IIUC, should this be
>
> if (!vma_test_single_mask(vma, VMA_GROWSUP))
>
> instead?
>
> #elif defined(CONFIG_PARISC)
> #define VM_GROWSUP INIT_VM_FLAG(GROWSUP)
> ...
> #ifndef VM_GROWSUP
> #define VM_GROWSUP VM_NONE
> ...
>
> VM_GROWSUP is only defined as GROWSUP on parisc and becomes VM_NONE
> elsewhere. But VMA_GROWSUP_BIT is the raw ARCH_1 bit, which is also used
> for other arch-specific VMA flags:
>
> DECLARE_VMA_BIT_ALIAS(SAO, ARCH_1), /* Strong Access Ordering (powerpc) */
> DECLARE_VMA_BIT_ALIAS(GROWSUP, ARCH_1), /* parisc */
> DECLARE_VMA_BIT_ALIAS(SPARC_ADI, ARCH_1), /* sparc64 */
> DECLARE_VMA_BIT_ALIAS(ARM64_BTI, ARCH_1), /* arm64 */
> DECLARE_VMA_BIT_ALIAS(ARCH_CLEAR, ARCH_1), /* sparc64, arm64 */
> DECLARE_VMA_BIT_ALIAS(MAPPED_COPY, ARCH_1), /* !CONFIG_MMU */
>
> Other vma_test() changes look fine to me: just fixed INIT_VM_FLAG()
> masks matching their VMA_*_BIT :)
Thanks you're right, will fix!
Again I swear I ran claude on all of this so it's failing me here :)
>
> Cheers, Lance
>
> > goto out;
> > }
> > }
> >@@ -918,7 +918,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> > }
> >
> > /* Does the application expect PROT_READ to imply PROT_EXEC */
> >- if (rier && (vma->vm_flags & VM_MAYEXEC))
> >+ if (rier && vma_test(vma, VMA_MAYEXEC_BIT))
> > prot |= PROT_EXEC;
> >
> > /*
> >--
> >2.54.0
> >
> >
^ permalink raw reply
* Re: [PATCH 13/13] mm/mremap: convert mremap code to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-02 16:07 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <20260702134947.25189-1-lance.yang@linux.dev>
On Thu, Jul 02, 2026 at 09:49:47PM +0800, Lance Yang wrote:
>
> On Mon, Jun 29, 2026 at 08:25:36PM +0100, Lorenzo Stoakes wrote:
> >Replace use of the legacy vm_flags_t flags with vma_flags_t values
> >throughout the mremap logic.
> >
> >Additionally update comments to reflect the changes to be consistent.
> >
> >No functional change intended.
> >
> >Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> >---
>
> The vm_flags_set() cases below spell out vma_start_write(), but the
> vm_flags_clear() cases don't?
Yep as I said elsewhere, implicitly taking the lock is terrible and me doing
this is completely on purpose to get rid of that :)
But I haven't been clear enough clearly, so I should put the argument as to why
that's ok in the commit message.
Will do so on respin.
>
> Thanks, Lance
>
> > mm/mremap.c | 38 ++++++++++++++++++++------------------
> > 1 file changed, 20 insertions(+), 18 deletions(-)
> >
> >diff --git a/mm/mremap.c b/mm/mremap.c
> >index 079a0ba0c4a7..0ea43302b7ed 100644
> >--- a/mm/mremap.c
> >+++ b/mm/mremap.c
> >@@ -68,7 +68,7 @@ struct vma_remap_struct {
> > bool populate_expand; /* mlock()'d expanded, must populate. */
> > enum mremap_type remap_type; /* expand, shrink, etc. */
> > bool mmap_locked; /* Is mm currently write-locked? */
> >- unsigned long charged; /* If VM_ACCOUNT, # pages to account. */
> >+ unsigned long charged; /* If VMA_ACCOUNT_BIT, # pgs to account */
> > bool vmi_needs_invalidate; /* Is the VMA iterator invalidated? */
> > };
> >
> >@@ -954,7 +954,7 @@ static unsigned long vrm_set_new_addr(struct vma_remap_struct *vrm)
> >
> > if (vrm->flags & MREMAP_FIXED)
> > map_flags |= MAP_FIXED;
> >- if (vma->vm_flags & VM_MAYSHARE)
> >+ if (vma_test(vma, VMA_MAYSHARE_BIT))
> > map_flags |= MAP_SHARED;
> >
> > res = get_unmapped_area(vma->vm_file, new_addr, vrm->new_len, pgoff,
> >@@ -976,7 +976,7 @@ static bool vrm_calc_charge(struct vma_remap_struct *vrm)
> > {
> > unsigned long charged;
> >
> >- if (!(vrm->vma->vm_flags & VM_ACCOUNT))
> >+ if (!vma_test(vrm->vma, VMA_ACCOUNT_BIT))
> > return true;
> >
> > /*
> >@@ -1003,7 +1003,7 @@ static bool vrm_calc_charge(struct vma_remap_struct *vrm)
> > */
> > static void vrm_uncharge(struct vma_remap_struct *vrm)
> > {
> >- if (!(vrm->vma->vm_flags & VM_ACCOUNT))
> >+ if (!vma_test(vrm->vma, VMA_ACCOUNT_BIT))
> > return;
> >
> > vm_unacct_memory(vrm->charged);
> >@@ -1023,7 +1023,7 @@ static void vrm_stat_account(struct vma_remap_struct *vrm,
> > struct vm_area_struct *vma = vrm->vma;
> >
> > vm_stat_account(mm, vma->vm_flags, pages);
> >- if (vma->vm_flags & VM_LOCKED)
> >+ if (vma_test(vma, VMA_LOCKED_BIT))
> > mm->locked_vm += pages;
> > }
> >
> >@@ -1167,7 +1167,7 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> > * arose, in which case we _do_ wish to unmap the _new_ VMA, which means
> > * we actually _do_ want it be unaccounted.
> > */
> >- bool accountable_move = (vma->vm_flags & VM_ACCOUNT) &&
> >+ bool accountable_move = vma_test(vma, VMA_ACCOUNT_BIT) &&
> > !(vrm->flags & MREMAP_DONTUNMAP);
> >
> > /*
> >@@ -1186,7 +1186,7 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> > * portions of the original VMA that remain.
> > */
> > if (accountable_move) {
> >- vm_flags_clear(vma, VM_ACCOUNT);
> >+ vma_clear_flags(vma, VMA_ACCOUNT_BIT);
This is called from move_vma() which holds the VMA write lock on vma.
> > /* We are about to split vma, so store the start/end. */
> > vm_start = vma->vm_start;
> > vm_end = vma->vm_end;
> >@@ -1211,8 +1211,8 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> > * | |
> > * |-------------|
> > *
> >- * Having cleared VM_ACCOUNT from the whole VMA, after we unmap above
> >- * we'll end up with:
> >+ * Having cleared VMA_ACCOUNT_BIT from the whole VMA, after we unmap
> >+ * above we'll end up with:
> > *
> > * addr end
> > * | |
> >@@ -1232,13 +1232,15 @@ static void unmap_source_vma(struct vma_remap_struct *vrm)
> > if (vm_start < addr) {
> > struct vm_area_struct *prev = vma_prev(&vmi);
> >
> >- vm_flags_set(prev, VM_ACCOUNT); /* Acquires VMA lock. */
> >+ vma_start_write(prev);
> >+ vma_set_flags(prev, VMA_ACCOUNT_BIT);
> > }
> >
> > if (vm_end > end) {
> > struct vm_area_struct *next = vma_next(&vmi);
> >
> >- vm_flags_set(next, VM_ACCOUNT); /* Acquires VMA lock. */
> >+ vma_start_write(next);
> >+ vma_set_flags(next, VMA_ACCOUNT_BIT);
These need vma_start_write() as referencing other, unlocked VMAs.
> > }
> > }
> > }
> >@@ -1321,8 +1323,8 @@ static void dontunmap_complete(struct vma_remap_struct *vrm,
> > unsigned long old_start = vrm->vma->vm_start;
> > unsigned long old_end = vrm->vma->vm_end;
> >
> >- /* We always clear VM_LOCKED[ONFAULT] on the old VMA. */
> >- vm_flags_clear(vrm->vma, VM_LOCKED_MASK);
> >+ /* We always clear VMA_LOCKED[ONFAULT]_BIT on the old VMA. */
> >+ vma_clear_flags_mask(vrm->vma, VMA_LOCKED_MASK);
-
Same as above, called from move_vma() with VMA write lock held.
> >
> > /*
> > * anon_vma links of the old vma is no longer needed after its page
> >@@ -1758,14 +1760,14 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
> > * based on the original. There are no known use cases for this
> > * behavior. As a result, fail such attempts.
> > */
> >- if (!old_len && !(vma->vm_flags & (VM_SHARED | VM_MAYSHARE))) {
> >+ if (!old_len && !vma_test_any(vma, VMA_SHARED_BIT, VMA_MAYSHARE_BIT)) {
> > pr_warn_once("%s (%d): attempted to duplicate a private mapping with mremap. This is not supported.\n",
> > current->comm, current->pid);
> > return -EINVAL;
> > }
> >
> > if ((vrm->flags & MREMAP_DONTUNMAP) &&
> >- (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)))
> >+ vma_test_any(vma, VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT))
> > return -EINVAL;
> >
> > /*
> >@@ -1795,7 +1797,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
> > return 0;
> >
> > /* We are expanding and the VMA is mlock()'d so we need to populate. */
> >- if (vma->vm_flags & VM_LOCKED)
> >+ if (vma_test(vma, VMA_LOCKED_BIT))
> > vrm->populate_expand = true;
> >
> > /* Need to be careful about a growing mapping */
> >@@ -1803,10 +1805,10 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
> > if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
> > return -EINVAL;
> >
> >- if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
> >+ if (vma_test_any(vma, VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT))
> > return -EFAULT;
> >
> >- if (!mlock_future_ok(mm, vma->vm_flags & VM_LOCKED, vrm->delta))
> >+ if (!mlock_future_ok(mm, vma_test(vma, VMA_LOCKED_BIT), vrm->delta))
> > return -EAGAIN;
> >
> > if (!may_expand_vm(mm, &vma->flags, vrm->delta >> PAGE_SHIFT))
> >--
> >2.54.0
> >
> >
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH 13/13] mm/mremap: convert mremap code to use vma_flags_t
From: Lance Yang @ 2026-07-02 16:17 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <akaJx8Zt8kazlrjq@lucifer>
On 2026/7/3 00:07, Lorenzo Stoakes wrote:
> On Thu, Jul 02, 2026 at 09:49:47PM +0800, Lance Yang wrote:
>>
>> On Mon, Jun 29, 2026 at 08:25:36PM +0100, Lorenzo Stoakes wrote:
>>> Replace use of the legacy vm_flags_t flags with vma_flags_t values
>>> throughout the mremap logic.
>>>
>>> Additionally update comments to reflect the changes to be consistent.
>>>
>>> No functional change intended.
>>>
>>> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>>> ---
>>
>> The vm_flags_set() cases below spell out vma_start_write(), but the
>> vm_flags_clear() cases don't?
>
> Yep as I said elsewhere, implicitly taking the lock is terrible and me doing
> this is completely on purpose to get rid of that :)
>
> But I haven't been clear enough clearly, so I should put the argument as to why
> that's ok in the commit message.
>
> Will do so on respin.
Makes sense, thanks for spelling it out! A short changelog note
should clear it up for me :D
[...]
^ permalink raw reply
* Re: [PATCH 13/13] mm/mremap: convert mremap code to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-02 16:31 UTC (permalink / raw)
To: Lance Yang
Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
npache, ryan.roberts, dev.jain, baohua, hughd, vbabka, rppt,
surenb, mhocko, jannh, pfalcato, kees, perex, tiwai, linux-mips,
linux-kernel, linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <2f36a2da-0686-485f-b4b9-ae699bef4fd4@linux.dev>
On Fri, Jul 03, 2026 at 12:17:29AM +0800, Lance Yang wrote:
>
>
> On 2026/7/3 00:07, Lorenzo Stoakes wrote:
> > On Thu, Jul 02, 2026 at 09:49:47PM +0800, Lance Yang wrote:
> > >
> > > On Mon, Jun 29, 2026 at 08:25:36PM +0100, Lorenzo Stoakes wrote:
> > > > Replace use of the legacy vm_flags_t flags with vma_flags_t values
> > > > throughout the mremap logic.
> > > >
> > > > Additionally update comments to reflect the changes to be consistent.
> > > >
> > > > No functional change intended.
> > > >
> > > > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > > > ---
> > >
> > > The vm_flags_set() cases below spell out vma_start_write(), but the
> > > vm_flags_clear() cases don't?
> >
> > Yep as I said elsewhere, implicitly taking the lock is terrible and me doing
> > this is completely on purpose to get rid of that :)
> >
> > But I haven't been clear enough clearly, so I should put the argument as to why
> > that's ok in the commit message.
> >
> > Will do so on respin.
>
> Makes sense, thanks for spelling it out! A short changelog note
> should clear it up for me :D
Yeah absolutely, that's necessary and was an oversight on my part, will correct!
Thanks for your great review here, much appreciated! :)
>
> [...]
Cheers, Lorenzo
^ permalink raw reply
* RE: [PATCH v5 01/51] x86/apic: Provide helpers to set local APIC timer period in hz and khz
From: Michael Kelley @ 2026-07-02 17:47 UTC (permalink / raw)
To: Sean Christopherson, Jonathan Corbet, Paolo Bonzini,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86@kernel.org, Kiryl Shutsemau, Rick Edgecombe, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
Juergen Gross, Daniel Lezcano, John Stultz
Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
xen-devel@lists.xenproject.org, Tom Lendacky, Nikunj A Dadhania,
David Woodhouse, David Woodhouse, Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-2-seanjc@google.com>
From: Sean Christopherson <seanjc@google.com> Sent: Wednesday, July 1, 2026 12:31 PM
>
> Add and use APIs to set the local APIC timer period instead of open coding
> the subtle HZ math in a all external callers, and make lapic_timer_period
Spurious word "a".
> local to apic.c. Provide APIs to specify the frequency in both hertz and
> kilohertz so that Hyper-V and VMware code aren't forced to lose precision.
>
> Opportunistically use mul_u64_u32_div() to harden against the possibility
> that the period in Khz is greater than 4294967, i.e. if the APIC timer runs
> at ~4.29 GHz. As pointed out by Sashiko, 4294968 * 1000 == 0x1_000002c0,
> and thus a Khz period of 4294968 would silently overflow the 32-bit
> unsigned integer used by most callers.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/include/asm/apic.h | 3 ++-
> arch/x86/kernel/apic/apic.c | 12 +++++++++++-
> arch/x86/kernel/cpu/mshyperv.c | 5 +----
> arch/x86/kernel/cpu/vmware.c | 4 +---
> arch/x86/kernel/jailhouse.c | 2 +-
> arch/x86/kernel/tsc.c | 2 +-
> arch/x86/kernel/tsc_msr.c | 2 +-
> 7 files changed, 18 insertions(+), 12 deletions(-)
>
> diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
> index 9cd493d467d4..cd84a94688a2 100644
> --- a/arch/x86/include/asm/apic.h
> +++ b/arch/x86/include/asm/apic.h
> @@ -63,7 +63,6 @@ extern int apic_verbosity;
> extern int local_apic_timer_c2_ok;
>
> extern bool apic_is_disabled;
> -extern unsigned int lapic_timer_period;
>
> extern enum apic_intr_mode_id apic_intr_mode;
> enum apic_intr_mode_id {
> @@ -138,6 +137,8 @@ void register_lapic_address(unsigned long address);
> extern void setup_boot_APIC_clock(void);
> extern void setup_secondary_APIC_clock(void);
> extern void lapic_update_tsc_freq(void);
> +extern void apic_set_timer_period_hz(u64 period_hz, const char *source);
> +extern void apic_set_timer_period_khz(u64 period_khz, const char *source);
>
> #ifdef CONFIG_X86_64
> static inline bool apic_force_enable(unsigned long addr)
> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
> index aa1e19979aa8..8d3d930576fd 100644
> --- a/arch/x86/kernel/apic/apic.c
> +++ b/arch/x86/kernel/apic/apic.c
> @@ -176,7 +176,7 @@ static struct resource lapic_resource = {
> };
>
> /* Measured in ticks per HZ. */
> -unsigned int lapic_timer_period = 0;
> +static unsigned int lapic_timer_period;
>
> static void apic_pm_activate(void);
>
> @@ -796,6 +796,16 @@ bool __init apic_needs_pit(void)
> return lapic_timer_period == 0;
> }
>
> +void apic_set_timer_period_khz(u64 period_khz, const char *source)
> +{
> + lapic_timer_period = mul_u64_u32_div(period_khz, 1000, HZ);
> +}
> +
> +void apic_set_timer_period_hz(u64 period_hz, const char *source)
> +{
> + lapic_timer_period = div_u64(period_hz, HZ);
> +}
A string "source" argument is passed in, but not used. Is there an
envisioned future use? Also, this function doesn't output a pr_info()
message like the existing Hyper-V and VMware code does. I don't
know that the message is all that useful, though I do remember
one case where I was debugging some clock/timer issue when I
looked at it.
Michael
> +
> static int __init calibrate_APIC_clock(void)
> {
> struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 185d4f677ec0..87beecec76f0 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -646,10 +646,7 @@ static void __init ms_hyperv_init_platform(void)
> u64 hv_lapic_frequency;
>
> rdmsrq(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency);
> - hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ);
> - lapic_timer_period = hv_lapic_frequency;
> - pr_info("Hyper-V: LAPIC Timer Frequency: %#x\n",
> - lapic_timer_period);
> + apic_set_timer_period_hz(hv_lapic_frequency, "Hyper-V hypervisor");
> }
>
> register_nmi_handler(NMI_UNKNOWN, hv_nmi_unknown, NMI_FLAG_FIRST,
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 34b73573b108..36f779dd311d 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -424,9 +424,7 @@ static void __init vmware_platform_setup(void)
>
> #ifdef CONFIG_X86_LOCAL_APIC
> /* Skip lapic calibration since we know the bus frequency. */
> - lapic_timer_period = ecx / HZ;
> - pr_info("Host bus clock speed read from hypervisor : %u Hz\n",
> - ecx);
> + apic_set_timer_period_hz(ecx, "VMware hypervisor");
> #endif
> } else {
> pr_warn("Failed to get TSC freq from the hypervisor\n");
> diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
> index f58ce9220e0f..f2d4ef89c085 100644
> --- a/arch/x86/kernel/jailhouse.c
> +++ b/arch/x86/kernel/jailhouse.c
> @@ -65,7 +65,7 @@ static void jailhouse_get_wallclock(struct timespec64 *now)
>
> static void __init jailhouse_timer_init(void)
> {
> - lapic_timer_period = setup_data.v1.apic_khz * (1000 / HZ);
> + apic_set_timer_period_khz(setup_data.v1.apic_khz, "Jailhouse hypervisor");
> }
>
> static unsigned long jailhouse_get_tsc(void)
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index ce10ae4b298b..f9ecc9256863 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -717,7 +717,7 @@ unsigned long native_calibrate_tsc(void)
> * lapic_timer_period here to avoid having to calibrate the APIC
> * timer later.
> */
> - lapic_timer_period = crystal_khz * 1000 / HZ;
> + apic_set_timer_period_khz(crystal_khz, "CPUID 0x15/0x16");
> #endif
>
> return crystal_khz * ebx_numerator / eax_denominator;
> diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
> index 48e6cc1cb017..7e990871e041 100644
> --- a/arch/x86/kernel/tsc_msr.c
> +++ b/arch/x86/kernel/tsc_msr.c
> @@ -211,7 +211,7 @@ unsigned long cpu_khz_from_msr(void)
> pr_err("Error MSR_FSB_FREQ index %d is unknown\n", index);
>
> #ifdef CONFIG_X86_LOCAL_APIC
> - lapic_timer_period = (freq * 1000) / HZ;
> + apic_set_timer_period_khz(freq, "MSR_FSB_FREQ");
> #endif
>
> /*
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* RE: [PATCH v5 11/51] x86/tsc: Add dedicated hypervisor hooks for getting known TSC/CPU frequencies
From: Michael Kelley @ 2026-07-02 17:47 UTC (permalink / raw)
To: Sean Christopherson, Jonathan Corbet, Paolo Bonzini,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86@kernel.org, Kiryl Shutsemau, Rick Edgecombe, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
Juergen Gross, Daniel Lezcano, John Stultz
Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
xen-devel@lists.xenproject.org, Tom Lendacky, Nikunj A Dadhania,
David Woodhouse, David Woodhouse, Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-12-seanjc@google.com>
From: Sean Christopherson <seanjc@google.com> Sent: Wednesday, July 1, 2026 12:32 PM
>
> Add dedicated hypervisor hooks for getting known TSC/CPU frequencies
> instead of overriding seemingly generic platform hooks, and explicitly
> priotize hypervisor-provided frequencies over native methods, but do NOT
s/priotize/prioritize/
> clobber the frequency obtained from trusted firmware. While shuffling the
> hooks around is arguably "six of one, half dozen of the other", scoping
> them to x86_hyper_init makes their purpose more obvious, and allows for
> explicitly defining the priority of sources (as is done here).
>
> As is already done when trusted firmware provides the TSC frequency, ignore
Word "ignore" is duplicated.
> ignore tsc_early_khz if the exact TSC frequency was obtained from the
> hypervisor, as attempting to refine the TSC frequency when running in a VM
> is all but guaranteed to cause problems sooner or later due to the
> calibration sources being emulated devices in the vast majority of setups.
>
> Cc: David Woodhouse <dwmw2@infradead.org>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
For the Hyper-V changes,
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
> ---
> .../admin-guide/kernel-parameters.txt | 3 +-
> arch/x86/include/asm/acrn.h | 5 ----
> arch/x86/include/asm/x86_init.h | 4 +++
> arch/x86/kernel/cpu/acrn.c | 10 +++++--
> arch/x86/kernel/cpu/mshyperv.c | 6 ++--
> arch/x86/kernel/cpu/vmware.c | 8 ++---
> arch/x86/kernel/jailhouse.c | 6 ++--
> arch/x86/kernel/kvmclock.c | 6 ++--
> arch/x86/kernel/tsc.c | 29 ++++++++++++++-----
> arch/x86/xen/time.c | 4 +--
> 10 files changed, 50 insertions(+), 31 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-
> guide/kernel-parameters.txt
> index 490e6aa72fc2..a387bb2c47e2 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -7948,7 +7948,8 @@ Kernel parameters
>
> Note, tsc_early_khz is ignored if the TSC frequency is
> provided by trusted firmware when running as an SNP or
> - TDX guest.
> + TDX guest, or when the hypervisor provides the exact
> + frequency via a paravirtual interface.
>
> tsx= [X86] Control Transactional Synchronization
> Extensions (TSX) feature in Intel processors that
> diff --git a/arch/x86/include/asm/acrn.h b/arch/x86/include/asm/acrn.h
> index db42b477c41d..a892179c61c6 100644
> --- a/arch/x86/include/asm/acrn.h
> +++ b/arch/x86/include/asm/acrn.h
> @@ -32,11 +32,6 @@ static inline u32 acrn_cpuid_base(void)
> return 0;
> }
>
> -static inline unsigned long acrn_get_tsc_khz(void)
> -{
> - return cpuid_eax(ACRN_CPUID_TIMING_INFO);
> -}
> -
> /*
> * Hypercalls for ACRN
> *
> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> index 953d3199408a..0c89bf40f507 100644
> --- a/arch/x86/include/asm/x86_init.h
> +++ b/arch/x86/include/asm/x86_init.h
> @@ -123,6 +123,8 @@ struct x86_init_pci {
> * @msi_ext_dest_id: MSI supports 15-bit APIC IDs
> * @init_mem_mapping: setup early mappings during init_mem_mapping()
> * @init_after_bootmem: guest init after boot allocator is finished
> + * @get_tsc_khz: get the TSC frequency (returns 0 if frequency is unknown)
> + * @get_cpu_khz: get the CPU frequency (returns 0 if frequency is unknown)
> */
> struct x86_hyper_init {
> void (*init_platform)(void);
> @@ -131,6 +133,8 @@ struct x86_hyper_init {
> bool (*msi_ext_dest_id)(void);
> void (*init_mem_mapping)(void);
> void (*init_after_bootmem)(void);
> + unsigned int (*get_tsc_khz)(void);
> + unsigned int (*get_cpu_khz)(void);
> };
>
> /**
> diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
> index dc119af83524..ad8f2da8003b 100644
> --- a/arch/x86/kernel/cpu/acrn.c
> +++ b/arch/x86/kernel/cpu/acrn.c
> @@ -24,13 +24,15 @@ static u32 __init acrn_detect(void)
> return acrn_cpuid_base();
> }
>
> +static unsigned int __init acrn_get_tsc_khz(void)
> +{
> + return cpuid_eax(ACRN_CPUID_TIMING_INFO);
> +}
> +
> static void __init acrn_init_platform(void)
> {
> /* Install system interrupt handler for ACRN hypervisor callback */
> sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_acrn_hv_callback);
> -
> - x86_platform.calibrate_tsc = acrn_get_tsc_khz;
> - x86_platform.calibrate_cpu = acrn_get_tsc_khz;
> }
>
> static bool acrn_x2apic_available(void)
> @@ -78,4 +80,6 @@ const __initconst struct hypervisor_x86 x86_hyper_acrn = {
> .type = X86_HYPER_ACRN,
> .init.init_platform = acrn_init_platform,
> .init.x2apic_available = acrn_x2apic_available,
> + .init.get_tsc_khz = acrn_get_tsc_khz,
> + .init.get_cpu_khz = acrn_get_tsc_khz,
> };
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 87beecec76f0..f9bc1c2d8c93 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -395,7 +395,7 @@ static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
> }
> #endif
>
> -static unsigned long hv_get_tsc_khz(void)
> +static unsigned int __init hv_get_tsc_khz(void)
> {
> unsigned long freq;
>
> @@ -573,8 +573,8 @@ static void __init ms_hyperv_init_platform(void)
>
> if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS &&
> ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
> - x86_platform.calibrate_tsc = hv_get_tsc_khz;
> - x86_platform.calibrate_cpu = hv_get_tsc_khz;
> + x86_init.hyper.get_tsc_khz = hv_get_tsc_khz;
> + x86_init.hyper.get_cpu_khz = hv_get_tsc_khz;
> setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> }
>
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 13b97265c535..3cb473cae462 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -64,7 +64,7 @@ struct vmware_steal_time {
> u64 reserved[7];
> };
>
> -static unsigned long vmware_tsc_khz __ro_after_init;
> +static unsigned long vmware_tsc_khz __initdata;
> static u8 vmware_hypercall_mode __ro_after_init;
>
> unsigned long vmware_hypercall_slow(unsigned long cmd,
> @@ -137,7 +137,7 @@ static inline int __vmware_platform(void)
> return eax != UINT_MAX && ebx == VMWARE_HYPERVISOR_MAGIC;
> }
>
> -static unsigned long vmware_get_tsc_khz(void)
> +static unsigned int __init vmware_get_tsc_khz(void)
> {
> return vmware_tsc_khz;
> }
> @@ -419,8 +419,8 @@ static void __init vmware_platform_setup(void)
> }
>
> vmware_tsc_khz = tsc_khz;
> - x86_platform.calibrate_tsc = vmware_get_tsc_khz;
> - x86_platform.calibrate_cpu = vmware_get_tsc_khz;
> + x86_init.hyper.get_tsc_khz = vmware_get_tsc_khz;
> + x86_init.hyper.get_cpu_khz = vmware_get_tsc_khz;
>
> /* Skip lapic calibration since we know the bus frequency. */
> apic_set_timer_period_hz(ecx, "VMware hypervisor");
> diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
> index f2d4ef89c085..e24c05ab4fae 100644
> --- a/arch/x86/kernel/jailhouse.c
> +++ b/arch/x86/kernel/jailhouse.c
> @@ -68,7 +68,7 @@ static void __init jailhouse_timer_init(void)
> apic_set_timer_period_khz(setup_data.v1.apic_khz, "Jailhouse hypervisor");
> }
>
> -static unsigned long jailhouse_get_tsc(void)
> +static unsigned int __init jailhouse_get_tsc(void)
> {
> return precalibrated_tsc_khz;
> }
> @@ -210,8 +210,6 @@ static void __init jailhouse_init_platform(void)
> x86_init.mpparse.parse_smp_cfg = jailhouse_parse_smp_config;
> x86_init.pci.arch_init = jailhouse_pci_arch_init;
>
> - x86_platform.calibrate_cpu = jailhouse_get_tsc;
> - x86_platform.calibrate_tsc = jailhouse_get_tsc;
> x86_platform.get_wallclock = jailhouse_get_wallclock;
> x86_platform.legacy.rtc = 0;
> x86_platform.legacy.warm_reset = 0;
> @@ -293,5 +291,7 @@ const struct hypervisor_x86 x86_hyper_jailhouse __refconst = {
> .detect = jailhouse_detect,
> .init.init_platform = jailhouse_init_platform,
> .init.x2apic_available = jailhouse_x2apic_available,
> + .init.get_tsc_khz = jailhouse_get_tsc,
> + .init.get_cpu_khz = jailhouse_get_tsc,
> .ignore_nopv = true,
> };
> diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
> index cb3d0ca1fa22..4f8299303a19 100644
> --- a/arch/x86/kernel/kvmclock.c
> +++ b/arch/x86/kernel/kvmclock.c
> @@ -136,7 +136,7 @@ static inline void kvm_sched_clock_init(bool stable)
> * poll of guests can be running and trouble each other. So we preset
> * lpj here
> */
> -static unsigned long kvm_get_tsc_khz(void)
> +static unsigned int __init kvm_get_tsc_khz(void)
> {
> setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> return pvclock_tsc_khz(this_cpu_pvti());
> @@ -343,8 +343,8 @@ void __init kvmclock_init(void)
> flags = pvclock_read_flags(&hv_clock_boot[0].pvti);
> kvm_sched_clock_init(flags & PVCLOCK_TSC_STABLE_BIT);
>
> - x86_platform.calibrate_tsc = kvm_get_tsc_khz;
> - x86_platform.calibrate_cpu = kvm_get_tsc_khz;
> + x86_init.hyper.get_tsc_khz = kvm_get_tsc_khz;
> + x86_init.hyper.get_cpu_khz = kvm_get_tsc_khz;
> x86_platform.get_wallclock = kvm_get_wallclock;
> x86_platform.set_wallclock = kvm_set_wallclock;
> #ifdef CONFIG_X86_LOCAL_APIC
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 86384a83a5f6..1dca9464b41c 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -1451,13 +1451,17 @@ static int __init init_tsc_clocksource(void)
> device_initcall(init_tsc_clocksource);
>
> static bool __init determine_cpu_tsc_frequencies(bool early,
> + unsigned int known_cpu_khz,
> unsigned int known_tsc_khz)
> {
> /* Make sure that cpu and tsc are not already calibrated */
> WARN_ON(cpu_khz || tsc_khz);
>
> if (early) {
> - cpu_khz = x86_platform.calibrate_cpu();
> + if (known_cpu_khz)
> + cpu_khz = known_cpu_khz;
> + else
> + cpu_khz = x86_platform.calibrate_cpu();
> if (known_tsc_khz)
> tsc_khz = known_tsc_khz;
> else
> @@ -1514,7 +1518,7 @@ static void __init tsc_enable_sched_clock(void)
>
> void __init tsc_early_init(void)
> {
> - unsigned int known_tsc_khz = 0;
> + unsigned int known_cpu_khz = 0, known_tsc_khz = 0;
>
> if (!boot_cpu_has(X86_FEATURE_TSC))
> return;
> @@ -1522,22 +1526,33 @@ void __init tsc_early_init(void)
> if (is_early_uv_system())
> return;
>
> + if (x86_init.hyper.get_cpu_khz)
> + known_cpu_khz = x86_init.hyper.get_cpu_khz();
> +
> if (cc_platform_has(CC_ATTR_GUEST_SNP_SECURE_TSC))
> known_tsc_khz = snp_secure_tsc_init();
> else if (boot_cpu_has(X86_FEATURE_TDX_GUEST))
> known_tsc_khz = tdx_tsc_init();
>
> + /*
> + * If the TSC frequency wasn't provided by trusted firmware, try to get
> + * it from the hypervisor (which is untrusted when running as a CoCo guest).
> + */
> + if (!known_tsc_khz && x86_init.hyper.get_tsc_khz)
> + known_tsc_khz = x86_init.hyper.get_tsc_khz();
> +
> /*
> * Ignore the user-provided TSC frequency if the exact frequency was
> - * obtained from trusted firmware, as the user-provided frequency is
> - * intended as a "starting point", not a known, guaranteed frequency.
> + * obtained from trusted firmware or the hypervisor, as the user-
> + * provided frequency is intended as a "starting point", not a known,
> + * guaranteed frequency.
> */
> if (!known_tsc_khz)
> known_tsc_khz = tsc_early_khz;
> else if (tsc_early_khz)
> - pr_err("Ignoring 'tsc_early_khz' in favor of trusted firmware.\n");
> + pr_err("Ignoring 'tsc_early_khz' in favor of firmware/hypervisor.\n");
>
> - if (!determine_cpu_tsc_frequencies(true, known_tsc_khz))
> + if (!determine_cpu_tsc_frequencies(true, known_cpu_khz, known_tsc_khz))
> return;
> tsc_enable_sched_clock();
> }
> @@ -1558,7 +1573,7 @@ void __init tsc_init(void)
>
> if (!tsc_khz) {
> /* We failed to determine frequencies earlier, try again */
> - if (!determine_cpu_tsc_frequencies(false, 0)) {
> + if (!determine_cpu_tsc_frequencies(false, 0, 0)) {
> mark_tsc_unstable("could not calculate TSC khz");
> setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
> return;
> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
> index d62c14334b35..1adb44fdddb2 100644
> --- a/arch/x86/xen/time.c
> +++ b/arch/x86/xen/time.c
> @@ -38,7 +38,7 @@
> static u64 xen_sched_clock_offset __read_mostly;
>
> /* Get the TSC speed from Xen */
> -static unsigned long xen_tsc_khz(void)
> +static unsigned int __init xen_tsc_khz(void)
> {
> struct pvclock_vcpu_time_info *info =
> &HYPERVISOR_shared_info->vcpu_info[0].time;
> @@ -569,7 +569,7 @@ static void __init xen_init_time_common(void)
> static_call_update(pv_steal_clock, xen_steal_clock);
> paravirt_set_sched_clock(xen_sched_clock);
>
> - x86_platform.calibrate_tsc = xen_tsc_khz;
> + x86_init.hyper.get_tsc_khz = xen_tsc_khz;
> x86_platform.get_wallclock = xen_get_wallclock;
> }
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* RE: [PATCH v5 14/51] x86/tsc: Consolidate forcing of X86_FEATURE_TSC_KNOWN_FREQ for PV code
From: Michael Kelley @ 2026-07-02 17:47 UTC (permalink / raw)
To: Sean Christopherson, Jonathan Corbet, Paolo Bonzini,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86@kernel.org, Kiryl Shutsemau, Rick Edgecombe, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
Juergen Gross, Daniel Lezcano, John Stultz
Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
xen-devel@lists.xenproject.org, Tom Lendacky, Nikunj A Dadhania,
David Woodhouse, David Woodhouse, Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-15-seanjc@google.com>
From: Sean Christopherson <seanjc@google.com> Sent: Wednesday, July 1, 2026 12:32 PM
>
> Now that all paravirt code that explicitly specifies the TSC frequency
> also sets X86_FEATURE_TSC_KNOWN_FREQ, replace all of the one-off code
> and simply set X86_FEATURE_TSC_KNOWN_FREQ if the TSC frequency is known.
>
> Do NOT force set TSC_KNOWN_FREQ if the "known" TSC frequency was provided
> by the user. Per commit bd35c77e32e4 ("x86/tsc: Add tsc_early_khz command
> line parameter"), one of the goals of the param is to allow the refined
> calibration work "to do meaningful error checking".
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
For the Hyper-V changes,
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
> ---
> arch/x86/coco/sev/core.c | 1 -
> arch/x86/coco/tdx/tdx.c | 1 -
> arch/x86/kernel/cpu/acrn.c | 1 -
> arch/x86/kernel/cpu/mshyperv.c | 1 -
> arch/x86/kernel/cpu/vmware.c | 2 --
> arch/x86/kernel/jailhouse.c | 1 -
> arch/x86/kernel/kvmclock.c | 1 -
> arch/x86/kernel/tsc.c | 13 ++++++++++---
> arch/x86/xen/time.c | 1 -
> 9 files changed, 10 insertions(+), 12 deletions(-)
>
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index bc5ae9ef74da..72313b36b6f5 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -2027,7 +2027,6 @@ unsigned int __init snp_secure_tsc_init(void)
>
> secrets = (__force struct snp_secrets_page *)mem;
>
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
>
> rdmsrq(MSR_AMD64_GUEST_TSC_FREQ, tsc_freq_mhz);
> diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
> index ae2d35f2ef33..94682aca188b 100644
> --- a/arch/x86/coco/tdx/tdx.c
> +++ b/arch/x86/coco/tdx/tdx.c
> @@ -1205,7 +1205,6 @@ unsigned int __init tdx_tsc_init(void)
>
> /* TSC is the only reliable clock in TDX guest */
> setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
>
> return info.crystal_khz * info.numerator / info.denominator;
> }
> diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
> index 3818f6ae0629..dc71a6fdd461 100644
> --- a/arch/x86/kernel/cpu/acrn.c
> +++ b/arch/x86/kernel/cpu/acrn.c
> @@ -40,7 +40,6 @@ static void __init acrn_init_platform(void)
> if (acrn_tsc_khz_cpuid) {
> x86_init.hyper.get_tsc_khz = acrn_get_tsc_khz;
> x86_init.hyper.get_cpu_khz = acrn_get_tsc_khz;
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> }
> }
>
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index f9bc1c2d8c93..e03c69a4db33 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -575,7 +575,6 @@ static void __init ms_hyperv_init_platform(void)
> ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
> x86_init.hyper.get_tsc_khz = hv_get_tsc_khz;
> x86_init.hyper.get_cpu_khz = hv_get_tsc_khz;
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> }
>
> if (ms_hyperv.priv_high & HV_ISOLATION) {
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 3cb473cae462..0a3bd90576d4 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -390,8 +390,6 @@ static void __init vmware_set_capabilities(void)
> {
> setup_force_cpu_cap(X86_FEATURE_CONSTANT_TSC);
> setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
> - if (vmware_tsc_khz)
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> if (vmware_hypercall_mode == CPUID_VMWARE_FEATURES_ECX_VMCALL)
> setup_force_cpu_cap(X86_FEATURE_VMCALL);
> else if (vmware_hypercall_mode == CPUID_VMWARE_FEATURES_ECX_VMMCALL)
> diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
> index e24c05ab4fae..ff173052cdce 100644
> --- a/arch/x86/kernel/jailhouse.c
> +++ b/arch/x86/kernel/jailhouse.c
> @@ -255,7 +255,6 @@ static void __init jailhouse_init_platform(void)
> pr_debug("Jailhouse: PM-Timer IO Port: %#x\n", pmtmr_ioport);
>
> precalibrated_tsc_khz = setup_data.v1.tsc_khz;
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
>
> pci_probe = 0;
>
> diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
> index 4f8299303a19..35a879d33e9e 100644
> --- a/arch/x86/kernel/kvmclock.c
> +++ b/arch/x86/kernel/kvmclock.c
> @@ -138,7 +138,6 @@ static inline void kvm_sched_clock_init(bool stable)
> */
> static unsigned int __init kvm_get_tsc_khz(void)
> {
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> return pvclock_tsc_khz(this_cpu_pvti());
> }
>
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 1dca9464b41c..676910292af7 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -1541,11 +1541,18 @@ void __init tsc_early_init(void)
> if (!known_tsc_khz && x86_init.hyper.get_tsc_khz)
> known_tsc_khz = x86_init.hyper.get_tsc_khz();
>
> + /*
> + * Mark the TSC frequency as known if it was obtained from a hypervisor
> + * or trusted firmware.
> + */
> + if (known_tsc_khz)
> + setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> +
> /*
> * Ignore the user-provided TSC frequency if the exact frequency was
> - * obtained from trusted firmware or the hypervisor, as the user-
> - * provided frequency is intended as a "starting point", not a known,
> - * guaranteed frequency.
> + * obtained from trusted firmware or the hypervisor, and don't mark the
> + * frequency as known, as the user-provided frequency is intended as a
> + * "starting point", not a known, guaranteed frequency
> */
> if (!known_tsc_khz)
> known_tsc_khz = tsc_early_khz;
> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
> index 1adb44fdddb2..487ad838c441 100644
> --- a/arch/x86/xen/time.c
> +++ b/arch/x86/xen/time.c
> @@ -43,7 +43,6 @@ static unsigned int __init xen_tsc_khz(void)
> struct pvclock_vcpu_time_info *info =
> &HYPERVISOR_shared_info->vcpu_info[0].time;
>
> - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> return pvclock_tsc_khz(info);
> }
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* RE: [PATCH v5 36/51] x86/paravirt: Pass sched_clock save/restore helpers during registration
From: Michael Kelley @ 2026-07-02 17:48 UTC (permalink / raw)
To: Sean Christopherson, Jonathan Corbet, Paolo Bonzini,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86@kernel.org, Kiryl Shutsemau, Rick Edgecombe, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
Juergen Gross, Daniel Lezcano, John Stultz
Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
xen-devel@lists.xenproject.org, Tom Lendacky, Nikunj A Dadhania,
David Woodhouse, David Woodhouse, Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-37-seanjc@google.com>
From: Sean Christopherson <seanjc@google.com> Sent: Wednesday, July 1, 2026 12:32 PM
>
> Pass in a PV clock's save/restore helpers when configuring sched_clock
> instead of relying on each PV clock to manually set the save/restore hooks.
> In addition to bringing sanity to the code, this will allow gracefully
> "rejecting" a PV sched_clock, e.g. when running as a CoCo guest that has
> access to a "secure" TSC.
>
> No functional change intended.
>
> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
For the Hyper-V changes,
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
> ---
> arch/x86/include/asm/timer.h | 9 ++++++---
> arch/x86/kernel/cpu/vmware.c | 8 +++-----
> arch/x86/kernel/kvmclock.c | 6 +++---
> arch/x86/kernel/tsc.c | 5 ++++-
> arch/x86/xen/time.c | 5 ++---
> drivers/clocksource/hyperv_timer.c | 6 ++----
> 6 files changed, 20 insertions(+), 19 deletions(-)
>
> diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
> index fe41d40a9ae6..e97cd1ae03d1 100644
> --- a/arch/x86/include/asm/timer.h
> +++ b/arch/x86/include/asm/timer.h
> @@ -14,11 +14,14 @@ extern int no_timer_check;
> extern bool using_native_sched_clock(void);
>
> #ifdef CONFIG_PARAVIRT
> -void __paravirt_set_sched_clock(u64 (*func)(void), bool stable);
> +void __paravirt_set_sched_clock(u64 (*func)(void), bool stable,
> + void (*save)(void), void (*restore)(void));
>
> -static inline void paravirt_set_sched_clock(u64 (*func)(void))
> +static inline void paravirt_set_sched_clock(u64 (*func)(void),
> + void (*save)(void),
> + void (*restore)(void))
> {
> - __paravirt_set_sched_clock(func, true);
> + __paravirt_set_sched_clock(func, true, save, restore);
> }
> #endif
>
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 5c1ccaf4a25e..232255279a6e 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -347,11 +347,9 @@ static void __init vmware_paravirt_ops_setup(void)
>
> vmware_cyc2ns_setup();
>
> - if (vmw_sched_clock) {
> - paravirt_set_sched_clock(vmware_sched_clock);
> - x86_platform.save_sched_clock_state = x86_init_noop;
> - x86_platform.restore_sched_clock_state = x86_init_noop;
> - }
> + if (vmw_sched_clock)
> + paravirt_set_sched_clock(vmware_sched_clock,
> + x86_init_noop, x86_init_noop);
>
> if (vmware_is_stealclock_available()) {
> has_steal_clock = true;
> diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
> index 07e875738c39..5b9955343199 100644
> --- a/arch/x86/kernel/kvmclock.c
> +++ b/arch/x86/kernel/kvmclock.c
> @@ -158,7 +158,9 @@ static void kvm_restore_sched_clock_state(void)
> static inline void kvm_sched_clock_init(bool stable)
> {
> kvm_sched_clock_offset = kvm_clock_read();
> - __paravirt_set_sched_clock(kvm_sched_clock_read, stable);
> + __paravirt_set_sched_clock(kvm_sched_clock_read, stable,
> + kvm_save_sched_clock_state,
> + kvm_restore_sched_clock_state);
>
> pr_info("kvm-clock: using sched offset of %llu cycles",
> kvm_sched_clock_offset);
> @@ -367,8 +369,6 @@ void __init kvmclock_init(bool prefer_tsc)
> #ifdef CONFIG_SMP
> x86_cpuinit.early_percpu_clock_init = kvm_setup_secondary_clock;
> #endif
> - x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
> - x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
> kvm_get_preset_lpj();
>
> /*
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 7473dcab4775..83353d643150 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -280,12 +280,15 @@ bool using_native_sched_clock(void)
> return static_call_query(pv_sched_clock) == native_sched_clock;
> }
>
> -void __paravirt_set_sched_clock(u64 (*func)(void), bool stable)
> +void __paravirt_set_sched_clock(u64 (*func)(void), bool stable,
> + void (*save)(void), void (*restore)(void))
> {
> if (!stable)
> clear_sched_clock_stable();
>
> static_call_update(pv_sched_clock, func);
> + x86_platform.save_sched_clock_state = save;
> + x86_platform.restore_sched_clock_state = restore;
> }
> #else
> u64 sched_clock_noinstr(void) __attribute__((alias("native_sched_clock")));
> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
> index 477441752f40..8cd8bfaf1320 100644
> --- a/arch/x86/xen/time.c
> +++ b/arch/x86/xen/time.c
> @@ -566,13 +566,12 @@ static void __init xen_init_time_common(void)
> {
> xen_sched_clock_offset = xen_clocksource_read();
> static_call_update(pv_steal_clock, xen_steal_clock);
> - paravirt_set_sched_clock(xen_sched_clock);
> +
> /*
> * Xen has paravirtualized suspend/resume and so doesn't use the common
> * x86 sched_clock save/restore hooks.
> */
> - x86_platform.save_sched_clock_state = x86_init_noop;
> - x86_platform.restore_sched_clock_state = x86_init_noop;
> + paravirt_set_sched_clock(xen_sched_clock, x86_init_noop, x86_init_noop);
>
> x86_init.hyper.get_tsc_khz = xen_tsc_khz;
> x86_platform.get_wallclock = xen_get_wallclock;
> diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
> index 220668207d19..8ee7a9de0f4f 100644
> --- a/drivers/clocksource/hyperv_timer.c
> +++ b/drivers/clocksource/hyperv_timer.c
> @@ -570,10 +570,8 @@ static void hv_restore_sched_clock_state(void)
> static __always_inline void hv_setup_sched_clock(void *sched_clock)
> {
> /* We're on x86/x64 *and* using PV ops */
> - paravirt_set_sched_clock(sched_clock);
> -
> - x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
> - x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
> + paravirt_set_sched_clock(sched_clock, hv_save_sched_clock_state,
> + hv_restore_sched_clock_state);
> }
> #else /* !CONFIG_GENERIC_SCHED_CLOCK && !CONFIG_PARAVIRT */
> static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* RE: [PATCH v5 47/51] x86/paravirt: Don't use a PV sched_clock in CoCo guests with trusted TSC
From: Michael Kelley @ 2026-07-02 17:48 UTC (permalink / raw)
To: Sean Christopherson, Jonathan Corbet, Paolo Bonzini,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86@kernel.org, Kiryl Shutsemau, Rick Edgecombe, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
Juergen Gross, Daniel Lezcano, John Stultz
Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
xen-devel@lists.xenproject.org, Tom Lendacky, Nikunj A Dadhania,
David Woodhouse, David Woodhouse, Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-48-seanjc@google.com>
From: Sean Christopherson <seanjc@google.com> Sent: Wednesday, July 1, 2026 12:32 PM
>
> Silently ignore attempts to switch to a paravirt sched_clock when running
> as a CoCo guest with trusted TSC. In hand-wavy theory, a misbehaving
> hypervisor could attack the guest by manipulating the PV clock to affect
> guest scheduling in some weird and/or predictable way. More importantly,
> reading TSC on such platforms is faster than any PV clock, and sched_clock
> is all about speed.
>
> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/kernel/tsc.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 012321fed5e5..a146fc7b5e74 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -283,6 +283,15 @@ bool using_native_sched_clock(void)
> int __init __paravirt_set_sched_clock(u64 (*func)(void), bool stable,
> void (*save)(void), void (*restore)(void))
> {
> + /*
> + * Don't replace TSC with a PV clock when running as a CoCo guest and
> + * the TSC is secure/trusted; PV clocks are emulated by the hypervisor,
> + * which isn't in the guest's TCB.
> + */
> + if (cc_platform_has(CC_ATTR_GUEST_SNP_SECURE_TSC) ||
> + boot_cpu_has(X86_FEATURE_TDX_GUEST))
> + return -EPERM;
Do a pr_warn() in the error case? Your commit message says to
do the ignore silently, but I wonder if that's a good idea. At least
for Hyper-V, the error case shouldn't happen.
Michael
> +
> if (!stable)
> clear_sched_clock_stable();
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
^ permalink raw reply
* Re: [PATCH v2 0/4] virtio_balloon: quiesce balloon work on device shutdown
From: Denis V. Lunev @ 2026-07-02 17:50 UTC (permalink / raw)
To: Denis V. Lunev, mst, david; +Cc: virtualization, linux-kernel
In-Reply-To: <20260624140846.2616797-1-den@openvz.org>
On 6/24/26 16:08, Denis V. Lunev wrote:
> This email originated from an IP that might not be authorized by the domain it was sent from.
> Do not click links or open attachments unless it is an email you expected to receive.
> Since commit 8bd2fa086a04 ("virtio: break and reset virtio devices on
> device_shutdown()") the virtio bus breaks and resets every virtio device
> during device_shutdown(), i.e. on reboot and kexec. virtio_balloon has no
> .shutdown of its own, so that generic path runs while the balloon's
> asynchronous work is still armed: the free page reporting worker, the
> inflate/deflate and stats workers, the OOM notifier and the free page
> shrinker.
>
> Once the device has been broken, virtqueue_add_inbuf() in
> virtballoon_free_page_report() returns -EIO and trips its WARN_ON_ONCE().
> On a kernel booted with panic_on_warn that turns an ordinary reboot into a
> fatal panic in the middle of device_shutdown(), so the machine never
> reaches the new kernel. The inflate/deflate and OOM paths do not warn but
> are no better off: they call wait_event(vb->acked, ...) and would block
> forever on a queue that can no longer complete.
>
> This was hit in the field as an intermittent failure of a virtualization
> cluster upgrade: guest storage nodes were rebooted via kexec into the new
> kernel, and the ones whose free page reporting happened to run during
> device_shutdown() panicked (the guests run with panic_on_warn) and never
> came back, stalling the rolling upgrade. The crash dump showed the WARN at
> virtio_balloon.c:216 in a page_reporting kworker, with all the balloon
> virtqueues already broken.
>
> Validated by churning balloon inflate/deflate from the host while
> kexec-rebooting the guest in a loop under panic_on_warn: the unpatched
> kernel reproduces the WARN within a couple of cycles, while the patched
> kernel survives many consecutive kexec cycles cleanly (12/12 in the final
> run, 0 WARNs). checkpatch is clean across the series.
>
> Changes in v2:
> - Add a virtio_device_shutdown() core helper and call it from the balloon
> .shutdown handler instead of open-coding break + synchronize_cbs + reset
> (David Hildenbrand).
> - New patch: make tell_host() warn and bail instead of hanging if a buffer
> add ever fails (David Hildenbrand); kept as a separate patch
> (Michael S. Tsirkin).
>
> v1: https://lore.kernel.org/all/20260622133715.3707707-1-den@openvz.org
>
> Denis V. Lunev (4):
> virtio: add virtio_device_shutdown() helper
> virtio_balloon: factor out virtballoon_quiesce()
> virtio_balloon: quiesce balloon work before device shutdown
> virtio_balloon: warn on failed buffer add in tell_host()
>
> drivers/virtio/virtio.c | 41 ++++++++++++++++++++++-----------
> drivers/virtio/virtio_balloon.c | 40 ++++++++++++++++++++++++--------
> include/linux/virtio.h | 1 +
> 3 files changed, 59 insertions(+), 23 deletions(-)
>
Hi, David!
Is this good to go in? I have not seen the confirmation that the
series is taken into your tree.
Thank you in advance,
Den
^ permalink raw reply
* [PATCH v3] drm/vblank: Don't arm vblank timer with invalid frame duration
From: Roman Ilin @ 2026-07-02 18:10 UTC (permalink / raw)
To: Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard, David Airlie,
Simona Vetter
Cc: Louis Chauvet, Javier Martinez Canillas, Dmitry Osipenko,
dri-devel, virtualization, linux-kernel, Ville Syrjälä,
Thorsten Leemhuis, Peter Arnesen, Roman Ilin
In-Reply-To: <20260613224434.96501-1-me@romanilin.is>
When a CRTC's display mode carries a too small pixel clock,
drm_calc_timestamping_constants() computes a frame duration that
exceeds INT_MAX. drm_vblank_crtc.framedur_ns becomes negative.
drm_crtc_vblank_start_timer() then arms the vblank hrtimer with this
interval, after which vblank events are no longer delivered. Pending
page flips never complete and the display appears frozen.
This could be triggered on virtio-gpu guests that have dynamic resolution
enabled: when the SPICE agent or the X server resizes the output, it
submits a mode whose pixel clock is off by a factor of 1000, e.g.:
clock = 406 kHz, htotal = 3152, vtotal = 2148
framedur_ns = 3152 * 2148 * 1000000 / 406 = 16675852216 ns (~16.7 s)
16675852216 does not fit into an int and wraps to roughly -504000000.
ns_to_ktime() then yields a negative interval and the timer stops working.
Found by bisection, which pointed at commit a036f5fceedb ("drm/virtgpu:
Use vblank timer"). That commit merely made virtio-gpu use the vblank
timer and thereby exposed the pre-existing problem in the timer setup
added by commit 74afeb812850 ("drm/vblank: Add vblank timer").
To fix this, modify drm_calc_timestamping_constants() to use u64 for
calculations, check for INT_MAX overflows, and return an error code.
drm_crtc_vblank_start_timer() will then propagate the error, enabling
the driver to fall back to immediate vblank events. Valid modes are
unaffected, and the timer self-heals on the next mode with a sane clock.
Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Roman Ilin <me@romanilin.is>
---
Changes in v3:
- Changed the WARN_ON_ONCE to drm_err_once
Notes:
drivers/gpu/drm/drm_vblank.c | 71 +++++++++++++++++++++++-------------
include/drm/drm_vblank.h | 4 +-
2 files changed, 48 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index f90fb2d13..629b9fcc7 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -631,42 +631,51 @@ EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
* drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from
* CRTC's true scanout timing, so they take things like panel scaling or
* other adjustments into account.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
*/
-void drm_calc_timestamping_constants(struct drm_crtc *crtc,
- const struct drm_display_mode *mode)
+int drm_calc_timestamping_constants(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
{
struct drm_device *dev = crtc->dev;
unsigned int pipe = drm_crtc_index(crtc);
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
- int linedur_ns = 0, framedur_ns = 0;
+ u64 linedur_ns, framedur_ns;
int dotclock = mode->crtc_clock;
+ unsigned int frame_size;
if (!drm_dev_has_vblank(dev))
- return;
+ return 0;
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
- return;
+ return -EINVAL;
- /* Valid dotclock? */
- if (dotclock > 0) {
- int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
+ if (dotclock <= 0) {
+ drm_err(dev, "crtc %u: Can't calculate constants, dotclock = %d!\n",
+ crtc->base.id, dotclock);
+ goto error;
+ }
- /*
- * Convert scanline length in pixels and video
- * dot clock to line duration and frame duration
- * in nanoseconds:
- */
- linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
- framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
+ frame_size = (unsigned int)mode->crtc_htotal * (unsigned int)mode->crtc_vtotal;
- /*
- * Fields of interlaced scanout modes are only half a frame duration.
- */
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- framedur_ns /= 2;
- } else {
- drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
- crtc->base.id);
+ /*
+ * Convert scanline length in pixels and video dot clock to line duration
+ * and frame duration in nanoseconds.
+ */
+ linedur_ns = div_u64((u64)mode->crtc_htotal * 1000000, dotclock);
+ framedur_ns = div_u64((u64)frame_size * 1000000, dotclock);
+
+ /*
+ * Fields of interlaced scanout modes are only half a frame duration.
+ */
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ framedur_ns /= 2;
+
+ if (linedur_ns > INT_MAX || framedur_ns > INT_MAX) {
+ drm_dbg_kms(dev, "crtc %u: Can't calculate constants, mode clock too small!\n",
+ crtc->base.id);
+ goto error;
}
vblank->linedur_ns = linedur_ns;
@@ -678,7 +687,16 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
crtc->base.id, mode->crtc_htotal,
mode->crtc_vtotal, mode->crtc_vdisplay);
drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
- crtc->base.id, dotclock, framedur_ns, linedur_ns);
+ crtc->base.id, dotclock,
+ vblank->framedur_ns, vblank->linedur_ns);
+
+ return 0;
+
+error:
+ vblank->linedur_ns = 0;
+ vblank->framedur_ns = 0;
+ drm_mode_copy(&vblank->hwmode, mode);
+ return -EINVAL;
}
EXPORT_SYMBOL(drm_calc_timestamping_constants);
@@ -2221,6 +2239,7 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
unsigned long flags;
+ int ret;
if (!vtimer->crtc) {
/*
@@ -2239,7 +2258,9 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
hrtimer_try_to_cancel(&vtimer->timer);
}
- drm_calc_timestamping_constants(crtc, &crtc->mode);
+ ret = drm_calc_timestamping_constants(crtc, &crtc->mode);
+ if (ret)
+ return ret;
spin_lock_irqsave(&vtimer->interval_lock, flags);
vtimer->interval = ns_to_ktime(vblank->framedur_ns);
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 2fcef9c0f..d99772dfa 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -311,8 +311,8 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc);
u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
void drm_crtc_vblank_restore(struct drm_crtc *crtc);
-void drm_calc_timestamping_constants(struct drm_crtc *crtc,
- const struct drm_display_mode *mode);
+int drm_calc_timestamping_constants(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode);
wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
u32 max_vblank_count);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v3] drm/vblank: Don't arm vblank timer with invalid frame duration
From: Roman Ilin @ 2026-07-02 18:23 UTC (permalink / raw)
To: Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard, David Airlie,
Simona Vetter
Cc: Louis Chauvet, Javier Martinez Canillas, Dmitry Osipenko,
dri-devel, virtualization, linux-kernel, Ville Syrjälä,
Thorsten Leemhuis, Peter Arnesen
In-Reply-To: <20260702181027.98526-1-me@romanilin.is>
Apologies, I accidentally fired off send-email before saving my final
changelog notes. Please ignore the changelog and notes in the original
v3 email.
The actual changes in v3 are:
- Changed the WARN_ON_ONCE to drm_dbg_kms (to avoid user-triggerable
panics).
- Updated drm_calc_timestamping_constants with the goto error fallback
to clear the stale state.
Also, an automated review bot pointed out an AB-BA deadlock in
drm_crtc_vblank_start_timer(). But I am leaving this out of the patch to
keep the fixes orthogonal.
Sorry for the noise.
> On Jul 2, 2026, at 21:10, Roman Ilin <me@romanilin.is> wrote:
>
> When a CRTC's display mode carries a too small pixel clock,
> drm_calc_timestamping_constants() computes a frame duration that
> exceeds INT_MAX. drm_vblank_crtc.framedur_ns becomes negative.
> drm_crtc_vblank_start_timer() then arms the vblank hrtimer with this
> interval, after which vblank events are no longer delivered. Pending
> page flips never complete and the display appears frozen.
>
> This could be triggered on virtio-gpu guests that have dynamic resolution
> enabled: when the SPICE agent or the X server resizes the output, it
> submits a mode whose pixel clock is off by a factor of 1000, e.g.:
>
> clock = 406 kHz, htotal = 3152, vtotal = 2148
>
> framedur_ns = 3152 * 2148 * 1000000 / 406 = 16675852216 ns (~16.7 s)
>
> 16675852216 does not fit into an int and wraps to roughly -504000000.
> ns_to_ktime() then yields a negative interval and the timer stops working.
>
> Found by bisection, which pointed at commit a036f5fceedb ("drm/virtgpu:
> Use vblank timer"). That commit merely made virtio-gpu use the vblank
> timer and thereby exposed the pre-existing problem in the timer setup
> added by commit 74afeb812850 ("drm/vblank: Add vblank timer").
>
> To fix this, modify drm_calc_timestamping_constants() to use u64 for
> calculations, check for INT_MAX overflows, and return an error code.
> drm_crtc_vblank_start_timer() will then propagate the error, enabling
> the driver to fall back to immediate vblank events. Valid modes are
> unaffected, and the timer self-heals on the next mode with a sane clock.
>
> Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
> Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
> Signed-off-by: Roman Ilin <me@romanilin.is>
> ---
> Changes in v3:
>
> - Changed the WARN_ON_ONCE to drm_err_once
>
> Notes:
>
>
>
> drivers/gpu/drm/drm_vblank.c | 71 +++++++++++++++++++++++-------------
> include/drm/drm_vblank.h | 4 +-
> 2 files changed, 48 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
> index f90fb2d13..629b9fcc7 100644
> --- a/drivers/gpu/drm/drm_vblank.c
> +++ b/drivers/gpu/drm/drm_vblank.c
> @@ -631,42 +631,51 @@ EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
> * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from
> * CRTC's true scanout timing, so they take things like panel scaling or
> * other adjustments into account.
> + *
> + * Returns:
> + * 0 on success, or a negative errno code otherwise.
> */
> -void drm_calc_timestamping_constants(struct drm_crtc *crtc,
> - const struct drm_display_mode *mode)
> +int drm_calc_timestamping_constants(struct drm_crtc *crtc,
> + const struct drm_display_mode *mode)
> {
> struct drm_device *dev = crtc->dev;
> unsigned int pipe = drm_crtc_index(crtc);
> struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
> - int linedur_ns = 0, framedur_ns = 0;
> + u64 linedur_ns, framedur_ns;
> int dotclock = mode->crtc_clock;
> + unsigned int frame_size;
>
> if (!drm_dev_has_vblank(dev))
> - return;
> + return 0;
>
> if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
> - return;
> + return -EINVAL;
>
> - /* Valid dotclock? */
> - if (dotclock > 0) {
> - int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
> + if (dotclock <= 0) {
> + drm_err(dev, "crtc %u: Can't calculate constants, dotclock = %d!\n",
> + crtc->base.id, dotclock);
> + goto error;
> + }
>
> - /*
> - * Convert scanline length in pixels and video
> - * dot clock to line duration and frame duration
> - * in nanoseconds:
> - */
> - linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
> - framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
> + frame_size = (unsigned int)mode->crtc_htotal * (unsigned int)mode->crtc_vtotal;
>
> - /*
> - * Fields of interlaced scanout modes are only half a frame duration.
> - */
> - if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> - framedur_ns /= 2;
> - } else {
> - drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
> - crtc->base.id);
> + /*
> + * Convert scanline length in pixels and video dot clock to line duration
> + * and frame duration in nanoseconds.
> + */
> + linedur_ns = div_u64((u64)mode->crtc_htotal * 1000000, dotclock);
> + framedur_ns = div_u64((u64)frame_size * 1000000, dotclock);
> +
> + /*
> + * Fields of interlaced scanout modes are only half a frame duration.
> + */
> + if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> + framedur_ns /= 2;
> +
> + if (linedur_ns > INT_MAX || framedur_ns > INT_MAX) {
> + drm_dbg_kms(dev, "crtc %u: Can't calculate constants, mode clock too small!\n",
> + crtc->base.id);
> + goto error;
> }
>
> vblank->linedur_ns = linedur_ns;
> @@ -678,7 +687,16 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
> crtc->base.id, mode->crtc_htotal,
> mode->crtc_vtotal, mode->crtc_vdisplay);
> drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
> - crtc->base.id, dotclock, framedur_ns, linedur_ns);
> + crtc->base.id, dotclock,
> + vblank->framedur_ns, vblank->linedur_ns);
> +
> + return 0;
> +
> +error:
> + vblank->linedur_ns = 0;
> + vblank->framedur_ns = 0;
> + drm_mode_copy(&vblank->hwmode, mode);
> + return -EINVAL;
> }
> EXPORT_SYMBOL(drm_calc_timestamping_constants);
>
> @@ -2221,6 +2239,7 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
> struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
> struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
> unsigned long flags;
> + int ret;
>
> if (!vtimer->crtc) {
> /*
> @@ -2239,7 +2258,9 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
> hrtimer_try_to_cancel(&vtimer->timer);
> }
>
> - drm_calc_timestamping_constants(crtc, &crtc->mode);
> + ret = drm_calc_timestamping_constants(crtc, &crtc->mode);
> + if (ret)
> + return ret;
>
> spin_lock_irqsave(&vtimer->interval_lock, flags);
> vtimer->interval = ns_to_ktime(vblank->framedur_ns);
> diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
> index 2fcef9c0f..d99772dfa 100644
> --- a/include/drm/drm_vblank.h
> +++ b/include/drm/drm_vblank.h
> @@ -311,8 +311,8 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc);
> u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
> void drm_crtc_vblank_restore(struct drm_crtc *crtc);
>
> -void drm_calc_timestamping_constants(struct drm_crtc *crtc,
> - const struct drm_display_mode *mode);
> +int drm_calc_timestamping_constants(struct drm_crtc *crtc,
> + const struct drm_display_mode *mode);
> wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
> void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
> u32 max_vblank_count);
> --
> 2.54.0
>
^ permalink raw reply
* Re: [PATCH v2 0/4] virtio_balloon: quiesce balloon work on device shutdown
From: David Hildenbrand (Arm) @ 2026-07-02 19:30 UTC (permalink / raw)
To: Denis V. Lunev, Denis V. Lunev, mst; +Cc: virtualization, linux-kernel
In-Reply-To: <c18ed056-72f3-4eab-a370-c02b735e536e@virtuozzo.com>
On 7/2/26 19:50, Denis V. Lunev wrote:
> On 6/24/26 16:08, Denis V. Lunev wrote:
>> This email originated from an IP that might not be authorized by the domain it was sent from.
>> Do not click links or open attachments unless it is an email you expected to receive.
>> Since commit 8bd2fa086a04 ("virtio: break and reset virtio devices on
>> device_shutdown()") the virtio bus breaks and resets every virtio device
>> during device_shutdown(), i.e. on reboot and kexec. virtio_balloon has no
>> .shutdown of its own, so that generic path runs while the balloon's
>> asynchronous work is still armed: the free page reporting worker, the
>> inflate/deflate and stats workers, the OOM notifier and the free page
>> shrinker.
>>
>> Once the device has been broken, virtqueue_add_inbuf() in
>> virtballoon_free_page_report() returns -EIO and trips its WARN_ON_ONCE().
>> On a kernel booted with panic_on_warn that turns an ordinary reboot into a
>> fatal panic in the middle of device_shutdown(), so the machine never
>> reaches the new kernel. The inflate/deflate and OOM paths do not warn but
>> are no better off: they call wait_event(vb->acked, ...) and would block
>> forever on a queue that can no longer complete.
>>
>> This was hit in the field as an intermittent failure of a virtualization
>> cluster upgrade: guest storage nodes were rebooted via kexec into the new
>> kernel, and the ones whose free page reporting happened to run during
>> device_shutdown() panicked (the guests run with panic_on_warn) and never
>> came back, stalling the rolling upgrade. The crash dump showed the WARN at
>> virtio_balloon.c:216 in a page_reporting kworker, with all the balloon
>> virtqueues already broken.
>>
>> Validated by churning balloon inflate/deflate from the host while
>> kexec-rebooting the guest in a loop under panic_on_warn: the unpatched
>> kernel reproduces the WARN within a couple of cycles, while the patched
>> kernel survives many consecutive kexec cycles cleanly (12/12 in the final
>> run, 0 WARNs). checkpatch is clean across the series.
>>
>> Changes in v2:
>> - Add a virtio_device_shutdown() core helper and call it from the balloon
>> .shutdown handler instead of open-coding break + synchronize_cbs + reset
>> (David Hildenbrand).
>> - New patch: make tell_host() warn and bail instead of hanging if a buffer
>> add ever fails (David Hildenbrand); kept as a separate patch
>> (Michael S. Tsirkin).
>>
>> v1: https://lore.kernel.org/all/20260622133715.3707707-1-den@openvz.org
>>
>> Denis V. Lunev (4):
>> virtio: add virtio_device_shutdown() helper
>> virtio_balloon: factor out virtballoon_quiesce()
>> virtio_balloon: quiesce balloon work before device shutdown
>> virtio_balloon: warn on failed buffer add in tell_host()
>>
>> drivers/virtio/virtio.c | 41 ++++++++++++++++++++++-----------
>> drivers/virtio/virtio_balloon.c | 40 ++++++++++++++++++++++++--------
>> include/linux/virtio.h | 1 +
>> 3 files changed, 59 insertions(+), 23 deletions(-)
>>
> Hi, David!
Hi! :)
>
> Is this good to go in? I have not seen the confirmation that the
> series is taken into your tree.
I don't have a tree (yet), and once I have one it will likely be more mm focused :)
@MST, I think this is good to go!
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH net 1/2] vsock/virtio: collapse receive queue under memory pressure
From: Bobby Eshleman @ 2026-07-02 20:09 UTC (permalink / raw)
To: Stefano Garzarella
Cc: netdev, Jason Wang, Jakub Kicinski, Paolo Abeni,
Michael S. Tsirkin, kvm, virtualization, Xuan Zhuo, Eric Dumazet,
Simon Horman, linux-kernel, Stefan Hajnoczi, David S. Miller,
Eugenio Pérez, stable, Brien Oberstein
In-Reply-To: <akYl38_9Y4ydXuqE@sgarzare-redhat>
On Thu, Jul 02, 2026 at 10:56:04AM +0200, Stefano Garzarella wrote:
> On Wed, Jul 01, 2026 at 09:34:35AM -0700, Bobby Eshleman wrote:
> > On Fri, Jun 26, 2026 at 03:48:22PM +0200, Stefano Garzarella wrote:
>
> [...]
>
> > > +out:
> > > + if (new_skb)
> > > + __skb_queue_tail(&new_queue, new_skb);
> > > +
> > > + skb_queue_splice(&new_queue, &vvs->rx_queue);
> >
> > I think the new skbs will also need skb_set_owner_sk_safe(skb, sk)
> > when adding to rx_queue?
>
> IIRC we added it in the rx path, mainily for loopback to pass the ownership
> from the tx socket to the rx socket, but here we are already in the rx path,
> so the skb will never leave this socket.
>
Ah that's right, I stand corrected. There is no sender to leak in this
case.
> Maybe it's necessary for the eBPF path?
Looking through sockmap, I don't think it depends on skb->sk being
non-null either (it reassigns owner to the redirect socket anyway using
skb_set_owner_r()).
Sorry for the false alarm. LGTM.
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox