kernel: fix the mips module relocation patch for 3.19+
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Mon, 2 Mar 2015 04:42:17 +0000 (04:42 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Mon, 2 Mar 2015 04:42:17 +0000 (04:42 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@44590 3c298f89-4303-0410-b956-a3cf2f4a3e73

target/linux/generic/patches-3.19/305-mips_module_reloc.patch
target/linux/generic/patches-4.0/305-mips_module_reloc.patch

index 2e92916..a9f10e1 100644 (file)
@@ -30,7 +30,7 @@
  typedef uint8_t Elf64_Byte;           /* Type for a 8-bit quantity.  */
 --- a/arch/mips/kernel/module.c
 +++ b/arch/mips/kernel/module.c
-@@ -43,14 +43,222 @@ struct mips_hi16 {
+@@ -43,14 +43,221 @@ struct mips_hi16 {
  static LIST_HEAD(dbe_list);
  static DEFINE_SPINLOCK(dbe_lock);
  
 +
 +      split_page(page, order);
 +
++      /* mark all pages except for the last one */
++      for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p)
++              set_bit(PG_owner_priv_1, &p->flags);
++
 +      for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
 +              __free_page(p);
 +
 +}
 +#endif
 +
-+static void free_phys(void *ptr, unsigned long size)
++static void free_phys(void *ptr)
 +{
 +      struct page *page;
-+      struct page *end;
++      bool free;
 +
 +      page = virt_to_page(ptr);
-+      end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
-+
-+      for (; page < end; ++page)
++      do {
++              free = test_and_clear_bit(PG_owner_priv_1, &page->flags);
 +              __free_page(page);
++              page++;
++      } while (free);
 +}
 +
 +
 +}
 +
 +/* Free memory returned from module_alloc */
-+void module_free(struct module *mod, void *module_region)
++void module_memfree(void *module_region)
 +{
-+      if (is_phys_addr(module_region)) {
-+              if (mod->module_init == module_region)
-+                      free_phys(module_region, mod->init_size);
-+              else if (mod->module_core == module_region)
-+                      free_phys(module_region, mod->core_size);
-+              else
-+                      BUG();
-+      } else {
++      if (is_phys_addr(module_region))
++              free_phys(module_region);
++      else
 +              vfree(module_region);
-+      }
 +}
 +
 +static void *__module_alloc(int size, bool phys)
  
  int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
  {
-@@ -64,8 +272,39 @@ static int apply_r_mips_32_rel(struct mo
+@@ -64,8 +271,39 @@ static int apply_r_mips_32_rel(struct mo
        return 0;
  }
  
        if (v % 4) {
                pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
                       me->name);
-@@ -73,14 +312,17 @@ static int apply_r_mips_26_rel(struct mo
+@@ -73,14 +311,17 @@ static int apply_r_mips_26_rel(struct mo
        }
  
        if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
  
        return 0;
  }
-@@ -287,11 +529,32 @@ int module_finalize(const Elf_Ehdr *hdr,
+@@ -287,11 +528,32 @@ int module_finalize(const Elf_Ehdr *hdr,
                list_add(&me->arch.dbe_list, &dbe_list);
                spin_unlock_irq(&dbe_lock);
        }
index 752d597..a9f10e1 100644 (file)
@@ -30,7 +30,7 @@
  typedef uint8_t Elf64_Byte;           /* Type for a 8-bit quantity.  */
 --- a/arch/mips/kernel/module.c
 +++ b/arch/mips/kernel/module.c
-@@ -43,14 +43,222 @@ struct mips_hi16 {
+@@ -43,14 +43,221 @@ struct mips_hi16 {
  static LIST_HEAD(dbe_list);
  static DEFINE_SPINLOCK(dbe_lock);
  
 +
 +      split_page(page, order);
 +
++      /* mark all pages except for the last one */
++      for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p)
++              set_bit(PG_owner_priv_1, &p->flags);
++
 +      for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
 +              __free_page(p);
 +
 +}
 +#endif
 +
-+static void free_phys(void *ptr, unsigned long size)
++static void free_phys(void *ptr)
 +{
 +      struct page *page;
-+      struct page *end;
++      bool free;
 +
 +      page = virt_to_page(ptr);
-+      end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
-+
-+      for (; page < end; ++page)
++      do {
++              free = test_and_clear_bit(PG_owner_priv_1, &page->flags);
 +              __free_page(page);
++              page++;
++      } while (free);
 +}
 +
 +
  {
 +#ifdef MODULE_START
        return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
-                               GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
+                               GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
                                __builtin_return_address(0));
 +#else
 +      void *ptr;
 +}
 +
 +/* Free memory returned from module_alloc */
-+void module_free(struct module *mod, void *module_region)
++void module_memfree(void *module_region)
 +{
-+      if (is_phys_addr(module_region)) {
-+              if (mod->module_init == module_region)
-+                      free_phys(module_region, mod->init_size);
-+              else if (mod->module_core == module_region)
-+                      free_phys(module_region, mod->core_size);
-+              else
-+                      BUG();
-+      } else {
++      if (is_phys_addr(module_region))
++              free_phys(module_region);
++      else
 +              vfree(module_region);
-+      }
 +}
 +
 +static void *__module_alloc(int size, bool phys)
  
  int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
  {
-@@ -64,8 +272,39 @@ static int apply_r_mips_32_rel(struct mo
+@@ -64,8 +271,39 @@ static int apply_r_mips_32_rel(struct mo
        return 0;
  }
  
        if (v % 4) {
                pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
                       me->name);
-@@ -73,14 +312,17 @@ static int apply_r_mips_26_rel(struct mo
+@@ -73,14 +311,17 @@ static int apply_r_mips_26_rel(struct mo
        }
  
        if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
  
        return 0;
  }
-@@ -287,11 +529,32 @@ int module_finalize(const Elf_Ehdr *hdr,
+@@ -287,11 +528,32 @@ int module_finalize(const Elf_Ehdr *hdr,
                list_add(&me->arch.dbe_list, &dbe_list);
                spin_unlock_irq(&dbe_lock);
        }