summaryrefslogtreecommitdiff
path: root/src/arch/i386/include/arch/smp/lapic.h
blob: 0ac87aa2d3e678f6d0b7d441500250a7697d77f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#ifndef ARCH_SMP_LAPIC_H
#define ARCH_SMP_LAPIC_H

#include <cpu/p6/msr.h>
#include <cpu/p6/apic.h>
#include <arch/hlt.h>

static void enable_lapic(void)
{

	msr_t msr;
	msr = rdmsr(0x1b);
	msr.hi &= 0xffffff00;
	msr.lo &= 0x000007ff;
	msr.lo |= APIC_DEFAULT_BASE | (1 << 11);
	wrmsr(0x1b, msr);
}

static void disable_lapic(void)
{
	msr_t msr;
	msr = rdmsr(0x1b);
	msr.lo &= ~ (1 << 11);
	wrmsr(0x1b, msr);
}

static inline unsigned long lapicid(void)
{
	return apic_read(APIC_ID) >> 24;
}

static void stop_this_cpu(void)
{
	unsigned apicid;
	apicid = lapicid();

	/* Send an APIC INIT to myself */
	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
	apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
	/* Wait for the ipi send to finish */
	apic_wait_icr_idle();

	/* Deassert the APIC INIT */
	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
	apic_write(APIC_ICR,  APIC_INT_LEVELTRIG | APIC_DM_INIT);
	/* Wait for the ipi send to finish */
	apic_wait_icr_idle();

	/* If I haven't halted spin forever */
	for(;;) {
		hlt();
	}
}

#endif /* ARCH_SMP_LAPIC_H */