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

Re: [Xen-devel] [PATCH RFC 2/2] xen: arm: Enable physical address space compression (PDX) on arm64



On Thu, Jul 31, 2014 at 4:01 AM, Ian Campbell <ian.campbell@xxxxxxxxxx> wrote:
This allows us to support sparse physical address maps which we previously
could not because the frametable would end up taking up an enourmous fraction
of RAM.

On a fast model which has RAM at 0x80000000-0x100000000 and
0x880000000-0x900000000 this reduces the size of the frametable from
478M to 84M.

This is very much a WIP. Things left to do:
 - Make it work for arm32 (completely broken)
 - Should xenheap_mfn_start/frametable_base_pdx be an (optional?) part of the
  common infra?
 - Sort out the semtantics of mfn/pdx vs frame table base, I suspect these are
  a bit confused right now...
 - Probably lots of bugs...

Posting because I'm going to be away but it will hopefully be useful for the
UEFI and grub+multiboot work being done by Linaro.

This works for me on the foundation model - it now looks like XEN is using
all of the memory, and there are no obvious problems.
Â

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
Âxen/arch/arm/Rules.mk    Â|  Â1 +
Âxen/arch/arm/mm.c      Â|  18 +++++++------
Âxen/arch/arm/setup.c     |  58 ++++++++++++++++++++++++++++++++----------
Âxen/include/asm-arm/config.h | Â Â4 ++-
Âxen/include/asm-arm/mm.h   |  31 +++++++++++-----------
Âxen/include/asm-arm/numa.h  |  Â2 +-
Â6 files changed, 76 insertions(+), 38 deletions(-)

diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk
index 8658176..26fafa2 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -10,6 +10,7 @@ HAS_DEVICE_TREE := y
ÂHAS_VIDEO := y
ÂHAS_ARM_HDLCD := y
ÂHAS_PASSTHROUGH := y
+HAS_PDX := y

ÂCFLAGS += -I$(BASEDIR)/include

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index fa6a729..bc399c0 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -140,7 +140,7 @@ unsigned long xenheap_mfn_start __read_mostly = ~0UL;
Âunsigned long xenheap_mfn_end __read_mostly;
Âunsigned long xenheap_virt_end __read_mostly;

-unsigned long frametable_base_mfn __read_mostly;
+unsigned long frametable_base_pdx __read_mostly;
Âunsigned long frametable_virt_end __read_mostly;

Âunsigned long max_page;
@@ -683,7 +683,7 @@ void __init setup_xenheap_mappings(unsigned long base_mfn,
  Â/* Align to previous 1GB boundary */
  Âbase_mfn &= ~((FIRST_SIZE>>PAGE_SHIFT)-1);

- Â Âoffset = base_mfn - xenheap_mfn_start;
+ Â Âoffset = pfn_to_pdx(base_mfn - xenheap_mfn_start);
  Âvaddr = DIRECTMAP_VIRT_START + offset*PAGE_SIZE;

  Âwhile ( base_mfn < end_mfn )
@@ -734,7 +734,8 @@ void __init setup_xenheap_mappings(unsigned long base_mfn,
Âvoid __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
Â{
  Âunsigned long nr_pages = (pe - ps) >> PAGE_SHIFT;
- Â Âunsigned long frametable_size = nr_pages * sizeof(struct page_info);
+ Â Âunsigned long nr_pdxs = pfn_to_pdx(nr_pages);
+ Â Âunsigned long frametable_size = nr_pdxs * sizeof(struct page_info);
  Âunsigned long base_mfn;
Â#ifdef CONFIG_ARM_64
  Âlpae_t *second, pte;
@@ -742,7 +743,7 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
  Âint i;
Â#endif

- Â Âframetable_base_mfn = ps >> PAGE_SHIFT;
+ Â Âframetable_base_pdx = pfn_to_pdx(ps >> PAGE_SHIFT);

  Â/* Round up to 32M boundary */
  Âframetable_size = (frametable_size + 0x1ffffff) & ~0x1ffffff;
@@ -763,11 +764,12 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
  Âcreate_32mb_mappings(xen_second, FRAMETABLE_VIRT_START, base_mfn, frametable_size >> PAGE_SHIFT);
Â#endif

- Â Âmemset(&frame_table[0], 0, nr_pages * sizeof(struct page_info));
- Â Âmemset(&frame_table[nr_pages], -1,
- Â Â Â Â Â frametable_size - (nr_pages * sizeof(struct page_info)));
+ Â Âmemset(&frame_table[0], 0, nr_pdxs * sizeof(struct page_info));
+ Â Âmemset(&frame_table[nr_pdxs], -1,
+ Â Â Â Â Â frametable_size - (nr_pdxs * sizeof(struct page_info)));
+
+ Â Âframetable_virt_end = FRAMETABLE_VIRT_START + (nr_pdxs * sizeof(struct page_info));

- Â Âframetable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info));
Â}

Âvoid *__init arch_vmap_virt_end(void)
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 446b4dc..dbd92bb 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -423,6 +423,46 @@ static paddr_t __init get_xen_paddr(void)
  Âreturn paddr;
Â}

+/* Sets all bits from the most-significant 1-bit down to the LSB */
+static u64 __init fill_mask(u64 mask)
+{
+ Â Âwhile (mask & (mask + 1))
+ Â Â Â Âmask |= mask + 1;
+ Â Âreturn mask;
+}
+
+static void init_pdx(void)
+{
+ Â Âu64 mask = fill_mask(bootinfo.mem.bank[0].start - 1);
+ Â Âint bank;
+
+ Â Âfor ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ Â Â{
+ Â Â Â Âpaddr_t bank_start = bootinfo.mem.bank[bank].start;
+ Â Â Â Âpaddr_t bank_size = bootinfo.mem.bank[bank].size;
+ Â Â Â Âpaddr_t bank_end = bank_start + bank_size;
+
+ Â Â Â Âset_pdx_range(paddr_to_pfn(bank_start),
+ Â Â Â Â Â Â Â Â Â Â Âpaddr_to_pfn(bank_end));
+
+
+ Â Â Â Âmask |= bank_start | fill_mask(bank_start ^ (bank_end - 1));
+ Â Â}
+
+ Â Âfor ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
+ Â Â{
+ Â Â Â Âpaddr_t bank_start = bootinfo.mem.bank[bank].start;
+ Â Â Â Âpaddr_t bank_size = bootinfo.mem.bank[bank].size;
+ Â Â Â Âpaddr_t bank_end = bank_start + bank_size;
+
+ Â Â Â Âif (~mask &
+ Â Â Â Â Â Âfill_mask(bank_start ^ (bank_end - 1)))
+ Â Â Â Â Â Âmask = 0;
+ Â Â}
+
+ Â Âpfn_pdx_hole_setup(mask >> PAGE_SHIFT);
+}
+
Â#ifdef CONFIG_ARM_32
Âstatic void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
Â{
@@ -439,6 +479,8 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
  Âif ( !bootinfo.mem.nr_banks )
    Âpanic("No memory bank");

+ Â Âinit_pdx();
+
  Â/*
   * We are going to accumulate two regions here.
   *
@@ -468,6 +510,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
    Âpaddr_t new_ram_start = min(ram_start,bank_start);
    Âpaddr_t new_ram_end = max(ram_end,bank_end);

+#error ARM32 not converted to PDX yet
    Â/*
     * If the new bank is contiguous with the initial contiguous
     * region then incorporate it into the contiguous region.
@@ -616,6 +659,8 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
  Âunsigned long dtb_pages;
  Âvoid *fdt;

+ Â Âinit_pdx();
+
  Âtotal_pages = 0;
  Âfor ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ )
  Â{
@@ -628,19 +673,6 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
    Âpaddr_t new_ram_start = min(ram_start,bank_start);
    Âpaddr_t new_ram_end = max(ram_end,bank_end);

- Â Â Â Â/*
- Â Â Â Â * We allow non-contigious regions so long as at least half of
- Â Â Â Â * the total RAM region actually contains RAM. We actually
- Â Â Â Â * fudge this slightly and require that adding the current
- Â Â Â Â * bank does not cause us to violate this restriction.
- Â Â Â Â *
- Â Â Â Â * This restriction ensures that the frametable (which is not
- Â Â Â Â * currently sparse) does not consume all available RAM.
- Â Â Â Â */
- Â Â Â Âif ( bank > 0 && 2 * new_ram_size < new_ram_end - new_ram_start )
- Â Â Â Â Â Â/* Would create memory map which is too sparse, so stop here. */
- Â Â Â Â Â Âbreak;
-
    Âram_start = new_ram_start;
    Âram_end = new_ram_end;
    Âram_size = new_ram_size;
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 1c3abcf..e525c7f 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -149,7 +149,9 @@
Â#define VMAP_VIRT_END Â Â(VMAP_VIRT_START + GB(1) - 1)

Â#define FRAMETABLE_VIRT_START ÂGB(32)
-#define FRAMETABLE_VIRT_END Â Â(FRAMETABLE_VIRT_START + GB(32) - 1)
+#define FRAMETABLE_SIZE Â Â Â ÂGB(32)
+#define FRAMETABLE_NR Â Â Â Â Â(FRAMETABLE_SIZE / sizeof(*frame_table))
+#define FRAMETABLE_VIRT_END Â Â(FRAMETABLE_VIRT_START + FRAMETABLE_SIZE - 1)

Â#define DIRECTMAP_VIRT_START Â SLOT0(256)
Â#define DIRECTMAP_SIZE Â Â Â Â (SLOT0_ENTRY_SIZE * (265-256))
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 9fa80a4..77901f7 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -6,6 +6,7 @@
Â#include <asm/page.h>
Â#include <public/xen.h>
Â#include <xen/domain_page.h>
+#include <xen/pdx.h>

Â/* Align Xen to a 2 MiB boundary. */
Â#define XEN_PADDR_ALIGN (1 << 21)
@@ -140,12 +141,14 @@ extern void share_xen_page_with_privileged_guests(
  Âstruct page_info *page, int readonly);

Â#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
-/* MFN of the first page in the frame table. */
-extern unsigned long frametable_base_mfn;
+/* PDX of the first page in the frame table. */
+extern unsigned long frametable_base_pdx;

Âextern unsigned long max_page;
Âextern unsigned long total_pages;

+#define PDX_GROUP_SHIFT SECOND_SHIFT
+
Â/* Boot-time pagetable setup */
Âextern void setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr);
Â/* Remove early mappings */
@@ -184,20 +187,15 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
  Âreturn ioremap_attr(start, len, PAGE_HYPERVISOR_WC);
Â}

+/* XXX -- account for base */
Â#define mfn_valid(mfn) Â Â Â Â({ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
  Âunsigned long __m_f_n = (mfn);                      Â\
- Â Âlikely(__m_f_n >= frametable_base_mfn && __m_f_n < max_page); Â Â Â Â Â Â \
+ Â Âlikely(pfn_to_pdx(__m_f_n) >= frametable_base_pdx && __mfn_valid(__m_f_n)); \
Â})

-#define max_pdx         max_page
-#define pfn_to_pdx(pfn) Â Â Â Â (pfn)
-#define pdx_to_pfn(pdx) Â Â Â Â (pdx)
-#define virt_to_pdx(va) Â Â Â Â virt_to_mfn(va)
-#define pdx_to_virt(pdx) Â Â Â Âmfn_to_virt(pdx)
-
Â/* Convert between machine frame numbers and page-info structures. */
-#define mfn_to_page(mfn) Â(frame_table + (pfn_to_pdx(mfn) - frametable_base_mfn))
-#define page_to_mfn(pg) Â pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_mfn)
+#define mfn_to_page(mfn) Â(frame_table + (pfn_to_pdx(mfn) - frametable_base_pdx))
+#define page_to_mfn(pg) Â pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_pdx)
Â#define __page_to_mfn(pg) Âpage_to_mfn(pg)
Â#define __mfn_to_page(mfn) mfn_to_page(mfn)

@@ -221,6 +219,7 @@ static inline paddr_t __virt_to_maddr(vaddr_t va)
Â#define virt_to_maddr(va) Â __virt_to_maddr((vaddr_t)(va))

Â#ifdef CONFIG_ARM_32
+#error ARM32 not converted to PDX yet
Âstatic inline void *maddr_to_virt(paddr_t ma)
Â{
  ÂASSERT(is_xen_heap_mfn(ma >> PAGE_SHIFT));
@@ -230,9 +229,11 @@ static inline void *maddr_to_virt(paddr_t ma)
Â#else
Âstatic inline void *maddr_to_virt(paddr_t ma)
Â{
- Â ÂASSERT((ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT));
- Â Âma -= pfn_to_paddr(xenheap_mfn_start);
- Â Âreturn (void *)(unsigned long) ma + DIRECTMAP_VIRT_START;
+ Â ÂASSERT(pfn_to_pdx(ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT));
+ Â Âreturn (void *)(DIRECTMAP_VIRT_START -
+ Â Â Â Â Â Â Â Â Â Âpfn_to_paddr(xenheap_mfn_start) +
+ Â Â Â Â Â Â Â Â Â Â((ma & ma_va_bottom_mask) |
+ Â Â Â Â Â Â Â Â Â Â ((ma & ma_top_mask) >> pfn_pdx_hole_shift)));
Â}
Â#endif

@@ -264,7 +265,7 @@ static inline struct page_info *virt_to_page(const void *v)
  Âreturn frame_table
    Â+ ((va - XENHEAP_VIRT_START) >> PAGE_SHIFT)
    Â+ xenheap_mfn_start
- Â Â Â Â- frametable_base_mfn;
+ Â Â Â Â- frametable_base_pdx;
Â}

Âstatic inline void *page_to_virt(const struct page_info *pg)
diff --git a/xen/include/asm-arm/numa.h b/xen/include/asm-arm/numa.h
index 2c019d7..06a9d5a 100644
--- a/xen/include/asm-arm/numa.h
+++ b/xen/include/asm-arm/numa.h
@@ -12,7 +12,7 @@ static inline __attribute__((pure)) int phys_to_nid(paddr_t addr)

Â/* XXX: implement NUMA support */
Â#define node_spanned_pages(nid) (total_pages)
-#define node_start_pfn(nid) (frametable_base_mfn)
+#define node_start_pfn(nid) (pdx_to_pfn(frametable_base_pdx))
Â#define __node_distance(a, b) (20)

Â#endif /* __ARCH_ARM_NUMA_H */
--
1.7.10.4


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