 97c4cb71c1
			
		
	
	
	97c4cb71c1
	
	
	
		
			
			Add code needed for basic suspend/resume of the XO-1 laptop. Based on earlier work by Jordan Crouse, Andres Salomon, and others. This patch incorporates all earlier feedback from Thomas Gleixner. To clarify a certain point (now more obvious in the code itself): On resume, OpenFirmware returns execution to Linux in protected mode with a kernel-compatible GDT already set up. The changes and simplifications suggested have all been included. Signed-off-by: Daniel Drake <dsd@laptop.org> Link: http://lkml.kernel.org/r/1309019658-1712-5-git-send-email-dsd@laptop.org Acked-by: Andres Salomon <dilinger@queued.net> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
		
			
				
	
	
		
			124 lines
		
	
	
	
		
			2.1 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
	
		
			2.1 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| .text
 | |
| #include <linux/linkage.h>
 | |
| #include <asm/segment.h>
 | |
| #include <asm/page.h>
 | |
| #include <asm/pgtable_32.h>
 | |
| 
 | |
| 	.macro writepost,value
 | |
| 		movb $0x34, %al
 | |
| 		outb %al, $0x70
 | |
| 		movb $\value, %al
 | |
| 		outb %al, $0x71
 | |
| 	.endm
 | |
| 
 | |
| wakeup_start:
 | |
| 	# OFW lands us here, running in protected mode, with a
 | |
| 	# kernel-compatible GDT already setup.
 | |
| 
 | |
| 	# Clear any dangerous flags
 | |
| 	pushl $0
 | |
| 	popfl
 | |
| 
 | |
| 	writepost 0x31
 | |
| 
 | |
| 	# Set up %cr3
 | |
| 	movl $initial_page_table - __PAGE_OFFSET, %eax
 | |
| 	movl %eax, %cr3
 | |
| 
 | |
| 	movl saved_cr4, %eax
 | |
| 	movl %eax, %cr4
 | |
| 
 | |
| 	movl saved_cr0, %eax
 | |
| 	movl %eax, %cr0
 | |
| 
 | |
| 	# Control registers were modified, pipeline resync is needed
 | |
| 	jmp 1f
 | |
| 1:
 | |
| 
 | |
| 	movw    $__KERNEL_DS, %ax
 | |
| 	movw    %ax, %ss
 | |
| 	movw    %ax, %ds
 | |
| 	movw    %ax, %es
 | |
| 	movw    %ax, %fs
 | |
| 	movw    %ax, %gs
 | |
| 
 | |
| 	lgdt    saved_gdt
 | |
| 	lidt    saved_idt
 | |
| 	lldt    saved_ldt
 | |
| 	ljmp    $(__KERNEL_CS),$1f
 | |
| 1:
 | |
| 	movl    %cr3, %eax
 | |
| 	movl    %eax, %cr3
 | |
| 	wbinvd
 | |
| 
 | |
| 	# Go back to the return point
 | |
| 	jmp ret_point
 | |
| 
 | |
| save_registers:
 | |
| 	sgdt  saved_gdt
 | |
| 	sidt  saved_idt
 | |
| 	sldt  saved_ldt
 | |
| 
 | |
| 	pushl %edx
 | |
| 	movl %cr4, %edx
 | |
| 	movl %edx, saved_cr4
 | |
| 
 | |
| 	movl %cr0, %edx
 | |
| 	movl %edx, saved_cr0
 | |
| 
 | |
| 	popl %edx
 | |
| 
 | |
| 	movl %ebx, saved_context_ebx
 | |
| 	movl %ebp, saved_context_ebp
 | |
| 	movl %esi, saved_context_esi
 | |
| 	movl %edi, saved_context_edi
 | |
| 
 | |
| 	pushfl
 | |
| 	popl saved_context_eflags
 | |
| 
 | |
| 	ret
 | |
| 
 | |
| restore_registers:
 | |
| 	movl saved_context_ebp, %ebp
 | |
| 	movl saved_context_ebx, %ebx
 | |
| 	movl saved_context_esi, %esi
 | |
| 	movl saved_context_edi, %edi
 | |
| 
 | |
| 	pushl saved_context_eflags
 | |
| 	popfl
 | |
| 
 | |
| 	ret
 | |
| 
 | |
| ENTRY(do_olpc_suspend_lowlevel)
 | |
| 	call	save_processor_state
 | |
| 	call	save_registers
 | |
| 
 | |
| 	# This is the stack context we want to remember
 | |
| 	movl %esp, saved_context_esp
 | |
| 
 | |
| 	pushl	$3
 | |
| 	call	xo1_do_sleep
 | |
| 
 | |
| 	jmp	wakeup_start
 | |
| 	.p2align 4,,7
 | |
| ret_point:
 | |
| 	movl    saved_context_esp, %esp
 | |
| 
 | |
| 	writepost 0x32
 | |
| 
 | |
| 	call	restore_registers
 | |
| 	call	restore_processor_state
 | |
| 	ret
 | |
| 
 | |
| .data
 | |
| saved_gdt:             .long   0,0
 | |
| saved_idt:             .long   0,0
 | |
| saved_ldt:             .long   0
 | |
| saved_cr4:             .long   0
 | |
| saved_cr0:             .long   0
 | |
| saved_context_esp:     .long   0
 | |
| saved_context_edi:     .long   0
 | |
| saved_context_esi:     .long   0
 | |
| saved_context_ebx:     .long   0
 | |
| saved_context_ebp:     .long   0
 | |
| saved_context_eflags:  .long   0
 |