Mega-MFC: Add SMP support and enable it by default. This includes:

conf/GENERIC: 1.73, 1.53
	ia64/exception.S: 1.57
	ia64/interrupt.c: 1.50, 1.51
	ia64/machdep.c: 1.201, 1.202
	ia64/mp_machdep.c: 1.56, 1.57, 1.58
	ia64/pmap.c: 1.161, 1.162, 1.164, 1.165, 1.166
	ia64/sal.c: 1.15
	ia64/trap.c: 1.114, 1.115
	ia64/vm_machdep.c: 1.91, 1.92
	include/ia64_cpu.h: 1.20
	include/param.h: 1.21
	include/pmap.h: 1.25
	include/proc.h: 1.15
	include/smp.h: 1.10

Approved by: re (kensmith, scottl -- thanks!)
This commit is contained in:
marcel 2005-09-13 21:07:14 +00:00
parent fcaf44b211
commit 48c62c6836
14 changed files with 446 additions and 434 deletions

View File

@ -28,7 +28,7 @@ makeoptions DEBUG=-g # Build kernel with debug information.
options CD9660 # ISO 9660 Filesystem
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options COMPAT_FREEBSD5 # Compatible with FreeBSD5
options COMPAT_FREEBSD5 # Compatible with FreeBSD5
options DDB # Support DDB
options FFS # Berkeley Fast Filesystem
options GDB # Support remote GDB
@ -46,7 +46,7 @@ options PSEUDOFS # Pseudo-filesystem framework
options SCHED_4BSD # 4BSD scheduler
#options SCHED_ULE # ULE scheduler
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
#options SMP # SMP support
options SMP # Symmetric Multi-Processor support
options SOFTUPDATES # Enable FFS soft updates support
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores

View File

@ -644,6 +644,7 @@ IVT_ENTRY(Instruction_TLB, 0x0400)
add r20=24,r18 // collision chain
;;
ld8 r21=[r21] // check VHPT tag
ld8 r20=[r20] // bucket head
;;
cmp.ne p15,p0=r21,r19
(p15) br.dpnt.few 1f
@ -722,6 +723,7 @@ IVT_ENTRY(Data_TLB, 0x0800)
add r20=24,r18 // collision chain
;;
ld8 r21=[r21] // check VHPT tag
ld8 r20=[r20] // bucket head
;;
cmp.ne p15,p0=r21,r19
(p15) br.dpnt.few 1f
@ -937,6 +939,8 @@ IVT_ENTRY(Dirty_Bit, 0x2000)
ttag r19=r16
add r20=24,r18 // collision chain
;;
ld8 r20=[r20] // bucket head
;;
ld8 r20=[r20] // first entry
;;
rsm psr.dt // turn off data translations
@ -1003,6 +1007,8 @@ IVT_ENTRY(Instruction_Access_Bit, 0x2400)
ttag r19=r16
add r20=24,r18 // collision chain
;;
ld8 r20=[r20] // bucket head
;;
ld8 r20=[r20] // first entry
;;
rsm psr.dt // turn off data translations
@ -1069,6 +1075,8 @@ IVT_ENTRY(Data_Access_Bit, 0x2800)
ttag r19=r16
add r20=24,r18 // collision chain
;;
ld8 r20=[r20] // bucket head
;;
ld8 r20=[r20] // first entry
;;
rsm psr.dt // turn off data translations

View File

@ -147,6 +147,8 @@ interrupt(u_int64_t vector, struct trapframe *tf)
if (vector == 0) {
vector = ib->ib_inta;
printf("ExtINT interrupt: vector=%ld\n", vector);
if (vector == 15)
goto stray;
}
if (vector == CLOCK_VECTOR) {/* clock interrupt */
@ -207,9 +209,11 @@ interrupt(u_int64_t vector, struct trapframe *tf)
} else if (vector == ipi_vector[IPI_HIGH_FP]) {
struct thread *thr = PCPU_GET(fpcurthread);
if (thr != NULL) {
mtx_lock_spin(&thr->td_md.md_highfp_mtx);
save_high_fp(&thr->td_pcb->pcb_high_fp);
thr->td_pcb->pcb_fpcpu = NULL;
PCPU_SET(fpcurthread, NULL);
mtx_unlock_spin(&thr->td_md.md_highfp_mtx);
}
} else if (vector == ipi_vector[IPI_RENDEZVOUS]) {
rdvs[PCPU_GET(cpuid)]++;
@ -239,6 +243,7 @@ interrupt(u_int64_t vector, struct trapframe *tf)
ia64_dispatch_intr(tf, vector);
}
stray:
atomic_subtract_int(&td->td_intr_nesting_level, 1);
return (TRAPF_USERMODE(tf));
}

View File

@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ptrace.h>
#include <sys/random.h>
#include <sys/reboot.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
@ -764,8 +765,8 @@ ia64_init(void)
*/
proc0kstack = (vm_offset_t)kstack;
thread0.td_kstack = proc0kstack;
thread0.td_pcb = (struct pcb *)
(thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
thread0.td_kstack_pages = KSTACK_PAGES;
/*
* Setup the global data for the bootstrap cpu.
*/
@ -774,6 +775,8 @@ ia64_init(void)
pcpu_init(pcpup, 0, PAGE_SIZE);
PCPU_SET(curthread, &thread0);
mutex_init();
/*
* Initialize the rest of proc 0's PCB.
*
@ -781,14 +784,11 @@ ia64_init(void)
* and make proc0's trapframe pointer point to it for sanity.
* Initialise proc0's backing store to start after u area.
*/
thread0.td_frame = (struct trapframe *)thread0.td_pcb - 1;
thread0.td_frame->tf_length = sizeof(struct trapframe);
cpu_thread_setup(&thread0);
thread0.td_frame->tf_flags = FRAME_SYSCALL;
thread0.td_pcb->pcb_special.sp =
(u_int64_t)thread0.td_frame - 16;
thread0.td_pcb->pcb_special.bspstore = (u_int64_t)proc0kstack;
mutex_init();
thread0.td_pcb->pcb_special.bspstore = thread0.td_kstack;
/*
* Initialize the virtual memory system.
@ -1428,7 +1428,6 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
/*
* High FP register functions.
* XXX no synchronization yet.
*/
int
@ -1438,13 +1437,17 @@ ia64_highfp_drop(struct thread *td)
struct pcpu *cpu;
struct thread *thr;
mtx_lock_spin(&td->td_md.md_highfp_mtx);
pcb = td->td_pcb;
cpu = pcb->pcb_fpcpu;
if (cpu == NULL)
if (cpu == NULL) {
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
return (0);
}
pcb->pcb_fpcpu = NULL;
thr = cpu->pc_fpcurthread;
cpu->pc_fpcurthread = NULL;
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
/* Post-mortem sanity checking. */
KASSERT(thr == td, ("Inconsistent high FP state"));
@ -1462,22 +1465,36 @@ ia64_highfp_save(struct thread *td)
if ((td->td_frame->tf_special.psr & IA64_PSR_MFH) == 0)
return (ia64_highfp_drop(td));
mtx_lock_spin(&td->td_md.md_highfp_mtx);
pcb = td->td_pcb;
cpu = pcb->pcb_fpcpu;
if (cpu == NULL)
if (cpu == NULL) {
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
return (0);
}
#ifdef SMP
if (td == curthread)
sched_pin();
if (cpu != pcpup) {
ipi_send(cpu->pc_lid, IPI_HIGH_FP);
while (pcb->pcb_fpcpu != cpu)
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
ipi_send(cpu, IPI_HIGH_FP);
if (td == curthread)
sched_unpin();
while (pcb->pcb_fpcpu == cpu)
DELAY(100);
return (1);
} else {
save_high_fp(&pcb->pcb_high_fp);
if (td == curthread)
sched_unpin();
}
#endif
#else
save_high_fp(&pcb->pcb_high_fp);
#endif
pcb->pcb_fpcpu = NULL;
thr = cpu->pc_fpcurthread;
cpu->pc_fpcurthread = NULL;
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
/* Post-mortem sanity cxhecking. */
KASSERT(thr == td, ("Inconsistent high FP state"));

View File

@ -64,8 +64,7 @@ MALLOC_DECLARE(M_PMAP);
void ia64_ap_startup(void);
extern vm_offset_t vhpt_base, vhpt_size;
extern u_int64_t ia64_lapic_address;
extern uint64_t ia64_lapic_address;
#define LID_SAPIC_ID(x) ((int)((x) >> 24) & 0xff)
#define LID_SAPIC_EID(x) ((int)((x) >> 16) & 0xff)
@ -74,9 +73,10 @@ extern u_int64_t ia64_lapic_address;
int mp_ipi_test = 0;
/* Variables used by os_boot_rendez */
void *ap_stack;
/* Variables used by os_boot_rendez and ia64_ap_startup */
struct pcpu *ap_pcpu;
void *ap_stack;
uint64_t ap_vhpt;
volatile int ap_delay;
volatile int ap_awake;
volatile int ap_spin;
@ -86,15 +86,16 @@ static void cpu_mp_unleash(void *);
void
ia64_ap_startup(void)
{
ap_awake = 1;
ap_delay = 0;
__asm __volatile("mov cr.pta=%0;; srlz.i;;" ::
"r" (vhpt_base + (1<<8) + (vhpt_size<<2) + 1));
pcpup = ap_pcpu;
ia64_set_k4((intptr_t)pcpup);
__asm __volatile("mov cr.pta=%0;; srlz.i;;" ::
"r" (ap_vhpt + (1<<8) + (pmap_vhpt_log2size<<2) + 1));
ap_awake = 1;
ap_delay = 0;
map_pal_code();
map_gateway_page();
@ -102,7 +103,7 @@ ia64_ap_startup(void)
/* Wait until it's time for us to be unleashed */
while (ap_spin)
/* spin */;
DELAY(0);
__asm __volatile("ssm psr.i;; srlz.d;;");
@ -119,7 +120,7 @@ ia64_ap_startup(void)
ap_awake++;
while (!smp_started)
/* spin */;
DELAY(0);
CTR1(KTR_SMP, "SMP: cpu%d launched", PCPU_GET(cpuid));
@ -242,16 +243,17 @@ cpu_mp_start()
pc->pc_current_pmap = kernel_pmap;
pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
if (pc->pc_cpuid > 0) {
ap_pcpu = pc;
ap_stack = malloc(KSTACK_PAGES * PAGE_SIZE, M_PMAP,
M_WAITOK);
ap_pcpu = pc;
ap_vhpt = pmap_vhpt_base[pc->pc_cpuid];
ap_delay = 2000;
ap_awake = 0;
if (bootverbose)
printf("SMP: waking up cpu%d\n", pc->pc_cpuid);
ipi_send(pc->pc_lid, IPI_AP_WAKEUP);
ipi_send(pc, IPI_AP_WAKEUP);
do {
DELAY(1000);
@ -292,7 +294,7 @@ cpu_mp_unleash(void *dummy)
ap_spin = 0;
while (ap_awake != smp_cpus)
/* spin */;
DELAY(0);
if (smp_cpus != cpus || cpus != mp_ncpus) {
printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n",
@ -307,13 +309,13 @@ cpu_mp_unleash(void *dummy)
* send an IPI to a set of cpus.
*/
void
ipi_selected(u_int64_t cpus, int ipi)
ipi_selected(cpumask_t cpus, int ipi)
{
struct pcpu *pc;
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
if (cpus & pc->pc_cpumask)
ipi_send(pc->pc_lid, ipi);
ipi_send(pc, ipi);
}
}
@ -326,7 +328,7 @@ ipi_all(int ipi)
struct pcpu *pc;
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
ipi_send(pc->pc_lid, ipi);
ipi_send(pc, ipi);
}
}
@ -340,7 +342,7 @@ ipi_all_but_self(int ipi)
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc != pcpup)
ipi_send(pc->pc_lid, ipi);
ipi_send(pc, ipi);
}
}
@ -351,7 +353,7 @@ void
ipi_self(int ipi)
{
ipi_send(ia64_get_lid(), ipi);
ipi_send(pcpup, ipi);
}
/*
@ -360,17 +362,18 @@ ipi_self(int ipi)
* fields are used here.
*/
void
ipi_send(u_int64_t lid, int ipi)
ipi_send(struct pcpu *cpu, int ipi)
{
volatile u_int64_t *pipi;
u_int64_t vector;
volatile uint64_t *pipi;
uint64_t vector;
pipi = __MEMIO_ADDR(ia64_lapic_address |
((lid & LID_SAPIC_MASK) >> 12));
vector = (u_int64_t)(ipi_vector[ipi] & 0xff);
((cpu->pc_lid & LID_SAPIC_MASK) >> 12));
vector = (uint64_t)(ipi_vector[ipi] & 0xff);
KASSERT(vector != 0, ("IPI %d is not assigned a vector", ipi));
*pipi = vector;
CTR3(KTR_SMP, "ipi_send(%p, %ld), cpuid=%d", pipi, vector,
PCPU_GET(cpuid));
*pipi = vector;
}
SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);

File diff suppressed because it is too large Load Diff

View File

@ -72,13 +72,15 @@ setup_ipi_vectors(int ceil)
int ipi;
ipi_vector[IPI_MCA_RENDEZ] = ceil - 0x10;
ipi_vector[IPI_MCA_CMCV] = ceil - 0x30;
ipi_vector[IPI_TEST] = ceil - 0x30 + 1;
ipi = IPI_AST; /* First generic IPI. */
ceil -= 0x20; /* First vector in group. */
while (ipi < IPI_COUNT)
ipi_vector[ipi++] = ceil++;
ipi_vector[IPI_HIGH_FP] = ceil - 0x30;
ipi_vector[IPI_MCA_CMCV] = ceil - 0x30 + 1;
ipi_vector[IPI_TEST] = ceil - 0x30 + 2;
}
void

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/exec.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/vmmeter.h>
#include <sys/sysent.h>
@ -629,7 +630,7 @@ trap(int vector, struct trapframe *tf)
if (!user)
trap_panic(vector, tf);
critical_enter();
sched_pin();
thr = PCPU_GET(fpcurthread);
if (thr == td) {
/*
@ -643,26 +644,29 @@ trap(int vector, struct trapframe *tf)
*/
printf("XXX: bogusly disabled high FP regs\n");
tf->tf_special.psr &= ~IA64_PSR_DFH;
critical_exit();
sched_unpin();
goto out;
} else if (thr != NULL) {
mtx_lock_spin(&thr->td_md.md_highfp_mtx);
pcb = thr->td_pcb;
save_high_fp(&pcb->pcb_high_fp);
pcb->pcb_fpcpu = NULL;
PCPU_SET(fpcurthread, NULL);
mtx_unlock_spin(&thr->td_md.md_highfp_mtx);
thr = NULL;
}
mtx_lock_spin(&td->td_md.md_highfp_mtx);
pcb = td->td_pcb;
pcpu = pcb->pcb_fpcpu;
#ifdef SMP
if (pcpu != NULL) {
ipi_send(pcpu->pc_lid, IPI_HIGH_FP);
critical_exit();
while (pcb->pcb_fpcpu != pcpu)
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
ipi_send(pcpu, IPI_HIGH_FP);
while (pcb->pcb_fpcpu == pcpu)
DELAY(100);
critical_enter();
mtx_lock_spin(&td->td_md.md_highfp_mtx);
pcpu = pcb->pcb_fpcpu;
thr = PCPU_GET(fpcurthread);
}
@ -676,7 +680,8 @@ trap(int vector, struct trapframe *tf)
tf->tf_special.psr &= ~IA64_PSR_DFH;
}
critical_exit();
mtx_unlock_spin(&td->td_md.md_highfp_mtx);
sched_unpin();
goto out;
}

View File

@ -118,6 +118,7 @@ cpu_thread_setup(struct thread *td)
sp -= sizeof(struct trapframe);
td->td_frame = (struct trapframe *)sp;
td->td_frame->tf_length = sizeof(struct trapframe);
mtx_init(&td->td_md.md_highfp_mtx, "High FP lock", NULL, MTX_SPIN);
}
void

View File

@ -226,7 +226,7 @@ ia64_tpa(u_int64_t va)
static __inline void
ia64_ptc_e(u_int64_t v)
{
__asm __volatile("ptc.e %0;; srlz.d;;" :: "r"(v));
__asm __volatile("ptc.e %0;; srlz.i;;" :: "r"(v));
}
/*
@ -235,7 +235,7 @@ ia64_ptc_e(u_int64_t v)
static __inline void
ia64_ptc_g(u_int64_t va, u_int64_t log2size)
{
__asm __volatile("ptc.g %0,%1;; srlz.d;;" :: "r"(va), "r"(log2size));
__asm __volatile("ptc.g %0,%1;; srlz.i;;" :: "r"(va), "r"(log2size));
}
/*
@ -244,7 +244,7 @@ ia64_ptc_g(u_int64_t va, u_int64_t log2size)
static __inline void
ia64_ptc_ga(u_int64_t va, u_int64_t log2size)
{
__asm __volatile("ptc.ga %0,%1;; srlz.d;;" :: "r"(va), "r"(log2size));
__asm __volatile("ptc.ga %0,%1;; srlz.i;;" :: "r"(va), "r"(log2size));
}
/*
@ -253,7 +253,7 @@ ia64_ptc_ga(u_int64_t va, u_int64_t log2size)
static __inline void
ia64_ptc_l(u_int64_t va, u_int64_t log2size)
{
__asm __volatile("ptc.l %0,%1;; srlz.d;;" :: "r"(va), "r"(log2size));
__asm __volatile("ptc.l %0,%1;; srlz.i;;" :: "r"(va), "r"(log2size));
}
/*

View File

@ -83,7 +83,7 @@
#endif
#ifdef SMP
#define MAXCPU 16
#define MAXCPU 4
#else
#define MAXCPU 1
#endif

View File

@ -115,6 +115,9 @@ extern vm_offset_t phys_avail[];
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;
extern uint64_t pmap_vhpt_base[];
extern int pmap_vhpt_log2size;
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
vm_offset_t pmap_steal_memory(vm_size_t);

View File

@ -30,8 +30,9 @@
#define _MACHINE_PROC_H_
struct mdthread {
struct mtx md_highfp_mtx;
int md_spinlock_count; /* (k) */
register_t md_saved_intr; /* (k) */
int md_saved_intr; /* (k) */
};
struct mdproc {

View File

@ -28,13 +28,15 @@
#ifndef LOCORE
struct pcpu;
extern int ipi_vector[];
void ipi_all(int ipi);
void ipi_all_but_self(int ipi);
void ipi_selected(u_int64_t cpus, int ipi);
void ipi_selected(cpumask_t cpus, int ipi);
void ipi_self(int ipi);
void ipi_send(u_int64_t lid, int ipi);
void ipi_send(struct pcpu *, int ipi);
#endif /* !LOCORE */
#endif /* _KERNEL */