Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Mar 2001 23:45:41 +0300 (MSK)
From:      belian@ratmir.ru
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/25781: Statclocks mislogics
Message-ID:  <200103132045.f2DKjfa00374@test202.ratmir.ru>

next in thread | raw e-mail | index | archive | help

>Number:         25781
>Category:       kern
>Synopsis:       Statclocks cannot be disables on ServerWorks chipset (MB: Acer Altos 1200, Tyan S2510, ...) if APM is enabled in SMP environment
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 13 12:50:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Vladimir Belian
>Release:        FreeBSD 4.x i386
>Organization:
Ratmir ADS
>Environment:

System: FreeBSD test202.ratmir.ru 4.3-BETA FreeBSD 4.3-BETA #0: Tue Mar 13 22:23:56 MSK 2001 root@test202.ratmir.ru:/usr/src/sys/compile/UNIX i386
Acer Altos 1200 motherboard, two Coppermines 933, 512M of registred DIMMs
Problem exists on all versions of FreeBSD 4.x

>Description:

The problem occurs with the two-processors configuration on the motherboards with 
ServerWorks chipset (such as described in the Environment section).

The following configuration leads to freezing computer before mounting root partition:

# To make an SMP kernel, the next two are needed
options 	SMP			# Symmetric MultiProcessor Kernel
options 	APIC_IO			# Symmetric (APIC) I/O

# Power management support (see LINT for more options)
device		apm0    at nexus? flags 0x20 # Advanced Power Management

	
>How-To-Repeat:

1) Include the srings above to the kernel config
2) Compile the kernel with the obtain config on the MB with ServerWorks chipset and
   dual processors
3) Boot

After hardware initialization computer will freeze.

>Fix:

It is necessary to fix the procedure cpu_initclocks() from /usr/src/sys/i386/isa/clock.c:


/*
 * Start both clocks running.
 */
void
cpu_initclocks()


There we have that part:



	if (statclock_disable) {
		/*
		 * The stat interrupt mask is different without the
		 * statistics clock.  Also, don't set the interrupt
		 * flag which would normally cause the RTC to generate
		 * interrupts.
		 */
		stat_imask = HWI_MASK | SWI_MASK;
		rtc_statusb = RTCSB_24HR;
	} else {
	        /* Setting stathz to nonzero early helps avoid races. */
		stathz = RTC_NOPROFRATE;
		profhz = RTC_PROFRATE;
        }




For which flag 0x20 in the apm(4) is sufficient. That's Ok. But than:




	/* Finish initializing 8253 timer 0. */
#ifdef APIC_IO

	apic_8254_intr = isa_apic_irq(0);
	apic_8254_trial = 0;
	if (apic_8254_intr >= 0 ) {
		if (apic_int_type(0, 0) == 3)
			apic_8254_trial = 1;
	} else {
		/* look for ExtInt on pin 0 */
		if (apic_int_type(0, 0) == 3) {
			apic_8254_intr = apic_irq(0, 0);
			setup_8254_mixed_mode();
		} else 
			panic("APIC_IO: Cannot route 8254 interrupt to CPU");
	}





we are detecting the flag ``apic_8254_trial''. That flag, as I understand,
indicates that the check if 8254 is broken (or, at least, non-standard) should be
performed. That's Ok as well. And now we do the following:





	clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
			      NULL, &clk_imask, INTR_EXCL);
	INTREN(1 << apic_8254_intr);
	
#else /* APIC_IO */

	inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
		    INTR_EXCL);
	INTREN(IRQ0);

#endif /* APIC_IO */

	/* Initialize RTC. */
	writertc(RTC_STATUSA, rtc_statusa);
	writertc(RTC_STATUSB, RTCSB_24HR);

	/* Don't bother enabling the statistics clock. */
	if (statclock_disable)
		return;



- and those check, the necessaty of wich we marked in the previous piece of code
will NEVER be done if we want to disable statclock. That's obviously wrong because
in the case of the non-standard 8254 we will handle it in the wrong way.




	diag = rtcin(RTC_DIAG);
	if (diag != 0)
		printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);

#ifdef APIC_IO
	if (isa_apic_irq(8) != 8)
		panic("APIC RTC != 8");
#endif /* APIC_IO */

	inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
		    INTR_EXCL);

#ifdef APIC_IO
	INTREN(APIC_IRQ8);
#else
	INTREN(IRQ8);
#endif /* APIC_IO */

	writertc(RTC_STATUSB, rtc_statusb);

#ifdef APIC_IO
	if (apic_8254_trial) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^




The testing that should be done is here. As you can see it is necessary only if we
have APIC_IO defined, i.e. in the SMP environment.

It is possible that we need early return from the procedure if statclock is
disabled but proper initialization of the APIC should be done anyway!

Also, probably ``flags 0x20'' should be deleted from the standard GENERIC kernel
since the most popular way of building new kernel config is stripping GENERIC
config people can getting trouble leaving that flag: from the comment in the LINT
it is absolutely unclear why it should be removed. At least, the comment about
the trouble described above is necessary in that remark in the LINT config since
it is not obvious at all that the apm flags can influence on the kernel boot-time
freezes.



By the way, it will be nice to have workaround for just turning power off without
including all those big and (as said in the man pages) instable code in order to
make possible to use FreeBSD on heavy-servers configurations without console at
all.

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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