123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- #include <libcflat.h>
- #include "processor.h"
- #include "atomic.h"
- #include "smp.h"
- #include "apic.h"
- #include "fwcfg.h"
- #include "desc.h"
- #define IPI_VECTOR 0x20
- typedef void (*ipi_function_type)(void *data);
- static struct spinlock ipi_lock;
- static volatile ipi_function_type ipi_function;
- static void *volatile ipi_data;
- static volatile int ipi_done;
- static volatile bool ipi_wait;
- static int _cpu_count;
- static atomic_t active_cpus;
- static __attribute__((used)) void ipi()
- {
- void (*function)(void *data) = ipi_function;
- void *data = ipi_data;
- bool wait = ipi_wait;
- if (!wait) {
- ipi_done = 1;
- apic_write(APIC_EOI, 0);
- }
- function(data);
- atomic_dec(&active_cpus);
- if (wait) {
- ipi_done = 1;
- apic_write(APIC_EOI, 0);
- }
- }
- asm (
- "ipi_entry: \n"
- " call ipi \n"
- #ifndef __x86_64__
- " iret"
- #else
- " iretq"
- #endif
- );
- int cpu_count(void)
- {
- return _cpu_count;
- }
- int smp_id(void)
- {
- unsigned id;
- asm ("mov %%gs:0, %0" : "=r"(id));
- return id;
- }
- static void setup_smp_id(void *data)
- {
- asm ("mov %0, %%gs:0" : : "r"(apic_id()) : "memory");
- }
- static void __on_cpu(int cpu, void (*function)(void *data), void *data,
- int wait)
- {
- spin_lock(&ipi_lock);
- if (cpu == smp_id())
- function(data);
- else {
- atomic_inc(&active_cpus);
- ipi_done = 0;
- ipi_function = function;
- ipi_data = data;
- ipi_wait = wait;
- apic_icr_write(APIC_INT_ASSERT | APIC_DEST_PHYSICAL | APIC_DM_FIXED
- | IPI_VECTOR,
- cpu);
- while (!ipi_done)
- ;
- }
- spin_unlock(&ipi_lock);
- }
- void on_cpu(int cpu, void (*function)(void *data), void *data)
- {
- __on_cpu(cpu, function, data, 1);
- }
- void on_cpu_async(int cpu, void (*function)(void *data), void *data)
- {
- __on_cpu(cpu, function, data, 0);
- }
- void on_cpus(void (*function)(void *data), void *data)
- {
- int cpu;
- for (cpu = cpu_count() - 1; cpu >= 0; --cpu)
- on_cpu_async(cpu, function, data);
- while (cpus_active() > 1)
- pause();
- }
- int cpus_active(void)
- {
- return atomic_read(&active_cpus);
- }
- void smp_init(void)
- {
- int i;
- void ipi_entry(void);
- _cpu_count = fwcfg_get_nb_cpus();
- setup_idt();
- set_idt_entry(IPI_VECTOR, ipi_entry, 0);
- setup_smp_id(0);
- for (i = 1; i < cpu_count(); ++i)
- on_cpu(i, setup_smp_id, 0);
- atomic_inc(&active_cpus);
- }
|