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@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
@@ -170,7 +170,7 @@ 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;
@@ -814,20 +814,46 @@ 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)
 {
@@ -835,28 +861,21 @@ 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);
_______________________________________________
freebsd-current@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to