17d36db35SAvi Kivity #include "libcflat.h" 27d36db35SAvi Kivity #include "apic.h" 3b5aa0cebSJan Kiszka #include "msr.h" 47d36db35SAvi Kivity 57d36db35SAvi Kivity static void *g_apic = (void *)0xfee00000; 67d36db35SAvi Kivity static void *g_ioapic = (void *)0xfec00000; 77d36db35SAvi Kivity 87d36db35SAvi Kivity struct apic_ops { 97d36db35SAvi Kivity u32 (*reg_read)(unsigned reg); 107d36db35SAvi Kivity void (*reg_write)(unsigned reg, u32 val); 117d36db35SAvi Kivity void (*icr_write)(u32 val, u32 dest); 127d36db35SAvi Kivity u32 (*id)(void); 137d36db35SAvi Kivity }; 147d36db35SAvi Kivity 157d36db35SAvi Kivity static void outb(unsigned char data, unsigned short port) 167d36db35SAvi Kivity { 177d36db35SAvi Kivity asm volatile ("out %0, %1" : : "a"(data), "d"(port)); 187d36db35SAvi Kivity } 197d36db35SAvi Kivity 20*0f187a08SSteve Rutherford void eoi(void) 21*0f187a08SSteve Rutherford { 22*0f187a08SSteve Rutherford apic_write(APIC_EOI, 0); 23*0f187a08SSteve Rutherford } 24*0f187a08SSteve Rutherford 257d36db35SAvi Kivity static u32 xapic_read(unsigned reg) 267d36db35SAvi Kivity { 277d36db35SAvi Kivity return *(volatile u32 *)(g_apic + reg); 287d36db35SAvi Kivity } 297d36db35SAvi Kivity 307d36db35SAvi Kivity static void xapic_write(unsigned reg, u32 val) 317d36db35SAvi Kivity { 327d36db35SAvi Kivity *(volatile u32 *)(g_apic + reg) = val; 337d36db35SAvi Kivity } 347d36db35SAvi Kivity 357d36db35SAvi Kivity static void xapic_icr_write(u32 val, u32 dest) 367d36db35SAvi Kivity { 377d36db35SAvi Kivity while (xapic_read(APIC_ICR) & APIC_ICR_BUSY) 387d36db35SAvi Kivity ; 397d36db35SAvi Kivity xapic_write(APIC_ICR2, dest << 24); 407d36db35SAvi Kivity xapic_write(APIC_ICR, val); 417d36db35SAvi Kivity } 427d36db35SAvi Kivity 437d36db35SAvi Kivity static uint32_t xapic_id(void) 447d36db35SAvi Kivity { 457d36db35SAvi Kivity return xapic_read(APIC_ID) >> 24; 467d36db35SAvi Kivity } 477d36db35SAvi Kivity 487d36db35SAvi Kivity static const struct apic_ops xapic_ops = { 497d36db35SAvi Kivity .reg_read = xapic_read, 507d36db35SAvi Kivity .reg_write = xapic_write, 517d36db35SAvi Kivity .icr_write = xapic_icr_write, 527d36db35SAvi Kivity .id = xapic_id, 537d36db35SAvi Kivity }; 547d36db35SAvi Kivity 557d36db35SAvi Kivity static const struct apic_ops *apic_ops = &xapic_ops; 567d36db35SAvi Kivity 577d36db35SAvi Kivity static u32 x2apic_read(unsigned reg) 587d36db35SAvi Kivity { 597d36db35SAvi Kivity unsigned a, d; 607d36db35SAvi Kivity 617d36db35SAvi Kivity asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16)); 627d36db35SAvi Kivity return a | (u64)d << 32; 637d36db35SAvi Kivity } 647d36db35SAvi Kivity 657d36db35SAvi Kivity static void x2apic_write(unsigned reg, u32 val) 667d36db35SAvi Kivity { 677d36db35SAvi Kivity asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16)); 687d36db35SAvi Kivity } 697d36db35SAvi Kivity 707d36db35SAvi Kivity static void x2apic_icr_write(u32 val, u32 dest) 717d36db35SAvi Kivity { 727d36db35SAvi Kivity asm volatile ("wrmsr" : : "a"(val), "d"(dest), 737d36db35SAvi Kivity "c"(APIC_BASE_MSR + APIC_ICR/16)); 747d36db35SAvi Kivity } 757d36db35SAvi Kivity 767d36db35SAvi Kivity static uint32_t x2apic_id(void) 777d36db35SAvi Kivity { 78a0837ab6SRadim Krčmář return x2apic_read(APIC_ID); 797d36db35SAvi Kivity } 807d36db35SAvi Kivity 817d36db35SAvi Kivity static const struct apic_ops x2apic_ops = { 827d36db35SAvi Kivity .reg_read = x2apic_read, 837d36db35SAvi Kivity .reg_write = x2apic_write, 847d36db35SAvi Kivity .icr_write = x2apic_icr_write, 857d36db35SAvi Kivity .id = x2apic_id, 867d36db35SAvi Kivity }; 877d36db35SAvi Kivity 887d36db35SAvi Kivity u32 apic_read(unsigned reg) 897d36db35SAvi Kivity { 907d36db35SAvi Kivity return apic_ops->reg_read(reg); 917d36db35SAvi Kivity } 927d36db35SAvi Kivity 937d36db35SAvi Kivity void apic_write(unsigned reg, u32 val) 947d36db35SAvi Kivity { 957d36db35SAvi Kivity apic_ops->reg_write(reg, val); 967d36db35SAvi Kivity } 977d36db35SAvi Kivity 987d36db35SAvi Kivity void apic_icr_write(u32 val, u32 dest) 997d36db35SAvi Kivity { 1007d36db35SAvi Kivity apic_ops->icr_write(val, dest); 1017d36db35SAvi Kivity } 1027d36db35SAvi Kivity 1037d36db35SAvi Kivity uint32_t apic_id(void) 1047d36db35SAvi Kivity { 1057d36db35SAvi Kivity return apic_ops->id(); 1067d36db35SAvi Kivity } 1077d36db35SAvi Kivity 1087d36db35SAvi Kivity int enable_x2apic(void) 1097d36db35SAvi Kivity { 1107d36db35SAvi Kivity unsigned a, b, c, d; 1117d36db35SAvi Kivity 1127d36db35SAvi Kivity asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); 1137d36db35SAvi Kivity 1147d36db35SAvi Kivity if (c & (1 << 21)) { 115b5aa0cebSJan Kiszka asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_IA32_APICBASE)); 1167d36db35SAvi Kivity a |= 1 << 10; 117b5aa0cebSJan Kiszka asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_IA32_APICBASE)); 1187d36db35SAvi Kivity apic_ops = &x2apic_ops; 1197d36db35SAvi Kivity return 1; 1207d36db35SAvi Kivity } else { 1217d36db35SAvi Kivity return 0; 1227d36db35SAvi Kivity } 1237d36db35SAvi Kivity } 1247d36db35SAvi Kivity 125*0f187a08SSteve Rutherford u32 ioapic_read_reg(unsigned reg) 126*0f187a08SSteve Rutherford { 127*0f187a08SSteve Rutherford *(volatile u32 *)g_ioapic = reg; 128*0f187a08SSteve Rutherford return *(volatile u32 *)(g_ioapic + 0x10); 129*0f187a08SSteve Rutherford } 130*0f187a08SSteve Rutherford 1317d36db35SAvi Kivity void ioapic_write_reg(unsigned reg, u32 value) 1327d36db35SAvi Kivity { 1337d36db35SAvi Kivity *(volatile u32 *)g_ioapic = reg; 1347d36db35SAvi Kivity *(volatile u32 *)(g_ioapic + 0x10) = value; 1357d36db35SAvi Kivity } 1367d36db35SAvi Kivity 1377d36db35SAvi Kivity void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e) 1387d36db35SAvi Kivity { 1397d36db35SAvi Kivity ioapic_write_reg(0x10 + line * 2 + 0, ((u32 *)&e)[0]); 1407d36db35SAvi Kivity ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]); 1417d36db35SAvi Kivity } 1427d36db35SAvi Kivity 143*0f187a08SSteve Rutherford ioapic_redir_entry_t ioapic_read_redir(unsigned line) 144*0f187a08SSteve Rutherford { 145*0f187a08SSteve Rutherford ioapic_redir_entry_t e; 146*0f187a08SSteve Rutherford 147*0f187a08SSteve Rutherford ((u32 *)&e)[0] = ioapic_read_reg(0x10 + line * 2 + 0); 148*0f187a08SSteve Rutherford ((u32 *)&e)[1] = ioapic_read_reg(0x10 + line * 2 + 1); 149*0f187a08SSteve Rutherford return e; 150*0f187a08SSteve Rutherford 151*0f187a08SSteve Rutherford } 152*0f187a08SSteve Rutherford 153*0f187a08SSteve Rutherford void set_mask(unsigned line, int mask) 154*0f187a08SSteve Rutherford { 155*0f187a08SSteve Rutherford ioapic_redir_entry_t e = ioapic_read_redir(line); 156*0f187a08SSteve Rutherford 157*0f187a08SSteve Rutherford e.mask = mask; 158*0f187a08SSteve Rutherford ioapic_write_redir(line, e); 159*0f187a08SSteve Rutherford } 160*0f187a08SSteve Rutherford 1617d36db35SAvi Kivity void enable_apic(void) 1627d36db35SAvi Kivity { 1637d36db35SAvi Kivity printf("enabling apic\n"); 1647d36db35SAvi Kivity xapic_write(0xf0, 0x1ff); /* spurious vector register */ 1657d36db35SAvi Kivity } 1667d36db35SAvi Kivity 1677d36db35SAvi Kivity void mask_pic_interrupts(void) 1687d36db35SAvi Kivity { 1697d36db35SAvi Kivity outb(0xff, 0x21); 1707d36db35SAvi Kivity outb(0xff, 0xa1); 1717d36db35SAvi Kivity } 172