qemu/hw/core/remote-port.c
<<
>>
Prefs
   1/*
   2 * QEMU remote attach
   3 *
   4 * Copyright (c) 2013 Xilinx Inc
   5 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   6 *
   7 * This code is licensed under the GNU GPL.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "sysemu/sysemu.h"
  12#include "sysemu/dma.h"
  13#include "sysemu/char.h"
  14#include "sysemu/cpus.h"
  15#include "hw/sysbus.h"
  16#include "hw/ptimer.h"
  17#include "qemu/sockets.h"
  18#include "qemu/thread.h"
  19#include "qemu/log.h"
  20#include "qapi/error.h"
  21#include "qemu/error-report.h"
  22#include "qom/cpu.h"
  23
  24#include <semaphore.h>
  25#ifndef _WIN32
  26#include <sys/mman.h>
  27#endif
  28
  29#include "hw/fdt_generic_util.h"
  30#include "hw/remote-port-proto.h"
  31#include "hw/remote-port-device.h"
  32#include "hw/remote-port.h"
  33
  34#define D(x)
  35#define SYNCD(x)
  36
  37#ifndef REMOTE_PORT_ERR_DEBUG
  38#define REMOTE_PORT_DEBUG_LEVEL 0
  39#else
  40#define REMOTE_PORT_DEBUG_LEVEL 1
  41#endif
  42
  43#define DB_PRINT_L(level, ...) do { \
  44    if (REMOTE_PORT_DEBUG_LEVEL > level) { \
  45        fprintf(stderr,  ": %s: ", __func__); \
  46        fprintf(stderr, ## __VA_ARGS__); \
  47    } \
  48} while (0);
  49
  50#define REMOTE_PORT_CLASS(klass)    \
  51     OBJECT_CLASS_CHECK(RemotePortClass, (klass), TYPE_REMOTE_PORT)
  52
  53static bool time_warp_enable = true;
  54
  55bool rp_time_warp_enable(bool en)
  56{
  57    bool ret = time_warp_enable;
  58
  59    time_warp_enable = en;
  60    return ret;
  61}
  62
  63static void rp_process(RemotePort *s);
  64static void rp_event_read(void *opaque);
  65static void sync_timer_hit(void *opaque);
  66static void syncresp_timer_hit(void *opaque);
  67
  68static void rp_pkt_dump(const char *prefix, const char *buf, size_t len)
  69{
  70    qemu_hexdump(buf, stdout, prefix, len);
  71}
  72
  73uint32_t rp_new_id(RemotePort *s)
  74{
  75    return s->current_id++;
  76}
  77
  78void rp_rsp_mutex_lock(RemotePort *s)
  79{
  80    qemu_mutex_lock(&s->rsp_mutex);
  81}
  82
  83void rp_rsp_mutex_unlock(RemotePort *s)
  84{
  85    qemu_mutex_unlock(&s->rsp_mutex);
  86}
  87
  88int64_t rp_normalized_vmclk(RemotePort *s)
  89{
  90    int64_t clk;
  91
  92    clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  93    clk -= s->peer.clk_base;
  94    return clk;
  95}
  96
  97static inline int64_t rp_denormalize_clk(RemotePort *s, int64_t rclk)
  98{
  99    int64_t clk;
 100    clk = rclk + s->peer.clk_base;
 101    return clk;
 102}
 103
 104void rp_restart_sync_timer(RemotePort *s)
 105{
 106    if (!use_icount || !s->do_sync) {
 107        return;
 108    }
 109
 110    if (s->sync.quantum) {
 111        ptimer_stop(s->sync.ptimer);
 112        ptimer_set_limit(s->sync.ptimer, s->sync.quantum, 1);
 113        ptimer_run(s->sync.ptimer, 1);
 114    } else {
 115        ptimer_stop(s->sync.ptimer);
 116        ptimer_set_limit(s->sync.ptimer, 10 * 1000, 1);
 117        ptimer_run(s->sync.ptimer, 1);
 118    }
 119}
 120
 121static void rp_fatal_error(RemotePort *s, const char *reason)
 122{
 123    int64_t clk = rp_normalized_vmclk(s);
 124    error_report("%s: %s clk=%" PRIu64 " ns\n", s->prefix, reason, clk);
 125    exit(EXIT_FAILURE);
 126}
 127
 128static ssize_t rp_recv(RemotePort *s, void *buf, size_t count)
 129{
 130    ssize_t r;
 131
 132    r = qemu_chr_fe_read_all(s->chr, buf, count);
 133    if (r <= 0) {
 134        rp_fatal_error(s, "Disconnected");
 135    }
 136    if (r != count) {
 137        error_report("%s: Bad read, expected %zd but got %zd\n",
 138                     s->prefix, count, r);
 139        rp_fatal_error(s, "Bad read");
 140    }
 141
 142    return r;
 143}
 144
 145ssize_t rp_write(RemotePort *s, const void *buf, size_t count)
 146{
 147    ssize_t r;
 148
 149    qemu_mutex_lock(&s->write_mutex);
 150    r = qemu_chr_fe_write(s->chr, buf, count);
 151    qemu_mutex_unlock(&s->write_mutex);
 152    if (r <= 0) {
 153        error_report("%s: Disconnected r=%zd buf=%p count=%zd\n",
 154                     s->prefix, r, buf, count);
 155        rp_fatal_error(s, "Bad write");
 156    }
 157    return r;
 158}
 159
 160/* Warp time if cpus are idle. diff is max time in ns to warp.  */
 161static int64_t rp_time_warp(RemotePort *s, int64_t diff)
 162{
 163    int64_t future = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + diff;
 164    int64_t clk;
 165
 166    if (!time_warp_enable) {
 167        return 0;
 168    }
 169
 170    /* If cpus are idle. warp.  */
 171    do {
 172        bool cpus_idle;
 173
 174        cpus_idle = tcg_idle_clock_warp(future);
 175        clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 176        if (!cpus_idle) {
 177            break;
 178        }
 179    } while (clk < future);
 180
 181    return future - clk;
 182}
 183
 184static void rp_idle(void *opaque)
 185{
 186    int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
 187    if (deadline == INT32_MAX) {
 188            return;
 189    }
 190    rp_time_warp(opaque, deadline);
 191}
 192
 193void rp_leave_iothread(RemotePort *s)
 194{
 195    if (use_icount && all_cpu_threads_idle() && time_warp_enable) {
 196        async_run_on_cpu(first_cpu, rp_idle, s);
 197    }
 198}
 199
 200RemotePortDynPkt rp_wait_resp(RemotePort *s)
 201{
 202    while (!rp_dpkt_is_valid(&s->rspqueue)) {
 203        rp_event_read(s);
 204        qemu_cond_wait(&s->progress_cond, &s->rsp_mutex);
 205    }
 206    return s->rspqueue;
 207}
 208
 209void rp_sync_vmclock(RemotePort *s, int64_t lclk, int64_t rclk)
 210{
 211    int64_t diff;
 212
 213    /* FIXME: syncing is broken at the moment.  */
 214    return;
 215
 216    if (!time_warp_enable) {
 217        return;
 218    }
 219
 220    /* Warp all the way to dest. We need to account for
 221       spent time in the remote call.  */
 222    while (lclk < rclk) {
 223        diff = rclk - lclk;
 224        tcg_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + diff);
 225        lclk = rp_normalized_vmclk(s);
 226    }
 227
 228    if (lclk < rclk) {
 229        printf("Wrong sync! local=%" PRIu64 " remote=%" PRIu64 "\n", lclk, rclk);
 230    }
 231}
 232
 233static void rp_cmd_hello(RemotePort *s, struct rp_pkt *pkt)
 234{
 235    s->peer.version = pkt->hello.version;
 236    if (pkt->hello.version.major != RP_VERSION_MAJOR) {
 237        error_report("remote-port version missmatch remote=%d.%d local=%d.%d\n",
 238                      pkt->hello.version.major, pkt->hello.version.minor,
 239                      RP_VERSION_MAJOR, RP_VERSION_MINOR);
 240        rp_fatal_error(s, "Bad version");
 241    }
 242
 243    if (pkt->hello.caps.len) {
 244        void *caps = (char *) pkt + pkt->hello.caps.offset;
 245
 246        rp_process_caps(&s->peer, caps, pkt->hello.caps.len);
 247    }
 248}
 249
 250static void rp_cmd_sync(RemotePort *s, struct rp_pkt *pkt)
 251{
 252    size_t enclen;
 253    int64_t clk;
 254    int64_t diff;
 255
 256    assert(!(pkt->hdr.flags & RP_PKT_FLAGS_response));
 257
 258    /* If cpus are idle. warp.  */
 259    clk = rp_normalized_vmclk(s);
 260    diff = pkt->sync.timestamp - clk;
 261    if (diff > 0LL && use_icount && time_warp_enable) {
 262        diff = rp_time_warp(s, diff);
 263    }
 264
 265    enclen = rp_encode_sync_resp(pkt->hdr.id, pkt->hdr.dev, &s->sync.rsp.sync,
 266                                 pkt->sync.timestamp);
 267    assert(enclen == sizeof s->sync.rsp.sync);
 268
 269    /* We are already a head of time.  */
 270    if (all_cpu_threads_idle() || 0) {
 271        if (pkt->sync.timestamp >  clk && use_icount)
 272            rp_sync_vmclock(s, clk, pkt->sync.timestamp);
 273    }
 274
 275    /* We have temporarily disabled blocking syncs into QEMU.  */
 276    if (diff <= 0LL || true) {
 277        /* We are already a head of time. Respond and issue a sync.  */
 278        SYNCD(printf("%s: sync resp %lu\n", s->prefix, pkt->sync.timestamp));
 279        rp_write(s, (void *) &s->sync.rsp, enclen);
 280        return;
 281    }
 282
 283    SYNCD(printf("%s: delayed sync resp - start diff=%ld (ts=%lu clk=%lu)\n",
 284          s->prefix, pkt->sync.timestamp - clk, pkt->sync.timestamp, clk));
 285    ptimer_set_limit(s->sync.ptimer_resp, diff, 1);
 286    ptimer_run(s->sync.ptimer_resp, 1);
 287    s->sync.resp_timer_enabled = true;
 288}
 289
 290static void rp_say_hello(RemotePort *s)
 291{
 292    struct rp_pkt_hello pkt;
 293    uint32_t caps[] = {
 294        CAP_BUSACCESS_EXT_BASE,
 295        CAP_BUSACCESS_EXT_BYTE_EN,
 296    };
 297    size_t len;
 298
 299    len = rp_encode_hello_caps(s->current_id++, 0, &pkt, RP_VERSION_MAJOR,
 300                               RP_VERSION_MINOR,
 301                               caps, caps, sizeof caps / sizeof caps[0]);
 302    rp_write(s, (void *) &pkt, len);
 303
 304    if (sizeof caps) {
 305        rp_write(s, caps, sizeof caps);
 306    }
 307}
 308
 309static void rp_say_sync(RemotePort *s, int64_t clk)
 310{
 311    struct rp_pkt_sync pkt;
 312    size_t len;
 313
 314    len = rp_encode_sync(s->current_id++, 0, &pkt, clk);
 315    rp_write(s, (void *) &pkt, len);
 316}
 317
 318static void syncresp_timer_hit(void *opaque)
 319{
 320    RemotePort *s = REMOTE_PORT(opaque);
 321
 322    s->sync.resp_timer_enabled = false;
 323    SYNCD(printf("%s: delayed sync response - send\n", s->prefix));
 324    rp_write(s, (void *) &s->sync.rsp, sizeof s->sync.rsp.sync);
 325    memset(&s->sync.rsp, 0, sizeof s->sync.rsp);
 326
 327    rp_leave_iothread(s);
 328}
 329
 330static void sync_timer_hit(void *opaque)
 331{
 332    RemotePort *s = REMOTE_PORT(opaque);
 333    int64_t clk;
 334    int64_t rclk;
 335    RemotePortDynPkt rsp;
 336
 337    if (!use_icount) {
 338        hw_error("Sync timer without icount??\n");
 339    }
 340
 341    clk = rp_normalized_vmclk(s);
 342    if (s->sync.resp_timer_enabled) {
 343        SYNCD(printf("%s: sync while delaying a resp! clk=%lu\n",
 344                     s->prefix, clk));
 345        s->sync.need_sync = true;
 346        rp_restart_sync_timer(s);
 347        rp_leave_iothread(s);
 348        return;
 349    }
 350
 351    /* Sync.  */
 352    s->sync.need_sync = false;
 353    qemu_mutex_lock(&s->rsp_mutex);
 354    /* Send the sync.  */
 355    rp_say_sync(s, clk);
 356
 357    SYNCD(printf("%s: syncing wait for resp %lu\n", s->prefix, clk));
 358    rsp = rp_wait_resp(s);
 359    rclk = rsp.pkt->sync.timestamp;
 360    rp_dpkt_invalidate(&rsp);
 361    qemu_mutex_unlock(&s->rsp_mutex);
 362
 363    rp_sync_vmclock(s, clk, rclk);
 364    rp_restart_sync_timer(s);
 365}
 366
 367static char *rp_sanitize_prefix(RemotePort *s)
 368{
 369    char *sanitized_name;
 370    char *c;
 371
 372    sanitized_name = g_strdup(s->prefix);
 373    for (c = sanitized_name; *c != '\0'; c++) {
 374        if (*c == '/')
 375            *c = '_';
 376    }
 377    return sanitized_name;
 378}
 379
 380static char *rp_autocreate_chardesc(RemotePort *s, bool server)
 381{
 382    char *prefix;
 383    char *chardesc;
 384    int r;
 385
 386    prefix = rp_sanitize_prefix(s);
 387    r = asprintf(&chardesc, "unix:%s/qemu-rport-%s,wait%s",
 388                 machine_path, prefix, server ? ",server" : "");
 389    assert(r > 0);
 390    free(prefix);
 391    return chardesc;
 392}
 393
 394static CharDriverState *rp_autocreate_chardev(RemotePort *s, char *name)
 395{
 396    CharDriverState *chr;
 397    char *chardesc;
 398
 399    chardesc = rp_autocreate_chardesc(s, false);
 400    chr = qemu_chr_new(name, chardesc, NULL);
 401    free(chardesc);
 402
 403    if (!chr) {
 404        chardesc = rp_autocreate_chardesc(s, true);
 405        chr = qemu_chr_new(name, chardesc, NULL);
 406        free(chardesc);
 407    }
 408    return chr;
 409}
 410
 411static unsigned int rp_has_work(RemotePort *s)
 412{
 413    unsigned int work = s->rx_queue.wpos - s->rx_queue.rpos;
 414    return work;
 415}
 416
 417static void rp_process(RemotePort *s)
 418{
 419    while (rp_has_work(s)) {
 420        struct rp_pkt *pkt;
 421        unsigned int rpos = s->rx_queue.rpos;
 422        bool actioned = false;
 423        RemotePortDevice *dev;
 424        RemotePortDeviceClass *rpdc;
 425
 426        rpos &= ARRAY_SIZE(s->rx_queue.pkt) - 1;
 427
 428        pkt = s->rx_queue.pkt[rpos].pkt;
 429        D(printf("%s: io-thread rpos=%d wpos=%d cmd=%d\n", s->prefix,
 430                 s->rx_queue.rpos, s->rx_queue.wpos, pkt->hdr.cmd));
 431
 432        dev = s->devs[pkt->hdr.dev];
 433        if (dev) {
 434            rpdc = REMOTE_PORT_DEVICE_GET_CLASS(dev);
 435            if (rpdc->ops[pkt->hdr.cmd]) {
 436                rpdc->ops[pkt->hdr.cmd](dev, pkt);
 437                actioned = true;
 438            }
 439        }
 440
 441        switch (pkt->hdr.cmd) {
 442        case RP_CMD_sync:
 443            rp_cmd_sync(s, pkt);
 444            break;
 445        default:
 446            assert(actioned);
 447        }
 448
 449        s->rx_queue.rpos++;
 450        qemu_sem_post(&s->rx_queue.sem);
 451    }
 452}
 453
 454static void rp_event_read(void *opaque)
 455{
 456    RemotePort *s = REMOTE_PORT(opaque);
 457    unsigned char buf[32];
 458    ssize_t r;
 459
 460    /* We don't care about the data. Just read it out to clear the event.  */
 461    do {
 462        r = read(s->event.pipe.read, buf, sizeof buf);
 463        if (r == 0) {
 464            hw_error("%s: pipe closed?\n", s->prefix);
 465        }
 466    } while (r == sizeof buf || (r < 0 && errno == EINTR));
 467
 468    rp_process(s);
 469    rp_leave_iothread(s);
 470}
 471
 472static void rp_event_notify(RemotePort *s)
 473{
 474    unsigned char d = 0;
 475    ssize_t r;
 476
 477#ifdef _WIN32
 478    /* Mingw is sensitive about doing write's to socket descriptors.  */
 479    r = qemu_send_wrap(s->event.pipe.write, &d, sizeof d, 0);
 480#else
 481    r = qemu_write_full(s->event.pipe.write, &d, sizeof d);
 482#endif
 483    if (r == 0) {
 484        hw_error("%s: pipe closed\n", s->prefix);
 485    }
 486}
 487
 488/* Handover a pkt to CPU or IO-thread context.  */
 489static void rp_pt_handover_pkt(RemotePort *s, RemotePortDynPkt *dpkt)
 490{
 491    /* Take the rsp lock around the wpos update, otherwise
 492       rp_wait_resp will race with us.  */
 493    qemu_mutex_lock(&s->rsp_mutex);
 494    s->rx_queue.wpos++;
 495    smp_mb();
 496    rp_event_notify(s);
 497    qemu_cond_signal(&s->progress_cond);
 498    qemu_mutex_unlock(&s->rsp_mutex);
 499    while (1) {
 500        if (qemu_sem_timedwait(&s->rx_queue.sem, 2 * 1000) == 0) {
 501            break;
 502        }
 503#ifndef _WIN32
 504        {
 505            int sval;
 506            sem_getvalue(&s->rx_queue.sem.sem, &sval);
 507            printf("semwait: %d rpos=%u wpos=%u\n", sval,
 508                   s->rx_queue.rpos, s->rx_queue.wpos);
 509        }
 510#endif
 511    }
 512}
 513
 514static bool rp_pt_cmd_sync(RemotePort *s, struct rp_pkt *pkt)
 515{
 516    size_t enclen;
 517    int64_t clk;
 518    int64_t diff = 0;
 519    struct rp_pkt rsp;
 520
 521    assert(!(pkt->hdr.flags & RP_PKT_FLAGS_response));
 522
 523    if (use_icount) {
 524        clk = rp_normalized_vmclk(s);
 525        diff = pkt->sync.timestamp - clk;
 526    }
 527    enclen = rp_encode_sync_resp(pkt->hdr.id, pkt->hdr.dev, &rsp.sync,
 528                                 pkt->sync.timestamp);
 529    assert(enclen == sizeof rsp.sync);
 530
 531    if (!use_icount || diff < s->sync.quantum) {
 532        /* We are still OK.  */
 533        rp_write(s, (void *) &rsp, enclen);
 534        return true;
 535    }
 536
 537    /* We need IO or CPU thread sync.  */
 538    return false;
 539}
 540
 541static void rp_pt_process_pkt(RemotePort *s, RemotePortDynPkt *dpkt)
 542{
 543    struct rp_pkt *pkt = dpkt->pkt;
 544
 545    D(printf("%s: cmd=%x rsp=%d\n", __func__, pkt->hdr.cmd,
 546             pkt->hdr.flags & RP_PKT_FLAGS_response));
 547
 548    if (pkt->hdr.dev >= ARRAY_SIZE(s->devs)) {
 549        /* FIXME: Respond with an error.  */
 550        return;
 551    }
 552
 553    if (pkt->hdr.flags & RP_PKT_FLAGS_response) {
 554        qemu_mutex_lock(&s->rsp_mutex);
 555        rp_dpkt_swap(&s->rspqueue, dpkt);
 556        qemu_cond_signal(&s->progress_cond);
 557        qemu_mutex_unlock(&s->rsp_mutex);
 558        return;
 559    }
 560
 561    switch (pkt->hdr.cmd) {
 562    case RP_CMD_hello:
 563        rp_cmd_hello(s, pkt);
 564        break;
 565    case RP_CMD_sync:
 566        if (rp_pt_cmd_sync(s, pkt)) {
 567            return;
 568        }
 569        /* Fall-through.  */
 570    case RP_CMD_read:
 571    case RP_CMD_write:
 572    case RP_CMD_interrupt:
 573        rp_pt_handover_pkt(s, dpkt);
 574        break;
 575    default:
 576        assert(0);
 577        break;
 578    }
 579}
 580
 581static void rp_read_pkt(RemotePort *s, RemotePortDynPkt *dpkt)
 582{
 583    struct rp_pkt *pkt = dpkt->pkt;
 584    int used;
 585
 586    rp_recv(s, pkt, sizeof pkt->hdr);
 587    used = rp_decode_hdr((void *) &pkt->hdr);
 588    assert(used == sizeof pkt->hdr);
 589
 590    if (pkt->hdr.len) {
 591        rp_dpkt_alloc(dpkt, sizeof pkt->hdr + pkt->hdr.len);
 592        /* pkt may move due to realloc.  */
 593        pkt = dpkt->pkt;
 594        rp_recv(s, &pkt->hdr + 1, pkt->hdr.len);
 595        rp_decode_payload(pkt);
 596    }
 597}
 598
 599static void *rp_protocol_thread(void *arg)
 600{
 601    RemotePort *s = REMOTE_PORT(arg);
 602    unsigned int i;
 603
 604    /* Make sure we have a decent bufsize to start with.  */
 605    rp_dpkt_alloc(&s->rsp, sizeof s->rsp.pkt->busaccess + 1024);
 606    rp_dpkt_alloc(&s->rspqueue, sizeof s->rspqueue.pkt->busaccess + 1024);
 607    for (i = 0; i < ARRAY_SIZE(s->rx_queue.pkt); i++) {
 608        rp_dpkt_alloc(&s->rx_queue.pkt[i],
 609                      sizeof s->rx_queue.pkt[i].pkt->busaccess + 1024);
 610    }
 611
 612    rp_say_hello(s);
 613
 614    while (1) {
 615        RemotePortDynPkt *dpkt;
 616        unsigned int wpos = s->rx_queue.wpos;
 617
 618        wpos &= ARRAY_SIZE(s->rx_queue.pkt) - 1;
 619        dpkt = &s->rx_queue.pkt[wpos];
 620
 621        rp_read_pkt(s, dpkt);
 622        if (0) {
 623            rp_pkt_dump("rport-pkt", (void *) dpkt->pkt,
 624                        sizeof dpkt->pkt->hdr + dpkt->pkt->hdr.len);
 625        }
 626        rp_pt_process_pkt(s, dpkt);
 627    }
 628    return NULL;
 629}
 630
 631static void rp_realize(DeviceState *dev, Error **errp)
 632{
 633    RemotePort *s = REMOTE_PORT(dev);
 634    int r;
 635
 636    s->prefix = object_get_canonical_path(OBJECT(dev));
 637
 638    s->peer.clk_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 639
 640    qemu_mutex_init(&s->write_mutex);
 641    qemu_mutex_init(&s->rsp_mutex);
 642    qemu_cond_init(&s->progress_cond);
 643
 644    if (!s->chr) {
 645        char *name;
 646        static int nr = 0;
 647        int r;
 648
 649        r = asprintf(&name, "rport%d", nr);
 650        nr++;
 651        assert(r > 0);
 652
 653        if (s->chrdev_id) {
 654            s->chr = qemu_chr_find(s->chrdev_id);
 655        }
 656
 657        if (s->chr) {
 658            /* Found the chardev via commandline */
 659        } else if (s->chardesc) {
 660            s->chr = qemu_chr_new(name, s->chardesc, NULL);
 661        } else {
 662            if (!machine_path) {
 663                error_report("%s: Missing chardesc prop."
 664                             " Forgot -machine-path?\n",
 665                             s->prefix);
 666                exit(EXIT_FAILURE);
 667            }
 668            s->chr = rp_autocreate_chardev(s, name);
 669        }
 670        free(name);
 671        if (!s->chr) {
 672            error_report("%s: Unable to create remort-port channel %s\n",
 673                         s->prefix, s->chardesc);
 674            exit(EXIT_FAILURE);
 675        }
 676    }
 677
 678
 679#ifdef _WIN32
 680    /* Create a socket connection between two sockets. We auto-bind
 681     * and read out the port selected by the kernel.
 682     */
 683    {
 684        char *name;
 685        int port;
 686
 687        s->event.pipe.read = inet_listen("127.0.0.1:0", NULL,
 688                                         256, SOCK_STREAM, 0, &error_abort);
 689        if (s->event.pipe.read < 0) {
 690            perror("socket read");
 691            exit(EXIT_FAILURE);
 692        }
 693
 694        {
 695            struct sockaddr_in saddr;
 696            socklen_t slen = sizeof saddr;
 697            int r;
 698
 699            r = getsockname(s->event.pipe.read, &saddr, &slen);
 700            if (r < 0) {
 701                perror("getsockname");
 702                exit(EXIT_FAILURE);
 703            }
 704            port = htons(saddr.sin_port);
 705        }
 706
 707        qemu_set_fd_handler(s->event.pipe.read, rp_event_read, NULL, s);
 708        name = g_strdup_printf("127.0.0.1:%d", port);
 709        s->event.pipe.write = inet_connect(name, &error_abort);
 710        g_free(name);
 711        if (s->event.pipe.write < 0) {
 712            perror("socket write");
 713            exit(EXIT_FAILURE);
 714        }
 715    }
 716#else
 717    r = qemu_pipe(s->event.pipes);
 718    if (r < 0) {
 719        error_report("%s: Unable to create remort-port internal pipes\n",
 720                    s->prefix);
 721        exit(EXIT_FAILURE);
 722    }
 723    qemu_set_nonblock(s->event.pipe.read);
 724    qemu_set_fd_handler(s->event.pipe.read, rp_event_read, NULL, s);
 725#endif
 726
 727
 728    /* Pick up the quantum from the local property setup.
 729       After config negotiation with the peer, sync.quantum value might
 730       change.  */
 731    s->sync.quantum = s->peer.local_cfg.quantum;
 732
 733    s->sync.bh = qemu_bh_new(sync_timer_hit, s);
 734    s->sync.bh_resp = qemu_bh_new(syncresp_timer_hit, s);
 735    s->sync.ptimer = ptimer_init(s->sync.bh);
 736    s->sync.ptimer_resp = ptimer_init(s->sync.bh_resp);
 737
 738    /* The Sync-quantum is expressed in nano-seconds.  */
 739    ptimer_set_freq(s->sync.ptimer, 1000 * 1000 * 1000);
 740    ptimer_set_freq(s->sync.ptimer_resp, 1000 * 1000 * 1000);
 741
 742    qemu_sem_init(&s->rx_queue.sem, ARRAY_SIZE(s->rx_queue.pkt) - 1);
 743    qemu_thread_create(&s->thread, "remote-port", rp_protocol_thread, s,
 744                       QEMU_THREAD_JOINABLE);
 745    rp_restart_sync_timer(s);
 746}
 747
 748static const VMStateDescription vmstate_rp = {
 749    .name = TYPE_REMOTE_PORT,
 750    .version_id = 1,
 751    .minimum_version_id = 1,
 752    .minimum_version_id_old = 1,
 753    .fields = (VMStateField[]) {
 754        VMSTATE_END_OF_LIST(),
 755    }
 756};
 757
 758static Property rp_properties[] = {
 759    DEFINE_PROP_CHR("chardev", RemotePort, chr),
 760    DEFINE_PROP_STRING("chardesc", RemotePort, chardesc),
 761    DEFINE_PROP_STRING("chrdev-id", RemotePort, chrdev_id),
 762    DEFINE_PROP_BOOL("sync", RemotePort, do_sync, false),
 763    DEFINE_PROP_UINT64("sync-quantum", RemotePort, peer.local_cfg.quantum, 0),
 764    DEFINE_PROP_END_OF_LIST(),
 765};
 766
 767static void rp_init(Object *obj)
 768{
 769    RemotePort *s = REMOTE_PORT(obj);
 770    int i;
 771
 772    /* Disable icount IDLE time warping. remoteport will take care of it.  */
 773    qemu_icount_enable_idle_timewarps(false);
 774
 775    for (i = 0; i < REMOTE_PORT_MAX_DEVS; ++i) {
 776        char *name = g_strdup_printf("remote-port-dev%d", i);
 777        object_property_add_link(obj, name, TYPE_REMOTE_PORT_DEVICE,
 778                             (Object **)&s->devs[i],
 779                             qdev_prop_allow_set_link,
 780                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 781                             &error_abort);
 782        g_free(name);
 783    }
 784}
 785
 786/* RP helper function to attach a device to an adaptor.  */
 787void rp_device_attach(Object *adaptor, Object *dev,
 788                      int rp_nr, int dev_nr,
 789                      Error **errp)
 790{
 791    Error *err = NULL;
 792    uint32_t nr_devs;
 793    char *name;
 794    int i;
 795
 796    assert(adaptor);
 797    assert(dev);
 798
 799    D(printf("%s: rp_nr-%d dev_nr=%d\n", __func__, rp_nr, dev_nr));
 800
 801    /* Verify that the adaptor is of Remote Port type.  */
 802    if (!object_dynamic_cast(adaptor, TYPE_REMOTE_PORT)) {
 803        error_setg(errp, "%s is not a Remote-Port adaptor!\n",
 804                   object_get_canonical_path(adaptor));
 805        return;
 806    }
 807
 808    name = g_strdup_printf("rp-adaptor%d", rp_nr);
 809    object_property_set_link(dev, adaptor, name, &err);
 810    g_free(name);
 811    if (err != NULL) {
 812        error_propagate(errp, err);
 813        return;
 814    }
 815
 816    name = g_strdup_printf("rp-chan%d", rp_nr);
 817    object_property_set_int(dev, dev_nr, name, &err);
 818    g_free(name);
 819    if (err != NULL
 820        && !object_dynamic_cast(dev, TYPE_REMOTE_PORT_DEVICE)) {
 821        /*
 822         * RP devices that only receive requests may not need to
 823         * know their channel/dev number. If not, treat this as
 824         * an error.
 825         */
 826        error_propagate(errp, err);
 827        return;
 828    }
 829    err = NULL;
 830
 831    nr_devs = object_property_get_int(dev, "nr-devs", &err);
 832    if (err) {
 833        nr_devs = 1;
 834        err = NULL;
 835    }
 836
 837    /* Multi-channel devs use consecutive numbering.  */
 838    for (i = 0; i < nr_devs; i++) {
 839        name = g_strdup_printf("remote-port-dev%d", dev_nr + i);
 840        object_property_set_link(adaptor, dev, name, &err);
 841        g_free(name);
 842        if (err != NULL) {
 843            error_propagate(errp, err);
 844            return;
 845        }
 846    }
 847}
 848
 849struct rp_peer_state *rp_get_peer(RemotePort *s)
 850{
 851    return &s->peer;
 852}
 853
 854static void rp_class_init(ObjectClass *klass, void *data)
 855{
 856    DeviceClass *dc = DEVICE_CLASS(klass);
 857
 858    dc->realize = rp_realize;
 859    dc->vmsd = &vmstate_rp;
 860    dc->props = rp_properties;
 861}
 862
 863static const TypeInfo rp_info = {
 864    .name          = TYPE_REMOTE_PORT,
 865    .parent        = TYPE_DEVICE,
 866    .instance_size = sizeof(RemotePort),
 867    .instance_init = rp_init,
 868    .class_init    = rp_class_init,
 869    .interfaces    = (InterfaceInfo[]) {
 870        { },
 871    },
 872};
 873
 874static const TypeInfo rp_device_info = {
 875    .name          = TYPE_REMOTE_PORT_DEVICE,
 876    .parent        = TYPE_INTERFACE,
 877    .class_size    = sizeof(RemotePortDeviceClass),
 878};
 879
 880static void rp_register_types(void)
 881{
 882    type_register_static(&rp_info);
 883    type_register_static(&rp_device_info);
 884}
 885
 886type_init(rp_register_types)
 887