1 /* 2 * RAM Oops/Panic logger 3 * 4 * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com> 5 * Copyright (C) 2011 Kees Cook <keescook@chromium.org> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * version 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19 * 02110-1301 USA 20 * 21 */ 22 23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24 25 #include <linux/kernel.h> 26 #include <linux/err.h> 27 #include <linux/module.h> 28 #include <linux/pstore.h> 29 #include <linux/time.h> 30 #include <linux/io.h> 31 #include <linux/ioport.h> 32 #include <linux/platform_device.h> 33 #include <linux/slab.h> 34 #include <linux/pstore_ram.h> 35 36 #define RAMOOPS_KERNMSG_HDR "====" 37 #define MIN_MEM_SIZE 4096UL 38 39 static ulong record_size = MIN_MEM_SIZE; 40 module_param(record_size, ulong, 0400); 41 MODULE_PARM_DESC(record_size, 42 "size of each dump done on oops/panic"); 43 44 static ulong mem_address; 45 module_param(mem_address, ulong, 0400); 46 MODULE_PARM_DESC(mem_address, 47 "start of reserved RAM used to store oops/panic logs"); 48 49 static ulong mem_size; 50 module_param(mem_size, ulong, 0400); 51 MODULE_PARM_DESC(mem_size, 52 "size of reserved RAM used to store oops/panic logs"); 53 54 static int dump_oops = 1; 55 module_param(dump_oops, int, 0600); 56 MODULE_PARM_DESC(dump_oops, 57 "set to 1 to dump oopses, 0 to only dump panics (default 1)"); 58 59 static int ramoops_ecc; 60 module_param_named(ecc, ramoops_ecc, int, 0600); 61 MODULE_PARM_DESC(ramoops_ecc, 62 "set to 1 to enable ECC support"); 63 64 struct ramoops_context { 65 struct persistent_ram_zone **przs; 66 phys_addr_t phys_addr; 67 unsigned long size; 68 size_t record_size; 69 int dump_oops; 70 bool ecc; 71 unsigned int count; 72 unsigned int max_count; 73 unsigned int read_count; 74 struct pstore_info pstore; 75 }; 76 77 static struct platform_device *dummy; 78 static struct ramoops_platform_data *dummy_data; 79 80 static int ramoops_pstore_open(struct pstore_info *psi) 81 { 82 struct ramoops_context *cxt = psi->data; 83 84 cxt->read_count = 0; 85 return 0; 86 } 87 88 static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, 89 struct timespec *time, 90 char **buf, 91 struct pstore_info *psi) 92 { 93 ssize_t size; 94 struct ramoops_context *cxt = psi->data; 95 struct persistent_ram_zone *prz; 96 97 if (cxt->read_count >= cxt->max_count) 98 return -EINVAL; 99 100 *id = cxt->read_count++; 101 prz = cxt->przs[*id]; 102 103 /* Only supports dmesg output so far. */ 104 *type = PSTORE_TYPE_DMESG; 105 /* TODO(kees): Bogus time for the moment. */ 106 time->tv_sec = 0; 107 time->tv_nsec = 0; 108 109 size = persistent_ram_old_size(prz); 110 *buf = kmalloc(size, GFP_KERNEL); 111 if (*buf == NULL) 112 return -ENOMEM; 113 memcpy(*buf, persistent_ram_old(prz), size); 114 115 return size; 116 } 117 118 static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz) 119 { 120 char *hdr; 121 struct timeval timestamp; 122 size_t len; 123 124 do_gettimeofday(×tamp); 125 hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu\n", 126 (long)timestamp.tv_sec, (long)timestamp.tv_usec); 127 WARN_ON_ONCE(!hdr); 128 len = hdr ? strlen(hdr) : 0; 129 persistent_ram_write(prz, hdr, len); 130 kfree(hdr); 131 132 return len; 133 } 134 135 static int ramoops_pstore_write(enum pstore_type_id type, 136 enum kmsg_dump_reason reason, 137 u64 *id, 138 unsigned int part, 139 size_t size, struct pstore_info *psi) 140 { 141 struct ramoops_context *cxt = psi->data; 142 struct persistent_ram_zone *prz = cxt->przs[cxt->count]; 143 size_t hlen; 144 145 /* Currently ramoops is designed to only store dmesg dumps. */ 146 if (type != PSTORE_TYPE_DMESG) 147 return -EINVAL; 148 149 /* Out of the various dmesg dump types, ramoops is currently designed 150 * to only store crash logs, rather than storing general kernel logs. 151 */ 152 if (reason != KMSG_DUMP_OOPS && 153 reason != KMSG_DUMP_PANIC) 154 return -EINVAL; 155 156 /* Skip Oopes when configured to do so. */ 157 if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) 158 return -EINVAL; 159 160 /* Explicitly only take the first part of any new crash. 161 * If our buffer is larger than kmsg_bytes, this can never happen, 162 * and if our buffer is smaller than kmsg_bytes, we don't want the 163 * report split across multiple records. 164 */ 165 if (part != 1) 166 return -ENOSPC; 167 168 hlen = ramoops_write_kmsg_hdr(prz); 169 if (size + hlen > prz->buffer_size) 170 size = prz->buffer_size - hlen; 171 persistent_ram_write(prz, cxt->pstore.buf, size); 172 173 cxt->count = (cxt->count + 1) % cxt->max_count; 174 175 return 0; 176 } 177 178 static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, 179 struct pstore_info *psi) 180 { 181 struct ramoops_context *cxt = psi->data; 182 183 if (id >= cxt->max_count) 184 return -EINVAL; 185 186 persistent_ram_free_old(cxt->przs[id]); 187 188 return 0; 189 } 190 191 static struct ramoops_context oops_cxt = { 192 .pstore = { 193 .owner = THIS_MODULE, 194 .name = "ramoops", 195 .open = ramoops_pstore_open, 196 .read = ramoops_pstore_read, 197 .write = ramoops_pstore_write, 198 .erase = ramoops_pstore_erase, 199 }, 200 }; 201 202 static int __init ramoops_probe(struct platform_device *pdev) 203 { 204 struct device *dev = &pdev->dev; 205 struct ramoops_platform_data *pdata = pdev->dev.platform_data; 206 struct ramoops_context *cxt = &oops_cxt; 207 int err = -EINVAL; 208 int i; 209 210 /* Only a single ramoops area allowed at a time, so fail extra 211 * probes. 212 */ 213 if (cxt->max_count) 214 goto fail_out; 215 216 if (!pdata->mem_size || !pdata->record_size) { 217 pr_err("The memory size and the record size must be " 218 "non-zero\n"); 219 goto fail_out; 220 } 221 222 pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); 223 pdata->record_size = rounddown_pow_of_two(pdata->record_size); 224 225 /* Check for the minimum memory size */ 226 if (pdata->mem_size < MIN_MEM_SIZE && 227 pdata->record_size < MIN_MEM_SIZE) { 228 pr_err("memory size too small, minimum is %lu\n", 229 MIN_MEM_SIZE); 230 goto fail_out; 231 } 232 233 if (pdata->mem_size < pdata->record_size) { 234 pr_err("The memory size must be larger than the " 235 "records size\n"); 236 goto fail_out; 237 } 238 239 cxt->max_count = pdata->mem_size / pdata->record_size; 240 cxt->count = 0; 241 cxt->size = pdata->mem_size; 242 cxt->phys_addr = pdata->mem_address; 243 cxt->record_size = pdata->record_size; 244 cxt->dump_oops = pdata->dump_oops; 245 cxt->ecc = pdata->ecc; 246 247 cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL); 248 if (!cxt->przs) { 249 err = -ENOMEM; 250 dev_err(dev, "failed to initialize a prz array\n"); 251 goto fail_out; 252 } 253 254 for (i = 0; i < cxt->max_count; i++) { 255 size_t sz = cxt->record_size; 256 phys_addr_t start = cxt->phys_addr + sz * i; 257 258 cxt->przs[i] = persistent_ram_new(start, sz, cxt->ecc); 259 if (IS_ERR(cxt->przs[i])) { 260 err = PTR_ERR(cxt->przs[i]); 261 dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", 262 sz, (unsigned long long)start, err); 263 goto fail_przs; 264 } 265 } 266 267 cxt->pstore.data = cxt; 268 cxt->pstore.bufsize = cxt->przs[0]->buffer_size; 269 cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); 270 spin_lock_init(&cxt->pstore.buf_lock); 271 if (!cxt->pstore.buf) { 272 pr_err("cannot allocate pstore buffer\n"); 273 goto fail_clear; 274 } 275 276 err = pstore_register(&cxt->pstore); 277 if (err) { 278 pr_err("registering with pstore failed\n"); 279 goto fail_buf; 280 } 281 282 /* 283 * Update the module parameter variables as well so they are visible 284 * through /sys/module/ramoops/parameters/ 285 */ 286 mem_size = pdata->mem_size; 287 mem_address = pdata->mem_address; 288 record_size = pdata->record_size; 289 dump_oops = pdata->dump_oops; 290 291 pr_info("attached 0x%lx@0x%llx (%ux0x%zx), ecc: %s\n", 292 cxt->size, (unsigned long long)cxt->phys_addr, 293 cxt->max_count, cxt->record_size, 294 ramoops_ecc ? "on" : "off"); 295 296 return 0; 297 298 fail_buf: 299 kfree(cxt->pstore.buf); 300 fail_clear: 301 cxt->pstore.bufsize = 0; 302 cxt->max_count = 0; 303 fail_przs: 304 for (i = 0; cxt->przs[i]; i++) 305 persistent_ram_free(cxt->przs[i]); 306 kfree(cxt->przs); 307 fail_out: 308 return err; 309 } 310 311 static int __exit ramoops_remove(struct platform_device *pdev) 312 { 313 #if 0 314 /* TODO(kees): We cannot unload ramoops since pstore doesn't support 315 * unregistering yet. 316 */ 317 struct ramoops_context *cxt = &oops_cxt; 318 319 iounmap(cxt->virt_addr); 320 release_mem_region(cxt->phys_addr, cxt->size); 321 cxt->max_count = 0; 322 323 /* TODO(kees): When pstore supports unregistering, call it here. */ 324 kfree(cxt->pstore.buf); 325 cxt->pstore.bufsize = 0; 326 327 return 0; 328 #endif 329 return -EBUSY; 330 } 331 332 static struct platform_driver ramoops_driver = { 333 .remove = __exit_p(ramoops_remove), 334 .driver = { 335 .name = "ramoops", 336 .owner = THIS_MODULE, 337 }, 338 }; 339 340 static int __init ramoops_init(void) 341 { 342 int ret; 343 ret = platform_driver_probe(&ramoops_driver, ramoops_probe); 344 if (ret == -ENODEV) { 345 /* 346 * If we didn't find a platform device, we use module parameters 347 * building platform data on the fly. 348 */ 349 pr_info("platform device not found, using module parameters\n"); 350 dummy_data = kzalloc(sizeof(struct ramoops_platform_data), 351 GFP_KERNEL); 352 if (!dummy_data) 353 return -ENOMEM; 354 dummy_data->mem_size = mem_size; 355 dummy_data->mem_address = mem_address; 356 dummy_data->record_size = record_size; 357 dummy_data->dump_oops = dump_oops; 358 dummy_data->ecc = ramoops_ecc; 359 dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, 360 NULL, 0, dummy_data, 361 sizeof(struct ramoops_platform_data)); 362 363 if (IS_ERR(dummy)) 364 ret = PTR_ERR(dummy); 365 else 366 ret = 0; 367 } 368 369 return ret; 370 } 371 372 static void __exit ramoops_exit(void) 373 { 374 platform_driver_unregister(&ramoops_driver); 375 kfree(dummy_data); 376 } 377 378 module_init(ramoops_init); 379 module_exit(ramoops_exit); 380 381 MODULE_LICENSE("GPL"); 382 MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>"); 383 MODULE_DESCRIPTION("RAM Oops/Panic logger/driver"); 384