* Re: [PATCH] xen: Use VCPUOP_register_{runstate,vcpu_time}_phys_area when available [not found] <1792146192.8631fc262581453bbf619ec5b2062170.1a1443cb7e90008425@vates.tech> @ 2026-10-16 11:15 ` Andrew Cooper 2026-10-16 14:10 ` Teddy Astie 0 siblings, 1 reply; 3+ messages in thread From: Andrew Cooper @ 2026-10-16 11:15 UTC (permalink / raw) To: Teddy Astie, xen-devel Cc: Andrew Cooper, Juergen Gross, Boris Ostrovsky, Stefano Stabellini, Oleksandr Tyshchenko, David Woodhouse, George Dunlap, x86, linux-kernel On 16/10/2026 11:22 am, Teddy Astie wrote: > Updating these area can be expensive when done through virtual addresses > (especially for runstate one), in particular for HVM/PVH guests. > Xen 4.18 introduced physical address alternatives to address those > short-commings, but they aren't used currently. > > Fix it by using these alternatives when available (when reported in > XENFEAT_{runstate,vcpu_time}_phys_area, but keep the current logic > in the PV case. > > Assisted-by: LLM > [guidance and testing] > Signed-off-by: Teddy Astie <teddy.astie@vates.tech> > --- > When using phys_area ABI, the struct is not allowed to cross a page > boundary anymore, hence we need to be careful with per-cpu struct > alignment. > > I've deliberately put the PV domain (!XENFEAT_auto_translated_physmap) > case aside as it profits less from the physical address ABI, and it > would make things more complicated as "physical address" doesn't have > a obvious meaning there. It should always have been a guest physical registration, even for PV guests. The virtual address registered with Xen doesn't exist in the user pagetables, and the way we discover that is taking a pagefault in Xen at the point we need to update things. > diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c > index 5c7822254a01..19ace1b78ae4 100644 > --- a/arch/x86/xen/time.c > +++ b/arch/x86/xen/time.c > @@ -37,6 +37,22 @@ > > static u64 xen_sched_clock_offset __read_mostly; > > +static int xen_register_time_area(struct pvclock_vcpu_time_info *pvti) This needs a comment explaining what's going on (by GPA, falling back to VA), including that passing NULL means unregister. > +{ > + struct vcpu_register_time_memory_area t; > + bool phys = xen_feature(XENFEAT_vcpu_time_phys_area) && > + xen_feature(XENFEAT_auto_translated_physmap); Not related to your patch, but the xen_feature() infrastructure is idiotic. It takes a bitmap from Xen, and transforms it into a u8 array of 1's or 0's. It wants storing as a proper Linux bitmap, with xen_feature() being a trivial wrapper around test_bit(), at which point the compiler will able to collapse expressions such as the one above into a single operation. (except, you need to remove the XENFEAT_auto_translated_physmap aspect to include PV guests.) > + int op = phys ? VCPUOP_register_vcpu_time_phys_area > + : VCPUOP_register_vcpu_time_memory_area; > + > + if (phys) > + t.addr.p = pvti ? virt_to_phys(pvti) : ~0LLU; > + else > + t.addr.v = pvti; > + > + return HYPERVISOR_vcpu_op(op, 0, &t); > +} > + > /* Get the TSC speed from Xen */ > static unsigned long xen_tsc_khz(void) > { > @@ -395,7 +411,6 @@ static u64 xen_clock_value_saved; > > void xen_save_time_memory_area(void) > { > - struct vcpu_register_time_memory_area t; > int ret; > > xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset; > @@ -403,9 +418,7 @@ void xen_save_time_memory_area(void) > if (!xen_clock) > return; > > - t.addr.v = NULL; > - > - ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); > + ret = xen_register_time_area(NULL); > if (ret != 0) > pr_notice("Cannot save secondary vcpu_time_info (err %d)", > ret); How does this work? Answer is it doesn't, because the print message is bogus. This is a failure to unregister the time area, not a failure to save the time value. At lest the error message wants fixing, and in a prep patch. > diff --git a/drivers/xen/time.c b/drivers/xen/time.c > index a2be0a4d45b0..6b6ddc7a5822 100644 > --- a/drivers/xen/time.c > +++ b/drivers/xen/time.c > @@ -152,11 +156,21 @@ u64 xen_steal_clock(int cpu) > void xen_setup_runstate_info(int cpu) > { > struct vcpu_register_runstate_memory_area area; > + unsigned int op; > > - area.addr.v = &per_cpu(xen_runstate, cpu); > + if (xen_feature(XENFEAT_runstate_phys_area) && > + xen_feature(XENFEAT_auto_translated_physmap)) Again, PV guests want to use phys when available. > + { > + op = VCPUOP_register_runstate_phys_area; > + area.addr.p = per_cpu_ptr_to_phys(&per_cpu(xen_runstate, cpu)); > + } > + else > + { > + op = VCPUOP_register_runstate_memory_area; > + area.addr.v = &per_cpu(xen_runstate, cpu); I'd suggest factoring out the &per_cpu(xen_runstate, cpu) calculation. It's not free, and can't be hoisted by the compiler. ~Andrew ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] xen: Use VCPUOP_register_{runstate,vcpu_time}_phys_area when available 2026-10-16 11:15 ` [PATCH] xen: Use VCPUOP_register_{runstate,vcpu_time}_phys_area when available Andrew Cooper @ 2026-10-16 14:10 ` Teddy Astie 2026-10-16 15:33 ` Andrew Cooper 0 siblings, 1 reply; 3+ messages in thread From: Teddy Astie @ 2026-10-16 14:10 UTC (permalink / raw) To: Andrew Cooper, xen-devel Cc: Juergen Gross, Boris Ostrovsky, Stefano Stabellini, Oleksandr Tyshchenko, David Woodhouse, George Dunlap, x86, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 4956 bytes --] Le 16/10/2026 à 13:20, Andrew Cooper a écrit : > On 16/10/2026 11:22 am, Teddy Astie wrote: >> Updating these area can be expensive when done through virtual addresses >> (especially for runstate one), in particular for HVM/PVH guests. >> Xen 4.18 introduced physical address alternatives to address those >> short-commings, but they aren't used currently. >> >> Fix it by using these alternatives when available (when reported in >> XENFEAT_{runstate,vcpu_time}_phys_area, but keep the current logic >> in the PV case. >> >> Assisted-by: LLM >> [guidance and testing] >> Signed-off-by: Teddy Astie <teddy.astie@vates.tech> >> --- >> When using phys_area ABI, the struct is not allowed to cross a page >> boundary anymore, hence we need to be careful with per-cpu struct >> alignment. >> >> I've deliberately put the PV domain (!XENFEAT_auto_translated_physmap) >> case aside as it profits less from the physical address ABI, and it >> would make things more complicated as "physical address" doesn't have >> a obvious meaning there. > > It should always have been a guest physical registration, even for PV > guests. > > The virtual address registered with Xen doesn't exist in the user > pagetables, and the way we discover that is taking a pagefault in Xen at > the point we need to update things. > I wasn't aware of that specific case. Will try to make the code compatible with PV guests. >> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c >> index 5c7822254a01..19ace1b78ae4 100644 >> --- a/arch/x86/xen/time.c >> +++ b/arch/x86/xen/time.c >> @@ -37,6 +37,22 @@ >> >> static u64 xen_sched_clock_offset __read_mostly; >> >> +static int xen_register_time_area(struct pvclock_vcpu_time_info *pvti) > > This needs a comment explaining what's going on (by GPA, falling back to > VA), including that passing NULL means unregister. > Will add, I guess we also want to mention that this does stuff on vCPU 0. >> +{ >> + struct vcpu_register_time_memory_area t; >> + bool phys = xen_feature(XENFEAT_vcpu_time_phys_area) && >> + xen_feature(XENFEAT_auto_translated_physmap); > > Not related to your patch, but the xen_feature() infrastructure is idiotic. > > It takes a bitmap from Xen, and transforms it into a u8 array of 1's or 0's. > > It wants storing as a proper Linux bitmap, with xen_feature() being a > trivial wrapper around test_bit(), at which point the compiler will able > to collapse expressions such as the one above into a single operation. > (except, you need to remove the XENFEAT_auto_translated_physmap aspect > to include PV guests.) > Looks good to me. >> + int op = phys ? VCPUOP_register_vcpu_time_phys_area >> + : VCPUOP_register_vcpu_time_memory_area; >> + >> + if (phys) >> + t.addr.p = pvti ? virt_to_phys(pvti) : ~0LLU; >> + else >> + t.addr.v = pvti; >> + >> + return HYPERVISOR_vcpu_op(op, 0, &t); >> +} >> + >> /* Get the TSC speed from Xen */ >> static unsigned long xen_tsc_khz(void) >> { >> @@ -395,7 +411,6 @@ static u64 xen_clock_value_saved; >> >> void xen_save_time_memory_area(void) >> { >> - struct vcpu_register_time_memory_area t; >> int ret; >> >> xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset; >> @@ -403,9 +418,7 @@ void xen_save_time_memory_area(void) >> if (!xen_clock) >> return; >> >> - t.addr.v = NULL; >> - >> - ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); >> + ret = xen_register_time_area(NULL); >> if (ret != 0) >> pr_notice("Cannot save secondary vcpu_time_info (err %d)", >> ret); > > How does this work? Answer is it doesn't, because the print message is > bogus. This is a failure to unregister the time area, not a failure to > save the time value. > > At lest the error message wants fixing, and in a prep patch. > Yes. >> diff --git a/drivers/xen/time.c b/drivers/xen/time.c >> index a2be0a4d45b0..6b6ddc7a5822 100644 >> --- a/drivers/xen/time.c >> +++ b/drivers/xen/time.c >> @@ -152,11 +156,21 @@ u64 xen_steal_clock(int cpu) >> void xen_setup_runstate_info(int cpu) >> { >> struct vcpu_register_runstate_memory_area area; >> + unsigned int op; >> >> - area.addr.v = &per_cpu(xen_runstate, cpu); >> + if (xen_feature(XENFEAT_runstate_phys_area) && >> + xen_feature(XENFEAT_auto_translated_physmap)) > > Again, PV guests want to use phys when available. > >> + { >> + op = VCPUOP_register_runstate_phys_area; >> + area.addr.p = per_cpu_ptr_to_phys(&per_cpu(xen_runstate, cpu)); >> + } >> + else >> + { >> + op = VCPUOP_register_runstate_memory_area; >> + area.addr.v = &per_cpu(xen_runstate, cpu); > > I'd suggest factoring out the &per_cpu(xen_runstate, cpu) calculation. > It's not free, and can't be hoisted by the compiler. > Done locally for both. > ~Andrew Teddy [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 665 bytes --] ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] xen: Use VCPUOP_register_{runstate,vcpu_time}_phys_area when available 2026-10-16 14:10 ` Teddy Astie @ 2026-10-16 15:33 ` Andrew Cooper 0 siblings, 0 replies; 3+ messages in thread From: Andrew Cooper @ 2026-10-16 15:33 UTC (permalink / raw) To: Teddy Astie, xen-devel Cc: Andrew Cooper, Juergen Gross, Boris Ostrovsky, Stefano Stabellini, Oleksandr Tyshchenko, David Woodhouse, George Dunlap, x86, linux-kernel On 16/10/2026 3:10 pm, Teddy Astie wrote: > Le 16/10/2026 à 13:20, Andrew Cooper a écrit : >> On 16/10/2026 11:22 am, Teddy Astie wrote: >>> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c >>> index 5c7822254a01..19ace1b78ae4 100644 >>> --- a/arch/x86/xen/time.c >>> +++ b/arch/x86/xen/time.c >>> @@ -37,6 +37,22 @@ >>> static u64 xen_sched_clock_offset __read_mostly; >>> +static int xen_register_time_area(struct pvclock_vcpu_time_info >>> *pvti) >> >> This needs a comment explaining what's going on (by GPA, falling back to >> VA), including that passing NULL means unregister. >> > > Will add, I guess we also want to mention that this does stuff on vCPU 0. I was puzzled at why it only ever uses vCPU 0 for time handling. Xen does allow there to be a time area per vCPU, and I have a suspicion that this might matter for older systems lacking INVARIANT_TSC. Either way, I don't suggest opening that particular can of worms now. ~Andrew ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-16 15:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <1792146192.8631fc262581453bbf619ec5b2062170.1a1443cb7e90008425@vates.tech>
2026-10-16 11:15 ` [PATCH] xen: Use VCPUOP_register_{runstate,vcpu_time}_phys_area when available Andrew Cooper
2026-10-16 14:10 ` Teddy Astie
2026-10-16 15:33 ` Andrew Cooper
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®