[PATCH] x86-64: Allow to run a program when a machine check event is detected

When a machine check event is detected (including a AMD RevF threshold
overflow event) allow to run a "trigger" program. This allows user space
to react to such events sooner.

The trigger is configured using a new trigger entry in the
machinecheck sysfs interface. It is currently shared between
all CPUs.

I also fixed the AMD threshold handler to run the machine
check polling code immediately to actually log any events
that might have caused the threshold interrupt.

Also added some documentation for the mce sysfs interface.

Signed-off-by: Andi Kleen <ak@suse.de>
This commit is contained in:
Andi Kleen
2007-02-13 13:26:23 +01:00
committed by Andi Kleen
parent 24ce0e96f2
commit a98f0dd34d
5 changed files with 160 additions and 26 deletions
+30 -14
View File
@@ -217,7 +217,10 @@ static int wait_for_helper(void *data)
sub_info->retval = ret;
}
complete(sub_info->complete);
if (sub_info->wait < 0)
kfree(sub_info);
else
complete(sub_info->complete);
return 0;
}
@@ -239,6 +242,9 @@ static void __call_usermodehelper(struct work_struct *work)
pid = kernel_thread(____call_usermodehelper, sub_info,
CLONE_VFORK | SIGCHLD);
if (wait < 0)
return;
if (pid < 0) {
sub_info->retval = pid;
complete(sub_info->complete);
@@ -253,6 +259,9 @@ static void __call_usermodehelper(struct work_struct *work)
* @envp: null-terminated environment list
* @session_keyring: session keyring for process (NULL for an empty keyring)
* @wait: wait for the application to finish and return status.
* when -1 don't wait at all, but you get no useful error back when
* the program couldn't be exec'ed. This makes it safe to call
* from interrupt context.
*
* Runs a user-space application. The application is started
* asynchronously if wait is not set, and runs as a child of keventd.
@@ -265,17 +274,8 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
struct key *session_keyring, int wait)
{
DECLARE_COMPLETION_ONSTACK(done);
struct subprocess_info sub_info = {
.work = __WORK_INITIALIZER(sub_info.work,
__call_usermodehelper),
.complete = &done,
.path = path,
.argv = argv,
.envp = envp,
.ring = session_keyring,
.wait = wait,
.retval = 0,
};
struct subprocess_info *sub_info;
int retval;
if (!khelper_wq)
return -EBUSY;
@@ -283,9 +283,25 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
if (path[0] == '\0')
return 0;
queue_work(khelper_wq, &sub_info.work);
sub_info = kzalloc(sizeof(struct subprocess_info), GFP_ATOMIC);
if (!sub_info)
return -ENOMEM;
INIT_WORK(&sub_info->work, __call_usermodehelper);
sub_info->complete = &done;
sub_info->path = path;
sub_info->argv = argv;
sub_info->envp = envp;
sub_info->ring = session_keyring;
sub_info->wait = wait;
queue_work(khelper_wq, &sub_info->work);
if (wait < 0) /* task has freed sub_info */
return 0;
wait_for_completion(&done);
return sub_info.retval;
retval = sub_info->retval;
kfree(sub_info);
return retval;
}
EXPORT_SYMBOL(call_usermodehelper_keys);