diff options
author | marcel <marcel@FreeBSD.org> | 2002-05-12 05:54:21 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2002-05-12 05:54:21 +0000 |
commit | 49d0eba5f2e4c8bc62afa196db9dc683dd92018e (patch) | |
tree | 60e30ee3008b26ae2fe106aea4d4197176e7a65c /sys | |
parent | e7bbea38d981582adb68f002d1abf784b0ea7047 (diff) | |
download | FreeBSD-src-49d0eba5f2e4c8bc62afa196db9dc683dd92018e.zip FreeBSD-src-49d0eba5f2e4c8bc62afa196db9dc683dd92018e.tar.gz |
o Rename ia64_count_aps to ia64_count_cpus and reimplement the
function to return the total number of CPUs and not the highest
CPU id.
o Define mp_maxid based on the minimum of the actual number of
CPUs in the system and MAXCPU.
o In cpu_mp_add, when the CPU id of the CPU we're trying to add
is larger than mp_maxid, don't add the CPU. Formerly this was
based on MAXCPU. Don't count CPUs when we add them. We already
know how many CPUs exist.
o Replace MAXCPU with mp_maxid when used in loops that iterate
over the id space. This avoids a couple of useless iterations.
o In cpu_mp_unleash, use the number of CPUs to determine if we
need to launch the CPUs.
o Remove mp_hardware as it's not used anymore.
o Move the IPI vector array from mp_machdep.c to sal.c. We use
the array as a centralized place to collect vector assignments.
Note that we still assign vectors to SMP specific IPIs in
non-SMP configurations. Rename the array from mp_ipi_vector to
ipi_vector.
o Add IPI_MCA_RENDEZ and IPI_MCA_CMCV. These are used by MCA.
Note that IPI_MCA_CMCV is not SMP specific.
o Initialize the ipi_vector array so that we place the IPIs in
sensible priority classes. The classes are relative to where
the AP wake-up vector is located to guarantee that it's the
highest priority (external) interrupt. Class assignment is
as follows:
class IPI notes
x AP wake-up (normally x=15)
x-1 MCA rendezvous
x-2 AST, Rendezvous, stop
x-3 CMCV, test
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ia64/acpica/madt.c | 35 | ||||
-rw-r--r-- | sys/ia64/ia64/interrupt.c | 8 | ||||
-rw-r--r-- | sys/ia64/ia64/mp_machdep.c | 45 | ||||
-rw-r--r-- | sys/ia64/ia64/sal.c | 70 | ||||
-rw-r--r-- | sys/ia64/include/cpu.h | 2 | ||||
-rw-r--r-- | sys/ia64/include/smp.h | 21 |
6 files changed, 125 insertions, 56 deletions
diff --git a/sys/ia64/acpica/madt.c b/sys/ia64/acpica/madt.c index 0734f3e..0ddd374 100644 --- a/sys/ia64/acpica/madt.c +++ b/sys/ia64/acpica/madt.c @@ -134,30 +134,39 @@ parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source) static int parse_madt(APIC_TABLE *madt, int countcpus) { - char *p, *end; - int maxid = 0; + char *end, *p; + int cpus; + + end = (char *)madt + madt->Header.Length; /* * MADT header is followed by a number of variable length * structures. */ - end = (char *) madt + madt->Header.Length; - for (p = (char *) (madt + 1); p < end; ) { - APIC_HEADER *head = (APIC_HEADER *) p; - if (countcpus) { + if (countcpus) { + cpus = 0; + + for (p = (char *)(madt + 1); p < end; ) { + APIC_HEADER *head = (APIC_HEADER *)p; + if (head->Type == APIC_LOCAL_SAPIC) { LOCAL_SAPIC *sapic = (LOCAL_SAPIC *) head; if (sapic->ProcessorEnabled) - if (sapic->ProcessorId > maxid) - maxid = sapic->ProcessorId; + cpus++; } p = p + head->Length; - continue; } + return (cpus); + } + + for (p = (char *)(madt + 1); p < end; ) { + APIC_HEADER *head = (APIC_HEADER *)p; + if (bootverbose) printf("\t"); + switch (head->Type) { case APIC_PROC: if (bootverbose) @@ -220,7 +229,7 @@ parse_madt(APIC_TABLE *madt, int countcpus) p = p + head->Length; } - return (maxid); + return (0); } static int @@ -262,11 +271,11 @@ ia64_probe_sapics(void) } /* - * Return the maximum cpuid used by any cpu in the system. This will - * return zero for systems with only one cpu. + * Count the number of local SAPIC entries in the APIC table. Every enabled + * entry corresponds to a processor. */ int -ia64_count_aps(void) +ia64_count_cpus(void) { return (parse_table(1)); } diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index a7483a5..ec26586 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -122,12 +122,12 @@ interrupt(u_int64_t vector, struct trapframe *framep) statclock((struct clockframe *)framep); critical_exit(); #ifdef SMP - } else if (vector == mp_ipi_vector[IPI_AST]) { + } else if (vector == ipi_vector[IPI_AST]) { CTR1(KTR_SMP, "IPI_AST, cpuid=%d", PCPU_GET(cpuid)); - } else if (vector == mp_ipi_vector[IPI_RENDEZVOUS]) { + } else if (vector == ipi_vector[IPI_RENDEZVOUS]) { CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid)); smp_rendezvous_action(); - } else if (vector == mp_ipi_vector[IPI_STOP]) { + } else if (vector == ipi_vector[IPI_STOP]) { u_int32_t mybit = PCPU_GET(cpumask); CTR1(KTR_SMP, "IPI_STOP, cpuid=%d", PCPU_GET(cpuid)); @@ -142,7 +142,7 @@ interrupt(u_int64_t vector, struct trapframe *framep) cpustop_restartfunc = NULL; (*f)(); } - } else if (vector == mp_ipi_vector[IPI_TEST]) { + } else if (vector == ipi_vector[IPI_TEST]) { CTR1(KTR_SMP, "IPI_TEST, cpuid=%d", PCPU_GET(cpuid)); mp_ipi_test++; #endif diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index ff5b4ae..cc7e181 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -63,8 +63,6 @@ extern vm_offset_t vhpt_base, vhpt_size; #define LID_SAPIC_SET(id,eid) (((id & 0xff) << 8 | (eid & 0xff)) << 16); #define LID_SAPIC_MASK 0xffff0000UL -int mp_hardware = 0; -int mp_ipi_vector[IPI_COUNT]; int mp_ipi_test = 0; /* Variables used by os_boot_rendez */ @@ -124,15 +122,26 @@ int cpu_mp_probe() { /* - * We've already discovered any APs when they're present. - * Just return the result here. + * Count the number of processors in the system by walking the ACPI + * tables. Note that we record the actual number of processors, even + * if this is larger than MAXCPU. We only activate MAXCPU processors. */ - if (mp_hardware) { - mp_maxid = ia64_count_aps(); - return (mp_maxid > 0); - } else { - return (0); - } + mp_ncpus = ia64_count_cpus(); + + /* + * Set the largest cpuid we're going to use. This is necessary for + * VM initialization. + */ + mp_maxid = min(mp_ncpus, MAXCPU) - 1; + + /* + * If there's only 1 processor, or we don't have a wake-up vector, + * we're not going to enable SMP. Note that no wake-up vector can + * also mean that the wake-up mechanism is not supported. In this + * case we can have multiple processors, but we simply can't wake + * them up... + */ + return (mp_ncpus > 1 && ipi_vector[IPI_AP_WAKEUP] != 0); } void @@ -141,14 +150,9 @@ cpu_mp_add(uint acpiid, uint apicid, uint apiceid) struct pcpu *pc; u_int64_t lid; - /* Count all CPUs, even the ones we cannot use */ - mp_ncpus++; - /* Ignore any processor numbers outside our range */ - if (acpiid >= MAXCPU) { - printf("SMP: cpu%d skipped; increase MAXCPU\n", acpiid); + if (acpiid > mp_maxid) return; - } KASSERT((all_cpus & (1UL << acpiid)) == 0, ("%s: cpu%d already in CPU map", __func__, acpiid)); @@ -176,7 +180,7 @@ cpu_mp_announce() struct pcpu *pc; int i; - for (i = 0; i < MAXCPU; i++) { + for (i = 0; i <= mp_maxid; i++) { pc = pcpu_find(i); if (pc != NULL) { printf("cpu%d: SAPIC Id=%x, SAPIC Eid=%x", i, @@ -247,7 +251,7 @@ cpu_mp_unleash(void *dummy) struct pcpu *pc; int cpus; - if (!mp_hardware) + if (mp_ncpus <= 1) return; if (mp_ipi_test != 1) @@ -340,8 +344,9 @@ ipi_send(u_int64_t lid, int ipi) pipi = ia64_memory_address(PAL_PIB_DEFAULT_ADDR | ((lid & LID_SAPIC_MASK) >> 12)); - vector = (u_int64_t)(mp_ipi_vector[ipi] & 0xff); - CTR3(KTR_SMP, "ipi_send(%p, %ld), cpuid=%d", pipi, vector, PCPU_GET(cpuid)); + vector = (u_int64_t)(ipi_vector[ipi] & 0xff); + CTR3(KTR_SMP, "ipi_send(%p, %ld), cpuid=%d", pipi, vector, + PCPU_GET(cpuid)); *pipi = vector; ia64_mf_a(); } diff --git a/sys/ia64/ia64/sal.c b/sys/ia64/ia64/sal.c index ee15042..db3a094 100644 --- a/sys/ia64/ia64/sal.c +++ b/sys/ia64/ia64/sal.c @@ -36,6 +36,13 @@ #include <machine/sal.h> #include <machine/smp.h> +/* + * IPIs are used more genericly than only + * for inter-processor interrupts. Don't + * make it a SMP specific thing... + */ +int ipi_vector[IPI_COUNT]; + static struct ia64_fdesc sal_fdesc; static sal_entry_t fake_sal; @@ -54,6 +61,21 @@ fake_sal(u_int64_t a1, u_int64_t a2, u_int64_t a3, u_int64_t a4, return res; } +static void +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++; +} + void ia64_sal_init(struct sal_system_table *saltab) { @@ -90,30 +112,60 @@ ia64_sal_init(struct sal_system_table *saltab) struct sal_ap_wakeup_descriptor *dp; #ifdef SMP struct ia64_sal_result result; - int ipi; #endif dp = (struct sal_ap_wakeup_descriptor*)p; - KASSERT(dp->sale_mechanism == 0, - ("Unsupported AP wake-up mechanism")); + if (dp->sale_mechanism != 0) { + printf("SAL: unsupported AP wake-up mechanism " + "(%d)\n", dp->sale_mechanism); + break; + } + + if (dp->sale_vector < 0x10 || dp->sale_vector > 0xff) { + printf("SAL: invalid AP wake-up vector " + "(0x%lx)\n", dp->sale_vector); + break; + } + + /* + * SAL documents that the wake-up vector should be + * high (close to 255). The MCA rendezvous vector + * should be less than the wake-up vector, but still + * "high". We use the following priority assignment: + * Wake-up: priority of the sale_vector + * Rendezvous: priority-1 + * Generic IPIs: priority-2 + * Special IPIs: priority-3 + * Consequently, the wake-up priority should be at + * least 4 (ie vector >= 0x40). + */ + if (dp->sale_vector < 0x40) { + printf("SAL: AP wake-up vector too low " + "(0x%lx)\n", dp->sale_vector); + break; + } + if (bootverbose) - printf("SMP: AP wake-up vector: 0x%lx\n", + printf("SAL: AP wake-up vector: 0x%x\n", dp->sale_vector); -#ifdef SMP - for (ipi = 0; ipi < IPI_COUNT; ipi++) - mp_ipi_vector[ipi] = dp->sale_vector + ipi; + ipi_vector[IPI_AP_WAKEUP] = dp->sale_vector; + setup_ipi_vectors(dp->sale_vector & 0xf0); + +#ifdef SMP result = ia64_sal_entry(SAL_SET_VECTORS, SAL_OS_BOOT_RENDEZ, ia64_tpa(FDESC_FUNC(os_boot_rendez)), ia64_tpa(FDESC_GP(os_boot_rendez)), 0, 0, 0, 0); - - mp_hardware = 1; #endif + break; } } p += sizes[*p]; } + + if (ipi_vector[IPI_AP_WAKEUP] == 0) + setup_ipi_vectors(0xf0); } diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h index c97450d..5169f37 100644 --- a/sys/ia64/include/cpu.h +++ b/sys/ia64/include/cpu.h @@ -136,7 +136,7 @@ void fork_trampoline(void); /* MAGIC */ void syscall(int, u_int64_t *, struct trapframe *); void trap(int vector, int imm, struct trapframe *framep); void ia64_probe_sapics(void); -int ia64_count_aps(void); +int ia64_count_cpus(void); void map_pal_code(void); void cpu_mp_add(uint, uint, uint); diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h index ba6677f..e985fc0 100644 --- a/sys/ia64/include/smp.h +++ b/sys/ia64/include/smp.h @@ -10,20 +10,23 @@ * Interprocessor interrupts for SMP. The following values are indices * into the IPI vector table. The SAL gives us the vector used for AP * wake-up. We base the other vectors on that. Keep IPI_AP_WAKEUP at - * index 0. + * index 0 and IPI_MCA_RENDEZ at index 1. See sal.c for details. */ -#define IPI_AP_WAKEUP 0 /* ia64 specific */ -#define IPI_AST 1 -#define IPI_RENDEZVOUS 2 -#define IPI_STOP 3 -#define IPI_TEST 4 /* ia64 specific */ +/* Architecture specific IPIs. */ +#define IPI_AP_WAKEUP 0 +#define IPI_MCA_RENDEZ 1 +#define IPI_MCA_CMCV 2 +#define IPI_TEST 3 +/* Machine independent IPIs. */ +#define IPI_AST 4 +#define IPI_RENDEZVOUS 5 +#define IPI_STOP 6 -#define IPI_COUNT 5 +#define IPI_COUNT 7 #ifndef LOCORE -extern int mp_hardware; -extern int mp_ipi_vector[]; +extern int ipi_vector[]; void ipi_all(int ipi); void ipi_all_but_self(int ipi); |