1*7d36db35SAvi Kivity #include "libcflat.h" 2*7d36db35SAvi Kivity #include "apic.h" 3*7d36db35SAvi Kivity 4*7d36db35SAvi Kivity static void *g_apic = (void *)0xfee00000; 5*7d36db35SAvi Kivity static void *g_ioapic = (void *)0xfec00000; 6*7d36db35SAvi Kivity 7*7d36db35SAvi Kivity struct apic_ops { 8*7d36db35SAvi Kivity u32 (*reg_read)(unsigned reg); 9*7d36db35SAvi Kivity void (*reg_write)(unsigned reg, u32 val); 10*7d36db35SAvi Kivity void (*icr_write)(u32 val, u32 dest); 11*7d36db35SAvi Kivity u32 (*id)(void); 12*7d36db35SAvi Kivity }; 13*7d36db35SAvi Kivity 14*7d36db35SAvi Kivity static void outb(unsigned char data, unsigned short port) 15*7d36db35SAvi Kivity { 16*7d36db35SAvi Kivity asm volatile ("out %0, %1" : : "a"(data), "d"(port)); 17*7d36db35SAvi Kivity } 18*7d36db35SAvi Kivity 19*7d36db35SAvi Kivity static u32 xapic_read(unsigned reg) 20*7d36db35SAvi Kivity { 21*7d36db35SAvi Kivity return *(volatile u32 *)(g_apic + reg); 22*7d36db35SAvi Kivity } 23*7d36db35SAvi Kivity 24*7d36db35SAvi Kivity static void xapic_write(unsigned reg, u32 val) 25*7d36db35SAvi Kivity { 26*7d36db35SAvi Kivity *(volatile u32 *)(g_apic + reg) = val; 27*7d36db35SAvi Kivity } 28*7d36db35SAvi Kivity 29*7d36db35SAvi Kivity static void xapic_icr_write(u32 val, u32 dest) 30*7d36db35SAvi Kivity { 31*7d36db35SAvi Kivity while (xapic_read(APIC_ICR) & APIC_ICR_BUSY) 32*7d36db35SAvi Kivity ; 33*7d36db35SAvi Kivity xapic_write(APIC_ICR2, dest << 24); 34*7d36db35SAvi Kivity xapic_write(APIC_ICR, val); 35*7d36db35SAvi Kivity } 36*7d36db35SAvi Kivity 37*7d36db35SAvi Kivity static uint32_t xapic_id(void) 38*7d36db35SAvi Kivity { 39*7d36db35SAvi Kivity return xapic_read(APIC_ID) >> 24; 40*7d36db35SAvi Kivity } 41*7d36db35SAvi Kivity 42*7d36db35SAvi Kivity static const struct apic_ops xapic_ops = { 43*7d36db35SAvi Kivity .reg_read = xapic_read, 44*7d36db35SAvi Kivity .reg_write = xapic_write, 45*7d36db35SAvi Kivity .icr_write = xapic_icr_write, 46*7d36db35SAvi Kivity .id = xapic_id, 47*7d36db35SAvi Kivity }; 48*7d36db35SAvi Kivity 49*7d36db35SAvi Kivity static const struct apic_ops *apic_ops = &xapic_ops; 50*7d36db35SAvi Kivity 51*7d36db35SAvi Kivity static u32 x2apic_read(unsigned reg) 52*7d36db35SAvi Kivity { 53*7d36db35SAvi Kivity unsigned a, d; 54*7d36db35SAvi Kivity 55*7d36db35SAvi Kivity asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16)); 56*7d36db35SAvi Kivity return a | (u64)d << 32; 57*7d36db35SAvi Kivity } 58*7d36db35SAvi Kivity 59*7d36db35SAvi Kivity static void x2apic_write(unsigned reg, u32 val) 60*7d36db35SAvi Kivity { 61*7d36db35SAvi Kivity asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16)); 62*7d36db35SAvi Kivity } 63*7d36db35SAvi Kivity 64*7d36db35SAvi Kivity static void x2apic_icr_write(u32 val, u32 dest) 65*7d36db35SAvi Kivity { 66*7d36db35SAvi Kivity asm volatile ("wrmsr" : : "a"(val), "d"(dest), 67*7d36db35SAvi Kivity "c"(APIC_BASE_MSR + APIC_ICR/16)); 68*7d36db35SAvi Kivity } 69*7d36db35SAvi Kivity 70*7d36db35SAvi Kivity static uint32_t x2apic_id(void) 71*7d36db35SAvi Kivity { 72*7d36db35SAvi Kivity return xapic_read(APIC_ID); 73*7d36db35SAvi Kivity } 74*7d36db35SAvi Kivity 75*7d36db35SAvi Kivity static const struct apic_ops x2apic_ops = { 76*7d36db35SAvi Kivity .reg_read = x2apic_read, 77*7d36db35SAvi Kivity .reg_write = x2apic_write, 78*7d36db35SAvi Kivity .icr_write = x2apic_icr_write, 79*7d36db35SAvi Kivity .id = x2apic_id, 80*7d36db35SAvi Kivity }; 81*7d36db35SAvi Kivity 82*7d36db35SAvi Kivity u32 apic_read(unsigned reg) 83*7d36db35SAvi Kivity { 84*7d36db35SAvi Kivity return apic_ops->reg_read(reg); 85*7d36db35SAvi Kivity } 86*7d36db35SAvi Kivity 87*7d36db35SAvi Kivity void apic_write(unsigned reg, u32 val) 88*7d36db35SAvi Kivity { 89*7d36db35SAvi Kivity apic_ops->reg_write(reg, val); 90*7d36db35SAvi Kivity } 91*7d36db35SAvi Kivity 92*7d36db35SAvi Kivity void apic_icr_write(u32 val, u32 dest) 93*7d36db35SAvi Kivity { 94*7d36db35SAvi Kivity apic_ops->icr_write(val, dest); 95*7d36db35SAvi Kivity } 96*7d36db35SAvi Kivity 97*7d36db35SAvi Kivity uint32_t apic_id(void) 98*7d36db35SAvi Kivity { 99*7d36db35SAvi Kivity return apic_ops->id(); 100*7d36db35SAvi Kivity } 101*7d36db35SAvi Kivity 102*7d36db35SAvi Kivity #define MSR_APIC_BASE 0x0000001b 103*7d36db35SAvi Kivity 104*7d36db35SAvi Kivity int enable_x2apic(void) 105*7d36db35SAvi Kivity { 106*7d36db35SAvi Kivity unsigned a, b, c, d; 107*7d36db35SAvi Kivity 108*7d36db35SAvi Kivity asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); 109*7d36db35SAvi Kivity 110*7d36db35SAvi Kivity if (c & (1 << 21)) { 111*7d36db35SAvi Kivity asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_APIC_BASE)); 112*7d36db35SAvi Kivity a |= 1 << 10; 113*7d36db35SAvi Kivity asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_APIC_BASE)); 114*7d36db35SAvi Kivity apic_ops = &x2apic_ops; 115*7d36db35SAvi Kivity return 1; 116*7d36db35SAvi Kivity } else { 117*7d36db35SAvi Kivity return 0; 118*7d36db35SAvi Kivity } 119*7d36db35SAvi Kivity } 120*7d36db35SAvi Kivity 121*7d36db35SAvi Kivity void ioapic_write_reg(unsigned reg, u32 value) 122*7d36db35SAvi Kivity { 123*7d36db35SAvi Kivity *(volatile u32 *)g_ioapic = reg; 124*7d36db35SAvi Kivity *(volatile u32 *)(g_ioapic + 0x10) = value; 125*7d36db35SAvi Kivity } 126*7d36db35SAvi Kivity 127*7d36db35SAvi Kivity void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e) 128*7d36db35SAvi Kivity { 129*7d36db35SAvi Kivity ioapic_write_reg(0x10 + line * 2 + 0, ((u32 *)&e)[0]); 130*7d36db35SAvi Kivity ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]); 131*7d36db35SAvi Kivity } 132*7d36db35SAvi Kivity 133*7d36db35SAvi Kivity void enable_apic(void) 134*7d36db35SAvi Kivity { 135*7d36db35SAvi Kivity printf("enabling apic\n"); 136*7d36db35SAvi Kivity xapic_write(0xf0, 0x1ff); /* spurious vector register */ 137*7d36db35SAvi Kivity } 138*7d36db35SAvi Kivity 139*7d36db35SAvi Kivity void mask_pic_interrupts(void) 140*7d36db35SAvi Kivity { 141*7d36db35SAvi Kivity outb(0xff, 0x21); 142*7d36db35SAvi Kivity outb(0xff, 0xa1); 143*7d36db35SAvi Kivity } 144