[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |