From patchwork Tue May 22 14:17:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 8880 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A827323F0A for ; Tue, 22 May 2012 14:20:43 +0000 (UTC) Received: from mail-yw0-f52.google.com (mail-yw0-f52.google.com [209.85.213.52]) by fiordland.canonical.com (Postfix) with ESMTP id 62199A18B74 for ; Tue, 22 May 2012 14:20:43 +0000 (UTC) Received: by yhpp61 with SMTP id p61so6656685yhp.11 for ; Tue, 22 May 2012 07:20:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=tQUlPkXmC355QjdboszD8BEM5ok3IwLzL+hMmNn2ZCY=; b=NHLG5Cvin9OGo/swL4WnNUPVO7B48skHOXyNrCCLIaQLG84ORfD7GmP69K4PfopgyB xHDgoWKCcSh9hmd4h/b/qfF4cxKyUkdXQ1PhN4FiiL2RRIDhvXT2GXzsPTELYkF0d4lp OZTURdq8cjtSC+4mC6/EDvLKK5NCmdWPR9uhhTuXngB+wg+pa3WM8tQOlLkhsMd/Jsql btqy6VvNVn+NJPeJ7T7OET4u/9EeIuIGR6agRU/gLKn3LtCCPt95pvodaawvUdL7sDB8 Vx7MvP8S2dLOMV2qknYpYdvsMSYFt7wLKrXt+KMjBZ+/anSn/yRbhYbd7bnKIa1rSFfi mq2w== Received: by 10.50.222.202 with SMTP id qo10mr9881583igc.0.1337696442594; Tue, 22 May 2012 07:20:42 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.35.72 with SMTP id o8csp369544ibd; Tue, 22 May 2012 07:20:42 -0700 (PDT) Received: by 10.68.228.2 with SMTP id se2mr80829417pbc.109.1337696441601; Tue, 22 May 2012 07:20:41 -0700 (PDT) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by mx.google.com with ESMTPS id s4si31657300pbc.45.2012.05.22.07.20.41 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 22 May 2012 07:20:41 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) client-ip=209.85.160.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) smtp.mail=anton.vorontsov@linaro.org Received: by mail-pb0-f50.google.com with SMTP id rr4so10070402pbb.37 for ; Tue, 22 May 2012 07:20:41 -0700 (PDT) Received: by 10.68.196.201 with SMTP id io9mr12018438pbc.126.1337696441319; Tue, 22 May 2012 07:20:41 -0700 (PDT) Received: from localhost (c-71-204-165-222.hsd1.ca.comcast.net. [71.204.165.222]) by mx.google.com with ESMTPS id x1sm26852267pbp.50.2012.05.22.07.20.38 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 22 May 2012 07:20:40 -0700 (PDT) From: Anton Vorontsov To: Greg Kroah-Hartman , Kees Cook , Colin Cross , Tony Luck Cc: Arnd Bergmann , John Stultz , Shuah Khan , arve@android.com, Rebecca Schultz Zavin , Jesper Juhl , Randy Dunlap , Stephen Boyd , Thomas Meyer , Andrew Morton , Marco Stornelli , WANG Cong , linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linaro-kernel@lists.linaro.org, patches@linaro.org, kernel-team@android.com Subject: [PATCH 10/16] pstore/ram: Add console messages handling Date: Tue, 22 May 2012 07:17:53 -0700 Message-Id: <1337696279-8994-10-git-send-email-anton.vorontsov@linaro.org> X-Mailer: git-send-email 1.7.9.2 In-Reply-To: <20120522141717.GA31574@lizard> References: <20120522141717.GA31574@lizard> X-Gm-Message-State: ALoCoQnEKcaqYmiI2Fh3UViRc8yLQCSqCsMbahSndyAB9mVJ/olt4RzA2tnwgOwi8EASF0KzO11w The console log size is configurable via ramoops.console_size module option, and the log itself is available via /console-ramoops file. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook --- fs/pstore/ram.c | 107 ++++++++++++++++++++++++++++++++++++++------ include/linux/pstore_ram.h | 1 + 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 6dc9e96..4e1ba41 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -41,6 +41,10 @@ module_param(record_size, ulong, 0400); MODULE_PARM_DESC(record_size, "size of each dump done on oops/panic"); +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 mem_address; module_param(mem_address, ulong, 0400); MODULE_PARM_DESC(mem_address, @@ -63,9 +67,11 @@ MODULE_PARM_DESC(ramoops_ecc, struct ramoops_context { struct persistent_ram_zone **przs; + struct persistent_ram_zone *cprz; phys_addr_t phys_addr; unsigned long size; size_t record_size; + size_t console_size; int dump_oops; bool ecc; unsigned int count; @@ -96,6 +102,9 @@ ramoops_get_dump_prz(u64 id, enum pstore_type_id *type, return NULL; prz = cxt->przs[id]; + + /* Update old/shadowed buffer. */ + persistent_ram_save_old(prz); if (!persistent_ram_old_size(prz)) return NULL; @@ -104,6 +113,19 @@ ramoops_get_dump_prz(u64 id, enum pstore_type_id *type, return prz; } +static struct persistent_ram_zone * +ramoops_get_console_prz(u64 id, enum pstore_type_id *type, + struct ramoops_context *cxt) +{ + if (id >= cxt->max_count) + return NULL; + + *type = PSTORE_TYPE_CONSOLE; + cxt->read_count = cxt->max_count; + + return cxt->cprz; +} + static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, struct timespec *time, char **buf, @@ -117,14 +139,14 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, prz = ramoops_get_dump_prz(*id, type, cxt); if (!prz) + prz = ramoops_get_console_prz(*id, type, cxt); + if (!prz) return 0; /* TODO(kees): Bogus time for the moment. */ time->tv_sec = 0; time->tv_nsec = 0; - /* Update old/shadowed buffer. */ - persistent_ram_save_old(prz); size = persistent_ram_old_size(prz); *buf = kmalloc(size, GFP_KERNEL); if (*buf == NULL) @@ -161,7 +183,13 @@ static int ramoops_pstore_write(enum pstore_type_id type, struct persistent_ram_zone *prz = cxt->przs[cxt->count]; size_t hlen; - /* Currently ramoops is designed to only store dmesg dumps. */ + if (type == PSTORE_TYPE_CONSOLE) { + if (!cxt->cprz) + return -ENOMEM; + persistent_ram_write(cxt->cprz, cxt->pstore.buf, size); + return 0; + } + if (type != PSTORE_TYPE_DMESG) return -EINVAL; @@ -198,12 +226,17 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, struct pstore_info *psi) { struct ramoops_context *cxt = psi->data; + struct persistent_ram_zone *prz; - if (id >= cxt->max_dump_count) + if (id >= cxt->max_dump_count && id < cxt->max_count) + prz = cxt->cprz; + else if (id < cxt->max_dump_count) + prz = cxt->przs[id]; + else return -EINVAL; - persistent_ram_free_old(cxt->przs[id]); - persistent_ram_zap(cxt->przs[id]); + persistent_ram_free_old(prz); + persistent_ram_zap(prz); return 0; } @@ -272,6 +305,35 @@ fail_prz: return err; } +static void ramoops_free_cprz(struct ramoops_context *cxt) +{ + kfree(cxt->cprz); +} + +static int ramoops_init_cprz(struct device *dev, struct ramoops_context *cxt, + phys_addr_t *paddr, size_t console_mem_sz) +{ + if (!console_mem_sz) + return 0; + + if (*paddr + console_mem_sz > *paddr + cxt->size) + return -ENOMEM; + + cxt->cprz = persistent_ram_new(*paddr, console_mem_sz, cxt->ecc); + if (IS_ERR(cxt->cprz)) { + int err = PTR_ERR(cxt->cprz); + + dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", + console_mem_sz, (unsigned long long)*paddr, err); + return err; + } + + *paddr += console_mem_sz; + cxt->max_count++; + + return 0; +} + static int __init ramoops_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -287,35 +349,51 @@ static int __init ramoops_probe(struct platform_device *pdev) if (cxt->max_dump_count) goto fail_out; - if (!pdata->mem_size || !pdata->record_size) { - pr_err("The memory size and the record size must be " + if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size)) { + pr_err("The memory size and the record/console size must be " "non-zero\n"); goto fail_out; } 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); cxt->max_count = 0; cxt->count = 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->dump_oops = pdata->dump_oops; cxt->ecc = pdata->ecc; paddr = cxt->phys_addr; - dump_mem_sz = cxt->size; + dump_mem_sz = cxt->size - cxt->console_size; err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); - if (err) { + if (err) + goto fail_out; + + err = ramoops_init_cprz(dev, cxt, &paddr, cxt->console_size); + if (err) + goto fail_init_cprz; + + if (!cxt->max_count) { pr_err("memory size too small, minimum is %lu\n", - cxt->record_size); + cxt->console_size + cxt->record_size); goto fail_count; } cxt->pstore.data = cxt; - cxt->pstore.bufsize = cxt->przs[0]->buffer_size; + /* + * Console can handle any buffer size, so prefer dumps buffer + * size since usually it is smaller. + */ + if (cxt->przs) + cxt->pstore.bufsize = cxt->przs[0]->buffer_size; + else + cxt->pstore.bufsize = cxt->cprz->buffer_size; cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); spin_lock_init(&cxt->pstore.buf_lock); if (!cxt->pstore.buf) { @@ -324,7 +402,7 @@ static int __init ramoops_probe(struct platform_device *pdev) } err = pstore_register(&cxt->pstore); - if (err || !cxt->max_count) { + if (err) { pr_err("registering with pstore failed\n"); goto fail_buf; } @@ -352,6 +430,8 @@ fail_clear: cxt->max_count = 0; cxt->max_dump_count = 0; fail_count: + ramoops_free_cprz(cxt); +fail_init_cprz: ramoops_free_przs(cxt); fail_out: return err; @@ -403,6 +483,7 @@ static int __init ramoops_init(void) dummy_data->mem_size = mem_size; dummy_data->mem_address = mem_address; dummy_data->record_size = record_size; + dummy_data->console_size = ramoops_console_size; dummy_data->dump_oops = dump_oops; dummy_data->ecc = ramoops_ecc; dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index 3b823d4..9385d41 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -93,6 +93,7 @@ struct ramoops_platform_data { unsigned long mem_size; unsigned long mem_address; unsigned long record_size; + unsigned long console_size; int dump_oops; bool ecc; };