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

Re: [Xen-devel] [PATCH v3 26/28] xen/arm64: head: Use a page mapping for the 1:1 mapping in create_page_tables()



On Mon, 12 Aug 2019, Julien Grall wrote:
> At the moment the function create_page_tables() will use 1GB/2MB
> mapping for the identity mapping. As we don't know what is present
> before and after Xen in memory, we may end up to map
> device/reserved-memory with cacheable memory. This may result to
> mismatched attributes as other users may access the same region
> differently.
> 
> To prevent any issues, we should only map the strict minimum in the
> 1:1 mapping. A check in xen.lds.S already guarantees anything
> necessary for turning on the MMU fits in a page (at the moment 4K).
> 
> As only one page will be mapped for the 1:1 mapping, it is necessary
> to pre-allocate a page for the 3rd level table.
> 
> For simplicity, all the tables that may be necessary for setting up the
> 1:1 mapping are linked together in advance. They will then be linked to
> the boot page tables at the correct level.
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxx>
> 
> ---
>     Changes in v3:
>         - Patch added
> ---
>  xen/arch/arm/arm64/head.S | 176 
> ++++++++++++++++++++--------------------------
>  xen/arch/arm/mm.c         |   2 +
>  2 files changed, 78 insertions(+), 100 deletions(-)
> 
> diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
> index f4177dbba1..1e5b1035b8 100644
> --- a/xen/arch/arm/arm64/head.S
> +++ b/xen/arch/arm/arm64/head.S
> @@ -566,100 +566,17 @@ ENDPROC(cpu_init)
>   *   x19: paddr(start)
>   *   x20: phys offset
>   *
> - * Clobbers x0 - x4, x25
> - *
> - * Register usage within this function:
> - *   x25: Identity map in place
> + * Clobbers x0 - x4
>   */
>  create_page_tables:
> -        /*
> -         * If Xen is loaded at exactly XEN_VIRT_START then we don't
> -         * need an additional 1:1 mapping, the virtual mapping will
> -         * suffice.
> -         */
> -        cmp   x19, #XEN_VIRT_START
> -        cset  x25, eq                /* x25 := identity map in place, or not 
> */
> -
> -        load_paddr x4, boot_pgtable
> -
> -        /* Setup boot_pgtable: */
> -        load_paddr x1, boot_first
> -
> -        /* ... map boot_first in boot_pgtable[0] */
> -        mov   x3, #PT_PT             /* x2 := table map of boot_first */
> -        orr   x2, x1, x3             /*       + rights for linear PT */
> -        str   x2, [x4, #0]           /* Map it in slot 0 */
> -
> -        /* ... map of paddr(start) in boot_pgtable+boot_first_id */
> -        lsr   x1, x19, #ZEROETH_SHIFT/* Offset of base paddr in boot_pgtable 
> */
> -        cbz   x1, 1f                 /* It's in slot 0, map in boot_first
> -                                      * or boot_second later on */
> -
> -        /*
> -         * Level zero does not support superpage mappings, so we have
> -         * to use an extra first level page in which we create a 1GB mapping.
> -         */
> -        load_paddr x2, boot_first_id
> -
> -        mov   x3, #PT_PT             /* x2 := table map of boot_first_id */
> -        orr   x2, x2, x3             /*       + rights for linear PT */
> -        str   x2, [x4, x1, lsl #3]
> -
> -        load_paddr x4, boot_first_id
> -
> -        lsr   x1, x19, #FIRST_SHIFT  /* x1 := Offset of base paddr in 
> boot_first_id */
> -        lsl   x2, x1, #FIRST_SHIFT   /* x2 := Base address for 1GB mapping */
> -        mov   x3, #PT_MEM            /* x2 := Section map */
> -        orr   x2, x2, x3
> -        and   x1, x1, #LPAE_ENTRY_MASK /* x1 := Slot offset */
> -        str   x2, [x4, x1, lsl #3]   /* Mapping of paddr(start) */
> -        mov   x25, #1                /* x25 := identity map now in place */
> -
> -1:      /* Setup boot_first: */
> -        load_paddr x4, boot_first   /* Next level into boot_first */
> -
> -        /* ... map boot_second in boot_first[0] */
> -        load_paddr x1, boot_second
> -        mov   x3, #PT_PT             /* x2 := table map of boot_second */
> -        orr   x2, x1, x3             /*       + rights for linear PT */
> -        str   x2, [x4, #0]           /* Map it in slot 0 */
> -
> -        /* ... map of paddr(start) in boot_first */
> -        cbnz  x25, 1f                /* x25 is set if already created */
> -        lsr   x2, x19, #FIRST_SHIFT  /* x2 := Offset of base paddr in 
> boot_first */
> -        and   x1, x2, #LPAE_ENTRY_MASK /* x1 := Slot to use */
> -        cbz   x1, 1f                 /* It's in slot 0, map in boot_second */
> -
> -        lsl   x2, x2, #FIRST_SHIFT   /* Base address for 1GB mapping */
> -        mov   x3, #PT_MEM            /* x2 := Section map */
> -        orr   x2, x2, x3
> -        str   x2, [x4, x1, lsl #3]   /* Create mapping of paddr(start)*/
> -        mov   x25, #1                /* x25 := identity map now in place */
> -
> -1:      /* Setup boot_second: */
> -        load_paddr x4, boot_second
> -
> -        /* ... map boot_third in boot_second[1] */
> -        load_paddr x1, boot_third
> -        mov   x3, #PT_PT             /* x2 := table map of boot_third */
> -        orr   x2, x1, x3             /*       + rights for linear PT */
> -        str   x2, [x4, #8]           /* Map it in slot 1 */
> -
> -        /* ... map of paddr(start) in boot_second */
> -        cbnz  x25, 1f                /* x25 is set if already created */
> -        lsr   x2, x19, #SECOND_SHIFT /* x2 := Offset of base paddr in 
> boot_second */
> -        and   x1, x2, #LPAE_ENTRY_MASK /* x1 := Slot to use */
> -        cmp   x1, #1
> -        b.eq  virtphys_clash         /* It's in slot 1, which we cannot 
> handle */
> -
> -        lsl   x2, x2, #SECOND_SHIFT  /* Base address for 2MB mapping */
> -        mov   x3, #PT_MEM            /* x2 := Section map */
> -        orr   x2, x2, x3
> -        str   x2, [x4, x1, lsl #3]   /* Create mapping of paddr(start)*/
> -        mov   x25, #1                /* x25 := identity map now in place */
> +        /* Prepare the page-tables for mapping Xen */
> +        ldr   x0, =XEN_VIRT_START
> +        create_table_entry boot_pgtable, boot_first, x0, ZEROETH_SHIFT, x1, 
> x2, x3
> +        create_table_entry boot_first, boot_second, x0, FIRST_SHIFT, x1, x2, 
> x3
> +        create_table_entry boot_second, boot_third, x0, SECOND_SHIFT, x1, 
> x2, x3
>  
> -1:      /* Setup boot_third: */
> -        load_paddr x4, boot_third
> +        /* Map Xen */
> +        adr_l x4, boot_third
>  
>          lsr   x2, x19, #THIRD_SHIFT  /* Base address for 4K mapping */
>          lsl   x2, x2, #THIRD_SHIFT
> @@ -674,21 +591,80 @@ create_page_tables:
>          cmp   x1, #(LPAE_ENTRIES<<3) /* 512 entries per page */
>          b.lt  1b

Why can't we use create_mapping_entry here?


> -        /* Defer fixmap and dtb mapping until after paging enabled, to
> -         * avoid them clashing with the 1:1 mapping. */
> +        /*
> +         * If Xen is loaded at exactly XEN_VIRT_START then we don't
> +         * need an additional 1:1 mapping, the virtual mapping will
> +         * suffice.
> +         */
> +        cmp   x19, #XEN_VIRT_START
> +        bne   1f
> +        ret
> +1:
> +        /*
> +         * Only the first page of Xen will be part of the 1:1 mapping.
> +         * All the boot_*_id tables are linked together even if they may
> +         * not be all used. They will then be linked to the boot page
> +         * tables at the correct level.
> +         */
> +        create_table_entry boot_first_id, boot_second_id, x19, FIRST_SHIFT, 
> x0, x1, x2
> +        create_table_entry boot_second_id, boot_third_id, x19, SECOND_SHIFT, 
> x0, x1, x2

If I understood the code right, it is not actually required to link
boot_first_id -> boot_second_id and/or boot_second_id -> boot_third_id:
it depends on whether x19 clashes with XEN_FIRST_SLOT, XEN_SECOND_SLOT,
etc. Do you think it would be possible without making the code complex
to only call create_table_entry boot_first_id, boot_second_id and
create_table_entry boot_second_id, boot_third_id when required?  So
moving the calls below after the relevant checks? It looks like it could
be done by adding those calls before "ret". I wouldn't mind if they are
duplicated but we could avoid it by adding appropriate labels and having
a single return path:

out1:
  create_table_entry boot_first_id, boot_second_id, x19, FIRST_SHIFT, x0, x1, x2
out2:
  create_table_entry boot_second_id, boot_third_id, x19, SECOND_SHIFT, x0, x1, 
x2
out3:
  ret

(I have similar comments for the arm32 version, I guess your answers
will be the same for both.)


> +        create_mapping_entry boot_third_id, x19, x19, x0, x1, x2
> +
> +        /*
> +         * Find the zeroeth slot used. Link boot_first_id into
> +         * boot_pgtable if the slot is not XEN_ZEROETH_SLOT. For slot
> +         * XEN_ZEROETH_SLOT, the tables associated with the 1:1 mapping
> +         * will need to be linked in boot_first or boot_second.
> +         */
> +        lsr   x0, x19, #ZEROETH_SHIFT   /* x0 := zeroeth slot */
> +        cmp   x0, #XEN_ZEROETH_SLOT
> +        beq   1f
> +        /*
> +         * It is not in slot XEN_ZEROETH_SLOT. Link boot_first_id
> +         * into boot_pgtable.
> +         */
> +        create_table_entry boot_pgtable, boot_first_id, x19, ZEROETH_SHIFT, 
> x0, x1, x2
> +        ret
> +
> +1:
> +        /*
> +         * Find the first slot used. Link boot_second_id into boot_first
> +         * if the slot is not XEN_FIRST_SLOT. For slot XEN_FIRST_SLOT,
> +         * the tables associated with the 1:1 mapping will need to be
> +         * linked in boot_second.
> +         */
> +        lsr   x0, x19, #FIRST_SHIFT
> +        and   x0, x0, #LPAE_ENTRY_MASK  /* x0 := first slot */
> +        cmp   x0, #XEN_FIRST_SLOT
> +        beq   1f
> +        /*
> +         * It is not in slot XEN_FIRST_SLOT. Link boot_second_id into
> +         * boot_first
> +         */
> +        create_table_entry boot_first, boot_second_id, x19, FIRST_SHIFT, x0, 
> x1, x2
> +        ret
>  
> -        /* boot pagetable setup complete */
> +1:
> +        /*
> +         * Find the second slot used. Link boot_third_id into boot_second
> +         * if the slot is not XEN_SECOND_SLOT. For slot XEN_SECOND_SLOT,
> +         * Xen is not yet able to handle it.
> +         */
> +        lsr   x0, x19, #SECOND_SHIFT
> +        and   x0, x0, #LPAE_ENTRY_MASK  /* x0 := first slot */
> +        cmp   x0, #XEN_SECOND_SLOT
> +        beq   virtphys_clash
> +        /*
> +         * It is not in slot XEN_SECOND_SLOT. Link boot_third_id into
> +         * boot_second.
> +         */
> +        create_table_entry boot_second, boot_third_id, x19, SECOND_SHIFT, 
> x0, x1, x2
> +        ret
>  
> -        cbnz  x25, 1f                /* Did we manage to create an identity 
> mapping ? */
> -        PRINT("Unable to build boot page tables - Failed to identity map 
> Xen.\r\n")
> -        b     fail
>  virtphys_clash:
>          /* Identity map clashes with boot_third, which we cannot handle yet 
> */
>          PRINT("- Unable to build boot page tables - virt and phys addresses 
> clash. -\r\n")
>          b     fail
> -
> -1:
> -        ret
>  ENDPROC(create_page_tables)
>  
>  /*
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index 65552da4ba..72ffea7472 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -105,6 +105,8 @@ DEFINE_BOOT_PAGE_TABLE(boot_pgtable);
>  #ifdef CONFIG_ARM_64
>  DEFINE_BOOT_PAGE_TABLE(boot_first);
>  DEFINE_BOOT_PAGE_TABLE(boot_first_id);
> +DEFINE_BOOT_PAGE_TABLE(boot_second_id);
> +DEFINE_BOOT_PAGE_TABLE(boot_third_id);
>  #endif
>  DEFINE_BOOT_PAGE_TABLE(boot_second);
>  DEFINE_BOOT_PAGE_TABLE(boot_third);
> -- 
> 2.11.0
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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