/root/src/xen/xen/arch/x86/genapic/probe.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2003 Andi Kleen, SuSE Labs. |
2 | | * Subject to the GNU Public License, v.2 |
3 | | * |
4 | | * Generic x86 APIC driver probe layer. |
5 | | */ |
6 | | #include <xen/cpumask.h> |
7 | | #include <xen/string.h> |
8 | | #include <xen/kernel.h> |
9 | | #include <xen/ctype.h> |
10 | | #include <xen/init.h> |
11 | | #include <asm/cache.h> |
12 | | #include <asm/fixmap.h> |
13 | | #include <asm/mpspec.h> |
14 | | #include <asm/apicdef.h> |
15 | | #include <asm/mach-generic/mach_apic.h> |
16 | | #include <asm/setup.h> |
17 | | |
18 | | extern const struct genapic apic_bigsmp; |
19 | | |
20 | | const struct genapic *__read_mostly genapic; |
21 | | |
22 | | const struct genapic *apic_probe[] __initdata = { |
23 | | &apic_bigsmp, |
24 | | &apic_default, /* must be last */ |
25 | | NULL, |
26 | | }; |
27 | | |
28 | | static bool_t __initdata cmdline_apic; |
29 | | |
30 | | void __init generic_bigsmp_probe(void) |
31 | 1 | { |
32 | 1 | /* |
33 | 1 | * This routine is used to switch to bigsmp mode when |
34 | 1 | * - There is no apic= option specified by the user |
35 | 1 | * - generic_apic_probe() has choosen apic_default as the sub_arch |
36 | 1 | * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support |
37 | 1 | */ |
38 | 1 | |
39 | 1 | if (!cmdline_apic && genapic == &apic_default) |
40 | 1 | if (apic_bigsmp.probe()) { |
41 | 1 | genapic = &apic_bigsmp; |
42 | 1 | printk(KERN_INFO "Overriding APIC driver with %s\n", |
43 | 1 | genapic->name); |
44 | 1 | } |
45 | 1 | } |
46 | | |
47 | | static int __init genapic_apic_force(const char *str) |
48 | 0 | { |
49 | 0 | int i, rc = -EINVAL; |
50 | 0 |
|
51 | 0 | for (i = 0; apic_probe[i]; i++) |
52 | 0 | if (!strcmp(apic_probe[i]->name, str)) { |
53 | 0 | genapic = apic_probe[i]; |
54 | 0 | rc = 0; |
55 | 0 | } |
56 | 0 |
|
57 | 0 | return rc; |
58 | 0 | } |
59 | | custom_param("apic", genapic_apic_force); |
60 | | |
61 | | void __init generic_apic_probe(void) |
62 | 1 | { |
63 | 1 | bool changed; |
64 | 1 | int i; |
65 | 1 | |
66 | 1 | record_boot_APIC_mode(); |
67 | 1 | |
68 | 1 | check_x2apic_preenabled(); |
69 | 1 | cmdline_apic = changed = (genapic != NULL); |
70 | 1 | |
71 | 3 | for (i = 0; !changed && apic_probe[i]; i++) { |
72 | 2 | if (apic_probe[i]->probe()) { |
73 | 1 | changed = 1; |
74 | 1 | genapic = apic_probe[i]; |
75 | 1 | } |
76 | 2 | } |
77 | 1 | if (!changed) |
78 | 0 | genapic = &apic_default; |
79 | 1 | |
80 | 1 | printk(KERN_INFO "Using APIC driver %s\n", genapic->name); |
81 | 1 | } |
82 | | |
83 | | /* These functions can switch the APIC even after the initial ->probe() */ |
84 | | |
85 | | int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) |
86 | 0 | { |
87 | 0 | int i; |
88 | 0 | for (i = 0; apic_probe[i]; ++i) { |
89 | 0 | if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { |
90 | 0 | if (!cmdline_apic) { |
91 | 0 | genapic = apic_probe[i]; |
92 | 0 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", |
93 | 0 | genapic->name); |
94 | 0 | } |
95 | 0 | return 1; |
96 | 0 | } |
97 | 0 | } |
98 | 0 | return 0; |
99 | 0 | } |
100 | | |
101 | | int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
102 | 1 | { |
103 | 1 | int i; |
104 | 3 | for (i = 0; apic_probe[i]; ++i) { |
105 | 2 | if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { |
106 | 0 | if (!cmdline_apic) { |
107 | 0 | genapic = apic_probe[i]; |
108 | 0 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", |
109 | 0 | genapic->name); |
110 | 0 | } |
111 | 0 | return 1; |
112 | 0 | } |
113 | 2 | } |
114 | 1 | return 0; |
115 | 1 | } |