17d36db35SAvi Kivity #include "libcflat.h" 27d36db35SAvi Kivity #include "apic.h" 3*b5aa0cebSJan 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 207d36db35SAvi Kivity static u32 xapic_read(unsigned reg) 217d36db35SAvi Kivity { 227d36db35SAvi Kivity return *(volatile u32 *)(g_apic + reg); 237d36db35SAvi Kivity } 247d36db35SAvi Kivity 257d36db35SAvi Kivity static void xapic_write(unsigned reg, u32 val) 267d36db35SAvi Kivity { 277d36db35SAvi Kivity *(volatile u32 *)(g_apic + reg) = val; 287d36db35SAvi Kivity } 297d36db35SAvi Kivity 307d36db35SAvi Kivity static void xapic_icr_write(u32 val, u32 dest) 317d36db35SAvi Kivity { 327d36db35SAvi Kivity while (xapic_read(APIC_ICR) & APIC_ICR_BUSY) 337d36db35SAvi Kivity ; 347d36db35SAvi Kivity xapic_write(APIC_ICR2, dest << 24); 357d36db35SAvi Kivity xapic_write(APIC_ICR, val); 367d36db35SAvi Kivity } 377d36db35SAvi Kivity 387d36db35SAvi Kivity static uint32_t xapic_id(void) 397d36db35SAvi Kivity { 407d36db35SAvi Kivity return xapic_read(APIC_ID) >> 24; 417d36db35SAvi Kivity } 427d36db35SAvi Kivity 437d36db35SAvi Kivity static const struct apic_ops xapic_ops = { 447d36db35SAvi Kivity .reg_read = xapic_read, 457d36db35SAvi Kivity .reg_write = xapic_write, 467d36db35SAvi Kivity .icr_write = xapic_icr_write, 477d36db35SAvi Kivity .id = xapic_id, 487d36db35SAvi Kivity }; 497d36db35SAvi Kivity 507d36db35SAvi Kivity static const struct apic_ops *apic_ops = &xapic_ops; 517d36db35SAvi Kivity 527d36db35SAvi Kivity static u32 x2apic_read(unsigned reg) 537d36db35SAvi Kivity { 547d36db35SAvi Kivity unsigned a, d; 557d36db35SAvi Kivity 567d36db35SAvi Kivity asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16)); 577d36db35SAvi Kivity return a | (u64)d << 32; 587d36db35SAvi Kivity } 597d36db35SAvi Kivity 607d36db35SAvi Kivity static void x2apic_write(unsigned reg, u32 val) 617d36db35SAvi Kivity { 627d36db35SAvi Kivity asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16)); 637d36db35SAvi Kivity } 647d36db35SAvi Kivity 657d36db35SAvi Kivity static void x2apic_icr_write(u32 val, u32 dest) 667d36db35SAvi Kivity { 677d36db35SAvi Kivity asm volatile ("wrmsr" : : "a"(val), "d"(dest), 687d36db35SAvi Kivity "c"(APIC_BASE_MSR + APIC_ICR/16)); 697d36db35SAvi Kivity } 707d36db35SAvi Kivity 717d36db35SAvi Kivity static uint32_t x2apic_id(void) 727d36db35SAvi Kivity { 737d36db35SAvi Kivity return xapic_read(APIC_ID); 747d36db35SAvi Kivity } 757d36db35SAvi Kivity 767d36db35SAvi Kivity static const struct apic_ops x2apic_ops = { 777d36db35SAvi Kivity .reg_read = x2apic_read, 787d36db35SAvi Kivity .reg_write = x2apic_write, 797d36db35SAvi Kivity .icr_write = x2apic_icr_write, 807d36db35SAvi Kivity .id = x2apic_id, 817d36db35SAvi Kivity }; 827d36db35SAvi Kivity 837d36db35SAvi Kivity u32 apic_read(unsigned reg) 847d36db35SAvi Kivity { 857d36db35SAvi Kivity return apic_ops->reg_read(reg); 867d36db35SAvi Kivity } 877d36db35SAvi Kivity 887d36db35SAvi Kivity void apic_write(unsigned reg, u32 val) 897d36db35SAvi Kivity { 907d36db35SAvi Kivity apic_ops->reg_write(reg, val); 917d36db35SAvi Kivity } 927d36db35SAvi Kivity 937d36db35SAvi Kivity void apic_icr_write(u32 val, u32 dest) 947d36db35SAvi Kivity { 957d36db35SAvi Kivity apic_ops->icr_write(val, dest); 967d36db35SAvi Kivity } 977d36db35SAvi Kivity 987d36db35SAvi Kivity uint32_t apic_id(void) 997d36db35SAvi Kivity { 1007d36db35SAvi Kivity return apic_ops->id(); 1017d36db35SAvi Kivity } 1027d36db35SAvi Kivity 1037d36db35SAvi Kivity int enable_x2apic(void) 1047d36db35SAvi Kivity { 1057d36db35SAvi Kivity unsigned a, b, c, d; 1067d36db35SAvi Kivity 1077d36db35SAvi Kivity asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); 1087d36db35SAvi Kivity 1097d36db35SAvi Kivity if (c & (1 << 21)) { 110*b5aa0cebSJan Kiszka asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_IA32_APICBASE)); 1117d36db35SAvi Kivity a |= 1 << 10; 112*b5aa0cebSJan Kiszka asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_IA32_APICBASE)); 1137d36db35SAvi Kivity apic_ops = &x2apic_ops; 1147d36db35SAvi Kivity return 1; 1157d36db35SAvi Kivity } else { 1167d36db35SAvi Kivity return 0; 1177d36db35SAvi Kivity } 1187d36db35SAvi Kivity } 1197d36db35SAvi Kivity 1207d36db35SAvi Kivity void ioapic_write_reg(unsigned reg, u32 value) 1217d36db35SAvi Kivity { 1227d36db35SAvi Kivity *(volatile u32 *)g_ioapic = reg; 1237d36db35SAvi Kivity *(volatile u32 *)(g_ioapic + 0x10) = value; 1247d36db35SAvi Kivity } 1257d36db35SAvi Kivity 1267d36db35SAvi Kivity void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e) 1277d36db35SAvi Kivity { 1287d36db35SAvi Kivity ioapic_write_reg(0x10 + line * 2 + 0, ((u32 *)&e)[0]); 1297d36db35SAvi Kivity ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]); 1307d36db35SAvi Kivity } 1317d36db35SAvi Kivity 1327d36db35SAvi Kivity void enable_apic(void) 1337d36db35SAvi Kivity { 1347d36db35SAvi Kivity printf("enabling apic\n"); 1357d36db35SAvi Kivity xapic_write(0xf0, 0x1ff); /* spurious vector register */ 1367d36db35SAvi Kivity } 1377d36db35SAvi Kivity 1387d36db35SAvi Kivity void mask_pic_interrupts(void) 1397d36db35SAvi Kivity { 1407d36db35SAvi Kivity outb(0xff, 0x21); 1417d36db35SAvi Kivity outb(0xff, 0xa1); 1427d36db35SAvi Kivity } 143