/************************************************************************** * arch/x86/src/qemu/qemu_fullcontextrestore.S * * Copyright (C) 2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /************************************************************************** * Conditional Compilation Options **************************************************************************/ /************************************************************************** * Included Files **************************************************************************/ #include #include #include "up_internal.h" .file "qemu_fullcontextrestore.S" /************************************************************************** * Pre-processor Definitions **************************************************************************/ /************************************************************************** * Global Variables **************************************************************************/ /**************************************************************************** * Macros ****************************************************************************/ /* Trace macros, use like trace 'i' to print char to serial port. */ .macro chout, addr, ch #ifdef CONFIG_DEBUG mov $\addr, %dx mov $\ch, %al out %al, %dx #endif .endm .macro trace, ch #ifdef CONFIG_DEBUG push %eax push %edx chout 0x3f8, \ch pop %edx pop %eax #endif .endm /************************************************************************** * Public Functions **************************************************************************/ .text /************************************************************************** * Name: up_fullcontextrestore * * Full C prototype: * void up_fullcontextrestore(uint32_t *regs) __attribute__ ((noreturn)); * **************************************************************************/ .globl up_fullcontextrestore .type up_fullcontextrestore, @function up_fullcontextrestore: /* Fetch the pointer to the register save array in EAX. */ movl 4(%esp), %eax /* Disable interrupts now (the correct EFLAGS will be restored before we * return */ cli /* We now have everything we need from the old stack. Now get the new * stack pointer. */ movl (4*REG_SP)(%eax), %esp /* Create an interrupt stack frame for the final iret. * * SP Before -> * SS * ESP * EFLAGS * CS * SP After -> EIP */ mov (4*REG_SS)(%eax), %ebx push %ebx movl (4*REG_SP)(%eax), %ebx push %ebx movl (4*REG_EFLAGS)(%eax), %ebx push %ebx mov (4*REG_CS)(%eax), %ebx push %ebx movl (4*REG_EIP)(%eax), %ebx push %ebx /* Save the value of EAX on the stack too */ movl (4*REG_EAX)(%eax), %ebx push %ebx /* Now restore the remaining registers */ movl (4*REG_ESI)(%eax), %esi movl (4*REG_EDI)(%eax), %edi movl (4*REG_EBP)(%eax), %ebp movl (4*REG_EBX)(%eax), %ebx movl (4*REG_EDX)(%eax), %edx movl (4*REG_ECX)(%eax), %ecx /* Restore the data segment register. I think there is an issue that will * need to be address here at some time: If the register save area is in * one data segment and the stack is in another, then the above would not * work (and, conversely, if they are in the same data segment, the * following is unnecessary and redundant). */ mov (4*REG_DS)(%eax), %ds /* Restore the correct value of EAX and then return */ popl %eax iret .size up_fullcontextrestore, . - up_fullcontextrestore .end