diff options
| author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2006-03-26 04:37:05 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-26 11:56:54 -0500 |
| commit | 136939a2b5aa4302281215745ccd567e1df2e8d4 (patch) | |
| tree | 384841deada5b0ceb44c255e0474866bbc8d3354 | |
| parent | 3ed3bce846abc7ef460104b461cac793e41afe5e (diff) | |
[PATCH] EFI, /dev/mem: simplify efi_mem_attribute_range()
Pass the size, not a pointer to the size, to efi_mem_attribute_range().
This function validates memory regions for the /dev/mem read/write/mmap paths.
The pointer allows arches to reduce the size of the range, but I think that's
unnecessary complexity. Simplifying it will let me use
efi_mem_attribute_range() to improve the ia64 ioremap() implementation.
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Matt Domsch <Matt_Domsch@dell.com>
Cc: "Tolentino, Matthew E" <matthew.e.tolentino@intel.com>
Cc: "Brown, Len" <len.brown@intel.com>
Cc: Andi Kleen <ak@muc.de>
Acked-by: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/ia64/kernel/efi.c | 41 | ||||
| -rw-r--r-- | drivers/char/mem.c | 18 | ||||
| -rw-r--r-- | include/asm-ia64/io.h | 4 | ||||
| -rw-r--r-- | include/linux/efi.h | 2 |
4 files changed, 30 insertions, 35 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 9990320b6f9a..2993748c13df 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
| @@ -677,27 +677,34 @@ EXPORT_SYMBOL(efi_mem_attributes); | |||
| 677 | /* | 677 | /* |
| 678 | * Determines whether the memory at phys_addr supports the desired | 678 | * Determines whether the memory at phys_addr supports the desired |
| 679 | * attribute (WB, UC, etc). If this returns 1, the caller can safely | 679 | * attribute (WB, UC, etc). If this returns 1, the caller can safely |
| 680 | * access *size bytes at phys_addr with the specified attribute. | 680 | * access size bytes at phys_addr with the specified attribute. |
| 681 | */ | 681 | */ |
| 682 | static int | 682 | int |
| 683 | efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) | 683 | efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr) |
| 684 | { | 684 | { |
| 685 | unsigned long end = phys_addr + size; | ||
| 685 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); | 686 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); |
| 686 | unsigned long md_end; | ||
| 687 | 687 | ||
| 688 | if (!md || (md->attribute & attr) != attr) | 688 | /* |
| 689 | * Some firmware doesn't report MMIO regions in the EFI memory | ||
| 690 | * map. The Intel BigSur (a.k.a. HP i2000) has this problem. | ||
| 691 | * On those platforms, we have to assume UC is valid everywhere. | ||
| 692 | */ | ||
| 693 | if (!md || (md->attribute & attr) != attr) { | ||
| 694 | if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio()) | ||
| 695 | return 1; | ||
| 689 | return 0; | 696 | return 0; |
| 697 | } | ||
| 690 | 698 | ||
| 691 | do { | 699 | do { |
| 692 | md_end = efi_md_end(md); | 700 | unsigned long md_end = efi_md_end(md); |
| 693 | if (phys_addr + *size <= md_end) | 701 | |
| 702 | if (end <= md_end) | ||
| 694 | return 1; | 703 | return 1; |
| 695 | 704 | ||
| 696 | md = efi_memory_descriptor(md_end); | 705 | md = efi_memory_descriptor(md_end); |
| 697 | if (!md || (md->attribute & attr) != attr) { | 706 | if (!md || (md->attribute & attr) != attr) |
| 698 | *size = md_end - phys_addr; | 707 | return 0; |
| 699 | return 1; | ||
| 700 | } | ||
| 701 | } while (md); | 708 | } while (md); |
| 702 | return 0; | 709 | return 0; |
| 703 | } | 710 | } |
| @@ -708,7 +715,7 @@ efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) | |||
| 708 | * control access size. | 715 | * control access size. |
| 709 | */ | 716 | */ |
| 710 | int | 717 | int |
| 711 | valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) | 718 | valid_phys_addr_range (unsigned long phys_addr, unsigned long size) |
| 712 | { | 719 | { |
| 713 | return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); | 720 | return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); |
| 714 | } | 721 | } |
| @@ -723,7 +730,7 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) | |||
| 723 | * because that doesn't appear in the boot-time EFI memory map. | 730 | * because that doesn't appear in the boot-time EFI memory map. |
| 724 | */ | 731 | */ |
| 725 | int | 732 | int |
| 726 | valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) | 733 | valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size) |
| 727 | { | 734 | { |
| 728 | if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) | 735 | if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) |
| 729 | return 1; | 736 | return 1; |
| @@ -731,14 +738,6 @@ valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) | |||
| 731 | if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) | 738 | if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) |
| 732 | return 1; | 739 | return 1; |
| 733 | 740 | ||
| 734 | /* | ||
| 735 | * Some firmware doesn't report MMIO regions in the EFI memory map. | ||
| 736 | * The Intel BigSur (a.k.a. HP i2000) has this problem. In this | ||
| 737 | * case, we can't use the EFI memory map to validate mmap requests. | ||
| 738 | */ | ||
| 739 | if (!efi_memmap_has_mmio()) | ||
| 740 | return 1; | ||
| 741 | |||
| 742 | return 0; | 741 | return 0; |
| 743 | } | 742 | } |
| 744 | 743 | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 26d0116b48d4..5245ba1649ed 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -88,21 +88,15 @@ static inline int uncached_access(struct file *file, unsigned long addr) | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE | 90 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE |
| 91 | static inline int valid_phys_addr_range(unsigned long addr, size_t *count) | 91 | static inline int valid_phys_addr_range(unsigned long addr, size_t count) |
| 92 | { | 92 | { |
| 93 | unsigned long end_mem; | 93 | if (addr + count > __pa(high_memory)) |
| 94 | |||
| 95 | end_mem = __pa(high_memory); | ||
| 96 | if (addr >= end_mem) | ||
| 97 | return 0; | 94 | return 0; |
| 98 | 95 | ||
| 99 | if (*count > end_mem - addr) | ||
| 100 | *count = end_mem - addr; | ||
| 101 | |||
| 102 | return 1; | 96 | return 1; |
| 103 | } | 97 | } |
| 104 | 98 | ||
| 105 | static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) | 99 | static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size) |
| 106 | { | 100 | { |
| 107 | return 1; | 101 | return 1; |
| 108 | } | 102 | } |
| @@ -119,7 +113,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
| 119 | ssize_t read, sz; | 113 | ssize_t read, sz; |
| 120 | char *ptr; | 114 | char *ptr; |
| 121 | 115 | ||
| 122 | if (!valid_phys_addr_range(p, &count)) | 116 | if (!valid_phys_addr_range(p, count)) |
| 123 | return -EFAULT; | 117 | return -EFAULT; |
| 124 | read = 0; | 118 | read = 0; |
| 125 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 119 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
| @@ -177,7 +171,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
| 177 | unsigned long copied; | 171 | unsigned long copied; |
| 178 | void *ptr; | 172 | void *ptr; |
| 179 | 173 | ||
| 180 | if (!valid_phys_addr_range(p, &count)) | 174 | if (!valid_phys_addr_range(p, count)) |
| 181 | return -EFAULT; | 175 | return -EFAULT; |
| 182 | 176 | ||
| 183 | written = 0; | 177 | written = 0; |
| @@ -249,7 +243,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) | |||
| 249 | { | 243 | { |
| 250 | size_t size = vma->vm_end - vma->vm_start; | 244 | size_t size = vma->vm_end - vma->vm_start; |
| 251 | 245 | ||
| 252 | if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size)) | 246 | if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size)) |
| 253 | return -EINVAL; | 247 | return -EINVAL; |
| 254 | 248 | ||
| 255 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, | 249 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, |
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index 0d9bcc36f2a9..acba019b08e9 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h | |||
| @@ -88,8 +88,8 @@ phys_to_virt (unsigned long address) | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE | 90 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE |
| 91 | extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */ | 91 | extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */ |
| 92 | extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count); | 92 | extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count); |
| 93 | 93 | ||
| 94 | /* | 94 | /* |
| 95 | * The following two macros are deprecated and scheduled for removal. | 95 | * The following two macros are deprecated and scheduled for removal. |
diff --git a/include/linux/efi.h b/include/linux/efi.h index c7c5dd316182..d15725470aa4 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
| @@ -292,6 +292,8 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos | |||
| 292 | extern u64 efi_get_iobase (void); | 292 | extern u64 efi_get_iobase (void); |
| 293 | extern u32 efi_mem_type (unsigned long phys_addr); | 293 | extern u32 efi_mem_type (unsigned long phys_addr); |
| 294 | extern u64 efi_mem_attributes (unsigned long phys_addr); | 294 | extern u64 efi_mem_attributes (unsigned long phys_addr); |
| 295 | extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, | ||
| 296 | u64 attr); | ||
| 295 | extern int __init efi_uart_console_only (void); | 297 | extern int __init efi_uart_console_only (void); |
| 296 | extern void efi_initialize_iomem_resources(struct resource *code_resource, | 298 | extern void efi_initialize_iomem_resources(struct resource *code_resource, |
| 297 | struct resource *data_resource); | 299 | struct resource *data_resource); |
