lkml.org 
[lkml]   [2012]   [Jul]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6/8] pstore/ram: Add ftrace messages handling
    Date
    The ftrace log size is configurable via ramoops.ftrace_size
    module option, and the log itself is available via
    <pstore-mount>/ftrace-ramoops file.

    Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
    ---
    Documentation/ramoops.txt | 25 +++++++++++++++++++++++++
    fs/pstore/ram.c | 37 +++++++++++++++++++++++++++++++++----
    include/linux/pstore_ram.h | 1 +
    3 files changed, 59 insertions(+), 4 deletions(-)

    diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
    index 59a74a8..197ad59 100644
    --- a/Documentation/ramoops.txt
    +++ b/Documentation/ramoops.txt
    @@ -94,3 +94,28 @@ timestamp and a new line. The dump then continues with the actual data.
    The dump data can be read from the pstore filesystem. The format for these
    files is "dmesg-ramoops-N", where N is the record number in memory. To delete
    a stored record from RAM, simply unlink the respective pstore file.
    +
    +5. Persistent function tracing
    +
    +Persistent function tracing might be useful for debugging software or hardware
    +related hangs. The functions call chain log is stored in a "ftrace-ramoops"
    +file. Here is an example of usage:
    +
    + # mount -t debugfs debugfs /sys/kernel/debug/
    + # cd /sys/kernel/debug/tracing
    + # echo function > current_tracer
    + # echo 1 > options/func_pstore
    + # reboot -f
    + [...]
    + # mount -t pstore pstore /mnt/
    + # tail /mnt/ftrace-ramoops
    + 0 ffffffff8101ea64 ffffffff8101bcda native_apic_mem_read <- disconnect_bsp_APIC+0x6a/0xc0
    + 0 ffffffff8101ea44 ffffffff8101bcf6 native_apic_mem_write <- disconnect_bsp_APIC+0x86/0xc0
    + 0 ffffffff81020084 ffffffff8101a4b5 hpet_disable <- native_machine_shutdown+0x75/0x90
    + 0 ffffffff81005f94 ffffffff8101a4bb iommu_shutdown_noop <- native_machine_shutdown+0x7b/0x90
    + 0 ffffffff8101a6a1 ffffffff8101a437 native_machine_emergency_restart <- native_machine_restart+0x37/0x40
    + 0 ffffffff811f9876 ffffffff8101a73a acpi_reboot <- native_machine_emergency_restart+0xaa/0x1e0
    + 0 ffffffff8101a514 ffffffff8101a772 mach_reboot_fixups <- native_machine_emergency_restart+0xe2/0x1e0
    + 0 ffffffff811d9c54 ffffffff8101a7a0 __const_udelay <- native_machine_emergency_restart+0x110/0x1e0
    + 0 ffffffff811d9c34 ffffffff811d9c80 __delay <- __const_udelay+0x30/0x40
    + 0 ffffffff811d9d14 ffffffff811d9c3f delay_tsc <- __delay+0xf/0x20
    diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
    index 74f4111..1dd108e 100644
    --- a/fs/pstore/ram.c
    +++ b/fs/pstore/ram.c
    @@ -45,6 +45,10 @@ static ulong ramoops_console_size = MIN_MEM_SIZE;
    module_param_named(console_size, ramoops_console_size, ulong, 0400);
    MODULE_PARM_DESC(console_size, "size of kernel console log");

    +static ulong ramoops_ftrace_size = MIN_MEM_SIZE;
    +module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400);
    +MODULE_PARM_DESC(ftrace_size, "size of ftrace log");
    +
    static ulong mem_address;
    module_param(mem_address, ulong, 0400);
    MODULE_PARM_DESC(mem_address,
    @@ -70,16 +74,19 @@ MODULE_PARM_DESC(ramoops_ecc,
    struct ramoops_context {
    struct persistent_ram_zone **przs;
    struct persistent_ram_zone *cprz;
    + struct persistent_ram_zone *fprz;
    phys_addr_t phys_addr;
    unsigned long size;
    size_t record_size;
    size_t console_size;
    + size_t ftrace_size;
    int dump_oops;
    int ecc_size;
    unsigned int max_dump_cnt;
    unsigned int dump_write_cnt;
    unsigned int dump_read_cnt;
    unsigned int console_read_cnt;
    + unsigned int ftrace_read_cnt;
    struct pstore_info pstore;
    };

    @@ -138,6 +145,9 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
    prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt,
    1, id, type, PSTORE_TYPE_CONSOLE, 0);
    if (!prz)
    + prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt,
    + 1, id, type, PSTORE_TYPE_FTRACE, 0);
    + if (!prz)
    return 0;

    /* TODO(kees): Bogus time for the moment. */
    @@ -186,6 +196,11 @@ static int ramoops_pstore_write_buf(enum pstore_type_id type,
    return -ENOMEM;
    persistent_ram_write(cxt->cprz, buf, size);
    return 0;
    + } else if (type == PSTORE_TYPE_FTRACE) {
    + if (!cxt->fprz)
    + return -ENOMEM;
    + persistent_ram_write(cxt->fprz, buf, size);
    + return 0;
    }

    if (type != PSTORE_TYPE_DMESG)
    @@ -235,6 +250,9 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id,
    case PSTORE_TYPE_CONSOLE:
    prz = cxt->cprz;
    break;
    + case PSTORE_TYPE_FTRACE:
    + prz = cxt->fprz;
    + break;
    default:
    return -EINVAL;
    }
    @@ -348,7 +366,8 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
    if (cxt->max_dump_cnt)
    goto fail_out;

    - if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size)) {
    + if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size &&
    + !pdata->ftrace_size)) {
    pr_err("The memory size and the record/console size must be "
    "non-zero\n");
    goto fail_out;
    @@ -357,18 +376,20 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
    pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
    pdata->record_size = rounddown_pow_of_two(pdata->record_size);
    pdata->console_size = rounddown_pow_of_two(pdata->console_size);
    + pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);

    cxt->dump_read_cnt = 0;
    cxt->size = pdata->mem_size;
    cxt->phys_addr = pdata->mem_address;
    cxt->record_size = pdata->record_size;
    cxt->console_size = pdata->console_size;
    + cxt->ftrace_size = pdata->ftrace_size;
    cxt->dump_oops = pdata->dump_oops;
    cxt->ecc_size = pdata->ecc_size;

    paddr = cxt->phys_addr;

    - dump_mem_sz = cxt->size - cxt->console_size;
    + dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size;
    err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz);
    if (err)
    goto fail_out;
    @@ -377,9 +398,14 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
    if (err)
    goto fail_init_cprz;

    - if (!cxt->przs && !cxt->cprz) {
    + err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size);
    + if (err)
    + goto fail_init_fprz;
    +
    + if (!cxt->przs && !cxt->cprz && !cxt->fprz) {
    pr_err("memory size too small, minimum is %lu\n",
    - cxt->console_size + cxt->record_size);
    + cxt->console_size + cxt->record_size +
    + cxt->ftrace_size);
    goto fail_cnt;
    }

    @@ -426,6 +452,8 @@ fail_clear:
    cxt->pstore.bufsize = 0;
    cxt->max_dump_cnt = 0;
    fail_cnt:
    + kfree(cxt->fprz);
    +fail_init_fprz:
    kfree(cxt->cprz);
    fail_init_cprz:
    ramoops_free_przs(cxt);
    @@ -480,6 +508,7 @@ static void ramoops_register_dummy(void)
    dummy_data->mem_address = mem_address;
    dummy_data->record_size = record_size;
    dummy_data->console_size = ramoops_console_size;
    + dummy_data->ftrace_size = ramoops_ftrace_size;
    dummy_data->dump_oops = dump_oops;
    /*
    * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC
    diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
    index dcf805f..af848e1 100644
    --- a/include/linux/pstore_ram.h
    +++ b/include/linux/pstore_ram.h
    @@ -72,6 +72,7 @@ struct ramoops_platform_data {
    unsigned long mem_address;
    unsigned long record_size;
    unsigned long console_size;
    + unsigned long ftrace_size;
    int dump_oops;
    int ecc_size;
    };
    --
    1.7.10.4


    \
     
     \ /
      Last update: 2012-07-10 03:01    [W:3.355 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site