bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v4 1/3 gnumach] smp: Parallel SMP init


From: Damien Zammit
Subject: [PATCH v4 1/3 gnumach] smp: Parallel SMP init
Date: Sun, 22 Dec 2024 01:43:28 +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 via waiting for individual flags stored
in separate memory locations.
---
 i386/i386/apic.h    |  4 ++-
 i386/i386/mp_desc.c | 65 ++++++++++++---------------------------------
 i386/i386/mp_desc.h |  4 ---
 i386/i386/smp.c     | 20 +++++++-------
 i386/i386/smp.h     |  2 +-
 kern/processor.c    |  4 ---
 6 files changed, 31 insertions(+), 68 deletions(-)

diff --git a/i386/i386/apic.h b/i386/i386/apic.h
index cb700c44..5b38bfba 100644
--- a/i386/i386/apic.h
+++ b/i386/i386/apic.h
@@ -314,7 +314,9 @@ extern uint32_t *hpet_addr;
 
 /* Since Logical Destination Register only has 8 bits of mask,
  * we can only address 8 unique groups of cpus for IPIs.  */
-#define APIC_LOGICAL_ID(cpu)             (1u << ((cpu) % 8))
+#define APIC_LOGICAL_CPU_GROUPS        8
+#define APIC_LOGICAL_ID(cpu)           (1u << ((cpu) % 
APIC_LOGICAL_CPU_GROUPS))
+
 
 /* Set or clear a bit in a 255-bit APIC mask register.
    These registers are spread through eight 32-bit registers.  */
diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
index 3802cdc6..c90600f2 100644
--- a/i386/i386/mp_desc.c
+++ b/i386/i386/mp_desc.c
@@ -95,11 +95,6 @@ interrupt_stack_alloc(void)
 }
 
 #if    NCPUS > 1
-/*
- * Flag to mark SMP init by BSP complete
- */
-int bspdone;
-
 phys_addr_t apboot_addr;
 extern void *apboot, *apbootend;
 extern volatile ApicLocalUnit* lapic;
@@ -233,9 +228,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();
@@ -260,13 +254,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;
@@ -284,36 +271,9 @@ cpu_ap_main()
 
     assert(cpu > 0);
 
-    do {
-       cpu_pause();
-    } 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)
 {
@@ -340,23 +300,32 @@ start_other_cpus(void)
         */
        lapic_disable();
 
-       bspdone = 0;
+       /* This is set once for all APs to use */
+       pmap_make_temporary_mapping();
+
        for (cpu = 1; cpu < ncpus; cpu++) {
                machine_slot[cpu].running = FALSE;
+       }
 
-               //Start cpu
-               printf("Starting AP %d\n", cpu);
-               cpu_start(cpu);
+       smp_startup_cpus(apic_get_current_cpu(), apboot_addr);
+
+       for (cpu = 1; cpu < ncpus; cpu++) {
+               printf("Waiting for AP %d\n", cpu);
 
-               bspdone++;
                do {
                        cpu_pause();
                } while (machine_slot[cpu].running == FALSE);
-
-               __sync_synchronize();
        }
        printf("BSP: Completed SMP init\n");
 
+       pmap_remove_temporary_mapping();
+
+       /* Flush TLB on all cpu groups */
+       ncpus = (ncpus < APIC_LOGICAL_CPU_GROUPS) ? ncpus : 
APIC_LOGICAL_CPU_GROUPS;
+       for (cpu = 1; cpu < ncpus; cpu++) {
+               interrupt_processor(cpu);
+       }
+
        /* Re-enable IOAPIC interrupts as per setup */
        lapic_enable();
 }
diff --git a/i386/i386/mp_desc.h b/i386/i386/mp_desc.h
index dc3a7dc8..92790171 100644
--- a/i386/i386/mp_desc.h
+++ b/i386/i386/mp_desc.h
@@ -74,8 +74,6 @@ extern struct real_descriptor *mp_gdt[NCPUS];
 
 extern uint8_t solid_intstack[];
 
-extern int bspdone;
-
 /*
  * Each CPU calls this routine to set up its descriptor tables.
  */
@@ -89,8 +87,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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]