rtasd.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 314 行
C
314 行
/* * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Communication to userspace based on kernel/printk.c */#include <linux/types.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/poll.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/rtas.h>#include <asm/prom.h>#if 0#define DEBUG(A...) printk(KERN_ERR A)#else#define DEBUG(A...)#endifstatic spinlock_t rtas_log_lock = SPIN_LOCK_UNLOCKED;DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait);#define LOG_NUMBER 64 /* must be a power of two */#define LOG_NUMBER_MASK (LOG_NUMBER-1)static char *rtas_log_buf;static unsigned long rtas_log_start;static unsigned long rtas_log_size;static int surveillance_requested;static unsigned int rtas_event_scan_rate;static unsigned int rtas_error_log_max;#define EVENT_SCAN_ALL_EVENTS 0xf0000000#define SURVEILLANCE_TOKEN 9000#define SURVEILLANCE_TIMEOUT 1#define SURVEILLANCE_SCANRATE 1/* * Since we use 32 bit RTAS, the physical address of this must be below * 4G or else bad things happen. Allocate this in the kernel data and * make it big enough. */#define RTAS_ERROR_LOG_MAX 1024static unsigned char logdata[RTAS_ERROR_LOG_MAX];static int rtas_log_open(struct inode * inode, struct file * file){ return 0;}static int rtas_log_release(struct inode * inode, struct file * file){ return 0;}static ssize_t rtas_log_read(struct file * file, char * buf, size_t count, loff_t *ppos){ int error; char *tmp; unsigned long offset; if (!buf || count < rtas_error_log_max) return -EINVAL; count = rtas_error_log_max; error = verify_area(VERIFY_WRITE, buf, count); if (error) return -EINVAL; tmp = kmalloc(rtas_error_log_max, GFP_KERNEL); if (!tmp) return -ENOMEM; error = wait_event_interruptible(rtas_log_wait, rtas_log_size); if (error) goto out; spin_lock(&rtas_log_lock); offset = rtas_error_log_max * (rtas_log_start & LOG_NUMBER_MASK); memcpy(tmp, &rtas_log_buf[offset], count); rtas_log_start += 1; rtas_log_size -= 1; spin_unlock(&rtas_log_lock); copy_to_user(buf, tmp, count); error = count;out: kfree(tmp); return error;}static unsigned int rtas_log_poll(struct file *file, poll_table * wait){ poll_wait(file, &rtas_log_wait, wait); if (rtas_log_size) return POLLIN | POLLRDNORM; return 0;}struct file_operations proc_rtas_log_operations = { read: rtas_log_read, poll: rtas_log_poll, open: rtas_log_open, release: rtas_log_release,};static void log_rtas(char *buf){ unsigned long offset; DEBUG("logging rtas event\n"); spin_lock(&rtas_log_lock); offset = rtas_error_log_max * ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); memcpy(&rtas_log_buf[offset], buf, rtas_error_log_max); if (rtas_log_size < LOG_NUMBER) rtas_log_size += 1; else rtas_log_start += 1; spin_unlock(&rtas_log_lock); wake_up_interruptible(&rtas_log_wait);}static int enable_surveillance(void){ int error; error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN, 0, SURVEILLANCE_TIMEOUT); if (error) { printk(KERN_ERR "rtasd: could not enable surveillance\n"); return -1; } rtas_event_scan_rate = SURVEILLANCE_SCANRATE; return 0;}static int get_eventscan_parms(void){ struct device_node *node; int *ip; node = find_path_device("/rtas"); ip = (int *)get_property(node, "rtas-event-scan-rate", NULL); if (ip == NULL) { printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); return -1; } rtas_event_scan_rate = *ip; DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate); ip = (int *)get_property(node, "rtas-error-log-max", NULL); if (ip == NULL) { printk(KERN_ERR "rtasd: no rtas-error-log-max\n"); return -1; } rtas_error_log_max = *ip; DEBUG("rtas-error-log-max %d\n", rtas_error_log_max); if (rtas_error_log_max > RTAS_ERROR_LOG_MAX) { printk(KERN_ERR "rtasd: truncated error log from %d to %d bytes\n", rtas_error_log_max, RTAS_ERROR_LOG_MAX); rtas_error_log_max = RTAS_ERROR_LOG_MAX; } return 0;}extern long sys_sched_get_priority_max(int policy);static int rtasd(void *unused){ int cpu = 0; int error; int first_pass = 1; int event_scan = rtas_token("event-scan"); if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1) goto error; rtas_log_buf = vmalloc(rtas_error_log_max*LOG_NUMBER); if (!rtas_log_buf) { printk(KERN_ERR "rtasd: no memory\n"); goto error; } DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2); daemonize(); sigfillset(¤t->blocked); sprintf(current->comm, "rtasd");#if 0 /* Rusty unreal time task */ current->policy = SCHED_FIFO; current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1;#endif cpu = 0; set_cpus_allowed(current, 1UL << cpu_logical_map(cpu)); while(1) { do { memset(logdata, 0, rtas_error_log_max); error = rtas_call(event_scan, 4, 1, NULL, EVENT_SCAN_ALL_EVENTS, 0, __pa(logdata), rtas_error_log_max); if (error == -1) { printk(KERN_ERR "event-scan failed\n"); break; } if (error == 0) log_rtas(logdata); } while(error == 0); DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id()); cpu++; if (cpu >= smp_num_cpus) { if (first_pass && surveillance_requested) { DEBUG("enabling surveillance\n"); if (enable_surveillance()) goto error_vfree; DEBUG("surveillance enabled\n"); } first_pass = 0; cpu = 0; } set_cpus_allowed(current, 1UL << cpu_logical_map(cpu)); /* Check all cpus for pending events before sleeping*/ if (!first_pass) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((HZ*60/rtas_event_scan_rate) / 2); } }error_vfree: vfree(rtas_log_buf);error: /* Should delete proc entries */ return -EINVAL;}static int __init rtas_init(void){ struct proc_dir_entry *rtas_dir, *entry; rtas_dir = proc_mkdir("rtas", 0); if (!rtas_dir) { printk(KERN_ERR "Failed to create rtas proc directory\n"); } else { entry = create_proc_entry("error_log", S_IRUSR, rtas_dir); if (entry) entry->proc_fops = &proc_rtas_log_operations; else printk(KERN_ERR "Failed to create rtas/error_log proc entry\n"); } if (kernel_thread(rtasd, 0, CLONE_FS) < 0) printk(KERN_ERR "Failed to start RTAS daemon\n"); printk(KERN_ERR "RTAS daemon started\n"); return 0;}static int __init surveillance_setup(char *str){ int i; if (get_option(&str,&i)) { if (i == 1) surveillance_requested = 1; } return 1;}__initcall(rtas_init);__setup("surveillance=", surveillance_setup);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?