[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 06/10] xen/arm: Implement virtual-linear page table for guest p2m mapping in live migration
Allocate and free the xen's virtual memory for virtual-linear page table of guest p2m. Slotting the guest p2m into the hypervisor's own page tables, such that the guest p2m table entries are available at known virtual addresses. For more info, see: http://www.technovelty.org/linux/virtual-linear-page-table.html This function is used in dirty-page tracing: when domU write-fault is trapped by xen, xen can immediately locate the p2m entry of the write-fault. Signed-off-by: Jaeyong Yoo <jaeyong.yoo@xxxxxxxxxxx> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/setup.c | 3 + xen/arch/arm/vlpt.c | 162 +++++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/config.h | 3 + xen/include/asm-arm/vlpt.h | 10 +++ 5 files changed, 179 insertions(+) create mode 100644 xen/arch/arm/vlpt.c create mode 100644 xen/include/asm-arm/vlpt.h diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index fa15412..86165e7 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -31,6 +31,7 @@ obj-y += vpl011.o obj-y += hvm.o obj-y += device.o obj-y += save.o +obj-y += vlpt.o #obj-bin-y += ....o diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 1ec5e38..27f0cca 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 <asm/vlpt.h> #include <asm/page.h> #include <asm/current.h> #include <asm/setup.h> @@ -447,6 +448,8 @@ void __init start_xen(unsigned long boot_phys_offset, dt_unflatten_host_device_tree(); dt_irq_xlate = gic_irq_xlate; + vlpt_init(); + dt_uart_init(); console_init_preirq(); diff --git a/xen/arch/arm/vlpt.c b/xen/arch/arm/vlpt.c new file mode 100644 index 0000000..49b1887 --- /dev/null +++ b/xen/arch/arm/vlpt.c @@ -0,0 +1,162 @@ +#ifdef VIRT_LIN_P2M_START +#include <xen/bitmap.h> +#include <xen/cache.h> +#include <xen/init.h> +#include <xen/mm.h> +#include <xen/pfn.h> +#include <xen/spinlock.h> +#include <xen/types.h> +#include <asm/vlpt.h> +#include <asm/page.h> +#include <asm/early_printk.h> + +static DEFINE_SPINLOCK(vlpt_lock); +static void *__read_mostly vlpt_base; +#define vlpt_bitmap ((unsigned long *)vlpt_base) +/* highest allocated bit in the bitmap */ +static unsigned int __read_mostly vlpt_top; +/* total number of bits in the bitmap */ +static unsigned int __read_mostly vlpt_end; +/* lowest known clear bit in the bitmap */ +static unsigned int vlpt_low; + +void __init vlpt_init(void) +{ + unsigned int i, nr; + unsigned long va; + + vlpt_base = (void *)VIRT_LIN_P2M_START; + vlpt_end = PFN_DOWN((void *)VIRT_LIN_P2M_END - vlpt_base); + vlpt_low = PFN_UP((vlpt_end + 7) / 8); + nr = PFN_UP((vlpt_low + 7) / 8); + vlpt_top = nr * PAGE_SIZE * 8; + + for ( i = 0, va = (unsigned long)vlpt_bitmap; i < nr; ++i, va += PAGE_SIZE ) + { + struct page_info *pg = alloc_domheap_page(NULL, 0); + + map_pages_to_xen(va, page_to_mfn(pg), 1, PAGE_HYPERVISOR); + clear_page((void *)va); + } + bitmap_fill(vlpt_bitmap, vlpt_low); + /* Populate page tables for the bitmap if necessary. */ + map_pages_to_xen(va, 0, vlpt_low - nr, MAP_SMALL_PAGES); +} + +void *vlpt_alloc(unsigned int nr, unsigned int align) +{ + unsigned int start, bit; + + if ( !align ) + align = 1; + else if ( align & (align - 1) ) + align &= -align; + + spin_lock(&vlpt_lock); + for ( ; ; ) + { + struct page_info *pg; + + ASSERT(!test_bit(vlpt_low, vlpt_bitmap)); + for ( start = vlpt_low; ; ) + { + bit = find_next_bit(vlpt_bitmap, vlpt_top, start + 1); + if ( bit > vlpt_top ) + bit = vlpt_top; + /* + * Note that this skips the first bit, making the + * corresponding page a guard one. + */ + start = (start + align) & ~(align - 1); + if ( start + nr <= bit ) + break; + start = bit < vlpt_top ? + find_next_zero_bit(vlpt_bitmap, vlpt_top, bit + 1) : bit; + if ( start >= vlpt_top ) + break; + } + + if ( start < vlpt_top ) + break; + + spin_unlock(&vlpt_lock); + + if ( vlpt_top >= vlpt_end ) + return NULL; + + pg = alloc_domheap_page(NULL, 0); + if ( !pg ) + return NULL; + + spin_lock(&vlpt_lock); + + if ( start >= vlpt_top ) + { + unsigned long va = (unsigned long)vlpt_bitmap + vlpt_top / 8; + + if ( !map_pages_to_xen(va, page_to_mfn(pg), 1, PAGE_HYPERVISOR) ) + { + clear_page((void *)va); + vlpt_top += PAGE_SIZE * 8; + if ( vlpt_top > vlpt_end ) + vlpt_top = vlpt_end; + continue; + } + } + + free_domheap_page(pg); + + if ( start >= vlpt_top ) + { + spin_unlock(&vlpt_lock); + return NULL; + } + } + + for ( bit = start; bit < start + nr; ++bit ) + __set_bit(bit, vlpt_bitmap); + if ( start <= vlpt_low + 2 ) + vlpt_low = bit; + spin_unlock(&vlpt_lock); + + return vlpt_base + start * PAGE_SIZE; +} + +static unsigned int vlpt_index(const void *va) +{ + unsigned long addr = (unsigned long)va & ~(PAGE_SIZE - 1); + unsigned int idx; + + if ( addr < VIRT_LIN_P2M_START + (vlpt_end / 8) || + addr >= VIRT_LIN_P2M_START + vlpt_top * PAGE_SIZE ) + return 0; + + idx = PFN_DOWN(va - vlpt_base); + return !test_bit(idx - 1, vlpt_bitmap) && + test_bit(idx, vlpt_bitmap) ? idx : 0; +} + +void vlpt_free(const void *va) +{ + unsigned int bit = vlpt_index(va); + + if ( !bit ) + { + WARN_ON(va != NULL); + return; + } + + spin_lock(&vlpt_lock); + if ( bit < vlpt_low ) + { + vlpt_low = bit - 1; + while ( !test_bit(vlpt_low - 1, vlpt_bitmap) ) + --vlpt_low; + } + while ( __test_and_clear_bit(bit, vlpt_bitmap) ) + if ( ++bit == vlpt_top ) + break; + spin_unlock(&vlpt_lock); +} + +#endif diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h index e3cfaf1..f9a7063 100644 --- a/xen/include/asm-arm/config.h +++ b/xen/include/asm-arm/config.h @@ -80,6 +80,7 @@ * 6M - 8M Early boot misc (see below) * * 32M - 128M Frametable: 24 bytes per page for 16GB of RAM + * 128M - 256M Virtual-linear mapping to P2M table * 256M - 1G VMAP: ioremap and early_ioremap use this virtual address * space * @@ -95,12 +96,14 @@ #define FIXMAP_ADDR(n) (mk_unsigned_long(0x00400000) + (n) * PAGE_SIZE) #define BOOT_MISC_VIRT_START mk_unsigned_long(0x00600000) #define FRAMETABLE_VIRT_START mk_unsigned_long(0x02000000) +#define VIRT_LIN_P2M_START mk_unsigned_long(0x08000000) #define VMAP_VIRT_START mk_unsigned_long(0x10000000) #define XENHEAP_VIRT_START mk_unsigned_long(0x40000000) #define DOMHEAP_VIRT_START mk_unsigned_long(0x80000000) #define DOMHEAP_VIRT_END mk_unsigned_long(0xffffffff) #define VMAP_VIRT_END XENHEAP_VIRT_START +#define VIRT_LIN_P2M_END VMAP_VIRT_START #define HYPERVISOR_VIRT_START XEN_VIRT_START #define DOMHEAP_ENTRIES 1024 /* 1024 2MB mapping slots */ diff --git a/xen/include/asm-arm/vlpt.h b/xen/include/asm-arm/vlpt.h new file mode 100644 index 0000000..da55293 --- /dev/null +++ b/xen/include/asm-arm/vlpt.h @@ -0,0 +1,10 @@ +#if !defined(__XEN_VLPT_H__) && defined(VIRT_LIN_P2M_START) +#define __XEN_VLPT_H__ + +#include <xen/types.h> + +void *vlpt_alloc(unsigned int nr, unsigned int align); +void vlpt_free(const void *); +void vlpt_init(void); + +#endif /* __XEN_VLPT_H__ */ -- 1.8.1.2 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |