[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 5/5 gnumach] smp: Parallel SMP init
From: |
Damien Zammit |
Subject: |
[PATCH 5/5 gnumach] smp: Parallel SMP init |
Date: |
Tue, 10 Dec 2024 07:30:11 +0000 |
Now that things are in place, we switch to parallel init.
The key to this change is that the INIT/STARTUP sequence
is done in one step, and all cpus wake up at the same time.
Synchronisation is done to complete each cpu setup individually.
---
i386/i386/mp_desc.c | 51 +++++++++++++++------------------------------
i386/i386/mp_desc.h | 2 --
i386/i386/smp.c | 20 +++++++++---------
i386/i386/smp.h | 2 +-
kern/processor.c | 4 ----
5 files changed, 28 insertions(+), 51 deletions(-)
diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
index 295fccc7..12583c9e 100644
--- a/i386/i386/mp_desc.c
+++ b/i386/i386/mp_desc.c
@@ -233,9 +233,8 @@ paging_enable(void)
void
cpu_setup(int cpu)
{
- pmap_make_temporary_mapping();
pmap_set_page_dir();
- printf("AP=(%u) tempmap done\n", cpu);
+ printf("AP=(%u) pagedir done\n", cpu);
paging_enable();
flush_instr_queue();
@@ -259,13 +258,6 @@ cpu_setup(int cpu)
ap_ktss_init(cpu);
printf("AP=(%u) ktss done\n", cpu);
- pmap_remove_temporary_mapping();
- printf("AP=(%u) remove tempmap done\n", cpu);
-
- pmap_set_page_dir();
- flush_tlb();
- printf("AP=(%u) reset page dir done\n", cpu);
-
/* Initialize machine_slot fields with the cpu data */
machine_slot[cpu].cpu_subtype = CPU_SUBTYPE_AT386;
machine_slot[cpu].cpu_type = machine_slot[0].cpu_type;
@@ -286,34 +278,13 @@ cpu_ap_main(void)
do {
cpu_pause();
- } while (bspdone != cpu);
+ } while (bspdone < cpu);
__sync_synchronize();
cpu_setup(cpu);
}
-kern_return_t
-cpu_start(int cpu)
-{
- int err;
-
- assert(machine_slot[cpu].running != TRUE);
-
- uint16_t apic_id = apic_get_cpu_apic_id(cpu);
-
- printf("Trying to enable: %d at 0x%lx\n", apic_id, apboot_addr);
-
- err = smp_startup_cpu(apic_id, apboot_addr);
-
- if (!err) {
- printf("Started cpu %d (lapic id %04x)\n", cpu, apic_id);
- return KERN_SUCCESS;
- }
- printf("FATAL: Cannot init AP %d\n", cpu);
- for (;;);
-}
-
void
start_other_cpus(void)
{
@@ -341,12 +312,16 @@ start_other_cpus(void)
lapic_disable();
bspdone = 0;
+
+ /* This is set once for all APs to use */
+ pmap_make_temporary_mapping();
+
+ smp_startup_cpus(apic_get_cpu_apic_id(0), apboot_addr);
+
for (cpu = 1; cpu < ncpus; cpu++) {
machine_slot[cpu].running = FALSE;
- //Start cpu
- printf("Starting AP %d\n", cpu);
- cpu_start(cpu);
+ printf("Waiting for AP %d\n", cpu);
bspdone++;
do {
@@ -357,6 +332,14 @@ start_other_cpus(void)
}
printf("BSP: Completed SMP init\n");
+ pmap_remove_temporary_mapping();
+
+ /* Flush TLB on all cpu groups */
+ ncpus = (ncpus < 8) ? ncpus : 8;
+ for (cpu = 1; cpu < ncpus; cpu++) {
+ interrupt_processor(cpu);
+ }
+
/* Re-enable IOAPIC interrupts as per setup */
lapic_enable();
spl_init = 1;
diff --git a/i386/i386/mp_desc.h b/i386/i386/mp_desc.h
index dc3a7dc8..6af311b7 100644
--- a/i386/i386/mp_desc.h
+++ b/i386/i386/mp_desc.h
@@ -89,8 +89,6 @@ extern void interrupt_processor(int cpu);
extern void start_other_cpus(void);
-extern kern_return_t cpu_start(int cpu);
-
extern kern_return_t cpu_control(int cpu, const int *info, unsigned int count);
extern void interrupt_stack_alloc(void);
diff --git a/i386/i386/smp.c b/i386/i386/smp.c
index 5861796a..befa0510 100644
--- a/i386/i386/smp.c
+++ b/i386/i386/smp.c
@@ -90,7 +90,7 @@ wait_for_ipi(void)
}
static int
-smp_send_ipi_init(int apic_id)
+smp_send_ipi_init(int bsp_apic_id)
{
int err;
@@ -100,7 +100,7 @@ smp_send_ipi_init(int apic_id)
*
* This is EDGE triggered to match the deassert
*/
- apic_send_ipi(NO_SHORTHAND, INIT, PHYSICAL, ASSERT, EDGE, 0, apic_id);
+ apic_send_ipi(ALL_EXCLUDING_SELF, INIT, PHYSICAL, ASSERT, EDGE, 0,
bsp_apic_id);
/* Wait for delivery */
wait_for_ipi();
@@ -113,7 +113,7 @@ smp_send_ipi_init(int apic_id)
* that does not support STARTUP IPIs at all, and instead jump
* via a warm reset vector.
*/
- apic_send_ipi(NO_SHORTHAND, INIT, PHYSICAL, DE_ASSERT, EDGE, 0, apic_id);
+ apic_send_ipi(ALL_EXCLUDING_SELF, INIT, PHYSICAL, DE_ASSERT, EDGE, 0,
bsp_apic_id);
/* Wait for delivery */
wait_for_ipi();
@@ -126,7 +126,7 @@ smp_send_ipi_init(int apic_id)
}
static int
-smp_send_ipi_startup(int apic_id, int vector)
+smp_send_ipi_startup(int bsp_apic_id, int vector)
{
int err;
@@ -137,7 +137,7 @@ smp_send_ipi_startup(int apic_id, int vector)
* Have not seen any documentation for trigger mode for this IPI
* but it seems to work with EDGE. (AMD BKDG FAM16h document specifies
dont care)
*/
- apic_send_ipi(NO_SHORTHAND, STARTUP, PHYSICAL, ASSERT, EDGE, vector,
apic_id);
+ apic_send_ipi(ALL_EXCLUDING_SELF, STARTUP, PHYSICAL, ASSERT, EDGE, vector,
bsp_apic_id);
/* Wait for delivery */
wait_for_ipi();
@@ -150,7 +150,7 @@ smp_send_ipi_startup(int apic_id, int vector)
}
/* See Intel IA32/64 Software Developer's Manual 3A Section 8.4.4.1 */
-int smp_startup_cpu(unsigned apic_id, phys_addr_t start_eip)
+int smp_startup_cpus(unsigned bsp_apic_id, phys_addr_t start_eip)
{
#if 0
/* This block goes with a legacy method of INIT that only works with
@@ -174,13 +174,13 @@ int smp_startup_cpu(unsigned apic_id, phys_addr_t
start_eip)
/* Local cache flush */
asm("wbinvd":::"memory");
- printf("Sending IPIs to APIC ID %u...\n", apic_id);
+ printf("Sending IPIs from BSP APIC ID %u...\n", bsp_apic_id);
- smp_send_ipi_init(apic_id);
+ smp_send_ipi_init(bsp_apic_id);
hpet_mdelay(10);
- smp_send_ipi_startup(apic_id, start_eip >> STARTUP_VECTOR_SHIFT);
+ smp_send_ipi_startup(bsp_apic_id, start_eip >> STARTUP_VECTOR_SHIFT);
hpet_udelay(200);
- smp_send_ipi_startup(apic_id, start_eip >> STARTUP_VECTOR_SHIFT);
+ smp_send_ipi_startup(bsp_apic_id, start_eip >> STARTUP_VECTOR_SHIFT);
hpet_udelay(200);
printf("done\n");
diff --git a/i386/i386/smp.h b/i386/i386/smp.h
index a34f79da..13b01787 100644
--- a/i386/i386/smp.h
+++ b/i386/i386/smp.h
@@ -26,7 +26,7 @@
int smp_init(void);
void smp_remote_ast(unsigned logical_id);
void smp_pmap_update(unsigned logical_id);
-int smp_startup_cpu(unsigned apic_id, phys_addr_t start_eip);
+int smp_startup_cpus(unsigned bsp_apic_id, phys_addr_t start_eip);
#define cpu_pause() asm volatile ("pause" : : : "memory")
#define STARTUP_VECTOR_SHIFT (20 - 8)
diff --git a/kern/processor.c b/kern/processor.c
index 0e42fa37..ba82ca2a 100644
--- a/kern/processor.c
+++ b/kern/processor.c
@@ -452,11 +452,7 @@ kern_return_t processor_start(
{
if (processor == PROCESSOR_NULL)
return KERN_INVALID_ARGUMENT;
-#if NCPUS > 1
- return cpu_start(processor->slot_num);
-#else /* NCPUS > 1 */
return KERN_FAILURE;
-#endif /* NCPUS > 1 */
}
kern_return_t processor_exit(
--
2.45.2