Commit 136939a2 authored by Bjorn Helgaas's avatar Bjorn Helgaas Committed by Linus Torvalds

[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: default avatarBjorn 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: default avatar"Luck, Tony" <tony.luck@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3ed3bce8
...@@ -677,27 +677,34 @@ EXPORT_SYMBOL(efi_mem_attributes); ...@@ -677,27 +677,34 @@ EXPORT_SYMBOL(efi_mem_attributes);
/* /*
* Determines whether the memory at phys_addr supports the desired * Determines whether the memory at phys_addr supports the desired
* attribute (WB, UC, etc). If this returns 1, the caller can safely * attribute (WB, UC, etc). If this returns 1, the caller can safely
* access *size bytes at phys_addr with the specified attribute. * access size bytes at phys_addr with the specified attribute.
*/ */
static int int
efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr)
{ {
unsigned long end = phys_addr + size;
efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
unsigned long md_end;
if (!md || (md->attribute & attr) != attr) /*
* Some firmware doesn't report MMIO regions in the EFI memory
* map. The Intel BigSur (a.k.a. HP i2000) has this problem.
* On those platforms, we have to assume UC is valid everywhere.
*/
if (!md || (md->attribute & attr) != attr) {
if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio())
return 1;
return 0; return 0;
}
do { do {
md_end = efi_md_end(md); unsigned long md_end = efi_md_end(md);
if (phys_addr + *size <= md_end)
if (end <= md_end)
return 1; return 1;
md = efi_memory_descriptor(md_end); md = efi_memory_descriptor(md_end);
if (!md || (md->attribute & attr) != attr) { if (!md || (md->attribute & attr) != attr)
*size = md_end - phys_addr; return 0;
return 1;
}
} while (md); } while (md);
return 0; return 0;
} }
...@@ -708,7 +715,7 @@ efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) ...@@ -708,7 +715,7 @@ efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr)
* control access size. * control access size.
*/ */
int int
valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
{ {
return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB);
} }
...@@ -723,7 +730,7 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) ...@@ -723,7 +730,7 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
* because that doesn't appear in the boot-time EFI memory map. * because that doesn't appear in the boot-time EFI memory map.
*/ */
int int
valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size)
{ {
if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB))
return 1; return 1;
...@@ -731,14 +738,6 @@ valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) ...@@ -731,14 +738,6 @@ valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size)
if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC))
return 1; return 1;
/*
* Some firmware doesn't report MMIO regions in the EFI memory map.
* The Intel BigSur (a.k.a. HP i2000) has this problem. In this
* case, we can't use the EFI memory map to validate mmap requests.
*/
if (!efi_memmap_has_mmio())
return 1;
return 0; return 0;
} }
......
...@@ -88,21 +88,15 @@ static inline int uncached_access(struct file *file, unsigned long addr) ...@@ -88,21 +88,15 @@ static inline int uncached_access(struct file *file, unsigned long addr)
} }
#ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
static inline int valid_phys_addr_range(unsigned long addr, size_t *count) static inline int valid_phys_addr_range(unsigned long addr, size_t count)
{ {
unsigned long end_mem; if (addr + count > __pa(high_memory))
end_mem = __pa(high_memory);
if (addr >= end_mem)
return 0; return 0;
if (*count > end_mem - addr)
*count = end_mem - addr;
return 1; return 1;
} }
static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size)
{ {
return 1; return 1;
} }
...@@ -119,7 +113,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, ...@@ -119,7 +113,7 @@ static ssize_t read_mem(struct file * file, char __user * buf,
ssize_t read, sz; ssize_t read, sz;
char *ptr; char *ptr;
if (!valid_phys_addr_range(p, &count)) if (!valid_phys_addr_range(p, count))
return -EFAULT; return -EFAULT;
read = 0; read = 0;
#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
...@@ -177,7 +171,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, ...@@ -177,7 +171,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
unsigned long copied; unsigned long copied;
void *ptr; void *ptr;
if (!valid_phys_addr_range(p, &count)) if (!valid_phys_addr_range(p, count))
return -EFAULT; return -EFAULT;
written = 0; written = 0;
...@@ -249,7 +243,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) ...@@ -249,7 +243,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{ {
size_t size = vma->vm_end - vma->vm_start; size_t size = vma->vm_end - vma->vm_start;
if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size)) if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size))
return -EINVAL; return -EINVAL;
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
......
...@@ -88,8 +88,8 @@ phys_to_virt (unsigned long address) ...@@ -88,8 +88,8 @@ phys_to_virt (unsigned long address)
} }
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */ extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count); extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count);
/* /*
* The following two macros are deprecated and scheduled for removal. * The following two macros are deprecated and scheduled for removal.
......
...@@ -292,6 +292,8 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos ...@@ -292,6 +292,8 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos
extern u64 efi_get_iobase (void); extern u64 efi_get_iobase (void);
extern u32 efi_mem_type (unsigned long phys_addr); extern u32 efi_mem_type (unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr);
extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
u64 attr);
extern int __init efi_uart_console_only (void); extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource, extern void efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource); struct resource *data_resource);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment