Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 02 Oct 2006 15:03:03 -0700
From:      Nate Lawson <nate@root.org>
To:        John Baldwin <jhb@freebsd.org>
Cc:        freebsd-acpi@freebsd.org, Andrea Bittau <a.bittau@cs.ucl.ac.uk>, freebsd-mobile@freebsd.org
Subject:   Re: hack for getting suspend/resume to half work on an IBM Thinkpad x60s [SMP]
Message-ID:  <45218C97.5050802@root.org>
In-Reply-To: <200610021424.18562.jhb@freebsd.org>
References:  <20060921000628.GA1832@shorty.sorbonet.org> <200610021424.18562.jhb@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
John Baldwin wrote:
> On Wednesday 20 September 2006 20:06, Andrea Bittau wrote:
>> This is a half working hack for getting suspend/resume to "work" on an IBM
>>
>> ...
>>
>> 2) apic.  FreeBSD reconfigures the io apic upon resume, but not the local 
> apic.
>>    The patch attached to this mail fixes this.  Indeed, it almost does so in 
> the
>>    "proper" way and not so much of a hack =D.
> 
> I actually have made a full patch for APIC I think (thanks for your work as it 
> reminded me about needing to resume lapic).  You can find it at 
> http://www.FreeBSD.org/~jhb/patches/apic_resume.patch  It changes the x86 
> interrupt code to resume interrupt controllers, not interrupt sources.  It 
> then uses this to make sure the 8259A PICs are properly reset on resume as 
> well as resuming the local APIC.  Can you test this w/o SMP and make sure it 
> works?

Great to see this work going on.  I just got a Core Duo laptop so this 
would be great to see fixed.

I'm kinda disappointed you're not using newbus for your device methods, 
but I think I mentioned that before.

On the reset code, shouldn't there be some delays between writes to the 
registers?

+	outb(IO_ICU1, ICW1_RESET | ICW1_IC4);
+	outb(IO_ICU1 + ICU_IMR_OFFSET, IDT_IO_INTS);
[delay?]
+	outb(IO_ICU1 + ICU_IMR_OFFSET, 1 << 2);
[delay?]
+	outb(IO_ICU1 + ICU_IMR_OFFSET, ICW4_8086);
[delay?]
+	outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff);
+	outb(IO_ICU1, OCW3_SEL | OCW3_RR);
+
+	outb(IO_ICU2, ICW1_RESET | ICW1_IC4);
+	outb(IO_ICU2 + ICU_IMR_OFFSET, IDT_IO_INTS + 8);
[delay?]
+	outb(IO_ICU2 + ICU_IMR_OFFSET, 2);
[delay?]
+	outb(IO_ICU2 + ICU_IMR_OFFSET, ICW4_8086);
[delay?]
+	outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff);
+	outb(IO_ICU2, OCW3_SEL | OCW3_RR);


>> 3) SMP.  The second core needs to be killed and woken up as appropriate.  
> The
>>    way I do this is quite lame.
>>    - Force the second core in the idle loop by setting machdep.hlt_cpus=2.
>>    - make system look like UP instead of SMP [i.e. deactivate SMP] & 
> suspend.
>>    - resume, wake up other core [which will run idle process] and activate 
> SMP.
> 
> Probably we need to get onto the BSP via sched_bind() during suspend and then 
> stop the other CPUs using stop_cpus().  The hard part, however, is properly 
> resuming the darn things.  Do you know what mode the CPUs come back up in?  
> It looks like we need to resend startup IPIs to them from your patch.

The writes to the PM registers should happen from the BSP anyway, so 
sched_bind() is the right way to go.  I think you need to start them up 
the same as boot, including startup IPI and then enabling scheduling on 
them.

-- 
Nate



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