Juergen:
Thanks for all your effort here! You're considerably ahead of me in
this project. :-)
I'm going to take a close look at the code sections you highlighted, and
go over them with Randy next week.
-- Garrett
Juergen Keil wrote:
> While my Tecra S1 Pentium-M Centrino notebook is now able to enter S3
> suspend-to-ram state, a power-on/resume has always resulted in a full
> reboot, not the expected wakeup from S3-STR state.
>
>
> There are apparently two problems in uts/i86pc/ml/cpr_wakecode.s:
>
>
> 1st Problem:
> ============
>
> The 32-bit i386 code at label kernel_wc_code in
> usr/src/uts/i86pc/ml/cpr_wakecode.s contains unconditional accesses to
> amd specific MSRs - most likely this doesn't work on non-amd cpus:
>
> movl $MSR_AMD_EFER, %ecx / re-enable NX bit
> rdmsr
> orl $AMD_EFER_NXE, %eax
> wrmsr
>
>
> This should be change to something like
>
>
> diff -r 111aa1baa84a usr/src/uts/i86pc/ml/cpr_wakecode.s
> --- a/usr/src/uts/i86pc/ml/cpr_wakecode.s Mon Oct 29 22:45:33 2007 -0700
> +++ b/usr/src/uts/i86pc/ml/cpr_wakecode.s Thu Nov 01 20:37:40 2007 +0100
>
> +
> + testl $X86_NX, x86_feature
> + jz 1f
> movl $MSR_AMD_EFER, %ecx / re-enable NX bit
> rdmsr
> orl $AMD_EFER_NXE, %eax
> wrmsr
> +1:
>
>
>
> 2nd Problem:
> ============
>
> The Tecra S1 is a uniprocessor PC and the BIOS doesn't
> enable the APIC. On this system there is no function to enable the APIC:
>
> # mdb -k
> Loading modules: [ unix genunix specfssrn open OK
> dtrace cpu.generic uppc scsi_vhci ufs ip hook neti sctp arp usba fctl nca
> zfs
> random lofs audiosup cpc fcip nsctl ptm sppp ]
>
>> ap_mlsetup::print
>>
> 0
>
> It seems cpr_wakecode.s just calls this NULL function pointer:
>
> /*
> * APIC initialization
> */
> call *ap_mlsetup
>
>
> Hmm, uppc.c defines psm_post_cpu_start as a NULL pointer in
> struct psm_ops uppc_ops. This replaces the initialization
> in usr/src/uts/i86pc/os/mp_machdep.c, which had set
> int (*ap_mlsetup)() = (int (*)(void))return_instr;
>
>
>
> Here we need something like the following fix:
>
> @@ -1003,9 +1107,12 @@ kernel_wc_code:
> movw WC_GS(%ebx), %gs
>
> /*
> - * APIC initialization
> - */
> + * APIC initialization, skip this on UPPC machines without APIC
> + */
> + cmpl $0, ap_mlsetup
> + je 2f
> call *ap_mlsetup
> +2:
>
> call *cpr_start_cpu_func
>
>
>
>
>
>
> I'm currently using this set of cpr_wakecode.s changes; this includes
> some changes to the SERIAL debug output code (where we need to
> wait until the previous char is removed from the COM1 transmit register
> before sending the next debug char, otherwise serial output is lost).
>
> With these changes a resume from S3-STR starts to work on the Tecra S1,
> but the resumed system stops with a "#df double fault" trap...
>
>
> diff -r 111aa1baa84a usr/src/uts/i86pc/ml/cpr_wakecode.s
> --- a/usr/src/uts/i86pc/ml/cpr_wakecode.s Mon Oct 29 22:45:33 2007 -0700
> +++ b/usr/src/uts/i86pc/ml/cpr_wakecode.s Thu Nov 01 20:37:40 2007 +0100
> @@ -844,15 +844,27 @@ wc_rm_end:
> #define SERIAL 1
>
> #if LED
> - D16 movl $0x80, %edx
> - D16 movb $0xd1, %al
> - outb (%dx)
> -#endif
> -
> -#if SERIAL
> - D16 movl $0x3f8, %edx
> - D16 movb $0x61, %al
> - outb (%dx)
> + D16 movl $0x80, %edx
> + D16 movb $0xd1, %al
> + outb (%dx)
> +#endif
> +
> +#if SERIAL
> + D16 movl $0x3fb, %edx / select com1 baud rate / ...
> + D16 movb $0x80, %al / ... divisor latch
> + outb (%dx)
> + D16 movl $0x3f8, %edx / baud rate = 115200 / divisor
> + D16 movb $0x0c, %al / set 9600 baud: divisor 0x0c
> + outb (%dx)
> + D16 movl $0x3f9, %edx
> + D16 movb $0x00, %al
> + outb (%dx)
> + D16 movl $0x3fb, %edx / select com1 transmit register
> + D16 movb $0x03, %al / ... and set com1 to "8n1"
> + outb (%dx)
> +
> + D16 movb $0x61, %al / transmit 'a'
> + D16 call comout
> #endif
>
>
> @@ -867,9 +879,8 @@ wc_rm_end:
> #endif
>
> #if SERIAL
> - D16 movl $0x3f8, %edx
> D16 movb $0x62, %al
> - outb (%dx)
> + D16 call comout
> #endif
>
> D16 A16 movl $WC_CPU, %ebx / base add of wc_cpu_t
> @@ -880,48 +891,97 @@ wc_rm_end:
> #endif
>
> #if SERIAL
> - D16 movl $0x3f8, %edx
> D16 movb $0x63, %al
> - outb (%dx)
> + D16 call comout
> #endif
>
> D16 A16 movl %cs:WC_DS(%ebx), %edx / %ds post prot/paging transit
>
> +#if LED
> D16 movb $0xd4, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x64, %al
> + D16 call comout
> +#endif
>
> D16 A16 lgdt %cs:WC_GDT(%ebx) / restore gdt and idtr
> D16 A16 lidt %cs:WC_IDT(%ebx)
>
> +#if LED
> D16 movb $0xd5, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x65, %al
> + D16 call comout
> +#endif
> +
>
> D16 A16 movl %cs:WC_CR4(%ebx), %eax / restore cr4
> D16 andl $-1!CR4_PGE, %eax / don't set Global Enable yet
> movl %eax, %cr4
>
> +#if LED
> D16 movb $0xd6, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x66, %al
> + D16 call comout
> +#endif
>
> D16 A16 movl %cs:WC_CR3(%ebx), %eax / set PDPT
> movl %eax, %cr3
>
> +#if LED
> D16 movb $0xd7, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x67, %al
> + D16 call comout
> +#endif
>
> D16 A16 movl %cs:WC_CR0(%ebx), %eax / enable prot/paging, etc.
> movl %eax, %cr0
>
> +#if LED
> D16 movb $0xd8, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x68, %al
> + D16 call comout
> +#endif
>
> D16 A16 movl %cs:WC_VIRTADDR(%ebx), %ebx / virtaddr of wc_cpu_t
>
> +#if LED
> D16 movb $0xd9, %al
> outb $0x80
> -
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x69, %al
> + D16 call comout
> +#endif
> +
> +#if LED
> D16 movb $0xda, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + D16 movb $0x6a, %al
> + D16 call comout
> +#endif
> jmp flush / flush prefetch queue
> flush:
> D16 pushl $KCS_SEL
> @@ -954,6 +1014,19 @@ cominit:
> int $0x14
> D16 ret
>
> +#if SERIAL
> +comout:
> + pushl %edx
> + D16 movl $0x3f8, %edx
> + outb (%dx)
> + D16 movl $0x3f8+5, %edx
> +1: inb (%dx)
> + testb $0x20, %al
> + jz 1b
> + popl %edx
> + D16 ret
> +#endif
> +
> .globl wc_rm_end
> wc_rm_end:
> nop
> @@ -967,19 +1040,50 @@ kernel_wc_code:
> / %ebx is wc_cpu
> / %dx is our ds
>
> +#if LED
> D16 movb $0xdb, %al
> outb $0x80
> +#endif
> +
> +#if SERIAL
> + movl %edx, %ecx
> + movw $0x3f8, %dx
> + movb $0x6b, %al
> + outb (%dx)
> + movw $0x3f8+5, %dx
> +1: inb (%dx)
> + testb $0x20, %al
> + jz 1b
> + movl %ecx, %edx
> +#endif
>
> / got here OK
>
> movw %dx, %ds / $KDS_SEL
> +#if LED
> movb $0xdc, %al
> outb $0x80
> -
> +#endif
> +
> +#if SERIAL
> + movl %edx, %ecx
> + movw $0x3f8, %dx
> + movb $0x6c, %al
> + outb (%dx)
> + movw $0x3f8+5, %dx
> +1: inb (%dx)
> + testb $0x20, %al
> + jz 1b
> + movl %ecx, %edx
> +#endif
> +
> + testl $X86_NX, x86_feature
> + jz 1f
> movl $MSR_AMD_EFER, %ecx / re-enable NX bit
> rdmsr
> orl $AMD_EFER_NXE, %eax
> wrmsr
> +1:
>
> movl WC_CR4(%ebx), %eax / restore full cr4 (with Global Enable)
> movl %eax, %cr4
> @@ -1003,9 +1107,12 @@ kernel_wc_code:
> movw WC_GS(%ebx), %gs
>
> /*
> - * APIC initialization
> - */
> + * APIC initialization, skip this on UPPC machines without APIC
> + */
> + cmpl $0, ap_mlsetup
> + je 2f
> call *ap_mlsetup
> +2:
>
> call *cpr_start_cpu_func
>
>
> _______________________________________________
> driver-discuss mailing list
> [email protected]
> http://mail.opensolaris.org/mailman/listinfo/driver-discuss
>
_______________________________________________
driver-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/driver-discuss