Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Apr 2010 22:30:06 GMT
From:      dfilter@FreeBSD.ORG (dfilter service)
To:        freebsd-ia64@FreeBSD.org
Subject:   Re: ia64/113102: commit references a PR
Message-ID:  <201004132230.o3DMU6sw006379@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR ia64/113102; it has been noted by GNATS.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: ia64/113102: commit references a PR
Date: Tue, 13 Apr 2010 22:20:22 +0000 (UTC)

 Author: marcel
 Date: Tue Apr 13 22:20:12 2010
 New Revision: 206570
 URL: http://svn.freebsd.org/changeset/base/206570
 
 Log:
   Populate the sysctl tree with any MCA records we collected.
   The sequence number is used as the name of a sysctl node,
   under which we add the MCA records using the CPU id as the
   leaf  name.
   
   Add the hw.mca.inject sysctl to provide a way to inject
   MC errors and trigger machine checks.
   
   PR:		ia64/113102
 
 Modified:
   head/sys/ia64/ia64/mca.c
   head/sys/ia64/include/mca.h
 
 Modified: head/sys/ia64/ia64/mca.c
 ==============================================================================
 --- head/sys/ia64/ia64/mca.c	Tue Apr 13 21:32:06 2010	(r206569)
 +++ head/sys/ia64/ia64/mca.c	Tue Apr 13 22:20:12 2010	(r206570)
 @@ -1,5 +1,5 @@
  /*-
 - * Copyright (c) 2002 Marcel Moolenaar
 + * Copyright (c) 2002-2010 Marcel Moolenaar
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
 @@ -37,6 +37,7 @@
  #include <vm/vm.h>
  #include <vm/vm_kern.h>
  #include <machine/mca.h>
 +#include <machine/pal.h>
  #include <machine/sal.h>
  #include <machine/smp.h>
  
 @@ -44,19 +45,19 @@ MALLOC_DEFINE(M_MCA, "MCA", "Machine Che
  
  struct mca_info {
  	STAILQ_ENTRY(mca_info) mi_link;
 -	char	mi_name[32];
 +	u_long	mi_seqnr;
 +	u_int	mi_cpuid;
  	size_t	mi_recsz;
  	char	mi_record[0];
  };
  
 -static STAILQ_HEAD(, mca_info) mca_records =
 -    STAILQ_HEAD_INITIALIZER(mca_records);
 +STAILQ_HEAD(mca_info_list, mca_info);
  
 -int64_t		mca_info_size[SAL_INFO_TYPES];
 -vm_offset_t	mca_info_block;
 -struct mtx	mca_info_block_lock;
 +static int64_t		mca_info_size[SAL_INFO_TYPES];
 +static vm_offset_t	mca_info_block;
 +static struct mtx	mca_info_block_lock;
  
 -SYSCTL_NODE(_hw, OID_AUTO, mca, CTLFLAG_RW, 0, "MCA container");
 +SYSCTL_NODE(_hw, OID_AUTO, mca, CTLFLAG_RW, NULL, "MCA container");
  
  static int mca_count;		/* Number of records stored. */
  static int mca_first;		/* First (lowest) record ID. */
 @@ -69,6 +70,32 @@ SYSCTL_INT(_hw_mca, OID_AUTO, first, CTL
  SYSCTL_INT(_hw_mca, OID_AUTO, last, CTLFLAG_RD, &mca_last, 0,
      "Last record id");
  
 +static struct mtx mca_sysctl_lock;
 +
 +static int
 +mca_sysctl_inject(SYSCTL_HANDLER_ARGS)
 +{
 +	struct ia64_pal_result res;
 +	u_int val;
 +	int error;
 +
 +	val = 0;
 +	error = sysctl_wire_old_buffer(req, sizeof(u_int));
 +	if (!error)
 +		error = sysctl_handle_int(oidp, &val, 0, req);
 +
 +	if (error != 0 || req->newptr == NULL)
 +		return (error);
 +
 +	/* For example: val=137 causes a fatal CPU error. */
 +	res = ia64_call_pal_stacked(PAL_MC_ERROR_INJECT, val, 0, 0);
 +	printf("%s: %#lx, %#lx, %#lx, %#lx\n", __func__, res.pal_status,
 +	    res.pal_result[0], res.pal_result[1], res.pal_result[2]);
 +	return (0);
 +}
 +SYSCTL_PROC(_hw_mca, OID_AUTO, inject, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
 +    mca_sysctl_inject, "I", "set to trigger a MCA");
 +
  static int
  mca_sysctl_handler(SYSCTL_HANDLER_ARGS)
  {
 @@ -85,27 +112,8 @@ mca_sysctl_handler(SYSCTL_HANDLER_ARGS)
  	return (error);
  }
  
 -void
 -ia64_mca_populate(void)
 -{
 -	struct mca_info *rec;
 -
 -	mtx_lock_spin(&mca_info_block_lock);
 -	while (!STAILQ_EMPTY(&mca_records)) {
 -		rec = STAILQ_FIRST(&mca_records);
 -		STAILQ_REMOVE_HEAD(&mca_records, mi_link);
 -		mtx_unlock_spin(&mca_info_block_lock);
 -		(void)SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca),
 -		    OID_AUTO, rec->mi_name, CTLTYPE_OPAQUE | CTLFLAG_RD,
 -		    rec->mi_record, rec->mi_recsz, mca_sysctl_handler, "S,MCA",
 -		    "Error record");
 -		mtx_lock_spin(&mca_info_block_lock);
 -	}
 -	mtx_unlock_spin(&mca_info_block_lock);
 -}
 -
 -void
 -ia64_mca_save_state(int type)
 +static void
 +ia64_mca_collect_state(int type, struct mca_info_list *reclst)
  {
  	struct ia64_sal_result result;
  	struct mca_record_header *hdr;
 @@ -123,13 +131,13 @@ ia64_mca_save_state(int type)
  	if (mca_info_block == 0)
  		return;
  
 -	mtx_lock_spin(&mca_info_block_lock);
  	while (1) {
 +		mtx_lock_spin(&mca_info_block_lock);
  		result = ia64_sal_entry(SAL_GET_STATE_INFO, type, 0,
  		    mca_info_block, 0, 0, 0, 0);
  		if (result.sal_status < 0) {
  			mtx_unlock_spin(&mca_info_block_lock);
 -			return;
 +			break;
  		}
  
  		hdr = (struct mca_record_header *)mca_info_block;
 @@ -142,9 +150,10 @@ ia64_mca_save_state(int type)
  		    M_NOWAIT | M_ZERO);
  		if (rec == NULL)
  			/* XXX: Not sure what to do. */
 -			return;
 +			break;
  
 -		sprintf(rec->mi_name, "%lld", (long long)seqnr);
 +		rec->mi_seqnr = seqnr;
 +		rec->mi_cpuid = PCPU_GET(cpuid);
  
  		mtx_lock_spin(&mca_info_block_lock);
  
 @@ -163,7 +172,6 @@ ia64_mca_save_state(int type)
  			if (seqnr != hdr->rh_seqnr) {
  				mtx_unlock_spin(&mca_info_block_lock);
  				free(rec, M_MCA);
 -				mtx_lock_spin(&mca_info_block_lock);
  				continue;
  			}
  		}
 @@ -171,23 +179,51 @@ ia64_mca_save_state(int type)
  		rec->mi_recsz = recsz;
  		bcopy((char*)mca_info_block, rec->mi_record, recsz);
  
 -		if (mca_count > 0) {
 -			if (seqnr < mca_first)
 -				mca_first = seqnr;
 -			else if (seqnr > mca_last)
 -				mca_last = seqnr;
 -		} else
 -			mca_first = mca_last = seqnr;
 -
 -		mca_count++;
 -		STAILQ_INSERT_TAIL(&mca_records, rec, mi_link);
 -
  		/*
  		 * Clear the state so that we get any other records when
  		 * they exist.
  		 */
  		result = ia64_sal_entry(SAL_CLEAR_STATE_INFO, type, 0, 0, 0,
  		    0, 0, 0);
 +
 +		mtx_unlock_spin(&mca_info_block_lock);
 +
 +		STAILQ_INSERT_TAIL(reclst, rec, mi_link);
 +	}
 +}
 +
 +void
 +ia64_mca_save_state(int type)
 +{
 +	char name[64];
 +	struct mca_info_list reclst = STAILQ_HEAD_INITIALIZER(reclst);
 +	struct mca_info *rec;
 +	struct sysctl_oid *oid;
 +
 +	ia64_mca_collect_state(type, &reclst);
 +
 +	STAILQ_FOREACH(rec, &reclst, mi_link) {
 +		sprintf(name, "%lu", rec->mi_seqnr);
 +		oid = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca),
 +		    OID_AUTO, name, CTLFLAG_RW, NULL, name);
 +		if (oid == NULL)
 +			continue;
 +
 +		mtx_lock(&mca_sysctl_lock);
 +		if (mca_count > 0) {
 +			if (rec->mi_seqnr < mca_first)
 +				mca_first = rec->mi_seqnr;
 +			else if (rec->mi_seqnr > mca_last)
 +				mca_last = rec->mi_seqnr;
 +		} else
 +			mca_first = mca_last = rec->mi_seqnr;
 +		mca_count++;
 +		mtx_unlock(&mca_sysctl_lock);
 +
 +		sprintf(name, "%u", rec->mi_cpuid);
 +		SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(oid), rec->mi_cpuid,
 +		    name, CTLTYPE_OPAQUE | CTLFLAG_RD, rec->mi_record,
 +		    rec->mi_recsz, mca_sysctl_handler, "S,MCA", "MCA record");
  	}
  }
  
 @@ -237,7 +273,14 @@ ia64_mca_init(void)
  	 * should be rare. On top of that, performance is not an issue when
  	 * dealing with machine checks...
  	 */
 -	mtx_init(&mca_info_block_lock, "MCA spin lock", NULL, MTX_SPIN);
 +	mtx_init(&mca_info_block_lock, "MCA info lock", NULL, MTX_SPIN);
 +
 +	/*
 +	 * Serialize sysctl operations with a sleep lock. Note that this
 +	 * implies that we update the sysctl tree in a context that allows
 +	 * sleeping.
 +	 */
 +	mtx_init(&mca_sysctl_lock, "MCA sysctl lock", NULL, MTX_DEF);
  
  	/*
  	 * Get and save any processor and platfom error records. Note that in
 
 Modified: head/sys/ia64/include/mca.h
 ==============================================================================
 --- head/sys/ia64/include/mca.h	Tue Apr 13 21:32:06 2010	(r206569)
 +++ head/sys/ia64/include/mca.h	Tue Apr 13 22:20:12 2010	(r206570)
 @@ -1,5 +1,5 @@
  /*-
 - * Copyright (c) 2002 Marcel Moolenaar
 + * Copyright (c) 2002-2010 Marcel Moolenaar
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
 @@ -240,7 +240,6 @@ struct mca_pcidev_reg {
  #ifdef _KERNEL
  
  void ia64_mca_init(void);
 -void ia64_mca_populate(void);
  void ia64_mca_save_state(int);
  
  #endif /* _KERNEL */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004132230.o3DMU6sw006379>