SMP - APs are fully enabled
- apic_send_ipi() to send inter-processor interrupts (IPIs) - APIC IPI schedule and halt handlers to signal x-cpu that a cpu shold reschedule or halt - various little changes to let APs run - no processes are scheduled at the APs and therefore they are idle except being interrupted by a timer time to time
This commit is contained in:
		
							parent
							
								
									d37b7ebc0b
								
							
						
					
					
						commit
						9e12630d75
					
				@ -294,6 +294,11 @@ PUBLIC void ioapic_eoi(int irq)
 | 
			
		||||
		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();
 | 
			
		||||
@ -389,16 +394,19 @@ PUBLIC void ioapic_mask_irq(unsigned irq)
 | 
			
		||||
		irq_8259_mask(irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PUBLIC void apic_ipi_sched_handler(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PUBLIC void apic_ipi_halt_handler(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PUBLIC unsigned int apicid(void)
 | 
			
		||||
{
 | 
			
		||||
	return lapic_read(LAPIC_ID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PUBLIC void ioapic_set_id(u32_t addr, unsigned int id)
 | 
			
		||||
{
 | 
			
		||||
	ioapic_write(addr, IOAPIC_ID, id << 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PRIVATE int calib_clk_handler(irq_hook_t * UNUSED(hook))
 | 
			
		||||
{
 | 
			
		||||
	u32_t tcrt;
 | 
			
		||||
@ -793,10 +801,8 @@ PRIVATE struct gate_table_s gate_table_common[] = {
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
@ -909,6 +915,45 @@ PUBLIC int detect_ioapics(void)
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
@ -919,6 +964,8 @@ PUBLIC int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline)
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 2; i++) {
 | 
			
		||||
		u32_t val;
 | 
			
		||||
		
 | 
			
		||||
		/* clear err status */
 | 
			
		||||
		lapic_errstatus();
 | 
			
		||||
 | 
			
		||||
		/* set target pe */
 | 
			
		||||
@ -938,8 +985,8 @@ PUBLIC int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline)
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,8 @@
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
@ -157,12 +159,31 @@ _PROTOTYPE(void ioapic_unset_irq, (unsigned irq));
 | 
			
		||||
 /* 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)
 | 
			
		||||
 | 
			
		||||
@ -68,26 +68,12 @@ ENTRY(lapic_timer_int_handler)
 | 
			
		||||
	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 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -126,13 +126,10 @@ PRIVATE void smp_start_aps(void)
 | 
			
		||||
	 * 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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -150,7 +147,6 @@ PRIVATE void smp_start_aps(void)
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
			}
 | 
			
		||||
@ -176,14 +172,42 @@ PUBLIC void smp_halt_cpu (void)
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@ -222,12 +246,6 @@ PRIVATE void ap_finish_booting(void)
 | 
			
		||||
	ap_boot_finished(cpu);
 | 
			
		||||
	spinlock_unlock(&boot_lock);
 | 
			
		||||
 | 
			
		||||
	/* finish processor initialisation. */
 | 
			
		||||
	lapic_enable(cpu);
 | 
			
		||||
 | 
			
		||||
	BKL_UNLOCK();
 | 
			
		||||
	for(;;);
 | 
			
		||||
 | 
			
		||||
	switch_to_user();
 | 
			
		||||
	NOT_REACHABLE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -69,8 +69,9 @@ PRIVATE void pagefault( struct proc *pr,
 | 
			
		||||
		/* 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);
 | 
			
		||||
@ -207,7 +208,7 @@ PUBLIC void exception_handler(int is_nested, struct exception_frame * frame)
 | 
			
		||||
	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",
 | 
			
		||||
 | 
			
		||||
@ -5,21 +5,6 @@
 | 
			
		||||
 | 
			
		||||
#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 */
 | 
			
		||||
@ -31,6 +16,8 @@
 | 
			
		||||
 */
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,5 @@ void wait_for_APs_to_finish_booting(void)
 | 
			
		||||
 | 
			
		||||
void ap_boot_finished(unsigned cpu)
 | 
			
		||||
{
 | 
			
		||||
	printf("CPU %d is running\n", cpu);
 | 
			
		||||
 | 
			
		||||
	ap_cpus_booted++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -28,13 +28,6 @@ EXTERN unsigned bsp_cpu_id;
 | 
			
		||||
 */
 | 
			
		||||
_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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user