123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- #include "libcflat.h"
- #include "apic.h"
- #include "msr.h"
- #include "processor.h"
- static void *g_apic = (void *)0xfee00000;
- static void *g_ioapic = (void *)0xfec00000;
- struct apic_ops {
- u32 (*reg_read)(unsigned reg);
- void (*reg_write)(unsigned reg, u32 val);
- void (*icr_write)(u32 val, u32 dest);
- u32 (*id)(void);
- };
- static void outb(unsigned char data, unsigned short port)
- {
- asm volatile ("out %0, %1" : : "a"(data), "d"(port));
- }
- void eoi(void)
- {
- apic_write(APIC_EOI, 0);
- }
- static u32 xapic_read(unsigned reg)
- {
- return *(volatile u32 *)(g_apic + reg);
- }
- static void xapic_write(unsigned reg, u32 val)
- {
- *(volatile u32 *)(g_apic + reg) = val;
- }
- static void xapic_icr_write(u32 val, u32 dest)
- {
- while (xapic_read(APIC_ICR) & APIC_ICR_BUSY)
- ;
- xapic_write(APIC_ICR2, dest << 24);
- xapic_write(APIC_ICR, val);
- }
- static uint32_t xapic_id(void)
- {
- return xapic_read(APIC_ID) >> 24;
- }
- static const struct apic_ops xapic_ops = {
- .reg_read = xapic_read,
- .reg_write = xapic_write,
- .icr_write = xapic_icr_write,
- .id = xapic_id,
- };
- static const struct apic_ops *apic_ops = &xapic_ops;
- static u32 x2apic_read(unsigned reg)
- {
- unsigned a, d;
- asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16));
- return a | (u64)d << 32;
- }
- static void x2apic_write(unsigned reg, u32 val)
- {
- asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16));
- }
- static void x2apic_icr_write(u32 val, u32 dest)
- {
- asm volatile ("wrmsr" : : "a"(val), "d"(dest),
- "c"(APIC_BASE_MSR + APIC_ICR/16));
- }
- static uint32_t x2apic_id(void)
- {
- return x2apic_read(APIC_ID);
- }
- static const struct apic_ops x2apic_ops = {
- .reg_read = x2apic_read,
- .reg_write = x2apic_write,
- .icr_write = x2apic_icr_write,
- .id = x2apic_id,
- };
- u32 apic_read(unsigned reg)
- {
- return apic_ops->reg_read(reg);
- }
- void apic_write(unsigned reg, u32 val)
- {
- apic_ops->reg_write(reg, val);
- }
- bool apic_read_bit(unsigned reg, int n)
- {
- reg += (n >> 5) << 4;
- n &= 31;
- return (apic_read(reg) & (1 << n)) != 0;
- }
- void apic_icr_write(u32 val, u32 dest)
- {
- apic_ops->icr_write(val, dest);
- }
- uint32_t apic_id(void)
- {
- return apic_ops->id();
- }
- uint8_t apic_get_tpr(void)
- {
- unsigned long tpr;
- #ifdef __x86_64__
- asm volatile ("mov %%cr8, %0" : "=r"(tpr));
- #else
- tpr = apic_read(APIC_TASKPRI) >> 4;
- #endif
- return tpr;
- }
- void apic_set_tpr(uint8_t tpr)
- {
- #ifdef __x86_64__
- asm volatile ("mov %0, %%cr8" : : "r"((unsigned long) tpr));
- #else
- apic_write(APIC_TASKPRI, tpr << 4);
- #endif
- }
- int enable_x2apic(void)
- {
- unsigned a, b, c, d;
- asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1));
- if (c & (1 << 21)) {
- asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_IA32_APICBASE));
- a |= 1 << 10;
- asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_IA32_APICBASE));
- apic_ops = &x2apic_ops;
- return 1;
- } else {
- return 0;
- }
- }
- void reset_apic(void)
- {
- u64 disabled = rdmsr(MSR_IA32_APICBASE) & ~(APIC_EN | APIC_EXTD);
- wrmsr(MSR_IA32_APICBASE, disabled);
- apic_ops = &xapic_ops;
- wrmsr(MSR_IA32_APICBASE, disabled | APIC_EN);
- }
- u32 ioapic_read_reg(unsigned reg)
- {
- *(volatile u32 *)g_ioapic = reg;
- return *(volatile u32 *)(g_ioapic + 0x10);
- }
- void ioapic_write_reg(unsigned reg, u32 value)
- {
- *(volatile u32 *)g_ioapic = reg;
- *(volatile u32 *)(g_ioapic + 0x10) = value;
- }
- void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e)
- {
- ioapic_write_reg(0x10 + line * 2 + 0, ((u32 *)&e)[0]);
- ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]);
- }
- ioapic_redir_entry_t ioapic_read_redir(unsigned line)
- {
- ioapic_redir_entry_t e;
- ((u32 *)&e)[0] = ioapic_read_reg(0x10 + line * 2 + 0);
- ((u32 *)&e)[1] = ioapic_read_reg(0x10 + line * 2 + 1);
- return e;
- }
- void set_mask(unsigned line, int mask)
- {
- ioapic_redir_entry_t e = ioapic_read_redir(line);
- e.mask = mask;
- ioapic_write_redir(line, e);
- }
- void enable_apic(void)
- {
- printf("enabling apic\n");
- xapic_write(0xf0, 0x1ff); /* spurious vector register */
- }
- void mask_pic_interrupts(void)
- {
- outb(0xff, 0x21);
- outb(0xff, 0xa1);
- }
|