Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xen: privcmd: Add support for ioeventfd

Virtio guests send VIRTIO_MMIO_QUEUE_NOTIFY notification when they need
to notify the backend of an update to the status of the virtqueue. The
backend or another entity, polls the MMIO address for updates to know
when the notification is sent.

It works well if the backend does this polling by itself. But as we move
towards generic backend implementations, we end up implementing this in
a separate user-space program.

Generally, the Virtio backends are implemented to work with the Eventfd
based mechanism. In order to make such backends work with Xen, another
software layer needs to do the polling and send an event via eventfd to
the backend once the notification from guest is received. This results
in an extra context switch.

This is not a new problem in Linux though. It is present with other
hypervisors like KVM, etc. as well. The generic solution implemented in
the kernel for them is to provide an IOCTL call to pass the address to
poll and eventfd, which lets the kernel take care of polling and raise
an event on the eventfd, instead of handling this in user space (which
involves an extra context switch).

This patch adds similar support for xen.

Inspired by existing implementations for KVM, etc..

This also copies ioreq.h header file (only struct ioreq and related
macros) from Xen's source tree (Top commit 5d84f07fe6bf ("xen/pci: drop
remaining uses of bool_t")).

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Juergen Gross <jgross@suse.com>
Link: https://lore.kernel.org/r/b20d83efba6453037d0c099912813c79c81f7714.1697439990.git.viresh.kumar@linaro.org
Signed-off-by: Juergen Gross <jgross@suse.com>

authored by

Viresh Kumar and committed by
Juergen Gross
f0d7db7b 9e90e58c

+476 -6
+4 -4
drivers/xen/Kconfig
··· 269 269 disaggregated Xen setups this driver might be needed for other 270 270 domains, too. 271 271 272 - config XEN_PRIVCMD_IRQFD 273 - bool "Xen irqfd support" 272 + config XEN_PRIVCMD_EVENTFD 273 + bool "Xen Ioeventfd and irqfd support" 274 274 depends on XEN_PRIVCMD && XEN_VIRTIO && EVENTFD 275 275 help 276 - Using the irqfd mechanism a virtio backend running in a daemon can 277 - speed up interrupt injection into a guest. 276 + Using the ioeventfd / irqfd mechanism a virtio backend running in a 277 + daemon can speed up interrupt delivery from / to a guest. 278 278 279 279 config XEN_ACPI_PROCESSOR 280 280 tristate "Xen ACPI processor"
+403 -2
drivers/xen/privcmd.c
··· 29 29 #include <linux/seq_file.h> 30 30 #include <linux/miscdevice.h> 31 31 #include <linux/moduleparam.h> 32 + #include <linux/virtio_mmio.h> 32 33 33 34 #include <asm/xen/hypervisor.h> 34 35 #include <asm/xen/hypercall.h> 35 36 36 37 #include <xen/xen.h> 38 + #include <xen/events.h> 37 39 #include <xen/privcmd.h> 38 40 #include <xen/interface/xen.h> 39 41 #include <xen/interface/memory.h> 40 42 #include <xen/interface/hvm/dm_op.h> 43 + #include <xen/interface/hvm/ioreq.h> 41 44 #include <xen/features.h> 42 45 #include <xen/page.h> 43 46 #include <xen/xen-ops.h> ··· 785 782 goto out; 786 783 787 784 pages = vma->vm_private_data; 785 + 788 786 for (i = 0; i < kdata.num; i++) { 789 787 xen_pfn_t pfn = 790 788 page_to_xen_pfn(pages[i / XEN_PFN_PER_PAGE]); ··· 842 838 return rc; 843 839 } 844 840 845 - #ifdef CONFIG_XEN_PRIVCMD_IRQFD 841 + #ifdef CONFIG_XEN_PRIVCMD_EVENTFD 846 842 /* Irqfd support */ 847 843 static struct workqueue_struct *irqfd_cleanup_wq; 848 844 static DEFINE_MUTEX(irqfds_lock); ··· 1083 1079 1084 1080 destroy_workqueue(irqfd_cleanup_wq); 1085 1081 } 1082 + 1083 + /* Ioeventfd Support */ 1084 + #define QUEUE_NOTIFY_VQ_MASK 0xFFFF 1085 + 1086 + static DEFINE_MUTEX(ioreq_lock); 1087 + static LIST_HEAD(ioreq_list); 1088 + 1089 + /* per-eventfd structure */ 1090 + struct privcmd_kernel_ioeventfd { 1091 + struct eventfd_ctx *eventfd; 1092 + struct list_head list; 1093 + u64 addr; 1094 + unsigned int addr_len; 1095 + unsigned int vq; 1096 + }; 1097 + 1098 + /* per-guest CPU / port structure */ 1099 + struct ioreq_port { 1100 + int vcpu; 1101 + unsigned int port; 1102 + struct privcmd_kernel_ioreq *kioreq; 1103 + }; 1104 + 1105 + /* per-guest structure */ 1106 + struct privcmd_kernel_ioreq { 1107 + domid_t dom; 1108 + unsigned int vcpus; 1109 + u64 uioreq; 1110 + struct ioreq *ioreq; 1111 + spinlock_t lock; /* Protects ioeventfds list */ 1112 + struct list_head ioeventfds; 1113 + struct list_head list; 1114 + struct ioreq_port ports[0]; 1115 + }; 1116 + 1117 + static irqreturn_t ioeventfd_interrupt(int irq, void *dev_id) 1118 + { 1119 + struct ioreq_port *port = dev_id; 1120 + struct privcmd_kernel_ioreq *kioreq = port->kioreq; 1121 + struct ioreq *ioreq = &kioreq->ioreq[port->vcpu]; 1122 + struct privcmd_kernel_ioeventfd *kioeventfd; 1123 + unsigned int state = STATE_IOREQ_READY; 1124 + 1125 + if (ioreq->state != STATE_IOREQ_READY || 1126 + ioreq->type != IOREQ_TYPE_COPY || ioreq->dir != IOREQ_WRITE) 1127 + return IRQ_NONE; 1128 + 1129 + /* 1130 + * We need a barrier, smp_mb(), here to ensure reads are finished before 1131 + * `state` is updated. Since the lock implementation ensures that 1132 + * appropriate barrier will be added anyway, we can avoid adding 1133 + * explicit barrier here. 1134 + * 1135 + * Ideally we don't need to update `state` within the locks, but we do 1136 + * that here to avoid adding explicit barrier. 1137 + */ 1138 + 1139 + spin_lock(&kioreq->lock); 1140 + ioreq->state = STATE_IOREQ_INPROCESS; 1141 + 1142 + list_for_each_entry(kioeventfd, &kioreq->ioeventfds, list) { 1143 + if (ioreq->addr == kioeventfd->addr + VIRTIO_MMIO_QUEUE_NOTIFY && 1144 + ioreq->size == kioeventfd->addr_len && 1145 + (ioreq->data & QUEUE_NOTIFY_VQ_MASK) == kioeventfd->vq) { 1146 + eventfd_signal(kioeventfd->eventfd, 1); 1147 + state = STATE_IORESP_READY; 1148 + break; 1149 + } 1150 + } 1151 + spin_unlock(&kioreq->lock); 1152 + 1153 + /* 1154 + * We need a barrier, smp_mb(), here to ensure writes are finished 1155 + * before `state` is updated. Since the lock implementation ensures that 1156 + * appropriate barrier will be added anyway, we can avoid adding 1157 + * explicit barrier here. 1158 + */ 1159 + 1160 + ioreq->state = state; 1161 + 1162 + if (state == STATE_IORESP_READY) { 1163 + notify_remote_via_evtchn(port->port); 1164 + return IRQ_HANDLED; 1165 + } 1166 + 1167 + return IRQ_NONE; 1168 + } 1169 + 1170 + static void ioreq_free(struct privcmd_kernel_ioreq *kioreq) 1171 + { 1172 + struct ioreq_port *ports = kioreq->ports; 1173 + int i; 1174 + 1175 + lockdep_assert_held(&ioreq_lock); 1176 + 1177 + list_del(&kioreq->list); 1178 + 1179 + for (i = kioreq->vcpus - 1; i >= 0; i--) 1180 + unbind_from_irqhandler(irq_from_evtchn(ports[i].port), &ports[i]); 1181 + 1182 + kfree(kioreq); 1183 + } 1184 + 1185 + static 1186 + struct privcmd_kernel_ioreq *alloc_ioreq(struct privcmd_ioeventfd *ioeventfd) 1187 + { 1188 + struct privcmd_kernel_ioreq *kioreq; 1189 + struct mm_struct *mm = current->mm; 1190 + struct vm_area_struct *vma; 1191 + struct page **pages; 1192 + unsigned int *ports; 1193 + int ret, size, i; 1194 + 1195 + lockdep_assert_held(&ioreq_lock); 1196 + 1197 + size = struct_size(kioreq, ports, ioeventfd->vcpus); 1198 + kioreq = kzalloc(size, GFP_KERNEL); 1199 + if (!kioreq) 1200 + return ERR_PTR(-ENOMEM); 1201 + 1202 + kioreq->dom = ioeventfd->dom; 1203 + kioreq->vcpus = ioeventfd->vcpus; 1204 + kioreq->uioreq = ioeventfd->ioreq; 1205 + spin_lock_init(&kioreq->lock); 1206 + INIT_LIST_HEAD(&kioreq->ioeventfds); 1207 + 1208 + /* The memory for ioreq server must have been mapped earlier */ 1209 + mmap_write_lock(mm); 1210 + vma = find_vma(mm, (unsigned long)ioeventfd->ioreq); 1211 + if (!vma) { 1212 + pr_err("Failed to find vma for ioreq page!\n"); 1213 + mmap_write_unlock(mm); 1214 + ret = -EFAULT; 1215 + goto error_kfree; 1216 + } 1217 + 1218 + pages = vma->vm_private_data; 1219 + kioreq->ioreq = (struct ioreq *)(page_to_virt(pages[0])); 1220 + mmap_write_unlock(mm); 1221 + 1222 + size = sizeof(*ports) * kioreq->vcpus; 1223 + ports = kzalloc(size, GFP_KERNEL); 1224 + if (!ports) { 1225 + ret = -ENOMEM; 1226 + goto error_kfree; 1227 + } 1228 + 1229 + if (copy_from_user(ports, u64_to_user_ptr(ioeventfd->ports), size)) { 1230 + ret = -EFAULT; 1231 + goto error_kfree_ports; 1232 + } 1233 + 1234 + for (i = 0; i < kioreq->vcpus; i++) { 1235 + kioreq->ports[i].vcpu = i; 1236 + kioreq->ports[i].port = ports[i]; 1237 + kioreq->ports[i].kioreq = kioreq; 1238 + 1239 + ret = bind_evtchn_to_irqhandler_lateeoi(ports[i], 1240 + ioeventfd_interrupt, IRQF_SHARED, "ioeventfd", 1241 + &kioreq->ports[i]); 1242 + if (ret < 0) 1243 + goto error_unbind; 1244 + } 1245 + 1246 + kfree(ports); 1247 + 1248 + list_add_tail(&kioreq->list, &ioreq_list); 1249 + 1250 + return kioreq; 1251 + 1252 + error_unbind: 1253 + while (--i >= 0) 1254 + unbind_from_irqhandler(irq_from_evtchn(ports[i]), &kioreq->ports[i]); 1255 + error_kfree_ports: 1256 + kfree(ports); 1257 + error_kfree: 1258 + kfree(kioreq); 1259 + return ERR_PTR(ret); 1260 + } 1261 + 1262 + static struct privcmd_kernel_ioreq * 1263 + get_ioreq(struct privcmd_ioeventfd *ioeventfd, struct eventfd_ctx *eventfd) 1264 + { 1265 + struct privcmd_kernel_ioreq *kioreq; 1266 + unsigned long flags; 1267 + 1268 + list_for_each_entry(kioreq, &ioreq_list, list) { 1269 + struct privcmd_kernel_ioeventfd *kioeventfd; 1270 + 1271 + /* 1272 + * kioreq fields can be accessed here without a lock as they are 1273 + * never updated after being added to the ioreq_list. 1274 + */ 1275 + if (kioreq->uioreq != ioeventfd->ioreq) { 1276 + continue; 1277 + } else if (kioreq->dom != ioeventfd->dom || 1278 + kioreq->vcpus != ioeventfd->vcpus) { 1279 + pr_err("Invalid ioeventfd configuration mismatch, dom (%u vs %u), vcpus (%u vs %u)\n", 1280 + kioreq->dom, ioeventfd->dom, kioreq->vcpus, 1281 + ioeventfd->vcpus); 1282 + return ERR_PTR(-EINVAL); 1283 + } 1284 + 1285 + /* Look for a duplicate eventfd for the same guest */ 1286 + spin_lock_irqsave(&kioreq->lock, flags); 1287 + list_for_each_entry(kioeventfd, &kioreq->ioeventfds, list) { 1288 + if (eventfd == kioeventfd->eventfd) { 1289 + spin_unlock_irqrestore(&kioreq->lock, flags); 1290 + return ERR_PTR(-EBUSY); 1291 + } 1292 + } 1293 + spin_unlock_irqrestore(&kioreq->lock, flags); 1294 + 1295 + return kioreq; 1296 + } 1297 + 1298 + /* Matching kioreq isn't found, allocate a new one */ 1299 + return alloc_ioreq(ioeventfd); 1300 + } 1301 + 1302 + static void ioeventfd_free(struct privcmd_kernel_ioeventfd *kioeventfd) 1303 + { 1304 + list_del(&kioeventfd->list); 1305 + eventfd_ctx_put(kioeventfd->eventfd); 1306 + kfree(kioeventfd); 1307 + } 1308 + 1309 + static int privcmd_ioeventfd_assign(struct privcmd_ioeventfd *ioeventfd) 1310 + { 1311 + struct privcmd_kernel_ioeventfd *kioeventfd; 1312 + struct privcmd_kernel_ioreq *kioreq; 1313 + unsigned long flags; 1314 + struct fd f; 1315 + int ret; 1316 + 1317 + /* Check for range overflow */ 1318 + if (ioeventfd->addr + ioeventfd->addr_len < ioeventfd->addr) 1319 + return -EINVAL; 1320 + 1321 + /* Vhost requires us to support length 1, 2, 4, and 8 */ 1322 + if (!(ioeventfd->addr_len == 1 || ioeventfd->addr_len == 2 || 1323 + ioeventfd->addr_len == 4 || ioeventfd->addr_len == 8)) 1324 + return -EINVAL; 1325 + 1326 + /* 4096 vcpus limit enough ? */ 1327 + if (!ioeventfd->vcpus || ioeventfd->vcpus > 4096) 1328 + return -EINVAL; 1329 + 1330 + kioeventfd = kzalloc(sizeof(*kioeventfd), GFP_KERNEL); 1331 + if (!kioeventfd) 1332 + return -ENOMEM; 1333 + 1334 + f = fdget(ioeventfd->event_fd); 1335 + if (!f.file) { 1336 + ret = -EBADF; 1337 + goto error_kfree; 1338 + } 1339 + 1340 + kioeventfd->eventfd = eventfd_ctx_fileget(f.file); 1341 + fdput(f); 1342 + 1343 + if (IS_ERR(kioeventfd->eventfd)) { 1344 + ret = PTR_ERR(kioeventfd->eventfd); 1345 + goto error_kfree; 1346 + } 1347 + 1348 + kioeventfd->addr = ioeventfd->addr; 1349 + kioeventfd->addr_len = ioeventfd->addr_len; 1350 + kioeventfd->vq = ioeventfd->vq; 1351 + 1352 + mutex_lock(&ioreq_lock); 1353 + kioreq = get_ioreq(ioeventfd, kioeventfd->eventfd); 1354 + if (IS_ERR(kioreq)) { 1355 + mutex_unlock(&ioreq_lock); 1356 + ret = PTR_ERR(kioreq); 1357 + goto error_eventfd; 1358 + } 1359 + 1360 + spin_lock_irqsave(&kioreq->lock, flags); 1361 + list_add_tail(&kioeventfd->list, &kioreq->ioeventfds); 1362 + spin_unlock_irqrestore(&kioreq->lock, flags); 1363 + 1364 + mutex_unlock(&ioreq_lock); 1365 + 1366 + return 0; 1367 + 1368 + error_eventfd: 1369 + eventfd_ctx_put(kioeventfd->eventfd); 1370 + 1371 + error_kfree: 1372 + kfree(kioeventfd); 1373 + return ret; 1374 + } 1375 + 1376 + static int privcmd_ioeventfd_deassign(struct privcmd_ioeventfd *ioeventfd) 1377 + { 1378 + struct privcmd_kernel_ioreq *kioreq, *tkioreq; 1379 + struct eventfd_ctx *eventfd; 1380 + unsigned long flags; 1381 + int ret = 0; 1382 + 1383 + eventfd = eventfd_ctx_fdget(ioeventfd->event_fd); 1384 + if (IS_ERR(eventfd)) 1385 + return PTR_ERR(eventfd); 1386 + 1387 + mutex_lock(&ioreq_lock); 1388 + list_for_each_entry_safe(kioreq, tkioreq, &ioreq_list, list) { 1389 + struct privcmd_kernel_ioeventfd *kioeventfd, *tmp; 1390 + /* 1391 + * kioreq fields can be accessed here without a lock as they are 1392 + * never updated after being added to the ioreq_list. 1393 + */ 1394 + if (kioreq->dom != ioeventfd->dom || 1395 + kioreq->uioreq != ioeventfd->ioreq || 1396 + kioreq->vcpus != ioeventfd->vcpus) 1397 + continue; 1398 + 1399 + spin_lock_irqsave(&kioreq->lock, flags); 1400 + list_for_each_entry_safe(kioeventfd, tmp, &kioreq->ioeventfds, list) { 1401 + if (eventfd == kioeventfd->eventfd) { 1402 + ioeventfd_free(kioeventfd); 1403 + spin_unlock_irqrestore(&kioreq->lock, flags); 1404 + 1405 + if (list_empty(&kioreq->ioeventfds)) 1406 + ioreq_free(kioreq); 1407 + goto unlock; 1408 + } 1409 + } 1410 + spin_unlock_irqrestore(&kioreq->lock, flags); 1411 + break; 1412 + } 1413 + 1414 + pr_err("Ioeventfd isn't already assigned, dom: %u, addr: %llu\n", 1415 + ioeventfd->dom, ioeventfd->addr); 1416 + ret = -ENODEV; 1417 + 1418 + unlock: 1419 + mutex_unlock(&ioreq_lock); 1420 + eventfd_ctx_put(eventfd); 1421 + 1422 + return ret; 1423 + } 1424 + 1425 + static long privcmd_ioctl_ioeventfd(struct file *file, void __user *udata) 1426 + { 1427 + struct privcmd_data *data = file->private_data; 1428 + struct privcmd_ioeventfd ioeventfd; 1429 + 1430 + if (copy_from_user(&ioeventfd, udata, sizeof(ioeventfd))) 1431 + return -EFAULT; 1432 + 1433 + /* No other flags should be set */ 1434 + if (ioeventfd.flags & ~PRIVCMD_IOEVENTFD_FLAG_DEASSIGN) 1435 + return -EINVAL; 1436 + 1437 + /* If restriction is in place, check the domid matches */ 1438 + if (data->domid != DOMID_INVALID && data->domid != ioeventfd.dom) 1439 + return -EPERM; 1440 + 1441 + if (ioeventfd.flags & PRIVCMD_IOEVENTFD_FLAG_DEASSIGN) 1442 + return privcmd_ioeventfd_deassign(&ioeventfd); 1443 + 1444 + return privcmd_ioeventfd_assign(&ioeventfd); 1445 + } 1446 + 1447 + static void privcmd_ioeventfd_exit(void) 1448 + { 1449 + struct privcmd_kernel_ioreq *kioreq, *tmp; 1450 + unsigned long flags; 1451 + 1452 + mutex_lock(&ioreq_lock); 1453 + list_for_each_entry_safe(kioreq, tmp, &ioreq_list, list) { 1454 + struct privcmd_kernel_ioeventfd *kioeventfd, *tmp; 1455 + 1456 + spin_lock_irqsave(&kioreq->lock, flags); 1457 + list_for_each_entry_safe(kioeventfd, tmp, &kioreq->ioeventfds, list) 1458 + ioeventfd_free(kioeventfd); 1459 + spin_unlock_irqrestore(&kioreq->lock, flags); 1460 + 1461 + ioreq_free(kioreq); 1462 + } 1463 + mutex_unlock(&ioreq_lock); 1464 + } 1086 1465 #else 1087 1466 static inline long privcmd_ioctl_irqfd(struct file *file, void __user *udata) 1088 1467 { ··· 1480 1093 static inline void privcmd_irqfd_exit(void) 1481 1094 { 1482 1095 } 1483 - #endif /* CONFIG_XEN_PRIVCMD_IRQFD */ 1096 + 1097 + static inline long privcmd_ioctl_ioeventfd(struct file *file, void __user *udata) 1098 + { 1099 + return -EOPNOTSUPP; 1100 + } 1101 + 1102 + static inline void privcmd_ioeventfd_exit(void) 1103 + { 1104 + } 1105 + #endif /* CONFIG_XEN_PRIVCMD_EVENTFD */ 1484 1106 1485 1107 static long privcmd_ioctl(struct file *file, 1486 1108 unsigned int cmd, unsigned long data) ··· 1528 1132 1529 1133 case IOCTL_PRIVCMD_IRQFD: 1530 1134 ret = privcmd_ioctl_irqfd(file, udata); 1135 + break; 1136 + 1137 + case IOCTL_PRIVCMD_IOEVENTFD: 1138 + ret = privcmd_ioctl_ioeventfd(file, udata); 1531 1139 break; 1532 1140 1533 1141 default: ··· 1678 1278 1679 1279 static void __exit privcmd_exit(void) 1680 1280 { 1281 + privcmd_ioeventfd_exit(); 1681 1282 privcmd_irqfd_exit(); 1682 1283 misc_deregister(&privcmd_dev); 1683 1284 misc_deregister(&xen_privcmdbuf_dev);
+18
include/uapi/xen/privcmd.h
··· 110 110 __u8 pad[2]; 111 111 }; 112 112 113 + /* For privcmd_ioeventfd::flags */ 114 + #define PRIVCMD_IOEVENTFD_FLAG_DEASSIGN (1 << 0) 115 + 116 + struct privcmd_ioeventfd { 117 + __u64 ioreq; 118 + __u64 ports; 119 + __u64 addr; 120 + __u32 addr_len; 121 + __u32 event_fd; 122 + __u32 vcpus; 123 + __u32 vq; 124 + __u32 flags; 125 + domid_t dom; 126 + __u8 pad[2]; 127 + }; 128 + 113 129 /* 114 130 * @cmd: IOCTL_PRIVCMD_HYPERCALL 115 131 * @arg: &privcmd_hypercall_t ··· 155 139 _IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource)) 156 140 #define IOCTL_PRIVCMD_IRQFD \ 157 141 _IOW('P', 8, struct privcmd_irqfd) 142 + #define IOCTL_PRIVCMD_IOEVENTFD \ 143 + _IOW('P', 9, struct privcmd_ioeventfd) 158 144 159 145 #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
+51
include/xen/interface/hvm/ioreq.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * ioreq.h: I/O request definitions for device models 4 + * Copyright (c) 2004, Intel Corporation. 5 + */ 6 + 7 + #ifndef __XEN_PUBLIC_HVM_IOREQ_H__ 8 + #define __XEN_PUBLIC_HVM_IOREQ_H__ 9 + 10 + #define IOREQ_READ 1 11 + #define IOREQ_WRITE 0 12 + 13 + #define STATE_IOREQ_NONE 0 14 + #define STATE_IOREQ_READY 1 15 + #define STATE_IOREQ_INPROCESS 2 16 + #define STATE_IORESP_READY 3 17 + 18 + #define IOREQ_TYPE_PIO 0 /* pio */ 19 + #define IOREQ_TYPE_COPY 1 /* mmio ops */ 20 + #define IOREQ_TYPE_PCI_CONFIG 2 21 + #define IOREQ_TYPE_TIMEOFFSET 7 22 + #define IOREQ_TYPE_INVALIDATE 8 /* mapcache */ 23 + 24 + /* 25 + * VMExit dispatcher should cooperate with instruction decoder to 26 + * prepare this structure and notify service OS and DM by sending 27 + * virq. 28 + * 29 + * For I/O type IOREQ_TYPE_PCI_CONFIG, the physical address is formatted 30 + * as follows: 31 + * 32 + * 63....48|47..40|39..35|34..32|31........0 33 + * SEGMENT |BUS |DEV |FN |OFFSET 34 + */ 35 + struct ioreq { 36 + uint64_t addr; /* physical address */ 37 + uint64_t data; /* data (or paddr of data) */ 38 + uint32_t count; /* for rep prefixes */ 39 + uint32_t size; /* size in bytes */ 40 + uint32_t vp_eport; /* evtchn for notifications to/from device model */ 41 + uint16_t _pad0; 42 + uint8_t state:4; 43 + uint8_t data_is_ptr:1; /* if 1, data above is the guest paddr 44 + * of the real data to use. */ 45 + uint8_t dir:1; /* 1=read, 0=write */ 46 + uint8_t df:1; 47 + uint8_t _pad1:1; 48 + uint8_t type; /* I/O type */ 49 + }; 50 + 51 + #endif /* __XEN_PUBLIC_HVM_IOREQ_H__ */