xref: /kvm-unit-tests/lib/x86/apic.c (revision b5aa0ceb7fc7a976e99fdf9a8ceeb82179549811)
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