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

wdt_diag288.c (3755B)


      1/*
      2 * watchdog device diag288 support
      3 *
      4 * Copyright IBM, Corp. 2015
      5 *
      6 * Authors:
      7 *  Xu Wang <gesaint@linux.vnet.ibm.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
     10 * option) any later version.  See the COPYING file in the top-level directory.
     11 *
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "sysemu/reset.h"
     16#include "sysemu/watchdog.h"
     17#include "qemu/timer.h"
     18#include "hw/watchdog/wdt_diag288.h"
     19#include "migration/vmstate.h"
     20#include "qemu/log.h"
     21
     22static WatchdogTimerModel model = {
     23    .wdt_name = TYPE_WDT_DIAG288,
     24    .wdt_description = "diag288 device for s390x platform",
     25};
     26
     27static const VMStateDescription vmstate_diag288 = {
     28    .name = "vmstate_diag288",
     29    .version_id = 0,
     30    .minimum_version_id = 0,
     31    .fields = (VMStateField[]) {
     32        VMSTATE_TIMER_PTR(timer, DIAG288State),
     33        VMSTATE_BOOL(enabled, DIAG288State),
     34        VMSTATE_END_OF_LIST()
     35    }
     36};
     37
     38static void wdt_diag288_reset(DeviceState *dev)
     39{
     40    DIAG288State *diag288 = DIAG288(dev);
     41
     42    diag288->enabled = false;
     43    timer_del(diag288->timer);
     44}
     45
     46static void diag288_reset(void *opaque)
     47{
     48    DeviceState *diag288 = opaque;
     49
     50    wdt_diag288_reset(diag288);
     51}
     52
     53static void diag288_timer_expired(void *dev)
     54{
     55    qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
     56    /* Reset the watchdog only if the guest gets notified about
     57     * expiry. watchdog_perform_action() may temporarily relinquish
     58     * the BQL; reset before triggering the action to avoid races with
     59     * diag288 instructions. */
     60    switch (get_watchdog_action()) {
     61    case WATCHDOG_ACTION_DEBUG:
     62    case WATCHDOG_ACTION_NONE:
     63    case WATCHDOG_ACTION_PAUSE:
     64        break;
     65    default:
     66        wdt_diag288_reset(dev);
     67    }
     68    watchdog_perform_action();
     69}
     70
     71static int wdt_diag288_handle_timer(DIAG288State *diag288,
     72                                     uint64_t func, uint64_t timeout)
     73{
     74    switch (func) {
     75    case WDT_DIAG288_INIT:
     76        diag288->enabled = true;
     77        /* fall through */
     78    case WDT_DIAG288_CHANGE:
     79        if (!diag288->enabled) {
     80            return -1;
     81        }
     82        timer_mod(diag288->timer,
     83                  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
     84                  timeout * NANOSECONDS_PER_SECOND);
     85        break;
     86    case WDT_DIAG288_CANCEL:
     87        if (!diag288->enabled) {
     88            return -1;
     89        }
     90        diag288->enabled = false;
     91        timer_del(diag288->timer);
     92        break;
     93    default:
     94        return -1;
     95    }
     96
     97    return 0;
     98}
     99
    100static void wdt_diag288_realize(DeviceState *dev, Error **errp)
    101{
    102    DIAG288State *diag288 = DIAG288(dev);
    103
    104    qemu_register_reset(diag288_reset, diag288);
    105    diag288->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, diag288_timer_expired,
    106                                  dev);
    107}
    108
    109static void wdt_diag288_unrealize(DeviceState *dev)
    110{
    111    DIAG288State *diag288 = DIAG288(dev);
    112
    113    timer_free(diag288->timer);
    114}
    115
    116static void wdt_diag288_class_init(ObjectClass *klass, void *data)
    117{
    118    DeviceClass *dc = DEVICE_CLASS(klass);
    119    DIAG288Class *diag288 = DIAG288_CLASS(klass);
    120
    121    dc->realize = wdt_diag288_realize;
    122    dc->unrealize = wdt_diag288_unrealize;
    123    dc->reset = wdt_diag288_reset;
    124    dc->hotpluggable = false;
    125    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    126    dc->vmsd = &vmstate_diag288;
    127    diag288->handle_timer = wdt_diag288_handle_timer;
    128}
    129
    130static const TypeInfo wdt_diag288_info = {
    131    .class_init = wdt_diag288_class_init,
    132    .parent = TYPE_DEVICE,
    133    .name  = TYPE_WDT_DIAG288,
    134    .instance_size  = sizeof(DIAG288State),
    135    .class_size = sizeof(DIAG288Class),
    136};
    137
    138static void wdt_diag288_register_types(void)
    139{
    140    watchdog_add_model(&model);
    141    type_register_static(&wdt_diag288_info);
    142}
    143
    144type_init(wdt_diag288_register_types)