debuggers.hg

changeset 20998:50ea24db1f88

x86/mcheck: do not blindly de-reference dom0 et al

Since machine checks and CMCIs can happen before Dom0 even gets
constructed, the handlers of these events have to avoid de-referencing
respective pointers without checking.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 17 12:04:50 2010 +0000 (2010-02-17)
parents e99d20837ac0
children 220e4996f0e8
files xen/arch/x86/cpu/mcheck/amd_nonfatal.c xen/arch/x86/cpu/mcheck/mce.c xen/arch/x86/cpu/mcheck/mce.h xen/arch/x86/cpu/mcheck/mce_intel.c xen/arch/x86/cpu/mcheck/non-fatal.c
line diff
     1.1 --- a/xen/arch/x86/cpu/mcheck/amd_nonfatal.c	Tue Feb 16 18:11:17 2010 +0000
     1.2 +++ b/xen/arch/x86/cpu/mcheck/amd_nonfatal.c	Wed Feb 17 12:04:50 2010 +0000
     1.3 @@ -84,12 +84,9 @@ static void mce_amd_checkregs(void *info
     1.4  {
     1.5  	mctelem_cookie_t mctc;
     1.6  	struct mca_summary bs;
     1.7 -	unsigned int event_enabled;
     1.8  
     1.9  	mctc = mcheck_mca_logout(MCA_POLLER, mca_allbanks, &bs, NULL);
    1.10  
    1.11 -	event_enabled = guest_enabled_event(dom0->vcpu[0], VIRQ_MCA);
    1.12 -
    1.13  	if (bs.errcnt && mctc != NULL) {
    1.14  		static uint64_t dumpcount = 0;
    1.15  
    1.16 @@ -101,7 +98,7 @@ static void mce_amd_checkregs(void *info
    1.17  		 * a simple-minded attempt to avoid spamming the console
    1.18  		 * for corrected errors in early startup. */
    1.19  
    1.20 -		if (event_enabled) {
    1.21 +		if (dom0_vmce_enabled()) {
    1.22  			mctelem_commit(mctc);
    1.23  			send_guest_global_virq(dom0, VIRQ_MCA);
    1.24  		} else if (++dumpcount >= 10) {
    1.25 @@ -136,7 +133,7 @@ static void mce_amd_work_fn(void *data)
    1.26  	on_each_cpu(mce_amd_checkregs, data, 1);
    1.27  
    1.28  	if (adjust > 0) {
    1.29 -		if (!guest_enabled_event(dom0->vcpu[0], VIRQ_MCA) ) {
    1.30 +		if (!dom0_vmce_enabled()) {
    1.31  			/* Dom0 did not enable VIRQ_MCA, so Xen is reporting. */
    1.32  			printk("MCE: polling routine found correctable error. "
    1.33  				" Use mcelog to parse above error output.\n");
     2.1 --- a/xen/arch/x86/cpu/mcheck/mce.c	Tue Feb 16 18:11:17 2010 +0000
     2.2 +++ b/xen/arch/x86/cpu/mcheck/mce.c	Wed Feb 17 12:04:50 2010 +0000
     2.3 @@ -414,7 +414,7 @@ void mcheck_cmn_handler(struct cpu_user_
     2.4  	 * as terminal for any context.
     2.5  	 */
     2.6  	ctx_xen = SEG_PL(regs->cs) == 0;
     2.7 -	ctx_dom0 = !ctx_xen && (domid == dom0->domain_id);
     2.8 +	ctx_dom0 = !ctx_xen && (domid == 0);
     2.9  	ctx_domU = !ctx_xen && !ctx_dom0;
    2.10  
    2.11  	xen_state_lost = bs.uc != 0 || (ctx_xen && (bs.pcc || !ripv)) ||
    2.12 @@ -463,7 +463,8 @@ void mcheck_cmn_handler(struct cpu_user_
    2.13  	 * XXFM Could add some Solaris dom0 contract kill here?
    2.14  	 */
    2.15  	if (dom0_state_lost) {
    2.16 -		if (guest_has_trap_callback(dom0, 0, TRAP_machine_check)) {
    2.17 +		if (dom0 && dom0->max_vcpus && dom0->vcpu[0] &&
    2.18 +		    guest_has_trap_callback(dom0, 0, TRAP_machine_check)) {
    2.19  			dom_state = DOM0_TRAP;
    2.20  			send_guest_trap(dom0, 0, TRAP_machine_check);
    2.21  			/* XXFM case of return with !ripv ??? */
    2.22 @@ -532,7 +533,7 @@ cmn_handler_done:
    2.23  	if (bs.errcnt) {
    2.24  		/* Not panicing, so forward telemetry to dom0 now if it
    2.25  		 * is interested. */
    2.26 -		if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
    2.27 +		if (dom0_vmce_enabled()) {
    2.28  			if (mctc != NULL)
    2.29  				mctelem_commit(mctc);
    2.30  			send_guest_global_virq(dom0, VIRQ_MCA);
     3.1 --- a/xen/arch/x86/cpu/mcheck/mce.h	Tue Feb 16 18:11:17 2010 +0000
     3.2 +++ b/xen/arch/x86/cpu/mcheck/mce.h	Wed Feb 17 12:04:50 2010 +0000
     3.3 @@ -55,6 +55,8 @@ void mc_panic(char *s);
     3.4  void x86_mc_get_cpu_info(unsigned, uint32_t *, uint16_t *, uint16_t *,
     3.5  			 uint32_t *, uint32_t *, uint32_t *, uint32_t *);
     3.6  
     3.7 +#define dom0_vmce_enabled() (dom0 && dom0->max_vcpus && dom0->vcpu[0] \
     3.8 +	&& guest_enabled_event(dom0->vcpu[0], VIRQ_MCA))
     3.9  
    3.10  /* Register a handler for machine check exceptions. */
    3.11  typedef void (*x86_mce_vector_t)(struct cpu_user_regs *, long);
     4.1 --- a/xen/arch/x86/cpu/mcheck/mce_intel.c	Tue Feb 16 18:11:17 2010 +0000
     4.2 +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c	Wed Feb 17 12:04:50 2010 +0000
     4.3 @@ -518,7 +518,7 @@ static void mce_softirq(void)
     4.4          }
     4.5  
     4.6          /* Step2: Send Log to DOM0 through vIRQ */
     4.7 -        if (dom0 && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
     4.8 +        if (dom0_vmce_enabled()) {
     4.9              mce_printk(MCE_VERBOSE, "MCE: send MCE# to DOM0 through virq\n");
    4.10              send_guest_global_virq(dom0, VIRQ_MCA);
    4.11          }
    4.12 @@ -864,7 +864,7 @@ static void cmci_discover(void)
    4.13          MCA_CMCI_HANDLER, __get_cpu_var(mce_banks_owned), &bs, NULL);
    4.14  
    4.15      if (bs.errcnt && mctc != NULL) {
    4.16 -        if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
    4.17 +        if (dom0_vmce_enabled()) {
    4.18              mctelem_commit(mctc);
    4.19              send_guest_global_virq(dom0, VIRQ_MCA);
    4.20          } else {
    4.21 @@ -979,7 +979,7 @@ fastcall void smp_cmci_interrupt(struct 
    4.22          MCA_CMCI_HANDLER, __get_cpu_var(mce_banks_owned), &bs, NULL);
    4.23  
    4.24      if (bs.errcnt && mctc != NULL) {
    4.25 -        if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
    4.26 +        if (dom0_vmce_enabled()) {
    4.27              mctelem_commit(mctc);
    4.28              mce_printk(MCE_VERBOSE, "CMCI: send CMCI to DOM0 through virq\n");
    4.29              send_guest_global_virq(dom0, VIRQ_MCA);
     5.1 --- a/xen/arch/x86/cpu/mcheck/non-fatal.c	Tue Feb 16 18:11:17 2010 +0000
     5.2 +++ b/xen/arch/x86/cpu/mcheck/non-fatal.c	Wed Feb 17 12:04:50 2010 +0000
     5.3 @@ -53,7 +53,7 @@ static void mce_checkregs (void *info)
     5.4  		 * for corrected errors in early startup.
     5.5  		 */
     5.6  
     5.7 -		if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
     5.8 +		if (dom0_vmce_enabled()) {
     5.9  			mctelem_commit(mctc);
    5.10  			send_guest_global_virq(dom0, VIRQ_MCA);
    5.11  		} else if (++dumpcount >= 10) {