1
2
3
4
5
6
7
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
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
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
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
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
256 if (diff <= 0LL || true) {
257
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
328 s->doing_sync = true;
329 s->sync.need_sync = false;
330 qemu_mutex_lock(&s->rsp_mutex);
331
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
409
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
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
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
474static void rp_pt_handover_pkt(RemotePort *s, RemotePortDynPkt *dpkt)
475{
476 bool full;
477
478
479
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
529 rp_write(s, (void *) &rsp, enclen);
530 return true;
531 }
532
533
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
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
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
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
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
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
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
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
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
733
734
735 qemu_chr_fe_set_blocking(&s->chr, true);
736
737#ifdef _WIN32
738
739
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
809
810
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
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
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