--- src/arch/alpha/Kconfig.orig 2008-04-11 19:24:19.000000000 -0400 +++ src/arch/alpha/Kconfig 2008-04-11 19:28:07.000000000 -0400 @@ -616,6 +616,32 @@ config VERBOSE_MCHECK_ON Take the default (1) unless you want more control or more info. +config ALPHA_UAC_SYSCTL + bool "Configure UAC policy via sysctl" + depends on SYSCTL + default y + ---help--- + Configuring the UAC (unaligned access control) policy on a Linux + system usually involves setting a compile time define. If you say + Y here, you will be able to modify the UAC policy at runtime using + the /proc interface. + + The UAC policy defines the action Linux should take when an + unaligned memory access occurs. The action can include printing a + warning message (NOPRINT), sending a signal to the offending + program to help developers debug their applications (SIGBUS), or + disabling the transparent fixing (NOFIX). + + The sysctls will be initialized to the compile-time defined UAC + policy. You can change these manually, or with the sysctl(8) + userspace utility. + + To disable the warning messages at runtime, you would use + + echo 1 > /proc/sys/kernel/uac/noprint + + This is pretty harmless. Say Y if you're not sure. + source "drivers/pci/Kconfig" source "drivers/eisa/Kconfig" --- src/arch/alpha/kernel/traps.c.orig 2008-04-11 19:24:50.000000000 -0400 +++ src/arch/alpha/kernel/traps.c 2008-04-12 09:37:05.000000000 -0400 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,39 @@ static char * ireg_name[] = {"v0", "t0", "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"}; #endif +#ifdef CONFIG_ALPHA_UAC_SYSCTL +static struct ctl_table_header *uac_sysctl_header; + +/* /proc/sys/kernel/uac */ +enum +{ + /* UAC policy on Alpha */ + KERN_UAC_NOPRINT=1, /* int: printk() on unaligned access */ + KERN_UAC_SIGBUS=2, /* int: send SIGBUS on unaligned access */ + KERN_UAC_NOFIX=3, /* int: don't fix the unaligned access */ +}; + +static int enabled_noprint = 0; +static int enabled_sigbus = 0; +static int enabled_nofix = 0; + +ctl_table uac_table[] = { + {KERN_UAC_NOPRINT, "noprint", &enabled_noprint, sizeof (int), 0644, NULL, NULL, &proc_dointvec}, + {KERN_UAC_SIGBUS, "sigbus", &enabled_sigbus, sizeof (int), 0644, NULL, NULL, &proc_dointvec}, + {KERN_UAC_NOFIX, "nofix", &enabled_nofix, sizeof (int), 0644, NULL, NULL, &proc_dointvec}, + {0} +}; + +static int __init init_uac_sysctl(void) +{ + /* Initialize sysctls with the #defined UAC policy */ + enabled_noprint = (test_thread_flag (TIF_UAC_NOPRINT)) ? 1 : 0; + enabled_sigbus = (test_thread_flag (TIF_UAC_SIGBUS)) ? 1 : 0; + enabled_nofix = (test_thread_flag (TIF_UAC_NOFIX)) ? 1 : 0; + return 0; +} +#endif + static void dik_show_code(unsigned int *pc) { @@ -780,7 +814,11 @@ do_entUnaUser(void __user * va, unsigned /* Check the UAC bits to decide what the user wants us to do with the unaliged access. */ +#ifndef CONFIG_ALPHA_UAC_SYSCTL if (!test_thread_flag (TIF_UAC_NOPRINT)) { +#else /* CONFIG_ALPHA_UAC_SYSCTL */ + if (!(enabled_noprint)) { +#endif /* CONFIG_ALPHA_UAC_SYSCTL */ if (cnt >= 5 && jiffies - last_time > 5*HZ) { cnt = 0; } @@ -791,10 +829,18 @@ do_entUnaUser(void __user * va, unsigned } last_time = jiffies; } +#ifndef CONFIG_ALPHA_UAC_SYSCTL if (test_thread_flag (TIF_UAC_SIGBUS)) +#else /* CONFIG_ALPHA_UAC_SYSCTL */ + if (enabled_sigbus) +#endif /* CONFIG_ALPHA_UAC_SYSCTL */ goto give_sigbus; /* Not sure why you'd want to use this, but... */ +#ifndef CONFIG_ALPHA_UAC_SYSCTL if (test_thread_flag (TIF_UAC_NOFIX)) +#else /* CONFIG_ALPHA_UAC_SYSCTL */ + if (enabled_nofix) +#endif /* CONFIG_ALPHA_UAC_SYSCTL */ return; /* Don't bother reading ds in the access check since we already @@ -1089,3 +1135,7 @@ trap_init(void) wrent(entSys, 5); wrent(entDbg, 6); } + +#ifdef CONFIG_ALPHA_UAC_SYSCTL +__initcall(init_uac_sysctl); +#endif --- src/kernel/sysctl.c.orig 2008-04-11 19:26:51.000000000 -0400 +++ src/kernel/sysctl.c 2008-04-11 19:38:44.000000000 -0400 @@ -155,6 +155,10 @@ static int proc_dointvec_taint(struct ct void __user *buffer, size_t *lenp, loff_t *ppos); #endif +#ifdef CONFIG_ALPHA_UAC_SYSCTL +extern ctl_table uac_table[]; +#endif + static struct ctl_table root_table[]; static struct ctl_table_header root_table_header = { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; @@ -221,6 +225,14 @@ static struct ctl_table root_table[] = { * NOTE: do not add new entries to this table unless you have read * Documentation/sysctl/ctl_unnumbered.txt */ +#ifdef CONFIG_ALPHA_UAC_SYSCTL + { + .ctl_name = CTL_UNNUMBERED, + .procname = "uac", + .mode = 0555, + .child = uac_table, + }, +#endif /* CONFIG_ALPHA_UAC_SYSCTL */ { .ctl_name = 0 } };