Re: [PATCH v2 08/10] mm, cma: clean-up cma allocation error path
Joonsoo Kim iamjoonsoo@lge.com writes: We can remove one call sites for clear_cma_bitmap() if we first call it before checking error number. Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com Reviewed-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com diff --git a/mm/cma.c b/mm/cma.c index 1e1b017..01a0713 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -282,11 +282,12 @@ struct page *cma_alloc(struct cma *cma, int count, unsigned int align) if (ret == 0) { page = pfn_to_page(pfn); break; - } else if (ret != -EBUSY) { - clear_cma_bitmap(cma, pfn, count); - break; } + clear_cma_bitmap(cma, pfn, count); + if (ret != -EBUSY) + break; + pr_debug(%s(): memory range at %p is busy, retrying\n, __func__, pfn_to_page(pfn)); /* try again with a bit different memory target */ -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 09/10] mm, cma: move output param to the end of param list
Joonsoo Kim iamjoonsoo@lge.com writes: Conventionally, we put output param to the end of param list. cma_declare_contiguous() doesn't look like that, so change it. Additionally, move down cma_areas reference code to the position where it is really needed. Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com Reviewed-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 28ec226..97613ea 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -184,7 +184,7 @@ void __init kvm_cma_reserve(void) align_size = max(kvm_rma_pages PAGE_SHIFT, align_size); cma_declare_contiguous(selected_size, 0, 0, align_size, - KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, kvm_cma, false); + KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, kvm_cma); } } diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index f177f73..bfd4553 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -149,7 +149,7 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, { int ret; - ret = cma_declare_contiguous(size, base, limit, 0, 0, res_cma, fixed); + ret = cma_declare_contiguous(size, base, limit, 0, 0, fixed, res_cma); if (ret) return ret; diff --git a/include/linux/cma.h b/include/linux/cma.h index e38efe9..e53eead 100644 --- a/include/linux/cma.h +++ b/include/linux/cma.h @@ -6,7 +6,7 @@ struct cma; extern int __init cma_declare_contiguous(phys_addr_t size, phys_addr_t base, phys_addr_t limit, phys_addr_t alignment, int order_per_bit, - struct cma **res_cma, bool fixed); + bool fixed, struct cma **res_cma); extern struct page *cma_alloc(struct cma *cma, int count, unsigned int align); extern bool cma_release(struct cma *cma, struct page *pages, int count); #endif diff --git a/mm/cma.c b/mm/cma.c index 01a0713..22a5b23 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -142,8 +142,8 @@ core_initcall(cma_init_reserved_areas); * @limit: End address of the reserved memory (optional, 0 for any). * @alignment: Alignment for the contiguous memory area, should be power of 2 * @order_per_bit: Order of pages represented by one bit on bitmap. - * @res_cma: Pointer to store the created cma region. * @fixed: hint about where to place the reserved area + * @res_cma: Pointer to store the created cma region. * * This function reserves memory from early allocator. It should be * called by arch specific code once the early allocator (memblock or bootmem) @@ -156,9 +156,9 @@ core_initcall(cma_init_reserved_areas); int __init cma_declare_contiguous(phys_addr_t size, phys_addr_t base, phys_addr_t limit, phys_addr_t alignment, int order_per_bit, - struct cma **res_cma, bool fixed) + bool fixed, struct cma **res_cma) { - struct cma *cma = cma_areas[cma_area_count]; + struct cma *cma; int ret = 0; pr_debug(%s(size %lx, base %08lx, limit %08lx alignment %08lx)\n, @@ -214,6 +214,7 @@ int __init cma_declare_contiguous(phys_addr_t size, * Each reserved area must be initialised later, when more kernel * subsystems (like slab allocator) are available. */ + cma = cma_areas[cma_area_count]; cma-base_pfn = PFN_DOWN(base); cma-count = size PAGE_SHIFT; cma-order_per_bit = order_per_bit; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 00/10] CMA: generalize CMA reserved area management code
Joonsoo Kim iamjoonsoo@lge.com writes: Currently, there are two users on CMA functionality, one is the DMA subsystem and the other is the kvm on powerpc. They have their own code to manage CMA reserved area even if they looks really similar. From my guess, it is caused by some needs on bitmap management. Kvm side wants to maintain bitmap not for 1 page, but for more size. Eventually it use bitmap where one bit represents 64 pages. When I implement CMA related patches, I should change those two places to apply my change and it seem to be painful to me. I want to change this situation and reduce future code management overhead through this patch. This change could also help developer who want to use CMA in their new feature development, since they can use CMA easily without copying pasting this reserved area management code. v2: Although this patchset looks very different with v1, the end result, that is, mm/cma.c is same with v1's one. So I carry Ack to patch 6-7. Patch 1-5 prepare some features to cover ppc kvm's requirements. Patch 6-7 generalize CMA reserved area management code and change users to use it. Patch 8-10 clean-up minor things. I wanted to test the ppc changes and found that the patch series doesn't apply against v3.15 . Do you have a kernel tree which I can clone to test this series ? -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 07/10] PPC, KVM, CMA: use general CMA reserved area management framework
Joonsoo Kim iamjoonsoo@lge.com writes: Now, we have general CMA reserved area management framework, so use it for future maintainabilty. There is no functional change. Acked-by: Michal Nazarewicz min...@mina86.com Acked-by: Paolo Bonzini pbonz...@redhat.com Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com Need this. We may want to keep the VM_BUG_ON by moving KVM_CMA_CHUNK_ORDER around. diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 8056107..1932e0e 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -37,8 +37,6 @@ #include asm/ppc-opcode.h #include asm/cputable.h -#include book3s_hv_cma.h - /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ #define MAX_LPID_970 63 @@ -64,7 +62,6 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp) } kvm-arch.hpt_cma_alloc = 0; - VM_BUG_ON(order KVM_CMA_CHUNK_ORDER); page = kvm_alloc_hpt(1 (order - PAGE_SHIFT)); if (page) { hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); -aneesh -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 07/10] PPC, KVM, CMA: use general CMA reserved area management framework
Joonsoo Kim iamjoonsoo@lge.com writes: Now, we have general CMA reserved area management framework, so use it for future maintainabilty. There is no functional change. Acked-by: Michal Nazarewicz min...@mina86.com Acked-by: Paolo Bonzini pbonz...@redhat.com Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 7cde8a6..28ec226 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -16,12 +16,14 @@ #include linux/init.h #include linux/memblock.h #include linux/sizes.h +#include linux/cma.h #include asm/cputable.h #include asm/kvm_ppc.h #include asm/kvm_book3s.h -#include book3s_hv_cma.h +#define KVM_CMA_CHUNK_ORDER 18 + /* * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206) * should be power of 2. @@ -43,6 +45,8 @@ static unsigned long kvm_cma_resv_ratio = 5; unsigned long kvm_rma_pages = (1 27) PAGE_SHIFT; /* 128MB */ EXPORT_SYMBOL_GPL(kvm_rma_pages); +static struct cma *kvm_cma; + /* Work out RMLS (real mode limit selector) field value for a given RMA size. Assumes POWER7 or PPC970. */ static inline int lpcr_rmls(unsigned long rma_size) @@ -97,7 +101,7 @@ struct kvm_rma_info *kvm_alloc_rma() ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL); if (!ri) return NULL; - page = kvm_alloc_cma(kvm_rma_pages, kvm_rma_pages); + page = cma_alloc(kvm_cma, kvm_rma_pages, get_order(kvm_rma_pages)); if (!page) goto err_out; atomic_set(ri-use_count, 1); @@ -112,7 +116,7 @@ EXPORT_SYMBOL_GPL(kvm_alloc_rma); void kvm_release_rma(struct kvm_rma_info *ri) { if (atomic_dec_and_test(ri-use_count)) { - kvm_release_cma(pfn_to_page(ri-base_pfn), kvm_rma_pages); + cma_release(kvm_cma, pfn_to_page(ri-base_pfn), kvm_rma_pages); kfree(ri); } } @@ -134,13 +138,13 @@ struct page *kvm_alloc_hpt(unsigned long nr_pages) /* Old CPUs require HPT aligned on a multiple of its size */ if (!cpu_has_feature(CPU_FTR_ARCH_206)) align_pages = nr_pages; - return kvm_alloc_cma(nr_pages, align_pages); + return cma_alloc(kvm_cma, nr_pages, get_order(align_pages)); } EXPORT_SYMBOL_GPL(kvm_alloc_hpt); void kvm_release_hpt(struct page *page, unsigned long nr_pages) { - kvm_release_cma(page, nr_pages); + cma_release(kvm_cma, page, nr_pages); } EXPORT_SYMBOL_GPL(kvm_release_hpt); @@ -179,7 +183,8 @@ void __init kvm_cma_reserve(void) align_size = HPT_ALIGN_PAGES PAGE_SHIFT; align_size = max(kvm_rma_pages PAGE_SHIFT, align_size); - kvm_cma_declare_contiguous(selected_size, align_size); + cma_declare_contiguous(selected_size, 0, 0, align_size, + KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, kvm_cma, false); } } diff --git a/arch/powerpc/kvm/book3s_hv_cma.c b/arch/powerpc/kvm/book3s_hv_cma.c deleted file mode 100644 index d9d3d85..000 --- a/arch/powerpc/kvm/book3s_hv_cma.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA - * for DMA mapping framework - * - * Copyright IBM Corporation, 2013 - * Author Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License or (at your optional) any later version of the license. - * - */ -#define pr_fmt(fmt) kvm_cma: fmt - -#ifdef CONFIG_CMA_DEBUG -#ifndef DEBUG -# define DEBUG -#endif -#endif - -#include linux/memblock.h -#include linux/mutex.h -#include linux/sizes.h -#include linux/slab.h - -#include book3s_hv_cma.h - -struct kvm_cma { - unsigned long base_pfn; - unsigned long count; - unsigned long *bitmap; -}; - -static DEFINE_MUTEX(kvm_cma_mutex); -static struct kvm_cma kvm_cma_area; - -/** - * kvm_cma_declare_contiguous() - reserve area for contiguous memory handling - * for kvm hash pagetable - * @size: Size of the reserved memory. - * @alignment: Alignment for the contiguous memory area - * - * This function reserves memory for kvm cma area. It should be - * called by arch code when early allocator (memblock or bootmem) - * is still activate. - */ -long __init kvm_cma_declare_contiguous(phys_addr_t size, phys_addr_t alignment) -{ - long base_pfn; - phys_addr_t addr; - struct kvm_cma *cma = kvm_cma_area; - - pr_debug(%s(size %lx)\n, __func__, (unsigned long)size); - - if (!size) - return -EINVAL; - /* - * Sanitise input arguments. - * We should be pageblock aligned for CMA. - */ -
Re: [PATCH v2 06/10] CMA: generalize CMA reserved area management functionality
Joonsoo Kim iamjoonsoo@lge.com writes: Currently, there are two users on CMA functionality, one is the DMA subsystem and the other is the kvm on powerpc. They have their own code to manage CMA reserved area even if they looks really similar. From my guess, it is caused by some needs on bitmap management. Kvm side wants to maintain bitmap not for 1 page, but for more size. Eventually it use bitmap where one bit represents 64 pages. When I implement CMA related patches, I should change those two places to apply my change and it seem to be painful to me. I want to change this situation and reduce future code management overhead through this patch. This change could also help developer who want to use CMA in their new feature development, since they can use CMA easily without copying pasting this reserved area management code. In previous patches, we have prepared some features to generalize CMA reserved area management and now it's time to do it. This patch moves core functions to mm/cma.c and change DMA APIs to use these functions. There is no functional change in DMA APIs. v2: There is no big change from v1 in mm/cma.c. Mostly renaming. Acked-by: Michal Nazarewicz min...@mina86.com Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com Reviewed-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 00e13ce..4eac559 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -283,16 +283,6 @@ config CMA_ALIGNMENT If unsure, leave the default value 8. -config CMA_AREAS - int Maximum count of the CMA device-private areas - default 7 - help - CMA allows to create CMA areas for particular devices. This parameter - sets the maximum number of such device private CMA areas in the - system. - - If unsure, leave the default value 7. - endif endmenu diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 9bc9340..f177f73 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -24,25 +24,10 @@ #include linux/memblock.h #include linux/err.h -#include linux/mm.h -#include linux/mutex.h -#include linux/page-isolation.h #include linux/sizes.h -#include linux/slab.h -#include linux/swap.h -#include linux/mm_types.h #include linux/dma-contiguous.h #include linux/log2.h - -struct cma { - unsigned long base_pfn; - unsigned long count; - unsigned long *bitmap; - int order_per_bit; /* Order of pages represented by one bit */ - struct mutexlock; -}; - -struct cma *dma_contiguous_default_area; +#include linux/cma.h #ifdef CONFIG_CMA_SIZE_MBYTES #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES @@ -50,6 +35,8 @@ struct cma *dma_contiguous_default_area; #define CMA_SIZE_MBYTES 0 #endif +struct cma *dma_contiguous_default_area; + /* * Default global CMA area size can be defined in kernel's .config. * This is useful mainly for distro maintainers to create a kernel @@ -156,199 +143,13 @@ void __init dma_contiguous_reserve(phys_addr_t limit) } } -static DEFINE_MUTEX(cma_mutex); - -static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order) -{ - return (1 (align_order cma-order_per_bit)) - 1; -} - -static unsigned long cma_bitmap_maxno(struct cma *cma) -{ - return cma-count cma-order_per_bit; -} - -static unsigned long cma_bitmap_pages_to_bits(struct cma *cma, - unsigned long pages) -{ - return ALIGN(pages, 1 cma-order_per_bit) cma-order_per_bit; -} - -static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) -{ - unsigned long bitmapno, nr_bits; - - bitmapno = (pfn - cma-base_pfn) cma-order_per_bit; - nr_bits = cma_bitmap_pages_to_bits(cma, count); - - mutex_lock(cma-lock); - bitmap_clear(cma-bitmap, bitmapno, nr_bits); - mutex_unlock(cma-lock); -} - -static int __init cma_activate_area(struct cma *cma) -{ - int bitmap_maxno = cma_bitmap_maxno(cma); - int bitmap_size = BITS_TO_LONGS(bitmap_maxno) * sizeof(long); - unsigned long base_pfn = cma-base_pfn, pfn = base_pfn; - unsigned i = cma-count pageblock_order; - struct zone *zone; - - pr_debug(%s()\n, __func__); - - cma-bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!cma-bitmap) - return -ENOMEM; - - WARN_ON_ONCE(!pfn_valid(pfn)); - zone = page_zone(pfn_to_page(pfn)); - - do { - unsigned j; - base_pfn = pfn; - for (j = pageblock_nr_pages; j; --j, pfn++) { - WARN_ON_ONCE(!pfn_valid(pfn)); - /* - * alloc_contig_range requires the pfn range - * specified to be in the same zone. Make this - * simple by forcing the
Re: [PATCH v2 06/10] CMA: generalize CMA reserved area management functionality
Joonsoo Kim iamjoonsoo@lge.com writes: Currently, there are two users on CMA functionality, one is the DMA subsystem and the other is the kvm on powerpc. They have their own code to manage CMA reserved area even if they looks really similar. From my guess, it is caused by some needs on bitmap management. Kvm side wants to maintain bitmap not for 1 page, but for more size. Eventually it use bitmap where one bit represents 64 pages. When I implement CMA related patches, I should change those two places to apply my change and it seem to be painful to me. I want to change this situation and reduce future code management overhead through this patch. This change could also help developer who want to use CMA in their new feature development, since they can use CMA easily without copying pasting this reserved area management code. In previous patches, we have prepared some features to generalize CMA reserved area management and now it's time to do it. This patch moves core functions to mm/cma.c and change DMA APIs to use these functions. There is no functional change in DMA APIs. v2: There is no big change from v1 in mm/cma.c. Mostly renaming. Acked-by: Michal Nazarewicz min...@mina86.com Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com Reviewed-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 00e13ce..4eac559 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -283,16 +283,6 @@ config CMA_ALIGNMENT If unsure, leave the default value 8. -config CMA_AREAS - int Maximum count of the CMA device-private areas - default 7 - help - CMA allows to create CMA areas for particular devices. This parameter - sets the maximum number of such device private CMA areas in the - system. - - If unsure, leave the default value 7. - endif endmenu diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 9bc9340..f177f73 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -24,25 +24,10 @@ #include linux/memblock.h #include linux/err.h -#include linux/mm.h -#include linux/mutex.h -#include linux/page-isolation.h #include linux/sizes.h -#include linux/slab.h -#include linux/swap.h -#include linux/mm_types.h #include linux/dma-contiguous.h #include linux/log2.h - -struct cma { - unsigned long base_pfn; - unsigned long count; - unsigned long *bitmap; - int order_per_bit; /* Order of pages represented by one bit */ - struct mutexlock; -}; - -struct cma *dma_contiguous_default_area; +#include linux/cma.h #ifdef CONFIG_CMA_SIZE_MBYTES #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES @@ -50,6 +35,8 @@ struct cma *dma_contiguous_default_area; #define CMA_SIZE_MBYTES 0 #endif +struct cma *dma_contiguous_default_area; + /* * Default global CMA area size can be defined in kernel's .config. * This is useful mainly for distro maintainers to create a kernel @@ -156,199 +143,13 @@ void __init dma_contiguous_reserve(phys_addr_t limit) } } -static DEFINE_MUTEX(cma_mutex); - -static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order) -{ - return (1 (align_order cma-order_per_bit)) - 1; -} - -static unsigned long cma_bitmap_maxno(struct cma *cma) -{ - return cma-count cma-order_per_bit; -} - -static unsigned long cma_bitmap_pages_to_bits(struct cma *cma, - unsigned long pages) -{ - return ALIGN(pages, 1 cma-order_per_bit) cma-order_per_bit; -} - -static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) -{ - unsigned long bitmapno, nr_bits; - - bitmapno = (pfn - cma-base_pfn) cma-order_per_bit; - nr_bits = cma_bitmap_pages_to_bits(cma, count); - - mutex_lock(cma-lock); - bitmap_clear(cma-bitmap, bitmapno, nr_bits); - mutex_unlock(cma-lock); -} - -static int __init cma_activate_area(struct cma *cma) -{ - int bitmap_maxno = cma_bitmap_maxno(cma); - int bitmap_size = BITS_TO_LONGS(bitmap_maxno) * sizeof(long); - unsigned long base_pfn = cma-base_pfn, pfn = base_pfn; - unsigned i = cma-count pageblock_order; - struct zone *zone; - - pr_debug(%s()\n, __func__); - - cma-bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!cma-bitmap) - return -ENOMEM; - - WARN_ON_ONCE(!pfn_valid(pfn)); - zone = page_zone(pfn_to_page(pfn)); - - do { - unsigned j; - base_pfn = pfn; - for (j = pageblock_nr_pages; j; --j, pfn++) { - WARN_ON_ONCE(!pfn_valid(pfn)); - /* - * alloc_contig_range requires the pfn range - * specified to be in the same zone. Make this - * simple by forcing the
Re: [PATCH v2 05/10] DMA, CMA: support arbitrary bitmap granularity
Joonsoo Kim iamjoonsoo@lge.com writes: ppc kvm's cma region management requires arbitrary bitmap granularity, since they want to reserve very large memory and manage this region with bitmap that one bit for several pages to reduce management overheads. So support arbitrary bitmap granularity for following generalization. Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com Reviewed-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index bc4c171..9bc9340 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -38,6 +38,7 @@ struct cma { unsigned long base_pfn; unsigned long count; unsigned long *bitmap; + int order_per_bit; /* Order of pages represented by one bit */ struct mutexlock; }; @@ -157,9 +158,38 @@ void __init dma_contiguous_reserve(phys_addr_t limit) static DEFINE_MUTEX(cma_mutex); +static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order) +{ + return (1 (align_order cma-order_per_bit)) - 1; +} + +static unsigned long cma_bitmap_maxno(struct cma *cma) +{ + return cma-count cma-order_per_bit; +} + +static unsigned long cma_bitmap_pages_to_bits(struct cma *cma, + unsigned long pages) +{ + return ALIGN(pages, 1 cma-order_per_bit) cma-order_per_bit; +} + +static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) +{ + unsigned long bitmapno, nr_bits; + + bitmapno = (pfn - cma-base_pfn) cma-order_per_bit; + nr_bits = cma_bitmap_pages_to_bits(cma, count); + + mutex_lock(cma-lock); + bitmap_clear(cma-bitmap, bitmapno, nr_bits); + mutex_unlock(cma-lock); +} + static int __init cma_activate_area(struct cma *cma) { - int bitmap_size = BITS_TO_LONGS(cma-count) * sizeof(long); + int bitmap_maxno = cma_bitmap_maxno(cma); + int bitmap_size = BITS_TO_LONGS(bitmap_maxno) * sizeof(long); unsigned long base_pfn = cma-base_pfn, pfn = base_pfn; unsigned i = cma-count pageblock_order; struct zone *zone; @@ -221,6 +251,7 @@ core_initcall(cma_init_reserved_areas); * @base: Base address of the reserved area optional, use 0 for any * @limit: End address of the reserved memory (optional, 0 for any). * @alignment: Alignment for the contiguous memory area, should be power of 2 + * @order_per_bit: Order of pages represented by one bit on bitmap. * @res_cma: Pointer to store the created cma region. * @fixed: hint about where to place the reserved area * @@ -235,7 +266,7 @@ core_initcall(cma_init_reserved_areas); */ static int __init __dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, phys_addr_t limit, - phys_addr_t alignment, + phys_addr_t alignment, int order_per_bit, struct cma **res_cma, bool fixed) { struct cma *cma = cma_areas[cma_area_count]; @@ -269,6 +300,8 @@ static int __init __dma_contiguous_reserve_area(phys_addr_t size, base = ALIGN(base, alignment); size = ALIGN(size, alignment); limit = ~(alignment - 1); + /* size should be aligned with order_per_bit */ + BUG_ON(!IS_ALIGNED(size PAGE_SHIFT, 1 order_per_bit)); /* Reserve memory */ if (base fixed) { @@ -294,6 +327,7 @@ static int __init __dma_contiguous_reserve_area(phys_addr_t size, */ cma-base_pfn = PFN_DOWN(base); cma-count = size PAGE_SHIFT; + cma-order_per_bit = order_per_bit; *res_cma = cma; cma_area_count++; @@ -313,7 +347,7 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, { int ret; - ret = __dma_contiguous_reserve_area(size, base, limit, 0, + ret = __dma_contiguous_reserve_area(size, base, limit, 0, 0, res_cma, fixed); if (ret) return ret; @@ -324,13 +358,6 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, return 0; } -static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) -{ - mutex_lock(cma-lock); - bitmap_clear(cma-bitmap, pfn - cma-base_pfn, count); - mutex_unlock(cma-lock); -} - /** * dma_alloc_from_contiguous() - allocate pages from contiguous area * @dev: Pointer to device for which the allocation is performed. @@ -345,7 +372,8 @@ static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) static struct page *__dma_alloc_from_contiguous(struct cma *cma, int count, unsigned int align) { - unsigned long mask, pfn, pageno, start = 0; + unsigned long mask, pfn, start = 0; + unsigned long bitmap_maxno, bitmapno, nr_bits; struct page *page =
Re: [PATCH v2 06/10] CMA: generalize CMA reserved area management functionality
Joonsoo Kim iamjoonsoo@lge.com writes: Currently, there are two users on CMA functionality, one is the DMA subsystem and the other is the kvm on powerpc. They have their own code to manage CMA reserved area even if they looks really similar. From my guess, it is caused by some needs on bitmap management. Kvm side wants to maintain bitmap not for 1 page, but for more size. Eventually it use bitmap where one bit represents 64 pages. When I implement CMA related patches, I should change those two places to apply my change and it seem to be painful to me. I want to change this situation and reduce future code management overhead through this patch. This change could also help developer who want to use CMA in their new feature development, since they can use CMA easily without copying pasting this reserved area management code. In previous patches, we have prepared some features to generalize CMA reserved area management and now it's time to do it. This patch moves core functions to mm/cma.c and change DMA APIs to use these functions. There is no functional change in DMA APIs. v2: There is no big change from v1 in mm/cma.c. Mostly renaming. Acked-by: Michal Nazarewicz min...@mina86.com Signed-off-by: Joonsoo Kim iamjoonsoo@lge.com . + + mask = cma_bitmap_aligned_mask(cma, align); + bitmap_maxno = cma_bitmap_maxno(cma); + nr_bits = cma_bitmap_pages_to_bits(cma, count); + + for (;;) { + mutex_lock(cma-lock); + bitmapno = bitmap_find_next_zero_area(cma-bitmap, + bitmap_maxno, start, nr_bits, mask); + if (bitmapno = bitmap_maxno) { + mutex_unlock(cma-lock); + break; + } + bitmap_set(cma-bitmap, bitmapno, nr_bits); + /* + * It's safe to drop the lock here. We've marked this region for + * our exclusive use. If the migration fails we will take the + * lock again and unmark it. + */ + mutex_unlock(cma-lock); + + pfn = cma-base_pfn + (bitmapno cma-order_per_bit); + mutex_lock(cma_mutex); + ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA); + mutex_unlock(cma_mutex); + if (ret == 0) { + page = pfn_to_page(pfn); + break; + } else if (ret != -EBUSY) { + clear_cma_bitmap(cma, pfn, count); + break; + } + For setting bit map we do bitmap_set(cma-bitmap, bitmapno, nr_bits); alloc_contig().. if (error) clear_cma_bitmap(cma, pfn, count); Why ? why not bitmap_clear() ? -aneesh -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] powerpc/kvm: support to handle sw breakpoint
This patch adds kernel side support for software breakpoint. Design is that, by using an illegal instruction, we trap to hypervisor via Emulation Assistance interrupt, where we check for the illegal instruction and accordingly we return to Host or Guest. Patch mandates use of abs instruction (primary opcode 31 and extended opcode 360) as sw breakpoint instruction. Based on PowerISA v2.01, ABS instruction has been dropped from the architecture and treated an illegal instruction. Signed-off-by: Madhavan Srinivasan ma...@linux.vnet.ibm.com --- arch/powerpc/kvm/book3s.c| 3 ++- arch/powerpc/kvm/book3s_hv.c | 23 +++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index c254c27..b40fe5d 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -789,7 +789,8 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) { - return -EINVAL; + vcpu-guest_debug = dbg-control; + return 0; } void kvmppc_decrementer_func(unsigned long data) diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 7a12edb..688421d 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -67,6 +67,14 @@ /* Used as a null value for timebase values */ #define TB_NIL (~(u64)0) +/* + * SW_BRK_DBG_INT is debug Instruction for supporting Software Breakpoint. + * Instruction mnemonic is ABS, primary opcode is 31 and extended opcode is 360. + * Based on PowerISA v2.01, ABS instruction has been dropped from the architecture + * and treated an illegal instruction. + */ +#define SW_BRK_DBG_INT 0x7c0002d0 + static void kvmppc_end_cede(struct kvm_vcpu *vcpu); static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); @@ -721,12 +729,19 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, break; /* * This occurs if the guest executes an illegal instruction. -* We just generate a program interrupt to the guest, since -* we don't emulate any guest instructions at this stage. +* To support software breakpoint, we check for the sw breakpoint +* instruction to return back to host, if not we just generate a +* program interrupt to the guest. */ case BOOK3S_INTERRUPT_H_EMUL_ASSIST: - kvmppc_core_queue_program(vcpu, SRR1_PROGILL); - r = RESUME_GUEST; + if (vcpu-arch.last_inst == SW_BRK_DBG_INT) { + run-exit_reason = KVM_EXIT_DEBUG; + run-debug.arch.address = vcpu-arch.pc; + r = RESUME_HOST; + } else { + kvmppc_core_queue_program(vcpu, 0x8); + r = RESUME_GUEST; + } break; /* * This occurs if the guest (kernel or userspace), does something that -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html