diff options
| -rw-r--r-- | arch/x86/include/asm/i387.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 5 | ||||
| -rw-r--r-- | arch/x86/mm/srat_32.c | 4 | ||||
| -rw-r--r-- | arch/x86/platform/mrst/vrtc.c | 4 | ||||
| -rw-r--r-- | arch/x86/platform/visws/visws_quirks.c | 20 | ||||
| -rw-r--r-- | drivers/rtc/rtc-mrst.c | 7 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 1 | ||||
| -rw-r--r-- | kernel/sched.c | 3 | ||||
| -rw-r--r-- | kernel/sched_fair.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 19 | ||||
| -rw-r--r-- | tools/perf/util/probe-finder.c | 159 |
11 files changed, 151 insertions, 89 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index ef328901c802..c9e09ea05644 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -237,7 +237,7 @@ static inline void fpu_save_init(struct fpu *fpu) | |||
| 237 | } else if (use_fxsr()) { | 237 | } else if (use_fxsr()) { |
| 238 | fpu_fxsave(fpu); | 238 | fpu_fxsave(fpu); |
| 239 | } else { | 239 | } else { |
| 240 | asm volatile("fsave %[fx]; fwait" | 240 | asm volatile("fnsave %[fx]; fwait" |
| 241 | : [fx] "=m" (fpu->state->fsave)); | 241 | : [fx] "=m" (fpu->state->fsave)); |
| 242 | return; | 242 | return; |
| 243 | } | 243 | } |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 5a0484a95ad6..4be9b398470e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -976,6 +976,11 @@ void __init setup_arch(char **cmdline_p) | |||
| 976 | paging_init(); | 976 | paging_init(); |
| 977 | x86_init.paging.pagetable_setup_done(swapper_pg_dir); | 977 | x86_init.paging.pagetable_setup_done(swapper_pg_dir); |
| 978 | 978 | ||
| 979 | if (boot_cpu_data.cpuid_level >= 0) { | ||
| 980 | /* A CPU has %cr4 if and only if it has CPUID */ | ||
| 981 | mmu_cr4_features = read_cr4(); | ||
| 982 | } | ||
| 983 | |||
| 979 | #ifdef CONFIG_X86_32 | 984 | #ifdef CONFIG_X86_32 |
| 980 | /* sync back kernel address range */ | 985 | /* sync back kernel address range */ |
| 981 | clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, | 986 | clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, |
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c index 48651c6f657d..364f36bdfad8 100644 --- a/arch/x86/mm/srat_32.c +++ b/arch/x86/mm/srat_32.c | |||
| @@ -211,10 +211,12 @@ int __init get_memcfg_from_srat(void) | |||
| 211 | { | 211 | { |
| 212 | int i, j, nid; | 212 | int i, j, nid; |
| 213 | 213 | ||
| 214 | |||
| 215 | if (srat_disabled()) | 214 | if (srat_disabled()) |
| 216 | goto out_fail; | 215 | goto out_fail; |
| 217 | 216 | ||
| 217 | if (acpi_numa_init() < 0) | ||
| 218 | goto out_fail; | ||
| 219 | |||
| 218 | if (num_memory_chunks == 0) { | 220 | if (num_memory_chunks == 0) { |
| 219 | printk(KERN_DEBUG | 221 | printk(KERN_DEBUG |
| 220 | "could not find any ACPI SRAT memory areas.\n"); | 222 | "could not find any ACPI SRAT memory areas.\n"); |
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c index 04cf645feb92..73d70d65e76e 100644 --- a/arch/x86/platform/mrst/vrtc.c +++ b/arch/x86/platform/mrst/vrtc.c | |||
| @@ -100,9 +100,11 @@ int vrtc_set_mmss(unsigned long nowtime) | |||
| 100 | 100 | ||
| 101 | void __init mrst_rtc_init(void) | 101 | void __init mrst_rtc_init(void) |
| 102 | { | 102 | { |
| 103 | unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr; | 103 | unsigned long vrtc_paddr; |
| 104 | 104 | ||
| 105 | sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); | 105 | sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); |
| 106 | |||
| 107 | vrtc_paddr = sfi_mrtc_array[0].phys_addr; | ||
| 106 | if (!sfi_mrtc_num || !vrtc_paddr) | 108 | if (!sfi_mrtc_num || !vrtc_paddr) |
| 107 | return; | 109 | return; |
| 108 | 110 | ||
diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c index fe4cf8294878..c7abf13a213f 100644 --- a/arch/x86/platform/visws/visws_quirks.c +++ b/arch/x86/platform/visws/visws_quirks.c | |||
| @@ -471,15 +471,7 @@ static unsigned int startup_piix4_master_irq(struct irq_data *data) | |||
| 471 | { | 471 | { |
| 472 | legacy_pic->init(0); | 472 | legacy_pic->init(0); |
| 473 | enable_cobalt_irq(data); | 473 | enable_cobalt_irq(data); |
| 474 | } | 474 | return 0; |
| 475 | |||
| 476 | static void end_piix4_master_irq(struct irq_data *data) | ||
| 477 | { | ||
| 478 | unsigned long flags; | ||
| 479 | |||
| 480 | spin_lock_irqsave(&cobalt_lock, flags); | ||
| 481 | enable_cobalt_irq(data); | ||
| 482 | spin_unlock_irqrestore(&cobalt_lock, flags); | ||
| 483 | } | 475 | } |
| 484 | 476 | ||
| 485 | static struct irq_chip piix4_master_irq_type = { | 477 | static struct irq_chip piix4_master_irq_type = { |
| @@ -492,7 +484,7 @@ static void pii4_mask(struct irq_data *data) { } | |||
| 492 | 484 | ||
| 493 | static struct irq_chip piix4_virtual_irq_type = { | 485 | static struct irq_chip piix4_virtual_irq_type = { |
| 494 | .name = "PIIX4-virtual", | 486 | .name = "PIIX4-virtual", |
| 495 | .mask = pii4_mask, | 487 | .irq_mask = pii4_mask, |
| 496 | }; | 488 | }; |
| 497 | 489 | ||
| 498 | /* | 490 | /* |
| @@ -580,9 +572,9 @@ static struct irqaction cascade_action = { | |||
| 580 | 572 | ||
| 581 | static inline void set_piix4_virtual_irq_type(void) | 573 | static inline void set_piix4_virtual_irq_type(void) |
| 582 | { | 574 | { |
| 583 | piix4_virtual_irq_type.enable = i8259A_chip.unmask; | 575 | piix4_virtual_irq_type.irq_enable = i8259A_chip.irq_unmask; |
| 584 | piix4_virtual_irq_type.disable = i8259A_chip.mask; | 576 | piix4_virtual_irq_type.irq_disable = i8259A_chip.irq_mask; |
| 585 | piix4_virtual_irq_type.unmask = i8259A_chip.unmask; | 577 | piix4_virtual_irq_type.irq_unmask = i8259A_chip.irq_unmask; |
| 586 | } | 578 | } |
| 587 | 579 | ||
| 588 | static void __init visws_pre_intr_init(void) | 580 | static void __init visws_pre_intr_init(void) |
| @@ -599,7 +591,7 @@ static void __init visws_pre_intr_init(void) | |||
| 599 | else if (i == CO_IRQ_IDE0) | 591 | else if (i == CO_IRQ_IDE0) |
| 600 | chip = &cobalt_irq_type; | 592 | chip = &cobalt_irq_type; |
| 601 | else if (i == CO_IRQ_IDE1) | 593 | else if (i == CO_IRQ_IDE1) |
| 602 | >chip = &cobalt_irq_type; | 594 | chip = &cobalt_irq_type; |
| 603 | else if (i == CO_IRQ_8259) | 595 | else if (i == CO_IRQ_8259) |
| 604 | chip = &piix4_master_irq_type; | 596 | chip = &piix4_master_irq_type; |
| 605 | else if (i < CO_IRQ_APIC0) | 597 | else if (i < CO_IRQ_APIC0) |
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 332a2c4a891c..b2f096871a97 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c | |||
| @@ -342,6 +342,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
| 342 | 342 | ||
| 343 | mrst_rtc.irq = rtc_irq; | 343 | mrst_rtc.irq = rtc_irq; |
| 344 | mrst_rtc.iomem = iomem; | 344 | mrst_rtc.iomem = iomem; |
| 345 | mrst_rtc.dev = dev; | ||
| 346 | dev_set_drvdata(dev, &mrst_rtc); | ||
| 345 | 347 | ||
| 346 | mrst_rtc.rtc = rtc_device_register(driver_name, dev, | 348 | mrst_rtc.rtc = rtc_device_register(driver_name, dev, |
| 347 | &mrst_rtc_ops, THIS_MODULE); | 349 | &mrst_rtc_ops, THIS_MODULE); |
| @@ -350,8 +352,6 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
| 350 | goto cleanup0; | 352 | goto cleanup0; |
| 351 | } | 353 | } |
| 352 | 354 | ||
| 353 | mrst_rtc.dev = dev; | ||
| 354 | dev_set_drvdata(dev, &mrst_rtc); | ||
| 355 | rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); | 355 | rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); |
| 356 | 356 | ||
| 357 | spin_lock_irq(&rtc_lock); | 357 | spin_lock_irq(&rtc_lock); |
| @@ -376,9 +376,10 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
| 376 | return 0; | 376 | return 0; |
| 377 | 377 | ||
| 378 | cleanup1: | 378 | cleanup1: |
| 379 | mrst_rtc.dev = NULL; | ||
| 380 | rtc_device_unregister(mrst_rtc.rtc); | 379 | rtc_device_unregister(mrst_rtc.rtc); |
| 381 | cleanup0: | 380 | cleanup0: |
| 381 | dev_set_drvdata(dev, NULL); | ||
| 382 | mrst_rtc.dev = NULL; | ||
| 382 | release_region(iomem->start, iomem->end + 1 - iomem->start); | 383 | release_region(iomem->start, iomem->end + 1 - iomem->start); |
| 383 | dev_err(dev, "rtc-mrst: unable to initialise\n"); | 384 | dev_err(dev, "rtc-mrst: unable to initialise\n"); |
| 384 | return retval; | 385 | return retval; |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 12a80fdae11c..07c1611f3899 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -1051,6 +1051,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1051 | register_irq_proc(irq, desc); | 1051 | register_irq_proc(irq, desc); |
| 1052 | new->dir = NULL; | 1052 | new->dir = NULL; |
| 1053 | register_handler_proc(irq, new); | 1053 | register_handler_proc(irq, new); |
| 1054 | free_cpumask_var(mask); | ||
| 1054 | 1055 | ||
| 1055 | return 0; | 1056 | return 0; |
| 1056 | 1057 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index dc7ca5c2a7ab..48013633d792 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -6331,6 +6331,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
| 6331 | break; | 6331 | break; |
| 6332 | #endif | 6332 | #endif |
| 6333 | } | 6333 | } |
| 6334 | |||
| 6335 | update_max_interval(); | ||
| 6336 | |||
| 6334 | return NOTIFY_OK; | 6337 | return NOTIFY_OK; |
| 6335 | } | 6338 | } |
| 6336 | 6339 | ||
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 4104533d43ef..7f00772e57c9 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
| @@ -3820,6 +3820,17 @@ void select_nohz_load_balancer(int stop_tick) | |||
| 3820 | 3820 | ||
| 3821 | static DEFINE_SPINLOCK(balancing); | 3821 | static DEFINE_SPINLOCK(balancing); |
| 3822 | 3822 | ||
| 3823 | static unsigned long __read_mostly max_load_balance_interval = HZ/10; | ||
| 3824 | |||
| 3825 | /* | ||
| 3826 | * Scale the max load_balance interval with the number of CPUs in the system. | ||
| 3827 | * This trades load-balance latency on larger machines for less cross talk. | ||
| 3828 | */ | ||
| 3829 | static void update_max_interval(void) | ||
| 3830 | { | ||
| 3831 | max_load_balance_interval = HZ*num_online_cpus()/10; | ||
| 3832 | } | ||
| 3833 | |||
| 3823 | /* | 3834 | /* |
| 3824 | * It checks each scheduling domain to see if it is due to be balanced, | 3835 | * It checks each scheduling domain to see if it is due to be balanced, |
| 3825 | * and initiates a balancing operation if so. | 3836 | * and initiates a balancing operation if so. |
| @@ -3849,10 +3860,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle) | |||
| 3849 | 3860 | ||
| 3850 | /* scale ms to jiffies */ | 3861 | /* scale ms to jiffies */ |
| 3851 | interval = msecs_to_jiffies(interval); | 3862 | interval = msecs_to_jiffies(interval); |
| 3852 | if (unlikely(!interval)) | 3863 | interval = clamp(interval, 1UL, max_load_balance_interval); |
| 3853 | interval = 1; | ||
| 3854 | if (interval > HZ*num_online_cpus()/10) | ||
| 3855 | interval = HZ*num_online_cpus()/10; | ||
| 3856 | 3864 | ||
| 3857 | need_serialize = sd->flags & SD_SERIALIZE; | 3865 | need_serialize = sd->flags & SD_SERIALIZE; |
| 3858 | 3866 | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 5ddee66020a7..f0223166e761 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -234,7 +234,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
| 234 | 234 | ||
| 235 | /* Searching trace events corresponding to probe event */ | 235 | /* Searching trace events corresponding to probe event */ |
| 236 | ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); | 236 | ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); |
| 237 | close(fd); | ||
| 238 | 237 | ||
| 239 | if (ntevs > 0) { /* Succeeded to find trace events */ | 238 | if (ntevs > 0) { /* Succeeded to find trace events */ |
| 240 | pr_debug("find %d probe_trace_events.\n", ntevs); | 239 | pr_debug("find %d probe_trace_events.\n", ntevs); |
| @@ -388,7 +387,6 @@ int show_line_range(struct line_range *lr, const char *module) | |||
| 388 | } | 387 | } |
| 389 | 388 | ||
| 390 | ret = find_line_range(fd, lr); | 389 | ret = find_line_range(fd, lr); |
| 391 | close(fd); | ||
| 392 | if (ret == 0) { | 390 | if (ret == 0) { |
| 393 | pr_warning("Specified source line is not found.\n"); | 391 | pr_warning("Specified source line is not found.\n"); |
| 394 | return -ENOENT; | 392 | return -ENOENT; |
| @@ -512,19 +510,18 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, | |||
| 512 | if (ret < 0) | 510 | if (ret < 0) |
| 513 | return ret; | 511 | return ret; |
| 514 | 512 | ||
| 515 | fd = open_vmlinux(module); | ||
| 516 | if (fd < 0) { | ||
| 517 | pr_warning("Failed to open debug information file.\n"); | ||
| 518 | return fd; | ||
| 519 | } | ||
| 520 | |||
| 521 | setup_pager(); | 513 | setup_pager(); |
| 522 | 514 | ||
| 523 | for (i = 0; i < npevs && ret >= 0; i++) | 515 | for (i = 0; i < npevs && ret >= 0; i++) { |
| 516 | fd = open_vmlinux(module); | ||
| 517 | if (fd < 0) { | ||
| 518 | pr_warning("Failed to open debug information file.\n"); | ||
| 519 | ret = fd; | ||
| 520 | break; | ||
| 521 | } | ||
| 524 | ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, | 522 | ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, |
| 525 | externs); | 523 | externs); |
| 526 | 524 | } | |
| 527 | close(fd); | ||
| 528 | return ret; | 525 | return ret; |
| 529 | } | 526 | } |
| 530 | 527 | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 194f9e2a3285..b7c85ce466a1 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -273,6 +273,25 @@ static const char *cu_get_comp_dir(Dwarf_Die *cu_die) | |||
| 273 | return dwarf_formstring(&attr); | 273 | return dwarf_formstring(&attr); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | /* Get a line number and file name for given address */ | ||
| 277 | static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, | ||
| 278 | const char **fname, int *lineno) | ||
| 279 | { | ||
| 280 | Dwarf_Line *line; | ||
| 281 | Dwarf_Addr laddr; | ||
| 282 | |||
| 283 | line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr); | ||
| 284 | if (line && dwarf_lineaddr(line, &laddr) == 0 && | ||
| 285 | addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) { | ||
| 286 | *fname = dwarf_linesrc(line, NULL, NULL); | ||
| 287 | if (!*fname) | ||
| 288 | /* line number is useless without filename */ | ||
| 289 | *lineno = 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | return *lineno ?: -ENOENT; | ||
| 293 | } | ||
| 294 | |||
| 276 | /* Compare diename and tname */ | 295 | /* Compare diename and tname */ |
| 277 | static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) | 296 | static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) |
| 278 | { | 297 | { |
| @@ -497,7 +516,20 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) | |||
| 497 | static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, | 516 | static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, |
| 498 | Dwarf_Die *die_mem) | 517 | Dwarf_Die *die_mem) |
| 499 | { | 518 | { |
| 500 | return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); | 519 | Dwarf_Die tmp_die; |
| 520 | |||
| 521 | sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die); | ||
| 522 | if (!sp_die) | ||
| 523 | return NULL; | ||
| 524 | |||
| 525 | /* Inlined function could be recursive. Trace it until fail */ | ||
| 526 | while (sp_die) { | ||
| 527 | memcpy(die_mem, sp_die, sizeof(Dwarf_Die)); | ||
| 528 | sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, | ||
| 529 | &tmp_die); | ||
| 530 | } | ||
| 531 | |||
| 532 | return die_mem; | ||
| 501 | } | 533 | } |
| 502 | 534 | ||
| 503 | /* Walker on lines (Note: line number will not be sorted) */ | 535 | /* Walker on lines (Note: line number will not be sorted) */ |
| @@ -1395,6 +1427,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) | |||
| 1395 | !die_compare_name(sp_die, pp->function)) | 1427 | !die_compare_name(sp_die, pp->function)) |
| 1396 | return DWARF_CB_OK; | 1428 | return DWARF_CB_OK; |
| 1397 | 1429 | ||
| 1430 | /* Check declared file */ | ||
| 1431 | if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) | ||
| 1432 | return DWARF_CB_OK; | ||
| 1433 | |||
| 1398 | pf->fname = dwarf_decl_file(sp_die); | 1434 | pf->fname = dwarf_decl_file(sp_die); |
| 1399 | if (pp->line) { /* Function relative line */ | 1435 | if (pp->line) { /* Function relative line */ |
| 1400 | dwarf_decl_line(sp_die, &pf->lno); | 1436 | dwarf_decl_line(sp_die, &pf->lno); |
| @@ -1451,6 +1487,7 @@ static int find_probes(int fd, struct probe_finder *pf) | |||
| 1451 | if (!dbg) { | 1487 | if (!dbg) { |
| 1452 | pr_warning("No debug information found in the vmlinux - " | 1488 | pr_warning("No debug information found in the vmlinux - " |
| 1453 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | 1489 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); |
| 1490 | close(fd); /* Without dwfl_end(), fd isn't closed. */ | ||
| 1454 | return -EBADF; | 1491 | return -EBADF; |
| 1455 | } | 1492 | } |
| 1456 | 1493 | ||
| @@ -1686,11 +1723,9 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) | |||
| 1686 | Dwarf_Die cudie, spdie, indie; | 1723 | Dwarf_Die cudie, spdie, indie; |
| 1687 | Dwarf *dbg = NULL; | 1724 | Dwarf *dbg = NULL; |
| 1688 | Dwfl *dwfl = NULL; | 1725 | Dwfl *dwfl = NULL; |
| 1689 | Dwarf_Line *line; | 1726 | Dwarf_Addr _addr, baseaddr, bias = 0; |
| 1690 | Dwarf_Addr laddr, eaddr, bias = 0; | 1727 | const char *fname = NULL, *func = NULL, *tmp; |
| 1691 | const char *tmp; | 1728 | int baseline = 0, lineno = 0, ret = 0; |
| 1692 | int lineno, ret = 0; | ||
| 1693 | bool found = false; | ||
| 1694 | 1729 | ||
| 1695 | /* Open the live linux kernel */ | 1730 | /* Open the live linux kernel */ |
| 1696 | dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); | 1731 | dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); |
| @@ -1711,68 +1746,79 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) | |||
| 1711 | goto end; | 1746 | goto end; |
| 1712 | } | 1747 | } |
| 1713 | 1748 | ||
| 1714 | /* Find a corresponding line */ | 1749 | /* Find a corresponding line (filename and lineno) */ |
| 1715 | line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); | 1750 | cu_find_lineinfo(&cudie, addr, &fname, &lineno); |
| 1716 | if (line) { | 1751 | /* Don't care whether it failed or not */ |
| 1717 | if (dwarf_lineaddr(line, &laddr) == 0 && | ||
| 1718 | (Dwarf_Addr)addr == laddr && | ||
| 1719 | dwarf_lineno(line, &lineno) == 0) { | ||
| 1720 | tmp = dwarf_linesrc(line, NULL, NULL); | ||
| 1721 | if (tmp) { | ||
| 1722 | ppt->line = lineno; | ||
| 1723 | ppt->file = strdup(tmp); | ||
| 1724 | if (ppt->file == NULL) { | ||
| 1725 | ret = -ENOMEM; | ||
| 1726 | goto end; | ||
| 1727 | } | ||
| 1728 | found = true; | ||
| 1729 | } | ||
| 1730 | } | ||
| 1731 | } | ||
| 1732 | 1752 | ||
| 1733 | /* Find a corresponding function */ | 1753 | /* Find a corresponding function (name, baseline and baseaddr) */ |
| 1734 | if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { | 1754 | if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { |
| 1755 | /* Get function entry information */ | ||
| 1735 | tmp = dwarf_diename(&spdie); | 1756 | tmp = dwarf_diename(&spdie); |
| 1736 | if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) | 1757 | if (!tmp || |
| 1737 | goto end; | 1758 | dwarf_entrypc(&spdie, &baseaddr) != 0 || |
| 1738 | 1759 | dwarf_decl_line(&spdie, &baseline) != 0) | |
| 1739 | if (ppt->line) { | 1760 | goto post; |
| 1740 | if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, | 1761 | func = tmp; |
| 1741 | &indie)) { | 1762 | |
| 1742 | /* addr in an inline function */ | 1763 | if (addr == (unsigned long)baseaddr) |
| 1764 | /* Function entry - Relative line number is 0 */ | ||
| 1765 | lineno = baseline; | ||
| 1766 | else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, | ||
| 1767 | &indie)) { | ||
| 1768 | if (dwarf_entrypc(&indie, &_addr) == 0 && | ||
| 1769 | _addr == addr) | ||
| 1770 | /* | ||
| 1771 | * addr is at an inline function entry. | ||
| 1772 | * In this case, lineno should be the call-site | ||
| 1773 | * line number. | ||
| 1774 | */ | ||
| 1775 | lineno = die_get_call_lineno(&indie); | ||
| 1776 | else { | ||
| 1777 | /* | ||
| 1778 | * addr is in an inline function body. | ||
| 1779 | * Since lineno points one of the lines | ||
| 1780 | * of the inline function, baseline should | ||
| 1781 | * be the entry line of the inline function. | ||
| 1782 | */ | ||
| 1743 | tmp = dwarf_diename(&indie); | 1783 | tmp = dwarf_diename(&indie); |
| 1744 | if (!tmp) | 1784 | if (tmp && |
| 1745 | goto end; | 1785 | dwarf_decl_line(&spdie, &baseline) == 0) |
| 1746 | ret = dwarf_decl_line(&indie, &lineno); | 1786 | func = tmp; |
| 1747 | } else { | ||
| 1748 | if (eaddr == addr) { /* Function entry */ | ||
| 1749 | lineno = ppt->line; | ||
| 1750 | ret = 0; | ||
| 1751 | } else | ||
| 1752 | ret = dwarf_decl_line(&spdie, &lineno); | ||
| 1753 | } | ||
| 1754 | if (ret == 0) { | ||
| 1755 | /* Make a relative line number */ | ||
| 1756 | ppt->line -= lineno; | ||
| 1757 | goto found; | ||
| 1758 | } | 1787 | } |
| 1759 | } | 1788 | } |
| 1760 | /* We don't have a line number, let's use offset */ | 1789 | } |
| 1761 | ppt->offset = addr - (unsigned long)eaddr; | 1790 | |
| 1762 | found: | 1791 | post: |
| 1763 | ppt->function = strdup(tmp); | 1792 | /* Make a relative line number or an offset */ |
| 1793 | if (lineno) | ||
| 1794 | ppt->line = lineno - baseline; | ||
| 1795 | else if (func) | ||
| 1796 | ppt->offset = addr - (unsigned long)baseaddr; | ||
| 1797 | |||
| 1798 | /* Duplicate strings */ | ||
| 1799 | if (func) { | ||
| 1800 | ppt->function = strdup(func); | ||
| 1764 | if (ppt->function == NULL) { | 1801 | if (ppt->function == NULL) { |
| 1765 | ret = -ENOMEM; | 1802 | ret = -ENOMEM; |
| 1766 | goto end; | 1803 | goto end; |
| 1767 | } | 1804 | } |
| 1768 | found = true; | ||
| 1769 | } | 1805 | } |
| 1770 | 1806 | if (fname) { | |
| 1807 | ppt->file = strdup(fname); | ||
| 1808 | if (ppt->file == NULL) { | ||
| 1809 | if (ppt->function) { | ||
| 1810 | free(ppt->function); | ||
| 1811 | ppt->function = NULL; | ||
| 1812 | } | ||
| 1813 | ret = -ENOMEM; | ||
| 1814 | goto end; | ||
| 1815 | } | ||
| 1816 | } | ||
| 1771 | end: | 1817 | end: |
| 1772 | if (dwfl) | 1818 | if (dwfl) |
| 1773 | dwfl_end(dwfl); | 1819 | dwfl_end(dwfl); |
| 1774 | if (ret >= 0) | 1820 | if (ret == 0 && (fname || func)) |
| 1775 | ret = found ? 1 : 0; | 1821 | ret = 1; /* Found a point */ |
| 1776 | return ret; | 1822 | return ret; |
| 1777 | } | 1823 | } |
| 1778 | 1824 | ||
| @@ -1840,6 +1886,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | |||
| 1840 | struct line_finder *lf = param->data; | 1886 | struct line_finder *lf = param->data; |
| 1841 | struct line_range *lr = lf->lr; | 1887 | struct line_range *lr = lf->lr; |
| 1842 | 1888 | ||
| 1889 | /* Check declared file */ | ||
| 1890 | if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) | ||
| 1891 | return DWARF_CB_OK; | ||
| 1892 | |||
| 1843 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && | 1893 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && |
| 1844 | die_compare_name(sp_die, lr->function)) { | 1894 | die_compare_name(sp_die, lr->function)) { |
| 1845 | lf->fname = dwarf_decl_file(sp_die); | 1895 | lf->fname = dwarf_decl_file(sp_die); |
| @@ -1892,6 +1942,7 @@ int find_line_range(int fd, struct line_range *lr) | |||
| 1892 | if (!dbg) { | 1942 | if (!dbg) { |
| 1893 | pr_warning("No debug information found in the vmlinux - " | 1943 | pr_warning("No debug information found in the vmlinux - " |
| 1894 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | 1944 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); |
| 1945 | close(fd); /* Without dwfl_end(), fd isn't closed. */ | ||
| 1895 | return -EBADF; | 1946 | return -EBADF; |
| 1896 | } | 1947 | } |
| 1897 | 1948 | ||
