diff options
author | Roland Dreier <rolandd@cisco.com> | 2005-10-28 20:46:18 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-29 00:25:49 -0400 |
commit | 8b150478aeb1a8edb9015c2f7ac4da637ff65c45 (patch) | |
tree | 621b038b9c041fe82b708c6c5cbee655be2a519a | |
parent | d49b340124a34fcb8bceda472558ccef7232c16f (diff) |
[PATCH] ppc: make phys_mem_access_prot() work with pfns instead of addresses
Change the phys_mem_access_prot() function to take a pfn instead of an
address. This allows mmap64() to work on /dev/mem for addresses above 4G
on 32-bit architectures. We start with a pfn in mmap_mem(), so there's no
need to convert to an address; in fact, it's actively bad, since the
conversion can overflow when the address is above 4G.
Similarly fix the ppc32 page_is_ram() function to avoid a conversion to an
address by directly comparing to max_pfn. Working with max_pfn instead of
high_memory fixes page_is_ram() to give the right answer for highmem pages.
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/mm/mem.c | 6 | ||||
-rw-r--r-- | arch/ppc/kernel/pci.c | 5 | ||||
-rw-r--r-- | arch/ppc/mm/init.c | 10 | ||||
-rw-r--r-- | arch/ppc64/kernel/pci.c | 5 | ||||
-rw-r--r-- | drivers/char/mem.c | 4 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 2 | ||||
-rw-r--r-- | include/asm-powerpc/machdep.h | 2 | ||||
-rw-r--r-- | include/asm-ppc/machdep.h | 2 | ||||
-rw-r--r-- | include/asm-ppc/pci.h | 2 | ||||
-rw-r--r-- | include/asm-ppc/pgtable.h | 2 | ||||
-rw-r--r-- | include/asm-ppc64/pci.h | 2 | ||||
-rw-r--r-- | include/asm-ppc64/pgtable.h | 2 |
12 files changed, 21 insertions, 23 deletions
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 695db6a588ce..3ca331728d21 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -88,13 +88,13 @@ int page_is_ram(unsigned long pfn) | |||
88 | } | 88 | } |
89 | EXPORT_SYMBOL(page_is_ram); | 89 | EXPORT_SYMBOL(page_is_ram); |
90 | 90 | ||
91 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | 91 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
92 | unsigned long size, pgprot_t vma_prot) | 92 | unsigned long size, pgprot_t vma_prot) |
93 | { | 93 | { |
94 | if (ppc_md.phys_mem_access_prot) | 94 | if (ppc_md.phys_mem_access_prot) |
95 | return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot); | 95 | return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot); |
96 | 96 | ||
97 | if (!page_is_ram(addr >> PAGE_SHIFT)) | 97 | if (!page_is_ram(pfn)) |
98 | vma_prot = __pgprot(pgprot_val(vma_prot) | 98 | vma_prot = __pgprot(pgprot_val(vma_prot) |
99 | | _PAGE_GUARDED | _PAGE_NO_CACHE); | 99 | | _PAGE_GUARDED | _PAGE_NO_CACHE); |
100 | return vma_prot; | 100 | return vma_prot; |
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index ad4ef2aaa6ab..e8f4e576750a 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c | |||
@@ -1594,16 +1594,17 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | |||
1594 | * above routine | 1594 | * above routine |
1595 | */ | 1595 | */ |
1596 | pgprot_t pci_phys_mem_access_prot(struct file *file, | 1596 | pgprot_t pci_phys_mem_access_prot(struct file *file, |
1597 | unsigned long offset, | 1597 | unsigned long pfn, |
1598 | unsigned long size, | 1598 | unsigned long size, |
1599 | pgprot_t protection) | 1599 | pgprot_t protection) |
1600 | { | 1600 | { |
1601 | struct pci_dev *pdev = NULL; | 1601 | struct pci_dev *pdev = NULL; |
1602 | struct resource *found = NULL; | 1602 | struct resource *found = NULL; |
1603 | unsigned long prot = pgprot_val(protection); | 1603 | unsigned long prot = pgprot_val(protection); |
1604 | unsigned long offset = pfn << PAGE_SHIFT; | ||
1604 | int i; | 1605 | int i; |
1605 | 1606 | ||
1606 | if (page_is_ram(offset >> PAGE_SHIFT)) | 1607 | if (page_is_ram(pfn)) |
1607 | return prot; | 1608 | return prot; |
1608 | 1609 | ||
1609 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | 1610 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; |
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index db94efd25369..99b48abd3296 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c | |||
@@ -637,18 +637,16 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | |||
637 | */ | 637 | */ |
638 | int page_is_ram(unsigned long pfn) | 638 | int page_is_ram(unsigned long pfn) |
639 | { | 639 | { |
640 | unsigned long paddr = (pfn << PAGE_SHIFT); | 640 | return pfn < max_pfn; |
641 | |||
642 | return paddr < __pa(high_memory); | ||
643 | } | 641 | } |
644 | 642 | ||
645 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | 643 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
646 | unsigned long size, pgprot_t vma_prot) | 644 | unsigned long size, pgprot_t vma_prot) |
647 | { | 645 | { |
648 | if (ppc_md.phys_mem_access_prot) | 646 | if (ppc_md.phys_mem_access_prot) |
649 | return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot); | 647 | return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot); |
650 | 648 | ||
651 | if (!page_is_ram(addr >> PAGE_SHIFT)) | 649 | if (!page_is_ram(pfn)) |
652 | vma_prot = __pgprot(pgprot_val(vma_prot) | 650 | vma_prot = __pgprot(pgprot_val(vma_prot) |
653 | | _PAGE_GUARDED | _PAGE_NO_CACHE); | 651 | | _PAGE_GUARDED | _PAGE_NO_CACHE); |
654 | return vma_prot; | 652 | return vma_prot; |
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index b2fb6746f00b..3d2106b022a1 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -726,16 +726,17 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | |||
726 | * above routine | 726 | * above routine |
727 | */ | 727 | */ |
728 | pgprot_t pci_phys_mem_access_prot(struct file *file, | 728 | pgprot_t pci_phys_mem_access_prot(struct file *file, |
729 | unsigned long offset, | 729 | unsigned long pfn, |
730 | unsigned long size, | 730 | unsigned long size, |
731 | pgprot_t protection) | 731 | pgprot_t protection) |
732 | { | 732 | { |
733 | struct pci_dev *pdev = NULL; | 733 | struct pci_dev *pdev = NULL; |
734 | struct resource *found = NULL; | 734 | struct resource *found = NULL; |
735 | unsigned long prot = pgprot_val(protection); | 735 | unsigned long prot = pgprot_val(protection); |
736 | unsigned long offset = pfn << PAGE_SHIFT; | ||
736 | int i; | 737 | int i; |
737 | 738 | ||
738 | if (page_is_ram(offset >> PAGE_SHIFT)) | 739 | if (page_is_ram(pfn)) |
739 | return __pgprot(prot); | 740 | return __pgprot(prot); |
740 | 741 | ||
741 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | 742 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index f182752fe918..9df928d4f68d 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -231,9 +231,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
231 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) | 231 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) |
232 | { | 232 | { |
233 | #if defined(__HAVE_PHYS_MEM_ACCESS_PROT) | 233 | #if defined(__HAVE_PHYS_MEM_ACCESS_PROT) |
234 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 234 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, |
235 | |||
236 | vma->vm_page_prot = phys_mem_access_prot(file, offset, | ||
237 | vma->vm_end - vma->vm_start, | 235 | vma->vm_end - vma->vm_start, |
238 | vma->vm_page_prot); | 236 | vma->vm_page_prot); |
239 | #elif defined(pgprot_noncached) | 237 | #elif defined(pgprot_noncached) |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 70be7009f8af..ca02aa2bfcec 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -918,7 +918,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) | |||
918 | } | 918 | } |
919 | #endif | 919 | #endif |
920 | #elif defined(__powerpc__) | 920 | #elif defined(__powerpc__) |
921 | vma->vm_page_prot = phys_mem_access_prot(file, off, | 921 | vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT, |
922 | vma->vm_end - vma->vm_start, | 922 | vma->vm_end - vma->vm_start, |
923 | vma->vm_page_prot); | 923 | vma->vm_page_prot); |
924 | #elif defined(__alpha__) | 924 | #elif defined(__alpha__) |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 706508b1b04b..451b345cfc78 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
@@ -144,7 +144,7 @@ struct machdep_calls { | |||
144 | 144 | ||
145 | /* Get access protection for /dev/mem */ | 145 | /* Get access protection for /dev/mem */ |
146 | pgprot_t (*phys_mem_access_prot)(struct file *file, | 146 | pgprot_t (*phys_mem_access_prot)(struct file *file, |
147 | unsigned long offset, | 147 | unsigned long pfn, |
148 | unsigned long size, | 148 | unsigned long size, |
149 | pgprot_t vma_prot); | 149 | pgprot_t vma_prot); |
150 | 150 | ||
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h index 6c6d23abbe91..f01255bd1dc3 100644 --- a/include/asm-ppc/machdep.h +++ b/include/asm-ppc/machdep.h | |||
@@ -98,7 +98,7 @@ struct machdep_calls { | |||
98 | 98 | ||
99 | /* Get access protection for /dev/mem */ | 99 | /* Get access protection for /dev/mem */ |
100 | pgprot_t (*phys_mem_access_prot)(struct file *file, | 100 | pgprot_t (*phys_mem_access_prot)(struct file *file, |
101 | unsigned long offset, | 101 | unsigned long pfn, |
102 | unsigned long size, | 102 | unsigned long size, |
103 | pgprot_t vma_prot); | 103 | pgprot_t vma_prot); |
104 | 104 | ||
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h index 643740dd727b..61434edbad7b 100644 --- a/include/asm-ppc/pci.h +++ b/include/asm-ppc/pci.h | |||
@@ -126,7 +126,7 @@ extern void pcibios_add_platform_entries(struct pci_dev *dev); | |||
126 | 126 | ||
127 | struct file; | 127 | struct file; |
128 | extern pgprot_t pci_phys_mem_access_prot(struct file *file, | 128 | extern pgprot_t pci_phys_mem_access_prot(struct file *file, |
129 | unsigned long offset, | 129 | unsigned long pfn, |
130 | unsigned long size, | 130 | unsigned long size, |
131 | pgprot_t prot); | 131 | pgprot_t prot); |
132 | 132 | ||
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index eee601bb9ada..b28a713ba862 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h | |||
@@ -705,7 +705,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty) | |||
705 | #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 705 | #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED)) |
706 | 706 | ||
707 | struct file; | 707 | struct file; |
708 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | 708 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
709 | unsigned long size, pgprot_t vma_prot); | 709 | unsigned long size, pgprot_t vma_prot); |
710 | #define __HAVE_PHYS_MEM_ACCESS_PROT | 710 | #define __HAVE_PHYS_MEM_ACCESS_PROT |
711 | 711 | ||
diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h index a88bbfc26967..342e2d755550 100644 --- a/include/asm-ppc64/pci.h +++ b/include/asm-ppc64/pci.h | |||
@@ -168,7 +168,7 @@ extern void pcibios_add_platform_entries(struct pci_dev *dev); | |||
168 | 168 | ||
169 | struct file; | 169 | struct file; |
170 | extern pgprot_t pci_phys_mem_access_prot(struct file *file, | 170 | extern pgprot_t pci_phys_mem_access_prot(struct file *file, |
171 | unsigned long offset, | 171 | unsigned long pfn, |
172 | unsigned long size, | 172 | unsigned long size, |
173 | pgprot_t prot); | 173 | pgprot_t prot); |
174 | 174 | ||
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index c83679c9d2b0..8cf5991540e3 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h | |||
@@ -471,7 +471,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty) | |||
471 | #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 471 | #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED)) |
472 | 472 | ||
473 | struct file; | 473 | struct file; |
474 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | 474 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
475 | unsigned long size, pgprot_t vma_prot); | 475 | unsigned long size, pgprot_t vma_prot); |
476 | #define __HAVE_PHYS_MEM_ACCESS_PROT | 476 | #define __HAVE_PHYS_MEM_ACCESS_PROT |
477 | 477 | ||