diff mbox series

[v6,07/13] xen/arm: Split MMU system SMP MM bringup code to mmu/smpboot.c

Message ID 20230828013224.669433-8-Henry.Wang@arm.com (mailing list archive)
State Superseded
Headers show
Series xen/arm: Split MMU code as the prepration of MPU work | expand

Commit Message

Henry Wang Aug. 28, 2023, 1:32 a.m. UTC
Move the code related to secondary page table initialization, clear
boot page tables and the global variable definitions of these boot
page tables from arch/arm/mm.c to arch/arm/mmu/smpboot.c

Drop the "static" attribute of arm32 global variable cpu0_pgtable,
and declare it in the arm32 mm.h header, because this variable
will be used by both arch/arm/mm.c and arch/arm/mmu/smpboot.c.

Take the opportunity to fix the in-code comment coding styles when
possible.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
Signed-off-by: Penny Zheng <penny.zheng@arm.com>
---
v6:
- Rework the original patch "[v5,07/13] xen/arm: Extract MMU-specific
  code", only split the smpboot related code out in this patch.
---
 xen/arch/arm/include/asm/arm32/mm.h |   1 +
 xen/arch/arm/mm.c                   | 103 +----------------------
 xen/arch/arm/mmu/Makefile           |   1 +
 xen/arch/arm/mmu/smpboot.c          | 121 ++++++++++++++++++++++++++++
 4 files changed, 124 insertions(+), 102 deletions(-)
 create mode 100644 xen/arch/arm/mmu/smpboot.c

Comments

Julien Grall Sept. 25, 2023, 7:13 p.m. UTC | #1
Hi Henry,

On 28/08/2023 02:32, Henry Wang wrote:
> Move the code related to secondary page table initialization, clear
> boot page tables and the global variable definitions of these boot
> page tables from arch/arm/mm.c to arch/arm/mmu/smpboot.c
> 
> Drop the "static" attribute of arm32 global variable cpu0_pgtable,
> and declare it in the arm32 mm.h header, because this variable
> will be used by both arch/arm/mm.c and arch/arm/mmu/smpboot.c.

I don't think you need to export cpu0_pgtable. You can instead replace 
use with per_cpu(xen_pgtable, 0).

> 
> Take the opportunity to fix the in-code comment coding styles when
> possible.
> 
> Signed-off-by: Henry Wang <Henry.Wang@arm.com>
> Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> ---
> v6:
> - Rework the original patch "[v5,07/13] xen/arm: Extract MMU-specific
>    code", only split the smpboot related code out in this patch.
> ---
>   xen/arch/arm/include/asm/arm32/mm.h |   1 +
>   xen/arch/arm/mm.c                   | 103 +----------------------
>   xen/arch/arm/mmu/Makefile           |   1 +
>   xen/arch/arm/mmu/smpboot.c          | 121 ++++++++++++++++++++++++++++
>   4 files changed, 124 insertions(+), 102 deletions(-)
>   create mode 100644 xen/arch/arm/mmu/smpboot.c
> 
> diff --git a/xen/arch/arm/include/asm/arm32/mm.h b/xen/arch/arm/include/asm/arm32/mm.h
> index 856f2dbec4..0e149945f9 100644
> --- a/xen/arch/arm/include/asm/arm32/mm.h
> +++ b/xen/arch/arm/include/asm/arm32/mm.h
> @@ -6,6 +6,7 @@
>   #include <asm/lpae.h>
>   
>   DECLARE_PER_CPU(lpae_t *, xen_pgtable);
> +extern DEFINE_PAGE_TABLE(cpu0_pgtable);
>   
>   /*
>    * Only a limited amount of RAM, called xenheap, is always mapped on ARM32.
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index b42814077c..f3ef0da0e3 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -27,39 +27,6 @@
>   #undef mfn_to_virt
>   #define mfn_to_virt(mfn) __mfn_to_virt(mfn_x(mfn))
>   
> -/* Static start-of-day pagetables that we use before the allocators
> - * are up. These are used by all CPUs during bringup before switching
> - * to the CPUs own pagetables.
> - *
> - * These pagetables have a very simple structure. They include:
> - *  - XEN_VIRT_SIZE worth of L3 mappings of xen at XEN_VIRT_START, boot_first
> - *    and boot_second are used to populate the tables down to boot_third
> - *    which contains the actual mapping.
> - *  - a 1:1 mapping of xen at its current physical address. This uses a
> - *    section mapping at whichever of boot_{pgtable,first,second}
> - *    covers that physical address.
> - *
> - * For the boot CPU these mappings point to the address where Xen was
> - * loaded by the bootloader. For secondary CPUs they point to the
> - * relocated copy of Xen for the benefit of secondary CPUs.
> - *
> - * In addition to the above for the boot CPU the device-tree is
> - * initially mapped in the boot misc slot. This mapping is not present
> - * for secondary CPUs.
> - *
> - * Finally, if EARLY_PRINTK is enabled then xen_fixmap will be mapped
> - * by the CPU once it has moved off the 1:1 mapping.
> - */
> -DEFINE_BOOT_PAGE_TABLE(boot_pgtable);
> -#ifdef CONFIG_ARM_64
> -DEFINE_BOOT_PAGE_TABLE(boot_first);
> -DEFINE_BOOT_PAGE_TABLE(boot_first_id);
> -#endif
> -DEFINE_BOOT_PAGE_TABLE(boot_second_id);
> -DEFINE_BOOT_PAGE_TABLE(boot_third_id);
> -DEFINE_BOOT_PAGE_TABLE(boot_second);
> -DEFINE_BOOT_PAGE_TABLES(boot_third, XEN_NR_ENTRIES(2));
> -
>   /* Main runtime page tables */
>   
>   /*
> @@ -80,7 +47,7 @@ static DEFINE_PAGE_TABLE(xen_first);
>   DEFINE_PER_CPU(lpae_t *, xen_pgtable);
>   #define THIS_CPU_PGTABLE this_cpu(xen_pgtable)
>   /* Root of the trie for cpu0, other CPU's PTs are dynamically allocated */
> -static DEFINE_PAGE_TABLE(cpu0_pgtable);
> +DEFINE_PAGE_TABLE(cpu0_pgtable);
>   #endif
>   
>   /* Common pagetable leaves */
> @@ -277,13 +244,6 @@ static void xen_pt_enforce_wnx(void)
>       flush_xen_tlb_local();
>   }
>   
> -/* Clear a translation table and clean & invalidate the cache */
> -static void clear_table(void *table)
> -{
> -    clear_page(table);
> -    clean_and_invalidate_dcache_va_range(table, PAGE_SIZE);
> -}
> -
>   /* Boot-time pagetable setup.
>    * Changes here may need matching changes in head.S */
>   void __init setup_pagetables(unsigned long boot_phys_offset)
> @@ -362,67 +322,6 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
>   #endif
>   }
>   
> -static void clear_boot_pagetables(void)
> -{
> -    /*
> -     * Clear the copy of the boot pagetables. Each secondary CPU
> -     * rebuilds these itself (see head.S).
> -     */
> -    clear_table(boot_pgtable);
> -#ifdef CONFIG_ARM_64
> -    clear_table(boot_first);
> -    clear_table(boot_first_id);
> -#endif
> -    clear_table(boot_second);
> -    clear_table(boot_third);
> -}
> -
> -#ifdef CONFIG_ARM_64
> -int init_secondary_pagetables(int cpu)
> -{
> -    clear_boot_pagetables();
> -
> -    /* Set init_ttbr for this CPU coming up. All CPus share a single setof
> -     * pagetables, but rewrite it each time for consistency with 32 bit. */
> -    init_ttbr = (uintptr_t) xen_pgtable + phys_offset;
> -    clean_dcache(init_ttbr);
> -    return 0;
> -}
> -#else
> -int init_secondary_pagetables(int cpu)
> -{
> -    lpae_t *first;
> -
> -    first = alloc_xenheap_page(); /* root == first level on 32-bit 3-level trie */
> -
> -    if ( !first )
> -    {
> -        printk("CPU%u: Unable to allocate the first page-table\n", cpu);
> -        return -ENOMEM;
> -    }
> -
> -    /* Initialise root pagetable from root of boot tables */
> -    memcpy(first, cpu0_pgtable, PAGE_SIZE);
> -    per_cpu(xen_pgtable, cpu) = first;
> -
> -    if ( !init_domheap_mappings(cpu) )
> -    {
> -        printk("CPU%u: Unable to prepare the domheap page-tables\n", cpu);
> -        per_cpu(xen_pgtable, cpu) = NULL;
> -        free_xenheap_page(first);
> -        return -ENOMEM;
> -    }
> -
> -    clear_boot_pagetables();
> -
> -    /* Set init_ttbr for this CPU coming up */
> -    init_ttbr = __pa(first);
> -    clean_dcache(init_ttbr);
> -
> -    return 0;
> -}
> -#endif
> -
>   /* MMU setup for secondary CPUS (which already have paging enabled) */
>   void mmu_init_secondary_cpu(void)
>   {
> diff --git a/xen/arch/arm/mmu/Makefile b/xen/arch/arm/mmu/Makefile
> index bdfc2e077d..0e82015ee1 100644
> --- a/xen/arch/arm/mmu/Makefile
> +++ b/xen/arch/arm/mmu/Makefile
> @@ -1 +1,2 @@
>   obj-y += pt.o
> +obj-y += smpboot.o
> diff --git a/xen/arch/arm/mmu/smpboot.c b/xen/arch/arm/mmu/smpboot.c
> new file mode 100644
> index 0000000000..a673989d09
> --- /dev/null
> +++ b/xen/arch/arm/mmu/smpboot.c
> @@ -0,0 +1,121 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * xen/arch/arm/mmu/smpboot.c
> + *
> + * MMU system secondary CPUs MM bringup code.
> + */
> +
> +#include <xen/domain_page.h>
> +
> +/*
> + * Static start-of-day pagetables that we use before the allocators
> + * are up. These are used by all CPUs during bringup before switching
> + * to the CPUs own pagetables.
> + *
> + * These pagetables have a very simple structure. They include:
> + *  - XEN_VIRT_SIZE worth of L3 mappings of xen at XEN_VIRT_START, boot_first
> + *    and boot_second are used to populate the tables down to boot_third
> + *    which contains the actual mapping.
> + *  - a 1:1 mapping of xen at its current physical address. This uses a
> + *    section mapping at whichever of boot_{pgtable,first,second}
> + *    covers that physical address.
> + *
> + * For the boot CPU these mappings point to the address where Xen was
> + * loaded by the bootloader. For secondary CPUs they point to the
> + * relocated copy of Xen for the benefit of secondary CPUs.
> + *
> + * In addition to the above for the boot CPU the device-tree is
> + * initially mapped in the boot misc slot. This mapping is not present
> + * for secondary CPUs.
> + *
> + * Finally, if EARLY_PRINTK is enabled then xen_fixmap will be mapped
> + * by the CPU once it has moved off the 1:1 mapping.
> + */
> +DEFINE_BOOT_PAGE_TABLE(boot_pgtable);
> +#ifdef CONFIG_ARM_64
> +DEFINE_BOOT_PAGE_TABLE(boot_first);
> +DEFINE_BOOT_PAGE_TABLE(boot_first_id);
> +#endif
> +DEFINE_BOOT_PAGE_TABLE(boot_second_id);
> +DEFINE_BOOT_PAGE_TABLE(boot_third_id);
> +DEFINE_BOOT_PAGE_TABLE(boot_second);
> +DEFINE_BOOT_PAGE_TABLES(boot_third, XEN_NR_ENTRIES(2));

Strictly speaking, boot_* are also used for CPU0 but not in C code. That 
said, I am ok if there are moved here.

In the longer term, I would actually like to remove boot_*. This should 
already be possible for arm64 (in fact they are not used for secondary 
CPU bring-up). For arm32, it requires a bit more work.

Anyway, that's not a request for your series. :)

> +
> +/* Clear a translation table and clean & invalidate the cache */
> +static void clear_table(void *table)
> +{
> +    clear_page(table);
> +    clean_and_invalidate_dcache_va_range(table, PAGE_SIZE);
> +}
> +
> +static void clear_boot_pagetables(void)
> +{
> +    /*
> +     * Clear the copy of the boot pagetables. Each secondary CPU
> +     * rebuilds these itself (see head.S).
> +     */
> +    clear_table(boot_pgtable);
> +#ifdef CONFIG_ARM_64
> +    clear_table(boot_first);
> +    clear_table(boot_first_id);
> +#endif
> +    clear_table(boot_second);
> +    clear_table(boot_third);
> +}
> +
> +#ifdef CONFIG_ARM_64
> +int init_secondary_pagetables(int cpu)
> +{
> +    clear_boot_pagetables();
> +
> +    /*
> +     * Set init_ttbr for this CPU coming up. All CPus share a single setof
> +     * pagetables, but rewrite it each time for consistency with 32 bit.
> +     */
> +    init_ttbr = (uintptr_t) xen_pgtable + phys_offset;
> +    clean_dcache(init_ttbr);
> +    return 0;
> +}
> +#else
> +int init_secondary_pagetables(int cpu)
> +{
> +    lpae_t *first;
> +
> +    first = alloc_xenheap_page(); /* root == first level on 32-bit 3-level trie */
> +
> +    if ( !first )
> +    {
> +        printk("CPU%u: Unable to allocate the first page-table\n", cpu);
> +        return -ENOMEM;
> +    }
> +
> +    /* Initialise root pagetable from root of boot tables */
> +    memcpy(first, cpu0_pgtable, PAGE_SIZE);
> +    per_cpu(xen_pgtable, cpu) = first;
> +
> +    if ( !init_domheap_mappings(cpu) )
> +    {
> +        printk("CPU%u: Unable to prepare the domheap page-tables\n", cpu);
> +        per_cpu(xen_pgtable, cpu) = NULL;
> +        free_xenheap_page(first);
> +        return -ENOMEM;
> +    }
> +
> +    clear_boot_pagetables();
> +
> +    /* Set init_ttbr for this CPU coming up */
> +    init_ttbr = __pa(first);

init_ttbr will only be used by smpboot.c and assembly code. So I think 
the declaration needs to also be moved and the prototype moved to mmu/mm.h.

Cheers,
Henry Wang Sept. 26, 2023, 1:31 a.m. UTC | #2
Hi Julien,

> On Sep 26, 2023, at 03:13, Julien Grall <julien@xen.org> wrote:
> 
> Hi Henry,
> 
> On 28/08/2023 02:32, Henry Wang wrote:
>> Move the code related to secondary page table initialization, clear
>> boot page tables and the global variable definitions of these boot
>> page tables from arch/arm/mm.c to arch/arm/mmu/smpboot.c
>> Drop the "static" attribute of arm32 global variable cpu0_pgtable,
>> and declare it in the arm32 mm.h header, because this variable
>> will be used by both arch/arm/mm.c and arch/arm/mmu/smpboot.c.
> 
> I don't think you need to export cpu0_pgtable. You can instead replace use with per_cpu(xen_pgtable, 0).

You mean using
```
memcpy(first, per_cpu(xen_pgtable, 0), PAGE_SIZE);
```
in the arm32 implementation of prepare_secondary_mm() in mmu/smpboot.c?

That sounds good to me and I will fix in v7.

> 
>> + */
>> +DEFINE_BOOT_PAGE_TABLE(boot_pgtable);
>> +#ifdef CONFIG_ARM_64
>> +DEFINE_BOOT_PAGE_TABLE(boot_first);
>> +DEFINE_BOOT_PAGE_TABLE(boot_first_id);
>> +#endif
>> +DEFINE_BOOT_PAGE_TABLE(boot_second_id);
>> +DEFINE_BOOT_PAGE_TABLE(boot_third_id);
>> +DEFINE_BOOT_PAGE_TABLE(boot_second);
>> +DEFINE_BOOT_PAGE_TABLES(boot_third, XEN_NR_ENTRIES(2));
> 
> Strictly speaking, boot_* are also used for CPU0 but not in C code. That said, I am ok if there are moved here.
> 
> In the longer term, I would actually like to remove boot_*. This should already be possible for arm64 (in fact they are not used for secondary CPU bring-up). For arm32, it requires a bit more work.
> 
> Anyway, that's not a request for your series. :)

Let’s see if we can do that in 4.19 dev cycle then :)

> 
>> +    /* Set init_ttbr for this CPU coming up */
>> +    init_ttbr = __pa(first);
> 
> init_ttbr will only be used by smpboot.c and assembly code. So I think the declaration needs to also be moved and the prototype moved to mmu/mm.h.

Ok, will do in v7.

Kind regards,
Henry

> 
> Cheers,
> 
> -- 
> Julien Grall
diff mbox series

Patch

diff --git a/xen/arch/arm/include/asm/arm32/mm.h b/xen/arch/arm/include/asm/arm32/mm.h
index 856f2dbec4..0e149945f9 100644
--- a/xen/arch/arm/include/asm/arm32/mm.h
+++ b/xen/arch/arm/include/asm/arm32/mm.h
@@ -6,6 +6,7 @@ 
 #include <asm/lpae.h>
 
 DECLARE_PER_CPU(lpae_t *, xen_pgtable);
+extern DEFINE_PAGE_TABLE(cpu0_pgtable);
 
 /*
  * Only a limited amount of RAM, called xenheap, is always mapped on ARM32.
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index b42814077c..f3ef0da0e3 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -27,39 +27,6 @@ 
 #undef mfn_to_virt
 #define mfn_to_virt(mfn) __mfn_to_virt(mfn_x(mfn))
 
-/* Static start-of-day pagetables that we use before the allocators
- * are up. These are used by all CPUs during bringup before switching
- * to the CPUs own pagetables.
- *
- * These pagetables have a very simple structure. They include:
- *  - XEN_VIRT_SIZE worth of L3 mappings of xen at XEN_VIRT_START, boot_first
- *    and boot_second are used to populate the tables down to boot_third
- *    which contains the actual mapping.
- *  - a 1:1 mapping of xen at its current physical address. This uses a
- *    section mapping at whichever of boot_{pgtable,first,second}
- *    covers that physical address.
- *
- * For the boot CPU these mappings point to the address where Xen was
- * loaded by the bootloader. For secondary CPUs they point to the
- * relocated copy of Xen for the benefit of secondary CPUs.
- *
- * In addition to the above for the boot CPU the device-tree is
- * initially mapped in the boot misc slot. This mapping is not present
- * for secondary CPUs.
- *
- * Finally, if EARLY_PRINTK is enabled then xen_fixmap will be mapped
- * by the CPU once it has moved off the 1:1 mapping.
- */
-DEFINE_BOOT_PAGE_TABLE(boot_pgtable);
-#ifdef CONFIG_ARM_64
-DEFINE_BOOT_PAGE_TABLE(boot_first);
-DEFINE_BOOT_PAGE_TABLE(boot_first_id);
-#endif
-DEFINE_BOOT_PAGE_TABLE(boot_second_id);
-DEFINE_BOOT_PAGE_TABLE(boot_third_id);
-DEFINE_BOOT_PAGE_TABLE(boot_second);
-DEFINE_BOOT_PAGE_TABLES(boot_third, XEN_NR_ENTRIES(2));
-
 /* Main runtime page tables */
 
 /*
@@ -80,7 +47,7 @@  static DEFINE_PAGE_TABLE(xen_first);
 DEFINE_PER_CPU(lpae_t *, xen_pgtable);
 #define THIS_CPU_PGTABLE this_cpu(xen_pgtable)
 /* Root of the trie for cpu0, other CPU's PTs are dynamically allocated */
-static DEFINE_PAGE_TABLE(cpu0_pgtable);
+DEFINE_PAGE_TABLE(cpu0_pgtable);
 #endif
 
 /* Common pagetable leaves */
@@ -277,13 +244,6 @@  static void xen_pt_enforce_wnx(void)
     flush_xen_tlb_local();
 }
 
-/* Clear a translation table and clean & invalidate the cache */
-static void clear_table(void *table)
-{
-    clear_page(table);
-    clean_and_invalidate_dcache_va_range(table, PAGE_SIZE);
-}
-
 /* Boot-time pagetable setup.
  * Changes here may need matching changes in head.S */
 void __init setup_pagetables(unsigned long boot_phys_offset)
@@ -362,67 +322,6 @@  void __init setup_pagetables(unsigned long boot_phys_offset)
 #endif
 }
 
-static void clear_boot_pagetables(void)
-{
-    /*
-     * Clear the copy of the boot pagetables. Each secondary CPU
-     * rebuilds these itself (see head.S).
-     */
-    clear_table(boot_pgtable);
-#ifdef CONFIG_ARM_64
-    clear_table(boot_first);
-    clear_table(boot_first_id);
-#endif
-    clear_table(boot_second);
-    clear_table(boot_third);
-}
-
-#ifdef CONFIG_ARM_64
-int init_secondary_pagetables(int cpu)
-{
-    clear_boot_pagetables();
-
-    /* Set init_ttbr for this CPU coming up. All CPus share a single setof
-     * pagetables, but rewrite it each time for consistency with 32 bit. */
-    init_ttbr = (uintptr_t) xen_pgtable + phys_offset;
-    clean_dcache(init_ttbr);
-    return 0;
-}
-#else
-int init_secondary_pagetables(int cpu)
-{
-    lpae_t *first;
-
-    first = alloc_xenheap_page(); /* root == first level on 32-bit 3-level trie */
-
-    if ( !first )
-    {
-        printk("CPU%u: Unable to allocate the first page-table\n", cpu);
-        return -ENOMEM;
-    }
-
-    /* Initialise root pagetable from root of boot tables */
-    memcpy(first, cpu0_pgtable, PAGE_SIZE);
-    per_cpu(xen_pgtable, cpu) = first;
-
-    if ( !init_domheap_mappings(cpu) )
-    {
-        printk("CPU%u: Unable to prepare the domheap page-tables\n", cpu);
-        per_cpu(xen_pgtable, cpu) = NULL;
-        free_xenheap_page(first);
-        return -ENOMEM;
-    }
-
-    clear_boot_pagetables();
-
-    /* Set init_ttbr for this CPU coming up */
-    init_ttbr = __pa(first);
-    clean_dcache(init_ttbr);
-
-    return 0;
-}
-#endif
-
 /* MMU setup for secondary CPUS (which already have paging enabled) */
 void mmu_init_secondary_cpu(void)
 {
diff --git a/xen/arch/arm/mmu/Makefile b/xen/arch/arm/mmu/Makefile
index bdfc2e077d..0e82015ee1 100644
--- a/xen/arch/arm/mmu/Makefile
+++ b/xen/arch/arm/mmu/Makefile
@@ -1 +1,2 @@ 
 obj-y += pt.o
+obj-y += smpboot.o
diff --git a/xen/arch/arm/mmu/smpboot.c b/xen/arch/arm/mmu/smpboot.c
new file mode 100644
index 0000000000..a673989d09
--- /dev/null
+++ b/xen/arch/arm/mmu/smpboot.c
@@ -0,0 +1,121 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * xen/arch/arm/mmu/smpboot.c
+ *
+ * MMU system secondary CPUs MM bringup code.
+ */
+
+#include <xen/domain_page.h>
+
+/*
+ * Static start-of-day pagetables that we use before the allocators
+ * are up. These are used by all CPUs during bringup before switching
+ * to the CPUs own pagetables.
+ *
+ * These pagetables have a very simple structure. They include:
+ *  - XEN_VIRT_SIZE worth of L3 mappings of xen at XEN_VIRT_START, boot_first
+ *    and boot_second are used to populate the tables down to boot_third
+ *    which contains the actual mapping.
+ *  - a 1:1 mapping of xen at its current physical address. This uses a
+ *    section mapping at whichever of boot_{pgtable,first,second}
+ *    covers that physical address.
+ *
+ * For the boot CPU these mappings point to the address where Xen was
+ * loaded by the bootloader. For secondary CPUs they point to the
+ * relocated copy of Xen for the benefit of secondary CPUs.
+ *
+ * In addition to the above for the boot CPU the device-tree is
+ * initially mapped in the boot misc slot. This mapping is not present
+ * for secondary CPUs.
+ *
+ * Finally, if EARLY_PRINTK is enabled then xen_fixmap will be mapped
+ * by the CPU once it has moved off the 1:1 mapping.
+ */
+DEFINE_BOOT_PAGE_TABLE(boot_pgtable);
+#ifdef CONFIG_ARM_64
+DEFINE_BOOT_PAGE_TABLE(boot_first);
+DEFINE_BOOT_PAGE_TABLE(boot_first_id);
+#endif
+DEFINE_BOOT_PAGE_TABLE(boot_second_id);
+DEFINE_BOOT_PAGE_TABLE(boot_third_id);
+DEFINE_BOOT_PAGE_TABLE(boot_second);
+DEFINE_BOOT_PAGE_TABLES(boot_third, XEN_NR_ENTRIES(2));
+
+/* Clear a translation table and clean & invalidate the cache */
+static void clear_table(void *table)
+{
+    clear_page(table);
+    clean_and_invalidate_dcache_va_range(table, PAGE_SIZE);
+}
+
+static void clear_boot_pagetables(void)
+{
+    /*
+     * Clear the copy of the boot pagetables. Each secondary CPU
+     * rebuilds these itself (see head.S).
+     */
+    clear_table(boot_pgtable);
+#ifdef CONFIG_ARM_64
+    clear_table(boot_first);
+    clear_table(boot_first_id);
+#endif
+    clear_table(boot_second);
+    clear_table(boot_third);
+}
+
+#ifdef CONFIG_ARM_64
+int init_secondary_pagetables(int cpu)
+{
+    clear_boot_pagetables();
+
+    /*
+     * Set init_ttbr for this CPU coming up. All CPus share a single setof
+     * pagetables, but rewrite it each time for consistency with 32 bit.
+     */
+    init_ttbr = (uintptr_t) xen_pgtable + phys_offset;
+    clean_dcache(init_ttbr);
+    return 0;
+}
+#else
+int init_secondary_pagetables(int cpu)
+{
+    lpae_t *first;
+
+    first = alloc_xenheap_page(); /* root == first level on 32-bit 3-level trie */
+
+    if ( !first )
+    {
+        printk("CPU%u: Unable to allocate the first page-table\n", cpu);
+        return -ENOMEM;
+    }
+
+    /* Initialise root pagetable from root of boot tables */
+    memcpy(first, cpu0_pgtable, PAGE_SIZE);
+    per_cpu(xen_pgtable, cpu) = first;
+
+    if ( !init_domheap_mappings(cpu) )
+    {
+        printk("CPU%u: Unable to prepare the domheap page-tables\n", cpu);
+        per_cpu(xen_pgtable, cpu) = NULL;
+        free_xenheap_page(first);
+        return -ENOMEM;
+    }
+
+    clear_boot_pagetables();
+
+    /* Set init_ttbr for this CPU coming up */
+    init_ttbr = __pa(first);
+    clean_dcache(init_ttbr);
+
+    return 0;
+}
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */