- 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:
parent
a384bdbfc9
commit
6c56727456
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=66716
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
157
sys/isa/atrtc.c
157
sys/isa/atrtc.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user