Merge SMP code from IBM-PC tree into PC-98 tree.

This commit is contained in:
KATO Takenori 1997-04-27 13:22:09 +00:00
parent a8a74574b2
commit e1ee467aaf
15 changed files with 736 additions and 57 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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