49
uint32_t fd;
50
uint32_t model;
51
hwaddr mapped;
52
+ NotifierWithReturn vmfd_change_notifier;
53
};
54
55
static void kvm_openpic_set_irq(void *opaque, int n_IRQ, int level)
115
},
116
};
117
118
+static int kvm_openpic_setup(KVMOpenPICState *opp, Error **errp)
119
+{
120
+ int kvm_openpic_model;
121
+ struct kvm_create_device cd = {0};
122
+ KVMState *s = kvm_state;
123
+ int ret;
124
+
125
+ switch (opp->model) {
126
+ case OPENPIC_MODEL_FSL_MPIC_20:
127
+ kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_20;
128
+ break;
129
+
130
+ case OPENPIC_MODEL_FSL_MPIC_42:
131
+ kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_42;
132
+ break;
133
+
134
+ default:
135
+ error_setg(errp, "Unsupported OpenPIC model %" PRIu32, opp->model);
136
+ return -1;
137
+ }
138
+
139
+ cd.type = kvm_openpic_model;
140
+ ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &cd);
141
+ if (ret < 0) {
142
+ error_setg(errp, "Can't create device %d: %s",
143
+ cd.type, strerror(errno));
144
+ return -1;
145
+ }
146
+ opp->fd = cd.fd;
147
+
148
+ return 0;
149
+}
150
+
151
+static int kvm_openpic_handle_vmfd_change(NotifierWithReturn *notifier,
152
+ void *data, Error **errp)
153
+{
154
+ KVMOpenPICState *opp = container_of(notifier, KVMOpenPICState,
155
+ vmfd_change_notifier);
156
+ uint64_t reg_base;
157
+ struct kvm_device_attr attr;
158
+ CPUState *cs;
159
+ int ret;
160
+
161
+ /* we are not interested in pre vmfd change notification */
162
+ if (((VmfdChangeNotifier *)data)->pre) {
163
+ return 0;
164
+ }
165
+
166
+ /* close the old descriptor */
167
+ close(opp->fd);
168
+
169
+ if (kvm_openpic_setup(opp, errp) < 0) {
170
+ return -1;
171
+ }
172
+
173
+ if (!opp->mapped) {
174
+ return 0;
175
+ }
176
+
177
+ reg_base = opp->mapped;
178
+ attr.group = KVM_DEV_MPIC_GRP_MISC;
179
+ attr.attr = KVM_DEV_MPIC_BASE_ADDR;
180
+ attr.addr = (uint64_t)(unsigned long)®_base;
181
+
182
+ ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
183
+ if (ret < 0) {
184
+ error_setg(errp, "%s: %s %" PRIx64, __func__,
185
+ strerror(errno), reg_base);
186
+ return -1;
187
+ }
188
+
189
+ CPU_FOREACH(cs) {
190
+ ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_MPIC, 0, opp->fd,
191
+ kvm_arch_vcpu_id(cs));
192
+ if (ret < 0) {
193
+ return ret;
194
+ }
195
+ }
196
+
197
+ return 0;
198
+}
199
+
200
static void kvm_openpic_region_add(MemoryListener *listener,
201
MemoryRegionSection *section)
202
{
280
SysBusDevice *d = SYS_BUS_DEVICE(dev);
281
KVMOpenPICState *opp = KVM_OPENPIC(dev);
282
KVMState *s = kvm_state;
200
- int kvm_openpic_model;
201
- struct kvm_create_device cd = {0};
202
- int ret, i;
283
+ int i;
284
285
if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) {
286
error_setg(errp, "Kernel is lacking Device Control API");
287
return;
288
}
289
209
- switch (opp->model) {
210
- case OPENPIC_MODEL_FSL_MPIC_20:
211
- kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_20;
212
- break;
213
-
214
- case OPENPIC_MODEL_FSL_MPIC_42:
215
- kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_42;
216
- break;
217
-
218
- default:
219
- error_setg(errp, "Unsupported OpenPIC model %" PRIu32, opp->model);
220
- return;
221
- }
222
-
223
- cd.type = kvm_openpic_model;
224
- ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &cd);
225
- if (ret < 0) {
226
- error_setg_errno(errp, errno, "Can't create device %d", cd.type);
227
- return;
228
- }
229
- opp->fd = cd.fd;
290
+ kvm_openpic_setup(opp, errp);
291
292
sysbus_init_mmio(d, &opp->mem);
293
qdev_init_gpio_in(dev, kvm_openpic_set_irq, OPENPIC_MAX_IRQ);
296
opp->mem_listener.region_del = kvm_openpic_region_del;
297
opp->mem_listener.name = "openpic-kvm";
298
memory_listener_register(&opp->mem_listener, &address_space_memory);
299
+ opp->vmfd_change_notifier.notify =
300
+ kvm_openpic_handle_vmfd_change;
301
+ kvm_vmfd_add_change_notifier(&opp->vmfd_change_notifier);
302
303
/* indicate pic capabilities */
304
msi_nonbroken = true;