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

Re: [Xen-devel] [PATCH 6/7] xen/arm: Support dtb /memreserve/ regions



On 09/12/2013 01:42 PM, Ian Campbell wrote:
> This requires a mapping of the DTB during setup_mm. Previosly this was in the
> BOOT_MISC slot, which is clobbered by setup_pagetables. Split it out into its
> own slot which can be preserved.
> 
> Also handle this regions are part of consider_modules() and next_modules() to
> ensure we do not locate any part of Xen or the heaps over them.
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
>  xen/arch/arm/arm32/head.S    |    2 +-
>  xen/arch/arm/arm32/traps.c   |    3 +++
>  xen/arch/arm/arm64/head.S    |    2 +-
>  xen/arch/arm/mm.c            |   10 +++++++-
>  xen/arch/arm/setup.c         |   58 
> ++++++++++++++++++++++++++++++++++++++++--
>  xen/arch/arm/traps.c         |    3 ++-
>  xen/common/device_tree.c     |   13 +++++++++-
>  xen/include/asm-arm/config.h |    7 ++---
>  xen/include/asm-arm/mm.h     |    2 ++
>  9 files changed, 90 insertions(+), 10 deletions(-)
> 
> diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S
> index 79e95b6..5072e2a 100644
> --- a/xen/arch/arm/arm32/head.S
> +++ b/xen/arch/arm/arm32/head.S
> @@ -301,7 +301,7 @@ cpu_init_done:
>          orr   r2, r2, #PT_UPPER(MEM)
>          orr   r2, r2, #PT_LOWER(MEM) /* r2:r3 := 2MB RAM incl. DTB */
>          add   r4, r4, #8
> -        strd  r2, r3, [r1, r4]       /* Map it in the early boot slot */
> +        strd  r2, r3, [r1, r4]       /* Map it in the early fdt slot */
>  
>  pt_ready:
>          PRINT("- Turning on paging -\r\n")
> diff --git a/xen/arch/arm/arm32/traps.c b/xen/arch/arm/arm32/traps.c
> index ff0b945..e8dd9f5 100644
> --- a/xen/arch/arm/arm32/traps.c
> +++ b/xen/arch/arm/arm32/traps.c
> @@ -22,6 +22,7 @@
>  #include <public/xen.h>
>  
>  #include <asm/processor.h>
> +#include <asm/early_printk.h>
>  
>  asmlinkage void do_trap_undefined_instruction(struct cpu_user_regs *regs)
>  {
> @@ -40,6 +41,8 @@ asmlinkage void do_trap_prefetch_abort(struct cpu_user_regs 
> *regs)
>  
>  asmlinkage void do_trap_data_abort(struct cpu_user_regs *regs)
>  {
> +    early_printk("Data Abort at %"PRIvaddr" DFAR %"PRIx32"\n",
> +                 regs->pc, READ_CP32(DFAR));

early_printk belongs to __init and will be discarded by
free_init_memory. Any data abort after this call will result to a
"double" hang.

>      do_unexpected_trap("Data Abort", regs);
>  }
>  
> diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
> index 21b7e4d..33ff489 100644
> --- a/xen/arch/arm/arm64/head.S
> +++ b/xen/arch/arm/arm64/head.S
> @@ -255,7 +255,7 @@ skip_bss:
>          mov   x3, #PT_MEM            /* x2 := 2MB RAM incl. DTB */
>          orr   x2, x2, x3
>          add   x4, x4, #8
> -        str   x2, [x1, x4]           /* Map it in the early boot slot */
> +        str   x2, [x1, x4]           /* Map it in the early fdt slot */
>  
>  pt_ready:
>          PRINT("- Turning on paging -\r\n")
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index 69c157a..86e3207 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -361,6 +361,13 @@ static inline lpae_t pte_of_xenaddr(vaddr_t va)
>      return mfn_to_xen_entry(mfn);
>  }
>  
> +void __init remove_early_mappings(void)
> +{
> +    lpae_t pte = {0};
> +    write_pte(xen_second + second_table_offset(BOOT_FDT_VIRT_START), pte);
> +    flush_xen_data_tlb_range_va(BOOT_FDT_VIRT_START, SECOND_SIZE);
> +}
> +
>  /* Boot-time pagetable setup.
>   * Changes here may need matching changes in head.S */
>  void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t 
> xen_paddr)
> @@ -401,7 +408,8 @@ void __init setup_pagetables(unsigned long 
> boot_phys_offset, paddr_t xen_paddr)
>          p[second_linear_offset(va)].bits = 0;
>      }
>      for ( i = 0; i < 4 * LPAE_ENTRIES; i++)
> -        if ( p[i].pt.valid )
> +        /* The FDT is not relocated */
> +        if ( p[i].pt.valid && i != second_linear_offset(BOOT_FDT_VIRT_START) 
> )
>              p[i].pt.base += (phys_offset - boot_phys_offset) >> PAGE_SHIFT;
>  
>      /* Change pagetables to the copy in the relocated Xen */
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 95f22a1..d88f121 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -35,6 +35,7 @@
>  #include <xen/cpu.h>
>  #include <xen/pfn.h>
>  #include <xen/vmap.h>
> +#include <xen/libfdt/libfdt.h>
>  #include <asm/page.h>
>  #include <asm/current.h>
>  #include <asm/setup.h>
> @@ -161,6 +162,8 @@ void __init discard_initial_modules(void)
>      }
>  
>      mi->nr_mods = 0;
> +
> +    remove_early_mappings();
>  }
>  
>  /*
> @@ -177,6 +180,7 @@ static paddr_t __init consider_modules(paddr_t s, paddr_t 
> e,
>  {
>      const struct dt_module_info *mi = &early_info.modules;
>      int i;
> +    int nr_rsvd;
>  
>      s = (s+align-1) & ~(align-1);
>      e = e & ~(align-1);
> @@ -184,6 +188,7 @@ static paddr_t __init consider_modules(paddr_t s, paddr_t 
> e,
>      if ( s > e ||  e - s < size )
>          return 0;
>  
> +    /* First check the boot modules */
>      for ( i = first_mod; i <= mi->nr_mods; i++ )
>      {
>          paddr_t mod_s = mi->module[i].start;
> @@ -199,6 +204,32 @@ static paddr_t __init consider_modules(paddr_t s, 
> paddr_t e,
>          }
>      }
>  
> +    /* Now check any fdt reserved areas. */
> +
> +    nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
> +
> +    for ( ; i < mi->nr_mods + nr_rsvd; i++ )
> +    {
> +        paddr_t mod_s, mod_e;
> +
> +        if ( fdt_get_mem_rsv(device_tree_flattened,
> +                             i - mi->nr_mods,
> +                             &mod_s, &mod_e ) < 0 )
> +            /* If we can't read it, pretend it doesn't exist... */
> +            continue;
> +
> +        /* fdt_get_mem_rsv returns length */
> +        mod_e += mod_s;
> +
> +        if ( s < mod_e && mod_s < e )
> +        {
> +            mod_e = consider_modules(mod_e, e, size, align, i+1);
> +            if ( mod_e )
> +                return mod_e;
> +
> +            return consider_modules(s, mod_s, size, align, i+1);
> +        }
> +    }
>      return e;
>  }
>  
> @@ -212,7 +243,29 @@ static paddr_t __init next_module(paddr_t s, paddr_t *n)
>  {
>      struct dt_module_info *mi = &early_info.modules;
>      paddr_t lowest = ~(paddr_t)0;
> -    int i;
> +    int i, nr_rsvd;
> +
> +    nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
> +
> +    for ( i=0 ; i < nr_rsvd; i++ )
> +    {
> +        paddr_t mod_s, mod_e;
> +
> +        if ( fdt_get_mem_rsv(device_tree_flattened, i,
> +                             &mod_s, &mod_e ) < 0 )
> +            /* If we can't read it, pretend it doesn't exist... */
> +            continue;
> +
> +        /* fdt_get_mem_rsv returns length */
> +        mod_e += mod_s;
> +
> +        if ( mod_s < s )
> +            continue;
> +        if ( mod_s > lowest )
> +            continue;
> +        lowest = mod_s;
> +        *n = mod_e;
> +    }

You use this same loop for ... fdt_get ... on different place. Can  you
add a function fdt_for_each_memreserve?
>  
>      for ( i = 0; i <= mi->nr_mods; i++ )
>      {
> @@ -226,6 +279,7 @@ static paddr_t __init next_module(paddr_t s, paddr_t *n)
>          lowest = mod_s;
>          *n = mod_e;
>      }
> +

Spurious line?

>      return lowest;
>  }
>  
> @@ -517,7 +571,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>      smp_clear_cpu_maps();
>  
>      /* This is mapped by head.S */
> -    device_tree_flattened = (void *)BOOT_MISC_VIRT_START
> +    device_tree_flattened = (void *)BOOT_FDT_VIRT_START
>          + (fdt_paddr & ((1 << SECOND_SHIFT) - 1));
>      fdt_size = device_tree_early_init(device_tree_flattened, fdt_paddr);
>  
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 0e9a141..a78c1e0 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -35,6 +35,7 @@
>  #include <asm/regs.h>
>  #include <asm/cpregs.h>
>  #include <asm/psci.h>
> +#include <asm/early_printk.h>
>  
>  #include "decode.h"
>  #include "io.h"
> @@ -810,7 +811,7 @@ void vcpu_show_execution_state(struct vcpu *v)
>  
>  void do_unexpected_trap(const char *msg, struct cpu_user_regs *regs)
>  {
> -    printk("CPU%d: Unexpected Trap: %s\n", smp_processor_id(), msg);
> +    early_printk("CPU%d: Unexpected Trap: %s\n", smp_processor_id(), msg);

Same issue as do data_abort_trap

>      show_execution_state(regs);
>      while(1);
>  }
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 9e0c224..132a2bd 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -489,7 +489,7 @@ static void __init early_print_info(void)
>  {
>      struct dt_mem_info *mi = &early_info.mem;
>      struct dt_module_info *mods = &early_info.modules;
> -    int i;
> +    int i, nr_rsvd;
>  
>      for ( i = 0; i < mi->nr_banks; i++ )
>          early_printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n",
> @@ -502,6 +502,17 @@ static void __init early_print_info(void)
>                       mods->module[i].start,
>                       mods->module[i].start + mods->module[i].size,
>                       mods->module[i].cmdline);
> +    nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
> +    for ( i = 0; i < nr_rsvd; i++ )
> +    {
> +        paddr_t s, e;
> +        if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 )
> +            continue;
> +        /* fdt_get_mem_rsv returns length */
> +        e += s;
> +        early_printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n",
> +                     i, s, e);
> +    }
>  }
>  
>  /**
> diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
> index 624c73e..efeb952 100644
> --- a/xen/include/asm-arm/config.h
> +++ b/xen/include/asm-arm/config.h
> @@ -80,10 +80,10 @@
>   *   0  -   2M   Unmapped
>   *   2M -   4M   Xen text, data, bss
>   *   4M -   6M   Fixmap: special-purpose 4K mapping slots
> - *   6M -   8M   Early boot misc (see below)
> + *   6M -   8M   Early boot mapping of FDT
> + *   8M -  10M   Early boot misc (see below)
>   *
>   * The early boot misc area is used:
> - *   - in head.S for the DTB for device_tree_early_init().
>   *   - in setup_pagetables() when relocating Xen.
>   *
>   * ARM32 layout:
> @@ -116,7 +116,8 @@
>  
>  #define XEN_VIRT_START         _AT(vaddr_t,0x00200000)
>  #define FIXMAP_ADDR(n)        (_AT(vaddr_t,0x00400000) + (n) * PAGE_SIZE)
> -#define BOOT_MISC_VIRT_START   _AT(vaddr_t,0x00600000)
> +#define BOOT_FDT_VIRT_START    _AT(vaddr_t,0x00600000)
> +#define BOOT_MISC_VIRT_START   _AT(vaddr_t,0x00800000)
>  
>  #define HYPERVISOR_VIRT_START  XEN_VIRT_START
>  
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index 97c2ee0..467687a 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -155,6 +155,8 @@ extern unsigned long total_pages;
>  
>  /* Boot-time pagetable setup */
>  extern void setup_pagetables(unsigned long boot_phys_offset, paddr_t 
> xen_paddr);
> +/* Remove early mappings */
> +extern void remove_early_mappings(void);
>  /* Allocate and initialise pagetables for a secondary CPU */
>  extern int __cpuinit init_secondary_pagetables(int cpu);
>  /* Switch secondary CPUS to its own pagetables and finalise MMU setup */
> 


-- 
Julien Grall

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