svn commit: r259996 - in user/gjb/hacking/release-embedded: bin/ps etc sys/amd64/vmm/io sys/ia64/ia64

Glen Barber gjb at FreeBSD.org
Sat Dec 28 03:11:10 UTC 2013


Author: gjb
Date: Sat Dec 28 03:11:09 2013
New Revision: 259996
URL: http://svnweb.freebsd.org/changeset/base/259996

Log:
  MFH: Tracking commit
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  user/gjb/hacking/release-embedded/bin/ps/ps.1
  user/gjb/hacking/release-embedded/etc/ntp.conf
  user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.c
  user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.h
  user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic_priv.h
  user/gjb/hacking/release-embedded/sys/ia64/ia64/dump_machdep.c
Directory Properties:
  user/gjb/hacking/release-embedded/   (props changed)

Modified: user/gjb/hacking/release-embedded/bin/ps/ps.1
==============================================================================
--- user/gjb/hacking/release-embedded/bin/ps/ps.1	Sat Dec 28 03:04:05 2013	(r259995)
+++ user/gjb/hacking/release-embedded/bin/ps/ps.1	Sat Dec 28 03:11:09 2013	(r259996)
@@ -29,7 +29,7 @@
 .\"     @(#)ps.1	8.3 (Berkeley) 4/18/94
 .\" $FreeBSD$
 .\"
-.Dd March 15, 2013
+.Dd December 27, 2013
 .Dt PS 1
 .Os
 .Sh NAME
@@ -416,8 +416,9 @@ The process has reduced CPU scheduling p
 .It Li s
 The process is a session leader.
 .It Li V
-The process is suspended during a
-.Xr vfork 2 .
+The process' parent is suspended during a
+.Xr vfork 2 ,
+waiting for the process to exec or exit.
 .It Li W
 The process is swapped out.
 .It Li X

Modified: user/gjb/hacking/release-embedded/etc/ntp.conf
==============================================================================
--- user/gjb/hacking/release-embedded/etc/ntp.conf	Sat Dec 28 03:04:05 2013	(r259995)
+++ user/gjb/hacking/release-embedded/etc/ntp.conf	Sat Dec 28 03:11:09 2013	(r259996)
@@ -17,7 +17,7 @@
 # users with a static IP and good upstream NTP servers to add a server
 # to the pool. See http://www.pool.ntp.org/join.html if you are interested.
 #
-# The option `iburst' is used for faster initial synchronisation.
+# The option `iburst' is used for faster initial synchronization.
 #
 server 0.freebsd.pool.ntp.org iburst
 server 1.freebsd.pool.ntp.org iburst
@@ -35,21 +35,37 @@ server 2.freebsd.pool.ntp.org iburst
 # server 2.CC.pool.ntp.org iburst
 
 #
-# Security: Only accept NTP traffic from the following hosts.
-# The following configuration example only accepts traffic from the
-# above defined servers.
+# Security:
+#
+# By default, only allow time queries and block all other requests
+# from unauthenticated clients.
+#
+# See http://support.ntp.org/bin/view/Support/AccessRestrictions
+# for more information.
+#
+restrict default kod nomodify notrap nopeer noquery
+restrict -6 default kod nomodify notrap nopeer noquery
+#
+# Alternatively, the following rules would block all unauthorized access.
+#
+#restrict default ignore
+#restrict -6 default ignore
+#
+# In this case, all remote NTP time servers also need to be explicitly
+# allowed or they would not be able to exchange time information with
+# this server.
 #
 # Please note that this example doesn't work for the servers in
 # the pool.ntp.org domain since they return multiple A records.
-# (This is the reason that by default they are commented out)
 #
-#restrict default ignore
 #restrict 0.pool.ntp.org nomodify nopeer noquery notrap
 #restrict 1.pool.ntp.org nomodify nopeer noquery notrap
 #restrict 2.pool.ntp.org nomodify nopeer noquery notrap
-#restrict 127.0.0.1
-#restrict -6 ::1
-#restrict 127.127.1.0
+#
+# The following settings allow unrestricted access from the localhost
+restrict 127.0.0.1
+restrict -6 ::1
+restrict 127.127.1.0
 
 #
 # If a server loses sync with all upstream servers, NTP clients

Modified: user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.c
==============================================================================
--- user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.c	Sat Dec 28 03:04:05 2013	(r259995)
+++ user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.c	Sat Dec 28 03:11:09 2013	(r259996)
@@ -94,20 +94,14 @@ do {									\
 #define	PRIO(x)			((x) >> 4)
 
 #define VLAPIC_VERSION		(16)
-#define VLAPIC_MAXLVT_ENTRIES	(APIC_LVT_CMCI)
 
 #define	x2apic(vlapic)	(((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0)
 
 /*
  * The 'vlapic->timer_mtx' is used to provide mutual exclusion between the
- * vlapic_callout_handler() and vcpu accesses to the following registers:
- * - initial count register aka icr_timer
- * - current count register aka ccr_timer
- * - divide config register aka dcr_timer
+ * vlapic_callout_handler() and vcpu accesses to:
+ * - timer_freq_bt, timer_period_bt, timer_fire_bt
  * - timer LVT register
- *
- * Note that the vlapic_callout_handler() does not write to any of these
- * registers so they can be safely read from the vcpu context without locking.
  */
 #define	VLAPIC_TIMER_LOCK(vlapic)	mtx_lock_spin(&((vlapic)->timer_mtx))
 #define	VLAPIC_TIMER_UNLOCK(vlapic)	mtx_unlock_spin(&((vlapic)->timer_mtx))
@@ -217,20 +211,6 @@ vlapic_timer_divisor(uint32_t dcr)
 	}
 }
 
-static void
-vlapic_mask_lvts(struct vlapic *vlapic)
-{
-	struct LAPIC *lapic = vlapic->apic_page;
-
-	lapic->lvt_cmci |= APIC_LVT_M;
-	lapic->lvt_timer |= APIC_LVT_M;
-	lapic->lvt_thermal |= APIC_LVT_M;
-	lapic->lvt_pcint |= APIC_LVT_M;
-	lapic->lvt_lint0 |= APIC_LVT_M;
-	lapic->lvt_lint1 |= APIC_LVT_M;
-	lapic->lvt_error |= APIC_LVT_M;
-}
-
 #if 0
 static inline void
 vlapic_dump_lvt(uint32_t offset, uint32_t *lvt)
@@ -273,8 +253,8 @@ vlapic_get_ccr(struct vlapic *vlapic)
 	return (ccr);
 }
 
-static void
-vlapic_set_dcr(struct vlapic *vlapic, uint32_t dcr)
+void
+vlapic_dcr_write_handler(struct vlapic *vlapic)
 {
 	struct LAPIC *lapic;
 	int divisor;
@@ -282,9 +262,9 @@ vlapic_set_dcr(struct vlapic *vlapic, ui
 	lapic = vlapic->apic_page;
 	VLAPIC_TIMER_LOCK(vlapic);
 
-	lapic->dcr_timer = dcr;
-	divisor = vlapic_timer_divisor(dcr);
-	VLAPIC_CTR2(vlapic, "vlapic dcr_timer=%#x, divisor=%d", dcr, divisor);
+	divisor = vlapic_timer_divisor(lapic->dcr_timer);
+	VLAPIC_CTR2(vlapic, "vlapic dcr_timer=%#x, divisor=%d",
+	    lapic->dcr_timer, divisor);
 
 	/*
 	 * Update the timer frequency and the timer period.
@@ -299,8 +279,8 @@ vlapic_set_dcr(struct vlapic *vlapic, ui
 	VLAPIC_TIMER_UNLOCK(vlapic);
 }
 
-static void
-vlapic_update_errors(struct vlapic *vlapic)
+void
+vlapic_esr_write_handler(struct vlapic *vlapic)
 {
 	struct LAPIC *lapic;
 	
@@ -309,30 +289,6 @@ vlapic_update_errors(struct vlapic *vlap
 	vlapic->esr_pending = 0;
 }
 
-static void
-vlapic_reset(struct vlapic *vlapic)
-{
-	struct LAPIC *lapic;
-	
-	lapic = vlapic->apic_page;
-	bzero(lapic, sizeof(struct LAPIC));
-
-	lapic->id = vlapic_get_id(vlapic);
-	lapic->version = VLAPIC_VERSION;
-	lapic->version |= (VLAPIC_MAXLVT_ENTRIES << MAXLVTSHIFT);
-	lapic->dfr = 0xffffffff;
-	lapic->svr = APIC_SVR_VECTOR;
-	vlapic_mask_lvts(vlapic);
-	vlapic_set_dcr(vlapic, 0);
-
-	if (vlapic->vcpuid == 0)
-		vlapic->boot_state = BS_RUNNING;	/* BSP */
-	else
-		vlapic->boot_state = BS_INIT;		/* AP */
-
-	vlapic->svr_last = lapic->svr;
-}
-
 void
 vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
 {
@@ -391,24 +347,65 @@ vlapic_get_lvtptr(struct vlapic *vlapic,
 	}
 }
 
+static __inline int
+lvt_off_to_idx(uint32_t offset)
+{
+	int index;
+
+	switch (offset) {
+	case APIC_OFFSET_CMCI_LVT:
+		index = APIC_LVT_CMCI;
+		break;
+	case APIC_OFFSET_TIMER_LVT:
+		index = APIC_LVT_TIMER;
+		break;
+	case APIC_OFFSET_THERM_LVT:
+		index = APIC_LVT_THERMAL;
+		break;
+	case APIC_OFFSET_PERF_LVT:
+		index = APIC_LVT_PMC;
+		break;
+	case APIC_OFFSET_LINT0_LVT:
+		index = APIC_LVT_LINT0;
+		break;
+	case APIC_OFFSET_LINT1_LVT:
+		index = APIC_LVT_LINT1;
+		break;
+	case APIC_OFFSET_ERROR_LVT:
+		index = APIC_LVT_ERROR;
+		break;
+	default:
+		index = -1;
+		break;
+	}
+	KASSERT(index >= 0 && index <= VLAPIC_MAXLVT_INDEX, ("lvt_off_to_idx: "
+	    "invalid lvt index %d for offset %#x", index, offset));
+
+	return (index);
+}
+
 static __inline uint32_t
 vlapic_get_lvt(struct vlapic *vlapic, uint32_t offset)
 {
+	int idx;
+	uint32_t val;
 
-	return (*vlapic_get_lvtptr(vlapic, offset));
+	idx = lvt_off_to_idx(offset);
+	val = atomic_load_acq_32(&vlapic->lvt_last[idx]);
+	return (val);
 }
 
-static void
-vlapic_set_lvt(struct vlapic *vlapic, uint32_t offset, uint32_t val)
+void
+vlapic_lvt_write_handler(struct vlapic *vlapic, uint32_t offset)
 {
-	uint32_t *lvtptr, mask;
+	uint32_t *lvtptr, mask, val;
 	struct LAPIC *lapic;
+	int idx;
 	
 	lapic = vlapic->apic_page;
 	lvtptr = vlapic_get_lvtptr(vlapic, offset);	
-
-	if (offset == APIC_OFFSET_TIMER_LVT)
-		VLAPIC_TIMER_LOCK(vlapic);
+	val = *lvtptr;
+	idx = lvt_off_to_idx(offset);
 
 	if (!(lapic->svr & APIC_SVR_ENABLE))
 		val |= APIC_LVT_M;
@@ -427,10 +424,36 @@ vlapic_set_lvt(struct vlapic *vlapic, ui
 		mask |= APIC_LVT_DM;
 		break;
 	}
-	*lvtptr = val & mask;
+	val &= mask;
+	*lvtptr = val;
+	atomic_store_rel_32(&vlapic->lvt_last[idx], val);
+}
+
+static void
+vlapic_mask_lvts(struct vlapic *vlapic)
+{
+	struct LAPIC *lapic = vlapic->apic_page;
+
+	lapic->lvt_cmci |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_CMCI_LVT);
+
+	lapic->lvt_timer |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_TIMER_LVT);
 
-	if (offset == APIC_OFFSET_TIMER_LVT)
-		VLAPIC_TIMER_UNLOCK(vlapic);
+	lapic->lvt_thermal |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_THERM_LVT);
+
+	lapic->lvt_pcint |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_PERF_LVT);
+
+	lapic->lvt_lint0 |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_LINT0_LVT);
+
+	lapic->lvt_lint1 |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_LINT1_LVT);
+
+	lapic->lvt_error |= APIC_LVT_M;
+	vlapic_lvt_write_handler(vlapic, APIC_OFFSET_ERROR_LVT);
 }
 
 static int
@@ -651,7 +674,7 @@ vlapic_fire_cmci(struct vlapic *vlapic)
 	}
 }
 
-static VMM_STAT_ARRAY(LVTS_TRIGGERRED, VLAPIC_MAXLVT_ENTRIES,
+static VMM_STAT_ARRAY(LVTS_TRIGGERRED, VLAPIC_MAXLVT_INDEX + 1,
     "lvts triggered");
 
 int
@@ -711,8 +734,6 @@ vlapic_callout_handler(void *arg)
 
 	callout_deactivate(&vlapic->callout);
 
-	KASSERT(vlapic->apic_page->icr_timer != 0, ("timer is disabled"));
-
 	vlapic_fire_timer(vlapic);
 
 	if (vlapic_periodic_timer(vlapic)) {
@@ -757,16 +778,17 @@ done:
 	VLAPIC_TIMER_UNLOCK(vlapic);
 }
 
-static void
-vlapic_set_icr_timer(struct vlapic *vlapic, uint32_t icr_timer)
+void
+vlapic_icrtmr_write_handler(struct vlapic *vlapic)
 {
 	struct LAPIC *lapic;
 	sbintime_t sbt;
+	uint32_t icr_timer;
 
 	VLAPIC_TIMER_LOCK(vlapic);
 
 	lapic = vlapic->apic_page;
-	lapic->icr_timer = icr_timer;
+	icr_timer = lapic->icr_timer;
 
 	vlapic->timer_period_bt = vlapic->timer_freq_bt;
 	bintime_mul(&vlapic->timer_period_bt, icr_timer);
@@ -888,16 +910,22 @@ vlapic_calcdest(struct vm *vm, cpuset_t 
 
 static VMM_STAT_ARRAY(IPIS_SENT, VM_MAXCPU, "ipis sent to vcpu");
 
-static int
-lapic_process_icr(struct vlapic *vlapic, uint64_t icrval, bool *retu)
+int
+vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
 {
 	int i;
 	bool phys;
 	cpuset_t dmask;
+	uint64_t icrval;
 	uint32_t dest, vec, mode;
 	struct vlapic *vlapic2;
 	struct vm_exit *vmexit;
-	
+	struct LAPIC *lapic;
+
+	lapic = vlapic->apic_page;
+	lapic->icr_lo &= ~APIC_DELSTAT_PEND;
+	icrval = ((uint64_t)lapic->icr_hi << 32) | lapic->icr_lo;
+
 	if (x2apic(vlapic))
 		dest = icrval >> 32;
 	else
@@ -1088,7 +1116,7 @@ vlapic_svr_write_handler(struct vlapic *
 			 */
 			VLAPIC_CTR0(vlapic, "vlapic is software-enabled");
 			if (vlapic_periodic_timer(vlapic))
-				vlapic_set_icr_timer(vlapic, lapic->icr_timer);
+				vlapic_icrtmr_write_handler(vlapic);
 		}
 	}
 }
@@ -1155,6 +1183,8 @@ vlapic_read(struct vlapic *vlapic, uint6
 			break;
 		case APIC_OFFSET_ICR_LOW: 
 			*data = lapic->icr_lo;
+			if (x2apic(vlapic))
+				*data |= (uint64_t)lapic->icr_hi << 32;
 			break;
 		case APIC_OFFSET_ICR_HI: 
 			*data = lapic->icr_hi;
@@ -1162,6 +1192,11 @@ vlapic_read(struct vlapic *vlapic, uint6
 		case APIC_OFFSET_CMCI_LVT:
 		case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
 			*data = vlapic_get_lvt(vlapic, offset);	
+#ifdef INVARIANTS
+			reg = vlapic_get_lvtptr(vlapic, offset);
+			KASSERT(*data == *reg, ("inconsistent lvt value at "
+			    "offset %#lx: %#lx/%#x", offset, *data, *reg));
+#endif
 			break;
 		case APIC_OFFSET_TIMER_ICR:
 			*data = lapic->icr_timer;
@@ -1186,6 +1221,7 @@ int
 vlapic_write(struct vlapic *vlapic, uint64_t offset, uint64_t data, bool *retu)
 {
 	struct LAPIC	*lapic = vlapic->apic_page;
+	uint32_t	*regptr;
 	int		retval;
 
 	KASSERT((offset & 0xf) == 0 && offset < PAGE_SIZE,
@@ -1224,32 +1260,32 @@ vlapic_write(struct vlapic *vlapic, uint
 			vlapic_svr_write_handler(vlapic);
 			break;
 		case APIC_OFFSET_ICR_LOW: 
-			if (!x2apic(vlapic)) {
-				data &= 0xffffffff;
-				data |= (uint64_t)lapic->icr_hi << 32;
-			}
-			retval = lapic_process_icr(vlapic, data, retu);
+			lapic->icr_lo = data;
+			if (x2apic(vlapic))
+				lapic->icr_hi = data >> 32;
+			retval = vlapic_icrlo_write_handler(vlapic, retu);
 			break;
 		case APIC_OFFSET_ICR_HI:
-			if (!x2apic(vlapic)) {
-				retval = 0;
-				lapic->icr_hi = data;
-			}
+			lapic->icr_hi = data;
 			break;
 		case APIC_OFFSET_CMCI_LVT:
 		case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
-			vlapic_set_lvt(vlapic, offset, data);
+			regptr = vlapic_get_lvtptr(vlapic, offset);
+			*regptr = data;
+			vlapic_lvt_write_handler(vlapic, offset);
 			break;
 		case APIC_OFFSET_TIMER_ICR:
-			vlapic_set_icr_timer(vlapic, data);
+			lapic->icr_timer = data;
+			vlapic_icrtmr_write_handler(vlapic);
 			break;
 
 		case APIC_OFFSET_TIMER_DCR:
-			vlapic_set_dcr(vlapic, data);
+			lapic->dcr_timer = data;
+			vlapic_dcr_write_handler(vlapic);
 			break;
 
 		case APIC_OFFSET_ESR:
-			vlapic_update_errors(vlapic);
+			vlapic_esr_write_handler(vlapic);
 			break;
 		case APIC_OFFSET_VER:
 		case APIC_OFFSET_APR:
@@ -1267,6 +1303,32 @@ vlapic_write(struct vlapic *vlapic, uint
 	return (retval);
 }
 
+static void
+vlapic_reset(struct vlapic *vlapic)
+{
+	struct LAPIC *lapic;
+	
+	lapic = vlapic->apic_page;
+	bzero(lapic, sizeof(struct LAPIC));
+
+	lapic->id = vlapic_get_id(vlapic);
+	lapic->version = VLAPIC_VERSION;
+	lapic->version |= (VLAPIC_MAXLVT_INDEX << MAXLVTSHIFT);
+	lapic->dfr = 0xffffffff;
+	lapic->svr = APIC_SVR_VECTOR;
+	vlapic_mask_lvts(vlapic);
+
+	lapic->dcr_timer = 0;
+	vlapic_dcr_write_handler(vlapic);
+
+	if (vlapic->vcpuid == 0)
+		vlapic->boot_state = BS_RUNNING;	/* BSP */
+	else
+		vlapic->boot_state = BS_INIT;		/* AP */
+
+	vlapic->svr_last = lapic->svr;
+}
+
 void
 vlapic_init(struct vlapic *vlapic)
 {

Modified: user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.h
==============================================================================
--- user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.h	Sat Dec 28 03:04:05 2013	(r259995)
+++ user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic.h	Sat Dec 28 03:11:09 2013	(r259996)
@@ -76,4 +76,9 @@ void vlapic_id_write_handler(struct vlap
 void vlapic_ldr_write_handler(struct vlapic *vlapic);
 void vlapic_dfr_write_handler(struct vlapic *vlapic);
 void vlapic_svr_write_handler(struct vlapic *vlapic);
+void vlapic_esr_write_handler(struct vlapic *vlapic);
+int vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu);
+void vlapic_icrtmr_write_handler(struct vlapic *vlapic);
+void vlapic_dcr_write_handler(struct vlapic *vlapic);
+void vlapic_lvt_write_handler(struct vlapic *vlapic, uint32_t offset);
 #endif	/* _VLAPIC_H_ */

Modified: user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic_priv.h
==============================================================================
--- user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic_priv.h	Sat Dec 28 03:04:05 2013	(r259995)
+++ user/gjb/hacking/release-embedded/sys/amd64/vmm/io/vlapic_priv.h	Sat Dec 28 03:11:09 2013	(r259996)
@@ -29,6 +29,8 @@
 #ifndef _VLAPIC_PRIV_H_
 #define	_VLAPIC_PRIV_H_
 
+#include <x86/apicreg.h>
+
 /*
  * APIC Register:		Offset	   Description
  */
@@ -91,6 +93,8 @@ enum boot_state {
  */
 #define	ISRVEC_STK_SIZE		(16 + 1)
 
+#define VLAPIC_MAXLVT_INDEX	APIC_LVT_CMCI
+
 struct vlapic {
 	struct vm		*vm;
 	int			vcpuid;
@@ -111,12 +115,20 @@ struct vlapic {
 	 * The vector on the top of the stack is used to compute the
 	 * Processor Priority in conjunction with the TPR.
 	 */
-	uint8_t			 isrvec_stk[ISRVEC_STK_SIZE];
-	int			 isrvec_stk_top;
+	uint8_t		isrvec_stk[ISRVEC_STK_SIZE];
+	int		isrvec_stk_top;
+
+	uint64_t	msr_apicbase;
+	enum boot_state	boot_state;
 
-	uint64_t		msr_apicbase;
-	enum boot_state		boot_state;
-	uint32_t		svr_last;
+	/*
+	 * Copies of some registers in the virtual APIC page. We do this for
+	 * a couple of different reasons:
+	 * - to be able to detect what changed (e.g. svr_last)
+	 * - to maintain a coherent snapshot of the register (e.g. lvt_last)
+	 */
+	uint32_t	svr_last;
+	uint32_t	lvt_last[VLAPIC_MAXLVT_INDEX + 1];
 };
 
 void vlapic_init(struct vlapic *vlapic);

Modified: user/gjb/hacking/release-embedded/sys/ia64/ia64/dump_machdep.c
==============================================================================
--- user/gjb/hacking/release-embedded/sys/ia64/ia64/dump_machdep.c	Sat Dec 28 03:04:05 2013	(r259995)
+++ user/gjb/hacking/release-embedded/sys/ia64/ia64/dump_machdep.c	Sat Dec 28 03:11:09 2013	(r259996)
@@ -56,7 +56,10 @@ CTASSERT(sizeof(struct kerneldumpheader)
 #define	MD_ALIGN(x)	(((off_t)(x) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK)
 #define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
 
-typedef int callback_t(struct efi_md*, int, void*);
+static int minidump = 0;
+TUNABLE_INT("debug.minidump", &minidump);
+SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RW, &minidump, 0,
+    "Enable mini crash dumps");
 
 static struct kerneldumpheader kdh;
 static off_t dumplo, fileofs;
@@ -83,7 +86,7 @@ buf_write(struct dumperinfo *di, char *p
 			error = dump_write(di, buffer, 0, dumplo,
 			    DEV_BSIZE);
 			if (error)
-				return error;
+				return (error);
 			dumplo += DEV_BSIZE;
 			fragsz = 0;
 		}
@@ -106,8 +109,14 @@ buf_flush(struct dumperinfo *di)
 	return (error);
 }
 
+/*
+ * Physical dump support
+ */
+
+typedef int phys_callback_t(struct efi_md*, int, void*);
+
 static int
-cb_dumpdata(struct efi_md *mdp, int seqnr, void *arg)
+phys_cb_dumpdata(struct efi_md *mdp, int seqnr, void *arg)
 {
 	struct dumperinfo *di = (struct dumperinfo*)arg;
 	vm_offset_t pa;
@@ -153,7 +162,7 @@ cb_dumpdata(struct efi_md *mdp, int seqn
 }
 
 static int
-cb_dumphdr(struct efi_md *mdp, int seqnr, void *arg)
+phys_cb_dumphdr(struct efi_md *mdp, int seqnr, void *arg)
 {
 	struct dumperinfo *di = (struct dumperinfo*)arg;
 	Elf64_Phdr phdr;
@@ -175,7 +184,7 @@ cb_dumphdr(struct efi_md *mdp, int seqnr
 }
 
 static int
-cb_size(struct efi_md *mdp, int seqnr, void *arg)
+phys_cb_size(struct efi_md *mdp, int seqnr, void *arg)
 {
 	uint64_t *sz = (uint64_t*)arg;
 
@@ -184,7 +193,7 @@ cb_size(struct efi_md *mdp, int seqnr, v
 }
 
 static int
-foreach_chunk(callback_t cb, void *arg)
+phys_foreach(phys_callback_t cb, void *arg)
 {
 	struct efi_md *mdp;
 	int error, seqnr;
@@ -206,6 +215,31 @@ foreach_chunk(callback_t cb, void *arg)
 	return (seqnr);
 }
 
+/*
+ * Virtual dump (aka minidump) support
+ */
+
+static int
+virt_size(uint64_t *dumpsize)
+{
+
+	return (0);
+}
+
+static int
+virt_dumphdrs(struct dumperinfo *di)
+{
+
+	return (-ENOSYS);
+}
+
+static int
+virt_dumpdata(struct dumperinfo *di)
+{
+
+	return (-ENOSYS);
+}
+
 void
 dumpsys(struct dumperinfo *di)
 {
@@ -213,7 +247,7 @@ dumpsys(struct dumperinfo *di)
 	uint64_t dumpsize;
 	off_t hdrgap;
 	size_t hdrsz;
-	int error;
+	int error, status;
 
 	bzero(&ehdr, sizeof(ehdr));
 	ehdr.e_ident[EI_MAG0] = ELFMAG0;
@@ -230,18 +264,25 @@ dumpsys(struct dumperinfo *di)
 	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
 	ehdr.e_type = ET_CORE;
 	ehdr.e_machine = EM_IA_64;
-	ehdr.e_entry = ia64_tpa((uintptr_t)bootinfo);
+	ehdr.e_entry = (minidump) ? (uintptr_t)bootinfo :
+	    ia64_tpa((uintptr_t)bootinfo);
 	ehdr.e_phoff = sizeof(ehdr);
-	ehdr.e_flags = EF_IA_64_ABSOLUTE;		/* XXX misuse? */
+	ehdr.e_flags = (minidump) ? 0 : EF_IA_64_ABSOLUTE; /* XXX misuse? */
 	ehdr.e_ehsize = sizeof(ehdr);
 	ehdr.e_phentsize = sizeof(Elf64_Phdr);
 	ehdr.e_shentsize = sizeof(Elf64_Shdr);
 
 	/* Calculate dump size. */
 	dumpsize = 0L;
-	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
+	status = (minidump) ? virt_size(&dumpsize) :
+	    phys_foreach(phys_cb_size, &dumpsize);
+	if (status < 0) {
+		error = -status;
+		goto fail;
+	}
+	ehdr.e_phnum = status;
 	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
-	fileofs = MD_ALIGN(hdrsz);
+	fileofs = (minidump) ? round_page(hdrsz) : MD_ALIGN(hdrsz);
 	dumpsize += fileofs;
 	hdrgap = fileofs - DEV_ALIGN(hdrsz);
 
@@ -270,24 +311,30 @@ dumpsys(struct dumperinfo *di)
 		goto fail;
 
 	/* Dump program headers */
-	error = foreach_chunk(cb_dumphdr, di);
-	if (error < 0)
+	status = (minidump) ? virt_dumphdrs(di) :
+	    phys_foreach(phys_cb_dumphdr, di);
+	if (status < 0) {
+		error = -status;
 		goto fail;
+	}
 	buf_flush(di);
 
 	/*
 	 * All headers are written using blocked I/O, so we know the
-	 * current offset is (still) block aligned. Skip the alignement
+	 * current offset is (still) block aligned. Skip the alignment
 	 * in the file to have the segment contents aligned at page
-	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
-	 * care and may very well be unaligned within the dump device.
+	 * boundary. For physical dumps, it's the EFI page size (= 4K).
+	 * For minidumps it's the kernel's page size (= 8K).
 	 */
 	dumplo += hdrgap;
 
 	/* Dump memory chunks (updates dumplo) */
-	error = foreach_chunk(cb_dumpdata, di);
-	if (error < 0)
+	status = (minidump) ? virt_dumpdata(di) :
+	    phys_foreach(phys_cb_dumpdata, di);
+	if (status < 0) {
+		error = -status;
 		goto fail;
+	}
 
 	/* Dump trailer */
 	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
@@ -300,9 +347,6 @@ dumpsys(struct dumperinfo *di)
 	return;
 
  fail:
-	if (error < 0)
-		error = -error;
-
 	if (error == ECANCELED)
 		printf("\nDump aborted\n");
 	else


More information about the svn-src-user mailing list