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 | 1 | ||||
| -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 | 111 | ||||
| -rw-r--r-- | arch/alpha/kernel/io.c | 2 | ||||
| -rw-r--r-- | arch/alpha/kernel/irq.c | 8 | ||||
| -rw-r--r-- | arch/alpha/kernel/module.c | 4 | ||||
| -rw-r--r-- | arch/alpha/kernel/osf_sys.c | 34 | ||||
| -rw-r--r-- | arch/alpha/kernel/pci-sysfs.c | 388 | ||||
| -rw-r--r-- | arch/alpha/kernel/pci.c | 3 | ||||
| -rw-r--r-- | arch/alpha/kernel/pci_iommu.c | 48 | ||||
| -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/vmlinux.lds.S | 1 |
19 files changed, 484 insertions, 308 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 e9dad60b147f..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> 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 f4d41b4538c2..fcfd06529b12 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -10,6 +10,7 @@ #include <asm/pal.h> #include <asm/errno.h> #include <asm/unistd.h> +#include <linux/errno.h> .text .set noat @@ -36,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 @@ -425,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 @@ -435,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 @@ -447,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) @@ -462,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: @@ -509,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 */ @@ -581,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) @@ -589,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 @@ -607,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 @@ -614,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 */ @@ -634,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/io.c b/arch/alpha/kernel/io.c index c28035d6d1e6..2bad1b4fb240 100644 --- a/arch/alpha/kernel/io.c +++ b/arch/alpha/kernel/io.c @@ -647,7 +647,7 @@ void _memset_c_io(volatile void __iomem *to, unsigned long c, long count) EXPORT_SYMBOL(_memset_c_io); -#if IS_ENABLED(CONFIG_VGA_CONSOLE) || IS_ENABLED(CONFIG_MDA_CONSOLE) +#if IS_ENABLED(CONFIG_VGA_CONSOLE) #include <asm/vga.h> diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index c67047c5d830..4a6a8b1d5a8b 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -72,16 +72,16 @@ int arch_show_interrupts(struct seq_file *p, int prec) int j; #ifdef CONFIG_SMP - seq_puts(p, "IPI: "); + seq_puts(p, " IPI: "); for_each_online_cpu(j) seq_printf(p, "%10lu ", cpu_data[j].ipi_count); seq_putc(p, '\n'); #endif - seq_puts(p, "PMI: "); + seq_puts(p, " PMI: "); for_each_online_cpu(j) seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j)); - seq_puts(p, " Performance Monitoring\n"); - seq_printf(p, "ERR: %10lu\n", irq_err_count); + seq_puts(p, " Performance Monitoring\n"); + seq_printf(p, " ERR: %10lu\n", irq_err_count); return 0; } 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 a08e8edef1a4..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 diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index 3048758304b5..94dbc470cd6c 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -11,8 +11,7 @@ */ #include <linux/sched.h> -#include <linux/stat.h> -#include <linux/slab.h> +#include <linux/security.h> #include <linux/pci.h> static int hose_mmap_page_range(struct pci_controller *hose, @@ -36,20 +35,18 @@ static int hose_mmap_page_range(struct pci_controller *hose, static int __pci_mmap_fits(struct pci_dev *pdev, int num, struct vm_area_struct *vma, int sparse) { + resource_size_t len = pci_resource_len(pdev, num); unsigned long nr, start, size; int shift = sparse ? 5 : 0; + if (!len) + return 0; + nr = vma_pages(vma); start = vma->vm_pgoff; - size = ((pci_resource_len(pdev, num) - 1) >> (PAGE_SHIFT - shift)) + 1; + size = ((len - 1) >> (PAGE_SHIFT - shift)) + 1; - if (start < size && size - start >= nr) - return 1; - WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on %s BAR %d " - "(size 0x%08lx)\n", - current->comm, sparse ? " sparse" : "", start, start + nr, - pci_name(pdev), num, size); - return 0; + return start < size && size - start >= nr; } /** @@ -68,26 +65,25 @@ static int pci_mmap_resource(struct kobject *kobj, struct vm_area_struct *vma, int sparse) { struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); - struct resource *res = attr->private; + int barno = (unsigned long)attr->private; enum pci_mmap_state mmap_type; struct pci_bus_region bar; - int i; + int ret; - for (i = 0; i < PCI_STD_NUM_BARS; i++) - if (res == &pdev->resource[i]) - break; - if (i >= PCI_STD_NUM_BARS) - return -ENODEV; + ret = security_locked_down(LOCKDOWN_PCI_ACCESS); + if (ret) + return ret; - if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start)) + if (pci_resource_is_mem(pdev, barno) && + iomem_is_exclusive(pci_resource_start(pdev, barno))) return -EINVAL; - if (!__pci_mmap_fits(pdev, i, vma, sparse)) + if (!__pci_mmap_fits(pdev, barno, vma, sparse)) return -EINVAL; - pcibios_resource_to_bus(pdev->bus, &bar, res); + pcibios_resource_to_bus(pdev->bus, &bar, pci_resource_n(pdev, barno)); vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0)); - mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; + mmap_type = pci_resource_is_mem(pdev, barno) ? pci_mmap_mem : pci_mmap_io; return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse); } @@ -106,34 +102,26 @@ static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj, return pci_mmap_resource(kobj, attr, vma, 0); } -/** - * pci_remove_resource_files - cleanup resource files - * @pdev: pci_dev to cleanup - * - * If we created resource files for @dev, remove them from sysfs and - * free their resources. - */ -void pci_remove_resource_files(struct pci_dev *pdev) -{ - int i; - - for (i = 0; i < PCI_STD_NUM_BARS; i++) { - struct bin_attribute *res_attr; - - res_attr = pdev->res_attr[i]; - if (res_attr) { - sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); - kfree(res_attr); - } - - res_attr = pdev->res_attr_wc[i]; - if (res_attr) { - sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); - kfree(res_attr); - } - } +#define __pci_dev_resource_attr(_bar, _name, _suffix, _mmap) \ +static const struct bin_attribute \ +pci_dev_resource##_bar##_suffix##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0600 }, \ + .private = (void *)(unsigned long)(_bar), \ + .mmap = (_mmap), \ } +#define pci_dev_resource_attr(_bar) \ + __pci_dev_resource_attr(_bar, resource##_bar,, \ + pci_mmap_resource_dense) + +#define pci_dev_resource_sparse_attr(_bar) \ + __pci_dev_resource_attr(_bar, resource##_bar##_sparse, _sparse, \ + pci_mmap_resource_sparse) + +#define pci_dev_resource_dense_attr(_bar) \ + __pci_dev_resource_attr(_bar, resource##_bar##_dense, _dense, \ + pci_mmap_resource_dense) + static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num) { struct pci_bus_region bar; @@ -141,7 +129,7 @@ static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num) long dense_offset; unsigned long sparse_size; - pcibios_resource_to_bus(pdev->bus, &bar, &pdev->resource[num]); + pcibios_resource_to_bus(pdev->bus, &bar, pci_resource_n(pdev, num)); /* All core logic chips have 4G sparse address space, except CIA which has 16G (see xxx_SPARSE_MEM and xxx_DENSE_MEM @@ -153,109 +141,10 @@ static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num) return bar.end < sparse_size; } -static int pci_create_one_attr(struct pci_dev *pdev, int num, char *name, - char *suffix, struct bin_attribute *res_attr, - unsigned long sparse) -{ - size_t size = pci_resource_len(pdev, num); - - sprintf(name, "resource%d%s", num, suffix); - res_attr->mmap = sparse ? pci_mmap_resource_sparse : - pci_mmap_resource_dense; - res_attr->attr.name = name; - res_attr->attr.mode = S_IRUSR | S_IWUSR; - res_attr->size = sparse ? size << 5 : size; - res_attr->private = &pdev->resource[num]; - return sysfs_create_bin_file(&pdev->dev.kobj, res_attr); -} - -static int pci_create_attr(struct pci_dev *pdev, int num) -{ - /* allocate attribute structure, piggyback attribute name */ - int retval, nlen1, nlen2 = 0, res_count = 1; - unsigned long sparse_base, dense_base; - struct bin_attribute *attr; - struct pci_controller *hose = pdev->sysdata; - char *suffix, *attr_name; - - suffix = ""; /* Assume bwx machine, normal resourceN files. */ - nlen1 = 10; - - if (pdev->resource[num].flags & IORESOURCE_MEM) { - sparse_base = hose->sparse_mem_base; - dense_base = hose->dense_mem_base; - if (sparse_base && !sparse_mem_mmap_fits(pdev, num)) { - sparse_base = 0; - suffix = "_dense"; - nlen1 = 16; /* resourceN_dense */ - } - } else { - sparse_base = hose->sparse_io_base; - dense_base = hose->dense_io_base; - } - - if (sparse_base) { - suffix = "_sparse"; - nlen1 = 17; - if (dense_base) { - nlen2 = 16; /* resourceN_dense */ - res_count = 2; - } - } - - attr = kzalloc(sizeof(*attr) * res_count + nlen1 + nlen2, GFP_ATOMIC); - if (!attr) - return -ENOMEM; - - /* Create bwx, sparse or single dense file */ - attr_name = (char *)(attr + res_count); - pdev->res_attr[num] = attr; - retval = pci_create_one_attr(pdev, num, attr_name, suffix, attr, - sparse_base); - if (retval || res_count == 1) - return retval; - - /* Create dense file */ - attr_name += nlen1; - attr++; - pdev->res_attr_wc[num] = attr; - return pci_create_one_attr(pdev, num, attr_name, "_dense", attr, 0); -} - -/** - * pci_create_resource_files - create resource files in sysfs for @pdev - * @pdev: pci_dev in question - * - * Walk the resources in @dev creating files for each resource available. - * - * Return: %0 on success, or negative error code - */ -int pci_create_resource_files(struct pci_dev *pdev) -{ - int i; - int retval; - - /* Expose the PCI resources from this device as files */ - for (i = 0; i < PCI_STD_NUM_BARS; i++) { - - /* skip empty resources */ - if (!pci_resource_len(pdev, i)) - continue; - - retval = pci_create_attr(pdev, i); - if (retval) { - pci_remove_resource_files(pdev); - return retval; - } - } - return 0; -} - /* Legacy I/O bus mapping stuff. */ -static int __legacy_mmap_fits(struct pci_controller *hose, - struct vm_area_struct *vma, - unsigned long res_size, int sparse) +static int __legacy_mmap_fits(struct vm_area_struct *vma, + unsigned long res_size) { unsigned long nr, start, size; @@ -263,13 +152,7 @@ static int __legacy_mmap_fits(struct pci_controller *hose, start = vma->vm_pgoff; size = ((res_size - 1) >> PAGE_SHIFT) + 1; - if (start < size && size - start >= nr) - return 1; - WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on hose %d " - "(size 0x%08lx)\n", - current->comm, sparse ? " sparse" : "", start, start + nr, - hose->index, size); - return 0; + return start < size && size - start >= nr; } static inline int has_sparse(struct pci_controller *hose, @@ -290,36 +173,22 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma, int sparse = has_sparse(hose, mmap_type); unsigned long res_size; - res_size = (mmap_type == pci_mmap_mem) ? bus->legacy_mem->size : - bus->legacy_io->size; - if (!__legacy_mmap_fits(hose, vma, res_size, sparse)) + res_size = (mmap_type == pci_mmap_mem) ? PCI_LEGACY_MEM_SIZE : + PCI_LEGACY_IO_SIZE; + if (sparse) + res_size <<= 5; + + if (!__legacy_mmap_fits(vma, res_size)) return -EINVAL; return hose_mmap_page_range(hose, vma, mmap_type, sparse); } -/** - * pci_adjust_legacy_attr - adjustment of legacy file attributes - * @bus: bus to create files under - * @mmap_type: I/O port or memory - * - * Adjust file name and size for sparse mappings. - */ -void pci_adjust_legacy_attr(struct pci_bus *bus, enum pci_mmap_state mmap_type) +bool pci_legacy_has_sparse(struct pci_bus *bus, enum pci_mmap_state type) { struct pci_controller *hose = bus->sysdata; - if (!has_sparse(hose, mmap_type)) - return; - - if (mmap_type == pci_mmap_mem) { - bus->legacy_mem->attr.name = "legacy_mem_sparse"; - bus->legacy_mem->size <<= 5; - } else { - bus->legacy_io->attr.name = "legacy_io_sparse"; - bus->legacy_io->size <<= 5; - } - return; + return has_sparse(hose, type); } /* Legacy I/O bus read/write functions */ @@ -370,3 +239,166 @@ int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size) } return -EINVAL; } + +pci_dev_resource_attr(0); +pci_dev_resource_attr(1); +pci_dev_resource_attr(2); +pci_dev_resource_attr(3); +pci_dev_resource_attr(4); +pci_dev_resource_attr(5); + +pci_dev_resource_sparse_attr(0); +pci_dev_resource_sparse_attr(1); +pci_dev_resource_sparse_attr(2); +pci_dev_resource_sparse_attr(3); +pci_dev_resource_sparse_attr(4); +pci_dev_resource_sparse_attr(5); + +pci_dev_resource_dense_attr(0); +pci_dev_resource_dense_attr(1); +pci_dev_resource_dense_attr(2); +pci_dev_resource_dense_attr(3); +pci_dev_resource_dense_attr(4); +pci_dev_resource_dense_attr(5); + +static inline enum pci_mmap_state pci_bar_mmap_type(struct pci_dev *pdev, + int bar) +{ + return pci_resource_is_mem(pdev, bar) ? pci_mmap_mem : pci_mmap_io; +} + +static inline umode_t __pci_resource_attr_is_visible(struct kobject *kobj, + const struct bin_attribute *a, + int bar) +{ + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + + if (!pci_resource_len(pdev, bar)) + return 0; + + return a->attr.mode; +} + +static umode_t pci_dev_resource_is_visible(struct kobject *kobj, + const struct bin_attribute *a, + int bar) +{ + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + struct pci_controller *hose = pdev->sysdata; + + if (has_sparse(hose, pci_bar_mmap_type(pdev, bar))) + return 0; + + return __pci_resource_attr_is_visible(kobj, a, bar); +} + +static umode_t pci_dev_resource_sparse_is_visible(struct kobject *kobj, + const struct bin_attribute *a, + int bar) +{ + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + struct pci_controller *hose = pdev->sysdata; + enum pci_mmap_state type = pci_bar_mmap_type(pdev, bar); + + if (!has_sparse(hose, type)) + return 0; + + if (type == pci_mmap_mem && !sparse_mem_mmap_fits(pdev, bar)) + return 0; + + return __pci_resource_attr_is_visible(kobj, a, bar); +} + +static umode_t pci_dev_resource_dense_is_visible(struct kobject *kobj, + const struct bin_attribute *a, + int bar) +{ + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + struct pci_controller *hose = pdev->sysdata; + enum pci_mmap_state type = pci_bar_mmap_type(pdev, bar); + unsigned long dense_base; + + if (!has_sparse(hose, type)) + return 0; + + if (type == pci_mmap_mem && !sparse_mem_mmap_fits(pdev, bar)) + return __pci_resource_attr_is_visible(kobj, a, bar); + + dense_base = (type == pci_mmap_mem) ? hose->dense_mem_base : + hose->dense_io_base; + if (!dense_base) + return 0; + + return __pci_resource_attr_is_visible(kobj, a, bar); +} + +static inline size_t __pci_dev_resource_bin_size(struct kobject *kobj, + int bar, bool sparse) +{ + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + size_t size = pci_resource_len(pdev, bar); + + return sparse ? size << 5 : size; +} + +static size_t pci_dev_resource_bin_size(struct kobject *kobj, + const struct bin_attribute *a, + int bar) +{ + return __pci_dev_resource_bin_size(kobj, bar, false); +} + +static size_t pci_dev_resource_sparse_bin_size(struct kobject *kobj, + const struct bin_attribute *a, + int bar) +{ + return __pci_dev_resource_bin_size(kobj, bar, true); +} + +static const struct bin_attribute *const pci_dev_resource_attrs[] = { + &pci_dev_resource0_attr, + &pci_dev_resource1_attr, + &pci_dev_resource2_attr, + &pci_dev_resource3_attr, + &pci_dev_resource4_attr, + &pci_dev_resource5_attr, + NULL, +}; + +static const struct bin_attribute *const pci_dev_resource_sparse_attrs[] = { + &pci_dev_resource0_sparse_attr, + &pci_dev_resource1_sparse_attr, + &pci_dev_resource2_sparse_attr, + &pci_dev_resource3_sparse_attr, + &pci_dev_resource4_sparse_attr, + &pci_dev_resource5_sparse_attr, + NULL, +}; + +static const struct bin_attribute *const pci_dev_resource_dense_attrs[] = { + &pci_dev_resource0_dense_attr, + &pci_dev_resource1_dense_attr, + &pci_dev_resource2_dense_attr, + &pci_dev_resource3_dense_attr, + &pci_dev_resource4_dense_attr, + &pci_dev_resource5_dense_attr, + NULL, +}; + +const struct attribute_group pci_dev_resource_attr_group = { + .bin_attrs = pci_dev_resource_attrs, + .is_bin_visible = pci_dev_resource_is_visible, + .bin_size = pci_dev_resource_bin_size, +}; + +const struct attribute_group pci_dev_resource_sparse_attr_group = { + .bin_attrs = pci_dev_resource_sparse_attrs, + .is_bin_visible = pci_dev_resource_sparse_is_visible, + .bin_size = pci_dev_resource_sparse_bin_size, +}; + +const struct attribute_group pci_dev_resource_dense_attr_group = { + .bin_attrs = pci_dev_resource_dense_attrs, + .is_bin_visible = pci_dev_resource_dense_is_visible, + .bin_size = pci_dev_resource_bin_size, +}; 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 dc91de50f906..955b6ca61627 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -224,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; } @@ -255,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; } @@ -290,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; } @@ -322,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 @@ -343,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) { @@ -353,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. */ @@ -429,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)) @@ -643,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; @@ -917,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/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 |
