/* * (C) 2011 Andre Nogueira * * Licensed under the terms of the GNU GPL License version 2. * * APIC register dumping. * TODO : decode the registers too. */ #include #include "apic.h" #include "x86info.h" static int fd; static int apic_msr_value(int cpu, int msr, unsigned long long *val) { if (read_msr(cpu, msr, val) == 1) return 1; else return 0; } static void dump_apic_base_msr(int cpu, int msr) { unsigned long long val; int ret; ret = apic_msr_value(cpu, msr, &val); if (ret) printf("0x%016llx\n", val); } static int apic_is_enable(int cpu, int msr) { unsigned long long val; int ret; ret = apic_msr_value(cpu, msr, &val); if (ret) ret = ((int)(val >> 11) & 0x1); return ret; } static unsigned int apic_physical_address(int cpu, int msr) { unsigned long long val; unsigned int apic_phys_addr; int ret; apic_phys_addr = 0; ret = apic_msr_value(cpu, msr, &val); if (ret) apic_phys_addr = ((val >> 12) << 12); return apic_phys_addr; } static unsigned int * mapping_apic_registers(unsigned long addr) { unsigned long offset; void *mapped; if ((fd = open("/dev/mem", O_RDONLY)) == -1) return NULL; offset = PAGE_OFFSET(addr); mapped = mmap(NULL, (APIC_REGISTER_SPACE + offset), PROT_READ, MAP_PRIVATE, fd, (unsigned long) addr - offset); if (mapped != MAP_FAILED) return (unsigned int *) (mapped + offset); else return NULL; } static void unmapping_apic_registers(void *mapped, unsigned int size) { if (munmap(mapped, size) == -1) return; if (close(fd) == -1) return; } static void dump_apic(unsigned int *apic_reg_buffer, unsigned int offset) { printf("0x%08x\n", apic_reg_buffer[ (offset * APIC_REGISTER_ALIGNED_SIZE) ]); } void dump_apics(struct cpudata *cpu) { unsigned int *apic_reg_buffer; unsigned int phys_addr; int i; /** * Verify if apic feature is supported **/ if (!(cpu->flags_edx & (X86_FEATURE_APIC))) return; /** * Verify if apic is enable **/ if (!(apic_is_enable(cpu->number, IA32_APIC_BASE_MSR))) return; phys_addr = apic_physical_address(cpu->number, IA32_APIC_BASE_MSR); /** * Mapping the apic registers **/ apic_reg_buffer = mapping_apic_registers(phys_addr); if (apic_reg_buffer == NULL) return; printf("APIC registers:\n"); printf("APIC MSR Base(0x%02x): : ", IA32_APIC_BASE_MSR); dump_apic_base_msr(cpu->number, IA32_APIC_BASE_MSR); printf("APIC Local ID : "); dump_apic(apic_reg_buffer, APIC_ID); printf("APIC Local Version : "); dump_apic(apic_reg_buffer, APIC_VER); printf("APIC Task Priority : "); dump_apic(apic_reg_buffer, APIC_TPR); printf("APIC Arbitration Priority : "); dump_apic(apic_reg_buffer, APIC_APR); printf("APIC Processor Priority : "); dump_apic(apic_reg_buffer, APIC_PPR); printf("APIC EOI : "); dump_apic(apic_reg_buffer, APIC_EOI); printf("APIC Remote Read : "); dump_apic(apic_reg_buffer, APIC_RRD); printf("APIC Logical Destination : "); dump_apic(apic_reg_buffer, APIC_LDR); printf("APIC Destination Format : "); dump_apic(apic_reg_buffer, APIC_DFR); printf("APIC Spurious Interrupt Vector : "); dump_apic(apic_reg_buffer, APIC_SIVR); for (i = 0 ; i < 8 ; i++) { printf("APIC In-Service (ISR%d) : ", i); dump_apic(apic_reg_buffer, APIC_ISR+i); } for (i = 0 ; i < 8 ; i++) { printf("APIC Trigger Mode (TMR%d) : ", i); dump_apic(apic_reg_buffer, APIC_TMR+i); } for (i = 0 ; i < 8 ; i++) { printf("APIC Interrupt Request (IRR0%d) : ", i); dump_apic(apic_reg_buffer, APIC_IRR+i); } printf("APIC Error Status : "); dump_apic(apic_reg_buffer, APIC_ESR); printf("APIC LVT CMCI : "); dump_apic(apic_reg_buffer, APIC_LVT); printf("APIC Interrupt Command (ICR0) : "); dump_apic(apic_reg_buffer, APIC_ICR0); printf("APIC Interrupt Command (ICR1) : "); dump_apic(apic_reg_buffer, APIC_ICR1); printf("APIC LVT Timer : "); dump_apic(apic_reg_buffer, APIC_LVTT); printf("APIC Thermal Sensor : "); dump_apic(apic_reg_buffer, APIC_LVTTS); printf("APIC LVT Performance Monitoring Counters: "); dump_apic(apic_reg_buffer, APIC_LVTPC); printf("APIC LVT LINT0 : "); dump_apic(apic_reg_buffer, APIC_LVT0); printf("APIC LVT LINT1 : "); dump_apic(apic_reg_buffer, APIC_LVT1); printf("APIC LVT Error : "); dump_apic(apic_reg_buffer, APIC_LVTER); printf("APIC Initial Count (for Timer) : "); dump_apic(apic_reg_buffer, APIC_TICR); printf("APIC Current Count (for Timer) : "); dump_apic(apic_reg_buffer, APIC_TCCR); printf("APIC Divide Configuration (for Timer) : "); dump_apic(apic_reg_buffer, APIC_TDCR); unmapping_apic_registers(apic_reg_buffer, APIC_REGISTER_SPACE); printf("\n"); }