irq_8259_eoi(irq);
}
+PUBLIC void ioapic_set_id(u32_t addr, unsigned int id)
+{
+ ioapic_write(addr, IOAPIC_ID, id << 24);
+}
+
PUBLIC int ioapic_enable_all(void)
{
i8259_disable();
irq_8259_mask(irq);
}
-PUBLIC unsigned int apicid(void)
+PUBLIC void apic_ipi_sched_handler(void)
{
- return lapic_read(LAPIC_ID);
}
-PUBLIC void ioapic_set_id(u32_t addr, unsigned int id)
+PUBLIC void apic_ipi_halt_handler(void)
{
- ioapic_write(addr, IOAPIC_ID, id << 24);
+}
+
+PUBLIC unsigned int apicid(void)
+{
+ return lapic_read(LAPIC_ID);
}
PRIVATE int calib_clk_handler(irq_hook_t * UNUSED(hook))
#ifdef CONFIG_SMP
PRIVATE struct gate_table_s gate_table_smp[] = {
- { smp_ipi_sched, SMP_SCHED_PROC, INTR_PRIVILEGE },
- { smp_ipi_dequeue, SMP_DEQUEUE_PROC, INTR_PRIVILEGE },
- { smp_ipi_reboot,SMP_CPU_REBOOT, INTR_PRIVILEGE },
- { smp_ipi_stop, SMP_CPU_HALT, INTR_PRIVILEGE },
+ { apic_ipi_sched_intr, APIC_SMP_SCHED_PROC_VECTOR, INTR_PRIVILEGE },
+ { apic_ipi_halt_intr, APIC_SMP_CPU_HALT_VECTOR, INTR_PRIVILEGE },
{ NULL, 0, 0}
};
#endif
#ifdef CONFIG_SMP
+PUBLIC void apic_send_ipi(unsigned vector, unsigned cpu, int type)
+{
+ u32_t icr1, icr2;
+
+ if (ncpus == 1)
+ /* no need of sending an IPI */
+ return;
+
+ while (lapic_read_icr1() & APIC_ICR_DELIVERY_PENDING)
+ arch_pause();
+
+ icr1 = lapic_read_icr1() & 0xFFF0F800;
+ icr2 = lapic_read_icr2() & 0xFFFFFF;
+
+ switch (type) {
+ case APIC_IPI_DEST:
+ if (!cpu_is_ready(cpu))
+ return;
+ lapic_write_icr2(icr2 | (cpuid2apicid[cpu] << 24));
+ lapic_write_icr1(icr1 | APIC_ICR_DEST_FIELD | vector);
+ break;
+ case APIC_IPI_SELF:
+ lapic_write_icr2(icr2);
+ lapic_write_icr1(icr1 | APIC_ICR_DEST_SELF | vector);
+ break;
+ case APIC_IPI_TO_ALL_BUT_SELF:
+ lapic_write_icr2(icr2);
+ lapic_write_icr1(icr1 | APIC_ICR_DEST_ALL_BUT_SELF | vector);
+ break;
+ case APIC_IPI_TO_ALL:
+ lapic_write_icr2(icr2);
+ lapic_write_icr1(icr1 | APIC_ICR_DEST_ALL | vector);
+ break;
+ default:
+ printf("WARNING : unknown send ipi type request\n");
+ }
+
+}
+
PUBLIC int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline)
{
int timeout;
for (i = 0; i < 2; i++) {
u32_t val;
+
+ /* clear err status */
lapic_errstatus();
/* set target pe */
lapic_microsec_sleep (200);
errstatus = 0;
- while ((lapic_read(LAPIC_ICR1) & APIC_ICR_DELIVERY_PENDING) && !errstatus)
- {
+ while ((lapic_read(LAPIC_ICR1) & APIC_ICR_DELIVERY_PENDING) &&
+ !errstatus) {
errstatus = lapic_errstatus();
timeout--;
if (!timeout) break;
#define IOAPIC_REDIR_TABLE 0x10
#define APIC_TIMER_INT_VECTOR 0xf0
+#define APIC_SMP_SCHED_PROC_VECTOR 0xf1
+#define APIC_SMP_CPU_HALT_VECTOR 0xf2
#define APIC_ERROR_INT_VECTOR 0xfe
#define APIC_SPURIOUS_INT_VECTOR 0xff
/* signal the end of interrupt handler to apic */
_PROTOTYPE(void ioapic_eoi, (int irq));
-_PROTOTYPE(void lapic_disable, (void));
-_PROTOTYPE(void ioapic_disable_all, (void));
-_PROTOTYPE(void ioapic_reset_pic, (void));
-
_PROTOTYPE(void dump_apic_irq_state, (void));
+_PROTOTYPE(void apic_send_ipi, (unsigned vector, unsigned cpu, int type));
+
+_PROTOTYPE(void apic_ipi_sched_intr, (void));
+_PROTOTYPE(void apic_ipi_halt_intr, (void));
+
+_PROTOTYPE(void apic_ipi_sched_handler, (void));
+_PROTOTYPE(void apic_ipi_halt_handler, (void));
+
+#define APIC_IPI_DEST 0
+#define APIC_IPI_SELF 1
+#define APIC_IPI_TO_ALL 2
+#define APIC_IPI_TO_ALL_BUT_SELF 3
+
+#define apic_send_ipi_single(vector,cpu) \
+ apic_send_ipi(vector, cpu, APIC_IPI_DEST);
+#define apic_send_ipi_self(vector) \
+ apic_send_ipi(vector, 0, APIC_IPI_SELF)
+#define apic_send_ipi_all(vector) \
+ apic_send_ipi (vector, 0, APIC_IPI_TO_ALL)
+#define apic_send_ipi_allbutself(vector) \
+ apic_send_ipi (vector, 0, APIC_IPI_TO_ALL_BUT_SELF);
+
+
#include <minix/cpufeature.h>
#define cpu_feature_apic_on_chip() _cpufeature(_CPUF_I386_APIC_ON_CHIP)
lapic_intr(_C_LABEL(timer_int_handler))
#ifdef CONFIG_SMP
-#include "arch_smp.h"
-/* FIXME dummy stubs */
-ENTRY(smp_ipi_sched)
-1: jmp 1b
+ENTRY(apic_ipi_sched_intr)
+ lapic_intr(_C_LABEL(apic_ipi_sched_handler))
-ENTRY(smp_ipi_dequeue)
-1: jmp 1b
-
-ENTRY(smp_ipi_stop)
-1: jmp 1b
-
-ENTRY(smp_ipi_reboot)
-1: jmp 1b
-
-ENTRY(smp_ipi_err_int)
-1: jmp 1b
-
-ENTRY(smp_ipi_spv_int)
-1: jmp 1b
+ENTRY(apic_ipi_halt_intr)
+ lapic_intr(_C_LABEL(apic_ipi_halt_handler))
#endif /* CONFIG_SMP */
* using the processor's apic id values.
*/
for (cpu = 0; cpu < ncpus; cpu++) {
- printf("Booting cpu %d\n", cpu);
ap_cpu_ready = -1;
/* Don't send INIT/SIPI to boot cpu. */
if((apicid() == cpuid2apicid[cpu]) &&
(apicid() == bsp_lapic_id)) {
- cpu_set_flag(cpu, CPU_IS_READY);
- printf("Skiping bsp\n");
continue;
}
while (lapic_read(LAPIC_TIMER_CCR)) {
if (ap_cpu_ready == cpu) {
- printf("CPU %d is up\n", cpu);
cpu_set_flag(cpu, CPU_IS_READY);
break;
}
PUBLIC void smp_shutdown_aps (void)
{
- NOT_IMPLEMENTED;
+ u8_t cpu;
+ unsigned aid = apicid();
+
+ if (ncpus == 1)
+ goto exit_shutdown_aps;
+
+ for (cpu = 0; cpu < ncpus; cpu++) {
+ u16_t i;
+ if (!cpu_is_ready(cpu))
+ continue;
+ if ((aid == cpuid2apicid[cpu]) && (aid == bsp_lapic_id))
+ continue;
+ apic_send_ipi(APIC_SMP_CPU_HALT_VECTOR, cpu, APIC_IPI_DEST);
+ /* TODO wait for the cpu to be down */
+ }
+
+ /* Sending INIT to a processor makes it to wait in a halt state */
+ for (cpu = 0; cpu < ncpus; cpu++) {
+ if ((aid == cpuid2apicid[cpu]) && (aid == bsp_lapic_id))
+ continue;
+ apic_send_init_ipi (cpu, 0);
+ }
+exit_shutdown_aps:
+ ioapic_disable_all();
+
+ lapic_disable();
+
+ ncpus = 1; /* hopefully !!! */
+ lapic_addr = lapic_eoi_addr = 0;
+ return;
}
PRIVATE void ap_finish_booting(void)
{
unsigned cpu = cpuid;
- printf("CPU %d says hello world!\n", cpu);
/* inform the world of our presence. */
ap_cpu_ready = cpu;
ap_boot_finished(cpu);
spinlock_unlock(&boot_lock);
- /* finish processor initialisation. */
- lapic_enable(cpu);
-
- BKL_UNLOCK();
- for(;;);
-
switch_to_user();
NOT_REACHABLE;
}
/* Page fault we can't / don't want to
* handle.
*/
- printf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n",
- pr->p_endpoint, pr->p_name, pr->p_reg.pc,
+ printf("pagefault for process %d ('%s') on CPU %d, "
+ "pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n",
+ pr->p_endpoint, pr->p_name, cpuid, pr->p_reg.pc,
pagefaultcr2, frame->errcode, is_nested);
proc_stacktrace(pr);
printf("pc of pagefault: 0x%lx\n", frame->eip);
printf("\nIntel-reserved exception %d\n", frame->vector);
else
printf("\n%s\n", ep->msg);
- printf("is_nested = %d ", is_nested);
+ printf("cpu %d is_nested = %d ", cpuid, is_nested);
printf("vec_nr= %d, trap_errno= 0x%x, eip= 0x%x, "
"cs= 0x%x, eflags= 0x%x trap_esp 0x%08x\n",
#define MAX_NR_INTERRUPT_ENTRIES 128
-#define SMP_SCHED_PROC 0xF0
-#define SMP_DEQUEUE_PROC 0xF1
-#define SMP_CPU_REBOOT 0xF2
-#define SMP_CPU_HALT 0xF3
-#define SMP_ERROR_INT 0xF4
-
-/* currently only 2 interrupt priority levels are used */
-#define SPL0 0x0
-#define SPLHI 0xF
-
-#define SMP_IPI_DEST 0
-#define SMP_IPI_SELF 1
-#define SMP_IPI_TO_ALL 2
-#define SMP_IPI_TO_ALL_BUT_SELF 3
-
#ifndef __ASSEMBLY__
/* returns the current cpu id */
*/
#define smp_single_cpu_fallback() do { \
tss_init(0, get_k_stack_top(0)); \
+ bsp_cpu_id = 0; \
+ ncpus = 1; \
bsp_finish_booting(); \
} while(0)
void ap_boot_finished(unsigned cpu)
{
- printf("CPU %d is running\n", cpu);
-
ap_cpus_booted++;
}
*/
_PROTOTYPE(void smp_init, (void));
-_PROTOTYPE(void smp_ipi_err_int, (void));
-_PROTOTYPE(void smp_ipi_spv_int, (void));
-_PROTOTYPE(void smp_ipi_sched, (void));
-_PROTOTYPE(void smp_ipi_dequeue, (void));
-_PROTOTYPE(void smp_ipi_stop, (void));
-_PROTOTYPE(void smp_ipi_reboot, (void));
-
#define CPU_IS_BSP 1
#define CPU_IS_READY 2