162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci.text 362306a36Sopenharmony_ci#include <linux/linkage.h> 462306a36Sopenharmony_ci#include <asm/segment.h> 562306a36Sopenharmony_ci#include <asm/page.h> 662306a36Sopenharmony_ci#include <asm/pgtable_32.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci .macro writepost,value 962306a36Sopenharmony_ci movb $0x34, %al 1062306a36Sopenharmony_ci outb %al, $0x70 1162306a36Sopenharmony_ci movb $\value, %al 1262306a36Sopenharmony_ci outb %al, $0x71 1362306a36Sopenharmony_ci .endm 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciwakeup_start: 1662306a36Sopenharmony_ci # OFW lands us here, running in protected mode, with a 1762306a36Sopenharmony_ci # kernel-compatible GDT already setup. 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci # Clear any dangerous flags 2062306a36Sopenharmony_ci pushl $0 2162306a36Sopenharmony_ci popfl 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci writepost 0x31 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci # Set up %cr3 2662306a36Sopenharmony_ci movl $initial_page_table - __PAGE_OFFSET, %eax 2762306a36Sopenharmony_ci movl %eax, %cr3 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci movl saved_cr4, %eax 3062306a36Sopenharmony_ci movl %eax, %cr4 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci movl saved_cr0, %eax 3362306a36Sopenharmony_ci movl %eax, %cr0 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci # Control registers were modified, pipeline resync is needed 3662306a36Sopenharmony_ci jmp 1f 3762306a36Sopenharmony_ci1: 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci movw $__KERNEL_DS, %ax 4062306a36Sopenharmony_ci movw %ax, %ss 4162306a36Sopenharmony_ci movw %ax, %ds 4262306a36Sopenharmony_ci movw %ax, %es 4362306a36Sopenharmony_ci movw %ax, %fs 4462306a36Sopenharmony_ci movw %ax, %gs 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci lgdt saved_gdt 4762306a36Sopenharmony_ci lidt saved_idt 4862306a36Sopenharmony_ci lldt saved_ldt 4962306a36Sopenharmony_ci ljmp $(__KERNEL_CS),$1f 5062306a36Sopenharmony_ci1: 5162306a36Sopenharmony_ci movl %cr3, %eax 5262306a36Sopenharmony_ci movl %eax, %cr3 5362306a36Sopenharmony_ci wbinvd 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci # Go back to the return point 5662306a36Sopenharmony_ci jmp ret_point 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cisave_registers: 5962306a36Sopenharmony_ci sgdt saved_gdt 6062306a36Sopenharmony_ci sidt saved_idt 6162306a36Sopenharmony_ci sldt saved_ldt 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci pushl %edx 6462306a36Sopenharmony_ci movl %cr4, %edx 6562306a36Sopenharmony_ci movl %edx, saved_cr4 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci movl %cr0, %edx 6862306a36Sopenharmony_ci movl %edx, saved_cr0 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci popl %edx 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci movl %ebx, saved_context_ebx 7362306a36Sopenharmony_ci movl %ebp, saved_context_ebp 7462306a36Sopenharmony_ci movl %esi, saved_context_esi 7562306a36Sopenharmony_ci movl %edi, saved_context_edi 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci pushfl 7862306a36Sopenharmony_ci popl saved_context_eflags 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci RET 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cirestore_registers: 8362306a36Sopenharmony_ci movl saved_context_ebp, %ebp 8462306a36Sopenharmony_ci movl saved_context_ebx, %ebx 8562306a36Sopenharmony_ci movl saved_context_esi, %esi 8662306a36Sopenharmony_ci movl saved_context_edi, %edi 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci pushl saved_context_eflags 8962306a36Sopenharmony_ci popfl 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci RET 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciSYM_CODE_START(do_olpc_suspend_lowlevel) 9462306a36Sopenharmony_ci call save_processor_state 9562306a36Sopenharmony_ci call save_registers 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci # This is the stack context we want to remember 9862306a36Sopenharmony_ci movl %esp, saved_context_esp 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci pushl $3 10162306a36Sopenharmony_ci call xo1_do_sleep 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci jmp wakeup_start 10462306a36Sopenharmony_ci .p2align 4,,7 10562306a36Sopenharmony_ciret_point: 10662306a36Sopenharmony_ci movl saved_context_esp, %esp 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci writepost 0x32 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci call restore_registers 11162306a36Sopenharmony_ci call restore_processor_state 11262306a36Sopenharmony_ci RET 11362306a36Sopenharmony_ciSYM_CODE_END(do_olpc_suspend_lowlevel) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci.data 11662306a36Sopenharmony_cisaved_gdt: .long 0,0 11762306a36Sopenharmony_cisaved_idt: .long 0,0 11862306a36Sopenharmony_cisaved_ldt: .long 0 11962306a36Sopenharmony_cisaved_cr4: .long 0 12062306a36Sopenharmony_cisaved_cr0: .long 0 12162306a36Sopenharmony_cisaved_context_esp: .long 0 12262306a36Sopenharmony_cisaved_context_edi: .long 0 12362306a36Sopenharmony_cisaved_context_esi: .long 0 12462306a36Sopenharmony_cisaved_context_ebx: .long 0 12562306a36Sopenharmony_cisaved_context_ebp: .long 0 12662306a36Sopenharmony_cisaved_context_eflags: .long 0 127