Skip to content

Commit 3e3b391

Browse files
author
Linus Torvalds
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
* git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86: x86: fix "Kernel panic - not syncing: IO-APIC + timer doesn't work!" genirq: revert lazy irq disable for simple irqs x86: also define AT_VECTOR_SIZE_ARCH x86: kprobes bugfix x86: jprobe bugfix timer: kernel/timer.c section fixes genirq: add unlocked version of set_irq_handler() clockevents: fix reprogramming decision in oneshot broadcast oprofile: op_model_athlon.c support for AMD family 10h barcelona performance counters
2 parents 51dad80 + 4aae070 commit 3e3b391

File tree

12 files changed

+102
-90
lines changed

12 files changed

+102
-90
lines changed

arch/x86/kernel/io_apic_32.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,13 +1882,16 @@ __setup("no_timer_check", notimercheck);
18821882
static int __init timer_irq_works(void)
18831883
{
18841884
unsigned long t1 = jiffies;
1885+
unsigned long flags;
18851886

18861887
if (no_timer_check)
18871888
return 1;
18881889

1890+
local_save_flags(flags);
18891891
local_irq_enable();
18901892
/* Let ten ticks pass... */
18911893
mdelay((10 * 1000) / HZ);
1894+
local_irq_restore(flags);
18921895

18931896
/*
18941897
* Expect a few ticks at least, to be sure some possible
@@ -2167,6 +2170,9 @@ static inline void __init check_timer(void)
21672170
int apic1, pin1, apic2, pin2;
21682171
int vector;
21692172
unsigned int ver;
2173+
unsigned long flags;
2174+
2175+
local_irq_save(flags);
21702176

21712177
ver = apic_read(APIC_LVR);
21722178
ver = GET_APIC_VERSION(ver);
@@ -2219,7 +2225,7 @@ static inline void __init check_timer(void)
22192225
}
22202226
if (disable_timer_pin_1 > 0)
22212227
clear_IO_APIC_pin(0, pin1);
2222-
return;
2228+
goto out;
22232229
}
22242230
clear_IO_APIC_pin(apic1, pin1);
22252231
printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
@@ -2242,7 +2248,7 @@ static inline void __init check_timer(void)
22422248
if (nmi_watchdog == NMI_IO_APIC) {
22432249
setup_nmi();
22442250
}
2245-
return;
2251+
goto out;
22462252
}
22472253
/*
22482254
* Cleanup, just in case ...
@@ -2266,7 +2272,7 @@ static inline void __init check_timer(void)
22662272

22672273
if (timer_irq_works()) {
22682274
printk(" works.\n");
2269-
return;
2275+
goto out;
22702276
}
22712277
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
22722278
printk(" failed.\n");
@@ -2282,11 +2288,13 @@ static inline void __init check_timer(void)
22822288

22832289
if (timer_irq_works()) {
22842290
printk(" works.\n");
2285-
return;
2291+
goto out;
22862292
}
22872293
printk(" failed :(.\n");
22882294
panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
22892295
"report. Then try booting with the 'noapic' option");
2296+
out:
2297+
local_irq_restore(flags);
22902298
}
22912299

22922300
/*

arch/x86/kernel/io_apic_64.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,10 +1281,13 @@ void disable_IO_APIC(void)
12811281
static int __init timer_irq_works(void)
12821282
{
12831283
unsigned long t1 = jiffies;
1284+
unsigned long flags;
12841285

1286+
local_save_flags(flags);
12851287
local_irq_enable();
12861288
/* Let ten ticks pass... */
12871289
mdelay((10 * 1000) / HZ);
1290+
local_irq_restore(flags);
12881291

12891292
/*
12901293
* Expect a few ticks at least, to be sure some possible
@@ -1655,6 +1658,9 @@ static inline void check_timer(void)
16551658
{
16561659
struct irq_cfg *cfg = irq_cfg + 0;
16571660
int apic1, pin1, apic2, pin2;
1661+
unsigned long flags;
1662+
1663+
local_irq_save(flags);
16581664

16591665
/*
16601666
* get/set the timer IRQ vector:
@@ -1696,7 +1702,7 @@ static inline void check_timer(void)
16961702
}
16971703
if (disable_timer_pin_1 > 0)
16981704
clear_IO_APIC_pin(0, pin1);
1699-
return;
1705+
goto out;
17001706
}
17011707
clear_IO_APIC_pin(apic1, pin1);
17021708
apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
@@ -1718,7 +1724,7 @@ static inline void check_timer(void)
17181724
if (nmi_watchdog == NMI_IO_APIC) {
17191725
setup_nmi();
17201726
}
1721-
return;
1727+
goto out;
17221728
}
17231729
/*
17241730
* Cleanup, just in case ...
@@ -1741,7 +1747,7 @@ static inline void check_timer(void)
17411747

17421748
if (timer_irq_works()) {
17431749
apic_printk(APIC_VERBOSE," works.\n");
1744-
return;
1750+
goto out;
17451751
}
17461752
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
17471753
apic_printk(APIC_VERBOSE," failed.\n");
@@ -1756,10 +1762,12 @@ static inline void check_timer(void)
17561762

17571763
if (timer_irq_works()) {
17581764
apic_printk(APIC_VERBOSE," works.\n");
1759-
return;
1765+
goto out;
17601766
}
17611767
apic_printk(APIC_VERBOSE," failed :(.\n");
17621768
panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
1769+
out:
1770+
local_irq_restore(flags);
17631771
}
17641772

17651773
static int __init notimercheck(char *s)

arch/x86/kernel/kprobes_32.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
727727

728728
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
729729
if (&regs->esp != kcb->jprobe_saved_esp) {
730-
struct pt_regs *saved_regs =
731-
container_of(kcb->jprobe_saved_esp,
732-
struct pt_regs, esp);
730+
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
733731
printk("current esp %p does not match saved esp %p\n",
734732
&regs->esp, kcb->jprobe_saved_esp);
735733
printk("Saved registers for jprobe %p\n", jp);

arch/x86/kernel/kprobes_64.c

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,6 @@ static void __kprobes resume_execution(struct kprobe *p,
485485
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
486486
{
487487
unsigned long *tos = (unsigned long *)regs->rsp;
488-
unsigned long next_rip = 0;
489488
unsigned long copy_rip = (unsigned long)p->ainsn.insn;
490489
unsigned long orig_rip = (unsigned long)p->addr;
491490
kprobe_opcode_t *insn = p->ainsn.insn;
@@ -494,46 +493,42 @@ static void __kprobes resume_execution(struct kprobe *p,
494493
if (*insn >= 0x40 && *insn <= 0x4f)
495494
insn++;
496495

496+
regs->eflags &= ~TF_MASK;
497497
switch (*insn) {
498-
case 0x9c: /* pushfl */
498+
case 0x9c: /* pushfl */
499499
*tos &= ~(TF_MASK | IF_MASK);
500500
*tos |= kcb->kprobe_old_rflags;
501501
break;
502-
case 0xc3: /* ret/lret */
503-
case 0xcb:
504-
case 0xc2:
502+
case 0xc2: /* iret/ret/lret */
503+
case 0xc3:
505504
case 0xca:
506-
regs->eflags &= ~TF_MASK;
507-
/* rip is already adjusted, no more changes required*/
508-
return;
509-
case 0xe8: /* call relative - Fix return addr */
505+
case 0xcb:
506+
case 0xcf:
507+
case 0xea: /* jmp absolute -- ip is correct */
508+
/* ip is already adjusted, no more changes required */
509+
goto no_change;
510+
case 0xe8: /* call relative - Fix return addr */
510511
*tos = orig_rip + (*tos - copy_rip);
511512
break;
512513
case 0xff:
513514
if ((insn[1] & 0x30) == 0x10) {
514515
/* call absolute, indirect */
515-
/* Fix return addr; rip is correct. */
516-
next_rip = regs->rip;
516+
/* Fix return addr; ip is correct. */
517517
*tos = orig_rip + (*tos - copy_rip);
518+
goto no_change;
518519
} else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
519520
((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
520-
/* rip is correct. */
521-
next_rip = regs->rip;
521+
/* ip is correct. */
522+
goto no_change;
522523
}
523-
break;
524-
case 0xea: /* jmp absolute -- rip is correct */
525-
next_rip = regs->rip;
526-
break;
527524
default:
528525
break;
529526
}
530527

531-
regs->eflags &= ~TF_MASK;
532-
if (next_rip) {
533-
regs->rip = next_rip;
534-
} else {
535-
regs->rip = orig_rip + (regs->rip - copy_rip);
536-
}
528+
regs->rip = orig_rip + (regs->rip - copy_rip);
529+
no_change:
530+
531+
return;
537532
}
538533

539534
int __kprobes post_kprobe_handler(struct pt_regs *regs)
@@ -716,10 +711,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
716711
struct jprobe *jp = container_of(p, struct jprobe, kp);
717712

718713
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
719-
if ((long *)regs->rsp != kcb->jprobe_saved_rsp) {
720-
struct pt_regs *saved_regs =
721-
container_of(kcb->jprobe_saved_rsp,
722-
struct pt_regs, rsp);
714+
if ((unsigned long *)regs->rsp != kcb->jprobe_saved_rsp) {
715+
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
723716
printk("current rsp %p does not match saved rsp %p\n",
724717
(long *)regs->rsp, kcb->jprobe_saved_rsp);
725718
printk("Saved registers for jprobe %p\n", jp);

arch/x86/oprofile/op_model_athlon.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file op_model_athlon.h
3-
* athlon / K7 model-specific MSR operations
3+
* athlon / K7 / K8 / Family 10h model-specific MSR operations
44
*
55
* @remark Copyright 2002 OProfile authors
66
* @remark Read the file COPYING
@@ -31,12 +31,16 @@
3131
#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
3232
#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
3333
#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
34-
#define CTRL_CLEAR(x) (x &= (1<<21))
34+
#define CTRL_CLEAR_LO(x) (x &= (1<<21))
35+
#define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0)
3536
#define CTRL_SET_ENABLE(val) (val |= 1<<20)
3637
#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
3738
#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
3839
#define CTRL_SET_UM(val, m) (val |= (m << 8))
39-
#define CTRL_SET_EVENT(val, e) (val |= e)
40+
#define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff))
41+
#define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf))
42+
#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9))
43+
#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8))
4044

4145
static unsigned long reset_value[NUM_COUNTERS];
4246

@@ -70,7 +74,8 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
7074
if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
7175
continue;
7276
CTRL_READ(low, high, msrs, i);
73-
CTRL_CLEAR(low);
77+
CTRL_CLEAR_LO(low);
78+
CTRL_CLEAR_HI(high);
7479
CTRL_WRITE(low, high, msrs, i);
7580
}
7681

@@ -89,12 +94,17 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
8994
CTR_WRITE(counter_config[i].count, msrs, i);
9095

9196
CTRL_READ(low, high, msrs, i);
92-
CTRL_CLEAR(low);
97+
CTRL_CLEAR_LO(low);
98+
CTRL_CLEAR_HI(high);
9399
CTRL_SET_ENABLE(low);
94100
CTRL_SET_USR(low, counter_config[i].user);
95101
CTRL_SET_KERN(low, counter_config[i].kernel);
96102
CTRL_SET_UM(low, counter_config[i].unit_mask);
97-
CTRL_SET_EVENT(low, counter_config[i].event);
103+
CTRL_SET_EVENT_LOW(low, counter_config[i].event);
104+
CTRL_SET_EVENT_HIGH(high, counter_config[i].event);
105+
CTRL_SET_HOST_ONLY(high, 0);
106+
CTRL_SET_GUEST_ONLY(high, 0);
107+
98108
CTRL_WRITE(low, high, msrs, i);
99109
} else {
100110
reset_value[i] = 0;

include/asm-x86/kprobes_32.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ struct kprobe_ctlblk {
7373
unsigned long kprobe_status;
7474
unsigned long kprobe_old_eflags;
7575
unsigned long kprobe_saved_eflags;
76-
long *jprobe_saved_esp;
76+
unsigned long *jprobe_saved_esp;
7777
struct pt_regs jprobe_saved_regs;
7878
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
7979
struct prev_kprobe prev_kprobe;

include/asm-x86/kprobes_64.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct kprobe_ctlblk {
6666
unsigned long kprobe_status;
6767
unsigned long kprobe_old_rflags;
6868
unsigned long kprobe_saved_rflags;
69-
long *jprobe_saved_rsp;
69+
unsigned long *jprobe_saved_rsp;
7070
struct pt_regs jprobe_saved_regs;
7171
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
7272
struct prev_kprobe prev_kprobe;

include/asm-x86/system_64.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77

88
#ifdef __KERNEL__
99

10+
/* entries in ARCH_DLINFO: */
11+
#ifdef CONFIG_IA32_EMULATION
12+
# define AT_VECTOR_SIZE_ARCH 2
13+
#else
14+
# define AT_VECTOR_SIZE_ARCH 1
15+
#endif
16+
1017
#define __SAVE(reg,offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
1118
#define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
1219

include/linux/irq.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,13 @@ extern void
339339
__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
340340
const char *name);
341341

342+
/* caller has locked the irq_desc and both params are valid */
343+
static inline void __set_irq_handler_unlocked(int irq,
344+
irq_flow_handler_t handler)
345+
{
346+
irq_desc[irq].handle_irq = handler;
347+
}
348+
342349
/*
343350
* Set a highlevel flow handler for a given IRQ:
344351
*/

kernel/irq/chip.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,18 +297,13 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
297297

298298
if (unlikely(desc->status & IRQ_INPROGRESS))
299299
goto out_unlock;
300+
desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
300301
kstat_cpu(cpu).irqs[irq]++;
301302

302303
action = desc->action;
303-
if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
304-
if (desc->chip->mask)
305-
desc->chip->mask(irq);
306-
desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
307-
desc->status |= IRQ_PENDING;
304+
if (unlikely(!action || (desc->status & IRQ_DISABLED)))
308305
goto out_unlock;
309-
}
310306

311-
desc->status &= ~(IRQ_REPLAY | IRQ_WAITING | IRQ_PENDING);
312307
desc->status |= IRQ_INPROGRESS;
313308
spin_unlock(&desc->lock);
314309

0 commit comments

Comments
 (0)