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 -+-