Skip to content
Newer
Older
100644 197 lines (160 sloc) 4.41 KB
ef66b35 @rmustacc HVM-275 coalesced mmio code should be in separate file
rmustacc authored
1 /*
2 * KVM coalesced MMIO
3 *
4 * Copyright (c) 2008 Bull S.A.S.
5 *
6 * Author: Laurent Vivier <Laurent.Vivier@bull.net>
7 *
8 * Copyright 2011 Joyent, Inc. All Rights Reserved.
9 */
10
11 #include "kvm_host.h"
12 #include "kvm_coalesced_mmio.h"
13
14 static struct kvm_coalesced_mmio_dev *
15 to_mmio(struct kvm_io_device *dev)
16 {
fc81a70 @rmustacc HVM-328 replace container_of with offsetof calculations
rmustacc authored
17 uintptr_t dp = (uintptr_t)dev;
18 return ((struct kvm_coalesced_mmio_dev *)(dp -
19 offsetof(struct kvm_coalesced_mmio_dev, dev)));
ef66b35 @rmustacc HVM-275 coalesced mmio code should be in separate file
rmustacc authored
20 }
21
22 static int
23 coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev, gpa_t addr, int len)
24 {
25 struct kvm_coalesced_mmio_zone *zone;
26 struct kvm_coalesced_mmio_ring *ring;
27 unsigned avail;
28 int i;
29
30 /* Are we able to batch it ? */
31
32 /*
33 * last is the first free entry
34 * check if we don't meet the first used entry
35 * there is always one unused entry in the buffer
36 */
37 ring = dev->kvm->coalesced_mmio_ring;
38 avail = (ring->first - ring->last - 1) % KVM_COALESCED_MMIO_MAX;
39 if (avail < KVM_MAX_VCPUS) {
40 /* full */
41 return (0);
42 }
43
44 /* is it in a batchable area ? */
45
46 for (i = 0; i < dev->nb_zones; i++) {
47 zone = &dev->zone[i];
48
49 /*
50 * (addr,len) is fully included in (zone->addr, zone->size)
51 */
52 if (zone->addr <= addr && addr + len <= zone->addr + zone->size)
53 return (1);
54 }
55 return (0);
56 }
57
58 static int
59 coalesced_mmio_write(struct kvm_io_device *this, gpa_t addr,
60 int len, const void *val)
61 {
62 struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
63 struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
64 if (!coalesced_mmio_in_range(dev, addr, len))
65 return (-EOPNOTSUPP);
66
67 mutex_enter(&dev->lock);
68
69 /* copy data in first free entry of the ring */
70
71 ring->coalesced_mmio[ring->last].phys_addr = addr;
72 ring->coalesced_mmio[ring->last].len = len;
73 memcpy(ring->coalesced_mmio[ring->last].data, val, len);
8d3d4a5 @max123 HVM-538 Implement smp_rmb/smp_wmb in kvm
max123 authored
74
ef66b35 @rmustacc HVM-275 coalesced mmio code should be in separate file
rmustacc authored
75 smp_wmb();
76 ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX;
77 mutex_exit(&dev->lock);
78 return (0);
79 }
80
81 /*
82 * We used to free the struct that contained us. We don't do that any more. It's
83 * just wrong in this case.
84 */
85 static void
86 coalesced_mmio_destructor(struct kvm_io_device *this)
87 {
88
89 }
90
91 static const struct kvm_io_device_ops coalesced_mmio_ops = {
92 .write = coalesced_mmio_write,
93 .destructor = coalesced_mmio_destructor,
94 };
95
96 int
97 kvm_coalesced_mmio_init(struct kvm *kvm)
98 {
99 struct kvm_coalesced_mmio_dev *dev;
100 page_t *page;
101 int ret;
102
103 kvm->coalesced_mmio_ring =
104 ddi_umem_alloc(PAGESIZE, DDI_UMEM_SLEEP, &kvm->mmio_cookie);
105
106 ret = -ENOMEM;
107 dev = kmem_zalloc(sizeof (struct kvm_coalesced_mmio_dev), KM_SLEEP);
c0cb8e8 @bcantrill HVM-543 clean-up some random XXXs
bcantrill authored
108
ef66b35 @rmustacc HVM-275 coalesced mmio code should be in separate file
rmustacc authored
109 mutex_init(&dev->lock, NULL, MUTEX_DRIVER, 0);
110 kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops);
111 dev->kvm = kvm;
112 kvm->coalesced_mmio_dev = dev;
113
114 mutex_enter(&kvm->slots_lock);
115 ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, &dev->dev);
116 mutex_exit(&kvm->slots_lock);
117 if (ret < 0)
118 goto out_free_dev;
119
120 return (ret);
121
122 out_free_dev:
123 kmem_free(dev, sizeof (struct kvm_coalesced_mmio_dev));
124 ddi_umem_free(kvm->mmio_cookie);
125 return (ret);
126 }
127
128 void
129 kvm_coalesced_mmio_free(struct kvm *kvmp)
130 {
131 struct kvm_coalesced_mmio_dev *dev = kvmp->coalesced_mmio_dev;
132 mutex_destroy(&dev->lock);
133 mutex_enter(&kvmp->slots_lock);
134 kvm_io_bus_unregister_dev(kvmp, KVM_MMIO_BUS, &dev->dev);
135 mutex_exit(&kvmp->slots_lock);
136 kvm_iodevice_destructor(&dev->dev);
137 kmem_free(dev, sizeof (struct kvm_coalesced_mmio_dev));
138 if (kvmp->coalesced_mmio_ring)
139 ddi_umem_free(kvmp->mmio_cookie);
140 }
141
142 int
143 kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
144 struct kvm_coalesced_mmio_zone *zone)
145 {
146 struct kvm_coalesced_mmio_dev *dev = kvm->coalesced_mmio_dev;
147
148 if (dev == NULL)
149 return (-EINVAL);
150
151 mutex_enter(&kvm->slots_lock);
152 if (dev->nb_zones >= KVM_COALESCED_MMIO_ZONE_MAX) {
153 mutex_exit(&kvm->slots_lock);
154 return (-ENOBUFS);
155 }
156
157 bcopy(zone, &dev->zone[dev->nb_zones],
158 sizeof (struct kvm_coalesced_mmio_zone));
159 dev->nb_zones++;
160
161 mutex_exit(&kvm->slots_lock);
162 return (0);
163 }
164
165 int
166 kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
167 struct kvm_coalesced_mmio_zone *zone)
168 {
169 int i;
170 struct kvm_coalesced_mmio_dev *dev = kvm->coalesced_mmio_dev;
171 struct kvm_coalesced_mmio_zone *z;
172
173 if (dev == NULL)
174 return (-EINVAL);
175
176 mutex_enter(&kvm->slots_lock);
177
178 i = dev->nb_zones;
179 while (i) {
180 z = &dev->zone[i - 1];
181
182 /*
183 * Unregister all zones included in (zone->addr, zone->size)
184 */
185 if (zone->addr <= z->addr &&
186 z->addr + z->size <= zone->addr + zone->size) {
187 dev->nb_zones--;
188 *z = dev->zone[dev->nb_zones];
189 }
190 i--;
191 }
192
193 mutex_exit(&kvm->slots_lock);
194
195 return (0);
196 }
Something went wrong with that request. Please try again.