aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/kernel/efi.c41
-rw-r--r--drivers/char/mem.c18
-rw-r--r--include/asm-ia64/io.h4
-rw-r--r--include/linux/efi.h2
4 files changed, 30 insertions, 35 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 9990320b6f9..2993748c13d 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 */
682static int 682int
683efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) 683efi_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 */
710int 717int
711valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) 718valid_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 */
725int 732int
726valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) 733valid_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 26d0116b48d..5245ba1649e 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
91static inline int valid_phys_addr_range(unsigned long addr, size_t *count) 91static 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
105static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) 99static 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 0d9bcc36f2a..acba019b08e 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
91extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */ 91extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
92extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count); 92extern 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 c7c5dd31618..d15725470aa 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
292extern u64 efi_get_iobase (void); 292extern u64 efi_get_iobase (void);
293extern u32 efi_mem_type (unsigned long phys_addr); 293extern u32 efi_mem_type (unsigned long phys_addr);
294extern u64 efi_mem_attributes (unsigned long phys_addr); 294extern u64 efi_mem_attributes (unsigned long phys_addr);
295extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
296 u64 attr);
295extern int __init efi_uart_console_only (void); 297extern int __init efi_uart_console_only (void);
296extern void efi_initialize_iomem_resources(struct resource *code_resource, 298extern void efi_initialize_iomem_resources(struct resource *code_resource,
297 struct resource *data_resource); 299 struct resource *data_resource);