Re: wakeup code translated to .c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sunday, 3 of February 2008, Rafael J. Wysocki wrote:
> On Sunday, 3 of February 2008, Pavel Machek wrote:
> > Hi!
> > 
> > > > This version works on 32-bit, and builds on 64-bit (but I'm pretty
> > > > sure it does not work. 32-bit code probably needs to go into rm/....)
> > > > 
> > > 
> > > Do you have an updated version or is this the latest one?
> > 
> > I'm glad you ask ;-). Here's reasonably-recent version (I have
> > slightly cleaner one, but it got obscured by 2.6.24-git merge), I
> > eventually got it to work on 64-bit, by reusing trampoline.S code.
> 
> I needed to rebase it against the current mainline (Makefile conflict).
> 
> Some remarks:
> 
> - It looks like arch/x86/kernel/acpi/wakeup.S is not necessary any more.
> 
> - These warnings:
> 
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c: In function ‘acpi_save_state_mem’:
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:41: warning: initialization makes pointer from integer without a cast
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:50: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:50: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long unsigned int’
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:70: warning: ISO C90 forbids mixed declarations and code
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:82: warning: assignment makes integer from pointer without a cast
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:83: warning: assignment makes integer from pointer without a cast
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:84: warning: ISO C90 forbids mixed declarations and code
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:87: warning: ISO C90 forbids mixed declarations and code
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:90: warning: assignment makes integer from pointer without a cast
> /home/rafael/src/linux-2.6/arch/x86/kernel/acpi/sleep.c:91: warning: ISO C90 forbids mixed declarations and code
> 
> look pretty scary.

Below is the arch/x86/kernel/acpi/sleep.c part without the warnings (untested).

It still contains some hardcoded magic numbers and extern declarations, so
I guess the #include list is not complete or another header is necessary.

BTW:
1) why exactly is acpi_wakeup_address not (void *)?
2) header->level3_ident_pgt and header->level3_ident_pgt could be (char *) IMO


--- linux-2.6.orig/arch/x86/kernel/acpi/sleep.c
+++ linux-2.6/arch/x86/kernel/acpi/sleep.c
@@ -11,29 +11,92 @@
 #include <linux/cpumask.h>
 
 #include <asm/smp.h>
+#include "rm/wakeup.h"
 
 /* address in low memory of the wakeup routine. */
-unsigned long acpi_wakeup_address = 0;
+static unsigned long acpi_realmode;
+unsigned long acpi_wakeup_address;
 unsigned long acpi_realmode_flags;
-extern char wakeup_start, wakeup_end;
 
+extern char wakeup_code_start, wakeup_code_end;
 extern unsigned long acpi_copy_wakeup_routine(unsigned long);
+extern unsigned long setup_trampoline(void);
+extern void wakeup_long64(void);
+
+extern unsigned long saved_video_mode;
+extern long saved_magic;
+extern char level3_ident_pgt[PAGE_SIZE];
+extern char level3_kernel_pgt[PAGE_SIZE];
+extern volatile unsigned long init_rsp;
+extern void (*initial_code)(void);
+#ifndef CONFIG_64BIT
+extern int wakeup_pmode_return;
+extern char swsusp_pg_dir[PAGE_SIZE];
+#endif
+
+static char temp_stack[10240];
 
 /**
  * acpi_save_state_mem - save kernel state
  *
  * Create an identity mapped page table and copy the wakeup routine to
  * low memory.
+ *
+ * Note that this is too late to change acpi_wakeup_address.
  */
 int acpi_save_state_mem(void)
 {
-	if (!acpi_wakeup_address) {
-		printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n");
+	struct wakeup_header *header;
+
+	printk("acpi_save_state_mem\n");
+
+	if (!acpi_realmode) {
+		printk(KERN_ERR "Could not allocate memory during boot, "
+				"S3 disabled\n");
 		return -ENOMEM;
 	}
-	memcpy((void *)acpi_wakeup_address, &wakeup_start,
-	       &wakeup_end - &wakeup_start);
-	acpi_copy_wakeup_routine(acpi_wakeup_address);
+
+	memcpy((void *)acpi_realmode, &wakeup_code_start, 4*PAGE_SIZE);
+
+	header = (struct wakeup_header *)(acpi_realmode + 0x3f00);
+	if (header->signature != 0x51ee1111) {
+		printk(KERN_ERR "wakeup header does not match\n");
+		return -EINVAL;
+	}
+
+	header->video_mode = saved_video_mode;
+	printk("Video mode = %lu, realmode flags = %lu\n",
+		saved_video_mode, acpi_realmode_flags);
+	mdelay(1000);
+
+#ifndef CONFIG_64BIT
+	store_gdt(&header->pmode_gdt);
+
+	header->pmode_efer_low = nx_enabled;
+	if (header->pmode_efer_low & 1) {
+		/* This is strange, why not save efer, always? */
+		rdmsr(MSR_EFER, header->pmode_efer_low,
+			header->pmode_efer_high);
+	}
+#endif /* !CONFIG_64BIT */
+
+	header->pmode_cr0 = read_cr0();
+	header->pmode_cr4 = read_cr4();
+	header->realmode_flags = acpi_realmode_flags;
+	header->real_magic = 0x12345678;
+
+#ifndef CONFIG_64BIT
+	header->pmode_entry = &wakeup_pmode_return;
+	header->pmode_cr3 = swsusp_pg_dir - __PAGE_OFFSET;
+	saved_magic = 0x12345678;
+#else /* CONFIG_64BIT */
+	header->level3_ident_pgt = (u64)level3_ident_pgt;
+	header->level3_kernel_pgt = (u64)level3_kernel_pgt;
+	header->trampoline_segment = setup_trampoline() >> 4;
+	init_rsp = (unsigned long)temp_stack + 4096;
+	initial_code = wakeup_long64;
+	saved_magic = 0x123456789abcdef0;
+#endif /* CONFIG_64BIT */
 
 	return 0;
 }
@@ -56,15 +119,20 @@ void acpi_restore_state_mem(void)
  */
 void __init acpi_reserve_bootmem(void)
 {
-	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE*2) {
+	if ((&wakeup_code_end - &wakeup_code_start) > PAGE_SIZE*4) {
 		printk(KERN_ERR
 		       "ACPI: Wakeup code way too big, S3 disabled.\n");
 		return;
 	}
 
-	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
-	if (!acpi_wakeup_address)
+	acpi_realmode = (unsigned long)alloc_bootmem_low(PAGE_SIZE*4);
+
+	if (!acpi_realmode) {
 		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
+		return;
+	}
+
+	acpi_wakeup_address = acpi_realmode;
 }
 
 

_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux