1 /* 2 * salinfo.c 3 * 4 * Creates entries in /proc/sal for various system features. 5 * 6 * Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved. 7 * Copyright (c) 2003 Hewlett-Packard Co 8 * Bjorn Helgaas <bjorn.helgaas@hp.com> 9 * 10 * 10/30/2001 jbarnes@sgi.com copied much of Stephane's palinfo 11 * code to create this file 12 * Oct 23 2003 kaos@sgi.com 13 * Replace IPI with set_cpus_allowed() to read a record from the required cpu. 14 * Redesign salinfo log processing to separate interrupt and user space 15 * contexts. 16 * Cache the record across multi-block reads from user space. 17 * Support > 64 cpus. 18 * Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module. 19 * 20 * Jan 28 2004 kaos@sgi.com 21 * Periodically check for outstanding MCA or INIT records. 22 * 23 * Dec 5 2004 kaos@sgi.com 24 * Standardize which records are cleared automatically. 25 * 26 * Aug 18 2005 kaos@sgi.com 27 * mca.c may not pass a buffer, a NULL buffer just indicates that a new 28 * record is available in SAL. 29 * Replace some NR_CPUS by cpus_online, for hotplug cpu. 30 * 31 * Jan 5 2006 kaos@sgi.com 32 * Handle hotplug cpus coming online. 33 * Handle hotplug cpus going offline while they still have outstanding records. 34 * Use the cpu_* macros consistently. 35 * Replace the counting semaphore with a mutex and a test if the cpumask is non-empty. 36 * Modify the locking to make the test for "work to do" an atomic operation. 37 */ 38 39 #include <linux/capability.h> 40 #include <linux/cpu.h> 41 #include <linux/types.h> 42 #include <linux/proc_fs.h> 43 #include <linux/seq_file.h> 44 #include <linux/module.h> 45 #include <linux/smp.h> 46 #include <linux/timer.h> 47 #include <linux/vmalloc.h> 48 #include <linux/semaphore.h> 49 50 #include <asm/sal.h> 51 #include <linux/uaccess.h> 52 53 MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>"); 54 MODULE_DESCRIPTION("/proc interface to IA-64 SAL features"); 55 MODULE_LICENSE("GPL"); 56 57 typedef struct { 58 const char *name; /* name of the proc entry */ 59 unsigned long feature; /* feature bit */ 60 struct proc_dir_entry *entry; /* registered entry (removal) */ 61 } salinfo_entry_t; 62 63 /* 64 * List {name,feature} pairs for every entry in /proc/sal/<feature> 65 * that this module exports 66 */ 67 static const salinfo_entry_t salinfo_entries[]={ 68 { "bus_lock", IA64_SAL_PLATFORM_FEATURE_BUS_LOCK, }, 69 { "irq_redirection", IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT, }, 70 { "ipi_redirection", IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT, }, 71 { "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, }, 72 }; 73 74 #define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries) 75 76 static char *salinfo_log_name[] = { 77 "mca", 78 "init", 79 "cmc", 80 "cpe", 81 }; 82 83 static struct proc_dir_entry *salinfo_proc_entries[ 84 ARRAY_SIZE(salinfo_entries) + /* /proc/sal/bus_lock */ 85 ARRAY_SIZE(salinfo_log_name) + /* /proc/sal/{mca,...} */ 86 (2 * ARRAY_SIZE(salinfo_log_name)) + /* /proc/sal/mca/{event,data} */ 87 1]; /* /proc/sal */ 88 89 /* Some records we get ourselves, some are accessed as saved data in buffers 90 * that are owned by mca.c. 91 */ 92 struct salinfo_data_saved { 93 u8* buffer; 94 u64 size; 95 u64 id; 96 int cpu; 97 }; 98 99 /* State transitions. Actions are :- 100 * Write "read <cpunum>" to the data file. 101 * Write "clear <cpunum>" to the data file. 102 * Write "oemdata <cpunum> <offset> to the data file. 103 * Read from the data file. 104 * Close the data file. 105 * 106 * Start state is NO_DATA. 107 * 108 * NO_DATA 109 * write "read <cpunum>" -> NO_DATA or LOG_RECORD. 110 * write "clear <cpunum>" -> NO_DATA or LOG_RECORD. 111 * write "oemdata <cpunum> <offset> -> return -EINVAL. 112 * read data -> return EOF. 113 * close -> unchanged. Free record areas. 114 * 115 * LOG_RECORD 116 * write "read <cpunum>" -> NO_DATA or LOG_RECORD. 117 * write "clear <cpunum>" -> NO_DATA or LOG_RECORD. 118 * write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA. 119 * read data -> return the INIT/MCA/CMC/CPE record. 120 * close -> unchanged. Keep record areas. 121 * 122 * OEMDATA 123 * write "read <cpunum>" -> NO_DATA or LOG_RECORD. 124 * write "clear <cpunum>" -> NO_DATA or LOG_RECORD. 125 * write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA. 126 * read data -> return the formatted oemdata. 127 * close -> unchanged. Keep record areas. 128 * 129 * Closing the data file does not change the state. This allows shell scripts 130 * to manipulate salinfo data, each shell redirection opens the file, does one 131 * action then closes it again. The record areas are only freed at close when 132 * the state is NO_DATA. 133 */ 134 enum salinfo_state { 135 STATE_NO_DATA, 136 STATE_LOG_RECORD, 137 STATE_OEMDATA, 138 }; 139 140 struct salinfo_data { 141 cpumask_t cpu_event; /* which cpus have outstanding events */ 142 wait_queue_head_t read_wait; 143 u8 *log_buffer; 144 u64 log_size; 145 u8 *oemdata; /* decoded oem data */ 146 u64 oemdata_size; 147 int open; /* single-open to prevent races */ 148 u8 type; 149 u8 saved_num; /* using a saved record? */ 150 enum salinfo_state state :8; /* processing state */ 151 u8 padding; 152 int cpu_check; /* next CPU to check */ 153 struct salinfo_data_saved data_saved[5];/* save last 5 records from mca.c, must be < 255 */ 154 }; 155 156 static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)]; 157 158 static DEFINE_SPINLOCK(data_lock); 159 static DEFINE_SPINLOCK(data_saved_lock); 160 161 /** salinfo_platform_oemdata - optional callback to decode oemdata from an error 162 * record. 163 * @sect_header: pointer to the start of the section to decode. 164 * @oemdata: returns vmalloc area containing the decoded output. 165 * @oemdata_size: returns length of decoded output (strlen). 166 * 167 * Description: If user space asks for oem data to be decoded by the kernel 168 * and/or prom and the platform has set salinfo_platform_oemdata to the address 169 * of a platform specific routine then call that routine. salinfo_platform_oemdata 170 * vmalloc's and formats its output area, returning the address of the text 171 * and its strlen. Returns 0 for success, -ve for error. The callback is 172 * invoked on the cpu that generated the error record. 173 */ 174 int (*salinfo_platform_oemdata)(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size); 175 176 struct salinfo_platform_oemdata_parms { 177 const u8 *efi_guid; 178 u8 **oemdata; 179 u64 *oemdata_size; 180 }; 181 182 static long 183 salinfo_platform_oemdata_cpu(void *context) 184 { 185 struct salinfo_platform_oemdata_parms *parms = context; 186 187 return salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size); 188 } 189 190 static void 191 shift1_data_saved (struct salinfo_data *data, int shift) 192 { 193 memcpy(data->data_saved+shift, data->data_saved+shift+1, 194 (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0])); 195 memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0, 196 sizeof(data->data_saved[0])); 197 } 198 199 /* This routine is invoked in interrupt context. Note: mca.c enables 200 * interrupts before calling this code for CMC/CPE. MCA and INIT events are 201 * not irq safe, do not call any routines that use spinlocks, they may deadlock. 202 * MCA and INIT records are recorded, a timer event will look for any 203 * outstanding events and wake up the user space code. 204 * 205 * The buffer passed from mca.c points to the output from ia64_log_get. This is 206 * a persistent buffer but its contents can change between the interrupt and 207 * when user space processes the record. Save the record id to identify 208 * changes. If the buffer is NULL then just update the bitmap. 209 */ 210 void 211 salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) 212 { 213 struct salinfo_data *data = salinfo_data + type; 214 struct salinfo_data_saved *data_saved; 215 unsigned long flags = 0; 216 int i; 217 int saved_size = ARRAY_SIZE(data->data_saved); 218 219 BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); 220 221 if (irqsafe) 222 spin_lock_irqsave(&data_saved_lock, flags); 223 if (buffer) { 224 for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { 225 if (!data_saved->buffer) 226 break; 227 } 228 if (i == saved_size) { 229 if (!data->saved_num) { 230 shift1_data_saved(data, 0); 231 data_saved = data->data_saved + saved_size - 1; 232 } else 233 data_saved = NULL; 234 } 235 if (data_saved) { 236 data_saved->cpu = smp_processor_id(); 237 data_saved->id = ((sal_log_record_header_t *)buffer)->id; 238 data_saved->size = size; 239 data_saved->buffer = buffer; 240 } 241 } 242 cpumask_set_cpu(smp_processor_id(), &data->cpu_event); 243 if (irqsafe) { 244 wake_up_interruptible(&data->read_wait); 245 spin_unlock_irqrestore(&data_saved_lock, flags); 246 } 247 } 248 249 /* Check for outstanding MCA/INIT records every minute (arbitrary) */ 250 #define SALINFO_TIMER_DELAY (60*HZ) 251 static struct timer_list salinfo_timer; 252 extern void ia64_mlogbuf_dump(void); 253 254 static void 255 salinfo_timeout_check(struct salinfo_data *data) 256 { 257 if (!data->open) 258 return; 259 if (!cpumask_empty(&data->cpu_event)) 260 wake_up_interruptible(&data->read_wait); 261 } 262 263 static void 264 salinfo_timeout(struct timer_list *unused) 265 { 266 ia64_mlogbuf_dump(); 267 salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); 268 salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT); 269 salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY; 270 add_timer(&salinfo_timer); 271 } 272 273 static int 274 salinfo_event_open(struct inode *inode, struct file *file) 275 { 276 if (!capable(CAP_SYS_ADMIN)) 277 return -EPERM; 278 return 0; 279 } 280 281 static ssize_t 282 salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 283 { 284 struct salinfo_data *data = PDE_DATA(file_inode(file)); 285 char cmd[32]; 286 size_t size; 287 int i, n, cpu = -1; 288 289 retry: 290 if (cpumask_empty(&data->cpu_event)) { 291 if (file->f_flags & O_NONBLOCK) 292 return -EAGAIN; 293 if (wait_event_interruptible(data->read_wait, 294 !cpumask_empty(&data->cpu_event))) 295 return -EINTR; 296 } 297 298 n = data->cpu_check; 299 for (i = 0; i < nr_cpu_ids; i++) { 300 if (cpumask_test_cpu(n, &data->cpu_event)) { 301 if (!cpu_online(n)) { 302 cpumask_clear_cpu(n, &data->cpu_event); 303 continue; 304 } 305 cpu = n; 306 break; 307 } 308 if (++n == nr_cpu_ids) 309 n = 0; 310 } 311 312 if (cpu == -1) 313 goto retry; 314 315 ia64_mlogbuf_dump(); 316 317 /* for next read, start checking at next CPU */ 318 data->cpu_check = cpu; 319 if (++data->cpu_check == nr_cpu_ids) 320 data->cpu_check = 0; 321 322 snprintf(cmd, sizeof(cmd), "read %d\n", cpu); 323 324 size = strlen(cmd); 325 if (size > count) 326 size = count; 327 if (copy_to_user(buffer, cmd, size)) 328 return -EFAULT; 329 330 return size; 331 } 332 333 static const struct file_operations salinfo_event_fops = { 334 .open = salinfo_event_open, 335 .read = salinfo_event_read, 336 .llseek = noop_llseek, 337 }; 338 339 static int 340 salinfo_log_open(struct inode *inode, struct file *file) 341 { 342 struct salinfo_data *data = PDE_DATA(inode); 343 344 if (!capable(CAP_SYS_ADMIN)) 345 return -EPERM; 346 347 spin_lock(&data_lock); 348 if (data->open) { 349 spin_unlock(&data_lock); 350 return -EBUSY; 351 } 352 data->open = 1; 353 spin_unlock(&data_lock); 354 355 if (data->state == STATE_NO_DATA && 356 !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) { 357 data->open = 0; 358 return -ENOMEM; 359 } 360 361 return 0; 362 } 363 364 static int 365 salinfo_log_release(struct inode *inode, struct file *file) 366 { 367 struct salinfo_data *data = PDE_DATA(inode); 368 369 if (data->state == STATE_NO_DATA) { 370 vfree(data->log_buffer); 371 vfree(data->oemdata); 372 data->log_buffer = NULL; 373 data->oemdata = NULL; 374 } 375 spin_lock(&data_lock); 376 data->open = 0; 377 spin_unlock(&data_lock); 378 return 0; 379 } 380 381 static long 382 salinfo_log_read_cpu(void *context) 383 { 384 struct salinfo_data *data = context; 385 sal_log_record_header_t *rh; 386 data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer); 387 rh = (sal_log_record_header_t *)(data->log_buffer); 388 /* Clear corrected errors as they are read from SAL */ 389 if (rh->severity == sal_log_severity_corrected) 390 ia64_sal_clear_state_info(data->type); 391 return 0; 392 } 393 394 static void 395 salinfo_log_new_read(int cpu, struct salinfo_data *data) 396 { 397 struct salinfo_data_saved *data_saved; 398 unsigned long flags; 399 int i; 400 int saved_size = ARRAY_SIZE(data->data_saved); 401 402 data->saved_num = 0; 403 spin_lock_irqsave(&data_saved_lock, flags); 404 retry: 405 for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { 406 if (data_saved->buffer && data_saved->cpu == cpu) { 407 sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer); 408 data->log_size = data_saved->size; 409 memcpy(data->log_buffer, rh, data->log_size); 410 barrier(); /* id check must not be moved */ 411 if (rh->id == data_saved->id) { 412 data->saved_num = i+1; 413 break; 414 } 415 /* saved record changed by mca.c since interrupt, discard it */ 416 shift1_data_saved(data, i); 417 goto retry; 418 } 419 } 420 spin_unlock_irqrestore(&data_saved_lock, flags); 421 422 if (!data->saved_num) 423 work_on_cpu_safe(cpu, salinfo_log_read_cpu, data); 424 if (!data->log_size) { 425 data->state = STATE_NO_DATA; 426 cpumask_clear_cpu(cpu, &data->cpu_event); 427 } else { 428 data->state = STATE_LOG_RECORD; 429 } 430 } 431 432 static ssize_t 433 salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 434 { 435 struct salinfo_data *data = PDE_DATA(file_inode(file)); 436 u8 *buf; 437 u64 bufsize; 438 439 if (data->state == STATE_LOG_RECORD) { 440 buf = data->log_buffer; 441 bufsize = data->log_size; 442 } else if (data->state == STATE_OEMDATA) { 443 buf = data->oemdata; 444 bufsize = data->oemdata_size; 445 } else { 446 buf = NULL; 447 bufsize = 0; 448 } 449 return simple_read_from_buffer(buffer, count, ppos, buf, bufsize); 450 } 451 452 static long 453 salinfo_log_clear_cpu(void *context) 454 { 455 struct salinfo_data *data = context; 456 457 ia64_sal_clear_state_info(data->type); 458 return 0; 459 } 460 461 static int 462 salinfo_log_clear(struct salinfo_data *data, int cpu) 463 { 464 sal_log_record_header_t *rh; 465 unsigned long flags; 466 spin_lock_irqsave(&data_saved_lock, flags); 467 data->state = STATE_NO_DATA; 468 if (!cpumask_test_cpu(cpu, &data->cpu_event)) { 469 spin_unlock_irqrestore(&data_saved_lock, flags); 470 return 0; 471 } 472 cpumask_clear_cpu(cpu, &data->cpu_event); 473 if (data->saved_num) { 474 shift1_data_saved(data, data->saved_num - 1); 475 data->saved_num = 0; 476 } 477 spin_unlock_irqrestore(&data_saved_lock, flags); 478 rh = (sal_log_record_header_t *)(data->log_buffer); 479 /* Corrected errors have already been cleared from SAL */ 480 if (rh->severity != sal_log_severity_corrected) 481 work_on_cpu_safe(cpu, salinfo_log_clear_cpu, data); 482 /* clearing a record may make a new record visible */ 483 salinfo_log_new_read(cpu, data); 484 if (data->state == STATE_LOG_RECORD) { 485 spin_lock_irqsave(&data_saved_lock, flags); 486 cpumask_set_cpu(cpu, &data->cpu_event); 487 wake_up_interruptible(&data->read_wait); 488 spin_unlock_irqrestore(&data_saved_lock, flags); 489 } 490 return 0; 491 } 492 493 static ssize_t 494 salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 495 { 496 struct salinfo_data *data = PDE_DATA(file_inode(file)); 497 char cmd[32]; 498 size_t size; 499 u32 offset; 500 int cpu; 501 502 size = sizeof(cmd); 503 if (count < size) 504 size = count; 505 if (copy_from_user(cmd, buffer, size)) 506 return -EFAULT; 507 508 if (sscanf(cmd, "read %d", &cpu) == 1) { 509 salinfo_log_new_read(cpu, data); 510 } else if (sscanf(cmd, "clear %d", &cpu) == 1) { 511 int ret; 512 if ((ret = salinfo_log_clear(data, cpu))) 513 count = ret; 514 } else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) == 2) { 515 if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA) 516 return -EINVAL; 517 if (offset > data->log_size - sizeof(efi_guid_t)) 518 return -EINVAL; 519 data->state = STATE_OEMDATA; 520 if (salinfo_platform_oemdata) { 521 struct salinfo_platform_oemdata_parms parms = { 522 .efi_guid = data->log_buffer + offset, 523 .oemdata = &data->oemdata, 524 .oemdata_size = &data->oemdata_size 525 }; 526 count = work_on_cpu_safe(cpu, salinfo_platform_oemdata_cpu, 527 &parms); 528 } else 529 data->oemdata_size = 0; 530 } else 531 return -EINVAL; 532 533 return count; 534 } 535 536 static const struct file_operations salinfo_data_fops = { 537 .open = salinfo_log_open, 538 .release = salinfo_log_release, 539 .read = salinfo_log_read, 540 .write = salinfo_log_write, 541 .llseek = default_llseek, 542 }; 543 544 static int salinfo_cpu_online(unsigned int cpu) 545 { 546 unsigned int i, end = ARRAY_SIZE(salinfo_data); 547 struct salinfo_data *data; 548 549 spin_lock_irq(&data_saved_lock); 550 for (i = 0, data = salinfo_data; i < end; ++i, ++data) { 551 cpumask_set_cpu(cpu, &data->cpu_event); 552 wake_up_interruptible(&data->read_wait); 553 } 554 spin_unlock_irq(&data_saved_lock); 555 return 0; 556 } 557 558 static int salinfo_cpu_pre_down(unsigned int cpu) 559 { 560 unsigned int i, end = ARRAY_SIZE(salinfo_data); 561 struct salinfo_data *data; 562 563 spin_lock_irq(&data_saved_lock); 564 for (i = 0, data = salinfo_data; i < end; ++i, ++data) { 565 struct salinfo_data_saved *data_saved; 566 int j = ARRAY_SIZE(data->data_saved) - 1; 567 568 for (data_saved = data->data_saved + j; j >= 0; 569 --j, --data_saved) { 570 if (data_saved->buffer && data_saved->cpu == cpu) 571 shift1_data_saved(data, j); 572 } 573 cpumask_clear_cpu(cpu, &data->cpu_event); 574 } 575 spin_unlock_irq(&data_saved_lock); 576 return 0; 577 } 578 579 /* 580 * 'data' contains an integer that corresponds to the feature we're 581 * testing 582 */ 583 static int proc_salinfo_show(struct seq_file *m, void *v) 584 { 585 unsigned long data = (unsigned long)v; 586 seq_puts(m, (sal_platform_features & data) ? "1\n" : "0\n"); 587 return 0; 588 } 589 590 static int __init 591 salinfo_init(void) 592 { 593 struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */ 594 struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ 595 struct proc_dir_entry *dir, *entry; 596 struct salinfo_data *data; 597 int i; 598 599 salinfo_dir = proc_mkdir("sal", NULL); 600 if (!salinfo_dir) 601 return 0; 602 603 for (i=0; i < NR_SALINFO_ENTRIES; i++) { 604 /* pass the feature bit in question as misc data */ 605 *sdir++ = proc_create_single_data(salinfo_entries[i].name, 0, 606 salinfo_dir, proc_salinfo_show, 607 (void *)salinfo_entries[i].feature); 608 } 609 610 for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { 611 data = salinfo_data + i; 612 data->type = i; 613 init_waitqueue_head(&data->read_wait); 614 dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); 615 if (!dir) 616 continue; 617 618 entry = proc_create_data("event", S_IRUSR, dir, 619 &salinfo_event_fops, data); 620 if (!entry) 621 continue; 622 *sdir++ = entry; 623 624 entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir, 625 &salinfo_data_fops, data); 626 if (!entry) 627 continue; 628 *sdir++ = entry; 629 630 *sdir++ = dir; 631 } 632 633 *sdir++ = salinfo_dir; 634 635 timer_setup(&salinfo_timer, salinfo_timeout, 0); 636 salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY; 637 add_timer(&salinfo_timer); 638 639 i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/salinfo:online", 640 salinfo_cpu_online, salinfo_cpu_pre_down); 641 WARN_ON(i < 0); 642 return 0; 643 } 644 645 module_init(salinfo_init); 646