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

Re: [Xen-devel] [PATCH] xen/arm64: Use __flush_dcache_area instead of __flush_dcache_all



Argh..  Forgot to edit subject - this is v3 or this patch, for 4.5

On Mon, Oct 20, 2014 at 8:55 PM, Roy Franz <roy.franz@xxxxxxxxxx> wrote:
> From: Suravee Suthikulpanit <Suravee.Suthikulpanit@xxxxxxx>
>
> When booting with EFI, __flush_dcache_all does not correctly flush data.
> According to Mark Rutland, __flush_dcache_all is not guaranteed to push
> data to the PoC if there is a system-level cache as it uses Set/Way
> operations.  Therefore, this patch switchs to use the "__flush_dcache_area"
> mechanism, which is coppied from Linux.
> Add flushing of FDT in addition to Xen text/data.
> Remove now unused __flush_dcache_all and related helper functions.
> Invalidate the instruction tlb before turning on paging
> later on when starting Xen in EL2.
>
> Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@xxxxxxx>
> Signed-off-by: Roy Franz <roy.franz@xxxxxxxxxx>
> ---
> Changes since v2:
> * Pass FDT size to efi_xen_start, flush exact FDT size rather than
>   max FDT size.  (Max size could extend past end of DRAM.)
>
> Changes since v1:
> * Added flushing of FDT memory region
> * Remove used __flush_dcache_all function, and related helper functions
> * Fix typo in comment
> * Properly set base address in __flush_dcache_area call.
> * Add flush of instruction TLB
>
>  xen/arch/arm/arm64/cache.S  | 89 
> +++++++++++----------------------------------
>  xen/arch/arm/arm64/head.S   | 31 +++++++++++++---
>  xen/arch/arm/efi/efi-boot.h |  4 +-
>  3 files changed, 48 insertions(+), 76 deletions(-)
>
> diff --git a/xen/arch/arm/arm64/cache.S b/xen/arch/arm/arm64/cache.S
> index a445cbf..eff4e16 100644
> --- a/xen/arch/arm/arm64/cache.S
> +++ b/xen/arch/arm/arm64/cache.S
> @@ -20,80 +20,33 @@
>   */
>
>  /*
> - * Enable and disable interrupts.
> + * dcache_line_size - get the minimum D-cache line size from the CTR 
> register.
>   */
> -       .macro  disable_irq
> -       msr     daifset, #2
> -       .endm
> -
> -       .macro  enable_irq
> -       msr     daifclr, #2
> -       .endm
> -
> -/*
> - * Save/disable and restore interrupts.
> - */
> -       .macro  save_and_disable_irqs, olddaif
> -       mrs     \olddaif, daif
> -       disable_irq
> -       .endm
> -
> -       .macro  restore_irqs, olddaif
> -       msr     daif, \olddaif
> +       .macro  dcache_line_size, reg, tmp
> +       mrs     \tmp, ctr_el0                   // read CTR
> +       ubfm    \tmp, \tmp, #16, #19            // cache line size encoding
> +       mov     \reg, #4                        // bytes per word
> +       lsl     \reg, \reg, \tmp                // actual cache line size
>         .endm
>
>  /*
> - *     __flush_dcache_all()
> + *     __flush_dcache_area(kaddr, size)
>   *
> - *     Flush the whole D-cache.
> + *     Ensure that the data held in the page kaddr is written back to the
> + *     page in question.
>   *
> - *     Corrupted registers: x0-x7, x9-x11
> + *     - kaddr   - kernel address
> + *     - size    - size in question
>   */
> -ENTRY(__flush_dcache_all)
> -       dmb     sy                              // ensure ordering with 
> previous memory accesses
> -       mrs     x0, clidr_el1                   // read clidr
> -       and     x3, x0, #0x7000000              // extract loc from clidr
> -       lsr     x3, x3, #23                     // left align loc bit field
> -       cbz     x3, finished                    // if loc is 0, then no need 
> to clean
> -       mov     x10, #0                         // start clean at cache level > 0
> -loop1:
> -       add     x2, x10, x10, lsr #1            // work out 3x current cache 
> level
> -       lsr     x1, x0, x2                      // extract cache type bits 
> from clidr
> -       and     x1, x1, #7                      // mask of the bits for 
> current cache only
> -       cmp     x1, #2                          // see what cache we have at 
> this level
> -       b.lt    skip                            // skip if no cache, or just 
> i-cache
> -       save_and_disable_irqs x9                // make CSSELR and CCSIDR 
> access atomic
> -       msr     csselr_el1, x10                 // select current cache level 
> in csselr
> -       isb                                     // isb to sych the new 
> cssr&csidr
> -       mrs     x1, ccsidr_el1                  // read the new ccsidr
> -       restore_irqs x9
> -       and     x2, x1, #7                      // extract the length of the 
> cache lines
> -       add     x2, x2, #4                      // add 4 (line length offset)
> -       mov     x4, #0x3ff
> -       and     x4, x4, x1, lsr #3              // find maximum number on the 
> way size
> -       clz     w5, w4                          // find bit position of way 
> size increment
> -       mov     x7, #0x7fff
> -       and     x7, x7, x1, lsr #13             // extract max number of the 
> index size
> -loop2:
> -       mov     x9, x4                          // create working copy of max 
> way size
> -loop3:
> -       lsl     x6, x9, x5
> -       orr     x11, x10, x6                    // factor way and cache 
> number into x11
> -       lsl     x6, x7, x2
> -       orr     x11, x11, x6                    // factor index number into 
> x11
> -       dc      cisw, x11                       // clean & invalidate by 
> set/way
> -       subs    x9, x9, #1                      // decrement the way
> -       b.ge    loop3
> -       subs    x7, x7, #1                      // decrement the index
> -       b.ge    loop2
> -skip:
> -       add     x10, x10, #2                    // increment cache number
> -       cmp     x3, x10
> -       b.gt    loop1
> -finished:
> -       mov     x10, #0                         // swith back to cache level 0
> -       msr     csselr_el1, x10                 // select current cache level 
> in csselr
> +ENTRY(__flush_dcache_area)
> +       dcache_line_size x2, x3
> +       add     x1, x0, x1
> +       sub     x3, x2, #1
> +       bic     x0, x0, x3
> +1:     dc      civac, x0                       // clean & invalidate D line 
> / unified line
> +       add     x0, x0, x2
> +       cmp     x0, x1
> +       b.lo    1b
>         dsb     sy
> -       isb
>         ret
> -ENDPROC(__flush_dcache_all)
> +ENDPROC(__flush_dcache_area)
> diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
> index 7650abe..9379dd1 100644
> --- a/xen/arch/arm/arm64/head.S
> +++ b/xen/arch/arm/arm64/head.S
> @@ -736,20 +736,39 @@ ENTRY(lookup_processor_type)
>          ret
>  /*
>   *  Function to transition from EFI loader in C, to Xen entry point.
> - *  void noreturn efi_xen_start(void *fdt_ptr);
> + *  void noreturn efi_xen_start(void *fdt_ptr, uint32_t fdt_size);
>   */
>  ENTRY(efi_xen_start)
>          /*
> +         * Preserve x0 (fdt pointer) across call to __flush_dcache_area,
> +         * restore for entry into Xen.
> +         */
> +        mov   x20, x0
> +
> +        /* flush dcache covering the FDT updated by EFI boot code */
> +        bl    __flush_dcache_area
> +
> +        /*
> +         * Flush dcache covering current runtime addresses
> +         * of xen text/data. Then flush all of icache.
> +         */
> +        adrp  x1, _start
> +        add   x1, x1, #:lo12:_start
> +        mov   x0, x1
> +        adrp  x2, _end
> +        add   x2, x2, #:lo12:_end
> +        sub   x1, x2, x1
> +
> +        bl    __flush_dcache_area
> +        ic    ialluis
> +        tlbi alle2
> +
> +        /*
>           * Turn off cache and MMU as Xen expects. EFI enables them, but also
>           * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
>           * MMU while executing EFI code before entering Xen.
>           * The EFI loader calls this to start Xen.
> -         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
> -         * restore for entry into Xen.
>           */
> -        mov   x20, x0
> -        bl    __flush_dcache_all
> -        ic    ialluis
>
>          /* Turn off Dcache and MMU */
>          mrs   x0, sctlr_el2
> diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h
> index 7abc059..d40d8b2 100644
> --- a/xen/arch/arm/efi/efi-boot.h
> +++ b/xen/arch/arm/efi/efi-boot.h
> @@ -7,7 +7,7 @@
>  #include <xen/libfdt/libfdt.h>
>  #include <asm/setup.h>
>
> -void noreturn efi_xen_start(void *fdt_ptr);
> +void noreturn efi_xen_start(void *fdt_ptr, uint32_t fdt_size);
>
>  #define DEVICE_TREE_GUID \
>  {0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 
> 0xe0}}
> @@ -343,7 +343,7 @@ static void __init efi_arch_pre_exit_boot(void)
>
>  static void __init efi_arch_post_exit_boot(void)
>  {
> -    efi_xen_start(fdt);
> +    efi_xen_start(fdt, fdt_totalsize(fdt));
>  }
>
>  static void __init efi_arch_cfg_file_early(EFI_FILE_HANDLE dir_handle, char 
> *section)
> --
> 1.9.1
>

_______________________________________________
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®.