- 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())
This commit is contained in:
John Baldwin 2000-10-06 02:20:21 +00:00
parent a384bdbfc9
commit 6c56727456
49 changed files with 484 additions and 1002 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -72,6 +72,7 @@
#include <machine/ipl.h>
#include <machine/limits.h>
#include <machine/md_var.h>
#include <machine/mutex.h>
#include <machine/psl.h>
#ifdef APIC_IO
#include <machine/segments.h>
@ -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 @@ calibrate_clocks(void)
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);
}

View File

@ -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)
/*

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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)

View File

@ -72,6 +72,7 @@
#include <machine/ipl.h>
#include <machine/limits.h>
#include <machine/md_var.h>
#include <machine/mutex.h>
#include <machine/psl.h>
#ifdef APIC_IO
#include <machine/segments.h>
@ -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 @@ calibrate_clocks(void)
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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -72,6 +72,7 @@
#include <machine/ipl.h>
#include <machine/limits.h>
#include <machine/md_var.h>
#include <machine/mutex.h>
#include <machine/psl.h>
#ifdef APIC_IO
#include <machine/segments.h>
@ -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 @@ calibrate_clocks(void)
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);
}

View File

@ -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)

View File

@ -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)
/*

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -72,6 +72,7 @@
#include <machine/ipl.h>
#include <machine/limits.h>
#include <machine/md_var.h>
#include <machine/mutex.h>
#include <machine/psl.h>
#ifdef APIC_IO
#include <machine/segments.h>
@ -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 @@ calibrate_clocks(void)
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);
}

View File

@ -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)

View File

@ -72,6 +72,7 @@
#include <machine/ipl.h>
#include <machine/limits.h>
#include <machine/md_var.h>
#include <machine/mutex.h>
#include <machine/psl.h>
#ifdef APIC_IO
#include <machine/segments.h>
@ -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 @@ calibrate_clocks(void)
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);
}

View File

@ -58,7 +58,9 @@
#include <sys/sysctl.h>
#include <machine/cpu.h>
#include <machine/ipl.h>
#include <machine/limits.h>
#include <machine/mutex.h>
#include <machine/smp.h>
#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);
}
/*

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */