#include #include #include #include #include extern int color_sysctl_add_pages_data; /* litmus/color.c */ static int zero = 0; static int one = 1; /* used as names for server proc entries */ static char *period_str = "period"; static char *wcet_str = "wcet"; /* servers have a WCET and period */ #define NR_SERVER_PARAMS 2 #define CPU_NAME_LEN 3 struct color_cpu_server { char name[CPU_NAME_LEN]; unsigned long wcet; unsigned long period; /* the + 1 is for the sentinel element */ struct ctl_table table[NR_SERVER_PARAMS + 1]; }; static struct color_cpu_server color_cpu_servers[NR_CPUS]; /* the + 1 is for the sentinel element */ static struct ctl_table color_cpu_tables[NR_CPUS + 1]; #define INFO_BUFFER_SIZE 100 static char info_buffer[100]; #define NR_PAGES_INDEX 0 /* location of nr_pages in the table below */ static struct ctl_table color_table[] = { { /* you MUST update NR_PAGES_INDEX if you move this entry */ .procname = "nr_pages", .mode = 0444, .proc_handler = color_nr_pages_handler, .data = NULL, /* dynamically set later */ .maxlen = 0, /* also set later */ }, { .procname = "servers", .mode = 0555, .child = color_cpu_tables, }, { .procname = "add_pages", .data = &color_sysctl_add_pages_data, .maxlen = sizeof(int), .mode = 0644, .proc_handler = color_add_pages_handler, .extra1 = &zero, .extra2 = &one, }, { .procname = "cache_info", .mode = 0444, .proc_handler = proc_dostring, .data = info_buffer, .maxlen = INFO_BUFFER_SIZE, }, { } }; static struct ctl_table litmus_table[] = { { .procname = "color", .mode = 0555, .child = color_table, }, { } }; static struct ctl_table litmus_dir_table[] = { { .procname = "litmus", .mode = 0555, .child = litmus_table, }, { } }; int color_server_params(int cpu, unsigned long *wcet, unsigned long *period) { struct color_cpu_server *svr; if (cpu >= num_online_cpus()) { printk(KERN_WARNING "Cannot access illegal CPU: %d\n", cpu); return -EFAULT; } svr = &color_cpu_servers[cpu]; if (svr->wcet == 0 || svr->period == 0) { printk(KERN_WARNING "Server %d is uninitialized!\n", cpu); return -EPERM; } *wcet = svr->wcet; *period = svr->period; TRACE("For %d: %lu, %lu\n", cpu, svr->wcet, svr->period); return 0; } /* must be called AFTER nr_colors is set */ static int __init init_sysctl_nr_colors(void) { int ret = 0, maxlen = ONE_COLOR_LEN * color_cache_info.nr_colors; color_table[NR_PAGES_INDEX].data = kmalloc(maxlen, GFP_KERNEL); if (!color_table[NR_PAGES_INDEX].data) { printk(KERN_WARNING "Could not allocate nr_pages buffer.\n"); ret = -ENOMEM; goto out; } color_table[NR_PAGES_INDEX].maxlen = maxlen; out: return ret; } static void __init init_server_entry(struct ctl_table *entry, unsigned long *parameter, char *name) { entry->procname = name; entry->mode = 0666; entry->proc_handler = proc_doulongvec_minmax; entry->data = parameter; entry->maxlen = sizeof(*parameter); } static int __init init_cpu_entry(struct ctl_table *cpu_table, struct color_cpu_server *svr, int cpu) { struct ctl_table *entry = svr->table; printk(KERN_INFO "Creating cpu %d\n", cpu); init_server_entry(entry, &svr->wcet, wcet_str); entry++; init_server_entry(entry, &svr->period, period_str); /* minus one for the null byte */ snprintf(svr->name, CPU_NAME_LEN - 1, "%d", cpu); cpu_table->procname = svr->name; cpu_table->mode = 0555; cpu_table->child = svr->table; return 0; } static int __init init_server_entries(void) { int cpu, err = 0; struct ctl_table *cpu_table; struct color_cpu_server *svr; for_each_online_cpu(cpu) { cpu_table = &color_cpu_tables[cpu]; svr = &color_cpu_servers[cpu]; err = init_cpu_entry(cpu_table, svr, cpu); if (err) goto out; } out: return err; } static struct ctl_table_header *litmus_sysctls; static int __init litmus_sysctl_init(void) { int ret = 0; printk(KERN_INFO "Registering LITMUS^RT proc sysctl.\n"); litmus_sysctls = register_sysctl_table(litmus_dir_table); if (!litmus_sysctls) { printk(KERN_WARNING "Could not register LITMUS^RT sysctl.\n"); ret = -EFAULT; goto out; } ret = init_sysctl_nr_colors(); if (ret) goto out; ret = init_server_entries(); if (ret) goto out; snprintf(info_buffer, INFO_BUFFER_SIZE, "Cache size\t: %lu B\n" "Line size\t: %lu B\n" "Page size\t: %lu B\n" "Ways\t\t: %lu\n" "Sets\t\t: %lu\n" "Colors\t\t: %lu", color_cache_info.size, color_cache_info.line_size, PAGE_SIZE, color_cache_info.ways, color_cache_info.sets, color_cache_info.nr_colors); out: return ret; } module_init(litmus_sysctl_init);