xref: /kvm-unit-tests/lib/chr-testdev.c (revision 74ff0e9675ec6d9477f5e98ec7d5d50878fa7ebc)
1b412ad0dSAndrew Jones /*
2b412ad0dSAndrew Jones  * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
3b412ad0dSAndrew Jones  *
4b412ad0dSAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
5b412ad0dSAndrew Jones  */
6b412ad0dSAndrew Jones #include "libcflat.h"
7b412ad0dSAndrew Jones #include "virtio.h"
8b412ad0dSAndrew Jones #include "asm/spinlock.h"
9b412ad0dSAndrew Jones 
100df901e0SAndrew Jones #include "chr-testdev.h"
110df901e0SAndrew Jones 
12b412ad0dSAndrew Jones #define TESTDEV_NAME "chr-testdev"
13b412ad0dSAndrew Jones 
14b412ad0dSAndrew Jones static struct virtio_device *vcon;
15b412ad0dSAndrew Jones static struct virtqueue *in_vq, *out_vq;
16b412ad0dSAndrew Jones static struct spinlock lock;
17b412ad0dSAndrew Jones 
__testdev_send(char * buf,unsigned int len)18368819a9SAndrew Jones static void __testdev_send(char *buf, unsigned int len)
19b412ad0dSAndrew Jones {
20b412ad0dSAndrew Jones 	int ret;
21b412ad0dSAndrew Jones 
22b412ad0dSAndrew Jones 	ret = virtqueue_add_outbuf(out_vq, buf, len);
23b412ad0dSAndrew Jones 	virtqueue_kick(out_vq);
24b412ad0dSAndrew Jones 
25b412ad0dSAndrew Jones 	if (ret < 0)
26b412ad0dSAndrew Jones 		return;
27b412ad0dSAndrew Jones 
28b412ad0dSAndrew Jones 	while (!virtqueue_get_buf(out_vq, &len))
29b412ad0dSAndrew Jones 		;
30b412ad0dSAndrew Jones }
31b412ad0dSAndrew Jones 
chr_testdev_exit(int code)32b412ad0dSAndrew Jones void chr_testdev_exit(int code)
33b412ad0dSAndrew Jones {
34368819a9SAndrew Jones 	unsigned int len;
3516444ac8SPaolo Bonzini 	static char buf[8];
3616444ac8SPaolo Bonzini 
3716444ac8SPaolo Bonzini 	spin_lock(&lock);
3816444ac8SPaolo Bonzini 	if (!vcon)
3916444ac8SPaolo Bonzini 		goto out;
40b412ad0dSAndrew Jones 
41b412ad0dSAndrew Jones 	snprintf(buf, sizeof(buf), "%dq", code);
42b412ad0dSAndrew Jones 	len = strlen(buf);
43b412ad0dSAndrew Jones 
44b412ad0dSAndrew Jones 	__testdev_send(buf, len);
45b412ad0dSAndrew Jones 
46b412ad0dSAndrew Jones out:
47b412ad0dSAndrew Jones 	spin_unlock(&lock);
48b412ad0dSAndrew Jones }
49b412ad0dSAndrew Jones 
chr_testdev_init(void)50b412ad0dSAndrew Jones void chr_testdev_init(void)
51b412ad0dSAndrew Jones {
52b412ad0dSAndrew Jones 	const char *io_names[] = { "input", "output" };
53b412ad0dSAndrew Jones 	struct virtqueue *vqs[2];
54b412ad0dSAndrew Jones 	int ret;
55b412ad0dSAndrew Jones 
56b412ad0dSAndrew Jones 	vcon = virtio_bind(VIRTIO_ID_CONSOLE);
57*5786c838SAndrew Jones 	if (vcon == NULL)
58b412ad0dSAndrew Jones 		return;
59b412ad0dSAndrew Jones 
60b412ad0dSAndrew Jones 	ret = vcon->config->find_vqs(vcon, 2, vqs, NULL, io_names);
61b412ad0dSAndrew Jones 	if (ret < 0) {
62b412ad0dSAndrew Jones 		printf("%s: %s: can't init virtqueues\n",
63b412ad0dSAndrew Jones 				__func__, TESTDEV_NAME);
64b412ad0dSAndrew Jones 		vcon = NULL;
65b412ad0dSAndrew Jones 		return;
66b412ad0dSAndrew Jones 	}
67b412ad0dSAndrew Jones 
68b412ad0dSAndrew Jones 	in_vq = vqs[0];
69b412ad0dSAndrew Jones 	out_vq = vqs[1];
70b412ad0dSAndrew Jones }
71