GENERIC-NODEBUG panics, GENERIC does not
Konstantin Belousov
kostikbel at gmail.com
Fri Apr 15 12:53:48 UTC 2016
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
@@ -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);
More information about the freebsd-current
mailing list