debuggers.hg

view xen/arch/x86/acpi.c @ 3674:fb875591fd72

bitkeeper revision 1.1159.223.63 (42028527-fv-d9BM0_LRp8UKGP19gQ)

Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Thu Feb 03 20:10:15 2005 +0000 (2005-02-03)
parents 4f0616f9dffe
children 0a4b76b6b5a0
line source
1 /*
2 * acpi.c - Architecture-Specific Low-Level ACPI Support
3 *
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
6 * Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
27 #include <xen/config.h>
28 #include <xen/kernel.h>
29 #include <xen/init.h>
30 #include <xen/types.h>
31 #include <xen/slab.h>
32 #include <xen/pci.h>
33 #include <xen/irq.h>
34 #include <xen/acpi.h>
35 #include <asm/mpspec.h>
36 #include <asm/io.h>
37 #include <asm/apic.h>
38 #include <asm/apicdef.h>
39 #include <asm/page.h>
40 #include <asm/io_apic.h>
41 #include <asm/acpi.h>
42 #include <asm/smpboot.h>
45 #define PREFIX "ACPI: "
47 int acpi_lapic;
48 int acpi_ioapic;
49 int acpi_strict;
51 acpi_interrupt_flags acpi_sci_flags __initdata;
52 int acpi_sci_override_gsi __initdata;
53 /* --------------------------------------------------------------------------
54 Boot-time Configuration
55 -------------------------------------------------------------------------- */
57 int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */
58 int acpi_ht __initdata = 1; /* enable HT */
60 enum acpi_irq_model_id acpi_irq_model;
63 /*
64 * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
65 * to map the target physical address. The problem is that set_fixmap()
66 * provides a single page, and it is possible that the page is not
67 * sufficient.
68 * By using this area, we can map up to MAX_IO_APICS pages temporarily,
69 * i.e. until the next __va_range() call.
70 *
71 * Important Safety Note: The fixed I/O APIC page numbers are *subtracted*
72 * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
73 * count idx down while incrementing the phys address.
74 */
75 char *__acpi_map_table(unsigned long phys, unsigned long size)
76 {
77 unsigned long base, offset, mapped_size;
78 int idx;
80 if (phys + size < 8*1024*1024)
81 return __va(phys);
83 offset = phys & (PAGE_SIZE - 1);
84 mapped_size = PAGE_SIZE - offset;
85 set_fixmap(FIX_ACPI_END, phys);
86 base = fix_to_virt(FIX_ACPI_END);
88 /*
89 * Most cases can be covered by the below.
90 */
91 idx = FIX_ACPI_END;
92 while (mapped_size < size) {
93 if (--idx < FIX_ACPI_BEGIN)
94 return 0; /* cannot handle this */
95 phys += PAGE_SIZE;
96 set_fixmap(idx, phys);
97 mapped_size += PAGE_SIZE;
98 }
100 return ((unsigned char *) base + offset);
101 }
104 #ifdef CONFIG_X86_LOCAL_APIC
106 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
109 static int __init
110 acpi_parse_madt (
111 unsigned long phys_addr,
112 unsigned long size)
113 {
114 struct acpi_table_madt *madt = NULL;
116 if (!phys_addr || !size)
117 return -EINVAL;
119 madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
120 if (!madt) {
121 printk(KERN_WARNING PREFIX "Unable to map MADT\n");
122 return -ENODEV;
123 }
125 if (madt->lapic_address)
126 acpi_lapic_addr = (u64) madt->lapic_address;
128 printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n",
129 madt->lapic_address);
131 detect_clustered_apic(madt->header.oem_id, madt->header.oem_table_id);
133 return 0;
134 }
137 static int __init
138 acpi_parse_lapic (
139 acpi_table_entry_header *header)
140 {
141 struct acpi_table_lapic *processor = NULL;
143 processor = (struct acpi_table_lapic*) header;
144 if (!processor)
145 return -EINVAL;
147 acpi_table_print_madt_entry(header);
149 mp_register_lapic (
150 processor->id, /* APIC ID */
151 processor->flags.enabled); /* Enabled? */
153 return 0;
154 }
157 static int __init
158 acpi_parse_lapic_addr_ovr (
159 acpi_table_entry_header *header)
160 {
161 struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
163 lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
164 if (!lapic_addr_ovr)
165 return -EINVAL;
167 acpi_lapic_addr = lapic_addr_ovr->address;
169 return 0;
170 }
172 static int __init
173 acpi_parse_lapic_nmi (
174 acpi_table_entry_header *header)
175 {
176 struct acpi_table_lapic_nmi *lapic_nmi = NULL;
178 lapic_nmi = (struct acpi_table_lapic_nmi*) header;
179 if (!lapic_nmi)
180 return -EINVAL;
182 acpi_table_print_madt_entry(header);
184 if (lapic_nmi->lint != 1)
185 printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
187 return 0;
188 }
190 #endif /*CONFIG_X86_LOCAL_APIC*/
192 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
194 static int __init
195 acpi_parse_ioapic (
196 acpi_table_entry_header *header)
197 {
198 struct acpi_table_ioapic *ioapic = NULL;
200 ioapic = (struct acpi_table_ioapic*) header;
201 if (!ioapic)
202 return -EINVAL;
204 acpi_table_print_madt_entry(header);
206 mp_register_ioapic (
207 ioapic->id,
208 ioapic->address,
209 ioapic->global_irq_base);
211 return 0;
212 }
214 /*
215 * Parse Interrupt Source Override for the ACPI SCI
216 */
217 static void
218 acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
219 {
220 if (trigger == 0) /* compatible SCI trigger is level */
221 trigger = 3;
223 if (polarity == 0) /* compatible SCI polarity is low */
224 polarity = 3;
226 /* Command-line over-ride via acpi_sci= */
227 if (acpi_sci_flags.trigger)
228 trigger = acpi_sci_flags.trigger;
230 if (acpi_sci_flags.polarity)
231 polarity = acpi_sci_flags.polarity;
233 /*
234 * mp_config_acpi_legacy_irqs() already setup IRQs < 16
235 * If GSI is < 16, this will update its flags,
236 * else it will create a new mp_irqs[] entry.
237 */
238 mp_override_legacy_irq(gsi, polarity, trigger, gsi);
240 /*
241 * stash over-ride to indicate we've been here
242 * and for later update of acpi_fadt
243 */
244 acpi_sci_override_gsi = gsi;
245 return;
246 }
248 static int __init
249 acpi_parse_fadt(unsigned long phys, unsigned long size)
250 {
251 struct fadt_descriptor_rev2 *fadt =0;
253 fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
254 if (!fadt) {
255 printk(KERN_WARNING PREFIX "Unable to map FADT\n");
256 return 0;
257 }
259 #ifdef CONFIG_ACPI_INTERPRETER
260 /* initialize sci_int early for INT_SRC_OVR MADT parsing */
261 acpi_fadt.sci_int = fadt->sci_int;
262 #endif
264 return 0;
265 }
268 static int __init
269 acpi_parse_int_src_ovr (
270 acpi_table_entry_header *header)
271 {
272 struct acpi_table_int_src_ovr *intsrc = NULL;
274 intsrc = (struct acpi_table_int_src_ovr*) header;
275 if (!intsrc)
276 return -EINVAL;
278 acpi_table_print_madt_entry(header);
280 if (intsrc->bus_irq == acpi_fadt.sci_int) {
281 acpi_sci_ioapic_setup(intsrc->global_irq,
282 intsrc->flags.polarity, intsrc->flags.trigger);
283 return 0;
284 }
286 mp_override_legacy_irq (
287 intsrc->bus_irq,
288 intsrc->flags.polarity,
289 intsrc->flags.trigger,
290 intsrc->global_irq);
292 return 0;
293 }
296 static int __init
297 acpi_parse_nmi_src (
298 acpi_table_entry_header *header)
299 {
300 struct acpi_table_nmi_src *nmi_src = NULL;
302 nmi_src = (struct acpi_table_nmi_src*) header;
303 if (!nmi_src)
304 return -EINVAL;
306 acpi_table_print_madt_entry(header);
308 /* TBD: Support nimsrc entries? */
310 return 0;
311 }
313 #endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
316 static unsigned long __init
317 acpi_scan_rsdp (
318 unsigned long start,
319 unsigned long length)
320 {
321 unsigned long offset = 0;
322 unsigned long sig_len = sizeof("RSD PTR ") - 1;
324 /*
325 * Scan all 16-byte boundaries of the physical memory region for the
326 * RSDP signature.
327 */
328 for (offset = 0; offset < length; offset += 16) {
329 if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
330 continue;
331 return (start + offset);
332 }
334 return 0;
335 }
338 unsigned long __init
339 acpi_find_rsdp (void)
340 {
341 unsigned long rsdp_phys = 0;
343 /*
344 * Scan memory looking for the RSDP signature. First search EBDA (low
345 * memory) paragraphs and then search upper memory (E0000-FFFFF).
346 */
347 rsdp_phys = acpi_scan_rsdp (0, 0x400);
348 if (!rsdp_phys)
349 rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
351 return rsdp_phys;
352 }
355 /*
356 * acpi_boot_init()
357 * called from setup_arch(), always.
358 * 1. maps ACPI tables for later use
359 * 2. enumerates lapics
360 * 3. enumerates io-apics
361 *
362 * side effects:
363 * acpi_lapic = 1 if LAPIC found
364 * acpi_ioapic = 1 if IOAPIC found
365 * if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
366 * if acpi_blacklisted() disable_acpi()
367 * acpi_irq_model=...
368 * ...
369 *
370 * return value: (currently ignored)
371 * 0: success
372 * !0: failure
373 */
374 int __init
375 acpi_boot_init (void)
376 {
377 int result = 0;
379 if (acpi_disabled && !acpi_ht)
380 return(1);
382 /*
383 * The default interrupt routing model is PIC (8259). This gets
384 * overriden if IOAPICs are enumerated (below).
385 */
386 acpi_irq_model = ACPI_IRQ_MODEL_PIC;
388 /*
389 * Initialize the ACPI boot-time table parser.
390 */
391 result = acpi_table_init();
392 if (result) {
393 disable_acpi();
394 return result;
395 }
397 result = acpi_blacklisted();
398 if (result) {
399 printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
400 disable_acpi();
401 return result;
402 }
404 #ifdef CONFIG_X86_LOCAL_APIC
406 /*
407 * MADT
408 * ----
409 * Parse the Multiple APIC Description Table (MADT), if exists.
410 * Note that this table provides platform SMP configuration
411 * information -- the successor to MPS tables.
412 */
414 result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
415 if (!result) {
416 return 0;
417 }
418 else if (result < 0) {
419 printk(KERN_ERR PREFIX "Error parsing MADT\n");
420 return result;
421 }
422 else if (result > 1)
423 printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n");
425 /*
426 * Local APIC
427 * ----------
428 * Note that the LAPIC address is obtained from the MADT (32-bit value)
429 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
430 */
432 result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
433 if (result < 0) {
434 printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
435 return result;
436 }
438 mp_register_lapic_address(acpi_lapic_addr);
440 result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
441 if (!result) {
442 printk(KERN_ERR PREFIX "No LAPIC entries present\n");
443 /* TBD: Cleanup to allow fallback to MPS */
444 return -ENODEV;
445 }
446 else if (result < 0) {
447 printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
448 /* TBD: Cleanup to allow fallback to MPS */
449 return result;
450 }
452 result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
453 if (result < 0) {
454 printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
455 /* TBD: Cleanup to allow fallback to MPS */
456 return result;
457 }
459 acpi_lapic = 1;
461 #endif /*CONFIG_X86_LOCAL_APIC*/
463 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
465 /*
466 * I/O APIC
467 * --------
468 */
470 /*
471 * ACPI interpreter is required to complete interrupt setup,
472 * so if it is off, don't enumerate the io-apics with ACPI.
473 * If MPS is present, it will handle them,
474 * otherwise the system will stay in PIC mode
475 */
476 if (acpi_disabled || acpi_noirq) {
477 return 1;
478 }
480 /*
481 * if "noapic" boot option, don't look for IO-APICs
482 */
483 if (ioapic_setup_disabled()) {
484 printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
485 "due to 'noapic' option.\n");
486 return 1;
487 }
490 result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
491 if (!result) {
492 printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
493 return -ENODEV;
494 }
495 else if (result < 0) {
496 printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
497 return result;
498 }
500 /* Build a default routing table for legacy (ISA) interrupts. */
501 mp_config_acpi_legacy_irqs();
503 /* Record sci_int for use when looking for MADT sci_int override */
504 acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
506 result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
507 if (result < 0) {
508 printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
509 /* TBD: Cleanup to allow fallback to MPS */
510 return result;
511 }
513 /*
514 * If BIOS did not supply an INT_SRC_OVR for the SCI
515 * pretend we got one so we can set the SCI flags.
516 */
517 if (!acpi_sci_override_gsi)
518 acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
520 result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
521 if (result < 0) {
522 printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
523 /* TBD: Cleanup to allow fallback to MPS */
524 return result;
525 }
527 acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
529 acpi_irq_balance_set(NULL);
531 acpi_ioapic = 1;
533 if (acpi_lapic && acpi_ioapic)
534 smp_found_config = 1;
536 #endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
538 return 0;
539 }
542 #ifdef CONFIG_ACPI_BUS
543 /*
544 * acpi_pic_sci_set_trigger()
545 *
546 * use ELCR to set PIC-mode trigger type for SCI
547 *
548 * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
549 * it may require Edge Trigger -- use "acpi_sci=edge"
550 *
551 * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
552 * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
553 * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
554 * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
555 */
557 void __init
558 acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
559 {
560 unsigned char mask = 1 << (irq & 7);
561 unsigned int port = 0x4d0 + (irq >> 3);
562 unsigned char val = inb(port);
565 printk(PREFIX "IRQ%d SCI:", irq);
566 if (!(val & mask)) {
567 printk(" Edge");
569 if (trigger == 3) {
570 printk(" set to Level");
571 outb(val | mask, port);
572 }
573 } else {
574 printk(" Level");
576 if (trigger == 1) {
577 printk(" set to Edge");
578 outb(val & ~mask, port);
579 }
580 }
581 printk(" Trigger.\n");
582 }
584 #endif /* CONFIG_ACPI_BUS */
587 /* --------------------------------------------------------------------------
588 Low-Level Sleep Support
589 -------------------------------------------------------------------------- */
591 #ifdef CONFIG_ACPI_SLEEP
593 #define DEBUG
595 #ifdef DEBUG
596 #include <xen/serial.h>
597 #endif
599 /* address in low memory of the wakeup routine. */
600 unsigned long acpi_wakeup_address = 0;
602 /* new page directory that we will be using */
603 static pmd_t *pmd;
605 /* saved page directory */
606 static pmd_t saved_pmd;
608 /* page which we'll use for the new page directory */
609 static pte_t *ptep;
611 extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
613 /*
614 * acpi_create_identity_pmd
615 *
616 * Create a new, identity mapped pmd.
617 *
618 * Do this by creating new page directory, and marking all the pages as R/W
619 * Then set it as the new Page Middle Directory.
620 * And, of course, flush the TLB so it takes effect.
621 *
622 * We save the address of the old one, for later restoration.
623 */
624 static void acpi_create_identity_pmd (void)
625 {
626 pgd_t *pgd;
627 int i;
629 ptep = (pte_t*)__get_free_page(GFP_KERNEL);
631 /* fill page with low mapping */
632 for (i = 0; i < PTRS_PER_PTE; i++)
633 set_pte(ptep + i, mk_pte_phys(i << PAGE_SHIFT, PAGE_SHARED));
635 pgd = pgd_offset(current->active_mm, 0);
636 pmd = pmd_alloc(current->mm,pgd, 0);
638 /* save the old pmd */
639 saved_pmd = *pmd;
641 /* set the new one */
642 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep)));
644 /* flush the TLB */
645 local_flush_tlb();
646 }
648 /*
649 * acpi_restore_pmd
650 *
651 * Restore the old pmd saved by acpi_create_identity_pmd and
652 * free the page that said function alloc'd
653 */
654 static void acpi_restore_pmd (void)
655 {
656 set_pmd(pmd, saved_pmd);
657 local_flush_tlb();
658 free_page((unsigned long)ptep);
659 }
661 /**
662 * acpi_save_state_mem - save kernel state
663 *
664 * Create an identity mapped page table and copy the wakeup routine to
665 * low memory.
666 */
667 int acpi_save_state_mem (void)
668 {
669 acpi_create_identity_pmd();
670 acpi_copy_wakeup_routine(acpi_wakeup_address);
672 return 0;
673 }
675 /**
676 * acpi_save_state_disk - save kernel state to disk
677 *
678 */
679 int acpi_save_state_disk (void)
680 {
681 return 1;
682 }
684 /*
685 * acpi_restore_state
686 */
687 void acpi_restore_state_mem (void)
688 {
689 acpi_restore_pmd();
690 }
692 /**
693 * acpi_reserve_bootmem - do _very_ early ACPI initialisation
694 *
695 * We allocate a page in low memory for the wakeup
696 * routine for when we come back from a sleep state. The
697 * runtime allocator allows specification of <16M pages, but not
698 * <1M pages.
699 */
700 void __init acpi_reserve_bootmem(void)
701 {
702 acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
703 if (!acpi_wakeup_address)
704 printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
705 }
707 void do_suspend_lowlevel_s4bios(int resume)
708 {
709 if (!resume) {
710 save_processor_context();
711 acpi_save_register_state((unsigned long)&&acpi_sleep_done);
712 acpi_enter_sleep_state_s4bios();
713 return;
714 }
715 acpi_sleep_done:
716 restore_processor_context();
717 }
720 #endif /*CONFIG_ACPI_SLEEP*/