[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>hifive-unleashed-5.1
parent
3ed3bce846
commit
136939a2b5
|
@ -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)
|
||||||
* 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)
|
||||||
* 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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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,
|
||||||
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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue