1 /*
2 * (C) 2011 Andre Nogueira
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * APIC register dumping.
7 * TODO : decode the registers too.
8 */
9
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <apic.h>
13 #include <fcntl.h>
14 #include <sys/mman.h>
15 #include <x86info.h>
16
17 static int fd;
18
apic_msr_value(int cpu,int msr,unsigned long long * val)19 static int apic_msr_value(int cpu, int msr, unsigned long long *val)
20 {
21 if (read_msr(cpu, msr, val) == 1)
22 return 1;
23 else
24 return 0;
25 }
26
dump_apic_base_msr(int cpu,int msr)27 static void dump_apic_base_msr(int cpu, int msr)
28 {
29 unsigned long long val;
30 int ret;
31
32 ret = apic_msr_value(cpu, msr, &val);
33 if (ret)
34 printf("0x%016llx\n", val);
35 }
36
apic_is_enable(int cpu,int msr)37 static int apic_is_enable(int cpu, int msr)
38 {
39 unsigned long long val;
40 int ret;
41
42 ret = apic_msr_value(cpu, msr, &val);
43 if (ret)
44 ret = ((int)(val >> 11) & 0x1);
45
46 return ret;
47 }
48
apic_physical_address(int cpu,int msr)49 static unsigned int apic_physical_address(int cpu, int msr)
50 {
51 unsigned long long val;
52 unsigned int apic_phys_addr;
53 int ret;
54
55 apic_phys_addr = 0;
56
57 ret = apic_msr_value(cpu, msr, &val);
58 if (ret)
59 apic_phys_addr = ((val >> 12) << 12);
60
61 return apic_phys_addr;
62 }
63
mapping_apic_registers(unsigned long addr)64 static unsigned int * mapping_apic_registers(unsigned long addr)
65 {
66 unsigned long offset;
67 void *mapped;
68
69 if ((fd = open("/dev/mem", O_RDONLY)) == -1)
70 return NULL;
71
72 offset = PAGE_OFFSET(addr);
73
74 mapped = mmap(NULL, (APIC_REGISTER_SPACE + offset), PROT_READ, MAP_SHARED, fd, (unsigned long) addr - offset);
75 if (mapped != MAP_FAILED)
76 return (unsigned int *) (mapped + offset);
77 else
78 return NULL;
79 }
80
unmapping_apic_registers(void * mapped,unsigned int size)81 static void unmapping_apic_registers(void *mapped, unsigned int size)
82 {
83 if (munmap(mapped, size) == -1)
84 return;
85 if (close(fd) == -1)
86 return;
87 }
88
89
dump_apic(unsigned int * apic_reg_buffer,unsigned int offset)90 static void dump_apic(unsigned int *apic_reg_buffer, unsigned int offset)
91 {
92 printf("0x%08x\n", apic_reg_buffer[ (offset * APIC_REGISTER_ALIGNED_SIZE) ]);
93 }
94
95
dump_apics(struct cpudata * cpu)96 void dump_apics(struct cpudata *cpu)
97 {
98 unsigned int *apic_reg_buffer;
99 unsigned int phys_addr;
100 int i;
101
102 /**
103 * Verify if apic feature is supported
104 **/
105 if (!(cpu->flags_edx & (X86_FEATURE_APIC)))
106 return;
107
108 /**
109 * Verify if apic is enable
110 **/
111 if (!(apic_is_enable(cpu->number, IA32_APIC_BASE_MSR)))
112 return;
113
114 phys_addr = apic_physical_address(cpu->number, IA32_APIC_BASE_MSR);
115
116 /**
117 * Mapping the apic registers
118 **/
119 apic_reg_buffer = mapping_apic_registers(phys_addr);
120 if (apic_reg_buffer == NULL)
121 return;
122
123 printf("APIC registers:\n");
124
125 printf("APIC MSR Base(0x%02x): : ", IA32_APIC_BASE_MSR);
126 dump_apic_base_msr(cpu->number, IA32_APIC_BASE_MSR);
127
128 printf("APIC Local ID : ");
129 dump_apic(apic_reg_buffer, APIC_ID);
130 printf("APIC Local Version : ");
131 dump_apic(apic_reg_buffer, APIC_VER);
132 printf("APIC Task Priority : ");
133 dump_apic(apic_reg_buffer, APIC_TPR);
134 printf("APIC Arbitration Priority : ");
135 dump_apic(apic_reg_buffer, APIC_APR);
136 printf("APIC Processor Priority : ");
137 dump_apic(apic_reg_buffer, APIC_PPR);
138 printf("APIC EOI : ");
139 dump_apic(apic_reg_buffer, APIC_EOI);
140 printf("APIC Remote Read : ");
141 dump_apic(apic_reg_buffer, APIC_RRD);
142 printf("APIC Logical Destination : ");
143 dump_apic(apic_reg_buffer, APIC_LDR);
144 printf("APIC Destination Format : ");
145 dump_apic(apic_reg_buffer, APIC_DFR);
146 printf("APIC Spurious Interrupt Vector : ");
147 dump_apic(apic_reg_buffer, APIC_SIVR);
148
149 for (i = 0 ; i < 8 ; i++) {
150 printf("APIC In-Service (ISR%d) : ", i);
151 dump_apic(apic_reg_buffer, APIC_ISR+i);
152 }
153
154 for (i = 0 ; i < 8 ; i++) {
155 printf("APIC Trigger Mode (TMR%d) : ", i);
156 dump_apic(apic_reg_buffer, APIC_TMR+i);
157 }
158
159 for (i = 0 ; i < 8 ; i++) {
160 printf("APIC Interrupt Request (IRR0%d) : ", i);
161 dump_apic(apic_reg_buffer, APIC_IRR+i);
162 }
163
164 printf("APIC Error Status : ");
165 dump_apic(apic_reg_buffer, APIC_ESR);
166 printf("APIC LVT CMCI : ");
167 dump_apic(apic_reg_buffer, APIC_LVT);
168 printf("APIC Interrupt Command (ICR0) : ");
169 dump_apic(apic_reg_buffer, APIC_ICR0);
170 printf("APIC Interrupt Command (ICR1) : ");
171 dump_apic(apic_reg_buffer, APIC_ICR1);
172 printf("APIC LVT Timer : ");
173 dump_apic(apic_reg_buffer, APIC_LVTT);
174 printf("APIC Thermal Sensor : ");
175 dump_apic(apic_reg_buffer, APIC_LVTTS);
176 printf("APIC LVT Performance Monitoring Counters: ");
177 dump_apic(apic_reg_buffer, APIC_LVTPC);
178 printf("APIC LVT LINT0 : ");
179 dump_apic(apic_reg_buffer, APIC_LVT0);
180 printf("APIC LVT LINT1 : ");
181 dump_apic(apic_reg_buffer, APIC_LVT1);
182 printf("APIC LVT Error : ");
183 dump_apic(apic_reg_buffer, APIC_LVTER);
184 printf("APIC Initial Count (for Timer) : ");
185 dump_apic(apic_reg_buffer, APIC_TICR);
186 printf("APIC Current Count (for Timer) : ");
187 dump_apic(apic_reg_buffer, APIC_TCCR);
188 printf("APIC Divide Configuration (for Timer) : ");
189 dump_apic(apic_reg_buffer, APIC_TDCR);
190
191 unmapping_apic_registers(apic_reg_buffer, APIC_REGISTER_SPACE);
192
193 printf("\n");
194 }
195