diff options
| author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-24 14:31:04 -0500 |
|---|---|---|
| committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-24 14:33:45 -0500 |
| commit | 109d28152b6e9d5de64cd23e3bc08885ccb3d1ef (patch) | |
| tree | b7b8863faa05254781acfb85cc41da3eef467c6b /arch/x86/kernel | |
| parent | 168cf9af699e87d5a6f44b684583714ecabb8e71 (diff) | |
| parent | 60b341b778cc2929df16c0a504c91621b3c6a4ad (diff) | |
Merge tag 'v2.6.33' for its firewire changes since last branch point
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'arch/x86/kernel')
34 files changed, 403 insertions, 950 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fb1035cd9a6a..af1c5833ff23 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
| @@ -1185,9 +1185,6 @@ static void __init acpi_process_madt(void) | |||
| 1185 | if (!error) { | 1185 | if (!error) { |
| 1186 | acpi_lapic = 1; | 1186 | acpi_lapic = 1; |
| 1187 | 1187 | ||
| 1188 | #ifdef CONFIG_X86_BIGSMP | ||
| 1189 | generic_bigsmp_probe(); | ||
| 1190 | #endif | ||
| 1191 | /* | 1188 | /* |
| 1192 | * Parse MADT IO-APIC entries | 1189 | * Parse MADT IO-APIC entries |
| 1193 | */ | 1190 | */ |
| @@ -1197,8 +1194,6 @@ static void __init acpi_process_madt(void) | |||
| 1197 | acpi_ioapic = 1; | 1194 | acpi_ioapic = 1; |
| 1198 | 1195 | ||
| 1199 | smp_found_config = 1; | 1196 | smp_found_config = 1; |
| 1200 | if (apic->setup_apic_routing) | ||
| 1201 | apic->setup_apic_routing(); | ||
| 1202 | } | 1197 | } |
| 1203 | } | 1198 | } |
| 1204 | if (error == -EINVAL) { | 1199 | if (error == -EINVAL) { |
| @@ -1349,14 +1344,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { | |||
| 1349 | }, | 1344 | }, |
| 1350 | { | 1345 | { |
| 1351 | .callback = force_acpi_ht, | 1346 | .callback = force_acpi_ht, |
| 1352 | .ident = "ASUS P2B-DS", | ||
| 1353 | .matches = { | ||
| 1354 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
| 1355 | DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"), | ||
| 1356 | }, | ||
| 1357 | }, | ||
| 1358 | { | ||
| 1359 | .callback = force_acpi_ht, | ||
| 1360 | .ident = "ASUS CUR-DLS", | 1347 | .ident = "ASUS CUR-DLS", |
| 1361 | .matches = { | 1348 | .matches = { |
| 1362 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | 1349 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), |
| @@ -1529,16 +1516,10 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { | |||
| 1529 | * if acpi_blacklisted() acpi_disabled = 1; | 1516 | * if acpi_blacklisted() acpi_disabled = 1; |
| 1530 | * acpi_irq_model=... | 1517 | * acpi_irq_model=... |
| 1531 | * ... | 1518 | * ... |
| 1532 | * | ||
| 1533 | * return value: (currently ignored) | ||
| 1534 | * 0: success | ||
| 1535 | * !0: failure | ||
| 1536 | */ | 1519 | */ |
| 1537 | 1520 | ||
| 1538 | int __init acpi_boot_table_init(void) | 1521 | void __init acpi_boot_table_init(void) |
| 1539 | { | 1522 | { |
| 1540 | int error; | ||
| 1541 | |||
| 1542 | dmi_check_system(acpi_dmi_table); | 1523 | dmi_check_system(acpi_dmi_table); |
| 1543 | 1524 | ||
| 1544 | /* | 1525 | /* |
| @@ -1546,15 +1527,14 @@ int __init acpi_boot_table_init(void) | |||
| 1546 | * One exception: acpi=ht continues far enough to enumerate LAPICs | 1527 | * One exception: acpi=ht continues far enough to enumerate LAPICs |
| 1547 | */ | 1528 | */ |
| 1548 | if (acpi_disabled && !acpi_ht) | 1529 | if (acpi_disabled && !acpi_ht) |
| 1549 | return 1; | 1530 | return; |
| 1550 | 1531 | ||
| 1551 | /* | 1532 | /* |
| 1552 | * Initialize the ACPI boot-time table parser. | 1533 | * Initialize the ACPI boot-time table parser. |
| 1553 | */ | 1534 | */ |
| 1554 | error = acpi_table_init(); | 1535 | if (acpi_table_init()) { |
| 1555 | if (error) { | ||
| 1556 | disable_acpi(); | 1536 | disable_acpi(); |
| 1557 | return error; | 1537 | return; |
| 1558 | } | 1538 | } |
| 1559 | 1539 | ||
| 1560 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); | 1540 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); |
| @@ -1562,18 +1542,15 @@ int __init acpi_boot_table_init(void) | |||
| 1562 | /* | 1542 | /* |
| 1563 | * blacklist may disable ACPI entirely | 1543 | * blacklist may disable ACPI entirely |
| 1564 | */ | 1544 | */ |
| 1565 | error = acpi_blacklisted(); | 1545 | if (acpi_blacklisted()) { |
| 1566 | if (error) { | ||
| 1567 | if (acpi_force) { | 1546 | if (acpi_force) { |
| 1568 | printk(KERN_WARNING PREFIX "acpi=force override\n"); | 1547 | printk(KERN_WARNING PREFIX "acpi=force override\n"); |
| 1569 | } else { | 1548 | } else { |
| 1570 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); | 1549 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); |
| 1571 | disable_acpi(); | 1550 | disable_acpi(); |
| 1572 | return error; | 1551 | return; |
| 1573 | } | 1552 | } |
| 1574 | } | 1553 | } |
| 1575 | |||
| 1576 | return 0; | ||
| 1577 | } | 1554 | } |
| 1578 | 1555 | ||
| 1579 | int __init early_acpi_boot_init(void) | 1556 | int __init early_acpi_boot_init(void) |
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 82e508677b91..f9961034e557 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
| @@ -162,6 +162,8 @@ static int __init acpi_sleep_setup(char *str) | |||
| 162 | #endif | 162 | #endif |
| 163 | if (strncmp(str, "old_ordering", 12) == 0) | 163 | if (strncmp(str, "old_ordering", 12) == 0) |
| 164 | acpi_old_suspend_ordering(); | 164 | acpi_old_suspend_ordering(); |
| 165 | if (strncmp(str, "sci_force_enable", 16) == 0) | ||
| 166 | acpi_set_sci_en_on_resume(); | ||
| 165 | str = strchr(str, ','); | 167 | str = strchr(str, ','); |
| 166 | if (str != NULL) | 168 | if (str != NULL) |
| 167 | str += strspn(str, ", \t"); | 169 | str += strspn(str, ", \t"); |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 23824fef789c..adb0ba025702 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
| @@ -980,7 +980,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom, | |||
| 980 | { | 980 | { |
| 981 | int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; | 981 | int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; |
| 982 | struct amd_iommu *iommu; | 982 | struct amd_iommu *iommu; |
| 983 | int i; | 983 | unsigned long i; |
| 984 | 984 | ||
| 985 | #ifdef CONFIG_IOMMU_STRESS | 985 | #ifdef CONFIG_IOMMU_STRESS |
| 986 | populate = false; | 986 | populate = false; |
| @@ -1489,11 +1489,14 @@ static void __detach_device(struct device *dev) | |||
| 1489 | { | 1489 | { |
| 1490 | struct iommu_dev_data *dev_data = get_dev_data(dev); | 1490 | struct iommu_dev_data *dev_data = get_dev_data(dev); |
| 1491 | struct iommu_dev_data *alias_data; | 1491 | struct iommu_dev_data *alias_data; |
| 1492 | struct protection_domain *domain; | ||
| 1492 | unsigned long flags; | 1493 | unsigned long flags; |
| 1493 | 1494 | ||
| 1494 | BUG_ON(!dev_data->domain); | 1495 | BUG_ON(!dev_data->domain); |
| 1495 | 1496 | ||
| 1496 | spin_lock_irqsave(&dev_data->domain->lock, flags); | 1497 | domain = dev_data->domain; |
| 1498 | |||
| 1499 | spin_lock_irqsave(&domain->lock, flags); | ||
| 1497 | 1500 | ||
| 1498 | if (dev_data->alias != dev) { | 1501 | if (dev_data->alias != dev) { |
| 1499 | alias_data = get_dev_data(dev_data->alias); | 1502 | alias_data = get_dev_data(dev_data->alias); |
| @@ -1504,13 +1507,15 @@ static void __detach_device(struct device *dev) | |||
| 1504 | if (atomic_dec_and_test(&dev_data->bind)) | 1507 | if (atomic_dec_and_test(&dev_data->bind)) |
| 1505 | do_detach(dev); | 1508 | do_detach(dev); |
| 1506 | 1509 | ||
| 1507 | spin_unlock_irqrestore(&dev_data->domain->lock, flags); | 1510 | spin_unlock_irqrestore(&domain->lock, flags); |
| 1508 | 1511 | ||
| 1509 | /* | 1512 | /* |
| 1510 | * If we run in passthrough mode the device must be assigned to the | 1513 | * If we run in passthrough mode the device must be assigned to the |
| 1511 | * passthrough domain if it is detached from any other domain | 1514 | * passthrough domain if it is detached from any other domain. |
| 1515 | * Make sure we can deassign from the pt_domain itself. | ||
| 1512 | */ | 1516 | */ |
| 1513 | if (iommu_pass_through && dev_data->domain == NULL) | 1517 | if (iommu_pass_through && |
| 1518 | (dev_data->domain == NULL && domain != pt_domain)) | ||
| 1514 | __attach_device(dev, pt_domain); | 1519 | __attach_device(dev, pt_domain); |
| 1515 | } | 1520 | } |
| 1516 | 1521 | ||
| @@ -2218,6 +2223,12 @@ static struct dma_map_ops amd_iommu_dma_ops = { | |||
| 2218 | /* | 2223 | /* |
| 2219 | * The function which clues the AMD IOMMU driver into dma_ops. | 2224 | * The function which clues the AMD IOMMU driver into dma_ops. |
| 2220 | */ | 2225 | */ |
| 2226 | |||
| 2227 | void __init amd_iommu_init_api(void) | ||
| 2228 | { | ||
| 2229 | register_iommu(&amd_iommu_ops); | ||
| 2230 | } | ||
| 2231 | |||
| 2221 | int __init amd_iommu_init_dma_ops(void) | 2232 | int __init amd_iommu_init_dma_ops(void) |
| 2222 | { | 2233 | { |
| 2223 | struct amd_iommu *iommu; | 2234 | struct amd_iommu *iommu; |
| @@ -2253,8 +2264,6 @@ int __init amd_iommu_init_dma_ops(void) | |||
| 2253 | /* Make the driver finally visible to the drivers */ | 2264 | /* Make the driver finally visible to the drivers */ |
| 2254 | dma_ops = &amd_iommu_dma_ops; | 2265 | dma_ops = &amd_iommu_dma_ops; |
| 2255 | 2266 | ||
| 2256 | register_iommu(&amd_iommu_ops); | ||
| 2257 | |||
| 2258 | amd_iommu_stats_init(); | 2267 | amd_iommu_stats_init(); |
| 2259 | 2268 | ||
| 2260 | return 0; | 2269 | return 0; |
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 1dca9c34eaeb..9dc91b431470 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
| @@ -138,6 +138,11 @@ int amd_iommus_present; | |||
| 138 | bool amd_iommu_np_cache __read_mostly; | 138 | bool amd_iommu_np_cache __read_mostly; |
| 139 | 139 | ||
| 140 | /* | 140 | /* |
| 141 | * Set to true if ACPI table parsing and hardware intialization went properly | ||
| 142 | */ | ||
| 143 | static bool amd_iommu_initialized; | ||
| 144 | |||
| 145 | /* | ||
| 141 | * List of protection domains - used during resume | 146 | * List of protection domains - used during resume |
| 142 | */ | 147 | */ |
| 143 | LIST_HEAD(amd_iommu_pd_list); | 148 | LIST_HEAD(amd_iommu_pd_list); |
| @@ -929,6 +934,8 @@ static int __init init_iommu_all(struct acpi_table_header *table) | |||
| 929 | } | 934 | } |
| 930 | WARN_ON(p != end); | 935 | WARN_ON(p != end); |
| 931 | 936 | ||
| 937 | amd_iommu_initialized = true; | ||
| 938 | |||
| 932 | return 0; | 939 | return 0; |
| 933 | } | 940 | } |
| 934 | 941 | ||
| @@ -1263,6 +1270,9 @@ static int __init amd_iommu_init(void) | |||
| 1263 | if (acpi_table_parse("IVRS", init_iommu_all) != 0) | 1270 | if (acpi_table_parse("IVRS", init_iommu_all) != 0) |
| 1264 | goto free; | 1271 | goto free; |
| 1265 | 1272 | ||
| 1273 | if (!amd_iommu_initialized) | ||
| 1274 | goto free; | ||
| 1275 | |||
| 1266 | if (acpi_table_parse("IVRS", init_memory_definitions) != 0) | 1276 | if (acpi_table_parse("IVRS", init_memory_definitions) != 0) |
| 1267 | goto free; | 1277 | goto free; |
| 1268 | 1278 | ||
| @@ -1282,9 +1292,12 @@ static int __init amd_iommu_init(void) | |||
| 1282 | ret = amd_iommu_init_passthrough(); | 1292 | ret = amd_iommu_init_passthrough(); |
| 1283 | else | 1293 | else |
| 1284 | ret = amd_iommu_init_dma_ops(); | 1294 | ret = amd_iommu_init_dma_ops(); |
| 1295 | |||
| 1285 | if (ret) | 1296 | if (ret) |
| 1286 | goto free; | 1297 | goto free; |
| 1287 | 1298 | ||
| 1299 | amd_iommu_init_api(); | ||
| 1300 | |||
| 1288 | amd_iommu_init_notifier(); | 1301 | amd_iommu_init_notifier(); |
| 1289 | 1302 | ||
| 1290 | enable_iommus(); | 1303 | enable_iommus(); |
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 3704997e8b25..f147a95fd84a 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <asm/x86_init.h> | 31 | #include <asm/x86_init.h> |
| 32 | 32 | ||
| 33 | int gart_iommu_aperture; | 33 | int gart_iommu_aperture; |
| 34 | EXPORT_SYMBOL_GPL(gart_iommu_aperture); | ||
| 34 | int gart_iommu_aperture_disabled __initdata; | 35 | int gart_iommu_aperture_disabled __initdata; |
| 35 | int gart_iommu_aperture_allowed __initdata; | 36 | int gart_iommu_aperture_allowed __initdata; |
| 36 | 37 | ||
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index aa57c079c98f..dfca210f6a10 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -61,12 +61,6 @@ unsigned int boot_cpu_physical_apicid = -1U; | |||
| 61 | 61 | ||
| 62 | /* | 62 | /* |
| 63 | * The highest APIC ID seen during enumeration. | 63 | * The highest APIC ID seen during enumeration. |
| 64 | * | ||
| 65 | * On AMD, this determines the messaging protocol we can use: if all APIC IDs | ||
| 66 | * are in the 0 ... 7 range, then we can use logical addressing which | ||
| 67 | * has some performance advantages (better broadcasting). | ||
| 68 | * | ||
| 69 | * If there's an APIC ID above 8, we use physical addressing. | ||
| 70 | */ | 64 | */ |
| 71 | unsigned int max_physical_apicid; | 65 | unsigned int max_physical_apicid; |
| 72 | 66 | ||
| @@ -1647,9 +1641,7 @@ int __init APIC_init_uniprocessor(void) | |||
| 1647 | #endif | 1641 | #endif |
| 1648 | 1642 | ||
| 1649 | enable_IR_x2apic(); | 1643 | enable_IR_x2apic(); |
| 1650 | #ifdef CONFIG_X86_64 | ||
| 1651 | default_setup_apic_routing(); | 1644 | default_setup_apic_routing(); |
| 1652 | #endif | ||
| 1653 | 1645 | ||
| 1654 | verify_local_APIC(); | 1646 | verify_local_APIC(); |
| 1655 | connect_bsp_APIC(); | 1647 | connect_bsp_APIC(); |
| @@ -1897,18 +1889,6 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
| 1897 | if (apicid > max_physical_apicid) | 1889 | if (apicid > max_physical_apicid) |
| 1898 | max_physical_apicid = apicid; | 1890 | max_physical_apicid = apicid; |
| 1899 | 1891 | ||
| 1900 | #ifdef CONFIG_X86_32 | ||
| 1901 | switch (boot_cpu_data.x86_vendor) { | ||
| 1902 | case X86_VENDOR_INTEL: | ||
| 1903 | if (num_processors > 8) | ||
| 1904 | def_to_bigsmp = 1; | ||
| 1905 | break; | ||
| 1906 | case X86_VENDOR_AMD: | ||
| 1907 | if (max_physical_apicid >= 8) | ||
| 1908 | def_to_bigsmp = 1; | ||
| 1909 | } | ||
| 1910 | #endif | ||
| 1911 | |||
| 1912 | #if defined(CONFIG_SMP) || defined(CONFIG_X86_64) | 1892 | #if defined(CONFIG_SMP) || defined(CONFIG_X86_64) |
| 1913 | early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; | 1893 | early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; |
| 1914 | early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; | 1894 | early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; |
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index eacbd2b31d27..e3c3d820c325 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c | |||
| @@ -240,6 +240,11 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 240 | printk(KERN_DEBUG "system APIC only can use physical flat"); | 240 | printk(KERN_DEBUG "system APIC only can use physical flat"); |
| 241 | return 1; | 241 | return 1; |
| 242 | } | 242 | } |
| 243 | |||
| 244 | if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) { | ||
| 245 | printk(KERN_DEBUG "IBM Summit detected, will use apic physical"); | ||
| 246 | return 1; | ||
| 247 | } | ||
| 243 | #endif | 248 | #endif |
| 244 | 249 | ||
| 245 | return 0; | 250 | return 0; |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index de00c4619a55..53243ca7816d 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2434,6 +2434,13 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
| 2434 | cfg = irq_cfg(irq); | 2434 | cfg = irq_cfg(irq); |
| 2435 | raw_spin_lock(&desc->lock); | 2435 | raw_spin_lock(&desc->lock); |
| 2436 | 2436 | ||
| 2437 | /* | ||
| 2438 | * Check if the irq migration is in progress. If so, we | ||
| 2439 | * haven't received the cleanup request yet for this irq. | ||
| 2440 | */ | ||
| 2441 | if (cfg->move_in_progress) | ||
| 2442 | goto unlock; | ||
| 2443 | |||
| 2437 | if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) | 2444 | if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) |
| 2438 | goto unlock; | 2445 | goto unlock; |
| 2439 | 2446 | ||
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 1a6559f6768c..99d2fe016084 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c | |||
| @@ -52,7 +52,32 @@ static int __init print_ipi_mode(void) | |||
| 52 | } | 52 | } |
| 53 | late_initcall(print_ipi_mode); | 53 | late_initcall(print_ipi_mode); |
| 54 | 54 | ||
| 55 | void default_setup_apic_routing(void) | 55 | void __init default_setup_apic_routing(void) |
| 56 | { | ||
| 57 | int version = apic_version[boot_cpu_physical_apicid]; | ||
| 58 | |||
| 59 | if (num_possible_cpus() > 8) { | ||
| 60 | switch (boot_cpu_data.x86_vendor) { | ||
| 61 | case X86_VENDOR_INTEL: | ||
| 62 | if (!APIC_XAPIC(version)) { | ||
| 63 | def_to_bigsmp = 0; | ||
| 64 | break; | ||
| 65 | } | ||
| 66 | /* If P4 and above fall through */ | ||
| 67 | case X86_VENDOR_AMD: | ||
| 68 | def_to_bigsmp = 1; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | #ifdef CONFIG_X86_BIGSMP | ||
| 73 | generic_bigsmp_probe(); | ||
| 74 | #endif | ||
| 75 | |||
| 76 | if (apic->setup_apic_routing) | ||
| 77 | apic->setup_apic_routing(); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void setup_apic_flat_routing(void) | ||
| 56 | { | 81 | { |
| 57 | #ifdef CONFIG_X86_IO_APIC | 82 | #ifdef CONFIG_X86_IO_APIC |
| 58 | printk(KERN_INFO | 83 | printk(KERN_INFO |
| @@ -103,7 +128,7 @@ struct apic apic_default = { | |||
| 103 | .init_apic_ldr = default_init_apic_ldr, | 128 | .init_apic_ldr = default_init_apic_ldr, |
| 104 | 129 | ||
| 105 | .ioapic_phys_id_map = default_ioapic_phys_id_map, | 130 | .ioapic_phys_id_map = default_ioapic_phys_id_map, |
| 106 | .setup_apic_routing = default_setup_apic_routing, | 131 | .setup_apic_routing = setup_apic_flat_routing, |
| 107 | .multi_timer_check = NULL, | 132 | .multi_timer_check = NULL, |
| 108 | .apicid_to_node = default_apicid_to_node, | 133 | .apicid_to_node = default_apicid_to_node, |
| 109 | .cpu_to_logical_apicid = default_cpu_to_logical_apicid, | 134 | .cpu_to_logical_apicid = default_cpu_to_logical_apicid, |
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index c4cbd3080c1c..83e9be4778e2 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c | |||
| @@ -67,17 +67,8 @@ void __init default_setup_apic_routing(void) | |||
| 67 | } | 67 | } |
| 68 | #endif | 68 | #endif |
| 69 | 69 | ||
| 70 | if (apic == &apic_flat) { | 70 | if (apic == &apic_flat && num_possible_cpus() > 8) |
| 71 | switch (boot_cpu_data.x86_vendor) { | 71 | apic = &apic_physflat; |
| 72 | case X86_VENDOR_INTEL: | ||
| 73 | if (num_processors > 8) | ||
| 74 | apic = &apic_physflat; | ||
| 75 | break; | ||
| 76 | case X86_VENDOR_AMD: | ||
| 77 | if (max_physical_apicid >= 8) | ||
| 78 | apic = &apic_physflat; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | 72 | ||
| 82 | printk(KERN_INFO "Setting APIC routing to %s\n", apic->name); | 73 | printk(KERN_INFO "Setting APIC routing to %s\n", apic->name); |
| 83 | 74 | ||
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index d56b0efb2057..21db3cbea7dc 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
| @@ -36,6 +36,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits); | |||
| 36 | 36 | ||
| 37 | static enum uv_system_type uv_system_type; | 37 | static enum uv_system_type uv_system_type; |
| 38 | static u64 gru_start_paddr, gru_end_paddr; | 38 | static u64 gru_start_paddr, gru_end_paddr; |
| 39 | int uv_min_hub_revision_id; | ||
| 40 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); | ||
| 39 | 41 | ||
| 40 | static inline bool is_GRU_range(u64 start, u64 end) | 42 | static inline bool is_GRU_range(u64 start, u64 end) |
| 41 | { | 43 | { |
| @@ -55,12 +57,19 @@ static int early_get_nodeid(void) | |||
| 55 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr)); | 57 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr)); |
| 56 | node_id.v = *mmr; | 58 | node_id.v = *mmr; |
| 57 | early_iounmap(mmr, sizeof(*mmr)); | 59 | early_iounmap(mmr, sizeof(*mmr)); |
| 60 | |||
| 61 | /* Currently, all blades have same revision number */ | ||
| 62 | uv_min_hub_revision_id = node_id.s.revision; | ||
| 63 | |||
| 58 | return node_id.s.node_id; | 64 | return node_id.s.node_id; |
| 59 | } | 65 | } |
| 60 | 66 | ||
| 61 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 67 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
| 62 | { | 68 | { |
| 69 | int nodeid; | ||
| 70 | |||
| 63 | if (!strcmp(oem_id, "SGI")) { | 71 | if (!strcmp(oem_id, "SGI")) { |
| 72 | nodeid = early_get_nodeid(); | ||
| 64 | x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; | 73 | x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; |
| 65 | if (!strcmp(oem_table_id, "UVL")) | 74 | if (!strcmp(oem_table_id, "UVL")) |
| 66 | uv_system_type = UV_LEGACY_APIC; | 75 | uv_system_type = UV_LEGACY_APIC; |
| @@ -68,7 +77,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 68 | uv_system_type = UV_X2APIC; | 77 | uv_system_type = UV_X2APIC; |
| 69 | else if (!strcmp(oem_table_id, "UVH")) { | 78 | else if (!strcmp(oem_table_id, "UVH")) { |
| 70 | __get_cpu_var(x2apic_extra_bits) = | 79 | __get_cpu_var(x2apic_extra_bits) = |
| 71 | early_get_nodeid() << (UV_APIC_PNODE_SHIFT - 1); | 80 | nodeid << (UV_APIC_PNODE_SHIFT - 1); |
| 72 | uv_system_type = UV_NON_UNIQUE_APIC; | 81 | uv_system_type = UV_NON_UNIQUE_APIC; |
| 73 | return 1; | 82 | return 1; |
| 74 | } | 83 | } |
| @@ -374,13 +383,13 @@ static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size) | |||
| 374 | 383 | ||
| 375 | enum map_type {map_wb, map_uc}; | 384 | enum map_type {map_wb, map_uc}; |
| 376 | 385 | ||
| 377 | static __init void map_high(char *id, unsigned long base, int shift, | 386 | static __init void map_high(char *id, unsigned long base, int pshift, |
| 378 | int max_pnode, enum map_type map_type) | 387 | int bshift, int max_pnode, enum map_type map_type) |
| 379 | { | 388 | { |
| 380 | unsigned long bytes, paddr; | 389 | unsigned long bytes, paddr; |
| 381 | 390 | ||
| 382 | paddr = base << shift; | 391 | paddr = base << pshift; |
| 383 | bytes = (1UL << shift) * (max_pnode + 1); | 392 | bytes = (1UL << bshift) * (max_pnode + 1); |
| 384 | printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, | 393 | printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, |
| 385 | paddr + bytes); | 394 | paddr + bytes); |
| 386 | if (map_type == map_uc) | 395 | if (map_type == map_uc) |
| @@ -396,7 +405,7 @@ static __init void map_gru_high(int max_pnode) | |||
| 396 | 405 | ||
| 397 | gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); | 406 | gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); |
| 398 | if (gru.s.enable) { | 407 | if (gru.s.enable) { |
| 399 | map_high("GRU", gru.s.base, shift, max_pnode, map_wb); | 408 | map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb); |
| 400 | gru_start_paddr = ((u64)gru.s.base << shift); | 409 | gru_start_paddr = ((u64)gru.s.base << shift); |
| 401 | gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1); | 410 | gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1); |
| 402 | 411 | ||
| @@ -410,7 +419,7 @@ static __init void map_mmr_high(int max_pnode) | |||
| 410 | 419 | ||
| 411 | mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR); | 420 | mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR); |
| 412 | if (mmr.s.enable) | 421 | if (mmr.s.enable) |
| 413 | map_high("MMR", mmr.s.base, shift, max_pnode, map_uc); | 422 | map_high("MMR", mmr.s.base, shift, shift, max_pnode, map_uc); |
| 414 | } | 423 | } |
| 415 | 424 | ||
| 416 | static __init void map_mmioh_high(int max_pnode) | 425 | static __init void map_mmioh_high(int max_pnode) |
| @@ -420,7 +429,8 @@ static __init void map_mmioh_high(int max_pnode) | |||
| 420 | 429 | ||
| 421 | mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR); | 430 | mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR); |
| 422 | if (mmioh.s.enable) | 431 | if (mmioh.s.enable) |
| 423 | map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc); | 432 | map_high("MMIOH", mmioh.s.base, shift, mmioh.s.m_io, |
| 433 | max_pnode, map_uc); | ||
| 424 | } | 434 | } |
| 425 | 435 | ||
| 426 | static __init void map_low_mmrs(void) | 436 | static __init void map_low_mmrs(void) |
| @@ -629,8 +639,10 @@ void __init uv_system_init(void) | |||
| 629 | uv_rtc_init(); | 639 | uv_rtc_init(); |
| 630 | 640 | ||
| 631 | for_each_present_cpu(cpu) { | 641 | for_each_present_cpu(cpu) { |
| 642 | int apicid = per_cpu(x86_cpu_to_apicid, cpu); | ||
| 643 | |||
| 632 | nid = cpu_to_node(cpu); | 644 | nid = cpu_to_node(cpu); |
| 633 | pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu)); | 645 | pnode = uv_apicid_to_pnode(apicid); |
| 634 | blade = boot_pnode_to_blade(pnode); | 646 | blade = boot_pnode_to_blade(pnode); |
| 635 | lcpu = uv_blade_info[blade].nr_possible_cpus; | 647 | lcpu = uv_blade_info[blade].nr_possible_cpus; |
| 636 | uv_blade_info[blade].nr_possible_cpus++; | 648 | uv_blade_info[blade].nr_possible_cpus++; |
| @@ -651,15 +663,13 @@ void __init uv_system_init(void) | |||
| 651 | uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra; | 663 | uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra; |
| 652 | uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; | 664 | uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; |
| 653 | uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id; | 665 | uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id; |
| 654 | uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu; | 666 | uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid); |
| 655 | uv_node_to_blade[nid] = blade; | 667 | uv_node_to_blade[nid] = blade; |
| 656 | uv_cpu_to_blade[cpu] = blade; | 668 | uv_cpu_to_blade[cpu] = blade; |
| 657 | max_pnode = max(pnode, max_pnode); | 669 | max_pnode = max(pnode, max_pnode); |
| 658 | 670 | ||
| 659 | printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, " | 671 | printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, lcpu %d, blade %d\n", |
| 660 | "lcpu %d, blade %d\n", | 672 | cpu, apicid, pnode, nid, lcpu, blade); |
| 661 | cpu, per_cpu(x86_cpu_to_apicid, cpu), pnode, nid, | ||
| 662 | lcpu, blade); | ||
| 663 | } | 673 | } |
| 664 | 674 | ||
| 665 | /* Add blade/pnode info for nodes without cpus */ | 675 | /* Add blade/pnode info for nodes without cpus */ |
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 1d2cb383410e..c202b62f3671 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
| @@ -19,8 +19,6 @@ obj-y += vmware.o hypervisor.o sched.o | |||
| 19 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o | 19 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o |
| 20 | obj-$(CONFIG_X86_64) += bugs_64.o | 20 | obj-$(CONFIG_X86_64) += bugs_64.o |
| 21 | 21 | ||
| 22 | obj-$(CONFIG_X86_CPU_DEBUG) += cpu_debug.o | ||
| 23 | |||
| 24 | obj-$(CONFIG_CPU_SUP_INTEL) += intel.o | 22 | obj-$(CONFIG_CPU_SUP_INTEL) += intel.o |
| 25 | obj-$(CONFIG_CPU_SUP_AMD) += amd.o | 23 | obj-$(CONFIG_CPU_SUP_AMD) += amd.o |
| 26 | obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o | 24 | obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o |
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c deleted file mode 100644 index b368cd862997..000000000000 --- a/arch/x86/kernel/cpu/cpu_debug.c +++ /dev/null | |||
| @@ -1,688 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * CPU x86 architecture debug code | ||
| 3 | * | ||
| 4 | * Copyright(C) 2009 Jaswinder Singh Rajput | ||
| 5 | * | ||
| 6 | * For licencing details see kernel-base/COPYING | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/compiler.h> | ||
| 11 | #include <linux/seq_file.h> | ||
| 12 | #include <linux/debugfs.h> | ||
| 13 | #include <linux/kprobes.h> | ||
| 14 | #include <linux/uaccess.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/percpu.h> | ||
| 18 | #include <linux/signal.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/types.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/smp.h> | ||
| 25 | |||
| 26 | #include <asm/cpu_debug.h> | ||
| 27 | #include <asm/paravirt.h> | ||
| 28 | #include <asm/system.h> | ||
| 29 | #include <asm/traps.h> | ||
| 30 | #include <asm/apic.h> | ||
| 31 | #include <asm/desc.h> | ||
| 32 | |||
| 33 | static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpud_arr); | ||
| 34 | static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], cpud_priv_arr); | ||
| 35 | static DEFINE_PER_CPU(int, cpud_priv_count); | ||
| 36 | |||
| 37 | static DEFINE_MUTEX(cpu_debug_lock); | ||
| 38 | |||
| 39 | static struct dentry *cpu_debugfs_dir; | ||
| 40 | |||
| 41 | static struct cpu_debug_base cpu_base[] = { | ||
| 42 | { "mc", CPU_MC, 0 }, | ||
| 43 | { "monitor", CPU_MONITOR, 0 }, | ||
| 44 | { "time", CPU_TIME, 0 }, | ||
| 45 | { "pmc", CPU_PMC, 1 }, | ||
| 46 | { "platform", CPU_PLATFORM, 0 }, | ||
| 47 | { "apic", CPU_APIC, 0 }, | ||
| 48 | { "poweron", CPU_POWERON, 0 }, | ||
| 49 | { "control", CPU_CONTROL, 0 }, | ||
| 50 | { "features", CPU_FEATURES, 0 }, | ||
| 51 | { "lastbranch", CPU_LBRANCH, 0 }, | ||
| 52 | { "bios", CPU_BIOS, 0 }, | ||
| 53 | { "freq", CPU_FREQ, 0 }, | ||
| 54 | { "mtrr", CPU_MTRR, 0 }, | ||
| 55 | { "perf", CPU_PERF, 0 }, | ||
| 56 | { "cache", CPU_CACHE, 0 }, | ||
| 57 | { "sysenter", CPU_SYSENTER, 0 }, | ||
| 58 | { "therm", CPU_THERM, 0 }, | ||
| 59 | { "misc", CPU_MISC, 0 }, | ||
| 60 | { "debug", CPU_DEBUG, 0 }, | ||
| 61 | { "pat", CPU_PAT, 0 }, | ||
| 62 | { "vmx", CPU_VMX, 0 }, | ||
| 63 | { "call", CPU_CALL, 0 }, | ||
| 64 | { "base", CPU_BASE, 0 }, | ||
| 65 | { "ver", CPU_VER, 0 }, | ||
| 66 | { "conf", CPU_CONF, 0 }, | ||
| 67 | { "smm", CPU_SMM, 0 }, | ||
| 68 | { "svm", CPU_SVM, 0 }, | ||
| 69 | { "osvm", CPU_OSVM, 0 }, | ||
| 70 | { "tss", CPU_TSS, 0 }, | ||
| 71 | { "cr", CPU_CR, 0 }, | ||
| 72 | { "dt", CPU_DT, 0 }, | ||
| 73 | { "registers", CPU_REG_ALL, 0 }, | ||
| 74 | }; | ||
| 75 | |||
| 76 | static struct cpu_file_base cpu_file[] = { | ||
| 77 | { "index", CPU_REG_ALL, 0 }, | ||
| 78 | { "value", CPU_REG_ALL, 1 }, | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* CPU Registers Range */ | ||
| 82 | static struct cpu_debug_range cpu_reg_range[] = { | ||
| 83 | { 0x00000000, 0x00000001, CPU_MC, }, | ||
| 84 | { 0x00000006, 0x00000007, CPU_MONITOR, }, | ||
| 85 | { 0x00000010, 0x00000010, CPU_TIME, }, | ||
| 86 | { 0x00000011, 0x00000013, CPU_PMC, }, | ||
| 87 | { 0x00000017, 0x00000017, CPU_PLATFORM, }, | ||
| 88 | { 0x0000001B, 0x0000001B, CPU_APIC, }, | ||
| 89 | { 0x0000002A, 0x0000002B, CPU_POWERON, }, | ||
| 90 | { 0x0000002C, 0x0000002C, CPU_FREQ, }, | ||
| 91 | { 0x0000003A, 0x0000003A, CPU_CONTROL, }, | ||
| 92 | { 0x00000040, 0x00000047, CPU_LBRANCH, }, | ||
| 93 | { 0x00000060, 0x00000067, CPU_LBRANCH, }, | ||
| 94 | { 0x00000079, 0x00000079, CPU_BIOS, }, | ||
| 95 | { 0x00000088, 0x0000008A, CPU_CACHE, }, | ||
| 96 | { 0x0000008B, 0x0000008B, CPU_BIOS, }, | ||
| 97 | { 0x0000009B, 0x0000009B, CPU_MONITOR, }, | ||
| 98 | { 0x000000C1, 0x000000C4, CPU_PMC, }, | ||
| 99 | { 0x000000CD, 0x000000CD, CPU_FREQ, }, | ||
| 100 | { 0x000000E7, 0x000000E8, CPU_PERF, }, | ||
| 101 | { 0x000000FE, 0x000000FE, CPU_MTRR, }, | ||
| 102 | |||
| 103 | { 0x00000116, 0x0000011E, CPU_CACHE, }, | ||
| 104 | { 0x00000174, 0x00000176, CPU_SYSENTER, }, | ||
| 105 | { 0x00000179, 0x0000017B, CPU_MC, }, | ||
| 106 | { 0x00000186, 0x00000189, CPU_PMC, }, | ||
| 107 | { 0x00000198, 0x00000199, CPU_PERF, }, | ||
| 108 | { 0x0000019A, 0x0000019A, CPU_TIME, }, | ||
| 109 | { 0x0000019B, 0x0000019D, CPU_THERM, }, | ||
| 110 | { 0x000001A0, 0x000001A0, CPU_MISC, }, | ||
| 111 | { 0x000001C9, 0x000001C9, CPU_LBRANCH, }, | ||
| 112 | { 0x000001D7, 0x000001D8, CPU_LBRANCH, }, | ||
| 113 | { 0x000001D9, 0x000001D9, CPU_DEBUG, }, | ||
| 114 | { 0x000001DA, 0x000001E0, CPU_LBRANCH, }, | ||
| 115 | |||
| 116 | { 0x00000200, 0x0000020F, CPU_MTRR, }, | ||
| 117 | { 0x00000250, 0x00000250, CPU_MTRR, }, | ||
| 118 | { 0x00000258, 0x00000259, CPU_MTRR, }, | ||
| 119 | { 0x00000268, 0x0000026F, CPU_MTRR, }, | ||
| 120 | { 0x00000277, 0x00000277, CPU_PAT, }, | ||
| 121 | { 0x000002FF, 0x000002FF, CPU_MTRR, }, | ||
| 122 | |||
| 123 | { 0x00000300, 0x00000311, CPU_PMC, }, | ||
| 124 | { 0x00000345, 0x00000345, CPU_PMC, }, | ||
| 125 | { 0x00000360, 0x00000371, CPU_PMC, }, | ||
| 126 | { 0x0000038D, 0x00000390, CPU_PMC, }, | ||
| 127 | { 0x000003A0, 0x000003BE, CPU_PMC, }, | ||
| 128 | { 0x000003C0, 0x000003CD, CPU_PMC, }, | ||
| 129 | { 0x000003E0, 0x000003E1, CPU_PMC, }, | ||
| 130 | { 0x000003F0, 0x000003F2, CPU_PMC, }, | ||
| 131 | |||
| 132 | { 0x00000400, 0x00000417, CPU_MC, }, | ||
| 133 | { 0x00000480, 0x0000048B, CPU_VMX, }, | ||
| 134 | |||
| 135 | { 0x00000600, 0x00000600, CPU_DEBUG, }, | ||
| 136 | { 0x00000680, 0x0000068F, CPU_LBRANCH, }, | ||
| 137 | { 0x000006C0, 0x000006CF, CPU_LBRANCH, }, | ||
| 138 | |||
| 139 | { 0x000107CC, 0x000107D3, CPU_PMC, }, | ||
| 140 | |||
| 141 | { 0xC0000080, 0xC0000080, CPU_FEATURES, }, | ||
| 142 | { 0xC0000081, 0xC0000084, CPU_CALL, }, | ||
| 143 | { 0xC0000100, 0xC0000102, CPU_BASE, }, | ||
| 144 | { 0xC0000103, 0xC0000103, CPU_TIME, }, | ||
| 145 | |||
| 146 | { 0xC0010000, 0xC0010007, CPU_PMC, }, | ||
| 147 | { 0xC0010010, 0xC0010010, CPU_CONF, }, | ||
| 148 | { 0xC0010015, 0xC0010015, CPU_CONF, }, | ||
| 149 | { 0xC0010016, 0xC001001A, CPU_MTRR, }, | ||
| 150 | { 0xC001001D, 0xC001001D, CPU_MTRR, }, | ||
| 151 | { 0xC001001F, 0xC001001F, CPU_CONF, }, | ||
| 152 | { 0xC0010030, 0xC0010035, CPU_BIOS, }, | ||
| 153 | { 0xC0010044, 0xC0010048, CPU_MC, }, | ||
| 154 | { 0xC0010050, 0xC0010056, CPU_SMM, }, | ||
| 155 | { 0xC0010058, 0xC0010058, CPU_CONF, }, | ||
| 156 | { 0xC0010060, 0xC0010060, CPU_CACHE, }, | ||
| 157 | { 0xC0010061, 0xC0010068, CPU_SMM, }, | ||
| 158 | { 0xC0010069, 0xC001006B, CPU_SMM, }, | ||
| 159 | { 0xC0010070, 0xC0010071, CPU_SMM, }, | ||
| 160 | { 0xC0010111, 0xC0010113, CPU_SMM, }, | ||
| 161 | { 0xC0010114, 0xC0010118, CPU_SVM, }, | ||
| 162 | { 0xC0010140, 0xC0010141, CPU_OSVM, }, | ||
| 163 | { 0xC0011022, 0xC0011023, CPU_CONF, }, | ||
| 164 | }; | ||
| 165 | |||
| 166 | static int is_typeflag_valid(unsigned cpu, unsigned flag) | ||
| 167 | { | ||
| 168 | int i; | ||
| 169 | |||
| 170 | /* Standard Registers should be always valid */ | ||
| 171 | if (flag >= CPU_TSS) | ||
| 172 | return 1; | ||
| 173 | |||
| 174 | for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { | ||
| 175 | if (cpu_reg_range[i].flag == flag) | ||
| 176 | return 1; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Invalid */ | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max, | ||
| 184 | int index, unsigned flag) | ||
| 185 | { | ||
| 186 | if (cpu_reg_range[index].flag == flag) { | ||
| 187 | *min = cpu_reg_range[index].min; | ||
| 188 | *max = cpu_reg_range[index].max; | ||
| 189 | } else | ||
| 190 | *max = 0; | ||
| 191 | |||
| 192 | return *max; | ||
| 193 | } | ||
| 194 | |||
| 195 | /* This function can also be called with seq = NULL for printk */ | ||
| 196 | static void print_cpu_data(struct seq_file *seq, unsigned type, | ||
| 197 | u32 low, u32 high) | ||
| 198 | { | ||
| 199 | struct cpu_private *priv; | ||
| 200 | u64 val = high; | ||
| 201 | |||
| 202 | if (seq) { | ||
| 203 | priv = seq->private; | ||
| 204 | if (priv->file) { | ||
| 205 | val = (val << 32) | low; | ||
| 206 | seq_printf(seq, "0x%llx\n", val); | ||
| 207 | } else | ||
| 208 | seq_printf(seq, " %08x: %08x_%08x\n", | ||
| 209 | type, high, low); | ||
| 210 | } else | ||
| 211 | printk(KERN_INFO " %08x: %08x_%08x\n", type, high, low); | ||
| 212 | } | ||
| 213 | |||
| 214 | /* This function can also be called with seq = NULL for printk */ | ||
| 215 | static void print_msr(struct seq_file *seq, unsigned cpu, unsigned flag) | ||
| 216 | { | ||
| 217 | unsigned msr, msr_min, msr_max; | ||
| 218 | struct cpu_private *priv; | ||
| 219 | u32 low, high; | ||
| 220 | int i; | ||
| 221 | |||
| 222 | if (seq) { | ||
| 223 | priv = seq->private; | ||
| 224 | if (priv->file) { | ||
| 225 | if (!rdmsr_safe_on_cpu(priv->cpu, priv->reg, | ||
| 226 | &low, &high)) | ||
| 227 | print_cpu_data(seq, priv->reg, low, high); | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { | ||
| 233 | if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag)) | ||
| 234 | continue; | ||
| 235 | |||
| 236 | for (msr = msr_min; msr <= msr_max; msr++) { | ||
| 237 | if (rdmsr_safe_on_cpu(cpu, msr, &low, &high)) | ||
| 238 | continue; | ||
| 239 | print_cpu_data(seq, msr, low, high); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | static void print_tss(void *arg) | ||
| 245 | { | ||
| 246 | struct pt_regs *regs = task_pt_regs(current); | ||
| 247 | struct seq_file *seq = arg; | ||
| 248 | unsigned int seg; | ||
| 249 | |||
| 250 | seq_printf(seq, " RAX\t: %016lx\n", regs->ax); | ||
| 251 | seq_printf(seq, " RBX\t: %016lx\n", regs->bx); | ||
| 252 | seq_printf(seq, " RCX\t: %016lx\n", regs->cx); | ||
| 253 | seq_printf(seq, " RDX\t: %016lx\n", regs->dx); | ||
| 254 | |||
| 255 | seq_printf(seq, " RSI\t: %016lx\n", regs->si); | ||
| 256 | seq_printf(seq, " RDI\t: %016lx\n", regs->di); | ||
| 257 | seq_printf(seq, " RBP\t: %016lx\n", regs->bp); | ||
| 258 | seq_printf(seq, " ESP\t: %016lx\n", regs->sp); | ||
| 259 | |||
| 260 | #ifdef CONFIG_X86_64 | ||
| 261 | seq_printf(seq, " R08\t: %016lx\n", regs->r8); | ||
| 262 | seq_printf(seq, " R09\t: %016lx\n", regs->r9); | ||
| 263 | seq_printf(seq, " R10\t: %016lx\n", regs->r10); | ||
| 264 | seq_printf(seq, " R11\t: %016lx\n", regs->r11); | ||
| 265 | seq_printf(seq, " R12\t: %016lx\n", regs->r12); | ||
| 266 | seq_printf(seq, " R13\t: %016lx\n", regs->r13); | ||
| 267 | seq_printf(seq, " R14\t: %016lx\n", regs->r14); | ||
| 268 | seq_printf(seq, " R15\t: %016lx\n", regs->r15); | ||
| 269 | #endif | ||
| 270 | |||
| 271 | asm("movl %%cs,%0" : "=r" (seg)); | ||
| 272 | seq_printf(seq, " CS\t: %04x\n", seg); | ||
| 273 | asm("movl %%ds,%0" : "=r" (seg)); | ||
| 274 | seq_printf(seq, " DS\t: %04x\n", seg); | ||
| 275 | seq_printf(seq, " SS\t: %04lx\n", regs->ss & 0xffff); | ||
| 276 | asm("movl %%es,%0" : "=r" (seg)); | ||
| 277 | seq_printf(seq, " ES\t: %04x\n", seg); | ||
| 278 | asm("movl %%fs,%0" : "=r" (seg)); | ||
| 279 | seq_printf(seq, " FS\t: %04x\n", seg); | ||
| 280 | asm("movl %%gs,%0" : "=r" (seg)); | ||
| 281 | seq_printf(seq, " GS\t: %04x\n", seg); | ||
| 282 | |||
| 283 | seq_printf(seq, " EFLAGS\t: %016lx\n", regs->flags); | ||
| 284 | |||
| 285 | seq_printf(seq, " EIP\t: %016lx\n", regs->ip); | ||
| 286 | } | ||
| 287 | |||
| 288 | static void print_cr(void *arg) | ||
| 289 | { | ||
| 290 | struct seq_file *seq = arg; | ||
| 291 | |||
| 292 | seq_printf(seq, " cr0\t: %016lx\n", read_cr0()); | ||
| 293 | seq_printf(seq, " cr2\t: %016lx\n", read_cr2()); | ||
| 294 | seq_printf(seq, " cr3\t: %016lx\n", read_cr3()); | ||
| 295 | seq_printf(seq, " cr4\t: %016lx\n", read_cr4_safe()); | ||
| 296 | #ifdef CONFIG_X86_64 | ||
| 297 | seq_printf(seq, " cr8\t: %016lx\n", read_cr8()); | ||
| 298 | #endif | ||
| 299 | } | ||
| 300 | |||
| 301 | static void print_desc_ptr(char *str, struct seq_file *seq, struct desc_ptr dt) | ||
| 302 | { | ||
| 303 | seq_printf(seq, " %s\t: %016llx\n", str, (u64)(dt.address | dt.size)); | ||
| 304 | } | ||
| 305 | |||
| 306 | static void print_dt(void *seq) | ||
| 307 | { | ||
| 308 | struct desc_ptr dt; | ||
| 309 | unsigned long ldt; | ||
| 310 | |||
| 311 | /* IDT */ | ||
| 312 | store_idt((struct desc_ptr *)&dt); | ||
| 313 | print_desc_ptr("IDT", seq, dt); | ||
| 314 | |||
| 315 | /* GDT */ | ||
| 316 | store_gdt((struct desc_ptr *)&dt); | ||
| 317 | print_desc_ptr("GDT", seq, dt); | ||
| 318 | |||
| 319 | /* LDT */ | ||
| 320 | store_ldt(ldt); | ||
| 321 | seq_printf(seq, " LDT\t: %016lx\n", ldt); | ||
| 322 | |||
| 323 | /* TR */ | ||
| 324 | store_tr(ldt); | ||
| 325 | seq_printf(seq, " TR\t: %016lx\n", ldt); | ||
| 326 | } | ||
| 327 | |||
| 328 | static void print_dr(void *arg) | ||
| 329 | { | ||
| 330 | struct seq_file *seq = arg; | ||
| 331 | unsigned long dr; | ||
| 332 | int i; | ||
| 333 | |||
| 334 | for (i = 0; i < 8; i++) { | ||
| 335 | /* Ignore db4, db5 */ | ||
| 336 | if ((i == 4) || (i == 5)) | ||
| 337 | continue; | ||
| 338 | get_debugreg(dr, i); | ||
| 339 | seq_printf(seq, " dr%d\t: %016lx\n", i, dr); | ||
| 340 | } | ||
| 341 | |||
| 342 | seq_printf(seq, "\n MSR\t:\n"); | ||
| 343 | } | ||
| 344 | |||
| 345 | static void print_apic(void *arg) | ||
| 346 | { | ||
| 347 | struct seq_file *seq = arg; | ||
| 348 | |||
| 349 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 350 | seq_printf(seq, " LAPIC\t:\n"); | ||
| 351 | seq_printf(seq, " ID\t\t: %08x\n", apic_read(APIC_ID) >> 24); | ||
| 352 | seq_printf(seq, " LVR\t\t: %08x\n", apic_read(APIC_LVR)); | ||
| 353 | seq_printf(seq, " TASKPRI\t: %08x\n", apic_read(APIC_TASKPRI)); | ||
| 354 | seq_printf(seq, " ARBPRI\t\t: %08x\n", apic_read(APIC_ARBPRI)); | ||
| 355 | seq_printf(seq, " PROCPRI\t: %08x\n", apic_read(APIC_PROCPRI)); | ||
| 356 | seq_printf(seq, " LDR\t\t: %08x\n", apic_read(APIC_LDR)); | ||
| 357 | seq_printf(seq, " DFR\t\t: %08x\n", apic_read(APIC_DFR)); | ||
| 358 | seq_printf(seq, " SPIV\t\t: %08x\n", apic_read(APIC_SPIV)); | ||
| 359 | seq_printf(seq, " ISR\t\t: %08x\n", apic_read(APIC_ISR)); | ||
| 360 | seq_printf(seq, " ESR\t\t: %08x\n", apic_read(APIC_ESR)); | ||
| 361 | seq_printf(seq, " ICR\t\t: %08x\n", apic_read(APIC_ICR)); | ||
| 362 | seq_printf(seq, " ICR2\t\t: %08x\n", apic_read(APIC_ICR2)); | ||
| 363 | seq_printf(seq, " LVTT\t\t: %08x\n", apic_read(APIC_LVTT)); | ||
| 364 | seq_printf(seq, " LVTTHMR\t: %08x\n", apic_read(APIC_LVTTHMR)); | ||
| 365 | seq_printf(seq, " LVTPC\t\t: %08x\n", apic_read(APIC_LVTPC)); | ||
| 366 | seq_printf(seq, " LVT0\t\t: %08x\n", apic_read(APIC_LVT0)); | ||
| 367 | seq_printf(seq, " LVT1\t\t: %08x\n", apic_read(APIC_LVT1)); | ||
| 368 | seq_printf(seq, " LVTERR\t\t: %08x\n", apic_read(APIC_LVTERR)); | ||
| 369 | seq_printf(seq, " TMICT\t\t: %08x\n", apic_read(APIC_TMICT)); | ||
| 370 | seq_printf(seq, " TMCCT\t\t: %08x\n", apic_read(APIC_TMCCT)); | ||
| 371 | seq_printf(seq, " TDCR\t\t: %08x\n", apic_read(APIC_TDCR)); | ||
| 372 | if (boot_cpu_has(X86_FEATURE_EXTAPIC)) { | ||
| 373 | unsigned int i, v, maxeilvt; | ||
| 374 | |||
| 375 | v = apic_read(APIC_EFEAT); | ||
| 376 | maxeilvt = (v >> 16) & 0xff; | ||
| 377 | seq_printf(seq, " EFEAT\t\t: %08x\n", v); | ||
| 378 | seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL)); | ||
| 379 | |||
| 380 | for (i = 0; i < maxeilvt; i++) { | ||
| 381 | v = apic_read(APIC_EILVTn(i)); | ||
| 382 | seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
| 386 | seq_printf(seq, "\n MSR\t:\n"); | ||
| 387 | } | ||
| 388 | |||
| 389 | static int cpu_seq_show(struct seq_file *seq, void *v) | ||
| 390 | { | ||
| 391 | struct cpu_private *priv = seq->private; | ||
| 392 | |||
| 393 | if (priv == NULL) | ||
| 394 | return -EINVAL; | ||
| 395 | |||
| 396 | switch (cpu_base[priv->type].flag) { | ||
| 397 | case CPU_TSS: | ||
| 398 | smp_call_function_single(priv->cpu, print_tss, seq, 1); | ||
| 399 | break; | ||
| 400 | case CPU_CR: | ||
| 401 | smp_call_function_single(priv->cpu, print_cr, seq, 1); | ||
| 402 | break; | ||
| 403 | case CPU_DT: | ||
| 404 | smp_call_function_single(priv->cpu, print_dt, seq, 1); | ||
| 405 | break; | ||
| 406 | case CPU_DEBUG: | ||
| 407 | if (priv->file == CPU_INDEX_BIT) | ||
| 408 | smp_call_function_single(priv->cpu, print_dr, seq, 1); | ||
| 409 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
| 410 | break; | ||
| 411 | case CPU_APIC: | ||
| 412 | if (priv->file == CPU_INDEX_BIT) | ||
| 413 | smp_call_function_single(priv->cpu, print_apic, seq, 1); | ||
| 414 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
| 415 | break; | ||
| 416 | |||
| 417 | default: | ||
| 418 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
| 419 | break; | ||
| 420 | } | ||
| 421 | seq_printf(seq, "\n"); | ||
| 422 | |||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static void *cpu_seq_start(struct seq_file *seq, loff_t *pos) | ||
| 427 | { | ||
| 428 | if (*pos == 0) /* One time is enough ;-) */ | ||
| 429 | return seq; | ||
| 430 | |||
| 431 | return NULL; | ||
| 432 | } | ||
| 433 | |||
| 434 | static void *cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
| 435 | { | ||
| 436 | (*pos)++; | ||
| 437 | |||
| 438 | return cpu_seq_start(seq, pos); | ||
| 439 | } | ||
| 440 | |||
| 441 | static void cpu_seq_stop(struct seq_file *seq, void *v) | ||
| 442 | { | ||
| 443 | } | ||
| 444 | |||
| 445 | static const struct seq_operations cpu_seq_ops = { | ||
| 446 | .start = cpu_seq_start, | ||
| 447 | .next = cpu_seq_next, | ||
| 448 | .stop = cpu_seq_stop, | ||
| 449 | .show = cpu_seq_show, | ||
| 450 | }; | ||
| 451 | |||
| 452 | static int cpu_seq_open(struct inode *inode, struct file *file) | ||
| 453 | { | ||
| 454 | struct cpu_private *priv = inode->i_private; | ||
| 455 | struct seq_file *seq; | ||
| 456 | int err; | ||
| 457 | |||
| 458 | err = seq_open(file, &cpu_seq_ops); | ||
| 459 | if (!err) { | ||
| 460 | seq = file->private_data; | ||
| 461 | seq->private = priv; | ||
| 462 | } | ||
| 463 | |||
| 464 | return err; | ||
| 465 | } | ||
| 466 | |||
| 467 | static int write_msr(struct cpu_private *priv, u64 val) | ||
| 468 | { | ||
| 469 | u32 low, high; | ||
| 470 | |||
| 471 | high = (val >> 32) & 0xffffffff; | ||
| 472 | low = val & 0xffffffff; | ||
| 473 | |||
| 474 | if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high)) | ||
| 475 | return 0; | ||
| 476 | |||
| 477 | return -EPERM; | ||
| 478 | } | ||
| 479 | |||
| 480 | static int write_cpu_register(struct cpu_private *priv, const char *buf) | ||
| 481 | { | ||
| 482 | int ret = -EPERM; | ||
| 483 | u64 val; | ||
| 484 | |||
| 485 | ret = strict_strtoull(buf, 0, &val); | ||
| 486 | if (ret < 0) | ||
| 487 | return ret; | ||
| 488 | |||
| 489 | /* Supporting only MSRs */ | ||
| 490 | if (priv->type < CPU_TSS_BIT) | ||
| 491 | return write_msr(priv, val); | ||
| 492 | |||
| 493 | return ret; | ||
| 494 | } | ||
| 495 | |||
| 496 | static ssize_t cpu_write(struct file *file, const char __user *ubuf, | ||
| 497 | size_t count, loff_t *off) | ||
| 498 | { | ||
| 499 | struct seq_file *seq = file->private_data; | ||
| 500 | struct cpu_private *priv = seq->private; | ||
| 501 | char buf[19]; | ||
| 502 | |||
| 503 | if ((priv == NULL) || (count >= sizeof(buf))) | ||
| 504 | return -EINVAL; | ||
| 505 | |||
| 506 | if (copy_from_user(&buf, ubuf, count)) | ||
| 507 | return -EFAULT; | ||
| 508 | |||
| 509 | buf[count] = 0; | ||
| 510 | |||
| 511 | if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write)) | ||
| 512 | if (!write_cpu_register(priv, buf)) | ||
| 513 | return count; | ||
| 514 | |||
| 515 | return -EACCES; | ||
| 516 | } | ||
| 517 | |||
| 518 | static const struct file_operations cpu_fops = { | ||
| 519 | .owner = THIS_MODULE, | ||
| 520 | .open = cpu_seq_open, | ||
| 521 | .read = seq_read, | ||
| 522 | .write = cpu_write, | ||
| 523 | .llseek = seq_lseek, | ||
| 524 | .release = seq_release, | ||
| 525 | }; | ||
| 526 | |||
| 527 | static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, | ||
| 528 | unsigned file, struct dentry *dentry) | ||
| 529 | { | ||
| 530 | struct cpu_private *priv = NULL; | ||
| 531 | |||
| 532 | /* Already intialized */ | ||
| 533 | if (file == CPU_INDEX_BIT) | ||
| 534 | if (per_cpu(cpud_arr[type].init, cpu)) | ||
| 535 | return 0; | ||
| 536 | |||
| 537 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 538 | if (priv == NULL) | ||
| 539 | return -ENOMEM; | ||
| 540 | |||
| 541 | priv->cpu = cpu; | ||
| 542 | priv->type = type; | ||
| 543 | priv->reg = reg; | ||
| 544 | priv->file = file; | ||
| 545 | mutex_lock(&cpu_debug_lock); | ||
| 546 | per_cpu(cpud_priv_arr[type], cpu) = priv; | ||
| 547 | per_cpu(cpud_priv_count, cpu)++; | ||
| 548 | mutex_unlock(&cpu_debug_lock); | ||
| 549 | |||
| 550 | if (file) | ||
| 551 | debugfs_create_file(cpu_file[file].name, S_IRUGO, | ||
| 552 | dentry, (void *)priv, &cpu_fops); | ||
| 553 | else { | ||
| 554 | debugfs_create_file(cpu_base[type].name, S_IRUGO, | ||
| 555 | per_cpu(cpud_arr[type].dentry, cpu), | ||
| 556 | (void *)priv, &cpu_fops); | ||
| 557 | mutex_lock(&cpu_debug_lock); | ||
| 558 | per_cpu(cpud_arr[type].init, cpu) = 1; | ||
| 559 | mutex_unlock(&cpu_debug_lock); | ||
| 560 | } | ||
| 561 | |||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | static int cpu_init_regfiles(unsigned cpu, unsigned int type, unsigned reg, | ||
| 566 | struct dentry *dentry) | ||
| 567 | { | ||
| 568 | unsigned file; | ||
| 569 | int err = 0; | ||
| 570 | |||
| 571 | for (file = 0; file < ARRAY_SIZE(cpu_file); file++) { | ||
| 572 | err = cpu_create_file(cpu, type, reg, file, dentry); | ||
| 573 | if (err) | ||
| 574 | return err; | ||
| 575 | } | ||
| 576 | |||
| 577 | return err; | ||
| 578 | } | ||
| 579 | |||
| 580 | static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry) | ||
| 581 | { | ||
| 582 | struct dentry *cpu_dentry = NULL; | ||
| 583 | unsigned reg, reg_min, reg_max; | ||
| 584 | int i, err = 0; | ||
| 585 | char reg_dir[12]; | ||
| 586 | u32 low, high; | ||
| 587 | |||
| 588 | for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { | ||
| 589 | if (!get_cpu_range(cpu, ®_min, ®_max, i, | ||
| 590 | cpu_base[type].flag)) | ||
| 591 | continue; | ||
| 592 | |||
| 593 | for (reg = reg_min; reg <= reg_max; reg++) { | ||
| 594 | if (rdmsr_safe_on_cpu(cpu, reg, &low, &high)) | ||
| 595 | continue; | ||
| 596 | |||
| 597 | sprintf(reg_dir, "0x%x", reg); | ||
| 598 | cpu_dentry = debugfs_create_dir(reg_dir, dentry); | ||
| 599 | err = cpu_init_regfiles(cpu, type, reg, cpu_dentry); | ||
| 600 | if (err) | ||
| 601 | return err; | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | return err; | ||
| 606 | } | ||
| 607 | |||
| 608 | static int cpu_init_allreg(unsigned cpu, struct dentry *dentry) | ||
| 609 | { | ||
| 610 | struct dentry *cpu_dentry = NULL; | ||
| 611 | unsigned type; | ||
| 612 | int err = 0; | ||
| 613 | |||
| 614 | for (type = 0; type < ARRAY_SIZE(cpu_base) - 1; type++) { | ||
| 615 | if (!is_typeflag_valid(cpu, cpu_base[type].flag)) | ||
| 616 | continue; | ||
| 617 | cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry); | ||
| 618 | per_cpu(cpud_arr[type].dentry, cpu) = cpu_dentry; | ||
| 619 | |||
| 620 | if (type < CPU_TSS_BIT) | ||
| 621 | err = cpu_init_msr(cpu, type, cpu_dentry); | ||
| 622 | else | ||
| 623 | err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT, | ||
| 624 | cpu_dentry); | ||
| 625 | if (err) | ||
| 626 | return err; | ||
| 627 | } | ||
| 628 | |||
| 629 | return err; | ||
| 630 | } | ||
| 631 | |||
| 632 | static int cpu_init_cpu(void) | ||
| 633 | { | ||
| 634 | struct dentry *cpu_dentry = NULL; | ||
| 635 | struct cpuinfo_x86 *cpui; | ||
| 636 | char cpu_dir[12]; | ||
| 637 | unsigned cpu; | ||
| 638 | int err = 0; | ||
| 639 | |||
| 640 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | ||
| 641 | cpui = &cpu_data(cpu); | ||
| 642 | if (!cpu_has(cpui, X86_FEATURE_MSR)) | ||
| 643 | continue; | ||
| 644 | |||
| 645 | sprintf(cpu_dir, "cpu%d", cpu); | ||
| 646 | cpu_dentry = debugfs_create_dir(cpu_dir, cpu_debugfs_dir); | ||
| 647 | err = cpu_init_allreg(cpu, cpu_dentry); | ||
| 648 | |||
| 649 | pr_info("cpu%d(%d) debug files %d\n", | ||
| 650 | cpu, nr_cpu_ids, per_cpu(cpud_priv_count, cpu)); | ||
| 651 | if (per_cpu(cpud_priv_count, cpu) > MAX_CPU_FILES) { | ||
| 652 | pr_err("Register files count %d exceeds limit %d\n", | ||
| 653 | per_cpu(cpud_priv_count, cpu), MAX_CPU_FILES); | ||
| 654 | per_cpu(cpud_priv_count, cpu) = MAX_CPU_FILES; | ||
| 655 | err = -ENFILE; | ||
| 656 | } | ||
| 657 | if (err) | ||
| 658 | return err; | ||
| 659 | } | ||
| 660 | |||
| 661 | return err; | ||
| 662 | } | ||
| 663 | |||
| 664 | static int __init cpu_debug_init(void) | ||
| 665 | { | ||
| 666 | cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir); | ||
| 667 | |||
| 668 | return cpu_init_cpu(); | ||
| 669 | } | ||
| 670 | |||
| 671 | static void __exit cpu_debug_exit(void) | ||
| 672 | { | ||
| 673 | int i, cpu; | ||
| 674 | |||
| 675 | if (cpu_debugfs_dir) | ||
| 676 | debugfs_remove_recursive(cpu_debugfs_dir); | ||
| 677 | |||
| 678 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) | ||
| 679 | for (i = 0; i < per_cpu(cpud_priv_count, cpu); i++) | ||
| 680 | kfree(per_cpu(cpud_priv_arr[i], cpu)); | ||
| 681 | } | ||
| 682 | |||
| 683 | module_init(cpu_debug_init); | ||
| 684 | module_exit(cpu_debug_exit); | ||
| 685 | |||
| 686 | MODULE_AUTHOR("Jaswinder Singh Rajput"); | ||
| 687 | MODULE_DESCRIPTION("CPU Debug module"); | ||
| 688 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index f125e5c551c0..6e44519960c8 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
| @@ -1356,6 +1356,7 @@ static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol) | |||
| 1356 | 1356 | ||
| 1357 | kfree(data->powernow_table); | 1357 | kfree(data->powernow_table); |
| 1358 | kfree(data); | 1358 | kfree(data); |
| 1359 | per_cpu(powernow_data, pol->cpu) = NULL; | ||
| 1359 | 1360 | ||
| 1360 | return 0; | 1361 | return 0; |
| 1361 | } | 1362 | } |
| @@ -1375,7 +1376,7 @@ static unsigned int powernowk8_get(unsigned int cpu) | |||
| 1375 | int err; | 1376 | int err; |
| 1376 | 1377 | ||
| 1377 | if (!data) | 1378 | if (!data) |
| 1378 | return -EINVAL; | 1379 | return 0; |
| 1379 | 1380 | ||
| 1380 | smp_call_function_single(cpu, query_values_on_cpu, &err, true); | 1381 | smp_call_function_single(cpu, query_values_on_cpu, &err, true); |
| 1381 | if (err) | 1382 | if (err) |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index c223b7e895d9..8c1c07073ccc 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -1343,6 +1343,13 @@ intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) | |||
| 1343 | bits |= 0x2; | 1343 | bits |= 0x2; |
| 1344 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | 1344 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) |
| 1345 | bits |= 0x1; | 1345 | bits |= 0x1; |
| 1346 | |||
| 1347 | /* | ||
| 1348 | * ANY bit is supported in v3 and up | ||
| 1349 | */ | ||
| 1350 | if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY) | ||
| 1351 | bits |= 0x4; | ||
| 1352 | |||
| 1346 | bits <<= (idx * 4); | 1353 | bits <<= (idx * 4); |
| 1347 | mask = 0xfULL << (idx * 4); | 1354 | mask = 0xfULL << (idx * 4); |
| 1348 | 1355 | ||
| @@ -2347,7 +2354,7 @@ perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
| 2347 | callchain_store(entry, PERF_CONTEXT_KERNEL); | 2354 | callchain_store(entry, PERF_CONTEXT_KERNEL); |
| 2348 | callchain_store(entry, regs->ip); | 2355 | callchain_store(entry, regs->ip); |
| 2349 | 2356 | ||
| 2350 | dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); | 2357 | dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry); |
| 2351 | } | 2358 | } |
| 2352 | 2359 | ||
| 2353 | /* | 2360 | /* |
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index cb27fd6136c9..83e5e628de73 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c | |||
| @@ -229,7 +229,7 @@ static void __exit cpuid_exit(void) | |||
| 229 | for_each_online_cpu(cpu) | 229 | for_each_online_cpu(cpu) |
| 230 | cpuid_device_destroy(cpu); | 230 | cpuid_device_destroy(cpu); |
| 231 | class_destroy(cpuid_class); | 231 | class_destroy(cpuid_class); |
| 232 | unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); | 232 | __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); |
| 233 | unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); | 233 | unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); |
| 234 | } | 234 | } |
| 235 | 235 | ||
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index c56bc2873030..6d817554780a 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
| @@ -123,13 +123,15 @@ print_context_stack_bp(struct thread_info *tinfo, | |||
| 123 | while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) { | 123 | while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) { |
| 124 | unsigned long addr = *ret_addr; | 124 | unsigned long addr = *ret_addr; |
| 125 | 125 | ||
| 126 | if (__kernel_text_address(addr)) { | 126 | if (!__kernel_text_address(addr)) |
| 127 | ops->address(data, addr, 1); | 127 | break; |
| 128 | frame = frame->next_frame; | 128 | |
| 129 | ret_addr = &frame->return_address; | 129 | ops->address(data, addr, 1); |
| 130 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); | 130 | frame = frame->next_frame; |
| 131 | } | 131 | ret_addr = &frame->return_address; |
| 132 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); | ||
| 132 | } | 133 | } |
| 134 | |||
| 133 | return (unsigned long)frame; | 135 | return (unsigned long)frame; |
| 134 | } | 136 | } |
| 135 | EXPORT_SYMBOL_GPL(print_context_stack_bp); | 137 | EXPORT_SYMBOL_GPL(print_context_stack_bp); |
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 05ed7ab2ca48..a1a7876cadcb 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
| @@ -733,13 +733,13 @@ struct early_res { | |||
| 733 | }; | 733 | }; |
| 734 | static struct early_res early_res[MAX_EARLY_RES] __initdata = { | 734 | static struct early_res early_res[MAX_EARLY_RES] __initdata = { |
| 735 | { 0, PAGE_SIZE, "BIOS data page", 1 }, /* BIOS data page */ | 735 | { 0, PAGE_SIZE, "BIOS data page", 1 }, /* BIOS data page */ |
| 736 | #ifdef CONFIG_X86_32 | 736 | #if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE) |
| 737 | /* | 737 | /* |
| 738 | * But first pinch a few for the stack/trampoline stuff | 738 | * But first pinch a few for the stack/trampoline stuff |
| 739 | * FIXME: Don't need the extra page at 4K, but need to fix | 739 | * FIXME: Don't need the extra page at 4K, but need to fix |
| 740 | * trampoline before removing it. (see the GDT stuff) | 740 | * trampoline before removing it. (see the GDT stuff) |
| 741 | */ | 741 | */ |
| 742 | { PAGE_SIZE, PAGE_SIZE, "EX TRAMPOLINE", 1 }, | 742 | { PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE", 1 }, |
| 743 | #endif | 743 | #endif |
| 744 | 744 | ||
| 745 | {} | 745 | {} |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ba6e65884603..ad80a1c718c6 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | */ | 34 | */ |
| 35 | unsigned long hpet_address; | 35 | unsigned long hpet_address; |
| 36 | u8 hpet_blockid; /* OS timer block num */ | 36 | u8 hpet_blockid; /* OS timer block num */ |
| 37 | u8 hpet_msi_disable; | ||
| 38 | |||
| 37 | #ifdef CONFIG_PCI_MSI | 39 | #ifdef CONFIG_PCI_MSI |
| 38 | static unsigned long hpet_num_timers; | 40 | static unsigned long hpet_num_timers; |
| 39 | #endif | 41 | #endif |
| @@ -596,6 +598,9 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) | |||
| 596 | unsigned int num_timers_used = 0; | 598 | unsigned int num_timers_used = 0; |
| 597 | int i; | 599 | int i; |
| 598 | 600 | ||
| 601 | if (hpet_msi_disable) | ||
| 602 | return; | ||
| 603 | |||
| 599 | if (boot_cpu_has(X86_FEATURE_ARAT)) | 604 | if (boot_cpu_has(X86_FEATURE_ARAT)) |
| 600 | return; | 605 | return; |
| 601 | id = hpet_readl(HPET_ID); | 606 | id = hpet_readl(HPET_ID); |
| @@ -928,6 +933,9 @@ static __init int hpet_late_init(void) | |||
| 928 | hpet_reserve_platform_timers(hpet_readl(HPET_ID)); | 933 | hpet_reserve_platform_timers(hpet_readl(HPET_ID)); |
| 929 | hpet_print_config(); | 934 | hpet_print_config(); |
| 930 | 935 | ||
| 936 | if (hpet_msi_disable) | ||
| 937 | return 0; | ||
| 938 | |||
| 931 | if (boot_cpu_has(X86_FEATURE_ARAT)) | 939 | if (boot_cpu_has(X86_FEATURE_ARAT)) |
| 932 | return 0; | 940 | return 0; |
| 933 | 941 | ||
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index 05d5fec64a94..bb6006e3e295 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c | |||
| @@ -212,25 +212,6 @@ static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len) | |||
| 212 | return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); | 212 | return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | /* | ||
| 216 | * Store a breakpoint's encoded address, length, and type. | ||
| 217 | */ | ||
| 218 | static int arch_store_info(struct perf_event *bp) | ||
| 219 | { | ||
| 220 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
| 221 | /* | ||
| 222 | * For kernel-addresses, either the address or symbol name can be | ||
| 223 | * specified. | ||
| 224 | */ | ||
| 225 | if (info->name) | ||
| 226 | info->address = (unsigned long) | ||
| 227 | kallsyms_lookup_name(info->name); | ||
| 228 | if (info->address) | ||
| 229 | return 0; | ||
| 230 | |||
| 231 | return -EINVAL; | ||
| 232 | } | ||
| 233 | |||
| 234 | int arch_bp_generic_fields(int x86_len, int x86_type, | 215 | int arch_bp_generic_fields(int x86_len, int x86_type, |
| 235 | int *gen_len, int *gen_type) | 216 | int *gen_len, int *gen_type) |
| 236 | { | 217 | { |
| @@ -362,10 +343,13 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp, | |||
| 362 | return ret; | 343 | return ret; |
| 363 | } | 344 | } |
| 364 | 345 | ||
| 365 | ret = arch_store_info(bp); | 346 | /* |
| 366 | 347 | * For kernel-addresses, either the address or symbol name can be | |
| 367 | if (ret < 0) | 348 | * specified. |
| 368 | return ret; | 349 | */ |
| 350 | if (info->name) | ||
| 351 | info->address = (unsigned long) | ||
| 352 | kallsyms_lookup_name(info->name); | ||
| 369 | /* | 353 | /* |
| 370 | * Check that the low-order bits of the address are appropriate | 354 | * Check that the low-order bits of the address are appropriate |
| 371 | * for the alignment implied by len. | 355 | * for the alignment implied by len. |
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index dd74fe7273b1..bfba6019d762 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
| 43 | #include <linux/smp.h> | 43 | #include <linux/smp.h> |
| 44 | #include <linux/nmi.h> | 44 | #include <linux/nmi.h> |
| 45 | #include <linux/hw_breakpoint.h> | ||
| 45 | 46 | ||
| 46 | #include <asm/debugreg.h> | 47 | #include <asm/debugreg.h> |
| 47 | #include <asm/apicdef.h> | 48 | #include <asm/apicdef.h> |
| @@ -204,40 +205,81 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
| 204 | 205 | ||
| 205 | static struct hw_breakpoint { | 206 | static struct hw_breakpoint { |
| 206 | unsigned enabled; | 207 | unsigned enabled; |
| 207 | unsigned type; | ||
| 208 | unsigned len; | ||
| 209 | unsigned long addr; | 208 | unsigned long addr; |
| 209 | int len; | ||
| 210 | int type; | ||
| 211 | struct perf_event **pev; | ||
| 210 | } breakinfo[4]; | 212 | } breakinfo[4]; |
| 211 | 213 | ||
| 212 | static void kgdb_correct_hw_break(void) | 214 | static void kgdb_correct_hw_break(void) |
| 213 | { | 215 | { |
| 214 | unsigned long dr7; | ||
| 215 | int correctit = 0; | ||
| 216 | int breakbit; | ||
| 217 | int breakno; | 216 | int breakno; |
| 218 | 217 | ||
| 219 | get_debugreg(dr7, 7); | ||
| 220 | for (breakno = 0; breakno < 4; breakno++) { | 218 | for (breakno = 0; breakno < 4; breakno++) { |
| 221 | breakbit = 2 << (breakno << 1); | 219 | struct perf_event *bp; |
| 222 | if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { | 220 | struct arch_hw_breakpoint *info; |
| 223 | correctit = 1; | 221 | int val; |
| 224 | dr7 |= breakbit; | 222 | int cpu = raw_smp_processor_id(); |
| 225 | dr7 &= ~(0xf0000 << (breakno << 2)); | 223 | if (!breakinfo[breakno].enabled) |
| 226 | dr7 |= ((breakinfo[breakno].len << 2) | | 224 | continue; |
| 227 | breakinfo[breakno].type) << | 225 | bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu); |
| 228 | ((breakno << 2) + 16); | 226 | info = counter_arch_bp(bp); |
| 229 | set_debugreg(breakinfo[breakno].addr, breakno); | 227 | if (bp->attr.disabled != 1) |
| 230 | 228 | continue; | |
| 231 | } else { | 229 | bp->attr.bp_addr = breakinfo[breakno].addr; |
| 232 | if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { | 230 | bp->attr.bp_len = breakinfo[breakno].len; |
| 233 | correctit = 1; | 231 | bp->attr.bp_type = breakinfo[breakno].type; |
| 234 | dr7 &= ~breakbit; | 232 | info->address = breakinfo[breakno].addr; |
| 235 | dr7 &= ~(0xf0000 << (breakno << 2)); | 233 | info->len = breakinfo[breakno].len; |
| 236 | } | 234 | info->type = breakinfo[breakno].type; |
| 237 | } | 235 | val = arch_install_hw_breakpoint(bp); |
| 236 | if (!val) | ||
| 237 | bp->attr.disabled = 0; | ||
| 238 | } | ||
| 239 | hw_breakpoint_restore(); | ||
| 240 | } | ||
| 241 | |||
| 242 | static int hw_break_reserve_slot(int breakno) | ||
| 243 | { | ||
| 244 | int cpu; | ||
| 245 | int cnt = 0; | ||
| 246 | struct perf_event **pevent; | ||
| 247 | |||
| 248 | for_each_online_cpu(cpu) { | ||
| 249 | cnt++; | ||
| 250 | pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); | ||
| 251 | if (dbg_reserve_bp_slot(*pevent)) | ||
| 252 | goto fail; | ||
| 253 | } | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | |||
| 257 | fail: | ||
| 258 | for_each_online_cpu(cpu) { | ||
| 259 | cnt--; | ||
| 260 | if (!cnt) | ||
| 261 | break; | ||
| 262 | pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); | ||
| 263 | dbg_release_bp_slot(*pevent); | ||
| 238 | } | 264 | } |
| 239 | if (correctit) | 265 | return -1; |
| 240 | set_debugreg(dr7, 7); | 266 | } |
| 267 | |||
| 268 | static int hw_break_release_slot(int breakno) | ||
| 269 | { | ||
| 270 | struct perf_event **pevent; | ||
| 271 | int cpu; | ||
| 272 | |||
| 273 | for_each_online_cpu(cpu) { | ||
| 274 | pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); | ||
| 275 | if (dbg_release_bp_slot(*pevent)) | ||
| 276 | /* | ||
| 277 | * The debugger is responisble for handing the retry on | ||
| 278 | * remove failure. | ||
| 279 | */ | ||
| 280 | return -1; | ||
| 281 | } | ||
| 282 | return 0; | ||
| 241 | } | 283 | } |
| 242 | 284 | ||
| 243 | static int | 285 | static int |
| @@ -251,6 +293,10 @@ kgdb_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) | |||
| 251 | if (i == 4) | 293 | if (i == 4) |
| 252 | return -1; | 294 | return -1; |
| 253 | 295 | ||
| 296 | if (hw_break_release_slot(i)) { | ||
| 297 | printk(KERN_ERR "Cannot remove hw breakpoint at %lx\n", addr); | ||
| 298 | return -1; | ||
| 299 | } | ||
| 254 | breakinfo[i].enabled = 0; | 300 | breakinfo[i].enabled = 0; |
| 255 | 301 | ||
| 256 | return 0; | 302 | return 0; |
| @@ -259,15 +305,23 @@ kgdb_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) | |||
| 259 | static void kgdb_remove_all_hw_break(void) | 305 | static void kgdb_remove_all_hw_break(void) |
| 260 | { | 306 | { |
| 261 | int i; | 307 | int i; |
| 308 | int cpu = raw_smp_processor_id(); | ||
| 309 | struct perf_event *bp; | ||
| 262 | 310 | ||
| 263 | for (i = 0; i < 4; i++) | 311 | for (i = 0; i < 4; i++) { |
| 264 | memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint)); | 312 | if (!breakinfo[i].enabled) |
| 313 | continue; | ||
| 314 | bp = *per_cpu_ptr(breakinfo[i].pev, cpu); | ||
| 315 | if (bp->attr.disabled == 1) | ||
| 316 | continue; | ||
| 317 | arch_uninstall_hw_breakpoint(bp); | ||
| 318 | bp->attr.disabled = 1; | ||
| 319 | } | ||
| 265 | } | 320 | } |
| 266 | 321 | ||
| 267 | static int | 322 | static int |
| 268 | kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) | 323 | kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) |
| 269 | { | 324 | { |
| 270 | unsigned type; | ||
| 271 | int i; | 325 | int i; |
| 272 | 326 | ||
| 273 | for (i = 0; i < 4; i++) | 327 | for (i = 0; i < 4; i++) |
| @@ -278,27 +332,42 @@ kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) | |||
| 278 | 332 | ||
| 279 | switch (bptype) { | 333 | switch (bptype) { |
| 280 | case BP_HARDWARE_BREAKPOINT: | 334 | case BP_HARDWARE_BREAKPOINT: |
| 281 | type = 0; | 335 | len = 1; |
| 282 | len = 1; | 336 | breakinfo[i].type = X86_BREAKPOINT_EXECUTE; |
| 283 | break; | 337 | break; |
| 284 | case BP_WRITE_WATCHPOINT: | 338 | case BP_WRITE_WATCHPOINT: |
| 285 | type = 1; | 339 | breakinfo[i].type = X86_BREAKPOINT_WRITE; |
| 286 | break; | 340 | break; |
| 287 | case BP_ACCESS_WATCHPOINT: | 341 | case BP_ACCESS_WATCHPOINT: |
| 288 | type = 3; | 342 | breakinfo[i].type = X86_BREAKPOINT_RW; |
| 289 | break; | 343 | break; |
| 290 | default: | 344 | default: |
| 291 | return -1; | 345 | return -1; |
| 292 | } | 346 | } |
| 293 | 347 | switch (len) { | |
| 294 | if (len == 1 || len == 2 || len == 4) | 348 | case 1: |
| 295 | breakinfo[i].len = len - 1; | 349 | breakinfo[i].len = X86_BREAKPOINT_LEN_1; |
| 296 | else | 350 | break; |
| 351 | case 2: | ||
| 352 | breakinfo[i].len = X86_BREAKPOINT_LEN_2; | ||
| 353 | break; | ||
| 354 | case 4: | ||
| 355 | breakinfo[i].len = X86_BREAKPOINT_LEN_4; | ||
| 356 | break; | ||
| 357 | #ifdef CONFIG_X86_64 | ||
| 358 | case 8: | ||
| 359 | breakinfo[i].len = X86_BREAKPOINT_LEN_8; | ||
| 360 | break; | ||
| 361 | #endif | ||
| 362 | default: | ||
| 297 | return -1; | 363 | return -1; |
| 298 | 364 | } | |
| 299 | breakinfo[i].enabled = 1; | ||
| 300 | breakinfo[i].addr = addr; | 365 | breakinfo[i].addr = addr; |
| 301 | breakinfo[i].type = type; | 366 | if (hw_break_reserve_slot(i)) { |
| 367 | breakinfo[i].addr = 0; | ||
| 368 | return -1; | ||
| 369 | } | ||
| 370 | breakinfo[i].enabled = 1; | ||
| 302 | 371 | ||
| 303 | return 0; | 372 | return 0; |
| 304 | } | 373 | } |
| @@ -313,8 +382,21 @@ kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) | |||
| 313 | */ | 382 | */ |
| 314 | void kgdb_disable_hw_debug(struct pt_regs *regs) | 383 | void kgdb_disable_hw_debug(struct pt_regs *regs) |
| 315 | { | 384 | { |
| 385 | int i; | ||
| 386 | int cpu = raw_smp_processor_id(); | ||
| 387 | struct perf_event *bp; | ||
| 388 | |||
| 316 | /* Disable hardware debugging while we are in kgdb: */ | 389 | /* Disable hardware debugging while we are in kgdb: */ |
| 317 | set_debugreg(0UL, 7); | 390 | set_debugreg(0UL, 7); |
| 391 | for (i = 0; i < 4; i++) { | ||
| 392 | if (!breakinfo[i].enabled) | ||
| 393 | continue; | ||
| 394 | bp = *per_cpu_ptr(breakinfo[i].pev, cpu); | ||
| 395 | if (bp->attr.disabled == 1) | ||
| 396 | continue; | ||
| 397 | arch_uninstall_hw_breakpoint(bp); | ||
| 398 | bp->attr.disabled = 1; | ||
| 399 | } | ||
| 318 | } | 400 | } |
| 319 | 401 | ||
| 320 | /** | 402 | /** |
| @@ -378,7 +460,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | |||
| 378 | struct pt_regs *linux_regs) | 460 | struct pt_regs *linux_regs) |
| 379 | { | 461 | { |
| 380 | unsigned long addr; | 462 | unsigned long addr; |
| 381 | unsigned long dr6; | ||
| 382 | char *ptr; | 463 | char *ptr; |
| 383 | int newPC; | 464 | int newPC; |
| 384 | 465 | ||
| @@ -404,20 +485,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | |||
| 404 | raw_smp_processor_id()); | 485 | raw_smp_processor_id()); |
| 405 | } | 486 | } |
| 406 | 487 | ||
| 407 | get_debugreg(dr6, 6); | ||
| 408 | if (!(dr6 & 0x4000)) { | ||
| 409 | int breakno; | ||
| 410 | |||
| 411 | for (breakno = 0; breakno < 4; breakno++) { | ||
| 412 | if (dr6 & (1 << breakno) && | ||
| 413 | breakinfo[breakno].type == 0) { | ||
| 414 | /* Set restore flag: */ | ||
| 415 | linux_regs->flags |= X86_EFLAGS_RF; | ||
| 416 | break; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | } | ||
| 420 | set_debugreg(0UL, 6); | ||
| 421 | kgdb_correct_hw_break(); | 488 | kgdb_correct_hw_break(); |
| 422 | 489 | ||
| 423 | return 0; | 490 | return 0; |
| @@ -485,8 +552,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) | |||
| 485 | break; | 552 | break; |
| 486 | 553 | ||
| 487 | case DIE_DEBUG: | 554 | case DIE_DEBUG: |
| 488 | if (atomic_read(&kgdb_cpu_doing_single_step) == | 555 | if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { |
| 489 | raw_smp_processor_id()) { | ||
| 490 | if (user_mode(regs)) | 556 | if (user_mode(regs)) |
| 491 | return single_step_cont(regs, args); | 557 | return single_step_cont(regs, args); |
| 492 | break; | 558 | break; |
| @@ -539,7 +605,42 @@ static struct notifier_block kgdb_notifier = { | |||
| 539 | */ | 605 | */ |
| 540 | int kgdb_arch_init(void) | 606 | int kgdb_arch_init(void) |
| 541 | { | 607 | { |
| 542 | return register_die_notifier(&kgdb_notifier); | 608 | int i, cpu; |
| 609 | int ret; | ||
| 610 | struct perf_event_attr attr; | ||
| 611 | struct perf_event **pevent; | ||
| 612 | |||
| 613 | ret = register_die_notifier(&kgdb_notifier); | ||
| 614 | if (ret != 0) | ||
| 615 | return ret; | ||
| 616 | /* | ||
| 617 | * Pre-allocate the hw breakpoint structions in the non-atomic | ||
| 618 | * portion of kgdb because this operation requires mutexs to | ||
| 619 | * complete. | ||
| 620 | */ | ||
| 621 | attr.bp_addr = (unsigned long)kgdb_arch_init; | ||
| 622 | attr.type = PERF_TYPE_BREAKPOINT; | ||
| 623 | attr.bp_len = HW_BREAKPOINT_LEN_1; | ||
| 624 | attr.bp_type = HW_BREAKPOINT_W; | ||
| 625 | attr.disabled = 1; | ||
| 626 | for (i = 0; i < 4; i++) { | ||
| 627 | breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL); | ||
| 628 | if (IS_ERR(breakinfo[i].pev)) { | ||
| 629 | printk(KERN_ERR "kgdb: Could not allocate hw breakpoints\n"); | ||
| 630 | breakinfo[i].pev = NULL; | ||
| 631 | kgdb_arch_exit(); | ||
| 632 | return -1; | ||
| 633 | } | ||
| 634 | for_each_online_cpu(cpu) { | ||
| 635 | pevent = per_cpu_ptr(breakinfo[i].pev, cpu); | ||
| 636 | pevent[0]->hw.sample_period = 1; | ||
| 637 | if (pevent[0]->destroy != NULL) { | ||
| 638 | pevent[0]->destroy = NULL; | ||
| 639 | release_bp_slot(*pevent); | ||
| 640 | } | ||
| 641 | } | ||
| 642 | } | ||
| 643 | return ret; | ||
| 543 | } | 644 | } |
| 544 | 645 | ||
| 545 | /** | 646 | /** |
| @@ -550,6 +651,13 @@ int kgdb_arch_init(void) | |||
| 550 | */ | 651 | */ |
| 551 | void kgdb_arch_exit(void) | 652 | void kgdb_arch_exit(void) |
| 552 | { | 653 | { |
| 654 | int i; | ||
| 655 | for (i = 0; i < 4; i++) { | ||
| 656 | if (breakinfo[i].pev) { | ||
| 657 | unregister_wide_hw_breakpoint(breakinfo[i].pev); | ||
| 658 | breakinfo[i].pev = NULL; | ||
| 659 | } | ||
| 660 | } | ||
| 553 | unregister_die_notifier(&kgdb_notifier); | 661 | unregister_die_notifier(&kgdb_notifier); |
| 554 | } | 662 | } |
| 555 | 663 | ||
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 37542b67c57e..e1af7c055c7d 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
| @@ -36,9 +36,6 @@ MODULE_LICENSE("GPL v2"); | |||
| 36 | #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 | 36 | #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 |
| 37 | #define UCODE_UCODE_TYPE 0x00000001 | 37 | #define UCODE_UCODE_TYPE 0x00000001 |
| 38 | 38 | ||
| 39 | const struct firmware *firmware; | ||
| 40 | static int supported_cpu; | ||
| 41 | |||
| 42 | struct equiv_cpu_entry { | 39 | struct equiv_cpu_entry { |
| 43 | u32 installed_cpu; | 40 | u32 installed_cpu; |
| 44 | u32 fixed_errata_mask; | 41 | u32 fixed_errata_mask; |
| @@ -77,12 +74,15 @@ static struct equiv_cpu_entry *equiv_cpu_table; | |||
| 77 | 74 | ||
| 78 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | 75 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) |
| 79 | { | 76 | { |
| 77 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 80 | u32 dummy; | 78 | u32 dummy; |
| 81 | 79 | ||
| 82 | if (!supported_cpu) | ||
| 83 | return -1; | ||
| 84 | |||
| 85 | memset(csig, 0, sizeof(*csig)); | 80 | memset(csig, 0, sizeof(*csig)); |
| 81 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { | ||
| 82 | pr_warning("microcode: CPU%d: AMD CPU family 0x%x not " | ||
| 83 | "supported\n", cpu, c->x86); | ||
| 84 | return -1; | ||
| 85 | } | ||
| 86 | rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy); | 86 | rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy); |
| 87 | pr_info("CPU%d: patch_level=0x%x\n", cpu, csig->rev); | 87 | pr_info("CPU%d: patch_level=0x%x\n", cpu, csig->rev); |
| 88 | return 0; | 88 | return 0; |
| @@ -294,10 +294,14 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) | |||
| 294 | 294 | ||
| 295 | static enum ucode_state request_microcode_fw(int cpu, struct device *device) | 295 | static enum ucode_state request_microcode_fw(int cpu, struct device *device) |
| 296 | { | 296 | { |
| 297 | const char *fw_name = "amd-ucode/microcode_amd.bin"; | ||
| 298 | const struct firmware *firmware; | ||
| 297 | enum ucode_state ret; | 299 | enum ucode_state ret; |
| 298 | 300 | ||
| 299 | if (firmware == NULL) | 301 | if (request_firmware(&firmware, fw_name, device)) { |
| 302 | printk(KERN_ERR "microcode: failed to load file %s\n", fw_name); | ||
| 300 | return UCODE_NFOUND; | 303 | return UCODE_NFOUND; |
| 304 | } | ||
| 301 | 305 | ||
| 302 | if (*(u32 *)firmware->data != UCODE_MAGIC) { | 306 | if (*(u32 *)firmware->data != UCODE_MAGIC) { |
| 303 | pr_err("invalid UCODE_MAGIC (0x%08x)\n", | 307 | pr_err("invalid UCODE_MAGIC (0x%08x)\n", |
| @@ -307,6 +311,8 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device) | |||
| 307 | 311 | ||
| 308 | ret = generic_load_microcode(cpu, firmware->data, firmware->size); | 312 | ret = generic_load_microcode(cpu, firmware->data, firmware->size); |
| 309 | 313 | ||
| 314 | release_firmware(firmware); | ||
| 315 | |||
| 310 | return ret; | 316 | return ret; |
| 311 | } | 317 | } |
| 312 | 318 | ||
| @@ -325,31 +331,7 @@ static void microcode_fini_cpu_amd(int cpu) | |||
| 325 | uci->mc = NULL; | 331 | uci->mc = NULL; |
| 326 | } | 332 | } |
| 327 | 333 | ||
| 328 | void init_microcode_amd(struct device *device) | ||
| 329 | { | ||
| 330 | const char *fw_name = "amd-ucode/microcode_amd.bin"; | ||
| 331 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
| 332 | |||
| 333 | WARN_ON(c->x86_vendor != X86_VENDOR_AMD); | ||
| 334 | |||
| 335 | if (c->x86 < 0x10) { | ||
| 336 | pr_warning("AMD CPU family 0x%x not supported\n", c->x86); | ||
| 337 | return; | ||
| 338 | } | ||
| 339 | supported_cpu = 1; | ||
| 340 | |||
| 341 | if (request_firmware(&firmware, fw_name, device)) | ||
| 342 | pr_err("failed to load file %s\n", fw_name); | ||
| 343 | } | ||
| 344 | |||
| 345 | void fini_microcode_amd(void) | ||
| 346 | { | ||
| 347 | release_firmware(firmware); | ||
| 348 | } | ||
| 349 | |||
| 350 | static struct microcode_ops microcode_amd_ops = { | 334 | static struct microcode_ops microcode_amd_ops = { |
| 351 | .init = init_microcode_amd, | ||
| 352 | .fini = fini_microcode_amd, | ||
| 353 | .request_microcode_user = request_microcode_user, | 335 | .request_microcode_user = request_microcode_user, |
| 354 | .request_microcode_fw = request_microcode_fw, | 336 | .request_microcode_fw = request_microcode_fw, |
| 355 | .collect_cpu_info = collect_cpu_info_amd, | 337 | .collect_cpu_info = collect_cpu_info_amd, |
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 0c8632433090..cceb5bc3c3c2 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
| @@ -521,9 +521,6 @@ static int __init microcode_init(void) | |||
| 521 | return PTR_ERR(microcode_pdev); | 521 | return PTR_ERR(microcode_pdev); |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | if (microcode_ops->init) | ||
| 525 | microcode_ops->init(µcode_pdev->dev); | ||
| 526 | |||
| 527 | get_online_cpus(); | 524 | get_online_cpus(); |
| 528 | mutex_lock(µcode_mutex); | 525 | mutex_lock(µcode_mutex); |
| 529 | 526 | ||
| @@ -566,9 +563,6 @@ static void __exit microcode_exit(void) | |||
| 566 | 563 | ||
| 567 | platform_device_unregister(microcode_pdev); | 564 | platform_device_unregister(microcode_pdev); |
| 568 | 565 | ||
| 569 | if (microcode_ops->fini) | ||
| 570 | microcode_ops->fini(); | ||
| 571 | |||
| 572 | microcode_ops = NULL; | 566 | microcode_ops = NULL; |
| 573 | 567 | ||
| 574 | pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); | 568 | pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); |
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 40b54ceb68b5..a2c1edd2d3ac 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
| @@ -359,13 +359,6 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
| 359 | x86_init.mpparse.mpc_record(1); | 359 | x86_init.mpparse.mpc_record(1); |
| 360 | } | 360 | } |
| 361 | 361 | ||
| 362 | #ifdef CONFIG_X86_BIGSMP | ||
| 363 | generic_bigsmp_probe(); | ||
| 364 | #endif | ||
| 365 | |||
| 366 | if (apic->setup_apic_routing) | ||
| 367 | apic->setup_apic_routing(); | ||
| 368 | |||
| 369 | if (!num_processors) | 362 | if (!num_processors) |
| 370 | printk(KERN_ERR "MPTABLE: no processors registered!\n"); | 363 | printk(KERN_ERR "MPTABLE: no processors registered!\n"); |
| 371 | return num_processors; | 364 | return num_processors; |
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 4bd93c9b2b27..206735ac8cbd 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
| @@ -285,7 +285,7 @@ static void __exit msr_exit(void) | |||
| 285 | for_each_online_cpu(cpu) | 285 | for_each_online_cpu(cpu) |
| 286 | msr_device_destroy(cpu); | 286 | msr_device_destroy(cpu); |
| 287 | class_destroy(msr_class); | 287 | class_destroy(msr_class); |
| 288 | unregister_chrdev(MSR_MAJOR, "cpu/msr"); | 288 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); |
| 289 | unregister_hotcpu_notifier(&msr_class_cpu_notifier); | 289 | unregister_hotcpu_notifier(&msr_class_cpu_notifier); |
| 290 | } | 290 | } |
| 291 | 291 | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 98c2cdeb599e..c9b3522b6b46 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -103,8 +103,8 @@ void show_regs_common(void) | |||
| 103 | if (!product) | 103 | if (!product) |
| 104 | product = ""; | 104 | product = ""; |
| 105 | 105 | ||
| 106 | printk("\n"); | 106 | printk(KERN_CONT "\n"); |
| 107 | printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n", | 107 | printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n", |
| 108 | current->pid, current->comm, print_tainted(), | 108 | current->pid, current->comm, print_tainted(), |
| 109 | init_utsname()->release, | 109 | init_utsname()->release, |
| 110 | (int)strcspn(init_utsname()->version, " "), | 110 | (int)strcspn(init_utsname()->version, " "), |
| @@ -115,18 +115,6 @@ void flush_thread(void) | |||
| 115 | { | 115 | { |
| 116 | struct task_struct *tsk = current; | 116 | struct task_struct *tsk = current; |
| 117 | 117 | ||
| 118 | #ifdef CONFIG_X86_64 | ||
| 119 | if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) { | ||
| 120 | clear_tsk_thread_flag(tsk, TIF_ABI_PENDING); | ||
| 121 | if (test_tsk_thread_flag(tsk, TIF_IA32)) { | ||
| 122 | clear_tsk_thread_flag(tsk, TIF_IA32); | ||
| 123 | } else { | ||
| 124 | set_tsk_thread_flag(tsk, TIF_IA32); | ||
| 125 | current_thread_info()->status |= TS_COMPAT; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | #endif | ||
| 129 | |||
| 130 | flush_ptrace_hw_breakpoint(tsk); | 118 | flush_ptrace_hw_breakpoint(tsk); |
| 131 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 119 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
| 132 | /* | 120 | /* |
| @@ -288,6 +276,8 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |||
| 288 | regs.es = __USER_DS; | 276 | regs.es = __USER_DS; |
| 289 | regs.fs = __KERNEL_PERCPU; | 277 | regs.fs = __KERNEL_PERCPU; |
| 290 | regs.gs = __KERNEL_STACK_CANARY; | 278 | regs.gs = __KERNEL_STACK_CANARY; |
| 279 | #else | ||
| 280 | regs.ss = __KERNEL_DS; | ||
| 291 | #endif | 281 | #endif |
| 292 | 282 | ||
| 293 | regs.orig_ax = -1; | 283 | regs.orig_ax = -1; |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 9c517b5858f0..37ad1e046aae 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -139,16 +139,16 @@ void __show_regs(struct pt_regs *regs, int all) | |||
| 139 | 139 | ||
| 140 | show_regs_common(); | 140 | show_regs_common(); |
| 141 | 141 | ||
| 142 | printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", | 142 | printk(KERN_DEFAULT "EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", |
| 143 | (u16)regs->cs, regs->ip, regs->flags, | 143 | (u16)regs->cs, regs->ip, regs->flags, |
| 144 | smp_processor_id()); | 144 | smp_processor_id()); |
| 145 | print_symbol("EIP is at %s\n", regs->ip); | 145 | print_symbol("EIP is at %s\n", regs->ip); |
| 146 | 146 | ||
| 147 | printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", | 147 | printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", |
| 148 | regs->ax, regs->bx, regs->cx, regs->dx); | 148 | regs->ax, regs->bx, regs->cx, regs->dx); |
| 149 | printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n", | 149 | printk(KERN_DEFAULT "ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n", |
| 150 | regs->si, regs->di, regs->bp, sp); | 150 | regs->si, regs->di, regs->bp, sp); |
| 151 | printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n", | 151 | printk(KERN_DEFAULT " DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n", |
| 152 | (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss); | 152 | (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss); |
| 153 | 153 | ||
| 154 | if (!all) | 154 | if (!all) |
| @@ -158,19 +158,19 @@ void __show_regs(struct pt_regs *regs, int all) | |||
| 158 | cr2 = read_cr2(); | 158 | cr2 = read_cr2(); |
| 159 | cr3 = read_cr3(); | 159 | cr3 = read_cr3(); |
| 160 | cr4 = read_cr4_safe(); | 160 | cr4 = read_cr4_safe(); |
| 161 | printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", | 161 | printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", |
| 162 | cr0, cr2, cr3, cr4); | 162 | cr0, cr2, cr3, cr4); |
| 163 | 163 | ||
| 164 | get_debugreg(d0, 0); | 164 | get_debugreg(d0, 0); |
| 165 | get_debugreg(d1, 1); | 165 | get_debugreg(d1, 1); |
| 166 | get_debugreg(d2, 2); | 166 | get_debugreg(d2, 2); |
| 167 | get_debugreg(d3, 3); | 167 | get_debugreg(d3, 3); |
| 168 | printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", | 168 | printk(KERN_DEFAULT "DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", |
| 169 | d0, d1, d2, d3); | 169 | d0, d1, d2, d3); |
| 170 | 170 | ||
| 171 | get_debugreg(d6, 6); | 171 | get_debugreg(d6, 6); |
| 172 | get_debugreg(d7, 7); | 172 | get_debugreg(d7, 7); |
| 173 | printk("DR6: %08lx DR7: %08lx\n", | 173 | printk(KERN_DEFAULT "DR6: %08lx DR7: %08lx\n", |
| 174 | d6, d7); | 174 | d6, d7); |
| 175 | } | 175 | } |
| 176 | 176 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 52fbd0c60198..126f0b493d04 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -161,19 +161,19 @@ void __show_regs(struct pt_regs *regs, int all) | |||
| 161 | unsigned int ds, cs, es; | 161 | unsigned int ds, cs, es; |
| 162 | 162 | ||
| 163 | show_regs_common(); | 163 | show_regs_common(); |
| 164 | printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); | 164 | printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); |
| 165 | printk_address(regs->ip, 1); | 165 | printk_address(regs->ip, 1); |
| 166 | printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, | 166 | printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, |
| 167 | regs->sp, regs->flags); | 167 | regs->sp, regs->flags); |
| 168 | printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", | 168 | printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n", |
| 169 | regs->ax, regs->bx, regs->cx); | 169 | regs->ax, regs->bx, regs->cx); |
| 170 | printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", | 170 | printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n", |
| 171 | regs->dx, regs->si, regs->di); | 171 | regs->dx, regs->si, regs->di); |
| 172 | printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", | 172 | printk(KERN_DEFAULT "RBP: %016lx R08: %016lx R09: %016lx\n", |
| 173 | regs->bp, regs->r8, regs->r9); | 173 | regs->bp, regs->r8, regs->r9); |
| 174 | printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", | 174 | printk(KERN_DEFAULT "R10: %016lx R11: %016lx R12: %016lx\n", |
| 175 | regs->r10, regs->r11, regs->r12); | 175 | regs->r10, regs->r11, regs->r12); |
| 176 | printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", | 176 | printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n", |
| 177 | regs->r13, regs->r14, regs->r15); | 177 | regs->r13, regs->r14, regs->r15); |
| 178 | 178 | ||
| 179 | asm("movl %%ds,%0" : "=r" (ds)); | 179 | asm("movl %%ds,%0" : "=r" (ds)); |
| @@ -194,21 +194,21 @@ void __show_regs(struct pt_regs *regs, int all) | |||
| 194 | cr3 = read_cr3(); | 194 | cr3 = read_cr3(); |
| 195 | cr4 = read_cr4(); | 195 | cr4 = read_cr4(); |
| 196 | 196 | ||
| 197 | printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", | 197 | printk(KERN_DEFAULT "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", |
| 198 | fs, fsindex, gs, gsindex, shadowgs); | 198 | fs, fsindex, gs, gsindex, shadowgs); |
| 199 | printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, | 199 | printk(KERN_DEFAULT "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, |
| 200 | es, cr0); | 200 | es, cr0); |
| 201 | printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, | 201 | printk(KERN_DEFAULT "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, |
| 202 | cr4); | 202 | cr4); |
| 203 | 203 | ||
| 204 | get_debugreg(d0, 0); | 204 | get_debugreg(d0, 0); |
| 205 | get_debugreg(d1, 1); | 205 | get_debugreg(d1, 1); |
| 206 | get_debugreg(d2, 2); | 206 | get_debugreg(d2, 2); |
| 207 | printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); | 207 | printk(KERN_DEFAULT "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); |
| 208 | get_debugreg(d3, 3); | 208 | get_debugreg(d3, 3); |
| 209 | get_debugreg(d6, 6); | 209 | get_debugreg(d6, 6); |
| 210 | get_debugreg(d7, 7); | 210 | get_debugreg(d7, 7); |
| 211 | printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); | 211 | printk(KERN_DEFAULT "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | void show_regs(struct pt_regs *regs) | 214 | void show_regs(struct pt_regs *regs) |
| @@ -521,6 +521,18 @@ void set_personality_64bit(void) | |||
| 521 | current->personality &= ~READ_IMPLIES_EXEC; | 521 | current->personality &= ~READ_IMPLIES_EXEC; |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | void set_personality_ia32(void) | ||
| 525 | { | ||
| 526 | /* inherit personality from parent */ | ||
| 527 | |||
| 528 | /* Make sure to be in 32bit mode */ | ||
| 529 | set_thread_flag(TIF_IA32); | ||
| 530 | current->personality |= force_personality32; | ||
| 531 | |||
| 532 | /* Prepare the first "return" to user space */ | ||
| 533 | current_thread_info()->status |= TS_COMPAT; | ||
| 534 | } | ||
| 535 | |||
| 524 | unsigned long get_wchan(struct task_struct *p) | 536 | unsigned long get_wchan(struct task_struct *p) |
| 525 | { | 537 | { |
| 526 | unsigned long stack; | 538 | unsigned long stack; |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 017d937639fe..0c1033d61e59 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -702,7 +702,7 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) | |||
| 702 | } else if (n == 6) { | 702 | } else if (n == 6) { |
| 703 | val = thread->debugreg6; | 703 | val = thread->debugreg6; |
| 704 | } else if (n == 7) { | 704 | } else if (n == 7) { |
| 705 | val = ptrace_get_dr7(thread->ptrace_bps); | 705 | val = thread->ptrace_dr7; |
| 706 | } | 706 | } |
| 707 | return val; | 707 | return val; |
| 708 | } | 708 | } |
| @@ -778,8 +778,11 @@ int ptrace_set_debugreg(struct task_struct *tsk, int n, unsigned long val) | |||
| 778 | return rc; | 778 | return rc; |
| 779 | } | 779 | } |
| 780 | /* All that's left is DR7 */ | 780 | /* All that's left is DR7 */ |
| 781 | if (n == 7) | 781 | if (n == 7) { |
| 782 | rc = ptrace_write_dr7(tsk, val); | 782 | rc = ptrace_write_dr7(tsk, val); |
| 783 | if (!rc) | ||
| 784 | thread->ptrace_dr7 = val; | ||
| 785 | } | ||
| 783 | 786 | ||
| 784 | ret_path: | 787 | ret_path: |
| 785 | return rc; | 788 | return rc; |
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 18093d7498f0..12e9feaa2f7a 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
| @@ -491,6 +491,19 @@ void force_hpet_resume(void) | |||
| 491 | break; | 491 | break; |
| 492 | } | 492 | } |
| 493 | } | 493 | } |
| 494 | |||
| 495 | /* | ||
| 496 | * HPET MSI on some boards (ATI SB700/SB800) has side effect on | ||
| 497 | * floppy DMA. Disable HPET MSI on such platforms. | ||
| 498 | */ | ||
| 499 | static void force_disable_hpet_msi(struct pci_dev *unused) | ||
| 500 | { | ||
| 501 | hpet_msi_disable = 1; | ||
| 502 | } | ||
| 503 | |||
| 504 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, | ||
| 505 | force_disable_hpet_msi); | ||
| 506 | |||
| 494 | #endif | 507 | #endif |
| 495 | 508 | ||
| 496 | #if defined(CONFIG_PCI) && defined(CONFIG_NUMA) | 509 | #if defined(CONFIG_PCI) && defined(CONFIG_NUMA) |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 1545bc0c9845..704bddcdf64d 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
| @@ -203,6 +203,15 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { | |||
| 203 | DMI_MATCH(DMI_BOARD_NAME, "0T656F"), | 203 | DMI_MATCH(DMI_BOARD_NAME, "0T656F"), |
| 204 | }, | 204 | }, |
| 205 | }, | 205 | }, |
| 206 | { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G*/ | ||
| 207 | .callback = set_bios_reboot, | ||
| 208 | .ident = "Dell OptiPlex 760", | ||
| 209 | .matches = { | ||
| 210 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 211 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"), | ||
| 212 | DMI_MATCH(DMI_BOARD_NAME, "0G919G"), | ||
| 213 | }, | ||
| 214 | }, | ||
| 206 | { /* Handle problems with rebooting on Dell 2400's */ | 215 | { /* Handle problems with rebooting on Dell 2400's */ |
| 207 | .callback = set_bios_reboot, | 216 | .callback = set_bios_reboot, |
| 208 | .ident = "Dell PowerEdge 2400", | 217 | .ident = "Dell PowerEdge 2400", |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f7b8b9894b22..5d9e40c58628 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -642,19 +642,27 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | |||
| 642 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"), | 642 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"), |
| 643 | }, | 643 | }, |
| 644 | }, | 644 | }, |
| 645 | { | ||
| 646 | /* | 645 | /* |
| 647 | * AMI BIOS with low memory corruption was found on Intel DG45ID board. | 646 | * AMI BIOS with low memory corruption was found on Intel DG45ID and |
| 648 | * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will | 647 | * DG45FC boards. |
| 648 | * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will | ||
| 649 | * match only DMI_BOARD_NAME and see if there is more bad products | 649 | * match only DMI_BOARD_NAME and see if there is more bad products |
| 650 | * with this vendor. | 650 | * with this vendor. |
| 651 | */ | 651 | */ |
| 652 | { | ||
| 652 | .callback = dmi_low_memory_corruption, | 653 | .callback = dmi_low_memory_corruption, |
| 653 | .ident = "AMI BIOS", | 654 | .ident = "AMI BIOS", |
| 654 | .matches = { | 655 | .matches = { |
| 655 | DMI_MATCH(DMI_BOARD_NAME, "DG45ID"), | 656 | DMI_MATCH(DMI_BOARD_NAME, "DG45ID"), |
| 656 | }, | 657 | }, |
| 657 | }, | 658 | }, |
| 659 | { | ||
| 660 | .callback = dmi_low_memory_corruption, | ||
| 661 | .ident = "AMI BIOS", | ||
| 662 | .matches = { | ||
| 663 | DMI_MATCH(DMI_BOARD_NAME, "DG45FC"), | ||
| 664 | }, | ||
| 665 | }, | ||
| 658 | #endif | 666 | #endif |
| 659 | {} | 667 | {} |
| 660 | }; | 668 | }; |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 678d0b8c26f3..b4e870cbdc60 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -1083,9 +1083,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
| 1083 | set_cpu_sibling_map(0); | 1083 | set_cpu_sibling_map(0); |
| 1084 | 1084 | ||
| 1085 | enable_IR_x2apic(); | 1085 | enable_IR_x2apic(); |
| 1086 | #ifdef CONFIG_X86_64 | ||
| 1087 | default_setup_apic_routing(); | 1086 | default_setup_apic_routing(); |
| 1088 | #endif | ||
| 1089 | 1087 | ||
| 1090 | if (smp_sanity_check(max_cpus) < 0) { | 1088 | if (smp_sanity_check(max_cpus) < 0) { |
| 1091 | printk(KERN_INFO "SMP disabled\n"); | 1089 | printk(KERN_INFO "SMP disabled\n"); |
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c index 3c84aa001c11..2b75ef638dbc 100644 --- a/arch/x86/kernel/uv_time.c +++ b/arch/x86/kernel/uv_time.c | |||
| @@ -282,10 +282,21 @@ static int uv_rtc_unset_timer(int cpu, int force) | |||
| 282 | 282 | ||
| 283 | /* | 283 | /* |
| 284 | * Read the RTC. | 284 | * Read the RTC. |
| 285 | * | ||
| 286 | * Starting with HUB rev 2.0, the UV RTC register is replicated across all | ||
| 287 | * cachelines of it's own page. This allows faster simultaneous reads | ||
| 288 | * from a given socket. | ||
| 285 | */ | 289 | */ |
| 286 | static cycle_t uv_read_rtc(struct clocksource *cs) | 290 | static cycle_t uv_read_rtc(struct clocksource *cs) |
| 287 | { | 291 | { |
| 288 | return (cycle_t)uv_read_local_mmr(UVH_RTC); | 292 | unsigned long offset; |
| 293 | |||
| 294 | if (uv_get_min_hub_revision_id() == 1) | ||
| 295 | offset = 0; | ||
| 296 | else | ||
| 297 | offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE; | ||
| 298 | |||
| 299 | return (cycle_t)uv_read_local_mmr(UVH_RTC | offset); | ||
| 289 | } | 300 | } |
| 290 | 301 | ||
| 291 | /* | 302 | /* |
