1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation, version 2 of the
8  * License.
9  */
10 
11 #ifndef _MCTELEM_H
12 
13 #define	_MCTELEM_H
14 
15 #include <xen/init.h>
16 #include <xen/smp.h>
17 #include <asm/traps.h>
18 
19 /* Helper functions used for collecting error telemetry.
20  *
21  * mctelem_init preallocates a number of data areas for use during
22  * machine check data "logout".  Two classes are distinguished -
23  * urgent uses, intended for use from machine check exception handlers,
24  * and non-urgent uses intended for use from error pollers.
25  * Associated with each logout entry of whatever class is a data area
26  * sized per the single argument to mctelem_init.  mctelem_init should be
27  * called from MCA init code before anybody has the chance to change the
28  * machine check vector with mcheck_mca_logout or to use mcheck_mca_logout.
29  *
30  * To reserve an entry of a given class for use in logout, call
31  * mctelem_reserve (or use the common handler functions which do all this
32  * for you).  This returns an opaque cookie, or NULL if no elements are
33  * available.  Elements are reserved with an atomic operation so no deadlock
34  * will occur if, for example, a machine check exception interrupts a
35  * scheduled error poll.  The implementation will raid free non-urgent
36  * entries if all urgent entries are in use when an urgent request is received.
37  * Once an entry is reserved the caller must eventually perform exactly
38  * one of two actions: mctelem_commit or mctelem_dismiss.
39  *
40  * On mctelem_commit the entry is appended to a processing list; mctelem_dismiss
41  * frees the element without processing.  After either call the cookie
42  * must not be referenced again.
43  *
44  * To consume committed telemetry call mctelem_consume_oldest_begin
45  * which will return a cookie referencing the oldest (first committed)
46  * entry of the requested class.  Access the associated data using
47  * mctelem_dataptr and when finished use mctelem_consume_oldest_end - in the
48  * begin .. end bracket you are guaranteed that the entry can't be freed
49  * even if it is ack'd elsewhere).  Once the ultimate consumer of the
50  * telemetry has processed it to stable storage it should acknowledge
51  * the telemetry quoting the cookie id, at which point we will free
52  * the element from the processing list.
53  */
54 
55 typedef struct mctelem_cookie *mctelem_cookie_t;
56 
57 typedef enum mctelem_class {
58 	MC_URGENT,
59 	MC_NONURGENT
60 } mctelem_class_t;
61 
62 extern void mctelem_init(unsigned int);
63 extern mctelem_cookie_t mctelem_reserve(mctelem_class_t);
64 extern void *mctelem_dataptr(mctelem_cookie_t);
65 extern void mctelem_commit(mctelem_cookie_t);
66 extern void mctelem_dismiss(mctelem_cookie_t);
67 extern mctelem_cookie_t mctelem_consume_oldest_begin(mctelem_class_t);
68 extern void mctelem_consume_oldest_end(mctelem_cookie_t);
69 extern void mctelem_ack(mctelem_class_t, mctelem_cookie_t);
70 extern void mctelem_defer(mctelem_cookie_t, bool lmce);
71 extern void mctelem_process_deferred(unsigned int,
72                                      int (*)(mctelem_cookie_t), bool lmce);
73 bool mctelem_has_deferred(unsigned int);
74 bool mctelem_has_deferred_lmce(unsigned int cpu);
75 
76 #endif
77