Merge SMP code from IBM-PC tree into PC-98 tree.
This commit is contained in:
parent
a8a74574b2
commit
e1ee467aaf
@ -3,7 +3,7 @@
|
||||
#
|
||||
# modified for PC-9801
|
||||
#
|
||||
# $Id: files.pc98,v 1.21 1997/04/08 10:33:24 kato Exp $
|
||||
# $Id: files.pc98,v 1.22 1997/04/15 11:43:10 kato Exp $
|
||||
#
|
||||
aic7xxx_asm optional ahc device-driver \
|
||||
dependency "$S/dev/aic7xxx/*.[chyl]" \
|
||||
@ -56,6 +56,10 @@ i386/i386/initcpu.c standard
|
||||
pc98/i386/machdep.c standard
|
||||
i386/i386/math_emulate.c optional math_emulate
|
||||
i386/i386/mem.c standard
|
||||
i386/i386/mp_machdep.c optional smp
|
||||
i386/i386/mpapic.c optional smp
|
||||
i386/i386/mpboot.s optional smp
|
||||
i386/i386/mplock.s optional smp
|
||||
pc98/i386/microtime.s standard
|
||||
i386/i386/perfmon.c optional perfmon profiling-routine
|
||||
i386/i386/perfmon.c optional perfmon
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: options.pc98,v 1.19 1997/03/22 18:54:15 kato Exp $
|
||||
# $Id: options.pc98,v 1.20 1997/04/05 15:06:30 kato Exp $
|
||||
BOUNCEPAGES opt_bounce.h
|
||||
USER_LDT
|
||||
MATH_EMULATE opt_math_emulate.h
|
||||
@ -28,6 +28,23 @@ PCVT_FREEBSD opt_pcvt.h
|
||||
PCVT_SCANSET opt_pcvt.h
|
||||
XSERVER opt_pcvt.h
|
||||
|
||||
SMP opt_smp.h
|
||||
APIC_IO opt_smp.h
|
||||
NCPU opt_smp.h
|
||||
NBUS opt_smp.h
|
||||
NAPIC opt_smp.h
|
||||
NINTR opt_smp.h
|
||||
SMP_TIMER_NC opt_smp.h
|
||||
|
||||
# Should be working. When one cpu flushes it's TLB, it's propagated to all.
|
||||
SMP_INVLTLB opt_smp_invltlb.h
|
||||
|
||||
# These three are known to be broken, don't enable them.
|
||||
SMP_PRIVPAGES opt_smp_privpages.h
|
||||
SMP_AUTOSTART opt_smp_autostart.h
|
||||
|
||||
SERIAL_DEBUG opt_serial.h
|
||||
|
||||
AHC_TAGENABLE opt_aic7xxx.h
|
||||
AHC_SCBPAGING_ENABLE opt_aic7xxx.h
|
||||
AHC_ALLOW_MEMIO opt_aic7xxx.h
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.18 1997/03/05 16:19:48 kato Exp $
|
||||
* $Id: clock.c,v 1.19 1997/04/07 10:53:14 kato Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -53,6 +53,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_clock.h"
|
||||
#include "opt_smp.h"
|
||||
#include "opt_cpu.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -110,7 +111,7 @@
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
u_int idelayed;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
u_int i586_ctr_bias;
|
||||
u_int i586_ctr_comultiplier;
|
||||
u_int i586_ctr_freq;
|
||||
@ -176,7 +177,7 @@ static int rtc_inb __P((void));
|
||||
static void rtc_outb __P((int));
|
||||
#endif
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
@ -694,7 +695,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
@ -727,7 +728,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
@ -832,7 +833,7 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
i586_ctr_freq = 0;
|
||||
#endif
|
||||
}
|
||||
@ -840,7 +841,7 @@ startrtclock()
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_I586_CALIBRATION
|
||||
if (i586_ctr_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -1123,12 +1124,29 @@ resettodr()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(APIC_IO)
|
||||
|
||||
/* from icu.s: */
|
||||
extern u_int hwisrs[];
|
||||
extern void vec8254 __P((void));
|
||||
extern void vecRTC __P((void));
|
||||
extern u_int ivectors[];
|
||||
extern u_int Xintr8254;
|
||||
extern u_int XintrRTC;
|
||||
extern u_int mask8254;
|
||||
extern u_int maskRTC;
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
/*
|
||||
* Start both clocks running.
|
||||
*/
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
#if defined(APIC_IO)
|
||||
int x;
|
||||
#endif /* APIC_IO */
|
||||
#ifndef PC98
|
||||
int diag;
|
||||
|
||||
@ -1149,11 +1167,51 @@ cpu_initclocks()
|
||||
#endif
|
||||
|
||||
/* Finish initializing 8253 timer 0. */
|
||||
#if defined(APIC_IO)
|
||||
/* 8254 is traditionally on ISA IRQ0 */
|
||||
if ((x = get_isa_apic_irq(0)) < 0) {
|
||||
/*
|
||||
* bummer, this mb doesn't have the 8254 on ISA irq0,
|
||||
* perhaps it's on the EISA bus...
|
||||
*/
|
||||
if ((x = get_eisa_apic_irq(0)) < 0) {
|
||||
/* double bummer, attempt to redirect thru the 8259 */
|
||||
if (bootverbose)
|
||||
printf("APIC missing 8254 connection\n");
|
||||
|
||||
/* allow 8254 timer to INTerrupt 8259 */
|
||||
#if !defined(IO_ICU1)
|
||||
#ifdef PC98
|
||||
#define IO_ICU1 0x00
|
||||
#else
|
||||
#define IO_ICU1 0x20
|
||||
#endif
|
||||
#endif
|
||||
x = inb(IO_ICU1 + 1); /* current mask in 8259 */
|
||||
x &= ~1; /* clear 8254 timer mask */
|
||||
outb(IO_ICU1 + 1, x); /* write new mask */
|
||||
|
||||
/* program IO APIC for type 3 INT on INT0 */
|
||||
if (ext_int_setup(0, 0) < 0)
|
||||
panic("8254 redirect impossible!");
|
||||
x = 0; /* 8259 is on 0 */
|
||||
}
|
||||
}
|
||||
|
||||
hwisrs[x] = (u_int)vec8254;
|
||||
Xintr8254 = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
|
||||
mask8254 = (1 << x);
|
||||
register_intr(/* irq */ x, /* XXX id */ 0, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)clkintr, &clk_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(mask8254);
|
||||
#else
|
||||
register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)clkintr, &clk_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(IRQ0);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#endif /* APIC_IO */
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
@ -1172,12 +1230,37 @@ cpu_initclocks()
|
||||
diag = rtcin(RTC_DIAG);
|
||||
if (diag != 0)
|
||||
printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
|
||||
#if defined(APIC_IO)
|
||||
/* RTC is traditionally on ISA IRQ8 */
|
||||
if ((x = get_isa_apic_irq(8)) < 0) {
|
||||
if ((x = get_eisa_apic_irq(8)) < 0) {
|
||||
panic("APIC missing RTC connection");
|
||||
}
|
||||
}
|
||||
|
||||
hwisrs[x] = (u_int)vecRTC;
|
||||
XintrRTC = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
|
||||
maskRTC = (1 << x);
|
||||
register_intr(/* irq */ x, /* XXX id */ 1, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)rtcintr, &stat_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(maskRTC);
|
||||
#else
|
||||
register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)rtcintr, &stat_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(IRQ8);
|
||||
#endif /* APIC_IO */
|
||||
writertc(RTC_STATUSB, rtc_statusb);
|
||||
#endif
|
||||
|
||||
#if defined(APIC_IO)
|
||||
printf("Enabled INTs: ");
|
||||
for (x = 0; x < 24; ++x)
|
||||
if ((imen & (1 << x)) == 0)
|
||||
printf("%d, ", x);
|
||||
printf("imen: 0x%08x\n", imen);
|
||||
#endif /* APIC_IO */
|
||||
}
|
||||
|
||||
void
|
||||
@ -1208,7 +1291,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_i586_ctr_freq(i586_ctr_freq, timer_freq);
|
||||
#endif
|
||||
}
|
||||
@ -1218,7 +1301,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq)
|
||||
{
|
||||
@ -1257,4 +1340,4 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* defined(I586_CPU) || defined(I686_CPU) */
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.18 1997/03/05 16:19:48 kato Exp $
|
||||
* $Id: clock.c,v 1.19 1997/04/07 10:53:14 kato Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -53,6 +53,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_clock.h"
|
||||
#include "opt_smp.h"
|
||||
#include "opt_cpu.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -110,7 +111,7 @@
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
u_int idelayed;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
u_int i586_ctr_bias;
|
||||
u_int i586_ctr_comultiplier;
|
||||
u_int i586_ctr_freq;
|
||||
@ -176,7 +177,7 @@ static int rtc_inb __P((void));
|
||||
static void rtc_outb __P((int));
|
||||
#endif
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
@ -694,7 +695,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
@ -727,7 +728,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
@ -832,7 +833,7 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
i586_ctr_freq = 0;
|
||||
#endif
|
||||
}
|
||||
@ -840,7 +841,7 @@ startrtclock()
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_I586_CALIBRATION
|
||||
if (i586_ctr_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -1123,12 +1124,29 @@ resettodr()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(APIC_IO)
|
||||
|
||||
/* from icu.s: */
|
||||
extern u_int hwisrs[];
|
||||
extern void vec8254 __P((void));
|
||||
extern void vecRTC __P((void));
|
||||
extern u_int ivectors[];
|
||||
extern u_int Xintr8254;
|
||||
extern u_int XintrRTC;
|
||||
extern u_int mask8254;
|
||||
extern u_int maskRTC;
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
/*
|
||||
* Start both clocks running.
|
||||
*/
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
#if defined(APIC_IO)
|
||||
int x;
|
||||
#endif /* APIC_IO */
|
||||
#ifndef PC98
|
||||
int diag;
|
||||
|
||||
@ -1149,11 +1167,51 @@ cpu_initclocks()
|
||||
#endif
|
||||
|
||||
/* Finish initializing 8253 timer 0. */
|
||||
#if defined(APIC_IO)
|
||||
/* 8254 is traditionally on ISA IRQ0 */
|
||||
if ((x = get_isa_apic_irq(0)) < 0) {
|
||||
/*
|
||||
* bummer, this mb doesn't have the 8254 on ISA irq0,
|
||||
* perhaps it's on the EISA bus...
|
||||
*/
|
||||
if ((x = get_eisa_apic_irq(0)) < 0) {
|
||||
/* double bummer, attempt to redirect thru the 8259 */
|
||||
if (bootverbose)
|
||||
printf("APIC missing 8254 connection\n");
|
||||
|
||||
/* allow 8254 timer to INTerrupt 8259 */
|
||||
#if !defined(IO_ICU1)
|
||||
#ifdef PC98
|
||||
#define IO_ICU1 0x00
|
||||
#else
|
||||
#define IO_ICU1 0x20
|
||||
#endif
|
||||
#endif
|
||||
x = inb(IO_ICU1 + 1); /* current mask in 8259 */
|
||||
x &= ~1; /* clear 8254 timer mask */
|
||||
outb(IO_ICU1 + 1, x); /* write new mask */
|
||||
|
||||
/* program IO APIC for type 3 INT on INT0 */
|
||||
if (ext_int_setup(0, 0) < 0)
|
||||
panic("8254 redirect impossible!");
|
||||
x = 0; /* 8259 is on 0 */
|
||||
}
|
||||
}
|
||||
|
||||
hwisrs[x] = (u_int)vec8254;
|
||||
Xintr8254 = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
|
||||
mask8254 = (1 << x);
|
||||
register_intr(/* irq */ x, /* XXX id */ 0, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)clkintr, &clk_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(mask8254);
|
||||
#else
|
||||
register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)clkintr, &clk_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(IRQ0);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#endif /* APIC_IO */
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
@ -1172,12 +1230,37 @@ cpu_initclocks()
|
||||
diag = rtcin(RTC_DIAG);
|
||||
if (diag != 0)
|
||||
printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
|
||||
#if defined(APIC_IO)
|
||||
/* RTC is traditionally on ISA IRQ8 */
|
||||
if ((x = get_isa_apic_irq(8)) < 0) {
|
||||
if ((x = get_eisa_apic_irq(8)) < 0) {
|
||||
panic("APIC missing RTC connection");
|
||||
}
|
||||
}
|
||||
|
||||
hwisrs[x] = (u_int)vecRTC;
|
||||
XintrRTC = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
|
||||
maskRTC = (1 << x);
|
||||
register_intr(/* irq */ x, /* XXX id */ 1, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)rtcintr, &stat_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(maskRTC);
|
||||
#else
|
||||
register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)rtcintr, &stat_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(IRQ8);
|
||||
#endif /* APIC_IO */
|
||||
writertc(RTC_STATUSB, rtc_statusb);
|
||||
#endif
|
||||
|
||||
#if defined(APIC_IO)
|
||||
printf("Enabled INTs: ");
|
||||
for (x = 0; x < 24; ++x)
|
||||
if ((imen & (1 << x)) == 0)
|
||||
printf("%d, ", x);
|
||||
printf("imen: 0x%08x\n", imen);
|
||||
#endif /* APIC_IO */
|
||||
}
|
||||
|
||||
void
|
||||
@ -1208,7 +1291,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_i586_ctr_freq(i586_ctr_freq, timer_freq);
|
||||
#endif
|
||||
}
|
||||
@ -1218,7 +1301,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq)
|
||||
{
|
||||
@ -1257,4 +1340,4 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* defined(I586_CPU) || defined(I686_CPU) */
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
|
@ -31,12 +31,13 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
|
||||
* $Id: sio.c,v 1.21 1997/04/05 15:04:32 kato Exp $
|
||||
* $Id: sio.c,v 1.22 1997/04/19 14:54:32 kato Exp $
|
||||
*/
|
||||
|
||||
#include "opt_comconsole.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_sio.h"
|
||||
#include "opt_smp.h"
|
||||
#include "sio.h"
|
||||
|
||||
/*
|
||||
@ -160,6 +161,16 @@
|
||||
#include <pccard/slot.h>
|
||||
#endif
|
||||
|
||||
#if defined(APIC_IO)
|
||||
/*
|
||||
* INTs are masked in the (global) IO APIC,
|
||||
* but the IRR register is in each LOCAL APIC,
|
||||
* so we HAVE to unmask the INT to be able to "see INT pending"
|
||||
* BUT how do we clear them???
|
||||
*/
|
||||
#define isa_irq_pending icu_irq_pending
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
|
||||
#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE)
|
||||
#define RS_IBUFSIZE 256
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# modified for PC-9801
|
||||
#
|
||||
# $Id: files.pc98,v 1.21 1997/04/08 10:33:24 kato Exp $
|
||||
# $Id: files.pc98,v 1.22 1997/04/15 11:43:10 kato Exp $
|
||||
#
|
||||
aic7xxx_asm optional ahc device-driver \
|
||||
dependency "$S/dev/aic7xxx/*.[chyl]" \
|
||||
@ -56,6 +56,10 @@ i386/i386/initcpu.c standard
|
||||
pc98/i386/machdep.c standard
|
||||
i386/i386/math_emulate.c optional math_emulate
|
||||
i386/i386/mem.c standard
|
||||
i386/i386/mp_machdep.c optional smp
|
||||
i386/i386/mpapic.c optional smp
|
||||
i386/i386/mpboot.s optional smp
|
||||
i386/i386/mplock.s optional smp
|
||||
pc98/i386/microtime.s standard
|
||||
i386/i386/perfmon.c optional perfmon profiling-routine
|
||||
i386/i386/perfmon.c optional perfmon
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: options.pc98,v 1.19 1997/03/22 18:54:15 kato Exp $
|
||||
# $Id: options.pc98,v 1.20 1997/04/05 15:06:30 kato Exp $
|
||||
BOUNCEPAGES opt_bounce.h
|
||||
USER_LDT
|
||||
MATH_EMULATE opt_math_emulate.h
|
||||
@ -28,6 +28,23 @@ PCVT_FREEBSD opt_pcvt.h
|
||||
PCVT_SCANSET opt_pcvt.h
|
||||
XSERVER opt_pcvt.h
|
||||
|
||||
SMP opt_smp.h
|
||||
APIC_IO opt_smp.h
|
||||
NCPU opt_smp.h
|
||||
NBUS opt_smp.h
|
||||
NAPIC opt_smp.h
|
||||
NINTR opt_smp.h
|
||||
SMP_TIMER_NC opt_smp.h
|
||||
|
||||
# Should be working. When one cpu flushes it's TLB, it's propagated to all.
|
||||
SMP_INVLTLB opt_smp_invltlb.h
|
||||
|
||||
# These three are known to be broken, don't enable them.
|
||||
SMP_PRIVPAGES opt_smp_privpages.h
|
||||
SMP_AUTOSTART opt_smp_autostart.h
|
||||
|
||||
SERIAL_DEBUG opt_serial.h
|
||||
|
||||
AHC_TAGENABLE opt_aic7xxx.h
|
||||
AHC_SCBPAGING_ENABLE opt_aic7xxx.h
|
||||
AHC_ALLOW_MEMIO opt_aic7xxx.h
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.36 1997/04/13 06:02:52 kato Exp $
|
||||
* $Id: machdep.c,v 1.37 1997/04/22 12:20:28 kato Exp $
|
||||
*/
|
||||
|
||||
#include "npx.h"
|
||||
@ -44,6 +44,7 @@
|
||||
#include "opt_bounce.h"
|
||||
#include "opt_machdep.h"
|
||||
#include "opt_perfmon.h"
|
||||
#include "opt_smp.h"
|
||||
#include "opt_userconfig.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -107,6 +108,9 @@
|
||||
#include <machine/cons.h>
|
||||
#include <machine/bootinfo.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef SMP
|
||||
#include <machine/smp.h>
|
||||
#endif
|
||||
#ifdef PERFMON
|
||||
#include <machine/perfmon.h>
|
||||
#endif
|
||||
@ -220,6 +224,9 @@ cpu_startup(dummy)
|
||||
* Good {morning,afternoon,evening,night}.
|
||||
*/
|
||||
printf(version);
|
||||
#ifdef SMP
|
||||
mp_announce();
|
||||
#endif
|
||||
earlysetcpuclass();
|
||||
startrtclock();
|
||||
printcpuinfo();
|
||||
@ -355,6 +362,23 @@ cpu_startup(dummy)
|
||||
u_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
||||
(maxproc*UPAGES*PAGE_SIZE), FALSE);
|
||||
|
||||
#if defined(SMP) && defined(SMP_PRIVPAGES)
|
||||
/* Per-cpu pages.. (the story so far is... subject to change)
|
||||
* ========= For the per-cpu data page ========
|
||||
* 1 private data page
|
||||
* 1 PDE (per-cpu PTD entry page)
|
||||
* 1 PT (per-cpu page table page)
|
||||
* ============ For the idle loop =============
|
||||
* 2 UPAGEs (per-cpu idle procs)
|
||||
* 1 PTD (for per-cpu equiv of IdlePTD)
|
||||
* ============================================
|
||||
* = total of 6 pages per cpu. The BSP reuses the ones allocated
|
||||
* by locore.s during boot to remove special cases at runtime.
|
||||
*/
|
||||
ppage_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
||||
(NCPU*6*PAGE_SIZE), FALSE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Finally, allocate mbuf pool. Since mclrefcnt is an off-size
|
||||
* we use the more space efficient malloc in place of kmem_alloc.
|
||||
@ -759,10 +783,24 @@ SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
|
||||
|
||||
int currentldt;
|
||||
int _default_ldt;
|
||||
#ifdef SMP
|
||||
union descriptor gdt[NGDT + NCPU]; /* global descriptor table */
|
||||
#else
|
||||
union descriptor gdt[NGDT]; /* global descriptor table */
|
||||
#endif
|
||||
struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */
|
||||
union descriptor ldt[NLDT]; /* local descriptor table */
|
||||
#ifdef SMP
|
||||
/* table descriptors - used to load tables by microp */
|
||||
struct region_descriptor r_gdt, r_idt;
|
||||
#endif
|
||||
|
||||
#ifdef SMP
|
||||
struct i386tss SMPcommon_tss[NCPU]; /* One tss per cpu */
|
||||
struct i386tss *SMPcommon_tss_ptr[NCPU]; /* for the benefit of asmp code */
|
||||
#else
|
||||
struct i386tss common_tss;
|
||||
#endif
|
||||
|
||||
static struct i386tss dblfault_tss;
|
||||
static char dblfault_stack[PAGE_SIZE];
|
||||
@ -775,7 +813,11 @@ int gsel_tss;
|
||||
#endif
|
||||
|
||||
/* software prototypes -- in more palatable form */
|
||||
struct soft_segment_descriptor gdt_segs[] = {
|
||||
struct soft_segment_descriptor gdt_segs[
|
||||
#ifdef SMP
|
||||
NGDT + NCPU
|
||||
#endif
|
||||
] = {
|
||||
/* GNULL_SEL 0 Null Descriptor */
|
||||
{ 0x0, /* segment base address */
|
||||
0x0, /* length */
|
||||
@ -831,7 +873,12 @@ struct soft_segment_descriptor gdt_segs[] = {
|
||||
0, /* unused - default 32 vs 16 bit size */
|
||||
0 /* limit granularity (byte/page units)*/ },
|
||||
/* GPROC0_SEL 6 Proc 0 Tss Descriptor */
|
||||
{ (int) &common_tss, /* segment base address */
|
||||
{
|
||||
#ifdef SMP
|
||||
(int) &SMPcommon_tss[0],/* segment base address */
|
||||
#else
|
||||
(int) &common_tss, /* segment base address */
|
||||
#endif
|
||||
sizeof(struct i386tss)-1,/* length - all address space */
|
||||
SDT_SYS386TSS, /* segment type */
|
||||
0, /* segment descriptor priority level */
|
||||
@ -979,8 +1026,10 @@ init386(first)
|
||||
int gsel_tss;
|
||||
#endif
|
||||
struct isa_device *idp;
|
||||
#ifndef SMP
|
||||
/* table descriptors - used to load tables by microp */
|
||||
struct region_descriptor r_gdt, r_idt;
|
||||
#endif
|
||||
int pagesinbase, pagesinext;
|
||||
int target_page, pa_indx;
|
||||
int off;
|
||||
@ -1020,6 +1069,18 @@ init386(first)
|
||||
for (x = 0; x < NGDT; x++)
|
||||
ssdtosd(&gdt_segs[x], &gdt[x].sd);
|
||||
|
||||
#ifdef SMP
|
||||
/*
|
||||
* Oh puke!
|
||||
*/
|
||||
for (x = 0; x < NCPU; x++) {
|
||||
SMPcommon_tss_ptr[x] = &SMPcommon_tss[x];
|
||||
gdt_segs[NGDT + x] = gdt_segs[GPROC0_SEL];
|
||||
gdt_segs[NGDT + x].ssd_base = (int) SMPcommon_tss_ptr[x];
|
||||
ssdtosd(&gdt_segs[NGDT + x], &gdt[NGDT + x].sd);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* make ldt memory segments */
|
||||
/*
|
||||
* The data segment limit must not cover the user area because we
|
||||
@ -1180,7 +1241,13 @@ init386(first)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SMP
|
||||
/* make hole for AP bootstrap code */
|
||||
pagesinbase = mp_bootaddress(biosbasemem) / PAGE_SIZE;
|
||||
#else
|
||||
pagesinbase = biosbasemem * 1024 / PAGE_SIZE;
|
||||
#endif
|
||||
|
||||
pagesinext = biosextmem * 1024 / PAGE_SIZE;
|
||||
|
||||
/*
|
||||
@ -1219,6 +1286,11 @@ init386(first)
|
||||
/* call pmap initialization to make new kernel address space */
|
||||
pmap_bootstrap (first, 0);
|
||||
|
||||
#ifdef SMP
|
||||
/* fire up the APs and APICs */
|
||||
mp_start();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Size up each available chunk of physical memory.
|
||||
*/
|
||||
@ -1351,12 +1423,23 @@ init386(first)
|
||||
avail_end + off, VM_PROT_ALL, TRUE);
|
||||
msgbufmapped = 1;
|
||||
|
||||
#ifdef SMP
|
||||
for(x = 0; x < NCPU; x++) {
|
||||
/* make an initial tss so cpu can get interrupt stack on syscall! */
|
||||
SMPcommon_tss[x].tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE;
|
||||
SMPcommon_tss[x].tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
|
||||
SMPcommon_tss[x].tss_ioopt = (sizeof SMPcommon_tss[x]) << 16;
|
||||
}
|
||||
gsel_tss = GSEL(NGDT + cpunumber(), SEL_KPL);
|
||||
ltr(gsel_tss);
|
||||
#else
|
||||
/* make an initial tss so cpu can get interrupt stack on syscall! */
|
||||
common_tss.tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE;
|
||||
common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
|
||||
common_tss.tss_ioopt = (sizeof common_tss) << 16;
|
||||
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
|
||||
ltr(gsel_tss);
|
||||
#endif
|
||||
|
||||
dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
|
||||
dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
|
||||
@ -1397,6 +1480,7 @@ init386(first)
|
||||
/* setup proc 0's pcb */
|
||||
proc0.p_addr->u_pcb.pcb_flags = 0;
|
||||
proc0.p_addr->u_pcb.pcb_cr3 = IdlePTD;
|
||||
proc0.p_addr->u_pcb.pcb_mpnest = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -32,11 +32,15 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Steve McCanne's microtime code
|
||||
* $Id$
|
||||
* $Id: microtime.s,v 1.8 1997/02/22 09:43:27 peter Exp $
|
||||
*/
|
||||
|
||||
#include "opt_cpu.h"
|
||||
#include "opt_smp.h"
|
||||
|
||||
#ifdef APIC_IO
|
||||
#include <machine/apic.h>
|
||||
#endif /* APIC_IO */
|
||||
#include <machine/asmacros.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
@ -49,7 +53,7 @@
|
||||
|
||||
ENTRY(microtime)
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
movl _i586_ctr_freq, %ecx
|
||||
testl %ecx, %ecx
|
||||
jne pentium_microtime
|
||||
@ -113,15 +117,26 @@ ENTRY(microtime)
|
||||
|
||||
movl _timer0_max_count, %edx /* prepare for 2 uses */
|
||||
|
||||
#if defined(APIC_IO)
|
||||
movl _ipending, %eax
|
||||
testl %eax, _mask8254 /* is soft timer interrupt pending? */
|
||||
#else
|
||||
testb $IRQ0, _ipending /* is a soft timer interrupt pending? */
|
||||
#endif /* APIC_IO */
|
||||
jne overflow
|
||||
|
||||
/* Do we have a possible overflow condition? */
|
||||
cmpl _timer0_overflow_threshold, %ecx
|
||||
jbe 1f
|
||||
|
||||
#if defined(APIC_IO)
|
||||
movl _apic_base, %eax
|
||||
movl APIC_IRR1(%eax), %eax /** XXX assumption: IRQ0-24 */
|
||||
testl %eax, _mask8254 /* is a hard timer interrupt pending? */
|
||||
#else
|
||||
inb $IO_ICU1, %al /* read IRR in ICU */
|
||||
testb $IRQ0, %al /* is a hard timer interrupt pending? */
|
||||
#endif /* APIC_IO */
|
||||
je 1f
|
||||
overflow:
|
||||
subl %edx, %ecx /* some intr pending, count timer down through 0 */
|
||||
@ -248,7 +263,7 @@ common_microtime:
|
||||
|
||||
ret
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
ALIGN_TEXT
|
||||
pentium_microtime:
|
||||
pushfl
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.16 1997/04/07 11:00:48 kato Exp $
|
||||
* $Id: trap.c,v 1.17 1997/04/15 11:49:00 kato Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -44,6 +44,7 @@
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_smp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -76,6 +77,7 @@
|
||||
#include <machine/reg.h>
|
||||
#include <machine/trap.h>
|
||||
#include <machine/../isa/isa_device.h>
|
||||
#include <machine/smp.h>
|
||||
|
||||
#ifdef POWERFAIL_NMI
|
||||
#include <sys/syslog.h>
|
||||
@ -85,7 +87,11 @@
|
||||
#include "isa.h"
|
||||
#include "npx.h"
|
||||
|
||||
#ifdef SMP
|
||||
extern struct i386tss *SMPcommon_tss_ptr[NCPU];
|
||||
#else
|
||||
extern struct i386tss common_tss;
|
||||
#endif
|
||||
|
||||
int (*pmath_emulate) __P((struct trapframe *));
|
||||
|
||||
@ -728,6 +734,9 @@ trap_fatal(frame)
|
||||
printf("\n\nFatal trap %d: %s while in %s mode\n",
|
||||
type, trap_msg[type],
|
||||
ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
|
||||
#ifdef SMP
|
||||
printf("cpunumber = %d\n", cpunumber());
|
||||
#endif
|
||||
if (type == T_PAGEFLT) {
|
||||
printf("fault virtual address = 0x%x\n", eva);
|
||||
printf("fault code = %s %s, %s\n",
|
||||
@ -790,6 +799,7 @@ trap_fatal(frame)
|
||||
if (kdb_trap (type, 0, frame))
|
||||
return;
|
||||
#endif
|
||||
printf("trap number = %d\n", type);
|
||||
if (type <= MAX_TRAP_MSG)
|
||||
panic(trap_msg[type]);
|
||||
else
|
||||
@ -811,11 +821,20 @@ trap_fatal(frame)
|
||||
void
|
||||
dblfault_handler()
|
||||
{
|
||||
#ifdef SMP
|
||||
int x = cpunumber();
|
||||
#endif
|
||||
|
||||
printf("\nFatal double fault:\n");
|
||||
#ifdef SMP
|
||||
printf("eip = 0x%x\n", SMPcommon_tss_ptr[x]->tss_eip);
|
||||
printf("esp = 0x%x\n", SMPcommon_tss_ptr[x]->tss_esp);
|
||||
printf("ebp = 0x%x\n", SMPcommon_tss_ptr[x]->tss_ebp);
|
||||
#else
|
||||
printf("eip = 0x%x\n", common_tss.tss_eip);
|
||||
printf("esp = 0x%x\n", common_tss.tss_esp);
|
||||
printf("ebp = 0x%x\n", common_tss.tss_ebp);
|
||||
#endif
|
||||
panic("double fault");
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.18 1997/03/05 16:19:48 kato Exp $
|
||||
* $Id: clock.c,v 1.19 1997/04/07 10:53:14 kato Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -53,6 +53,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_clock.h"
|
||||
#include "opt_smp.h"
|
||||
#include "opt_cpu.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -110,7 +111,7 @@
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
u_int idelayed;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
u_int i586_ctr_bias;
|
||||
u_int i586_ctr_comultiplier;
|
||||
u_int i586_ctr_freq;
|
||||
@ -176,7 +177,7 @@ static int rtc_inb __P((void));
|
||||
static void rtc_outb __P((int));
|
||||
#endif
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
@ -694,7 +695,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
@ -727,7 +728,7 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
@ -832,7 +833,7 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
i586_ctr_freq = 0;
|
||||
#endif
|
||||
}
|
||||
@ -840,7 +841,7 @@ startrtclock()
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_I586_CALIBRATION
|
||||
if (i586_ctr_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -1123,12 +1124,29 @@ resettodr()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(APIC_IO)
|
||||
|
||||
/* from icu.s: */
|
||||
extern u_int hwisrs[];
|
||||
extern void vec8254 __P((void));
|
||||
extern void vecRTC __P((void));
|
||||
extern u_int ivectors[];
|
||||
extern u_int Xintr8254;
|
||||
extern u_int XintrRTC;
|
||||
extern u_int mask8254;
|
||||
extern u_int maskRTC;
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
/*
|
||||
* Start both clocks running.
|
||||
*/
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
#if defined(APIC_IO)
|
||||
int x;
|
||||
#endif /* APIC_IO */
|
||||
#ifndef PC98
|
||||
int diag;
|
||||
|
||||
@ -1149,11 +1167,51 @@ cpu_initclocks()
|
||||
#endif
|
||||
|
||||
/* Finish initializing 8253 timer 0. */
|
||||
#if defined(APIC_IO)
|
||||
/* 8254 is traditionally on ISA IRQ0 */
|
||||
if ((x = get_isa_apic_irq(0)) < 0) {
|
||||
/*
|
||||
* bummer, this mb doesn't have the 8254 on ISA irq0,
|
||||
* perhaps it's on the EISA bus...
|
||||
*/
|
||||
if ((x = get_eisa_apic_irq(0)) < 0) {
|
||||
/* double bummer, attempt to redirect thru the 8259 */
|
||||
if (bootverbose)
|
||||
printf("APIC missing 8254 connection\n");
|
||||
|
||||
/* allow 8254 timer to INTerrupt 8259 */
|
||||
#if !defined(IO_ICU1)
|
||||
#ifdef PC98
|
||||
#define IO_ICU1 0x00
|
||||
#else
|
||||
#define IO_ICU1 0x20
|
||||
#endif
|
||||
#endif
|
||||
x = inb(IO_ICU1 + 1); /* current mask in 8259 */
|
||||
x &= ~1; /* clear 8254 timer mask */
|
||||
outb(IO_ICU1 + 1, x); /* write new mask */
|
||||
|
||||
/* program IO APIC for type 3 INT on INT0 */
|
||||
if (ext_int_setup(0, 0) < 0)
|
||||
panic("8254 redirect impossible!");
|
||||
x = 0; /* 8259 is on 0 */
|
||||
}
|
||||
}
|
||||
|
||||
hwisrs[x] = (u_int)vec8254;
|
||||
Xintr8254 = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
|
||||
mask8254 = (1 << x);
|
||||
register_intr(/* irq */ x, /* XXX id */ 0, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)clkintr, &clk_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(mask8254);
|
||||
#else
|
||||
register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)clkintr, &clk_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(IRQ0);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#endif /* APIC_IO */
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
@ -1172,12 +1230,37 @@ cpu_initclocks()
|
||||
diag = rtcin(RTC_DIAG);
|
||||
if (diag != 0)
|
||||
printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
|
||||
#if defined(APIC_IO)
|
||||
/* RTC is traditionally on ISA IRQ8 */
|
||||
if ((x = get_isa_apic_irq(8)) < 0) {
|
||||
if ((x = get_eisa_apic_irq(8)) < 0) {
|
||||
panic("APIC missing RTC connection");
|
||||
}
|
||||
}
|
||||
|
||||
hwisrs[x] = (u_int)vecRTC;
|
||||
XintrRTC = (u_int)ivectors[x]; /* XXX might need Xfastintr# */
|
||||
maskRTC = (1 << x);
|
||||
register_intr(/* irq */ x, /* XXX id */ 1, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)rtcintr, &stat_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(maskRTC);
|
||||
#else
|
||||
register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
|
||||
/* XXX */ (inthand2_t *)rtcintr, &stat_imask,
|
||||
/* unit */ 0);
|
||||
INTREN(IRQ8);
|
||||
#endif /* APIC_IO */
|
||||
writertc(RTC_STATUSB, rtc_statusb);
|
||||
#endif
|
||||
|
||||
#if defined(APIC_IO)
|
||||
printf("Enabled INTs: ");
|
||||
for (x = 0; x < 24; ++x)
|
||||
if ((imen & (1 << x)) == 0)
|
||||
printf("%d, ", x);
|
||||
printf("imen: 0x%08x\n", imen);
|
||||
#endif /* APIC_IO */
|
||||
}
|
||||
|
||||
void
|
||||
@ -1208,7 +1291,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_i586_ctr_freq(i586_ctr_freq, timer_freq);
|
||||
#endif
|
||||
}
|
||||
@ -1218,7 +1301,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq)
|
||||
{
|
||||
@ -1257,4 +1340,4 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* defined(I586_CPU) || defined(I686_CPU) */
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.36 1997/04/13 06:02:52 kato Exp $
|
||||
* $Id: machdep.c,v 1.37 1997/04/22 12:20:28 kato Exp $
|
||||
*/
|
||||
|
||||
#include "npx.h"
|
||||
@ -44,6 +44,7 @@
|
||||
#include "opt_bounce.h"
|
||||
#include "opt_machdep.h"
|
||||
#include "opt_perfmon.h"
|
||||
#include "opt_smp.h"
|
||||
#include "opt_userconfig.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -107,6 +108,9 @@
|
||||
#include <machine/cons.h>
|
||||
#include <machine/bootinfo.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef SMP
|
||||
#include <machine/smp.h>
|
||||
#endif
|
||||
#ifdef PERFMON
|
||||
#include <machine/perfmon.h>
|
||||
#endif
|
||||
@ -220,6 +224,9 @@ cpu_startup(dummy)
|
||||
* Good {morning,afternoon,evening,night}.
|
||||
*/
|
||||
printf(version);
|
||||
#ifdef SMP
|
||||
mp_announce();
|
||||
#endif
|
||||
earlysetcpuclass();
|
||||
startrtclock();
|
||||
printcpuinfo();
|
||||
@ -355,6 +362,23 @@ cpu_startup(dummy)
|
||||
u_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
||||
(maxproc*UPAGES*PAGE_SIZE), FALSE);
|
||||
|
||||
#if defined(SMP) && defined(SMP_PRIVPAGES)
|
||||
/* Per-cpu pages.. (the story so far is... subject to change)
|
||||
* ========= For the per-cpu data page ========
|
||||
* 1 private data page
|
||||
* 1 PDE (per-cpu PTD entry page)
|
||||
* 1 PT (per-cpu page table page)
|
||||
* ============ For the idle loop =============
|
||||
* 2 UPAGEs (per-cpu idle procs)
|
||||
* 1 PTD (for per-cpu equiv of IdlePTD)
|
||||
* ============================================
|
||||
* = total of 6 pages per cpu. The BSP reuses the ones allocated
|
||||
* by locore.s during boot to remove special cases at runtime.
|
||||
*/
|
||||
ppage_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
||||
(NCPU*6*PAGE_SIZE), FALSE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Finally, allocate mbuf pool. Since mclrefcnt is an off-size
|
||||
* we use the more space efficient malloc in place of kmem_alloc.
|
||||
@ -759,10 +783,24 @@ SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
|
||||
|
||||
int currentldt;
|
||||
int _default_ldt;
|
||||
#ifdef SMP
|
||||
union descriptor gdt[NGDT + NCPU]; /* global descriptor table */
|
||||
#else
|
||||
union descriptor gdt[NGDT]; /* global descriptor table */
|
||||
#endif
|
||||
struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */
|
||||
union descriptor ldt[NLDT]; /* local descriptor table */
|
||||
#ifdef SMP
|
||||
/* table descriptors - used to load tables by microp */
|
||||
struct region_descriptor r_gdt, r_idt;
|
||||
#endif
|
||||
|
||||
#ifdef SMP
|
||||
struct i386tss SMPcommon_tss[NCPU]; /* One tss per cpu */
|
||||
struct i386tss *SMPcommon_tss_ptr[NCPU]; /* for the benefit of asmp code */
|
||||
#else
|
||||
struct i386tss common_tss;
|
||||
#endif
|
||||
|
||||
static struct i386tss dblfault_tss;
|
||||
static char dblfault_stack[PAGE_SIZE];
|
||||
@ -775,7 +813,11 @@ int gsel_tss;
|
||||
#endif
|
||||
|
||||
/* software prototypes -- in more palatable form */
|
||||
struct soft_segment_descriptor gdt_segs[] = {
|
||||
struct soft_segment_descriptor gdt_segs[
|
||||
#ifdef SMP
|
||||
NGDT + NCPU
|
||||
#endif
|
||||
] = {
|
||||
/* GNULL_SEL 0 Null Descriptor */
|
||||
{ 0x0, /* segment base address */
|
||||
0x0, /* length */
|
||||
@ -831,7 +873,12 @@ struct soft_segment_descriptor gdt_segs[] = {
|
||||
0, /* unused - default 32 vs 16 bit size */
|
||||
0 /* limit granularity (byte/page units)*/ },
|
||||
/* GPROC0_SEL 6 Proc 0 Tss Descriptor */
|
||||
{ (int) &common_tss, /* segment base address */
|
||||
{
|
||||
#ifdef SMP
|
||||
(int) &SMPcommon_tss[0],/* segment base address */
|
||||
#else
|
||||
(int) &common_tss, /* segment base address */
|
||||
#endif
|
||||
sizeof(struct i386tss)-1,/* length - all address space */
|
||||
SDT_SYS386TSS, /* segment type */
|
||||
0, /* segment descriptor priority level */
|
||||
@ -979,8 +1026,10 @@ init386(first)
|
||||
int gsel_tss;
|
||||
#endif
|
||||
struct isa_device *idp;
|
||||
#ifndef SMP
|
||||
/* table descriptors - used to load tables by microp */
|
||||
struct region_descriptor r_gdt, r_idt;
|
||||
#endif
|
||||
int pagesinbase, pagesinext;
|
||||
int target_page, pa_indx;
|
||||
int off;
|
||||
@ -1020,6 +1069,18 @@ init386(first)
|
||||
for (x = 0; x < NGDT; x++)
|
||||
ssdtosd(&gdt_segs[x], &gdt[x].sd);
|
||||
|
||||
#ifdef SMP
|
||||
/*
|
||||
* Oh puke!
|
||||
*/
|
||||
for (x = 0; x < NCPU; x++) {
|
||||
SMPcommon_tss_ptr[x] = &SMPcommon_tss[x];
|
||||
gdt_segs[NGDT + x] = gdt_segs[GPROC0_SEL];
|
||||
gdt_segs[NGDT + x].ssd_base = (int) SMPcommon_tss_ptr[x];
|
||||
ssdtosd(&gdt_segs[NGDT + x], &gdt[NGDT + x].sd);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* make ldt memory segments */
|
||||
/*
|
||||
* The data segment limit must not cover the user area because we
|
||||
@ -1180,7 +1241,13 @@ init386(first)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SMP
|
||||
/* make hole for AP bootstrap code */
|
||||
pagesinbase = mp_bootaddress(biosbasemem) / PAGE_SIZE;
|
||||
#else
|
||||
pagesinbase = biosbasemem * 1024 / PAGE_SIZE;
|
||||
#endif
|
||||
|
||||
pagesinext = biosextmem * 1024 / PAGE_SIZE;
|
||||
|
||||
/*
|
||||
@ -1219,6 +1286,11 @@ init386(first)
|
||||
/* call pmap initialization to make new kernel address space */
|
||||
pmap_bootstrap (first, 0);
|
||||
|
||||
#ifdef SMP
|
||||
/* fire up the APs and APICs */
|
||||
mp_start();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Size up each available chunk of physical memory.
|
||||
*/
|
||||
@ -1351,12 +1423,23 @@ init386(first)
|
||||
avail_end + off, VM_PROT_ALL, TRUE);
|
||||
msgbufmapped = 1;
|
||||
|
||||
#ifdef SMP
|
||||
for(x = 0; x < NCPU; x++) {
|
||||
/* make an initial tss so cpu can get interrupt stack on syscall! */
|
||||
SMPcommon_tss[x].tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE;
|
||||
SMPcommon_tss[x].tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
|
||||
SMPcommon_tss[x].tss_ioopt = (sizeof SMPcommon_tss[x]) << 16;
|
||||
}
|
||||
gsel_tss = GSEL(NGDT + cpunumber(), SEL_KPL);
|
||||
ltr(gsel_tss);
|
||||
#else
|
||||
/* make an initial tss so cpu can get interrupt stack on syscall! */
|
||||
common_tss.tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE;
|
||||
common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
|
||||
common_tss.tss_ioopt = (sizeof common_tss) << 16;
|
||||
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
|
||||
ltr(gsel_tss);
|
||||
#endif
|
||||
|
||||
dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
|
||||
dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
|
||||
@ -1397,6 +1480,7 @@ init386(first)
|
||||
/* setup proc 0's pcb */
|
||||
proc0.p_addr->u_pcb.pcb_flags = 0;
|
||||
proc0.p_addr->u_pcb.pcb_cr3 = IdlePTD;
|
||||
proc0.p_addr->u_pcb.pcb_mpnest = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -32,7 +32,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: npx.c,v 1.15 1997/03/24 12:29:39 bde Exp $
|
||||
* $Id: npx.c,v 1.16 1997/04/22 12:20:50 kato Exp $
|
||||
*/
|
||||
|
||||
#include "npx.h"
|
||||
@ -40,6 +40,7 @@
|
||||
|
||||
#include "opt_cpu.h"
|
||||
#include "opt_math_emulate.h"
|
||||
#include "opt_smp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -60,6 +61,10 @@
|
||||
#include <machine/trap.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/specialreg.h>
|
||||
#if defined(APIC_IO)
|
||||
#include <machine/apic.h>
|
||||
#include <machine/mpapic.h>
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
@ -138,7 +143,12 @@ SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
|
||||
"Floatingpoint instructions executed in hardware");
|
||||
|
||||
static u_int npx0_imask = SWI_CLOCK_MASK;
|
||||
#ifdef SMP
|
||||
#define npxproc (SMPnpxproc[cpunumber()])
|
||||
struct proc *SMPnpxproc[NCPU];
|
||||
#else
|
||||
struct proc *npxproc;
|
||||
#endif
|
||||
|
||||
static bool_t npx_ex16;
|
||||
static bool_t npx_exists;
|
||||
@ -153,8 +163,32 @@ static volatile u_int npx_traps_while_probing;
|
||||
* interrupts. We'll still need a special exception 16 handler. The busy
|
||||
* latch stuff in probeintr() can be moved to npxprobe().
|
||||
*/
|
||||
|
||||
inthand_t probeintr;
|
||||
|
||||
#if defined(APIC_IO)
|
||||
|
||||
asm
|
||||
("
|
||||
.text
|
||||
.p2align 2,0x90
|
||||
" __XSTRING(CNAME(probeintr)) ":
|
||||
ss
|
||||
incl " __XSTRING(CNAME(npx_intrs_while_probing)) "
|
||||
pushl %eax
|
||||
movl " __XSTRING(CNAME(apic_base)) ",%eax # EOI to local APIC
|
||||
movl $0,0xb0(,%eax,1) # movl $0, APIC_EOI(%eax)
|
||||
movb $0,%al
|
||||
#ifdef PC98
|
||||
outb %al,$0xf8 # clear BUSY# latch
|
||||
#else
|
||||
outb %al,$0xf0 # clear BUSY# latch
|
||||
#endif
|
||||
popl %eax
|
||||
iret
|
||||
");
|
||||
|
||||
#else
|
||||
|
||||
asm
|
||||
("
|
||||
.text
|
||||
@ -181,6 +215,8 @@ asm
|
||||
iret
|
||||
");
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
inthand_t probetrap;
|
||||
asm
|
||||
("
|
||||
@ -205,8 +241,12 @@ npxprobe(dvp)
|
||||
{
|
||||
int result;
|
||||
u_long save_eflags;
|
||||
#if defined(APIC_IO)
|
||||
u_int save_apic_mask;
|
||||
#else
|
||||
u_char save_icu1_mask;
|
||||
u_char save_icu2_mask;
|
||||
#endif /* APIC_IO */
|
||||
struct gate_descriptor save_idt_npxintr;
|
||||
struct gate_descriptor save_idt_npxtrap;
|
||||
/*
|
||||
@ -219,6 +259,9 @@ npxprobe(dvp)
|
||||
npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1;
|
||||
save_eflags = read_eflags();
|
||||
disable_intr();
|
||||
#if defined(APIC_IO)
|
||||
save_apic_mask = INTRGET();
|
||||
#else
|
||||
#ifdef PC98
|
||||
save_icu1_mask = inb(IO_ICU1 + 2);
|
||||
save_icu2_mask = inb(IO_ICU2 + 2);
|
||||
@ -226,8 +269,12 @@ npxprobe(dvp)
|
||||
save_icu1_mask = inb(IO_ICU1 + 1);
|
||||
save_icu2_mask = inb(IO_ICU2 + 1);
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
save_idt_npxintr = idt[npx_intrno];
|
||||
save_idt_npxtrap = idt[16];
|
||||
#if defined(APIC_IO)
|
||||
INTRSET( ~dvp->id_irq );
|
||||
#else
|
||||
#ifdef PC98
|
||||
outb(IO_ICU1 + 2, ~(IRQ_SLAVE | dvp->id_irq));
|
||||
outb(IO_ICU2 + 2, ~(dvp->id_irq >> 8));
|
||||
@ -235,12 +282,16 @@ npxprobe(dvp)
|
||||
outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq));
|
||||
outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8));
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
npx_idt_probeintr = idt[npx_intrno];
|
||||
enable_intr();
|
||||
result = npxprobe1(dvp);
|
||||
disable_intr();
|
||||
#if defined(APIC_IO)
|
||||
INTRSET( save_apic_mask );
|
||||
#else
|
||||
#ifdef PC98
|
||||
outb(IO_ICU1 + 2, save_icu1_mask);
|
||||
outb(IO_ICU2 + 2, save_icu2_mask);
|
||||
@ -248,6 +299,7 @@ npxprobe(dvp)
|
||||
outb(IO_ICU1 + 1, save_icu1_mask);
|
||||
outb(IO_ICU2 + 1, save_icu2_mask);
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
idt[npx_intrno] = save_idt_npxintr;
|
||||
idt[16] = save_idt_npxtrap;
|
||||
write_eflags(save_eflags);
|
||||
@ -406,7 +458,8 @@ npxattach(dvp)
|
||||
}
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
||||
#ifdef I586_CPU
|
||||
#if defined(I586_CPU) && !defined(SMP)
|
||||
/* FPU not working under SMP yet */
|
||||
if (cpu_class == CPUCLASS_586 && npx_ex16) {
|
||||
if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) {
|
||||
bcopy_vector = i586_bcopy;
|
||||
@ -622,13 +675,21 @@ void
|
||||
npxsave(addr)
|
||||
struct save87 *addr;
|
||||
{
|
||||
#if defined(APIC_IO)
|
||||
u_int apic_mask;
|
||||
u_int old_apic_mask;
|
||||
#else
|
||||
u_char icu1_mask;
|
||||
u_char icu2_mask;
|
||||
u_char old_icu1_mask;
|
||||
u_char old_icu2_mask;
|
||||
#endif /* APIC_IO */
|
||||
struct gate_descriptor save_idt_npxintr;
|
||||
|
||||
disable_intr();
|
||||
#if defined(APIC_IO)
|
||||
old_apic_mask = INTRGET();
|
||||
#else
|
||||
#ifdef PC98
|
||||
old_icu1_mask = inb(IO_ICU1 + 2);
|
||||
old_icu2_mask = inb(IO_ICU2 + 2);
|
||||
@ -636,7 +697,12 @@ npxsave(addr)
|
||||
old_icu1_mask = inb(IO_ICU1 + 1);
|
||||
old_icu2_mask = inb(IO_ICU2 + 1);
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
save_idt_npxintr = idt[npx_intrno];
|
||||
#if defined(APIC_IO)
|
||||
/** FIXME: try clrIoApicMaskBit( npx0_imask ); */
|
||||
INTRSET( old_apic_mask & ~(npx0_imask & 0xffff) );
|
||||
#else
|
||||
#ifdef PC98
|
||||
outb(IO_ICU1 + 2, old_icu1_mask & ~(IRQ_SLAVE | npx0_imask));
|
||||
outb(IO_ICU2 + 2, old_icu2_mask & ~(npx0_imask >> 8));
|
||||
@ -644,6 +710,7 @@ npxsave(addr)
|
||||
outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0_imask));
|
||||
outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0_imask >> 8));
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
idt[npx_intrno] = npx_idt_probeintr;
|
||||
enable_intr();
|
||||
stop_emulating();
|
||||
@ -652,6 +719,11 @@ npxsave(addr)
|
||||
start_emulating();
|
||||
npxproc = NULL;
|
||||
disable_intr();
|
||||
#if defined(APIC_IO)
|
||||
apic_mask = INTRGET(); /* masks may have changed */
|
||||
INTRSET( (apic_mask & ~(npx0_imask & 0xffff)) |
|
||||
(old_apic_mask & (npx0_imask & 0xffff)));
|
||||
#else
|
||||
#ifdef PC98
|
||||
icu1_mask = inb(IO_ICU1 + 2); /* masks may have changed */
|
||||
icu2_mask = inb(IO_ICU2 + 2);
|
||||
@ -669,6 +741,7 @@ npxsave(addr)
|
||||
(icu2_mask & ~(npx0_imask >> 8))
|
||||
| (old_icu2_mask & (npx0_imask >> 8)));
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
idt[npx_intrno] = save_idt_npxintr;
|
||||
enable_intr(); /* back to usual state */
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
|
||||
* $Id: pc98.c,v 1.21 1997/03/29 02:43:49 kato Exp $
|
||||
* $Id: pc98.c,v 1.22 1997/04/11 12:29:51 kato Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -53,6 +53,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_auto_eoi.h"
|
||||
#include "opt_smp.h"
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -62,6 +63,10 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/segments.h>
|
||||
#if defined(APIC_IO)
|
||||
#include <machine/smp.h>
|
||||
#include <machine/apic.h>
|
||||
#endif /* APIC_IO */
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
@ -78,6 +83,14 @@
|
||||
#include <i386/isa/ic/i8237.h>
|
||||
#include "vector.h"
|
||||
|
||||
#ifdef APIC_IO
|
||||
/*
|
||||
* This is to accommodate "mixed-mode" programming for
|
||||
* motherboards that don't connect the 8254 to the IO APIC.
|
||||
*/
|
||||
#define AUTO_EOI_1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Register definitions for DMA controller 1 (channels 0..3):
|
||||
*/
|
||||
@ -116,6 +129,16 @@ static inthand_t *fastintr[ICU_LEN] = {
|
||||
&IDTVEC(fastintr10), &IDTVEC(fastintr11),
|
||||
&IDTVEC(fastintr12), &IDTVEC(fastintr13),
|
||||
&IDTVEC(fastintr14), &IDTVEC(fastintr15)
|
||||
#if defined(APIC_IO)
|
||||
, &IDTVEC(fastintr16), &IDTVEC(fastintr17),
|
||||
&IDTVEC(fastintr18), &IDTVEC(fastintr19),
|
||||
&IDTVEC(fastintr20), &IDTVEC(fastintr21),
|
||||
&IDTVEC(fastintr22), &IDTVEC(fastintr23)
|
||||
#if defined(IPI_INTS)
|
||||
/* XXX probably NOT needed, we register_intr(slowintr[I]) */
|
||||
, &IDTVEC(ipi24), &IDTVEC(ipi25), &IDTVEC(ipi26), &IDTVEC(ipi27)
|
||||
#endif /* IPI_INTS */
|
||||
#endif /* APIC_IO */
|
||||
};
|
||||
|
||||
static inthand_t *slowintr[ICU_LEN] = {
|
||||
@ -123,6 +146,13 @@ static inthand_t *slowintr[ICU_LEN] = {
|
||||
&IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
|
||||
&IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
|
||||
&IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
|
||||
#if defined(APIC_IO)
|
||||
, &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
|
||||
&IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
|
||||
#if defined(IPI_INTS)
|
||||
, &IDTVEC(ipi24), &IDTVEC(ipi25), &IDTVEC(ipi26), &IDTVEC(ipi27)
|
||||
#endif /* IPI_INTS */
|
||||
#endif /* APIC_IO */
|
||||
};
|
||||
|
||||
static void config_isadev __P((struct isa_device *isdp, u_int *mp));
|
||||
@ -1016,6 +1046,39 @@ struct isa_device *find_isadev(table, driverp, unit)
|
||||
/*
|
||||
* Return nonzero if a (masked) irq is pending for a given device.
|
||||
*/
|
||||
#if defined(APIC_IO)
|
||||
|
||||
int
|
||||
isa_irq_pending(dvp)
|
||||
struct isa_device *dvp;
|
||||
{
|
||||
/* read APIC IRR containing the 16 ISA INTerrupts */
|
||||
#if defined(TEST_UPPERPRIO)
|
||||
if ((u_int32_t)dvp->id_irq == APIC_IRQ10)
|
||||
return (int)(apic_base[APIC_IRR2] & 1);
|
||||
else
|
||||
#endif /** TEST_UPPERPRIO */
|
||||
return ((apic_base[APIC_IRR1] & 0x00ffffff)
|
||||
& (u_int32_t)dvp->id_irq) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* an 8259 specific routine,
|
||||
* for use by boot probes in certain device drivers.
|
||||
*/
|
||||
int
|
||||
icu_irq_pending(dvp)
|
||||
struct isa_device *dvp;
|
||||
{
|
||||
unsigned id_irq;
|
||||
id_irq = dvp->id_irq;
|
||||
if (id_irq & 0xff)
|
||||
return (inb(IO_ICU1) & id_irq);
|
||||
return (inb(IO_ICU2) & (id_irq >> 8));
|
||||
}
|
||||
|
||||
#else /* APIC_IO */
|
||||
|
||||
int
|
||||
isa_irq_pending(dvp)
|
||||
struct isa_device *dvp;
|
||||
@ -1028,6 +1091,8 @@ isa_irq_pending(dvp)
|
||||
return (inb(IO_ICU2) & (id_irq >> 8));
|
||||
}
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
int
|
||||
update_intr_masks(void)
|
||||
{
|
||||
@ -1035,11 +1100,15 @@ update_intr_masks(void)
|
||||
u_int mask,*maskptr;
|
||||
|
||||
for (intr=0; intr < ICU_LEN; intr ++) {
|
||||
#ifdef PC98
|
||||
if (intr==7) continue;
|
||||
#if defined(APIC_IO)
|
||||
/* no 8259 SLAVE to ignore */
|
||||
#else
|
||||
if (intr==2) continue;
|
||||
#ifdef PC98
|
||||
if (intr==7) continue; /* ignore 8259 SLAVE output */
|
||||
#else
|
||||
if (intr==2) continue; /* ignore 8259 SLAVE output */
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
maskptr = intr_mptr[intr];
|
||||
if (!maskptr) continue;
|
||||
*maskptr |= 1 << intr;
|
||||
@ -1071,11 +1140,15 @@ register_intr(intr, device_id, flags, handler, maskptr, unit)
|
||||
int id;
|
||||
u_int mask = (maskptr ? *maskptr : 0);
|
||||
|
||||
#if defined(APIC_IO)
|
||||
if ((u_int)intr >= ICU_LEN /* no 8259 SLAVE to ignore */
|
||||
#else
|
||||
#ifdef PC98
|
||||
if ((u_int)intr >= ICU_LEN || intr == 7
|
||||
#else
|
||||
if ((u_int)intr >= ICU_LEN || intr == 2
|
||||
#endif
|
||||
#endif /* APIC_IO */
|
||||
|| (u_int)device_id >= NR_DEVICES)
|
||||
return (EINVAL);
|
||||
if (intr_handler[intr] != isa_strayintr)
|
||||
@ -1087,9 +1160,24 @@ register_intr(intr, device_id, flags, handler, maskptr, unit)
|
||||
intr_mptr[intr] = maskptr;
|
||||
intr_mask[intr] = mask | (1 << intr);
|
||||
intr_unit[intr] = unit;
|
||||
#if defined(TEST_UPPERPRIO)
|
||||
if (intr == 10) {
|
||||
printf("--- setting IRQ10 to IDT64\n");
|
||||
setidt(64,
|
||||
flags & RI_FAST ? fastintr[intr] : slowintr[intr],
|
||||
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
}
|
||||
else {
|
||||
printf("setting IRQ%02d to IDT%02d\n", intr, ICU_OFFSET+intr);
|
||||
setidt(ICU_OFFSET + intr,
|
||||
flags & RI_FAST ? fastintr[intr] : slowintr[intr],
|
||||
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
}
|
||||
#else
|
||||
setidt(ICU_OFFSET + intr,
|
||||
flags & RI_FAST ? fastintr[intr] : slowintr[intr],
|
||||
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#endif /** TEST_UPPERPRIO */
|
||||
write_eflags(ef);
|
||||
for (cp = intrnames, id = 0; id <= device_id; id++)
|
||||
while (*cp++ != '\0')
|
||||
@ -1099,9 +1187,12 @@ register_intr(intr, device_id, flags, handler, maskptr, unit)
|
||||
if (intr < 10) {
|
||||
cp[-3] = intr + '0';
|
||||
cp[-2] = ' ';
|
||||
} else {
|
||||
} else if (intr < 20) {
|
||||
cp[-3] = '1';
|
||||
cp[-2] = intr - 10 + '0';
|
||||
} else {
|
||||
cp[-3] = '2';
|
||||
cp[-2] = intr - 20 + '0';
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
@ -31,12 +31,13 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
|
||||
* $Id: sio.c,v 1.21 1997/04/05 15:04:32 kato Exp $
|
||||
* $Id: sio.c,v 1.22 1997/04/19 14:54:32 kato Exp $
|
||||
*/
|
||||
|
||||
#include "opt_comconsole.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_sio.h"
|
||||
#include "opt_smp.h"
|
||||
#include "sio.h"
|
||||
|
||||
/*
|
||||
@ -160,6 +161,16 @@
|
||||
#include <pccard/slot.h>
|
||||
#endif
|
||||
|
||||
#if defined(APIC_IO)
|
||||
/*
|
||||
* INTs are masked in the (global) IO APIC,
|
||||
* but the IRR register is in each LOCAL APIC,
|
||||
* so we HAVE to unmask the INT to be able to "see INT pending"
|
||||
* BUT how do we clear them???
|
||||
*/
|
||||
#define isa_irq_pending icu_irq_pending
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
|
||||
#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE)
|
||||
#define RS_IBUFSIZE 256
|
||||
|
Loading…
Reference in New Issue
Block a user