From 6c5672745624fb3de88d3b0c58dc89d5d524bbdb Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 6 Oct 2000 02:20:21 +0000 Subject: [PATCH] - Change fast interrupts on x86 to push a full interrupt frame and to return through doreti to handle ast's. This is necessary for the clock interrupts to work properly. - Change the clock interrupts on the x86 to be fast instead of threaded. This is needed because both hardclock() and statclock() need to run in the context of the current process, not in a separate thread context. - Kill the prevproc hack as it is no longer needed. - We really need Giant when we call psignal(), but we don't want to block during the clock interrupt. Instead, use two p_flag's in the proc struct to mark the current process as having a pending SIGVTALRM or a SIGPROF and let them be delivered during ast() when hardclock() has finished running. - Remove CLKF_BASEPRI, which was #ifdef'd out on the x86 anyways. It was broken on the x86 if it was turned on since cpl is gone. It's only use was to bogusly run softclock() directly during hardclock() rather than scheduling an SWI. - Remove the COM_LOCK simplelock and replace it with a clock_lock spin mutex. Since the spin mutex already handles disabling/restoring interrupts appropriately, this also lets us axe all the *_intr() fu. - Back out the hacks in the APIC_IO x86 cpu_initclocks() code to use temporary fast interrupts for the APIC trial. - Add two new process flags P_ALRMPEND and P_PROFPEND to mark the pending signals in hardclock() that are to be delivered in ast(). Submitted by: jakeb (making statclock safe in a fast interrupt) Submitted by: cp (concept of delaying signals until ast()) --- sys/alpha/alpha/trap.c | 13 +++ sys/alpha/include/cpu.h | 2 - sys/alpha/include/globals.h | 1 - sys/amd64/amd64/apic_vector.S | 67 ++++++--------- sys/amd64/amd64/cpu_switch.S | 1 - sys/amd64/amd64/genassym.c | 1 - sys/amd64/amd64/machdep.c | 9 +- sys/amd64/amd64/mp_machdep.c | 9 -- sys/amd64/amd64/mptable.c | 9 -- sys/amd64/amd64/swtch.s | 1 - sys/amd64/amd64/trap.c | 12 +++ sys/amd64/amd64/tsc.c | 157 +++++++++++----------------------- sys/amd64/include/cpu.h | 15 ---- sys/amd64/include/mptable.h | 9 -- sys/amd64/include/mutex.h | 1 + sys/amd64/include/pcpu.h | 1 - sys/amd64/isa/atpic_vector.S | 48 ++--------- sys/amd64/isa/clock.c | 157 +++++++++++----------------------- sys/amd64/isa/icu_vector.S | 48 ++--------- sys/amd64/isa/icu_vector.s | 48 ++--------- sys/i386/i386/apic_vector.s | 67 ++++++--------- sys/i386/i386/genassym.c | 1 - sys/i386/i386/globals.s | 6 +- sys/i386/i386/machdep.c | 9 +- sys/i386/i386/mp_machdep.c | 9 -- sys/i386/i386/mptable.c | 9 -- sys/i386/i386/swtch.s | 1 - sys/i386/i386/trap.c | 12 +++ sys/i386/i386/tsc.c | 157 +++++++++++----------------------- sys/i386/include/asnames.h | 1 - sys/i386/include/cpu.h | 15 ---- sys/i386/include/globaldata.h | 1 - sys/i386/include/globals.h | 2 - sys/i386/include/lock.h | 15 ---- sys/i386/include/mptable.h | 9 -- sys/i386/include/mutex.h | 1 + sys/i386/include/pcpu.h | 1 - sys/i386/include/smptests.h | 2 - sys/i386/isa/apic_vector.s | 67 ++++++--------- sys/i386/isa/atpic_vector.s | 48 ++--------- sys/i386/isa/clock.c | 157 +++++++++++----------------------- sys/i386/isa/icu_vector.s | 48 ++--------- sys/isa/atrtc.c | 157 +++++++++++----------------------- sys/kern/kern_clock.c | 42 +++++---- sys/kern/kern_synch.c | 14 +-- sys/kern/subr_smp.c | 9 -- sys/kern/subr_trap.c | 12 +++ sys/powerpc/include/globals.h | 1 - sys/sys/proc.h | 4 +- 49 files changed, 484 insertions(+), 1002 deletions(-) diff --git a/sys/alpha/alpha/trap.c b/sys/alpha/alpha/trap.c index 3e773d3b5186..79019bd6fd89 100644 --- a/sys/alpha/alpha/trap.c +++ b/sys/alpha/alpha/trap.c @@ -784,6 +784,11 @@ ast(framep) sticks = p->p_sticks; p->p_md.md_tf = framep; + /* + * XXX - is this still correct? What about a clock interrupt + * that runs hardclock() and triggers a delayed SIGVTALRM or + * SIGPROF? + */ if ((framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) == 0) panic("ast and not user"); @@ -795,6 +800,14 @@ ast(framep) addupc_task(p, p->p_stats->p_prof.pr_addr, p->p_stats->p_prof.pr_ticks); } + if (p->p_flag & P_ALRMPEND) { + p->p_flag &= ~P_ALRMPEND; + psignal(p, SIGVTALRM); + } + if (p->p_flag & P_PROFPEND) { + p->p_flag &= ~P_PROFPEND; + psignal(p, SIGPROF); + } userret(p, framep->tf_regs[FRAME_PC], sticks, 1); diff --git a/sys/alpha/include/cpu.h b/sys/alpha/include/cpu.h index cd60cc644ddf..a45b4d10558e 100644 --- a/sys/alpha/include/cpu.h +++ b/sys/alpha/include/cpu.h @@ -62,8 +62,6 @@ struct clockframe { }; #define CLKF_USERMODE(framep) \ (((framep)->cf_tf.tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0) -#define CLKF_BASEPRI(framep) \ - (((framep)->cf_tf.tf_regs[FRAME_PS] & ALPHA_PSL_IPL_MASK) == 0) #define CLKF_PC(framep) ((framep)->cf_tf.tf_regs[FRAME_PC]) #define CLKF_INTR(framep) (PCPU_GET(intr_nesting_level) >= 2) diff --git a/sys/alpha/include/globals.h b/sys/alpha/include/globals.h index 303efdfe9f6a..f85a67c4c37e 100644 --- a/sys/alpha/include/globals.h +++ b/sys/alpha/include/globals.h @@ -56,7 +56,6 @@ register struct globaldata *globalp __asm__("$8"); #define switchtime PCPU_GET(switchtime) #define switchticks PCPU_GET(switchticks) #define cpuid PCPU_GET(cpuno) -#define prevproc PCPU_GET(curproc) /* XXX - until ithreads */ #endif /* _KERNEL */ diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index 11d9797e7948..1f80224628b4 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -15,45 +15,6 @@ /* make an index into the IO APIC from the IRQ# */ #define REDTBL_IDX(irq_num) (0x10 + ((irq_num) * 2)) - -/* - * Macros for interrupt entry, call to handler, and exit. - */ - -#define FAST_INTR(irq_num, vec_name) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - pushl %fs ; \ - movl $KDSEL,%eax ; \ - mov %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - movl $KPSEL,%eax ; \ - mov %ax,%fs ; \ - FAKE_MCOUNT((5+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - addl $4, %esp ; \ - movl $0, lapic_eoi ; \ - lock ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4, %eax ; \ - lock ; \ - incl (%eax) ; \ - MEXITCOUNT ; \ - popl %fs ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret - /* * */ @@ -72,6 +33,34 @@ IDTVEC(vec_name) ; \ popal ; \ addl $4+4,%esp +/* + * Macros for interrupt entry, call to handler, and exit. + */ + +#define FAST_INTR(irq_num, vec_name) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(vec_name) ; \ + PUSH_FRAME ; \ + movl $KDSEL,%eax ; \ + mov %ax,%ds ; \ + mov %ax,%es ; \ + movl $KPSEL,%eax ; \ + mov %ax,%fs ; \ + FAKE_MCOUNT(13*4(%esp)) ; \ + incb _intr_nesting_level ; \ + pushl _intr_unit + (irq_num) * 4 ; \ + call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ + addl $4, %esp ; \ + movl $0, lapic_eoi ; \ + lock ; \ + incl _cnt+V_INTR ; /* book-keeping can wait */ \ + movl _intr_countp + (irq_num) * 4, %eax ; \ + lock ; \ + incl (%eax) ; \ + MEXITCOUNT ; \ + jmp doreti_next + #define IOAPICADDR(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 8 #define REDIRIDX(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 12 diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index ac71f0c43be9..32dbe56e686a 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -82,7 +82,6 @@ ENTRY(cpu_switch) /* switch to new process. first, save context as needed */ movl _curproc,%ecx - movl %ecx,_prevproc /* if no process to save, don't bother */ testl %ecx,%ecx diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index 78c607591875..0566dd7e0f45 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -173,7 +173,6 @@ ASSYM(BI_ESYMTAB, offsetof(struct bootinfo, bi_esymtab)); ASSYM(BI_KERNEND, offsetof(struct bootinfo, bi_kernend)); ASSYM(GD_SIZEOF, sizeof(struct globaldata)); ASSYM(GD_CURPROC, offsetof(struct globaldata, gd_curproc)); -ASSYM(GD_PREVPROC, offsetof(struct globaldata, gd_prevproc)); ASSYM(GD_NPXPROC, offsetof(struct globaldata, gd_npxproc)); ASSYM(GD_IDLEPROC, offsetof(struct globaldata, gd_idleproc)); ASSYM(GD_CURPCB, offsetof(struct globaldata, gd_curpcb)); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 355a0a953184..705501062ac8 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1883,7 +1883,6 @@ init386(first) /* setup curproc so that mutexes work */ PCPU_SET(curproc, &proc0); - PCPU_SET(prevproc, &proc0); /* make ldt memory segments */ /* @@ -1944,6 +1943,11 @@ init386(first) r_idt.rd_base = (int) idt; lidt(&r_idt); + /* + * We need this mutex before the console probe. + */ + mtx_init(&clock_lock, "clk interrupt lock", MTX_SPIN); + /* * Initialize the console before we print anything out. */ @@ -1955,8 +1959,7 @@ init386(first) #endif /* - * Giant is used early for at least debugger traps, unexpected traps, - * and vm86bios initialization. + * Giant is used early for at least debugger traps and unexpected traps. */ mtx_init(&Giant, "Giant", MTX_DEF); diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/amd64/amd64/mptable.c +++ b/sys/amd64/amd64/mptable.c @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s index ac71f0c43be9..32dbe56e686a 100644 --- a/sys/amd64/amd64/swtch.s +++ b/sys/amd64/amd64/swtch.s @@ -82,7 +82,6 @@ ENTRY(cpu_switch) /* switch to new process. first, save context as needed */ movl _curproc,%ecx - movl %ecx,_prevproc /* if no process to save, don't bother */ testl %ecx,%ecx diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 1cbfcfad4ed7..b9ebb600cb05 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -1244,6 +1244,18 @@ ast(frame) addupc_task(p, p->p_stats->p_prof.pr_addr, p->p_stats->p_prof.pr_ticks); } + if (p->p_flag & P_ALRMPEND) { + if (!mtx_owned(&Giant)) + mtx_enter(&Giant, MTX_DEF); + p->p_flag &= ~P_ALRMPEND; + psignal(p, SIGVTALRM); + } + if (p->p_flag & P_PROFPEND) { + if (!mtx_owned(&Giant)) + mtx_enter(&Giant, MTX_DEF); + p->p_flag &= ~P_PROFPEND; + psignal(p, SIGPROF); + } if (userret(p, &frame, sticks, mtx_owned(&Giant)) != 0) mtx_exit(&Giant, MTX_DEF); } diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 0e630d9b2d7b..a164288dd17e 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #ifdef APIC_IO #include @@ -139,6 +140,7 @@ int timer0_max_count; u_int tsc_freq; int tsc_is_broken; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +struct mtx clock_lock; static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -198,12 +200,9 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, static void clkintr(struct clockframe frame) { - int intrsave; if (timecounter->tc_get_timecount == i8254_get_timecount) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); if (i8254_ticked) i8254_ticked = 0; else { @@ -211,8 +210,7 @@ clkintr(struct clockframe frame) i8254_lastcount = 0; } clkintr_pending = 0; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } timer_func(&frame); switch (timer0_state) { @@ -231,17 +229,14 @@ clkintr(struct clockframe frame) break; case ACQUIRE_PENDING: - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = TIMER_DIV(new_rate); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer_func = new_function; timer0_state = ACQUIRED; setdelayed(); @@ -250,9 +245,7 @@ clkintr(struct clockframe frame) case RELEASE_PENDING: if ((timer0_prescaler_count += timer0_max_count) >= hardclock_max_count) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = hardclock_max_count; @@ -260,8 +253,7 @@ clkintr(struct clockframe frame) TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer0_prescaler_count = 0; timer_func = hardclock; timer0_state = RELEASED; @@ -408,11 +400,9 @@ DB_SHOW_COMMAND(rtc, rtc) static int getit(void) { - int high, low, intrsave; + int high, low; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -420,8 +410,7 @@ getit(void) low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return ((high << 8) | low); } @@ -527,7 +516,6 @@ sysbeepstop(void *chan) int sysbeep(int pitch, int period) { - int intrsave; int x = splclock(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) @@ -536,13 +524,10 @@ sysbeep(int pitch, int period) splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); if (!beeping) { /* enable counter2 output to speaker */ outb(IO_PPI, inb(IO_PPI) | 3); @@ -691,12 +676,9 @@ fail: static void set_timer_freq(u_int freq, int intr_freq) { - int intrsave; int new_timer0_max_count; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); if (new_timer0_max_count != timer0_max_count) { @@ -705,8 +687,7 @@ set_timer_freq(u_int freq, int intr_freq) outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); } - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -720,16 +701,12 @@ set_timer_freq(u_int freq, int intr_freq) void i8254_restore(void) { - int intrsave; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -989,8 +966,8 @@ cpu_initclocks() { int diag; #ifdef APIC_IO - int apic_8254_trial, num_8254_ticks; - struct intrec *clkdesc, *rtcdesc; + int apic_8254_trial; + struct intrec *clkdesc; #endif /* APIC_IO */ if (statclock_disable) { @@ -1023,6 +1000,11 @@ cpu_initclocks() } else panic("APIC_IO: Cannot route 8254 interrupt to CPU"); } + + clkdesc = inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, + NULL, PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); + #else /* APIC_IO */ /* @@ -1030,9 +1012,8 @@ cpu_initclocks() * couldn't find anything suitable in the BSD/OS code (grog, * 19 July 2000). */ - /* Setup the PIC clk handler. The APIC handler is setup later */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, PI_REALTIME, - INTR_EXCL); + INTR_FAST); INTREN(IRQ0); #endif /* APIC_IO */ @@ -1042,18 +1023,8 @@ cpu_initclocks() writertc(RTC_STATUSB, RTCSB_24HR); /* Don't bother enabling the statistics clock. */ - if (statclock_disable) { -#ifdef APIC_IO - /* - * XXX - if statclock is disabled, don't attempt the APIC - * trial. Not sure this is sane for APIC_IO. - */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, - NULL, PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif /* APIC_IO */ + if (statclock_disable) return; - } diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); @@ -1061,44 +1032,34 @@ cpu_initclocks() #ifdef APIC_IO if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); +#endif /* APIC_IO */ + inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, + INTR_FAST); + +#ifdef APIC_IO + INTREN(APIC_IRQ8); +#else + INTREN(IRQ8); +#endif /* APIC_IO */ + + writertc(RTC_STATUSB, rtc_statusb); + +#ifdef APIC_IO if (apic_8254_trial) { - /* - * XXX - We use fast interrupts for clk and rtc long enough to - * perform the APIC probe and then revert to exclusive - * interrupts. - */ - clkdesc = inthand_add("clk", apic_8254_intr, - (driver_intr_t *)clkintr, NULL, PI_REALTIME, INTR_FAST); - INTREN(1 << apic_8254_intr); - - rtcdesc = inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, - PI_REALTIME, INTR_FAST); /* XXX */ - INTREN(APIC_IRQ8); - writertc(RTC_STATUSB, rtc_statusb); printf("APIC_IO: Testing 8254 interrupt delivery\n"); while (read_intr_count(8) < 6) ; /* nothing */ - num_8254_ticks = read_intr_count(apic_8254_intr); - - /* disable and remove our fake handlers */ - INTRDIS(1 << apic_8254_intr); - inthand_remove(clkdesc); - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - INTRDIS(APIC_IRQ8); - inthand_remove(rtcdesc); - - if (num_8254_ticks < 3) { + if (read_intr_count(apic_8254_intr) < 3) { /* * The MP table is broken. * The 8254 was not connected to the specified pin * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + INTRDIS(1 << apic_8254_intr); + inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " "IOAPIC #%d intpin %d\n", @@ -1117,27 +1078,13 @@ cpu_initclocks() } apic_8254_intr = apic_irq(0, 0); setup_8254_mixed_mode(); + inthand_add("clk", apic_8254_intr, + (driver_intr_t *)clkintr, NULL, + PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); } } - - /* Finally, setup the real clock handlers */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, - PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif - - inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, - INTR_EXCL); -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || int_to_apicintpin[apic_8254_intr].int_pin != 0) @@ -1242,12 +1189,11 @@ static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; - int intrsave; u_int high, low; + u_int eflags; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + eflags = read_eflags(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -1257,7 +1203,7 @@ i8254_get_timecount(struct timecounter *tc) count = timer0_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(intrsave & PSL_I) && count < timer0_max_count / 2u)) && + ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && #ifdef APIC_IO #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ /* XXX this assumes that apic_8254_intr is < 24. */ @@ -1271,8 +1217,7 @@ i8254_get_timecount(struct timecounter *tc) } i8254_lastcount = count; count += i8254_offset; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return (count); } diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h index 18822b87cc5b..d35b94077130 100644 --- a/sys/amd64/include/cpu.h +++ b/sys/amd64/include/cpu.h @@ -62,21 +62,6 @@ ((ISPL((framep)->cf_cs) == SEL_UPL) || (framep->cf_eflags & PSL_VM)) #define CLKF_INTR(framep) (intr_nesting_level >= 2) -#if 0 -/* - * XXX splsoftclock() is very broken and barely worth fixing. It doesn't - * turn off the clock bit in imen or in the icu. (This is not a serious - * problem at 100 Hz but it is serious at 16000 Hz for pcaudio. softclock() - * can take more than 62.5 usec so clock interrupts are lost.) It doesn't - * check for pending interrupts being unmasked. clkintr() and Xintr0() - * assume that the ipl is high when hardclock() returns. Our SWI_CLOCK - * handling is efficient enough that little is gained by calling - * softclock() directly. - */ -#define CLKF_BASEPRI(framep) ((framep)->cf_ppl == 0) -#else -#define CLKF_BASEPRI(framep) (0) -#endif #define CLKF_PC(framep) ((framep)->cf_eip) /* diff --git a/sys/amd64/include/mptable.h b/sys/amd64/include/mptable.h index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/amd64/include/mptable.h +++ b/sys/amd64/include/mptable.h @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/amd64/include/mutex.h b/sys/amd64/include/mutex.h index ca518d98fd44..881cbfae3c72 100644 --- a/sys/amd64/include/mutex.h +++ b/sys/amd64/include/mutex.h @@ -146,6 +146,7 @@ void _mtx_exit(struct mtx *mtxp, int type, const char *file, int line); /* Global locks */ extern struct mtx sched_lock; extern struct mtx Giant; +extern struct mtx clock_lock; /* * Used to replace return with an exit Giant and return. diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h index ace3602a2844..27884997a535 100644 --- a/sys/amd64/include/pcpu.h +++ b/sys/amd64/include/pcpu.h @@ -55,7 +55,6 @@ struct globaldata { struct privatespace *gd_prvspace; /* self-reference */ struct proc *gd_curproc; - struct proc *gd_prevproc; struct proc *gd_npxproc; struct pcb *gd_curpcb; struct proc *gd_idleproc; diff --git a/sys/amd64/isa/atpic_vector.S b/sys/amd64/isa/atpic_vector.S index 0a89492d8ba0..7644c03aeb3a 100644 --- a/sys/amd64/isa/atpic_vector.S +++ b/sys/amd64/isa/atpic_vector.S @@ -49,17 +49,18 @@ .text ; \ SUPERALIGN_TEXT ; \ IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ + pushl $0 ; /* dummy error code */ \ + pushl $0 ; /* dummy trap type */ \ + pushal ; \ pushl %ds ; \ + pushl %es ; \ pushl %fs ; \ - MAYBE_PUSHL_ES ; \ mov $KDSEL,%ax ; \ mov %ax,%ds ; \ + mov %ax,%es ; \ mov %ax,%fs ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ + FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \ + incb _intr_nesting_level ; \ pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ @@ -67,19 +68,8 @@ IDTVEC(vec_name) ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ incl (%eax) ; \ -/* movl _cpl,%eax ; // are we unmasking pending SWIs? / \ - notl %eax ; \ - andl _spending,$SWI_MASK ; \ - jne 2f ; // yes, maybe handle them */ \ -1: ; \ MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %fs ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ + jmp doreti_next #if 0 ; \ @@ -141,7 +131,7 @@ IDTVEC(vec_name) ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ - incb _intr_nesting_level ; /* XXX do we need this? */ \ + incb _intr_nesting_level ; \ __CONCAT(Xresume,irq_num): ; \ FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \ pushl $irq_num; /* pass the IRQ */ \ @@ -153,26 +143,6 @@ __CONCAT(Xresume,irq_num): ; \ /* _doreti, but it's probably better to use less cache. */ \ jmp doreti_next /* and catch up inside doreti */ -/* - * Reenable the interrupt mask after completing an interrupt. Called - * from ithd_loop. There are two separate functions, one for each - * ICU. - */ - .globl setimask0, setimask1 -setimask0: - cli - movb _imen,%al - outb %al,$IO_ICU1 + ICU_IMR_OFFSET - sti - ret - -setimask1: - cli - movb _imen + 1,%al - outb %al,$IO_ICU2 + ICU_IMR_OFFSET - sti - ret - MCOUNT_LABEL(bintr) FAST_INTR(0,fastintr0, ENABLE_ICU1) FAST_INTR(1,fastintr1, ENABLE_ICU1) diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 0e630d9b2d7b..a164288dd17e 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #ifdef APIC_IO #include @@ -139,6 +140,7 @@ int timer0_max_count; u_int tsc_freq; int tsc_is_broken; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +struct mtx clock_lock; static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -198,12 +200,9 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, static void clkintr(struct clockframe frame) { - int intrsave; if (timecounter->tc_get_timecount == i8254_get_timecount) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); if (i8254_ticked) i8254_ticked = 0; else { @@ -211,8 +210,7 @@ clkintr(struct clockframe frame) i8254_lastcount = 0; } clkintr_pending = 0; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } timer_func(&frame); switch (timer0_state) { @@ -231,17 +229,14 @@ clkintr(struct clockframe frame) break; case ACQUIRE_PENDING: - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = TIMER_DIV(new_rate); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer_func = new_function; timer0_state = ACQUIRED; setdelayed(); @@ -250,9 +245,7 @@ clkintr(struct clockframe frame) case RELEASE_PENDING: if ((timer0_prescaler_count += timer0_max_count) >= hardclock_max_count) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = hardclock_max_count; @@ -260,8 +253,7 @@ clkintr(struct clockframe frame) TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer0_prescaler_count = 0; timer_func = hardclock; timer0_state = RELEASED; @@ -408,11 +400,9 @@ DB_SHOW_COMMAND(rtc, rtc) static int getit(void) { - int high, low, intrsave; + int high, low; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -420,8 +410,7 @@ getit(void) low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return ((high << 8) | low); } @@ -527,7 +516,6 @@ sysbeepstop(void *chan) int sysbeep(int pitch, int period) { - int intrsave; int x = splclock(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) @@ -536,13 +524,10 @@ sysbeep(int pitch, int period) splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); if (!beeping) { /* enable counter2 output to speaker */ outb(IO_PPI, inb(IO_PPI) | 3); @@ -691,12 +676,9 @@ fail: static void set_timer_freq(u_int freq, int intr_freq) { - int intrsave; int new_timer0_max_count; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); if (new_timer0_max_count != timer0_max_count) { @@ -705,8 +687,7 @@ set_timer_freq(u_int freq, int intr_freq) outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); } - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -720,16 +701,12 @@ set_timer_freq(u_int freq, int intr_freq) void i8254_restore(void) { - int intrsave; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -989,8 +966,8 @@ cpu_initclocks() { int diag; #ifdef APIC_IO - int apic_8254_trial, num_8254_ticks; - struct intrec *clkdesc, *rtcdesc; + int apic_8254_trial; + struct intrec *clkdesc; #endif /* APIC_IO */ if (statclock_disable) { @@ -1023,6 +1000,11 @@ cpu_initclocks() } else panic("APIC_IO: Cannot route 8254 interrupt to CPU"); } + + clkdesc = inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, + NULL, PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); + #else /* APIC_IO */ /* @@ -1030,9 +1012,8 @@ cpu_initclocks() * couldn't find anything suitable in the BSD/OS code (grog, * 19 July 2000). */ - /* Setup the PIC clk handler. The APIC handler is setup later */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, PI_REALTIME, - INTR_EXCL); + INTR_FAST); INTREN(IRQ0); #endif /* APIC_IO */ @@ -1042,18 +1023,8 @@ cpu_initclocks() writertc(RTC_STATUSB, RTCSB_24HR); /* Don't bother enabling the statistics clock. */ - if (statclock_disable) { -#ifdef APIC_IO - /* - * XXX - if statclock is disabled, don't attempt the APIC - * trial. Not sure this is sane for APIC_IO. - */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, - NULL, PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif /* APIC_IO */ + if (statclock_disable) return; - } diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); @@ -1061,44 +1032,34 @@ cpu_initclocks() #ifdef APIC_IO if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); +#endif /* APIC_IO */ + inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, + INTR_FAST); + +#ifdef APIC_IO + INTREN(APIC_IRQ8); +#else + INTREN(IRQ8); +#endif /* APIC_IO */ + + writertc(RTC_STATUSB, rtc_statusb); + +#ifdef APIC_IO if (apic_8254_trial) { - /* - * XXX - We use fast interrupts for clk and rtc long enough to - * perform the APIC probe and then revert to exclusive - * interrupts. - */ - clkdesc = inthand_add("clk", apic_8254_intr, - (driver_intr_t *)clkintr, NULL, PI_REALTIME, INTR_FAST); - INTREN(1 << apic_8254_intr); - - rtcdesc = inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, - PI_REALTIME, INTR_FAST); /* XXX */ - INTREN(APIC_IRQ8); - writertc(RTC_STATUSB, rtc_statusb); printf("APIC_IO: Testing 8254 interrupt delivery\n"); while (read_intr_count(8) < 6) ; /* nothing */ - num_8254_ticks = read_intr_count(apic_8254_intr); - - /* disable and remove our fake handlers */ - INTRDIS(1 << apic_8254_intr); - inthand_remove(clkdesc); - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - INTRDIS(APIC_IRQ8); - inthand_remove(rtcdesc); - - if (num_8254_ticks < 3) { + if (read_intr_count(apic_8254_intr) < 3) { /* * The MP table is broken. * The 8254 was not connected to the specified pin * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + INTRDIS(1 << apic_8254_intr); + inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " "IOAPIC #%d intpin %d\n", @@ -1117,27 +1078,13 @@ cpu_initclocks() } apic_8254_intr = apic_irq(0, 0); setup_8254_mixed_mode(); + inthand_add("clk", apic_8254_intr, + (driver_intr_t *)clkintr, NULL, + PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); } } - - /* Finally, setup the real clock handlers */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, - PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif - - inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, - INTR_EXCL); -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || int_to_apicintpin[apic_8254_intr].int_pin != 0) @@ -1242,12 +1189,11 @@ static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; - int intrsave; u_int high, low; + u_int eflags; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + eflags = read_eflags(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -1257,7 +1203,7 @@ i8254_get_timecount(struct timecounter *tc) count = timer0_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(intrsave & PSL_I) && count < timer0_max_count / 2u)) && + ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && #ifdef APIC_IO #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ /* XXX this assumes that apic_8254_intr is < 24. */ @@ -1271,8 +1217,7 @@ i8254_get_timecount(struct timecounter *tc) } i8254_lastcount = count; count += i8254_offset; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return (count); } diff --git a/sys/amd64/isa/icu_vector.S b/sys/amd64/isa/icu_vector.S index 0a89492d8ba0..7644c03aeb3a 100644 --- a/sys/amd64/isa/icu_vector.S +++ b/sys/amd64/isa/icu_vector.S @@ -49,17 +49,18 @@ .text ; \ SUPERALIGN_TEXT ; \ IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ + pushl $0 ; /* dummy error code */ \ + pushl $0 ; /* dummy trap type */ \ + pushal ; \ pushl %ds ; \ + pushl %es ; \ pushl %fs ; \ - MAYBE_PUSHL_ES ; \ mov $KDSEL,%ax ; \ mov %ax,%ds ; \ + mov %ax,%es ; \ mov %ax,%fs ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ + FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \ + incb _intr_nesting_level ; \ pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ @@ -67,19 +68,8 @@ IDTVEC(vec_name) ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ incl (%eax) ; \ -/* movl _cpl,%eax ; // are we unmasking pending SWIs? / \ - notl %eax ; \ - andl _spending,$SWI_MASK ; \ - jne 2f ; // yes, maybe handle them */ \ -1: ; \ MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %fs ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ + jmp doreti_next #if 0 ; \ @@ -141,7 +131,7 @@ IDTVEC(vec_name) ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ - incb _intr_nesting_level ; /* XXX do we need this? */ \ + incb _intr_nesting_level ; \ __CONCAT(Xresume,irq_num): ; \ FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \ pushl $irq_num; /* pass the IRQ */ \ @@ -153,26 +143,6 @@ __CONCAT(Xresume,irq_num): ; \ /* _doreti, but it's probably better to use less cache. */ \ jmp doreti_next /* and catch up inside doreti */ -/* - * Reenable the interrupt mask after completing an interrupt. Called - * from ithd_loop. There are two separate functions, one for each - * ICU. - */ - .globl setimask0, setimask1 -setimask0: - cli - movb _imen,%al - outb %al,$IO_ICU1 + ICU_IMR_OFFSET - sti - ret - -setimask1: - cli - movb _imen + 1,%al - outb %al,$IO_ICU2 + ICU_IMR_OFFSET - sti - ret - MCOUNT_LABEL(bintr) FAST_INTR(0,fastintr0, ENABLE_ICU1) FAST_INTR(1,fastintr1, ENABLE_ICU1) diff --git a/sys/amd64/isa/icu_vector.s b/sys/amd64/isa/icu_vector.s index 0a89492d8ba0..7644c03aeb3a 100644 --- a/sys/amd64/isa/icu_vector.s +++ b/sys/amd64/isa/icu_vector.s @@ -49,17 +49,18 @@ .text ; \ SUPERALIGN_TEXT ; \ IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ + pushl $0 ; /* dummy error code */ \ + pushl $0 ; /* dummy trap type */ \ + pushal ; \ pushl %ds ; \ + pushl %es ; \ pushl %fs ; \ - MAYBE_PUSHL_ES ; \ mov $KDSEL,%ax ; \ mov %ax,%ds ; \ + mov %ax,%es ; \ mov %ax,%fs ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ + FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \ + incb _intr_nesting_level ; \ pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ @@ -67,19 +68,8 @@ IDTVEC(vec_name) ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ incl (%eax) ; \ -/* movl _cpl,%eax ; // are we unmasking pending SWIs? / \ - notl %eax ; \ - andl _spending,$SWI_MASK ; \ - jne 2f ; // yes, maybe handle them */ \ -1: ; \ MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %fs ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ + jmp doreti_next #if 0 ; \ @@ -141,7 +131,7 @@ IDTVEC(vec_name) ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ - incb _intr_nesting_level ; /* XXX do we need this? */ \ + incb _intr_nesting_level ; \ __CONCAT(Xresume,irq_num): ; \ FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \ pushl $irq_num; /* pass the IRQ */ \ @@ -153,26 +143,6 @@ __CONCAT(Xresume,irq_num): ; \ /* _doreti, but it's probably better to use less cache. */ \ jmp doreti_next /* and catch up inside doreti */ -/* - * Reenable the interrupt mask after completing an interrupt. Called - * from ithd_loop. There are two separate functions, one for each - * ICU. - */ - .globl setimask0, setimask1 -setimask0: - cli - movb _imen,%al - outb %al,$IO_ICU1 + ICU_IMR_OFFSET - sti - ret - -setimask1: - cli - movb _imen + 1,%al - outb %al,$IO_ICU2 + ICU_IMR_OFFSET - sti - ret - MCOUNT_LABEL(bintr) FAST_INTR(0,fastintr0, ENABLE_ICU1) FAST_INTR(1,fastintr1, ENABLE_ICU1) diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s index 11d9797e7948..1f80224628b4 100644 --- a/sys/i386/i386/apic_vector.s +++ b/sys/i386/i386/apic_vector.s @@ -15,45 +15,6 @@ /* make an index into the IO APIC from the IRQ# */ #define REDTBL_IDX(irq_num) (0x10 + ((irq_num) * 2)) - -/* - * Macros for interrupt entry, call to handler, and exit. - */ - -#define FAST_INTR(irq_num, vec_name) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - pushl %fs ; \ - movl $KDSEL,%eax ; \ - mov %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - movl $KPSEL,%eax ; \ - mov %ax,%fs ; \ - FAKE_MCOUNT((5+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - addl $4, %esp ; \ - movl $0, lapic_eoi ; \ - lock ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4, %eax ; \ - lock ; \ - incl (%eax) ; \ - MEXITCOUNT ; \ - popl %fs ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret - /* * */ @@ -72,6 +33,34 @@ IDTVEC(vec_name) ; \ popal ; \ addl $4+4,%esp +/* + * Macros for interrupt entry, call to handler, and exit. + */ + +#define FAST_INTR(irq_num, vec_name) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(vec_name) ; \ + PUSH_FRAME ; \ + movl $KDSEL,%eax ; \ + mov %ax,%ds ; \ + mov %ax,%es ; \ + movl $KPSEL,%eax ; \ + mov %ax,%fs ; \ + FAKE_MCOUNT(13*4(%esp)) ; \ + incb _intr_nesting_level ; \ + pushl _intr_unit + (irq_num) * 4 ; \ + call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ + addl $4, %esp ; \ + movl $0, lapic_eoi ; \ + lock ; \ + incl _cnt+V_INTR ; /* book-keeping can wait */ \ + movl _intr_countp + (irq_num) * 4, %eax ; \ + lock ; \ + incl (%eax) ; \ + MEXITCOUNT ; \ + jmp doreti_next + #define IOAPICADDR(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 8 #define REDIRIDX(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 12 diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index 78c607591875..0566dd7e0f45 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -173,7 +173,6 @@ ASSYM(BI_ESYMTAB, offsetof(struct bootinfo, bi_esymtab)); ASSYM(BI_KERNEND, offsetof(struct bootinfo, bi_kernend)); ASSYM(GD_SIZEOF, sizeof(struct globaldata)); ASSYM(GD_CURPROC, offsetof(struct globaldata, gd_curproc)); -ASSYM(GD_PREVPROC, offsetof(struct globaldata, gd_prevproc)); ASSYM(GD_NPXPROC, offsetof(struct globaldata, gd_npxproc)); ASSYM(GD_IDLEPROC, offsetof(struct globaldata, gd_idleproc)); ASSYM(GD_CURPCB, offsetof(struct globaldata, gd_curpcb)); diff --git a/sys/i386/i386/globals.s b/sys/i386/i386/globals.s index f3181429cad5..aaa6f817afb6 100644 --- a/sys/i386/i386/globals.s +++ b/sys/i386/i386/globals.s @@ -61,11 +61,10 @@ globaldata: #else .set globaldata,0 #endif - .globl gd_curproc, gd_prevproc, gd_curpcb, gd_npxproc, gd_idleproc + .globl gd_curproc, gd_curpcb, gd_npxproc, gd_idleproc .globl gd_astpending, gd_common_tss, gd_switchtime, gd_switchticks .globl gd_intr_nesting_level .set gd_curproc,globaldata + GD_CURPROC - .set gd_prevproc,globaldata + GD_PREVPROC .set gd_astpending,globaldata + GD_ASTPENDING .set gd_curpcb,globaldata + GD_CURPCB .set gd_npxproc,globaldata + GD_NPXPROC @@ -96,11 +95,10 @@ globaldata: #endif #ifndef SMP - .globl _curproc, _prevproc, _curpcb, _npxproc, _idleproc, + .globl _curproc, _curpcb, _npxproc, _idleproc, .globl _astpending, _common_tss, _switchtime, _switchticks .global _intr_nesting_level .set _curproc,globaldata + GD_CURPROC - .set _prevproc,globaldata + GD_PREVPROC .set _astpending,globaldata + GD_ASTPENDING .set _curpcb,globaldata + GD_CURPCB .set _npxproc,globaldata + GD_NPXPROC diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 355a0a953184..705501062ac8 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -1883,7 +1883,6 @@ init386(first) /* setup curproc so that mutexes work */ PCPU_SET(curproc, &proc0); - PCPU_SET(prevproc, &proc0); /* make ldt memory segments */ /* @@ -1944,6 +1943,11 @@ init386(first) r_idt.rd_base = (int) idt; lidt(&r_idt); + /* + * We need this mutex before the console probe. + */ + mtx_init(&clock_lock, "clk interrupt lock", MTX_SPIN); + /* * Initialize the console before we print anything out. */ @@ -1955,8 +1959,7 @@ init386(first) #endif /* - * Giant is used early for at least debugger traps, unexpected traps, - * and vm86bios initialization. + * Giant is used early for at least debugger traps and unexpected traps. */ mtx_init(&Giant, "Giant", MTX_DEF); diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/i386/i386/mptable.c +++ b/sys/i386/i386/mptable.c @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s index ac71f0c43be9..32dbe56e686a 100644 --- a/sys/i386/i386/swtch.s +++ b/sys/i386/i386/swtch.s @@ -82,7 +82,6 @@ ENTRY(cpu_switch) /* switch to new process. first, save context as needed */ movl _curproc,%ecx - movl %ecx,_prevproc /* if no process to save, don't bother */ testl %ecx,%ecx diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 1cbfcfad4ed7..b9ebb600cb05 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -1244,6 +1244,18 @@ ast(frame) addupc_task(p, p->p_stats->p_prof.pr_addr, p->p_stats->p_prof.pr_ticks); } + if (p->p_flag & P_ALRMPEND) { + if (!mtx_owned(&Giant)) + mtx_enter(&Giant, MTX_DEF); + p->p_flag &= ~P_ALRMPEND; + psignal(p, SIGVTALRM); + } + if (p->p_flag & P_PROFPEND) { + if (!mtx_owned(&Giant)) + mtx_enter(&Giant, MTX_DEF); + p->p_flag &= ~P_PROFPEND; + psignal(p, SIGPROF); + } if (userret(p, &frame, sticks, mtx_owned(&Giant)) != 0) mtx_exit(&Giant, MTX_DEF); } diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 0e630d9b2d7b..a164288dd17e 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #ifdef APIC_IO #include @@ -139,6 +140,7 @@ int timer0_max_count; u_int tsc_freq; int tsc_is_broken; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +struct mtx clock_lock; static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -198,12 +200,9 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, static void clkintr(struct clockframe frame) { - int intrsave; if (timecounter->tc_get_timecount == i8254_get_timecount) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); if (i8254_ticked) i8254_ticked = 0; else { @@ -211,8 +210,7 @@ clkintr(struct clockframe frame) i8254_lastcount = 0; } clkintr_pending = 0; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } timer_func(&frame); switch (timer0_state) { @@ -231,17 +229,14 @@ clkintr(struct clockframe frame) break; case ACQUIRE_PENDING: - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = TIMER_DIV(new_rate); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer_func = new_function; timer0_state = ACQUIRED; setdelayed(); @@ -250,9 +245,7 @@ clkintr(struct clockframe frame) case RELEASE_PENDING: if ((timer0_prescaler_count += timer0_max_count) >= hardclock_max_count) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = hardclock_max_count; @@ -260,8 +253,7 @@ clkintr(struct clockframe frame) TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer0_prescaler_count = 0; timer_func = hardclock; timer0_state = RELEASED; @@ -408,11 +400,9 @@ DB_SHOW_COMMAND(rtc, rtc) static int getit(void) { - int high, low, intrsave; + int high, low; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -420,8 +410,7 @@ getit(void) low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return ((high << 8) | low); } @@ -527,7 +516,6 @@ sysbeepstop(void *chan) int sysbeep(int pitch, int period) { - int intrsave; int x = splclock(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) @@ -536,13 +524,10 @@ sysbeep(int pitch, int period) splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); if (!beeping) { /* enable counter2 output to speaker */ outb(IO_PPI, inb(IO_PPI) | 3); @@ -691,12 +676,9 @@ fail: static void set_timer_freq(u_int freq, int intr_freq) { - int intrsave; int new_timer0_max_count; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); if (new_timer0_max_count != timer0_max_count) { @@ -705,8 +687,7 @@ set_timer_freq(u_int freq, int intr_freq) outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); } - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -720,16 +701,12 @@ set_timer_freq(u_int freq, int intr_freq) void i8254_restore(void) { - int intrsave; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -989,8 +966,8 @@ cpu_initclocks() { int diag; #ifdef APIC_IO - int apic_8254_trial, num_8254_ticks; - struct intrec *clkdesc, *rtcdesc; + int apic_8254_trial; + struct intrec *clkdesc; #endif /* APIC_IO */ if (statclock_disable) { @@ -1023,6 +1000,11 @@ cpu_initclocks() } else panic("APIC_IO: Cannot route 8254 interrupt to CPU"); } + + clkdesc = inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, + NULL, PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); + #else /* APIC_IO */ /* @@ -1030,9 +1012,8 @@ cpu_initclocks() * couldn't find anything suitable in the BSD/OS code (grog, * 19 July 2000). */ - /* Setup the PIC clk handler. The APIC handler is setup later */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, PI_REALTIME, - INTR_EXCL); + INTR_FAST); INTREN(IRQ0); #endif /* APIC_IO */ @@ -1042,18 +1023,8 @@ cpu_initclocks() writertc(RTC_STATUSB, RTCSB_24HR); /* Don't bother enabling the statistics clock. */ - if (statclock_disable) { -#ifdef APIC_IO - /* - * XXX - if statclock is disabled, don't attempt the APIC - * trial. Not sure this is sane for APIC_IO. - */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, - NULL, PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif /* APIC_IO */ + if (statclock_disable) return; - } diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); @@ -1061,44 +1032,34 @@ cpu_initclocks() #ifdef APIC_IO if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); +#endif /* APIC_IO */ + inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, + INTR_FAST); + +#ifdef APIC_IO + INTREN(APIC_IRQ8); +#else + INTREN(IRQ8); +#endif /* APIC_IO */ + + writertc(RTC_STATUSB, rtc_statusb); + +#ifdef APIC_IO if (apic_8254_trial) { - /* - * XXX - We use fast interrupts for clk and rtc long enough to - * perform the APIC probe and then revert to exclusive - * interrupts. - */ - clkdesc = inthand_add("clk", apic_8254_intr, - (driver_intr_t *)clkintr, NULL, PI_REALTIME, INTR_FAST); - INTREN(1 << apic_8254_intr); - - rtcdesc = inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, - PI_REALTIME, INTR_FAST); /* XXX */ - INTREN(APIC_IRQ8); - writertc(RTC_STATUSB, rtc_statusb); printf("APIC_IO: Testing 8254 interrupt delivery\n"); while (read_intr_count(8) < 6) ; /* nothing */ - num_8254_ticks = read_intr_count(apic_8254_intr); - - /* disable and remove our fake handlers */ - INTRDIS(1 << apic_8254_intr); - inthand_remove(clkdesc); - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - INTRDIS(APIC_IRQ8); - inthand_remove(rtcdesc); - - if (num_8254_ticks < 3) { + if (read_intr_count(apic_8254_intr) < 3) { /* * The MP table is broken. * The 8254 was not connected to the specified pin * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + INTRDIS(1 << apic_8254_intr); + inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " "IOAPIC #%d intpin %d\n", @@ -1117,27 +1078,13 @@ cpu_initclocks() } apic_8254_intr = apic_irq(0, 0); setup_8254_mixed_mode(); + inthand_add("clk", apic_8254_intr, + (driver_intr_t *)clkintr, NULL, + PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); } } - - /* Finally, setup the real clock handlers */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, - PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif - - inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, - INTR_EXCL); -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || int_to_apicintpin[apic_8254_intr].int_pin != 0) @@ -1242,12 +1189,11 @@ static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; - int intrsave; u_int high, low; + u_int eflags; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + eflags = read_eflags(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -1257,7 +1203,7 @@ i8254_get_timecount(struct timecounter *tc) count = timer0_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(intrsave & PSL_I) && count < timer0_max_count / 2u)) && + ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && #ifdef APIC_IO #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ /* XXX this assumes that apic_8254_intr is < 24. */ @@ -1271,8 +1217,7 @@ i8254_get_timecount(struct timecounter *tc) } i8254_lastcount = count; count += i8254_offset; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return (count); } diff --git a/sys/i386/include/asnames.h b/sys/i386/include/asnames.h index fe5d6ca587b9..b99b9af837b9 100644 --- a/sys/i386/include/asnames.h +++ b/sys/i386/include/asnames.h @@ -342,7 +342,6 @@ #define _cpu_lockid FS(cpu_lockid) #define _curpcb FS(curpcb) #define _curproc FS(curproc) -#define _prevproc FS(prevproc) #define _idleproc FS(idleproc) #define _astpending FS(astpending) #define _currentldt FS(currentldt) diff --git a/sys/i386/include/cpu.h b/sys/i386/include/cpu.h index 18822b87cc5b..d35b94077130 100644 --- a/sys/i386/include/cpu.h +++ b/sys/i386/include/cpu.h @@ -62,21 +62,6 @@ ((ISPL((framep)->cf_cs) == SEL_UPL) || (framep->cf_eflags & PSL_VM)) #define CLKF_INTR(framep) (intr_nesting_level >= 2) -#if 0 -/* - * XXX splsoftclock() is very broken and barely worth fixing. It doesn't - * turn off the clock bit in imen or in the icu. (This is not a serious - * problem at 100 Hz but it is serious at 16000 Hz for pcaudio. softclock() - * can take more than 62.5 usec so clock interrupts are lost.) It doesn't - * check for pending interrupts being unmasked. clkintr() and Xintr0() - * assume that the ipl is high when hardclock() returns. Our SWI_CLOCK - * handling is efficient enough that little is gained by calling - * softclock() directly. - */ -#define CLKF_BASEPRI(framep) ((framep)->cf_ppl == 0) -#else -#define CLKF_BASEPRI(framep) (0) -#endif #define CLKF_PC(framep) ((framep)->cf_eip) /* diff --git a/sys/i386/include/globaldata.h b/sys/i386/include/globaldata.h index ace3602a2844..27884997a535 100644 --- a/sys/i386/include/globaldata.h +++ b/sys/i386/include/globaldata.h @@ -55,7 +55,6 @@ struct globaldata { struct privatespace *gd_prvspace; /* self-reference */ struct proc *gd_curproc; - struct proc *gd_prevproc; struct proc *gd_npxproc; struct pcb *gd_curpcb; struct proc *gd_idleproc; diff --git a/sys/i386/include/globals.h b/sys/i386/include/globals.h index 71bbbd580d9e..d18c0acd5a03 100644 --- a/sys/i386/include/globals.h +++ b/sys/i386/include/globals.h @@ -90,7 +90,6 @@ _global_globaldata(void) * portability between UP and SMP kernels. */ #define curproc GLOBAL_RVALUE_NV(curproc, struct proc *) -#define prevproc GLOBAL_RVALUE_NV(prevproc, struct proc *) #define curpcb GLOBAL_RVALUE_NV(curpcb, struct pcb *) #define npxproc GLOBAL_RVALUE_NV(npxproc, struct proc *) #define idleproc GLOBAL_RVALUE_NV(idleproc, struct proc *) @@ -126,7 +125,6 @@ _global_globaldata(void) #endif /*UP kernel*/ GLOBAL_FUNC(curproc) -GLOBAL_FUNC(prevproc) GLOBAL_FUNC(astpending) GLOBAL_FUNC(curpcb) GLOBAL_FUNC(npxproc) diff --git a/sys/i386/include/lock.h b/sys/i386/include/lock.h index 7871606ddddc..aa527ef2dd4c 100644 --- a/sys/i386/include/lock.h +++ b/sys/i386/include/lock.h @@ -74,24 +74,10 @@ #define COM_UNLOCK() #endif /* USE_COMLOCK */ -/* - * Clock hardware/struct lock. - * XXX pcaudio and friends still need this lock installed. - */ -#ifdef USE_CLOCKLOCK -#define CLOCK_LOCK() s_lock(&clock_lock) -#define CLOCK_UNLOCK() s_unlock(&clock_lock) -#else -#define CLOCK_LOCK() -#define CLOCK_UNLOCK() -#endif /* USE_CLOCKLOCK */ - #else /* SMP */ #define COM_LOCK() #define COM_UNLOCK() -#define CLOCK_LOCK() -#define CLOCK_UNLOCK() #endif /* SMP */ @@ -124,7 +110,6 @@ extern struct simplelock imen_lock; extern struct simplelock cpl_lock; extern struct simplelock fast_intr_lock; extern struct simplelock intr_lock; -extern struct simplelock clock_lock; extern struct simplelock com_lock; extern struct simplelock mpintr_lock; extern struct simplelock mcount_lock; diff --git a/sys/i386/include/mptable.h b/sys/i386/include/mptable.h index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/i386/include/mptable.h +++ b/sys/i386/include/mptable.h @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/i386/include/mutex.h b/sys/i386/include/mutex.h index ca518d98fd44..881cbfae3c72 100644 --- a/sys/i386/include/mutex.h +++ b/sys/i386/include/mutex.h @@ -146,6 +146,7 @@ void _mtx_exit(struct mtx *mtxp, int type, const char *file, int line); /* Global locks */ extern struct mtx sched_lock; extern struct mtx Giant; +extern struct mtx clock_lock; /* * Used to replace return with an exit Giant and return. diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h index ace3602a2844..27884997a535 100644 --- a/sys/i386/include/pcpu.h +++ b/sys/i386/include/pcpu.h @@ -55,7 +55,6 @@ struct globaldata { struct privatespace *gd_prvspace; /* self-reference */ struct proc *gd_curproc; - struct proc *gd_prevproc; struct proc *gd_npxproc; struct pcb *gd_curpcb; struct proc *gd_idleproc; diff --git a/sys/i386/include/smptests.h b/sys/i386/include/smptests.h index 304e99051295..239f849ee088 100644 --- a/sys/i386/include/smptests.h +++ b/sys/i386/include/smptests.h @@ -87,14 +87,12 @@ * protected via cli/sti in the UP kernel. * * COMLOCK protects the sio/cy drivers. - * CLOCKLOCK protects clock hardware and data * known to be incomplete: * joystick lkm * ? */ #ifdef PUSHDOWN_LEVEL_1 #define USE_COMLOCK -#define USE_CLOCKLOCK #endif diff --git a/sys/i386/isa/apic_vector.s b/sys/i386/isa/apic_vector.s index 11d9797e7948..1f80224628b4 100644 --- a/sys/i386/isa/apic_vector.s +++ b/sys/i386/isa/apic_vector.s @@ -15,45 +15,6 @@ /* make an index into the IO APIC from the IRQ# */ #define REDTBL_IDX(irq_num) (0x10 + ((irq_num) * 2)) - -/* - * Macros for interrupt entry, call to handler, and exit. - */ - -#define FAST_INTR(irq_num, vec_name) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - pushl %fs ; \ - movl $KDSEL,%eax ; \ - mov %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - movl $KPSEL,%eax ; \ - mov %ax,%fs ; \ - FAKE_MCOUNT((5+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - addl $4, %esp ; \ - movl $0, lapic_eoi ; \ - lock ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4, %eax ; \ - lock ; \ - incl (%eax) ; \ - MEXITCOUNT ; \ - popl %fs ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret - /* * */ @@ -72,6 +33,34 @@ IDTVEC(vec_name) ; \ popal ; \ addl $4+4,%esp +/* + * Macros for interrupt entry, call to handler, and exit. + */ + +#define FAST_INTR(irq_num, vec_name) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(vec_name) ; \ + PUSH_FRAME ; \ + movl $KDSEL,%eax ; \ + mov %ax,%ds ; \ + mov %ax,%es ; \ + movl $KPSEL,%eax ; \ + mov %ax,%fs ; \ + FAKE_MCOUNT(13*4(%esp)) ; \ + incb _intr_nesting_level ; \ + pushl _intr_unit + (irq_num) * 4 ; \ + call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ + addl $4, %esp ; \ + movl $0, lapic_eoi ; \ + lock ; \ + incl _cnt+V_INTR ; /* book-keeping can wait */ \ + movl _intr_countp + (irq_num) * 4, %eax ; \ + lock ; \ + incl (%eax) ; \ + MEXITCOUNT ; \ + jmp doreti_next + #define IOAPICADDR(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 8 #define REDIRIDX(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 12 diff --git a/sys/i386/isa/atpic_vector.s b/sys/i386/isa/atpic_vector.s index 0a89492d8ba0..7644c03aeb3a 100644 --- a/sys/i386/isa/atpic_vector.s +++ b/sys/i386/isa/atpic_vector.s @@ -49,17 +49,18 @@ .text ; \ SUPERALIGN_TEXT ; \ IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ + pushl $0 ; /* dummy error code */ \ + pushl $0 ; /* dummy trap type */ \ + pushal ; \ pushl %ds ; \ + pushl %es ; \ pushl %fs ; \ - MAYBE_PUSHL_ES ; \ mov $KDSEL,%ax ; \ mov %ax,%ds ; \ + mov %ax,%es ; \ mov %ax,%fs ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ + FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \ + incb _intr_nesting_level ; \ pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ @@ -67,19 +68,8 @@ IDTVEC(vec_name) ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ incl (%eax) ; \ -/* movl _cpl,%eax ; // are we unmasking pending SWIs? / \ - notl %eax ; \ - andl _spending,$SWI_MASK ; \ - jne 2f ; // yes, maybe handle them */ \ -1: ; \ MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %fs ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ + jmp doreti_next #if 0 ; \ @@ -141,7 +131,7 @@ IDTVEC(vec_name) ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ - incb _intr_nesting_level ; /* XXX do we need this? */ \ + incb _intr_nesting_level ; \ __CONCAT(Xresume,irq_num): ; \ FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \ pushl $irq_num; /* pass the IRQ */ \ @@ -153,26 +143,6 @@ __CONCAT(Xresume,irq_num): ; \ /* _doreti, but it's probably better to use less cache. */ \ jmp doreti_next /* and catch up inside doreti */ -/* - * Reenable the interrupt mask after completing an interrupt. Called - * from ithd_loop. There are two separate functions, one for each - * ICU. - */ - .globl setimask0, setimask1 -setimask0: - cli - movb _imen,%al - outb %al,$IO_ICU1 + ICU_IMR_OFFSET - sti - ret - -setimask1: - cli - movb _imen + 1,%al - outb %al,$IO_ICU2 + ICU_IMR_OFFSET - sti - ret - MCOUNT_LABEL(bintr) FAST_INTR(0,fastintr0, ENABLE_ICU1) FAST_INTR(1,fastintr1, ENABLE_ICU1) diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 0e630d9b2d7b..a164288dd17e 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #ifdef APIC_IO #include @@ -139,6 +140,7 @@ int timer0_max_count; u_int tsc_freq; int tsc_is_broken; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +struct mtx clock_lock; static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -198,12 +200,9 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, static void clkintr(struct clockframe frame) { - int intrsave; if (timecounter->tc_get_timecount == i8254_get_timecount) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); if (i8254_ticked) i8254_ticked = 0; else { @@ -211,8 +210,7 @@ clkintr(struct clockframe frame) i8254_lastcount = 0; } clkintr_pending = 0; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } timer_func(&frame); switch (timer0_state) { @@ -231,17 +229,14 @@ clkintr(struct clockframe frame) break; case ACQUIRE_PENDING: - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = TIMER_DIV(new_rate); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer_func = new_function; timer0_state = ACQUIRED; setdelayed(); @@ -250,9 +245,7 @@ clkintr(struct clockframe frame) case RELEASE_PENDING: if ((timer0_prescaler_count += timer0_max_count) >= hardclock_max_count) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = hardclock_max_count; @@ -260,8 +253,7 @@ clkintr(struct clockframe frame) TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer0_prescaler_count = 0; timer_func = hardclock; timer0_state = RELEASED; @@ -408,11 +400,9 @@ DB_SHOW_COMMAND(rtc, rtc) static int getit(void) { - int high, low, intrsave; + int high, low; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -420,8 +410,7 @@ getit(void) low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return ((high << 8) | low); } @@ -527,7 +516,6 @@ sysbeepstop(void *chan) int sysbeep(int pitch, int period) { - int intrsave; int x = splclock(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) @@ -536,13 +524,10 @@ sysbeep(int pitch, int period) splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); if (!beeping) { /* enable counter2 output to speaker */ outb(IO_PPI, inb(IO_PPI) | 3); @@ -691,12 +676,9 @@ fail: static void set_timer_freq(u_int freq, int intr_freq) { - int intrsave; int new_timer0_max_count; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); if (new_timer0_max_count != timer0_max_count) { @@ -705,8 +687,7 @@ set_timer_freq(u_int freq, int intr_freq) outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); } - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -720,16 +701,12 @@ set_timer_freq(u_int freq, int intr_freq) void i8254_restore(void) { - int intrsave; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -989,8 +966,8 @@ cpu_initclocks() { int diag; #ifdef APIC_IO - int apic_8254_trial, num_8254_ticks; - struct intrec *clkdesc, *rtcdesc; + int apic_8254_trial; + struct intrec *clkdesc; #endif /* APIC_IO */ if (statclock_disable) { @@ -1023,6 +1000,11 @@ cpu_initclocks() } else panic("APIC_IO: Cannot route 8254 interrupt to CPU"); } + + clkdesc = inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, + NULL, PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); + #else /* APIC_IO */ /* @@ -1030,9 +1012,8 @@ cpu_initclocks() * couldn't find anything suitable in the BSD/OS code (grog, * 19 July 2000). */ - /* Setup the PIC clk handler. The APIC handler is setup later */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, PI_REALTIME, - INTR_EXCL); + INTR_FAST); INTREN(IRQ0); #endif /* APIC_IO */ @@ -1042,18 +1023,8 @@ cpu_initclocks() writertc(RTC_STATUSB, RTCSB_24HR); /* Don't bother enabling the statistics clock. */ - if (statclock_disable) { -#ifdef APIC_IO - /* - * XXX - if statclock is disabled, don't attempt the APIC - * trial. Not sure this is sane for APIC_IO. - */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, - NULL, PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif /* APIC_IO */ + if (statclock_disable) return; - } diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); @@ -1061,44 +1032,34 @@ cpu_initclocks() #ifdef APIC_IO if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); +#endif /* APIC_IO */ + inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, + INTR_FAST); + +#ifdef APIC_IO + INTREN(APIC_IRQ8); +#else + INTREN(IRQ8); +#endif /* APIC_IO */ + + writertc(RTC_STATUSB, rtc_statusb); + +#ifdef APIC_IO if (apic_8254_trial) { - /* - * XXX - We use fast interrupts for clk and rtc long enough to - * perform the APIC probe and then revert to exclusive - * interrupts. - */ - clkdesc = inthand_add("clk", apic_8254_intr, - (driver_intr_t *)clkintr, NULL, PI_REALTIME, INTR_FAST); - INTREN(1 << apic_8254_intr); - - rtcdesc = inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, - PI_REALTIME, INTR_FAST); /* XXX */ - INTREN(APIC_IRQ8); - writertc(RTC_STATUSB, rtc_statusb); printf("APIC_IO: Testing 8254 interrupt delivery\n"); while (read_intr_count(8) < 6) ; /* nothing */ - num_8254_ticks = read_intr_count(apic_8254_intr); - - /* disable and remove our fake handlers */ - INTRDIS(1 << apic_8254_intr); - inthand_remove(clkdesc); - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - INTRDIS(APIC_IRQ8); - inthand_remove(rtcdesc); - - if (num_8254_ticks < 3) { + if (read_intr_count(apic_8254_intr) < 3) { /* * The MP table is broken. * The 8254 was not connected to the specified pin * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + INTRDIS(1 << apic_8254_intr); + inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " "IOAPIC #%d intpin %d\n", @@ -1117,27 +1078,13 @@ cpu_initclocks() } apic_8254_intr = apic_irq(0, 0); setup_8254_mixed_mode(); + inthand_add("clk", apic_8254_intr, + (driver_intr_t *)clkintr, NULL, + PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); } } - - /* Finally, setup the real clock handlers */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, - PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif - - inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, - INTR_EXCL); -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || int_to_apicintpin[apic_8254_intr].int_pin != 0) @@ -1242,12 +1189,11 @@ static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; - int intrsave; u_int high, low; + u_int eflags; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + eflags = read_eflags(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -1257,7 +1203,7 @@ i8254_get_timecount(struct timecounter *tc) count = timer0_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(intrsave & PSL_I) && count < timer0_max_count / 2u)) && + ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && #ifdef APIC_IO #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ /* XXX this assumes that apic_8254_intr is < 24. */ @@ -1271,8 +1217,7 @@ i8254_get_timecount(struct timecounter *tc) } i8254_lastcount = count; count += i8254_offset; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return (count); } diff --git a/sys/i386/isa/icu_vector.s b/sys/i386/isa/icu_vector.s index 0a89492d8ba0..7644c03aeb3a 100644 --- a/sys/i386/isa/icu_vector.s +++ b/sys/i386/isa/icu_vector.s @@ -49,17 +49,18 @@ .text ; \ SUPERALIGN_TEXT ; \ IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ + pushl $0 ; /* dummy error code */ \ + pushl $0 ; /* dummy trap type */ \ + pushal ; \ pushl %ds ; \ + pushl %es ; \ pushl %fs ; \ - MAYBE_PUSHL_ES ; \ mov $KDSEL,%ax ; \ mov %ax,%ds ; \ + mov %ax,%es ; \ mov %ax,%fs ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ + FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ; \ + incb _intr_nesting_level ; \ pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ @@ -67,19 +68,8 @@ IDTVEC(vec_name) ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ incl (%eax) ; \ -/* movl _cpl,%eax ; // are we unmasking pending SWIs? / \ - notl %eax ; \ - andl _spending,$SWI_MASK ; \ - jne 2f ; // yes, maybe handle them */ \ -1: ; \ MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %fs ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ + jmp doreti_next #if 0 ; \ @@ -141,7 +131,7 @@ IDTVEC(vec_name) ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ - incb _intr_nesting_level ; /* XXX do we need this? */ \ + incb _intr_nesting_level ; \ __CONCAT(Xresume,irq_num): ; \ FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \ pushl $irq_num; /* pass the IRQ */ \ @@ -153,26 +143,6 @@ __CONCAT(Xresume,irq_num): ; \ /* _doreti, but it's probably better to use less cache. */ \ jmp doreti_next /* and catch up inside doreti */ -/* - * Reenable the interrupt mask after completing an interrupt. Called - * from ithd_loop. There are two separate functions, one for each - * ICU. - */ - .globl setimask0, setimask1 -setimask0: - cli - movb _imen,%al - outb %al,$IO_ICU1 + ICU_IMR_OFFSET - sti - ret - -setimask1: - cli - movb _imen + 1,%al - outb %al,$IO_ICU2 + ICU_IMR_OFFSET - sti - ret - MCOUNT_LABEL(bintr) FAST_INTR(0,fastintr0, ENABLE_ICU1) FAST_INTR(1,fastintr1, ENABLE_ICU1) diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 0e630d9b2d7b..a164288dd17e 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #ifdef APIC_IO #include @@ -139,6 +140,7 @@ int timer0_max_count; u_int tsc_freq; int tsc_is_broken; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +struct mtx clock_lock; static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -198,12 +200,9 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, static void clkintr(struct clockframe frame) { - int intrsave; if (timecounter->tc_get_timecount == i8254_get_timecount) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); if (i8254_ticked) i8254_ticked = 0; else { @@ -211,8 +210,7 @@ clkintr(struct clockframe frame) i8254_lastcount = 0; } clkintr_pending = 0; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } timer_func(&frame); switch (timer0_state) { @@ -231,17 +229,14 @@ clkintr(struct clockframe frame) break; case ACQUIRE_PENDING: - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = TIMER_DIV(new_rate); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer_func = new_function; timer0_state = ACQUIRED; setdelayed(); @@ -250,9 +245,7 @@ clkintr(struct clockframe frame) case RELEASE_PENDING: if ((timer0_prescaler_count += timer0_max_count) >= hardclock_max_count) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = hardclock_max_count; @@ -260,8 +253,7 @@ clkintr(struct clockframe frame) TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer0_prescaler_count = 0; timer_func = hardclock; timer0_state = RELEASED; @@ -408,11 +400,9 @@ DB_SHOW_COMMAND(rtc, rtc) static int getit(void) { - int high, low, intrsave; + int high, low; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -420,8 +410,7 @@ getit(void) low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return ((high << 8) | low); } @@ -527,7 +516,6 @@ sysbeepstop(void *chan) int sysbeep(int pitch, int period) { - int intrsave; int x = splclock(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) @@ -536,13 +524,10 @@ sysbeep(int pitch, int period) splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); if (!beeping) { /* enable counter2 output to speaker */ outb(IO_PPI, inb(IO_PPI) | 3); @@ -691,12 +676,9 @@ fail: static void set_timer_freq(u_int freq, int intr_freq) { - int intrsave; int new_timer0_max_count; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); if (new_timer0_max_count != timer0_max_count) { @@ -705,8 +687,7 @@ set_timer_freq(u_int freq, int intr_freq) outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); } - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -720,16 +701,12 @@ set_timer_freq(u_int freq, int intr_freq) void i8254_restore(void) { - int intrsave; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -989,8 +966,8 @@ cpu_initclocks() { int diag; #ifdef APIC_IO - int apic_8254_trial, num_8254_ticks; - struct intrec *clkdesc, *rtcdesc; + int apic_8254_trial; + struct intrec *clkdesc; #endif /* APIC_IO */ if (statclock_disable) { @@ -1023,6 +1000,11 @@ cpu_initclocks() } else panic("APIC_IO: Cannot route 8254 interrupt to CPU"); } + + clkdesc = inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, + NULL, PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); + #else /* APIC_IO */ /* @@ -1030,9 +1012,8 @@ cpu_initclocks() * couldn't find anything suitable in the BSD/OS code (grog, * 19 July 2000). */ - /* Setup the PIC clk handler. The APIC handler is setup later */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, PI_REALTIME, - INTR_EXCL); + INTR_FAST); INTREN(IRQ0); #endif /* APIC_IO */ @@ -1042,18 +1023,8 @@ cpu_initclocks() writertc(RTC_STATUSB, RTCSB_24HR); /* Don't bother enabling the statistics clock. */ - if (statclock_disable) { -#ifdef APIC_IO - /* - * XXX - if statclock is disabled, don't attempt the APIC - * trial. Not sure this is sane for APIC_IO. - */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, - NULL, PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif /* APIC_IO */ + if (statclock_disable) return; - } diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); @@ -1061,44 +1032,34 @@ cpu_initclocks() #ifdef APIC_IO if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); +#endif /* APIC_IO */ + inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, + INTR_FAST); + +#ifdef APIC_IO + INTREN(APIC_IRQ8); +#else + INTREN(IRQ8); +#endif /* APIC_IO */ + + writertc(RTC_STATUSB, rtc_statusb); + +#ifdef APIC_IO if (apic_8254_trial) { - /* - * XXX - We use fast interrupts for clk and rtc long enough to - * perform the APIC probe and then revert to exclusive - * interrupts. - */ - clkdesc = inthand_add("clk", apic_8254_intr, - (driver_intr_t *)clkintr, NULL, PI_REALTIME, INTR_FAST); - INTREN(1 << apic_8254_intr); - - rtcdesc = inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, - PI_REALTIME, INTR_FAST); /* XXX */ - INTREN(APIC_IRQ8); - writertc(RTC_STATUSB, rtc_statusb); printf("APIC_IO: Testing 8254 interrupt delivery\n"); while (read_intr_count(8) < 6) ; /* nothing */ - num_8254_ticks = read_intr_count(apic_8254_intr); - - /* disable and remove our fake handlers */ - INTRDIS(1 << apic_8254_intr); - inthand_remove(clkdesc); - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - INTRDIS(APIC_IRQ8); - inthand_remove(rtcdesc); - - if (num_8254_ticks < 3) { + if (read_intr_count(apic_8254_intr) < 3) { /* * The MP table is broken. * The 8254 was not connected to the specified pin * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + INTRDIS(1 << apic_8254_intr); + inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " "IOAPIC #%d intpin %d\n", @@ -1117,27 +1078,13 @@ cpu_initclocks() } apic_8254_intr = apic_irq(0, 0); setup_8254_mixed_mode(); + inthand_add("clk", apic_8254_intr, + (driver_intr_t *)clkintr, NULL, + PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); } } - - /* Finally, setup the real clock handlers */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, - PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif - - inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, - INTR_EXCL); -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || int_to_apicintpin[apic_8254_intr].int_pin != 0) @@ -1242,12 +1189,11 @@ static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; - int intrsave; u_int high, low; + u_int eflags; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + eflags = read_eflags(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -1257,7 +1203,7 @@ i8254_get_timecount(struct timecounter *tc) count = timer0_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(intrsave & PSL_I) && count < timer0_max_count / 2u)) && + ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && #ifdef APIC_IO #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ /* XXX this assumes that apic_8254_intr is < 24. */ @@ -1271,8 +1217,7 @@ i8254_get_timecount(struct timecounter *tc) } i8254_lastcount = count; count += i8254_offset; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return (count); } diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index bc6bf0636a51..6b3153fc5546 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -58,7 +58,9 @@ #include #include +#include #include +#include #include #ifdef GPROF @@ -161,11 +163,15 @@ hardclock(frame) pstats = p->p_stats; if (CLKF_USERMODE(frame) && timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) && - itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) - psignal(p, SIGVTALRM); + itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) { + p->p_flag |= P_ALRMPEND; + aston(); + } if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) && - itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) - psignal(p, SIGPROF); + itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) { + p->p_flag |= P_PROFPEND; + aston(); + } } #if defined(SMP) && defined(BETTER_CLOCK) @@ -186,15 +192,7 @@ hardclock(frame) * relatively high clock interrupt priority any longer than necessary. */ if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) { - if (CLKF_BASEPRI(frame)) { - /* - * Save the overhead of a software interrupt; - * it will happen as soon as we return, so do it now. - */ - (void)splsoftclock(); - softclock(); - } else - setsoftclock(); + setsoftclock(); } else if (softticks + 1 == ticks) ++softticks; } @@ -321,20 +319,24 @@ statclock(frame) struct rusage *ru; struct vmspace *vm; + mtx_enter(&sched_lock, MTX_SPIN); + if (CLKF_USERMODE(frame)) { /* * Came from user mode; CPU was in user state. * If this process is being profiled, record the tick. */ - p = prevproc; + p = curproc; if (p->p_flag & P_PROFIL) addupc_intr(p, CLKF_PC(frame), 1); #if defined(SMP) && defined(BETTER_CLOCK) if (stathz != 0) forward_statclock(pscnt); #endif - if (--pscnt > 0) + if (--pscnt > 0) { + mtx_exit(&sched_lock, MTX_SPIN); return; + } /* * Charge the time as appropriate. */ @@ -361,8 +363,10 @@ statclock(frame) if (stathz != 0) forward_statclock(pscnt); #endif - if (--pscnt > 0) + if (--pscnt > 0) { + mtx_exit(&sched_lock, MTX_SPIN); return; + } /* * Came from kernel mode, so we were: * - handling an interrupt, @@ -375,8 +379,8 @@ statclock(frame) * so that we know how much of its real time was spent * in ``non-process'' (i.e., interrupt) work. */ - p = prevproc; - if (p->p_ithd) { + p = curproc; + if ((p->p_ithd != NULL) || CLKF_INTR(frame)) { p->p_iticks++; cp_time[CP_INTR]++; } else { @@ -402,6 +406,8 @@ statclock(frame) if (ru->ru_maxrss < rss) ru->ru_maxrss = rss; } + + mtx_exit(&sched_lock, MTX_SPIN); } /* diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index eeddeb6c8348..303133461113 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -289,6 +289,7 @@ schedcpu(arg) if (p->p_stat == SWAIT) continue; */ + mtx_enter(&sched_lock, MTX_SPIN); p->p_swtime++; if (p->p_stat == SSLEEP || p->p_stat == SSTOP) p->p_slptime++; @@ -297,13 +298,15 @@ schedcpu(arg) * If the process has slept the entire second, * stop recalculating its priority until it wakes up. */ - if (p->p_slptime > 1) + if (p->p_slptime > 1) { + mtx_exit(&sched_lock, MTX_SPIN); continue; + } + /* * prevent state changes and protect run queue */ s = splhigh(); - mtx_enter(&sched_lock, MTX_SPIN); /* * p_pctcpu is only for ps. @@ -451,9 +454,6 @@ msleep(ident, mtx, priority, wmesg, timo) * in case this is the idle process and already asleep. */ mtx_exit(&sched_lock, MTX_SPIN); -#if 0 - splx(safepri); -#endif splx(s); return (0); } @@ -994,7 +994,6 @@ setrunnable(p) p->p_stat = SRUN; if (p->p_flag & P_INMEM) setrunqueue(p); - mtx_exit(&sched_lock, MTX_SPIN); splx(s); if (p->p_slptime > 1) updatepri(p); @@ -1005,6 +1004,7 @@ setrunnable(p) } else maybe_resched(p); + mtx_exit(&sched_lock, MTX_SPIN); } /* @@ -1018,6 +1018,7 @@ resetpriority(p) { register unsigned int newpriority; + mtx_enter(&sched_lock, MTX_SPIN); if (p->p_rtprio.type == RTP_PRIO_NORMAL) { newpriority = PUSER + p->p_estcpu / INVERSE_ESTCPU_WEIGHT + NICE_WEIGHT * (p->p_nice - PRIO_MIN); @@ -1025,6 +1026,7 @@ resetpriority(p) p->p_usrpri = newpriority; } maybe_resched(p); + mtx_exit(&sched_lock, MTX_SPIN); } /* ARGSUSED */ diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index ea9aee8ddbcd..5ef95b3607a7 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -1900,11 +1900,6 @@ struct simplelock mcount_lock; struct simplelock com_lock; #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK -/* lock regions around the clock hardware */ -struct simplelock clock_lock; -#endif /* USE_CLOCKLOCK */ - /* lock around the MP rendezvous */ static struct simplelock smp_rv_lock; @@ -1930,9 +1925,6 @@ init_locks(void) #ifdef USE_COMLOCK s_lock_init((struct simplelock*)&com_lock); #endif /* USE_COMLOCK */ -#ifdef USE_CLOCKLOCK - s_lock_init((struct simplelock*)&clock_lock); -#endif /* USE_CLOCKLOCK */ s_lock_init(&ap_boot_lock); } @@ -2425,7 +2417,6 @@ ap_init(void) * something unique to lock with. */ PCPU_SET(curproc,idleproc); - PCPU_SET(prevproc,idleproc); microuptime(&switchtime); switchticks = ticks; diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 1cbfcfad4ed7..b9ebb600cb05 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -1244,6 +1244,18 @@ ast(frame) addupc_task(p, p->p_stats->p_prof.pr_addr, p->p_stats->p_prof.pr_ticks); } + if (p->p_flag & P_ALRMPEND) { + if (!mtx_owned(&Giant)) + mtx_enter(&Giant, MTX_DEF); + p->p_flag &= ~P_ALRMPEND; + psignal(p, SIGVTALRM); + } + if (p->p_flag & P_PROFPEND) { + if (!mtx_owned(&Giant)) + mtx_enter(&Giant, MTX_DEF); + p->p_flag &= ~P_PROFPEND; + psignal(p, SIGPROF); + } if (userret(p, &frame, sticks, mtx_owned(&Giant)) != 0) mtx_exit(&Giant, MTX_DEF); } diff --git a/sys/powerpc/include/globals.h b/sys/powerpc/include/globals.h index 303efdfe9f6a..f85a67c4c37e 100644 --- a/sys/powerpc/include/globals.h +++ b/sys/powerpc/include/globals.h @@ -56,7 +56,6 @@ register struct globaldata *globalp __asm__("$8"); #define switchtime PCPU_GET(switchtime) #define switchticks PCPU_GET(switchticks) #define cpuid PCPU_GET(cpuno) -#define prevproc PCPU_GET(curproc) /* XXX - until ithreads */ #endif /* _KERNEL */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 1f7515034250..3a14e341d977 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -273,6 +273,7 @@ struct proc { #define P_ADVLOCK 0x00001 /* Process may hold a POSIX advisory lock. */ #define P_CONTROLT 0x00002 /* Has a controlling terminal. */ #define P_INMEM 0x00004 /* Loaded into memory. */ +#define P_NOLOAD 0x00008 /* Ignore during load avg calculations. */ #define P_PPWAIT 0x00010 /* Parent is waiting for child to exec/exit. */ #define P_PROFIL 0x00020 /* Has started profiling. */ #define P_SELECT 0x00040 /* Selecting; wakeup/waiting danger. */ @@ -284,7 +285,8 @@ struct proc { #define P_WAITED 0x01000 /* Debugging process has waited for child. */ #define P_WEXIT 0x02000 /* Working on exiting. */ #define P_EXEC 0x04000 /* Process called exec. */ -#define P_NOLOAD 0x08000 /* Ignore during load avg calculations. */ +#define P_ALRMPEND 0x08000 /* Pending SIGVTALRM needs to be posted. */ +#define P_PROFPEND 0x08000 /* Pending SIGPROF needs to be posted. */ /* Should probably be changed into a hold count. */ /* was P_NOSWAP 0x08000 was: Do not swap upages; p->p_hold */