@samitouri / QOSamiQemu / commits / c320bd40f7

ppc/openpic: create a new openpic device and reattach mem region on coco reset

For confidential guests during the reset process, the old KVM VM file descriptor is closed and a new one is created. When a new file descriptor is created, a new openpic device needs to be created against this new KVM VM file descriptor as well. Additionally, existing memory region needs to be reattached to this new openpic device and proper CPU attributes set associating new file descriptor. This change makes this happen with the help of a callback handler that gets called when the KVM VM file descriptor changes as a part of the confidential guest reset process. Reviewed-by: Bernhard Beschow <shentey@gmail.com> Signed-off-by: Ani Sinha <anisinha@redhat.com> Link: https://lore.kernel.org/r/20260225035000.385950-30-anisinha@redhat.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Ani Sinha committed Feb 25, 2026 at 09:19 UTC c320bd40f7cddc2a755ad3eac4ee2088a7d466cd
1 file changed +88 -24
hw/intc/openpic_kvm.c
+88 -24
@@ -49,6 +49,7 @@ struct KVMOpenPICState {
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)
@@ -114,6 +115,88 @@ static const MemoryRegionOps kvm_openpic_mem_ops = {
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)&reg_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 {
@@ -197,36 +280,14 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp)
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);
@@ -235,6 +296,9 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp)
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;