]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'linus' into x86/mm
authorThomas Gleixner <tglx@linutronix.de>
Wed, 17 Feb 2010 17:27:37 +0000 (18:27 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 17 Feb 2010 17:28:05 +0000 (18:28 +0100)
x86/mm is on 32-rc4 and missing the spinlock namespace changes which
are needed for further commits into this topic.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1  2 
arch/mips/mm/init.c
arch/score/mm/init.c
arch/x86/kernel/e820.c
arch/x86/kernel/setup.c
arch/x86/mm/ioremap.c
include/linux/mm.h
kernel/resource.c

diff --combined arch/mips/mm/init.c
index 4d72aabe8352680f83902de32ead255f6c180e1b,1651942f7febe79eeea81927f34264e01c7c4217..dee564aad23a8ae49a380f383ff92d8ee5cadaaf
@@@ -27,6 -27,7 +27,7 @@@
  #include <linux/swap.h>
  #include <linux/proc_fs.h>
  #include <linux/pfn.h>
+ #include <linux/hardirq.h>
  
  #include <asm/asm-offsets.h>
  #include <asm/bootinfo.h>
@@@ -132,7 -133,10 +133,10 @@@ void *kmap_coherent(struct page *page, 
        inc_preempt_count();
        idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
  #ifdef CONFIG_MIPS_MT_SMTC
-       idx += FIX_N_COLOURS * smp_processor_id();
+       idx += FIX_N_COLOURS * smp_processor_id() +
+               (in_interrupt() ? (FIX_N_COLOURS * NR_CPUS) : 0);
+ #else
+       idx += in_interrupt() ? FIX_N_COLOURS : 0;
  #endif
        vaddr = __fix_to_virt(FIX_CMAP_END - idx);
        pte = mk_pte(page, PAGE_KERNEL);
@@@ -294,7 -298,7 +298,7 @@@ void __init fixrange_init(unsigned lon
  }
  
  #ifndef CONFIG_NEED_MULTIPLE_NODES
 -static int __init page_is_ram(unsigned long pagenr)
 +int page_is_ram(unsigned long pagenr)
  {
        int i;
  
@@@ -420,7 -424,7 +424,7 @@@ void __init mem_init(void
               reservedpages << (PAGE_SHIFT-10),
               datasize >> 10,
               initsize >> 10,
-              (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+              totalhigh_pages << (PAGE_SHIFT-10));
  }
  #endif /* !CONFIG_NEED_MULTIPLE_NODES */
  
@@@ -458,7 -462,9 +462,9 @@@ void __init_refok free_initmem(void
                        __pa_symbol(&__init_end));
  }
  
+ #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
  unsigned long pgd_current[NR_CPUS];
+ #endif
  /*
   * On 64-bit we've got three-level pagetables with a slightly
   * different layout ...
diff --combined arch/score/mm/init.c
index f684a590c21d83d0b8c992faba20021e8174d85a,dfaf458d6702459ba9b5f85d7be5e30b1528a2ba..7f001bbedb00a463d0746c2690421eec1df5bf3a
@@@ -59,7 -59,7 +59,7 @@@ static unsigned long setup_zero_page(vo
  }
  
  #ifndef CONFIG_NEED_MULTIPLE_NODES
 -static int __init page_is_ram(unsigned long pagenr)
 +int page_is_ram(unsigned long pagenr)
  {
        if (pagenr >= min_low_pfn && pagenr < max_low_pfn)
                return 1;
@@@ -83,7 -83,6 +83,6 @@@ void __init mem_init(void
        unsigned long codesize, reservedpages, datasize, initsize;
        unsigned long tmp, ram = 0;
  
-       max_mapnr = max_low_pfn;
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
        totalram_pages += free_all_bootmem();
        totalram_pages -= setup_zero_page();    /* Setup zeroed pages. */
        datasize = (unsigned long) &_edata - (unsigned long) &_etext;
        initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
  
-       kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
-       kclist_add(&kcore_vmalloc, (void *) VMALLOC_START,
-                       VMALLOC_END - VMALLOC_START);
        printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
                        "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
                        (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                        ram << (PAGE_SHIFT-10), codesize >> 10,
                        reservedpages << (PAGE_SHIFT-10), datasize >> 10,
                        initsize >> 10,
-                       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+                       totalhigh_pages << (PAGE_SHIFT-10));
  }
  #endif /* !CONFIG_NEED_MULTIPLE_NODES */
  
diff --combined arch/x86/kernel/e820.c
index 230687ba5ba5fd0feb6a2fcdfffa9520eccc33b7,a1a7876cadcbfa2b0fdbfa9d9416ee62c14cd85c..a966b753e4961446863f9e4c114f8315cedff274
@@@ -517,19 -517,11 +517,19 @@@ u64 __init e820_remove_range(u64 start
                             int checktype)
  {
        int i;
 +      u64 end;
        u64 real_removed_size = 0;
  
        if (size > (ULLONG_MAX - start))
                size = ULLONG_MAX - start;
  
 +      end = start + size;
 +      printk(KERN_DEBUG "e820 remove range: %016Lx - %016Lx ",
 +                     (unsigned long long) start,
 +                     (unsigned long long) end);
 +      e820_print_type(old_type);
 +      printk(KERN_CONT "\n");
 +
        for (i = 0; i < e820.nr_map; i++) {
                struct e820entry *ei = &e820.map[i];
                u64 final_start, final_end;
@@@ -732,7 -724,7 +732,7 @@@ core_initcall(e820_mark_nvs_memory)
  /*
   * Early reserved memory areas.
   */
- #define MAX_EARLY_RES 20
+ #define MAX_EARLY_RES 32
  
  struct early_res {
        u64 start, end;
        char overlap_ok;
  };
  static struct early_res early_res[MAX_EARLY_RES] __initdata = {
-       { 0, PAGE_SIZE, "BIOS data page" },     /* BIOS data page */
+       { 0, PAGE_SIZE, "BIOS data page", 1 },  /* BIOS data page */
+ #if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE)
+       /*
+        * But first pinch a few for the stack/trampoline stuff
+        * FIXME: Don't need the extra page at 4K, but need to fix
+        * trampoline before removing it. (see the GDT stuff)
+        */
+       { PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE", 1 },
+ #endif
        {}
  };
  
diff --combined arch/x86/kernel/setup.c
index f9b1f4e5ab74cb5dc7cf4c0b64c0edfc3e0709af,5d9e40c58628ca2509c2e16718518dda9dac4149..3499b4fabc94b58aca76651c0fc7e297f6571cb0
@@@ -73,6 -73,7 +73,7 @@@
  
  #include <asm/mtrr.h>
  #include <asm/apic.h>
+ #include <asm/trampoline.h>
  #include <asm/e820.h>
  #include <asm/mpspec.h>
  #include <asm/setup.h>
  #ifdef CONFIG_X86_64
  #include <asm/numa_64.h>
  #endif
+ #include <asm/mce.h>
  
  /*
   * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@@ -248,7 -250,7 +250,7 @@@ EXPORT_SYMBOL(edd)
   *              from boot_params into a safe place.
   *
   */
- static inline void copy_edd(void)
+ static inline void __init copy_edd(void)
  {
       memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
            sizeof(edd.mbr_signature));
       edd.edd_info_nr = boot_params.eddbuf_entries;
  }
  #else
- static inline void copy_edd(void)
+ static inline void __init copy_edd(void)
  {
  }
  #endif
@@@ -634,39 -636,37 +636,54 @@@ static struct dmi_system_id __initdata 
                },
        },
        {
+               .callback = dmi_low_memory_corruption,
+               .ident = "Phoenix/MSC BIOS",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
+               },
+       },
        /*
-        * AMI BIOS with low memory corruption was found on Intel DG45ID board.
-        * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+        * AMI BIOS with low memory corruption was found on Intel DG45ID and
+        * DG45FC boards.
+        * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
         * match only DMI_BOARD_NAME and see if there is more bad products
         * with this vendor.
         */
+       {
                .callback = dmi_low_memory_corruption,
                .ident = "AMI BIOS",
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
                },
        },
+       {
+               .callback = dmi_low_memory_corruption,
+               .ident = "AMI BIOS",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
+               },
+       },
  #endif
        {}
  };
  
 +static void __init trim_bios_range(void)
 +{
 +      /*
 +       * A special case is the first 4Kb of memory;
 +       * This is a BIOS owned area, not kernel ram, but generally
 +       * not listed as such in the E820 table.
 +       */
 +      e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED);
 +      /*
 +       * special case: Some BIOSen report the PC BIOS
 +       * area (640->1Mb) as ram even though it is not.
 +       * take them out.
 +       */
 +      e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1);
 +      sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 +}
 +
  /*
   * Determine if we were loaded by an EFI loader.  If so, then we have also been
   * passed the efi memmap, systab, etc., so we should use these data structures
@@@ -830,7 -830,7 +847,7 @@@ void __init setup_arch(char **cmdline_p
        insert_resource(&iomem_resource, &data_resource);
        insert_resource(&iomem_resource, &bss_resource);
  
 -
 +      trim_bios_range();
  #ifdef CONFIG_X86_32
        if (ppro_with_ram_bug()) {
                e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
  
        reserve_brk();
  
+       /*
+        * Find and reserve possible boot-time SMP configuration:
+        */
+       find_smp_config();
+       reserve_trampoline_memory();
  #ifdef CONFIG_ACPI_SLEEP
        /*
         * Reserve low memory region for sleep support.
  
        early_acpi_boot_init();
  
-       /*
-        * Find and reserve possible boot-time SMP configuration:
-        */
-       find_smp_config();
  #ifdef CONFIG_ACPI_NUMA
        /*
         * Parse SRAT to discover nodes.
  #endif
  #endif
        x86_init.oem.banner();
+       mcheck_init();
  }
  
  #ifdef CONFIG_X86_32
diff --combined arch/x86/mm/ioremap.c
index 1bf9e08ed733102e3e6db1475a03e66ffd811eec,c246d259822d8b5a3d32a35275368a5bcbbf19b8..e404ffe302105f3a7a38107fc4d4e23286799594
  
  #include "physaddr.h"
  
 -int page_is_ram(unsigned long pagenr)
 -{
 -      resource_size_t addr, end;
 -      int i;
 -
 -      /*
 -       * A special case is the first 4Kb of memory;
 -       * This is a BIOS owned area, not kernel ram, but generally
 -       * not listed as such in the E820 table.
 -       */
 -      if (pagenr == 0)
 -              return 0;
 -
 -      /*
 -       * Second special case: Some BIOSen report the PC BIOS
 -       * area (640->1Mb) as ram even though it is not.
 -       */
 -      if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) &&
 -                  pagenr < (BIOS_END >> PAGE_SHIFT))
 -              return 0;
 -
 -      for (i = 0; i < e820.nr_map; i++) {
 -              /*
 -               * Not usable memory:
 -               */
 -              if (e820.map[i].type != E820_RAM)
 -                      continue;
 -              addr = (e820.map[i].addr + PAGE_SIZE-1) >> PAGE_SHIFT;
 -              end = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
 -
 -
 -              if ((pagenr >= addr) && (pagenr < end))
 -                      return 1;
 -      }
 -      return 0;
 -}
 -
  /*
   * Fix up the linear direct mapping of the kernel to avoid cache attribute
   * conflicts.
@@@ -133,8 -170,7 +133,7 @@@ static void __iomem *__ioremap_caller(r
                                (unsigned long long)phys_addr,
                                (unsigned long long)(phys_addr + size),
                                prot_val, new_prot_val);
-                       free_memtype(phys_addr, phys_addr + size);
-                       return NULL;
+                       goto err_free_memtype;
                }
                prot_val = new_prot_val;
        }
         */
        area = get_vm_area_caller(size, VM_IOREMAP, caller);
        if (!area)
-               return NULL;
+               goto err_free_memtype;
        area->phys_addr = phys_addr;
        vaddr = (unsigned long) area->addr;
  
-       if (kernel_map_sync_memtype(phys_addr, size, prot_val)) {
-               free_memtype(phys_addr, phys_addr + size);
-               free_vm_area(area);
-               return NULL;
-       }
+       if (kernel_map_sync_memtype(phys_addr, size, prot_val))
+               goto err_free_area;
  
-       if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
-               free_memtype(phys_addr, phys_addr + size);
-               free_vm_area(area);
-               return NULL;
-       }
+       if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot))
+               goto err_free_area;
  
        ret_addr = (void __iomem *) (vaddr + offset);
        mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
  
        return ret_addr;
+ err_free_area:
+       free_vm_area(area);
+ err_free_memtype:
+       free_memtype(phys_addr, phys_addr + size);
+       return NULL;
  }
  
  /**
@@@ -246,30 -281,6 +244,6 @@@ void __iomem *ioremap_cache(resource_si
  }
  EXPORT_SYMBOL(ioremap_cache);
  
- static void __iomem *ioremap_default(resource_size_t phys_addr,
-                                       unsigned long size)
- {
-       unsigned long flags;
-       void __iomem *ret;
-       int err;
-       /*
-        * - WB for WB-able memory and no other conflicting mappings
-        * - UC_MINUS for non-WB-able memory with no other conflicting mappings
-        * - Inherit from confliting mappings otherwise
-        */
-       err = reserve_memtype(phys_addr, phys_addr + size,
-                               _PAGE_CACHE_WB, &flags);
-       if (err < 0)
-               return NULL;
-       ret = __ioremap_caller(phys_addr, size, flags,
-                              __builtin_return_address(0));
-       free_memtype(phys_addr, phys_addr + size);
-       return ret;
- }
  void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
                                unsigned long prot_val)
  {
@@@ -345,7 -356,7 +319,7 @@@ void *xlate_dev_mem_ptr(unsigned long p
        if (page_is_ram(start >> PAGE_SHIFT))
                return __va(phys);
  
-       addr = (void __force *)ioremap_default(start, PAGE_SIZE);
+       addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
        if (addr)
                addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
  
diff --combined include/linux/mm.h
index bad433fdbfce5d67f0ca845aad870756d4321d47,60c467bfbabd66dbd295721c5afb9cb39b47594d..8b2fa8593c61935f36ffa128d72c7236c198e119
@@@ -265,8 -265,6 +265,8 @@@ static inline int get_page_unless_zero(
        return atomic_inc_not_zero(&page->_count);
  }
  
 +extern int page_is_ram(unsigned long pfn);
 +
  /* Support for virtually mapped pages */
  struct page *vmalloc_to_page(const void *addr);
  unsigned long vmalloc_to_pfn(const void *addr);
@@@ -622,13 -620,22 +622,22 @@@ void page_address_init(void)
  /*
   * On an anonymous page mapped into a user virtual memory area,
   * page->mapping points to its anon_vma, not to a struct address_space;
-  * with the PAGE_MAPPING_ANON bit set to distinguish it.
+  * with the PAGE_MAPPING_ANON bit set to distinguish it.  See rmap.h.
+  *
+  * On an anonymous page in a VM_MERGEABLE area, if CONFIG_KSM is enabled,
+  * the PAGE_MAPPING_KSM bit may be set along with the PAGE_MAPPING_ANON bit;
+  * and then page->mapping points, not to an anon_vma, but to a private
+  * structure which KSM associates with that merged page.  See ksm.h.
+  *
+  * PAGE_MAPPING_KSM without PAGE_MAPPING_ANON is currently never used.
   *
   * Please note that, confusingly, "page_mapping" refers to the inode
   * address_space which maps the page from disk; whereas "page_mapped"
   * refers to user virtual address space into which the page is mapped.
   */
  #define PAGE_MAPPING_ANON     1
+ #define PAGE_MAPPING_KSM      2
+ #define PAGE_MAPPING_FLAGS    (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM)
  
  extern struct address_space swapper_space;
  static inline struct address_space *page_mapping(struct page *page)
        struct address_space *mapping = page->mapping;
  
        VM_BUG_ON(PageSlab(page));
- #ifdef CONFIG_SWAP
        if (unlikely(PageSwapCache(page)))
                mapping = &swapper_space;
-       else
- #endif
-       if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
+       else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
                mapping = NULL;
        return mapping;
  }
  
+ /* Neutral page->mapping pointer to address_space or anon_vma or other */
+ static inline void *page_rmapping(struct page *page)
+ {
+       return (void *)((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
+ }
  static inline int PageAnon(struct page *page)
  {
        return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0;
@@@ -760,6 -770,7 +772,7 @@@ unsigned long unmap_vmas(struct mmu_gat
   * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry
   * @pte_entry: if set, called for each non-empty PTE (4th-level) entry
   * @pte_hole: if set, called for each hole at all levels
+  * @hugetlb_entry: if set, called for each hugetlb entry
   *
   * (see walk_page_range for more details)
   */
@@@ -769,6 -780,8 +782,8 @@@ struct mm_walk 
        int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *);
        int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *);
        int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *);
+       int (*hugetlb_entry)(pte_t *, unsigned long, unsigned long,
+                            struct mm_walk *);
        struct mm_struct *mm;
        void *private;
  };
@@@ -1024,6 -1037,9 +1039,9 @@@ extern void add_active_range(unsigned i
  extern void remove_active_range(unsigned int nid, unsigned long start_pfn,
                                        unsigned long end_pfn);
  extern void remove_all_active_ranges(void);
+ void sort_node_map(void);
+ unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
+                                               unsigned long end_pfn);
  extern unsigned long absent_pages_in_range(unsigned long start_pfn,
                                                unsigned long end_pfn);
  extern void get_pfn_range_for_nid(unsigned int nid,
@@@ -1073,6 -1089,7 +1091,7 @@@ extern void zone_pcp_update(struct zon
  
  /* nommu.c */
  extern atomic_long_t mmap_pages_allocated;
+ extern int nommu_shrink_inode_mappings(struct inode *, size_t, size_t);
  
  /* prio_tree.c */
  void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
@@@ -1318,11 -1335,17 +1337,17 @@@ extern int account_locked_memory(struc
                                 size_t size);
  extern void refund_locked_memory(struct mm_struct *mm, size_t size);
  
+ enum mf_flags {
+       MF_COUNT_INCREASED = 1 << 0,
+ };
  extern void memory_failure(unsigned long pfn, int trapno);
- extern int __memory_failure(unsigned long pfn, int trapno, int ref);
+ extern int __memory_failure(unsigned long pfn, int trapno, int flags);
+ extern int unpoison_memory(unsigned long pfn);
  extern int sysctl_memory_failure_early_kill;
  extern int sysctl_memory_failure_recovery;
+ extern void shake_page(struct page *p, int access);
  extern atomic_long_t mce_bad_pages;
+ extern int soft_offline_page(struct page *page, int flags);
  
  #endif /* __KERNEL__ */
  #endif /* _LINUX_MM_H */
diff --combined kernel/resource.c
index e68cd7477c4001b55d912e39d206be54a70d4f6e,af96c1e4b54b11b27fe445b834e3106b5b76b472..03c897f7935e100276e41ed83e1e3af3f549bbd9
@@@ -297,19 -297,6 +297,19 @@@ int walk_system_ram_range(unsigned lon
  
  #endif
  
 +static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
 +{
 +      return 1;
 +}
 +/*
 + * This generic page_is_ram() returns true if specified address is
 + * registered as "System RAM" in iomem_resource list.
 + */
 +int __weak page_is_ram(unsigned long pfn)
 +{
 +      return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
 +}
 +
  /*
   * Find empty slot in the resource tree given range and alignment.
   */
@@@ -321,35 -308,37 +321,37 @@@ static int find_resource(struct resourc
                         void *alignf_data)
  {
        struct resource *this = root->child;
+       struct resource tmp = *new;
  
-       new->start = root->start;
+       tmp.start = root->start;
        /*
         * Skip past an allocated resource that starts at 0, since the assignment
-        * of this->start - 1 to new->end below would cause an underflow.
+        * of this->start - 1 to tmp->end below would cause an underflow.
         */
        if (this && this->start == 0) {
-               new->start = this->end + 1;
+               tmp.start = this->end + 1;
                this = this->sibling;
        }
        for(;;) {
                if (this)
-                       new->end = this->start - 1;
+                       tmp.end = this->start - 1;
                else
-                       new->end = root->end;
-               if (new->start < min)
-                       new->start = min;
-               if (new->end > max)
-                       new->end = max;
-               new->start = ALIGN(new->start, align);
+                       tmp.end = root->end;
+               if (tmp.start < min)
+                       tmp.start = min;
+               if (tmp.end > max)
+                       tmp.end = max;
+               tmp.start = ALIGN(tmp.start, align);
                if (alignf)
-                       alignf(alignf_data, new, size, align);
-               if (new->start < new->end && new->end - new->start >= size - 1) {
-                       new->end = new->start + size - 1;
+                       alignf(alignf_data, &tmp, size, align);
+               if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) {
+                       new->start = tmp.start;
+                       new->end = tmp.start + size - 1;
                        return 0;
                }
                if (!this)
                        break;
-               new->start = this->end + 1;
+               tmp.start = this->end + 1;
                this = this->sibling;
        }
        return -EBUSY;