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