Re: GENERIC-NODEBUG panics, GENERIC does not

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Fri, 15 Apr 2016 15:53:41 +0300
On Fri, Apr 15, 2016 at 02:38:18PM +0300, Vladimir Zakharov wrote:
> On Fri, Apr 15, 2016, Konstantin Belousov wrote:
> > On Fri, Apr 15, 2016 at 01:26:44PM +0300, Vladimir Zakharov wrote:
> > > Hello
> > > 
> > > Setting 'kern.eventtimer.periodic = 1' in /etc/sysctl.conf leads to
> > > GENERIC-NODEBUG panic. GENERIC loads without problems.
> > > So do GENERIC-NODEBUG as of r297245.
> > > 
> > > https://imgur.com/0DtDU3m
> > > 
> > > $ uname -a
> > > 
> > > FreeBSD vzakharov 11.0-CURRENT FreeBSD 11.0-CURRENT #4 r298037: Fri Apr
> > > 15 12:27:40 MSK 2016 root_at_vzakharov:/home/obj/usr/src/sys/GENERIC-NODEBUG  amd64
> > > 
> > 
> > I cannot reproduce it locally.
> > Please provide me verbose dmesg from the successfull boot on your machine.
> 
> GENERIC with kern.eventtimer.periodic=1: http://pastebin.com/raw/TB0TKSje
> GENERIC-NODEBUG: http://pastebin.com/raw/05CchraS
I need _verbose_ dmesg.  I need the reports about LAPICs initializations,
with register dumps.

> 
> > Also, for the panic, show me the output of the same data as on the
> > screenshot and the output of 'show registers'.
> 
> https://imgur.com/pO8Yc3w
Ok, this seems to be yet another case of missed count mode divisor
initialization. Please try the patch at the end of the messasge.

> 
> > Also please load your kernel into kgdb and do
> > list *lapic_et_start+0x281
By 'your kernel' I mean 'your panicing kernel'.


diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 5830b77..854bda4 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
_at__at_ -170,7 +170,7 _at__at_ vm_paddr_t lapic_paddr;
 int x2apic_mode;
 int lapic_eoi_suppression;
 static int lapic_timer_tsc_deadline;
-static u_long lapic_timer_divisor;
+static u_long lapic_timer_divisor, count_freq;
 static struct eventtimer lapic_et;
 #ifdef SMP
 static uint64_t lapic_ipi_wait_mult;
_at__at_ -814,20 +814,46 _at__at_ lapic_calibrate_initcount(struct eventtimer *et, struct lapic *la)
 		printf("lapic: Divisor %lu, Frequency %lu Hz\n",
 		    lapic_timer_divisor, value);
 	}
-	et->et_frequency = value;
+	count_freq = value;
 }
 
 static void
 lapic_calibrate_deadline(struct eventtimer *et, struct lapic *la __unused)
 {
 
-	et->et_frequency = tsc_freq;
 	if (bootverbose) {
 		printf("lapic: deadline tsc mode, Frequency %ju Hz\n",
-		    (uintmax_t)et->et_frequency);
+		    (uintmax_t)tsc_freq);
 	}
 }
 
+static void
+lapic_change_mode(struct eventtimer *et, struct lapic *la,
+    enum lat_timer_mode newmode)
+{
+
+	if (la->la_timer_mode == newmode)
+		return;
+	switch (newmode) {
+	case LAT_MODE_PERIODIC:
+		lapic_timer_set_divisor(lapic_timer_divisor);
+		et->et_frequency = count_freq;
+		break;
+	case LAT_MODE_DEADLINE:
+		et->et_frequency = tsc_freq;
+		break;
+	case LAT_MODE_ONESHOT:
+		lapic_timer_set_divisor(lapic_timer_divisor);
+		et->et_frequency = count_freq;
+		break;
+	default:
+		panic("lapic_change_mode %d", newmode);
+	}
+	la->la_timer_mode = newmode;
+	et->et_min_period = (0x00000002LLU << 32) / et->et_frequency;
+	et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency;
+}
+
 static int
 lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
 {
_at__at_ -835,28 +861,21 _at__at_ lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
 
 	la = &lapics[PCPU_GET(apic_id)];
 	if (et->et_frequency == 0) {
+		lapic_calibrate_initcount(et, la);
 		if (lapic_timer_tsc_deadline)
 			lapic_calibrate_deadline(et, la);
-		else
-			lapic_calibrate_initcount(et, la);
-		et->et_min_period = (0x00000002LLU << 32) / et->et_frequency;
-		et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency;
 	}
 	if (period != 0) {
-		if (la->la_timer_mode == LAT_MODE_UNDEF)
-			lapic_timer_set_divisor(lapic_timer_divisor);
-		la->la_timer_mode = LAT_MODE_PERIODIC;
+		lapic_change_mode(et, la, LAT_MODE_PERIODIC);
 		la->la_timer_period = ((uint32_t)et->et_frequency * period) >>
 		    32;
 		lapic_timer_periodic(la);
 	} else if (lapic_timer_tsc_deadline) {
-		la->la_timer_mode = LAT_MODE_DEADLINE;
+		lapic_change_mode(et, la, LAT_MODE_DEADLINE);
 		la->la_timer_period = (et->et_frequency * first) >> 32;
 		lapic_timer_deadline(la);
 	} else {
-		if (la->la_timer_mode == LAT_MODE_UNDEF)
-			lapic_timer_set_divisor(lapic_timer_divisor);
-		la->la_timer_mode = LAT_MODE_ONESHOT;
+		lapic_change_mode(et, la, LAT_MODE_ONESHOT);
 		la->la_timer_period = ((uint32_t)et->et_frequency * first) >>
 		    32;
 		lapic_timer_oneshot(la);
Received on Fri Apr 15 2016 - 10:53:48 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:04 UTC