* [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking
@ 2026-05-26 15:05 Juergen Gross
2026-05-26 15:05 ` [PATCH 1/5] x86/xen: Drop lazy mode from trace entries Juergen Gross
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Juergen Gross @ 2026-05-26 15:05 UTC (permalink / raw)
To: linux-kernel, x86, linux-trace-kernel, linux-mm, virtualization
Cc: Juergen Gross, Boris Ostrovsky, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, xen-devel, Andrew Morton,
David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Ajay Kaher, Alexey Makhalov,
Broadcom internal kernel review list
With generic lazy MMU mode tracking being available, there is no real
need for having Xen PV specific code to track lazy MMU mode, too.
This makes it possible to drop two paravirt hooks.
Note that this series is based on my series "x86/xen: Do some Xen-PV
related cleanups" [1].
[1]: https://lore.kernel.org/lkml/20260522152114.77319-1-jgross@suse.com/
Juergen Gross (5):
x86/xen: Drop lazy mode from trace entries
x86/xen: Change interface of xen_mc_issue()
mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume()
x86/xen: Get rid of last XEN_LAZY_MMU uses
x86/xen: Replace generic lazy tracking with cpu specific one
arch/x86/include/asm/paravirt.h | 9 ++--
arch/x86/include/asm/paravirt_types.h | 11 +----
arch/x86/include/asm/xen/hypervisor.h | 25 +---------
arch/x86/kernel/paravirt.c | 6 +--
arch/x86/xen/enlighten_pv.c | 30 +++++-------
arch/x86/xen/mmu_pv.c | 66 +++++++++------------------
arch/x86/xen/xen-ops.h | 12 +++--
include/linux/pgtable.h | 56 ++++++++++++++++++-----
include/trace/events/xen.h | 33 ++++++++------
9 files changed, 112 insertions(+), 136 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] x86/xen: Drop lazy mode from trace entries
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
@ 2026-05-26 15:05 ` Juergen Gross
2026-05-26 15:05 ` [PATCH 2/5] x86/xen: Change interface of xen_mc_issue() Juergen Gross
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Juergen Gross @ 2026-05-26 15:05 UTC (permalink / raw)
To: linux-kernel, x86, linux-trace-kernel
Cc: Juergen Gross, Boris Ostrovsky, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, xen-devel
Drop the lazy mode (cpu or mmu) from the xen_mc_batch and xen_mc_issue
trace entries.
This is done in preparation of removing the xen_lazy_mode percpu
variable.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/xen/xen-ops.h | 11 +++++++----
include/trace/events/xen.h | 33 +++++++++++++++++++--------------
2 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 6808010ac379..dc892f421f25 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -98,7 +98,7 @@ static inline void xen_mc_batch(void)
/* need to disable interrupts until this entry is complete */
local_irq_save(flags);
- trace_xen_mc_batch(xen_get_lazy_mode());
+ trace_xen_mc_batch(flags);
__this_cpu_write(xen_mc_irq_flags, flags);
}
@@ -114,13 +114,16 @@ void xen_mc_flush(void);
/* Issue a multicall if we're not in a lazy mode */
static inline void xen_mc_issue(unsigned mode)
{
- trace_xen_mc_issue(mode);
+ bool flush = !(xen_get_lazy_mode() & mode);
+ unsigned long flags = this_cpu_read(xen_mc_irq_flags);
- if ((xen_get_lazy_mode() & mode) == 0)
+ trace_xen_mc_issue(flush, flags);
+
+ if (flush)
xen_mc_flush();
/* restore flags saved in xen_mc_batch */
- local_irq_restore(this_cpu_read(xen_mc_irq_flags));
+ local_irq_restore(flags);
}
/* Set up a callback to be called when the current batch is flushed */
diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h
index e3f139f0bc78..ad384969e2cb 100644
--- a/include/trace/events/xen.h
+++ b/include/trace/events/xen.h
@@ -12,24 +12,29 @@
struct multicall_entry;
/* Multicalls */
-DECLARE_EVENT_CLASS(xen_mc__batch,
- TP_PROTO(enum xen_lazy_mode mode),
- TP_ARGS(mode),
+TRACE_EVENT(xen_mc_batch,
+ TP_PROTO(unsigned long flags),
+ TP_ARGS(flags),
TP_STRUCT__entry(
- __field(enum xen_lazy_mode, mode)
+ __field(unsigned long, flags)
),
- TP_fast_assign(__entry->mode = mode),
- TP_printk("start batch LAZY_%s",
- (__entry->mode == XEN_LAZY_MMU) ? "MMU" :
- (__entry->mode == XEN_LAZY_CPU) ? "CPU" : "NONE")
+ TP_fast_assign(__entry->flags = flags),
+ TP_printk("start batch lazy flags %lx", __entry->flags)
);
-#define DEFINE_XEN_MC_BATCH(name) \
- DEFINE_EVENT(xen_mc__batch, name, \
- TP_PROTO(enum xen_lazy_mode mode), \
- TP_ARGS(mode))
-DEFINE_XEN_MC_BATCH(xen_mc_batch);
-DEFINE_XEN_MC_BATCH(xen_mc_issue);
+TRACE_EVENT(xen_mc_issue,
+ TP_PROTO(bool flush, unsigned long flags),
+ TP_ARGS(flush, flags),
+ TP_STRUCT__entry(
+ __field(unsigned long, flags)
+ __field(bool, flush)
+ ),
+ TP_fast_assign(__entry->flush = flush;
+ __entry->flags = flags;
+ ),
+ TP_printk("flush: %s, flags %lx",
+ __entry->flush ? "yes" : "no", __entry->flags)
+ );
TRACE_DEFINE_SIZEOF(ulong);
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/5] x86/xen: Change interface of xen_mc_issue()
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
2026-05-26 15:05 ` [PATCH 1/5] x86/xen: Drop lazy mode from trace entries Juergen Gross
@ 2026-05-26 15:05 ` Juergen Gross
2026-05-26 15:05 ` [PATCH 3/5] mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume() Juergen Gross
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Juergen Gross @ 2026-05-26 15:05 UTC (permalink / raw)
To: linux-kernel, x86
Cc: Juergen Gross, Boris Ostrovsky, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, xen-devel
Today xen_mc_issue() is deciding whether to call xen_mc_flush() or not
based on the lazy mode input parameter passed.
Modify this interface to pass a boolean indicating whether the flush
should be done.
For querying lazy mmu mode use the is_lazy_mmu_mode_active() helper.
This is done in preparation for dropping the xen_lazy_mode percpu
variable.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/xen/enlighten_pv.c | 8 ++++----
arch/x86/xen/mmu_pv.c | 38 ++++++++++++++++++-------------------
arch/x86/xen/xen-ops.h | 3 +--
3 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index ed2d7a3756ce..428189f5d437 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -544,7 +544,7 @@ static void xen_set_ldt(const void *addr, unsigned entries)
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue(XEN_LAZY_CPU);
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
}
static void xen_load_gdt(const struct desc_ptr *dtr)
@@ -649,7 +649,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
load_TLS_descriptor(t, cpu, 1);
load_TLS_descriptor(t, cpu, 2);
- xen_mc_issue(XEN_LAZY_CPU);
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
}
static void xen_load_gs_index(unsigned int idx)
@@ -1011,7 +1011,7 @@ static void xen_load_sp0(unsigned long sp0)
mcs = xen_mc_entry(0);
MULTI_stack_switch(mcs.mc, __KERNEL_DS, sp0);
- xen_mc_issue(XEN_LAZY_CPU);
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
}
@@ -1071,7 +1071,7 @@ static void xen_write_cr0(unsigned long cr0)
MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0);
- xen_mc_issue(XEN_LAZY_CPU);
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
}
static void xen_write_cr4(unsigned long cr4)
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index cd80406be9c6..51dbdc67c73c 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -290,7 +290,7 @@ static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
u.val = pmd_val_ma(val);
xen_extend_mmu_update(&u);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
preempt_enable();
}
@@ -333,7 +333,7 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval)
u.val = pte_val_ma(pteval);
xen_extend_mmu_update(&u);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
return true;
}
@@ -380,7 +380,7 @@ static void xen_ptep_modify_prot_commit(struct vm_area_struct *vma,
u.val = pte_val_ma(pte);
xen_extend_mmu_update(&u);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
}
/* Assume pteval_t is equivalent to all the other *val_t types. */
@@ -474,7 +474,7 @@ static void xen_set_pud_hyper(pud_t *ptr, pud_t val)
u.val = pud_val_ma(val);
xen_extend_mmu_update(&u);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
preempt_enable();
}
@@ -557,7 +557,7 @@ static void __init xen_set_p4d_hyper(p4d_t *ptr, p4d_t val)
__xen_set_p4d_hyper(ptr, val);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
preempt_enable();
}
@@ -589,7 +589,7 @@ static void xen_set_p4d(p4d_t *ptr, p4d_t val)
if (user_ptr)
__xen_set_p4d_hyper((p4d_t *)user_ptr, val);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
}
__visible p4dval_t xen_p4d_val(p4d_t p4d)
@@ -816,7 +816,7 @@ static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
PFN_DOWN(__pa(user_pgd)));
}
- xen_mc_issue(0);
+ xen_mc_issue(true);
}
static void xen_pgd_pin(struct mm_struct *mm)
@@ -933,7 +933,7 @@ static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd)
__xen_pgd_walk(mm, pgd, xen_unpin_page, USER_LIMIT);
- xen_mc_issue(0);
+ xen_mc_issue(true);
}
static void xen_pgd_unpin(struct mm_struct *mm)
@@ -1309,7 +1309,7 @@ static noinline void xen_flush_tlb(void)
op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
preempt_enable();
}
@@ -1329,7 +1329,7 @@ static void xen_flush_tlb_one_user(unsigned long addr)
op->arg1.linear_addr = addr & PAGE_MASK;
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
preempt_enable();
}
@@ -1366,7 +1366,7 @@ static void xen_flush_tlb_multi(const struct cpumask *cpus,
MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
}
static unsigned long xen_read_cr3(void)
@@ -1425,7 +1425,7 @@ static void xen_write_cr3(unsigned long cr3)
else
__xen_write_cr3(false, 0);
- xen_mc_issue(XEN_LAZY_CPU); /* interrupts restored */
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU); /* interrupts restored */
}
/*
@@ -1460,7 +1460,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
__xen_write_cr3(true, cr3);
- xen_mc_issue(XEN_LAZY_CPU); /* interrupts restored */
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU); /* interrupts restored */
}
static int xen_pgd_alloc(struct mm_struct *mm)
@@ -1622,7 +1622,7 @@ static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn,
!pinned)
__pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
}
}
@@ -1652,7 +1652,7 @@ static inline void xen_release_ptpage(unsigned long pfn, unsigned level)
__set_pfn_prot(pfn, PAGE_KERNEL);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
ClearPagePinned(page);
}
@@ -1875,7 +1875,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
*/
xen_mc_batch();
__xen_write_cr3(true, __pa(init_top_pgt));
- xen_mc_issue(XEN_LAZY_CPU);
+ xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
/* We can't that easily rip out L3 and L2, as the Xen pagetables are
* set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ... for
@@ -2266,7 +2266,7 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order,
if (out_frames)
out_frames[i] = virt_to_pfn((void *)vaddr);
}
- xen_mc_issue(0);
+ xen_mc_issue(true);
}
/*
@@ -2309,7 +2309,7 @@ static void xen_remap_exchanged_ptes(unsigned long vaddr, int order,
set_phys_to_machine(virt_to_pfn((void *)vaddr), mfn);
}
- xen_mc_issue(0);
+ xen_mc_issue(true);
}
/*
@@ -2450,7 +2450,7 @@ static noinline void xen_flush_tlb_all(void)
op->cmd = MMUEXT_TLB_FLUSH_ALL;
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue(XEN_LAZY_MMU);
+ xen_mc_issue(!is_lazy_mmu_mode_active());
preempt_enable();
}
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index dc892f421f25..dc265bdda24d 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -112,9 +112,8 @@ static inline struct multicall_space xen_mc_entry(size_t args)
void xen_mc_flush(void);
/* Issue a multicall if we're not in a lazy mode */
-static inline void xen_mc_issue(unsigned mode)
+static inline void xen_mc_issue(bool flush)
{
- bool flush = !(xen_get_lazy_mode() & mode);
unsigned long flags = this_cpu_read(xen_mc_irq_flags);
trace_xen_mc_issue(flush, flags);
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/5] mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume()
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
2026-05-26 15:05 ` [PATCH 1/5] x86/xen: Drop lazy mode from trace entries Juergen Gross
2026-05-26 15:05 ` [PATCH 2/5] x86/xen: Change interface of xen_mc_issue() Juergen Gross
@ 2026-05-26 15:05 ` Juergen Gross
2026-06-01 15:09 ` David Hildenbrand (Arm)
2026-05-26 15:05 ` [PATCH 4/5] x86/xen: Get rid of last XEN_LAZY_MMU uses Juergen Gross
` (2 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Juergen Gross @ 2026-05-26 15:05 UTC (permalink / raw)
To: linux-kernel, linux-mm
Cc: Juergen Gross, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko
In order to allow pausing and resuming MMU lazy mode for other tasks
than current, refactor lazy_mmu_mode_pause() and
lazy_mmu_mode_resume().
This will be needed when dropping the Xen PV private lazy MMU
bookkeeping.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
include/linux/pgtable.h | 56 +++++++++++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index cdd68ed3ae1a..07483ed9b3ce 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -300,6 +300,28 @@ static inline void lazy_mmu_mode_disable(void)
}
+/**
+ * __task_lazy_mmu_mode_pause() - Pause the lazy MMU mode for a task.
+ * @tsk: The task to check.
+ *
+ * Pauses the lazy MMU mode of @tsk.
+ *
+ * This function only operates on the state saved in task_struct; to pause
+ * current lazy_mmu_mode_pause() should be used instead.
+ *
+ * This function is intended for architectures that implement the lazy MMU
+ * mode; it must not be called from generic code.
+ */
+static inline void __task_lazy_mmu_mode_pause(struct task_struct *tsk)
+{
+ struct lazy_mmu_state *state = &tsk->lazy_mmu_state;
+
+ VM_WARN_ON_ONCE(state->pause_count == U8_MAX);
+
+ if (state->pause_count++ == 0 && state->enable_count > 0)
+ arch_leave_lazy_mmu_mode();
+}
+
/**
* lazy_mmu_mode_pause() - Pause the lazy MMU mode.
*
@@ -315,15 +337,32 @@ static inline void lazy_mmu_mode_disable(void)
*/
static inline void lazy_mmu_mode_pause(void)
{
- struct lazy_mmu_state *state = ¤t->lazy_mmu_state;
-
if (in_interrupt())
return;
- VM_WARN_ON_ONCE(state->pause_count == U8_MAX);
+ __task_lazy_mmu_mode_pause(current);
+}
- if (state->pause_count++ == 0 && state->enable_count > 0)
- arch_leave_lazy_mmu_mode();
+/**
+ * __task_lazy_mmu_mode_resume() - Resume the lazy MMU mode for a task.
+ * @tsk: The task to check.
+ *
+ * Resumes the lazy MMU mode of @tsk.
+ *
+ * This function only operates on the state saved in task_struct; to resume
+ * current lazy_mmu_mode_resume() should be used instead.
+ *
+ * This function is intended for architectures that implement the lazy MMU
+ * mode; it must not be called from generic code.
+ */
+static inline void __task_lazy_mmu_mode_resume(struct task_struct *tsk)
+{
+ struct lazy_mmu_state *state = &tsk->lazy_mmu_state;
+
+ VM_WARN_ON_ONCE(state->pause_count == 0);
+
+ if (--state->pause_count == 0 && state->enable_count > 0)
+ arch_enter_lazy_mmu_mode();
}
/**
@@ -341,15 +380,10 @@ static inline void lazy_mmu_mode_pause(void)
*/
static inline void lazy_mmu_mode_resume(void)
{
- struct lazy_mmu_state *state = ¤t->lazy_mmu_state;
-
if (in_interrupt())
return;
- VM_WARN_ON_ONCE(state->pause_count == 0);
-
- if (--state->pause_count == 0 && state->enable_count > 0)
- arch_enter_lazy_mmu_mode();
+ __task_lazy_mmu_mode_resume(current);
}
#else
static inline void lazy_mmu_mode_enable(void) {}
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/5] x86/xen: Get rid of last XEN_LAZY_MMU uses
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
` (2 preceding siblings ...)
2026-05-26 15:05 ` [PATCH 3/5] mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume() Juergen Gross
@ 2026-05-26 15:05 ` Juergen Gross
2026-05-26 15:05 ` [PATCH 5/5] x86/xen: Replace generic lazy tracking with cpu specific one Juergen Gross
2026-06-01 15:08 ` [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking David Hildenbrand (Arm)
5 siblings, 0 replies; 8+ messages in thread
From: Juergen Gross @ 2026-05-26 15:05 UTC (permalink / raw)
To: linux-kernel, x86, virtualization
Cc: Juergen Gross, Ajay Kaher, Alexey Makhalov,
Broadcom internal kernel review list, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
Boris Ostrovsky, xen-devel
There are only very few use cases of XEN_LAZY_MMU left. Get rid of
them in order to avoid having to call enter_lazy(XEN_LAZY_MMU) and
leave_lazy(XEN_LAZY_MMU).
The query in xen_batched_set_pte() can be replaced by using
is_lazy_mmu_mode_active() instead.
As xen_flush_lazy_mmu() will be called only with lazy MMU mode being
active, the test for the lazy mode can just be dropped.
In xen_start_context_switch() and xen_end_context_switch() use
__task_lazy_mmu_mode_pause() and __task_lazy_mmu_mode_resume(),
allowing to drop xen_enter_lazy_mmu() and xen_leave_lazy_mmu()
completely.
Call arch_flush_lazy_mmu_mode() from arch_leave_lazy_mmu_mode(), as
this is the only required action now.
Drop the lazy mmu enter and leave paravirt hooks, leaving the flush
hook as the only needed one.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/include/asm/paravirt.h | 9 ++++-----
arch/x86/include/asm/paravirt_types.h | 11 +----------
arch/x86/kernel/paravirt.c | 6 +-----
arch/x86/xen/enlighten_pv.c | 7 ++-----
arch/x86/xen/mmu_pv.c | 28 +++------------------------
5 files changed, 11 insertions(+), 50 deletions(-)
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index cdfe4007443e..0591aa38fd85 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -483,17 +483,16 @@ static inline void arch_end_context_switch(struct task_struct *next)
static inline void arch_enter_lazy_mmu_mode(void)
{
- PVOP_VCALL0(pv_ops, mmu.lazy_mode.enter);
}
-static inline void arch_leave_lazy_mmu_mode(void)
+static inline void arch_flush_lazy_mmu_mode(void)
{
- PVOP_VCALL0(pv_ops, mmu.lazy_mode.leave);
+ PVOP_VCALL0(pv_ops, mmu.lazy_mode_flush);
}
-static inline void arch_flush_lazy_mmu_mode(void)
+static inline void arch_leave_lazy_mmu_mode(void)
{
- PVOP_VCALL0(pv_ops, mmu.lazy_mode.flush);
+ arch_flush_lazy_mmu_mode();
}
static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 4f5ae0068aab..b4c4a23e77a1 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -19,15 +19,6 @@ struct cpumask;
struct flush_tlb_info;
struct vm_area_struct;
-#ifdef CONFIG_PARAVIRT_XXL
-struct pv_lazy_ops {
- /* Set deferred update mode, used for batching operations. */
- void (*enter)(void);
- void (*leave)(void);
- void (*flush)(void);
-} __no_randomize_layout;
-#endif
-
struct pv_cpu_ops {
/* hooks for various privileged instructions */
#ifdef CONFIG_PARAVIRT_XXL
@@ -171,7 +162,7 @@ struct pv_mmu_ops {
void (*set_pgd)(pgd_t *pgdp, pgd_t pgdval);
- struct pv_lazy_ops lazy_mode;
+ void (*lazy_mode_flush)(void);
/* dom0 ops */
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 792fa96b3233..22f72034470f 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -204,11 +204,7 @@ struct paravirt_patch_template pv_ops = {
.mmu.enter_mmap = paravirt_nop,
- .mmu.lazy_mode = {
- .enter = paravirt_nop,
- .leave = paravirt_nop,
- .flush = paravirt_nop,
- },
+ .mmu.lazy_mode_flush = paravirt_nop,
.mmu.set_fixmap = native_set_fixmap,
#endif /* CONFIG_PARAVIRT_XXL */
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 428189f5d437..8ee4910d597a 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -424,9 +424,7 @@ static void xen_start_context_switch(struct task_struct *prev)
{
BUG_ON(preemptible());
- if (this_cpu_read(xen_lazy_mode) == XEN_LAZY_MMU) {
- arch_leave_lazy_mmu_mode();
- }
+ __task_lazy_mmu_mode_pause(prev);
enter_lazy(XEN_LAZY_CPU);
}
@@ -436,8 +434,7 @@ static void xen_end_context_switch(struct task_struct *next)
xen_mc_flush();
leave_lazy(XEN_LAZY_CPU);
- if (__task_lazy_mmu_mode_active(next))
- arch_enter_lazy_mmu_mode();
+ __task_lazy_mmu_mode_resume(next);
}
static unsigned long xen_store_tr(void)
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index 51dbdc67c73c..928b4b0a4484 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -324,7 +324,7 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval)
{
struct mmu_update u;
- if (xen_get_lazy_mode() != XEN_LAZY_MMU)
+ if (!is_lazy_mmu_mode_active())
return false;
xen_mc_batch();
@@ -2151,21 +2151,10 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
#endif
}
-static void xen_enter_lazy_mmu(void)
-{
- preempt_disable();
- if (xen_get_lazy_mode() != XEN_LAZY_MMU)
- enter_lazy(XEN_LAZY_MMU);
- preempt_enable();
-}
-
static void xen_flush_lazy_mmu(void)
{
preempt_disable();
-
- if (xen_get_lazy_mode() == XEN_LAZY_MMU)
- xen_mc_flush();
-
+ xen_mc_flush();
preempt_enable();
}
@@ -2189,15 +2178,6 @@ static void __init xen_post_allocator_init(void)
pv_ops.mmu.write_cr3 = &xen_write_cr3;
}
-static void xen_leave_lazy_mmu(void)
-{
- preempt_disable();
- xen_mc_flush();
- if (xen_get_lazy_mode() != XEN_LAZY_NONE)
- leave_lazy(XEN_LAZY_MMU);
- preempt_enable();
-}
-
void __init xen_init_mmu_ops(void)
{
x86_init.paging.pagetable_init = xen_pagetable_init;
@@ -2237,9 +2217,7 @@ void __init xen_init_mmu_ops(void)
pv_ops.mmu.make_p4d = PV_CALLEE_SAVE(xen_make_p4d);
pv_ops.mmu.enter_mmap = xen_enter_mmap;
pv_ops.mmu.exit_mmap = xen_exit_mmap;
- pv_ops.mmu.lazy_mode.enter = xen_enter_lazy_mmu;
- pv_ops.mmu.lazy_mode.leave = xen_leave_lazy_mmu;
- pv_ops.mmu.lazy_mode.flush = xen_flush_lazy_mmu;
+ pv_ops.mmu.lazy_mode_flush = xen_flush_lazy_mmu;
pv_ops.mmu.set_fixmap = xen_set_fixmap;
memset(dummy_mapping, 0xff, PAGE_SIZE);
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 5/5] x86/xen: Replace generic lazy tracking with cpu specific one
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
` (3 preceding siblings ...)
2026-05-26 15:05 ` [PATCH 4/5] x86/xen: Get rid of last XEN_LAZY_MMU uses Juergen Gross
@ 2026-05-26 15:05 ` Juergen Gross
2026-06-01 15:08 ` [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking David Hildenbrand (Arm)
5 siblings, 0 replies; 8+ messages in thread
From: Juergen Gross @ 2026-05-26 15:05 UTC (permalink / raw)
To: linux-kernel, x86
Cc: Juergen Gross, Boris Ostrovsky, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, xen-devel
Now that lazy mmu state tracking no longer relies on the Xen specific
one, cpu lazy mode is the only user of the Xen generic lazy tracking.
Replace the Xen generic lazy tracking with a cpu lazy specific one.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/include/asm/xen/hypervisor.h | 25 +------------------------
arch/x86/xen/enlighten_pv.c | 23 ++++++++++-------------
arch/x86/xen/mmu_pv.c | 6 +++---
3 files changed, 14 insertions(+), 40 deletions(-)
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
index c2fc7869b996..f666637d773e 100644
--- a/arch/x86/include/asm/xen/hypervisor.h
+++ b/arch/x86/include/asm/xen/hypervisor.h
@@ -64,30 +64,7 @@ void __init xen_pvh_init(struct boot_params *boot_params);
void __init mem_map_via_hcall(struct boot_params *boot_params_p);
#endif
-/* Lazy mode for batching updates / context switch */
-enum xen_lazy_mode {
- XEN_LAZY_NONE,
- XEN_LAZY_MMU,
- XEN_LAZY_CPU,
-};
-
-DECLARE_PER_CPU(enum xen_lazy_mode, xen_lazy_mode);
-
-static inline void enter_lazy(enum xen_lazy_mode mode)
-{
- BUG_ON(this_cpu_read(xen_lazy_mode) != XEN_LAZY_NONE);
-
- this_cpu_write(xen_lazy_mode, mode);
-}
-
-static inline void leave_lazy(enum xen_lazy_mode mode)
-{
- BUG_ON(this_cpu_read(xen_lazy_mode) != mode);
-
- this_cpu_write(xen_lazy_mode, XEN_LAZY_NONE);
-}
-
-enum xen_lazy_mode xen_get_lazy_mode(void);
+bool xen_is_cpu_lazy_mode(void);
#if defined(CONFIG_XEN_DOM0) && defined(CONFIG_ACPI)
void xen_sanitize_proc_cap_bits(uint32_t *buf);
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 8ee4910d597a..b310b91f2994 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -138,14 +138,11 @@ struct tls_descs {
struct desc_struct desc[3];
};
-DEFINE_PER_CPU(enum xen_lazy_mode, xen_lazy_mode) = XEN_LAZY_NONE;
+static DEFINE_PER_CPU(bool, xen_cpu_lazy_mode);
-enum xen_lazy_mode xen_get_lazy_mode(void)
+bool xen_is_cpu_lazy_mode(void)
{
- if (in_interrupt())
- return XEN_LAZY_NONE;
-
- return this_cpu_read(xen_lazy_mode);
+ return !in_interrupt() && this_cpu_read(xen_cpu_lazy_mode);
}
/*
@@ -425,7 +422,7 @@ static void xen_start_context_switch(struct task_struct *prev)
BUG_ON(preemptible());
__task_lazy_mmu_mode_pause(prev);
- enter_lazy(XEN_LAZY_CPU);
+ this_cpu_write(xen_cpu_lazy_mode, true);
}
static void xen_end_context_switch(struct task_struct *next)
@@ -433,7 +430,7 @@ static void xen_end_context_switch(struct task_struct *next)
BUG_ON(preemptible());
xen_mc_flush();
- leave_lazy(XEN_LAZY_CPU);
+ this_cpu_write(xen_cpu_lazy_mode, false);
__task_lazy_mmu_mode_resume(next);
}
@@ -541,7 +538,7 @@ static void xen_set_ldt(const void *addr, unsigned entries)
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
+ xen_mc_issue(!xen_is_cpu_lazy_mode());
}
static void xen_load_gdt(const struct desc_ptr *dtr)
@@ -637,7 +634,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
* exception between the new %fs descriptor being loaded and
* %fs being effectively cleared at __switch_to().
*/
- if (xen_get_lazy_mode() == XEN_LAZY_CPU)
+ if (xen_is_cpu_lazy_mode())
loadsegment(fs, 0);
xen_mc_batch();
@@ -646,7 +643,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
load_TLS_descriptor(t, cpu, 1);
load_TLS_descriptor(t, cpu, 2);
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
+ xen_mc_issue(!xen_is_cpu_lazy_mode());
}
static void xen_load_gs_index(unsigned int idx)
@@ -1008,7 +1005,7 @@ static void xen_load_sp0(unsigned long sp0)
mcs = xen_mc_entry(0);
MULTI_stack_switch(mcs.mc, __KERNEL_DS, sp0);
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
+ xen_mc_issue(!xen_is_cpu_lazy_mode());
this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
}
@@ -1068,7 +1065,7 @@ static void xen_write_cr0(unsigned long cr0)
MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0);
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
+ xen_mc_issue(!xen_is_cpu_lazy_mode());
}
static void xen_write_cr4(unsigned long cr4)
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index 928b4b0a4484..aab5f70d407c 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -1425,7 +1425,7 @@ static void xen_write_cr3(unsigned long cr3)
else
__xen_write_cr3(false, 0);
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU); /* interrupts restored */
+ xen_mc_issue(!xen_is_cpu_lazy_mode()); /* interrupts restored */
}
/*
@@ -1460,7 +1460,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
__xen_write_cr3(true, cr3);
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU); /* interrupts restored */
+ xen_mc_issue(!xen_is_cpu_lazy_mode()); /* interrupts restored */
}
static int xen_pgd_alloc(struct mm_struct *mm)
@@ -1875,7 +1875,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
*/
xen_mc_batch();
__xen_write_cr3(true, __pa(init_top_pgt));
- xen_mc_issue(xen_get_lazy_mode() != XEN_LAZY_CPU);
+ xen_mc_issue(!xen_is_cpu_lazy_mode());
/* We can't that easily rip out L3 and L2, as the Xen pagetables are
* set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ... for
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
` (4 preceding siblings ...)
2026-05-26 15:05 ` [PATCH 5/5] x86/xen: Replace generic lazy tracking with cpu specific one Juergen Gross
@ 2026-06-01 15:08 ` David Hildenbrand (Arm)
5 siblings, 0 replies; 8+ messages in thread
From: David Hildenbrand (Arm) @ 2026-06-01 15:08 UTC (permalink / raw)
To: Juergen Gross, linux-kernel, x86, linux-trace-kernel, linux-mm,
virtualization
Cc: Boris Ostrovsky, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, H. Peter Anvin, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, xen-devel, Andrew Morton, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Ajay Kaher, Alexey Makhalov,
Broadcom internal kernel review list
On 5/26/26 17:05, Juergen Gross wrote:
> With generic lazy MMU mode tracking being available, there is no real
> need for having Xen PV specific code to track lazy MMU mode, too.
>
> This makes it possible to drop two paravirt hooks.
Nice!
--
Cheers,
David
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/5] mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume()
2026-05-26 15:05 ` [PATCH 3/5] mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume() Juergen Gross
@ 2026-06-01 15:09 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 8+ messages in thread
From: David Hildenbrand (Arm) @ 2026-06-01 15:09 UTC (permalink / raw)
To: Juergen Gross, linux-kernel, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko
On 5/26/26 17:05, Juergen Gross wrote:
> In order to allow pausing and resuming MMU lazy mode for other tasks
> than current, refactor lazy_mmu_mode_pause() and
> lazy_mmu_mode_resume().
>
> This will be needed when dropping the Xen PV private lazy MMU
> bookkeeping.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-06-01 15:09 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-26 15:05 [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking Juergen Gross
2026-05-26 15:05 ` [PATCH 1/5] x86/xen: Drop lazy mode from trace entries Juergen Gross
2026-05-26 15:05 ` [PATCH 2/5] x86/xen: Change interface of xen_mc_issue() Juergen Gross
2026-05-26 15:05 ` [PATCH 3/5] mm: Refactor lazy_mmu_mode_pause() and lazy_mmu_mode_resume() Juergen Gross
2026-06-01 15:09 ` David Hildenbrand (Arm)
2026-05-26 15:05 ` [PATCH 4/5] x86/xen: Get rid of last XEN_LAZY_MMU uses Juergen Gross
2026-05-26 15:05 ` [PATCH 5/5] x86/xen: Replace generic lazy tracking with cpu specific one Juergen Gross
2026-06-01 15:08 ` [PATCH 0/5] x86/xen: Get rid of Xen private lazy MMU mode tracking David Hildenbrand (Arm)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome