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