bug-hurd
[Top][All Lists]
Advanced

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

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


From: Samuel Thibault
Subject: Re: [PATCH v4 1/3 gnumach] smp: Parallel SMP init
Date: Sun, 22 Dec 2024 02:45:24 +0100

Applied, thanks!

Damien Zammit via Bug reports for the GNU Hurd, le dim. 22 déc. 2024 01:43:28 
+0000, a ecrit:
> 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
> 
> 
> 

-- 
Samuel
 PS> Salut ! J'ai un sujet de philo à vous soumettre : "Suffit-il
 PS> d'observer pour connaître" Idées + plan Merçi
 Oui, ya qu'a t'observer pour connaître le fait que tu es une feignasse.
 -+- FF in: Guide du Neuneu d'Usenet - Neuneu fait de la philo -+-



reply via email to

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