diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-21 10:47:13 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-21 10:47:13 -0800 |
commit | 0c961c5511fe48834c73215d2203bdac3353dcae (patch) | |
tree | a27fe6de2c087f4f72eb9e2f6ce7af8ea3cd6b51 /arch | |
parent | bc1ecd626bedfa6b8cb09bacd56756ad18aed08f (diff) | |
parent | 160494d381373cfa21208484aea4e5db2d3cb0a8 (diff) |
Merge branch 'parisc-4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc updates from Helge Deller:
- add Kernel address space layout randomization support
- re-enable interrupts earlier now that we have a working IRQ stack
- optimize the timer interrupt function to better cope with missed
timer irqs
- fix error return code in parisc perf code (by Dan Carpenter)
- fix PAT debug code
* 'parisc-4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Optimize timer interrupt function
parisc: perf: return -EFAULT on error
parisc: Enhance CPU detection code on PAT machines
parisc: Re-enable interrupts early
parisc: Enable KASLR
Diffstat (limited to 'arch')
-rw-r--r-- | arch/parisc/Kconfig | 1 | ||||
-rw-r--r-- | arch/parisc/include/asm/elf.h | 7 | ||||
-rw-r--r-- | arch/parisc/include/asm/pdcpat.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/processor.h | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/parisc/kernel/firmware.c | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/inventory.c | 8 | ||||
-rw-r--r-- | arch/parisc/kernel/perf.c | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/parisc/kernel/processor.c | 29 | ||||
-rw-r--r-- | arch/parisc/kernel/sys_parisc.c | 18 | ||||
-rw-r--r-- | arch/parisc/kernel/time.c | 112 |
12 files changed, 67 insertions, 139 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index a14b86587013..3a71f38cdc05 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -7,6 +7,7 @@ config PARISC select HAVE_FUNCTION_GRAPH_TRACER select HAVE_SYSCALL_TRACEPOINTS select ARCH_WANT_FRAME_POINTERS + select ARCH_HAS_ELF_RANDOMIZE select RTC_CLASS select RTC_DRV_GENERIC select INIT_ALL_POSSIBLE diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h index 78c9fd32c554..a6b2a421571e 100644 --- a/arch/parisc/include/asm/elf.h +++ b/arch/parisc/include/asm/elf.h @@ -348,9 +348,10 @@ struct pt_regs; /* forward declaration... */ #define ELF_HWCAP 0 -#define STACK_RND_MASK (is_32bit_task() ? \ - 0x7ff >> (PAGE_SHIFT - 12) : \ - 0x3ffff >> (PAGE_SHIFT - 12)) +/* Masks for stack and mmap randomization */ +#define BRK_RND_MASK (is_32bit_task() ? 0x07ffUL : 0x3ffffUL) +#define MMAP_RND_MASK (is_32bit_task() ? 0x1fffUL : 0x3ffffUL) +#define STACK_RND_MASK MMAP_RND_MASK struct mm_struct; extern unsigned long arch_randomize_brk(struct mm_struct *); diff --git a/arch/parisc/include/asm/pdcpat.h b/arch/parisc/include/asm/pdcpat.h index 47539f117958..e1d289092705 100644 --- a/arch/parisc/include/asm/pdcpat.h +++ b/arch/parisc/include/asm/pdcpat.h @@ -289,7 +289,7 @@ extern int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info); extern int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr); extern int pdc_pat_cell_num_to_loc(void *, unsigned long); -extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa); +extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa); extern int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset); diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index ca40741378be..a3661ee6b060 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -93,9 +93,7 @@ struct system_cpuinfo_parisc { /* Per CPU data structure - ie varies per CPU. */ struct cpuinfo_parisc { unsigned long it_value; /* Interval Timer at last timer Intr */ - unsigned long it_delta; /* Interval delta (tic_10ms / HZ * 100) */ unsigned long irq_count; /* number of IRQ's since boot */ - unsigned long irq_max_cr16; /* longest time to handle a single IRQ */ unsigned long cpuid; /* aka slot_number or set to NO_PROC_ID */ unsigned long hpa; /* Host Physical address */ unsigned long txn_addr; /* MMIO addr of EIR or id_eid */ @@ -103,8 +101,6 @@ struct cpuinfo_parisc { unsigned long pending_ipi; /* bitmap of type ipi_message_type */ #endif unsigned long bh_count; /* number of times bh was invoked */ - unsigned long prof_counter; /* per CPU profiling support */ - unsigned long prof_multiplier; /* per CPU profiling support */ unsigned long fp_rev; unsigned long fp_model; unsigned int state; diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 4fcff2dcc9c3..ad4cb1613c57 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -878,6 +878,9 @@ ENTRY_CFI(syscall_exit_rfi) STREG %r19,PT_SR7(%r16) intr_return: + /* NOTE: Need to enable interrupts incase we schedule. */ + ssm PSW_SM_I, %r0 + /* check for reschedule */ mfctl %cr30,%r1 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ @@ -904,11 +907,6 @@ intr_check_sig: LDREG PT_IASQ1(%r16), %r20 cmpib,COND(=),n 0,%r20,intr_restore /* backward */ - /* NOTE: We need to enable interrupts if we have to deliver - * signals. We used to do this earlier but it caused kernel - * stack overflows. */ - ssm PSW_SM_I, %r0 - copy %r0, %r25 /* long in_syscall = 0 */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ @@ -960,10 +958,6 @@ intr_do_resched: cmpib,COND(=) 0, %r20, intr_do_preempt nop - /* NOTE: We need to enable interrupts if we schedule. We used - * to do this earlier but it caused kernel stack overflows. */ - ssm PSW_SM_I, %r0 - #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index e5d71905cad5..9d797ae4fa22 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1258,7 +1258,7 @@ int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long * * Retrieve the cpu number for the cpu at the specified HPA. */ -int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa) +int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa) { int retval; unsigned long flags; diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index c05d1876d27c..c9789d9c73b4 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -216,9 +216,9 @@ pat_query_module(ulong pcell_loc, ulong mod_index) register_parisc_device(dev); /* advertise device */ #ifdef DEBUG_PAT - pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* dump what we see so far... */ switch (PAT_GET_ENTITY(dev->mod_info)) { + pdc_pat_cell_mod_maddr_block_t io_pdc_cell; unsigned long i; case PAT_ENTITY_PROC: @@ -259,9 +259,9 @@ pat_query_module(ulong pcell_loc, ulong mod_index) pa_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */ printk(KERN_DEBUG " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", - i, io_pdc_cell->mod[2 + i * 3], /* type */ - io_pdc_cell->mod[3 + i * 3], /* start */ - io_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */ + i, io_pdc_cell.mod[2 + i * 3], /* type */ + io_pdc_cell.mod[3 + i * 3], /* start */ + io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ } printk(KERN_DEBUG "\n"); break; diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 518f4f5f1f43..6eabce62463b 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -301,7 +301,6 @@ static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - int err; size_t image_size; uint32_t image_type; uint32_t interface_type; @@ -320,8 +319,8 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun if (count != sizeof(uint32_t)) return -EIO; - if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0) - return err; + if (copy_from_user(&image_type, buf, sizeof(uint32_t))) + return -EFAULT; /* Get the interface type and test type */ interface_type = (image_type >> 16) & 0xffff; diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 40639439d8b3..ea6603ee8d24 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -276,11 +276,7 @@ void *dereference_function_descriptor(void *ptr) static inline unsigned long brk_rnd(void) { - /* 8MB for 32bit, 1GB for 64bit */ - if (is_32bit_task()) - return (get_random_int() & 0x7ffUL) << PAGE_SHIFT; - else - return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT; + return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT; } unsigned long arch_randomize_brk(struct mm_struct *mm) diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 0c2a94a0f751..85de47f4eb59 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -78,11 +78,6 @@ DEFINE_PER_CPU(struct cpuinfo_parisc, cpu_data); static void init_percpu_prof(unsigned long cpunum) { - struct cpuinfo_parisc *p; - - p = &per_cpu(cpu_data, cpunum); - p->prof_counter = 1; - p->prof_multiplier = 1; } @@ -99,6 +94,7 @@ static int processor_probe(struct parisc_device *dev) unsigned long txn_addr; unsigned long cpuid; struct cpuinfo_parisc *p; + struct pdc_pat_cpu_num cpu_info __maybe_unused; #ifdef CONFIG_SMP if (num_online_cpus() >= nr_cpu_ids) { @@ -123,10 +119,6 @@ static int processor_probe(struct parisc_device *dev) ulong status; unsigned long bytecnt; pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; -#undef USE_PAT_CPUID -#ifdef USE_PAT_CPUID - struct pdc_pat_cpu_num cpu_info; -#endif pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL); if (!pa_pdc_cell) @@ -145,22 +137,27 @@ static int processor_probe(struct parisc_device *dev) kfree(pa_pdc_cell); + /* get the cpu number */ + status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start); + BUG_ON(PDC_OK != status); + + pr_info("Logical CPU #%lu is physical cpu #%lu at location " + "0x%lx with hpa %pa\n", + cpuid, cpu_info.cpu_num, cpu_info.cpu_loc, + &dev->hpa.start); + +#undef USE_PAT_CPUID #ifdef USE_PAT_CPUID /* We need contiguous numbers for cpuid. Firmware's notion * of cpuid is for physical CPUs and we just don't care yet. * We'll care when we need to query PAT PDC about a CPU *after* * boot time (ie shutdown a CPU from an OS perspective). */ - /* get the cpu number */ - status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start); - - BUG_ON(PDC_OK != status); - if (cpu_info.cpu_num >= NR_CPUS) { - printk(KERN_WARNING "IGNORING CPU at 0x%x," + printk(KERN_WARNING "IGNORING CPU at %pa," " cpu_slot_id > NR_CPUS" " (%ld > %d)\n", - dev->hpa.start, cpu_info.cpu_num, NR_CPUS); + &dev->hpa.start, cpu_info.cpu_num, NR_CPUS); /* Ignore CPU since it will only crash */ boot_cpu_data.cpu_count--; return 1; diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 0a393a04e891..a81e177cac7b 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -225,19 +225,17 @@ static unsigned long mmap_rnd(void) { unsigned long rnd = 0; - /* - * 8 bits of randomness in 32bit mmaps, 20 address space bits - * 28 bits of randomness in 64bit mmaps, 40 address space bits - */ - if (current->flags & PF_RANDOMIZE) { - if (is_32bit_task()) - rnd = get_random_int() % (1<<8); - else - rnd = get_random_int() % (1<<28); - } + if (current->flags & PF_RANDOMIZE) + rnd = get_random_int() & MMAP_RND_MASK; + return rnd << PAGE_SHIFT; } +unsigned long arch_mmap_rnd(void) +{ + return (get_random_int() & MMAP_RND_MASK) << PAGE_SHIFT; +} + static unsigned long mmap_legacy_base(void) { return TASK_UNMAPPED_BASE + mmap_rnd(); diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 325f30d82b64..4215f5596c8b 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -59,10 +59,9 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */ */ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) { - unsigned long now, now2; + unsigned long now; unsigned long next_tick; - unsigned long cycles_elapsed, ticks_elapsed = 1; - unsigned long cycles_remainder; + unsigned long ticks_elapsed = 0; unsigned int cpu = smp_processor_id(); struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu); @@ -71,102 +70,49 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) profile_tick(CPU_PROFILING); - /* Initialize next_tick to the expected tick time. */ + /* Initialize next_tick to the old expected tick time. */ next_tick = cpuinfo->it_value; - /* Get current cycle counter (Control Register 16). */ - now = mfctl(16); - - cycles_elapsed = now - next_tick; - - if ((cycles_elapsed >> 6) < cpt) { - /* use "cheap" math (add/subtract) instead - * of the more expensive div/mul method - */ - cycles_remainder = cycles_elapsed; - while (cycles_remainder > cpt) { - cycles_remainder -= cpt; - ticks_elapsed++; - } - } else { - /* TODO: Reduce this to one fdiv op */ - cycles_remainder = cycles_elapsed % cpt; - ticks_elapsed += cycles_elapsed / cpt; - } - - /* convert from "division remainder" to "remainder of clock tick" */ - cycles_remainder = cpt - cycles_remainder; - - /* Determine when (in CR16 cycles) next IT interrupt will fire. - * We want IT to fire modulo clocktick even if we miss/skip some. - * But those interrupts don't in fact get delivered that regularly. - */ - next_tick = now + cycles_remainder; + /* Calculate how many ticks have elapsed. */ + do { + ++ticks_elapsed; + next_tick += cpt; + now = mfctl(16); + } while (next_tick - now > cpt); + /* Store (in CR16 cycles) up to when we are accounting right now. */ cpuinfo->it_value = next_tick; - /* Program the IT when to deliver the next interrupt. - * Only bottom 32-bits of next_tick are writable in CR16! - */ - mtctl(next_tick, 16); + /* Go do system house keeping. */ + if (cpu == 0) + xtime_update(ticks_elapsed); + + update_process_times(user_mode(get_irq_regs())); - /* Skip one clocktick on purpose if we missed next_tick. + /* Skip clockticks on purpose if we know we would miss those. * The new CR16 must be "later" than current CR16 otherwise * itimer would not fire until CR16 wrapped - e.g 4 seconds * later on a 1Ghz processor. We'll account for the missed - * tick on the next timer interrupt. + * ticks on the next timer interrupt. + * We want IT to fire modulo clocktick even if we miss/skip some. + * But those interrupts don't in fact get delivered that regularly. * * "next_tick - now" will always give the difference regardless * if one or the other wrapped. If "now" is "bigger" we'll end up * with a very large unsigned number. */ - now2 = mfctl(16); - if (next_tick - now2 > cpt) - mtctl(next_tick+cpt, 16); + while (next_tick - mfctl(16) > cpt) + next_tick += cpt; -#if 1 -/* - * GGG: DEBUG code for how many cycles programming CR16 used. - */ - if (unlikely(now2 - now > 0x3000)) /* 12K cycles */ - printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!" - " cyc %lX rem %lX " - " next/now %lX/%lX\n", - cpu, now2 - now, cycles_elapsed, cycles_remainder, - next_tick, now ); -#endif - - /* Can we differentiate between "early CR16" (aka Scenario 1) and - * "long delay" (aka Scenario 3)? I don't think so. - * - * Timer_interrupt will be delivered at least a few hundred cycles - * after the IT fires. But it's arbitrary how much time passes - * before we call it "late". I've picked one second. - * - * It's important NO printk's are between reading CR16 and - * setting up the next value. May introduce huge variance. - */ - if (unlikely(ticks_elapsed > HZ)) { - /* Scenario 3: very long delay? bad in any case */ - printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" - " cycles %lX rem %lX " - " next/now %lX/%lX\n", - cpu, - cycles_elapsed, cycles_remainder, - next_tick, now ); - } - - /* Done mucking with unreliable delivery of interrupts. - * Go do system house keeping. + /* Program the IT when to deliver the next interrupt. + * Only bottom 32-bits of next_tick are writable in CR16! + * Timer interrupt will be delivered at least a few hundred cycles + * after the IT fires, so if we are too close (<= 500 cycles) to the + * next cycle, simply skip it. */ - - if (!--cpuinfo->prof_counter) { - cpuinfo->prof_counter = cpuinfo->prof_multiplier; - update_process_times(user_mode(get_irq_regs())); - } - - if (cpu == 0) - xtime_update(ticks_elapsed); + if (next_tick - mfctl(16) <= 500) + next_tick += cpt; + mtctl(next_tick, 16); return IRQ_HANDLED; } |