aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-21 13:47:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-21 13:47:13 -0500
commit0c961c5511fe48834c73215d2203bdac3353dcae (patch)
treea27fe6de2c087f4f72eb9e2f6ce7af8ea3cd6b51
parentbc1ecd626bedfa6b8cb09bacd56756ad18aed08f (diff)
parent160494d381373cfa21208484aea4e5db2d3cb0a8 (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
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/include/asm/elf.h7
-rw-r--r--arch/parisc/include/asm/pdcpat.h2
-rw-r--r--arch/parisc/include/asm/processor.h4
-rw-r--r--arch/parisc/kernel/entry.S12
-rw-r--r--arch/parisc/kernel/firmware.c2
-rw-r--r--arch/parisc/kernel/inventory.c8
-rw-r--r--arch/parisc/kernel/perf.c5
-rw-r--r--arch/parisc/kernel/process.c6
-rw-r--r--arch/parisc/kernel/processor.c29
-rw-r--r--arch/parisc/kernel/sys_parisc.c18
-rw-r--r--arch/parisc/kernel/time.c112
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
7 select HAVE_FUNCTION_GRAPH_TRACER 7 select HAVE_FUNCTION_GRAPH_TRACER
8 select HAVE_SYSCALL_TRACEPOINTS 8 select HAVE_SYSCALL_TRACEPOINTS
9 select ARCH_WANT_FRAME_POINTERS 9 select ARCH_WANT_FRAME_POINTERS
10 select ARCH_HAS_ELF_RANDOMIZE
10 select RTC_CLASS 11 select RTC_CLASS
11 select RTC_DRV_GENERIC 12 select RTC_DRV_GENERIC
12 select INIT_ALL_POSSIBLE 13 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... */
348 348
349#define ELF_HWCAP 0 349#define ELF_HWCAP 0
350 350
351#define STACK_RND_MASK (is_32bit_task() ? \ 351/* Masks for stack and mmap randomization */
352 0x7ff >> (PAGE_SHIFT - 12) : \ 352#define BRK_RND_MASK (is_32bit_task() ? 0x07ffUL : 0x3ffffUL)
353 0x3ffff >> (PAGE_SHIFT - 12)) 353#define MMAP_RND_MASK (is_32bit_task() ? 0x1fffUL : 0x3ffffUL)
354#define STACK_RND_MASK MMAP_RND_MASK
354 355
355struct mm_struct; 356struct mm_struct;
356extern unsigned long arch_randomize_brk(struct mm_struct *); 357extern 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);
289extern int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr); 289extern int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr);
290extern int pdc_pat_cell_num_to_loc(void *, unsigned long); 290extern int pdc_pat_cell_num_to_loc(void *, unsigned long);
291 291
292extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa); 292extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa);
293 293
294extern int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset); 294extern int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset);
295 295
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 {
93/* Per CPU data structure - ie varies per CPU. */ 93/* Per CPU data structure - ie varies per CPU. */
94struct cpuinfo_parisc { 94struct cpuinfo_parisc {
95 unsigned long it_value; /* Interval Timer at last timer Intr */ 95 unsigned long it_value; /* Interval Timer at last timer Intr */
96 unsigned long it_delta; /* Interval delta (tic_10ms / HZ * 100) */
97 unsigned long irq_count; /* number of IRQ's since boot */ 96 unsigned long irq_count; /* number of IRQ's since boot */
98 unsigned long irq_max_cr16; /* longest time to handle a single IRQ */
99 unsigned long cpuid; /* aka slot_number or set to NO_PROC_ID */ 97 unsigned long cpuid; /* aka slot_number or set to NO_PROC_ID */
100 unsigned long hpa; /* Host Physical address */ 98 unsigned long hpa; /* Host Physical address */
101 unsigned long txn_addr; /* MMIO addr of EIR or id_eid */ 99 unsigned long txn_addr; /* MMIO addr of EIR or id_eid */
@@ -103,8 +101,6 @@ struct cpuinfo_parisc {
103 unsigned long pending_ipi; /* bitmap of type ipi_message_type */ 101 unsigned long pending_ipi; /* bitmap of type ipi_message_type */
104#endif 102#endif
105 unsigned long bh_count; /* number of times bh was invoked */ 103 unsigned long bh_count; /* number of times bh was invoked */
106 unsigned long prof_counter; /* per CPU profiling support */
107 unsigned long prof_multiplier; /* per CPU profiling support */
108 unsigned long fp_rev; 104 unsigned long fp_rev;
109 unsigned long fp_model; 105 unsigned long fp_model;
110 unsigned int state; 106 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)
878 STREG %r19,PT_SR7(%r16) 878 STREG %r19,PT_SR7(%r16)
879 879
880intr_return: 880intr_return:
881 /* NOTE: Need to enable interrupts incase we schedule. */
882 ssm PSW_SM_I, %r0
883
881 /* check for reschedule */ 884 /* check for reschedule */
882 mfctl %cr30,%r1 885 mfctl %cr30,%r1
883 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ 886 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
@@ -904,11 +907,6 @@ intr_check_sig:
904 LDREG PT_IASQ1(%r16), %r20 907 LDREG PT_IASQ1(%r16), %r20
905 cmpib,COND(=),n 0,%r20,intr_restore /* backward */ 908 cmpib,COND(=),n 0,%r20,intr_restore /* backward */
906 909
907 /* NOTE: We need to enable interrupts if we have to deliver
908 * signals. We used to do this earlier but it caused kernel
909 * stack overflows. */
910 ssm PSW_SM_I, %r0
911
912 copy %r0, %r25 /* long in_syscall = 0 */ 910 copy %r0, %r25 /* long in_syscall = 0 */
913#ifdef CONFIG_64BIT 911#ifdef CONFIG_64BIT
914 ldo -16(%r30),%r29 /* Reference param save area */ 912 ldo -16(%r30),%r29 /* Reference param save area */
@@ -960,10 +958,6 @@ intr_do_resched:
960 cmpib,COND(=) 0, %r20, intr_do_preempt 958 cmpib,COND(=) 0, %r20, intr_do_preempt
961 nop 959 nop
962 960
963 /* NOTE: We need to enable interrupts if we schedule. We used
964 * to do this earlier but it caused kernel stack overflows. */
965 ssm PSW_SM_I, %r0
966
967#ifdef CONFIG_64BIT 961#ifdef CONFIG_64BIT
968 ldo -16(%r30),%r29 /* Reference param save area */ 962 ldo -16(%r30),%r29 /* Reference param save area */
969#endif 963#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
1258 * 1258 *
1259 * Retrieve the cpu number for the cpu at the specified HPA. 1259 * Retrieve the cpu number for the cpu at the specified HPA.
1260 */ 1260 */
1261int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa) 1261int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa)
1262{ 1262{
1263 int retval; 1263 int retval;
1264 unsigned long flags; 1264 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)
216 register_parisc_device(dev); /* advertise device */ 216 register_parisc_device(dev); /* advertise device */
217 217
218#ifdef DEBUG_PAT 218#ifdef DEBUG_PAT
219 pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
220 /* dump what we see so far... */ 219 /* dump what we see so far... */
221 switch (PAT_GET_ENTITY(dev->mod_info)) { 220 switch (PAT_GET_ENTITY(dev->mod_info)) {
221 pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
222 unsigned long i; 222 unsigned long i;
223 223
224 case PAT_ENTITY_PROC: 224 case PAT_ENTITY_PROC:
@@ -259,9 +259,9 @@ pat_query_module(ulong pcell_loc, ulong mod_index)
259 pa_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */ 259 pa_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */
260 printk(KERN_DEBUG 260 printk(KERN_DEBUG
261 " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 261 " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
262 i, io_pdc_cell->mod[2 + i * 3], /* type */ 262 i, io_pdc_cell.mod[2 + i * 3], /* type */
263 io_pdc_cell->mod[3 + i * 3], /* start */ 263 io_pdc_cell.mod[3 + i * 3], /* start */
264 io_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */ 264 io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
265 } 265 }
266 printk(KERN_DEBUG "\n"); 266 printk(KERN_DEBUG "\n");
267 break; 267 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
301static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, 301static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
302 loff_t *ppos) 302 loff_t *ppos)
303{ 303{
304 int err;
305 size_t image_size; 304 size_t image_size;
306 uint32_t image_type; 305 uint32_t image_type;
307 uint32_t interface_type; 306 uint32_t interface_type;
@@ -320,8 +319,8 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun
320 if (count != sizeof(uint32_t)) 319 if (count != sizeof(uint32_t))
321 return -EIO; 320 return -EIO;
322 321
323 if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0) 322 if (copy_from_user(&image_type, buf, sizeof(uint32_t)))
324 return err; 323 return -EFAULT;
325 324
326 /* Get the interface type and test type */ 325 /* Get the interface type and test type */
327 interface_type = (image_type >> 16) & 0xffff; 326 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)
276 276
277static inline unsigned long brk_rnd(void) 277static inline unsigned long brk_rnd(void)
278{ 278{
279 /* 8MB for 32bit, 1GB for 64bit */ 279 return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
280 if (is_32bit_task())
281 return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
282 else
283 return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT;
284} 280}
285 281
286unsigned long arch_randomize_brk(struct mm_struct *mm) 282unsigned 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);
78static void 78static void
79init_percpu_prof(unsigned long cpunum) 79init_percpu_prof(unsigned long cpunum)
80{ 80{
81 struct cpuinfo_parisc *p;
82
83 p = &per_cpu(cpu_data, cpunum);
84 p->prof_counter = 1;
85 p->prof_multiplier = 1;
86} 81}
87 82
88 83
@@ -99,6 +94,7 @@ static int processor_probe(struct parisc_device *dev)
99 unsigned long txn_addr; 94 unsigned long txn_addr;
100 unsigned long cpuid; 95 unsigned long cpuid;
101 struct cpuinfo_parisc *p; 96 struct cpuinfo_parisc *p;
97 struct pdc_pat_cpu_num cpu_info __maybe_unused;
102 98
103#ifdef CONFIG_SMP 99#ifdef CONFIG_SMP
104 if (num_online_cpus() >= nr_cpu_ids) { 100 if (num_online_cpus() >= nr_cpu_ids) {
@@ -123,10 +119,6 @@ static int processor_probe(struct parisc_device *dev)
123 ulong status; 119 ulong status;
124 unsigned long bytecnt; 120 unsigned long bytecnt;
125 pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; 121 pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;
126#undef USE_PAT_CPUID
127#ifdef USE_PAT_CPUID
128 struct pdc_pat_cpu_num cpu_info;
129#endif
130 122
131 pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL); 123 pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL);
132 if (!pa_pdc_cell) 124 if (!pa_pdc_cell)
@@ -145,22 +137,27 @@ static int processor_probe(struct parisc_device *dev)
145 137
146 kfree(pa_pdc_cell); 138 kfree(pa_pdc_cell);
147 139
140 /* get the cpu number */
141 status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start);
142 BUG_ON(PDC_OK != status);
143
144 pr_info("Logical CPU #%lu is physical cpu #%lu at location "
145 "0x%lx with hpa %pa\n",
146 cpuid, cpu_info.cpu_num, cpu_info.cpu_loc,
147 &dev->hpa.start);
148
149#undef USE_PAT_CPUID
148#ifdef USE_PAT_CPUID 150#ifdef USE_PAT_CPUID
149/* We need contiguous numbers for cpuid. Firmware's notion 151/* We need contiguous numbers for cpuid. Firmware's notion
150 * of cpuid is for physical CPUs and we just don't care yet. 152 * of cpuid is for physical CPUs and we just don't care yet.
151 * We'll care when we need to query PAT PDC about a CPU *after* 153 * We'll care when we need to query PAT PDC about a CPU *after*
152 * boot time (ie shutdown a CPU from an OS perspective). 154 * boot time (ie shutdown a CPU from an OS perspective).
153 */ 155 */
154 /* get the cpu number */
155 status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start);
156
157 BUG_ON(PDC_OK != status);
158
159 if (cpu_info.cpu_num >= NR_CPUS) { 156 if (cpu_info.cpu_num >= NR_CPUS) {
160 printk(KERN_WARNING "IGNORING CPU at 0x%x," 157 printk(KERN_WARNING "IGNORING CPU at %pa,"
161 " cpu_slot_id > NR_CPUS" 158 " cpu_slot_id > NR_CPUS"
162 " (%ld > %d)\n", 159 " (%ld > %d)\n",
163 dev->hpa.start, cpu_info.cpu_num, NR_CPUS); 160 &dev->hpa.start, cpu_info.cpu_num, NR_CPUS);
164 /* Ignore CPU since it will only crash */ 161 /* Ignore CPU since it will only crash */
165 boot_cpu_data.cpu_count--; 162 boot_cpu_data.cpu_count--;
166 return 1; 163 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)
225{ 225{
226 unsigned long rnd = 0; 226 unsigned long rnd = 0;
227 227
228 /* 228 if (current->flags & PF_RANDOMIZE)
229 * 8 bits of randomness in 32bit mmaps, 20 address space bits 229 rnd = get_random_int() & MMAP_RND_MASK;
230 * 28 bits of randomness in 64bit mmaps, 40 address space bits 230
231 */
232 if (current->flags & PF_RANDOMIZE) {
233 if (is_32bit_task())
234 rnd = get_random_int() % (1<<8);
235 else
236 rnd = get_random_int() % (1<<28);
237 }
238 return rnd << PAGE_SHIFT; 231 return rnd << PAGE_SHIFT;
239} 232}
240 233
234unsigned long arch_mmap_rnd(void)
235{
236 return (get_random_int() & MMAP_RND_MASK) << PAGE_SHIFT;
237}
238
241static unsigned long mmap_legacy_base(void) 239static unsigned long mmap_legacy_base(void)
242{ 240{
243 return TASK_UNMAPPED_BASE + mmap_rnd(); 241 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 */
59 */ 59 */
60irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) 60irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
61{ 61{
62 unsigned long now, now2; 62 unsigned long now;
63 unsigned long next_tick; 63 unsigned long next_tick;
64 unsigned long cycles_elapsed, ticks_elapsed = 1; 64 unsigned long ticks_elapsed = 0;
65 unsigned long cycles_remainder;
66 unsigned int cpu = smp_processor_id(); 65 unsigned int cpu = smp_processor_id();
67 struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu); 66 struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
68 67
@@ -71,102 +70,49 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
71 70
72 profile_tick(CPU_PROFILING); 71 profile_tick(CPU_PROFILING);
73 72
74 /* Initialize next_tick to the expected tick time. */ 73 /* Initialize next_tick to the old expected tick time. */
75 next_tick = cpuinfo->it_value; 74 next_tick = cpuinfo->it_value;
76 75
77 /* Get current cycle counter (Control Register 16). */ 76 /* Calculate how many ticks have elapsed. */
78 now = mfctl(16); 77 do {
79 78 ++ticks_elapsed;
80 cycles_elapsed = now - next_tick; 79 next_tick += cpt;
81 80 now = mfctl(16);
82 if ((cycles_elapsed >> 6) < cpt) { 81 } while (next_tick - now > cpt);
83 /* use "cheap" math (add/subtract) instead
84 * of the more expensive div/mul method
85 */
86 cycles_remainder = cycles_elapsed;
87 while (cycles_remainder > cpt) {
88 cycles_remainder -= cpt;
89 ticks_elapsed++;
90 }
91 } else {
92 /* TODO: Reduce this to one fdiv op */
93 cycles_remainder = cycles_elapsed % cpt;
94 ticks_elapsed += cycles_elapsed / cpt;
95 }
96
97 /* convert from "division remainder" to "remainder of clock tick" */
98 cycles_remainder = cpt - cycles_remainder;
99
100 /* Determine when (in CR16 cycles) next IT interrupt will fire.
101 * We want IT to fire modulo clocktick even if we miss/skip some.
102 * But those interrupts don't in fact get delivered that regularly.
103 */
104 next_tick = now + cycles_remainder;
105 82
83 /* Store (in CR16 cycles) up to when we are accounting right now. */
106 cpuinfo->it_value = next_tick; 84 cpuinfo->it_value = next_tick;
107 85
108 /* Program the IT when to deliver the next interrupt. 86 /* Go do system house keeping. */
109 * Only bottom 32-bits of next_tick are writable in CR16! 87 if (cpu == 0)
110 */ 88 xtime_update(ticks_elapsed);
111 mtctl(next_tick, 16); 89
90 update_process_times(user_mode(get_irq_regs()));
112 91
113 /* Skip one clocktick on purpose if we missed next_tick. 92 /* Skip clockticks on purpose if we know we would miss those.
114 * The new CR16 must be "later" than current CR16 otherwise 93 * The new CR16 must be "later" than current CR16 otherwise
115 * itimer would not fire until CR16 wrapped - e.g 4 seconds 94 * itimer would not fire until CR16 wrapped - e.g 4 seconds
116 * later on a 1Ghz processor. We'll account for the missed 95 * later on a 1Ghz processor. We'll account for the missed
117 * tick on the next timer interrupt. 96 * ticks on the next timer interrupt.
97 * We want IT to fire modulo clocktick even if we miss/skip some.
98 * But those interrupts don't in fact get delivered that regularly.
118 * 99 *
119 * "next_tick - now" will always give the difference regardless 100 * "next_tick - now" will always give the difference regardless
120 * if one or the other wrapped. If "now" is "bigger" we'll end up 101 * if one or the other wrapped. If "now" is "bigger" we'll end up
121 * with a very large unsigned number. 102 * with a very large unsigned number.
122 */ 103 */
123 now2 = mfctl(16); 104 while (next_tick - mfctl(16) > cpt)
124 if (next_tick - now2 > cpt) 105 next_tick += cpt;
125 mtctl(next_tick+cpt, 16);
126 106
127#if 1 107 /* Program the IT when to deliver the next interrupt.
128/* 108 * Only bottom 32-bits of next_tick are writable in CR16!
129 * GGG: DEBUG code for how many cycles programming CR16 used. 109 * Timer interrupt will be delivered at least a few hundred cycles
130 */ 110 * after the IT fires, so if we are too close (<= 500 cycles) to the
131 if (unlikely(now2 - now > 0x3000)) /* 12K cycles */ 111 * next cycle, simply skip it.
132 printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!"
133 " cyc %lX rem %lX "
134 " next/now %lX/%lX\n",
135 cpu, now2 - now, cycles_elapsed, cycles_remainder,
136 next_tick, now );
137#endif
138
139 /* Can we differentiate between "early CR16" (aka Scenario 1) and
140 * "long delay" (aka Scenario 3)? I don't think so.
141 *
142 * Timer_interrupt will be delivered at least a few hundred cycles
143 * after the IT fires. But it's arbitrary how much time passes
144 * before we call it "late". I've picked one second.
145 *
146 * It's important NO printk's are between reading CR16 and
147 * setting up the next value. May introduce huge variance.
148 */
149 if (unlikely(ticks_elapsed > HZ)) {
150 /* Scenario 3: very long delay? bad in any case */
151 printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
152 " cycles %lX rem %lX "
153 " next/now %lX/%lX\n",
154 cpu,
155 cycles_elapsed, cycles_remainder,
156 next_tick, now );
157 }
158
159 /* Done mucking with unreliable delivery of interrupts.
160 * Go do system house keeping.
161 */ 112 */
162 113 if (next_tick - mfctl(16) <= 500)
163 if (!--cpuinfo->prof_counter) { 114 next_tick += cpt;
164 cpuinfo->prof_counter = cpuinfo->prof_multiplier; 115 mtctl(next_tick, 16);
165 update_process_times(user_mode(get_irq_regs()));
166 }
167
168 if (cpu == 0)
169 xtime_update(ticks_elapsed);
170 116
171 return IRQ_HANDLED; 117 return IRQ_HANDLED;
172} 118}