diff options
Diffstat (limited to 'arch/x86/kernel')
60 files changed, 2974 insertions, 2390 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 0acbcdfa5ca4..738fcb60e708 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
| @@ -49,6 +49,7 @@ EXPORT_SYMBOL(acpi_disabled); | |||
| 49 | 49 | ||
| 50 | #ifdef CONFIG_X86_64 | 50 | #ifdef CONFIG_X86_64 |
| 51 | # include <asm/proto.h> | 51 | # include <asm/proto.h> |
| 52 | # include <asm/numa_64.h> | ||
| 52 | #endif /* X86 */ | 53 | #endif /* X86 */ |
| 53 | 54 | ||
| 54 | #define BAD_MADT_ENTRY(entry, end) ( \ | 55 | #define BAD_MADT_ENTRY(entry, end) ( \ |
| @@ -446,6 +447,12 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) | |||
| 446 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | 447 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) |
| 447 | { | 448 | { |
| 448 | *irq = gsi; | 449 | *irq = gsi; |
| 450 | |||
| 451 | #ifdef CONFIG_X86_IO_APIC | ||
| 452 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) | ||
| 453 | setup_IO_APIC_irq_extra(gsi); | ||
| 454 | #endif | ||
| 455 | |||
| 449 | return 0; | 456 | return 0; |
| 450 | } | 457 | } |
| 451 | 458 | ||
| @@ -473,7 +480,8 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
| 473 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); | 480 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); |
| 474 | } | 481 | } |
| 475 | #endif | 482 | #endif |
| 476 | acpi_gsi_to_irq(plat_gsi, &irq); | 483 | irq = plat_gsi; |
| 484 | |||
| 477 | return irq; | 485 | return irq; |
| 478 | } | 486 | } |
| 479 | 487 | ||
| @@ -482,6 +490,25 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
| 482 | */ | 490 | */ |
| 483 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | 491 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
| 484 | 492 | ||
| 493 | static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) | ||
| 494 | { | ||
| 495 | #ifdef CONFIG_ACPI_NUMA | ||
| 496 | int nid; | ||
| 497 | |||
| 498 | nid = acpi_get_node(handle); | ||
| 499 | if (nid == -1 || !node_online(nid)) | ||
| 500 | return; | ||
| 501 | #ifdef CONFIG_X86_64 | ||
| 502 | apicid_to_node[physid] = nid; | ||
| 503 | numa_set_node(cpu, nid); | ||
| 504 | #else /* CONFIG_X86_32 */ | ||
| 505 | apicid_2_node[physid] = nid; | ||
| 506 | cpu_to_node_map[cpu] = nid; | ||
| 507 | #endif | ||
| 508 | |||
| 509 | #endif | ||
| 510 | } | ||
| 511 | |||
| 485 | static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | 512 | static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) |
| 486 | { | 513 | { |
| 487 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 514 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -540,6 +567,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
| 540 | } | 567 | } |
| 541 | 568 | ||
| 542 | cpu = cpumask_first(new_map); | 569 | cpu = cpumask_first(new_map); |
| 570 | acpi_map_cpu2node(handle, cpu, physid); | ||
| 543 | 571 | ||
| 544 | *pcpu = cpu; | 572 | *pcpu = cpu; |
| 545 | retval = 0; | 573 | retval = 0; |
| @@ -1344,14 +1372,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { | |||
| 1344 | }, | 1372 | }, |
| 1345 | { | 1373 | { |
| 1346 | .callback = force_acpi_ht, | 1374 | .callback = force_acpi_ht, |
| 1347 | .ident = "ASUS P2B-DS", | ||
| 1348 | .matches = { | ||
| 1349 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
| 1350 | DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"), | ||
| 1351 | }, | ||
| 1352 | }, | ||
| 1353 | { | ||
| 1354 | .callback = force_acpi_ht, | ||
| 1355 | .ident = "ASUS CUR-DLS", | 1375 | .ident = "ASUS CUR-DLS", |
| 1356 | .matches = { | 1376 | .matches = { |
| 1357 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | 1377 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), |
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index de7353c0ce9c..e6ea0342c8f8 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
| @@ -205,7 +205,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start, | |||
| 205 | struct alt_instr *end) | 205 | struct alt_instr *end) |
| 206 | { | 206 | { |
| 207 | struct alt_instr *a; | 207 | struct alt_instr *a; |
| 208 | char insnbuf[MAX_PATCH_LEN]; | 208 | u8 insnbuf[MAX_PATCH_LEN]; |
| 209 | 209 | ||
| 210 | DPRINTK("%s: alt table %p -> %p\n", __func__, start, end); | 210 | DPRINTK("%s: alt table %p -> %p\n", __func__, start, end); |
| 211 | for (a = start; a < end; a++) { | 211 | for (a = start; a < end; a++) { |
| @@ -223,6 +223,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start, | |||
| 223 | } | 223 | } |
| 224 | #endif | 224 | #endif |
| 225 | memcpy(insnbuf, a->replacement, a->replacementlen); | 225 | memcpy(insnbuf, a->replacement, a->replacementlen); |
| 226 | if (*insnbuf == 0xe8 && a->replacementlen == 5) | ||
| 227 | *(s32 *)(insnbuf + 1) += a->replacement - a->instr; | ||
| 226 | add_nops(insnbuf + a->replacementlen, | 228 | add_nops(insnbuf + a->replacementlen, |
| 227 | a->instrlen - a->replacementlen); | 229 | a->instrlen - a->replacementlen); |
| 228 | text_poke_early(instr, insnbuf, a->instrlen); | 230 | text_poke_early(instr, insnbuf, a->instrlen); |
| @@ -390,6 +392,24 @@ void alternatives_smp_switch(int smp) | |||
| 390 | mutex_unlock(&smp_alt); | 392 | mutex_unlock(&smp_alt); |
| 391 | } | 393 | } |
| 392 | 394 | ||
| 395 | /* Return 1 if the address range is reserved for smp-alternatives */ | ||
| 396 | int alternatives_text_reserved(void *start, void *end) | ||
| 397 | { | ||
| 398 | struct smp_alt_module *mod; | ||
| 399 | u8 **ptr; | ||
| 400 | u8 *text_start = start; | ||
| 401 | u8 *text_end = end; | ||
| 402 | |||
| 403 | list_for_each_entry(mod, &smp_alt_modules, next) { | ||
| 404 | if (mod->text > text_end || mod->text_end < text_start) | ||
| 405 | continue; | ||
| 406 | for (ptr = mod->locks; ptr < mod->locks_end; ptr++) | ||
| 407 | if (text_start <= *ptr && text_end >= *ptr) | ||
| 408 | return 1; | ||
| 409 | } | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 393 | #endif | 413 | #endif |
| 394 | 414 | ||
| 395 | #ifdef CONFIG_PARAVIRT | 415 | #ifdef CONFIG_PARAVIRT |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index dfca210f6a10..6e29b2a77aa8 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -581,7 +581,7 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) | |||
| 581 | res = (((u64)(*deltatsc)) * pm_100ms); | 581 | res = (((u64)(*deltatsc)) * pm_100ms); |
| 582 | do_div(res, deltapm); | 582 | do_div(res, deltapm); |
| 583 | apic_printk(APIC_VERBOSE, "TSC delta adjusted to " | 583 | apic_printk(APIC_VERBOSE, "TSC delta adjusted to " |
| 584 | "PM-Timer: %lu (%ld) \n", | 584 | "PM-Timer: %lu (%ld)\n", |
| 585 | (unsigned long)res, *deltatsc); | 585 | (unsigned long)res, *deltatsc); |
| 586 | *deltatsc = (long)res; | 586 | *deltatsc = (long)res; |
| 587 | } | 587 | } |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 53243ca7816d..14862f11cc4a 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -73,8 +73,8 @@ | |||
| 73 | */ | 73 | */ |
| 74 | int sis_apic_bug = -1; | 74 | int sis_apic_bug = -1; |
| 75 | 75 | ||
| 76 | static DEFINE_SPINLOCK(ioapic_lock); | 76 | static DEFINE_RAW_SPINLOCK(ioapic_lock); |
| 77 | static DEFINE_SPINLOCK(vector_lock); | 77 | static DEFINE_RAW_SPINLOCK(vector_lock); |
| 78 | 78 | ||
| 79 | /* | 79 | /* |
| 80 | * # of IRQ routing registers | 80 | * # of IRQ routing registers |
| @@ -94,8 +94,6 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; | |||
| 94 | /* # of MP IRQ source entries */ | 94 | /* # of MP IRQ source entries */ |
| 95 | int mp_irq_entries; | 95 | int mp_irq_entries; |
| 96 | 96 | ||
| 97 | /* Number of legacy interrupts */ | ||
| 98 | static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY; | ||
| 99 | /* GSI interrupts */ | 97 | /* GSI interrupts */ |
| 100 | static int nr_irqs_gsi = NR_IRQS_LEGACY; | 98 | static int nr_irqs_gsi = NR_IRQS_LEGACY; |
| 101 | 99 | ||
| @@ -140,27 +138,10 @@ static struct irq_pin_list *get_one_free_irq_2_pin(int node) | |||
| 140 | 138 | ||
| 141 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ | 139 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ |
| 142 | #ifdef CONFIG_SPARSE_IRQ | 140 | #ifdef CONFIG_SPARSE_IRQ |
| 143 | static struct irq_cfg irq_cfgx[] = { | 141 | static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; |
| 144 | #else | 142 | #else |
| 145 | static struct irq_cfg irq_cfgx[NR_IRQS] = { | 143 | static struct irq_cfg irq_cfgx[NR_IRQS]; |
| 146 | #endif | 144 | #endif |
| 147 | [0] = { .vector = IRQ0_VECTOR, }, | ||
| 148 | [1] = { .vector = IRQ1_VECTOR, }, | ||
| 149 | [2] = { .vector = IRQ2_VECTOR, }, | ||
| 150 | [3] = { .vector = IRQ3_VECTOR, }, | ||
| 151 | [4] = { .vector = IRQ4_VECTOR, }, | ||
| 152 | [5] = { .vector = IRQ5_VECTOR, }, | ||
| 153 | [6] = { .vector = IRQ6_VECTOR, }, | ||
| 154 | [7] = { .vector = IRQ7_VECTOR, }, | ||
| 155 | [8] = { .vector = IRQ8_VECTOR, }, | ||
| 156 | [9] = { .vector = IRQ9_VECTOR, }, | ||
| 157 | [10] = { .vector = IRQ10_VECTOR, }, | ||
| 158 | [11] = { .vector = IRQ11_VECTOR, }, | ||
| 159 | [12] = { .vector = IRQ12_VECTOR, }, | ||
| 160 | [13] = { .vector = IRQ13_VECTOR, }, | ||
| 161 | [14] = { .vector = IRQ14_VECTOR, }, | ||
| 162 | [15] = { .vector = IRQ15_VECTOR, }, | ||
| 163 | }; | ||
| 164 | 145 | ||
| 165 | void __init io_apic_disable_legacy(void) | 146 | void __init io_apic_disable_legacy(void) |
| 166 | { | 147 | { |
| @@ -185,8 +166,14 @@ int __init arch_early_irq_init(void) | |||
| 185 | desc->chip_data = &cfg[i]; | 166 | desc->chip_data = &cfg[i]; |
| 186 | zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node); | 167 | zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node); |
| 187 | zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node); | 168 | zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node); |
| 188 | if (i < nr_legacy_irqs) | 169 | /* |
| 189 | cpumask_setall(cfg[i].domain); | 170 | * For legacy IRQ's, start with assigning irq0 to irq15 to |
| 171 | * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0. | ||
| 172 | */ | ||
| 173 | if (i < nr_legacy_irqs) { | ||
| 174 | cfg[i].vector = IRQ0_VECTOR + i; | ||
| 175 | cpumask_set_cpu(0, cfg[i].domain); | ||
| 176 | } | ||
| 190 | } | 177 | } |
| 191 | 178 | ||
| 192 | return 0; | 179 | return 0; |
| @@ -406,7 +393,7 @@ static bool io_apic_level_ack_pending(struct irq_cfg *cfg) | |||
| 406 | struct irq_pin_list *entry; | 393 | struct irq_pin_list *entry; |
| 407 | unsigned long flags; | 394 | unsigned long flags; |
| 408 | 395 | ||
| 409 | spin_lock_irqsave(&ioapic_lock, flags); | 396 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 410 | for_each_irq_pin(entry, cfg->irq_2_pin) { | 397 | for_each_irq_pin(entry, cfg->irq_2_pin) { |
| 411 | unsigned int reg; | 398 | unsigned int reg; |
| 412 | int pin; | 399 | int pin; |
| @@ -415,11 +402,11 @@ static bool io_apic_level_ack_pending(struct irq_cfg *cfg) | |||
| 415 | reg = io_apic_read(entry->apic, 0x10 + pin*2); | 402 | reg = io_apic_read(entry->apic, 0x10 + pin*2); |
| 416 | /* Is the remote IRR bit set? */ | 403 | /* Is the remote IRR bit set? */ |
| 417 | if (reg & IO_APIC_REDIR_REMOTE_IRR) { | 404 | if (reg & IO_APIC_REDIR_REMOTE_IRR) { |
| 418 | spin_unlock_irqrestore(&ioapic_lock, flags); | 405 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 419 | return true; | 406 | return true; |
| 420 | } | 407 | } |
| 421 | } | 408 | } |
| 422 | spin_unlock_irqrestore(&ioapic_lock, flags); | 409 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 423 | 410 | ||
| 424 | return false; | 411 | return false; |
| 425 | } | 412 | } |
| @@ -433,10 +420,10 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) | |||
| 433 | { | 420 | { |
| 434 | union entry_union eu; | 421 | union entry_union eu; |
| 435 | unsigned long flags; | 422 | unsigned long flags; |
| 436 | spin_lock_irqsave(&ioapic_lock, flags); | 423 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 437 | eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); | 424 | eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); |
| 438 | eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); | 425 | eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); |
| 439 | spin_unlock_irqrestore(&ioapic_lock, flags); | 426 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 440 | return eu.entry; | 427 | return eu.entry; |
| 441 | } | 428 | } |
| 442 | 429 | ||
| @@ -459,9 +446,9 @@ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | |||
| 459 | void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | 446 | void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) |
| 460 | { | 447 | { |
| 461 | unsigned long flags; | 448 | unsigned long flags; |
| 462 | spin_lock_irqsave(&ioapic_lock, flags); | 449 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 463 | __ioapic_write_entry(apic, pin, e); | 450 | __ioapic_write_entry(apic, pin, e); |
| 464 | spin_unlock_irqrestore(&ioapic_lock, flags); | 451 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 465 | } | 452 | } |
| 466 | 453 | ||
| 467 | /* | 454 | /* |
| @@ -474,10 +461,10 @@ static void ioapic_mask_entry(int apic, int pin) | |||
| 474 | unsigned long flags; | 461 | unsigned long flags; |
| 475 | union entry_union eu = { .entry.mask = 1 }; | 462 | union entry_union eu = { .entry.mask = 1 }; |
| 476 | 463 | ||
| 477 | spin_lock_irqsave(&ioapic_lock, flags); | 464 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 478 | io_apic_write(apic, 0x10 + 2*pin, eu.w1); | 465 | io_apic_write(apic, 0x10 + 2*pin, eu.w1); |
| 479 | io_apic_write(apic, 0x11 + 2*pin, eu.w2); | 466 | io_apic_write(apic, 0x11 + 2*pin, eu.w2); |
| 480 | spin_unlock_irqrestore(&ioapic_lock, flags); | 467 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 481 | } | 468 | } |
| 482 | 469 | ||
| 483 | /* | 470 | /* |
| @@ -604,9 +591,9 @@ static void mask_IO_APIC_irq_desc(struct irq_desc *desc) | |||
| 604 | 591 | ||
| 605 | BUG_ON(!cfg); | 592 | BUG_ON(!cfg); |
| 606 | 593 | ||
| 607 | spin_lock_irqsave(&ioapic_lock, flags); | 594 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 608 | __mask_IO_APIC_irq(cfg); | 595 | __mask_IO_APIC_irq(cfg); |
| 609 | spin_unlock_irqrestore(&ioapic_lock, flags); | 596 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 610 | } | 597 | } |
| 611 | 598 | ||
| 612 | static void unmask_IO_APIC_irq_desc(struct irq_desc *desc) | 599 | static void unmask_IO_APIC_irq_desc(struct irq_desc *desc) |
| @@ -614,9 +601,9 @@ static void unmask_IO_APIC_irq_desc(struct irq_desc *desc) | |||
| 614 | struct irq_cfg *cfg = desc->chip_data; | 601 | struct irq_cfg *cfg = desc->chip_data; |
| 615 | unsigned long flags; | 602 | unsigned long flags; |
| 616 | 603 | ||
| 617 | spin_lock_irqsave(&ioapic_lock, flags); | 604 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 618 | __unmask_IO_APIC_irq(cfg); | 605 | __unmask_IO_APIC_irq(cfg); |
| 619 | spin_unlock_irqrestore(&ioapic_lock, flags); | 606 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 620 | } | 607 | } |
| 621 | 608 | ||
| 622 | static void mask_IO_APIC_irq(unsigned int irq) | 609 | static void mask_IO_APIC_irq(unsigned int irq) |
| @@ -1140,12 +1127,12 @@ void lock_vector_lock(void) | |||
| 1140 | /* Used to the online set of cpus does not change | 1127 | /* Used to the online set of cpus does not change |
| 1141 | * during assign_irq_vector. | 1128 | * during assign_irq_vector. |
| 1142 | */ | 1129 | */ |
| 1143 | spin_lock(&vector_lock); | 1130 | raw_spin_lock(&vector_lock); |
| 1144 | } | 1131 | } |
| 1145 | 1132 | ||
| 1146 | void unlock_vector_lock(void) | 1133 | void unlock_vector_lock(void) |
| 1147 | { | 1134 | { |
| 1148 | spin_unlock(&vector_lock); | 1135 | raw_spin_unlock(&vector_lock); |
| 1149 | } | 1136 | } |
| 1150 | 1137 | ||
| 1151 | static int | 1138 | static int |
| @@ -1162,7 +1149,8 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) | |||
| 1162 | * Also, we've got to be careful not to trash gate | 1149 | * Also, we've got to be careful not to trash gate |
| 1163 | * 0x80, because int 0x80 is hm, kind of importantish. ;) | 1150 | * 0x80, because int 0x80 is hm, kind of importantish. ;) |
| 1164 | */ | 1151 | */ |
| 1165 | static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; | 1152 | static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; |
| 1153 | static int current_offset = VECTOR_OFFSET_START % 8; | ||
| 1166 | unsigned int old_vector; | 1154 | unsigned int old_vector; |
| 1167 | int cpu, err; | 1155 | int cpu, err; |
| 1168 | cpumask_var_t tmp_mask; | 1156 | cpumask_var_t tmp_mask; |
| @@ -1198,7 +1186,7 @@ next: | |||
| 1198 | if (vector >= first_system_vector) { | 1186 | if (vector >= first_system_vector) { |
| 1199 | /* If out of vectors on large boxen, must share them. */ | 1187 | /* If out of vectors on large boxen, must share them. */ |
| 1200 | offset = (offset + 1) % 8; | 1188 | offset = (offset + 1) % 8; |
| 1201 | vector = FIRST_DEVICE_VECTOR + offset; | 1189 | vector = FIRST_EXTERNAL_VECTOR + offset; |
| 1202 | } | 1190 | } |
| 1203 | if (unlikely(current_vector == vector)) | 1191 | if (unlikely(current_vector == vector)) |
| 1204 | continue; | 1192 | continue; |
| @@ -1232,9 +1220,9 @@ int assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) | |||
| 1232 | int err; | 1220 | int err; |
| 1233 | unsigned long flags; | 1221 | unsigned long flags; |
| 1234 | 1222 | ||
| 1235 | spin_lock_irqsave(&vector_lock, flags); | 1223 | raw_spin_lock_irqsave(&vector_lock, flags); |
| 1236 | err = __assign_irq_vector(irq, cfg, mask); | 1224 | err = __assign_irq_vector(irq, cfg, mask); |
| 1237 | spin_unlock_irqrestore(&vector_lock, flags); | 1225 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
| 1238 | return err; | 1226 | return err; |
| 1239 | } | 1227 | } |
| 1240 | 1228 | ||
| @@ -1268,11 +1256,16 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) | |||
| 1268 | void __setup_vector_irq(int cpu) | 1256 | void __setup_vector_irq(int cpu) |
| 1269 | { | 1257 | { |
| 1270 | /* Initialize vector_irq on a new cpu */ | 1258 | /* Initialize vector_irq on a new cpu */ |
| 1271 | /* This function must be called with vector_lock held */ | ||
| 1272 | int irq, vector; | 1259 | int irq, vector; |
| 1273 | struct irq_cfg *cfg; | 1260 | struct irq_cfg *cfg; |
| 1274 | struct irq_desc *desc; | 1261 | struct irq_desc *desc; |
| 1275 | 1262 | ||
| 1263 | /* | ||
| 1264 | * vector_lock will make sure that we don't run into irq vector | ||
| 1265 | * assignments that might be happening on another cpu in parallel, | ||
| 1266 | * while we setup our initial vector to irq mappings. | ||
| 1267 | */ | ||
| 1268 | raw_spin_lock(&vector_lock); | ||
| 1276 | /* Mark the inuse vectors */ | 1269 | /* Mark the inuse vectors */ |
| 1277 | for_each_irq_desc(irq, desc) { | 1270 | for_each_irq_desc(irq, desc) { |
| 1278 | cfg = desc->chip_data; | 1271 | cfg = desc->chip_data; |
| @@ -1291,6 +1284,7 @@ void __setup_vector_irq(int cpu) | |||
| 1291 | if (!cpumask_test_cpu(cpu, cfg->domain)) | 1284 | if (!cpumask_test_cpu(cpu, cfg->domain)) |
| 1292 | per_cpu(vector_irq, cpu)[vector] = -1; | 1285 | per_cpu(vector_irq, cpu)[vector] = -1; |
| 1293 | } | 1286 | } |
| 1287 | raw_spin_unlock(&vector_lock); | ||
| 1294 | } | 1288 | } |
| 1295 | 1289 | ||
| 1296 | static struct irq_chip ioapic_chip; | 1290 | static struct irq_chip ioapic_chip; |
| @@ -1440,6 +1434,14 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq | |||
| 1440 | 1434 | ||
| 1441 | cfg = desc->chip_data; | 1435 | cfg = desc->chip_data; |
| 1442 | 1436 | ||
| 1437 | /* | ||
| 1438 | * For legacy irqs, cfg->domain starts with cpu 0 for legacy | ||
| 1439 | * controllers like 8259. Now that IO-APIC can handle this irq, update | ||
| 1440 | * the cfg->domain. | ||
| 1441 | */ | ||
| 1442 | if (irq < nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain)) | ||
| 1443 | apic->vector_allocation_domain(0, cfg->domain); | ||
| 1444 | |||
| 1443 | if (assign_irq_vector(irq, cfg, apic->target_cpus())) | 1445 | if (assign_irq_vector(irq, cfg, apic->target_cpus())) |
| 1444 | return; | 1446 | return; |
| 1445 | 1447 | ||
| @@ -1473,7 +1475,7 @@ static struct { | |||
| 1473 | 1475 | ||
| 1474 | static void __init setup_IO_APIC_irqs(void) | 1476 | static void __init setup_IO_APIC_irqs(void) |
| 1475 | { | 1477 | { |
| 1476 | int apic_id = 0, pin, idx, irq; | 1478 | int apic_id, pin, idx, irq; |
| 1477 | int notcon = 0; | 1479 | int notcon = 0; |
| 1478 | struct irq_desc *desc; | 1480 | struct irq_desc *desc; |
| 1479 | struct irq_cfg *cfg; | 1481 | struct irq_cfg *cfg; |
| @@ -1481,14 +1483,7 @@ static void __init setup_IO_APIC_irqs(void) | |||
| 1481 | 1483 | ||
| 1482 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 1484 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); |
| 1483 | 1485 | ||
| 1484 | #ifdef CONFIG_ACPI | 1486 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) |
| 1485 | if (!acpi_disabled && acpi_ioapic) { | ||
| 1486 | apic_id = mp_find_ioapic(0); | ||
| 1487 | if (apic_id < 0) | ||
| 1488 | apic_id = 0; | ||
| 1489 | } | ||
| 1490 | #endif | ||
| 1491 | |||
| 1492 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { | 1487 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { |
| 1493 | idx = find_irq_entry(apic_id, pin, mp_INT); | 1488 | idx = find_irq_entry(apic_id, pin, mp_INT); |
| 1494 | if (idx == -1) { | 1489 | if (idx == -1) { |
| @@ -1510,6 +1505,9 @@ static void __init setup_IO_APIC_irqs(void) | |||
| 1510 | 1505 | ||
| 1511 | irq = pin_2_irq(idx, apic_id, pin); | 1506 | irq = pin_2_irq(idx, apic_id, pin); |
| 1512 | 1507 | ||
| 1508 | if ((apic_id > 0) && (irq > 16)) | ||
| 1509 | continue; | ||
| 1510 | |||
| 1513 | /* | 1511 | /* |
| 1514 | * Skip the timer IRQ if there's a quirk handler | 1512 | * Skip the timer IRQ if there's a quirk handler |
| 1515 | * installed and if it returns 1: | 1513 | * installed and if it returns 1: |
| @@ -1539,6 +1537,56 @@ static void __init setup_IO_APIC_irqs(void) | |||
| 1539 | } | 1537 | } |
| 1540 | 1538 | ||
| 1541 | /* | 1539 | /* |
| 1540 | * for the gsit that is not in first ioapic | ||
| 1541 | * but could not use acpi_register_gsi() | ||
| 1542 | * like some special sci in IBM x3330 | ||
| 1543 | */ | ||
| 1544 | void setup_IO_APIC_irq_extra(u32 gsi) | ||
| 1545 | { | ||
| 1546 | int apic_id = 0, pin, idx, irq; | ||
| 1547 | int node = cpu_to_node(boot_cpu_id); | ||
| 1548 | struct irq_desc *desc; | ||
| 1549 | struct irq_cfg *cfg; | ||
| 1550 | |||
| 1551 | /* | ||
| 1552 | * Convert 'gsi' to 'ioapic.pin'. | ||
| 1553 | */ | ||
| 1554 | apic_id = mp_find_ioapic(gsi); | ||
| 1555 | if (apic_id < 0) | ||
| 1556 | return; | ||
| 1557 | |||
| 1558 | pin = mp_find_ioapic_pin(apic_id, gsi); | ||
| 1559 | idx = find_irq_entry(apic_id, pin, mp_INT); | ||
| 1560 | if (idx == -1) | ||
| 1561 | return; | ||
| 1562 | |||
| 1563 | irq = pin_2_irq(idx, apic_id, pin); | ||
| 1564 | #ifdef CONFIG_SPARSE_IRQ | ||
| 1565 | desc = irq_to_desc(irq); | ||
| 1566 | if (desc) | ||
| 1567 | return; | ||
| 1568 | #endif | ||
| 1569 | desc = irq_to_desc_alloc_node(irq, node); | ||
| 1570 | if (!desc) { | ||
| 1571 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
| 1572 | return; | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | cfg = desc->chip_data; | ||
| 1576 | add_pin_to_irq_node(cfg, node, apic_id, pin); | ||
| 1577 | |||
| 1578 | if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) { | ||
| 1579 | pr_debug("Pin %d-%d already programmed\n", | ||
| 1580 | mp_ioapics[apic_id].apicid, pin); | ||
| 1581 | return; | ||
| 1582 | } | ||
| 1583 | set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed); | ||
| 1584 | |||
| 1585 | setup_IO_APIC_irq(apic_id, pin, irq, desc, | ||
| 1586 | irq_trigger(idx), irq_polarity(idx)); | ||
| 1587 | } | ||
| 1588 | |||
| 1589 | /* | ||
| 1542 | * Set up the timer pin, possibly with the 8259A-master behind. | 1590 | * Set up the timer pin, possibly with the 8259A-master behind. |
| 1543 | */ | 1591 | */ |
| 1544 | static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, | 1592 | static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, |
| @@ -1601,14 +1649,14 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
| 1601 | 1649 | ||
| 1602 | for (apic = 0; apic < nr_ioapics; apic++) { | 1650 | for (apic = 0; apic < nr_ioapics; apic++) { |
| 1603 | 1651 | ||
| 1604 | spin_lock_irqsave(&ioapic_lock, flags); | 1652 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 1605 | reg_00.raw = io_apic_read(apic, 0); | 1653 | reg_00.raw = io_apic_read(apic, 0); |
| 1606 | reg_01.raw = io_apic_read(apic, 1); | 1654 | reg_01.raw = io_apic_read(apic, 1); |
| 1607 | if (reg_01.bits.version >= 0x10) | 1655 | if (reg_01.bits.version >= 0x10) |
| 1608 | reg_02.raw = io_apic_read(apic, 2); | 1656 | reg_02.raw = io_apic_read(apic, 2); |
| 1609 | if (reg_01.bits.version >= 0x20) | 1657 | if (reg_01.bits.version >= 0x20) |
| 1610 | reg_03.raw = io_apic_read(apic, 3); | 1658 | reg_03.raw = io_apic_read(apic, 3); |
| 1611 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1659 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 1612 | 1660 | ||
| 1613 | printk("\n"); | 1661 | printk("\n"); |
| 1614 | printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid); | 1662 | printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid); |
| @@ -1647,7 +1695,7 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
| 1647 | printk(KERN_DEBUG ".... IRQ redirection table:\n"); | 1695 | printk(KERN_DEBUG ".... IRQ redirection table:\n"); |
| 1648 | 1696 | ||
| 1649 | printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol" | 1697 | printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol" |
| 1650 | " Stat Dmod Deli Vect: \n"); | 1698 | " Stat Dmod Deli Vect:\n"); |
| 1651 | 1699 | ||
| 1652 | for (i = 0; i <= reg_01.bits.entries; i++) { | 1700 | for (i = 0; i <= reg_01.bits.entries; i++) { |
| 1653 | struct IO_APIC_route_entry entry; | 1701 | struct IO_APIC_route_entry entry; |
| @@ -1830,7 +1878,7 @@ __apicdebuginit(void) print_PIC(void) | |||
| 1830 | 1878 | ||
| 1831 | printk(KERN_DEBUG "\nprinting PIC contents\n"); | 1879 | printk(KERN_DEBUG "\nprinting PIC contents\n"); |
| 1832 | 1880 | ||
| 1833 | spin_lock_irqsave(&i8259A_lock, flags); | 1881 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 1834 | 1882 | ||
| 1835 | v = inb(0xa1) << 8 | inb(0x21); | 1883 | v = inb(0xa1) << 8 | inb(0x21); |
| 1836 | printk(KERN_DEBUG "... PIC IMR: %04x\n", v); | 1884 | printk(KERN_DEBUG "... PIC IMR: %04x\n", v); |
| @@ -1844,7 +1892,7 @@ __apicdebuginit(void) print_PIC(void) | |||
| 1844 | outb(0x0a,0xa0); | 1892 | outb(0x0a,0xa0); |
| 1845 | outb(0x0a,0x20); | 1893 | outb(0x0a,0x20); |
| 1846 | 1894 | ||
| 1847 | spin_unlock_irqrestore(&i8259A_lock, flags); | 1895 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 1848 | 1896 | ||
| 1849 | printk(KERN_DEBUG "... PIC ISR: %04x\n", v); | 1897 | printk(KERN_DEBUG "... PIC ISR: %04x\n", v); |
| 1850 | 1898 | ||
| @@ -1903,9 +1951,9 @@ void __init enable_IO_APIC(void) | |||
| 1903 | * The number of IO-APIC IRQ registers (== #pins): | 1951 | * The number of IO-APIC IRQ registers (== #pins): |
| 1904 | */ | 1952 | */ |
| 1905 | for (apic = 0; apic < nr_ioapics; apic++) { | 1953 | for (apic = 0; apic < nr_ioapics; apic++) { |
| 1906 | spin_lock_irqsave(&ioapic_lock, flags); | 1954 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 1907 | reg_01.raw = io_apic_read(apic, 1); | 1955 | reg_01.raw = io_apic_read(apic, 1); |
| 1908 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1956 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 1909 | nr_ioapic_registers[apic] = reg_01.bits.entries+1; | 1957 | nr_ioapic_registers[apic] = reg_01.bits.entries+1; |
| 1910 | } | 1958 | } |
| 1911 | 1959 | ||
| @@ -2045,9 +2093,9 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
| 2045 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { | 2093 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { |
| 2046 | 2094 | ||
| 2047 | /* Read the register 0 value */ | 2095 | /* Read the register 0 value */ |
| 2048 | spin_lock_irqsave(&ioapic_lock, flags); | 2096 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 2049 | reg_00.raw = io_apic_read(apic_id, 0); | 2097 | reg_00.raw = io_apic_read(apic_id, 0); |
| 2050 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2098 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 2051 | 2099 | ||
| 2052 | old_id = mp_ioapics[apic_id].apicid; | 2100 | old_id = mp_ioapics[apic_id].apicid; |
| 2053 | 2101 | ||
| @@ -2106,16 +2154,16 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
| 2106 | mp_ioapics[apic_id].apicid); | 2154 | mp_ioapics[apic_id].apicid); |
| 2107 | 2155 | ||
| 2108 | reg_00.bits.ID = mp_ioapics[apic_id].apicid; | 2156 | reg_00.bits.ID = mp_ioapics[apic_id].apicid; |
| 2109 | spin_lock_irqsave(&ioapic_lock, flags); | 2157 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 2110 | io_apic_write(apic_id, 0, reg_00.raw); | 2158 | io_apic_write(apic_id, 0, reg_00.raw); |
| 2111 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2159 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 2112 | 2160 | ||
| 2113 | /* | 2161 | /* |
| 2114 | * Sanity check | 2162 | * Sanity check |
| 2115 | */ | 2163 | */ |
| 2116 | spin_lock_irqsave(&ioapic_lock, flags); | 2164 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 2117 | reg_00.raw = io_apic_read(apic_id, 0); | 2165 | reg_00.raw = io_apic_read(apic_id, 0); |
| 2118 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2166 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 2119 | if (reg_00.bits.ID != mp_ioapics[apic_id].apicid) | 2167 | if (reg_00.bits.ID != mp_ioapics[apic_id].apicid) |
| 2120 | printk("could not set ID!\n"); | 2168 | printk("could not set ID!\n"); |
| 2121 | else | 2169 | else |
| @@ -2198,7 +2246,7 @@ static unsigned int startup_ioapic_irq(unsigned int irq) | |||
| 2198 | unsigned long flags; | 2246 | unsigned long flags; |
| 2199 | struct irq_cfg *cfg; | 2247 | struct irq_cfg *cfg; |
| 2200 | 2248 | ||
| 2201 | spin_lock_irqsave(&ioapic_lock, flags); | 2249 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 2202 | if (irq < nr_legacy_irqs) { | 2250 | if (irq < nr_legacy_irqs) { |
| 2203 | disable_8259A_irq(irq); | 2251 | disable_8259A_irq(irq); |
| 2204 | if (i8259A_irq_pending(irq)) | 2252 | if (i8259A_irq_pending(irq)) |
| @@ -2206,7 +2254,7 @@ static unsigned int startup_ioapic_irq(unsigned int irq) | |||
| 2206 | } | 2254 | } |
| 2207 | cfg = irq_cfg(irq); | 2255 | cfg = irq_cfg(irq); |
| 2208 | __unmask_IO_APIC_irq(cfg); | 2256 | __unmask_IO_APIC_irq(cfg); |
| 2209 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2257 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 2210 | 2258 | ||
| 2211 | return was_pending; | 2259 | return was_pending; |
| 2212 | } | 2260 | } |
| @@ -2217,9 +2265,9 @@ static int ioapic_retrigger_irq(unsigned int irq) | |||
| 2217 | struct irq_cfg *cfg = irq_cfg(irq); | 2265 | struct irq_cfg *cfg = irq_cfg(irq); |
| 2218 | unsigned long flags; | 2266 | unsigned long flags; |
| 2219 | 2267 | ||
| 2220 | spin_lock_irqsave(&vector_lock, flags); | 2268 | raw_spin_lock_irqsave(&vector_lock, flags); |
| 2221 | apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector); | 2269 | apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector); |
| 2222 | spin_unlock_irqrestore(&vector_lock, flags); | 2270 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
| 2223 | 2271 | ||
| 2224 | return 1; | 2272 | return 1; |
| 2225 | } | 2273 | } |
| @@ -2312,14 +2360,14 @@ set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | |||
| 2312 | irq = desc->irq; | 2360 | irq = desc->irq; |
| 2313 | cfg = desc->chip_data; | 2361 | cfg = desc->chip_data; |
| 2314 | 2362 | ||
| 2315 | spin_lock_irqsave(&ioapic_lock, flags); | 2363 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 2316 | ret = set_desc_affinity(desc, mask, &dest); | 2364 | ret = set_desc_affinity(desc, mask, &dest); |
| 2317 | if (!ret) { | 2365 | if (!ret) { |
| 2318 | /* Only the high 8 bits are valid. */ | 2366 | /* Only the high 8 bits are valid. */ |
| 2319 | dest = SET_APIC_LOGICAL_ID(dest); | 2367 | dest = SET_APIC_LOGICAL_ID(dest); |
| 2320 | __target_IO_APIC_irq(irq, dest, cfg); | 2368 | __target_IO_APIC_irq(irq, dest, cfg); |
| 2321 | } | 2369 | } |
| 2322 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2370 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 2323 | 2371 | ||
| 2324 | return ret; | 2372 | return ret; |
| 2325 | } | 2373 | } |
| @@ -2554,9 +2602,9 @@ static void eoi_ioapic_irq(struct irq_desc *desc) | |||
| 2554 | irq = desc->irq; | 2602 | irq = desc->irq; |
| 2555 | cfg = desc->chip_data; | 2603 | cfg = desc->chip_data; |
| 2556 | 2604 | ||
| 2557 | spin_lock_irqsave(&ioapic_lock, flags); | 2605 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 2558 | __eoi_ioapic_irq(irq, cfg); | 2606 | __eoi_ioapic_irq(irq, cfg); |
| 2559 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2607 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 2560 | } | 2608 | } |
| 2561 | 2609 | ||
| 2562 | static void ack_apic_level(unsigned int irq) | 2610 | static void ack_apic_level(unsigned int irq) |
| @@ -3138,13 +3186,13 @@ static int ioapic_resume(struct sys_device *dev) | |||
| 3138 | data = container_of(dev, struct sysfs_ioapic_data, dev); | 3186 | data = container_of(dev, struct sysfs_ioapic_data, dev); |
| 3139 | entry = data->entry; | 3187 | entry = data->entry; |
| 3140 | 3188 | ||
| 3141 | spin_lock_irqsave(&ioapic_lock, flags); | 3189 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 3142 | reg_00.raw = io_apic_read(dev->id, 0); | 3190 | reg_00.raw = io_apic_read(dev->id, 0); |
| 3143 | if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) { | 3191 | if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) { |
| 3144 | reg_00.bits.ID = mp_ioapics[dev->id].apicid; | 3192 | reg_00.bits.ID = mp_ioapics[dev->id].apicid; |
| 3145 | io_apic_write(dev->id, 0, reg_00.raw); | 3193 | io_apic_write(dev->id, 0, reg_00.raw); |
| 3146 | } | 3194 | } |
| 3147 | spin_unlock_irqrestore(&ioapic_lock, flags); | 3195 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 3148 | for (i = 0; i < nr_ioapic_registers[dev->id]; i++) | 3196 | for (i = 0; i < nr_ioapic_registers[dev->id]; i++) |
| 3149 | ioapic_write_entry(dev->id, i, entry[i]); | 3197 | ioapic_write_entry(dev->id, i, entry[i]); |
| 3150 | 3198 | ||
| @@ -3207,7 +3255,7 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) | |||
| 3207 | if (irq_want < nr_irqs_gsi) | 3255 | if (irq_want < nr_irqs_gsi) |
| 3208 | irq_want = nr_irqs_gsi; | 3256 | irq_want = nr_irqs_gsi; |
| 3209 | 3257 | ||
| 3210 | spin_lock_irqsave(&vector_lock, flags); | 3258 | raw_spin_lock_irqsave(&vector_lock, flags); |
| 3211 | for (new = irq_want; new < nr_irqs; new++) { | 3259 | for (new = irq_want; new < nr_irqs; new++) { |
| 3212 | desc_new = irq_to_desc_alloc_node(new, node); | 3260 | desc_new = irq_to_desc_alloc_node(new, node); |
| 3213 | if (!desc_new) { | 3261 | if (!desc_new) { |
| @@ -3226,14 +3274,11 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) | |||
| 3226 | irq = new; | 3274 | irq = new; |
| 3227 | break; | 3275 | break; |
| 3228 | } | 3276 | } |
| 3229 | spin_unlock_irqrestore(&vector_lock, flags); | 3277 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
| 3278 | |||
| 3279 | if (irq > 0) | ||
| 3280 | dynamic_irq_init_keep_chip_data(irq); | ||
| 3230 | 3281 | ||
| 3231 | if (irq > 0) { | ||
| 3232 | dynamic_irq_init(irq); | ||
| 3233 | /* restore it, in case dynamic_irq_init clear it */ | ||
| 3234 | if (desc_new) | ||
| 3235 | desc_new->chip_data = cfg_new; | ||
| 3236 | } | ||
| 3237 | return irq; | 3282 | return irq; |
| 3238 | } | 3283 | } |
| 3239 | 3284 | ||
| @@ -3255,20 +3300,13 @@ int create_irq(void) | |||
| 3255 | void destroy_irq(unsigned int irq) | 3300 | void destroy_irq(unsigned int irq) |
| 3256 | { | 3301 | { |
| 3257 | unsigned long flags; | 3302 | unsigned long flags; |
| 3258 | struct irq_cfg *cfg; | ||
| 3259 | struct irq_desc *desc; | ||
| 3260 | 3303 | ||
| 3261 | /* store it, in case dynamic_irq_cleanup clear it */ | 3304 | dynamic_irq_cleanup_keep_chip_data(irq); |
| 3262 | desc = irq_to_desc(irq); | ||
| 3263 | cfg = desc->chip_data; | ||
| 3264 | dynamic_irq_cleanup(irq); | ||
| 3265 | /* connect back irq_cfg */ | ||
| 3266 | desc->chip_data = cfg; | ||
| 3267 | 3305 | ||
| 3268 | free_irte(irq); | 3306 | free_irte(irq); |
| 3269 | spin_lock_irqsave(&vector_lock, flags); | 3307 | raw_spin_lock_irqsave(&vector_lock, flags); |
| 3270 | __clear_irq_vector(irq, cfg); | 3308 | __clear_irq_vector(irq, get_irq_chip_data(irq)); |
| 3271 | spin_unlock_irqrestore(&vector_lock, flags); | 3309 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
| 3272 | } | 3310 | } |
| 3273 | 3311 | ||
| 3274 | /* | 3312 | /* |
| @@ -3805,9 +3843,9 @@ int __init io_apic_get_redir_entries (int ioapic) | |||
| 3805 | union IO_APIC_reg_01 reg_01; | 3843 | union IO_APIC_reg_01 reg_01; |
| 3806 | unsigned long flags; | 3844 | unsigned long flags; |
| 3807 | 3845 | ||
| 3808 | spin_lock_irqsave(&ioapic_lock, flags); | 3846 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 3809 | reg_01.raw = io_apic_read(ioapic, 1); | 3847 | reg_01.raw = io_apic_read(ioapic, 1); |
| 3810 | spin_unlock_irqrestore(&ioapic_lock, flags); | 3848 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 3811 | 3849 | ||
| 3812 | return reg_01.bits.entries; | 3850 | return reg_01.bits.entries; |
| 3813 | } | 3851 | } |
| @@ -3969,9 +4007,9 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id) | |||
| 3969 | if (physids_empty(apic_id_map)) | 4007 | if (physids_empty(apic_id_map)) |
| 3970 | apic->ioapic_phys_id_map(&phys_cpu_present_map, &apic_id_map); | 4008 | apic->ioapic_phys_id_map(&phys_cpu_present_map, &apic_id_map); |
| 3971 | 4009 | ||
| 3972 | spin_lock_irqsave(&ioapic_lock, flags); | 4010 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 3973 | reg_00.raw = io_apic_read(ioapic, 0); | 4011 | reg_00.raw = io_apic_read(ioapic, 0); |
| 3974 | spin_unlock_irqrestore(&ioapic_lock, flags); | 4012 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 3975 | 4013 | ||
| 3976 | if (apic_id >= get_physical_broadcast()) { | 4014 | if (apic_id >= get_physical_broadcast()) { |
| 3977 | printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " | 4015 | printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " |
| @@ -4005,10 +4043,10 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id) | |||
| 4005 | if (reg_00.bits.ID != apic_id) { | 4043 | if (reg_00.bits.ID != apic_id) { |
| 4006 | reg_00.bits.ID = apic_id; | 4044 | reg_00.bits.ID = apic_id; |
| 4007 | 4045 | ||
| 4008 | spin_lock_irqsave(&ioapic_lock, flags); | 4046 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 4009 | io_apic_write(ioapic, 0, reg_00.raw); | 4047 | io_apic_write(ioapic, 0, reg_00.raw); |
| 4010 | reg_00.raw = io_apic_read(ioapic, 0); | 4048 | reg_00.raw = io_apic_read(ioapic, 0); |
| 4011 | spin_unlock_irqrestore(&ioapic_lock, flags); | 4049 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 4012 | 4050 | ||
| 4013 | /* Sanity check */ | 4051 | /* Sanity check */ |
| 4014 | if (reg_00.bits.ID != apic_id) { | 4052 | if (reg_00.bits.ID != apic_id) { |
| @@ -4029,9 +4067,9 @@ int __init io_apic_get_version(int ioapic) | |||
| 4029 | union IO_APIC_reg_01 reg_01; | 4067 | union IO_APIC_reg_01 reg_01; |
| 4030 | unsigned long flags; | 4068 | unsigned long flags; |
| 4031 | 4069 | ||
| 4032 | spin_lock_irqsave(&ioapic_lock, flags); | 4070 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
| 4033 | reg_01.raw = io_apic_read(ioapic, 1); | 4071 | reg_01.raw = io_apic_read(ioapic, 1); |
| 4034 | spin_unlock_irqrestore(&ioapic_lock, flags); | 4072 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
| 4035 | 4073 | ||
| 4036 | return reg_01.bits.version; | 4074 | return reg_01.bits.version; |
| 4037 | } | 4075 | } |
| @@ -4063,27 +4101,23 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | |||
| 4063 | #ifdef CONFIG_SMP | 4101 | #ifdef CONFIG_SMP |
| 4064 | void __init setup_ioapic_dest(void) | 4102 | void __init setup_ioapic_dest(void) |
| 4065 | { | 4103 | { |
| 4066 | int pin, ioapic = 0, irq, irq_entry; | 4104 | int pin, ioapic, irq, irq_entry; |
| 4067 | struct irq_desc *desc; | 4105 | struct irq_desc *desc; |
| 4068 | const struct cpumask *mask; | 4106 | const struct cpumask *mask; |
| 4069 | 4107 | ||
| 4070 | if (skip_ioapic_setup == 1) | 4108 | if (skip_ioapic_setup == 1) |
| 4071 | return; | 4109 | return; |
| 4072 | 4110 | ||
| 4073 | #ifdef CONFIG_ACPI | 4111 | for (ioapic = 0; ioapic < nr_ioapics; ioapic++) |
| 4074 | if (!acpi_disabled && acpi_ioapic) { | ||
| 4075 | ioapic = mp_find_ioapic(0); | ||
| 4076 | if (ioapic < 0) | ||
| 4077 | ioapic = 0; | ||
| 4078 | } | ||
| 4079 | #endif | ||
| 4080 | |||
| 4081 | for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { | 4112 | for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { |
| 4082 | irq_entry = find_irq_entry(ioapic, pin, mp_INT); | 4113 | irq_entry = find_irq_entry(ioapic, pin, mp_INT); |
| 4083 | if (irq_entry == -1) | 4114 | if (irq_entry == -1) |
| 4084 | continue; | 4115 | continue; |
| 4085 | irq = pin_2_irq(irq_entry, ioapic, pin); | 4116 | irq = pin_2_irq(irq_entry, ioapic, pin); |
| 4086 | 4117 | ||
| 4118 | if ((ioapic > 0) && (irq > 16)) | ||
| 4119 | continue; | ||
| 4120 | |||
| 4087 | desc = irq_to_desc(irq); | 4121 | desc = irq_to_desc(irq); |
| 4088 | 4122 | ||
| 4089 | /* | 4123 | /* |
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c index 0159a69396cb..bd7c96b5e8d8 100644 --- a/arch/x86/kernel/apic/nmi.c +++ b/arch/x86/kernel/apic/nmi.c | |||
| @@ -416,13 +416,13 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) | |||
| 416 | 416 | ||
| 417 | /* We can be called before check_nmi_watchdog, hence NULL check. */ | 417 | /* We can be called before check_nmi_watchdog, hence NULL check. */ |
| 418 | if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { | 418 | if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { |
| 419 | static DEFINE_SPINLOCK(lock); /* Serialise the printks */ | 419 | static DEFINE_RAW_SPINLOCK(lock); /* Serialise the printks */ |
| 420 | 420 | ||
| 421 | spin_lock(&lock); | 421 | raw_spin_lock(&lock); |
| 422 | printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu); | 422 | printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu); |
| 423 | show_regs(regs); | 423 | show_regs(regs); |
| 424 | dump_stack(); | 424 | dump_stack(); |
| 425 | spin_unlock(&lock); | 425 | raw_spin_unlock(&lock); |
| 426 | cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); | 426 | cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); |
| 427 | 427 | ||
| 428 | rc = 1; | 428 | rc = 1; |
| @@ -438,8 +438,8 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) | |||
| 438 | * Ayiee, looks like this CPU is stuck ... | 438 | * Ayiee, looks like this CPU is stuck ... |
| 439 | * wait a few IRQs (5 seconds) before doing the oops ... | 439 | * wait a few IRQs (5 seconds) before doing the oops ... |
| 440 | */ | 440 | */ |
| 441 | __this_cpu_inc(per_cpu_var(alert_counter)); | 441 | __this_cpu_inc(alert_counter); |
| 442 | if (__this_cpu_read(per_cpu_var(alert_counter)) == 5 * nmi_hz) | 442 | if (__this_cpu_read(alert_counter) == 5 * nmi_hz) |
| 443 | /* | 443 | /* |
| 444 | * die_nmi will return ONLY if NOTIFY_STOP happens.. | 444 | * die_nmi will return ONLY if NOTIFY_STOP happens.. |
| 445 | */ | 445 | */ |
| @@ -447,7 +447,7 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) | |||
| 447 | regs, panic_on_timeout); | 447 | regs, panic_on_timeout); |
| 448 | } else { | 448 | } else { |
| 449 | __get_cpu_var(last_irq_sum) = sum; | 449 | __get_cpu_var(last_irq_sum) = sum; |
| 450 | __this_cpu_write(per_cpu_var(alert_counter), 0); | 450 | __this_cpu_write(alert_counter, 0); |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | /* see if the nmi watchdog went off */ | 453 | /* see if the nmi watchdog went off */ |
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index 98c4665f251c..47dd856708e5 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c | |||
| @@ -225,7 +225,7 @@ static void __init smp_read_mpc_oem(struct mpc_table *mpc) | |||
| 225 | 225 | ||
| 226 | mpc_record = 0; | 226 | mpc_record = 0; |
| 227 | printk(KERN_INFO | 227 | printk(KERN_INFO |
| 228 | "Found an OEM MPC table at %8p - parsing it ... \n", oemtable); | 228 | "Found an OEM MPC table at %8p - parsing it...\n", oemtable); |
| 229 | 229 | ||
| 230 | if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) { | 230 | if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) { |
| 231 | printk(KERN_WARNING | 231 | printk(KERN_WARNING |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 21db3cbea7dc..3740c8a4eae7 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * SGI UV APIC functions (note: not an Intel compatible APIC) | 6 | * SGI UV APIC functions (note: not an Intel compatible APIC) |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. | 8 | * Copyright (C) 2007-2009 Silicon Graphics, Inc. All rights reserved. |
| 9 | */ | 9 | */ |
| 10 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
| 11 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
| @@ -20,6 +20,8 @@ | |||
| 20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
| 21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 23 | #include <linux/pci.h> | ||
| 24 | #include <linux/kdebug.h> | ||
| 23 | 25 | ||
| 24 | #include <asm/uv/uv_mmrs.h> | 26 | #include <asm/uv/uv_mmrs.h> |
| 25 | #include <asm/uv/uv_hub.h> | 27 | #include <asm/uv/uv_hub.h> |
| @@ -34,10 +36,13 @@ | |||
| 34 | 36 | ||
| 35 | DEFINE_PER_CPU(int, x2apic_extra_bits); | 37 | DEFINE_PER_CPU(int, x2apic_extra_bits); |
| 36 | 38 | ||
| 39 | #define PR_DEVEL(fmt, args...) pr_devel("%s: " fmt, __func__, args) | ||
| 40 | |||
| 37 | static enum uv_system_type uv_system_type; | 41 | static enum uv_system_type uv_system_type; |
| 38 | static u64 gru_start_paddr, gru_end_paddr; | 42 | static u64 gru_start_paddr, gru_end_paddr; |
| 39 | int uv_min_hub_revision_id; | 43 | int uv_min_hub_revision_id; |
| 40 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); | 44 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); |
| 45 | static DEFINE_SPINLOCK(uv_nmi_lock); | ||
| 41 | 46 | ||
| 42 | static inline bool is_GRU_range(u64 start, u64 end) | 47 | static inline bool is_GRU_range(u64 start, u64 end) |
| 43 | { | 48 | { |
| @@ -71,6 +76,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 71 | if (!strcmp(oem_id, "SGI")) { | 76 | if (!strcmp(oem_id, "SGI")) { |
| 72 | nodeid = early_get_nodeid(); | 77 | nodeid = early_get_nodeid(); |
| 73 | x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; | 78 | x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; |
| 79 | x86_platform.nmi_init = uv_nmi_init; | ||
| 74 | if (!strcmp(oem_table_id, "UVL")) | 80 | if (!strcmp(oem_table_id, "UVL")) |
| 75 | uv_system_type = UV_LEGACY_APIC; | 81 | uv_system_type = UV_LEGACY_APIC; |
| 76 | else if (!strcmp(oem_table_id, "UVX")) | 82 | else if (!strcmp(oem_table_id, "UVX")) |
| @@ -482,7 +488,7 @@ static void uv_heartbeat(unsigned long ignored) | |||
| 482 | 488 | ||
| 483 | static void __cpuinit uv_heartbeat_enable(int cpu) | 489 | static void __cpuinit uv_heartbeat_enable(int cpu) |
| 484 | { | 490 | { |
| 485 | if (!uv_cpu_hub_info(cpu)->scir.enabled) { | 491 | while (!uv_cpu_hub_info(cpu)->scir.enabled) { |
| 486 | struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer; | 492 | struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer; |
| 487 | 493 | ||
| 488 | uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY); | 494 | uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY); |
| @@ -490,11 +496,10 @@ static void __cpuinit uv_heartbeat_enable(int cpu) | |||
| 490 | timer->expires = jiffies + SCIR_CPU_HB_INTERVAL; | 496 | timer->expires = jiffies + SCIR_CPU_HB_INTERVAL; |
| 491 | add_timer_on(timer, cpu); | 497 | add_timer_on(timer, cpu); |
| 492 | uv_cpu_hub_info(cpu)->scir.enabled = 1; | 498 | uv_cpu_hub_info(cpu)->scir.enabled = 1; |
| 493 | } | ||
| 494 | 499 | ||
| 495 | /* check boot cpu */ | 500 | /* also ensure that boot cpu is enabled */ |
| 496 | if (!uv_cpu_hub_info(0)->scir.enabled) | 501 | cpu = 0; |
| 497 | uv_heartbeat_enable(0); | 502 | } |
| 498 | } | 503 | } |
| 499 | 504 | ||
| 500 | #ifdef CONFIG_HOTPLUG_CPU | 505 | #ifdef CONFIG_HOTPLUG_CPU |
| @@ -553,6 +558,30 @@ late_initcall(uv_init_heartbeat); | |||
| 553 | 558 | ||
| 554 | #endif /* !CONFIG_HOTPLUG_CPU */ | 559 | #endif /* !CONFIG_HOTPLUG_CPU */ |
| 555 | 560 | ||
| 561 | /* Direct Legacy VGA I/O traffic to designated IOH */ | ||
| 562 | int uv_set_vga_state(struct pci_dev *pdev, bool decode, | ||
| 563 | unsigned int command_bits, bool change_bridge) | ||
| 564 | { | ||
| 565 | int domain, bus, rc; | ||
| 566 | |||
| 567 | PR_DEVEL("devfn %x decode %d cmd %x chg_brdg %d\n", | ||
| 568 | pdev->devfn, decode, command_bits, change_bridge); | ||
| 569 | |||
| 570 | if (!change_bridge) | ||
| 571 | return 0; | ||
| 572 | |||
| 573 | if ((command_bits & PCI_COMMAND_IO) == 0) | ||
| 574 | return 0; | ||
| 575 | |||
| 576 | domain = pci_domain_nr(pdev->bus); | ||
| 577 | bus = pdev->bus->number; | ||
| 578 | |||
| 579 | rc = uv_bios_set_legacy_vga_target(decode, domain, bus); | ||
| 580 | PR_DEVEL("vga decode %d %x:%x, rc: %d\n", decode, domain, bus, rc); | ||
| 581 | |||
| 582 | return rc; | ||
| 583 | } | ||
| 584 | |||
| 556 | /* | 585 | /* |
| 557 | * Called on each cpu to initialize the per_cpu UV data area. | 586 | * Called on each cpu to initialize the per_cpu UV data area. |
| 558 | * FIXME: hotplug not supported yet | 587 | * FIXME: hotplug not supported yet |
| @@ -569,6 +598,46 @@ void __cpuinit uv_cpu_init(void) | |||
| 569 | set_x2apic_extra_bits(uv_hub_info->pnode); | 598 | set_x2apic_extra_bits(uv_hub_info->pnode); |
| 570 | } | 599 | } |
| 571 | 600 | ||
| 601 | /* | ||
| 602 | * When NMI is received, print a stack trace. | ||
| 603 | */ | ||
| 604 | int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data) | ||
| 605 | { | ||
| 606 | if (reason != DIE_NMI_IPI) | ||
| 607 | return NOTIFY_OK; | ||
| 608 | /* | ||
| 609 | * Use a lock so only one cpu prints at a time | ||
| 610 | * to prevent intermixed output. | ||
| 611 | */ | ||
| 612 | spin_lock(&uv_nmi_lock); | ||
| 613 | pr_info("NMI stack dump cpu %u:\n", smp_processor_id()); | ||
| 614 | dump_stack(); | ||
| 615 | spin_unlock(&uv_nmi_lock); | ||
| 616 | |||
| 617 | return NOTIFY_STOP; | ||
| 618 | } | ||
| 619 | |||
| 620 | static struct notifier_block uv_dump_stack_nmi_nb = { | ||
| 621 | .notifier_call = uv_handle_nmi | ||
| 622 | }; | ||
| 623 | |||
| 624 | void uv_register_nmi_notifier(void) | ||
| 625 | { | ||
| 626 | if (register_die_notifier(&uv_dump_stack_nmi_nb)) | ||
| 627 | printk(KERN_WARNING "UV NMI handler failed to register\n"); | ||
| 628 | } | ||
| 629 | |||
| 630 | void uv_nmi_init(void) | ||
| 631 | { | ||
| 632 | unsigned int value; | ||
| 633 | |||
| 634 | /* | ||
| 635 | * Unmask NMI on all cpus | ||
| 636 | */ | ||
| 637 | value = apic_read(APIC_LVT1) | APIC_DM_NMI; | ||
| 638 | value &= ~APIC_LVT_MASKED; | ||
| 639 | apic_write(APIC_LVT1, value); | ||
| 640 | } | ||
| 572 | 641 | ||
| 573 | void __init uv_system_init(void) | 642 | void __init uv_system_init(void) |
| 574 | { | 643 | { |
| @@ -634,8 +703,8 @@ void __init uv_system_init(void) | |||
| 634 | } | 703 | } |
| 635 | 704 | ||
| 636 | uv_bios_init(); | 705 | uv_bios_init(); |
| 637 | uv_bios_get_sn_info(0, &uv_type, &sn_partition_id, | 706 | uv_bios_get_sn_info(0, &uv_type, &sn_partition_id, &sn_coherency_id, |
| 638 | &sn_coherency_id, &sn_region_size); | 707 | &sn_region_size, &system_serial_number); |
| 639 | uv_rtc_init(); | 708 | uv_rtc_init(); |
| 640 | 709 | ||
| 641 | for_each_present_cpu(cpu) { | 710 | for_each_present_cpu(cpu) { |
| @@ -690,5 +759,9 @@ void __init uv_system_init(void) | |||
| 690 | 759 | ||
| 691 | uv_cpu_init(); | 760 | uv_cpu_init(); |
| 692 | uv_scir_register_cpu_notifier(); | 761 | uv_scir_register_cpu_notifier(); |
| 762 | uv_register_nmi_notifier(); | ||
| 693 | proc_mkdir("sgi_uv", NULL); | 763 | proc_mkdir("sgi_uv", NULL); |
| 764 | |||
| 765 | /* register Legacy VGA I/O redirection handler */ | ||
| 766 | pci_register_set_vga_state(uv_set_vga_state); | ||
| 694 | } | 767 | } |
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index b5b6b23bce53..031aa887b0eb 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
| @@ -1992,8 +1992,8 @@ static int __init apm_is_horked_d850md(const struct dmi_system_id *d) | |||
| 1992 | apm_info.disabled = 1; | 1992 | apm_info.disabled = 1; |
| 1993 | printk(KERN_INFO "%s machine detected. " | 1993 | printk(KERN_INFO "%s machine detected. " |
| 1994 | "Disabling APM.\n", d->ident); | 1994 | "Disabling APM.\n", d->ident); |
| 1995 | printk(KERN_INFO "This bug is fixed in bios P15 which is available for \n"); | 1995 | printk(KERN_INFO "This bug is fixed in bios P15 which is available for\n"); |
| 1996 | printk(KERN_INFO "download from support.intel.com \n"); | 1996 | printk(KERN_INFO "download from support.intel.com\n"); |
| 1997 | } | 1997 | } |
| 1998 | return 0; | 1998 | return 0; |
| 1999 | } | 1999 | } |
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c index b0206a211b09..8bc57baaa9ad 100644 --- a/arch/x86/kernel/bios_uv.c +++ b/arch/x86/kernel/bios_uv.c | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 | * | 17 | * |
| 18 | * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. | 18 | * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved. |
| 19 | * Copyright (c) Russ Anderson | 19 | * Copyright (c) Russ Anderson <rja@sgi.com> |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/efi.h> | 22 | #include <linux/efi.h> |
| @@ -30,6 +30,7 @@ static struct uv_systab uv_systab; | |||
| 30 | s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5) | 30 | s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5) |
| 31 | { | 31 | { |
| 32 | struct uv_systab *tab = &uv_systab; | 32 | struct uv_systab *tab = &uv_systab; |
| 33 | s64 ret; | ||
| 33 | 34 | ||
| 34 | if (!tab->function) | 35 | if (!tab->function) |
| 35 | /* | 36 | /* |
| @@ -37,9 +38,11 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5) | |||
| 37 | */ | 38 | */ |
| 38 | return BIOS_STATUS_UNIMPLEMENTED; | 39 | return BIOS_STATUS_UNIMPLEMENTED; |
| 39 | 40 | ||
| 40 | return efi_call6((void *)__va(tab->function), | 41 | ret = efi_call6((void *)__va(tab->function), (u64)which, |
| 41 | (u64)which, a1, a2, a3, a4, a5); | 42 | a1, a2, a3, a4, a5); |
| 43 | return ret; | ||
| 42 | } | 44 | } |
| 45 | EXPORT_SYMBOL_GPL(uv_bios_call); | ||
| 43 | 46 | ||
| 44 | s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, | 47 | s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, |
| 45 | u64 a4, u64 a5) | 48 | u64 a4, u64 a5) |
| @@ -73,11 +76,14 @@ long sn_coherency_id; | |||
| 73 | EXPORT_SYMBOL_GPL(sn_coherency_id); | 76 | EXPORT_SYMBOL_GPL(sn_coherency_id); |
| 74 | long sn_region_size; | 77 | long sn_region_size; |
| 75 | EXPORT_SYMBOL_GPL(sn_region_size); | 78 | EXPORT_SYMBOL_GPL(sn_region_size); |
| 79 | long system_serial_number; | ||
| 80 | EXPORT_SYMBOL_GPL(system_serial_number); | ||
| 76 | int uv_type; | 81 | int uv_type; |
| 82 | EXPORT_SYMBOL_GPL(uv_type); | ||
| 77 | 83 | ||
| 78 | 84 | ||
| 79 | s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher, | 85 | s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher, |
| 80 | long *region) | 86 | long *region, long *ssn) |
| 81 | { | 87 | { |
| 82 | s64 ret; | 88 | s64 ret; |
| 83 | u64 v0, v1; | 89 | u64 v0, v1; |
| @@ -97,8 +103,11 @@ s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher, | |||
| 97 | *coher = part.coherence_id; | 103 | *coher = part.coherence_id; |
| 98 | if (region) | 104 | if (region) |
| 99 | *region = part.region_size; | 105 | *region = part.region_size; |
| 106 | if (ssn) | ||
| 107 | *ssn = v1; | ||
| 100 | return ret; | 108 | return ret; |
| 101 | } | 109 | } |
| 110 | EXPORT_SYMBOL_GPL(uv_bios_get_sn_info); | ||
| 102 | 111 | ||
| 103 | int | 112 | int |
| 104 | uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size, | 113 | uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size, |
| @@ -154,6 +163,25 @@ s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second) | |||
| 154 | } | 163 | } |
| 155 | EXPORT_SYMBOL_GPL(uv_bios_freq_base); | 164 | EXPORT_SYMBOL_GPL(uv_bios_freq_base); |
| 156 | 165 | ||
| 166 | /* | ||
| 167 | * uv_bios_set_legacy_vga_target - Set Legacy VGA I/O Target | ||
| 168 | * @decode: true to enable target, false to disable target | ||
| 169 | * @domain: PCI domain number | ||
| 170 | * @bus: PCI bus number | ||
| 171 | * | ||
| 172 | * Returns: | ||
| 173 | * 0: Success | ||
| 174 | * -EINVAL: Invalid domain or bus number | ||
| 175 | * -ENOSYS: Capability not available | ||
| 176 | * -EBUSY: Legacy VGA I/O cannot be retargeted at this time | ||
| 177 | */ | ||
| 178 | int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus) | ||
| 179 | { | ||
| 180 | return uv_bios_call(UV_BIOS_SET_LEGACY_VGA_TARGET, | ||
| 181 | (u64)decode, (u64)domain, (u64)bus, 0, 0); | ||
| 182 | } | ||
| 183 | EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); | ||
| 184 | |||
| 157 | 185 | ||
| 158 | #ifdef CONFIG_EFI | 186 | #ifdef CONFIG_EFI |
| 159 | void uv_bios_init(void) | 187 | void uv_bios_init(void) |
| @@ -185,4 +213,3 @@ void uv_bios_init(void) | |||
| 185 | 213 | ||
| 186 | void uv_bios_init(void) { } | 214 | void uv_bios_init(void) { } |
| 187 | #endif | 215 | #endif |
| 188 | |||
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 468489b57aae..97ad79cdf688 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c | |||
| @@ -32,6 +32,10 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
| 32 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { | 32 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { |
| 33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, | 33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, |
| 34 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, | 34 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, |
| 35 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, | ||
| 36 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, | ||
| 37 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, | ||
| 38 | { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a }, | ||
| 35 | { 0, 0, 0, 0 } | 39 | { 0, 0, 0, 0 } |
| 36 | }; | 40 | }; |
| 37 | 41 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 6e44519960c8..d360b56e9825 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
| @@ -806,7 +806,7 @@ static int find_psb_table(struct powernow_k8_data *data) | |||
| 806 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, | 806 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, |
| 807 | unsigned int index) | 807 | unsigned int index) |
| 808 | { | 808 | { |
| 809 | acpi_integer control; | 809 | u64 control; |
| 810 | 810 | ||
| 811 | if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) | 811 | if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) |
| 812 | return; | 812 | return; |
| @@ -824,7 +824,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | |||
| 824 | { | 824 | { |
| 825 | struct cpufreq_frequency_table *powernow_table; | 825 | struct cpufreq_frequency_table *powernow_table; |
| 826 | int ret_val = -ENODEV; | 826 | int ret_val = -ENODEV; |
| 827 | acpi_integer control, status; | 827 | u64 control, status; |
| 828 | 828 | ||
| 829 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { | 829 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { |
| 830 | dprintk("register performance failed: bad ACPI data\n"); | 830 | dprintk("register performance failed: bad ACPI data\n"); |
| @@ -948,7 +948,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, | |||
| 948 | u32 fid; | 948 | u32 fid; |
| 949 | u32 vid; | 949 | u32 vid; |
| 950 | u32 freq, index; | 950 | u32 freq, index; |
| 951 | acpi_integer status, control; | 951 | u64 status, control; |
| 952 | 952 | ||
| 953 | if (data->exttype) { | 953 | if (data->exttype) { |
| 954 | status = data->acpi_data.states[i].status; | 954 | status = data->acpi_data.states[i].status; |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index fc6c8ef92dcc..eddb1bdd1b8f 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
| 19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
| 20 | #include <asm/k8.h> | 20 | #include <asm/k8.h> |
| 21 | #include <asm/smp.h> | ||
| 21 | 22 | ||
| 22 | #define LVL_1_INST 1 | 23 | #define LVL_1_INST 1 |
| 23 | #define LVL_1_DATA 2 | 24 | #define LVL_1_DATA 2 |
| @@ -31,6 +32,8 @@ struct _cache_table { | |||
| 31 | short size; | 32 | short size; |
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 35 | #define MB(x) ((x) * 1024) | ||
| 36 | |||
| 34 | /* All the cache descriptor types we care about (no TLB or | 37 | /* All the cache descriptor types we care about (no TLB or |
| 35 | trace cache entries) */ | 38 | trace cache entries) */ |
| 36 | 39 | ||
| @@ -44,9 +47,9 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
| 44 | { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ | 47 | { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ |
| 45 | { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ | 48 | { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ |
| 46 | { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 49 | { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
| 47 | { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 50 | { 0x23, LVL_3, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 48 | { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 51 | { 0x25, LVL_3, MB(2) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 49 | { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 52 | { 0x29, LVL_3, MB(4) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 50 | { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ | 53 | { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ |
| 51 | { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ | 54 | { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ |
| 52 | { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 55 | { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
| @@ -59,16 +62,16 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
| 59 | { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ | 62 | { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ |
| 60 | { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ | 63 | { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ |
| 61 | { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ | 64 | { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ |
| 62 | { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */ | 65 | { 0x44, LVL_2, MB(1) }, /* 4-way set assoc, 32 byte line size */ |
| 63 | { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */ | 66 | { 0x45, LVL_2, MB(2) }, /* 4-way set assoc, 32 byte line size */ |
| 64 | { 0x46, LVL_3, 4096 }, /* 4-way set assoc, 64 byte line size */ | 67 | { 0x46, LVL_3, MB(4) }, /* 4-way set assoc, 64 byte line size */ |
| 65 | { 0x47, LVL_3, 8192 }, /* 8-way set assoc, 64 byte line size */ | 68 | { 0x47, LVL_3, MB(8) }, /* 8-way set assoc, 64 byte line size */ |
| 66 | { 0x49, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ | 69 | { 0x49, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */ |
| 67 | { 0x4a, LVL_3, 6144 }, /* 12-way set assoc, 64 byte line size */ | 70 | { 0x4a, LVL_3, MB(6) }, /* 12-way set assoc, 64 byte line size */ |
| 68 | { 0x4b, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ | 71 | { 0x4b, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */ |
| 69 | { 0x4c, LVL_3, 12288 }, /* 12-way set assoc, 64 byte line size */ | 72 | { 0x4c, LVL_3, MB(12) }, /* 12-way set assoc, 64 byte line size */ |
| 70 | { 0x4d, LVL_3, 16384 }, /* 16-way set assoc, 64 byte line size */ | 73 | { 0x4d, LVL_3, MB(16) }, /* 16-way set assoc, 64 byte line size */ |
| 71 | { 0x4e, LVL_2, 6144 }, /* 24-way set assoc, 64 byte line size */ | 74 | { 0x4e, LVL_2, MB(6) }, /* 24-way set assoc, 64 byte line size */ |
| 72 | { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 75 | { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 73 | { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 76 | { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
| 74 | { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 77 | { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
| @@ -77,34 +80,34 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
| 77 | { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ | 80 | { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ |
| 78 | { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ | 81 | { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ |
| 79 | { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */ | 82 | { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */ |
| 80 | { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */ | 83 | { 0x78, LVL_2, MB(1) }, /* 4-way set assoc, 64 byte line size */ |
| 81 | { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 84 | { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 82 | { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 85 | { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 83 | { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 86 | { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 84 | { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 87 | { 0x7c, LVL_2, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
| 85 | { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */ | 88 | { 0x7d, LVL_2, MB(2) }, /* 8-way set assoc, 64 byte line size */ |
| 86 | { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ | 89 | { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ |
| 87 | { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ | 90 | { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ |
| 88 | { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ | 91 | { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ |
| 89 | { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */ | 92 | { 0x84, LVL_2, MB(1) }, /* 8-way set assoc, 32 byte line size */ |
| 90 | { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */ | 93 | { 0x85, LVL_2, MB(2) }, /* 8-way set assoc, 32 byte line size */ |
| 91 | { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ | 94 | { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ |
| 92 | { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */ | 95 | { 0x87, LVL_2, MB(1) }, /* 8-way set assoc, 64 byte line size */ |
| 93 | { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */ | 96 | { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */ |
| 94 | { 0xd1, LVL_3, 1024 }, /* 4-way set assoc, 64 byte line size */ | 97 | { 0xd1, LVL_3, MB(1) }, /* 4-way set assoc, 64 byte line size */ |
| 95 | { 0xd2, LVL_3, 2048 }, /* 4-way set assoc, 64 byte line size */ | 98 | { 0xd2, LVL_3, MB(2) }, /* 4-way set assoc, 64 byte line size */ |
| 96 | { 0xd6, LVL_3, 1024 }, /* 8-way set assoc, 64 byte line size */ | 99 | { 0xd6, LVL_3, MB(1) }, /* 8-way set assoc, 64 byte line size */ |
| 97 | { 0xd7, LVL_3, 2048 }, /* 8-way set assoc, 64 byte line size */ | 100 | { 0xd7, LVL_3, MB(2) }, /* 8-way set assoc, 64 byte line size */ |
| 98 | { 0xd8, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ | 101 | { 0xd8, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */ |
| 99 | { 0xdc, LVL_3, 2048 }, /* 12-way set assoc, 64 byte line size */ | 102 | { 0xdc, LVL_3, MB(2) }, /* 12-way set assoc, 64 byte line size */ |
| 100 | { 0xdd, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ | 103 | { 0xdd, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */ |
| 101 | { 0xde, LVL_3, 8192 }, /* 12-way set assoc, 64 byte line size */ | 104 | { 0xde, LVL_3, MB(8) }, /* 12-way set assoc, 64 byte line size */ |
| 102 | { 0xe2, LVL_3, 2048 }, /* 16-way set assoc, 64 byte line size */ | 105 | { 0xe2, LVL_3, MB(2) }, /* 16-way set assoc, 64 byte line size */ |
| 103 | { 0xe3, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ | 106 | { 0xe3, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */ |
| 104 | { 0xe4, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ | 107 | { 0xe4, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */ |
| 105 | { 0xea, LVL_3, 12288 }, /* 24-way set assoc, 64 byte line size */ | 108 | { 0xea, LVL_3, MB(12) }, /* 24-way set assoc, 64 byte line size */ |
| 106 | { 0xeb, LVL_3, 18432 }, /* 24-way set assoc, 64 byte line size */ | 109 | { 0xeb, LVL_3, MB(18) }, /* 24-way set assoc, 64 byte line size */ |
| 107 | { 0xec, LVL_3, 24576 }, /* 24-way set assoc, 64 byte line size */ | 110 | { 0xec, LVL_3, MB(24) }, /* 24-way set assoc, 64 byte line size */ |
| 108 | { 0x00, 0, 0} | 111 | { 0x00, 0, 0} |
| 109 | }; | 112 | }; |
| 110 | 113 | ||
| @@ -150,7 +153,8 @@ struct _cpuid4_info { | |||
| 150 | union _cpuid4_leaf_ebx ebx; | 153 | union _cpuid4_leaf_ebx ebx; |
| 151 | union _cpuid4_leaf_ecx ecx; | 154 | union _cpuid4_leaf_ecx ecx; |
| 152 | unsigned long size; | 155 | unsigned long size; |
| 153 | unsigned long can_disable; | 156 | bool can_disable; |
| 157 | unsigned int l3_indices; | ||
| 154 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); | 158 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); |
| 155 | }; | 159 | }; |
| 156 | 160 | ||
| @@ -160,7 +164,8 @@ struct _cpuid4_info_regs { | |||
| 160 | union _cpuid4_leaf_ebx ebx; | 164 | union _cpuid4_leaf_ebx ebx; |
| 161 | union _cpuid4_leaf_ecx ecx; | 165 | union _cpuid4_leaf_ecx ecx; |
| 162 | unsigned long size; | 166 | unsigned long size; |
| 163 | unsigned long can_disable; | 167 | bool can_disable; |
| 168 | unsigned int l3_indices; | ||
| 164 | }; | 169 | }; |
| 165 | 170 | ||
| 166 | unsigned short num_cache_leaves; | 171 | unsigned short num_cache_leaves; |
| @@ -290,6 +295,36 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, | |||
| 290 | (ebx->split.ways_of_associativity + 1) - 1; | 295 | (ebx->split.ways_of_associativity + 1) - 1; |
| 291 | } | 296 | } |
| 292 | 297 | ||
| 298 | struct _cache_attr { | ||
| 299 | struct attribute attr; | ||
| 300 | ssize_t (*show)(struct _cpuid4_info *, char *); | ||
| 301 | ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count); | ||
| 302 | }; | ||
| 303 | |||
| 304 | #ifdef CONFIG_CPU_SUP_AMD | ||
| 305 | static unsigned int __cpuinit amd_calc_l3_indices(void) | ||
| 306 | { | ||
| 307 | /* | ||
| 308 | * We're called over smp_call_function_single() and therefore | ||
| 309 | * are on the correct cpu. | ||
| 310 | */ | ||
| 311 | int cpu = smp_processor_id(); | ||
| 312 | int node = cpu_to_node(cpu); | ||
| 313 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
| 314 | unsigned int sc0, sc1, sc2, sc3; | ||
| 315 | u32 val = 0; | ||
| 316 | |||
| 317 | pci_read_config_dword(dev, 0x1C4, &val); | ||
| 318 | |||
| 319 | /* calculate subcache sizes */ | ||
| 320 | sc0 = !(val & BIT(0)); | ||
| 321 | sc1 = !(val & BIT(4)); | ||
| 322 | sc2 = !(val & BIT(8)) + !(val & BIT(9)); | ||
| 323 | sc3 = !(val & BIT(12)) + !(val & BIT(13)); | ||
| 324 | |||
| 325 | return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; | ||
| 326 | } | ||
| 327 | |||
| 293 | static void __cpuinit | 328 | static void __cpuinit |
| 294 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | 329 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) |
| 295 | { | 330 | { |
| @@ -299,12 +334,103 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | |||
| 299 | if (boot_cpu_data.x86 == 0x11) | 334 | if (boot_cpu_data.x86 == 0x11) |
| 300 | return; | 335 | return; |
| 301 | 336 | ||
| 302 | /* see erratum #382 */ | 337 | /* see errata #382 and #388 */ |
| 303 | if ((boot_cpu_data.x86 == 0x10) && (boot_cpu_data.x86_model < 0x8)) | 338 | if ((boot_cpu_data.x86 == 0x10) && |
| 339 | ((boot_cpu_data.x86_model < 0x8) || | ||
| 340 | (boot_cpu_data.x86_mask < 0x1))) | ||
| 304 | return; | 341 | return; |
| 305 | 342 | ||
| 306 | this_leaf->can_disable = 1; | 343 | this_leaf->can_disable = true; |
| 344 | this_leaf->l3_indices = amd_calc_l3_indices(); | ||
| 345 | } | ||
| 346 | |||
| 347 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | ||
| 348 | unsigned int index) | ||
| 349 | { | ||
| 350 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
| 351 | int node = amd_get_nb_id(cpu); | ||
| 352 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
| 353 | unsigned int reg = 0; | ||
| 354 | |||
| 355 | if (!this_leaf->can_disable) | ||
| 356 | return -EINVAL; | ||
| 357 | |||
| 358 | if (!dev) | ||
| 359 | return -EINVAL; | ||
| 360 | |||
| 361 | pci_read_config_dword(dev, 0x1BC + index * 4, ®); | ||
| 362 | return sprintf(buf, "0x%08x\n", reg); | ||
| 363 | } | ||
| 364 | |||
| 365 | #define SHOW_CACHE_DISABLE(index) \ | ||
| 366 | static ssize_t \ | ||
| 367 | show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \ | ||
| 368 | { \ | ||
| 369 | return show_cache_disable(this_leaf, buf, index); \ | ||
| 307 | } | 370 | } |
| 371 | SHOW_CACHE_DISABLE(0) | ||
| 372 | SHOW_CACHE_DISABLE(1) | ||
| 373 | |||
| 374 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | ||
| 375 | const char *buf, size_t count, unsigned int index) | ||
| 376 | { | ||
| 377 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
| 378 | int node = amd_get_nb_id(cpu); | ||
| 379 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
| 380 | unsigned long val = 0; | ||
| 381 | |||
| 382 | #define SUBCACHE_MASK (3UL << 20) | ||
| 383 | #define SUBCACHE_INDEX 0xfff | ||
| 384 | |||
| 385 | if (!this_leaf->can_disable) | ||
| 386 | return -EINVAL; | ||
| 387 | |||
| 388 | if (!capable(CAP_SYS_ADMIN)) | ||
| 389 | return -EPERM; | ||
| 390 | |||
| 391 | if (!dev) | ||
| 392 | return -EINVAL; | ||
| 393 | |||
| 394 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 395 | return -EINVAL; | ||
| 396 | |||
| 397 | /* do not allow writes outside of allowed bits */ | ||
| 398 | if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || | ||
| 399 | ((val & SUBCACHE_INDEX) > this_leaf->l3_indices)) | ||
| 400 | return -EINVAL; | ||
| 401 | |||
| 402 | val |= BIT(30); | ||
| 403 | pci_write_config_dword(dev, 0x1BC + index * 4, val); | ||
| 404 | /* | ||
| 405 | * We need to WBINVD on a core on the node containing the L3 cache which | ||
| 406 | * indices we disable therefore a simple wbinvd() is not sufficient. | ||
| 407 | */ | ||
| 408 | wbinvd_on_cpu(cpu); | ||
| 409 | pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31)); | ||
| 410 | return count; | ||
| 411 | } | ||
| 412 | |||
| 413 | #define STORE_CACHE_DISABLE(index) \ | ||
| 414 | static ssize_t \ | ||
| 415 | store_cache_disable_##index(struct _cpuid4_info *this_leaf, \ | ||
| 416 | const char *buf, size_t count) \ | ||
| 417 | { \ | ||
| 418 | return store_cache_disable(this_leaf, buf, count, index); \ | ||
| 419 | } | ||
| 420 | STORE_CACHE_DISABLE(0) | ||
| 421 | STORE_CACHE_DISABLE(1) | ||
| 422 | |||
| 423 | static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644, | ||
| 424 | show_cache_disable_0, store_cache_disable_0); | ||
| 425 | static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | ||
| 426 | show_cache_disable_1, store_cache_disable_1); | ||
| 427 | |||
| 428 | #else /* CONFIG_CPU_SUP_AMD */ | ||
| 429 | static void __cpuinit | ||
| 430 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | ||
| 431 | { | ||
| 432 | }; | ||
| 433 | #endif /* CONFIG_CPU_SUP_AMD */ | ||
| 308 | 434 | ||
| 309 | static int | 435 | static int |
| 310 | __cpuinit cpuid4_cache_lookup_regs(int index, | 436 | __cpuinit cpuid4_cache_lookup_regs(int index, |
| @@ -711,82 +837,6 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) | |||
| 711 | #define to_object(k) container_of(k, struct _index_kobject, kobj) | 837 | #define to_object(k) container_of(k, struct _index_kobject, kobj) |
| 712 | #define to_attr(a) container_of(a, struct _cache_attr, attr) | 838 | #define to_attr(a) container_of(a, struct _cache_attr, attr) |
| 713 | 839 | ||
| 714 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | ||
| 715 | unsigned int index) | ||
| 716 | { | ||
| 717 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
| 718 | int node = cpu_to_node(cpu); | ||
| 719 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
| 720 | unsigned int reg = 0; | ||
| 721 | |||
| 722 | if (!this_leaf->can_disable) | ||
| 723 | return -EINVAL; | ||
| 724 | |||
| 725 | if (!dev) | ||
| 726 | return -EINVAL; | ||
| 727 | |||
| 728 | pci_read_config_dword(dev, 0x1BC + index * 4, ®); | ||
| 729 | return sprintf(buf, "%x\n", reg); | ||
| 730 | } | ||
| 731 | |||
| 732 | #define SHOW_CACHE_DISABLE(index) \ | ||
| 733 | static ssize_t \ | ||
| 734 | show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \ | ||
| 735 | { \ | ||
| 736 | return show_cache_disable(this_leaf, buf, index); \ | ||
| 737 | } | ||
| 738 | SHOW_CACHE_DISABLE(0) | ||
| 739 | SHOW_CACHE_DISABLE(1) | ||
| 740 | |||
| 741 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | ||
| 742 | const char *buf, size_t count, unsigned int index) | ||
| 743 | { | ||
| 744 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
| 745 | int node = cpu_to_node(cpu); | ||
| 746 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
| 747 | unsigned long val = 0; | ||
| 748 | unsigned int scrubber = 0; | ||
| 749 | |||
| 750 | if (!this_leaf->can_disable) | ||
| 751 | return -EINVAL; | ||
| 752 | |||
| 753 | if (!capable(CAP_SYS_ADMIN)) | ||
| 754 | return -EPERM; | ||
| 755 | |||
| 756 | if (!dev) | ||
| 757 | return -EINVAL; | ||
| 758 | |||
| 759 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 760 | return -EINVAL; | ||
| 761 | |||
| 762 | val |= 0xc0000000; | ||
| 763 | |||
| 764 | pci_read_config_dword(dev, 0x58, &scrubber); | ||
| 765 | scrubber &= ~0x1f000000; | ||
| 766 | pci_write_config_dword(dev, 0x58, scrubber); | ||
| 767 | |||
| 768 | pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); | ||
| 769 | wbinvd(); | ||
| 770 | pci_write_config_dword(dev, 0x1BC + index * 4, val); | ||
| 771 | return count; | ||
| 772 | } | ||
| 773 | |||
| 774 | #define STORE_CACHE_DISABLE(index) \ | ||
| 775 | static ssize_t \ | ||
| 776 | store_cache_disable_##index(struct _cpuid4_info *this_leaf, \ | ||
| 777 | const char *buf, size_t count) \ | ||
| 778 | { \ | ||
| 779 | return store_cache_disable(this_leaf, buf, count, index); \ | ||
| 780 | } | ||
| 781 | STORE_CACHE_DISABLE(0) | ||
| 782 | STORE_CACHE_DISABLE(1) | ||
| 783 | |||
| 784 | struct _cache_attr { | ||
| 785 | struct attribute attr; | ||
| 786 | ssize_t (*show)(struct _cpuid4_info *, char *); | ||
| 787 | ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count); | ||
| 788 | }; | ||
| 789 | |||
| 790 | #define define_one_ro(_name) \ | 840 | #define define_one_ro(_name) \ |
| 791 | static struct _cache_attr _name = \ | 841 | static struct _cache_attr _name = \ |
| 792 | __ATTR(_name, 0444, show_##_name, NULL) | 842 | __ATTR(_name, 0444, show_##_name, NULL) |
| @@ -801,23 +851,28 @@ define_one_ro(size); | |||
| 801 | define_one_ro(shared_cpu_map); | 851 | define_one_ro(shared_cpu_map); |
| 802 | define_one_ro(shared_cpu_list); | 852 | define_one_ro(shared_cpu_list); |
| 803 | 853 | ||
| 804 | static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644, | 854 | #define DEFAULT_SYSFS_CACHE_ATTRS \ |
| 805 | show_cache_disable_0, store_cache_disable_0); | 855 | &type.attr, \ |
| 806 | static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | 856 | &level.attr, \ |
| 807 | show_cache_disable_1, store_cache_disable_1); | 857 | &coherency_line_size.attr, \ |
| 858 | &physical_line_partition.attr, \ | ||
| 859 | &ways_of_associativity.attr, \ | ||
| 860 | &number_of_sets.attr, \ | ||
| 861 | &size.attr, \ | ||
| 862 | &shared_cpu_map.attr, \ | ||
| 863 | &shared_cpu_list.attr | ||
| 808 | 864 | ||
| 809 | static struct attribute *default_attrs[] = { | 865 | static struct attribute *default_attrs[] = { |
| 810 | &type.attr, | 866 | DEFAULT_SYSFS_CACHE_ATTRS, |
| 811 | &level.attr, | 867 | NULL |
| 812 | &coherency_line_size.attr, | 868 | }; |
| 813 | &physical_line_partition.attr, | 869 | |
| 814 | &ways_of_associativity.attr, | 870 | static struct attribute *default_l3_attrs[] = { |
| 815 | &number_of_sets.attr, | 871 | DEFAULT_SYSFS_CACHE_ATTRS, |
| 816 | &size.attr, | 872 | #ifdef CONFIG_CPU_SUP_AMD |
| 817 | &shared_cpu_map.attr, | ||
| 818 | &shared_cpu_list.attr, | ||
| 819 | &cache_disable_0.attr, | 873 | &cache_disable_0.attr, |
| 820 | &cache_disable_1.attr, | 874 | &cache_disable_1.attr, |
| 875 | #endif | ||
| 821 | NULL | 876 | NULL |
| 822 | }; | 877 | }; |
| 823 | 878 | ||
| @@ -908,6 +963,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
| 908 | unsigned int cpu = sys_dev->id; | 963 | unsigned int cpu = sys_dev->id; |
| 909 | unsigned long i, j; | 964 | unsigned long i, j; |
| 910 | struct _index_kobject *this_object; | 965 | struct _index_kobject *this_object; |
| 966 | struct _cpuid4_info *this_leaf; | ||
| 911 | int retval; | 967 | int retval; |
| 912 | 968 | ||
| 913 | retval = cpuid4_cache_sysfs_init(cpu); | 969 | retval = cpuid4_cache_sysfs_init(cpu); |
| @@ -926,6 +982,14 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
| 926 | this_object = INDEX_KOBJECT_PTR(cpu, i); | 982 | this_object = INDEX_KOBJECT_PTR(cpu, i); |
| 927 | this_object->cpu = cpu; | 983 | this_object->cpu = cpu; |
| 928 | this_object->index = i; | 984 | this_object->index = i; |
| 985 | |||
| 986 | this_leaf = CPUID4_INFO_IDX(cpu, i); | ||
| 987 | |||
| 988 | if (this_leaf->can_disable) | ||
| 989 | ktype_cache.default_attrs = default_l3_attrs; | ||
| 990 | else | ||
| 991 | ktype_cache.default_attrs = default_attrs; | ||
| 992 | |||
| 929 | retval = kobject_init_and_add(&(this_object->kobj), | 993 | retval = kobject_init_and_add(&(this_object->kobj), |
| 930 | &ktype_cache, | 994 | &ktype_cache, |
| 931 | per_cpu(ici_cache_kobject, cpu), | 995 | per_cpu(ici_cache_kobject, cpu), |
diff --git a/arch/x86/kernel/cpu/mtrr/Makefile b/arch/x86/kernel/cpu/mtrr/Makefile index f4361b56f8e9..ad9e5ed81181 100644 --- a/arch/x86/kernel/cpu/mtrr/Makefile +++ b/arch/x86/kernel/cpu/mtrr/Makefile | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | obj-y := main.o if.o generic.o state.o cleanup.o | 1 | obj-y := main.o if.o generic.o cleanup.o |
| 2 | obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o | 2 | obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o |
| 3 | 3 | ||
diff --git a/arch/x86/kernel/cpu/mtrr/amd.c b/arch/x86/kernel/cpu/mtrr/amd.c index 33af14110dfd..92ba9cd31c9a 100644 --- a/arch/x86/kernel/cpu/mtrr/amd.c +++ b/arch/x86/kernel/cpu/mtrr/amd.c | |||
| @@ -108,7 +108,7 @@ amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type) | |||
| 108 | return 0; | 108 | return 0; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static struct mtrr_ops amd_mtrr_ops = { | 111 | static const struct mtrr_ops amd_mtrr_ops = { |
| 112 | .vendor = X86_VENDOR_AMD, | 112 | .vendor = X86_VENDOR_AMD, |
| 113 | .set = amd_set_mtrr, | 113 | .set = amd_set_mtrr, |
| 114 | .get = amd_get_mtrr, | 114 | .get = amd_get_mtrr, |
diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c index de89f14eff3a..316fe3e60a97 100644 --- a/arch/x86/kernel/cpu/mtrr/centaur.c +++ b/arch/x86/kernel/cpu/mtrr/centaur.c | |||
| @@ -110,7 +110,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t | |||
| 110 | return 0; | 110 | return 0; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | static struct mtrr_ops centaur_mtrr_ops = { | 113 | static const struct mtrr_ops centaur_mtrr_ops = { |
| 114 | .vendor = X86_VENDOR_CENTAUR, | 114 | .vendor = X86_VENDOR_CENTAUR, |
| 115 | .set = centaur_set_mcr, | 115 | .set = centaur_set_mcr, |
| 116 | .get = centaur_get_mcr, | 116 | .get = centaur_get_mcr, |
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 09b1698e0466..06130b52f012 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c | |||
| @@ -22,10 +22,10 @@ | |||
| 22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
| 23 | #include <linux/smp.h> | 23 | #include <linux/smp.h> |
| 24 | #include <linux/cpu.h> | 24 | #include <linux/cpu.h> |
| 25 | #include <linux/sort.h> | ||
| 26 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 27 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
| 28 | #include <linux/kvm_para.h> | 27 | #include <linux/kvm_para.h> |
| 28 | #include <linux/range.h> | ||
| 29 | 29 | ||
| 30 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
| 31 | #include <asm/e820.h> | 31 | #include <asm/e820.h> |
| @@ -34,11 +34,6 @@ | |||
| 34 | 34 | ||
| 35 | #include "mtrr.h" | 35 | #include "mtrr.h" |
| 36 | 36 | ||
| 37 | struct res_range { | ||
| 38 | unsigned long start; | ||
| 39 | unsigned long end; | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct var_mtrr_range_state { | 37 | struct var_mtrr_range_state { |
| 43 | unsigned long base_pfn; | 38 | unsigned long base_pfn; |
| 44 | unsigned long size_pfn; | 39 | unsigned long size_pfn; |
| @@ -56,7 +51,7 @@ struct var_mtrr_state { | |||
| 56 | /* Should be related to MTRR_VAR_RANGES nums */ | 51 | /* Should be related to MTRR_VAR_RANGES nums */ |
| 57 | #define RANGE_NUM 256 | 52 | #define RANGE_NUM 256 |
| 58 | 53 | ||
| 59 | static struct res_range __initdata range[RANGE_NUM]; | 54 | static struct range __initdata range[RANGE_NUM]; |
| 60 | static int __initdata nr_range; | 55 | static int __initdata nr_range; |
| 61 | 56 | ||
| 62 | static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; | 57 | static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; |
| @@ -64,152 +59,11 @@ static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; | |||
| 64 | static int __initdata debug_print; | 59 | static int __initdata debug_print; |
| 65 | #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0) | 60 | #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0) |
| 66 | 61 | ||
| 67 | |||
| 68 | static int __init | ||
| 69 | add_range(struct res_range *range, int nr_range, | ||
| 70 | unsigned long start, unsigned long end) | ||
| 71 | { | ||
| 72 | /* Out of slots: */ | ||
| 73 | if (nr_range >= RANGE_NUM) | ||
| 74 | return nr_range; | ||
| 75 | |||
| 76 | range[nr_range].start = start; | ||
| 77 | range[nr_range].end = end; | ||
| 78 | |||
| 79 | nr_range++; | ||
| 80 | |||
| 81 | return nr_range; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int __init | ||
| 85 | add_range_with_merge(struct res_range *range, int nr_range, | ||
| 86 | unsigned long start, unsigned long end) | ||
| 87 | { | ||
| 88 | int i; | ||
| 89 | |||
| 90 | /* Try to merge it with old one: */ | ||
| 91 | for (i = 0; i < nr_range; i++) { | ||
| 92 | unsigned long final_start, final_end; | ||
| 93 | unsigned long common_start, common_end; | ||
| 94 | |||
| 95 | if (!range[i].end) | ||
| 96 | continue; | ||
| 97 | |||
| 98 | common_start = max(range[i].start, start); | ||
| 99 | common_end = min(range[i].end, end); | ||
| 100 | if (common_start > common_end + 1) | ||
| 101 | continue; | ||
| 102 | |||
| 103 | final_start = min(range[i].start, start); | ||
| 104 | final_end = max(range[i].end, end); | ||
| 105 | |||
| 106 | range[i].start = final_start; | ||
| 107 | range[i].end = final_end; | ||
| 108 | return nr_range; | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Need to add it: */ | ||
| 112 | return add_range(range, nr_range, start, end); | ||
| 113 | } | ||
| 114 | |||
| 115 | static void __init | ||
| 116 | subtract_range(struct res_range *range, unsigned long start, unsigned long end) | ||
| 117 | { | ||
| 118 | int i, j; | ||
| 119 | |||
| 120 | for (j = 0; j < RANGE_NUM; j++) { | ||
| 121 | if (!range[j].end) | ||
| 122 | continue; | ||
| 123 | |||
| 124 | if (start <= range[j].start && end >= range[j].end) { | ||
| 125 | range[j].start = 0; | ||
| 126 | range[j].end = 0; | ||
| 127 | continue; | ||
| 128 | } | ||
| 129 | |||
| 130 | if (start <= range[j].start && end < range[j].end && | ||
| 131 | range[j].start < end + 1) { | ||
| 132 | range[j].start = end + 1; | ||
| 133 | continue; | ||
| 134 | } | ||
| 135 | |||
| 136 | |||
| 137 | if (start > range[j].start && end >= range[j].end && | ||
| 138 | range[j].end > start - 1) { | ||
| 139 | range[j].end = start - 1; | ||
| 140 | continue; | ||
| 141 | } | ||
| 142 | |||
| 143 | if (start > range[j].start && end < range[j].end) { | ||
| 144 | /* Find the new spare: */ | ||
| 145 | for (i = 0; i < RANGE_NUM; i++) { | ||
| 146 | if (range[i].end == 0) | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | if (i < RANGE_NUM) { | ||
| 150 | range[i].end = range[j].end; | ||
| 151 | range[i].start = end + 1; | ||
| 152 | } else { | ||
| 153 | printk(KERN_ERR "run of slot in ranges\n"); | ||
| 154 | } | ||
| 155 | range[j].end = start - 1; | ||
| 156 | continue; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | static int __init cmp_range(const void *x1, const void *x2) | ||
| 162 | { | ||
| 163 | const struct res_range *r1 = x1; | ||
| 164 | const struct res_range *r2 = x2; | ||
| 165 | long start1, start2; | ||
| 166 | |||
| 167 | start1 = r1->start; | ||
| 168 | start2 = r2->start; | ||
| 169 | |||
| 170 | return start1 - start2; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int __init clean_sort_range(struct res_range *range, int az) | ||
| 174 | { | ||
| 175 | int i, j, k = az - 1, nr_range = 0; | ||
| 176 | |||
| 177 | for (i = 0; i < k; i++) { | ||
| 178 | if (range[i].end) | ||
| 179 | continue; | ||
| 180 | for (j = k; j > i; j--) { | ||
| 181 | if (range[j].end) { | ||
| 182 | k = j; | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | if (j == i) | ||
| 187 | break; | ||
| 188 | range[i].start = range[k].start; | ||
| 189 | range[i].end = range[k].end; | ||
| 190 | range[k].start = 0; | ||
| 191 | range[k].end = 0; | ||
| 192 | k--; | ||
| 193 | } | ||
| 194 | /* count it */ | ||
| 195 | for (i = 0; i < az; i++) { | ||
| 196 | if (!range[i].end) { | ||
| 197 | nr_range = i; | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | /* sort them */ | ||
| 203 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | ||
| 204 | |||
| 205 | return nr_range; | ||
| 206 | } | ||
| 207 | |||
| 208 | #define BIOS_BUG_MSG KERN_WARNING \ | 62 | #define BIOS_BUG_MSG KERN_WARNING \ |
| 209 | "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" | 63 | "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" |
| 210 | 64 | ||
| 211 | static int __init | 65 | static int __init |
| 212 | x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | 66 | x86_get_mtrr_mem_range(struct range *range, int nr_range, |
| 213 | unsigned long extra_remove_base, | 67 | unsigned long extra_remove_base, |
| 214 | unsigned long extra_remove_size) | 68 | unsigned long extra_remove_size) |
| 215 | { | 69 | { |
| @@ -223,14 +77,14 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
| 223 | continue; | 77 | continue; |
| 224 | base = range_state[i].base_pfn; | 78 | base = range_state[i].base_pfn; |
| 225 | size = range_state[i].size_pfn; | 79 | size = range_state[i].size_pfn; |
| 226 | nr_range = add_range_with_merge(range, nr_range, base, | 80 | nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, |
| 227 | base + size - 1); | 81 | base, base + size); |
| 228 | } | 82 | } |
| 229 | if (debug_print) { | 83 | if (debug_print) { |
| 230 | printk(KERN_DEBUG "After WB checking\n"); | 84 | printk(KERN_DEBUG "After WB checking\n"); |
| 231 | for (i = 0; i < nr_range; i++) | 85 | for (i = 0; i < nr_range; i++) |
| 232 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 86 | printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", |
| 233 | range[i].start, range[i].end + 1); | 87 | range[i].start, range[i].end); |
| 234 | } | 88 | } |
| 235 | 89 | ||
| 236 | /* Take out UC ranges: */ | 90 | /* Take out UC ranges: */ |
| @@ -252,19 +106,19 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
| 252 | size -= (1<<(20-PAGE_SHIFT)) - base; | 106 | size -= (1<<(20-PAGE_SHIFT)) - base; |
| 253 | base = 1<<(20-PAGE_SHIFT); | 107 | base = 1<<(20-PAGE_SHIFT); |
| 254 | } | 108 | } |
| 255 | subtract_range(range, base, base + size - 1); | 109 | subtract_range(range, RANGE_NUM, base, base + size); |
| 256 | } | 110 | } |
| 257 | if (extra_remove_size) | 111 | if (extra_remove_size) |
| 258 | subtract_range(range, extra_remove_base, | 112 | subtract_range(range, RANGE_NUM, extra_remove_base, |
| 259 | extra_remove_base + extra_remove_size - 1); | 113 | extra_remove_base + extra_remove_size); |
| 260 | 114 | ||
| 261 | if (debug_print) { | 115 | if (debug_print) { |
| 262 | printk(KERN_DEBUG "After UC checking\n"); | 116 | printk(KERN_DEBUG "After UC checking\n"); |
| 263 | for (i = 0; i < RANGE_NUM; i++) { | 117 | for (i = 0; i < RANGE_NUM; i++) { |
| 264 | if (!range[i].end) | 118 | if (!range[i].end) |
| 265 | continue; | 119 | continue; |
| 266 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 120 | printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", |
| 267 | range[i].start, range[i].end + 1); | 121 | range[i].start, range[i].end); |
| 268 | } | 122 | } |
| 269 | } | 123 | } |
| 270 | 124 | ||
| @@ -273,26 +127,22 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
| 273 | if (debug_print) { | 127 | if (debug_print) { |
| 274 | printk(KERN_DEBUG "After sorting\n"); | 128 | printk(KERN_DEBUG "After sorting\n"); |
| 275 | for (i = 0; i < nr_range; i++) | 129 | for (i = 0; i < nr_range; i++) |
| 276 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 130 | printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", |
| 277 | range[i].start, range[i].end + 1); | 131 | range[i].start, range[i].end); |
| 278 | } | 132 | } |
| 279 | 133 | ||
| 280 | /* clear those is not used */ | ||
| 281 | for (i = nr_range; i < RANGE_NUM; i++) | ||
| 282 | memset(&range[i], 0, sizeof(range[i])); | ||
| 283 | |||
| 284 | return nr_range; | 134 | return nr_range; |
| 285 | } | 135 | } |
| 286 | 136 | ||
| 287 | #ifdef CONFIG_MTRR_SANITIZER | 137 | #ifdef CONFIG_MTRR_SANITIZER |
| 288 | 138 | ||
| 289 | static unsigned long __init sum_ranges(struct res_range *range, int nr_range) | 139 | static unsigned long __init sum_ranges(struct range *range, int nr_range) |
| 290 | { | 140 | { |
| 291 | unsigned long sum = 0; | 141 | unsigned long sum = 0; |
| 292 | int i; | 142 | int i; |
| 293 | 143 | ||
| 294 | for (i = 0; i < nr_range; i++) | 144 | for (i = 0; i < nr_range; i++) |
| 295 | sum += range[i].end + 1 - range[i].start; | 145 | sum += range[i].end - range[i].start; |
| 296 | 146 | ||
| 297 | return sum; | 147 | return sum; |
| 298 | } | 148 | } |
| @@ -621,7 +471,7 @@ static int __init parse_mtrr_spare_reg(char *arg) | |||
| 621 | early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg); | 471 | early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg); |
| 622 | 472 | ||
| 623 | static int __init | 473 | static int __init |
| 624 | x86_setup_var_mtrrs(struct res_range *range, int nr_range, | 474 | x86_setup_var_mtrrs(struct range *range, int nr_range, |
| 625 | u64 chunk_size, u64 gran_size) | 475 | u64 chunk_size, u64 gran_size) |
| 626 | { | 476 | { |
| 627 | struct var_mtrr_state var_state; | 477 | struct var_mtrr_state var_state; |
| @@ -639,7 +489,7 @@ x86_setup_var_mtrrs(struct res_range *range, int nr_range, | |||
| 639 | /* Write the range: */ | 489 | /* Write the range: */ |
| 640 | for (i = 0; i < nr_range; i++) { | 490 | for (i = 0; i < nr_range; i++) { |
| 641 | set_var_mtrr_range(&var_state, range[i].start, | 491 | set_var_mtrr_range(&var_state, range[i].start, |
| 642 | range[i].end - range[i].start + 1); | 492 | range[i].end - range[i].start); |
| 643 | } | 493 | } |
| 644 | 494 | ||
| 645 | /* Write the last range: */ | 495 | /* Write the last range: */ |
| @@ -742,7 +592,7 @@ mtrr_calc_range_state(u64 chunk_size, u64 gran_size, | |||
| 742 | unsigned long x_remove_base, | 592 | unsigned long x_remove_base, |
| 743 | unsigned long x_remove_size, int i) | 593 | unsigned long x_remove_size, int i) |
| 744 | { | 594 | { |
| 745 | static struct res_range range_new[RANGE_NUM]; | 595 | static struct range range_new[RANGE_NUM]; |
| 746 | unsigned long range_sums_new; | 596 | unsigned long range_sums_new; |
| 747 | static int nr_range_new; | 597 | static int nr_range_new; |
| 748 | int num_reg; | 598 | int num_reg; |
| @@ -869,10 +719,10 @@ int __init mtrr_cleanup(unsigned address_bits) | |||
| 869 | * [0, 1M) should always be covered by var mtrr with WB | 719 | * [0, 1M) should always be covered by var mtrr with WB |
| 870 | * and fixed mtrrs should take effect before var mtrr for it: | 720 | * and fixed mtrrs should take effect before var mtrr for it: |
| 871 | */ | 721 | */ |
| 872 | nr_range = add_range_with_merge(range, nr_range, 0, | 722 | nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, 0, |
| 873 | (1ULL<<(20 - PAGE_SHIFT)) - 1); | 723 | 1ULL<<(20 - PAGE_SHIFT)); |
| 874 | /* Sort the ranges: */ | 724 | /* Sort the ranges: */ |
| 875 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | 725 | sort_range(range, nr_range); |
| 876 | 726 | ||
| 877 | range_sums = sum_ranges(range, nr_range); | 727 | range_sums = sum_ranges(range, nr_range); |
| 878 | printk(KERN_INFO "total RAM covered: %ldM\n", | 728 | printk(KERN_INFO "total RAM covered: %ldM\n", |
| @@ -1089,9 +939,9 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
| 1089 | nr_range = 0; | 939 | nr_range = 0; |
| 1090 | if (mtrr_tom2) { | 940 | if (mtrr_tom2) { |
| 1091 | range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT)); | 941 | range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT)); |
| 1092 | range[nr_range].end = (mtrr_tom2 >> PAGE_SHIFT) - 1; | 942 | range[nr_range].end = mtrr_tom2 >> PAGE_SHIFT; |
| 1093 | if (highest_pfn < range[nr_range].end + 1) | 943 | if (highest_pfn < range[nr_range].end) |
| 1094 | highest_pfn = range[nr_range].end + 1; | 944 | highest_pfn = range[nr_range].end; |
| 1095 | nr_range++; | 945 | nr_range++; |
| 1096 | } | 946 | } |
| 1097 | nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0); | 947 | nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0); |
| @@ -1103,15 +953,15 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
| 1103 | 953 | ||
| 1104 | /* Check the holes: */ | 954 | /* Check the holes: */ |
| 1105 | for (i = 0; i < nr_range - 1; i++) { | 955 | for (i = 0; i < nr_range - 1; i++) { |
| 1106 | if (range[i].end + 1 < range[i+1].start) | 956 | if (range[i].end < range[i+1].start) |
| 1107 | total_trim_size += real_trim_memory(range[i].end + 1, | 957 | total_trim_size += real_trim_memory(range[i].end, |
| 1108 | range[i+1].start); | 958 | range[i+1].start); |
| 1109 | } | 959 | } |
| 1110 | 960 | ||
| 1111 | /* Check the top: */ | 961 | /* Check the top: */ |
| 1112 | i = nr_range - 1; | 962 | i = nr_range - 1; |
| 1113 | if (range[i].end + 1 < end_pfn) | 963 | if (range[i].end < end_pfn) |
| 1114 | total_trim_size += real_trim_memory(range[i].end + 1, | 964 | total_trim_size += real_trim_memory(range[i].end, |
| 1115 | end_pfn); | 965 | end_pfn); |
| 1116 | 966 | ||
| 1117 | if (total_trim_size) { | 967 | if (total_trim_size) { |
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index 228d982ce09c..68a3343e5798 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c | |||
| @@ -265,7 +265,7 @@ static void cyrix_set_all(void) | |||
| 265 | post_set(); | 265 | post_set(); |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | static struct mtrr_ops cyrix_mtrr_ops = { | 268 | static const struct mtrr_ops cyrix_mtrr_ops = { |
| 269 | .vendor = X86_VENDOR_CYRIX, | 269 | .vendor = X86_VENDOR_CYRIX, |
| 270 | .set_all = cyrix_set_all, | 270 | .set_all = cyrix_set_all, |
| 271 | .set = cyrix_set_arr, | 271 | .set = cyrix_set_arr, |
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 55da0c5f68dd..9aa5dc76ff4a 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c | |||
| @@ -464,7 +464,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, | |||
| 464 | tmp |= ~((1<<(hi - 1)) - 1); | 464 | tmp |= ~((1<<(hi - 1)) - 1); |
| 465 | 465 | ||
| 466 | if (tmp != mask_lo) { | 466 | if (tmp != mask_lo) { |
| 467 | WARN_ONCE(1, KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); | 467 | printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); |
| 468 | mask_lo = tmp; | 468 | mask_lo = tmp; |
| 469 | } | 469 | } |
| 470 | } | 470 | } |
| @@ -570,7 +570,7 @@ static unsigned long set_mtrr_state(void) | |||
| 570 | 570 | ||
| 571 | 571 | ||
| 572 | static unsigned long cr4; | 572 | static unsigned long cr4; |
| 573 | static DEFINE_SPINLOCK(set_atomicity_lock); | 573 | static DEFINE_RAW_SPINLOCK(set_atomicity_lock); |
| 574 | 574 | ||
| 575 | /* | 575 | /* |
| 576 | * Since we are disabling the cache don't allow any interrupts, | 576 | * Since we are disabling the cache don't allow any interrupts, |
| @@ -590,7 +590,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) | |||
| 590 | * changes to the way the kernel boots | 590 | * changes to the way the kernel boots |
| 591 | */ | 591 | */ |
| 592 | 592 | ||
| 593 | spin_lock(&set_atomicity_lock); | 593 | raw_spin_lock(&set_atomicity_lock); |
| 594 | 594 | ||
| 595 | /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */ | 595 | /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */ |
| 596 | cr0 = read_cr0() | X86_CR0_CD; | 596 | cr0 = read_cr0() | X86_CR0_CD; |
| @@ -627,7 +627,7 @@ static void post_set(void) __releases(set_atomicity_lock) | |||
| 627 | /* Restore value of CR4 */ | 627 | /* Restore value of CR4 */ |
| 628 | if (cpu_has_pge) | 628 | if (cpu_has_pge) |
| 629 | write_cr4(cr4); | 629 | write_cr4(cr4); |
| 630 | spin_unlock(&set_atomicity_lock); | 630 | raw_spin_unlock(&set_atomicity_lock); |
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | static void generic_set_all(void) | 633 | static void generic_set_all(void) |
| @@ -752,7 +752,7 @@ int positive_have_wrcomb(void) | |||
| 752 | /* | 752 | /* |
| 753 | * Generic structure... | 753 | * Generic structure... |
| 754 | */ | 754 | */ |
| 755 | struct mtrr_ops generic_mtrr_ops = { | 755 | const struct mtrr_ops generic_mtrr_ops = { |
| 756 | .use_intel_if = 1, | 756 | .use_intel_if = 1, |
| 757 | .set_all = generic_set_all, | 757 | .set_all = generic_set_all, |
| 758 | .get = generic_get_mtrr, | 758 | .get = generic_get_mtrr, |
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 84e83de54575..fe4622e8c837 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c | |||
| @@ -60,14 +60,14 @@ static DEFINE_MUTEX(mtrr_mutex); | |||
| 60 | u64 size_or_mask, size_and_mask; | 60 | u64 size_or_mask, size_and_mask; |
| 61 | static bool mtrr_aps_delayed_init; | 61 | static bool mtrr_aps_delayed_init; |
| 62 | 62 | ||
| 63 | static struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM]; | 63 | static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM]; |
| 64 | 64 | ||
| 65 | struct mtrr_ops *mtrr_if; | 65 | const struct mtrr_ops *mtrr_if; |
| 66 | 66 | ||
| 67 | static void set_mtrr(unsigned int reg, unsigned long base, | 67 | static void set_mtrr(unsigned int reg, unsigned long base, |
| 68 | unsigned long size, mtrr_type type); | 68 | unsigned long size, mtrr_type type); |
| 69 | 69 | ||
| 70 | void set_mtrr_ops(struct mtrr_ops *ops) | 70 | void set_mtrr_ops(const struct mtrr_ops *ops) |
| 71 | { | 71 | { |
| 72 | if (ops->vendor && ops->vendor < X86_VENDOR_NUM) | 72 | if (ops->vendor && ops->vendor < X86_VENDOR_NUM) |
| 73 | mtrr_ops[ops->vendor] = ops; | 73 | mtrr_ops[ops->vendor] = ops; |
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index a501dee9a87a..df5e41f31a27 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h | |||
| @@ -32,7 +32,7 @@ extern int generic_get_free_region(unsigned long base, unsigned long size, | |||
| 32 | extern int generic_validate_add_page(unsigned long base, unsigned long size, | 32 | extern int generic_validate_add_page(unsigned long base, unsigned long size, |
| 33 | unsigned int type); | 33 | unsigned int type); |
| 34 | 34 | ||
| 35 | extern struct mtrr_ops generic_mtrr_ops; | 35 | extern const struct mtrr_ops generic_mtrr_ops; |
| 36 | 36 | ||
| 37 | extern int positive_have_wrcomb(void); | 37 | extern int positive_have_wrcomb(void); |
| 38 | 38 | ||
| @@ -53,10 +53,10 @@ void fill_mtrr_var_range(unsigned int index, | |||
| 53 | u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); | 53 | u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); |
| 54 | void get_mtrr_state(void); | 54 | void get_mtrr_state(void); |
| 55 | 55 | ||
| 56 | extern void set_mtrr_ops(struct mtrr_ops *ops); | 56 | extern void set_mtrr_ops(const struct mtrr_ops *ops); |
| 57 | 57 | ||
| 58 | extern u64 size_or_mask, size_and_mask; | 58 | extern u64 size_or_mask, size_and_mask; |
| 59 | extern struct mtrr_ops *mtrr_if; | 59 | extern const struct mtrr_ops *mtrr_if; |
| 60 | 60 | ||
| 61 | #define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd) | 61 | #define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd) |
| 62 | #define use_intel() (mtrr_if && mtrr_if->use_intel_if == 1) | 62 | #define use_intel() (mtrr_if && mtrr_if->use_intel_if == 1) |
diff --git a/arch/x86/kernel/cpu/mtrr/state.c b/arch/x86/kernel/cpu/mtrr/state.c deleted file mode 100644 index dfc80b4e6b0d..000000000000 --- a/arch/x86/kernel/cpu/mtrr/state.c +++ /dev/null | |||
| @@ -1,94 +0,0 @@ | |||
| 1 | #include <linux/init.h> | ||
| 2 | #include <linux/io.h> | ||
| 3 | #include <linux/mm.h> | ||
| 4 | |||
| 5 | #include <asm/processor-cyrix.h> | ||
| 6 | #include <asm/processor-flags.h> | ||
| 7 | #include <asm/mtrr.h> | ||
| 8 | #include <asm/msr.h> | ||
| 9 | |||
| 10 | #include "mtrr.h" | ||
| 11 | |||
| 12 | /* Put the processor into a state where MTRRs can be safely set */ | ||
| 13 | void set_mtrr_prepare_save(struct set_mtrr_context *ctxt) | ||
| 14 | { | ||
| 15 | unsigned int cr0; | ||
| 16 | |||
| 17 | /* Disable interrupts locally */ | ||
| 18 | local_irq_save(ctxt->flags); | ||
| 19 | |||
| 20 | if (use_intel() || is_cpu(CYRIX)) { | ||
| 21 | |||
| 22 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ | ||
| 23 | if (cpu_has_pge) { | ||
| 24 | ctxt->cr4val = read_cr4(); | ||
| 25 | write_cr4(ctxt->cr4val & ~X86_CR4_PGE); | ||
| 26 | } | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Disable and flush caches. Note that wbinvd flushes the TLBs | ||
| 30 | * as a side-effect | ||
| 31 | */ | ||
| 32 | cr0 = read_cr0() | X86_CR0_CD; | ||
| 33 | wbinvd(); | ||
| 34 | write_cr0(cr0); | ||
| 35 | wbinvd(); | ||
| 36 | |||
| 37 | if (use_intel()) { | ||
| 38 | /* Save MTRR state */ | ||
| 39 | rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi); | ||
| 40 | } else { | ||
| 41 | /* | ||
| 42 | * Cyrix ARRs - | ||
| 43 | * everything else were excluded at the top | ||
| 44 | */ | ||
| 45 | ctxt->ccr3 = getCx86(CX86_CCR3); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | void set_mtrr_cache_disable(struct set_mtrr_context *ctxt) | ||
| 51 | { | ||
| 52 | if (use_intel()) { | ||
| 53 | /* Disable MTRRs, and set the default type to uncached */ | ||
| 54 | mtrr_wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL, | ||
| 55 | ctxt->deftype_hi); | ||
| 56 | } else { | ||
| 57 | if (is_cpu(CYRIX)) { | ||
| 58 | /* Cyrix ARRs - everything else were excluded at the top */ | ||
| 59 | setCx86(CX86_CCR3, (ctxt->ccr3 & 0x0f) | 0x10); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | /* Restore the processor after a set_mtrr_prepare */ | ||
| 65 | void set_mtrr_done(struct set_mtrr_context *ctxt) | ||
| 66 | { | ||
| 67 | if (use_intel() || is_cpu(CYRIX)) { | ||
| 68 | |||
| 69 | /* Flush caches and TLBs */ | ||
| 70 | wbinvd(); | ||
| 71 | |||
| 72 | /* Restore MTRRdefType */ | ||
| 73 | if (use_intel()) { | ||
| 74 | /* Intel (P6) standard MTRRs */ | ||
| 75 | mtrr_wrmsr(MSR_MTRRdefType, ctxt->deftype_lo, | ||
| 76 | ctxt->deftype_hi); | ||
| 77 | } else { | ||
| 78 | /* | ||
| 79 | * Cyrix ARRs - | ||
| 80 | * everything else was excluded at the top | ||
| 81 | */ | ||
| 82 | setCx86(CX86_CCR3, ctxt->ccr3); | ||
| 83 | } | ||
| 84 | |||
| 85 | /* Enable caches */ | ||
| 86 | write_cr0(read_cr0() & 0xbfffffff); | ||
| 87 | |||
| 88 | /* Restore value of CR4 */ | ||
| 89 | if (cpu_has_pge) | ||
| 90 | write_cr4(ctxt->cr4val); | ||
| 91 | } | ||
| 92 | /* Re-enable interrupts locally (if enabled previously) */ | ||
| 93 | local_irq_restore(ctxt->flags); | ||
| 94 | } | ||
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 8c1c07073ccc..641ccb9dddbc 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter | 7 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter |
| 8 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | 8 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> |
| 9 | * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> | 9 | * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> |
| 10 | * Copyright (C) 2009 Google, Inc., Stephane Eranian | ||
| 10 | * | 11 | * |
| 11 | * For licencing details see kernel-base/COPYING | 12 | * For licencing details see kernel-base/COPYING |
| 12 | */ | 13 | */ |
| @@ -22,6 +23,7 @@ | |||
| 22 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 23 | #include <linux/highmem.h> | 24 | #include <linux/highmem.h> |
| 24 | #include <linux/cpu.h> | 25 | #include <linux/cpu.h> |
| 26 | #include <linux/bitops.h> | ||
| 25 | 27 | ||
| 26 | #include <asm/apic.h> | 28 | #include <asm/apic.h> |
| 27 | #include <asm/stacktrace.h> | 29 | #include <asm/stacktrace.h> |
| @@ -68,26 +70,59 @@ struct debug_store { | |||
| 68 | u64 pebs_event_reset[MAX_PEBS_EVENTS]; | 70 | u64 pebs_event_reset[MAX_PEBS_EVENTS]; |
| 69 | }; | 71 | }; |
| 70 | 72 | ||
| 73 | struct event_constraint { | ||
| 74 | union { | ||
| 75 | unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | ||
| 76 | u64 idxmsk64[1]; | ||
| 77 | }; | ||
| 78 | int code; | ||
| 79 | int cmask; | ||
| 80 | int weight; | ||
| 81 | }; | ||
| 82 | |||
| 83 | struct amd_nb { | ||
| 84 | int nb_id; /* NorthBridge id */ | ||
| 85 | int refcnt; /* reference count */ | ||
| 86 | struct perf_event *owners[X86_PMC_IDX_MAX]; | ||
| 87 | struct event_constraint event_constraints[X86_PMC_IDX_MAX]; | ||
| 88 | }; | ||
| 89 | |||
| 71 | struct cpu_hw_events { | 90 | struct cpu_hw_events { |
| 72 | struct perf_event *events[X86_PMC_IDX_MAX]; | 91 | struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ |
| 73 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | ||
| 74 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 92 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
| 75 | unsigned long interrupts; | 93 | unsigned long interrupts; |
| 76 | int enabled; | 94 | int enabled; |
| 77 | struct debug_store *ds; | 95 | struct debug_store *ds; |
| 78 | }; | ||
| 79 | 96 | ||
| 80 | struct event_constraint { | 97 | int n_events; |
| 81 | unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 98 | int n_added; |
| 82 | int code; | 99 | int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ |
| 100 | u64 tags[X86_PMC_IDX_MAX]; | ||
| 101 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ | ||
| 102 | struct amd_nb *amd_nb; | ||
| 83 | }; | 103 | }; |
| 84 | 104 | ||
| 85 | #define EVENT_CONSTRAINT(c, m) { .code = (c), .idxmsk[0] = (m) } | 105 | #define __EVENT_CONSTRAINT(c, n, m, w) {\ |
| 86 | #define EVENT_CONSTRAINT_END { .code = 0, .idxmsk[0] = 0 } | 106 | { .idxmsk64[0] = (n) }, \ |
| 107 | .code = (c), \ | ||
| 108 | .cmask = (m), \ | ||
| 109 | .weight = (w), \ | ||
| 110 | } | ||
| 111 | |||
| 112 | #define EVENT_CONSTRAINT(c, n, m) \ | ||
| 113 | __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n)) | ||
| 87 | 114 | ||
| 88 | #define for_each_event_constraint(e, c) \ | 115 | #define INTEL_EVENT_CONSTRAINT(c, n) \ |
| 89 | for ((e) = (c); (e)->idxmsk[0]; (e)++) | 116 | EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK) |
| 90 | 117 | ||
| 118 | #define FIXED_EVENT_CONSTRAINT(c, n) \ | ||
| 119 | EVENT_CONSTRAINT(c, n, INTEL_ARCH_FIXED_MASK) | ||
| 120 | |||
| 121 | #define EVENT_CONSTRAINT_END \ | ||
| 122 | EVENT_CONSTRAINT(0, 0, 0) | ||
| 123 | |||
| 124 | #define for_each_event_constraint(e, c) \ | ||
| 125 | for ((e) = (c); (e)->cmask; (e)++) | ||
| 91 | 126 | ||
| 92 | /* | 127 | /* |
| 93 | * struct x86_pmu - generic x86 pmu | 128 | * struct x86_pmu - generic x86 pmu |
| @@ -114,8 +149,14 @@ struct x86_pmu { | |||
| 114 | u64 intel_ctrl; | 149 | u64 intel_ctrl; |
| 115 | void (*enable_bts)(u64 config); | 150 | void (*enable_bts)(u64 config); |
| 116 | void (*disable_bts)(void); | 151 | void (*disable_bts)(void); |
| 117 | int (*get_event_idx)(struct cpu_hw_events *cpuc, | 152 | |
| 118 | struct hw_perf_event *hwc); | 153 | struct event_constraint * |
| 154 | (*get_event_constraints)(struct cpu_hw_events *cpuc, | ||
| 155 | struct perf_event *event); | ||
| 156 | |||
| 157 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, | ||
| 158 | struct perf_event *event); | ||
| 159 | struct event_constraint *event_constraints; | ||
| 119 | }; | 160 | }; |
| 120 | 161 | ||
| 121 | static struct x86_pmu x86_pmu __read_mostly; | 162 | static struct x86_pmu x86_pmu __read_mostly; |
| @@ -124,111 +165,8 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { | |||
| 124 | .enabled = 1, | 165 | .enabled = 1, |
| 125 | }; | 166 | }; |
| 126 | 167 | ||
| 127 | static const struct event_constraint *event_constraints; | 168 | static int x86_perf_event_set_period(struct perf_event *event, |
| 128 | 169 | struct hw_perf_event *hwc, int idx); | |
| 129 | /* | ||
| 130 | * Not sure about some of these | ||
| 131 | */ | ||
| 132 | static const u64 p6_perfmon_event_map[] = | ||
| 133 | { | ||
| 134 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, | ||
| 135 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 136 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, | ||
| 137 | [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, | ||
| 138 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 139 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 140 | [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static u64 p6_pmu_event_map(int hw_event) | ||
| 144 | { | ||
| 145 | return p6_perfmon_event_map[hw_event]; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Event setting that is specified not to count anything. | ||
| 150 | * We use this to effectively disable a counter. | ||
| 151 | * | ||
| 152 | * L2_RQSTS with 0 MESI unit mask. | ||
| 153 | */ | ||
| 154 | #define P6_NOP_EVENT 0x0000002EULL | ||
| 155 | |||
| 156 | static u64 p6_pmu_raw_event(u64 hw_event) | ||
| 157 | { | ||
| 158 | #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
| 159 | #define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
| 160 | #define P6_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
| 161 | #define P6_EVNTSEL_INV_MASK 0x00800000ULL | ||
| 162 | #define P6_EVNTSEL_REG_MASK 0xFF000000ULL | ||
| 163 | |||
| 164 | #define P6_EVNTSEL_MASK \ | ||
| 165 | (P6_EVNTSEL_EVENT_MASK | \ | ||
| 166 | P6_EVNTSEL_UNIT_MASK | \ | ||
| 167 | P6_EVNTSEL_EDGE_MASK | \ | ||
| 168 | P6_EVNTSEL_INV_MASK | \ | ||
| 169 | P6_EVNTSEL_REG_MASK) | ||
| 170 | |||
| 171 | return hw_event & P6_EVNTSEL_MASK; | ||
| 172 | } | ||
| 173 | |||
| 174 | static const struct event_constraint intel_p6_event_constraints[] = | ||
| 175 | { | ||
| 176 | EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ | ||
| 177 | EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
| 178 | EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */ | ||
| 179 | EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
| 180 | EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
| 181 | EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
| 182 | EVENT_CONSTRAINT_END | ||
| 183 | }; | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Intel PerfMon v3. Used on Core2 and later. | ||
| 187 | */ | ||
| 188 | static const u64 intel_perfmon_event_map[] = | ||
| 189 | { | ||
| 190 | [PERF_COUNT_HW_CPU_CYCLES] = 0x003c, | ||
| 191 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 192 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e, | ||
| 193 | [PERF_COUNT_HW_CACHE_MISSES] = 0x412e, | ||
| 194 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 195 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 196 | [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, | ||
| 197 | }; | ||
| 198 | |||
| 199 | static const struct event_constraint intel_core_event_constraints[] = | ||
| 200 | { | ||
| 201 | EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
| 202 | EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
| 203 | EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
| 204 | EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
| 205 | EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
| 206 | EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ | ||
| 207 | EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
| 208 | EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ | ||
| 209 | EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */ | ||
| 210 | EVENT_CONSTRAINT_END | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const struct event_constraint intel_nehalem_event_constraints[] = | ||
| 214 | { | ||
| 215 | EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ | ||
| 216 | EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ | ||
| 217 | EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ | ||
| 218 | EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */ | ||
| 219 | EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */ | ||
| 220 | EVENT_CONSTRAINT(0x4c, 0x3), /* LOAD_HIT_PRE */ | ||
| 221 | EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
| 222 | EVENT_CONSTRAINT(0x52, 0x3), /* L1D_CACHE_PREFETCH_LOCK_FB_HIT */ | ||
| 223 | EVENT_CONSTRAINT(0x53, 0x3), /* L1D_CACHE_LOCK_FB_HIT */ | ||
| 224 | EVENT_CONSTRAINT(0xc5, 0x3), /* CACHE_LOCK_CYCLES */ | ||
| 225 | EVENT_CONSTRAINT_END | ||
| 226 | }; | ||
| 227 | |||
| 228 | static u64 intel_pmu_event_map(int hw_event) | ||
| 229 | { | ||
| 230 | return intel_perfmon_event_map[hw_event]; | ||
| 231 | } | ||
| 232 | 170 | ||
| 233 | /* | 171 | /* |
| 234 | * Generalized hw caching related hw_event table, filled | 172 | * Generalized hw caching related hw_event table, filled |
| @@ -245,424 +183,6 @@ static u64 __read_mostly hw_cache_event_ids | |||
| 245 | [PERF_COUNT_HW_CACHE_OP_MAX] | 183 | [PERF_COUNT_HW_CACHE_OP_MAX] |
| 246 | [PERF_COUNT_HW_CACHE_RESULT_MAX]; | 184 | [PERF_COUNT_HW_CACHE_RESULT_MAX]; |
| 247 | 185 | ||
| 248 | static __initconst u64 nehalem_hw_cache_event_ids | ||
| 249 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 250 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 251 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 252 | { | ||
| 253 | [ C(L1D) ] = { | ||
| 254 | [ C(OP_READ) ] = { | ||
| 255 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
| 256 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
| 257 | }, | ||
| 258 | [ C(OP_WRITE) ] = { | ||
| 259 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
| 260 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
| 261 | }, | ||
| 262 | [ C(OP_PREFETCH) ] = { | ||
| 263 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
| 264 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
| 265 | }, | ||
| 266 | }, | ||
| 267 | [ C(L1I ) ] = { | ||
| 268 | [ C(OP_READ) ] = { | ||
| 269 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
| 270 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
| 271 | }, | ||
| 272 | [ C(OP_WRITE) ] = { | ||
| 273 | [ C(RESULT_ACCESS) ] = -1, | ||
| 274 | [ C(RESULT_MISS) ] = -1, | ||
| 275 | }, | ||
| 276 | [ C(OP_PREFETCH) ] = { | ||
| 277 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 278 | [ C(RESULT_MISS) ] = 0x0, | ||
| 279 | }, | ||
| 280 | }, | ||
| 281 | [ C(LL ) ] = { | ||
| 282 | [ C(OP_READ) ] = { | ||
| 283 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
| 284 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
| 285 | }, | ||
| 286 | [ C(OP_WRITE) ] = { | ||
| 287 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
| 288 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
| 289 | }, | ||
| 290 | [ C(OP_PREFETCH) ] = { | ||
| 291 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
| 292 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
| 293 | }, | ||
| 294 | }, | ||
| 295 | [ C(DTLB) ] = { | ||
| 296 | [ C(OP_READ) ] = { | ||
| 297 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
| 298 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
| 299 | }, | ||
| 300 | [ C(OP_WRITE) ] = { | ||
| 301 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
| 302 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
| 303 | }, | ||
| 304 | [ C(OP_PREFETCH) ] = { | ||
| 305 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 306 | [ C(RESULT_MISS) ] = 0x0, | ||
| 307 | }, | ||
| 308 | }, | ||
| 309 | [ C(ITLB) ] = { | ||
| 310 | [ C(OP_READ) ] = { | ||
| 311 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
| 312 | [ C(RESULT_MISS) ] = 0x20c8, /* ITLB_MISS_RETIRED */ | ||
| 313 | }, | ||
| 314 | [ C(OP_WRITE) ] = { | ||
| 315 | [ C(RESULT_ACCESS) ] = -1, | ||
| 316 | [ C(RESULT_MISS) ] = -1, | ||
| 317 | }, | ||
| 318 | [ C(OP_PREFETCH) ] = { | ||
| 319 | [ C(RESULT_ACCESS) ] = -1, | ||
| 320 | [ C(RESULT_MISS) ] = -1, | ||
| 321 | }, | ||
| 322 | }, | ||
| 323 | [ C(BPU ) ] = { | ||
| 324 | [ C(OP_READ) ] = { | ||
| 325 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
| 326 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
| 327 | }, | ||
| 328 | [ C(OP_WRITE) ] = { | ||
| 329 | [ C(RESULT_ACCESS) ] = -1, | ||
| 330 | [ C(RESULT_MISS) ] = -1, | ||
| 331 | }, | ||
| 332 | [ C(OP_PREFETCH) ] = { | ||
| 333 | [ C(RESULT_ACCESS) ] = -1, | ||
| 334 | [ C(RESULT_MISS) ] = -1, | ||
| 335 | }, | ||
| 336 | }, | ||
| 337 | }; | ||
| 338 | |||
| 339 | static __initconst u64 core2_hw_cache_event_ids | ||
| 340 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 341 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 342 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 343 | { | ||
| 344 | [ C(L1D) ] = { | ||
| 345 | [ C(OP_READ) ] = { | ||
| 346 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
| 347 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
| 348 | }, | ||
| 349 | [ C(OP_WRITE) ] = { | ||
| 350 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
| 351 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
| 352 | }, | ||
| 353 | [ C(OP_PREFETCH) ] = { | ||
| 354 | [ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS */ | ||
| 355 | [ C(RESULT_MISS) ] = 0, | ||
| 356 | }, | ||
| 357 | }, | ||
| 358 | [ C(L1I ) ] = { | ||
| 359 | [ C(OP_READ) ] = { | ||
| 360 | [ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS */ | ||
| 361 | [ C(RESULT_MISS) ] = 0x0081, /* L1I.MISSES */ | ||
| 362 | }, | ||
| 363 | [ C(OP_WRITE) ] = { | ||
| 364 | [ C(RESULT_ACCESS) ] = -1, | ||
| 365 | [ C(RESULT_MISS) ] = -1, | ||
| 366 | }, | ||
| 367 | [ C(OP_PREFETCH) ] = { | ||
| 368 | [ C(RESULT_ACCESS) ] = 0, | ||
| 369 | [ C(RESULT_MISS) ] = 0, | ||
| 370 | }, | ||
| 371 | }, | ||
| 372 | [ C(LL ) ] = { | ||
| 373 | [ C(OP_READ) ] = { | ||
| 374 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
| 375 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
| 376 | }, | ||
| 377 | [ C(OP_WRITE) ] = { | ||
| 378 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
| 379 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
| 380 | }, | ||
| 381 | [ C(OP_PREFETCH) ] = { | ||
| 382 | [ C(RESULT_ACCESS) ] = 0, | ||
| 383 | [ C(RESULT_MISS) ] = 0, | ||
| 384 | }, | ||
| 385 | }, | ||
| 386 | [ C(DTLB) ] = { | ||
| 387 | [ C(OP_READ) ] = { | ||
| 388 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
| 389 | [ C(RESULT_MISS) ] = 0x0208, /* DTLB_MISSES.MISS_LD */ | ||
| 390 | }, | ||
| 391 | [ C(OP_WRITE) ] = { | ||
| 392 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
| 393 | [ C(RESULT_MISS) ] = 0x0808, /* DTLB_MISSES.MISS_ST */ | ||
| 394 | }, | ||
| 395 | [ C(OP_PREFETCH) ] = { | ||
| 396 | [ C(RESULT_ACCESS) ] = 0, | ||
| 397 | [ C(RESULT_MISS) ] = 0, | ||
| 398 | }, | ||
| 399 | }, | ||
| 400 | [ C(ITLB) ] = { | ||
| 401 | [ C(OP_READ) ] = { | ||
| 402 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
| 403 | [ C(RESULT_MISS) ] = 0x1282, /* ITLBMISSES */ | ||
| 404 | }, | ||
| 405 | [ C(OP_WRITE) ] = { | ||
| 406 | [ C(RESULT_ACCESS) ] = -1, | ||
| 407 | [ C(RESULT_MISS) ] = -1, | ||
| 408 | }, | ||
| 409 | [ C(OP_PREFETCH) ] = { | ||
| 410 | [ C(RESULT_ACCESS) ] = -1, | ||
| 411 | [ C(RESULT_MISS) ] = -1, | ||
| 412 | }, | ||
| 413 | }, | ||
| 414 | [ C(BPU ) ] = { | ||
| 415 | [ C(OP_READ) ] = { | ||
| 416 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
| 417 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
| 418 | }, | ||
| 419 | [ C(OP_WRITE) ] = { | ||
| 420 | [ C(RESULT_ACCESS) ] = -1, | ||
| 421 | [ C(RESULT_MISS) ] = -1, | ||
| 422 | }, | ||
| 423 | [ C(OP_PREFETCH) ] = { | ||
| 424 | [ C(RESULT_ACCESS) ] = -1, | ||
| 425 | [ C(RESULT_MISS) ] = -1, | ||
| 426 | }, | ||
| 427 | }, | ||
| 428 | }; | ||
| 429 | |||
| 430 | static __initconst u64 atom_hw_cache_event_ids | ||
| 431 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 432 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 433 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 434 | { | ||
| 435 | [ C(L1D) ] = { | ||
| 436 | [ C(OP_READ) ] = { | ||
| 437 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE.LD */ | ||
| 438 | [ C(RESULT_MISS) ] = 0, | ||
| 439 | }, | ||
| 440 | [ C(OP_WRITE) ] = { | ||
| 441 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST */ | ||
| 442 | [ C(RESULT_MISS) ] = 0, | ||
| 443 | }, | ||
| 444 | [ C(OP_PREFETCH) ] = { | ||
| 445 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 446 | [ C(RESULT_MISS) ] = 0, | ||
| 447 | }, | ||
| 448 | }, | ||
| 449 | [ C(L1I ) ] = { | ||
| 450 | [ C(OP_READ) ] = { | ||
| 451 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
| 452 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
| 453 | }, | ||
| 454 | [ C(OP_WRITE) ] = { | ||
| 455 | [ C(RESULT_ACCESS) ] = -1, | ||
| 456 | [ C(RESULT_MISS) ] = -1, | ||
| 457 | }, | ||
| 458 | [ C(OP_PREFETCH) ] = { | ||
| 459 | [ C(RESULT_ACCESS) ] = 0, | ||
| 460 | [ C(RESULT_MISS) ] = 0, | ||
| 461 | }, | ||
| 462 | }, | ||
| 463 | [ C(LL ) ] = { | ||
| 464 | [ C(OP_READ) ] = { | ||
| 465 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
| 466 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
| 467 | }, | ||
| 468 | [ C(OP_WRITE) ] = { | ||
| 469 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
| 470 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
| 471 | }, | ||
| 472 | [ C(OP_PREFETCH) ] = { | ||
| 473 | [ C(RESULT_ACCESS) ] = 0, | ||
| 474 | [ C(RESULT_MISS) ] = 0, | ||
| 475 | }, | ||
| 476 | }, | ||
| 477 | [ C(DTLB) ] = { | ||
| 478 | [ C(OP_READ) ] = { | ||
| 479 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI (alias) */ | ||
| 480 | [ C(RESULT_MISS) ] = 0x0508, /* DTLB_MISSES.MISS_LD */ | ||
| 481 | }, | ||
| 482 | [ C(OP_WRITE) ] = { | ||
| 483 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI (alias) */ | ||
| 484 | [ C(RESULT_MISS) ] = 0x0608, /* DTLB_MISSES.MISS_ST */ | ||
| 485 | }, | ||
| 486 | [ C(OP_PREFETCH) ] = { | ||
| 487 | [ C(RESULT_ACCESS) ] = 0, | ||
| 488 | [ C(RESULT_MISS) ] = 0, | ||
| 489 | }, | ||
| 490 | }, | ||
| 491 | [ C(ITLB) ] = { | ||
| 492 | [ C(OP_READ) ] = { | ||
| 493 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
| 494 | [ C(RESULT_MISS) ] = 0x0282, /* ITLB.MISSES */ | ||
| 495 | }, | ||
| 496 | [ C(OP_WRITE) ] = { | ||
| 497 | [ C(RESULT_ACCESS) ] = -1, | ||
| 498 | [ C(RESULT_MISS) ] = -1, | ||
| 499 | }, | ||
| 500 | [ C(OP_PREFETCH) ] = { | ||
| 501 | [ C(RESULT_ACCESS) ] = -1, | ||
| 502 | [ C(RESULT_MISS) ] = -1, | ||
| 503 | }, | ||
| 504 | }, | ||
| 505 | [ C(BPU ) ] = { | ||
| 506 | [ C(OP_READ) ] = { | ||
| 507 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
| 508 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
| 509 | }, | ||
| 510 | [ C(OP_WRITE) ] = { | ||
| 511 | [ C(RESULT_ACCESS) ] = -1, | ||
| 512 | [ C(RESULT_MISS) ] = -1, | ||
| 513 | }, | ||
| 514 | [ C(OP_PREFETCH) ] = { | ||
| 515 | [ C(RESULT_ACCESS) ] = -1, | ||
| 516 | [ C(RESULT_MISS) ] = -1, | ||
| 517 | }, | ||
| 518 | }, | ||
| 519 | }; | ||
| 520 | |||
| 521 | static u64 intel_pmu_raw_event(u64 hw_event) | ||
| 522 | { | ||
| 523 | #define CORE_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
| 524 | #define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
| 525 | #define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
| 526 | #define CORE_EVNTSEL_INV_MASK 0x00800000ULL | ||
| 527 | #define CORE_EVNTSEL_REG_MASK 0xFF000000ULL | ||
| 528 | |||
| 529 | #define CORE_EVNTSEL_MASK \ | ||
| 530 | (CORE_EVNTSEL_EVENT_MASK | \ | ||
| 531 | CORE_EVNTSEL_UNIT_MASK | \ | ||
| 532 | CORE_EVNTSEL_EDGE_MASK | \ | ||
| 533 | CORE_EVNTSEL_INV_MASK | \ | ||
| 534 | CORE_EVNTSEL_REG_MASK) | ||
| 535 | |||
| 536 | return hw_event & CORE_EVNTSEL_MASK; | ||
| 537 | } | ||
| 538 | |||
| 539 | static __initconst u64 amd_hw_cache_event_ids | ||
| 540 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 541 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 542 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 543 | { | ||
| 544 | [ C(L1D) ] = { | ||
| 545 | [ C(OP_READ) ] = { | ||
| 546 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
| 547 | [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ | ||
| 548 | }, | ||
| 549 | [ C(OP_WRITE) ] = { | ||
| 550 | [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ | ||
| 551 | [ C(RESULT_MISS) ] = 0, | ||
| 552 | }, | ||
| 553 | [ C(OP_PREFETCH) ] = { | ||
| 554 | [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts */ | ||
| 555 | [ C(RESULT_MISS) ] = 0x0167, /* Data Prefetcher :cancelled */ | ||
| 556 | }, | ||
| 557 | }, | ||
| 558 | [ C(L1I ) ] = { | ||
| 559 | [ C(OP_READ) ] = { | ||
| 560 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches */ | ||
| 561 | [ C(RESULT_MISS) ] = 0x0081, /* Instruction cache misses */ | ||
| 562 | }, | ||
| 563 | [ C(OP_WRITE) ] = { | ||
| 564 | [ C(RESULT_ACCESS) ] = -1, | ||
| 565 | [ C(RESULT_MISS) ] = -1, | ||
| 566 | }, | ||
| 567 | [ C(OP_PREFETCH) ] = { | ||
| 568 | [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */ | ||
| 569 | [ C(RESULT_MISS) ] = 0, | ||
| 570 | }, | ||
| 571 | }, | ||
| 572 | [ C(LL ) ] = { | ||
| 573 | [ C(OP_READ) ] = { | ||
| 574 | [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */ | ||
| 575 | [ C(RESULT_MISS) ] = 0x037E, /* L2 Cache Misses : IC+DC */ | ||
| 576 | }, | ||
| 577 | [ C(OP_WRITE) ] = { | ||
| 578 | [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback */ | ||
| 579 | [ C(RESULT_MISS) ] = 0, | ||
| 580 | }, | ||
| 581 | [ C(OP_PREFETCH) ] = { | ||
| 582 | [ C(RESULT_ACCESS) ] = 0, | ||
| 583 | [ C(RESULT_MISS) ] = 0, | ||
| 584 | }, | ||
| 585 | }, | ||
| 586 | [ C(DTLB) ] = { | ||
| 587 | [ C(OP_READ) ] = { | ||
| 588 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
| 589 | [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */ | ||
| 590 | }, | ||
| 591 | [ C(OP_WRITE) ] = { | ||
| 592 | [ C(RESULT_ACCESS) ] = 0, | ||
| 593 | [ C(RESULT_MISS) ] = 0, | ||
| 594 | }, | ||
| 595 | [ C(OP_PREFETCH) ] = { | ||
| 596 | [ C(RESULT_ACCESS) ] = 0, | ||
| 597 | [ C(RESULT_MISS) ] = 0, | ||
| 598 | }, | ||
| 599 | }, | ||
| 600 | [ C(ITLB) ] = { | ||
| 601 | [ C(OP_READ) ] = { | ||
| 602 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes */ | ||
| 603 | [ C(RESULT_MISS) ] = 0x0085, /* Instr. fetch ITLB misses */ | ||
| 604 | }, | ||
| 605 | [ C(OP_WRITE) ] = { | ||
| 606 | [ C(RESULT_ACCESS) ] = -1, | ||
| 607 | [ C(RESULT_MISS) ] = -1, | ||
| 608 | }, | ||
| 609 | [ C(OP_PREFETCH) ] = { | ||
| 610 | [ C(RESULT_ACCESS) ] = -1, | ||
| 611 | [ C(RESULT_MISS) ] = -1, | ||
| 612 | }, | ||
| 613 | }, | ||
| 614 | [ C(BPU ) ] = { | ||
| 615 | [ C(OP_READ) ] = { | ||
| 616 | [ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr. */ | ||
| 617 | [ C(RESULT_MISS) ] = 0x00c3, /* Retired Mispredicted BI */ | ||
| 618 | }, | ||
| 619 | [ C(OP_WRITE) ] = { | ||
| 620 | [ C(RESULT_ACCESS) ] = -1, | ||
| 621 | [ C(RESULT_MISS) ] = -1, | ||
| 622 | }, | ||
| 623 | [ C(OP_PREFETCH) ] = { | ||
| 624 | [ C(RESULT_ACCESS) ] = -1, | ||
| 625 | [ C(RESULT_MISS) ] = -1, | ||
| 626 | }, | ||
| 627 | }, | ||
| 628 | }; | ||
| 629 | |||
| 630 | /* | ||
| 631 | * AMD Performance Monitor K7 and later. | ||
| 632 | */ | ||
| 633 | static const u64 amd_perfmon_event_map[] = | ||
| 634 | { | ||
| 635 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, | ||
| 636 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 637 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, | ||
| 638 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, | ||
| 639 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 640 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 641 | }; | ||
| 642 | |||
| 643 | static u64 amd_pmu_event_map(int hw_event) | ||
| 644 | { | ||
| 645 | return amd_perfmon_event_map[hw_event]; | ||
| 646 | } | ||
| 647 | |||
| 648 | static u64 amd_pmu_raw_event(u64 hw_event) | ||
| 649 | { | ||
| 650 | #define K7_EVNTSEL_EVENT_MASK 0x7000000FFULL | ||
| 651 | #define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL | ||
| 652 | #define K7_EVNTSEL_EDGE_MASK 0x000040000ULL | ||
| 653 | #define K7_EVNTSEL_INV_MASK 0x000800000ULL | ||
| 654 | #define K7_EVNTSEL_REG_MASK 0x0FF000000ULL | ||
| 655 | |||
| 656 | #define K7_EVNTSEL_MASK \ | ||
| 657 | (K7_EVNTSEL_EVENT_MASK | \ | ||
| 658 | K7_EVNTSEL_UNIT_MASK | \ | ||
| 659 | K7_EVNTSEL_EDGE_MASK | \ | ||
| 660 | K7_EVNTSEL_INV_MASK | \ | ||
| 661 | K7_EVNTSEL_REG_MASK) | ||
| 662 | |||
| 663 | return hw_event & K7_EVNTSEL_MASK; | ||
| 664 | } | ||
| 665 | |||
| 666 | /* | 186 | /* |
| 667 | * Propagate event elapsed time into the generic event. | 187 | * Propagate event elapsed time into the generic event. |
| 668 | * Can only be executed on the CPU where the event is active. | 188 | * Can only be executed on the CPU where the event is active. |
| @@ -914,42 +434,6 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) | |||
| 914 | return 0; | 434 | return 0; |
| 915 | } | 435 | } |
| 916 | 436 | ||
| 917 | static void intel_pmu_enable_bts(u64 config) | ||
| 918 | { | ||
| 919 | unsigned long debugctlmsr; | ||
| 920 | |||
| 921 | debugctlmsr = get_debugctlmsr(); | ||
| 922 | |||
| 923 | debugctlmsr |= X86_DEBUGCTL_TR; | ||
| 924 | debugctlmsr |= X86_DEBUGCTL_BTS; | ||
| 925 | debugctlmsr |= X86_DEBUGCTL_BTINT; | ||
| 926 | |||
| 927 | if (!(config & ARCH_PERFMON_EVENTSEL_OS)) | ||
| 928 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; | ||
| 929 | |||
| 930 | if (!(config & ARCH_PERFMON_EVENTSEL_USR)) | ||
| 931 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; | ||
| 932 | |||
| 933 | update_debugctlmsr(debugctlmsr); | ||
| 934 | } | ||
| 935 | |||
| 936 | static void intel_pmu_disable_bts(void) | ||
| 937 | { | ||
| 938 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 939 | unsigned long debugctlmsr; | ||
| 940 | |||
| 941 | if (!cpuc->ds) | ||
| 942 | return; | ||
| 943 | |||
| 944 | debugctlmsr = get_debugctlmsr(); | ||
| 945 | |||
| 946 | debugctlmsr &= | ||
| 947 | ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | | ||
| 948 | X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); | ||
| 949 | |||
| 950 | update_debugctlmsr(debugctlmsr); | ||
| 951 | } | ||
| 952 | |||
| 953 | /* | 437 | /* |
| 954 | * Setup the hardware configuration for a given attr_type | 438 | * Setup the hardware configuration for a given attr_type |
| 955 | */ | 439 | */ |
| @@ -988,6 +472,8 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
| 988 | hwc->config = ARCH_PERFMON_EVENTSEL_INT; | 472 | hwc->config = ARCH_PERFMON_EVENTSEL_INT; |
| 989 | 473 | ||
| 990 | hwc->idx = -1; | 474 | hwc->idx = -1; |
| 475 | hwc->last_cpu = -1; | ||
| 476 | hwc->last_tag = ~0ULL; | ||
| 991 | 477 | ||
| 992 | /* | 478 | /* |
| 993 | * Count user and OS events unless requested not to. | 479 | * Count user and OS events unless requested not to. |
| @@ -1056,216 +542,323 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
| 1056 | return 0; | 542 | return 0; |
| 1057 | } | 543 | } |
| 1058 | 544 | ||
| 1059 | static void p6_pmu_disable_all(void) | 545 | static void x86_pmu_disable_all(void) |
| 1060 | { | 546 | { |
| 1061 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 547 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1062 | u64 val; | 548 | int idx; |
| 1063 | |||
| 1064 | if (!cpuc->enabled) | ||
| 1065 | return; | ||
| 1066 | 549 | ||
| 1067 | cpuc->enabled = 0; | 550 | for (idx = 0; idx < x86_pmu.num_events; idx++) { |
| 1068 | barrier(); | 551 | u64 val; |
| 1069 | 552 | ||
| 1070 | /* p6 only has one enable register */ | 553 | if (!test_bit(idx, cpuc->active_mask)) |
| 1071 | rdmsrl(MSR_P6_EVNTSEL0, val); | 554 | continue; |
| 1072 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | 555 | rdmsrl(x86_pmu.eventsel + idx, val); |
| 1073 | wrmsrl(MSR_P6_EVNTSEL0, val); | 556 | if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE)) |
| 557 | continue; | ||
| 558 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 559 | wrmsrl(x86_pmu.eventsel + idx, val); | ||
| 560 | } | ||
| 1074 | } | 561 | } |
| 1075 | 562 | ||
| 1076 | static void intel_pmu_disable_all(void) | 563 | void hw_perf_disable(void) |
| 1077 | { | 564 | { |
| 1078 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 565 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1079 | 566 | ||
| 567 | if (!x86_pmu_initialized()) | ||
| 568 | return; | ||
| 569 | |||
| 1080 | if (!cpuc->enabled) | 570 | if (!cpuc->enabled) |
| 1081 | return; | 571 | return; |
| 1082 | 572 | ||
| 573 | cpuc->n_added = 0; | ||
| 1083 | cpuc->enabled = 0; | 574 | cpuc->enabled = 0; |
| 1084 | barrier(); | 575 | barrier(); |
| 1085 | 576 | ||
| 1086 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | 577 | x86_pmu.disable_all(); |
| 1087 | |||
| 1088 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) | ||
| 1089 | intel_pmu_disable_bts(); | ||
| 1090 | } | 578 | } |
| 1091 | 579 | ||
| 1092 | static void amd_pmu_disable_all(void) | 580 | static void x86_pmu_enable_all(void) |
| 1093 | { | 581 | { |
| 1094 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 582 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1095 | int idx; | 583 | int idx; |
| 1096 | 584 | ||
| 1097 | if (!cpuc->enabled) | ||
| 1098 | return; | ||
| 1099 | |||
| 1100 | cpuc->enabled = 0; | ||
| 1101 | /* | ||
| 1102 | * ensure we write the disable before we start disabling the | ||
| 1103 | * events proper, so that amd_pmu_enable_event() does the | ||
| 1104 | * right thing. | ||
| 1105 | */ | ||
| 1106 | barrier(); | ||
| 1107 | |||
| 1108 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | 585 | for (idx = 0; idx < x86_pmu.num_events; idx++) { |
| 586 | struct perf_event *event = cpuc->events[idx]; | ||
| 1109 | u64 val; | 587 | u64 val; |
| 1110 | 588 | ||
| 1111 | if (!test_bit(idx, cpuc->active_mask)) | 589 | if (!test_bit(idx, cpuc->active_mask)) |
| 1112 | continue; | 590 | continue; |
| 1113 | rdmsrl(MSR_K7_EVNTSEL0 + idx, val); | 591 | |
| 1114 | if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE)) | 592 | val = event->hw.config; |
| 1115 | continue; | 593 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; |
| 1116 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | 594 | wrmsrl(x86_pmu.eventsel + idx, val); |
| 1117 | wrmsrl(MSR_K7_EVNTSEL0 + idx, val); | ||
| 1118 | } | 595 | } |
| 1119 | } | 596 | } |
| 1120 | 597 | ||
| 1121 | void hw_perf_disable(void) | 598 | static const struct pmu pmu; |
| 599 | |||
| 600 | static inline int is_x86_event(struct perf_event *event) | ||
| 1122 | { | 601 | { |
| 1123 | if (!x86_pmu_initialized()) | 602 | return event->pmu == &pmu; |
| 1124 | return; | ||
| 1125 | return x86_pmu.disable_all(); | ||
| 1126 | } | 603 | } |
| 1127 | 604 | ||
| 1128 | static void p6_pmu_enable_all(void) | 605 | static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) |
| 1129 | { | 606 | { |
| 1130 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 607 | struct event_constraint *c, *constraints[X86_PMC_IDX_MAX]; |
| 1131 | unsigned long val; | 608 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
| 609 | int i, j, w, wmax, num = 0; | ||
| 610 | struct hw_perf_event *hwc; | ||
| 1132 | 611 | ||
| 1133 | if (cpuc->enabled) | 612 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); |
| 1134 | return; | ||
| 1135 | 613 | ||
| 1136 | cpuc->enabled = 1; | 614 | for (i = 0; i < n; i++) { |
| 1137 | barrier(); | 615 | constraints[i] = |
| 616 | x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); | ||
| 617 | } | ||
| 1138 | 618 | ||
| 1139 | /* p6 only has one enable register */ | 619 | /* |
| 1140 | rdmsrl(MSR_P6_EVNTSEL0, val); | 620 | * fastpath, try to reuse previous register |
| 1141 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 621 | */ |
| 1142 | wrmsrl(MSR_P6_EVNTSEL0, val); | 622 | for (i = 0; i < n; i++) { |
| 1143 | } | 623 | hwc = &cpuc->event_list[i]->hw; |
| 624 | c = constraints[i]; | ||
| 1144 | 625 | ||
| 1145 | static void intel_pmu_enable_all(void) | 626 | /* never assigned */ |
| 1146 | { | 627 | if (hwc->idx == -1) |
| 1147 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 628 | break; |
| 1148 | 629 | ||
| 1149 | if (cpuc->enabled) | 630 | /* constraint still honored */ |
| 1150 | return; | 631 | if (!test_bit(hwc->idx, c->idxmsk)) |
| 632 | break; | ||
| 1151 | 633 | ||
| 1152 | cpuc->enabled = 1; | 634 | /* not already used */ |
| 1153 | barrier(); | 635 | if (test_bit(hwc->idx, used_mask)) |
| 636 | break; | ||
| 637 | |||
| 638 | set_bit(hwc->idx, used_mask); | ||
| 639 | if (assign) | ||
| 640 | assign[i] = hwc->idx; | ||
| 641 | } | ||
| 642 | if (i == n) | ||
| 643 | goto done; | ||
| 644 | |||
| 645 | /* | ||
| 646 | * begin slow path | ||
| 647 | */ | ||
| 648 | |||
| 649 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); | ||
| 650 | |||
| 651 | /* | ||
| 652 | * weight = number of possible counters | ||
| 653 | * | ||
| 654 | * 1 = most constrained, only works on one counter | ||
| 655 | * wmax = least constrained, works on any counter | ||
| 656 | * | ||
| 657 | * assign events to counters starting with most | ||
| 658 | * constrained events. | ||
| 659 | */ | ||
| 660 | wmax = x86_pmu.num_events; | ||
| 661 | |||
| 662 | /* | ||
| 663 | * when fixed event counters are present, | ||
| 664 | * wmax is incremented by 1 to account | ||
| 665 | * for one more choice | ||
| 666 | */ | ||
| 667 | if (x86_pmu.num_events_fixed) | ||
| 668 | wmax++; | ||
| 1154 | 669 | ||
| 1155 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | 670 | for (w = 1, num = n; num && w <= wmax; w++) { |
| 671 | /* for each event */ | ||
| 672 | for (i = 0; num && i < n; i++) { | ||
| 673 | c = constraints[i]; | ||
| 674 | hwc = &cpuc->event_list[i]->hw; | ||
| 1156 | 675 | ||
| 1157 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { | 676 | if (c->weight != w) |
| 1158 | struct perf_event *event = | 677 | continue; |
| 1159 | cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
| 1160 | 678 | ||
| 1161 | if (WARN_ON_ONCE(!event)) | 679 | for_each_bit(j, c->idxmsk, X86_PMC_IDX_MAX) { |
| 1162 | return; | 680 | if (!test_bit(j, used_mask)) |
| 681 | break; | ||
| 682 | } | ||
| 683 | |||
| 684 | if (j == X86_PMC_IDX_MAX) | ||
| 685 | break; | ||
| 686 | |||
| 687 | set_bit(j, used_mask); | ||
| 1163 | 688 | ||
| 1164 | intel_pmu_enable_bts(event->hw.config); | 689 | if (assign) |
| 690 | assign[i] = j; | ||
| 691 | num--; | ||
| 692 | } | ||
| 693 | } | ||
| 694 | done: | ||
| 695 | /* | ||
| 696 | * scheduling failed or is just a simulation, | ||
| 697 | * free resources if necessary | ||
| 698 | */ | ||
| 699 | if (!assign || num) { | ||
| 700 | for (i = 0; i < n; i++) { | ||
| 701 | if (x86_pmu.put_event_constraints) | ||
| 702 | x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]); | ||
| 703 | } | ||
| 1165 | } | 704 | } |
| 705 | return num ? -ENOSPC : 0; | ||
| 1166 | } | 706 | } |
| 1167 | 707 | ||
| 1168 | static void amd_pmu_enable_all(void) | 708 | /* |
| 709 | * dogrp: true if must collect siblings events (group) | ||
| 710 | * returns total number of events and error code | ||
| 711 | */ | ||
| 712 | static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, bool dogrp) | ||
| 1169 | { | 713 | { |
| 1170 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 714 | struct perf_event *event; |
| 1171 | int idx; | 715 | int n, max_count; |
| 1172 | 716 | ||
| 1173 | if (cpuc->enabled) | 717 | max_count = x86_pmu.num_events + x86_pmu.num_events_fixed; |
| 1174 | return; | ||
| 1175 | 718 | ||
| 1176 | cpuc->enabled = 1; | 719 | /* current number of events already accepted */ |
| 1177 | barrier(); | 720 | n = cpuc->n_events; |
| 1178 | 721 | ||
| 1179 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | 722 | if (is_x86_event(leader)) { |
| 1180 | struct perf_event *event = cpuc->events[idx]; | 723 | if (n >= max_count) |
| 1181 | u64 val; | 724 | return -ENOSPC; |
| 725 | cpuc->event_list[n] = leader; | ||
| 726 | n++; | ||
| 727 | } | ||
| 728 | if (!dogrp) | ||
| 729 | return n; | ||
| 1182 | 730 | ||
| 1183 | if (!test_bit(idx, cpuc->active_mask)) | 731 | list_for_each_entry(event, &leader->sibling_list, group_entry) { |
| 732 | if (!is_x86_event(event) || | ||
| 733 | event->state <= PERF_EVENT_STATE_OFF) | ||
| 1184 | continue; | 734 | continue; |
| 1185 | 735 | ||
| 1186 | val = event->hw.config; | 736 | if (n >= max_count) |
| 1187 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 737 | return -ENOSPC; |
| 1188 | wrmsrl(MSR_K7_EVNTSEL0 + idx, val); | ||
| 1189 | } | ||
| 1190 | } | ||
| 1191 | 738 | ||
| 1192 | void hw_perf_enable(void) | 739 | cpuc->event_list[n] = event; |
| 1193 | { | 740 | n++; |
| 1194 | if (!x86_pmu_initialized()) | 741 | } |
| 1195 | return; | 742 | return n; |
| 1196 | x86_pmu.enable_all(); | ||
| 1197 | } | 743 | } |
| 1198 | 744 | ||
| 1199 | static inline u64 intel_pmu_get_status(void) | 745 | static inline void x86_assign_hw_event(struct perf_event *event, |
| 746 | struct cpu_hw_events *cpuc, int i) | ||
| 1200 | { | 747 | { |
| 1201 | u64 status; | 748 | struct hw_perf_event *hwc = &event->hw; |
| 1202 | 749 | ||
| 1203 | rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); | 750 | hwc->idx = cpuc->assign[i]; |
| 751 | hwc->last_cpu = smp_processor_id(); | ||
| 752 | hwc->last_tag = ++cpuc->tags[i]; | ||
| 1204 | 753 | ||
| 1205 | return status; | 754 | if (hwc->idx == X86_PMC_IDX_FIXED_BTS) { |
| 755 | hwc->config_base = 0; | ||
| 756 | hwc->event_base = 0; | ||
| 757 | } else if (hwc->idx >= X86_PMC_IDX_FIXED) { | ||
| 758 | hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; | ||
| 759 | /* | ||
| 760 | * We set it so that event_base + idx in wrmsr/rdmsr maps to | ||
| 761 | * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2: | ||
| 762 | */ | ||
| 763 | hwc->event_base = | ||
| 764 | MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED; | ||
| 765 | } else { | ||
| 766 | hwc->config_base = x86_pmu.eventsel; | ||
| 767 | hwc->event_base = x86_pmu.perfctr; | ||
| 768 | } | ||
| 1206 | } | 769 | } |
| 1207 | 770 | ||
| 1208 | static inline void intel_pmu_ack_status(u64 ack) | 771 | static inline int match_prev_assignment(struct hw_perf_event *hwc, |
| 772 | struct cpu_hw_events *cpuc, | ||
| 773 | int i) | ||
| 1209 | { | 774 | { |
| 1210 | wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); | 775 | return hwc->idx == cpuc->assign[i] && |
| 776 | hwc->last_cpu == smp_processor_id() && | ||
| 777 | hwc->last_tag == cpuc->tags[i]; | ||
| 1211 | } | 778 | } |
| 1212 | 779 | ||
| 1213 | static inline void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) | 780 | static void x86_pmu_stop(struct perf_event *event); |
| 1214 | { | ||
| 1215 | (void)checking_wrmsrl(hwc->config_base + idx, | ||
| 1216 | hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); | ||
| 1217 | } | ||
| 1218 | 781 | ||
| 1219 | static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx) | 782 | void hw_perf_enable(void) |
| 1220 | { | 783 | { |
| 1221 | (void)checking_wrmsrl(hwc->config_base + idx, hwc->config); | 784 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1222 | } | 785 | struct perf_event *event; |
| 786 | struct hw_perf_event *hwc; | ||
| 787 | int i; | ||
| 1223 | 788 | ||
| 1224 | static inline void | 789 | if (!x86_pmu_initialized()) |
| 1225 | intel_pmu_disable_fixed(struct hw_perf_event *hwc, int __idx) | 790 | return; |
| 1226 | { | ||
| 1227 | int idx = __idx - X86_PMC_IDX_FIXED; | ||
| 1228 | u64 ctrl_val, mask; | ||
| 1229 | 791 | ||
| 1230 | mask = 0xfULL << (idx * 4); | 792 | if (cpuc->enabled) |
| 793 | return; | ||
| 1231 | 794 | ||
| 1232 | rdmsrl(hwc->config_base, ctrl_val); | 795 | if (cpuc->n_added) { |
| 1233 | ctrl_val &= ~mask; | 796 | /* |
| 1234 | (void)checking_wrmsrl(hwc->config_base, ctrl_val); | 797 | * apply assignment obtained either from |
| 1235 | } | 798 | * hw_perf_group_sched_in() or x86_pmu_enable() |
| 799 | * | ||
| 800 | * step1: save events moving to new counters | ||
| 801 | * step2: reprogram moved events into new counters | ||
| 802 | */ | ||
| 803 | for (i = 0; i < cpuc->n_events; i++) { | ||
| 1236 | 804 | ||
| 1237 | static inline void | 805 | event = cpuc->event_list[i]; |
| 1238 | p6_pmu_disable_event(struct hw_perf_event *hwc, int idx) | 806 | hwc = &event->hw; |
| 1239 | { | ||
| 1240 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 1241 | u64 val = P6_NOP_EVENT; | ||
| 1242 | 807 | ||
| 1243 | if (cpuc->enabled) | 808 | /* |
| 1244 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 809 | * we can avoid reprogramming counter if: |
| 810 | * - assigned same counter as last time | ||
| 811 | * - running on same CPU as last time | ||
| 812 | * - no other event has used the counter since | ||
| 813 | */ | ||
| 814 | if (hwc->idx == -1 || | ||
| 815 | match_prev_assignment(hwc, cpuc, i)) | ||
| 816 | continue; | ||
| 1245 | 817 | ||
| 1246 | (void)checking_wrmsrl(hwc->config_base + idx, val); | 818 | x86_pmu_stop(event); |
| 1247 | } | ||
| 1248 | 819 | ||
| 1249 | static inline void | 820 | hwc->idx = -1; |
| 1250 | intel_pmu_disable_event(struct hw_perf_event *hwc, int idx) | 821 | } |
| 1251 | { | ||
| 1252 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
| 1253 | intel_pmu_disable_bts(); | ||
| 1254 | return; | ||
| 1255 | } | ||
| 1256 | 822 | ||
| 1257 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 823 | for (i = 0; i < cpuc->n_events; i++) { |
| 1258 | intel_pmu_disable_fixed(hwc, idx); | 824 | |
| 1259 | return; | 825 | event = cpuc->event_list[i]; |
| 826 | hwc = &event->hw; | ||
| 827 | |||
| 828 | if (hwc->idx == -1) { | ||
| 829 | x86_assign_hw_event(event, cpuc, i); | ||
| 830 | x86_perf_event_set_period(event, hwc, hwc->idx); | ||
| 831 | } | ||
| 832 | /* | ||
| 833 | * need to mark as active because x86_pmu_disable() | ||
| 834 | * clear active_mask and events[] yet it preserves | ||
| 835 | * idx | ||
| 836 | */ | ||
| 837 | set_bit(hwc->idx, cpuc->active_mask); | ||
| 838 | cpuc->events[hwc->idx] = event; | ||
| 839 | |||
| 840 | x86_pmu.enable(hwc, hwc->idx); | ||
| 841 | perf_event_update_userpage(event); | ||
| 842 | } | ||
| 843 | cpuc->n_added = 0; | ||
| 844 | perf_events_lapic_init(); | ||
| 1260 | } | 845 | } |
| 1261 | 846 | ||
| 1262 | x86_pmu_disable_event(hwc, idx); | 847 | cpuc->enabled = 1; |
| 848 | barrier(); | ||
| 849 | |||
| 850 | x86_pmu.enable_all(); | ||
| 851 | } | ||
| 852 | |||
| 853 | static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
| 854 | { | ||
| 855 | (void)checking_wrmsrl(hwc->config_base + idx, | ||
| 856 | hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); | ||
| 1263 | } | 857 | } |
| 1264 | 858 | ||
| 1265 | static inline void | 859 | static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx) |
| 1266 | amd_pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
| 1267 | { | 860 | { |
| 1268 | x86_pmu_disable_event(hwc, idx); | 861 | (void)checking_wrmsrl(hwc->config_base + idx, hwc->config); |
| 1269 | } | 862 | } |
| 1270 | 863 | ||
| 1271 | static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); | 864 | static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); |
| @@ -1326,220 +919,60 @@ x86_perf_event_set_period(struct perf_event *event, | |||
| 1326 | return ret; | 919 | return ret; |
| 1327 | } | 920 | } |
| 1328 | 921 | ||
| 1329 | static inline void | 922 | static void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) |
| 1330 | intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) | ||
| 1331 | { | ||
| 1332 | int idx = __idx - X86_PMC_IDX_FIXED; | ||
| 1333 | u64 ctrl_val, bits, mask; | ||
| 1334 | int err; | ||
| 1335 | |||
| 1336 | /* | ||
| 1337 | * Enable IRQ generation (0x8), | ||
| 1338 | * and enable ring-3 counting (0x2) and ring-0 counting (0x1) | ||
| 1339 | * if requested: | ||
| 1340 | */ | ||
| 1341 | bits = 0x8ULL; | ||
| 1342 | if (hwc->config & ARCH_PERFMON_EVENTSEL_USR) | ||
| 1343 | bits |= 0x2; | ||
| 1344 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | ||
| 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 | |||
| 1353 | bits <<= (idx * 4); | ||
| 1354 | mask = 0xfULL << (idx * 4); | ||
| 1355 | |||
| 1356 | rdmsrl(hwc->config_base, ctrl_val); | ||
| 1357 | ctrl_val &= ~mask; | ||
| 1358 | ctrl_val |= bits; | ||
| 1359 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | static void p6_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
| 1363 | { | 923 | { |
| 1364 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 924 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1365 | u64 val; | ||
| 1366 | |||
| 1367 | val = hwc->config; | ||
| 1368 | if (cpuc->enabled) | 925 | if (cpuc->enabled) |
| 1369 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 926 | __x86_pmu_enable_event(hwc, idx); |
| 1370 | |||
| 1371 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
| 1372 | } | 927 | } |
| 1373 | 928 | ||
| 1374 | 929 | /* | |
| 1375 | static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) | 930 | * activate a single event |
| 1376 | { | 931 | * |
| 1377 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | 932 | * The event is added to the group of enabled events |
| 1378 | if (!__get_cpu_var(cpu_hw_events).enabled) | 933 | * but only if it can be scehduled with existing events. |
| 1379 | return; | 934 | * |
| 1380 | 935 | * Called with PMU disabled. If successful and return value 1, | |
| 1381 | intel_pmu_enable_bts(hwc->config); | 936 | * then guaranteed to call perf_enable() and hw_perf_enable() |
| 1382 | return; | 937 | */ |
| 1383 | } | 938 | static int x86_pmu_enable(struct perf_event *event) |
| 1384 | |||
| 1385 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
| 1386 | intel_pmu_enable_fixed(hwc, idx); | ||
| 1387 | return; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | x86_pmu_enable_event(hwc, idx); | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | static void amd_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
| 1394 | { | 939 | { |
| 1395 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 940 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 941 | struct hw_perf_event *hwc; | ||
| 942 | int assign[X86_PMC_IDX_MAX]; | ||
| 943 | int n, n0, ret; | ||
| 1396 | 944 | ||
| 1397 | if (cpuc->enabled) | 945 | hwc = &event->hw; |
| 1398 | x86_pmu_enable_event(hwc, idx); | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | static int fixed_mode_idx(struct hw_perf_event *hwc) | ||
| 1402 | { | ||
| 1403 | unsigned int hw_event; | ||
| 1404 | |||
| 1405 | hw_event = hwc->config & ARCH_PERFMON_EVENT_MASK; | ||
| 1406 | |||
| 1407 | if (unlikely((hw_event == | ||
| 1408 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | ||
| 1409 | (hwc->sample_period == 1))) | ||
| 1410 | return X86_PMC_IDX_FIXED_BTS; | ||
| 1411 | 946 | ||
| 1412 | if (!x86_pmu.num_events_fixed) | 947 | n0 = cpuc->n_events; |
| 1413 | return -1; | 948 | n = collect_events(cpuc, event, false); |
| 949 | if (n < 0) | ||
| 950 | return n; | ||
| 1414 | 951 | ||
| 952 | ret = x86_schedule_events(cpuc, n, assign); | ||
| 953 | if (ret) | ||
| 954 | return ret; | ||
| 1415 | /* | 955 | /* |
| 1416 | * fixed counters do not take all possible filters | 956 | * copy new assignment, now we know it is possible |
| 957 | * will be used by hw_perf_enable() | ||
| 1417 | */ | 958 | */ |
| 1418 | if (hwc->config & ARCH_PERFMON_EVENT_FILTER_MASK) | 959 | memcpy(cpuc->assign, assign, n*sizeof(int)); |
| 1419 | return -1; | ||
| 1420 | 960 | ||
| 1421 | if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) | 961 | cpuc->n_events = n; |
| 1422 | return X86_PMC_IDX_FIXED_INSTRUCTIONS; | 962 | cpuc->n_added = n - n0; |
| 1423 | if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) | ||
| 1424 | return X86_PMC_IDX_FIXED_CPU_CYCLES; | ||
| 1425 | if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_BUS_CYCLES))) | ||
| 1426 | return X86_PMC_IDX_FIXED_BUS_CYCLES; | ||
| 1427 | 963 | ||
| 1428 | return -1; | 964 | return 0; |
| 1429 | } | ||
| 1430 | |||
| 1431 | /* | ||
| 1432 | * generic counter allocator: get next free counter | ||
| 1433 | */ | ||
| 1434 | static int | ||
| 1435 | gen_get_event_idx(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc) | ||
| 1436 | { | ||
| 1437 | int idx; | ||
| 1438 | |||
| 1439 | idx = find_first_zero_bit(cpuc->used_mask, x86_pmu.num_events); | ||
| 1440 | return idx == x86_pmu.num_events ? -1 : idx; | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | /* | ||
| 1444 | * intel-specific counter allocator: check event constraints | ||
| 1445 | */ | ||
| 1446 | static int | ||
| 1447 | intel_get_event_idx(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc) | ||
| 1448 | { | ||
| 1449 | const struct event_constraint *event_constraint; | ||
| 1450 | int i, code; | ||
| 1451 | |||
| 1452 | if (!event_constraints) | ||
| 1453 | goto skip; | ||
| 1454 | |||
| 1455 | code = hwc->config & CORE_EVNTSEL_EVENT_MASK; | ||
| 1456 | |||
| 1457 | for_each_event_constraint(event_constraint, event_constraints) { | ||
| 1458 | if (code == event_constraint->code) { | ||
| 1459 | for_each_bit(i, event_constraint->idxmsk, X86_PMC_IDX_MAX) { | ||
| 1460 | if (!test_and_set_bit(i, cpuc->used_mask)) | ||
| 1461 | return i; | ||
| 1462 | } | ||
| 1463 | return -1; | ||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | skip: | ||
| 1467 | return gen_get_event_idx(cpuc, hwc); | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | static int | ||
| 1471 | x86_schedule_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc) | ||
| 1472 | { | ||
| 1473 | int idx; | ||
| 1474 | |||
| 1475 | idx = fixed_mode_idx(hwc); | ||
| 1476 | if (idx == X86_PMC_IDX_FIXED_BTS) { | ||
| 1477 | /* BTS is already occupied. */ | ||
| 1478 | if (test_and_set_bit(idx, cpuc->used_mask)) | ||
| 1479 | return -EAGAIN; | ||
| 1480 | |||
| 1481 | hwc->config_base = 0; | ||
| 1482 | hwc->event_base = 0; | ||
| 1483 | hwc->idx = idx; | ||
| 1484 | } else if (idx >= 0) { | ||
| 1485 | /* | ||
| 1486 | * Try to get the fixed event, if that is already taken | ||
| 1487 | * then try to get a generic event: | ||
| 1488 | */ | ||
| 1489 | if (test_and_set_bit(idx, cpuc->used_mask)) | ||
| 1490 | goto try_generic; | ||
| 1491 | |||
| 1492 | hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; | ||
| 1493 | /* | ||
| 1494 | * We set it so that event_base + idx in wrmsr/rdmsr maps to | ||
| 1495 | * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2: | ||
| 1496 | */ | ||
| 1497 | hwc->event_base = | ||
| 1498 | MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED; | ||
| 1499 | hwc->idx = idx; | ||
| 1500 | } else { | ||
| 1501 | idx = hwc->idx; | ||
| 1502 | /* Try to get the previous generic event again */ | ||
| 1503 | if (idx == -1 || test_and_set_bit(idx, cpuc->used_mask)) { | ||
| 1504 | try_generic: | ||
| 1505 | idx = x86_pmu.get_event_idx(cpuc, hwc); | ||
| 1506 | if (idx == -1) | ||
| 1507 | return -EAGAIN; | ||
| 1508 | |||
| 1509 | set_bit(idx, cpuc->used_mask); | ||
| 1510 | hwc->idx = idx; | ||
| 1511 | } | ||
| 1512 | hwc->config_base = x86_pmu.eventsel; | ||
| 1513 | hwc->event_base = x86_pmu.perfctr; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | return idx; | ||
| 1517 | } | 965 | } |
| 1518 | 966 | ||
| 1519 | /* | 967 | static int x86_pmu_start(struct perf_event *event) |
| 1520 | * Find a PMC slot for the freshly enabled / scheduled in event: | ||
| 1521 | */ | ||
| 1522 | static int x86_pmu_enable(struct perf_event *event) | ||
| 1523 | { | 968 | { |
| 1524 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 1525 | struct hw_perf_event *hwc = &event->hw; | 969 | struct hw_perf_event *hwc = &event->hw; |
| 1526 | int idx; | ||
| 1527 | |||
| 1528 | idx = x86_schedule_event(cpuc, hwc); | ||
| 1529 | if (idx < 0) | ||
| 1530 | return idx; | ||
| 1531 | 970 | ||
| 1532 | perf_events_lapic_init(); | 971 | if (hwc->idx == -1) |
| 1533 | 972 | return -EAGAIN; | |
| 1534 | x86_pmu.disable(hwc, idx); | ||
| 1535 | 973 | ||
| 1536 | cpuc->events[idx] = event; | 974 | x86_perf_event_set_period(event, hwc, hwc->idx); |
| 1537 | set_bit(idx, cpuc->active_mask); | 975 | x86_pmu.enable(hwc, hwc->idx); |
| 1538 | |||
| 1539 | x86_perf_event_set_period(event, hwc, idx); | ||
| 1540 | x86_pmu.enable(hwc, idx); | ||
| 1541 | |||
| 1542 | perf_event_update_userpage(event); | ||
| 1543 | 976 | ||
| 1544 | return 0; | 977 | return 0; |
| 1545 | } | 978 | } |
| @@ -1583,7 +1016,7 @@ void perf_event_print_debug(void) | |||
| 1583 | pr_info("CPU#%d: overflow: %016llx\n", cpu, overflow); | 1016 | pr_info("CPU#%d: overflow: %016llx\n", cpu, overflow); |
| 1584 | pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed); | 1017 | pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed); |
| 1585 | } | 1018 | } |
| 1586 | pr_info("CPU#%d: used: %016llx\n", cpu, *(u64 *)cpuc->used_mask); | 1019 | pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask); |
| 1587 | 1020 | ||
| 1588 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | 1021 | for (idx = 0; idx < x86_pmu.num_events; idx++) { |
| 1589 | rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl); | 1022 | rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl); |
| @@ -1607,67 +1040,7 @@ void perf_event_print_debug(void) | |||
| 1607 | local_irq_restore(flags); | 1040 | local_irq_restore(flags); |
| 1608 | } | 1041 | } |
| 1609 | 1042 | ||
| 1610 | static void intel_pmu_drain_bts_buffer(struct cpu_hw_events *cpuc) | 1043 | static void x86_pmu_stop(struct perf_event *event) |
| 1611 | { | ||
| 1612 | struct debug_store *ds = cpuc->ds; | ||
| 1613 | struct bts_record { | ||
| 1614 | u64 from; | ||
| 1615 | u64 to; | ||
| 1616 | u64 flags; | ||
| 1617 | }; | ||
| 1618 | struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
| 1619 | struct bts_record *at, *top; | ||
| 1620 | struct perf_output_handle handle; | ||
| 1621 | struct perf_event_header header; | ||
| 1622 | struct perf_sample_data data; | ||
| 1623 | struct pt_regs regs; | ||
| 1624 | |||
| 1625 | if (!event) | ||
| 1626 | return; | ||
| 1627 | |||
| 1628 | if (!ds) | ||
| 1629 | return; | ||
| 1630 | |||
| 1631 | at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; | ||
| 1632 | top = (struct bts_record *)(unsigned long)ds->bts_index; | ||
| 1633 | |||
| 1634 | if (top <= at) | ||
| 1635 | return; | ||
| 1636 | |||
| 1637 | ds->bts_index = ds->bts_buffer_base; | ||
| 1638 | |||
| 1639 | |||
| 1640 | data.period = event->hw.last_period; | ||
| 1641 | data.addr = 0; | ||
| 1642 | data.raw = NULL; | ||
| 1643 | regs.ip = 0; | ||
| 1644 | |||
| 1645 | /* | ||
| 1646 | * Prepare a generic sample, i.e. fill in the invariant fields. | ||
| 1647 | * We will overwrite the from and to address before we output | ||
| 1648 | * the sample. | ||
| 1649 | */ | ||
| 1650 | perf_prepare_sample(&header, &data, event, ®s); | ||
| 1651 | |||
| 1652 | if (perf_output_begin(&handle, event, | ||
| 1653 | header.size * (top - at), 1, 1)) | ||
| 1654 | return; | ||
| 1655 | |||
| 1656 | for (; at < top; at++) { | ||
| 1657 | data.ip = at->from; | ||
| 1658 | data.addr = at->to; | ||
| 1659 | |||
| 1660 | perf_output_sample(&handle, &header, &data, event); | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | perf_output_end(&handle); | ||
| 1664 | |||
| 1665 | /* There's new data available. */ | ||
| 1666 | event->hw.interrupts++; | ||
| 1667 | event->pending_kill = POLL_IN; | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | static void x86_pmu_disable(struct perf_event *event) | ||
| 1671 | { | 1044 | { |
| 1672 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1045 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1673 | struct hw_perf_event *hwc = &event->hw; | 1046 | struct hw_perf_event *hwc = &event->hw; |
| @@ -1681,183 +1054,38 @@ static void x86_pmu_disable(struct perf_event *event) | |||
| 1681 | x86_pmu.disable(hwc, idx); | 1054 | x86_pmu.disable(hwc, idx); |
| 1682 | 1055 | ||
| 1683 | /* | 1056 | /* |
| 1684 | * Make sure the cleared pointer becomes visible before we | ||
| 1685 | * (potentially) free the event: | ||
| 1686 | */ | ||
| 1687 | barrier(); | ||
| 1688 | |||
| 1689 | /* | ||
| 1690 | * Drain the remaining delta count out of a event | 1057 | * Drain the remaining delta count out of a event |
| 1691 | * that we are disabling: | 1058 | * that we are disabling: |
| 1692 | */ | 1059 | */ |
| 1693 | x86_perf_event_update(event, hwc, idx); | 1060 | x86_perf_event_update(event, hwc, idx); |
| 1694 | 1061 | ||
| 1695 | /* Drain the remaining BTS records. */ | ||
| 1696 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) | ||
| 1697 | intel_pmu_drain_bts_buffer(cpuc); | ||
| 1698 | |||
| 1699 | cpuc->events[idx] = NULL; | 1062 | cpuc->events[idx] = NULL; |
| 1700 | clear_bit(idx, cpuc->used_mask); | ||
| 1701 | |||
| 1702 | perf_event_update_userpage(event); | ||
| 1703 | } | ||
| 1704 | |||
| 1705 | /* | ||
| 1706 | * Save and restart an expired event. Called by NMI contexts, | ||
| 1707 | * so it has to be careful about preempting normal event ops: | ||
| 1708 | */ | ||
| 1709 | static int intel_pmu_save_and_restart(struct perf_event *event) | ||
| 1710 | { | ||
| 1711 | struct hw_perf_event *hwc = &event->hw; | ||
| 1712 | int idx = hwc->idx; | ||
| 1713 | int ret; | ||
| 1714 | |||
| 1715 | x86_perf_event_update(event, hwc, idx); | ||
| 1716 | ret = x86_perf_event_set_period(event, hwc, idx); | ||
| 1717 | |||
| 1718 | if (event->state == PERF_EVENT_STATE_ACTIVE) | ||
| 1719 | intel_pmu_enable_event(hwc, idx); | ||
| 1720 | |||
| 1721 | return ret; | ||
| 1722 | } | 1063 | } |
| 1723 | 1064 | ||
| 1724 | static void intel_pmu_reset(void) | 1065 | static void x86_pmu_disable(struct perf_event *event) |
| 1725 | { | ||
| 1726 | struct debug_store *ds = __get_cpu_var(cpu_hw_events).ds; | ||
| 1727 | unsigned long flags; | ||
| 1728 | int idx; | ||
| 1729 | |||
| 1730 | if (!x86_pmu.num_events) | ||
| 1731 | return; | ||
| 1732 | |||
| 1733 | local_irq_save(flags); | ||
| 1734 | |||
| 1735 | printk("clearing PMU state on CPU#%d\n", smp_processor_id()); | ||
| 1736 | |||
| 1737 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | ||
| 1738 | checking_wrmsrl(x86_pmu.eventsel + idx, 0ull); | ||
| 1739 | checking_wrmsrl(x86_pmu.perfctr + idx, 0ull); | ||
| 1740 | } | ||
| 1741 | for (idx = 0; idx < x86_pmu.num_events_fixed; idx++) { | ||
| 1742 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); | ||
| 1743 | } | ||
| 1744 | if (ds) | ||
| 1745 | ds->bts_index = ds->bts_buffer_base; | ||
| 1746 | |||
| 1747 | local_irq_restore(flags); | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | static int p6_pmu_handle_irq(struct pt_regs *regs) | ||
| 1751 | { | ||
| 1752 | struct perf_sample_data data; | ||
| 1753 | struct cpu_hw_events *cpuc; | ||
| 1754 | struct perf_event *event; | ||
| 1755 | struct hw_perf_event *hwc; | ||
| 1756 | int idx, handled = 0; | ||
| 1757 | u64 val; | ||
| 1758 | |||
| 1759 | data.addr = 0; | ||
| 1760 | data.raw = NULL; | ||
| 1761 | |||
| 1762 | cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 1763 | |||
| 1764 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | ||
| 1765 | if (!test_bit(idx, cpuc->active_mask)) | ||
| 1766 | continue; | ||
| 1767 | |||
| 1768 | event = cpuc->events[idx]; | ||
| 1769 | hwc = &event->hw; | ||
| 1770 | |||
| 1771 | val = x86_perf_event_update(event, hwc, idx); | ||
| 1772 | if (val & (1ULL << (x86_pmu.event_bits - 1))) | ||
| 1773 | continue; | ||
| 1774 | |||
| 1775 | /* | ||
| 1776 | * event overflow | ||
| 1777 | */ | ||
| 1778 | handled = 1; | ||
| 1779 | data.period = event->hw.last_period; | ||
| 1780 | |||
| 1781 | if (!x86_perf_event_set_period(event, hwc, idx)) | ||
| 1782 | continue; | ||
| 1783 | |||
| 1784 | if (perf_event_overflow(event, 1, &data, regs)) | ||
| 1785 | p6_pmu_disable_event(hwc, idx); | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | if (handled) | ||
| 1789 | inc_irq_stat(apic_perf_irqs); | ||
| 1790 | |||
| 1791 | return handled; | ||
| 1792 | } | ||
| 1793 | |||
| 1794 | /* | ||
| 1795 | * This handler is triggered by the local APIC, so the APIC IRQ handling | ||
| 1796 | * rules apply: | ||
| 1797 | */ | ||
| 1798 | static int intel_pmu_handle_irq(struct pt_regs *regs) | ||
| 1799 | { | 1066 | { |
| 1800 | struct perf_sample_data data; | 1067 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1801 | struct cpu_hw_events *cpuc; | 1068 | int i; |
| 1802 | int bit, loops; | ||
| 1803 | u64 ack, status; | ||
| 1804 | |||
| 1805 | data.addr = 0; | ||
| 1806 | data.raw = NULL; | ||
| 1807 | |||
| 1808 | cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 1809 | |||
| 1810 | perf_disable(); | ||
| 1811 | intel_pmu_drain_bts_buffer(cpuc); | ||
| 1812 | status = intel_pmu_get_status(); | ||
| 1813 | if (!status) { | ||
| 1814 | perf_enable(); | ||
| 1815 | return 0; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | loops = 0; | ||
| 1819 | again: | ||
| 1820 | if (++loops > 100) { | ||
| 1821 | WARN_ONCE(1, "perfevents: irq loop stuck!\n"); | ||
| 1822 | perf_event_print_debug(); | ||
| 1823 | intel_pmu_reset(); | ||
| 1824 | perf_enable(); | ||
| 1825 | return 1; | ||
| 1826 | } | ||
| 1827 | 1069 | ||
| 1828 | inc_irq_stat(apic_perf_irqs); | 1070 | x86_pmu_stop(event); |
| 1829 | ack = status; | ||
| 1830 | for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | ||
| 1831 | struct perf_event *event = cpuc->events[bit]; | ||
| 1832 | 1071 | ||
| 1833 | clear_bit(bit, (unsigned long *) &status); | 1072 | for (i = 0; i < cpuc->n_events; i++) { |
| 1834 | if (!test_bit(bit, cpuc->active_mask)) | 1073 | if (event == cpuc->event_list[i]) { |
| 1835 | continue; | ||
| 1836 | 1074 | ||
| 1837 | if (!intel_pmu_save_and_restart(event)) | 1075 | if (x86_pmu.put_event_constraints) |
| 1838 | continue; | 1076 | x86_pmu.put_event_constraints(cpuc, event); |
| 1839 | 1077 | ||
| 1840 | data.period = event->hw.last_period; | 1078 | while (++i < cpuc->n_events) |
| 1079 | cpuc->event_list[i-1] = cpuc->event_list[i]; | ||
| 1841 | 1080 | ||
| 1842 | if (perf_event_overflow(event, 1, &data, regs)) | 1081 | --cpuc->n_events; |
| 1843 | intel_pmu_disable_event(&event->hw, bit); | 1082 | break; |
| 1083 | } | ||
| 1844 | } | 1084 | } |
| 1845 | 1085 | perf_event_update_userpage(event); | |
| 1846 | intel_pmu_ack_status(ack); | ||
| 1847 | |||
| 1848 | /* | ||
| 1849 | * Repeat if there is more work to be done: | ||
| 1850 | */ | ||
| 1851 | status = intel_pmu_get_status(); | ||
| 1852 | if (status) | ||
| 1853 | goto again; | ||
| 1854 | |||
| 1855 | perf_enable(); | ||
| 1856 | |||
| 1857 | return 1; | ||
| 1858 | } | 1086 | } |
| 1859 | 1087 | ||
| 1860 | static int amd_pmu_handle_irq(struct pt_regs *regs) | 1088 | static int x86_pmu_handle_irq(struct pt_regs *regs) |
| 1861 | { | 1089 | { |
| 1862 | struct perf_sample_data data; | 1090 | struct perf_sample_data data; |
| 1863 | struct cpu_hw_events *cpuc; | 1091 | struct cpu_hw_events *cpuc; |
| @@ -1892,7 +1120,7 @@ static int amd_pmu_handle_irq(struct pt_regs *regs) | |||
| 1892 | continue; | 1120 | continue; |
| 1893 | 1121 | ||
| 1894 | if (perf_event_overflow(event, 1, &data, regs)) | 1122 | if (perf_event_overflow(event, 1, &data, regs)) |
| 1895 | amd_pmu_disable_event(hwc, idx); | 1123 | x86_pmu.disable(hwc, idx); |
| 1896 | } | 1124 | } |
| 1897 | 1125 | ||
| 1898 | if (handled) | 1126 | if (handled) |
| @@ -1975,194 +1203,137 @@ static __read_mostly struct notifier_block perf_event_nmi_notifier = { | |||
| 1975 | .priority = 1 | 1203 | .priority = 1 |
| 1976 | }; | 1204 | }; |
| 1977 | 1205 | ||
| 1978 | static __initconst struct x86_pmu p6_pmu = { | 1206 | static struct event_constraint unconstrained; |
| 1979 | .name = "p6", | 1207 | static struct event_constraint emptyconstraint; |
| 1980 | .handle_irq = p6_pmu_handle_irq, | ||
| 1981 | .disable_all = p6_pmu_disable_all, | ||
| 1982 | .enable_all = p6_pmu_enable_all, | ||
| 1983 | .enable = p6_pmu_enable_event, | ||
| 1984 | .disable = p6_pmu_disable_event, | ||
| 1985 | .eventsel = MSR_P6_EVNTSEL0, | ||
| 1986 | .perfctr = MSR_P6_PERFCTR0, | ||
| 1987 | .event_map = p6_pmu_event_map, | ||
| 1988 | .raw_event = p6_pmu_raw_event, | ||
| 1989 | .max_events = ARRAY_SIZE(p6_perfmon_event_map), | ||
| 1990 | .apic = 1, | ||
| 1991 | .max_period = (1ULL << 31) - 1, | ||
| 1992 | .version = 0, | ||
| 1993 | .num_events = 2, | ||
| 1994 | /* | ||
| 1995 | * Events have 40 bits implemented. However they are designed such | ||
| 1996 | * that bits [32-39] are sign extensions of bit 31. As such the | ||
| 1997 | * effective width of a event for P6-like PMU is 32 bits only. | ||
| 1998 | * | ||
| 1999 | * See IA-32 Intel Architecture Software developer manual Vol 3B | ||
| 2000 | */ | ||
| 2001 | .event_bits = 32, | ||
| 2002 | .event_mask = (1ULL << 32) - 1, | ||
| 2003 | .get_event_idx = intel_get_event_idx, | ||
| 2004 | }; | ||
| 2005 | 1208 | ||
| 2006 | static __initconst struct x86_pmu intel_pmu = { | 1209 | static struct event_constraint * |
| 2007 | .name = "Intel", | 1210 | x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) |
| 2008 | .handle_irq = intel_pmu_handle_irq, | 1211 | { |
| 2009 | .disable_all = intel_pmu_disable_all, | 1212 | struct event_constraint *c; |
| 2010 | .enable_all = intel_pmu_enable_all, | ||
| 2011 | .enable = intel_pmu_enable_event, | ||
| 2012 | .disable = intel_pmu_disable_event, | ||
| 2013 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
| 2014 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
| 2015 | .event_map = intel_pmu_event_map, | ||
| 2016 | .raw_event = intel_pmu_raw_event, | ||
| 2017 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
| 2018 | .apic = 1, | ||
| 2019 | /* | ||
| 2020 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
| 2021 | * so we install an artificial 1<<31 period regardless of | ||
| 2022 | * the generic event period: | ||
| 2023 | */ | ||
| 2024 | .max_period = (1ULL << 31) - 1, | ||
| 2025 | .enable_bts = intel_pmu_enable_bts, | ||
| 2026 | .disable_bts = intel_pmu_disable_bts, | ||
| 2027 | .get_event_idx = intel_get_event_idx, | ||
| 2028 | }; | ||
| 2029 | 1213 | ||
| 2030 | static __initconst struct x86_pmu amd_pmu = { | 1214 | if (x86_pmu.event_constraints) { |
| 2031 | .name = "AMD", | 1215 | for_each_event_constraint(c, x86_pmu.event_constraints) { |
| 2032 | .handle_irq = amd_pmu_handle_irq, | 1216 | if ((event->hw.config & c->cmask) == c->code) |
| 2033 | .disable_all = amd_pmu_disable_all, | 1217 | return c; |
| 2034 | .enable_all = amd_pmu_enable_all, | 1218 | } |
| 2035 | .enable = amd_pmu_enable_event, | 1219 | } |
| 2036 | .disable = amd_pmu_disable_event, | 1220 | |
| 2037 | .eventsel = MSR_K7_EVNTSEL0, | 1221 | return &unconstrained; |
| 2038 | .perfctr = MSR_K7_PERFCTR0, | 1222 | } |
| 2039 | .event_map = amd_pmu_event_map, | ||
| 2040 | .raw_event = amd_pmu_raw_event, | ||
| 2041 | .max_events = ARRAY_SIZE(amd_perfmon_event_map), | ||
| 2042 | .num_events = 4, | ||
| 2043 | .event_bits = 48, | ||
| 2044 | .event_mask = (1ULL << 48) - 1, | ||
| 2045 | .apic = 1, | ||
| 2046 | /* use highest bit to detect overflow */ | ||
| 2047 | .max_period = (1ULL << 47) - 1, | ||
| 2048 | .get_event_idx = gen_get_event_idx, | ||
| 2049 | }; | ||
| 2050 | 1223 | ||
| 2051 | static __init int p6_pmu_init(void) | 1224 | static int x86_event_sched_in(struct perf_event *event, |
| 1225 | struct perf_cpu_context *cpuctx) | ||
| 2052 | { | 1226 | { |
| 2053 | switch (boot_cpu_data.x86_model) { | 1227 | int ret = 0; |
| 2054 | case 1: | ||
| 2055 | case 3: /* Pentium Pro */ | ||
| 2056 | case 5: | ||
| 2057 | case 6: /* Pentium II */ | ||
| 2058 | case 7: | ||
| 2059 | case 8: | ||
| 2060 | case 11: /* Pentium III */ | ||
| 2061 | event_constraints = intel_p6_event_constraints; | ||
| 2062 | break; | ||
| 2063 | case 9: | ||
| 2064 | case 13: | ||
| 2065 | /* Pentium M */ | ||
| 2066 | event_constraints = intel_p6_event_constraints; | ||
| 2067 | break; | ||
| 2068 | default: | ||
| 2069 | pr_cont("unsupported p6 CPU model %d ", | ||
| 2070 | boot_cpu_data.x86_model); | ||
| 2071 | return -ENODEV; | ||
| 2072 | } | ||
| 2073 | 1228 | ||
| 2074 | x86_pmu = p6_pmu; | 1229 | event->state = PERF_EVENT_STATE_ACTIVE; |
| 1230 | event->oncpu = smp_processor_id(); | ||
| 1231 | event->tstamp_running += event->ctx->time - event->tstamp_stopped; | ||
| 2075 | 1232 | ||
| 2076 | return 0; | 1233 | if (!is_x86_event(event)) |
| 1234 | ret = event->pmu->enable(event); | ||
| 1235 | |||
| 1236 | if (!ret && !is_software_event(event)) | ||
| 1237 | cpuctx->active_oncpu++; | ||
| 1238 | |||
| 1239 | if (!ret && event->attr.exclusive) | ||
| 1240 | cpuctx->exclusive = 1; | ||
| 1241 | |||
| 1242 | return ret; | ||
| 2077 | } | 1243 | } |
| 2078 | 1244 | ||
| 2079 | static __init int intel_pmu_init(void) | 1245 | static void x86_event_sched_out(struct perf_event *event, |
| 1246 | struct perf_cpu_context *cpuctx) | ||
| 2080 | { | 1247 | { |
| 2081 | union cpuid10_edx edx; | 1248 | event->state = PERF_EVENT_STATE_INACTIVE; |
| 2082 | union cpuid10_eax eax; | 1249 | event->oncpu = -1; |
| 2083 | unsigned int unused; | ||
| 2084 | unsigned int ebx; | ||
| 2085 | int version; | ||
| 2086 | |||
| 2087 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { | ||
| 2088 | /* check for P6 processor family */ | ||
| 2089 | if (boot_cpu_data.x86 == 6) { | ||
| 2090 | return p6_pmu_init(); | ||
| 2091 | } else { | ||
| 2092 | return -ENODEV; | ||
| 2093 | } | ||
| 2094 | } | ||
| 2095 | 1250 | ||
| 2096 | /* | 1251 | if (!is_x86_event(event)) |
| 2097 | * Check whether the Architectural PerfMon supports | 1252 | event->pmu->disable(event); |
| 2098 | * Branch Misses Retired hw_event or not. | ||
| 2099 | */ | ||
| 2100 | cpuid(10, &eax.full, &ebx, &unused, &edx.full); | ||
| 2101 | if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED) | ||
| 2102 | return -ENODEV; | ||
| 2103 | 1253 | ||
| 2104 | version = eax.split.version_id; | 1254 | event->tstamp_running -= event->ctx->time - event->tstamp_stopped; |
| 2105 | if (version < 2) | ||
| 2106 | return -ENODEV; | ||
| 2107 | 1255 | ||
| 2108 | x86_pmu = intel_pmu; | 1256 | if (!is_software_event(event)) |
| 2109 | x86_pmu.version = version; | 1257 | cpuctx->active_oncpu--; |
| 2110 | x86_pmu.num_events = eax.split.num_events; | ||
| 2111 | x86_pmu.event_bits = eax.split.bit_width; | ||
| 2112 | x86_pmu.event_mask = (1ULL << eax.split.bit_width) - 1; | ||
| 2113 | 1258 | ||
| 2114 | /* | 1259 | if (event->attr.exclusive || !cpuctx->active_oncpu) |
| 2115 | * Quirk: v2 perfmon does not report fixed-purpose events, so | 1260 | cpuctx->exclusive = 0; |
| 2116 | * assume at least 3 events: | 1261 | } |
| 2117 | */ | ||
| 2118 | x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); | ||
| 2119 | 1262 | ||
| 1263 | /* | ||
| 1264 | * Called to enable a whole group of events. | ||
| 1265 | * Returns 1 if the group was enabled, or -EAGAIN if it could not be. | ||
| 1266 | * Assumes the caller has disabled interrupts and has | ||
| 1267 | * frozen the PMU with hw_perf_save_disable. | ||
| 1268 | * | ||
| 1269 | * called with PMU disabled. If successful and return value 1, | ||
| 1270 | * then guaranteed to call perf_enable() and hw_perf_enable() | ||
| 1271 | */ | ||
| 1272 | int hw_perf_group_sched_in(struct perf_event *leader, | ||
| 1273 | struct perf_cpu_context *cpuctx, | ||
| 1274 | struct perf_event_context *ctx) | ||
| 1275 | { | ||
| 1276 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 1277 | struct perf_event *sub; | ||
| 1278 | int assign[X86_PMC_IDX_MAX]; | ||
| 1279 | int n0, n1, ret; | ||
| 1280 | |||
| 1281 | /* n0 = total number of events */ | ||
| 1282 | n0 = collect_events(cpuc, leader, true); | ||
| 1283 | if (n0 < 0) | ||
| 1284 | return n0; | ||
| 1285 | |||
| 1286 | ret = x86_schedule_events(cpuc, n0, assign); | ||
| 1287 | if (ret) | ||
| 1288 | return ret; | ||
| 1289 | |||
| 1290 | ret = x86_event_sched_in(leader, cpuctx); | ||
| 1291 | if (ret) | ||
| 1292 | return ret; | ||
| 1293 | |||
| 1294 | n1 = 1; | ||
| 1295 | list_for_each_entry(sub, &leader->sibling_list, group_entry) { | ||
| 1296 | if (sub->state > PERF_EVENT_STATE_OFF) { | ||
| 1297 | ret = x86_event_sched_in(sub, cpuctx); | ||
| 1298 | if (ret) | ||
| 1299 | goto undo; | ||
| 1300 | ++n1; | ||
| 1301 | } | ||
| 1302 | } | ||
| 2120 | /* | 1303 | /* |
| 2121 | * Install the hw-cache-events table: | 1304 | * copy new assignment, now we know it is possible |
| 1305 | * will be used by hw_perf_enable() | ||
| 2122 | */ | 1306 | */ |
| 2123 | switch (boot_cpu_data.x86_model) { | 1307 | memcpy(cpuc->assign, assign, n0*sizeof(int)); |
| 2124 | case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ | ||
| 2125 | case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ | ||
| 2126 | case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ | ||
| 2127 | case 29: /* six-core 45 nm xeon "Dunnington" */ | ||
| 2128 | memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, | ||
| 2129 | sizeof(hw_cache_event_ids)); | ||
| 2130 | |||
| 2131 | pr_cont("Core2 events, "); | ||
| 2132 | event_constraints = intel_core_event_constraints; | ||
| 2133 | break; | ||
| 2134 | default: | ||
| 2135 | case 26: | ||
| 2136 | memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, | ||
| 2137 | sizeof(hw_cache_event_ids)); | ||
| 2138 | 1308 | ||
| 2139 | event_constraints = intel_nehalem_event_constraints; | 1309 | cpuc->n_events = n0; |
| 2140 | pr_cont("Nehalem/Corei7 events, "); | 1310 | cpuc->n_added = n1; |
| 2141 | break; | 1311 | ctx->nr_active += n1; |
| 2142 | case 28: | ||
| 2143 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | ||
| 2144 | sizeof(hw_cache_event_ids)); | ||
| 2145 | 1312 | ||
| 2146 | pr_cont("Atom events, "); | 1313 | /* |
| 2147 | break; | 1314 | * 1 means successful and events are active |
| 1315 | * This is not quite true because we defer | ||
| 1316 | * actual activation until hw_perf_enable() but | ||
| 1317 | * this way we* ensure caller won't try to enable | ||
| 1318 | * individual events | ||
| 1319 | */ | ||
| 1320 | return 1; | ||
| 1321 | undo: | ||
| 1322 | x86_event_sched_out(leader, cpuctx); | ||
| 1323 | n0 = 1; | ||
| 1324 | list_for_each_entry(sub, &leader->sibling_list, group_entry) { | ||
| 1325 | if (sub->state == PERF_EVENT_STATE_ACTIVE) { | ||
| 1326 | x86_event_sched_out(sub, cpuctx); | ||
| 1327 | if (++n0 == n1) | ||
| 1328 | break; | ||
| 1329 | } | ||
| 2148 | } | 1330 | } |
| 2149 | return 0; | 1331 | return ret; |
| 2150 | } | 1332 | } |
| 2151 | 1333 | ||
| 2152 | static __init int amd_pmu_init(void) | 1334 | #include "perf_event_amd.c" |
| 2153 | { | 1335 | #include "perf_event_p6.c" |
| 2154 | /* Performance-monitoring supported from K7 and later: */ | 1336 | #include "perf_event_intel.c" |
| 2155 | if (boot_cpu_data.x86 < 6) | ||
| 2156 | return -ENODEV; | ||
| 2157 | |||
| 2158 | x86_pmu = amd_pmu; | ||
| 2159 | |||
| 2160 | /* Events are common for all AMDs */ | ||
| 2161 | memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, | ||
| 2162 | sizeof(hw_cache_event_ids)); | ||
| 2163 | |||
| 2164 | return 0; | ||
| 2165 | } | ||
| 2166 | 1337 | ||
| 2167 | static void __init pmu_check_apic(void) | 1338 | static void __init pmu_check_apic(void) |
| 2168 | { | 1339 | { |
| @@ -2220,6 +1391,10 @@ void __init init_hw_perf_events(void) | |||
| 2220 | perf_events_lapic_init(); | 1391 | perf_events_lapic_init(); |
| 2221 | register_die_notifier(&perf_event_nmi_notifier); | 1392 | register_die_notifier(&perf_event_nmi_notifier); |
| 2222 | 1393 | ||
| 1394 | unconstrained = (struct event_constraint) | ||
| 1395 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1, | ||
| 1396 | 0, x86_pmu.num_events); | ||
| 1397 | |||
| 2223 | pr_info("... version: %d\n", x86_pmu.version); | 1398 | pr_info("... version: %d\n", x86_pmu.version); |
| 2224 | pr_info("... bit width: %d\n", x86_pmu.event_bits); | 1399 | pr_info("... bit width: %d\n", x86_pmu.event_bits); |
| 2225 | pr_info("... generic registers: %d\n", x86_pmu.num_events); | 1400 | pr_info("... generic registers: %d\n", x86_pmu.num_events); |
| @@ -2237,50 +1412,79 @@ static inline void x86_pmu_read(struct perf_event *event) | |||
| 2237 | static const struct pmu pmu = { | 1412 | static const struct pmu pmu = { |
| 2238 | .enable = x86_pmu_enable, | 1413 | .enable = x86_pmu_enable, |
| 2239 | .disable = x86_pmu_disable, | 1414 | .disable = x86_pmu_disable, |
| 1415 | .start = x86_pmu_start, | ||
| 1416 | .stop = x86_pmu_stop, | ||
| 2240 | .read = x86_pmu_read, | 1417 | .read = x86_pmu_read, |
| 2241 | .unthrottle = x86_pmu_unthrottle, | 1418 | .unthrottle = x86_pmu_unthrottle, |
| 2242 | }; | 1419 | }; |
| 2243 | 1420 | ||
| 2244 | static int | 1421 | /* |
| 2245 | validate_event(struct cpu_hw_events *cpuc, struct perf_event *event) | 1422 | * validate a single event group |
| 2246 | { | 1423 | * |
| 2247 | struct hw_perf_event fake_event = event->hw; | 1424 | * validation include: |
| 2248 | 1425 | * - check events are compatible which each other | |
| 2249 | if (event->pmu && event->pmu != &pmu) | 1426 | * - events do not compete for the same counter |
| 2250 | return 0; | 1427 | * - number of events <= number of counters |
| 2251 | 1428 | * | |
| 2252 | return x86_schedule_event(cpuc, &fake_event) >= 0; | 1429 | * validation ensures the group can be loaded onto the |
| 2253 | } | 1430 | * PMU if it was the only group available. |
| 2254 | 1431 | */ | |
| 2255 | static int validate_group(struct perf_event *event) | 1432 | static int validate_group(struct perf_event *event) |
| 2256 | { | 1433 | { |
| 2257 | struct perf_event *sibling, *leader = event->group_leader; | 1434 | struct perf_event *leader = event->group_leader; |
| 2258 | struct cpu_hw_events fake_pmu; | 1435 | struct cpu_hw_events *fake_cpuc; |
| 1436 | int ret, n; | ||
| 2259 | 1437 | ||
| 2260 | memset(&fake_pmu, 0, sizeof(fake_pmu)); | 1438 | ret = -ENOMEM; |
| 1439 | fake_cpuc = kmalloc(sizeof(*fake_cpuc), GFP_KERNEL | __GFP_ZERO); | ||
| 1440 | if (!fake_cpuc) | ||
| 1441 | goto out; | ||
| 1442 | |||
| 1443 | /* | ||
| 1444 | * the event is not yet connected with its | ||
| 1445 | * siblings therefore we must first collect | ||
| 1446 | * existing siblings, then add the new event | ||
| 1447 | * before we can simulate the scheduling | ||
| 1448 | */ | ||
| 1449 | ret = -ENOSPC; | ||
| 1450 | n = collect_events(fake_cpuc, leader, true); | ||
| 1451 | if (n < 0) | ||
| 1452 | goto out_free; | ||
| 2261 | 1453 | ||
| 2262 | if (!validate_event(&fake_pmu, leader)) | 1454 | fake_cpuc->n_events = n; |
| 2263 | return -ENOSPC; | 1455 | n = collect_events(fake_cpuc, event, false); |
| 1456 | if (n < 0) | ||
| 1457 | goto out_free; | ||
| 2264 | 1458 | ||
| 2265 | list_for_each_entry(sibling, &leader->sibling_list, group_entry) { | 1459 | fake_cpuc->n_events = n; |
| 2266 | if (!validate_event(&fake_pmu, sibling)) | ||
| 2267 | return -ENOSPC; | ||
| 2268 | } | ||
| 2269 | 1460 | ||
| 2270 | if (!validate_event(&fake_pmu, event)) | 1461 | ret = x86_schedule_events(fake_cpuc, n, NULL); |
| 2271 | return -ENOSPC; | ||
| 2272 | 1462 | ||
| 2273 | return 0; | 1463 | out_free: |
| 1464 | kfree(fake_cpuc); | ||
| 1465 | out: | ||
| 1466 | return ret; | ||
| 2274 | } | 1467 | } |
| 2275 | 1468 | ||
| 2276 | const struct pmu *hw_perf_event_init(struct perf_event *event) | 1469 | const struct pmu *hw_perf_event_init(struct perf_event *event) |
| 2277 | { | 1470 | { |
| 1471 | const struct pmu *tmp; | ||
| 2278 | int err; | 1472 | int err; |
| 2279 | 1473 | ||
| 2280 | err = __hw_perf_event_init(event); | 1474 | err = __hw_perf_event_init(event); |
| 2281 | if (!err) { | 1475 | if (!err) { |
| 1476 | /* | ||
| 1477 | * we temporarily connect event to its pmu | ||
| 1478 | * such that validate_group() can classify | ||
| 1479 | * it as an x86 event using is_x86_event() | ||
| 1480 | */ | ||
| 1481 | tmp = event->pmu; | ||
| 1482 | event->pmu = &pmu; | ||
| 1483 | |||
| 2282 | if (event->group_leader != event) | 1484 | if (event->group_leader != event) |
| 2283 | err = validate_group(event); | 1485 | err = validate_group(event); |
| 1486 | |||
| 1487 | event->pmu = tmp; | ||
| 2284 | } | 1488 | } |
| 2285 | if (err) { | 1489 | if (err) { |
| 2286 | if (event->destroy) | 1490 | if (event->destroy) |
| @@ -2304,7 +1508,6 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip) | |||
| 2304 | 1508 | ||
| 2305 | static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); | 1509 | static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); |
| 2306 | static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_nmi_entry); | 1510 | static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_nmi_entry); |
| 2307 | static DEFINE_PER_CPU(int, in_ignored_frame); | ||
| 2308 | 1511 | ||
| 2309 | 1512 | ||
| 2310 | static void | 1513 | static void |
| @@ -2320,10 +1523,6 @@ static void backtrace_warning(void *data, char *msg) | |||
| 2320 | 1523 | ||
| 2321 | static int backtrace_stack(void *data, char *name) | 1524 | static int backtrace_stack(void *data, char *name) |
| 2322 | { | 1525 | { |
| 2323 | per_cpu(in_ignored_frame, smp_processor_id()) = | ||
| 2324 | x86_is_stack_id(NMI_STACK, name) || | ||
| 2325 | x86_is_stack_id(DEBUG_STACK, name); | ||
| 2326 | |||
| 2327 | return 0; | 1526 | return 0; |
| 2328 | } | 1527 | } |
| 2329 | 1528 | ||
| @@ -2331,9 +1530,6 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) | |||
| 2331 | { | 1530 | { |
| 2332 | struct perf_callchain_entry *entry = data; | 1531 | struct perf_callchain_entry *entry = data; |
| 2333 | 1532 | ||
| 2334 | if (per_cpu(in_ignored_frame, smp_processor_id())) | ||
| 2335 | return; | ||
| 2336 | |||
| 2337 | if (reliable) | 1533 | if (reliable) |
| 2338 | callchain_store(entry, addr); | 1534 | callchain_store(entry, addr); |
| 2339 | } | 1535 | } |
| @@ -2440,9 +1636,6 @@ perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
| 2440 | 1636 | ||
| 2441 | is_user = user_mode(regs); | 1637 | is_user = user_mode(regs); |
| 2442 | 1638 | ||
| 2443 | if (!current || current->pid == 0) | ||
| 2444 | return; | ||
| 2445 | |||
| 2446 | if (is_user && current->state != TASK_RUNNING) | 1639 | if (is_user && current->state != TASK_RUNNING) |
| 2447 | return; | 1640 | return; |
| 2448 | 1641 | ||
| @@ -2472,4 +1665,25 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
| 2472 | void hw_perf_event_setup_online(int cpu) | 1665 | void hw_perf_event_setup_online(int cpu) |
| 2473 | { | 1666 | { |
| 2474 | init_debug_store_on_cpu(cpu); | 1667 | init_debug_store_on_cpu(cpu); |
| 1668 | |||
| 1669 | switch (boot_cpu_data.x86_vendor) { | ||
| 1670 | case X86_VENDOR_AMD: | ||
| 1671 | amd_pmu_cpu_online(cpu); | ||
| 1672 | break; | ||
| 1673 | default: | ||
| 1674 | return; | ||
| 1675 | } | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | void hw_perf_event_setup_offline(int cpu) | ||
| 1679 | { | ||
| 1680 | init_debug_store_on_cpu(cpu); | ||
| 1681 | |||
| 1682 | switch (boot_cpu_data.x86_vendor) { | ||
| 1683 | case X86_VENDOR_AMD: | ||
| 1684 | amd_pmu_cpu_offline(cpu); | ||
| 1685 | break; | ||
| 1686 | default: | ||
| 1687 | return; | ||
| 1688 | } | ||
| 2475 | } | 1689 | } |
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c new file mode 100644 index 000000000000..8f3dbfda3c4f --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_amd.c | |||
| @@ -0,0 +1,416 @@ | |||
| 1 | #ifdef CONFIG_CPU_SUP_AMD | ||
| 2 | |||
| 3 | static DEFINE_RAW_SPINLOCK(amd_nb_lock); | ||
| 4 | |||
| 5 | static __initconst u64 amd_hw_cache_event_ids | ||
| 6 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 7 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 8 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 9 | { | ||
| 10 | [ C(L1D) ] = { | ||
| 11 | [ C(OP_READ) ] = { | ||
| 12 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
| 13 | [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ | ||
| 14 | }, | ||
| 15 | [ C(OP_WRITE) ] = { | ||
| 16 | [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ | ||
| 17 | [ C(RESULT_MISS) ] = 0, | ||
| 18 | }, | ||
| 19 | [ C(OP_PREFETCH) ] = { | ||
| 20 | [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts */ | ||
| 21 | [ C(RESULT_MISS) ] = 0x0167, /* Data Prefetcher :cancelled */ | ||
| 22 | }, | ||
| 23 | }, | ||
| 24 | [ C(L1I ) ] = { | ||
| 25 | [ C(OP_READ) ] = { | ||
| 26 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches */ | ||
| 27 | [ C(RESULT_MISS) ] = 0x0081, /* Instruction cache misses */ | ||
| 28 | }, | ||
| 29 | [ C(OP_WRITE) ] = { | ||
| 30 | [ C(RESULT_ACCESS) ] = -1, | ||
| 31 | [ C(RESULT_MISS) ] = -1, | ||
| 32 | }, | ||
| 33 | [ C(OP_PREFETCH) ] = { | ||
| 34 | [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */ | ||
| 35 | [ C(RESULT_MISS) ] = 0, | ||
| 36 | }, | ||
| 37 | }, | ||
| 38 | [ C(LL ) ] = { | ||
| 39 | [ C(OP_READ) ] = { | ||
| 40 | [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */ | ||
| 41 | [ C(RESULT_MISS) ] = 0x037E, /* L2 Cache Misses : IC+DC */ | ||
| 42 | }, | ||
| 43 | [ C(OP_WRITE) ] = { | ||
| 44 | [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback */ | ||
| 45 | [ C(RESULT_MISS) ] = 0, | ||
| 46 | }, | ||
| 47 | [ C(OP_PREFETCH) ] = { | ||
| 48 | [ C(RESULT_ACCESS) ] = 0, | ||
| 49 | [ C(RESULT_MISS) ] = 0, | ||
| 50 | }, | ||
| 51 | }, | ||
| 52 | [ C(DTLB) ] = { | ||
| 53 | [ C(OP_READ) ] = { | ||
| 54 | [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ | ||
| 55 | [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */ | ||
| 56 | }, | ||
| 57 | [ C(OP_WRITE) ] = { | ||
| 58 | [ C(RESULT_ACCESS) ] = 0, | ||
| 59 | [ C(RESULT_MISS) ] = 0, | ||
| 60 | }, | ||
| 61 | [ C(OP_PREFETCH) ] = { | ||
| 62 | [ C(RESULT_ACCESS) ] = 0, | ||
| 63 | [ C(RESULT_MISS) ] = 0, | ||
| 64 | }, | ||
| 65 | }, | ||
| 66 | [ C(ITLB) ] = { | ||
| 67 | [ C(OP_READ) ] = { | ||
| 68 | [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes */ | ||
| 69 | [ C(RESULT_MISS) ] = 0x0085, /* Instr. fetch ITLB misses */ | ||
| 70 | }, | ||
| 71 | [ C(OP_WRITE) ] = { | ||
| 72 | [ C(RESULT_ACCESS) ] = -1, | ||
| 73 | [ C(RESULT_MISS) ] = -1, | ||
| 74 | }, | ||
| 75 | [ C(OP_PREFETCH) ] = { | ||
| 76 | [ C(RESULT_ACCESS) ] = -1, | ||
| 77 | [ C(RESULT_MISS) ] = -1, | ||
| 78 | }, | ||
| 79 | }, | ||
| 80 | [ C(BPU ) ] = { | ||
| 81 | [ C(OP_READ) ] = { | ||
| 82 | [ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr. */ | ||
| 83 | [ C(RESULT_MISS) ] = 0x00c3, /* Retired Mispredicted BI */ | ||
| 84 | }, | ||
| 85 | [ C(OP_WRITE) ] = { | ||
| 86 | [ C(RESULT_ACCESS) ] = -1, | ||
| 87 | [ C(RESULT_MISS) ] = -1, | ||
| 88 | }, | ||
| 89 | [ C(OP_PREFETCH) ] = { | ||
| 90 | [ C(RESULT_ACCESS) ] = -1, | ||
| 91 | [ C(RESULT_MISS) ] = -1, | ||
| 92 | }, | ||
| 93 | }, | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * AMD Performance Monitor K7 and later. | ||
| 98 | */ | ||
| 99 | static const u64 amd_perfmon_event_map[] = | ||
| 100 | { | ||
| 101 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, | ||
| 102 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 103 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, | ||
| 104 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, | ||
| 105 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 106 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static u64 amd_pmu_event_map(int hw_event) | ||
| 110 | { | ||
| 111 | return amd_perfmon_event_map[hw_event]; | ||
| 112 | } | ||
| 113 | |||
| 114 | static u64 amd_pmu_raw_event(u64 hw_event) | ||
| 115 | { | ||
| 116 | #define K7_EVNTSEL_EVENT_MASK 0xF000000FFULL | ||
| 117 | #define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL | ||
| 118 | #define K7_EVNTSEL_EDGE_MASK 0x000040000ULL | ||
| 119 | #define K7_EVNTSEL_INV_MASK 0x000800000ULL | ||
| 120 | #define K7_EVNTSEL_REG_MASK 0x0FF000000ULL | ||
| 121 | |||
| 122 | #define K7_EVNTSEL_MASK \ | ||
| 123 | (K7_EVNTSEL_EVENT_MASK | \ | ||
| 124 | K7_EVNTSEL_UNIT_MASK | \ | ||
| 125 | K7_EVNTSEL_EDGE_MASK | \ | ||
| 126 | K7_EVNTSEL_INV_MASK | \ | ||
| 127 | K7_EVNTSEL_REG_MASK) | ||
| 128 | |||
| 129 | return hw_event & K7_EVNTSEL_MASK; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* | ||
| 133 | * AMD64 events are detected based on their event codes. | ||
| 134 | */ | ||
| 135 | static inline int amd_is_nb_event(struct hw_perf_event *hwc) | ||
| 136 | { | ||
| 137 | return (hwc->config & 0xe0) == 0xe0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void amd_put_event_constraints(struct cpu_hw_events *cpuc, | ||
| 141 | struct perf_event *event) | ||
| 142 | { | ||
| 143 | struct hw_perf_event *hwc = &event->hw; | ||
| 144 | struct amd_nb *nb = cpuc->amd_nb; | ||
| 145 | int i; | ||
| 146 | |||
| 147 | /* | ||
| 148 | * only care about NB events | ||
| 149 | */ | ||
| 150 | if (!(nb && amd_is_nb_event(hwc))) | ||
| 151 | return; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * need to scan whole list because event may not have | ||
| 155 | * been assigned during scheduling | ||
| 156 | * | ||
| 157 | * no race condition possible because event can only | ||
| 158 | * be removed on one CPU at a time AND PMU is disabled | ||
| 159 | * when we come here | ||
| 160 | */ | ||
| 161 | for (i = 0; i < x86_pmu.num_events; i++) { | ||
| 162 | if (nb->owners[i] == event) { | ||
| 163 | cmpxchg(nb->owners+i, event, NULL); | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * AMD64 NorthBridge events need special treatment because | ||
| 171 | * counter access needs to be synchronized across all cores | ||
| 172 | * of a package. Refer to BKDG section 3.12 | ||
| 173 | * | ||
| 174 | * NB events are events measuring L3 cache, Hypertransport | ||
| 175 | * traffic. They are identified by an event code >= 0xe00. | ||
| 176 | * They measure events on the NorthBride which is shared | ||
| 177 | * by all cores on a package. NB events are counted on a | ||
| 178 | * shared set of counters. When a NB event is programmed | ||
| 179 | * in a counter, the data actually comes from a shared | ||
| 180 | * counter. Thus, access to those counters needs to be | ||
| 181 | * synchronized. | ||
| 182 | * | ||
| 183 | * We implement the synchronization such that no two cores | ||
| 184 | * can be measuring NB events using the same counters. Thus, | ||
| 185 | * we maintain a per-NB allocation table. The available slot | ||
| 186 | * is propagated using the event_constraint structure. | ||
| 187 | * | ||
| 188 | * We provide only one choice for each NB event based on | ||
| 189 | * the fact that only NB events have restrictions. Consequently, | ||
| 190 | * if a counter is available, there is a guarantee the NB event | ||
| 191 | * will be assigned to it. If no slot is available, an empty | ||
| 192 | * constraint is returned and scheduling will eventually fail | ||
| 193 | * for this event. | ||
| 194 | * | ||
| 195 | * Note that all cores attached the same NB compete for the same | ||
| 196 | * counters to host NB events, this is why we use atomic ops. Some | ||
| 197 | * multi-chip CPUs may have more than one NB. | ||
| 198 | * | ||
| 199 | * Given that resources are allocated (cmpxchg), they must be | ||
| 200 | * eventually freed for others to use. This is accomplished by | ||
| 201 | * calling amd_put_event_constraints(). | ||
| 202 | * | ||
| 203 | * Non NB events are not impacted by this restriction. | ||
| 204 | */ | ||
| 205 | static struct event_constraint * | ||
| 206 | amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | ||
| 207 | { | ||
| 208 | struct hw_perf_event *hwc = &event->hw; | ||
| 209 | struct amd_nb *nb = cpuc->amd_nb; | ||
| 210 | struct perf_event *old = NULL; | ||
| 211 | int max = x86_pmu.num_events; | ||
| 212 | int i, j, k = -1; | ||
| 213 | |||
| 214 | /* | ||
| 215 | * if not NB event or no NB, then no constraints | ||
| 216 | */ | ||
| 217 | if (!(nb && amd_is_nb_event(hwc))) | ||
| 218 | return &unconstrained; | ||
| 219 | |||
| 220 | /* | ||
| 221 | * detect if already present, if so reuse | ||
| 222 | * | ||
| 223 | * cannot merge with actual allocation | ||
| 224 | * because of possible holes | ||
| 225 | * | ||
| 226 | * event can already be present yet not assigned (in hwc->idx) | ||
| 227 | * because of successive calls to x86_schedule_events() from | ||
| 228 | * hw_perf_group_sched_in() without hw_perf_enable() | ||
| 229 | */ | ||
| 230 | for (i = 0; i < max; i++) { | ||
| 231 | /* | ||
| 232 | * keep track of first free slot | ||
| 233 | */ | ||
| 234 | if (k == -1 && !nb->owners[i]) | ||
| 235 | k = i; | ||
| 236 | |||
| 237 | /* already present, reuse */ | ||
| 238 | if (nb->owners[i] == event) | ||
| 239 | goto done; | ||
| 240 | } | ||
| 241 | /* | ||
| 242 | * not present, so grab a new slot | ||
| 243 | * starting either at: | ||
| 244 | */ | ||
| 245 | if (hwc->idx != -1) { | ||
| 246 | /* previous assignment */ | ||
| 247 | i = hwc->idx; | ||
| 248 | } else if (k != -1) { | ||
| 249 | /* start from free slot found */ | ||
| 250 | i = k; | ||
| 251 | } else { | ||
| 252 | /* | ||
| 253 | * event not found, no slot found in | ||
| 254 | * first pass, try again from the | ||
| 255 | * beginning | ||
| 256 | */ | ||
| 257 | i = 0; | ||
| 258 | } | ||
| 259 | j = i; | ||
| 260 | do { | ||
| 261 | old = cmpxchg(nb->owners+i, NULL, event); | ||
| 262 | if (!old) | ||
| 263 | break; | ||
| 264 | if (++i == max) | ||
| 265 | i = 0; | ||
| 266 | } while (i != j); | ||
| 267 | done: | ||
| 268 | if (!old) | ||
| 269 | return &nb->event_constraints[i]; | ||
| 270 | |||
| 271 | return &emptyconstraint; | ||
| 272 | } | ||
| 273 | |||
| 274 | static __initconst struct x86_pmu amd_pmu = { | ||
| 275 | .name = "AMD", | ||
| 276 | .handle_irq = x86_pmu_handle_irq, | ||
| 277 | .disable_all = x86_pmu_disable_all, | ||
| 278 | .enable_all = x86_pmu_enable_all, | ||
| 279 | .enable = x86_pmu_enable_event, | ||
| 280 | .disable = x86_pmu_disable_event, | ||
| 281 | .eventsel = MSR_K7_EVNTSEL0, | ||
| 282 | .perfctr = MSR_K7_PERFCTR0, | ||
| 283 | .event_map = amd_pmu_event_map, | ||
| 284 | .raw_event = amd_pmu_raw_event, | ||
| 285 | .max_events = ARRAY_SIZE(amd_perfmon_event_map), | ||
| 286 | .num_events = 4, | ||
| 287 | .event_bits = 48, | ||
| 288 | .event_mask = (1ULL << 48) - 1, | ||
| 289 | .apic = 1, | ||
| 290 | /* use highest bit to detect overflow */ | ||
| 291 | .max_period = (1ULL << 47) - 1, | ||
| 292 | .get_event_constraints = amd_get_event_constraints, | ||
| 293 | .put_event_constraints = amd_put_event_constraints | ||
| 294 | }; | ||
| 295 | |||
| 296 | static struct amd_nb *amd_alloc_nb(int cpu, int nb_id) | ||
| 297 | { | ||
| 298 | struct amd_nb *nb; | ||
| 299 | int i; | ||
| 300 | |||
| 301 | nb = kmalloc(sizeof(struct amd_nb), GFP_KERNEL); | ||
| 302 | if (!nb) | ||
| 303 | return NULL; | ||
| 304 | |||
| 305 | memset(nb, 0, sizeof(*nb)); | ||
| 306 | nb->nb_id = nb_id; | ||
| 307 | |||
| 308 | /* | ||
| 309 | * initialize all possible NB constraints | ||
| 310 | */ | ||
| 311 | for (i = 0; i < x86_pmu.num_events; i++) { | ||
| 312 | set_bit(i, nb->event_constraints[i].idxmsk); | ||
| 313 | nb->event_constraints[i].weight = 1; | ||
| 314 | } | ||
| 315 | return nb; | ||
| 316 | } | ||
| 317 | |||
| 318 | static void amd_pmu_cpu_online(int cpu) | ||
| 319 | { | ||
| 320 | struct cpu_hw_events *cpu1, *cpu2; | ||
| 321 | struct amd_nb *nb = NULL; | ||
| 322 | int i, nb_id; | ||
| 323 | |||
| 324 | if (boot_cpu_data.x86_max_cores < 2) | ||
| 325 | return; | ||
| 326 | |||
| 327 | /* | ||
| 328 | * function may be called too early in the | ||
| 329 | * boot process, in which case nb_id is bogus | ||
| 330 | */ | ||
| 331 | nb_id = amd_get_nb_id(cpu); | ||
| 332 | if (nb_id == BAD_APICID) | ||
| 333 | return; | ||
| 334 | |||
| 335 | cpu1 = &per_cpu(cpu_hw_events, cpu); | ||
| 336 | cpu1->amd_nb = NULL; | ||
| 337 | |||
| 338 | raw_spin_lock(&amd_nb_lock); | ||
| 339 | |||
| 340 | for_each_online_cpu(i) { | ||
| 341 | cpu2 = &per_cpu(cpu_hw_events, i); | ||
| 342 | nb = cpu2->amd_nb; | ||
| 343 | if (!nb) | ||
| 344 | continue; | ||
| 345 | if (nb->nb_id == nb_id) | ||
| 346 | goto found; | ||
| 347 | } | ||
| 348 | |||
| 349 | nb = amd_alloc_nb(cpu, nb_id); | ||
| 350 | if (!nb) { | ||
| 351 | pr_err("perf_events: failed NB allocation for CPU%d\n", cpu); | ||
| 352 | raw_spin_unlock(&amd_nb_lock); | ||
| 353 | return; | ||
| 354 | } | ||
| 355 | found: | ||
| 356 | nb->refcnt++; | ||
| 357 | cpu1->amd_nb = nb; | ||
| 358 | |||
| 359 | raw_spin_unlock(&amd_nb_lock); | ||
| 360 | } | ||
| 361 | |||
| 362 | static void amd_pmu_cpu_offline(int cpu) | ||
| 363 | { | ||
| 364 | struct cpu_hw_events *cpuhw; | ||
| 365 | |||
| 366 | if (boot_cpu_data.x86_max_cores < 2) | ||
| 367 | return; | ||
| 368 | |||
| 369 | cpuhw = &per_cpu(cpu_hw_events, cpu); | ||
| 370 | |||
| 371 | raw_spin_lock(&amd_nb_lock); | ||
| 372 | |||
| 373 | if (--cpuhw->amd_nb->refcnt == 0) | ||
| 374 | kfree(cpuhw->amd_nb); | ||
| 375 | |||
| 376 | cpuhw->amd_nb = NULL; | ||
| 377 | |||
| 378 | raw_spin_unlock(&amd_nb_lock); | ||
| 379 | } | ||
| 380 | |||
| 381 | static __init int amd_pmu_init(void) | ||
| 382 | { | ||
| 383 | /* Performance-monitoring supported from K7 and later: */ | ||
| 384 | if (boot_cpu_data.x86 < 6) | ||
| 385 | return -ENODEV; | ||
| 386 | |||
| 387 | x86_pmu = amd_pmu; | ||
| 388 | |||
| 389 | /* Events are common for all AMDs */ | ||
| 390 | memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, | ||
| 391 | sizeof(hw_cache_event_ids)); | ||
| 392 | |||
| 393 | /* | ||
| 394 | * explicitly initialize the boot cpu, other cpus will get | ||
| 395 | * the cpu hotplug callbacks from smp_init() | ||
| 396 | */ | ||
| 397 | amd_pmu_cpu_online(smp_processor_id()); | ||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | |||
| 401 | #else /* CONFIG_CPU_SUP_AMD */ | ||
| 402 | |||
| 403 | static int amd_pmu_init(void) | ||
| 404 | { | ||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static void amd_pmu_cpu_online(int cpu) | ||
| 409 | { | ||
| 410 | } | ||
| 411 | |||
| 412 | static void amd_pmu_cpu_offline(int cpu) | ||
| 413 | { | ||
| 414 | } | ||
| 415 | |||
| 416 | #endif | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c new file mode 100644 index 000000000000..cf6590cf4a5f --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
| @@ -0,0 +1,971 @@ | |||
| 1 | #ifdef CONFIG_CPU_SUP_INTEL | ||
| 2 | |||
| 3 | /* | ||
| 4 | * Intel PerfMon v3. Used on Core2 and later. | ||
| 5 | */ | ||
| 6 | static const u64 intel_perfmon_event_map[] = | ||
| 7 | { | ||
| 8 | [PERF_COUNT_HW_CPU_CYCLES] = 0x003c, | ||
| 9 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 10 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e, | ||
| 11 | [PERF_COUNT_HW_CACHE_MISSES] = 0x412e, | ||
| 12 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 13 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 14 | [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, | ||
| 15 | }; | ||
| 16 | |||
| 17 | static struct event_constraint intel_core_event_constraints[] = | ||
| 18 | { | ||
| 19 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
| 20 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
| 21 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
| 22 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
| 23 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
| 24 | INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FP_COMP_INSTR_RET */ | ||
| 25 | EVENT_CONSTRAINT_END | ||
| 26 | }; | ||
| 27 | |||
| 28 | static struct event_constraint intel_core2_event_constraints[] = | ||
| 29 | { | ||
| 30 | FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
| 31 | FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
| 32 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
| 33 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | ||
| 34 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
| 35 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
| 36 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
| 37 | INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ | ||
| 38 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | ||
| 39 | INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ | ||
| 40 | INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */ | ||
| 41 | EVENT_CONSTRAINT_END | ||
| 42 | }; | ||
| 43 | |||
| 44 | static struct event_constraint intel_nehalem_event_constraints[] = | ||
| 45 | { | ||
| 46 | FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
| 47 | FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
| 48 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ | ||
| 49 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ | ||
| 50 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ | ||
| 51 | INTEL_EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */ | ||
| 52 | INTEL_EVENT_CONSTRAINT(0x48, 0x3), /* L1D_PEND_MISS */ | ||
| 53 | INTEL_EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */ | ||
| 54 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
| 55 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | ||
| 56 | EVENT_CONSTRAINT_END | ||
| 57 | }; | ||
| 58 | |||
| 59 | static struct event_constraint intel_westmere_event_constraints[] = | ||
| 60 | { | ||
| 61 | FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
| 62 | FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
| 63 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | ||
| 64 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ | ||
| 65 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | ||
| 66 | EVENT_CONSTRAINT_END | ||
| 67 | }; | ||
| 68 | |||
| 69 | static struct event_constraint intel_gen_event_constraints[] = | ||
| 70 | { | ||
| 71 | FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | ||
| 72 | FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | ||
| 73 | EVENT_CONSTRAINT_END | ||
| 74 | }; | ||
| 75 | |||
| 76 | static u64 intel_pmu_event_map(int hw_event) | ||
| 77 | { | ||
| 78 | return intel_perfmon_event_map[hw_event]; | ||
| 79 | } | ||
| 80 | |||
| 81 | static __initconst u64 westmere_hw_cache_event_ids | ||
| 82 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 83 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 84 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 85 | { | ||
| 86 | [ C(L1D) ] = { | ||
| 87 | [ C(OP_READ) ] = { | ||
| 88 | [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ | ||
| 89 | [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPL */ | ||
| 90 | }, | ||
| 91 | [ C(OP_WRITE) ] = { | ||
| 92 | [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ | ||
| 93 | [ C(RESULT_MISS) ] = 0x0251, /* L1D.M_REPL */ | ||
| 94 | }, | ||
| 95 | [ C(OP_PREFETCH) ] = { | ||
| 96 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
| 97 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
| 98 | }, | ||
| 99 | }, | ||
| 100 | [ C(L1I ) ] = { | ||
| 101 | [ C(OP_READ) ] = { | ||
| 102 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
| 103 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
| 104 | }, | ||
| 105 | [ C(OP_WRITE) ] = { | ||
| 106 | [ C(RESULT_ACCESS) ] = -1, | ||
| 107 | [ C(RESULT_MISS) ] = -1, | ||
| 108 | }, | ||
| 109 | [ C(OP_PREFETCH) ] = { | ||
| 110 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 111 | [ C(RESULT_MISS) ] = 0x0, | ||
| 112 | }, | ||
| 113 | }, | ||
| 114 | [ C(LL ) ] = { | ||
| 115 | [ C(OP_READ) ] = { | ||
| 116 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
| 117 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
| 118 | }, | ||
| 119 | [ C(OP_WRITE) ] = { | ||
| 120 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
| 121 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
| 122 | }, | ||
| 123 | [ C(OP_PREFETCH) ] = { | ||
| 124 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
| 125 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
| 126 | }, | ||
| 127 | }, | ||
| 128 | [ C(DTLB) ] = { | ||
| 129 | [ C(OP_READ) ] = { | ||
| 130 | [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ | ||
| 131 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
| 132 | }, | ||
| 133 | [ C(OP_WRITE) ] = { | ||
| 134 | [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ | ||
| 135 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
| 136 | }, | ||
| 137 | [ C(OP_PREFETCH) ] = { | ||
| 138 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 139 | [ C(RESULT_MISS) ] = 0x0, | ||
| 140 | }, | ||
| 141 | }, | ||
| 142 | [ C(ITLB) ] = { | ||
| 143 | [ C(OP_READ) ] = { | ||
| 144 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
| 145 | [ C(RESULT_MISS) ] = 0x0185, /* ITLB_MISSES.ANY */ | ||
| 146 | }, | ||
| 147 | [ C(OP_WRITE) ] = { | ||
| 148 | [ C(RESULT_ACCESS) ] = -1, | ||
| 149 | [ C(RESULT_MISS) ] = -1, | ||
| 150 | }, | ||
| 151 | [ C(OP_PREFETCH) ] = { | ||
| 152 | [ C(RESULT_ACCESS) ] = -1, | ||
| 153 | [ C(RESULT_MISS) ] = -1, | ||
| 154 | }, | ||
| 155 | }, | ||
| 156 | [ C(BPU ) ] = { | ||
| 157 | [ C(OP_READ) ] = { | ||
| 158 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
| 159 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
| 160 | }, | ||
| 161 | [ C(OP_WRITE) ] = { | ||
| 162 | [ C(RESULT_ACCESS) ] = -1, | ||
| 163 | [ C(RESULT_MISS) ] = -1, | ||
| 164 | }, | ||
| 165 | [ C(OP_PREFETCH) ] = { | ||
| 166 | [ C(RESULT_ACCESS) ] = -1, | ||
| 167 | [ C(RESULT_MISS) ] = -1, | ||
| 168 | }, | ||
| 169 | }, | ||
| 170 | }; | ||
| 171 | |||
| 172 | static __initconst u64 nehalem_hw_cache_event_ids | ||
| 173 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 174 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 175 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 176 | { | ||
| 177 | [ C(L1D) ] = { | ||
| 178 | [ C(OP_READ) ] = { | ||
| 179 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
| 180 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
| 181 | }, | ||
| 182 | [ C(OP_WRITE) ] = { | ||
| 183 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
| 184 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
| 185 | }, | ||
| 186 | [ C(OP_PREFETCH) ] = { | ||
| 187 | [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ | ||
| 188 | [ C(RESULT_MISS) ] = 0x024e, /* L1D_PREFETCH.MISS */ | ||
| 189 | }, | ||
| 190 | }, | ||
| 191 | [ C(L1I ) ] = { | ||
| 192 | [ C(OP_READ) ] = { | ||
| 193 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
| 194 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
| 195 | }, | ||
| 196 | [ C(OP_WRITE) ] = { | ||
| 197 | [ C(RESULT_ACCESS) ] = -1, | ||
| 198 | [ C(RESULT_MISS) ] = -1, | ||
| 199 | }, | ||
| 200 | [ C(OP_PREFETCH) ] = { | ||
| 201 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 202 | [ C(RESULT_MISS) ] = 0x0, | ||
| 203 | }, | ||
| 204 | }, | ||
| 205 | [ C(LL ) ] = { | ||
| 206 | [ C(OP_READ) ] = { | ||
| 207 | [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ | ||
| 208 | [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ | ||
| 209 | }, | ||
| 210 | [ C(OP_WRITE) ] = { | ||
| 211 | [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ | ||
| 212 | [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ | ||
| 213 | }, | ||
| 214 | [ C(OP_PREFETCH) ] = { | ||
| 215 | [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ | ||
| 216 | [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ | ||
| 217 | }, | ||
| 218 | }, | ||
| 219 | [ C(DTLB) ] = { | ||
| 220 | [ C(OP_READ) ] = { | ||
| 221 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
| 222 | [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.ANY */ | ||
| 223 | }, | ||
| 224 | [ C(OP_WRITE) ] = { | ||
| 225 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
| 226 | [ C(RESULT_MISS) ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS */ | ||
| 227 | }, | ||
| 228 | [ C(OP_PREFETCH) ] = { | ||
| 229 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 230 | [ C(RESULT_MISS) ] = 0x0, | ||
| 231 | }, | ||
| 232 | }, | ||
| 233 | [ C(ITLB) ] = { | ||
| 234 | [ C(OP_READ) ] = { | ||
| 235 | [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P */ | ||
| 236 | [ C(RESULT_MISS) ] = 0x20c8, /* ITLB_MISS_RETIRED */ | ||
| 237 | }, | ||
| 238 | [ C(OP_WRITE) ] = { | ||
| 239 | [ C(RESULT_ACCESS) ] = -1, | ||
| 240 | [ C(RESULT_MISS) ] = -1, | ||
| 241 | }, | ||
| 242 | [ C(OP_PREFETCH) ] = { | ||
| 243 | [ C(RESULT_ACCESS) ] = -1, | ||
| 244 | [ C(RESULT_MISS) ] = -1, | ||
| 245 | }, | ||
| 246 | }, | ||
| 247 | [ C(BPU ) ] = { | ||
| 248 | [ C(OP_READ) ] = { | ||
| 249 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ | ||
| 250 | [ C(RESULT_MISS) ] = 0x03e8, /* BPU_CLEARS.ANY */ | ||
| 251 | }, | ||
| 252 | [ C(OP_WRITE) ] = { | ||
| 253 | [ C(RESULT_ACCESS) ] = -1, | ||
| 254 | [ C(RESULT_MISS) ] = -1, | ||
| 255 | }, | ||
| 256 | [ C(OP_PREFETCH) ] = { | ||
| 257 | [ C(RESULT_ACCESS) ] = -1, | ||
| 258 | [ C(RESULT_MISS) ] = -1, | ||
| 259 | }, | ||
| 260 | }, | ||
| 261 | }; | ||
| 262 | |||
| 263 | static __initconst u64 core2_hw_cache_event_ids | ||
| 264 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 265 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 266 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 267 | { | ||
| 268 | [ C(L1D) ] = { | ||
| 269 | [ C(OP_READ) ] = { | ||
| 270 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ | ||
| 271 | [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ | ||
| 272 | }, | ||
| 273 | [ C(OP_WRITE) ] = { | ||
| 274 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ | ||
| 275 | [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ | ||
| 276 | }, | ||
| 277 | [ C(OP_PREFETCH) ] = { | ||
| 278 | [ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS */ | ||
| 279 | [ C(RESULT_MISS) ] = 0, | ||
| 280 | }, | ||
| 281 | }, | ||
| 282 | [ C(L1I ) ] = { | ||
| 283 | [ C(OP_READ) ] = { | ||
| 284 | [ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS */ | ||
| 285 | [ C(RESULT_MISS) ] = 0x0081, /* L1I.MISSES */ | ||
| 286 | }, | ||
| 287 | [ C(OP_WRITE) ] = { | ||
| 288 | [ C(RESULT_ACCESS) ] = -1, | ||
| 289 | [ C(RESULT_MISS) ] = -1, | ||
| 290 | }, | ||
| 291 | [ C(OP_PREFETCH) ] = { | ||
| 292 | [ C(RESULT_ACCESS) ] = 0, | ||
| 293 | [ C(RESULT_MISS) ] = 0, | ||
| 294 | }, | ||
| 295 | }, | ||
| 296 | [ C(LL ) ] = { | ||
| 297 | [ C(OP_READ) ] = { | ||
| 298 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
| 299 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
| 300 | }, | ||
| 301 | [ C(OP_WRITE) ] = { | ||
| 302 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
| 303 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
| 304 | }, | ||
| 305 | [ C(OP_PREFETCH) ] = { | ||
| 306 | [ C(RESULT_ACCESS) ] = 0, | ||
| 307 | [ C(RESULT_MISS) ] = 0, | ||
| 308 | }, | ||
| 309 | }, | ||
| 310 | [ C(DTLB) ] = { | ||
| 311 | [ C(OP_READ) ] = { | ||
| 312 | [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI (alias) */ | ||
| 313 | [ C(RESULT_MISS) ] = 0x0208, /* DTLB_MISSES.MISS_LD */ | ||
| 314 | }, | ||
| 315 | [ C(OP_WRITE) ] = { | ||
| 316 | [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI (alias) */ | ||
| 317 | [ C(RESULT_MISS) ] = 0x0808, /* DTLB_MISSES.MISS_ST */ | ||
| 318 | }, | ||
| 319 | [ C(OP_PREFETCH) ] = { | ||
| 320 | [ C(RESULT_ACCESS) ] = 0, | ||
| 321 | [ C(RESULT_MISS) ] = 0, | ||
| 322 | }, | ||
| 323 | }, | ||
| 324 | [ C(ITLB) ] = { | ||
| 325 | [ C(OP_READ) ] = { | ||
| 326 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
| 327 | [ C(RESULT_MISS) ] = 0x1282, /* ITLBMISSES */ | ||
| 328 | }, | ||
| 329 | [ C(OP_WRITE) ] = { | ||
| 330 | [ C(RESULT_ACCESS) ] = -1, | ||
| 331 | [ C(RESULT_MISS) ] = -1, | ||
| 332 | }, | ||
| 333 | [ C(OP_PREFETCH) ] = { | ||
| 334 | [ C(RESULT_ACCESS) ] = -1, | ||
| 335 | [ C(RESULT_MISS) ] = -1, | ||
| 336 | }, | ||
| 337 | }, | ||
| 338 | [ C(BPU ) ] = { | ||
| 339 | [ C(OP_READ) ] = { | ||
| 340 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
| 341 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
| 342 | }, | ||
| 343 | [ C(OP_WRITE) ] = { | ||
| 344 | [ C(RESULT_ACCESS) ] = -1, | ||
| 345 | [ C(RESULT_MISS) ] = -1, | ||
| 346 | }, | ||
| 347 | [ C(OP_PREFETCH) ] = { | ||
| 348 | [ C(RESULT_ACCESS) ] = -1, | ||
| 349 | [ C(RESULT_MISS) ] = -1, | ||
| 350 | }, | ||
| 351 | }, | ||
| 352 | }; | ||
| 353 | |||
| 354 | static __initconst u64 atom_hw_cache_event_ids | ||
| 355 | [PERF_COUNT_HW_CACHE_MAX] | ||
| 356 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
| 357 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
| 358 | { | ||
| 359 | [ C(L1D) ] = { | ||
| 360 | [ C(OP_READ) ] = { | ||
| 361 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE.LD */ | ||
| 362 | [ C(RESULT_MISS) ] = 0, | ||
| 363 | }, | ||
| 364 | [ C(OP_WRITE) ] = { | ||
| 365 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST */ | ||
| 366 | [ C(RESULT_MISS) ] = 0, | ||
| 367 | }, | ||
| 368 | [ C(OP_PREFETCH) ] = { | ||
| 369 | [ C(RESULT_ACCESS) ] = 0x0, | ||
| 370 | [ C(RESULT_MISS) ] = 0, | ||
| 371 | }, | ||
| 372 | }, | ||
| 373 | [ C(L1I ) ] = { | ||
| 374 | [ C(OP_READ) ] = { | ||
| 375 | [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS */ | ||
| 376 | [ C(RESULT_MISS) ] = 0x0280, /* L1I.MISSES */ | ||
| 377 | }, | ||
| 378 | [ C(OP_WRITE) ] = { | ||
| 379 | [ C(RESULT_ACCESS) ] = -1, | ||
| 380 | [ C(RESULT_MISS) ] = -1, | ||
| 381 | }, | ||
| 382 | [ C(OP_PREFETCH) ] = { | ||
| 383 | [ C(RESULT_ACCESS) ] = 0, | ||
| 384 | [ C(RESULT_MISS) ] = 0, | ||
| 385 | }, | ||
| 386 | }, | ||
| 387 | [ C(LL ) ] = { | ||
| 388 | [ C(OP_READ) ] = { | ||
| 389 | [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI */ | ||
| 390 | [ C(RESULT_MISS) ] = 0x4129, /* L2_LD.ISTATE */ | ||
| 391 | }, | ||
| 392 | [ C(OP_WRITE) ] = { | ||
| 393 | [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI */ | ||
| 394 | [ C(RESULT_MISS) ] = 0x412A, /* L2_ST.ISTATE */ | ||
| 395 | }, | ||
| 396 | [ C(OP_PREFETCH) ] = { | ||
| 397 | [ C(RESULT_ACCESS) ] = 0, | ||
| 398 | [ C(RESULT_MISS) ] = 0, | ||
| 399 | }, | ||
| 400 | }, | ||
| 401 | [ C(DTLB) ] = { | ||
| 402 | [ C(OP_READ) ] = { | ||
| 403 | [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI (alias) */ | ||
| 404 | [ C(RESULT_MISS) ] = 0x0508, /* DTLB_MISSES.MISS_LD */ | ||
| 405 | }, | ||
| 406 | [ C(OP_WRITE) ] = { | ||
| 407 | [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI (alias) */ | ||
| 408 | [ C(RESULT_MISS) ] = 0x0608, /* DTLB_MISSES.MISS_ST */ | ||
| 409 | }, | ||
| 410 | [ C(OP_PREFETCH) ] = { | ||
| 411 | [ C(RESULT_ACCESS) ] = 0, | ||
| 412 | [ C(RESULT_MISS) ] = 0, | ||
| 413 | }, | ||
| 414 | }, | ||
| 415 | [ C(ITLB) ] = { | ||
| 416 | [ C(OP_READ) ] = { | ||
| 417 | [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */ | ||
| 418 | [ C(RESULT_MISS) ] = 0x0282, /* ITLB.MISSES */ | ||
| 419 | }, | ||
| 420 | [ C(OP_WRITE) ] = { | ||
| 421 | [ C(RESULT_ACCESS) ] = -1, | ||
| 422 | [ C(RESULT_MISS) ] = -1, | ||
| 423 | }, | ||
| 424 | [ C(OP_PREFETCH) ] = { | ||
| 425 | [ C(RESULT_ACCESS) ] = -1, | ||
| 426 | [ C(RESULT_MISS) ] = -1, | ||
| 427 | }, | ||
| 428 | }, | ||
| 429 | [ C(BPU ) ] = { | ||
| 430 | [ C(OP_READ) ] = { | ||
| 431 | [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */ | ||
| 432 | [ C(RESULT_MISS) ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */ | ||
| 433 | }, | ||
| 434 | [ C(OP_WRITE) ] = { | ||
| 435 | [ C(RESULT_ACCESS) ] = -1, | ||
| 436 | [ C(RESULT_MISS) ] = -1, | ||
| 437 | }, | ||
| 438 | [ C(OP_PREFETCH) ] = { | ||
| 439 | [ C(RESULT_ACCESS) ] = -1, | ||
| 440 | [ C(RESULT_MISS) ] = -1, | ||
| 441 | }, | ||
| 442 | }, | ||
| 443 | }; | ||
| 444 | |||
| 445 | static u64 intel_pmu_raw_event(u64 hw_event) | ||
| 446 | { | ||
| 447 | #define CORE_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
| 448 | #define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
| 449 | #define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
| 450 | #define CORE_EVNTSEL_INV_MASK 0x00800000ULL | ||
| 451 | #define CORE_EVNTSEL_REG_MASK 0xFF000000ULL | ||
| 452 | |||
| 453 | #define CORE_EVNTSEL_MASK \ | ||
| 454 | (INTEL_ARCH_EVTSEL_MASK | \ | ||
| 455 | INTEL_ARCH_UNIT_MASK | \ | ||
| 456 | INTEL_ARCH_EDGE_MASK | \ | ||
| 457 | INTEL_ARCH_INV_MASK | \ | ||
| 458 | INTEL_ARCH_CNT_MASK) | ||
| 459 | |||
| 460 | return hw_event & CORE_EVNTSEL_MASK; | ||
| 461 | } | ||
| 462 | |||
| 463 | static void intel_pmu_enable_bts(u64 config) | ||
| 464 | { | ||
| 465 | unsigned long debugctlmsr; | ||
| 466 | |||
| 467 | debugctlmsr = get_debugctlmsr(); | ||
| 468 | |||
| 469 | debugctlmsr |= X86_DEBUGCTL_TR; | ||
| 470 | debugctlmsr |= X86_DEBUGCTL_BTS; | ||
| 471 | debugctlmsr |= X86_DEBUGCTL_BTINT; | ||
| 472 | |||
| 473 | if (!(config & ARCH_PERFMON_EVENTSEL_OS)) | ||
| 474 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; | ||
| 475 | |||
| 476 | if (!(config & ARCH_PERFMON_EVENTSEL_USR)) | ||
| 477 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; | ||
| 478 | |||
| 479 | update_debugctlmsr(debugctlmsr); | ||
| 480 | } | ||
| 481 | |||
| 482 | static void intel_pmu_disable_bts(void) | ||
| 483 | { | ||
| 484 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 485 | unsigned long debugctlmsr; | ||
| 486 | |||
| 487 | if (!cpuc->ds) | ||
| 488 | return; | ||
| 489 | |||
| 490 | debugctlmsr = get_debugctlmsr(); | ||
| 491 | |||
| 492 | debugctlmsr &= | ||
| 493 | ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | | ||
| 494 | X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); | ||
| 495 | |||
| 496 | update_debugctlmsr(debugctlmsr); | ||
| 497 | } | ||
| 498 | |||
| 499 | static void intel_pmu_disable_all(void) | ||
| 500 | { | ||
| 501 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 502 | |||
| 503 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | ||
| 504 | |||
| 505 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) | ||
| 506 | intel_pmu_disable_bts(); | ||
| 507 | } | ||
| 508 | |||
| 509 | static void intel_pmu_enable_all(void) | ||
| 510 | { | ||
| 511 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 512 | |||
| 513 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | ||
| 514 | |||
| 515 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { | ||
| 516 | struct perf_event *event = | ||
| 517 | cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
| 518 | |||
| 519 | if (WARN_ON_ONCE(!event)) | ||
| 520 | return; | ||
| 521 | |||
| 522 | intel_pmu_enable_bts(event->hw.config); | ||
| 523 | } | ||
| 524 | } | ||
| 525 | |||
| 526 | static inline u64 intel_pmu_get_status(void) | ||
| 527 | { | ||
| 528 | u64 status; | ||
| 529 | |||
| 530 | rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); | ||
| 531 | |||
| 532 | return status; | ||
| 533 | } | ||
| 534 | |||
| 535 | static inline void intel_pmu_ack_status(u64 ack) | ||
| 536 | { | ||
| 537 | wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); | ||
| 538 | } | ||
| 539 | |||
| 540 | static inline void | ||
| 541 | intel_pmu_disable_fixed(struct hw_perf_event *hwc, int __idx) | ||
| 542 | { | ||
| 543 | int idx = __idx - X86_PMC_IDX_FIXED; | ||
| 544 | u64 ctrl_val, mask; | ||
| 545 | |||
| 546 | mask = 0xfULL << (idx * 4); | ||
| 547 | |||
| 548 | rdmsrl(hwc->config_base, ctrl_val); | ||
| 549 | ctrl_val &= ~mask; | ||
| 550 | (void)checking_wrmsrl(hwc->config_base, ctrl_val); | ||
| 551 | } | ||
| 552 | |||
| 553 | static void intel_pmu_drain_bts_buffer(void) | ||
| 554 | { | ||
| 555 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 556 | struct debug_store *ds = cpuc->ds; | ||
| 557 | struct bts_record { | ||
| 558 | u64 from; | ||
| 559 | u64 to; | ||
| 560 | u64 flags; | ||
| 561 | }; | ||
| 562 | struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS]; | ||
| 563 | struct bts_record *at, *top; | ||
| 564 | struct perf_output_handle handle; | ||
| 565 | struct perf_event_header header; | ||
| 566 | struct perf_sample_data data; | ||
| 567 | struct pt_regs regs; | ||
| 568 | |||
| 569 | if (!event) | ||
| 570 | return; | ||
| 571 | |||
| 572 | if (!ds) | ||
| 573 | return; | ||
| 574 | |||
| 575 | at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; | ||
| 576 | top = (struct bts_record *)(unsigned long)ds->bts_index; | ||
| 577 | |||
| 578 | if (top <= at) | ||
| 579 | return; | ||
| 580 | |||
| 581 | ds->bts_index = ds->bts_buffer_base; | ||
| 582 | |||
| 583 | |||
| 584 | data.period = event->hw.last_period; | ||
| 585 | data.addr = 0; | ||
| 586 | data.raw = NULL; | ||
| 587 | regs.ip = 0; | ||
| 588 | |||
| 589 | /* | ||
| 590 | * Prepare a generic sample, i.e. fill in the invariant fields. | ||
| 591 | * We will overwrite the from and to address before we output | ||
| 592 | * the sample. | ||
| 593 | */ | ||
| 594 | perf_prepare_sample(&header, &data, event, ®s); | ||
| 595 | |||
| 596 | if (perf_output_begin(&handle, event, | ||
| 597 | header.size * (top - at), 1, 1)) | ||
| 598 | return; | ||
| 599 | |||
| 600 | for (; at < top; at++) { | ||
| 601 | data.ip = at->from; | ||
| 602 | data.addr = at->to; | ||
| 603 | |||
| 604 | perf_output_sample(&handle, &header, &data, event); | ||
| 605 | } | ||
| 606 | |||
| 607 | perf_output_end(&handle); | ||
| 608 | |||
| 609 | /* There's new data available. */ | ||
| 610 | event->hw.interrupts++; | ||
| 611 | event->pending_kill = POLL_IN; | ||
| 612 | } | ||
| 613 | |||
| 614 | static inline void | ||
| 615 | intel_pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
| 616 | { | ||
| 617 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
| 618 | intel_pmu_disable_bts(); | ||
| 619 | intel_pmu_drain_bts_buffer(); | ||
| 620 | return; | ||
| 621 | } | ||
| 622 | |||
| 623 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
| 624 | intel_pmu_disable_fixed(hwc, idx); | ||
| 625 | return; | ||
| 626 | } | ||
| 627 | |||
| 628 | x86_pmu_disable_event(hwc, idx); | ||
| 629 | } | ||
| 630 | |||
| 631 | static inline void | ||
| 632 | intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) | ||
| 633 | { | ||
| 634 | int idx = __idx - X86_PMC_IDX_FIXED; | ||
| 635 | u64 ctrl_val, bits, mask; | ||
| 636 | int err; | ||
| 637 | |||
| 638 | /* | ||
| 639 | * Enable IRQ generation (0x8), | ||
| 640 | * and enable ring-3 counting (0x2) and ring-0 counting (0x1) | ||
| 641 | * if requested: | ||
| 642 | */ | ||
| 643 | bits = 0x8ULL; | ||
| 644 | if (hwc->config & ARCH_PERFMON_EVENTSEL_USR) | ||
| 645 | bits |= 0x2; | ||
| 646 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | ||
| 647 | bits |= 0x1; | ||
| 648 | |||
| 649 | /* | ||
| 650 | * ANY bit is supported in v3 and up | ||
| 651 | */ | ||
| 652 | if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY) | ||
| 653 | bits |= 0x4; | ||
| 654 | |||
| 655 | bits <<= (idx * 4); | ||
| 656 | mask = 0xfULL << (idx * 4); | ||
| 657 | |||
| 658 | rdmsrl(hwc->config_base, ctrl_val); | ||
| 659 | ctrl_val &= ~mask; | ||
| 660 | ctrl_val |= bits; | ||
| 661 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | ||
| 662 | } | ||
| 663 | |||
| 664 | static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
| 665 | { | ||
| 666 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
| 667 | if (!__get_cpu_var(cpu_hw_events).enabled) | ||
| 668 | return; | ||
| 669 | |||
| 670 | intel_pmu_enable_bts(hwc->config); | ||
| 671 | return; | ||
| 672 | } | ||
| 673 | |||
| 674 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | ||
| 675 | intel_pmu_enable_fixed(hwc, idx); | ||
| 676 | return; | ||
| 677 | } | ||
| 678 | |||
| 679 | __x86_pmu_enable_event(hwc, idx); | ||
| 680 | } | ||
| 681 | |||
| 682 | /* | ||
| 683 | * Save and restart an expired event. Called by NMI contexts, | ||
| 684 | * so it has to be careful about preempting normal event ops: | ||
| 685 | */ | ||
| 686 | static int intel_pmu_save_and_restart(struct perf_event *event) | ||
| 687 | { | ||
| 688 | struct hw_perf_event *hwc = &event->hw; | ||
| 689 | int idx = hwc->idx; | ||
| 690 | int ret; | ||
| 691 | |||
| 692 | x86_perf_event_update(event, hwc, idx); | ||
| 693 | ret = x86_perf_event_set_period(event, hwc, idx); | ||
| 694 | |||
| 695 | return ret; | ||
| 696 | } | ||
| 697 | |||
| 698 | static void intel_pmu_reset(void) | ||
| 699 | { | ||
| 700 | struct debug_store *ds = __get_cpu_var(cpu_hw_events).ds; | ||
| 701 | unsigned long flags; | ||
| 702 | int idx; | ||
| 703 | |||
| 704 | if (!x86_pmu.num_events) | ||
| 705 | return; | ||
| 706 | |||
| 707 | local_irq_save(flags); | ||
| 708 | |||
| 709 | printk("clearing PMU state on CPU#%d\n", smp_processor_id()); | ||
| 710 | |||
| 711 | for (idx = 0; idx < x86_pmu.num_events; idx++) { | ||
| 712 | checking_wrmsrl(x86_pmu.eventsel + idx, 0ull); | ||
| 713 | checking_wrmsrl(x86_pmu.perfctr + idx, 0ull); | ||
| 714 | } | ||
| 715 | for (idx = 0; idx < x86_pmu.num_events_fixed; idx++) { | ||
| 716 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); | ||
| 717 | } | ||
| 718 | if (ds) | ||
| 719 | ds->bts_index = ds->bts_buffer_base; | ||
| 720 | |||
| 721 | local_irq_restore(flags); | ||
| 722 | } | ||
| 723 | |||
| 724 | /* | ||
| 725 | * This handler is triggered by the local APIC, so the APIC IRQ handling | ||
| 726 | * rules apply: | ||
| 727 | */ | ||
| 728 | static int intel_pmu_handle_irq(struct pt_regs *regs) | ||
| 729 | { | ||
| 730 | struct perf_sample_data data; | ||
| 731 | struct cpu_hw_events *cpuc; | ||
| 732 | int bit, loops; | ||
| 733 | u64 ack, status; | ||
| 734 | |||
| 735 | data.addr = 0; | ||
| 736 | data.raw = NULL; | ||
| 737 | |||
| 738 | cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 739 | |||
| 740 | perf_disable(); | ||
| 741 | intel_pmu_drain_bts_buffer(); | ||
| 742 | status = intel_pmu_get_status(); | ||
| 743 | if (!status) { | ||
| 744 | perf_enable(); | ||
| 745 | return 0; | ||
| 746 | } | ||
| 747 | |||
| 748 | loops = 0; | ||
| 749 | again: | ||
| 750 | if (++loops > 100) { | ||
| 751 | WARN_ONCE(1, "perfevents: irq loop stuck!\n"); | ||
| 752 | perf_event_print_debug(); | ||
| 753 | intel_pmu_reset(); | ||
| 754 | perf_enable(); | ||
| 755 | return 1; | ||
| 756 | } | ||
| 757 | |||
| 758 | inc_irq_stat(apic_perf_irqs); | ||
| 759 | ack = status; | ||
| 760 | for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | ||
| 761 | struct perf_event *event = cpuc->events[bit]; | ||
| 762 | |||
| 763 | clear_bit(bit, (unsigned long *) &status); | ||
| 764 | if (!test_bit(bit, cpuc->active_mask)) | ||
| 765 | continue; | ||
| 766 | |||
| 767 | if (!intel_pmu_save_and_restart(event)) | ||
| 768 | continue; | ||
| 769 | |||
| 770 | data.period = event->hw.last_period; | ||
| 771 | |||
| 772 | if (perf_event_overflow(event, 1, &data, regs)) | ||
| 773 | intel_pmu_disable_event(&event->hw, bit); | ||
| 774 | } | ||
| 775 | |||
| 776 | intel_pmu_ack_status(ack); | ||
| 777 | |||
| 778 | /* | ||
| 779 | * Repeat if there is more work to be done: | ||
| 780 | */ | ||
| 781 | status = intel_pmu_get_status(); | ||
| 782 | if (status) | ||
| 783 | goto again; | ||
| 784 | |||
| 785 | perf_enable(); | ||
| 786 | |||
| 787 | return 1; | ||
| 788 | } | ||
| 789 | |||
| 790 | static struct event_constraint bts_constraint = | ||
| 791 | EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); | ||
| 792 | |||
| 793 | static struct event_constraint * | ||
| 794 | intel_special_constraints(struct perf_event *event) | ||
| 795 | { | ||
| 796 | unsigned int hw_event; | ||
| 797 | |||
| 798 | hw_event = event->hw.config & INTEL_ARCH_EVENT_MASK; | ||
| 799 | |||
| 800 | if (unlikely((hw_event == | ||
| 801 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | ||
| 802 | (event->hw.sample_period == 1))) { | ||
| 803 | |||
| 804 | return &bts_constraint; | ||
| 805 | } | ||
| 806 | return NULL; | ||
| 807 | } | ||
| 808 | |||
| 809 | static struct event_constraint * | ||
| 810 | intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | ||
| 811 | { | ||
| 812 | struct event_constraint *c; | ||
| 813 | |||
| 814 | c = intel_special_constraints(event); | ||
| 815 | if (c) | ||
| 816 | return c; | ||
| 817 | |||
| 818 | return x86_get_event_constraints(cpuc, event); | ||
| 819 | } | ||
| 820 | |||
| 821 | static __initconst struct x86_pmu core_pmu = { | ||
| 822 | .name = "core", | ||
| 823 | .handle_irq = x86_pmu_handle_irq, | ||
| 824 | .disable_all = x86_pmu_disable_all, | ||
| 825 | .enable_all = x86_pmu_enable_all, | ||
| 826 | .enable = x86_pmu_enable_event, | ||
| 827 | .disable = x86_pmu_disable_event, | ||
| 828 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
| 829 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
| 830 | .event_map = intel_pmu_event_map, | ||
| 831 | .raw_event = intel_pmu_raw_event, | ||
| 832 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
| 833 | .apic = 1, | ||
| 834 | /* | ||
| 835 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
| 836 | * so we install an artificial 1<<31 period regardless of | ||
| 837 | * the generic event period: | ||
| 838 | */ | ||
| 839 | .max_period = (1ULL << 31) - 1, | ||
| 840 | .get_event_constraints = intel_get_event_constraints, | ||
| 841 | .event_constraints = intel_core_event_constraints, | ||
| 842 | }; | ||
| 843 | |||
| 844 | static __initconst struct x86_pmu intel_pmu = { | ||
| 845 | .name = "Intel", | ||
| 846 | .handle_irq = intel_pmu_handle_irq, | ||
| 847 | .disable_all = intel_pmu_disable_all, | ||
| 848 | .enable_all = intel_pmu_enable_all, | ||
| 849 | .enable = intel_pmu_enable_event, | ||
| 850 | .disable = intel_pmu_disable_event, | ||
| 851 | .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, | ||
| 852 | .perfctr = MSR_ARCH_PERFMON_PERFCTR0, | ||
| 853 | .event_map = intel_pmu_event_map, | ||
| 854 | .raw_event = intel_pmu_raw_event, | ||
| 855 | .max_events = ARRAY_SIZE(intel_perfmon_event_map), | ||
| 856 | .apic = 1, | ||
| 857 | /* | ||
| 858 | * Intel PMCs cannot be accessed sanely above 32 bit width, | ||
| 859 | * so we install an artificial 1<<31 period regardless of | ||
| 860 | * the generic event period: | ||
| 861 | */ | ||
| 862 | .max_period = (1ULL << 31) - 1, | ||
| 863 | .enable_bts = intel_pmu_enable_bts, | ||
| 864 | .disable_bts = intel_pmu_disable_bts, | ||
| 865 | .get_event_constraints = intel_get_event_constraints | ||
| 866 | }; | ||
| 867 | |||
| 868 | static __init int intel_pmu_init(void) | ||
| 869 | { | ||
| 870 | union cpuid10_edx edx; | ||
| 871 | union cpuid10_eax eax; | ||
| 872 | unsigned int unused; | ||
| 873 | unsigned int ebx; | ||
| 874 | int version; | ||
| 875 | |||
| 876 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { | ||
| 877 | /* check for P6 processor family */ | ||
| 878 | if (boot_cpu_data.x86 == 6) { | ||
| 879 | return p6_pmu_init(); | ||
| 880 | } else { | ||
| 881 | return -ENODEV; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | |||
| 885 | /* | ||
| 886 | * Check whether the Architectural PerfMon supports | ||
| 887 | * Branch Misses Retired hw_event or not. | ||
| 888 | */ | ||
| 889 | cpuid(10, &eax.full, &ebx, &unused, &edx.full); | ||
| 890 | if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED) | ||
| 891 | return -ENODEV; | ||
| 892 | |||
| 893 | version = eax.split.version_id; | ||
| 894 | if (version < 2) | ||
| 895 | x86_pmu = core_pmu; | ||
| 896 | else | ||
| 897 | x86_pmu = intel_pmu; | ||
| 898 | |||
| 899 | x86_pmu.version = version; | ||
| 900 | x86_pmu.num_events = eax.split.num_events; | ||
| 901 | x86_pmu.event_bits = eax.split.bit_width; | ||
| 902 | x86_pmu.event_mask = (1ULL << eax.split.bit_width) - 1; | ||
| 903 | |||
| 904 | /* | ||
| 905 | * Quirk: v2 perfmon does not report fixed-purpose events, so | ||
| 906 | * assume at least 3 events: | ||
| 907 | */ | ||
| 908 | if (version > 1) | ||
| 909 | x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); | ||
| 910 | |||
| 911 | /* | ||
| 912 | * Install the hw-cache-events table: | ||
| 913 | */ | ||
| 914 | switch (boot_cpu_data.x86_model) { | ||
| 915 | case 14: /* 65 nm core solo/duo, "Yonah" */ | ||
| 916 | pr_cont("Core events, "); | ||
| 917 | break; | ||
| 918 | |||
| 919 | case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ | ||
| 920 | case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ | ||
| 921 | case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ | ||
| 922 | case 29: /* six-core 45 nm xeon "Dunnington" */ | ||
| 923 | memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, | ||
| 924 | sizeof(hw_cache_event_ids)); | ||
| 925 | |||
| 926 | x86_pmu.event_constraints = intel_core2_event_constraints; | ||
| 927 | pr_cont("Core2 events, "); | ||
| 928 | break; | ||
| 929 | |||
| 930 | case 26: /* 45 nm nehalem, "Bloomfield" */ | ||
| 931 | case 30: /* 45 nm nehalem, "Lynnfield" */ | ||
| 932 | memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, | ||
| 933 | sizeof(hw_cache_event_ids)); | ||
| 934 | |||
| 935 | x86_pmu.event_constraints = intel_nehalem_event_constraints; | ||
| 936 | pr_cont("Nehalem/Corei7 events, "); | ||
| 937 | break; | ||
| 938 | case 28: | ||
| 939 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | ||
| 940 | sizeof(hw_cache_event_ids)); | ||
| 941 | |||
| 942 | x86_pmu.event_constraints = intel_gen_event_constraints; | ||
| 943 | pr_cont("Atom events, "); | ||
| 944 | break; | ||
| 945 | |||
| 946 | case 37: /* 32 nm nehalem, "Clarkdale" */ | ||
| 947 | case 44: /* 32 nm nehalem, "Gulftown" */ | ||
| 948 | memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, | ||
| 949 | sizeof(hw_cache_event_ids)); | ||
| 950 | |||
| 951 | x86_pmu.event_constraints = intel_westmere_event_constraints; | ||
| 952 | pr_cont("Westmere events, "); | ||
| 953 | break; | ||
| 954 | default: | ||
| 955 | /* | ||
| 956 | * default constraints for v2 and up | ||
| 957 | */ | ||
| 958 | x86_pmu.event_constraints = intel_gen_event_constraints; | ||
| 959 | pr_cont("generic architected perfmon, "); | ||
| 960 | } | ||
| 961 | return 0; | ||
| 962 | } | ||
| 963 | |||
| 964 | #else /* CONFIG_CPU_SUP_INTEL */ | ||
| 965 | |||
| 966 | static int intel_pmu_init(void) | ||
| 967 | { | ||
| 968 | return 0; | ||
| 969 | } | ||
| 970 | |||
| 971 | #endif /* CONFIG_CPU_SUP_INTEL */ | ||
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c new file mode 100644 index 000000000000..1ca5ba078afd --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_p6.c | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | #ifdef CONFIG_CPU_SUP_INTEL | ||
| 2 | |||
| 3 | /* | ||
| 4 | * Not sure about some of these | ||
| 5 | */ | ||
| 6 | static const u64 p6_perfmon_event_map[] = | ||
| 7 | { | ||
| 8 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, | ||
| 9 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 10 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, | ||
| 11 | [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, | ||
| 12 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 13 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 14 | [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, | ||
| 15 | }; | ||
| 16 | |||
| 17 | static u64 p6_pmu_event_map(int hw_event) | ||
| 18 | { | ||
| 19 | return p6_perfmon_event_map[hw_event]; | ||
| 20 | } | ||
| 21 | |||
| 22 | /* | ||
| 23 | * Event setting that is specified not to count anything. | ||
| 24 | * We use this to effectively disable a counter. | ||
| 25 | * | ||
| 26 | * L2_RQSTS with 0 MESI unit mask. | ||
| 27 | */ | ||
| 28 | #define P6_NOP_EVENT 0x0000002EULL | ||
| 29 | |||
| 30 | static u64 p6_pmu_raw_event(u64 hw_event) | ||
| 31 | { | ||
| 32 | #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
| 33 | #define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
| 34 | #define P6_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
| 35 | #define P6_EVNTSEL_INV_MASK 0x00800000ULL | ||
| 36 | #define P6_EVNTSEL_REG_MASK 0xFF000000ULL | ||
| 37 | |||
| 38 | #define P6_EVNTSEL_MASK \ | ||
| 39 | (P6_EVNTSEL_EVENT_MASK | \ | ||
| 40 | P6_EVNTSEL_UNIT_MASK | \ | ||
| 41 | P6_EVNTSEL_EDGE_MASK | \ | ||
| 42 | P6_EVNTSEL_INV_MASK | \ | ||
| 43 | P6_EVNTSEL_REG_MASK) | ||
| 44 | |||
| 45 | return hw_event & P6_EVNTSEL_MASK; | ||
| 46 | } | ||
| 47 | |||
| 48 | static struct event_constraint p6_event_constraints[] = | ||
| 49 | { | ||
| 50 | INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ | ||
| 51 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | ||
| 52 | INTEL_EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */ | ||
| 53 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | ||
| 54 | INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ | ||
| 55 | INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ | ||
| 56 | EVENT_CONSTRAINT_END | ||
| 57 | }; | ||
| 58 | |||
| 59 | static void p6_pmu_disable_all(void) | ||
| 60 | { | ||
| 61 | u64 val; | ||
| 62 | |||
| 63 | /* p6 only has one enable register */ | ||
| 64 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
| 65 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 66 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
| 67 | } | ||
| 68 | |||
| 69 | static void p6_pmu_enable_all(void) | ||
| 70 | { | ||
| 71 | unsigned long val; | ||
| 72 | |||
| 73 | /* p6 only has one enable register */ | ||
| 74 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
| 75 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 76 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
| 77 | } | ||
| 78 | |||
| 79 | static inline void | ||
| 80 | p6_pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
| 81 | { | ||
| 82 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 83 | u64 val = P6_NOP_EVENT; | ||
| 84 | |||
| 85 | if (cpuc->enabled) | ||
| 86 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 87 | |||
| 88 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
| 89 | } | ||
| 90 | |||
| 91 | static void p6_pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
| 92 | { | ||
| 93 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
| 94 | u64 val; | ||
| 95 | |||
| 96 | val = hwc->config; | ||
| 97 | if (cpuc->enabled) | ||
| 98 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 99 | |||
| 100 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
| 101 | } | ||
| 102 | |||
| 103 | static __initconst struct x86_pmu p6_pmu = { | ||
| 104 | .name = "p6", | ||
| 105 | .handle_irq = x86_pmu_handle_irq, | ||
| 106 | .disable_all = p6_pmu_disable_all, | ||
| 107 | .enable_all = p6_pmu_enable_all, | ||
| 108 | .enable = p6_pmu_enable_event, | ||
| 109 | .disable = p6_pmu_disable_event, | ||
| 110 | .eventsel = MSR_P6_EVNTSEL0, | ||
| 111 | .perfctr = MSR_P6_PERFCTR0, | ||
| 112 | .event_map = p6_pmu_event_map, | ||
| 113 | .raw_event = p6_pmu_raw_event, | ||
| 114 | .max_events = ARRAY_SIZE(p6_perfmon_event_map), | ||
| 115 | .apic = 1, | ||
| 116 | .max_period = (1ULL << 31) - 1, | ||
| 117 | .version = 0, | ||
| 118 | .num_events = 2, | ||
| 119 | /* | ||
| 120 | * Events have 40 bits implemented. However they are designed such | ||
| 121 | * that bits [32-39] are sign extensions of bit 31. As such the | ||
| 122 | * effective width of a event for P6-like PMU is 32 bits only. | ||
| 123 | * | ||
| 124 | * See IA-32 Intel Architecture Software developer manual Vol 3B | ||
| 125 | */ | ||
| 126 | .event_bits = 32, | ||
| 127 | .event_mask = (1ULL << 32) - 1, | ||
| 128 | .get_event_constraints = x86_get_event_constraints, | ||
| 129 | .event_constraints = p6_event_constraints, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static __init int p6_pmu_init(void) | ||
| 133 | { | ||
| 134 | switch (boot_cpu_data.x86_model) { | ||
| 135 | case 1: | ||
| 136 | case 3: /* Pentium Pro */ | ||
| 137 | case 5: | ||
| 138 | case 6: /* Pentium II */ | ||
| 139 | case 7: | ||
| 140 | case 8: | ||
| 141 | case 11: /* Pentium III */ | ||
| 142 | case 9: | ||
| 143 | case 13: | ||
| 144 | /* Pentium M */ | ||
| 145 | break; | ||
| 146 | default: | ||
| 147 | pr_cont("unsupported p6 CPU model %d ", | ||
| 148 | boot_cpu_data.x86_model); | ||
| 149 | return -ENODEV; | ||
| 150 | } | ||
| 151 | |||
| 152 | x86_pmu = p6_pmu; | ||
| 153 | |||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | #endif /* CONFIG_CPU_SUP_INTEL */ | ||
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 898df9719afb..74f4e85a5727 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c | |||
| @@ -115,17 +115,6 @@ int avail_to_resrv_perfctr_nmi_bit(unsigned int counter) | |||
| 115 | 115 | ||
| 116 | return !test_bit(counter, perfctr_nmi_owner); | 116 | return !test_bit(counter, perfctr_nmi_owner); |
| 117 | } | 117 | } |
| 118 | |||
| 119 | /* checks the an msr for availability */ | ||
| 120 | int avail_to_resrv_perfctr_nmi(unsigned int msr) | ||
| 121 | { | ||
| 122 | unsigned int counter; | ||
| 123 | |||
| 124 | counter = nmi_perfctr_msr_to_bit(msr); | ||
| 125 | BUG_ON(counter > NMI_MAX_COUNTER_BITS); | ||
| 126 | |||
| 127 | return !test_bit(counter, perfctr_nmi_owner); | ||
| 128 | } | ||
| 129 | EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit); | 118 | EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit); |
| 130 | 119 | ||
| 131 | int reserve_perfctr_nmi(unsigned int msr) | 120 | int reserve_perfctr_nmi(unsigned int msr) |
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index ae775ca47b25..11540a189d93 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c | |||
| @@ -18,11 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #include "dumpstack.h" | 19 | #include "dumpstack.h" |
| 20 | 20 | ||
| 21 | /* Just a stub for now */ | ||
| 22 | int x86_is_stack_id(int id, char *name) | ||
| 23 | { | ||
| 24 | return 0; | ||
| 25 | } | ||
| 26 | 21 | ||
| 27 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | 22 | void dump_trace(struct task_struct *task, struct pt_regs *regs, |
| 28 | unsigned long *stack, unsigned long bp, | 23 | unsigned long *stack, unsigned long bp, |
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 0ad9597073f5..dce99abb4496 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
| @@ -33,11 +33,6 @@ static char x86_stack_ids[][8] = { | |||
| 33 | #endif | 33 | #endif |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | int x86_is_stack_id(int id, char *name) | ||
| 37 | { | ||
| 38 | return x86_stack_ids[id - 1] == name; | ||
| 39 | } | ||
| 40 | |||
| 41 | static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, | 36 | static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, |
| 42 | unsigned *usedp, char **idp) | 37 | unsigned *usedp, char **idp) |
| 43 | { | 38 | { |
| @@ -291,6 +286,7 @@ void show_registers(struct pt_regs *regs) | |||
| 291 | 286 | ||
| 292 | sp = regs->sp; | 287 | sp = regs->sp; |
| 293 | printk("CPU %d ", cpu); | 288 | printk("CPU %d ", cpu); |
| 289 | print_modules(); | ||
| 294 | __show_regs(regs, 1); | 290 | __show_regs(regs, 1); |
| 295 | printk("Process %s (pid: %d, threadinfo %p, task %p)\n", | 291 | printk("Process %s (pid: %d, threadinfo %p, task %p)\n", |
| 296 | cur->comm, cur->pid, task_thread_info(cur), cur); | 292 | cur->comm, cur->pid, task_thread_info(cur), cur); |
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index a1a7876cadcb..740b440fbd73 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
| @@ -12,21 +12,13 @@ | |||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
| 15 | #include <linux/ioport.h> | ||
| 16 | #include <linux/string.h> | ||
| 17 | #include <linux/kexec.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/mm.h> | ||
| 20 | #include <linux/pfn.h> | 15 | #include <linux/pfn.h> |
| 21 | #include <linux/suspend.h> | 16 | #include <linux/suspend.h> |
| 22 | #include <linux/firmware-map.h> | 17 | #include <linux/firmware-map.h> |
| 23 | 18 | ||
| 24 | #include <asm/pgtable.h> | ||
| 25 | #include <asm/page.h> | ||
| 26 | #include <asm/e820.h> | 19 | #include <asm/e820.h> |
| 27 | #include <asm/proto.h> | 20 | #include <asm/proto.h> |
| 28 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
| 29 | #include <asm/trampoline.h> | ||
| 30 | 22 | ||
| 31 | /* | 23 | /* |
| 32 | * The e820 map is the map that gets modified e.g. with command line parameters | 24 | * The e820 map is the map that gets modified e.g. with command line parameters |
| @@ -517,11 +509,19 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type, | |||
| 517 | int checktype) | 509 | int checktype) |
| 518 | { | 510 | { |
| 519 | int i; | 511 | int i; |
| 512 | u64 end; | ||
| 520 | u64 real_removed_size = 0; | 513 | u64 real_removed_size = 0; |
| 521 | 514 | ||
| 522 | if (size > (ULLONG_MAX - start)) | 515 | if (size > (ULLONG_MAX - start)) |
| 523 | size = ULLONG_MAX - start; | 516 | size = ULLONG_MAX - start; |
| 524 | 517 | ||
| 518 | end = start + size; | ||
| 519 | printk(KERN_DEBUG "e820 remove range: %016Lx - %016Lx ", | ||
| 520 | (unsigned long long) start, | ||
| 521 | (unsigned long long) end); | ||
| 522 | e820_print_type(old_type); | ||
| 523 | printk(KERN_CONT "\n"); | ||
| 524 | |||
| 525 | for (i = 0; i < e820.nr_map; i++) { | 525 | for (i = 0; i < e820.nr_map; i++) { |
| 526 | struct e820entry *ei = &e820.map[i]; | 526 | struct e820entry *ei = &e820.map[i]; |
| 527 | u64 final_start, final_end; | 527 | u64 final_start, final_end; |
| @@ -722,319 +722,44 @@ core_initcall(e820_mark_nvs_memory); | |||
| 722 | #endif | 722 | #endif |
| 723 | 723 | ||
| 724 | /* | 724 | /* |
| 725 | * Early reserved memory areas. | 725 | * Find a free area with specified alignment in a specific range. |
| 726 | */ | ||
| 727 | #define MAX_EARLY_RES 32 | ||
| 728 | |||
| 729 | struct early_res { | ||
| 730 | u64 start, end; | ||
| 731 | char name[16]; | ||
| 732 | char overlap_ok; | ||
| 733 | }; | ||
| 734 | static struct early_res early_res[MAX_EARLY_RES] __initdata = { | ||
| 735 | { 0, PAGE_SIZE, "BIOS data page", 1 }, /* BIOS data page */ | ||
| 736 | #if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE) | ||
| 737 | /* | ||
| 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 | ||
| 740 | * trampoline before removing it. (see the GDT stuff) | ||
| 741 | */ | ||
| 742 | { PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE", 1 }, | ||
| 743 | #endif | ||
| 744 | |||
| 745 | {} | ||
| 746 | }; | ||
| 747 | |||
| 748 | static int __init find_overlapped_early(u64 start, u64 end) | ||
| 749 | { | ||
| 750 | int i; | ||
| 751 | struct early_res *r; | ||
| 752 | |||
| 753 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) { | ||
| 754 | r = &early_res[i]; | ||
| 755 | if (end > r->start && start < r->end) | ||
| 756 | break; | ||
| 757 | } | ||
| 758 | |||
| 759 | return i; | ||
| 760 | } | ||
| 761 | |||
| 762 | /* | ||
| 763 | * Drop the i-th range from the early reservation map, | ||
| 764 | * by copying any higher ranges down one over it, and | ||
| 765 | * clearing what had been the last slot. | ||
| 766 | */ | ||
| 767 | static void __init drop_range(int i) | ||
| 768 | { | ||
| 769 | int j; | ||
| 770 | |||
| 771 | for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++) | ||
| 772 | ; | ||
| 773 | |||
| 774 | memmove(&early_res[i], &early_res[i + 1], | ||
| 775 | (j - 1 - i) * sizeof(struct early_res)); | ||
| 776 | |||
| 777 | early_res[j - 1].end = 0; | ||
| 778 | } | ||
| 779 | |||
| 780 | /* | ||
| 781 | * Split any existing ranges that: | ||
| 782 | * 1) are marked 'overlap_ok', and | ||
| 783 | * 2) overlap with the stated range [start, end) | ||
| 784 | * into whatever portion (if any) of the existing range is entirely | ||
| 785 | * below or entirely above the stated range. Drop the portion | ||
| 786 | * of the existing range that overlaps with the stated range, | ||
| 787 | * which will allow the caller of this routine to then add that | ||
| 788 | * stated range without conflicting with any existing range. | ||
| 789 | */ | 726 | */ |
| 790 | static void __init drop_overlaps_that_are_ok(u64 start, u64 end) | 727 | u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align) |
| 791 | { | 728 | { |
| 792 | int i; | 729 | int i; |
| 793 | struct early_res *r; | ||
| 794 | u64 lower_start, lower_end; | ||
| 795 | u64 upper_start, upper_end; | ||
| 796 | char name[16]; | ||
| 797 | 730 | ||
| 798 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) { | 731 | for (i = 0; i < e820.nr_map; i++) { |
| 799 | r = &early_res[i]; | 732 | struct e820entry *ei = &e820.map[i]; |
| 733 | u64 addr; | ||
| 734 | u64 ei_start, ei_last; | ||
| 800 | 735 | ||
| 801 | /* Continue past non-overlapping ranges */ | 736 | if (ei->type != E820_RAM) |
| 802 | if (end <= r->start || start >= r->end) | ||
| 803 | continue; | 737 | continue; |
| 804 | 738 | ||
| 805 | /* | 739 | ei_last = ei->addr + ei->size; |
| 806 | * Leave non-ok overlaps as is; let caller | 740 | ei_start = ei->addr; |
| 807 | * panic "Overlapping early reservations" | 741 | addr = find_early_area(ei_start, ei_last, start, end, |
| 808 | * when it hits this overlap. | 742 | size, align); |
| 809 | */ | ||
| 810 | if (!r->overlap_ok) | ||
| 811 | return; | ||
| 812 | |||
| 813 | /* | ||
| 814 | * We have an ok overlap. We will drop it from the early | ||
| 815 | * reservation map, and add back in any non-overlapping | ||
| 816 | * portions (lower or upper) as separate, overlap_ok, | ||
| 817 | * non-overlapping ranges. | ||
| 818 | */ | ||
| 819 | |||
| 820 | /* 1. Note any non-overlapping (lower or upper) ranges. */ | ||
| 821 | strncpy(name, r->name, sizeof(name) - 1); | ||
| 822 | |||
| 823 | lower_start = lower_end = 0; | ||
| 824 | upper_start = upper_end = 0; | ||
| 825 | if (r->start < start) { | ||
| 826 | lower_start = r->start; | ||
| 827 | lower_end = start; | ||
| 828 | } | ||
| 829 | if (r->end > end) { | ||
| 830 | upper_start = end; | ||
| 831 | upper_end = r->end; | ||
| 832 | } | ||
| 833 | |||
| 834 | /* 2. Drop the original ok overlapping range */ | ||
| 835 | drop_range(i); | ||
| 836 | |||
| 837 | i--; /* resume for-loop on copied down entry */ | ||
| 838 | |||
| 839 | /* 3. Add back in any non-overlapping ranges. */ | ||
| 840 | if (lower_end) | ||
| 841 | reserve_early_overlap_ok(lower_start, lower_end, name); | ||
| 842 | if (upper_end) | ||
| 843 | reserve_early_overlap_ok(upper_start, upper_end, name); | ||
| 844 | } | ||
| 845 | } | ||
| 846 | |||
| 847 | static void __init __reserve_early(u64 start, u64 end, char *name, | ||
| 848 | int overlap_ok) | ||
| 849 | { | ||
| 850 | int i; | ||
| 851 | struct early_res *r; | ||
| 852 | |||
| 853 | i = find_overlapped_early(start, end); | ||
| 854 | if (i >= MAX_EARLY_RES) | ||
| 855 | panic("Too many early reservations"); | ||
| 856 | r = &early_res[i]; | ||
| 857 | if (r->end) | ||
| 858 | panic("Overlapping early reservations " | ||
| 859 | "%llx-%llx %s to %llx-%llx %s\n", | ||
| 860 | start, end - 1, name?name:"", r->start, | ||
| 861 | r->end - 1, r->name); | ||
| 862 | r->start = start; | ||
| 863 | r->end = end; | ||
| 864 | r->overlap_ok = overlap_ok; | ||
| 865 | if (name) | ||
| 866 | strncpy(r->name, name, sizeof(r->name) - 1); | ||
| 867 | } | ||
| 868 | |||
| 869 | /* | ||
| 870 | * A few early reservtations come here. | ||
| 871 | * | ||
| 872 | * The 'overlap_ok' in the name of this routine does -not- mean it | ||
| 873 | * is ok for these reservations to overlap an earlier reservation. | ||
| 874 | * Rather it means that it is ok for subsequent reservations to | ||
| 875 | * overlap this one. | ||
| 876 | * | ||
| 877 | * Use this entry point to reserve early ranges when you are doing | ||
| 878 | * so out of "Paranoia", reserving perhaps more memory than you need, | ||
| 879 | * just in case, and don't mind a subsequent overlapping reservation | ||
| 880 | * that is known to be needed. | ||
| 881 | * | ||
| 882 | * The drop_overlaps_that_are_ok() call here isn't really needed. | ||
| 883 | * It would be needed if we had two colliding 'overlap_ok' | ||
| 884 | * reservations, so that the second such would not panic on the | ||
| 885 | * overlap with the first. We don't have any such as of this | ||
| 886 | * writing, but might as well tolerate such if it happens in | ||
| 887 | * the future. | ||
| 888 | */ | ||
| 889 | void __init reserve_early_overlap_ok(u64 start, u64 end, char *name) | ||
| 890 | { | ||
| 891 | drop_overlaps_that_are_ok(start, end); | ||
| 892 | __reserve_early(start, end, name, 1); | ||
| 893 | } | ||
| 894 | |||
| 895 | /* | ||
| 896 | * Most early reservations come here. | ||
| 897 | * | ||
| 898 | * We first have drop_overlaps_that_are_ok() drop any pre-existing | ||
| 899 | * 'overlap_ok' ranges, so that we can then reserve this memory | ||
| 900 | * range without risk of panic'ing on an overlapping overlap_ok | ||
| 901 | * early reservation. | ||
| 902 | */ | ||
| 903 | void __init reserve_early(u64 start, u64 end, char *name) | ||
| 904 | { | ||
| 905 | if (start >= end) | ||
| 906 | return; | ||
| 907 | |||
| 908 | drop_overlaps_that_are_ok(start, end); | ||
| 909 | __reserve_early(start, end, name, 0); | ||
| 910 | } | ||
| 911 | |||
| 912 | void __init free_early(u64 start, u64 end) | ||
| 913 | { | ||
| 914 | struct early_res *r; | ||
| 915 | int i; | ||
| 916 | |||
| 917 | i = find_overlapped_early(start, end); | ||
| 918 | r = &early_res[i]; | ||
| 919 | if (i >= MAX_EARLY_RES || r->end != end || r->start != start) | ||
| 920 | panic("free_early on not reserved area: %llx-%llx!", | ||
| 921 | start, end - 1); | ||
| 922 | |||
| 923 | drop_range(i); | ||
| 924 | } | ||
| 925 | |||
| 926 | void __init early_res_to_bootmem(u64 start, u64 end) | ||
| 927 | { | ||
| 928 | int i, count; | ||
| 929 | u64 final_start, final_end; | ||
| 930 | |||
| 931 | count = 0; | ||
| 932 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) | ||
| 933 | count++; | ||
| 934 | |||
| 935 | printk(KERN_INFO "(%d early reservations) ==> bootmem [%010llx - %010llx]\n", | ||
| 936 | count, start, end); | ||
| 937 | for (i = 0; i < count; i++) { | ||
| 938 | struct early_res *r = &early_res[i]; | ||
| 939 | printk(KERN_INFO " #%d [%010llx - %010llx] %16s", i, | ||
| 940 | r->start, r->end, r->name); | ||
| 941 | final_start = max(start, r->start); | ||
| 942 | final_end = min(end, r->end); | ||
| 943 | if (final_start >= final_end) { | ||
| 944 | printk(KERN_CONT "\n"); | ||
| 945 | continue; | ||
| 946 | } | ||
| 947 | printk(KERN_CONT " ==> [%010llx - %010llx]\n", | ||
| 948 | final_start, final_end); | ||
| 949 | reserve_bootmem_generic(final_start, final_end - final_start, | ||
| 950 | BOOTMEM_DEFAULT); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | 743 | ||
| 954 | /* Check for already reserved areas */ | 744 | if (addr != -1ULL) |
| 955 | static inline int __init bad_addr(u64 *addrp, u64 size, u64 align) | 745 | return addr; |
| 956 | { | ||
| 957 | int i; | ||
| 958 | u64 addr = *addrp; | ||
| 959 | int changed = 0; | ||
| 960 | struct early_res *r; | ||
| 961 | again: | ||
| 962 | i = find_overlapped_early(addr, addr + size); | ||
| 963 | r = &early_res[i]; | ||
| 964 | if (i < MAX_EARLY_RES && r->end) { | ||
| 965 | *addrp = addr = round_up(r->end, align); | ||
| 966 | changed = 1; | ||
| 967 | goto again; | ||
| 968 | } | 746 | } |
| 969 | return changed; | 747 | return -1ULL; |
| 970 | } | 748 | } |
| 971 | 749 | ||
| 972 | /* Check for already reserved areas */ | 750 | u64 __init find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align) |
| 973 | static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align) | ||
| 974 | { | 751 | { |
| 975 | int i; | 752 | return find_e820_area(start, end, size, align); |
| 976 | u64 addr = *addrp, last; | ||
| 977 | u64 size = *sizep; | ||
| 978 | int changed = 0; | ||
| 979 | again: | ||
| 980 | last = addr + size; | ||
| 981 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) { | ||
| 982 | struct early_res *r = &early_res[i]; | ||
| 983 | if (last > r->start && addr < r->start) { | ||
| 984 | size = r->start - addr; | ||
| 985 | changed = 1; | ||
| 986 | goto again; | ||
| 987 | } | ||
| 988 | if (last > r->end && addr < r->end) { | ||
| 989 | addr = round_up(r->end, align); | ||
| 990 | size = last - addr; | ||
| 991 | changed = 1; | ||
| 992 | goto again; | ||
| 993 | } | ||
| 994 | if (last <= r->end && addr >= r->start) { | ||
| 995 | (*sizep)++; | ||
| 996 | return 0; | ||
| 997 | } | ||
| 998 | } | ||
| 999 | if (changed) { | ||
| 1000 | *addrp = addr; | ||
| 1001 | *sizep = size; | ||
| 1002 | } | ||
| 1003 | return changed; | ||
| 1004 | } | 753 | } |
| 1005 | 754 | ||
| 1006 | /* | 755 | u64 __init get_max_mapped(void) |
| 1007 | * Find a free area with specified alignment in a specific range. | ||
| 1008 | */ | ||
| 1009 | u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align) | ||
| 1010 | { | 756 | { |
| 1011 | int i; | 757 | u64 end = max_pfn_mapped; |
| 1012 | 758 | ||
| 1013 | for (i = 0; i < e820.nr_map; i++) { | 759 | end <<= PAGE_SHIFT; |
| 1014 | struct e820entry *ei = &e820.map[i]; | ||
| 1015 | u64 addr, last; | ||
| 1016 | u64 ei_last; | ||
| 1017 | 760 | ||
| 1018 | if (ei->type != E820_RAM) | 761 | return end; |
| 1019 | continue; | ||
| 1020 | addr = round_up(ei->addr, align); | ||
| 1021 | ei_last = ei->addr + ei->size; | ||
| 1022 | if (addr < start) | ||
| 1023 | addr = round_up(start, align); | ||
| 1024 | if (addr >= ei_last) | ||
| 1025 | continue; | ||
| 1026 | while (bad_addr(&addr, size, align) && addr+size <= ei_last) | ||
| 1027 | ; | ||
| 1028 | last = addr + size; | ||
| 1029 | if (last > ei_last) | ||
| 1030 | continue; | ||
| 1031 | if (last > end) | ||
| 1032 | continue; | ||
| 1033 | return addr; | ||
| 1034 | } | ||
| 1035 | return -1ULL; | ||
| 1036 | } | 762 | } |
| 1037 | |||
| 1038 | /* | 763 | /* |
| 1039 | * Find next free range after *start | 764 | * Find next free range after *start |
| 1040 | */ | 765 | */ |
| @@ -1044,25 +769,19 @@ u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align) | |||
| 1044 | 769 | ||
| 1045 | for (i = 0; i < e820.nr_map; i++) { | 770 | for (i = 0; i < e820.nr_map; i++) { |
| 1046 | struct e820entry *ei = &e820.map[i]; | 771 | struct e820entry *ei = &e820.map[i]; |
| 1047 | u64 addr, last; | 772 | u64 addr; |
| 1048 | u64 ei_last; | 773 | u64 ei_start, ei_last; |
| 1049 | 774 | ||
| 1050 | if (ei->type != E820_RAM) | 775 | if (ei->type != E820_RAM) |
| 1051 | continue; | 776 | continue; |
| 1052 | addr = round_up(ei->addr, align); | 777 | |
| 1053 | ei_last = ei->addr + ei->size; | 778 | ei_last = ei->addr + ei->size; |
| 1054 | if (addr < start) | 779 | ei_start = ei->addr; |
| 1055 | addr = round_up(start, align); | 780 | addr = find_early_area_size(ei_start, ei_last, start, |
| 1056 | if (addr >= ei_last) | 781 | sizep, align); |
| 1057 | continue; | 782 | |
| 1058 | *sizep = ei_last - addr; | 783 | if (addr != -1ULL) |
| 1059 | while (bad_addr_size(&addr, sizep, align) && | 784 | return addr; |
| 1060 | addr + *sizep <= ei_last) | ||
| 1061 | ; | ||
| 1062 | last = addr + *sizep; | ||
| 1063 | if (last > ei_last) | ||
| 1064 | continue; | ||
| 1065 | return addr; | ||
| 1066 | } | 785 | } |
| 1067 | 786 | ||
| 1068 | return -1ULL; | 787 | return -1ULL; |
| @@ -1421,6 +1140,8 @@ void __init e820_reserve_resources_late(void) | |||
| 1421 | end = MAX_RESOURCE_SIZE; | 1140 | end = MAX_RESOURCE_SIZE; |
| 1422 | if (start >= end) | 1141 | if (start >= end) |
| 1423 | continue; | 1142 | continue; |
| 1143 | printk(KERN_DEBUG "reserve RAM buffer: %016llx - %016llx ", | ||
| 1144 | start, end); | ||
| 1424 | reserve_region_with_split(&iomem_resource, start, end, | 1145 | reserve_region_with_split(&iomem_resource, start, end, |
| 1425 | "RAM buffer"); | 1146 | "RAM buffer"); |
| 1426 | } | 1147 | } |
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index cdcfb122f256..c2fa9b8b497e 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c | |||
| @@ -362,7 +362,7 @@ void __init efi_init(void) | |||
| 362 | printk(KERN_ERR PFX "Could not map the firmware vendor!\n"); | 362 | printk(KERN_ERR PFX "Could not map the firmware vendor!\n"); |
| 363 | early_iounmap(tmp, 2); | 363 | early_iounmap(tmp, 2); |
| 364 | 364 | ||
| 365 | printk(KERN_INFO "EFI v%u.%.02u by %s \n", | 365 | printk(KERN_INFO "EFI v%u.%.02u by %s\n", |
| 366 | efi.systab->hdr.revision >> 16, | 366 | efi.systab->hdr.revision >> 16, |
| 367 | efi.systab->hdr.revision & 0xffff, vendor); | 367 | efi.systab->hdr.revision & 0xffff, vendor); |
| 368 | 368 | ||
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 309689245431..cd37469b54ee 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
| @@ -30,14 +30,32 @@ | |||
| 30 | 30 | ||
| 31 | #ifdef CONFIG_DYNAMIC_FTRACE | 31 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 32 | 32 | ||
| 33 | /* | ||
| 34 | * modifying_code is set to notify NMIs that they need to use | ||
| 35 | * memory barriers when entering or exiting. But we don't want | ||
| 36 | * to burden NMIs with unnecessary memory barriers when code | ||
| 37 | * modification is not being done (which is most of the time). | ||
| 38 | * | ||
| 39 | * A mutex is already held when ftrace_arch_code_modify_prepare | ||
| 40 | * and post_process are called. No locks need to be taken here. | ||
| 41 | * | ||
| 42 | * Stop machine will make sure currently running NMIs are done | ||
| 43 | * and new NMIs will see the updated variable before we need | ||
| 44 | * to worry about NMIs doing memory barriers. | ||
| 45 | */ | ||
| 46 | static int modifying_code __read_mostly; | ||
| 47 | static DEFINE_PER_CPU(int, save_modifying_code); | ||
| 48 | |||
| 33 | int ftrace_arch_code_modify_prepare(void) | 49 | int ftrace_arch_code_modify_prepare(void) |
| 34 | { | 50 | { |
| 35 | set_kernel_text_rw(); | 51 | set_kernel_text_rw(); |
| 52 | modifying_code = 1; | ||
| 36 | return 0; | 53 | return 0; |
| 37 | } | 54 | } |
| 38 | 55 | ||
| 39 | int ftrace_arch_code_modify_post_process(void) | 56 | int ftrace_arch_code_modify_post_process(void) |
| 40 | { | 57 | { |
| 58 | modifying_code = 0; | ||
| 41 | set_kernel_text_ro(); | 59 | set_kernel_text_ro(); |
| 42 | return 0; | 60 | return 0; |
| 43 | } | 61 | } |
| @@ -149,6 +167,11 @@ static void ftrace_mod_code(void) | |||
| 149 | 167 | ||
| 150 | void ftrace_nmi_enter(void) | 168 | void ftrace_nmi_enter(void) |
| 151 | { | 169 | { |
| 170 | __get_cpu_var(save_modifying_code) = modifying_code; | ||
| 171 | |||
| 172 | if (!__get_cpu_var(save_modifying_code)) | ||
| 173 | return; | ||
| 174 | |||
| 152 | if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) { | 175 | if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) { |
| 153 | smp_rmb(); | 176 | smp_rmb(); |
| 154 | ftrace_mod_code(); | 177 | ftrace_mod_code(); |
| @@ -160,6 +183,9 @@ void ftrace_nmi_enter(void) | |||
| 160 | 183 | ||
| 161 | void ftrace_nmi_exit(void) | 184 | void ftrace_nmi_exit(void) |
| 162 | { | 185 | { |
| 186 | if (!__get_cpu_var(save_modifying_code)) | ||
| 187 | return; | ||
| 188 | |||
| 163 | /* Finish all executions before clearing nmi_running */ | 189 | /* Finish all executions before clearing nmi_running */ |
| 164 | smp_mb(); | 190 | smp_mb(); |
| 165 | atomic_dec(&nmi_running); | 191 | atomic_dec(&nmi_running); |
| @@ -484,13 +510,3 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | |||
| 484 | } | 510 | } |
| 485 | } | 511 | } |
| 486 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 512 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
| 487 | |||
| 488 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
| 489 | |||
| 490 | extern unsigned long *sys_call_table; | ||
| 491 | |||
| 492 | unsigned long __init arch_syscall_addr(int nr) | ||
| 493 | { | ||
| 494 | return (unsigned long)(&sys_call_table)[nr]; | ||
| 495 | } | ||
| 496 | #endif | ||
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 5051b94c9069..adedeef1dedc 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
| @@ -29,6 +29,16 @@ static void __init i386_default_early_setup(void) | |||
| 29 | 29 | ||
| 30 | void __init i386_start_kernel(void) | 30 | void __init i386_start_kernel(void) |
| 31 | { | 31 | { |
| 32 | #ifdef CONFIG_X86_TRAMPOLINE | ||
| 33 | /* | ||
| 34 | * But first pinch a few for the stack/trampoline stuff | ||
| 35 | * FIXME: Don't need the extra page at 4K, but need to fix | ||
| 36 | * trampoline before removing it. (see the GDT stuff) | ||
| 37 | */ | ||
| 38 | reserve_early_overlap_ok(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, | ||
| 39 | "EX TRAMPOLINE"); | ||
| 40 | #endif | ||
| 41 | |||
| 32 | reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); | 42 | reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); |
| 33 | 43 | ||
| 34 | #ifdef CONFIG_BLK_DEV_INITRD | 44 | #ifdef CONFIG_BLK_DEV_INITRD |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 7fd318bac59c..37c3d4b17d85 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
| @@ -442,8 +442,8 @@ is386: movl $2,%ecx # set MP | |||
| 442 | */ | 442 | */ |
| 443 | cmpb $0,ready | 443 | cmpb $0,ready |
| 444 | jne 1f | 444 | jne 1f |
| 445 | movl $per_cpu__gdt_page,%eax | 445 | movl $gdt_page,%eax |
| 446 | movl $per_cpu__stack_canary,%ecx | 446 | movl $stack_canary,%ecx |
| 447 | movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) | 447 | movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) |
| 448 | shrl $16, %ecx | 448 | shrl $16, %ecx |
| 449 | movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) | 449 | movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) |
| @@ -706,7 +706,7 @@ idt_descr: | |||
| 706 | .word 0 # 32 bit align gdt_desc.address | 706 | .word 0 # 32 bit align gdt_desc.address |
| 707 | ENTRY(early_gdt_descr) | 707 | ENTRY(early_gdt_descr) |
| 708 | .word GDT_ENTRIES*8-1 | 708 | .word GDT_ENTRIES*8-1 |
| 709 | .long per_cpu__gdt_page /* Overwritten for secondary CPUs */ | 709 | .long gdt_page /* Overwritten for secondary CPUs */ |
| 710 | 710 | ||
| 711 | /* | 711 | /* |
| 712 | * The boot_gdt must mirror the equivalent in setup.S and is | 712 | * The boot_gdt must mirror the equivalent in setup.S and is |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ad80a1c718c6..ee4fa1bfcb33 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
| @@ -266,7 +266,7 @@ static void hpet_resume_device(void) | |||
| 266 | force_hpet_resume(); | 266 | force_hpet_resume(); |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | static void hpet_resume_counter(void) | 269 | static void hpet_resume_counter(struct clocksource *cs) |
| 270 | { | 270 | { |
| 271 | hpet_resume_device(); | 271 | hpet_resume_device(); |
| 272 | hpet_restart_counter(); | 272 | hpet_restart_counter(); |
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index 05d5fec64a94..dca2802c666f 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. |
| @@ -502,8 +486,6 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args) | |||
| 502 | rcu_read_lock(); | 486 | rcu_read_lock(); |
| 503 | 487 | ||
| 504 | bp = per_cpu(bp_per_reg[i], cpu); | 488 | bp = per_cpu(bp_per_reg[i], cpu); |
| 505 | if (bp) | ||
| 506 | rc = NOTIFY_DONE; | ||
| 507 | /* | 489 | /* |
| 508 | * Reset the 'i'th TRAP bit in dr6 to denote completion of | 490 | * Reset the 'i'th TRAP bit in dr6 to denote completion of |
| 509 | * exception handling | 491 | * exception handling |
| @@ -522,7 +504,13 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args) | |||
| 522 | 504 | ||
| 523 | rcu_read_unlock(); | 505 | rcu_read_unlock(); |
| 524 | } | 506 | } |
| 525 | if (dr6 & (~DR_TRAP_BITS)) | 507 | /* |
| 508 | * Further processing in do_debug() is needed for a) user-space | ||
| 509 | * breakpoints (to generate signals) and b) when the system has | ||
| 510 | * taken exception due to multiple causes | ||
| 511 | */ | ||
| 512 | if ((current->thread.debugreg6 & DR_TRAP_BITS) || | ||
| 513 | (dr6 & (~DR_TRAP_BITS))) | ||
| 526 | rc = NOTIFY_DONE; | 514 | rc = NOTIFY_DONE; |
| 527 | 515 | ||
| 528 | set_debugreg(dr7, 7); | 516 | set_debugreg(dr7, 7); |
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index f2f8540a7f3d..c01a2b846d47 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
| @@ -164,6 +164,11 @@ int init_fpu(struct task_struct *tsk) | |||
| 164 | return 0; | 164 | return 0; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | /* | ||
| 168 | * The xstateregs_active() routine is the same as the fpregs_active() routine, | ||
| 169 | * as the "regset->n" for the xstate regset will be updated based on the feature | ||
| 170 | * capabilites supported by the xsave. | ||
| 171 | */ | ||
| 167 | int fpregs_active(struct task_struct *target, const struct user_regset *regset) | 172 | int fpregs_active(struct task_struct *target, const struct user_regset *regset) |
| 168 | { | 173 | { |
| 169 | return tsk_used_math(target) ? regset->n : 0; | 174 | return tsk_used_math(target) ? regset->n : 0; |
| @@ -204,8 +209,6 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, | |||
| 204 | if (ret) | 209 | if (ret) |
| 205 | return ret; | 210 | return ret; |
| 206 | 211 | ||
| 207 | set_stopped_child_used_math(target); | ||
| 208 | |||
| 209 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 212 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
| 210 | &target->thread.xstate->fxsave, 0, -1); | 213 | &target->thread.xstate->fxsave, 0, -1); |
| 211 | 214 | ||
| @@ -224,6 +227,68 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, | |||
| 224 | return ret; | 227 | return ret; |
| 225 | } | 228 | } |
| 226 | 229 | ||
| 230 | int xstateregs_get(struct task_struct *target, const struct user_regset *regset, | ||
| 231 | unsigned int pos, unsigned int count, | ||
| 232 | void *kbuf, void __user *ubuf) | ||
| 233 | { | ||
| 234 | int ret; | ||
| 235 | |||
| 236 | if (!cpu_has_xsave) | ||
| 237 | return -ENODEV; | ||
| 238 | |||
| 239 | ret = init_fpu(target); | ||
| 240 | if (ret) | ||
| 241 | return ret; | ||
| 242 | |||
| 243 | /* | ||
| 244 | * Copy the 48bytes defined by the software first into the xstate | ||
| 245 | * memory layout in the thread struct, so that we can copy the entire | ||
| 246 | * xstateregs to the user using one user_regset_copyout(). | ||
| 247 | */ | ||
| 248 | memcpy(&target->thread.xstate->fxsave.sw_reserved, | ||
| 249 | xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes)); | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Copy the xstate memory layout. | ||
| 253 | */ | ||
| 254 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
| 255 | &target->thread.xstate->xsave, 0, -1); | ||
| 256 | return ret; | ||
| 257 | } | ||
| 258 | |||
| 259 | int xstateregs_set(struct task_struct *target, const struct user_regset *regset, | ||
| 260 | unsigned int pos, unsigned int count, | ||
| 261 | const void *kbuf, const void __user *ubuf) | ||
| 262 | { | ||
| 263 | int ret; | ||
| 264 | struct xsave_hdr_struct *xsave_hdr; | ||
| 265 | |||
| 266 | if (!cpu_has_xsave) | ||
| 267 | return -ENODEV; | ||
| 268 | |||
| 269 | ret = init_fpu(target); | ||
| 270 | if (ret) | ||
| 271 | return ret; | ||
| 272 | |||
| 273 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
| 274 | &target->thread.xstate->xsave, 0, -1); | ||
| 275 | |||
| 276 | /* | ||
| 277 | * mxcsr reserved bits must be masked to zero for security reasons. | ||
| 278 | */ | ||
| 279 | target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; | ||
| 280 | |||
| 281 | xsave_hdr = &target->thread.xstate->xsave.xsave_hdr; | ||
| 282 | |||
| 283 | xsave_hdr->xstate_bv &= pcntxt_mask; | ||
| 284 | /* | ||
| 285 | * These bits must be zero. | ||
| 286 | */ | ||
| 287 | xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; | ||
| 288 | |||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 227 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 292 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
| 228 | 293 | ||
| 229 | /* | 294 | /* |
| @@ -404,8 +469,6 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, | |||
| 404 | if (ret) | 469 | if (ret) |
| 405 | return ret; | 470 | return ret; |
| 406 | 471 | ||
| 407 | set_stopped_child_used_math(target); | ||
| 408 | |||
| 409 | if (!HAVE_HWFP) | 472 | if (!HAVE_HWFP) |
| 410 | return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf); | 473 | return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf); |
| 411 | 474 | ||
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index df89102bef80..8c93a84bb627 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | static int i8259A_auto_eoi; | 34 | static int i8259A_auto_eoi; |
| 35 | DEFINE_SPINLOCK(i8259A_lock); | 35 | DEFINE_RAW_SPINLOCK(i8259A_lock); |
| 36 | static void mask_and_ack_8259A(unsigned int); | 36 | static void mask_and_ack_8259A(unsigned int); |
| 37 | 37 | ||
| 38 | struct irq_chip i8259A_chip = { | 38 | struct irq_chip i8259A_chip = { |
| @@ -68,13 +68,13 @@ void disable_8259A_irq(unsigned int irq) | |||
| 68 | unsigned int mask = 1 << irq; | 68 | unsigned int mask = 1 << irq; |
| 69 | unsigned long flags; | 69 | unsigned long flags; |
| 70 | 70 | ||
| 71 | spin_lock_irqsave(&i8259A_lock, flags); | 71 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 72 | cached_irq_mask |= mask; | 72 | cached_irq_mask |= mask; |
| 73 | if (irq & 8) | 73 | if (irq & 8) |
| 74 | outb(cached_slave_mask, PIC_SLAVE_IMR); | 74 | outb(cached_slave_mask, PIC_SLAVE_IMR); |
| 75 | else | 75 | else |
| 76 | outb(cached_master_mask, PIC_MASTER_IMR); | 76 | outb(cached_master_mask, PIC_MASTER_IMR); |
| 77 | spin_unlock_irqrestore(&i8259A_lock, flags); | 77 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | void enable_8259A_irq(unsigned int irq) | 80 | void enable_8259A_irq(unsigned int irq) |
| @@ -82,13 +82,13 @@ void enable_8259A_irq(unsigned int irq) | |||
| 82 | unsigned int mask = ~(1 << irq); | 82 | unsigned int mask = ~(1 << irq); |
| 83 | unsigned long flags; | 83 | unsigned long flags; |
| 84 | 84 | ||
| 85 | spin_lock_irqsave(&i8259A_lock, flags); | 85 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 86 | cached_irq_mask &= mask; | 86 | cached_irq_mask &= mask; |
| 87 | if (irq & 8) | 87 | if (irq & 8) |
| 88 | outb(cached_slave_mask, PIC_SLAVE_IMR); | 88 | outb(cached_slave_mask, PIC_SLAVE_IMR); |
| 89 | else | 89 | else |
| 90 | outb(cached_master_mask, PIC_MASTER_IMR); | 90 | outb(cached_master_mask, PIC_MASTER_IMR); |
| 91 | spin_unlock_irqrestore(&i8259A_lock, flags); | 91 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | int i8259A_irq_pending(unsigned int irq) | 94 | int i8259A_irq_pending(unsigned int irq) |
| @@ -97,12 +97,12 @@ int i8259A_irq_pending(unsigned int irq) | |||
| 97 | unsigned long flags; | 97 | unsigned long flags; |
| 98 | int ret; | 98 | int ret; |
| 99 | 99 | ||
| 100 | spin_lock_irqsave(&i8259A_lock, flags); | 100 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 101 | if (irq < 8) | 101 | if (irq < 8) |
| 102 | ret = inb(PIC_MASTER_CMD) & mask; | 102 | ret = inb(PIC_MASTER_CMD) & mask; |
| 103 | else | 103 | else |
| 104 | ret = inb(PIC_SLAVE_CMD) & (mask >> 8); | 104 | ret = inb(PIC_SLAVE_CMD) & (mask >> 8); |
| 105 | spin_unlock_irqrestore(&i8259A_lock, flags); | 105 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 106 | 106 | ||
| 107 | return ret; | 107 | return ret; |
| 108 | } | 108 | } |
| @@ -150,7 +150,7 @@ static void mask_and_ack_8259A(unsigned int irq) | |||
| 150 | unsigned int irqmask = 1 << irq; | 150 | unsigned int irqmask = 1 << irq; |
| 151 | unsigned long flags; | 151 | unsigned long flags; |
| 152 | 152 | ||
| 153 | spin_lock_irqsave(&i8259A_lock, flags); | 153 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 154 | /* | 154 | /* |
| 155 | * Lightweight spurious IRQ detection. We do not want | 155 | * Lightweight spurious IRQ detection. We do not want |
| 156 | * to overdo spurious IRQ handling - it's usually a sign | 156 | * to overdo spurious IRQ handling - it's usually a sign |
| @@ -183,7 +183,7 @@ handle_real_irq: | |||
| 183 | outb(cached_master_mask, PIC_MASTER_IMR); | 183 | outb(cached_master_mask, PIC_MASTER_IMR); |
| 184 | outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */ | 184 | outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */ |
| 185 | } | 185 | } |
| 186 | spin_unlock_irqrestore(&i8259A_lock, flags); | 186 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 187 | return; | 187 | return; |
| 188 | 188 | ||
| 189 | spurious_8259A_irq: | 189 | spurious_8259A_irq: |
| @@ -285,24 +285,24 @@ void mask_8259A(void) | |||
| 285 | { | 285 | { |
| 286 | unsigned long flags; | 286 | unsigned long flags; |
| 287 | 287 | ||
| 288 | spin_lock_irqsave(&i8259A_lock, flags); | 288 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 289 | 289 | ||
| 290 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 290 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
| 291 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ | 291 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ |
| 292 | 292 | ||
| 293 | spin_unlock_irqrestore(&i8259A_lock, flags); | 293 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | void unmask_8259A(void) | 296 | void unmask_8259A(void) |
| 297 | { | 297 | { |
| 298 | unsigned long flags; | 298 | unsigned long flags; |
| 299 | 299 | ||
| 300 | spin_lock_irqsave(&i8259A_lock, flags); | 300 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 301 | 301 | ||
| 302 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ | 302 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ |
| 303 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ | 303 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ |
| 304 | 304 | ||
| 305 | spin_unlock_irqrestore(&i8259A_lock, flags); | 305 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | void init_8259A(int auto_eoi) | 308 | void init_8259A(int auto_eoi) |
| @@ -311,7 +311,7 @@ void init_8259A(int auto_eoi) | |||
| 311 | 311 | ||
| 312 | i8259A_auto_eoi = auto_eoi; | 312 | i8259A_auto_eoi = auto_eoi; |
| 313 | 313 | ||
| 314 | spin_lock_irqsave(&i8259A_lock, flags); | 314 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 315 | 315 | ||
| 316 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 316 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
| 317 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ | 317 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ |
| @@ -356,5 +356,5 @@ void init_8259A(int auto_eoi) | |||
| 356 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ | 356 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ |
| 357 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ | 357 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ |
| 358 | 358 | ||
| 359 | spin_unlock_irqrestore(&i8259A_lock, flags); | 359 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 360 | } | 360 | } |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index d5932226614f..fce55d532631 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
| @@ -84,24 +84,7 @@ static struct irqaction irq2 = { | |||
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | DEFINE_PER_CPU(vector_irq_t, vector_irq) = { | 86 | DEFINE_PER_CPU(vector_irq_t, vector_irq) = { |
| 87 | [0 ... IRQ0_VECTOR - 1] = -1, | 87 | [0 ... NR_VECTORS - 1] = -1, |
| 88 | [IRQ0_VECTOR] = 0, | ||
| 89 | [IRQ1_VECTOR] = 1, | ||
| 90 | [IRQ2_VECTOR] = 2, | ||
| 91 | [IRQ3_VECTOR] = 3, | ||
| 92 | [IRQ4_VECTOR] = 4, | ||
| 93 | [IRQ5_VECTOR] = 5, | ||
| 94 | [IRQ6_VECTOR] = 6, | ||
| 95 | [IRQ7_VECTOR] = 7, | ||
| 96 | [IRQ8_VECTOR] = 8, | ||
| 97 | [IRQ9_VECTOR] = 9, | ||
| 98 | [IRQ10_VECTOR] = 10, | ||
| 99 | [IRQ11_VECTOR] = 11, | ||
| 100 | [IRQ12_VECTOR] = 12, | ||
| 101 | [IRQ13_VECTOR] = 13, | ||
| 102 | [IRQ14_VECTOR] = 14, | ||
| 103 | [IRQ15_VECTOR] = 15, | ||
| 104 | [IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1 | ||
| 105 | }; | 88 | }; |
| 106 | 89 | ||
| 107 | int vector_used_by_percpu_irq(unsigned int vector) | 90 | int vector_used_by_percpu_irq(unsigned int vector) |
| @@ -116,6 +99,9 @@ int vector_used_by_percpu_irq(unsigned int vector) | |||
| 116 | return 0; | 99 | return 0; |
| 117 | } | 100 | } |
| 118 | 101 | ||
| 102 | /* Number of legacy interrupts */ | ||
| 103 | int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY; | ||
| 104 | |||
| 119 | void __init init_ISA_irqs(void) | 105 | void __init init_ISA_irqs(void) |
| 120 | { | 106 | { |
| 121 | int i; | 107 | int i; |
| @@ -142,6 +128,19 @@ void __init init_ISA_irqs(void) | |||
| 142 | 128 | ||
| 143 | void __init init_IRQ(void) | 129 | void __init init_IRQ(void) |
| 144 | { | 130 | { |
| 131 | int i; | ||
| 132 | |||
| 133 | /* | ||
| 134 | * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15. | ||
| 135 | * If these IRQ's are handled by legacy interrupt-controllers like PIC, | ||
| 136 | * then this configuration will likely be static after the boot. If | ||
| 137 | * these IRQ's are handled by more mordern controllers like IO-APIC, | ||
| 138 | * then this vector space can be freed and re-used dynamically as the | ||
| 139 | * irq's migrate etc. | ||
| 140 | */ | ||
| 141 | for (i = 0; i < nr_legacy_irqs; i++) | ||
| 142 | per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i; | ||
| 143 | |||
| 145 | x86_init.irqs.intr_init(); | 144 | x86_init.irqs.intr_init(); |
| 146 | } | 145 | } |
| 147 | 146 | ||
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 5b8c7505b3bc..5de9f4a9c3fd 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
| @@ -337,6 +337,9 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p) | |||
| 337 | 337 | ||
| 338 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 338 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
| 339 | { | 339 | { |
| 340 | if (alternatives_text_reserved(p->addr, p->addr)) | ||
| 341 | return -EINVAL; | ||
| 342 | |||
| 340 | if (!can_probe((unsigned long)p->addr)) | 343 | if (!can_probe((unsigned long)p->addr)) |
| 341 | return -EILSEQ; | 344 | return -EILSEQ; |
| 342 | /* insn: must be on special executable page on x86. */ | 345 | /* insn: must be on special executable page on x86. */ |
| @@ -429,7 +432,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | |||
| 429 | static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs, | 432 | static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs, |
| 430 | struct kprobe_ctlblk *kcb) | 433 | struct kprobe_ctlblk *kcb) |
| 431 | { | 434 | { |
| 432 | #if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER) | 435 | #if !defined(CONFIG_PREEMPT) |
| 433 | if (p->ainsn.boostable == 1 && !p->post_handler) { | 436 | if (p->ainsn.boostable == 1 && !p->post_handler) { |
| 434 | /* Boost up -- we can execute copied instructions directly */ | 437 | /* Boost up -- we can execute copied instructions directly */ |
| 435 | reset_current_kprobe(); | 438 | reset_current_kprobe(); |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index ebd193e476ca..85a343e28937 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
| @@ -328,7 +328,7 @@ static int apply_microcode(int cpu) | |||
| 328 | cpu_num, mc_intel->hdr.rev); | 328 | cpu_num, mc_intel->hdr.rev); |
| 329 | return -1; | 329 | return -1; |
| 330 | } | 330 | } |
| 331 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x \n", | 331 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", |
| 332 | cpu_num, val[1], | 332 | cpu_num, val[1], |
| 333 | mc_intel->hdr.date & 0xffff, | 333 | mc_intel->hdr.date & 0xffff, |
| 334 | mc_intel->hdr.date >> 24, | 334 | mc_intel->hdr.date >> 24, |
diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index 712d15fdc416..71825806cd44 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
| 8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
| 9 | #include <linux/dmi.h> | 9 | #include <linux/dmi.h> |
| 10 | #include <linux/range.h> | ||
| 11 | |||
| 10 | #include <asm/pci-direct.h> | 12 | #include <asm/pci-direct.h> |
| 11 | #include <linux/sort.h> | 13 | #include <linux/sort.h> |
| 12 | #include <asm/io.h> | 14 | #include <asm/io.h> |
| @@ -30,11 +32,6 @@ static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = { | |||
| 30 | { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, | 32 | { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, |
| 31 | }; | 33 | }; |
| 32 | 34 | ||
| 33 | struct range { | ||
| 34 | u64 start; | ||
| 35 | u64 end; | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int __cpuinit cmp_range(const void *x1, const void *x2) | 35 | static int __cpuinit cmp_range(const void *x1, const void *x2) |
| 39 | { | 36 | { |
| 40 | const struct range *r1 = x1; | 37 | const struct range *r1 = x1; |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 75e14e21f61a..1aa966c565f9 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
| @@ -65,7 +65,7 @@ int dma_set_mask(struct device *dev, u64 mask) | |||
| 65 | } | 65 | } |
| 66 | EXPORT_SYMBOL(dma_set_mask); | 66 | EXPORT_SYMBOL(dma_set_mask); |
| 67 | 67 | ||
| 68 | #ifdef CONFIG_X86_64 | 68 | #if defined(CONFIG_X86_64) && !defined(CONFIG_NUMA) |
| 69 | static __initdata void *dma32_bootmem_ptr; | 69 | static __initdata void *dma32_bootmem_ptr; |
| 70 | static unsigned long dma32_bootmem_size __initdata = (128ULL<<20); | 70 | static unsigned long dma32_bootmem_size __initdata = (128ULL<<20); |
| 71 | 71 | ||
| @@ -116,14 +116,21 @@ static void __init dma32_free_bootmem(void) | |||
| 116 | dma32_bootmem_ptr = NULL; | 116 | dma32_bootmem_ptr = NULL; |
| 117 | dma32_bootmem_size = 0; | 117 | dma32_bootmem_size = 0; |
| 118 | } | 118 | } |
| 119 | #else | ||
| 120 | void __init dma32_reserve_bootmem(void) | ||
| 121 | { | ||
| 122 | } | ||
| 123 | static void __init dma32_free_bootmem(void) | ||
| 124 | { | ||
| 125 | } | ||
| 126 | |||
| 119 | #endif | 127 | #endif |
| 120 | 128 | ||
| 121 | void __init pci_iommu_alloc(void) | 129 | void __init pci_iommu_alloc(void) |
| 122 | { | 130 | { |
| 123 | #ifdef CONFIG_X86_64 | ||
| 124 | /* free the range so iommu could get some range less than 4G */ | 131 | /* free the range so iommu could get some range less than 4G */ |
| 125 | dma32_free_bootmem(); | 132 | dma32_free_bootmem(); |
| 126 | #endif | 133 | |
| 127 | if (pci_swiotlb_detect()) | 134 | if (pci_swiotlb_detect()) |
| 128 | goto out; | 135 | goto out; |
| 129 | 136 | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index c9b3522b6b46..02d678065d7d 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -92,6 +92,13 @@ void exit_thread(void) | |||
| 92 | } | 92 | } |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void show_regs(struct pt_regs *regs) | ||
| 96 | { | ||
| 97 | show_registers(regs); | ||
| 98 | show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs), | ||
| 99 | regs->bp); | ||
| 100 | } | ||
| 101 | |||
| 95 | void show_regs_common(void) | 102 | void show_regs_common(void) |
| 96 | { | 103 | { |
| 97 | const char *board, *product; | 104 | const char *board, *product; |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 37ad1e046aae..f6c62667e30c 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -174,12 +174,6 @@ void __show_regs(struct pt_regs *regs, int all) | |||
| 174 | d6, d7); | 174 | d6, d7); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | void show_regs(struct pt_regs *regs) | ||
| 178 | { | ||
| 179 | show_registers(regs); | ||
| 180 | show_trace(NULL, regs, ®s->sp, regs->bp); | ||
| 181 | } | ||
| 182 | |||
| 183 | void release_thread(struct task_struct *dead_task) | 177 | void release_thread(struct task_struct *dead_task) |
| 184 | { | 178 | { |
| 185 | BUG_ON(dead_task->mm); | 179 | BUG_ON(dead_task->mm); |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 41a26a82470a..dc9690b4c4cc 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -211,12 +211,6 @@ void __show_regs(struct pt_regs *regs, int all) | |||
| 211 | printk(KERN_DEFAULT "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) | ||
| 215 | { | ||
| 216 | show_registers(regs); | ||
| 217 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); | ||
| 218 | } | ||
| 219 | |||
| 220 | void release_thread(struct task_struct *dead_task) | 214 | void release_thread(struct task_struct *dead_task) |
| 221 | { | 215 | { |
| 222 | if (dead_task->mm) { | 216 | if (dead_task->mm) { |
| @@ -527,6 +521,7 @@ void set_personality_ia32(void) | |||
| 527 | 521 | ||
| 528 | /* Make sure to be in 32bit mode */ | 522 | /* Make sure to be in 32bit mode */ |
| 529 | set_thread_flag(TIF_IA32); | 523 | set_thread_flag(TIF_IA32); |
| 524 | current->personality |= force_personality32; | ||
| 530 | 525 | ||
| 531 | /* Prepare the first "return" to user space */ | 526 | /* Prepare the first "return" to user space */ |
| 532 | current_thread_info()->status |= TS_COMPAT; | 527 | current_thread_info()->status |= TS_COMPAT; |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 017d937639fe..2d96aab82a48 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -48,6 +48,7 @@ enum x86_regset { | |||
| 48 | REGSET_FP, | 48 | REGSET_FP, |
| 49 | REGSET_XFP, | 49 | REGSET_XFP, |
| 50 | REGSET_IOPERM64 = REGSET_XFP, | 50 | REGSET_IOPERM64 = REGSET_XFP, |
| 51 | REGSET_XSTATE, | ||
| 51 | REGSET_TLS, | 52 | REGSET_TLS, |
| 52 | REGSET_IOPERM32, | 53 | REGSET_IOPERM32, |
| 53 | }; | 54 | }; |
| @@ -140,30 +141,6 @@ static const int arg_offs_table[] = { | |||
| 140 | #endif | 141 | #endif |
| 141 | }; | 142 | }; |
| 142 | 143 | ||
| 143 | /** | ||
| 144 | * regs_get_argument_nth() - get Nth argument at function call | ||
| 145 | * @regs: pt_regs which contains registers at function entry. | ||
| 146 | * @n: argument number. | ||
| 147 | * | ||
| 148 | * regs_get_argument_nth() returns @n th argument of a function call. | ||
| 149 | * Since usually the kernel stack will be changed right after function entry, | ||
| 150 | * you must use this at function entry. If the @n th entry is NOT in the | ||
| 151 | * kernel stack or pt_regs, this returns 0. | ||
| 152 | */ | ||
| 153 | unsigned long regs_get_argument_nth(struct pt_regs *regs, unsigned int n) | ||
| 154 | { | ||
| 155 | if (n < ARRAY_SIZE(arg_offs_table)) | ||
| 156 | return *(unsigned long *)((char *)regs + arg_offs_table[n]); | ||
| 157 | else { | ||
| 158 | /* | ||
| 159 | * The typical case: arg n is on the stack. | ||
| 160 | * (Note: stack[0] = return address, so skip it) | ||
| 161 | */ | ||
| 162 | n -= ARRAY_SIZE(arg_offs_table); | ||
| 163 | return regs_get_kernel_stack_nth(regs, 1 + n); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | /* | 144 | /* |
| 168 | * does not yet catch signals sent when the child dies. | 145 | * does not yet catch signals sent when the child dies. |
| 169 | * in exit.c or in signal.c. | 146 | * in exit.c or in signal.c. |
| @@ -702,7 +679,7 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) | |||
| 702 | } else if (n == 6) { | 679 | } else if (n == 6) { |
| 703 | val = thread->debugreg6; | 680 | val = thread->debugreg6; |
| 704 | } else if (n == 7) { | 681 | } else if (n == 7) { |
| 705 | val = ptrace_get_dr7(thread->ptrace_bps); | 682 | val = thread->ptrace_dr7; |
| 706 | } | 683 | } |
| 707 | return val; | 684 | return val; |
| 708 | } | 685 | } |
| @@ -778,8 +755,11 @@ int ptrace_set_debugreg(struct task_struct *tsk, int n, unsigned long val) | |||
| 778 | return rc; | 755 | return rc; |
| 779 | } | 756 | } |
| 780 | /* All that's left is DR7 */ | 757 | /* All that's left is DR7 */ |
| 781 | if (n == 7) | 758 | if (n == 7) { |
| 782 | rc = ptrace_write_dr7(tsk, val); | 759 | rc = ptrace_write_dr7(tsk, val); |
| 760 | if (!rc) | ||
| 761 | thread->ptrace_dr7 = val; | ||
| 762 | } | ||
| 783 | 763 | ||
| 784 | ret_path: | 764 | ret_path: |
| 785 | return rc; | 765 | return rc; |
| @@ -1584,7 +1564,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
| 1584 | 1564 | ||
| 1585 | #ifdef CONFIG_X86_64 | 1565 | #ifdef CONFIG_X86_64 |
| 1586 | 1566 | ||
| 1587 | static const struct user_regset x86_64_regsets[] = { | 1567 | static struct user_regset x86_64_regsets[] __read_mostly = { |
| 1588 | [REGSET_GENERAL] = { | 1568 | [REGSET_GENERAL] = { |
| 1589 | .core_note_type = NT_PRSTATUS, | 1569 | .core_note_type = NT_PRSTATUS, |
| 1590 | .n = sizeof(struct user_regs_struct) / sizeof(long), | 1570 | .n = sizeof(struct user_regs_struct) / sizeof(long), |
| @@ -1597,6 +1577,12 @@ static const struct user_regset x86_64_regsets[] = { | |||
| 1597 | .size = sizeof(long), .align = sizeof(long), | 1577 | .size = sizeof(long), .align = sizeof(long), |
| 1598 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set | 1578 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set |
| 1599 | }, | 1579 | }, |
| 1580 | [REGSET_XSTATE] = { | ||
| 1581 | .core_note_type = NT_X86_XSTATE, | ||
| 1582 | .size = sizeof(u64), .align = sizeof(u64), | ||
| 1583 | .active = xstateregs_active, .get = xstateregs_get, | ||
| 1584 | .set = xstateregs_set | ||
| 1585 | }, | ||
| 1600 | [REGSET_IOPERM64] = { | 1586 | [REGSET_IOPERM64] = { |
| 1601 | .core_note_type = NT_386_IOPERM, | 1587 | .core_note_type = NT_386_IOPERM, |
| 1602 | .n = IO_BITMAP_LONGS, | 1588 | .n = IO_BITMAP_LONGS, |
| @@ -1622,7 +1608,7 @@ static const struct user_regset_view user_x86_64_view = { | |||
| 1622 | #endif /* CONFIG_X86_64 */ | 1608 | #endif /* CONFIG_X86_64 */ |
| 1623 | 1609 | ||
| 1624 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 1610 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
| 1625 | static const struct user_regset x86_32_regsets[] = { | 1611 | static struct user_regset x86_32_regsets[] __read_mostly = { |
| 1626 | [REGSET_GENERAL] = { | 1612 | [REGSET_GENERAL] = { |
| 1627 | .core_note_type = NT_PRSTATUS, | 1613 | .core_note_type = NT_PRSTATUS, |
| 1628 | .n = sizeof(struct user_regs_struct32) / sizeof(u32), | 1614 | .n = sizeof(struct user_regs_struct32) / sizeof(u32), |
| @@ -1641,6 +1627,12 @@ static const struct user_regset x86_32_regsets[] = { | |||
| 1641 | .size = sizeof(u32), .align = sizeof(u32), | 1627 | .size = sizeof(u32), .align = sizeof(u32), |
| 1642 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set | 1628 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set |
| 1643 | }, | 1629 | }, |
| 1630 | [REGSET_XSTATE] = { | ||
| 1631 | .core_note_type = NT_X86_XSTATE, | ||
| 1632 | .size = sizeof(u64), .align = sizeof(u64), | ||
| 1633 | .active = xstateregs_active, .get = xstateregs_get, | ||
| 1634 | .set = xstateregs_set | ||
| 1635 | }, | ||
| 1644 | [REGSET_TLS] = { | 1636 | [REGSET_TLS] = { |
| 1645 | .core_note_type = NT_386_TLS, | 1637 | .core_note_type = NT_386_TLS, |
| 1646 | .n = GDT_ENTRY_TLS_ENTRIES, .bias = GDT_ENTRY_TLS_MIN, | 1638 | .n = GDT_ENTRY_TLS_ENTRIES, .bias = GDT_ENTRY_TLS_MIN, |
| @@ -1663,6 +1655,23 @@ static const struct user_regset_view user_x86_32_view = { | |||
| 1663 | }; | 1655 | }; |
| 1664 | #endif | 1656 | #endif |
| 1665 | 1657 | ||
| 1658 | /* | ||
| 1659 | * This represents bytes 464..511 in the memory layout exported through | ||
| 1660 | * the REGSET_XSTATE interface. | ||
| 1661 | */ | ||
| 1662 | u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; | ||
| 1663 | |||
| 1664 | void update_regset_xstate_info(unsigned int size, u64 xstate_mask) | ||
| 1665 | { | ||
| 1666 | #ifdef CONFIG_X86_64 | ||
| 1667 | x86_64_regsets[REGSET_XSTATE].n = size / sizeof(u64); | ||
| 1668 | #endif | ||
| 1669 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | ||
| 1670 | x86_32_regsets[REGSET_XSTATE].n = size / sizeof(u64); | ||
| 1671 | #endif | ||
| 1672 | xstate_fx_sw_bytes[USER_XSTATE_XCR0_WORD] = xstate_mask; | ||
| 1673 | } | ||
| 1674 | |||
| 1666 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | 1675 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) |
| 1667 | { | 1676 | { |
| 1668 | #ifdef CONFIG_IA32_EMULATION | 1677 | #ifdef CONFIG_IA32_EMULATION |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 704bddcdf64d..8e1aac86b50c 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
| @@ -461,6 +461,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { | |||
| 461 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"), | 461 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"), |
| 462 | }, | 462 | }, |
| 463 | }, | 463 | }, |
| 464 | { /* Handle problems with rebooting on the iMac9,1. */ | ||
| 465 | .callback = set_pci_reboot, | ||
| 466 | .ident = "Apple iMac9,1", | ||
| 467 | .matches = { | ||
| 468 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
| 469 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"), | ||
| 470 | }, | ||
| 471 | }, | ||
| 464 | { } | 472 | { } |
| 465 | }; | 473 | }; |
| 466 | 474 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 5d9e40c58628..5d7ba1a449bd 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -121,7 +121,9 @@ | |||
| 121 | unsigned long max_low_pfn_mapped; | 121 | unsigned long max_low_pfn_mapped; |
| 122 | unsigned long max_pfn_mapped; | 122 | unsigned long max_pfn_mapped; |
| 123 | 123 | ||
| 124 | #ifdef CONFIG_DMI | ||
| 124 | RESERVE_BRK(dmi_alloc, 65536); | 125 | RESERVE_BRK(dmi_alloc, 65536); |
| 126 | #endif | ||
| 125 | 127 | ||
| 126 | unsigned int boot_cpu_id __read_mostly; | 128 | unsigned int boot_cpu_id __read_mostly; |
| 127 | 129 | ||
| @@ -667,6 +669,23 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | |||
| 667 | {} | 669 | {} |
| 668 | }; | 670 | }; |
| 669 | 671 | ||
| 672 | static void __init trim_bios_range(void) | ||
| 673 | { | ||
| 674 | /* | ||
| 675 | * A special case is the first 4Kb of memory; | ||
| 676 | * This is a BIOS owned area, not kernel ram, but generally | ||
| 677 | * not listed as such in the E820 table. | ||
| 678 | */ | ||
| 679 | e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED); | ||
| 680 | /* | ||
| 681 | * special case: Some BIOSen report the PC BIOS | ||
| 682 | * area (640->1Mb) as ram even though it is not. | ||
| 683 | * take them out. | ||
| 684 | */ | ||
| 685 | e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); | ||
| 686 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
| 687 | } | ||
| 688 | |||
| 670 | /* | 689 | /* |
| 671 | * Determine if we were loaded by an EFI loader. If so, then we have also been | 690 | * Determine if we were loaded by an EFI loader. If so, then we have also been |
| 672 | * passed the efi memmap, systab, etc., so we should use these data structures | 691 | * passed the efi memmap, systab, etc., so we should use these data structures |
| @@ -830,7 +849,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 830 | insert_resource(&iomem_resource, &data_resource); | 849 | insert_resource(&iomem_resource, &data_resource); |
| 831 | insert_resource(&iomem_resource, &bss_resource); | 850 | insert_resource(&iomem_resource, &bss_resource); |
| 832 | 851 | ||
| 833 | 852 | trim_bios_range(); | |
| 834 | #ifdef CONFIG_X86_32 | 853 | #ifdef CONFIG_X86_32 |
| 835 | if (ppro_with_ram_bug()) { | 854 | if (ppro_with_ram_bug()) { |
| 836 | e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM, | 855 | e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM, |
| @@ -950,15 +969,11 @@ void __init setup_arch(char **cmdline_p) | |||
| 950 | #endif | 969 | #endif |
| 951 | 970 | ||
| 952 | initmem_init(0, max_pfn, acpi, k8); | 971 | initmem_init(0, max_pfn, acpi, k8); |
| 972 | #ifndef CONFIG_NO_BOOTMEM | ||
| 973 | early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT); | ||
| 974 | #endif | ||
| 953 | 975 | ||
| 954 | #ifdef CONFIG_X86_64 | ||
| 955 | /* | ||
| 956 | * dma32_reserve_bootmem() allocates bootmem which may conflict | ||
| 957 | * with the crashkernel command line, so do that after | ||
| 958 | * reserve_crashkernel() | ||
| 959 | */ | ||
| 960 | dma32_reserve_bootmem(); | 976 | dma32_reserve_bootmem(); |
| 961 | #endif | ||
| 962 | 977 | ||
| 963 | reserve_ibft_region(); | 978 | reserve_ibft_region(); |
| 964 | 979 | ||
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 35abcb8b00e9..ef6370b00e70 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
| @@ -137,7 +137,13 @@ static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) | |||
| 137 | 137 | ||
| 138 | static void __init pcpu_fc_free(void *ptr, size_t size) | 138 | static void __init pcpu_fc_free(void *ptr, size_t size) |
| 139 | { | 139 | { |
| 140 | #ifdef CONFIG_NO_BOOTMEM | ||
| 141 | u64 start = __pa(ptr); | ||
| 142 | u64 end = start + size; | ||
| 143 | free_early_partial(start, end); | ||
| 144 | #else | ||
| 140 | free_bootmem(__pa(ptr), size); | 145 | free_bootmem(__pa(ptr), size); |
| 146 | #endif | ||
| 141 | } | 147 | } |
| 142 | 148 | ||
| 143 | static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) | 149 | static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index b4e870cbdc60..a435c76d714e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -241,6 +241,11 @@ static void __cpuinit smp_callin(void) | |||
| 241 | map_cpu_to_logical_apicid(); | 241 | map_cpu_to_logical_apicid(); |
| 242 | 242 | ||
| 243 | notify_cpu_starting(cpuid); | 243 | notify_cpu_starting(cpuid); |
| 244 | |||
| 245 | /* | ||
| 246 | * Need to setup vector mappings before we enable interrupts. | ||
| 247 | */ | ||
| 248 | __setup_vector_irq(smp_processor_id()); | ||
| 244 | /* | 249 | /* |
| 245 | * Get our bogomips. | 250 | * Get our bogomips. |
| 246 | * | 251 | * |
| @@ -315,11 +320,11 @@ notrace static void __cpuinit start_secondary(void *unused) | |||
| 315 | */ | 320 | */ |
| 316 | ipi_call_lock(); | 321 | ipi_call_lock(); |
| 317 | lock_vector_lock(); | 322 | lock_vector_lock(); |
| 318 | __setup_vector_irq(smp_processor_id()); | ||
| 319 | set_cpu_online(smp_processor_id(), true); | 323 | set_cpu_online(smp_processor_id(), true); |
| 320 | unlock_vector_lock(); | 324 | unlock_vector_lock(); |
| 321 | ipi_call_unlock(); | 325 | ipi_call_unlock(); |
| 322 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; | 326 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; |
| 327 | x86_platform.nmi_init(); | ||
| 323 | 328 | ||
| 324 | /* enable local interrupts */ | 329 | /* enable local interrupts */ |
| 325 | local_irq_enable(); | 330 | local_irq_enable(); |
| @@ -1211,11 +1216,12 @@ __init void prefill_possible_map(void) | |||
| 1211 | 1216 | ||
| 1212 | total_cpus = max_t(int, possible, num_processors + disabled_cpus); | 1217 | total_cpus = max_t(int, possible, num_processors + disabled_cpus); |
| 1213 | 1218 | ||
| 1214 | if (possible > CONFIG_NR_CPUS) { | 1219 | /* nr_cpu_ids could be reduced via nr_cpus= */ |
| 1220 | if (possible > nr_cpu_ids) { | ||
| 1215 | printk(KERN_WARNING | 1221 | printk(KERN_WARNING |
| 1216 | "%d Processors exceeds NR_CPUS limit of %d\n", | 1222 | "%d Processors exceeds NR_CPUS limit of %d\n", |
| 1217 | possible, CONFIG_NR_CPUS); | 1223 | possible, nr_cpu_ids); |
| 1218 | possible = CONFIG_NR_CPUS; | 1224 | possible = nr_cpu_ids; |
| 1219 | } | 1225 | } |
| 1220 | 1226 | ||
| 1221 | printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n", | 1227 | printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n", |
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c index be2573448ed9..fb5cc5e14cfa 100644 --- a/arch/x86/kernel/time.c +++ b/arch/x86/kernel/time.c | |||
| @@ -70,11 +70,11 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
| 70 | * manually to deassert NMI lines for the watchdog if run | 70 | * manually to deassert NMI lines for the watchdog if run |
| 71 | * on an 82489DX-based system. | 71 | * on an 82489DX-based system. |
| 72 | */ | 72 | */ |
| 73 | spin_lock(&i8259A_lock); | 73 | raw_spin_lock(&i8259A_lock); |
| 74 | outb(0x0c, PIC_MASTER_OCW3); | 74 | outb(0x0c, PIC_MASTER_OCW3); |
| 75 | /* Ack the IRQ; AEOI will end it automatically. */ | 75 | /* Ack the IRQ; AEOI will end it automatically. */ |
| 76 | inb(PIC_MASTER_POLL); | 76 | inb(PIC_MASTER_POLL); |
| 77 | spin_unlock(&i8259A_lock); | 77 | raw_spin_unlock(&i8259A_lock); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | global_clock_event->event_handler(global_clock_event); | 80 | global_clock_event->event_handler(global_clock_event); |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 33399176512a..1168e4454188 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -534,6 +534,9 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 534 | 534 | ||
| 535 | get_debugreg(dr6, 6); | 535 | get_debugreg(dr6, 6); |
| 536 | 536 | ||
| 537 | /* Filter out all the reserved bits which are preset to 1 */ | ||
| 538 | dr6 &= ~DR6_RESERVED; | ||
| 539 | |||
| 537 | /* Catch kmemcheck conditions first of all! */ | 540 | /* Catch kmemcheck conditions first of all! */ |
| 538 | if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) | 541 | if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) |
| 539 | return; | 542 | return; |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 597683aa5ba0..208a857c679f 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -740,7 +740,7 @@ static cycle_t __vsyscall_fn vread_tsc(void) | |||
| 740 | } | 740 | } |
| 741 | #endif | 741 | #endif |
| 742 | 742 | ||
| 743 | static void resume_tsc(void) | 743 | static void resume_tsc(struct clocksource *cs) |
| 744 | { | 744 | { |
| 745 | clocksource_tsc.cycle_last = 0; | 745 | clocksource_tsc.cycle_last = 0; |
| 746 | } | 746 | } |
| @@ -806,7 +806,7 @@ static void __init check_system_tsc_reliable(void) | |||
| 806 | unsigned long res_low, res_high; | 806 | unsigned long res_low, res_high; |
| 807 | 807 | ||
| 808 | rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); | 808 | rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); |
| 809 | /* Geode_LX - the OLPC CPU has a possibly a very reliable TSC */ | 809 | /* Geode_LX - the OLPC CPU has a very reliable TSC */ |
| 810 | if (res_low & RTSC_SUSP) | 810 | if (res_low & RTSC_SUSP) |
| 811 | tsc_clocksource_reliable = 1; | 811 | tsc_clocksource_reliable = 1; |
| 812 | #endif | 812 | #endif |
diff --git a/arch/x86/kernel/uv_sysfs.c b/arch/x86/kernel/uv_sysfs.c index 36afb98675a4..309c70fb7759 100644 --- a/arch/x86/kernel/uv_sysfs.c +++ b/arch/x86/kernel/uv_sysfs.c | |||
| @@ -54,19 +54,19 @@ static int __init sgi_uv_sysfs_init(void) | |||
| 54 | if (!sgi_uv_kobj) | 54 | if (!sgi_uv_kobj) |
| 55 | sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj); | 55 | sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj); |
| 56 | if (!sgi_uv_kobj) { | 56 | if (!sgi_uv_kobj) { |
| 57 | printk(KERN_WARNING "kobject_create_and_add sgi_uv failed \n"); | 57 | printk(KERN_WARNING "kobject_create_and_add sgi_uv failed\n"); |
| 58 | return -EINVAL; | 58 | return -EINVAL; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | ret = sysfs_create_file(sgi_uv_kobj, &partition_id_attr.attr); | 61 | ret = sysfs_create_file(sgi_uv_kobj, &partition_id_attr.attr); |
| 62 | if (ret) { | 62 | if (ret) { |
| 63 | printk(KERN_WARNING "sysfs_create_file partition_id failed \n"); | 63 | printk(KERN_WARNING "sysfs_create_file partition_id failed\n"); |
| 64 | return ret; | 64 | return ret; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | ret = sysfs_create_file(sgi_uv_kobj, &coherence_id_attr.attr); | 67 | ret = sysfs_create_file(sgi_uv_kobj, &coherence_id_attr.attr); |
| 68 | if (ret) { | 68 | if (ret) { |
| 69 | printk(KERN_WARNING "sysfs_create_file coherence_id failed \n"); | 69 | printk(KERN_WARNING "sysfs_create_file coherence_id failed\n"); |
| 70 | return ret; | 70 | return ret; |
| 71 | } | 71 | } |
| 72 | 72 | ||
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 34a279a7471d..ab38ce0984fa 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c | |||
| @@ -559,7 +559,7 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id) | |||
| 559 | struct irq_desc *desc; | 559 | struct irq_desc *desc; |
| 560 | unsigned long flags; | 560 | unsigned long flags; |
| 561 | 561 | ||
| 562 | spin_lock_irqsave(&i8259A_lock, flags); | 562 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 563 | 563 | ||
| 564 | /* Find out what's interrupting in the PIIX4 master 8259 */ | 564 | /* Find out what's interrupting in the PIIX4 master 8259 */ |
| 565 | outb(0x0c, 0x20); /* OCW3 Poll command */ | 565 | outb(0x0c, 0x20); /* OCW3 Poll command */ |
| @@ -596,7 +596,7 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id) | |||
| 596 | outb(0x60 + realirq, 0x20); | 596 | outb(0x60 + realirq, 0x20); |
| 597 | } | 597 | } |
| 598 | 598 | ||
| 599 | spin_unlock_irqrestore(&i8259A_lock, flags); | 599 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 600 | 600 | ||
| 601 | desc = irq_to_desc(realirq); | 601 | desc = irq_to_desc(realirq); |
| 602 | 602 | ||
| @@ -614,7 +614,7 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id) | |||
| 614 | return IRQ_HANDLED; | 614 | return IRQ_HANDLED; |
| 615 | 615 | ||
| 616 | out_unlock: | 616 | out_unlock: |
| 617 | spin_unlock_irqrestore(&i8259A_lock, flags); | 617 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 618 | return IRQ_NONE; | 618 | return IRQ_NONE; |
| 619 | } | 619 | } |
| 620 | 620 | ||
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c index 74c92bb194df..2f1ca5614292 100644 --- a/arch/x86/kernel/vmiclock_32.c +++ b/arch/x86/kernel/vmiclock_32.c | |||
| @@ -79,11 +79,7 @@ unsigned long vmi_tsc_khz(void) | |||
| 79 | 79 | ||
| 80 | static inline unsigned int vmi_get_timer_vector(void) | 80 | static inline unsigned int vmi_get_timer_vector(void) |
| 81 | { | 81 | { |
| 82 | #ifdef CONFIG_X86_IO_APIC | 82 | return IRQ0_VECTOR; |
| 83 | return FIRST_DEVICE_VECTOR; | ||
| 84 | #else | ||
| 85 | return FIRST_EXTERNAL_VECTOR; | ||
| 86 | #endif | ||
| 87 | } | 83 | } |
| 88 | 84 | ||
| 89 | /** vmi clockchip */ | 85 | /** vmi clockchip */ |
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index f92a0da608cb..44879df55696 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S | |||
| @@ -341,7 +341,7 @@ SECTIONS | |||
| 341 | * Per-cpu symbols which need to be offset from __per_cpu_load | 341 | * Per-cpu symbols which need to be offset from __per_cpu_load |
| 342 | * for the boot processor. | 342 | * for the boot processor. |
| 343 | */ | 343 | */ |
| 344 | #define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load | 344 | #define INIT_PER_CPU(x) init_per_cpu__##x = x + __per_cpu_load |
| 345 | INIT_PER_CPU(gdt_page); | 345 | INIT_PER_CPU(gdt_page); |
| 346 | INIT_PER_CPU(irq_stack_union); | 346 | INIT_PER_CPU(irq_stack_union); |
| 347 | 347 | ||
| @@ -352,7 +352,7 @@ INIT_PER_CPU(irq_stack_union); | |||
| 352 | "kernel image bigger than KERNEL_IMAGE_SIZE"); | 352 | "kernel image bigger than KERNEL_IMAGE_SIZE"); |
| 353 | 353 | ||
| 354 | #ifdef CONFIG_SMP | 354 | #ifdef CONFIG_SMP |
| 355 | . = ASSERT((per_cpu__irq_stack_union == 0), | 355 | . = ASSERT((irq_stack_union == 0), |
| 356 | "irq_stack_union is not at start of per-cpu area"); | 356 | "irq_stack_union is not at start of per-cpu area"); |
| 357 | #endif | 357 | #endif |
| 358 | 358 | ||
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 619f7f88b8cc..693920b22496 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c | |||
| @@ -26,7 +26,8 @@ EXPORT_SYMBOL(__put_user_2); | |||
| 26 | EXPORT_SYMBOL(__put_user_4); | 26 | EXPORT_SYMBOL(__put_user_4); |
| 27 | EXPORT_SYMBOL(__put_user_8); | 27 | EXPORT_SYMBOL(__put_user_8); |
| 28 | 28 | ||
| 29 | EXPORT_SYMBOL(copy_user_generic); | 29 | EXPORT_SYMBOL(copy_user_generic_string); |
| 30 | EXPORT_SYMBOL(copy_user_generic_unrolled); | ||
| 30 | EXPORT_SYMBOL(__copy_user_nocache); | 31 | EXPORT_SYMBOL(__copy_user_nocache); |
| 31 | EXPORT_SYMBOL(_copy_from_user); | 32 | EXPORT_SYMBOL(_copy_from_user); |
| 32 | EXPORT_SYMBOL(_copy_to_user); | 33 | EXPORT_SYMBOL(_copy_to_user); |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index ccd179dec36e..ee5746c94628 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
| @@ -76,10 +76,13 @@ struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { | |||
| 76 | .setup_percpu_clockev = setup_secondary_APIC_clock, | 76 | .setup_percpu_clockev = setup_secondary_APIC_clock, |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | static void default_nmi_init(void) { }; | ||
| 80 | |||
| 79 | struct x86_platform_ops x86_platform = { | 81 | struct x86_platform_ops x86_platform = { |
| 80 | .calibrate_tsc = native_calibrate_tsc, | 82 | .calibrate_tsc = native_calibrate_tsc, |
| 81 | .get_wallclock = mach_get_cmos_time, | 83 | .get_wallclock = mach_get_cmos_time, |
| 82 | .set_wallclock = mach_set_rtc_mmss, | 84 | .set_wallclock = mach_set_rtc_mmss, |
| 83 | .iommu_shutdown = iommu_shutdown_noop, | 85 | .iommu_shutdown = iommu_shutdown_noop, |
| 84 | .is_untracked_pat_range = is_ISA_range, | 86 | .is_untracked_pat_range = is_ISA_range, |
| 87 | .nmi_init = default_nmi_init | ||
| 85 | }; | 88 | }; |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index c5ee17e8c6d9..782c3a362ec6 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
| @@ -337,6 +337,7 @@ void __ref xsave_cntxt_init(void) | |||
| 337 | cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); | 337 | cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); |
| 338 | xstate_size = ebx; | 338 | xstate_size = ebx; |
| 339 | 339 | ||
| 340 | update_regset_xstate_info(xstate_size, pcntxt_mask); | ||
| 340 | prepare_fx_sw_frame(); | 341 | prepare_fx_sw_frame(); |
| 341 | 342 | ||
| 342 | setup_xstate_init(); | 343 | setup_xstate_init(); |
