]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Apr 2008 19:48:08 +0000 (12:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Apr 2008 19:48:08 +0000 (12:48 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-pat:
  generic: add ioremap_wc() interface wrapper
  /dev/mem: make promisc the default
  pat: cleanups
  x86: PAT use reserve free memtype in mmap of /dev/mem
  x86: PAT phys_mem_access_prot_allowed for dev/mem mmap
  x86: PAT avoid aliasing in /dev/mem read/write
  devmem: add range_is_allowed() check to mmap of /dev/mem
  x86: introduce /dev/mem restrictions with a config option

1  2 
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
include/asm-x86/pgtable.h

diff --combined arch/x86/mm/init_32.c
index 08aa1878fad4c22440ffd5956f16be742b438705,39852d539018cf24c84f9835ec10244cee89499e..baf7c4f643c86ec7e8a7101b2f3306551269bba7
@@@ -71,7 -71,7 +71,7 @@@ static pmd_t * __init one_md_table_init
        if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
                pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
  
 -              paravirt_alloc_pd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
 +              paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
                set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
                pud = pud_offset(pgd, 0);
                BUG_ON(pmd_table != pmd_offset(pud, 0));
@@@ -100,7 -100,7 +100,7 @@@ static pte_t * __init one_page_table_in
                                (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
                }
  
 -              paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
 +              paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
                set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
                BUG_ON(page_table != pte_offset_kernel(pmd, 0));
        }
@@@ -227,6 -227,25 +227,25 @@@ static inline int page_kills_ppro(unsig
        return 0;
  }
  
+ /*
+  * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+  * is valid. The argument is a physical page number.
+  *
+  *
+  * On x86, access has to be given to the first megabyte of ram because that area
+  * contains bios code and data regions used by X and dosemu and similar apps.
+  * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+  * mmio resources as well as potential bios/acpi data regions.
+  */
+ int devmem_is_allowed(unsigned long pagenr)
+ {
+       if (pagenr <= 256)
+               return 1;
+       if (!page_is_ram(pagenr))
+               return 1;
+       return 0;
+ }
  #ifdef CONFIG_HIGHMEM
  pte_t *kmap_pte;
  pgprot_t kmap_prot;
@@@ -365,7 -384,7 +384,7 @@@ void __init native_pagetable_setup_star
  
                pte_clear(NULL, va, pte);
        }
 -      paravirt_alloc_pd(&init_mm, __pa(base) >> PAGE_SHIFT);
 +      paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT);
  }
  
  void __init native_pagetable_setup_done(pgd_t *base)
@@@ -457,7 -476,7 +476,7 @@@ void zap_low_mappings(void
         * Note that "pgd_clear()" doesn't do it for
         * us, because pgd_clear() is a no-op on i386.
         */
 -      for (i = 0; i < USER_PTRS_PER_PGD; i++) {
 +      for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
  #ifdef CONFIG_X86_PAE
                set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
  #else
diff --combined arch/x86/mm/init_64.c
index b798e7b92b1709819a5985f51d40782363da6c51,49c274ee2fba64ea9b48713b96f814fc0afa5d23..0cca626630377738a8af7d8f16a29dfdad5ac27e
@@@ -135,7 -135,7 +135,7 @@@ static __init void *spp_getpage(void
        return ptr;
  }
  
 -static __init void
 +static void
  set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
  {
        pgd_t *pgd;
        new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
  
        pte = pte_offset_kernel(pmd, vaddr);
 -      if (!pte_none(*pte) &&
 +      if (!pte_none(*pte) && pte_val(new_pte) &&
            pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
                pte_ERROR(*pte);
        set_pte(pte, new_pte);
@@@ -214,7 -214,8 +214,7 @@@ void __init cleanup_highmap(void
  }
  
  /* NOTE: this is meant to be run only at boot */
 -void __init
 -__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 +void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
  {
        unsigned long address = __fix_to_virt(idx);
  
@@@ -663,6 -664,26 +663,26 @@@ EXPORT_SYMBOL_GPL(memory_add_physaddr_t
  
  #endif /* CONFIG_MEMORY_HOTPLUG */
  
+ /*
+  * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+  * is valid. The argument is a physical page number.
+  *
+  *
+  * On x86, access has to be given to the first megabyte of ram because that area
+  * contains bios code and data regions used by X and dosemu and similar apps.
+  * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+  * mmio resources as well as potential bios/acpi data regions.
+  */
+ int devmem_is_allowed(unsigned long pagenr)
+ {
+       if (pagenr <= 256)
+               return 1;
+       if (!page_is_ram(pagenr))
+               return 1;
+       return 0;
+ }
  static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
                         kcore_modules, kcore_vsyscall;
  
diff --combined arch/x86/mm/ioremap.c
index 36a3f7ded6262c7063ee291e1aa55082a917771f,caac7d5699a75190b00131a1b50535ac2da78b3d..d176b23110cc875187be67d3c22f227ec38cbdeb
@@@ -336,6 -336,35 +336,35 @@@ void iounmap(volatile void __iomem *add
  }
  EXPORT_SYMBOL(iounmap);
  
+ /*
+  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+  * access
+  */
+ void *xlate_dev_mem_ptr(unsigned long phys)
+ {
+       void *addr;
+       unsigned long start = phys & PAGE_MASK;
+       /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
+       if (page_is_ram(start >> PAGE_SHIFT))
+               return __va(phys);
+       addr = (void *)ioremap(start, PAGE_SIZE);
+       if (addr)
+               addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+       return addr;
+ }
+ void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+ {
+       if (page_is_ram(phys >> PAGE_SHIFT))
+               return;
+       iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
+       return;
+ }
  #ifdef CONFIG_X86_32
  
  int __initdata early_ioremap_debug;
@@@ -407,7 -436,7 +436,7 @@@ void __init early_ioremap_clear(void
  
        pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
        pmd_clear(pmd);
 -      paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
 +      paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
        __flush_tlb_all();
  }
  
index b8a08bd7bd48db84f62e7653a32e0c5e14fb3254,1902f0aed6c13ae0ee73f18d66a82905f00ae6bb..a496d6335d3baa644f80bd0c9e293ce5b9fc480c
@@@ -1,6 -1,7 +1,6 @@@
  #ifndef _ASM_X86_PGTABLE_H
  #define _ASM_X86_PGTABLE_H
  
 -#define USER_PTRS_PER_PGD     ((TASK_SIZE-1)/PGDIR_SIZE+1)
  #define FIRST_USER_ADDRESS    0
  
  #define _PAGE_BIT_PRESENT     0       /* is present */
@@@ -288,6 -289,15 +288,15 @@@ static inline pte_t pte_modify(pte_t pt
  
  #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
  
+ #ifndef __ASSEMBLY__
+ #define __HAVE_PHYS_MEM_ACCESS_PROT
+ struct file;
+ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                               unsigned long size, pgprot_t vma_prot);
+ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+                               unsigned long size, pgprot_t *vma_prot);
+ #endif
  #ifdef CONFIG_PARAVIRT
  #include <asm/paravirt.h>
  #else  /* !CONFIG_PARAVIRT */
  # include "pgtable_64.h"
  #endif
  
 +#define KERNEL_PGD_BOUNDARY   pgd_index(PAGE_OFFSET)
 +#define KERNEL_PGD_PTRS               (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
 +
  #ifndef __ASSEMBLY__
  
  enum {
@@@ -391,17 -398,37 +400,17 @@@ static inline void native_set_pte_at(st
   * bit at the same time.
   */
  #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 -#define ptep_set_access_flags(vma, address, ptep, entry, dirty)               \
 -({                                                                    \
 -      int __changed = !pte_same(*(ptep), entry);                      \
 -      if (__changed && dirty) {                                       \
 -              *ptep = entry;                                          \
 -              pte_update_defer((vma)->vm_mm, (address), (ptep));      \
 -              flush_tlb_page(vma, address);                           \
 -      }                                                               \
 -      __changed;                                                      \
 -})
 +extern int ptep_set_access_flags(struct vm_area_struct *vma,
 +                               unsigned long address, pte_t *ptep,
 +                               pte_t entry, int dirty);
  
  #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 -#define ptep_test_and_clear_young(vma, addr, ptep) ({                 \
 -      int __ret = 0;                                                  \
 -      if (pte_young(*(ptep)))                                         \
 -              __ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,          \
 -                                         &(ptep)->pte);               \
 -      if (__ret)                                                      \
 -              pte_update((vma)->vm_mm, addr, ptep);                   \
 -      __ret;                                                          \
 -})
 +extern int ptep_test_and_clear_young(struct vm_area_struct *vma,
 +                                   unsigned long addr, pte_t *ptep);
  
  #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
 -#define ptep_clear_flush_young(vma, address, ptep)                    \
 -({                                                                    \
 -      int __young;                                                    \
 -      __young = ptep_test_and_clear_young((vma), (address), (ptep));  \
 -      if (__young)                                                    \
 -              flush_tlb_page(vma, address);                           \
 -      __young;                                                        \
 -})
 +extern int ptep_clear_flush_young(struct vm_area_struct *vma,
 +                                unsigned long address, pte_t *ptep);
  
  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
  static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
@@@ -438,22 -465,6 +447,22 @@@ static inline void ptep_set_wrprotect(s
        pte_update(mm, addr, ptep);
  }
  
 +/*
 + * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
 + *
 + *  dst - pointer to pgd range anwhere on a pgd page
 + *  src - ""
 + *  count - the number of pgds to copy.
 + *
 + * dst and src can be on the same page, but the range must not overlap,
 + * and must not cross a page boundary.
 + */
 +static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
 +{
 +       memcpy(dst, src, count * sizeof(pgd_t));
 +}
 +
 +
  #include <asm-generic/pgtable.h>
  #endif        /* __ASSEMBLY__ */