From b8a64c8808be7549b4ca378a54dd8dae9a3d6032 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 13 Jun 2016 07:53:38 +0800 Subject: [PATCH] x86_64/timer: Xtimer is generic enough for per-cpu timer. --- sys/kern/kern_systimer.c | 27 ++++++++ sys/platform/pc64/apic/apic_vector.s | 4 +- sys/platform/pc64/apic/lapic.c | 85 ------------------------ sys/platform/pc64/include/intr_machdep.h | 2 +- sys/platform/pc64/x86_64/ipl.s | 4 +- sys/platform/pc64/x86_64/machdep.c | 60 +++++++++++++++++ 6 files changed, 92 insertions(+), 90 deletions(-) diff --git a/sys/kern/kern_systimer.c b/sys/kern/kern_systimer.c index 50283004a8..a73d1a0730 100644 --- a/sys/kern/kern_systimer.c +++ b/sys/kern/kern_systimer.c @@ -58,6 +58,9 @@ #include #include +extern void pcpu_timer_process(void); +extern void pcpu_timer_process_frame(struct intrframe *); + /* * Execute ready systimers. Called directly from the platform-specific * one-shot timer clock interrupt (e.g. clkintr()) or via an IPI. May @@ -298,3 +301,27 @@ systimer_init_oneshot(systimer_t info, systimer_func_t func, void *data, int us) info->gd = mycpu; systimer_add(info); } + +static void +pcpu_timer_process_oncpu(struct globaldata *gd, struct intrframe *frame) +{ + sysclock_t count; + + gd->gd_timer_running = 0; + + count = sys_cputimer->count(); + if (TAILQ_FIRST(&gd->gd_systimerq) != NULL) + systimer_intr(&count, 0, frame); +} + +void +pcpu_timer_process(void) +{ + pcpu_timer_process_oncpu(mycpu, NULL); +} + +void +pcpu_timer_process_frame(struct intrframe *frame) +{ + pcpu_timer_process_oncpu(mycpu, frame); +} diff --git a/sys/platform/pc64/apic/apic_vector.s b/sys/platform/pc64/apic/apic_vector.s index 2cf8dab45f..a2f351bbcc 100644 --- a/sys/platform/pc64/apic/apic_vector.s +++ b/sys/platform/pc64/apic/apic_vector.s @@ -348,7 +348,7 @@ Xtimer: subq $8,%rsp /* make same as interrupt frame */ movq %rsp,%rdi /* pass frame by reference */ - call lapic_timer_always + call pcpu_timer_always addq $8,%rsp /* turn into trapframe */ incl PCPU(cnt) + V_TIMER @@ -364,7 +364,7 @@ Xtimer: incl PCPU(intr_nesting_level) incl TD_CRITCOUNT(%rbx) sti - call lapic_timer_process_frame + call pcpu_timer_process_frame decl TD_CRITCOUNT(%rbx) decl PCPU(intr_nesting_level) addq $8,%rsp /* turn into trapframe */ diff --git a/sys/platform/pc64/apic/lapic.c b/sys/platform/pc64/apic/lapic.c index 1d7793c0a4..7e9df916cf 100644 --- a/sys/platform/pc64/apic/lapic.c +++ b/sys/platform/pc64/apic/lapic.c @@ -55,9 +55,6 @@ static void lapic_timer_set_divisor(int); static void lapic_timer_fixup_handler(void *); static void lapic_timer_restart_handler(void *); -void lapic_timer_process(void); -void lapic_timer_process_frame(struct intrframe *); -void lapic_timer_always(struct intrframe *); static int lapic_timer_enable = 1; TUNABLE_INT("hw.lapic_timer_enable", &lapic_timer_enable); @@ -330,88 +327,6 @@ lapic_timer_calibrate(void) lapic_timer_divisor_idx, lapic_cputimer_intr.freq); } -static void -lapic_timer_process_oncpu(struct globaldata *gd, struct intrframe *frame) -{ - sysclock_t count; - - gd->gd_timer_running = 0; - - count = sys_cputimer->count(); - if (TAILQ_FIRST(&gd->gd_systimerq) != NULL) - systimer_intr(&count, 0, frame); -} - -void -lapic_timer_process(void) -{ - lapic_timer_process_oncpu(mycpu, NULL); -} - -void -lapic_timer_process_frame(struct intrframe *frame) -{ - lapic_timer_process_oncpu(mycpu, frame); -} - -/* - * This manual debugging code is called unconditionally from Xtimer - * (the lapic timer interrupt) whether the current thread is in a - * critical section or not) and can be useful in tracking down lockups. - * - * NOTE: MANUAL DEBUG CODE - */ -#if 0 -static int saveticks[SMP_MAXCPU]; -static int savecounts[SMP_MAXCPU]; -#endif - -void -lapic_timer_always(struct intrframe *frame) -{ -#if 0 - globaldata_t gd = mycpu; - int cpu = gd->gd_cpuid; - char buf[64]; - short *gptr; - int i; - - if (cpu <= 20) { - gptr = (short *)0xFFFFFFFF800b8000 + 80 * cpu; - *gptr = ((*gptr + 1) & 0x00FF) | 0x0700; - ++gptr; - - ksnprintf(buf, sizeof(buf), " %p %16s %d %16s ", - (void *)frame->if_rip, gd->gd_curthread->td_comm, ticks, - gd->gd_infomsg); - for (i = 0; buf[i]; ++i) { - gptr[i] = 0x0700 | (unsigned char)buf[i]; - } - } -#if 0 - if (saveticks[gd->gd_cpuid] != ticks) { - saveticks[gd->gd_cpuid] = ticks; - savecounts[gd->gd_cpuid] = 0; - } - ++savecounts[gd->gd_cpuid]; - if (savecounts[gd->gd_cpuid] > 2000 && panicstr == NULL) { - panic("cpud %d panicing on ticks failure", - gd->gd_cpuid); - } - for (i = 0; i < ncpus; ++i) { - int delta; - if (saveticks[i] && panicstr == NULL) { - delta = saveticks[i] - ticks; - if (delta < -10 || delta > 10) { - panic("cpu %d panicing on cpu %d watchdog", - gd->gd_cpuid, i); - } - } - } -#endif -#endif -} - static void lapic_timer_intr_reload(struct cputimer_intr *cti, sysclock_t reload) { diff --git a/sys/platform/pc64/include/intr_machdep.h b/sys/platform/pc64/include/intr_machdep.h index afad0f7678..4224aa0c55 100644 --- a/sys/platform/pc64/include/intr_machdep.h +++ b/sys/platform/pc64/include/intr_machdep.h @@ -138,7 +138,7 @@ typedef void inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); inthand_t Xspuriousint, /* handle APIC "spurious INTs" */ - Xtimer; /* handle LAPIC timer INT */ + Xtimer; /* handle per-cpu timer INT */ inthand_t Xinvltlb, /* TLB shootdowns */ diff --git a/sys/platform/pc64/x86_64/ipl.s b/sys/platform/pc64/x86_64/ipl.s index 6d19ce6b62..3198d176fe 100644 --- a/sys/platform/pc64/x86_64/ipl.s +++ b/sys/platform/pc64/x86_64/ipl.s @@ -324,7 +324,7 @@ doreti_timer: sti subq $8,%rsp /* trapframe->intrframe */ movq %rsp,%rdi /* pass frame by ref (C arg) */ - call lapic_timer_process_frame + call pcpu_timer_process_frame addq $8,%rsp /* intrframe->trapframe */ decl PCPU(intr_nesting_level) movl %r12d,%eax /* restore cpl for loop */ @@ -446,7 +446,7 @@ splz_timer: andl $~RQF_TIMER,PCPU(reqflags) sti pushq %rax - call lapic_timer_process + call pcpu_timer_process popq %rax jmp splz_next diff --git a/sys/platform/pc64/x86_64/machdep.c b/sys/platform/pc64/x86_64/machdep.c index 00024b2498..9191b8ca23 100644 --- a/sys/platform/pc64/x86_64/machdep.c +++ b/sys/platform/pc64/x86_64/machdep.c @@ -154,6 +154,8 @@ extern void ffs_rawread_setup(void); #endif /* DIRECTIO */ static void init_locks(void); +extern void pcpu_timer_always(struct intrframe *); + SYSINIT(cpu, SI_BOOT2_START_CPU, SI_ORDER_FIRST, cpu_startup, NULL); SYSINIT(pic_finish, SI_BOOT2_FINISH_PIC, SI_ORDER_FIRST, pic_finish, NULL); SYSINIT(cpu_finish, SI_BOOT2_FINISH_CPU, SI_ORDER_FIRST, cpu_finish, NULL); @@ -3070,3 +3072,61 @@ cpu_mwait_cx_spin_sysctl(SYSCTL_HANDLER_ARGS) &cpu_mwait_spin, FALSE); return error; } + +/* + * This manual debugging code is called unconditionally from Xtimer + * (the per-cpu timer interrupt) whether the current thread is in a + * critical section or not) and can be useful in tracking down lockups. + * + * NOTE: MANUAL DEBUG CODE + */ +#if 0 +static int saveticks[SMP_MAXCPU]; +static int savecounts[SMP_MAXCPU]; +#endif + +void +pcpu_timer_always(struct intrframe *frame) +{ +#if 0 + globaldata_t gd = mycpu; + int cpu = gd->gd_cpuid; + char buf[64]; + short *gptr; + int i; + + if (cpu <= 20) { + gptr = (short *)0xFFFFFFFF800b8000 + 80 * cpu; + *gptr = ((*gptr + 1) & 0x00FF) | 0x0700; + ++gptr; + + ksnprintf(buf, sizeof(buf), " %p %16s %d %16s ", + (void *)frame->if_rip, gd->gd_curthread->td_comm, ticks, + gd->gd_infomsg); + for (i = 0; buf[i]; ++i) { + gptr[i] = 0x0700 | (unsigned char)buf[i]; + } + } +#if 0 + if (saveticks[gd->gd_cpuid] != ticks) { + saveticks[gd->gd_cpuid] = ticks; + savecounts[gd->gd_cpuid] = 0; + } + ++savecounts[gd->gd_cpuid]; + if (savecounts[gd->gd_cpuid] > 2000 && panicstr == NULL) { + panic("cpud %d panicing on ticks failure", + gd->gd_cpuid); + } + for (i = 0; i < ncpus; ++i) { + int delta; + if (saveticks[i] && panicstr == NULL) { + delta = saveticks[i] - ticks; + if (delta < -10 || delta > 10) { + panic("cpu %d panicing on cpu %d watchdog", + gd->gd_cpuid, i); + } + } + } +#endif +#endif +} -- 2.41.0