diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/Makefile | 4 | ||||
-rw-r--r-- | arch/ia64/ia32/sys_ia32.c | 16 | ||||
-rw-r--r-- | arch/ia64/kernel/efi.c | 160 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/ia64_ksyms.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/ptrace.c | 9 | ||||
-rw-r--r-- | arch/ia64/oprofile/backtrace.c | 2 |
8 files changed, 121 insertions, 75 deletions
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 67932ad5308..57b047c27e4 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -37,10 +37,6 @@ $(error Sorry, you need a newer version of the assember, one that is built from ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz) endif -ifneq ($(shell if [ $(GCC_VERSION) -lt 0300 ] ; then echo "bad"; fi ;),) -$(error Sorry, your compiler is too old. GCC v2.96 is known to generate bad code.) -endif - ifeq ($(GCC_VERSION),0304) cflags-$(CONFIG_ITANIUM) += -mtune=merced cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index dc282710421..9f8e8d55887 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -1761,21 +1761,15 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data) lock_kernel(); if (request == PTRACE_TRACEME) { - ret = sys_ptrace(request, pid, addr, data); + ret = ptrace_traceme(); goto out; } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); goto out; - ret = -EPERM; - if (pid == 1) /* no messing around with init! */ - goto out_tsk; + } if (request == PTRACE_ATTACH) { ret = sys_ptrace(request, pid, addr, data); diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index a3aa45cbcfa..c485a3b32ba 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -247,6 +247,32 @@ typedef struct kern_memdesc { static kern_memdesc_t *kern_memmap; +#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) + +static inline u64 +kmd_end(kern_memdesc_t *kmd) +{ + return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); +} + +static inline u64 +efi_md_end(efi_memory_desc_t *md) +{ + return (md->phys_addr + efi_md_size(md)); +} + +static inline int +efi_wb(efi_memory_desc_t *md) +{ + return (md->attribute & EFI_MEMORY_WB); +} + +static inline int +efi_uc(efi_memory_desc_t *md) +{ + return (md->attribute & EFI_MEMORY_UC); +} + static void walk (efi_freemem_callback_t callback, void *arg, u64 attr) { @@ -595,8 +621,8 @@ efi_get_iobase (void) return 0; } -u32 -efi_mem_type (unsigned long phys_addr) +static efi_memory_desc_t * +efi_memory_descriptor (unsigned long phys_addr) { void *efi_map_start, *efi_map_end, *p; efi_memory_desc_t *md; @@ -610,13 +636,13 @@ efi_mem_type (unsigned long phys_addr) md = p; if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) - return md->type; + return md; } return 0; } -u64 -efi_mem_attributes (unsigned long phys_addr) +static int +efi_memmap_has_mmio (void) { void *efi_map_start, *efi_map_end, *p; efi_memory_desc_t *md; @@ -629,36 +655,98 @@ efi_mem_attributes (unsigned long phys_addr) for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { md = p; - if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) - return md->attribute; + if (md->type == EFI_MEMORY_MAPPED_IO) + return 1; } return 0; } + +u32 +efi_mem_type (unsigned long phys_addr) +{ + efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); + + if (md) + return md->type; + return 0; +} + +u64 +efi_mem_attributes (unsigned long phys_addr) +{ + efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); + + if (md) + return md->attribute; + return 0; +} EXPORT_SYMBOL(efi_mem_attributes); +/* + * Determines whether the memory at phys_addr supports the desired + * attribute (WB, UC, etc). If this returns 1, the caller can safely + * access *size bytes at phys_addr with the specified attribute. + */ +static int +efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) +{ + efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); + unsigned long md_end; + + if (!md || (md->attribute & attr) != attr) + return 0; + + do { + md_end = efi_md_end(md); + if (phys_addr + *size <= md_end) + return 1; + + md = efi_memory_descriptor(md_end); + if (!md || (md->attribute & attr) != attr) { + *size = md_end - phys_addr; + return 1; + } + } while (md); + return 0; +} + +/* + * For /dev/mem, we only allow read & write system calls to access + * write-back memory, because read & write don't allow the user to + * control access size. + */ int valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) { - void *efi_map_start, *efi_map_end, *p; - efi_memory_desc_t *md; - u64 efi_desc_size; + return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); +} - efi_map_start = __va(ia64_boot_param->efi_memmap); - efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; - efi_desc_size = ia64_boot_param->efi_memdesc_size; +/* + * We allow mmap of anything in the EFI memory map that supports + * either write-back or uncacheable access. For uncacheable regions, + * the supported access sizes are system-dependent, and the user is + * responsible for using the correct size. + * + * Note that this doesn't currently allow access to hot-added memory, + * because that doesn't appear in the boot-time EFI memory map. + */ +int +valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) +{ + if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) + return 1; - for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { - md = p; + if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) + return 1; - if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) { - if (!(md->attribute & EFI_MEMORY_WB)) - return 0; + /* + * 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; - if (*size > md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr) - *size = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr; - return 1; - } - } return 0; } @@ -707,32 +795,6 @@ efi_uart_console_only(void) return 0; } -#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) - -static inline u64 -kmd_end(kern_memdesc_t *kmd) -{ - return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); -} - -static inline u64 -efi_md_end(efi_memory_desc_t *md) -{ - return (md->phys_addr + efi_md_size(md)); -} - -static inline int -efi_wb(efi_memory_desc_t *md) -{ - return (md->attribute & EFI_MEMORY_WB); -} - -static inline int -efi_uc(efi_memory_desc_t *md) -{ - return (md->attribute & EFI_MEMORY_UC); -} - /* * Look for the first granule aligned memory descriptor memory * that is big enough to hold EFI memory map. Make sure this diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 0741b066b98..7a6ffd61378 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1600,5 +1600,6 @@ sys_call_table: data8 sys_inotify_init data8 sys_inotify_add_watch data8 sys_inotify_rm_watch + data8 sys_migrate_pages // 1280 .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index bfe65b2e862..fbc7ea35dd5 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -1060,7 +1060,7 @@ SET_REG(b5); * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h. */ -#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4) .prologue diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index 5db9d3bcbbc..e72de580ebb 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -103,7 +103,7 @@ EXPORT_SYMBOL(unw_init_running); #ifdef ASM_SUPPORTED # ifdef CONFIG_SMP -# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +# if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) /* * This is not a normal routine and we don't want a function descriptor for it, so we use * a fake declaration here. diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 4b19d041063..8d88eeea02d 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1422,14 +1422,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) lock_kernel(); ret = -EPERM; if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - current->ptrace |= PT_PTRACED; - ret = 0; + ret = ptrace_traceme(); goto out; } diff --git a/arch/ia64/oprofile/backtrace.c b/arch/ia64/oprofile/backtrace.c index b7dabbfb0d6..adb01566bd5 100644 --- a/arch/ia64/oprofile/backtrace.c +++ b/arch/ia64/oprofile/backtrace.c @@ -32,7 +32,7 @@ typedef struct u64 *prev_pfs_loc; /* state for WAR for old spinlock ool code */ } ia64_backtrace_t; -#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) /* * Returns non-zero if the PC is in the spinlock contention out-of-line code * with non-standard calling sequence (on older compilers). |