aboutsummaryrefslogtreecommitdiff
path: root/lib/libvirtio/virtio.h
blob: c4eafe40dd3151354e6723f59e0b54a7700ebb8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/******************************************************************************
 * Copyright (c) 2011 IBM Corporation
 * All rights reserved.
 * This program and the accompanying materials
 * are made available under the terms of the BSD License
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/bsd-license.php
 *
 * Contributors:
 *     IBM Corporation - initial implementation
 *****************************************************************************/

#ifndef _LIBVIRTIO_H
#define _LIBVIRTIO_H

#include <stdint.h>

/* Device status bits */
#define VIRTIO_STAT_ACKNOWLEDGE		1
#define VIRTIO_STAT_DRIVER		2
#define VIRTIO_STAT_DRIVER_OK		4
#define VIRTIO_STAT_FEATURES_OK		8
#define VIRTIO_STAT_NEEDS_RESET		64
#define VIRTIO_STAT_FAILED		128

#define BIT(x) (1UL << (x))

/* VIRTIO 1.0 Device independent feature bits */
#define VIRTIO_F_RING_INDIRECT_DESC	BIT(28)
#define VIRTIO_F_RING_EVENT_IDX		BIT(29)
#define VIRTIO_F_VERSION_1		BIT(32)
#define VIRTIO_F_IOMMU_PLATFORM         BIT(33)

#define VIRTIO_TIMEOUT		        5000 /* 5 sec timeout */

/* Definitions for vring_desc.flags */
#define VRING_DESC_F_NEXT	1	/* buffer continues via the next field */
#define VRING_DESC_F_WRITE	2	/* buffer is write-only (otherwise read-only) */
#define VRING_DESC_F_INDIRECT	4	/* buffer contains a list of buffer descriptors */

/* Descriptor table entry - see Virtio Spec chapter 2.3.2 */
struct vring_desc {
	uint64_t addr;		/* Address (guest-physical) */
	uint32_t len;		/* Length */
	uint16_t flags;		/* The flags as indicated above */
	uint16_t next;		/* Next field if flags & NEXT */
};

/* Definitions for vring_avail.flags */
#define VRING_AVAIL_F_NO_INTERRUPT	1

/* Available ring - see Virtio Spec chapter 2.3.4 */
struct vring_avail {
	uint16_t flags;
	uint16_t idx;
	uint16_t ring[];
};

/* Definitions for vring_used.flags */
#define VRING_USED_F_NO_NOTIFY		1

struct vring_used_elem {
	uint32_t id;		/* Index of start of used descriptor chain */
	uint32_t len;		/* Total length of the descriptor chain which was used */
};

struct vring_used {
	uint16_t flags;
	uint16_t idx;
	struct vring_used_elem ring[];
};

/* Structure shared with SLOF and is 16bytes */
struct virtio_cap {
	void *addr;
	uint8_t bar;
	uint8_t is_io;
	uint8_t cap_id;
};

struct vqs {
	uint32_t size;
	void *buf_mem;
	struct vring_desc *desc;
	struct vring_avail *avail;
	struct vring_used *used;
	void **desc_gpas; /* to get gpa from desc->addr (which is ioba) */
	uint64_t bus_desc;
};

struct virtio_device {
	uint64_t features;
	struct virtio_cap legacy;
	struct virtio_cap common;
	struct virtio_cap notify;
	struct virtio_cap isr;
	struct virtio_cap device;
	struct virtio_cap pci;
	uint32_t notify_off_mul;
	struct vqs vq[3];
};

/* Parts of the virtqueue are aligned on a 4096 byte page boundary */
#define VQ_ALIGN(addr)	(((addr) + 0xfff) & ~0xfff)

extern unsigned long virtio_vring_size(unsigned int qsize);
extern unsigned int virtio_get_qsize(struct virtio_device *dev, int queue);
extern struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue);
extern struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue);
extern struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue);
extern void virtio_fill_desc(struct vqs *vq, int id, uint64_t features,
                             uint64_t addr, uint32_t len,
                             uint16_t flags, uint16_t next);
extern void virtio_free_desc(struct vqs *vq, int id, uint64_t features);
void *virtio_desc_addr(struct virtio_device *vdev, int queue, int id);
extern struct vqs *virtio_queue_init_vq(struct virtio_device *dev, unsigned int id);
extern void virtio_queue_term_vq(struct virtio_device *dev, struct vqs *vq, unsigned int id);

extern struct virtio_device *virtio_setup_vd(void);
extern void virtio_reset_device(struct virtio_device *dev);
extern void virtio_queue_notify(struct virtio_device *dev, int queue);
extern void virtio_set_status(struct virtio_device *dev, int status);
extern void virtio_get_status(struct virtio_device *dev, int *status);
extern void virtio_set_guest_features(struct virtio_device *dev, uint64_t features);
extern uint64_t virtio_get_host_features(struct virtio_device *dev);
extern int virtio_negotiate_guest_features(struct virtio_device *dev, uint64_t features);
extern uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size);
extern int __virtio_read_config(struct virtio_device *dev, void *dst,
				int offset, int len);


#endif /* _LIBVIRTIO_H */