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

Re: [Xen-devel] [PATCH 02/14] xen: arm: tweak arm64 stack frame layout



On Mon, 2013-04-08 at 14:31 +0100, Stefano Stabellini wrote:
> On Tue, 12 Mar 2013, Ian Campbell wrote:
> > From: Ian Campbell <ian.campbell@xxxxxxxxxx>
> > 
> > Correct definition of UREGS_kernel_sizeof and use it.
> > 
> > Correct adjustment of stack on entry and exit.
> > 
> > Add 64-bit versions of the build time checks for stack pointer alignment
> > correctness when pushing the stack frames.
> > 
> > Lastly, correct the padding in the stack frames to properly align the inner 
> > and
> > outer frames and also avoid an unnecessary 64bit padding field.
> > 
> > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> > ---
> >  xen/arch/arm/arm64/asm-offsets.c      |    2 +-
> >  xen/arch/arm/arm64/entry.S            |    9 +++++----
> >  xen/arch/arm/domain.c                 |    2 ++
> >  xen/arch/arm/traps.c                  |    7 +++++++
> >  xen/include/asm-arm/arm64/processor.h |    7 +++----
> >  5 files changed, 18 insertions(+), 9 deletions(-)
> > 
> > diff --git a/xen/arch/arm/arm64/asm-offsets.c 
> > b/xen/arch/arm/arm64/asm-offsets.c
> > index 7949e3e..7544082 100644
> > --- a/xen/arch/arm/arm64/asm-offsets.c
> > +++ b/xen/arch/arm/arm64/asm-offsets.c
> > @@ -39,7 +39,7 @@ void __dummy__(void)
> >     OFFSET(UREGS_SP_el1, struct cpu_user_regs, sp_el1);
> >     OFFSET(UREGS_ELR_el1, struct cpu_user_regs, elr_el1);
> >  
> > -   OFFSET(UREGS_kernel_sizeof, struct cpu_user_regs, cpsr);
> > +   OFFSET(UREGS_kernel_sizeof, struct cpu_user_regs, spsr_el1);
> >     DEFINE(UREGS_user_sizeof, sizeof(struct cpu_user_regs));
> >     BLANK();
> >  
> > diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
> > index 9d38088..a5fd608 100644
> > --- a/xen/arch/arm/arm64/entry.S
> > +++ b/xen/arch/arm/arm64/entry.S
> > @@ -34,7 +34,7 @@ lr      .req    x30             // link register
> >          mrs     x22, SP_el0
> >          str     x22, [x21]
> >  
> > -        add     x21, sp, #UREGS_ELR_el1
> > +        add     x21, sp, #UREGS_SP_el1
> >          mrs     x22, SP_el1
> >          mrs     x23, ELR_el1
> >          stp     x22, x23, [x21]
> 
> Honestly I think it would be much cleaner and easier to read if we saved
> sp_el1 and elr_el1 separately.

I think stp is supposed to be faster, but I'm running on a model so I'm
not sure. Also there are weird quadword alignment constraints on the
stack and stp is atomic from that PoV.

> 
> 
> > @@ -59,7 +59,7 @@ lr      .req    x30             // link register
> >   * Save state on entry to hypervisor
> >   */
> >          .macro  entry, hyp, compat
> > -        sub     sp, sp, #(UREGS_SPSR_el1 - UREGS_SP)
> > +        sub     sp, sp, #(UREGS_SPSR_el1 - UREGS_LR) /* CPSR, PC, SP, LR */
> >          push    x28, x29
> >          push    x26, x27
> >          push    x24, x25
> > @@ -78,7 +78,7 @@ lr      .req    x30             // link register
> >  
> >          .if \hyp == 1        /* Hypervisor mode */
> >  
> > -        add     x21, sp, #(UREGS_X0 - UREGS_SP)
> > +        add     x21, sp, #UREGS_kernel_sizeof
> >  
> >          .else                /* Guest mode */
> >  
> > @@ -213,7 +213,8 @@ ENTRY(return_to_hypervisor)
> >          pop     x26, x27
> >          pop     x28, x29
> >  
> > -        ldr     lr, [sp], #(UREGS_SPSR_el1 - UREGS_SP)
> > +        ldr     lr, [sp], #(UREGS_SPSR_el1 - UREGS_LR) /* CPSR, PC, SP, LR 
> > */
> > +
> >          eret
> >  
> >  /*
> > diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> > index f369871..08bb132 100644
> > --- a/xen/arch/arm/domain.c
> > +++ b/xen/arch/arm/domain.c
> > @@ -419,6 +419,8 @@ int vcpu_initialise(struct vcpu *v)
> >  {
> >      int rc = 0;
> >  
> > +    BUILD_BUG_ON( sizeof(struct cpu_info) > STACK_SIZE );
> > +
> >      v->arch.stack = alloc_xenheap_pages(STACK_ORDER, 
> > MEMF_node(vcpu_to_node(v)));
> >      if ( v->arch.stack == NULL )
> >          return -ENOMEM;
> > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> > index a98a45e..6b19bc5 100644
> > --- a/xen/arch/arm/traps.c
> > +++ b/xen/arch/arm/traps.c
> > @@ -43,9 +43,16 @@
> >   * entry.S) and struct cpu_info (which lives at the bottom of a Xen
> >   * stack) must be doubleword-aligned in size.  */
> >  static inline void check_stack_alignment_constraints(void) {
> > +#ifdef CONFIG_ARM_64
> > +    BUILD_BUG_ON((sizeof (struct cpu_user_regs)) & 0xf);
> > +    BUILD_BUG_ON((offsetof(struct cpu_user_regs, spsr_el1)) & 0xf);
> > +    BUILD_BUG_ON((offsetof(struct cpu_user_regs, lr)) & 0xf);
> > +    BUILD_BUG_ON((sizeof (struct cpu_info)) & 0xf);
> 
> Why both spsr_el1 and lr?
> From the comment on top of check_stack_alignment_constraints I would
> think that only spsr_el1 is needed?

You are right spsr_el1 is needed to check the alignments of the
inner/outer frames.

The lr check is because I had a few problems getting the inner code
pushing working correctly, IIRC it relates to the use of stp (since you
need to make sure the pair are correctly aligned)

> 
> 
> > +#else
> >      BUILD_BUG_ON((sizeof (struct cpu_user_regs)) & 0x7);
> >      BUILD_BUG_ON((offsetof(struct cpu_user_regs, sp_usr)) & 0x7);
> >      BUILD_BUG_ON((sizeof (struct cpu_info)) & 0x7);
> > +#endif
> >  }
> >  
> >  static int debug_stack_lines = 20;
> > diff --git a/xen/include/asm-arm/arm64/processor.h 
> > b/xen/include/asm-arm/arm64/processor.h
> > index b4602fa..bf436c8 100644
> > --- a/xen/include/asm-arm/arm64/processor.h
> > +++ b/xen/include/asm-arm/arm64/processor.h
> > @@ -51,6 +51,7 @@ struct cpu_user_regs
> >      __DECL_REG(x27,          r11_fiq);
> >      __DECL_REG(x28,          r12_fiq);
> >      __DECL_REG(/* x29 */ fp, /* r13_fiq */ sp_fiq);
> > +
> >      __DECL_REG(/* x30 */ lr, /* r14_fiq */ lr_fiq);
> >  
> >      register_t sp; /* Valid for hypervisor frames */
> > @@ -59,7 +60,7 @@ struct cpu_user_regs
> >      __DECL_REG(pc,           pc32);             /* ELR_EL2 */
> >      uint32_t cpsr;                              /* SPSR_EL2 */
> >  
> > -    uint64_t pad0;
> > +    uint32_t pad0; /* Align end of kernel frame. */
> 
> That would be because cpsr is a uint32_t, right?

Right, I think.
> 
> 
> >      /* Outer guest frame only from here on... */
> >  
> > @@ -68,7 +69,7 @@ struct cpu_user_regs
> >          uint32_t spsr_svc;       /* AArch32 */
> >      };
> >  
> > -    uint32_t pad1; /* Align */
> > +    uint32_t pad1; /* Doubleword-align the user half of the frame */
> 
> This one is because of the preceding union of two uint32_t

Yup.

> 
> >      /* AArch32 guests only */
> >      uint32_t spsr_fiq, spsr_irq, spsr_und, spsr_abt;
> > @@ -76,8 +77,6 @@ struct cpu_user_regs
> >      /* AArch64 guests only */
> >      uint64_t sp_el0;
> >      uint64_t sp_el1, elr_el1;
> > -
> > -    uint64_t pad2; /* Doubleword-align the user half of the frame */
> >  };
> 
> of course padding with uint64_t is useless on arm (32 and 64)

Right.



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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