Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 19764
b: refs/heads/master
c: 73dea47
h: refs/heads/master
v: v3
  • Loading branch information
Andi Kleen authored and Linus Torvalds committed Feb 5, 2006
1 parent fa580e9 commit 0da8530
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 76b461c21468f41837283b7888d55f1c0671f719
refs/heads/master: 73dea47faeb96d54a984b9d7f4de564816966354
7 changes: 7 additions & 0 deletions trunk/Documentation/x86_64/boot-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ APICs
no_timer_check Don't check the IO-APIC timer. This can work around
problems with incorrect timer initialization on some boards.

apicmaintimer Run time keeping from the local APIC timer instead
of using the PIT/HPET interrupt for this. This is useful
when the PIT/HPET interrupts are unreliable.

noapicmaintimer Don't do time keeping using the APIC timer.
Useful when this option was auto selected, but doesn't work.

Early Console

syntax: earlyprintk=vga
Expand Down
34 changes: 32 additions & 2 deletions trunk/arch/x86_64/kernel/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@
#include <asm/mach_apic.h>
#include <asm/nmi.h>
#include <asm/idle.h>
#include <asm/proto.h>
#include <asm/timex.h>

int apic_verbosity;
int apic_runs_main_timer;

int disable_apic_timer __initdata;

Expand Down Expand Up @@ -702,9 +705,17 @@ static void setup_APIC_timer(unsigned int clocks)
c2 |= inb_p(0x40) << 8;
} while (c2 - c1 < 300);
}

__setup_APIC_LVTT(clocks);

/* Turn off PIT interrupt if we use APIC timer as main timer.
Only works with the PM timer right now
TBD fix it for HPET too. */
if (vxtime.mode == VXTIME_PMTMR &&
smp_processor_id() == boot_cpu_id &&
apic_runs_main_timer == 1 &&
!cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) {
stop_timer_interrupt();
apic_runs_main_timer++;
}
local_irq_restore(flags);
}

Expand Down Expand Up @@ -872,6 +883,8 @@ void smp_local_timer_interrupt(struct pt_regs *regs)
#ifdef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id)
main_timer_handler(regs);
/*
* We take the 'long' return path, and there every subsystem
* grabs the appropriate locks (kernel lock/ irq lock).
Expand Down Expand Up @@ -1081,10 +1094,27 @@ static __init int setup_nolapic(char *str)

static __init int setup_noapictimer(char *str)
{
if (str[0] != ' ' && str[0] != 0)
return -1;
disable_apic_timer = 1;
return 0;
}

static __init int setup_apicmaintimer(char *str)
{
apic_runs_main_timer = 1;
nohpet = 1;
return 0;
}
__setup("apicmaintimer", setup_apicmaintimer);

static __init int setup_noapicmaintimer(char *str)
{
apic_runs_main_timer = -1;
return 0;
}
__setup("noapicmaintimer", setup_noapicmaintimer);

/* dummy parsing: see setup.c */

__setup("disableapic", setup_disableapic);
Expand Down
45 changes: 38 additions & 7 deletions trunk/arch/x86_64/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extern int using_apic_timer;
DEFINE_SPINLOCK(rtc_lock);
DEFINE_SPINLOCK(i8253_lock);

static int nohpet __initdata = 0;
int nohpet __initdata = 0;
static int notsc __initdata = 0;

#undef HPET_HACK_ENABLE_DANGEROUS
Expand Down Expand Up @@ -345,7 +345,7 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
#endif
}

static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
void main_timer_handler(struct pt_regs *regs)
{
static unsigned long rtc_update = 0;
unsigned long tsc;
Expand Down Expand Up @@ -458,12 +458,17 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}

write_sequnlock(&xtime_lock);
}

static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
if (apic_runs_main_timer > 1)
return IRQ_HANDLED;
main_timer_handler(regs);
#ifdef CONFIG_X86_LOCAL_APIC
if (using_apic_timer)
smp_send_timer_broadcast_ipi();
#endif

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -843,17 +848,43 @@ static int hpet_reenable(void)
return hpet_timer_stop_set_go(hpet_tick);
}

void __init pit_init(void)
#define PIT_MODE 0x43
#define PIT_CH0 0x40

static void __init __pit_init(int val, u8 mode)
{
unsigned long flags;

spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff, 0x40); /* LSB */
outb_p(LATCH >> 8, 0x40); /* MSB */
outb_p(mode, PIT_MODE);
outb_p(val & 0xff, PIT_CH0); /* LSB */
outb_p(val >> 8, PIT_CH0); /* MSB */
spin_unlock_irqrestore(&i8253_lock, flags);
}

void __init pit_init(void)
{
__pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
}

void __init pit_stop_interrupt(void)
{
__pit_init(0, 0x30); /* mode 0 */
}

void __init stop_timer_interrupt(void)
{
char *name;
if (vxtime.hpet_address) {
name = "HPET";
hpet_timer_stop_set_go(0);
} else {
name = "PIT";
pit_stop_interrupt();
}
printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
}

int __init time_setup(char *str)
{
report_lost_ticks = 1;
Expand Down
1 change: 1 addition & 0 deletions trunk/include/asm-x86_64/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define APIC_DEBUG 2

extern int apic_verbosity;
extern int apic_runs_main_timer;

/*
* Define the default level of output to be very little
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/asm-x86_64/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ extern u32 pmtmr_ioport;
#endif
extern unsigned long long monotonic_base;
extern int sysctl_vsyscall;
extern int nohpet;
extern unsigned long vxtime_hz;

extern void do_softirq_thunk(void);

Expand All @@ -69,6 +71,9 @@ extern void free_bootmem_generic(unsigned long phys, unsigned len);

extern void load_gs_index(unsigned gs);

extern void stop_timer_interrupt(void);
extern void main_timer_handler(struct pt_regs *regs);

extern unsigned long end_pfn_map;

extern void show_trace(unsigned long * rsp);
Expand Down

0 comments on commit 0da8530

Please sign in to comment.