diff options
Diffstat (limited to 'arch/alpha/kernel')
| -rw-r--r-- | arch/alpha/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/alpha/kernel/asm-offsets.c | 5 | ||||
| -rw-r--r-- | arch/alpha/kernel/core_marvel.c | 15 | ||||
| -rw-r--r-- | arch/alpha/kernel/core_titan.c | 4 | ||||
| -rw-r--r-- | arch/alpha/kernel/entry.S | 135 | ||||
| -rw-r--r-- | arch/alpha/kernel/module.c | 4 | ||||
| -rw-r--r-- | arch/alpha/kernel/osf_sys.c | 45 | ||||
| -rw-r--r-- | arch/alpha/kernel/pci.c | 3 | ||||
| -rw-r--r-- | arch/alpha/kernel/pci_iommu.c | 51 | ||||
| -rw-r--r-- | arch/alpha/kernel/perf_event.c | 11 | ||||
| -rw-r--r-- | arch/alpha/kernel/process.c | 2 | ||||
| -rw-r--r-- | arch/alpha/kernel/ptrace.c | 83 | ||||
| -rw-r--r-- | arch/alpha/kernel/setup.c | 3 | ||||
| -rw-r--r-- | arch/alpha/kernel/srmcons.c | 67 | ||||
| -rw-r--r-- | arch/alpha/kernel/syscalls/syscall.tbl | 5 | ||||
| -rw-r--r-- | arch/alpha/kernel/traps.c | 2 | ||||
| -rw-r--r-- | arch/alpha/kernel/vmlinux.lds.S | 1 |
17 files changed, 288 insertions, 150 deletions
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index b6c862dff1f6..187cd8df2faf 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -3,7 +3,7 @@ # Makefile for the linux kernel. # -extra-y := vmlinux.lds +always-$(KBUILD_BUILTIN) := vmlinux.lds asflags-y := $(KBUILD_CFLAGS) ccflags-y := -Wno-sign-compare diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c index 4cfeae42c79a..1ebb05890499 100644 --- a/arch/alpha/kernel/asm-offsets.c +++ b/arch/alpha/kernel/asm-offsets.c @@ -4,6 +4,7 @@ * This code generates raw asm output which is post-processed to extract * and format the required data. */ +#define COMPILE_OFFSETS #include <linux/types.h> #include <linux/stddef.h> @@ -19,9 +20,13 @@ static void __used foo(void) DEFINE(TI_STATUS, offsetof(struct thread_info, status)); BLANK(); + DEFINE(SP_OFF, offsetof(struct pt_regs, ps)); DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs)); BLANK(); + DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack)); + BLANK(); + DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache)); DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register)); } diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c index b1bfbd11980d..92e3312e786e 100644 --- a/arch/alpha/kernel/core_marvel.c +++ b/arch/alpha/kernel/core_marvel.c @@ -17,6 +17,7 @@ #include <linux/vmalloc.h> #include <linux/mc146818rtc.h> #include <linux/rtc.h> +#include <linux/string.h> #include <linux/module.h> #include <linux/memblock.h> @@ -79,10 +80,12 @@ mk_resource_name(int pe, int port, char *str) { char tmp[80]; char *name; - - sprintf(tmp, "PCI %s PE %d PORT %d", str, pe, port); - name = memblock_alloc_or_panic(strlen(tmp) + 1, SMP_CACHE_BYTES); - strcpy(name, tmp); + size_t sz; + + sz = scnprintf(tmp, sizeof(tmp), "PCI %s PE %d PORT %d", str, pe, port); + sz += 1; /* NUL terminator */ + name = memblock_alloc_or_panic(sz, SMP_CACHE_BYTES); + strscpy(name, tmp, sz); return name; } @@ -858,7 +861,7 @@ marvel_agp_setup(alpha_agp_info *agp) if (!alpha_agpgart_size) return -ENOMEM; - aper = kmalloc(sizeof(*aper), GFP_KERNEL); + aper = kmalloc_obj(*aper); if (aper == NULL) return -ENOMEM; aper->arena = agp->hose->sg_pci; @@ -1056,7 +1059,7 @@ marvel_agp_info(void) /* * Allocate the info structure. */ - agp = kmalloc(sizeof(*agp), GFP_KERNEL); + agp = kmalloc_obj(*agp); if (!agp) return NULL; diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c index 77f5d68ed04b..6b6b9e6d631f 100644 --- a/arch/alpha/kernel/core_titan.c +++ b/arch/alpha/kernel/core_titan.c @@ -594,7 +594,7 @@ titan_agp_setup(alpha_agp_info *agp) if (!alpha_agpgart_size) return -ENOMEM; - aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL); + aper = kmalloc_obj(struct titan_agp_aperture); if (aper == NULL) return -ENOMEM; @@ -760,7 +760,7 @@ titan_agp_info(void) /* * Allocate the info structure. */ - agp = kmalloc(sizeof(*agp), GFP_KERNEL); + agp = kmalloc_obj(*agp); if (!agp) return NULL; diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index dd26062d75b3..fcfd06529b12 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -10,15 +10,12 @@ #include <asm/pal.h> #include <asm/errno.h> #include <asm/unistd.h> +#include <linux/errno.h> .text .set noat .cfi_sections .debug_frame -/* Stack offsets. */ -#define SP_OFF 184 -#define SWITCH_STACK_SIZE 64 - .macro CFI_START_OSF_FRAME func .align 4 .globl \func @@ -40,6 +37,64 @@ .endm /* + * SYSCALL_SKIP_RETURN_RESTART_GATE + * + * Used when syscall dispatch is skipped (seccomp/ptrace injected nr=-1). + * - Ensure we never return r0==-1 with a3==0 (success); convert to ENOSYS. + * - Gate whether syscall restart is allowed by preserving restart context + * only for ERESTART* returns. Result: + * $26 = 0 => restart allowed + * $26 = 1 => restart NOT allowed + * $18 = preserved syscall nr (regs->r2) if restart allowed, else 0 + */ +.macro SYSCALL_SKIP_RETURN_RESTART_GATE + /* Fix up invalid "-1 success" return state. */ + ldq $19, 72($sp) /* a3 */ + bne $19, 1f /* already error => skip fixup */ + + ldq $20, 0($sp) /* r0 */ + lda $21, -1($31) + cmpeq $20, $21, $22 + beq $22, 1f /* r0 != -1 => skip fixup */ + + + lda $20, ENOSYS($31) + stq $20, 0($sp) /* r0 = ENOSYS */ + lda $19, 1($31) + stq $19, 72($sp) /* a3 = 1 */ +1: + /* Restart gating: success is never restartable here. */ + ldq $19, 72($sp) /* a3 */ + beq $19, 3f /* success => not restartable */ + + ldq $20, 0($sp) /* r0 (positive errno if a3==1) */ + lda $21, ERESTARTSYS($31) + cmpeq $20, $21, $22 + bne $22, 2f + lda $21, ERESTARTNOINTR($31) + cmpeq $20, $21, $22 + bne $22, 2f + lda $21, ERESTARTNOHAND($31) + cmpeq $20, $21, $22 + bne $22, 2f + lda $21, ERESTART_RESTARTBLOCK($31) + cmpeq $20, $21, $22 + bne $22, 2f + +3: /* Not a restart code (or success) => restart NOT allowed. */ + addq $31, 1, $26 /* $26=1 => restart NOT allowed */ + mov 0, $18 + br 4f + +2: /* Restart allowed. */ + ldq $18, 16($sp) /* preserved syscall nr (regs->r2) */ + mov $31, $26 /* $26=0 => restart allowed */ + br 4f +4: +.endm + + +/* * This defines the normal kernel pt-regs layout. * * regs 9-15 preserved by C code @@ -198,8 +253,8 @@ CFI_END_OSF_FRAME entArith CFI_START_OSF_FRAME entMM SAVE_ALL /* save $9 - $15 so the inline exception code can manipulate them. */ - subq $sp, 56, $sp - .cfi_adjust_cfa_offset 56 + subq $sp, 64, $sp + .cfi_adjust_cfa_offset 64 stq $9, 0($sp) stq $10, 8($sp) stq $11, 16($sp) @@ -214,7 +269,7 @@ CFI_START_OSF_FRAME entMM .cfi_rel_offset $13, 32 .cfi_rel_offset $14, 40 .cfi_rel_offset $15, 48 - addq $sp, 56, $19 + addq $sp, 64, $19 /* handle the fault */ lda $8, 0x3fff bic $sp, $8, $8 @@ -227,7 +282,7 @@ CFI_START_OSF_FRAME entMM ldq $13, 32($sp) ldq $14, 40($sp) ldq $15, 48($sp) - addq $sp, 56, $sp + addq $sp, 64, $sp .cfi_restore $9 .cfi_restore $10 .cfi_restore $11 @@ -235,7 +290,7 @@ CFI_START_OSF_FRAME entMM .cfi_restore $13 .cfi_restore $14 .cfi_restore $15 - .cfi_adjust_cfa_offset -56 + .cfi_adjust_cfa_offset -64 /* finish up the syscall as normal. */ br ret_from_sys_call CFI_END_OSF_FRAME entMM @@ -382,8 +437,8 @@ entUnaUser: .cfi_restore $0 .cfi_adjust_cfa_offset -256 SAVE_ALL /* setup normal kernel stack */ - lda $sp, -56($sp) - .cfi_adjust_cfa_offset 56 + lda $sp, -64($sp) + .cfi_adjust_cfa_offset 64 stq $9, 0($sp) stq $10, 8($sp) stq $11, 16($sp) @@ -399,7 +454,7 @@ entUnaUser: .cfi_rel_offset $14, 40 .cfi_rel_offset $15, 48 lda $8, 0x3fff - addq $sp, 56, $19 + addq $sp, 64, $19 bic $sp, $8, $8 jsr $26, do_entUnaUser ldq $9, 0($sp) @@ -409,7 +464,7 @@ entUnaUser: ldq $13, 32($sp) ldq $14, 40($sp) ldq $15, 48($sp) - lda $sp, 56($sp) + lda $sp, 64($sp) .cfi_restore $9 .cfi_restore $10 .cfi_restore $11 @@ -417,7 +472,7 @@ entUnaUser: .cfi_restore $13 .cfi_restore $14 .cfi_restore $15 - .cfi_adjust_cfa_offset -56 + .cfi_adjust_cfa_offset -64 br ret_from_sys_call CFI_END_OSF_FRAME entUna @@ -429,7 +484,7 @@ CFI_START_OSF_FRAME entDbg mov $sp, $16 jsr $31, do_entDbg CFI_END_OSF_FRAME entDbg - + /* * The system call entry point is special. Most importantly, it looks * like a function call to userspace as far as clobbered registers. We @@ -439,6 +494,17 @@ CFI_END_OSF_FRAME entDbg * So much for theory. We don't take advantage of this yet. * * Note that a0-a2 are not saved by PALcode as with the other entry points. + * + * Alpha syscall ABI uses: + * - r0 for return value + * - r19 ("a3") as error indicator (0=success, 1=error; r0 holds errno) + * + * For seccomp/ptrace/generic syscall helpers we track the syscall + * number separately: + * - regs->r1: current (mutable) syscall number (may be changed or set to -1) + * - regs->r2: original syscall number for restart/rollback + * + * On entry PAL provides the syscall number in r0; copy it into r1/r2. */ .align 4 @@ -451,6 +517,10 @@ CFI_END_OSF_FRAME entDbg .cfi_rel_offset $gp, 16 entSys: SAVE_ALL + ldq $1, 0($sp) /* syscall nr from saved r0 */ + stq $1, 8($sp) /* regs->r1 = shadow syscall nr */ + stq $1, 16($sp) /* regs->r2 = restart syscall nr */ + lda $8, 0x3fff bic $sp, $8, $8 lda $4, NR_syscalls($31) @@ -466,15 +536,19 @@ entSys: .cfi_rel_offset $17, SP_OFF+32 .cfi_rel_offset $18, SP_OFF+40 #ifdef CONFIG_AUDITSYSCALL - lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP and $3, $6, $3 bne $3, strace #else - blbs $3, strace /* check for SYSCALL_TRACE in disguise */ + lda $6, _TIF_SYSCALL_TRACE | _TIF_SECCOMP + and $3, $6, $3 + bne $3, strace #endif beq $4, 1f ldq $27, 0($5) -1: jsr $26, ($27), sys_ni_syscall +1: ldq $0, 8($sp) /* syscall nr shadow (regs->r1) */ + + jsr $26, ($27), sys_ni_syscall ldgp $gp, 0($26) blt $0, $syscall_error /* the call failed */ $ret_success: @@ -513,15 +587,8 @@ ret_to_kernel: .align 3 $syscall_error: - /* - * Some system calls (e.g., ptrace) can return arbitrary - * values which might normally be mistaken as error numbers. - * Those functions must zero $0 (v0) directly in the stack - * frame to indicate that a negative return value wasn't an - * error number.. - */ - ldq $18, 0($sp) /* old syscall nr (zero if success) */ - beq $18, $ret_success + /* Restart syscall nr comes from saved r2 (preserved even if r0 overwritten). */ + ldq $18, 16($sp) /* old syscall nr for restart */ ldq $19, 72($sp) /* .. and this a3 */ subq $31, $0, $0 /* with error in v0 */ @@ -585,6 +652,8 @@ strace: jsr $26, syscall_trace_enter /* returns the syscall number */ UNDO_SWITCH_STACK + stq $0, 8($sp) /* regs->r1 = shadow syscall nr */ + /* get the arguments back.. */ ldq $16, SP_OFF+24($sp) ldq $17, SP_OFF+32($sp) @@ -593,6 +662,11 @@ strace: ldq $20, 80($sp) ldq $21, 88($sp) + /* nr == -1: internal skip-dispatch or userspace syscall(-1)? */ + lda $6, -1($31) + cmpeq $0, $6, $6 + bne $6, $strace_skip_call /* nr == -1 => dispatch */ + /* get the system call pointer.. */ lda $1, NR_syscalls($31) lda $2, sys_call_table @@ -611,6 +685,8 @@ $strace_success: stq $31, 72($sp) /* a3=0 => no error */ stq $0, 0($sp) /* save return value */ +$strace_skip_call: + SYSCALL_SKIP_RETURN_RESTART_GATE DO_SWITCH_STACK jsr $26, syscall_trace_leave UNDO_SWITCH_STACK @@ -618,8 +694,7 @@ $strace_success: .align 3 $strace_error: - ldq $18, 0($sp) /* old syscall nr (zero if success) */ - beq $18, $strace_success + ldq $18, 16($sp) /* restart syscall nr */ ldq $19, 72($sp) /* .. and this a3 */ subq $31, $0, $0 /* with error in v0 */ @@ -638,7 +713,7 @@ $strace_error: mov $31, $26 /* tell "ret_from_sys_call" we can restart */ br ret_from_sys_call CFI_END_OSF_FRAME entSys - + /* * Save and restore the switch stack -- aka the balance of the user context. */ diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c index cbefa5a77384..548d1591cfa9 100644 --- a/arch/alpha/kernel/module.c +++ b/arch/alpha/kernel/module.c @@ -46,7 +46,7 @@ process_reloc_for_got(Elf64_Rela *rela, goto found_entry; } - g = kmalloc (sizeof (*g), GFP_KERNEL); + g = kmalloc_obj(*g); g->next = chains[r_sym].next; g->r_addend = r_addend; g->got_offset = *poffset; @@ -93,7 +93,7 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs, } nsyms = symtab->sh_size / sizeof(Elf64_Sym); - chains = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL); + chains = kzalloc_objs(struct got_entry, nsyms); if (!chains) { printk(KERN_ERR "module %s: no memory for symbol chain buffer\n", diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 86185021f75a..7b6543d2cca3 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -454,42 +454,30 @@ static int osf_ufs_mount(const char __user *dirname, struct ufs_args __user *args, int flags) { - int retval; - struct cdfs_args tmp; - struct filename *devname; + struct ufs_args tmp; + char *devname __free(kfree) = NULL; - retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) - goto out; - devname = getname(tmp.devname); - retval = PTR_ERR(devname); + return -EFAULT; + devname = strndup_user(tmp.devname, PATH_MAX); if (IS_ERR(devname)) - goto out; - retval = do_mount(devname->name, dirname, "ext2", flags, NULL); - putname(devname); - out: - return retval; + return PTR_ERR(devname); + return do_mount(devname, dirname, "ext2", flags, NULL); } static int osf_cdfs_mount(const char __user *dirname, struct cdfs_args __user *args, int flags) { - int retval; struct cdfs_args tmp; - struct filename *devname; + char *devname __free(kfree) = NULL; - retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) - goto out; - devname = getname(tmp.devname); - retval = PTR_ERR(devname); + return -EFAULT; + devname = strndup_user(tmp.devname, PATH_MAX); if (IS_ERR(devname)) - goto out; - retval = do_mount(devname->name, dirname, "iso9660", flags, NULL); - putname(devname); - out: - return retval; + return PTR_ERR(devname); + return do_mount(devname, dirname, "iso9660", flags, NULL); } static int @@ -1210,8 +1198,7 @@ SYSCALL_DEFINE1(old_adjtimex, struct timex32 __user *, txc_p) return ret; } -/* Get an address range which is currently unmapped. Similar to the - generic version except that we know how to honor ADDR_LIMIT_32BIT. */ +/* Get an address range which is currently unmapped. */ static unsigned long arch_get_unmapped_area_1(unsigned long addr, unsigned long len, @@ -1230,13 +1217,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags) { - unsigned long limit; - - /* "32 bit" actually means 31 bit, since pointers sign extend. */ - if (current->personality & ADDR_LIMIT_32BIT) - limit = 0x80000000; - else - limit = TASK_SIZE; + unsigned long limit = TASK_SIZE; if (len > limit) return -ENOMEM; diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 8e9b4ac86b7e..11df411b1d18 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -125,6 +125,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final); resource_size_t pcibios_align_resource(void *data, const struct resource *res, + const struct resource *empty_res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; @@ -220,7 +221,7 @@ static void pdev_save_srm_config(struct pci_dev *dev) printed = 1; } - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + tmp = kmalloc_obj(*tmp); if (!tmp) { printk(KERN_ERR "%s: kmalloc() failed!\n", __func__); return; diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 681f56089d9c..955b6ca61627 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -13,6 +13,7 @@ #include <linux/log2.h> #include <linux/dma-map-ops.h> #include <linux/iommu-helper.h> +#include <linux/string_choices.h> #include <asm/io.h> #include <asm/hwrpb.h> @@ -212,7 +213,7 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask) /* If both conditions above are met, we are fine. */ DBGA("pci_dac_dma_supported %s from %ps\n", - ok ? "yes" : "no", __builtin_return_address(0)); + str_yes_no(ok), __builtin_return_address(0)); return ok; } @@ -223,28 +224,26 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask) until either pci_unmap_single or pci_dma_sync_single is performed. */ static dma_addr_t -pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, +pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size, int dac_allowed) { struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose; dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK; + unsigned long offset = offset_in_page(paddr); struct pci_iommu_arena *arena; long npages, dma_ofs, i; - unsigned long paddr; dma_addr_t ret; unsigned int align = 0; struct device *dev = pdev ? &pdev->dev : NULL; - paddr = __pa(cpu_addr); - #if !DEBUG_NODIRECT /* First check to see if we can use the direct map window. */ if (paddr + size + __direct_map_base - 1 <= max_dma && paddr + size <= __direct_map_size) { ret = paddr + __direct_map_base; - DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %ps\n", - cpu_addr, size, ret, __builtin_return_address(0)); + DBGA2("pci_map_single: [%pa,%zx] -> direct %llx from %ps\n", + &paddr, size, ret, __builtin_return_address(0)); return ret; } @@ -254,8 +253,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, if (dac_allowed) { ret = paddr + alpha_mv.pci_dac_offset; - DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %ps\n", - cpu_addr, size, ret, __builtin_return_address(0)); + DBGA2("pci_map_single: [%pa,%zx] -> DAC %llx from %ps\n", + &paddr, size, ret, __builtin_return_address(0)); return ret; } @@ -289,10 +288,10 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr); ret = arena->dma_base + dma_ofs * PAGE_SIZE; - ret += (unsigned long)cpu_addr & ~PAGE_MASK; + ret += offset; - DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %ps\n", - cpu_addr, size, npages, ret, __builtin_return_address(0)); + DBGA2("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n", + &paddr, size, npages, ret, __builtin_return_address(0)); return ret; } @@ -321,19 +320,18 @@ static struct pci_dev *alpha_gendev_to_pci(struct device *dev) return NULL; } -static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, +static dma_addr_t alpha_pci_map_phys(struct device *dev, phys_addr_t phys, + size_t size, enum dma_data_direction dir, unsigned long attrs) { struct pci_dev *pdev = alpha_gendev_to_pci(dev); int dac_allowed; - BUG_ON(dir == DMA_NONE); + if (unlikely(attrs & DMA_ATTR_MMIO)) + return DMA_MAPPING_ERROR; - dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; - return pci_map_single_1(pdev, (char *)page_address(page) + offset, - size, dac_allowed); + dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; + return pci_map_single_1(pdev, phys, size, dac_allowed); } /* Unmap a single streaming mode DMA translation. The DMA_ADDR and @@ -342,7 +340,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page, the cpu to the buffer are guaranteed to see whatever the device wrote there. */ -static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr, +static void alpha_pci_unmap_phys(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir, unsigned long attrs) { @@ -352,8 +350,6 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr, struct pci_iommu_arena *arena; long dma_ofs, npages; - BUG_ON(dir == DMA_NONE); - if (dma_addr >= __direct_map_base && dma_addr < __direct_map_base + __direct_map_size) { /* Nothing to do. */ @@ -428,7 +424,7 @@ try_again: } memset(cpu_addr, 0, size); - *dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0); + *dma_addrp = pci_map_single_1(pdev, virt_to_phys(cpu_addr), size, 0); if (*dma_addrp == DMA_MAPPING_ERROR) { free_pages((unsigned long)cpu_addr, order); if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA)) @@ -642,9 +638,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg, /* Fast path single entry scatterlists. */ if (nents == 1) { sg->dma_length = sg->length; - sg->dma_address - = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg), - sg->length, dac_allowed); + sg->dma_address = pci_map_single_1(pdev, sg_phys(sg), + sg->length, dac_allowed); if (sg->dma_address == DMA_MAPPING_ERROR) return -EIO; return 1; @@ -916,8 +911,8 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count) const struct dma_map_ops alpha_pci_ops = { .alloc = alpha_pci_alloc_coherent, .free = alpha_pci_free_coherent, - .map_page = alpha_pci_map_page, - .unmap_page = alpha_pci_unmap_page, + .map_phys = alpha_pci_map_phys, + .unmap_phys = alpha_pci_unmap_phys, .map_sg = alpha_pci_map_sg, .unmap_sg = alpha_pci_unmap_sg, .dma_supported = alpha_pci_supported, diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c index 1f0eb4f25c0f..a3eaab094ece 100644 --- a/arch/alpha/kernel/perf_event.c +++ b/arch/alpha/kernel/perf_event.c @@ -852,14 +852,9 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr, alpha_perf_event_update(event, hwc, idx, alpha_pmu->pmc_max_period[idx]+1); perf_sample_data_init(&data, 0, hwc->last_period); - if (alpha_perf_event_set_period(event, hwc, idx)) { - if (perf_event_overflow(event, &data, regs)) { - /* Interrupts coming too quickly; "throttle" the - * counter, i.e., disable it for a little while. - */ - alpha_pmu_stop(event, 0); - } - } + if (alpha_perf_event_set_period(event, hwc, idx)) + perf_event_overflow(event, &data, regs); + wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask); return; diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 582d96548385..06522451f018 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -231,7 +231,7 @@ flush_thread(void) */ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { - unsigned long clone_flags = args->flags; + u64 clone_flags = args->flags; unsigned long usp = args->stack; unsigned long tls = args->tls; extern void ret_from_fork(void); diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index fde4c68e7a0b..0687760ea466 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -16,11 +16,14 @@ #include <linux/security.h> #include <linux/signal.h> #include <linux/audit.h> +#include <linux/seccomp.h> +#include <asm/syscall.h> #include <linux/uaccess.h> #include <asm/fpu.h> #include "proto.h" +#include <linux/uio.h> #define DEBUG DBG_MEM #undef DEBUG @@ -312,6 +315,54 @@ long arch_ptrace(struct task_struct *child, long request, DBG(DBG_MEM, ("poke $%lu<-%#lx\n", addr, data)); ret = put_reg(child, addr, data); break; + case PTRACE_GETREGSET: + case PTRACE_SETREGSET: { + struct iovec __user *uiov = (struct iovec __user *)data; + struct iovec iov; + struct pt_regs *regs; + size_t len; + + /* Only support NT_PRSTATUS (general registers) for now. */ + if (addr != NT_PRSTATUS) { + ret = -EIO; + break; + } + + if (copy_from_user(&iov, uiov, sizeof(iov))) { + ret = -EFAULT; + break; + } + + regs = task_pt_regs(child); + len = min_t(size_t, iov.iov_len, sizeof(*regs)); + + if (request == PTRACE_GETREGSET) { + if (copy_to_user(iov.iov_base, regs, len)) { + ret = -EFAULT; + break; + } + } else { + /* + * Allow writing back regs. This is needed by the TRACE_syscall + * tests (they change PC/syscall nr/retval). + */ + if (copy_from_user(regs, iov.iov_base, len)) { + ret = -EFAULT; + break; + } + } + + /* Per API, update iov_len with amount transferred. */ + iov.iov_len = len; + if (copy_to_user(uiov, &iov, sizeof(iov))) { + ret = -EFAULT; + break; + } + + ret = 0; + break; + } + default: ret = ptrace_request(child, request, addr, data); break; @@ -321,15 +372,37 @@ long arch_ptrace(struct task_struct *child, long request, asmlinkage unsigned long syscall_trace_enter(void) { - unsigned long ret = 0; struct pt_regs *regs = current_pt_regs(); + if (test_thread_flag(TIF_SYSCALL_TRACE) && - ptrace_report_syscall_entry(current_pt_regs())) - ret = -1UL; - audit_syscall_entry(regs->r0, regs->r16, regs->r17, regs->r18, regs->r19); - return ret ?: current_pt_regs()->r0; + ptrace_report_syscall_entry(regs)) { + syscall_set_nr(current, regs, -1); + if (regs->r19 == 0 && regs->r0 == (unsigned long)-1) + syscall_set_return_value(current, regs, -ENOSYS, 0); + return -1UL; + } + + /* + * Do the secure computing after ptrace; failures should be fast. + * If this fails, seccomp may already have set up the return value + * (e.g. SECCOMP_RET_ERRNO / TRACE). + */ + if (secure_computing() == -1) { + if (regs->r19 == 0 && regs->r0 == (unsigned long)-1) + syscall_set_return_value(current, regs, -ENOSYS, 0); + syscall_set_nr(current, regs, -1); + return -1UL; + } + +#ifdef CONFIG_AUDITSYSCALL + audit_syscall_entry(syscall_get_nr(current, regs), + regs->r16, regs->r17, regs->r18, regs->r19); +#endif + return syscall_get_nr(current, regs); } + + asmlinkage void syscall_trace_leave(void) { diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index bebdffafaee8..4cbcfb1852d5 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -392,7 +392,7 @@ register_cpus(void) int i; for_each_possible_cpu(i) { - struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL); + struct cpu *p = kzalloc_obj(*p); if (!p) return -ENOMEM; register_cpu(p, i); @@ -607,7 +607,6 @@ setup_arch(char **cmdline_p) /* Find our memory. */ setup_memory(kernel_end); memblock_set_bottom_up(true); - sparse_init(); /* First guess at cpu cache sizes. Do this before init_arch. */ determine_cpu_caches(cpu->type); diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index 3e61073f4b30..d19e51ec711d 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c @@ -69,7 +69,8 @@ srmcons_do_receive_chars(struct tty_port *port) static void srmcons_receive_chars(struct timer_list *t) { - struct srmcons_private *srmconsp = from_timer(srmconsp, t, timer); + struct srmcons_private *srmconsp = timer_container_of(srmconsp, t, + timer); struct tty_port *port = &srmconsp->port; unsigned long flags; int incr = 10; @@ -177,7 +178,7 @@ srmcons_close(struct tty_struct *tty, struct file *filp) if (tty->count == 1) { port->tty = NULL; - del_timer(&srmconsp->timer); + timer_delete(&srmconsp->timer); } spin_unlock_irqrestore(&port->lock, flags); @@ -196,40 +197,44 @@ static const struct tty_operations srmcons_ops = { static int __init srmcons_init(void) { + struct tty_driver *driver; + int err; + timer_setup(&srmcons_singleton.timer, srmcons_receive_chars, 0); - if (srm_is_registered_console) { - struct tty_driver *driver; - int err; - - driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0); - if (IS_ERR(driver)) - return PTR_ERR(driver); - - tty_port_init(&srmcons_singleton.port); - - driver->driver_name = "srm"; - driver->name = "srm"; - driver->major = 0; /* dynamic */ - driver->minor_start = 0; - driver->type = TTY_DRIVER_TYPE_SYSTEM; - driver->subtype = SYSTEM_TYPE_SYSCONS; - driver->init_termios = tty_std_termios; - tty_set_operations(driver, &srmcons_ops); - tty_port_link_device(&srmcons_singleton.port, driver, 0); - err = tty_register_driver(driver); - if (err) { - tty_driver_kref_put(driver); - tty_port_destroy(&srmcons_singleton.port); - return err; - } - srmcons_driver = driver; - } - return -ENODEV; + if (!srm_is_registered_console) + return -ENODEV; + + driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0); + if (IS_ERR(driver)) + return PTR_ERR(driver); + + tty_port_init(&srmcons_singleton.port); + + driver->driver_name = "srm"; + driver->name = "srm"; + driver->major = 0; /* dynamic */ + driver->minor_start = 0; + driver->type = TTY_DRIVER_TYPE_SYSTEM; + driver->subtype = SYSTEM_TYPE_SYSCONS; + driver->init_termios = tty_std_termios; + tty_set_operations(driver, &srmcons_ops); + tty_port_link_device(&srmcons_singleton.port, driver, 0); + err = tty_register_driver(driver); + if (err) + goto err_free_drv; + + srmcons_driver = driver; + + return 0; +err_free_drv: + tty_driver_kref_put(driver); + tty_port_destroy(&srmcons_singleton.port); + + return err; } device_initcall(srmcons_init); - /* * The console driver */ diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index c59d53d6d3f3..f31b7afffc34 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -506,3 +506,8 @@ 574 common getxattrat sys_getxattrat 575 common listxattrat sys_listxattrat 576 common removexattrat sys_removexattrat +577 common open_tree_attr sys_open_tree_attr +578 common file_getattr sys_file_getattr +579 common file_setattr sys_file_setattr +580 common listns sys_listns +581 common rseq_slice_yield sys_rseq_slice_yield diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index a9a38c80c4a7..7004397937cf 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -649,7 +649,7 @@ s_reg_to_mem (unsigned long s_reg) static int unauser_reg_offsets[32] = { R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), /* r9 ... r15 are stored in front of regs. */ - -56, -48, -40, -32, -24, -16, -8, + -64, -56, -48, -40, -32, -24, -16, /* padding at -8 */ R(r16), R(r17), R(r18), R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), R(r27), R(r28), R(gp), diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 2efa7dfc798a..2d136c63db16 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -71,6 +71,7 @@ SECTIONS STABS_DEBUG DWARF_DEBUG + MODINFO ELF_DETAILS DISCARDS |
