debuggers.hg

view tools/firmware/hvmloader/acpi/mk_dsdt.c @ 20985:54c09c71fe47

Vcpu hotplug: Move ACPI processor from \_PR to \_SB

Move processor from \_PR to \_SB. ACPI processor can be defined
under \_PR or \_SB. However, recently os like linux 2.6.30/32 support
cpu hotplug better for \_SB processor object.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 15 08:13:26 2010 +0000 (2010-02-15)
parents a259e779467c
children 8a8392a84280
line source
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <stdint.h>
4 #include <xen/hvm/hvm_info_table.h>
6 static unsigned int indent_level;
8 static void indent(void)
9 {
10 unsigned int i;
11 for ( i = 0; i < indent_level; i++ )
12 printf(" ");
13 }
15 static void _stmt(const char *name, const char *fmt, ...)
16 {
17 va_list args;
19 indent();
20 printf("%s", name);
22 if ( !fmt )
23 return;
25 printf(" ( ");
26 va_start(args, fmt);
27 vprintf(fmt, args);
28 va_end(args);
29 printf(" )");
30 }
32 #define stmt(n, f, a...) \
33 do { \
34 _stmt(n, f , ## a ); \
35 printf("\n"); \
36 } while (0)
38 #define push_block(n, f, a...) \
39 do { \
40 _stmt(n, f , ## a ); \
41 printf(" {\n"); \
42 indent_level++; \
43 } while (0)
45 static void pop_block(void)
46 {
47 indent_level--;
48 indent();
49 printf("}\n");
50 }
52 static void pci_hotplug_notify(unsigned int slt)
53 {
54 stmt("Notify", "\\_SB.PCI0.S%02X, EVT", slt);
55 }
57 static void decision_tree(
58 unsigned int s, unsigned int e, char *var, void (*leaf)(unsigned int))
59 {
60 if ( s == (e-1) )
61 {
62 (*leaf)(s);
63 return;
64 }
66 push_block("If", "And(%s, 0x%02x)", var, (e-s)/2);
67 decision_tree((s+e)/2, e, var, leaf);
68 pop_block();
69 push_block("Else", NULL);
70 decision_tree(s, (s+e)/2, var, leaf);
71 pop_block();
72 }
74 int main(int argc, char **argv)
75 {
76 unsigned int slot, dev, intx, link, cpu, max_cpus = HVM_MAX_VCPUS;
78 /* Extract optional maximum-cpu specification from invocation name. */
79 sscanf(argv[0], "%*[^0-9]%u", &max_cpus); /* e.g., ./mk_dsdt15 */
81 /**** DSDT DefinitionBlock start ****/
82 /* (we append to existing DSDT definition block) */
83 indent_level++;
85 /**** Processor start ****/
86 push_block("Scope", "\\_SB");
88 /* MADT checksum */
89 stmt("OperationRegion", "MSUM, SystemMemory, \\_SB.MSUA, 1");
90 push_block("Field", "MSUM, ByteAcc, NoLock, Preserve");
91 indent(); printf("MSU, 8\n");
92 pop_block();
94 /* Define processor objects and control methods. */
95 for ( cpu = 0; cpu < max_cpus; cpu++)
96 {
97 push_block("Processor", "PR%02X, %d, 0x0000b010, 0x06", cpu, cpu);
99 stmt("Name", "_HID, \"ACPI0007\"");
101 /* Name this processor's MADT LAPIC descriptor. */
102 stmt("OperationRegion",
103 "MATR, SystemMemory, Add(\\_SB.MAPA, %d), 8", cpu*8);
105 push_block("Field", "MATR, ByteAcc, NoLock, Preserve");
106 indent(); printf("MAT, 64\n");
107 pop_block();
109 push_block("Field", "MATR, ByteAcc, NoLock, Preserve");
110 indent(); printf("Offset(4),\n");
111 indent(); printf("FLG, 1\n");
112 pop_block();
114 push_block("Method", "_MAT, 0");
115 stmt("Return", "ToBuffer(MAT)");
116 pop_block();
118 push_block("Method", "_STA");
119 push_block("If", "FLG");
120 stmt("Return", "0xF");
121 pop_block();
122 push_block("Else", NULL);
123 stmt("Return", "0x0");
124 pop_block();
125 pop_block();
127 push_block("Method", "_EJ0, 1, NotSerialized");
128 stmt("Sleep", "0xC8");
129 pop_block();
131 pop_block();
132 }
134 /* Operation Region 'PRST': bitmask of online CPUs. */
135 stmt("OperationRegion", "PRST, SystemIO, 0xaf00, 32");
136 push_block("Field", "PRST, ByteAcc, NoLock, Preserve");
137 indent(); printf("PRS, %u\n", max_cpus);
138 pop_block();
140 /* Control method 'PRSC': CPU hotplug GPE handler. */
141 push_block("Method", "PRSC, 0");
142 stmt("Store", "PRS, Local0");
143 for ( cpu = 0; cpu < max_cpus; cpu++ )
144 {
145 /* Read a byte at a time from the PRST online-CPU bitmask. */
146 if ( (cpu & 7) == 0 )
147 stmt("Store", "DerefOf(Index(Local0, %u)), Local1", cpu/8);
148 else
149 stmt("ShiftRight", "Local1, 1, Local1");
150 /* Extract current CPU's status: 0=offline; 1=online. */
151 stmt("And", "Local1, 1, Local2");
152 /* Check if status is up-to-date in the relevant MADT LAPIC entry... */
153 push_block("If", "LNotEqual(Local2, \\_SB.PR%02X.FLG)", cpu);
154 /* ...If not, update it and the MADT checksum, and notify OSPM. */
155 stmt("Store", "Local2, \\_SB.PR%02X.FLG", cpu);
156 push_block("If", "LEqual(Local2, 1)");
157 stmt("Notify", "PR%02X, 1", cpu); /* Notify: Device Check */
158 stmt("Subtract", "\\_SB.MSU, 1, \\_SB.MSU"); /* Adjust MADT csum */
159 pop_block();
160 push_block("Else", NULL);
161 stmt("Notify", "PR%02X, 3", cpu); /* Notify: Eject Request */
162 stmt("Add", "\\_SB.MSU, 1, \\_SB.MSU"); /* Adjust MADT csum */
163 pop_block();
164 pop_block();
165 }
166 stmt("Return", "One");
167 pop_block();
169 pop_block();
171 /* Define GPE control method '_L02'. */
172 push_block("Scope", "\\_GPE");
173 push_block("Method", "_L02");
174 stmt("Return", "\\_SB.PRSC()");
175 pop_block();
176 pop_block();
177 /**** Processor end ****/
180 /**** PCI0 start ****/
181 push_block("Scope", "\\_SB.PCI0");
183 /*** PCI-ISA link definitions ***/
184 /* BUFA: List of ISA IRQs available for linking to PCI INTx. */
185 stmt("Name", "BUFA, ResourceTemplate() { "
186 "IRQ(Level, ActiveLow, Shared) { 5, 10, 11 } }");
187 /* BUFB: IRQ descriptor for returning from link-device _CRS methods. */
188 stmt("Name", "BUFB, Buffer() { "
189 "0x23, 0x00, 0x00, 0x18, " /* IRQ descriptor */
190 "0x79, 0 }"); /* End tag, null checksum */
191 stmt("CreateWordField", "BUFB, 0x01, IRQV");
192 /* Create four PCI-ISA link devices: LNKA, LNKB, LNKC, LNKD. */
193 for ( link = 0; link < 4; link++ )
194 {
195 push_block("Device", "LNK%c", 'A'+link);
196 stmt("Name", "_HID, EISAID(\"PNP0C0F\")"); /* PCI interrupt link */
197 stmt("Name", "_UID, %u", link+1);
198 push_block("Method", "_STA, 0");
199 push_block("If", "And(PIR%c, 0x80)", 'A'+link);
200 stmt("Return", "0x09");
201 pop_block();
202 push_block("Else", NULL);
203 stmt("Return", "0x0B");
204 pop_block();
205 pop_block();
206 push_block("Method", "_PRS");
207 stmt("Return", "BUFA");
208 pop_block();
209 push_block("Method", "_DIS");
210 stmt("Or", "PIR%c, 0x80, PIR%c", 'A'+link, 'A'+link);
211 pop_block();
212 push_block("Method", "_CRS");
213 stmt("And", "PIR%c, 0x0f, Local0", 'A'+link);
214 stmt("ShiftLeft", "0x1, Local0, IRQV");
215 stmt("Return", "BUFB");
216 pop_block();
217 push_block("Method", "_SRS, 1");
218 stmt("CreateWordField", "ARG0, 0x01, IRQ1");
219 stmt("FindSetRightBit", "IRQ1, Local0");
220 stmt("Decrement", "Local0");
221 stmt("Store", "Local0, PIR%c", 'A'+link);
222 pop_block();
223 pop_block();
224 }
226 /*** PCI interrupt routing definitions***/
227 /* _PRT: Method to return routing table. */
228 push_block("Method", "_PRT, 0");
229 push_block("If", "PICD");
230 stmt("Return", "PRTA");
231 pop_block();
232 stmt("Return", "PRTP");
233 pop_block();
234 /* PRTP: PIC routing table (via ISA links). */
235 printf("Name(PRTP, Package() {\n");
236 for ( dev = 1; dev < 32; dev++ )
237 for ( intx = 0; intx < 4; intx++ ) /* INTA-D */
238 printf("Package(){0x%04xffff, %u, \\_SB.PCI0.LNK%c, 0},\n",
239 dev, intx, 'A'+((dev+intx)&3));
240 printf("})\n");
241 /* PRTA: APIC routing table (via non-legacy IOAPIC GSIs). */
242 printf("Name(PRTA, Package() {\n");
243 for ( dev = 1; dev < 32; dev++ )
244 for ( intx = 0; intx < 4; intx++ ) /* INTA-D */
245 printf("Package(){0x%04xffff, %u, 0, %u},\n",
246 dev, intx, ((dev*4+dev/8+intx)&31)+16);
247 printf("})\n");
249 /*
250 * Each PCI hotplug slot needs at least two methods to handle
251 * the ACPI event:
252 * _EJ0: eject a device
253 * _STA: return a device's status, e.g. enabled or removed
254 * Other methods are optional:
255 * _PS0/3: put them here for debug purpose
256 *
257 * Eject button would generate a general-purpose event, then the
258 * control method for this event uses Notify() to inform OSPM which
259 * action happened and on which device.
260 *
261 * Pls. refer "6.3 Device Insertion, Removal, and Status Objects"
262 * in ACPI spec 3.0b for details.
263 *
264 * QEMU provides a simple hotplug controller with some I/O to handle
265 * the hotplug action and status, which is beyond the ACPI scope.
266 */
267 for ( slot = 0; slot < 0x100; slot++ )
268 {
269 push_block("Device", "S%02X", slot);
270 /* _ADR == dev:fn (16:16) */
271 stmt("Name", "_ADR, 0x%08x", ((slot & ~7) << 13) | (slot & 7));
272 /* _SUN == dev */
273 stmt("Name", "_SUN, 0x%08x", slot >> 3);
274 push_block("Method", "_PS0, 0");
275 stmt("Store", "0x%02x, \\_GPE.DPT1", slot);
276 stmt("Store", "0x80, \\_GPE.DPT2");
277 pop_block();
278 push_block("Method", "_PS3, 0");
279 stmt("Store", "0x%02x, \\_GPE.DPT1", slot);
280 stmt("Store", "0x83, \\_GPE.DPT2");
281 pop_block();
282 push_block("Method", "_EJ0, 1");
283 stmt("Store", "0x%02x, \\_GPE.DPT1", slot);
284 stmt("Store", "0x88, \\_GPE.DPT2");
285 stmt("Store", "0x%02x, \\_GPE.PH%02X", /* eject */
286 (slot & 1) ? 0x10 : 0x01, slot & ~1);
287 pop_block();
288 push_block("Method", "_STA, 0");
289 stmt("Store", "0x%02x, \\_GPE.DPT1", slot);
290 stmt("Store", "0x89, \\_GPE.DPT2");
291 if ( slot & 1 )
292 stmt("ShiftRight", "0x4, \\_GPE.PH%02X, Local1", slot & ~1);
293 else
294 stmt("And", "\\_GPE.PH%02X, 0x0f, Local1", slot & ~1);
295 stmt("Return", "Local1"); /* IN status as the _STA */
296 pop_block();
297 pop_block();
298 }
300 pop_block();
301 /**** PCI0 end ****/
304 /**** GPE start ****/
305 push_block("Scope", "\\_GPE");
307 stmt("OperationRegion", "PHP, SystemIO, 0x10c0, 0x82");
309 push_block("Field", "PHP, ByteAcc, NoLock, Preserve");
310 indent(); printf("PSTA, 8,\n"); /* hotplug controller event reg */
311 indent(); printf("PSTB, 8,\n"); /* hotplug controller slot reg */
312 for ( slot = 0; slot < 0x100; slot += 2 )
313 {
314 indent();
315 /* Each hotplug control register manages a pair of pci functions. */
316 printf("PH%02X, 8,\n", slot);
317 }
318 pop_block();
320 stmt("OperationRegion", "DG1, SystemIO, 0xb044, 0x04");
322 push_block("Field", "DG1, ByteAcc, NoLock, Preserve");
323 indent(); printf("DPT1, 8, DPT2, 8\n");
324 pop_block();
326 push_block("Method", "_L03, 0, Serialized");
327 /* Detect slot and event (remove/add). */
328 stmt("Name", "SLT, 0x0");
329 stmt("Name", "EVT, 0x0");
330 stmt("Store", "PSTA, Local1");
331 stmt("And", "Local1, 0xf, EVT");
332 stmt("Store", "PSTB, Local1"); /* XXX: Store (PSTB, SLT) ? */
333 stmt("And", "Local1, 0xff, SLT");
334 /* Debug */
335 stmt("Store", "SLT, DPT1");
336 stmt("Store", "EVT, DPT2");
337 /* Decision tree */
338 decision_tree(0x00, 0x100, "SLT", pci_hotplug_notify);
339 pop_block();
341 pop_block();
342 /**** GPE end ****/
345 pop_block();
346 /**** DSDT DefinitionBlock end ****/
348 return 0;
349 }