cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

coroutine-win32.c (3120B)


      1/*
      2 * Win32 coroutine initialization code
      3 *
      4 * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu-common.h"
     27#include "qemu/coroutine_int.h"
     28
     29typedef struct
     30{
     31    Coroutine base;
     32
     33    LPVOID fiber;
     34    CoroutineAction action;
     35} CoroutineWin32;
     36
     37static __thread CoroutineWin32 leader;
     38static __thread Coroutine *current;
     39
     40/* This function is marked noinline to prevent GCC from inlining it
     41 * into coroutine_trampoline(). If we allow it to do that then it
     42 * hoists the code to get the address of the TLS variable "current"
     43 * out of the while() loop. This is an invalid transformation because
     44 * the SwitchToFiber() call may be called when running thread A but
     45 * return in thread B, and so we might be in a different thread
     46 * context each time round the loop.
     47 */
     48CoroutineAction __attribute__((noinline))
     49qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
     50                      CoroutineAction action)
     51{
     52    CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
     53    CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
     54
     55    current = to_;
     56
     57    to->action = action;
     58    SwitchToFiber(to->fiber);
     59    return from->action;
     60}
     61
     62static void CALLBACK coroutine_trampoline(void *co_)
     63{
     64    Coroutine *co = co_;
     65
     66    while (true) {
     67        co->entry(co->entry_arg);
     68        qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
     69    }
     70}
     71
     72Coroutine *qemu_coroutine_new(void)
     73{
     74    const size_t stack_size = COROUTINE_STACK_SIZE;
     75    CoroutineWin32 *co;
     76
     77    co = g_malloc0(sizeof(*co));
     78    co->fiber = CreateFiber(stack_size, coroutine_trampoline, &co->base);
     79    return &co->base;
     80}
     81
     82void qemu_coroutine_delete(Coroutine *co_)
     83{
     84    CoroutineWin32 *co = DO_UPCAST(CoroutineWin32, base, co_);
     85
     86    DeleteFiber(co->fiber);
     87    g_free(co);
     88}
     89
     90Coroutine *qemu_coroutine_self(void)
     91{
     92    if (!current) {
     93        current = &leader.base;
     94        leader.fiber = ConvertThreadToFiber(NULL);
     95    }
     96    return current;
     97}
     98
     99bool qemu_in_coroutine(void)
    100{
    101    return current && current->caller;
    102}