qemu/hw/misc/sss.c
<<
>>
Prefs
   1/*
   2 * QEMU model of ZynqMP CSU Secure Stream Switch (SSS)
   3 *
   4 * For the most part, a dummy device model. Consumes as much data off the stream
   5 * interface as you can throw at it and produces zeros as fast as the sink is
   6 * willing to accept them.
   7 *
   8 * Copyright (c) 2013 Peter Xilinx Inc
   9 * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
  10 *
  11 * Permission is hereby granted, free of charge, to any person obtaining a copy
  12 * of this software and associated documentation files (the "Software"), to deal
  13 * in the Software without restriction, including without limitation the rights
  14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15 * copies of the Software, and to permit persons to whom the Software is
  16 * furnished to do so, subject to the following conditions:
  17 *
  18 * The above copyright notice and this permission notice shall be included in
  19 * all copies or substantial portions of the Software.
  20 *
  21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27 * THE SOFTWARE.
  28 */
  29
  30#include "qemu/osdep.h"
  31#include "hw/sysbus.h"
  32#include "qapi/error.h"
  33#include "qemu/log.h"
  34
  35#include "qemu/bitops.h"
  36#include "qapi/qmp/qerror.h"
  37#include "hw/misc/sss.h"
  38
  39void sss_notify_all(SSSBase *s)
  40{
  41    int remote;
  42
  43    for (remote = 0; remote < s->num_remotes; ++remote) {
  44        if (s->notifys[remote]) {
  45            s->notifys[remote](s->notify_opaques[remote]);
  46            s->notifys[remote] = NULL;
  47        }
  48    }
  49}
  50
  51static inline int
  52sss_lookup_rx_remote(SSSBase *s, SSSStream *ss)
  53{
  54    int ret;
  55
  56    for (ret = 0; ret < s->num_remotes; ++ret) {
  57        if (ss == &s->rx_devs[ret]) {
  58            break;
  59        }
  60    }
  61    return ret;
  62}
  63
  64static inline int
  65sss_lookup_tx_remote(SSSBase *s, int rx_remote)
  66{
  67    uint32_t enc;
  68    if (rx_remote == NOT_REMOTE(s)) {
  69        return NOT_REMOTE(s);
  70    }
  71
  72    int ret;
  73
  74    for (ret = 0; ret < NOT_REMOTE(s); ++ret) {
  75        if (s->r_sss_shifts[ret] == -1) {
  76            /* This unit has no input. Ignore it.  */
  77            continue;
  78        }
  79
  80        enc = s->get_sss_regfield(s, ret);
  81        if (s->r_sss_encodings[rx_remote] == enc) {
  82            break;
  83        }
  84    }
  85    return (s->sss_population[ret] & (1 << rx_remote)) ?
  86                    ret : NOT_REMOTE(s);
  87}
  88
  89static bool
  90sss_stream_can_push(StreamSlave *obj, StreamCanPushNotifyFn notify,
  91                                void *notify_opaque)
  92{
  93    SSSStream *ss = SSS_STREAM(obj);
  94    SSSBase *s = SSS_BASE(ss->sss);
  95    int rx = sss_lookup_rx_remote(s, ss);
  96    int tx = sss_lookup_tx_remote(s, rx);
  97
  98    if (tx != NOT_REMOTE(s) && s->tx_devs[tx] &&
  99            stream_can_push(s->tx_devs[tx], notify, notify_opaque)) {
 100        return true;
 101    }
 102
 103    s->notifys[rx] = notify;
 104    s->notify_opaques[rx] = notify_opaque;
 105    return false;
 106}
 107
 108
 109
 110static size_t sss_stream_push(StreamSlave *obj, uint8_t *buf,
 111                                          size_t len, uint32_t attr)
 112{
 113    SSSStream *ss = SSS_STREAM(obj);
 114    SSSBase *s = SSS_BASE(ss->sss);
 115    int rx = sss_lookup_rx_remote(s, ss);
 116    int tx = sss_lookup_tx_remote(s, rx);
 117
 118    return (tx != NOT_REMOTE(s)) ?
 119            stream_push(s->tx_devs[tx], buf, len, attr) : 0;
 120}
 121
 122/* FIXME: With no regs we are actually stateless. Although post load we need
 123 * to call notify() to start up the fire-hose of zeros again.
 124 */
 125
 126static void sss_stream_class_init(ObjectClass *klass, void *data)
 127{
 128    StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
 129
 130    ssc->push = sss_stream_push;
 131    ssc->can_push = sss_stream_can_push;
 132}
 133
 134static const TypeInfo sss_info = {
 135    .name         = TYPE_SSS_BASE,
 136    .parent       = TYPE_SYS_BUS_DEVICE,
 137    .instance_size = sizeof(SSSBase),
 138};
 139
 140static const TypeInfo sss_stream_info = {
 141    .name          = TYPE_SSS_STREAM,
 142    .parent        = TYPE_DEVICE,
 143    .instance_size = sizeof(SSSStream),
 144    .class_init    = sss_stream_class_init,
 145    .interfaces = (InterfaceInfo[]) {
 146        { TYPE_STREAM_SLAVE },
 147        { }
 148    }
 149};
 150
 151static void sss_register_types(void)
 152{
 153    type_register_static(&sss_info);
 154    type_register_static(&sss_stream_info);
 155}
 156
 157type_init(sss_register_types)
 158