[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] x86/domctl: Stop using XLAT_cpu_user_regs()



commit 9f892f84c27970840d255aef7e2851b762967de7
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Dec 30 11:49:14 2024 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Fri Aug 8 13:23:11 2025 +0100

    x86/domctl: Stop using XLAT_cpu_user_regs()
    
    In order to support FRED, we're going to have to remove the {ds..gs} fields
    from struct cpu_user_regs, meaning that it is going to have to become a
    different type to the structure embedded in vcpu_guest_context_u.
    
    In both arch_{get,set}_info_guest(), expand the 
memcpy()/XLAT_cpu_user_regs()
    to copy the fields individually.  This will allow us to eventually make them
    different types.
    
    This does cause some minor changes in behaviour for the hypercalls.
    
    It is specifically not the case that a toolstack could set_info(); 
get_info();
    and get an identical bit pattern back.  Amongst other things, the
    architectural sticky bits in registers are applied during setting.
    
    Previously, XLAT_cpu_user_regs() omitted the _pad fields in the compat case
    whereas the non-compat case included them owing to the single memcpy().
    
    Omit the _pad fields in the non-compat case too; for all but the oldest of
    CPUs, the segment selectors are zero-extended by hardware when pushed onto 
the
    stack, so non-zero values here get lost naturally.  Furthermore, FRED reuses
    the space above cs and ss for extra state, and a PV guest for now at least
    must not be able to write the control state.
    
    Omit the error_code and entry_vector fields too.  They're already identified
    as private fields in the public API, and are stale outside of Xen's
    interrupt/exception/syscall handler.  They're also a very minor information
    leak of which event caused the last deschedule of a vCPU.
    
    Finally, omit saved_upcall_mask.  Xen doesn't consume this, and only 
produces
    it in {compat_,}create_bounce_frame(), based on the vcpu_info shared state 
and
    settings about the event being injected.  Similar to 
error_code/entry_vector,
    it is stale outside of the guest's event handler.
    
    No change that toolstacks or guests are expected to notice or care about.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/domain.c | 38 ++++++++++++++++++++++++++++++++++++--
 xen/arch/x86/domctl.c | 38 ++++++++++++++++++++++++++++++++++++--
 xen/include/xlat.lst  |  2 --
 3 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 56c3816187..41d75dde42 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1231,9 +1231,27 @@ int arch_set_info_guest(
     else
         vcpu_reset_fpu(v);
 
+    memset(&v->arch.user_regs, 0, sizeof(v->arch.user_regs));
+
     if ( !compat )
     {
-        memcpy(&v->arch.user_regs, &c.nat->user_regs, 
sizeof(c.nat->user_regs));
+        v->arch.user_regs.rbx               = c.nat->user_regs.rbx;
+        v->arch.user_regs.rcx               = c.nat->user_regs.rcx;
+        v->arch.user_regs.rdx               = c.nat->user_regs.rdx;
+        v->arch.user_regs.rsi               = c.nat->user_regs.rsi;
+        v->arch.user_regs.rdi               = c.nat->user_regs.rdi;
+        v->arch.user_regs.rbp               = c.nat->user_regs.rbp;
+        v->arch.user_regs.rax               = c.nat->user_regs.rax;
+        v->arch.user_regs.rip               = c.nat->user_regs.rip;
+        v->arch.user_regs.cs                = c.nat->user_regs.cs;
+        v->arch.user_regs.rflags            = c.nat->user_regs.rflags;
+        v->arch.user_regs.rsp               = c.nat->user_regs.rsp;
+        v->arch.user_regs.ss                = c.nat->user_regs.ss;
+        v->arch.user_regs.es                = c.nat->user_regs.es;
+        v->arch.user_regs.ds                = c.nat->user_regs.ds;
+        v->arch.user_regs.fs                = c.nat->user_regs.fs;
+        v->arch.user_regs.gs                = c.nat->user_regs.gs;
+
         if ( is_pv_domain(d) )
             memcpy(v->arch.pv.trap_ctxt, c.nat->trap_ctxt,
                    sizeof(c.nat->trap_ctxt));
@@ -1241,7 +1259,23 @@ int arch_set_info_guest(
 #ifdef CONFIG_COMPAT
     else
     {
-        XLAT_cpu_user_regs(&v->arch.user_regs, &c.cmp->user_regs);
+        v->arch.user_regs.ebx               = c.cmp->user_regs.ebx;
+        v->arch.user_regs.ecx               = c.cmp->user_regs.ecx;
+        v->arch.user_regs.edx               = c.cmp->user_regs.edx;
+        v->arch.user_regs.esi               = c.cmp->user_regs.esi;
+        v->arch.user_regs.edi               = c.cmp->user_regs.edi;
+        v->arch.user_regs.ebp               = c.cmp->user_regs.ebp;
+        v->arch.user_regs.eax               = c.cmp->user_regs.eax;
+        v->arch.user_regs.eip               = c.cmp->user_regs.eip;
+        v->arch.user_regs.cs                = c.cmp->user_regs.cs;
+        v->arch.user_regs.eflags            = c.cmp->user_regs.eflags;
+        v->arch.user_regs.esp               = c.cmp->user_regs.esp;
+        v->arch.user_regs.ss                = c.cmp->user_regs.ss;
+        v->arch.user_regs.es                = c.cmp->user_regs.es;
+        v->arch.user_regs.ds                = c.cmp->user_regs.ds;
+        v->arch.user_regs.fs                = c.cmp->user_regs.fs;
+        v->arch.user_regs.gs                = c.cmp->user_regs.gs;
+
         if ( is_pv_domain(d) )
         {
             for ( i = 0; i < ARRAY_SIZE(c.cmp->trap_ctxt); ++i )
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 3044f706de..28fec0e12d 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1399,7 +1399,24 @@ void arch_get_info_guest(struct vcpu *v, 
vcpu_guest_context_u c)
         c(flags |= VGCF_online);
     if ( !compat )
     {
-        memcpy(&c.nat->user_regs, &v->arch.user_regs, 
sizeof(c.nat->user_regs));
+        /* Backing memory is pre-zeroed. */
+        c.nat->user_regs.rbx               = v->arch.user_regs.rbx;
+        c.nat->user_regs.rcx               = v->arch.user_regs.rcx;
+        c.nat->user_regs.rdx               = v->arch.user_regs.rdx;
+        c.nat->user_regs.rsi               = v->arch.user_regs.rsi;
+        c.nat->user_regs.rdi               = v->arch.user_regs.rdi;
+        c.nat->user_regs.rbp               = v->arch.user_regs.rbp;
+        c.nat->user_regs.rax               = v->arch.user_regs.rax;
+        c.nat->user_regs.rip               = v->arch.user_regs.rip;
+        c.nat->user_regs.cs                = v->arch.user_regs.cs;
+        c.nat->user_regs.rflags            = v->arch.user_regs.rflags;
+        c.nat->user_regs.rsp               = v->arch.user_regs.rsp;
+        c.nat->user_regs.ss                = v->arch.user_regs.ss;
+        c.nat->user_regs.es                = v->arch.user_regs.es;
+        c.nat->user_regs.ds                = v->arch.user_regs.ds;
+        c.nat->user_regs.fs                = v->arch.user_regs.fs;
+        c.nat->user_regs.gs                = v->arch.user_regs.gs;
+
         if ( is_pv_domain(d) )
             memcpy(c.nat->trap_ctxt, v->arch.pv.trap_ctxt,
                    sizeof(c.nat->trap_ctxt));
@@ -1407,7 +1424,24 @@ void arch_get_info_guest(struct vcpu *v, 
vcpu_guest_context_u c)
 #ifdef CONFIG_COMPAT
     else
     {
-        XLAT_cpu_user_regs(&c.cmp->user_regs, &v->arch.user_regs);
+        /* Backing memory is pre-zeroed. */
+        c.cmp->user_regs.ebx               = v->arch.user_regs.ebx;
+        c.cmp->user_regs.ecx               = v->arch.user_regs.ecx;
+        c.cmp->user_regs.edx               = v->arch.user_regs.edx;
+        c.cmp->user_regs.esi               = v->arch.user_regs.esi;
+        c.cmp->user_regs.edi               = v->arch.user_regs.edi;
+        c.cmp->user_regs.ebp               = v->arch.user_regs.ebp;
+        c.cmp->user_regs.eax               = v->arch.user_regs.eax;
+        c.cmp->user_regs.eip               = v->arch.user_regs.eip;
+        c.cmp->user_regs.cs                = v->arch.user_regs.cs;
+        c.cmp->user_regs.eflags            = v->arch.user_regs.eflags;
+        c.cmp->user_regs.esp               = v->arch.user_regs.esp;
+        c.cmp->user_regs.ss                = v->arch.user_regs.ss;
+        c.cmp->user_regs.es                = v->arch.user_regs.es;
+        c.cmp->user_regs.ds                = v->arch.user_regs.ds;
+        c.cmp->user_regs.fs                = v->arch.user_regs.fs;
+        c.cmp->user_regs.gs                = v->arch.user_regs.gs;
+
         if ( is_pv_domain(d) )
         {
             for ( i = 0; i < ARRAY_SIZE(c.cmp->trap_ctxt); ++i )
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index 3c7b6c6830..6d6c6cfab2 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -34,8 +34,6 @@
 ?      pmu_intel_ctxt                  arch-x86/pmu.h
 ?      pmu_regs                        arch-x86/pmu.h
 
-!      cpu_user_regs                   arch-x86/xen-@arch@.h
-
 ?      cpu_offline_action              arch-x86/xen-mca.h
 ?      mc                              arch-x86/xen-mca.h
 !      mc_fetch                        arch-x86/xen-mca.h
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.