|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH FOR-4.5] xen: arm64: Handle memory banks which are not 1GB aligned
On Fri, Oct 10, 2014 at 7:43 AM, Ian Campbell <ian.campbell@xxxxxxxxxx> wrote:
> The code in the arm64 version of setup_xenheap_mappings was making
> some very confused attempts to handle this but was bogus.
>
> As well as adjusting the mapping to start on a 1GB boundary we also
> need to account for the offset between the start of the mapping and
> the actual start of the heap when converting between page pointers,
> virtual addresses and machine addresses.
>
> I preferred to do this by explicitly accounting for the offset rather
> than adding an offset to the frametable because that approach could
> potentially waste a large amount of frametable (up to just less than
> 1GB worth) but also because of issues with converting mfns from
> outside the regions considered for pdx initialisation (which are not
> 1GB aligned) back and forth.
>
> We already have an idea of the distinction between the start of the
> direct map and the start of the xenheap in the difference between
> DIRECTMAP_VIRT_START and XENHEAP_VIRT_START. Until now these were the
> same thing, but now we change XENHEAP_VIRT_START to point to the
> actual start of heap not the mapping. Surprisingly there was only one
> place which was using the conceptually wrong value.
>
> Also change xenheap_virt_end to a vaddr_t for consistency.
>
> We've been lucky so far that most hardware happens to locate memory
> on a 1GB boundary (we did have reports of a system with memory at a
> half gig boundary which exhibited failures which I didn't manage to
> follow up on successfully). The EFI support has exposed this
> shortcoming by the way it handles reserved memory, which has a
> similar effect to having memory non-1GB aligned.
>
> arm32 does things differently here due to using a small Xen heap and
> a demand mapped domain heap, so isn't affected.
>
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> Cc: Suravee Suthikulanit <suravee.suthikulpanit@xxxxxxx>
> Cc: Roy Franz <roy.franz@xxxxxxxxxx>
> Cc: Vijay Kilari <vijay.kilari@xxxxxxxxx>
Works for me on the FVP model. This platform didn't trigger the bug,
so it continues
to work as before.
Roy
> ---
> FOR-4.5: This is a bug fix.
> ---
> xen/arch/arm/mm.c | 36 +++++++++++++++++++++++++-----------
> xen/include/asm-arm/config.h | 2 +-
> xen/include/asm-arm/mm.h | 7 +++++--
> 3 files changed, 31 insertions(+), 14 deletions(-)
>
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index c5b48ef..97e5bc39 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -138,7 +138,10 @@ static paddr_t phys_offset;
> /* Limits of the Xen heap */
> unsigned long xenheap_mfn_start __read_mostly = ~0UL;
> unsigned long xenheap_mfn_end __read_mostly;
> -unsigned long xenheap_virt_end __read_mostly;
> +vaddr_t xenheap_virt_end __read_mostly;
> +#ifdef CONFIG_ARM_64
> +vaddr_t xenheap_virt_start __read_mostly;
> +#endif
>
> unsigned long frametable_base_pdx __read_mostly;
> unsigned long frametable_virt_end __read_mostly;
> @@ -155,7 +158,11 @@ static inline void
> check_memory_layout_alignment_constraints(void) {
> BUILD_BUG_ON(FIXMAP_ADDR(0) & ~SECOND_MASK);
> BUILD_BUG_ON(BOOT_RELOC_VIRT_START & ~SECOND_MASK);
> /* 1GB aligned regions */
> +#ifdef CONFIG_ARM_32
> BUILD_BUG_ON(XENHEAP_VIRT_START & ~FIRST_MASK);
> +#else
> + BUILD_BUG_ON(DIRECTMAP_VIRT_START & ~FIRST_MASK);
> +#endif
> /* Page table structure constraints */
> #ifdef CONFIG_ARM_64
> BUILD_BUG_ON(zeroeth_table_offset(XEN_VIRT_START));
> @@ -665,12 +672,19 @@ void __init setup_xenheap_mappings(unsigned long
> base_mfn,
> unsigned long nr_mfns)
> {
> lpae_t *first, pte;
> - unsigned long offset, end_mfn;
> + unsigned long mfn, end_mfn;
> vaddr_t vaddr;
>
> - /* First call sets the xenheap physical offset. */
> + /* Align to previous 1GB boundary */
> + mfn = base_mfn & ~((FIRST_SIZE>>PAGE_SHIFT)-1);
> +
> + /* First call sets the xenheap physical and virtual offset. */
> if ( xenheap_mfn_start == ~0UL )
> + {
> xenheap_mfn_start = base_mfn;
> + xenheap_virt_start = DIRECTMAP_VIRT_START +
> + (base_mfn - mfn) * PAGE_SIZE;
> + }
>
> if ( base_mfn < xenheap_mfn_start )
> panic("cannot add xenheap mapping at %lx below heap start %lx",
> @@ -678,13 +692,13 @@ void __init setup_xenheap_mappings(unsigned long
> base_mfn,
>
> end_mfn = base_mfn + nr_mfns;
>
> - /* Align to previous 1GB boundary */
> - base_mfn &= ~((FIRST_SIZE>>PAGE_SHIFT)-1);
> -
> - offset = pfn_to_pdx(base_mfn - xenheap_mfn_start);
> - vaddr = DIRECTMAP_VIRT_START + offset*PAGE_SIZE;
> + /*
> + * Virtual address aligned to previous 1GB to match physical
> + * address alignment done above.
> + */
> + vaddr = (vaddr_t)mfn_to_virt(base_mfn) & FIRST_MASK;
>
> - while ( base_mfn < end_mfn )
> + while ( mfn < end_mfn )
> {
> int slot = zeroeth_table_offset(vaddr);
> lpae_t *p = &xen_pgtable[slot];
> @@ -716,11 +730,11 @@ void __init setup_xenheap_mappings(unsigned long
> base_mfn,
> first = mfn_to_virt(first_mfn);
> }
>
> - pte = mfn_to_xen_entry(base_mfn, WRITEALLOC);
> + pte = mfn_to_xen_entry(mfn, WRITEALLOC);
> /* TODO: Set pte.pt.contig when appropriate. */
> write_pte(&first[first_table_offset(vaddr)], pte);
>
> - base_mfn += FIRST_SIZE>>PAGE_SHIFT;
> + mfn += FIRST_SIZE>>PAGE_SHIFT;
> vaddr += FIRST_SIZE;
> }
>
> diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
> index 59b2887..264e2c1 100644
> --- a/xen/include/asm-arm/config.h
> +++ b/xen/include/asm-arm/config.h
> @@ -162,7 +162,7 @@
> #define DIRECTMAP_SIZE (SLOT0_ENTRY_SIZE * (265-256))
> #define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + DIRECTMAP_SIZE - 1)
>
> -#define XENHEAP_VIRT_START DIRECTMAP_VIRT_START
> +#define XENHEAP_VIRT_START xenheap_virt_start
>
> #define HYPERVISOR_VIRT_END DIRECTMAP_VIRT_END
>
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index 1e4711c..d25e485 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -110,7 +110,10 @@ struct page_info
> #define PGC_count_mask ((1UL<<PGC_count_width)-1)
>
> extern unsigned long xenheap_mfn_start, xenheap_mfn_end;
> -extern unsigned long xenheap_virt_end;
> +extern vaddr_t xenheap_virt_end;
> +#ifdef CONFIG_ARM_64
> +extern vaddr_t xenheap_virt_start;
> +#endif
>
> #ifdef CONFIG_ARM_32
> #define is_xen_heap_page(page) is_xen_heap_mfn(page_to_mfn(page))
> @@ -227,7 +230,7 @@ static inline void *maddr_to_virt(paddr_t ma)
> static inline void *maddr_to_virt(paddr_t ma)
> {
> ASSERT(pfn_to_pdx(ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT));
> - return (void *)(DIRECTMAP_VIRT_START -
> + return (void *)(XENHEAP_VIRT_START -
> pfn_to_paddr(xenheap_mfn_start) +
> ((ma & ma_va_bottom_mask) |
> ((ma & ma_top_mask) >> pfn_pdx_hole_shift)));
> --
> 1.7.10.4
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |