From 756d122f8328293ae8a4a2fcc1262bd99a4415f3 Mon Sep 17 00:00:00 2001 From: Martin Kuettler Date: Thu, 26 Oct 2023 10:20:15 +0200 Subject: [PATCH] Removed uvmm and virtio-net --- src/l4/pkg/uvmm/Control | 4 - src/l4/pkg/uvmm/Kconfig.L4 | 328 ---- src/l4/pkg/uvmm/LICENSE.spdx | 47 - src/l4/pkg/uvmm/Makefile | 6 - src/l4/pkg/uvmm/README.md | 22 - src/l4/pkg/uvmm/SECURITY.md | 29 - src/l4/pkg/uvmm/configs/Makefile | 11 - src/l4/pkg/uvmm/configs/dts/Makefile | 18 - src/l4/pkg/uvmm/configs/dts/ic-arm.dtsi | 21 - src/l4/pkg/uvmm/configs/dts/ic-mips.dtsi | 32 - .../interrupt-controller/arm-gic.h | 23 - .../dt-bindings/interrupt-controller/irq.h | 20 - .../pkg/uvmm/configs/dts/pl031_overlay.dtso | 38 - src/l4/pkg/uvmm/configs/dts/skeleton.dtsi | 13 - src/l4/pkg/uvmm/configs/dts/skeleton64.dtsi | 13 - src/l4/pkg/uvmm/configs/dts/syscon.dtsi | 33 - src/l4/pkg/uvmm/configs/dts/virt-arm_sbsa.dts | 165 -- .../pkg/uvmm/configs/dts/virt-arm_virt-32.dts | 96 -- .../pkg/uvmm/configs/dts/virt-arm_virt-64.dts | 93 -- .../configs/dts/virt-arm_virt-64_pci.dtso | 42 - .../pkg/uvmm/configs/dts/virt-armada37xx.dts | 34 - src/l4/pkg/uvmm/configs/dts/virt-exynos5.dts | 30 - src/l4/pkg/uvmm/configs/dts/virt-mips32.dts | 32 - src/l4/pkg/uvmm/configs/dts/virt-mips64.dts | 44 - src/l4/pkg/uvmm/configs/dts/virt-omap5.dts | 31 - src/l4/pkg/uvmm/configs/dts/virt-pc.dts | 262 ---- src/l4/pkg/uvmm/configs/dts/virt-riscv.dtsi | 77 - src/l4/pkg/uvmm/configs/dts/virt-riscv32.dts | 6 - src/l4/pkg/uvmm/configs/dts/virt-riscv64.dts | 6 - .../pkg/uvmm/configs/dts/vmm-devices-arm.dtsi | 50 - .../uvmm/configs/dts/vmm-devices-mips.dtsi | 32 - .../uvmm/configs/dts/vmm-devices-riscv.dtsi | 46 - ...printk-patch-l4re-uvmm-virt.config-f.patch | 79 - .../pkg/uvmm/configs/guests/Linux/arm/README | 60 - ...-MIPS-Add-virtual-platform-linux-4.4.patch | 603 -------- ...-MIPS-Add-virtual-platform-linux-4.8.patch | 603 -------- ...-MIPS-Add-virtual-platform-linux-4.9.patch | 602 -------- .../pkg/uvmm/configs/guests/Linux/mips/README | 25 - src/l4/pkg/uvmm/configs/modules.list | 17 - src/l4/pkg/uvmm/configs/uvmm.ned | 54 - src/l4/pkg/uvmm/configs/vmm.lua | 244 --- src/l4/pkg/uvmm/doc/files.cfg | 3 - src/l4/pkg/uvmm/doc/uvmm-ram.dox | 82 - src/l4/pkg/uvmm/doc/uvmm.dox | 512 ------ src/l4/pkg/uvmm/doc/uvmm_dtg.md | 81 - src/l4/pkg/uvmm/server/Makefile | 4 - src/l4/pkg/uvmm/server/include/cell.h | 333 ---- src/l4/pkg/uvmm/server/include/device_tree.h | 1376 ----------------- src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi.h | 851 ---------- .../server/src/ARCH-amd64/acpi_platform.cc | 555 ------- .../uvmm/server/src/ARCH-amd64/acpi_timer.cc | 106 -- .../src/ARCH-amd64/binary_loader_linux.cc | 62 - .../src/ARCH-amd64/binary_loader_openbsd.cc | 50 - .../src/ARCH-amd64/binary_loader_openbsd.h | 32 - .../server/src/ARCH-amd64/binary_loader_raw.h | 24 - .../pkg/uvmm/server/src/ARCH-amd64/cpu_dev.cc | 8 - .../pkg/uvmm/server/src/ARCH-amd64/cpu_dev.h | 266 ---- src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid.h | 421 ----- .../uvmm/server/src/ARCH-amd64/cpuid_device.h | 40 - .../src/ARCH-amd64/debugger/guest_debugger.h | 22 - .../server/src/ARCH-amd64/event_record.cc | 58 - .../uvmm/server/src/ARCH-amd64/event_record.h | 124 -- .../src/ARCH-amd64/event_record_lapic.h | 50 - .../server/src/ARCH-amd64/event_recorder.cc | 114 -- .../server/src/ARCH-amd64/event_recorder.h | 307 ---- .../uvmm/server/src/ARCH-amd64/framebuffer.cc | 119 -- .../uvmm/server/src/ARCH-amd64/guest-svm.cc | 340 ---- .../uvmm/server/src/ARCH-amd64/guest-vmx.cc | 374 ----- .../pkg/uvmm/server/src/ARCH-amd64/guest.cc | 1064 ------------- src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.h | 489 ------ .../src/ARCH-amd64/io_port_handler_l4util.cc | 59 - .../pkg/uvmm/server/src/ARCH-amd64/ioapic.cc | 263 ---- .../pkg/uvmm/server/src/ARCH-amd64/ioapic.h | 294 ---- .../server/src/ARCH-amd64/isa_debugport.cc | 119 -- .../uvmm/server/src/ARCH-amd64/kvm_clock.cc | 32 - .../uvmm/server/src/ARCH-amd64/kvm_clock.h | 235 --- .../uvmm/server/src/ARCH-amd64/legacy_pic.cc | 35 - .../uvmm/server/src/ARCH-amd64/legacy_pic.h | 488 ------ src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.cc | 651 -------- src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.h | 156 -- .../ARCH-amd64/monitor/cpu_dev_cmd_handler.h | 218 --- .../ARCH-amd64/monitor/ioapic_cmd_handler.h | 147 -- .../ARCH-amd64/monitor/lapic_cmd_handler.h | 202 --- .../src/ARCH-amd64/monitor/monitor_arch.h | 8 - .../pkg/uvmm/server/src/ARCH-amd64/msi_arch.h | 61 - .../uvmm/server/src/ARCH-amd64/msr_devices.h | 51 - .../src/ARCH-amd64/openbsd_bootparams.cc | 159 -- .../src/ARCH-amd64/openbsd_bootparams.h | 196 --- src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.cc | 284 ---- src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.h | 432 ------ .../uvmm/server/src/ARCH-amd64/pt_walker.h | 188 --- .../server/src/ARCH-amd64/qemu_fw_cfg_acpi.cc | 217 --- .../server/src/ARCH-amd64/qemu_fw_cfg_boot.cc | 167 -- src/l4/pkg/uvmm/server/src/ARCH-amd64/rtc.cc | 599 ------- .../uvmm/server/src/ARCH-amd64/vcpu_ptr.cc | 213 --- .../pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.h | 94 -- .../uvmm/server/src/ARCH-amd64/virt_lapic.cc | 431 ------ .../uvmm/server/src/ARCH-amd64/virt_lapic.h | 1207 --------------- .../pkg/uvmm/server/src/ARCH-amd64/vm_state.h | 86 -- .../server/src/ARCH-amd64/vm_state_svm.cc | 699 --------- .../uvmm/server/src/ARCH-amd64/vm_state_svm.h | 469 ------ .../server/src/ARCH-amd64/vm_state_vmx.cc | 843 ---------- .../uvmm/server/src/ARCH-amd64/vm_state_vmx.h | 1042 ------------- src/l4/pkg/uvmm/server/src/ARCH-amd64/vmcs.h | 267 ---- .../server/src/ARCH-amd64/vmx_exit_to_str.h | 94 -- .../uvmm/server/src/ARCH-amd64/zeropage.cc | 201 --- .../pkg/uvmm/server/src/ARCH-amd64/zeropage.h | 160 -- .../uvmm/server/src/ARCH-arm/aarch32_hyp.h | 20 - .../pkg/uvmm/server/src/ARCH-arm/cpu_dev.cc | 7 - .../server/src/ARCH-arm/cpu_dev_subarch.h | 45 - .../uvmm/server/src/ARCH-arm/guest_arm_exc.cc | 91 -- .../uvmm/server/src/ARCH-arm/guest_subarch.cc | 40 - .../uvmm/server/src/ARCH-arm/guest_subarch.h | 14 - .../ARCH-arm/monitor/cpu_dev_cmd_handler.h | 70 - .../pkg/uvmm/server/src/ARCH-arm/vcpu_ptr.h | 253 --- .../uvmm/server/src/ARCH-arm64/aarch64_hyp.h | 40 - .../pkg/uvmm/server/src/ARCH-arm64/cpu_dev.cc | 8 - .../server/src/ARCH-arm64/cpu_dev_subarch.h | 38 - .../server/src/ARCH-arm64/guest_arm_exc.cc | 169 -- .../server/src/ARCH-arm64/guest_subarch.cc | 535 ------- .../server/src/ARCH-arm64/guest_subarch.h | 14 - .../ARCH-arm64/monitor/cpu_dev_cmd_handler.h | 68 - .../pkg/uvmm/server/src/ARCH-arm64/vcpu_ptr.h | 124 -- .../server/src/ARCH-mips/binary_loader_raw.h | 23 - src/l4/pkg/uvmm/server/src/ARCH-mips/cm.h | 199 --- .../pkg/uvmm/server/src/ARCH-mips/core_ic.h | 206 --- src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.cc | 117 -- src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.h | 114 -- .../pkg/uvmm/server/src/ARCH-mips/cpu_dev.cc | 125 -- .../pkg/uvmm/server/src/ARCH-mips/cpu_dev.h | 157 -- .../src/ARCH-mips/debugger/guest_debugger.h | 22 - src/l4/pkg/uvmm/server/src/ARCH-mips/gic.cc | 334 ---- src/l4/pkg/uvmm/server/src/ARCH-mips/gic.h | 228 --- src/l4/pkg/uvmm/server/src/ARCH-mips/guest.cc | 263 ---- src/l4/pkg/uvmm/server/src/ARCH-mips/guest.h | 309 ---- .../uvmm/server/src/ARCH-mips/guest_entry.cc | 167 -- .../uvmm/server/src/ARCH-mips/guest_entry.h | 14 - .../server/src/ARCH-mips/mips_instructions.h | 160 -- .../ARCH-mips/monitor/cpu_dev_cmd_handler.h | 123 -- .../src/ARCH-mips/monitor/monitor_arch.h | 8 - .../pkg/uvmm/server/src/ARCH-mips/vcpu_ptr.h | 273 ---- .../src/ARCH-riscv/binary_loader_linux.cc | 43 - .../server/src/ARCH-riscv/binary_loader_raw.h | 29 - .../pkg/uvmm/server/src/ARCH-riscv/cpu_dev.cc | 171 -- .../pkg/uvmm/server/src/ARCH-riscv/cpu_dev.h | 182 --- .../src/ARCH-riscv/debugger/guest_debugger.h | 22 - .../pkg/uvmm/server/src/ARCH-riscv/guest.cc | 461 ------ src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.h | 104 -- .../ARCH-riscv/monitor/cpu_dev_cmd_handler.h | 107 -- .../src/ARCH-riscv/monitor/monitor_arch.h | 8 - src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.cc | 411 ----- src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.h | 416 ----- .../uvmm/server/src/ARCH-riscv/riscv_arch.h | 74 - .../server/src/ARCH-riscv/riscv_instruction.h | 267 ---- src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.cc | 605 -------- src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.h | 316 ---- .../pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.cc | 112 -- .../pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.h | 99 -- .../pkg/uvmm/server/src/ARCH-riscv/vcpu_ptr.h | 117 -- .../server/src/ARCH-riscv/virtual_timer.cc | 191 --- .../server/src/ARCH-riscv/virtual_timer.h | 144 -- src/l4/pkg/uvmm/server/src/Makefile | 150 -- .../uvmm/server/src/address_space_manager.cc | 227 --- .../uvmm/server/src/address_space_manager.h | 167 -- src/l4/pkg/uvmm/server/src/arm/arm_exc.h | 310 ---- src/l4/pkg/uvmm/server/src/arm/arm_hyp.h | 245 --- .../pkg/uvmm/server/src/arm/atomic_fwd_list.h | 210 --- .../server/src/arm/binary_loader_linux.cc | 56 - .../uvmm/server/src/arm/binary_loader_raw.h | 26 - src/l4/pkg/uvmm/server/src/arm/core_timer.h | 231 --- src/l4/pkg/uvmm/server/src/arm/cpu_dev.h | 225 --- src/l4/pkg/uvmm/server/src/arm/cpu_dev_arm.cc | 186 --- .../server/src/arm/debugger/guest_debugger.h | 22 - src/l4/pkg/uvmm/server/src/arm/gic-v2.cc | 279 ---- src/l4/pkg/uvmm/server/src/arm/gic-v3.cc | 412 ----- src/l4/pkg/uvmm/server/src/arm/gic-v3.h | 341 ---- src/l4/pkg/uvmm/server/src/arm/gic-v3_its.cc | 881 ----------- src/l4/pkg/uvmm/server/src/arm/gic_cpu.cc | 121 -- src/l4/pkg/uvmm/server/src/arm/gic_cpu.h | 1100 ------------- src/l4/pkg/uvmm/server/src/arm/gic_dist.h | 587 ------- src/l4/pkg/uvmm/server/src/arm/gic_iface.cc | 41 - src/l4/pkg/uvmm/server/src/arm/gic_iface.h | 102 -- src/l4/pkg/uvmm/server/src/arm/gic_mixin.h | 148 -- src/l4/pkg/uvmm/server/src/arm/guest.h | 198 --- src/l4/pkg/uvmm/server/src/arm/guest_arm.cc | 826 ---------- .../uvmm/server/src/arm/guest_arm_noexc.cc | 27 - .../server/src/arm/monitor/gic_cmd_handler.h | 63 - .../server/src/arm/monitor/monitor_arch.h | 8 - src/l4/pkg/uvmm/server/src/arm/sys_reg.h | 111 -- src/l4/pkg/uvmm/server/src/batch_unmapper.h | 50 - src/l4/pkg/uvmm/server/src/binary_loader.cc | 121 -- src/l4/pkg/uvmm/server/src/binary_loader.h | 191 --- .../pkg/uvmm/server/src/binary_loader_elf.cc | 39 - .../pkg/uvmm/server/src/binary_loader_linux.h | 25 - .../src/binary_loader_linux_compressed.cc | 98 -- .../pkg/uvmm/server/src/binary_loader_pe.cc | 49 - .../pkg/uvmm/server/src/binary_loader_raw.cc | 44 - .../pkg/uvmm/server/src/binary_loader_rom.cc | 56 - src/l4/pkg/uvmm/server/src/consts.h | 89 -- src/l4/pkg/uvmm/server/src/cpu_dev_array.cc | 67 - src/l4/pkg/uvmm/server/src/cpu_dev_array.h | 130 -- src/l4/pkg/uvmm/server/src/debug.cc | 148 -- src/l4/pkg/uvmm/server/src/debug.h | 171 -- .../src/debugger/generic_guest_debugger.cc | 51 - .../src/debugger/generic_guest_debugger.h | 47 - src/l4/pkg/uvmm/server/src/device.h | 241 --- .../pkg/uvmm/server/src/device/arm/pl031.cc | 313 ---- src/l4/pkg/uvmm/server/src/device/arm/psci.cc | 365 ----- .../uvmm/server/src/device/arm/smccc_device.h | 60 - .../uvmm/server/src/device/arm/smccc_proxy.cc | 101 -- .../pkg/uvmm/server/src/device/arm/vm_print.h | 60 - .../uvmm/server/src/device/bcm2835_mbox.cc | 248 --- src/l4/pkg/uvmm/server/src/device/cfi.cc | 559 ------- .../pkg/uvmm/server/src/device/framebuffer.cc | 308 ---- src/l4/pkg/uvmm/server/src/device/l4rtc.cc | 162 -- .../pkg/uvmm/server/src/device/mmio_proxy.cc | 274 ---- src/l4/pkg/uvmm/server/src/device/optee.cc | 234 --- .../server/src/device/pci_bridge_windows.h | 325 ---- .../uvmm/server/src/device/pci_bus_cfg_ecam.h | 76 - .../uvmm/server/src/device/pci_host_bridge.cc | 746 --------- .../uvmm/server/src/device/pci_host_bridge.h | 792 ---------- .../src/device/pci_host_ecam_generic.cc | 385 ----- .../server/src/device/pci_host_generic.cc | 675 -------- src/l4/pkg/uvmm/server/src/device/pl011.cc | 377 ----- .../pkg/uvmm/server/src/device/qemu_fw_cfg.cc | 715 --------- .../pkg/uvmm/server/src/device/qemu_fw_cfg.h | 47 - src/l4/pkg/uvmm/server/src/device/rom.cc | 70 - src/l4/pkg/uvmm/server/src/device/rtc-hub.cc | 10 - src/l4/pkg/uvmm/server/src/device/rtc-hub.h | 55 - src/l4/pkg/uvmm/server/src/device/sysctl.cc | 114 -- .../pkg/uvmm/server/src/device/uart_8250.cc | 568 ------- src/l4/pkg/uvmm/server/src/device/virq.cc | 154 -- .../src/device/virtio_device_mem_pool.cc | 38 - .../src/device/virtio_device_mem_pool.h | 131 -- .../server/src/device/virtio_device_proxy.cc | 161 -- .../server/src/device/virtio_device_proxy.h | 323 ---- .../src/device/virtio_device_proxy_pci.cc | 248 --- .../server/src/device/virtio_input_event.cc | 154 -- .../server/src/device/virtio_input_event.h | 297 ---- .../src/device/virtio_input_event_pci.cc | 159 -- .../server/src/device/virtio_input_power.cc | 151 -- .../server/src/device/virtio_input_power.h | 276 ---- .../src/device/virtio_input_power_pci.cc | 116 -- src/l4/pkg/uvmm/server/src/device_factory.cc | 138 -- src/l4/pkg/uvmm/server/src/device_factory.h | 160 -- src/l4/pkg/uvmm/server/src/device_repo.h | 86 -- src/l4/pkg/uvmm/server/src/ds_manager.h | 134 -- src/l4/pkg/uvmm/server/src/ds_mmio_handling.h | 133 -- src/l4/pkg/uvmm/server/src/ds_mmio_mapper.h | 283 ---- .../pkg/uvmm/server/src/event_connector_pci.h | 87 -- src/l4/pkg/uvmm/server/src/generic_cpu_dev.cc | 92 -- src/l4/pkg/uvmm/server/src/generic_cpu_dev.h | 210 --- src/l4/pkg/uvmm/server/src/generic_guest.cc | 68 - src/l4/pkg/uvmm/server/src/generic_guest.h | 276 ---- src/l4/pkg/uvmm/server/src/generic_vcpu_ptr.h | 178 --- src/l4/pkg/uvmm/server/src/host_dt.cc | 290 ---- src/l4/pkg/uvmm/server/src/host_dt.h | 102 -- src/l4/pkg/uvmm/server/src/io_device.h | 41 - src/l4/pkg/uvmm/server/src/io_port_handler.h | 34 - .../uvmm/server/src/io_port_handler_noop.cc | 23 - src/l4/pkg/uvmm/server/src/io_proxy.cc | 409 ----- src/l4/pkg/uvmm/server/src/io_proxy.h | 58 - src/l4/pkg/uvmm/server/src/irq.h | 242 --- src/l4/pkg/uvmm/server/src/irq_dt.h | 235 --- src/l4/pkg/uvmm/server/src/irq_svr.h | 332 ---- src/l4/pkg/uvmm/server/src/main.cc | 303 ---- src/l4/pkg/uvmm/server/src/mem_access.h | 118 -- src/l4/pkg/uvmm/server/src/mem_types.h | 128 -- src/l4/pkg/uvmm/server/src/mmio_device.cc | 63 - src/l4/pkg/uvmm/server/src/mmio_device.h | 417 ----- .../pkg/uvmm/server/src/mmio_space_handler.h | 44 - .../src/monitor/cpu_dev_array_cmd_handler.h | 132 -- .../uvmm/server/src/monitor/dbg_cmd_handler.h | 84 - .../src/monitor/dbg_enable_cmd_handler.h | 68 - .../uvmm/server/src/monitor/dt_cmd_handler.h | 316 ---- src/l4/pkg/uvmm/server/src/monitor/mem_dump.h | 164 -- src/l4/pkg/uvmm/server/src/monitor/monitor.cc | 549 ------- src/l4/pkg/uvmm/server/src/monitor/monitor.h | 158 -- .../uvmm/server/src/monitor/monitor_args.h | 487 ------ .../server/src/monitor/virtio_cmd_handler.h | 120 -- .../monitor/virtio_input_power_cmd_handler.h | 47 - .../uvmm/server/src/monitor/vm_cmd_handler.h | 164 -- .../src/monitor/vm_io_mem_cmd_handler.h | 88 -- .../server/src/monitor/vm_ram_cmd_handler.h | 95 -- src/l4/pkg/uvmm/server/src/msi.h | 93 -- src/l4/pkg/uvmm/server/src/msi_allocator.h | 41 - src/l4/pkg/uvmm/server/src/msi_controller.h | 73 - src/l4/pkg/uvmm/server/src/msi_irq_src.h | 157 -- src/l4/pkg/uvmm/server/src/msi_memory.h | 259 ---- src/l4/pkg/uvmm/server/src/msix.h | 58 - src/l4/pkg/uvmm/server/src/msr_device.h | 47 - src/l4/pkg/uvmm/server/src/pci_device.cc | 207 --- src/l4/pkg/uvmm/server/src/pci_device.h | 1000 ------------ .../pkg/uvmm/server/src/pci_virtio_config.h | 172 --- .../pkg/uvmm/server/src/pci_virtio_device.h | 344 ----- src/l4/pkg/uvmm/server/src/pm.cc | 157 -- src/l4/pkg/uvmm/server/src/pm.h | 66 - src/l4/pkg/uvmm/server/src/pm_device_if.cc | 47 - src/l4/pkg/uvmm/server/src/pm_device_if.h | 94 -- src/l4/pkg/uvmm/server/src/ram_ds.cc | 128 -- src/l4/pkg/uvmm/server/src/ram_ds.h | 116 -- src/l4/pkg/uvmm/server/src/timer.h | 253 --- src/l4/pkg/uvmm/server/src/vbus_event.cc | 42 - src/l4/pkg/uvmm/server/src/vbus_event.h | 52 - src/l4/pkg/uvmm/server/src/vcon_device.h | 49 - .../pkg/uvmm/server/src/vcpu_obj_registry.h | 70 - src/l4/pkg/uvmm/server/src/virt_bus.cc | 209 --- src/l4/pkg/uvmm/server/src/virt_bus.h | 286 ---- src/l4/pkg/uvmm/server/src/virt_pci_device.cc | 127 -- src/l4/pkg/uvmm/server/src/virt_pci_device.h | 317 ---- src/l4/pkg/uvmm/server/src/virtio_console.cc | 43 - src/l4/pkg/uvmm/server/src/virtio_console.h | 311 ---- .../pkg/uvmm/server/src/virtio_console_pci.cc | 111 -- src/l4/pkg/uvmm/server/src/virtio_dev.h | 361 ----- .../uvmm/server/src/virtio_event_connector.h | 73 - src/l4/pkg/uvmm/server/src/virtio_input.h | 209 --- .../uvmm/server/src/virtio_pci_connector.h | 444 ------ src/l4/pkg/uvmm/server/src/virtio_proxy.cc | 74 - src/l4/pkg/uvmm/server/src/virtio_proxy.h | 374 ----- .../pkg/uvmm/server/src/virtio_proxy_pci.cc | 110 -- src/l4/pkg/uvmm/server/src/virtio_qword.h | 17 - src/l4/pkg/uvmm/server/src/vm.cc | 212 --- src/l4/pkg/uvmm/server/src/vm.h | 152 -- src/l4/pkg/uvmm/server/src/vm_memmap.cc | 90 -- src/l4/pkg/uvmm/server/src/vm_memmap.h | 33 - src/l4/pkg/uvmm/server/src/vm_ram.cc | 421 ----- src/l4/pkg/uvmm/server/src/vm_ram.h | 224 --- src/l4/pkg/uvmm/server/src/vmprint.h | 45 - src/l4/pkg/uvmm/tools/Makefile | 6 - src/l4/pkg/uvmm/tools/uvmm_cli/Makefile | 10 - src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.cc | 419 ----- src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.h | 81 - src/l4/pkg/uvmm/tools/uvmm_dtg/Makefile | 6 - .../uvmm/tools/uvmm_dtg/build-host/Makefile | 12 - .../tools/uvmm_dtg/build/ARCH-amd64/config.h | 9 - .../tools/uvmm_dtg/build/ARCH-arm/config.h | 9 - .../tools/uvmm_dtg/build/ARCH-arm64/config.h | 9 - .../tools/uvmm_dtg/build/ARCH-mips/config.h | 9 - .../tools/uvmm_dtg/build/ARCH-x86/config.h | 9 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/Makefile | 53 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/algh.h | 69 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/const.h | 116 -- .../pkg/uvmm/tools/uvmm_dtg/build/device.cc | 10 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.h | 361 ----- .../uvmm_dtg/build/devices/acpi_platform.cc | 49 - .../uvmm_dtg/build/devices/acpi_timer.cc | 38 - .../tools/uvmm_dtg/build/devices/arm_psci.cc | 45 - .../tools/uvmm_dtg/build/devices/arm_timer.cc | 46 - .../uvmm/tools/uvmm_dtg/build/devices/cfi.cc | 87 -- .../uvmm/tools/uvmm_dtg/build/devices/cpu.cc | 65 - .../uvmm/tools/uvmm_dtg/build/devices/eisa.cc | 51 - .../uvmm_dtg/build/devices/framebuffer.cc | 67 - .../uvmm/tools/uvmm_dtg/build/devices/gic.cc | 73 - .../tools/uvmm_dtg/build/devices/ioapic.cc | 64 - .../uvmm_dtg/build/devices/isa-debugport.cc | 46 - .../tools/uvmm_dtg/build/devices/kvm_clock.cc | 35 - .../tools/uvmm_dtg/build/devices/l4rtc.cc | 44 - .../tools/uvmm_dtg/build/devices/memory.cc | 69 - .../uvmm_dtg/build/devices/mmio_proxy.cc | 64 - .../uvmm_dtg/build/devices/msi_control.cc | 40 - .../tools/uvmm_dtg/build/devices/ns8250.cc | 80 - .../tools/uvmm_dtg/build/devices/optee.cc | 55 - .../uvmm_dtg/build/devices/pci_bridge.cc | 86 -- .../tools/uvmm_dtg/build/devices/pci_bridge.h | 22 - .../uvmm_dtg/build/devices/pci_host_ecam.cc | 113 -- .../uvmm/tools/uvmm_dtg/build/devices/pic.cc | 45 - .../uvmm/tools/uvmm_dtg/build/devices/pit.cc | 44 - .../tools/uvmm_dtg/build/devices/pl011.cc | 63 - .../tools/uvmm_dtg/build/devices/pl031.cc | 48 - .../uvmm_dtg/build/devices/qemu_fw_if.cc | 60 - .../uvmm/tools/uvmm_dtg/build/devices/rom.cc | 51 - .../uvmm/tools/uvmm_dtg/build/devices/rtc.cc | 39 - .../tools/uvmm_dtg/build/devices/stats.cc | 47 - .../tools/uvmm_dtg/build/devices/sysclock.cc | 38 - .../tools/uvmm_dtg/build/devices/syscon.cc | 65 - .../tools/uvmm_dtg/build/devices/virq_rcv.cc | 49 - .../tools/uvmm_dtg/build/devices/virq_snd.cc | 49 - .../uvmm_dtg/build/devices/virtio_console.cc | 55 - .../build/devices/virtio_console_pci.cc | 55 - .../build/devices/virtio_device_proxy.cc | 67 - .../build/devices/virtio_input_event_pci.cc | 59 - .../build/devices/virtio_input_power.cc | 59 - .../build/devices/virtio_input_power_pci.cc | 59 - .../uvmm_dtg/build/devices/virtio_proxy.cc | 59 - .../build/devices/virtio_proxy_pci.cc | 59 - .../pkg/uvmm/tools/uvmm_dtg/build/generic.h | 68 - .../uvmm/tools/uvmm_dtg/build/host/config.h | 9 - .../uvmm/tools/uvmm_dtg/build/host/support.h | 18 - .../uvmm/tools/uvmm_dtg/build/host/writer.h | 31 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/ic.cc | 9 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/ic.h | 38 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/opts.h | 611 -------- .../uvmm/tools/uvmm_dtg/build/output_bin.h | 160 -- .../uvmm/tools/uvmm_dtg/build/output_txt.h | 151 -- .../tools/uvmm_dtg/build/target/support.h | 36 - .../uvmm/tools/uvmm_dtg/build/target/writer.h | 51 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/tree.cc | 9 - src/l4/pkg/uvmm/tools/uvmm_dtg/build/tree.h | 521 ------- .../pkg/uvmm/tools/uvmm_dtg/build/uvmm_dtg.cc | 148 -- src/l4/pkg/virtio-net/Control | 2 - src/l4/pkg/virtio-net/LICENSE.spdx | 22 - src/l4/pkg/virtio-net/Makefile | 4 - src/l4/pkg/virtio-net/README.md | 21 - src/l4/pkg/virtio-net/SECURITY.md | 29 - src/l4/pkg/virtio-net/doc/files.cfg | 2 - src/l4/pkg/virtio-net/doc/usage.md | 87 -- src/l4/pkg/virtio-net/doc/virtio-net-p2p.dox | 6 - src/l4/pkg/virtio-net/server/Makefile | 6 - .../pkg/virtio-net/server/include/checksum.h | 67 - src/l4/pkg/virtio-net/server/include/debug.h | 30 - .../pkg/virtio-net/server/p2p-link/Makefile | 9 - src/l4/pkg/virtio-net/server/p2p-link/net.cc | 1211 --------------- 412 files changed, 71723 deletions(-) delete mode 100644 src/l4/pkg/uvmm/Control delete mode 100644 src/l4/pkg/uvmm/Kconfig.L4 delete mode 100644 src/l4/pkg/uvmm/LICENSE.spdx delete mode 100644 src/l4/pkg/uvmm/Makefile delete mode 100644 src/l4/pkg/uvmm/README.md delete mode 100644 src/l4/pkg/uvmm/SECURITY.md delete mode 100644 src/l4/pkg/uvmm/configs/Makefile delete mode 100644 src/l4/pkg/uvmm/configs/dts/Makefile delete mode 100644 src/l4/pkg/uvmm/configs/dts/ic-arm.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/ic-mips.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/arm-gic.h delete mode 100644 src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/irq.h delete mode 100644 src/l4/pkg/uvmm/configs/dts/pl031_overlay.dtso delete mode 100644 src/l4/pkg/uvmm/configs/dts/skeleton.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/skeleton64.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/syscon.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-arm_sbsa.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-arm_virt-32.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64_pci.dtso delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-armada37xx.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-exynos5.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-mips32.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-mips64.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-omap5.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-pc.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-riscv.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-riscv32.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/virt-riscv64.dts delete mode 100644 src/l4/pkg/uvmm/configs/dts/vmm-devices-arm.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/vmm-devices-mips.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/dts/vmm-devices-riscv.dtsi delete mode 100644 src/l4/pkg/uvmm/configs/guests/Linux/amd64/0001-L4Re-UVMM-early_printk-patch-l4re-uvmm-virt.config-f.patch delete mode 100644 src/l4/pkg/uvmm/configs/guests/Linux/arm/README delete mode 100644 src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.4.patch delete mode 100644 src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.8.patch delete mode 100644 src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.9.patch delete mode 100644 src/l4/pkg/uvmm/configs/guests/Linux/mips/README delete mode 100644 src/l4/pkg/uvmm/configs/modules.list delete mode 100644 src/l4/pkg/uvmm/configs/uvmm.ned delete mode 100644 src/l4/pkg/uvmm/configs/vmm.lua delete mode 100644 src/l4/pkg/uvmm/doc/files.cfg delete mode 100644 src/l4/pkg/uvmm/doc/uvmm-ram.dox delete mode 100644 src/l4/pkg/uvmm/doc/uvmm.dox delete mode 100644 src/l4/pkg/uvmm/doc/uvmm_dtg.md delete mode 100644 src/l4/pkg/uvmm/server/Makefile delete mode 100644 src/l4/pkg/uvmm/server/include/cell.h delete mode 100644 src/l4/pkg/uvmm/server/include/device_tree.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_platform.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_timer.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_linux.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_raw.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/debugger/guest_debugger.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record_lapic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/framebuffer.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-svm.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-vmx.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/io_port_handler_l4util.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/isa_debugport.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/cpu_dev_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/ioapic_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/lapic_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/monitor_arch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/msi_arch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/msr_devices.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/pt_walker.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_acpi.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_boot.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/rtc.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vmcs.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/vmx_exit_to_str.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/aarch32_hyp.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev_subarch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/guest_arm_exc.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/monitor/cpu_dev_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm/vcpu_ptr.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/aarch64_hyp.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev_subarch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_arm_exc.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/monitor/cpu_dev_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-arm64/vcpu_ptr.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/binary_loader_raw.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/cm.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/core_ic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/debugger/guest_debugger.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/gic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/gic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/guest.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/guest.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/mips_instructions.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/cpu_dev_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/monitor_arch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-mips/vcpu_ptr.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_linux.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_raw.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/debugger/guest_debugger.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/cpu_dev_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/monitor_arch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_arch.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_instruction.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ptr.h delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.h delete mode 100644 src/l4/pkg/uvmm/server/src/Makefile delete mode 100644 src/l4/pkg/uvmm/server/src/address_space_manager.cc delete mode 100644 src/l4/pkg/uvmm/server/src/address_space_manager.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/arm_exc.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/arm_hyp.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/atomic_fwd_list.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/binary_loader_linux.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/binary_loader_raw.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/core_timer.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/cpu_dev.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/cpu_dev_arm.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/debugger/guest_debugger.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic-v2.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic-v3.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic-v3.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic-v3_its.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic_cpu.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic_cpu.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic_dist.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic_iface.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic_iface.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/gic_mixin.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/guest.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/guest_arm.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/guest_arm_noexc.cc delete mode 100644 src/l4/pkg/uvmm/server/src/arm/monitor/gic_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/monitor/monitor_arch.h delete mode 100644 src/l4/pkg/uvmm/server/src/arm/sys_reg.h delete mode 100644 src/l4/pkg/uvmm/server/src/batch_unmapper.h delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader.cc delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader.h delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader_elf.cc delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader_linux.h delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader_linux_compressed.cc delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader_pe.cc delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader_raw.cc delete mode 100644 src/l4/pkg/uvmm/server/src/binary_loader_rom.cc delete mode 100644 src/l4/pkg/uvmm/server/src/consts.h delete mode 100644 src/l4/pkg/uvmm/server/src/cpu_dev_array.cc delete mode 100644 src/l4/pkg/uvmm/server/src/cpu_dev_array.h delete mode 100644 src/l4/pkg/uvmm/server/src/debug.cc delete mode 100644 src/l4/pkg/uvmm/server/src/debug.h delete mode 100644 src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.cc delete mode 100644 src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.h delete mode 100644 src/l4/pkg/uvmm/server/src/device.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/arm/pl031.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/arm/psci.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/arm/smccc_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/arm/smccc_proxy.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/arm/vm_print.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/bcm2835_mbox.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/cfi.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/framebuffer.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/l4rtc.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/mmio_proxy.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/optee.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/pci_bridge_windows.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/pci_bus_cfg_ecam.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/pci_host_bridge.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/pci_host_bridge.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/pci_host_ecam_generic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/pci_host_generic.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/pl011.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/rom.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/rtc-hub.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/rtc-hub.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/sysctl.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/uart_8250.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virq.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_device_proxy_pci.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_input_event.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_input_event.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_input_event_pci.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_input_power.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_input_power.h delete mode 100644 src/l4/pkg/uvmm/server/src/device/virtio_input_power_pci.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device_factory.cc delete mode 100644 src/l4/pkg/uvmm/server/src/device_factory.h delete mode 100644 src/l4/pkg/uvmm/server/src/device_repo.h delete mode 100644 src/l4/pkg/uvmm/server/src/ds_manager.h delete mode 100644 src/l4/pkg/uvmm/server/src/ds_mmio_handling.h delete mode 100644 src/l4/pkg/uvmm/server/src/ds_mmio_mapper.h delete mode 100644 src/l4/pkg/uvmm/server/src/event_connector_pci.h delete mode 100644 src/l4/pkg/uvmm/server/src/generic_cpu_dev.cc delete mode 100644 src/l4/pkg/uvmm/server/src/generic_cpu_dev.h delete mode 100644 src/l4/pkg/uvmm/server/src/generic_guest.cc delete mode 100644 src/l4/pkg/uvmm/server/src/generic_guest.h delete mode 100644 src/l4/pkg/uvmm/server/src/generic_vcpu_ptr.h delete mode 100644 src/l4/pkg/uvmm/server/src/host_dt.cc delete mode 100644 src/l4/pkg/uvmm/server/src/host_dt.h delete mode 100644 src/l4/pkg/uvmm/server/src/io_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/io_port_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/io_port_handler_noop.cc delete mode 100644 src/l4/pkg/uvmm/server/src/io_proxy.cc delete mode 100644 src/l4/pkg/uvmm/server/src/io_proxy.h delete mode 100644 src/l4/pkg/uvmm/server/src/irq.h delete mode 100644 src/l4/pkg/uvmm/server/src/irq_dt.h delete mode 100644 src/l4/pkg/uvmm/server/src/irq_svr.h delete mode 100644 src/l4/pkg/uvmm/server/src/main.cc delete mode 100644 src/l4/pkg/uvmm/server/src/mem_access.h delete mode 100644 src/l4/pkg/uvmm/server/src/mem_types.h delete mode 100644 src/l4/pkg/uvmm/server/src/mmio_device.cc delete mode 100644 src/l4/pkg/uvmm/server/src/mmio_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/mmio_space_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/cpu_dev_array_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/dbg_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/dbg_enable_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/dt_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/mem_dump.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/monitor.cc delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/monitor.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/monitor_args.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/virtio_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/virtio_input_power_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/vm_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/vm_io_mem_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/monitor/vm_ram_cmd_handler.h delete mode 100644 src/l4/pkg/uvmm/server/src/msi.h delete mode 100644 src/l4/pkg/uvmm/server/src/msi_allocator.h delete mode 100644 src/l4/pkg/uvmm/server/src/msi_controller.h delete mode 100644 src/l4/pkg/uvmm/server/src/msi_irq_src.h delete mode 100644 src/l4/pkg/uvmm/server/src/msi_memory.h delete mode 100644 src/l4/pkg/uvmm/server/src/msix.h delete mode 100644 src/l4/pkg/uvmm/server/src/msr_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/pci_device.cc delete mode 100644 src/l4/pkg/uvmm/server/src/pci_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/pci_virtio_config.h delete mode 100644 src/l4/pkg/uvmm/server/src/pci_virtio_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/pm.cc delete mode 100644 src/l4/pkg/uvmm/server/src/pm.h delete mode 100644 src/l4/pkg/uvmm/server/src/pm_device_if.cc delete mode 100644 src/l4/pkg/uvmm/server/src/pm_device_if.h delete mode 100644 src/l4/pkg/uvmm/server/src/ram_ds.cc delete mode 100644 src/l4/pkg/uvmm/server/src/ram_ds.h delete mode 100644 src/l4/pkg/uvmm/server/src/timer.h delete mode 100644 src/l4/pkg/uvmm/server/src/vbus_event.cc delete mode 100644 src/l4/pkg/uvmm/server/src/vbus_event.h delete mode 100644 src/l4/pkg/uvmm/server/src/vcon_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/vcpu_obj_registry.h delete mode 100644 src/l4/pkg/uvmm/server/src/virt_bus.cc delete mode 100644 src/l4/pkg/uvmm/server/src/virt_bus.h delete mode 100644 src/l4/pkg/uvmm/server/src/virt_pci_device.cc delete mode 100644 src/l4/pkg/uvmm/server/src/virt_pci_device.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_console.cc delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_console.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_console_pci.cc delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_dev.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_event_connector.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_input.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_pci_connector.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_proxy.cc delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_proxy.h delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_proxy_pci.cc delete mode 100644 src/l4/pkg/uvmm/server/src/virtio_qword.h delete mode 100644 src/l4/pkg/uvmm/server/src/vm.cc delete mode 100644 src/l4/pkg/uvmm/server/src/vm.h delete mode 100644 src/l4/pkg/uvmm/server/src/vm_memmap.cc delete mode 100644 src/l4/pkg/uvmm/server/src/vm_memmap.h delete mode 100644 src/l4/pkg/uvmm/server/src/vm_ram.cc delete mode 100644 src/l4/pkg/uvmm/server/src/vm_ram.h delete mode 100644 src/l4/pkg/uvmm/server/src/vmprint.h delete mode 100644 src/l4/pkg/uvmm/tools/Makefile delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_cli/Makefile delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/Makefile delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build-host/Makefile delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-amd64/config.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm/config.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm64/config.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-mips/config.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-x86/config.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/Makefile delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/algh.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/const.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/acpi_platform.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/acpi_timer.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/arm_psci.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/arm_timer.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/cfi.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/cpu.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/eisa.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/framebuffer.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/gic.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/ioapic.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/isa-debugport.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/kvm_clock.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/l4rtc.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/memory.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/mmio_proxy.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/msi_control.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/ns8250.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/optee.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pci_bridge.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pci_bridge.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pci_host_ecam.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pic.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pit.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pl011.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/pl031.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/qemu_fw_if.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/rom.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/rtc.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/stats.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/sysclock.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/syscon.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virq_rcv.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virq_snd.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_console.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_console_pci.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_device_proxy.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_input_event_pci.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_input_power.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_input_power_pci.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_proxy.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/devices/virtio_proxy_pci.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/generic.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/host/config.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/host/support.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/host/writer.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ic.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/ic.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/opts.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/output_bin.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/output_txt.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/target/support.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/target/writer.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/tree.cc delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/tree.h delete mode 100644 src/l4/pkg/uvmm/tools/uvmm_dtg/build/uvmm_dtg.cc delete mode 100644 src/l4/pkg/virtio-net/Control delete mode 100644 src/l4/pkg/virtio-net/LICENSE.spdx delete mode 100644 src/l4/pkg/virtio-net/Makefile delete mode 100644 src/l4/pkg/virtio-net/README.md delete mode 100644 src/l4/pkg/virtio-net/SECURITY.md delete mode 100644 src/l4/pkg/virtio-net/doc/files.cfg delete mode 100644 src/l4/pkg/virtio-net/doc/usage.md delete mode 100644 src/l4/pkg/virtio-net/doc/virtio-net-p2p.dox delete mode 100644 src/l4/pkg/virtio-net/server/Makefile delete mode 100644 src/l4/pkg/virtio-net/server/include/checksum.h delete mode 100644 src/l4/pkg/virtio-net/server/include/debug.h delete mode 100644 src/l4/pkg/virtio-net/server/p2p-link/Makefile delete mode 100644 src/l4/pkg/virtio-net/server/p2p-link/net.cc diff --git a/src/l4/pkg/uvmm/Control b/src/l4/pkg/uvmm/Control deleted file mode 100644 index b045149f..00000000 --- a/src/l4/pkg/uvmm/Control +++ /dev/null @@ -1,4 +0,0 @@ -requires: stdlibs libstdc++ libpthread libio-vbus libfdt l4virtio libloader -optional: readline acpica zlib rtc libmbox-bcm2835 -variants: nofpu[server/src] -maintainer: alexander.warg@kernkonzept.com adam@l4re.org diff --git a/src/l4/pkg/uvmm/Kconfig.L4 b/src/l4/pkg/uvmm/Kconfig.L4 deleted file mode 100644 index 6bb81124..00000000 --- a/src/l4/pkg/uvmm/Kconfig.L4 +++ /dev/null @@ -1,328 +0,0 @@ -config UVMM_SUPPORTED - def_bool BUILD_ARCH_arm64 || BUILD_ARCH_arm || BUILD_ARCH_amd64 || BUILD_ARCH_mips || BUILD_ARCH_riscv - -comment "uvmm is not supported on this architecture" - depends on !UVMM_SUPPORTED - -comment "uvmm requires L4Re libgcc instead of toolchain version" - depends on UVMM_SUPPORTED && COMPILER_RT_USE_TOOLCHAIN_LIBGCC - -menu "uvmm virtual machine monitor" - depends on UVMM_SUPPORTED - depends on !COMPILER_RT_USE_TOOLCHAIN_LIBGCC - -config UVMM_MONITOR - bool "Monitor interface" - depends on !RELEASE_MODE - default y - help - Enables the monitoring interface that can be used to query and manipulate - the guest state at runtime. When enabled the interface must also be switched - on at runtime using the `mon` command line option. - -menu "Supported Loaders" - -config UVMM_LOADER_RAW - bool "RAW images" - default y - help - Allows to raw kernel images from an address. The format for the file name - is 'raw:addr=0xcaffee:filename' where addr is the address the image should - be loaded to, relative to the guest ram base. - -config UVMM_LOADER_ELF - bool "ELF images" - default y - help - Enable loading of elf images. The file found under the file name passed to - uvmm must be a valid ELF file for the loader to pick it up. - -config UVMM_LOADER_PE - bool "PE images (error handling only)" - default y - help - Print usefull errors when trying to load PE images. If the file found under - the file name passed to uvmm is a PE file uvmm will not load it but provides - helpful error messages. - -config UVMM_LOADER_ROM - bool "ROM images (from guest memory locations)" - default y - help - Enable loading of images from a guest memory location. The format for the - kernel file name passed to uvmm is 'rom:addr=0xcaffee' where 0xcaffee is - a valid address in the memory of the guest. If the format is - 'rom:addr=0xcaffee:64bit' then the guest is a 64 bit guest. - -config UVMM_LOADER_LINUX - bool "Linux images (non-elf)" - depends on BUILD_ARCH_arm64 || BUILD_ARCH_arm || BUILD_ARCH_amd64 || BUILD_ARCH_riscv - default y - help - Loads a Linux image. - -config UVMM_LOADER_OPENBSD - bool "OpenBSD images" - depends on BUILD_ARCH_amd64 - default y - help - Loads an OpenBSD image. - -config UVMM_LOADER_GZIP - bool "GZIP/ZLIB loading for Linux images" - depends on (BUILD_ARCH_arm64 || BUILD_ARCH_arm || BUILD_ARCH_riscv) && HAVE_BIDPC_ZLIB && UVMM_LOADER_LINUX - default y - help - Allows to load gzip or zlib compressed kernel images. - -endmenu - -comment "GZIP/ZLIB compression not available due to missing zlib package" - depends on !HAVE_BIDPC_ZLIB - -config UVMM_QEMU_FW_IF - bool "Qemu firmware configuration device" - default y - help - The device allows guests to gain access to the configuration of the - hypervisor or any kind of data like boot/kernel images in a defined way. - Some bootloaders make use of this to setup the platform and start the guest - OS. - - For details on the configuration see device/qemu_fw_cfg.cc. - -config UVMM_FAULT_INJECT - bool "Fault injection" - depends on BUILD_ARCH_arm64 || BUILD_ARCH_arm - -comment "Interfacing with L4 applications or physical hardware" - -config UVMM_VDEV_PSCI - bool "PSCI interface support" - depends on BUILD_ARCH_arm || BUILD_ARCH_arm64 - default y - help - Emulates a PSCI interface for the guest. - -config UVMM_VDEV_SMCCC_PROXY - bool "Smc device proxy" - depends on BUILD_ARCH_arm || BUILD_ARCH_arm64 - default y - help - Proxies Smccc calls. - -config UVMM_PCI_SUPPORT - bool "Support PCI emulation" if BUILD_ARCH_arm64 || BUILD_ARCH_arm - default y - help - Configures if the PCI subsystem (and the corresponding devices using the - PCI transport) should be available in uvmm. - -config UVMM_VDEV_OPTEE - bool "OPTEE SMC call forwarding" - depends on BUILD_ARCH_arm || BUILD_ARCH_arm64 - default y - help - Allows forwarding of OP-TEE SMC calls either to a running OP-TEE instance - or to a native L4 application implementing the protocol. - - For details on the configuration see device/optee.cc. - -config UVMM_VDEV_VIRQ - bool "Forward L4 interrupts" - default y - help - Add a device for relaying L4 IRQs into the guest. - - For details on the configuration see device/virq.cc - -config UVMM_VDEV_MMIO_PROXY - bool "Proxy dataspaces and MMIO protocol" - default y - help - Emulate a device that proxies memory accesses to an external dataspace or - MMIO space. - - For details on the configuration see device/mmio_proxy.cc - -config UVMM_VDEV_SYSCTL - bool "System control device" - default y - help - Mmio-based device for triggering system events (shutdown, reboot). - The device can be used with the generic syscon device from Linux. - - For details on the configuration see device/sysctl.cc - -config UVMM_VDEV_ROM - bool "Read-only dataspace based devices" - default y - help - A device for adding L4 dataspaces read-only to the guest. - - For details on the configuration see device/rom.cc - -config UVMM_EXTERNAL_RTC - bool "l4rtc time source" - depends on HAVE_BIDPC_RTC - default y - help - A driver to retrieve wallclock time from an L4Re rtc server. - - For details on the configuration see device/l4rtc.cc - -comment "l4rtc time source not available due to missing rtc package" - depends on !HAVE_BIDPC_RTC - -comment "Device Emulation" - -config UVMM_VDEV_8250 - bool "8250-compatible UART" - default y - help - Emulate an 8250 compatible UART for the guest. - - For details on the configuration see device/uart_8250.cc - -config UVMM_VDEV_PL011 - bool "PL011 UART" - default y - help - Emulate a PrimeCell pl011-compatible UART for the guest. - - For details on the configuration see device/pl011.cc - -config UVMM_VDEV_PL031 - bool "PL031 RTC" - default y - depends on BUILD_ARCH_arm64 || BUILD_ARCH_arm - help - Emluate a simple PL0311 RTC for the guest. This is not a complete device - model and does not come with write support. - - For details on the configuration see device/arm/pl031.cc - -config UVMM_VDEV_DEVICE_PCI_HOST_ECAM_GENERIC - bool "ECAM PCIe host bridge support" - default y - depends on (BUILD_ARCH_arm || BUILD_ARCH_arm64) && UVMM_PCI_SUPPORT - help - Emulates a generic PCIe host bridge for ARM platforms. - -config UVMM_VDEV_DEVICE_FRAMEBUFFER - bool "Generic framebuffer device" - default y - help - Emulate a simple generic framebuffer device - -config UVMM_VDEV_CFI_FLASH - bool "CFI flash device" - default y - help - Emulate a simple CFI compliant flash device with the Intel command set. - - For details on the configuration see device/cfi.cc - -config UVMM_VDEV_ISA_DEBUG_PORT - bool "Bochs debug port" - default y - depends on BUILD_ARCH_amd64 - help - Emulate the BOCHS debug IO-port (0x402) to enable guests to print on the - vcon device. - - For details on the configuration see ARCH-amd64/isa_debugport.cc - -config UVMM_VDEV_BCM2835_MBOX - bool "Support for external bcm2835 mailbox service" - depends on BUILD_ARCH_arm || BUILD_ARCH_arm64 - help - Emulate the bcm2835 mailbox device as found on Raspberry Pi 4. - -config UVMM_VDEV_GIC_V2 - def_bool UVMM_VDEV_SEL_GIC_V2 || UVMM_VDEV_SEL_GIC_BOTH - -config UVMM_VDEV_GIC_V3 - def_bool UVMM_VDEV_SEL_GIC_V3 || UVMM_VDEV_SEL_GIC_BOTH - -choice - prompt "GIC Support" - depends on BUILD_ARCH_arm || BUILD_ARCH_arm64 - help - Select which GIC emulations uvmm should support for the virtual interrupt - controller. - -config UVMM_VDEV_SEL_GIC_BOTH - bool "GICv2 + GICv3" - -config UVMM_VDEV_SEL_GIC_V2 - bool "GICv2" - -config UVMM_VDEV_SEL_GIC_V3 - bool "GICv3" - -endchoice - -config UVMM_VDEV_GIC_ITS - bool "Emulate ITS in GICv3 to support MSIs" - depends on UVMM_VDEV_GIC_V3 - default y - -config UVMM_IRQ_DIRECT_INJECT - bool "Utilize direct guest vIRQ injection" - depends on BUILD_ARCH_arm || BUILD_ARCH_arm64 - default y - help - On Arm platforms, the kernel optionally supports forwarding hardware - interrupts directly to a guest. This reduces the interrupt latency - but the "pending" and "active" bits in the virtual distributor are - not updated any more. This usually does not pose any problem, though. - - It is safe to enable the feature in uvmm even if the kernel does not - support it. Uvmm will transparently fall back to regular, IPC based - interrupt forwarding. - -menuconfig UVMM_VDEV_VIRTIO - bool "Virtio driver/device support" - default y - -if UVMM_VDEV_VIRTIO - -config UVMM_VDEV_VIRTIO_CONSOLE - bool "Support forwarding vcon as virtio-console to the guest" - default y - -config UVMM_VDEV_VIRTIO_POWER - bool "Virtio-input based power events" - default y - help - Support sending power events via Virtio-input. - -config UVMM_VDEV_VIRTIO_INPUT - bool "Forward L4Re::Events via Virtio-input" - default y - help - Support forwarding input device events via Virtio-input. - -config UVMM_VDEV_VIRTIO_PROXY - bool "Support forwarding L4virtio devices to the guest" - default y - help - Support forwarding L4Re virtio devices to the guest. This enables - guests to use L4Re drivers e.g., block devices or virtual network - bridges. - - If unsure, say Y. - -config UVMM_VDEV_DEVICE_PROXY - bool "Virtio device proxy" - default y - help - Proxy for virtio devices implemented in the guest. Can be used to export - devices driven by a guest using the virtio protocol. - - For details on the configuration see device/virtio_device_proxy.cc - -endif - -endmenu diff --git a/src/l4/pkg/uvmm/LICENSE.spdx b/src/l4/pkg/uvmm/LICENSE.spdx deleted file mode 100644 index 0d7eb552..00000000 --- a/src/l4/pkg/uvmm/LICENSE.spdx +++ /dev/null @@ -1,47 +0,0 @@ -## This file states the license of this package and possibly its subpackages -## in machine and human readable format. The PackageName refers to the package -## whose license is defined by PackageLicenseConcluded. -## For more information about this file format visit the SPDX website at -## https://spdx.org - -SPDXVersion: SPDX-2.3 -DataLicense: CC0-1.0 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: spdx:kernkonzept/uvmm-c9ac5a16-e7f6-11e8-9023-e32cdff45c32 -DocumentName: uvmm -Creator: Organization: Kernkonzept GmbH (info@kernkonzept.com) -Created: 2018-11-13T00:00:00Z - -## Package Information -PackageName: uvmm -SPDXID: SPDXRef-uvmm -PackageOriginator: Organization: Kernkonzept GmbH (info@kernkonzept.com) -PackageLicenseDeclared: GPL-2.0-only -PackageLicenseConcluded: GPL-2.0-only -FilesAnalyzed: true -PackageCopyrightText: NOASSERTION -PackageDownloadLocation: NOASSERTION - -FileName: ./configs/dts/ls1021a-twr.dts -SPDXID: SPDXRef-dts-ls1021a-twr-dts -LicenseConcluded: GPL-2.0-only -LicenseInfoInFile: NOASSERTION -FileCopyrightText: NOASSERTION - -FileName: ./configs/dts/ls1021a.dtsi -SPDXID: SPDXRef-dts-ls1021a-dtsi -LicenseConcluded: GPL-2.0-only -LicenseInfoInFile: NOASSERTION -FileCopyrightText: NOASSERTION - -FileName: ./configs/dts/include/dt-bindings/interrupt-controller/irq.h -SPDXID: SPDXRef-dts-irq-h -LicenseConcluded: GPL-2.0-only OR MIT -LicenseInfoInFile: NOASSERTION -FileCopyrightText: NOASSERTION - -FileName: ./configs/dts/include/dt-bindings/interrupt-controller/arm-gic.h -SPDXID: SPDXRef-dts-arm-gic-h -LicenseConcluded: GPL-2.0-only OR MIT -LicenseInfoInFile: NOASSERTION -FileCopyrightText: NOASSERTION diff --git a/src/l4/pkg/uvmm/Makefile b/src/l4/pkg/uvmm/Makefile deleted file mode 100644 index 4f6f0177..00000000 --- a/src/l4/pkg/uvmm/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -PKGDIR = . -L4DIR ?= $(PKGDIR)/../.. - -TARGET = server configs tools - -include $(L4DIR)/mk/subdir.mk diff --git a/src/l4/pkg/uvmm/README.md b/src/l4/pkg/uvmm/README.md deleted file mode 100644 index 8ab2ee98..00000000 --- a/src/l4/pkg/uvmm/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# L4Re uvmm - -uvmm is the virtual machine monitor for the L4Re operating system. It -allows to configure and execute guest OSes on top of L4Re. It provides -a number of virtual interfaces to the guest, so that it can interact with -L4 components in a secure way. - -# Documentation - -This package is part of the L4Re operating system. For documentation and -build instructions see the -[L4Re wiki](https://kernkonzept.com/L4Re/guides/l4re). - -# Contributions - -We welcome contributions. Please see our contributors guide on -[how to contribute](https://kernkonzept.com/L4Re/contributing/l4re). - -# License - -Detailed licensing and copyright information can be found in -the [LICENSE](LICENSE.spdx) file. diff --git a/src/l4/pkg/uvmm/SECURITY.md b/src/l4/pkg/uvmm/SECURITY.md deleted file mode 100644 index dbbc5904..00000000 --- a/src/l4/pkg/uvmm/SECURITY.md +++ /dev/null @@ -1,29 +0,0 @@ -# Security Policy - -This document outlines security procedures for the open-source projects of the -L4Re Operating System Framework as found on https://github.com/kernkonzept. - -# Reporting a vulnerability - -Security is very important to us and we take all security vulnerabilities -seriously. Thank you for improving the security of our open source software. If -you have discovered a security issue, we appreciate your efforts and your -responsible disclosure. - -Please report a security vulnerability by sending an encrypted email to our -security team using our [public -key](https://www.kernkonzept.com/dl/security-at-kernkonzept.pub) -to **security@kernkonzept.com**. The fingerprint of our public key is - -```` -C4DC 2909 A22E D080 C012 5373 4055 CBA2 A4FD 855B -```` - -Please include the following in your report: - -* A description of the vulnerability -* Steps to reproduce the vulnerability - -A member of Kernkonzept's security team will confirm the vulnerability, -determine its impact, and develop a fix. The fix will be applied to the master -branch, tested, and released. diff --git a/src/l4/pkg/uvmm/configs/Makefile b/src/l4/pkg/uvmm/configs/Makefile deleted file mode 100644 index b9484ebf..00000000 --- a/src/l4/pkg/uvmm/configs/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -PKGDIR ?= .. -L4DIR ?= $(PKGDIR)/../.. - -SRC_ASSETS_MODLIST = modules.list -SRC_ASSETS_NED = vmm.lua uvmm.ned - -SUBDIRS += dts - -all:: $(SUBDIRS) - -include $(L4DIR)/mk/assets.mk diff --git a/src/l4/pkg/uvmm/configs/dts/Makefile b/src/l4/pkg/uvmm/configs/dts/Makefile deleted file mode 100644 index 3a4b96ab..00000000 --- a/src/l4/pkg/uvmm/configs/dts/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -PKGDIR ?= ../.. -L4DIR ?= $(PKGDIR)/../.. - -include $(L4DIR)/mk/Makeconf - -ASSET_TYPE = dtb -SRC_DTS = $(subst $(SRC_DIR)/,,$(wildcard $(SRC_DIR)/*.dts $(SRC_DIR)/*.dtso)) -PRIVATE_INCDIR = $(PKGDIR)/configs/dts/include $(PKGDIR)/configs/dts -DTC_FLAGS := $(call checkdtc,-Wno-unit_address_vs_reg) \ - $(call checkdtc,-Wno-simple_bus_reg) \ - $(call checkdtc,-Wno-spi_bus_bridge) \ - $(call checkdtc,-Wno-alias_paths) \ - $(call checkdtc,-@) - -clean:: - $(VERBOSE)$(RM) $(wildcard *.dtb *.dtbo) - -include $(L4DIR)/mk/assets.mk diff --git a/src/l4/pkg/uvmm/configs/dts/ic-arm.dtsi b/src/l4/pkg/uvmm/configs/dts/ic-arm.dtsi deleted file mode 100644 index fefa0ae5..00000000 --- a/src/l4/pkg/uvmm/configs/dts/ic-arm.dtsi +++ /dev/null @@ -1,21 +0,0 @@ -/* - * GIC for ARM guests. - */ - -/ { - icsoc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - gic: interrupt-controller { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0x1000 0x1000>, - <0x2000 0x100>; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/ic-mips.dtsi b/src/l4/pkg/uvmm/configs/dts/ic-mips.dtsi deleted file mode 100644 index 032ef408..00000000 --- a/src/l4/pkg/uvmm/configs/dts/ic-mips.dtsi +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Basic interrupt controllers for MIPS: core IC and GIC. - */ - - -/ { - cpu_intc: cpu_intc { - #address-cells = <0>; - compatible = "mti,cpu-interrupt-controller"; - - interrupt-controller; - #interrupt-cells = <1>; - }; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - gic: interrupt-controller { - compatible = "mti,gic"; - - reg = <0x1bdc0000 0x20000>; - - mti,reserved-cpu-vectors = <7>; - - interrupt-controller; - #interrupt-cells = <3>; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/arm-gic.h b/src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/arm-gic.h deleted file mode 100644 index 35b6f69b..00000000 --- a/src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/arm-gic.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR MIT */ -/* - * This header provides constants for the ARM GIC. - */ - -#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H -#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H - -#include - -/* interrupt specifier cell 0 */ - -#define GIC_SPI 0 -#define GIC_PPI 1 - -/* - * Interrupt specifier cell 2. - * The flags in irq.h are valid, plus those below. - */ -#define GIC_CPU_MASK_RAW(x) ((x) << 8) -#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) - -#endif diff --git a/src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/irq.h b/src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/irq.h deleted file mode 100644 index 9e3d183e..00000000 --- a/src/l4/pkg/uvmm/configs/dts/include/dt-bindings/interrupt-controller/irq.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR MIT */ -/* - * This header provides constants for most IRQ bindings. - * - * Most IRQ bindings include a flags cell as part of the IRQ specifier. - * In most cases, the format of the flags cell uses the standard values - * defined in this header. - */ - -#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H -#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H - -#define IRQ_TYPE_NONE 0 -#define IRQ_TYPE_EDGE_RISING 1 -#define IRQ_TYPE_EDGE_FALLING 2 -#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) -#define IRQ_TYPE_LEVEL_HIGH 4 -#define IRQ_TYPE_LEVEL_LOW 8 - -#endif diff --git a/src/l4/pkg/uvmm/configs/dts/pl031_overlay.dtso b/src/l4/pkg/uvmm/configs/dts/pl031_overlay.dtso deleted file mode 100644 index f5de4445..00000000 --- a/src/l4/pkg/uvmm/configs/dts/pl031_overlay.dtso +++ /dev/null @@ -1,38 +0,0 @@ -/dts-v1/; -/plugin/; - -/** - * Example overlay for use of the PL031 real-time clock. - * It also adds a node to connect uvmm to the L4Re RTC service, make sure to - * provide this cap to uvmm in your ned script. - */ - -/ { - - fragment@0 { - target-path = "/"; - __overlay__ { - l4vmm { - l4rtc { - compatible = "l4rtc"; - l4vmm,rtccap = "rtc"; - }; - - virt_pl031 { - compatible = "arm,pl031", "arm,primecell"; - reg = <0x13000 0x1000>; - interrupts = <0x00 0x02 0x04>; - clocks = <&apb_dummy_pclk>; - clock-names = "apb_pclk"; - }; - - apb_dummy_pclk: dummy_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <1000000>; - }; - }; - }; - }; - -}; diff --git a/src/l4/pkg/uvmm/configs/dts/skeleton.dtsi b/src/l4/pkg/uvmm/configs/dts/skeleton.dtsi deleted file mode 100644 index ba0f67ef..00000000 --- a/src/l4/pkg/uvmm/configs/dts/skeleton.dtsi +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Skeleton device tree; the bare minimum needed to boot; just include and - * add a compatible value. The bootloader will typically populate the memory - * node. - */ - -/ { - #address-cells = <1>; - #size-cells = <1>; - chosen { }; - aliases { }; - cpus { }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/skeleton64.dtsi b/src/l4/pkg/uvmm/configs/dts/skeleton64.dtsi deleted file mode 100644 index 751af88c..00000000 --- a/src/l4/pkg/uvmm/configs/dts/skeleton64.dtsi +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Skeleton device tree in the 64 bits version; the bare minimum - * needed to boot; just include and add a compatible value. The - * bootloader will typically populate the memory node. - */ - -/ { - #address-cells = <2>; - #size-cells = <2>; - chosen { }; - aliases { }; - cpus { }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/syscon.dtsi b/src/l4/pkg/uvmm/configs/dts/syscon.dtsi deleted file mode 100644 index e735aa08..00000000 --- a/src/l4/pkg/uvmm/configs/dts/syscon.dtsi +++ /dev/null @@ -1,33 +0,0 @@ -/** - * L4 uvmm system management console. Provides reboot and poweroff hooks - * towards the vmm. - */ - -/ { - vmm-syscon { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges = <0x0 0x30030000 0x4>; - - l4syscon: syscon { - compatible = "syscon", "syscon-l4vmm"; - reg = <0x0 0x4>; - little-endian; - }; - - reboot { - compatible = "syscon-reboot"; - regmap = <&l4syscon>; - offset = <0x0>; - mask = <0x66>; - }; - - poweroff { - compatible = "syscon-poweroff"; - regmap = <&l4syscon>; - offset = <0x0>; - mask = <0x0>; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-arm_sbsa.dts b/src/l4/pkg/uvmm/configs/dts/virt-arm_sbsa.dts deleted file mode 100644 index cb7fe7cb..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-arm_sbsa.dts +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Example device tree for a virtual machine on Arm SBSA compliant systems. It - * provides MSIs and PCI hardware pass-though capabilities. - */ - -/dts-v1/; -/include/ "skeleton64.dtsi" -/include/ "vmm-devices-arm.dtsi" - -#define CPU(x, r) cpu##x: cpu@x { \ - device_type = "cpu"; \ - compatible = "arm,armv8"; \ - reg = ; \ - enable-method = "psci"; \ - } - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - interrupt-parent = <&gic>; - - memory@0 { - device_type = "memory"; - // Ram starts at 4GiB to make room for virtual devices. Currently, io - // will map the ITS somewhere after 0xf0000000 so there should be no - // RAM at this location. Size will be updated by uvmm based on ds size. - reg = <0x1 0x00000000 0 0x0>; - l4vmm,dscap = "ram"; - }; - - icsoc { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* Dist/Redist interface for gicv3 (0x10000, 0x20000 * number of CPUs). - * The entries provided here support up to 32 CPUs. - */ - gic: interrupt-controller { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - #address-cells = <2>; - #size-cells = <2>; - ranges; - interrupt-controller; - reg = <0 0x40000 0 0x10000>, // GICD - <0 0x50000 0 0x400000>; // GICR - }; - - its: msi-controller@500000 { - #msi-cells = <1>; - compatible = "arm,gic-v3-its"; - reg = <0x0 0x500000 0x0 0x20000>; // GITS - msi-controller; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = <1 13 0xf08>, - <1 14 0xf08>, - <1 11 0xf08>, - <1 10 0xf08>; - always-on; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - // Beware: the Aff0 field must be in the [0..15] range! - CPU( 0, 0x0000); - CPU( 1, 0x0001); - CPU( 2, 0x0002); - CPU( 3, 0x0003); - CPU( 4, 0x0004); - CPU( 5, 0x0005); - CPU( 6, 0x0006); - CPU( 7, 0x0007); - CPU( 8, 0x0008); - CPU( 9, 0x0009); - CPU(10, 0x000a); - CPU(11, 0x000b); - CPU(12, 0x000c); - CPU(13, 0x000d); - CPU(14, 0x000e); - CPU(15, 0x000f); - CPU(16, 0x0100); - CPU(17, 0x0101); - CPU(18, 0x0102); - CPU(19, 0x0103); - CPU(20, 0x0104); - CPU(21, 0x0105); - CPU(22, 0x0106); - CPU(23, 0x0107); - CPU(24, 0x0108); - CPU(25, 0x0109); - CPU(26, 0x010a); - CPU(27, 0x010b); - CPU(28, 0x010c); - CPU(29, 0x010d); - CPU(30, 0x010e); - CPU(31, 0x010f); - }; - - pcie@10000000 { - // Interrupt map for any number of devices. Legacy interrupts are - // interwoven based on the two device number LSBs. Uvmm supports only - // one bus... - interrupt-map-mask = <0x1800 0x00 0x00 0x07>; - - // Interrupt cell (SPI / line / LEVEL triggered) -+ - // GIC #address-cells (ignored) --+ | - // GIC phandle -----------+ | | - // PCI interrupt pin -+ | | | - // | | | | - // PCI address | | | | - // ---------------- --+- -+-- ----+---- ----------+--- - interrupt-map = < - 0x0000 0x00 0x00 0x01 &gic 0x00 0x00 0x00 0x83 0x04 - 0x0000 0x00 0x00 0x02 &gic 0x00 0x00 0x00 0x84 0x04 - 0x0000 0x00 0x00 0x03 &gic 0x00 0x00 0x00 0x85 0x04 - 0x0000 0x00 0x00 0x04 &gic 0x00 0x00 0x00 0x86 0x04 - 0x0800 0x00 0x00 0x01 &gic 0x00 0x00 0x00 0x84 0x04 - 0x0800 0x00 0x00 0x02 &gic 0x00 0x00 0x00 0x85 0x04 - 0x0800 0x00 0x00 0x03 &gic 0x00 0x00 0x00 0x86 0x04 - 0x0800 0x00 0x00 0x04 &gic 0x00 0x00 0x00 0x83 0x04 - 0x1000 0x00 0x00 0x01 &gic 0x00 0x00 0x00 0x85 0x04 - 0x1000 0x00 0x00 0x02 &gic 0x00 0x00 0x00 0x86 0x04 - 0x1000 0x00 0x00 0x03 &gic 0x00 0x00 0x00 0x83 0x04 - 0x1000 0x00 0x00 0x04 &gic 0x00 0x00 0x00 0x84 0x04 - 0x1800 0x00 0x00 0x01 &gic 0x00 0x00 0x00 0x86 0x04 - 0x1800 0x00 0x00 0x02 &gic 0x00 0x00 0x00 0x83 0x04 - 0x1800 0x00 0x00 0x03 &gic 0x00 0x00 0x00 0x84 0x04 - 0x1800 0x00 0x00 0x04 &gic 0x00 0x00 0x00 0x85 0x04 - >; - #interrupt-cells = <0x01>; - - // The bridge windows (IO, MEM32, MEM64). We still have to officially map - // x86 ports because real hardware provides such BARs even though they - // won't be used on Arm. - ranges = <0x01000000 0x00 0x00000000 0x00 0x00000000 0x00 0x10000 - 0x02000000 0x00 0x40000000 0x00 0x40000000 0x00 0x30000000 - 0x43000000 0xc0 0x00000000 0xc0 0x00000000 0x10 0x00000000>; - reg = <0x0 0x10000000 0x00 0x10000000>; - msi-map = <0 &its 0 0x10000>; - dma-coherent; - bus-range = <0x00 0xff>; - #address-cells = <0x03>; - #size-cells = <0x02>; - device_type = "pci"; - compatible = "pci-host-ecam-generic"; - }; - - l4vmm { - ranges = <0x0 0x0 0x10000 0x21000>; - }; - - psci { - compatible = "arm,psci-1.0"; - method = "hvc"; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-32.dts b/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-32.dts deleted file mode 100644 index 83d5eb93..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-32.dts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Device tree for a virtual machine without any hardware pass-through. - */ - -/dts-v1/; -/include/ "skeleton.dtsi" -/include/ "vmm-devices-arm.dtsi" - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - interrupt-parent = <&gic>; - - memory@0 { - device_type = "memory"; - // Ram starts at 128MB - // Size will be updated by uvmm based on ds size - reg = <0x8000000 0x0>; - l4vmm,dscap = "ram"; - }; - - icsoc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x40000 0x100000>; - - /* Uvmm will adapt the compatible string depending on the present gic - * version. It expects reg entries that provide enough space for the - * Cpu/Dist interface for gicv2 (at least 0x1000, 0x1000) or the - * Dist/Redist interface for gicv3 (0x10000, 0x20000 * number of CPUs). - * The entries provided here support any gicv2 setup or a gicv3 setup - * with up to 4 CPUs. - */ - gic: interrupt-controller { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0x10000 0x10000>, - <0x20000 0x80000>; - }; - }; - - timer { - compatible = "arm,armv7-timer"; - interrupts = <1 13 0xf08>, - <1 14 0xf08>, - <1 11 0xf08>, - <1 10 0xf08>; - always-on; - }; - - cpus { - #address-cells = <2>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,armv7"; - reg = <0x0 0x0>; - enable-method = "psci"; - }; - - cpu@1 { - device_type = "cpu"; - compatible = "arm,armv7"; - reg = <0x0 0x1>; - enable-method = "psci"; - }; - - cpu@2 { - device_type = "cpu"; - compatible = "arm,armv7"; - reg = <0x0 0x2>; - enable-method = "psci"; - }; - - cpu@3 { - device_type = "cpu"; - compatible = "arm,armv7"; - reg = <0x0 0x3>; - enable-method = "psci"; - }; - }; - - l4vmm { - ranges = <0x0 0x10000 0x21000>; - }; - - psci { - compatible = "arm,psci-1.0"; - method = "hvc"; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64.dts b/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64.dts deleted file mode 100644 index 3662a65c..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64.dts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Device tree for a virtual machine without any hardware pass-through. - */ - -/dts-v1/; -/include/ "skeleton64.dtsi" -/include/ "vmm-devices-arm.dtsi" - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - interrupt-parent = <&gic>; - - memory@0 { - device_type = "memory"; - // Ram starts at 128MB - // Size will be updated by uvmm based on ds size - reg = <0 0x8000000 0 0x0>; - l4vmm,dscap = "ram"; - }; - - icsoc { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* Uvmm will adapt the compatible string depending on the present gic - * version. It expects reg entries that provide enough space for the - * Cpu/Dist interface for gicv2 (at least 0x1000, 0x1000) or the - * Dist/Redist interface for gicv3 (0x10000, 0x20000 * number of CPUs). - * The entries provided here support any gicv2 setup or a gicv3 setup - * with up to 32 CPUs. - */ - gic: interrupt-controller { - compatible = "arm,gic-400", "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0 0x40000 0 0x10000>, - <0 0x50000 0 0x400000>; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = <1 13 0xf08>, - <1 14 0xf08>, - <1 11 0xf08>, - <1 10 0xf08>; - always-on; - }; - - cpus { - #address-cells = <2>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x0>; - enable-method = "psci"; - }; - cpu@1 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x1>; - enable-method = "psci"; - }; - cpu@2 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x2>; - enable-method = "psci"; - }; - cpu@3 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x3>; - enable-method = "psci"; - }; - }; - - l4vmm { - ranges = <0x0 0x0 0x10000 0x21000>; - }; - - psci { - compatible = "arm,psci-1.0"; - method = "hvc"; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64_pci.dtso b/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64_pci.dtso deleted file mode 100644 index a4e3b582..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-arm_virt-64_pci.dtso +++ /dev/null @@ -1,42 +0,0 @@ -/dts-v1/; -/plugin/; - -/ { - - fragment@0 { - target-path = "/pcie@10000000"; - __overlay__ { - ranges = <0x1000000 0x00 0x00000000 0x00 0x3eff0000 0x00 0x00010000 - 0x2000000 0x00 0x10000000 0x00 0x10000000 0x00 0x2eff0000 - 0x3000000 0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>; - }; - }; - - fragment@1 { - target-path = "/"; - __overlay__ { - l4vmm { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges = <0x0 0x0 0x30000000 0x21000>; - - virtio_uart@20000 { - compatible = "virtio,mmio"; - reg = <0x20000 0x100>; - interrupts = <0 122 4>; - l4vmm,vdev = "console"; - }; - - virtio_net@10000 { - compatible = "virtio,mmio"; - reg = <0x10000 0x200>; - interrupts = <0 123 4>; - l4vmm,vdev = "proxy"; - l4vmm,virtiocap = "net"; - }; - }; - }; - }; - -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-armada37xx.dts b/src/l4/pkg/uvmm/configs/dts/virt-armada37xx.dts deleted file mode 100644 index f8c35943..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-armada37xx.dts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Device tree for a virtual machine without any hardware pass-through. - */ - -/dts-v1/; -/include/ "skeleton.dtsi" -/include/ "syscon.dtsi" -/include/ "vmm-devices-arm.dtsi" -#include - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - interrupt-parent = <&gic>; - - gic: interrupt-controller@1d00000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-controller; - interrupts = ; - reg = <0x1d00000 0x10000>, /* GICD */ - <0x1d40000 0x40000>; /* GICR */ - }; - - timer { - compatible = "arm,cortex-a15-timer", "arm,armv7-timer"; - interrupts = <1 13 0xf08>, - <1 14 0xf08>, - <1 11 0xf08>, - <1 10 0xf08>; - always-on; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-exynos5.dts b/src/l4/pkg/uvmm/configs/dts/virt-exynos5.dts deleted file mode 100644 index 197a7919..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-exynos5.dts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Device tree for a virtual machine without any hardware pass-through. - */ - -/dts-v1/; -/include/ "skeleton.dtsi" -/include/ "syscon.dtsi" -/include/ "ic-arm.dtsi" -/include/ "vmm-devices-arm.dtsi" - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - interrupt-parent = <&gic>; - - icsoc { - ranges = <0x0 0x10480000 0x3000>; - }; - - timer { - compatible = "arm,cortex-a15-timer", "arm,armv7-timer"; - interrupts = <1 13 0xf08>, - <1 14 0xf08>, - <1 11 0xf08>, - <1 10 0xf08>; - always-on; - }; -}; - diff --git a/src/l4/pkg/uvmm/configs/dts/virt-mips32.dts b/src/l4/pkg/uvmm/configs/dts/virt-mips32.dts deleted file mode 100644 index 9fbcedbd..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-mips32.dts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Devic tree for purely virtual guests on the MIPS architecture. - */ - -/dts-v1/; - -/include/ "skeleton.dtsi" -/include/ "ic-mips.dtsi" -/include/ "vmm-devices-mips.dtsi" -/include/ "syscon.dtsi" - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - CPU0: cpu@0 { - device_type = "cpu"; - compatible = "mips,p5600"; - reg = <0x0>; - }; - - CPU1: cpu@1 { - device_type = "cpu"; - compatible = "mips,p5600"; - reg = <0x1>; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-mips64.dts b/src/l4/pkg/uvmm/configs/dts/virt-mips64.dts deleted file mode 100644 index cefa5c45..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-mips64.dts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Devic tree for purely virtual guests on the MIPS architecture. - */ - -/dts-v1/; - -/include/ "skeleton64.dtsi" -/include/ "ic-mips.dtsi" -/include/ "vmm-devices-mips.dtsi" -/include/ "syscon.dtsi" - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - CPU0: cpu@0 { - device_type = "cpu"; - compatible = "mips,i6400"; - reg = <0x0>; - }; - - CPU1: cpu@1 { - device_type = "cpu"; - compatible = "mips,i6400"; - reg = <0x1>; - }; - }; - - l4vmm { - ranges = <0x0 0x0 0x30000000 0x21000>; - }; - - soc { - ranges = <0x0 0x0 0x0 0xffffffff>; - }; - - vmm-syscon { - ranges = <0x0 0x0 0x30030000 0x4>; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-omap5.dts b/src/l4/pkg/uvmm/configs/dts/virt-omap5.dts deleted file mode 100644 index 9dfcf83f..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-omap5.dts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Device tree for a virtual machine without any hardware pass-through. - */ - -/dts-v1/; -/include/ "skeleton.dtsi" -/include/ "syscon.dtsi" -/include/ "ic-arm.dtsi" -/include/ "vmm-devices-arm.dtsi" - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - interrupt-parent = <&gic>; - - timer { - compatible = "arm,cortex-a15-timer", "arm,armv7-timer"; - interrupts = <1 13 0xf08>, - <1 14 0xf08>, - <1 11 0xf08>, - <1 10 0xf08>; - clock-frequency = <6144000>; - always-on; - }; - - icsoc { - ranges = <0x0 0x48210000 0x3000>; - }; -}; - diff --git a/src/l4/pkg/uvmm/configs/dts/virt-pc.dts b/src/l4/pkg/uvmm/configs/dts/virt-pc.dts deleted file mode 100644 index b6bc77e1..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-pc.dts +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Device tree for a virtual machine without any hardware pass-through. - * - * Information sources: - * https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.3 - * For PCI reg cell encoding: - * [1] https://www.devicetree.org/open-firmware/bindings/pci/pci2_1.pdf - * For (E)ISA reg cell encoding: - * [2] https://www.devicetree.org/open-firmware/bindings/isa/isa0_4d.ps - */ - -/dts-v1/; - -/include/ "skeleton64.dtsi" - -#define CPU(x) cpu##x: cpu@x { \ - device_type = "cpu"; \ - compatible = "virt-intel"; \ - reg = ; \ - } - -/ { - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - memory@0 { - device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000 - 0x1 0x00000000 0xffffffff 0x0>; - l4vmm,dscap = "ram"; - }; - - IOAPIC: ioapic { - compatible = "intel,ioapic"; - interrupt-controller; - msi-parent = <&msi_ctrl>; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - - msi_ctrl: msictrl { - compatible = "intel,msi-controller"; - msi-controller; - #msi-cells = <0>; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - CPU(0); - CPU(1); - CPU(2); - CPU(3); - CPU(4); - CPU(5); - CPU(6); - CPU(7); - CPU(8); - CPU(9); - CPU(10); - CPU(11); - CPU(12); - CPU(13); - CPU(14); - CPU(15); - CPU(16); - CPU(17); - CPU(18); - CPU(19); - CPU(20); - CPU(21); - CPU(22); - CPU(23); - CPU(24); - CPU(25); - CPU(26); - CPU(27); - CPU(28); - CPU(29); - CPU(30); - CPU(31); - }; - - pit { - compatible = "virt-pit"; - reg = <0x0 0x0 0x0 0x0>; - interrupt-parent = <&IOAPIC>; - interrupts = <0>; - }; - - acpi_platform { - compatible = "virt-acpi"; - interrupt-parent = <&IOAPIC>; - interrupts = <9>; - l4vmm,pwrinput = "acpi_pwr_input"; - }; - - acpi_timer { - compatible = "acpi-timer"; - }; - - rtc { - compatible = "virt-rtc"; - interrupt-parent = <&IOAPIC>; - interrupts = <8>; - reg = <0x0 0x0 0x0 0x0>; - }; - - uart8250 { - compatible = "ns8250", "uart,8250"; - reg = <0x0 0x0 0x0 0x0>; - interrupt-parent = <&IOAPIC>; - interrupts = <4>; - /* Redirecting to another vcon channel is possible: */ - /* l4vmm,vcon_cap = "uart"; */ - }; - - l4rtc { - compatible = "l4rtc"; - l4vmm,rtccap = "rtc"; - }; - - kvm_clock { - compatible = "kvm-clock"; - reg = <0x0 0x0 0x0 0x0>; - }; - - isa { - device_type = "eisa"; - #address-cells = <2>; - #size-cells = <1>; - // The first cell of a child nodes reg property encodes the - // following information. See the ISA bus device-tree binding [2] - // for more details: - // - // [2] 11-bit aliased (IOPORT only) - // [1] 10-bit aliased (IOPORT only) - // [0] 0=MMIO32, 1=IOPORT - // - // The standard ranges property defines the translation of child - // reg address entries into the parent address space. Effectively - // removes the upper word. For the purpose of the ISA translation, - // only bit [0] is considered of the first word. - ranges = <0x0 0x0 0x0 0x0 0xffffffff - 0x1 0x0 0x0 0x0 0x1000>; - - // example { - // reg = < 0x0 0xA0000 0x20000 // MMIO [0xA0000-0xBFFFF] - // 0x1 0x3C0 0x20 > // IO [0x3C0-0x3DF] - // } - - isa_debugport { - compatible = "l4vmm,isa-debugport"; - reg = <0x1 0x402 0x1>; - l4vmm,vcon_cap = "debug"; - }; - - qemu_fw_if { - compatible = "l4vmm,qemu-fw-cfg"; - l4vmm,kernel = ""; - l4vmm,ramdisk = ""; - l4vmm,cmdline = ""; - reg = <0x1 0x510 0x0c>; - }; - }; - - pci0: pci@aa000000 { - compatible = "virt-pci-bridge"; - device_type = "pci"; - interrupt-parent = <&IOAPIC>; - msi-parent = <&msi_ctrl>; - bus-range = <0x0 0xff>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - - // The first cell encodes the following information. See the PCI - // bus device-tree binding [1] for more details: - // - // [31] non-relocatable - // [30] prefetchable - // [29] aliased - // [25:24] 0=CFGSPACE, 1=IOPORT, 2=MMIO32, 3=MMIO64 - // [23:16] bus - // [15:11] device - // [10:8] function - // [7:0] register (used to indicate BAR register, e.g. 0x10) - // - // The standard ranges property defines the translation of child - // reg address entries into the parent address space. Effectively - // removes the upper word. For the purpose of the PCI translation, - // only bits [25:24] are considered of the first word. - // - // Attention: the ranges property is parsed by uvmm and by the - // firmware to detect the bridge windows! - ranges = <0x01000000 0x0 0x00006000 0x0 0x00006000 0x0 0x5000 - 0x02000000 0x0 0xaa000000 0x0 0xaa000000 0x0 0x10000000 - 0x03000000 0x3 0x00000000 0x3 0x00000000 0x1 0x00000000>; - - // ECAM MCFG window - reg = <0x00 0xb0000000 0x00 0x10000000>; - - // Every virtual device needs a cfgspace address as first reg - // entry. Currently uvmm will ignore the bus/device/function - // address, though. - - virtio_uart@0 { - compatible = "virtio,pci"; - // The register property is required to be structured as follows: - // reg 0: CFGSPACE address - // reg 1: BAR[0] MMIO memory region for the MSIX table: 2 pages. - // reg 2: BAR[1] IO port range for the device configuration. - // The address of all entries should be 0 because it's defined as - // *offset* from the associated BAR register. - reg = <0x00000000 0x0 0x0 0x0 0x0000 - 0x02000010 0x0 0x0 0x0 0x2000 - 0x01000014 0x0 0x0 0x0 0x80>; - msi-parent = <&msi_ctrl>; - l4vmm,vdev = "console"; - /* Emulated UART is used by default for best bring-up - * experience */ - status = "disabled"; - }; - - virtio_net@1 { - compatible = "virtio,pci"; - // The reg property requirements are described in virtio_uart. - reg = <0x00000800 0x0 0x0 0x0 0x0000 - 0x02000810 0x0 0x0 0x0 0x2000 - 0x01000814 0x0 0x0 0x0 0x80>; - msi-parent = <&msi_ctrl>; - l4vmm,virtiocap = "net"; - l4vmm,vdev = "proxy"; - }; - - virtio_disk@2 { - compatible = "virtio,pci"; - // The reg property requirements are described in virtio_uart. - reg = <0x00001000 0x0 0x0 0x0 0x0000 - 0x02001010 0x0 0x0 0x0 0x2000 - 0x01001014 0x0 0x0 0x0 0x100>; - msi-parent = <&msi_ctrl>; - l4vmm,virtiocap = "qdrv"; - l4vmm,vdev = "proxy"; - }; - }; - - rom@ffc84000 { - compatible = "l4vmm,rom"; - reg = <0x0 0xffc84000 0x0 0x37c000>; - l4vmm,dscap = "bios_code"; - }; - - nvm@ffc00000 { - compatible = "cfi-flash"; - reg = <0x0 0xffc00000 0x0 0x84000>; - l4vmm,dscap = "bios_vars"; - erase-size = <4>; - bank-width = <4>; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-riscv.dtsi b/src/l4/pkg/uvmm/configs/dts/virt-riscv.dtsi deleted file mode 100644 index 6e0bdcca..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-riscv.dtsi +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Device tree for purely virtual guests on the RISC-V architecture. - * - * Expects the RISCV_ISA macro to be defined when being included. - */ - -/include/ "vmm-devices-riscv.dtsi" -/include/ "syscon.dtsi" - -#define CPU(x) cpu##x: cpu@x { \ - device_type = "cpu"; \ - reg = ; \ - status = "okay"; \ - compatible = "riscv"; \ - riscv,isa = RISCV_ISA; \ - \ - cpu##x##_intc: interrupt-controller { \ - #interrupt-cells = <0x01>; \ - interrupt-controller; \ - compatible = "riscv,cpu-intc"; \ - }; \ - } - -#define EXT_INT_AT_CPU(x) &cpu##x##_intc 0x09 - -/ { - #address-cells = <2>; - #size-cells = <2>; - - model = "L4 VM"; - compatible = "l4,virt", "linux,dummy-virt"; - - chosen { - stdout-path = "uart0"; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - /* NOTE: If a CPU(n) is added here, a corresponding EXT_INT_AT_CPU(n) - must be added to interrupts-extended in the PLIC below. */ - CPU(0); - CPU(1); - CPU(2); - CPU(3); - }; - - soc { - #address-cells = <0x01>; - #size-cells = <0x01>; - compatible = "simple-bus"; - ranges = <0x0 0x0 0x0 0xffffffff>; - - /* Platform-Level Interrupt Controller (PLIC) */ - gic: interrupt-controller@c000000 { - reg = <0xc000000 0x4000000>; - /* PLIC triggers external interrupt at interrupt controller of CPUs. */ - interrupts-extended = ; - interrupt-controller; - compatible = "riscv,plic0"; - #interrupt-cells = <0x01>; - #address-cells = <0x00>; - }; - }; - - l4vmm { - ranges = <0x0 0x0 0x30000000 0x21000>; - }; - vmm-syscon { - ranges = <0x0 0x0 0x30030000 0x4>; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/virt-riscv32.dts b/src/l4/pkg/uvmm/configs/dts/virt-riscv32.dts deleted file mode 100644 index d5ba2bfb..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-riscv32.dts +++ /dev/null @@ -1,6 +0,0 @@ -/dts-v1/; - -/include/ "skeleton.dtsi" - -#define RISCV_ISA "rv32imafd" -#include "virt-riscv.dtsi" diff --git a/src/l4/pkg/uvmm/configs/dts/virt-riscv64.dts b/src/l4/pkg/uvmm/configs/dts/virt-riscv64.dts deleted file mode 100644 index 1356ec37..00000000 --- a/src/l4/pkg/uvmm/configs/dts/virt-riscv64.dts +++ /dev/null @@ -1,6 +0,0 @@ -/dts-v1/; - -/include/ "skeleton64.dtsi" - -#define RISCV_ISA "rv64imafd" -#include "virt-riscv.dtsi" diff --git a/src/l4/pkg/uvmm/configs/dts/vmm-devices-arm.dtsi b/src/l4/pkg/uvmm/configs/dts/vmm-devices-arm.dtsi deleted file mode 100644 index 44eddc18..00000000 --- a/src/l4/pkg/uvmm/configs/dts/vmm-devices-arm.dtsi +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Basic set of VMM virtual devices for ARM guests. - * - * * console device - * * network virtio proxy device - */ - -/ { - l4vmm { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges = <0x0 0x30000000 0x21000>; - - apb_dummy_pclk: dummy_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <1000000>; - }; - - uart0: pl011_uart@2000 { - compatible = "arm,primecell", "arm,pl011"; - reg = <0x2000 0x1000>; - interrupt-parent = <&gic>; - interrupts = <0 121 4>; - clocks = <&apb_dummy_pclk>; - clock-names = "apb_pclk"; - status = "okay"; - }; - - virtio_uart@3000 { - compatible = "virtio,mmio"; - reg = <0x3000 0x100>; - interrupt-parent = <&gic>; - interrupts = <0 122 4>; - l4vmm,vdev = "console"; - /* To be used instead of pl011 UART */ - status = "disabled"; - }; - - virtio_net@4000 { - compatible = "virtio,mmio"; - reg = <0x4000 0x200>; - interrupt-parent = <&gic>; - interrupts = <0 123 4>; - l4vmm,vdev = "proxy"; - l4vmm,virtiocap = "net"; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/vmm-devices-mips.dtsi b/src/l4/pkg/uvmm/configs/dts/vmm-devices-mips.dtsi deleted file mode 100644 index eee93e52..00000000 --- a/src/l4/pkg/uvmm/configs/dts/vmm-devices-mips.dtsi +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Basic set of VMM virtual devices for MIPS guests. - * - * * console device - * * network virtio proxy device - */ - -/ { - l4vmm { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges = <0x0 0x30000000 0x21000>; - - virtio_uart@20000 { - compatible = "virtio,mmio"; - reg = <0x20000 0x100>; - interrupt-parent = <&gic>; - interrupts = <0 3 4>; - l4vmm,vdev = "console"; - }; - - virtio_net@10000 { - compatible = "virtio,mmio"; - reg = <0x10000 0x200>; - interrupt-parent = <&gic>; - interrupts = <0 4 4>; - l4vmm,vdev = "proxy"; - l4vmm,virtiocap = "net"; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/dts/vmm-devices-riscv.dtsi b/src/l4/pkg/uvmm/configs/dts/vmm-devices-riscv.dtsi deleted file mode 100644 index 14f2c970..00000000 --- a/src/l4/pkg/uvmm/configs/dts/vmm-devices-riscv.dtsi +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Basic set of VMM virtual devices for RISC-V guests. - * - * * console device - * * network virtio proxy device - */ - -/ { - l4vmm { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges = <0x0 0x30000000 0x21000>; - - uart0: ns16550a_uart@2000 { - compatible = "ns16550a"; - reg = <0x2000 0x100>; - interrupt-parent = <&gic>; - interrupts = <0x01>; - clock-frequency = <1000000>; - l4vmm,vdev = "console"; - /* Redirecting to another vcon channel is possible: */ - /* l4vmm,vcon_cap = "uart"; */ - }; - - virtio_uart@20000 { - compatible = "virtio,mmio"; - reg = <0x20000 0x100>; - interrupt-parent = <&gic>; - interrupts = <0x02>; - l4vmm,vdev = "console"; - /* Emulated UART is used by default for best bring-up experience */ - status = "disabled"; - }; - - virtio_net@10000 { - compatible = "virtio,mmio"; - reg = <0x10000 0x200>; - interrupt-parent = <&gic>; - interrupts = <0x03>; - l4vmm,vdev = "proxy"; - l4vmm,virtiocap = "net"; - l4vmm,no-notify = <1>; - }; - }; -}; diff --git a/src/l4/pkg/uvmm/configs/guests/Linux/amd64/0001-L4Re-UVMM-early_printk-patch-l4re-uvmm-virt.config-f.patch b/src/l4/pkg/uvmm/configs/guests/Linux/amd64/0001-L4Re-UVMM-early_printk-patch-l4re-uvmm-virt.config-f.patch deleted file mode 100644 index abb687d0..00000000 --- a/src/l4/pkg/uvmm/configs/guests/Linux/amd64/0001-L4Re-UVMM-early_printk-patch-l4re-uvmm-virt.config-f.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 247e6cca1bbfcd1cc8442d3f0e4cc359d9453550 Mon Sep 17 00:00:00 2001 -From: Philipp Eppelt -Date: Thu, 6 Apr 2017 14:34:45 +0200 -Subject: [PATCH] L4Re UVMM: early_printk patch & l4re-uvmm-virt.config for - amd64 - ---- - arch/x86/configs/l4re-uvmm-virt.config | 21 +++++++++++++++++++++ - arch/x86/kernel/early_printk.c | 19 +++++++++++++++++++ - 2 files changed, 40 insertions(+) - create mode 100644 arch/x86/configs/l4re-uvmm-virt.config - -diff --git a/arch/x86/configs/l4re-uvmm-virt.config b/arch/x86/configs/l4re-uvmm-virt.config -new file mode 100644 -index 0000000..6c2e94f ---- /dev/null -+++ b/arch/x86/configs/l4re-uvmm-virt.config -@@ -0,0 +1,21 @@ -+CONFIG_KERNEL_XZ=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_CC_STACKPROTECTOR_REGULAR=y -+CONFIG_PCI_MSI=y -+CONFIG_OF=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=16384 -+CONFIG_VIRTIO_BLK=y -+CONFIG_SERIO_RAW=y -+CONFIG_VT_HW_CONSOLE_BINDING=y -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_HW_RANDOM_VIRTIO=y -+CONFIG_VIRTIO_PCI=y -+# CONFIG_VIRTIO_PCI_LEGACY is not set -+CONFIG_VIRTIO_INPUT=y -+CONFIG_EXT3_FS=y -+CONFIG_TMPFS=y -+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 -+CONFIG_DEBUG_FS=y -+CONFIG_STACKTRACE=y -+CONFIG_MEMTEST=y -diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c -index 8a12199..2639abb 100644 ---- a/arch/x86/kernel/early_printk.c -+++ b/arch/x86/kernel/early_printk.c -@@ -316,6 +316,21 @@ static struct console early_serial_console = { - .index = -1, - }; - -+static void early_vmcall_write(struct console *con, const char *s, unsigned n) -+{ -+ while (*s && n-- > 0) { -+ asm("vmcall" : : "a"(0), "c"(*s)); -+ s++; -+ } -+} -+ -+static struct console early_vmcall_console = { -+ .name = "earlvmcall", -+ .write = early_vmcall_write, -+ .flags = CON_PRINTBUFFER, -+ .index = -1, -+}; -+ - static void early_console_register(struct console *con, int keep_early) - { - if (con->index != -1) { -@@ -344,6 +359,10 @@ static int __init setup_early_printk(char *buf) - keep = (strstr(buf, "keep") != NULL); - - while (*buf != '\0') { -+ if (!strncmp(buf, "vmcall", 6)) { -+ buf += 6; -+ early_console_register(&early_vmcall_console, keep); -+ } - if (!strncmp(buf, "serial", 6)) { - buf += 6; - early_serial_init(buf); --- -2.9.4 - diff --git a/src/l4/pkg/uvmm/configs/guests/Linux/arm/README b/src/l4/pkg/uvmm/configs/guests/Linux/arm/README deleted file mode 100644 index d429d95c..00000000 --- a/src/l4/pkg/uvmm/configs/guests/Linux/arm/README +++ /dev/null @@ -1,60 +0,0 @@ - - -Do the following to compile a Linux to be used as a guest. - -Any recent Linux kernel as well as older ones are supposed work -out of the box with vanilla Linux, including 3.16 and also 4.4 -and more recent versions. - -Select the 'multi_v7_defconfig' config: - -$ make ARCH=arm CROSS_COMPILE=arm-linux- multi_v7_defconfig -$ make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig - -Enable at least: -CONFIG_VIRTIO_CONSOLE - -and probably some RAM disk support or similar. - -Beginners may also want to enable those: -DEBUG_LL -DEBUG_ICEDCC -EARLY_PRINTK - - -Build the kernel -$ make ARCH=arm CROSS_COMPILE=arm-linux- -j40 - -Then use arch/arm/boot/zImage - - -Use an appropriate device tree file from dts/ directory. - -IO configurations are in bsp/platform - - -Caveats with at least Linux 3.14.1, 3.15 and 3.16: - - With the multiplatform config enabling CONFIG_DEBUG_LL / - CONFIG_EARLY_PRINTK selects the PL0X1 debug UART because of some - (unfortunate?) settings in arch/arm/Kconfig.debug. Remove / modify the - CONFIG_DEBUG_UART_PL01X option in a way so that CONFIG_DEBUG_LL_INCLUDE - is set to debug/icedcc.S and also select CONFIG_DEBUG_ICEDCC - accordingly. If this is given, early-printk should work. - - The Linux boot code misses an 'ISB' instruction that might hit in your - setup. You'll be seeing unresolvable page-faults or other unusual - behavior if you hit it. The issue triggers depending on memory layout. - ---- a/arch/arm/boot/compressed/head.S -+++ b/arch/arm/boot/compressed/head.S -@@ -403,6 +403,7 @@ - tst r4, #1 - bleq cache_clean_flush - -+ isb - adr r0, BSYM(restart) - add r0, r0, r6 - mov pc, r0 - - According to the internet, a patch is floating around for this which - hopefully gets merged soon. - diff --git a/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.4.patch b/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.4.patch deleted file mode 100644 index afad07f4..00000000 --- a/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.4.patch +++ /dev/null @@ -1,603 +0,0 @@ -From babd3c04fbb493e1bb65f15fd5ae0cb032f99e52 Mon Sep 17 00:00:00 2001 -From: Sarah Hoffmann -Date: Mon, 8 Aug 2016 10:27:28 +0200 -Subject: [PATCH] MIPS: Add virtual platform - -This adds a virtual platform to use as a guest in VZ-enabled -virtualization environments. ---- - arch/mips/Kbuild.platforms | 1 + - arch/mips/Kconfig | 28 ++++++ - arch/mips/configs/mach_virt_defconfig | 11 +++ - .../include/asm/mach-virt/cpu-feature-overrides.h | 15 +++ - arch/mips/include/asm/mach-virt/dma-coherence.h | 102 +++++++++++++++++++++ - arch/mips/include/asm/mach-virt/hypcall.h | 96 +++++++++++++++++++ - arch/mips/include/asm/timex.h | 6 +- - arch/mips/mach-virt/Makefile | 3 + - arch/mips/mach-virt/Platform | 9 ++ - arch/mips/mach-virt/dma.c | 53 +++++++++++ - arch/mips/mach-virt/early_printk.c | 13 +++ - arch/mips/mach-virt/irq.c | 17 ++++ - arch/mips/mach-virt/setup.c | 95 +++++++++++++++++++ - arch/mips/mm/c-r4k.c | 2 + - 14 files changed, 448 insertions(+), 3 deletions(-) - create mode 100644 arch/mips/configs/mach_virt_defconfig - create mode 100644 arch/mips/include/asm/mach-virt/cpu-feature-overrides.h - create mode 100644 arch/mips/include/asm/mach-virt/dma-coherence.h - create mode 100644 arch/mips/include/asm/mach-virt/hypcall.h - create mode 100644 arch/mips/mach-virt/Makefile - create mode 100644 arch/mips/mach-virt/Platform - create mode 100644 arch/mips/mach-virt/dma.c - create mode 100644 arch/mips/mach-virt/early_printk.c - create mode 100644 arch/mips/mach-virt/irq.c - create mode 100644 arch/mips/mach-virt/setup.c - -diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms -index a96c81d..f83c5b2 100644 ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -17,6 +17,7 @@ platforms += lantiq - platforms += lasat - platforms += loongson32 - platforms += loongson64 -+platforms += mach-virt - platforms += mti-malta - platforms += mti-sead3 - platforms += netlogic -diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig -index 71683a8..4677f89 100644 ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -481,6 +481,34 @@ config MIPS_MALTA - This enables support for the MIPS Technologies Malta evaluation - board. - -+config MIPS_VIRT -+ bool "MIPS virtual platform" -+ select HW_HAS_PCI -+ select BOOT_ELF32 -+ select BOOT_RAW -+ select CEVT_R4K -+ select CSRC_R4K -+ select COMMON_CLK -+ select IRQ_MIPS_CPU -+ select DMA_NONCOHERENT -+ select MIPS_GIC -+ select MIPS_CPU_SCACHE -+ select LIBFDT -+ select HW_HAS_PCI -+ select SMP_UP if SMP -+ select SWAP_IO_SPACE -+ select SYS_HAS_CPU_MIPS32_R2 -+ select SYS_HAS_CPU_MIPS32_R3_5 -+ select SYS_HAS_CPU_MIPS64_R6 -+ select SYS_HAS_EARLY_PRINTK -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_64BIT_KERNEL -+ select SYS_SUPPORTS_HIGHMEM -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SYS_SUPPORTS_MIPS_CPS -+ select SYS_SUPPORTS_SMARTMIPS -+ select USE_OF -+ - config MIPS_SEAD3 - bool "MIPS SEAD3 board" - select BOOT_ELF32 -diff --git a/arch/mips/configs/mach_virt_defconfig b/arch/mips/configs/mach_virt_defconfig -new file mode 100644 -index 0000000..20a0353 ---- /dev/null -+++ b/arch/mips/configs/mach_virt_defconfig -@@ -0,0 +1,11 @@ -+CONFIG_MIPS_VIRT=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_BLK_DEV_RAM=y -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_MOUSE_PS2 is not set -+# CONFIG_SERIO is not set -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_VIRTIO_MMIO=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -diff --git a/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h -new file mode 100644 -index 0000000..ded8a1a ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h -@@ -0,0 +1,14 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ */ -+#ifndef __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H -+#define __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H -+ -+#define cpu_has_maar 0 -+#define cpu_has_htw 0 -+#define cpu_has_dc_aliases 1 -+#define cpu_has_nan_legacy 1 -+ -+#endif /* __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H */ -diff --git a/arch/mips/include/asm/mach-virt/dma-coherence.h b/arch/mips/include/asm/mach-virt/dma-coherence.h -new file mode 100644 -index 0000000..a9a3661 ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/dma-coherence.h -@@ -0,0 +1,102 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+#pragma once -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern unsigned long l4vmm_gpa_start; -+extern unsigned long l4vmm_gpa_size; -+extern dma_addr_t l4vmm_dma_start; -+ -+struct device; -+ -+static inline dma_addr_t plat_map_gpa_to_dma(unsigned long gpa) -+{ -+ if (likely(l4vmm_gpa_size)) { -+ if (likely(l4vmm_gpa_start <= gpa -+ && gpa < l4vmm_gpa_start + l4vmm_gpa_size)) -+ return gpa - l4vmm_gpa_start + l4vmm_dma_start; -+ } -+ -+ pr_err("Failed to translate guest-physical 0x%lx to dma-addr\n", -+ gpa); -+ BUG(); /* What else? If not here we'll go chaos sooner anyway */ -+} -+ -+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, -+ size_t size) -+{ -+ return plat_map_gpa_to_dma(virt_to_phys(addr)); -+} -+ -+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, -+ struct page *page) -+{ -+ return plat_map_gpa_to_dma(page_to_phys(page)); -+} -+ -+static inline unsigned long plat_dma_addr_to_phys(struct device *dev, -+ dma_addr_t dma_addr) -+{ -+ if (likely(l4vmm_gpa_size)) { -+ if (likely(l4vmm_dma_start <= dma_addr -+ && dma_addr < l4vmm_dma_start + l4vmm_gpa_size)) -+ return dma_addr - l4vmm_dma_start + l4vmm_gpa_start; -+ } -+ -+ pr_err("%s: Do not know about dma_addr=%lx\n", __func__, -+ (unsigned long) dma_addr); -+ BUG(); -+} -+ -+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, -+ size_t size, enum dma_data_direction direction) -+{ -+ if (0) pr_warn("%s\n", __func__); -+} -+ -+static inline int plat_dma_supported(struct device *dev, u64 mask) -+{ -+ /* -+ * we fall back to GFP_DMA when the mask isn't all 1s, -+ * so we can't guarantee allocations that must be -+ * within a tighter range than GFP_DMA.. -+ */ -+ if (mask < DMA_BIT_MASK(24)) -+ return 0; -+ -+ return 1; -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+ return coherentio; -+} -+ -+#ifndef plat_post_dma_flush -+static inline void plat_post_dma_flush(struct device *dev) -+{ -+} -+#endif -+ -+#ifdef CONFIG_SWIOTLB -+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) -+{ -+ return plat_map_gpa_to_dma(paddr); -+} -+ -+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) -+{ -+ return daddr; -+} -+#endif -diff --git a/arch/mips/include/asm/mach-virt/hypcall.h b/arch/mips/include/asm/mach-virt/hypcall.h -new file mode 100644 -index 0000000..8a7e881 ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/hypcall.h -@@ -0,0 +1,96 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * (C) 2016 Kernkonzept GmbH, Adam Lackorzynski -+ */ -+#pragma once -+ -+enum { -+ L4VMM_FUNC_BASE = 0x160, -+ L4VMM_FUNC_PRINTCHAR = L4VMM_FUNC_BASE + 0, -+}; -+ -+static inline unsigned long -+l4vmm_hypcall1(unsigned func, unsigned long a0) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0) -+ : [func] "K" (func), -+ "0" (_a0) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall2(unsigned func, unsigned long a0, unsigned long a1) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = a1; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall2_ret(unsigned func, unsigned long a0, unsigned long *a1) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = *a1; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1) -+ : "cc", "memory"); -+ *a1 = _a1; -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall3(unsigned func, unsigned long a0, unsigned long a1, -+ unsigned long a2) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = a1; -+ register unsigned long _a2 asm ("a2") = a2; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1), -+ "=r" (_a2) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1), -+ "2" (_a2) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall3_ret(unsigned func, unsigned long a0, unsigned long *a1, -+ unsigned long *a2) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = *a1; -+ register unsigned long _a2 asm ("a2") = *a2; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1), -+ "=r" (_a2) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1), -+ "2" (_a2) -+ : "cc", "memory"); -+ *a1 = _a1; -+ *a2 = _a2; -+ return _a0; -+} -diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h -index b05bb70..3222504 100644 ---- a/arch/mips/include/asm/timex.h -+++ b/arch/mips/include/asm/timex.h -@@ -71,7 +71,7 @@ static inline int can_use_mips_counter(unsigned int prid) - - static inline cycles_t get_cycles(void) - { -- if (can_use_mips_counter(read_c0_prid())) -+ if (IS_ENABLED(CONFIG_MIPS_VIRT) || can_use_mips_counter(read_c0_prid())) - return read_c0_count(); - else - return 0; /* no usable counter */ -@@ -86,10 +86,10 @@ static inline cycles_t get_cycles(void) - */ - static inline unsigned long random_get_entropy(void) - { -- unsigned int prid = read_c0_prid(); -+ unsigned int prid = IS_ENABLED(CONFIG_MIPS_VIRT) ? 0 : read_c0_prid(); - unsigned int imp = prid & PRID_IMP_MASK; - -- if (can_use_mips_counter(prid)) -+ if (IS_ENABLED(CONFIG_MIPS_VIRT) || can_use_mips_counter(prid)) - return read_c0_count(); - else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A)) - return read_c0_random(); -diff --git a/arch/mips/mach-virt/Makefile b/arch/mips/mach-virt/Makefile -new file mode 100644 -index 0000000..bb4b020 ---- /dev/null -+++ b/arch/mips/mach-virt/Makefile -@@ -0,0 +1,3 @@ -+obj-y += setup.o irq.o dma.o -+ -+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -diff --git a/arch/mips/mach-virt/Platform b/arch/mips/mach-virt/Platform -new file mode 100644 -index 0000000..52ddca7 ---- /dev/null -+++ b/arch/mips/mach-virt/Platform -@@ -0,0 +1,9 @@ -+# -+# Virtual platform. -+# -+platform-$(CONFIG_MIPS_VIRT) += mach-virt/ -+cflags-$(CONFIG_MIPS_VIRT) += -I$(srctree)/arch/mips/include/asm/mach-virt -+ -+load-$(CONFIG_MIPS_VIRT) += 0xffffffff80100000 -+ -+all-$(CONFIG_MIPS_VIRT) := $(COMPRESSION_FNAME).bin -diff --git a/arch/mips/mach-virt/dma.c b/arch/mips/mach-virt/dma.c -new file mode 100644 -index 0000000..9d86a2e ---- /dev/null -+++ b/arch/mips/mach-virt/dma.c -@@ -0,0 +1,53 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+unsigned long l4vmm_gpa_start; -+unsigned long l4vmm_gpa_size; -+dma_addr_t l4vmm_dma_start; -+ -+/* For now, we just have a single contiguous physical region in the -+ * hypervisor */ -+static int __init mips_virt_dma_init(void) -+{ -+ struct device_node *np; -+ const __be32 *ranges = NULL; -+ int naddr, nsize, len; -+ -+ l4vmm_gpa_size = 0; -+ -+ np = of_find_node_by_name(NULL, "memory"); -+ if (!np) -+ return 0; -+ -+ naddr = of_n_addr_cells(np); -+ nsize = of_n_size_cells(np); -+ -+ ranges = of_get_property(np, "dma-ranges", &len); -+ -+ if (ranges && len >= (sizeof(*ranges) * (2 * naddr + nsize))) { -+ l4vmm_dma_start = of_read_number(ranges, naddr); -+ l4vmm_gpa_start = of_read_number(ranges + naddr, naddr); -+ l4vmm_gpa_size = of_read_number(ranges + 2 * naddr, nsize); -+ -+ pr_info("DMA range for memory 0x%lx - 0x%lx set @ 0x%lx\n", -+ l4vmm_gpa_start, -+ l4vmm_gpa_start + l4vmm_gpa_size, -+ (unsigned long) l4vmm_dma_start); -+ } -+ -+ return 0; -+} -+ -+fs_initcall(mips_virt_dma_init); -diff --git a/arch/mips/mach-virt/early_printk.c b/arch/mips/mach-virt/early_printk.c -new file mode 100644 -index 0000000..591ed45 ---- /dev/null -+++ b/arch/mips/mach-virt/early_printk.c -@@ -0,0 +1,13 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+#include -+ -+void prom_putchar(char c) -+{ -+ l4vmm_hypcall1(L4VMM_FUNC_PRINTCHAR, c); -+} -diff --git a/arch/mips/mach-virt/irq.c b/arch/mips/mach-virt/irq.c -new file mode 100644 -index 0000000..8a4c9ad ---- /dev/null -+++ b/arch/mips/mach-virt/irq.c -@@ -0,0 +1,17 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+#include -+#include -+ -+#include -+ -+void __init arch_init_irq(void) -+{ -+ irqchip_init(); -+} -diff --git a/arch/mips/mach-virt/setup.c b/arch/mips/mach-virt/setup.c -new file mode 100644 -index 0000000..4182221 ---- /dev/null -+++ b/arch/mips/mach-virt/setup.c -@@ -0,0 +1,95 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+const char *get_system_type(void) -+{ -+ return "MIPS Virtual Platform"; -+} -+ -+static void __init init_mips_cpu_timer(void) -+{ -+ struct device_node *np; -+ u32 freq; -+ -+ mips_hpt_frequency = 0; -+ -+ /* The timer frequency must be defined in the device tree. -+ If the definition is missing, we assume that the timer should -+ not be used. -+ */ -+ np = of_find_node_by_name(NULL, "cpus"); -+ if (np && of_property_read_u32(np, "mips-hpt-frequency", &freq) >= 0) { -+ mips_hpt_frequency = freq; -+ -+ printk("CPU frequency %d.%02d MHz\n", freq/1000000, -+ (freq%1000000)*100/1000000); -+ } else -+ pr_warn("MIPS CPU core timer not used. %p, %u\n", np, freq); -+ -+ of_node_put(np); -+} -+ -+void __init plat_time_init(void) -+{ -+ init_mips_cpu_timer(); -+} -+ -+void __init prom_init(void) -+{ -+ int i; -+ int argc = fw_arg0; -+ char **argv = (char **)fw_arg1; -+ -+ for (i = 0; i < argc; i++) { -+ strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE); -+ if (i < argc - 1) -+ strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); -+ } -+ -+ printk("DT at address %p\n", (void *)fw_arg3); -+ __dt_setup_arch((void *)fw_arg3); -+} -+ -+void __init plat_mem_setup(void) -+{ -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init device_tree_init(void) -+{ -+ unflatten_and_copy_device_tree(); -+} -+ -+static int __init publish_devices(void) -+{ -+ if (!of_have_populated_dt()) -+ return 0; -+ -+ if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)) -+ panic("Failed to populate DT"); -+ -+ return 0; -+} -+device_initcall(publish_devices); -diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c -index 5d3a25e..355e7c6 100644 ---- a/arch/mips/mm/c-r4k.c -+++ b/arch/mips/mm/c-r4k.c -@@ -1505,9 +1505,11 @@ static void setup_scache(void) - way_string[c->scache.ways], c->scache.linesz); - } - #else -+#ifndef CONFIG_MIPS_VIRT - if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT)) - panic("Dunno how to handle MIPS32 / MIPS64 second level cache"); - #endif -+#endif - return; - } - sc_present = 0; --- -2.1.4 - diff --git a/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.8.patch b/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.8.patch deleted file mode 100644 index db03c989..00000000 --- a/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.8.patch +++ /dev/null @@ -1,603 +0,0 @@ -From f7b2513f5b82ee9966c2ba56bb8e35e185e5db57 Mon Sep 17 00:00:00 2001 -From: Sarah Hoffmann -Date: Wed, 7 Dec 2016 11:53:15 +0100 -Subject: [PATCH] MIPS: Add virtual platform - -This adds a virtual platform to use as a guest in VZ-enabled -virtualization environments. ---- - arch/mips/Kbuild.platforms | 1 + - arch/mips/Kconfig | 28 ++++++ - arch/mips/configs/mach_virt_defconfig | 11 +++ - .../include/asm/mach-virt/cpu-feature-overrides.h | 15 +++ - arch/mips/include/asm/mach-virt/dma-coherence.h | 102 +++++++++++++++++++++ - arch/mips/include/asm/mach-virt/hypcall.h | 96 +++++++++++++++++++ - arch/mips/include/asm/timex.h | 6 +- - arch/mips/mach-virt/Makefile | 3 + - arch/mips/mach-virt/Platform | 9 ++ - arch/mips/mach-virt/dma.c | 53 +++++++++++ - arch/mips/mach-virt/early_printk.c | 13 +++ - arch/mips/mach-virt/irq.c | 17 ++++ - arch/mips/mach-virt/setup.c | 95 +++++++++++++++++++ - arch/mips/mm/c-r4k.c | 2 + - 14 files changed, 448 insertions(+), 3 deletions(-) - create mode 100644 arch/mips/configs/mach_virt_defconfig - create mode 100644 arch/mips/include/asm/mach-virt/cpu-feature-overrides.h - create mode 100644 arch/mips/include/asm/mach-virt/dma-coherence.h - create mode 100644 arch/mips/include/asm/mach-virt/hypcall.h - create mode 100644 arch/mips/mach-virt/Makefile - create mode 100644 arch/mips/mach-virt/Platform - create mode 100644 arch/mips/mach-virt/dma.c - create mode 100644 arch/mips/mach-virt/early_printk.c - create mode 100644 arch/mips/mach-virt/irq.c - create mode 100644 arch/mips/mach-virt/setup.c - -diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms -index c5cd63a..5971326 100644 ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -17,6 +17,7 @@ platforms += lantiq - platforms += lasat - platforms += loongson32 - platforms += loongson64 -+platforms += mach-virt - platforms += mti-malta - platforms += mti-sead3 - platforms += netlogic -diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig -index 212ff92..0249b11 100644 ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -494,6 +494,34 @@ config MACH_PIC32 - Microchip PIC32 is a family of general-purpose 32 bit MIPS core - microcontrollers. - -+config MIPS_VIRT -+ bool "MIPS virtual platform" -+ select HW_HAS_PCI -+ select BOOT_ELF32 -+ select BOOT_RAW -+ select CEVT_R4K -+ select CSRC_R4K -+ select COMMON_CLK -+ select IRQ_MIPS_CPU -+ select DMA_NONCOHERENT -+ select MIPS_GIC -+ select MIPS_CPU_SCACHE -+ select LIBFDT -+ select HW_HAS_PCI -+ select SMP_UP if SMP -+ select SWAP_IO_SPACE -+ select SYS_HAS_CPU_MIPS32_R2 -+ select SYS_HAS_CPU_MIPS32_R3_5 -+ select SYS_HAS_CPU_MIPS64_R6 -+ select SYS_HAS_EARLY_PRINTK -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_64BIT_KERNEL -+ select SYS_SUPPORTS_HIGHMEM -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SYS_SUPPORTS_MIPS_CPS -+ select SYS_SUPPORTS_SMARTMIPS -+ select USE_OF -+ - config MIPS_SEAD3 - bool "MIPS SEAD3 board" - select BOOT_ELF32 -diff --git a/arch/mips/configs/mach_virt_defconfig b/arch/mips/configs/mach_virt_defconfig -new file mode 100644 -index 0000000..20a0353 ---- /dev/null -+++ b/arch/mips/configs/mach_virt_defconfig -@@ -0,0 +1,11 @@ -+CONFIG_MIPS_VIRT=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_BLK_DEV_RAM=y -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_MOUSE_PS2 is not set -+# CONFIG_SERIO is not set -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_VIRTIO_MMIO=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -diff --git a/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h -new file mode 100644 -index 0000000..ded8a1a ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h -@@ -0,0 +1,14 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ */ -+#ifndef __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H -+#define __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H -+ -+#define cpu_has_maar 0 -+#define cpu_has_htw 0 -+#define cpu_has_dc_aliases 1 -+#define cpu_has_nan_legacy 1 -+ -+#endif /* __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H */ -diff --git a/arch/mips/include/asm/mach-virt/dma-coherence.h b/arch/mips/include/asm/mach-virt/dma-coherence.h -new file mode 100644 -index 0000000..a9a3661 ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/dma-coherence.h -@@ -0,0 +1,102 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+#pragma once -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern unsigned long l4vmm_gpa_start; -+extern unsigned long l4vmm_gpa_size; -+extern dma_addr_t l4vmm_dma_start; -+ -+struct device; -+ -+static inline dma_addr_t plat_map_gpa_to_dma(unsigned long gpa) -+{ -+ if (likely(l4vmm_gpa_size)) { -+ if (likely(l4vmm_gpa_start <= gpa -+ && gpa < l4vmm_gpa_start + l4vmm_gpa_size)) -+ return gpa - l4vmm_gpa_start + l4vmm_dma_start; -+ } -+ -+ pr_err("Failed to translate guest-physical 0x%lx to dma-addr\n", -+ gpa); -+ BUG(); /* What else? If not here we'll go chaos sooner anyway */ -+} -+ -+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, -+ size_t size) -+{ -+ return plat_map_gpa_to_dma(virt_to_phys(addr)); -+} -+ -+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, -+ struct page *page) -+{ -+ return plat_map_gpa_to_dma(page_to_phys(page)); -+} -+ -+static inline unsigned long plat_dma_addr_to_phys(struct device *dev, -+ dma_addr_t dma_addr) -+{ -+ if (likely(l4vmm_gpa_size)) { -+ if (likely(l4vmm_dma_start <= dma_addr -+ && dma_addr < l4vmm_dma_start + l4vmm_gpa_size)) -+ return dma_addr - l4vmm_dma_start + l4vmm_gpa_start; -+ } -+ -+ pr_err("%s: Do not know about dma_addr=%lx\n", __func__, -+ (unsigned long) dma_addr); -+ BUG(); -+} -+ -+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, -+ size_t size, enum dma_data_direction direction) -+{ -+ if (0) pr_warn("%s\n", __func__); -+} -+ -+static inline int plat_dma_supported(struct device *dev, u64 mask) -+{ -+ /* -+ * we fall back to GFP_DMA when the mask isn't all 1s, -+ * so we can't guarantee allocations that must be -+ * within a tighter range than GFP_DMA.. -+ */ -+ if (mask < DMA_BIT_MASK(24)) -+ return 0; -+ -+ return 1; -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+ return coherentio; -+} -+ -+#ifndef plat_post_dma_flush -+static inline void plat_post_dma_flush(struct device *dev) -+{ -+} -+#endif -+ -+#ifdef CONFIG_SWIOTLB -+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) -+{ -+ return plat_map_gpa_to_dma(paddr); -+} -+ -+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) -+{ -+ return daddr; -+} -+#endif -diff --git a/arch/mips/include/asm/mach-virt/hypcall.h b/arch/mips/include/asm/mach-virt/hypcall.h -new file mode 100644 -index 0000000..8a7e881 ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/hypcall.h -@@ -0,0 +1,96 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * (C) 2016 Kernkonzept GmbH, Adam Lackorzynski -+ */ -+#pragma once -+ -+enum { -+ L4VMM_FUNC_BASE = 0x160, -+ L4VMM_FUNC_PRINTCHAR = L4VMM_FUNC_BASE + 0, -+}; -+ -+static inline unsigned long -+l4vmm_hypcall1(unsigned func, unsigned long a0) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0) -+ : [func] "K" (func), -+ "0" (_a0) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall2(unsigned func, unsigned long a0, unsigned long a1) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = a1; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall2_ret(unsigned func, unsigned long a0, unsigned long *a1) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = *a1; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1) -+ : "cc", "memory"); -+ *a1 = _a1; -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall3(unsigned func, unsigned long a0, unsigned long a1, -+ unsigned long a2) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = a1; -+ register unsigned long _a2 asm ("a2") = a2; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1), -+ "=r" (_a2) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1), -+ "2" (_a2) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall3_ret(unsigned func, unsigned long a0, unsigned long *a1, -+ unsigned long *a2) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = *a1; -+ register unsigned long _a2 asm ("a2") = *a2; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1), -+ "=r" (_a2) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1), -+ "2" (_a2) -+ : "cc", "memory"); -+ *a1 = _a1; -+ *a2 = _a2; -+ return _a0; -+} -diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h -index b05bb70..3222504 100644 ---- a/arch/mips/include/asm/timex.h -+++ b/arch/mips/include/asm/timex.h -@@ -71,7 +71,7 @@ static inline int can_use_mips_counter(unsigned int prid) - - static inline cycles_t get_cycles(void) - { -- if (can_use_mips_counter(read_c0_prid())) -+ if (IS_ENABLED(CONFIG_MIPS_VIRT) || can_use_mips_counter(read_c0_prid())) - return read_c0_count(); - else - return 0; /* no usable counter */ -@@ -86,10 +86,10 @@ static inline cycles_t get_cycles(void) - */ - static inline unsigned long random_get_entropy(void) - { -- unsigned int prid = read_c0_prid(); -+ unsigned int prid = IS_ENABLED(CONFIG_MIPS_VIRT) ? 0 : read_c0_prid(); - unsigned int imp = prid & PRID_IMP_MASK; - -- if (can_use_mips_counter(prid)) -+ if (IS_ENABLED(CONFIG_MIPS_VIRT) || can_use_mips_counter(prid)) - return read_c0_count(); - else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A)) - return read_c0_random(); -diff --git a/arch/mips/mach-virt/Makefile b/arch/mips/mach-virt/Makefile -new file mode 100644 -index 0000000..bb4b020 ---- /dev/null -+++ b/arch/mips/mach-virt/Makefile -@@ -0,0 +1,3 @@ -+obj-y += setup.o irq.o dma.o -+ -+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -diff --git a/arch/mips/mach-virt/Platform b/arch/mips/mach-virt/Platform -new file mode 100644 -index 0000000..52ddca7 ---- /dev/null -+++ b/arch/mips/mach-virt/Platform -@@ -0,0 +1,9 @@ -+# -+# Virtual platform. -+# -+platform-$(CONFIG_MIPS_VIRT) += mach-virt/ -+cflags-$(CONFIG_MIPS_VIRT) += -I$(srctree)/arch/mips/include/asm/mach-virt -+ -+load-$(CONFIG_MIPS_VIRT) += 0xffffffff80100000 -+ -+all-$(CONFIG_MIPS_VIRT) := $(COMPRESSION_FNAME).bin -diff --git a/arch/mips/mach-virt/dma.c b/arch/mips/mach-virt/dma.c -new file mode 100644 -index 0000000..9d86a2e ---- /dev/null -+++ b/arch/mips/mach-virt/dma.c -@@ -0,0 +1,53 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+unsigned long l4vmm_gpa_start; -+unsigned long l4vmm_gpa_size; -+dma_addr_t l4vmm_dma_start; -+ -+/* For now, we just have a single contiguous physical region in the -+ * hypervisor */ -+static int __init mips_virt_dma_init(void) -+{ -+ struct device_node *np; -+ const __be32 *ranges = NULL; -+ int naddr, nsize, len; -+ -+ l4vmm_gpa_size = 0; -+ -+ np = of_find_node_by_name(NULL, "memory"); -+ if (!np) -+ return 0; -+ -+ naddr = of_n_addr_cells(np); -+ nsize = of_n_size_cells(np); -+ -+ ranges = of_get_property(np, "dma-ranges", &len); -+ -+ if (ranges && len >= (sizeof(*ranges) * (2 * naddr + nsize))) { -+ l4vmm_dma_start = of_read_number(ranges, naddr); -+ l4vmm_gpa_start = of_read_number(ranges + naddr, naddr); -+ l4vmm_gpa_size = of_read_number(ranges + 2 * naddr, nsize); -+ -+ pr_info("DMA range for memory 0x%lx - 0x%lx set @ 0x%lx\n", -+ l4vmm_gpa_start, -+ l4vmm_gpa_start + l4vmm_gpa_size, -+ (unsigned long) l4vmm_dma_start); -+ } -+ -+ return 0; -+} -+ -+fs_initcall(mips_virt_dma_init); -diff --git a/arch/mips/mach-virt/early_printk.c b/arch/mips/mach-virt/early_printk.c -new file mode 100644 -index 0000000..591ed45 ---- /dev/null -+++ b/arch/mips/mach-virt/early_printk.c -@@ -0,0 +1,13 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+#include -+ -+void prom_putchar(char c) -+{ -+ l4vmm_hypcall1(L4VMM_FUNC_PRINTCHAR, c); -+} -diff --git a/arch/mips/mach-virt/irq.c b/arch/mips/mach-virt/irq.c -new file mode 100644 -index 0000000..8a4c9ad ---- /dev/null -+++ b/arch/mips/mach-virt/irq.c -@@ -0,0 +1,17 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+#include -+#include -+ -+#include -+ -+void __init arch_init_irq(void) -+{ -+ irqchip_init(); -+} -diff --git a/arch/mips/mach-virt/setup.c b/arch/mips/mach-virt/setup.c -new file mode 100644 -index 0000000..4182221 ---- /dev/null -+++ b/arch/mips/mach-virt/setup.c -@@ -0,0 +1,95 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+const char *get_system_type(void) -+{ -+ return "MIPS Virtual Platform"; -+} -+ -+static void __init init_mips_cpu_timer(void) -+{ -+ struct device_node *np; -+ u32 freq; -+ -+ mips_hpt_frequency = 0; -+ -+ /* The timer frequency must be defined in the device tree. -+ If the definition is missing, we assume that the timer should -+ not be used. -+ */ -+ np = of_find_node_by_name(NULL, "cpus"); -+ if (np && of_property_read_u32(np, "mips-hpt-frequency", &freq) >= 0) { -+ mips_hpt_frequency = freq; -+ -+ printk("CPU frequency %d.%02d MHz\n", freq/1000000, -+ (freq%1000000)*100/1000000); -+ } else -+ pr_warn("MIPS CPU core timer not used. %p, %u\n", np, freq); -+ -+ of_node_put(np); -+} -+ -+void __init plat_time_init(void) -+{ -+ init_mips_cpu_timer(); -+} -+ -+void __init prom_init(void) -+{ -+ int i; -+ int argc = fw_arg0; -+ char **argv = (char **)fw_arg1; -+ -+ for (i = 0; i < argc; i++) { -+ strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE); -+ if (i < argc - 1) -+ strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); -+ } -+ -+ printk("DT at address %p\n", (void *)fw_arg3); -+ __dt_setup_arch((void *)fw_arg3); -+} -+ -+void __init plat_mem_setup(void) -+{ -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init device_tree_init(void) -+{ -+ unflatten_and_copy_device_tree(); -+} -+ -+static int __init publish_devices(void) -+{ -+ if (!of_have_populated_dt()) -+ return 0; -+ -+ if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)) -+ panic("Failed to populate DT"); -+ -+ return 0; -+} -+device_initcall(publish_devices); -diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c -index fa7d8d3..dbf8775 100644 ---- a/arch/mips/mm/c-r4k.c -+++ b/arch/mips/mm/c-r4k.c -@@ -1725,9 +1725,11 @@ static void setup_scache(void) - way_string[c->scache.ways], c->scache.linesz); - } - #else -+#ifndef CONFIG_MIPS_VIRT - if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT)) - panic("Dunno how to handle MIPS32 / MIPS64 second level cache"); - #endif -+#endif - return; - } - sc_present = 0; --- -2.1.4 - diff --git a/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.9.patch b/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.9.patch deleted file mode 100644 index 2864360d..00000000 --- a/src/l4/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.9.patch +++ /dev/null @@ -1,602 +0,0 @@ -From 998a547c11c9a36a2c3fa21f1d6efe492bf489ea Mon Sep 17 00:00:00 2001 -From: Adam Lackorzynski -Subject: [PATCH] MIPS: Add virtual platform - -This adds a virtual platform to use as a guest in VZ-enabled -virtualization environments. ---- - arch/mips/Kbuild.platforms | 1 + - arch/mips/Kconfig | 28 ++++++ - arch/mips/configs/mach_virt_defconfig | 11 +++ - .../include/asm/mach-virt/cpu-feature-overrides.h | 14 +++ - arch/mips/include/asm/mach-virt/dma-coherence.h | 102 +++++++++++++++++++++ - arch/mips/include/asm/mach-virt/hypcall.h | 96 +++++++++++++++++++ - arch/mips/include/asm/timex.h | 6 +- - arch/mips/mach-virt/Makefile | 3 + - arch/mips/mach-virt/Platform | 9 ++ - arch/mips/mach-virt/dma.c | 53 +++++++++++ - arch/mips/mach-virt/early_printk.c | 13 +++ - arch/mips/mach-virt/irq.c | 17 ++++ - arch/mips/mach-virt/setup.c | 95 +++++++++++++++++++ - arch/mips/mm/c-r4k.c | 2 + - 14 files changed, 447 insertions(+), 3 deletions(-) - create mode 100644 arch/mips/configs/mach_virt_defconfig - create mode 100644 arch/mips/include/asm/mach-virt/cpu-feature-overrides.h - create mode 100644 arch/mips/include/asm/mach-virt/dma-coherence.h - create mode 100644 arch/mips/include/asm/mach-virt/hypcall.h - create mode 100644 arch/mips/mach-virt/Makefile - create mode 100644 arch/mips/mach-virt/Platform - create mode 100644 arch/mips/mach-virt/dma.c - create mode 100644 arch/mips/mach-virt/early_printk.c - create mode 100644 arch/mips/mach-virt/irq.c - create mode 100644 arch/mips/mach-virt/setup.c - -diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms -index f5f1bdb292de..74a19cda1f13 100644 ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -18,6 +18,7 @@ platforms += lantiq - platforms += lasat - platforms += loongson32 - platforms += loongson64 -+platforms += mach-virt - platforms += mti-malta - platforms += netlogic - platforms += paravirt -diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig -index b3c5bde43d34..6251c9b12455 100644 ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -546,6 +546,34 @@ config MACH_PIC32 - Microchip PIC32 is a family of general-purpose 32 bit MIPS core - microcontrollers. - -+config MIPS_VIRT -+ bool "MIPS virtual platform" -+ select HW_HAS_PCI -+ select BOOT_ELF32 -+ select BOOT_RAW -+ select CEVT_R4K -+ select CSRC_R4K -+ select COMMON_CLK -+ select IRQ_MIPS_CPU -+ select DMA_NONCOHERENT -+ select MIPS_GIC -+ select MIPS_CPU_SCACHE -+ select LIBFDT -+ select HW_HAS_PCI -+ select SMP_UP if SMP -+ select SWAP_IO_SPACE -+ select SYS_HAS_CPU_MIPS32_R2 -+ select SYS_HAS_CPU_MIPS32_R3_5 -+ select SYS_HAS_CPU_MIPS64_R6 -+ select SYS_HAS_EARLY_PRINTK -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_64BIT_KERNEL -+ select SYS_SUPPORTS_HIGHMEM -+ select SYS_SUPPORTS_LITTLE_ENDIAN -+ select SYS_SUPPORTS_MIPS_CPS -+ select SYS_SUPPORTS_SMARTMIPS -+ select USE_OF -+ - config NEC_MARKEINS - bool "NEC EMMA2RH Mark-eins board" - select SOC_EMMA2RH -diff --git a/arch/mips/configs/mach_virt_defconfig b/arch/mips/configs/mach_virt_defconfig -new file mode 100644 -index 000000000000..20a03530c490 ---- /dev/null -+++ b/arch/mips/configs/mach_virt_defconfig -@@ -0,0 +1,11 @@ -+CONFIG_MIPS_VIRT=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_BLK_DEV_RAM=y -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_MOUSE_PS2 is not set -+# CONFIG_SERIO is not set -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_VIRTIO_MMIO=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -diff --git a/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h -new file mode 100644 -index 000000000000..8994952808e4 ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/cpu-feature-overrides.h -@@ -0,0 +1,14 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ */ -+#ifndef __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H -+#define __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H -+ -+#define cpu_has_maar 0 -+#define cpu_has_htw 0 -+#define cpu_has_dc_aliases 1 -+#define cpu_has_nan_legacy 1 -+ -+#endif /* __ASM_MACH_VIRT_CPU_FEATURE_OVERRIDES_H */ -diff --git a/arch/mips/include/asm/mach-virt/dma-coherence.h b/arch/mips/include/asm/mach-virt/dma-coherence.h -new file mode 100644 -index 000000000000..a9a3661b68d3 ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/dma-coherence.h -@@ -0,0 +1,102 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+#pragma once -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern unsigned long l4vmm_gpa_start; -+extern unsigned long l4vmm_gpa_size; -+extern dma_addr_t l4vmm_dma_start; -+ -+struct device; -+ -+static inline dma_addr_t plat_map_gpa_to_dma(unsigned long gpa) -+{ -+ if (likely(l4vmm_gpa_size)) { -+ if (likely(l4vmm_gpa_start <= gpa -+ && gpa < l4vmm_gpa_start + l4vmm_gpa_size)) -+ return gpa - l4vmm_gpa_start + l4vmm_dma_start; -+ } -+ -+ pr_err("Failed to translate guest-physical 0x%lx to dma-addr\n", -+ gpa); -+ BUG(); /* What else? If not here we'll go chaos sooner anyway */ -+} -+ -+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, -+ size_t size) -+{ -+ return plat_map_gpa_to_dma(virt_to_phys(addr)); -+} -+ -+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, -+ struct page *page) -+{ -+ return plat_map_gpa_to_dma(page_to_phys(page)); -+} -+ -+static inline unsigned long plat_dma_addr_to_phys(struct device *dev, -+ dma_addr_t dma_addr) -+{ -+ if (likely(l4vmm_gpa_size)) { -+ if (likely(l4vmm_dma_start <= dma_addr -+ && dma_addr < l4vmm_dma_start + l4vmm_gpa_size)) -+ return dma_addr - l4vmm_dma_start + l4vmm_gpa_start; -+ } -+ -+ pr_err("%s: Do not know about dma_addr=%lx\n", __func__, -+ (unsigned long) dma_addr); -+ BUG(); -+} -+ -+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, -+ size_t size, enum dma_data_direction direction) -+{ -+ if (0) pr_warn("%s\n", __func__); -+} -+ -+static inline int plat_dma_supported(struct device *dev, u64 mask) -+{ -+ /* -+ * we fall back to GFP_DMA when the mask isn't all 1s, -+ * so we can't guarantee allocations that must be -+ * within a tighter range than GFP_DMA.. -+ */ -+ if (mask < DMA_BIT_MASK(24)) -+ return 0; -+ -+ return 1; -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+ return coherentio; -+} -+ -+#ifndef plat_post_dma_flush -+static inline void plat_post_dma_flush(struct device *dev) -+{ -+} -+#endif -+ -+#ifdef CONFIG_SWIOTLB -+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) -+{ -+ return plat_map_gpa_to_dma(paddr); -+} -+ -+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) -+{ -+ return daddr; -+} -+#endif -diff --git a/arch/mips/include/asm/mach-virt/hypcall.h b/arch/mips/include/asm/mach-virt/hypcall.h -new file mode 100644 -index 000000000000..8a7e8818fbfb ---- /dev/null -+++ b/arch/mips/include/asm/mach-virt/hypcall.h -@@ -0,0 +1,96 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * (C) 2016 Kernkonzept GmbH, Adam Lackorzynski -+ */ -+#pragma once -+ -+enum { -+ L4VMM_FUNC_BASE = 0x160, -+ L4VMM_FUNC_PRINTCHAR = L4VMM_FUNC_BASE + 0, -+}; -+ -+static inline unsigned long -+l4vmm_hypcall1(unsigned func, unsigned long a0) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0) -+ : [func] "K" (func), -+ "0" (_a0) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall2(unsigned func, unsigned long a0, unsigned long a1) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = a1; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall2_ret(unsigned func, unsigned long a0, unsigned long *a1) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = *a1; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1) -+ : "cc", "memory"); -+ *a1 = _a1; -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall3(unsigned func, unsigned long a0, unsigned long a1, -+ unsigned long a2) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = a1; -+ register unsigned long _a2 asm ("a2") = a2; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1), -+ "=r" (_a2) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1), -+ "2" (_a2) -+ : "cc", "memory"); -+ return _a0; -+} -+ -+static inline unsigned long -+l4vmm_hypcall3_ret(unsigned func, unsigned long a0, unsigned long *a1, -+ unsigned long *a2) -+{ -+ register unsigned long _a0 asm ("a0") = a0; -+ register unsigned long _a1 asm ("a1") = *a1; -+ register unsigned long _a2 asm ("a2") = *a2; -+ asm volatile(".set push; .set virt; hypcall %[func]; .set pop" -+ : "=r" (_a0), -+ "=r" (_a1), -+ "=r" (_a2) -+ : [func] "K" (func), -+ "0" (_a0), -+ "1" (_a1), -+ "2" (_a2) -+ : "cc", "memory"); -+ *a1 = _a1; -+ *a2 = _a2; -+ return _a0; -+} -diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h -index b05bb70a2e46..322250454979 100644 ---- a/arch/mips/include/asm/timex.h -+++ b/arch/mips/include/asm/timex.h -@@ -71,7 +71,7 @@ static inline int can_use_mips_counter(unsigned int prid) - - static inline cycles_t get_cycles(void) - { -- if (can_use_mips_counter(read_c0_prid())) -+ if (IS_ENABLED(CONFIG_MIPS_VIRT) || can_use_mips_counter(read_c0_prid())) - return read_c0_count(); - else - return 0; /* no usable counter */ -@@ -86,10 +86,10 @@ static inline cycles_t get_cycles(void) - */ - static inline unsigned long random_get_entropy(void) - { -- unsigned int prid = read_c0_prid(); -+ unsigned int prid = IS_ENABLED(CONFIG_MIPS_VIRT) ? 0 : read_c0_prid(); - unsigned int imp = prid & PRID_IMP_MASK; - -- if (can_use_mips_counter(prid)) -+ if (IS_ENABLED(CONFIG_MIPS_VIRT) || can_use_mips_counter(prid)) - return read_c0_count(); - else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A)) - return read_c0_random(); -diff --git a/arch/mips/mach-virt/Makefile b/arch/mips/mach-virt/Makefile -new file mode 100644 -index 000000000000..bb4b0207b85c ---- /dev/null -+++ b/arch/mips/mach-virt/Makefile -@@ -0,0 +1,3 @@ -+obj-y += setup.o irq.o dma.o -+ -+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -diff --git a/arch/mips/mach-virt/Platform b/arch/mips/mach-virt/Platform -new file mode 100644 -index 000000000000..52ddca75c1a2 ---- /dev/null -+++ b/arch/mips/mach-virt/Platform -@@ -0,0 +1,9 @@ -+# -+# Virtual platform. -+# -+platform-$(CONFIG_MIPS_VIRT) += mach-virt/ -+cflags-$(CONFIG_MIPS_VIRT) += -I$(srctree)/arch/mips/include/asm/mach-virt -+ -+load-$(CONFIG_MIPS_VIRT) += 0xffffffff80100000 -+ -+all-$(CONFIG_MIPS_VIRT) := $(COMPRESSION_FNAME).bin -diff --git a/arch/mips/mach-virt/dma.c b/arch/mips/mach-virt/dma.c -new file mode 100644 -index 000000000000..9d86a2e6ff0a ---- /dev/null -+++ b/arch/mips/mach-virt/dma.c -@@ -0,0 +1,53 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+unsigned long l4vmm_gpa_start; -+unsigned long l4vmm_gpa_size; -+dma_addr_t l4vmm_dma_start; -+ -+/* For now, we just have a single contiguous physical region in the -+ * hypervisor */ -+static int __init mips_virt_dma_init(void) -+{ -+ struct device_node *np; -+ const __be32 *ranges = NULL; -+ int naddr, nsize, len; -+ -+ l4vmm_gpa_size = 0; -+ -+ np = of_find_node_by_name(NULL, "memory"); -+ if (!np) -+ return 0; -+ -+ naddr = of_n_addr_cells(np); -+ nsize = of_n_size_cells(np); -+ -+ ranges = of_get_property(np, "dma-ranges", &len); -+ -+ if (ranges && len >= (sizeof(*ranges) * (2 * naddr + nsize))) { -+ l4vmm_dma_start = of_read_number(ranges, naddr); -+ l4vmm_gpa_start = of_read_number(ranges + naddr, naddr); -+ l4vmm_gpa_size = of_read_number(ranges + 2 * naddr, nsize); -+ -+ pr_info("DMA range for memory 0x%lx - 0x%lx set @ 0x%lx\n", -+ l4vmm_gpa_start, -+ l4vmm_gpa_start + l4vmm_gpa_size, -+ (unsigned long) l4vmm_dma_start); -+ } -+ -+ return 0; -+} -+ -+fs_initcall(mips_virt_dma_init); -diff --git a/arch/mips/mach-virt/early_printk.c b/arch/mips/mach-virt/early_printk.c -new file mode 100644 -index 000000000000..591ed45f37f8 ---- /dev/null -+++ b/arch/mips/mach-virt/early_printk.c -@@ -0,0 +1,13 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+#include -+ -+void prom_putchar(char c) -+{ -+ l4vmm_hypcall1(L4VMM_FUNC_PRINTCHAR, c); -+} -diff --git a/arch/mips/mach-virt/irq.c b/arch/mips/mach-virt/irq.c -new file mode 100644 -index 000000000000..8a4c9addf4cc ---- /dev/null -+++ b/arch/mips/mach-virt/irq.c -@@ -0,0 +1,17 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+#include -+#include -+ -+#include -+ -+void __init arch_init_irq(void) -+{ -+ irqchip_init(); -+} -diff --git a/arch/mips/mach-virt/setup.c b/arch/mips/mach-virt/setup.c -new file mode 100644 -index 000000000000..4182221ebbaf ---- /dev/null -+++ b/arch/mips/mach-virt/setup.c -@@ -0,0 +1,95 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2016 Kernkonzept GmbH -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+const char *get_system_type(void) -+{ -+ return "MIPS Virtual Platform"; -+} -+ -+static void __init init_mips_cpu_timer(void) -+{ -+ struct device_node *np; -+ u32 freq; -+ -+ mips_hpt_frequency = 0; -+ -+ /* The timer frequency must be defined in the device tree. -+ If the definition is missing, we assume that the timer should -+ not be used. -+ */ -+ np = of_find_node_by_name(NULL, "cpus"); -+ if (np && of_property_read_u32(np, "mips-hpt-frequency", &freq) >= 0) { -+ mips_hpt_frequency = freq; -+ -+ printk("CPU frequency %d.%02d MHz\n", freq/1000000, -+ (freq%1000000)*100/1000000); -+ } else -+ pr_warn("MIPS CPU core timer not used. %p, %u\n", np, freq); -+ -+ of_node_put(np); -+} -+ -+void __init plat_time_init(void) -+{ -+ init_mips_cpu_timer(); -+} -+ -+void __init prom_init(void) -+{ -+ int i; -+ int argc = fw_arg0; -+ char **argv = (char **)fw_arg1; -+ -+ for (i = 0; i < argc; i++) { -+ strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE); -+ if (i < argc - 1) -+ strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); -+ } -+ -+ printk("DT at address %p\n", (void *)fw_arg3); -+ __dt_setup_arch((void *)fw_arg3); -+} -+ -+void __init plat_mem_setup(void) -+{ -+} -+ -+void __init prom_free_prom_memory(void) -+{ -+} -+ -+void __init device_tree_init(void) -+{ -+ unflatten_and_copy_device_tree(); -+} -+ -+static int __init publish_devices(void) -+{ -+ if (!of_have_populated_dt()) -+ return 0; -+ -+ if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)) -+ panic("Failed to populate DT"); -+ -+ return 0; -+} -+device_initcall(publish_devices); -diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c -index 88cfaf81c958..cad123f7127f 100644 ---- a/arch/mips/mm/c-r4k.c -+++ b/arch/mips/mm/c-r4k.c -@@ -1741,9 +1741,11 @@ static void setup_scache(void) - way_string[c->scache.ways], c->scache.linesz); - } - #else -+#ifndef CONFIG_MIPS_VIRT - if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT)) - panic("Dunno how to handle MIPS32 / MIPS64 second level cache"); - #endif -+#endif - return; - } - sc_present = 0; --- -2.11.0 - diff --git a/src/l4/pkg/uvmm/configs/guests/Linux/mips/README b/src/l4/pkg/uvmm/configs/guests/Linux/mips/README deleted file mode 100644 index 09b267ee..00000000 --- a/src/l4/pkg/uvmm/configs/guests/Linux/mips/README +++ /dev/null @@ -1,25 +0,0 @@ - -How to build a Linux kernel to be used as a guest kernel in uvmm? - -The following brief instructions assume that the reader has -a basic knowledge how to build Linux and has the necessary -environment and tools installed. - -This directory contains patches against various versions -of the Linux kernel. Choose the appropriate patch and apply with - -/tmp $ cd linux-4.4 -/tmp/linux-4.4 $ patch -p1 -i /path/to/pkg/uvmm/configs/guests/Linux/mips/0001-MIPS-Add-virtual-platform-linux-4.4.patch - -Configure the kernel: - -/tmp/linux-4.4 $ make ARCH=mips mach_virt_defconfig - -Further configure the kernel to your needs. - -Build: - -/tmp/linux-4.4 $ make ARCH=mips CROSS_COMPILE=mips-linux- - -The resulting file /tmp/linux-4.4/vmlinux is used as a kernel -for uvmm. diff --git a/src/l4/pkg/uvmm/configs/modules.list b/src/l4/pkg/uvmm/configs/modules.list deleted file mode 100644 index 31eab3c9..00000000 --- a/src/l4/pkg/uvmm/configs/modules.list +++ /dev/null @@ -1,17 +0,0 @@ - -entry uvmm -kernel fiasco -serial_esc -roottask moe rom/uvmm.ned -module uvmm -module l4re -module ned -module cons -module io -module l4vio_net_p2p -module[shell] echo dtb/virt-$PLATFORM_TYPE.dtb -module[shell] echo ned/uvmm/vmm.lua -module[shell] echo io/plat-$PLATFORM_TYPE/io.cfg -module[shell] echo io/plat-$PLATFORM_TYPE/vm_hw.vbus -module[shell] echo ned/uvmm/uvmm.ned -module[shell,uncompress] echo $ZIMAGE_FILE -#module /arm-image diff --git a/src/l4/pkg/uvmm/configs/uvmm.ned b/src/l4/pkg/uvmm/configs/uvmm.ned deleted file mode 100644 index b5e45895..00000000 --- a/src/l4/pkg/uvmm/configs/uvmm.ned +++ /dev/null @@ -1,54 +0,0 @@ --- vi:ft=lua - -package.path = "rom/?.lua"; - -local L4 = require "L4"; -local vmm = require "vmm"; - -vmm.loader.log_fab = L4.default_loader:new_channel(); - --- start cons server for console multiplexing -L4.default_loader:start( - { - scheduler = vmm.new_sched(0x40); - log = L4.Env.log, - caps = { cons = vmm.loader.log_fab:svr() } - }, "rom/cons -a"); - - --- virtual IO busses -local io_busses = { - vm_hw = 1, -} - --- virtio network ports -local net_ports = { - net0 = 1, - net1 = 1, -} - -local common_bootargs = "console=ttyAMA0 earlyprintk=1"; - -vmm.start_io(io_busses, "rom/io.cfg"); -vmm.start_virtio_switch(net_ports, 0xa, 0x1); -vmm.start_vm{ - id=1, - mem=256, - vbus=io_busses.vm_hw, - net=net_ports.net0, - rd="rom/ramdisk-arm.rd", - fdt="rom/virt-omap5.dtb", - --bootargs=common_bootargs .. " ip=192.168.1.1:::255.255.255.0:server:eth0 root=/dev/sda1", - bootargs=common_bootargs .. " ramdisk_size=9100 root=/dev/ram", - prio=nil, cpus=0x1 -}; - -vmm.start_vm{ - id=2, - mem=256, - net=net_ports.net1, - rd="rom/ramdisk-arm.rd", - fdt="rom/virt-omap5.dtb", - bootargs=common_bootargs .. " ramdisk_size=9100 root=/dev/ram", - prio=nil, cpus=0x1 -}; diff --git a/src/l4/pkg/uvmm/configs/vmm.lua b/src/l4/pkg/uvmm/configs/vmm.lua deleted file mode 100644 index 65520091..00000000 --- a/src/l4/pkg/uvmm/configs/vmm.lua +++ /dev/null @@ -1,244 +0,0 @@ -local L4 = require "L4"; - -local l = L4.Loader.new({mem = L4.Env.user_factory}); -loader = l; - -function table_override(...) - local combined = {} - for _, tab in ipairs({...}) do - for k, v in pairs(tab) do - combined[k] = v - end - end - return combined -end - -function new_sched(prio, cpus) - return L4.Env.user_factory:create(L4.Proto.Scheduler, prio + 10, prio, cpus); -end - --- Starts IO service with the given options: --- --- `busses` : Table of vBus names to create. One file per vBus; file name must --- be .vbus for busses.. --- `cmdline`: io command line parameters --- `opts` : Option table for loader.start function, e.g. scheduler or --- ext_caps. ext_caps overwrites default caps created by this --- function. -function start_io(busses, cmdline, opts) - if opts == nil then opts = {} end - - if opts.caps ~= nil then - print("Warning: use opts.ext_caps to pass custom/additional capabilities.") - end - - if opts.scheduler == nil then - print("IO started with base priority. Risk of priority related deadlocks! " - .. "Provide an opts.scheduler entry.") - end - - local caps = { - sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0); - icu = L4.Env.icu; - iommu = L4.Env.iommu; - }; - - local files = ""; - - for k, v in pairs(busses) do - if caps[k] ~= nil then - print("Warning: overwriting caps." .. k .. " with vbus of same name.") - end - local c = l:new_channel(); - busses[k] = c - caps[k] = c:svr(); - files = files .. " rom/" .. k .. ".vbus"; - end - - opts.caps = table_override(caps, opts.caps or {}, opts.ext_caps or {}) - opts.log = opts.log or { "io", "red" } - - return l:start(opts, "rom/io " .. cmdline .. files) -end - --- Creates a scheduler proxy and writes it into the `opts` table. --- --- Four cases happen here: --- A) No prio and no cpus: No scheduler proxy created. --- B) A prio, but no cpus: Create a scheduler proxy with only a priority limit. --- C) No Prio, but cpus: Create a scheduler proxy with default prio and cpus --- limit. --- D) A prio and cpus: Create a scheduler proxy with given limits. -function set_sched(opts, prio, cpus) - if cpus == nil and prio == nil then - return - end - - if prio == nil then - -- Default to zero to use the L4Re Default_thread_prio - prio = 0 - end - - local sched = new_sched(prio, cpus); - opts["scheduler"] = sched; -end - -function start_virtio_switch(ports, prio, cpus, switch_type, ext_caps) - local switch = l:new_channel(); - - local opts = { - log = { "switch", "Blue" }, - caps = table_override({ svr = switch:svr() }, ext_caps or {}); - }; - - set_sched(opts, prio, cpus); - if switch_type == "switch" then - local port_count = 0; - for k, v in pairs(ports) do - port_count = port_count + 1; - end - svr = l:start(opts, "rom/l4vio_switch -v -m -p " .. port_count ); - - for k, v in pairs(ports) do - ports[k] = L4.cast(L4.Proto.Factory, switch):create(0, "ds-max=4", "name=" .. k) - end - else - svr = l:start(opts, "rom/l4vio_net_p2p"); - - for k, v in pairs(ports) do - ports[k] = L4.cast(L4.Proto.Factory, switch):create(0, "ds-max=4"); - end - end - - return svr; -end - -function start_vm(options) - local nr = options.id; - local size_mb = 0; - local vbus = options.vbus; - local vnet = options.net; - local prio = options.prio; - local cpus = options.cpus; - local scheduler = options.scheduler; - local nonidentmem = options.nonidentmem; - - local align = 10; - if L4.Info.arch() == "arm" then - align = 28; - elseif L4.Info.arch() == "arm64" then - align = 21; - end - align = options.mem_align or align; - - local cmdline = {}; - if options.fdt then - if type(options.fdt) ~= "table" then - options.fdt = { options.fdt } - end - for _,v in ipairs(options.fdt) do - cmdline[#cmdline+1] = "-d" .. v; - end - end - - if options.bootargs then - cmdline[#cmdline+1] = "-c" .. options.bootargs; - end - - if options.rd then - cmdline[#cmdline+1] = "-r" .. options.rd; - end - - if options.kernel then - cmdline[#cmdline+1] = "-k" .. options.kernel; - end - - if options.ram_base then - cmdline[#cmdline+1] = "-b" .. options.ram_base; - end - - if L4.Info.arch() == "arm" or L4.Info.arch() == "arm64" then - if not options.nonidentmem then - cmdline[#cmdline+1] = "-i"; - end - end - - local keyb_shortcut = nil; - if nr ~= nil then - keyb_shortcut = "key=" .. nr; - end - - local vm_ram; - if type(options.mem) == "userdata" then - -- User gave us a cap. Using this as dataspace for guest RAM. - vm_ram = options.mem - elseif type(options.mem) == "number" then - -- User gave us a number. Using this as size for a new Dataspace. - size_mb = options.mem - elseif type(options.mem) == "string" then - print("start_vm: mem parameter '" .. options.mem .. "' is of type string, " - .. "please use integer."); - size_mb = tonumber(options.mem) - else - -- User did not give us any valid value. - size_mb = 16 - end - - if size_mb > 0 then - local mem_flags = L4.Mem_alloc_flags.Continuous - | L4.Mem_alloc_flags.Pinned - | L4.Mem_alloc_flags.Super_pages; - - vm_ram = L4.Env.user_factory:create(L4.Proto.Dataspace, - size_mb * 1024 * 1024, - mem_flags, align):m("rw"); - end - - local caps = { - net = vnet; - vbus = vbus; - ram = vm_ram; - }; - - if options.jdb then - caps["jdb"] = L4.Env.jdb - end - - if options.ext_args then - for _,v in ipairs(options.ext_args) do - cmdline[#cmdline+1] = v - end - end - - local opts = { - log = options.log or l.log_fab:create(L4.Proto.Log, "vm" .. nr, "w", - keyb_shortcut); - caps = table_override(caps, options.ext_caps or {}); - }; - - if scheduler then - opts["scheduler"] = scheduler; - else - set_sched(opts, prio, cpus); - end - - if type(options.mon) == 'string' then - -- assume 'mon' is the name of a server binary which implements the uvmm - -- CLI interface - mon = l:new_channel() - - l:start({ - scheduler = opts.scheduler; - log = l.log_fab:create(L4.Proto.Log, "mon" .. nr), - caps = { mon = mon:svr() } - }, "rom/" .. options.mon) - - caps["mon"] = mon - elseif options.mon ~= false then - caps["mon"] = l.log_fab:create(L4.Proto.Log, "mon" .. nr, "g"); - end - - return l:startv(opts, "rom/uvmm", table.unpack(cmdline)); -end - -return _ENV diff --git a/src/l4/pkg/uvmm/doc/files.cfg b/src/l4/pkg/uvmm/doc/files.cfg deleted file mode 100644 index 6ef468e3..00000000 --- a/src/l4/pkg/uvmm/doc/files.cfg +++ /dev/null @@ -1,3 +0,0 @@ -INPUT += %PKGDIR%/doc/uvmm.dox -INPUT += %PKGDIR%/doc/uvmm-ram.dox -INPUT += %PKGDIR%/doc/uvmm_dtg.md diff --git a/src/l4/pkg/uvmm/doc/uvmm-ram.dox b/src/l4/pkg/uvmm/doc/uvmm-ram.dox deleted file mode 100644 index 8ce38cb2..00000000 --- a/src/l4/pkg/uvmm/doc/uvmm-ram.dox +++ /dev/null @@ -1,82 +0,0 @@ -// vi:ft=c -/** - * \page l4re_servers_uvmm_ram_details RAM configuration - * - * ## RAM configuration for uvmm - * - * ### Without a memory node in the device tree - * - * * setup default RAM for guest VM. - * * RAM starts either - * * at base-address which defaults to 0x0 or the base address value - * set via the -b cmdline option or - * * in case of identity mapping at the host-physical address of the - * dataspace allocated for the RAM - * - * - * ### With a memory node in the device tree - * - * The memory node needs at least the properties device_type and l4vmm,dscap: - * - * memory@0 { - * device_type = "memory"; - * l4vmm,dscap = "ram"; - * } - * - * Where the given l4vmm,dscap name is accessible in the capability namespace - * of the uvmm. If the capability is invalid, the memory node is disabled. - * - * If memory nodes are given, but none provides valid RAM the configuration is - * invalid and uvmm refuses to boot. - * - * Additional properties of the memory node are `reg` and `dma-ranges`. - * - * The `reg` property describes the location in the guest's address space that - * should be backed by RAM. - * - * The `dma-ranges` property describes the offset between guest-physical and - * host-physical addresses. The guest can evaluate this non-standard property - * to derive the correct DMA addresses to program into passed-through devices. - * Usage of this property __requires__ modification of guest code. - * - * - * #### Without reg and dma-ranges properties - * - * The reg property is optional only in case the uvmm maps the guest's RAM into - * the VM under the host-physical addresses of the backing memory - * (l4vmm,dscap). - * - * This case can be forced via the cmdline parameter -i and is the default for - * platforms without IOMMU, but with DMA capable devices on the configured - * vBus. - * - * - * #### Without a reg property, but with a dma-ranges property - * - * If the -i cmdline parameter is given, identity mapping is forced and the - * behavior is the same as in the case above. - * Additionally, the dma-ranges property is written - * - * In case no -i cmdline parameter is given, the configuration is invalid and - * uvmm refuses to boot. - * - * - * #### With a reg property - * - * uvmm parses the reg property of the memory node and maps the memory into the - * VM to the given range(s). - * - * If the -i cmdline parameter is set, the reg property is ignored and the - * memory is mapped into the VM under the corresponding host-physical addresses - * of the backing memory (l4vmm,dscap) - * - * - * #### With a reg and dma-ranges property - * - * uvmm parses the reg property of the memory node and maps the memory into the - * VM to the given range(s). - * - * The dma-ranges property is filled with the corresponding host-physical - * addresses of the backing memory (l4vmm,dscap). - * - */ diff --git a/src/l4/pkg/uvmm/doc/uvmm.dox b/src/l4/pkg/uvmm/doc/uvmm.dox deleted file mode 100644 index b8693315..00000000 --- a/src/l4/pkg/uvmm/doc/uvmm.dox +++ /dev/null @@ -1,512 +0,0 @@ -// vi:ft=c -/** - * \page l4re_servers L4Re Servers - * - * - \subpage l4re_servers_uvmm - * - * \page l4re_servers_uvmm Uvmm, the virtual machine monitor - * - * Uvmm provides a virtual machine for running an unmodified guest in - * non-privileged mode. - * - * Command Line Options - * -------------------- - * - * uvmm provides the following command line options: - * - * * `-c, --cmdline=` - * - * Command line that is passed to the guest on boot. - * - * * `-k, --kernel=` - * - * The name of the guest-kernel image file present in the ROM namespace. - * - * * `-d, --dtb=` - * - * The name of the device tree file present in the ROM namespace. - * The device tree will be placed in the upmost region of guest memory. - * Optionally, a user may use an additional parameter in the form of - * ":limit=0xffffffff" to set an upper limit for the device tree - * location. - * - * * `-r, --ramdisk=` - * - * The name of the RAM disk file present in the ROM namespace - * - * * `-b, --rambase=` - * - * Physical start address for the guest RAM. This value is - * platform specific. - * - * * `-D, --debug=[=][level]` - * - * Control the verbosity level of the uvmm. Possible `level` values are: - * quiet, warn, info, trace - * - * Using the `component` prefix, the verbosity level of each uvmm - * component is configurable. The component names are: - * core, cpu, mmio, irq, dev, pm, vbus_event - * - * For example, the following command line sets the verbosity of all uvmm - * components to `info` except for IRQ handling, which is set to `trace`. - * - * uvmm -D info -D irq=trace - * - * * `-f, --fault-mode` - * - * Control the handling of guest reads/writes to non-existing memory. - * Possible values are: - * - * * `ignore` - Invalid writes are ignored. Invalid reads either return 0 or - * are skipped. The guest may experience undefined behaviour. - * * `halt` - Halt the VM on the first invalid memory access. - * * `inject` - Try to forward the invalid access to the guest. This is not - * supported on all architectures. Falls back to `halt` if the error could - * not be forwarded to the guest. - * - * Defaults to `ignore`. - * - * * `-q, --quiet` - * - * Silence all uvmm output. - * - * * `-v, --verbose` - * - * Increase the verbosity of the uvmm. Repeating the option increases the - * verbosity by another level. - * - * * `-W, --wakeup-on-system-resume` - * - * When set, the uvmm resumes when the host system resumes after a - * suspend call. - * - * * `-i` - * - * When set, the option forces the guest RAM to be mapped to its - * corresponding host-physical addresses. - * - * \note Options `-q, --quiet`, `-v, --verbose` and `-D, --debug` cancel each - * other out. - * - * Setting up guest memory - * ----------------------- - * - * In the most simple setup, memory for the guest can be provided via a - * simple dataspace. In your ned script, create a new dataspace of the - * required size and hand it into uvmm as the `ram` capability: - * - * local ramds = L4.Env.user_factory:create(L4.Proto.Dataspace, 60 * 1024 * 1024) - * - * L4.default_loader::startv({caps = {ram = ramds:m("rw")}}, "rom/uvmm") - * - * The memory will be mapped to the most appropriate place and a memory node - * added to the device tree, so that the guest can find the memory. - * - * For a more complex setup, the memory can be configured via the device tree. - * uvmm scans for memory nodes and tries to set up the memory from them. A - * memory device node should look like this: - * - * memory@0 { - * device_type = "memory"; - * reg = <0x00000000 0x00100000 - * 0x00200000 0xffffffff>; - * l4vmm,dscap = "memcap"; - * dma-ranges = <>; - * }; - * - * The `device_type` property is mandatory and needs to be set to `memory`. - * - * `l4vmm,dscap` contains the name of the capability containing the dataspace - * to be used for the RAM. `reg` describe the memory regions to use for the - * memory. The regions will be filled up to the size of the supplied dataspace. - * If they are larger, then the remaining area will be cut. - * - * If the optional `dma-ranges` property is given, the host-physical address - * ranges for the memory regions will be added here. Note that the property is - * not cleared first, so it should be left empty. - * - * For more details see \subpage l4re_servers_uvmm_ram_details. - * - * ### Memory layout - * - * uvmm populates the RAM with the following data: - * - * * kernel binary - * * (optional) ramdisk - * * (optional) device tree - * - * The kernel binary is put at the predefined address. For ELF binaries, this - * is an absolute physical address. If the binary supports relative addressing, - * the binary is put to the requested offset relative to beginning of the - * first 'memory' region defined in the device tree. - * - * The ramdisk and device tree are placed as far as possible to the end of the - * regions defined in the first 'memory' node. - * - * If there is a part of RAM that must remain empty, then define an extra - * memory node for it in the device tree. uvmm only writes to memory in - * the first memory node it finds. - * - * Warning: uvmm does not touch any unpopulated memory. In particular, it does - * not ensure that the memory is cleared. It is the responsibility of the provider - * of the RAM dataspace to make sure that no data leakage can happen. Normally - * this is not an issue because dataspaces are guaranteed to be cleaned when - * they are newly created but users should be careful when reusing memory or - * dataspaces, for example, when restarting the uvmm. - * - * Forwarding hardware resources to the guest - * ------------------------------------------ - * - * Hardware resources must be specified in two places: the device tree contains - * the description of all hardware devices the guest could see and the Vbus - * describes which resources are actually available to the uvmm. - * - * The vbus allows the uvmm access to hardware resources in the same way as - * any other L4 application. uvmm expects a capability named 'vbus' where it - * can access its hardware resources. It is possible to leave out the capability - * for purely virtual guests (Note that this is not actually practical on some - * architectures. On ARM, for example, the guest needs hardware access to the - * interrupt controller. Without a 'vbus' capability, interrupts will not work.) - * For information on how to configure a vbus, see the \ref io "IO documentation". - * - * The device tree needs to contain the hardware description the guest should - * see. For hardware devices this usually means to use a device tree that would - * also be used when running the guest directly on hardware. - * - * On startup, uvmm scans the device tree for any devices that require memory - * or interrupt resources and compares the required resources with the ones - * available from its vbus. When all resources are available, it sets up the - * appropriate forwarding, so that the guest now has direct access to the - * hardware. If the resources are not available, the device will be marked - * as 'disabled'. This mechanism allows to work with a standard device tree - * for all guests in the system while handling the actual resource allocation - * in a flexible manner via the vbus configuration. - * - * - * The default mechanism assigns all resources 1:1, i.e. with the same memory - * address and interrupt number as on hardware. It is also possible to map a - * hardware device to a different location. In this case, the assignment - * between vbus device and device tree device must be known in advance and - * marked in the device tree using the `l4vmm,vbus-dev` property. - * - * The following device will for example be bound with the vbus device with - * the HID 'l4-test,dev': - * - * test@e0000000 { - * compatible = "memdev,bar"; - * reg = <0 0xe0000000 0 0x50000>, - * <0 0xe1000000 0 0x50000>; - * l4vmm,vbus-dev = "l4-test,dev"; - * interrupts-extended = <&gic 0 139 4>; - * }; - * - * Resources are then matched by name. Memory resources in the vbus must - * be named `reg0` to `reg9` to match against the address ranges in the - * device tree `reg` property. Interrupts must be called `irq0` to `irq9` - * and will be matched against `interrupts` or `interrupts-extended` entries - * in the device tree. The vbus must expose resources for all resources - * defined in the device tree entry or the initialisation will fail. - * - * An appropriate IO entry for the above device would thus be: - * - * MEM = Io.Hw.Device(function() - * Property.hid = "l4-test,dev" - * Resource.reg0 = Io.Res.mmio(0x41000000, 0x4104ffff) - * Resource.reg1 = Io.Res.mmio(0x42000000, 0x4204ffff) - * Resource.irq0 = Io.Res.irq(134); - * end) - * - * Please note that HIDs on the vbus are not necessarily unique. If multiple - * devices with the HID given in `l4vmm,vbus-dev` are available on the vbus, - * then one device is chosen at random. - * - * If no vbus device with the given HID is available, the device is disabled. - * - * How to enable guest suspend/resume - * ---------------------------------- - * - * \note Currently only supported on ARM. It should work fine with Linux - * version 4.4 or newer. - * - * Uvmm (partially) implements the power state coordination interface (PSCI), - * which is the standard ARM power management interface. To make use of this - * interface, you have to announce its availability to the guest operating - * system via the device tree like so: - * - * psci { - * compatible = "arm,psci-0.2"; - * method = "hvc"; - * }; - * - * The Linux guest must be configured with at least these options: - * - * CONFIG_SUSPEND=y - * CONFIG_ARM_PSCI=y - * - * How to communicate power management (PM) events - * ----------------------------------------------- - * - * Uvmm can be instructed to inform a PM manager of PM events through the - * L4::Platform_control interface. To that end, uvmm may be equipped with a - * `pfc` cap. On suspend, uvmm will call l4_platform_ctl_system_suspend(). - * - * The `pfc` cap can also be implemented by IO. In that case the guest can - * start a machine suspend/shutdown/reboot. - * - * Ram block device support - * ------------------------ - * - * The example ramdisk works by loading a file system into RAM, which needs RAM - * block device support to work. In the Linux kernel configuration add: - * CONFIG_BLK_DEV_RAM=y - * - * Framebuffer support for uvmm/amd64 guests - * ----------------------------------------- - * Uvmm can be instructed to pass along a framebuffer to the Linux guest. To - * enable this three things need to be done: - * - * 1. Configure Linux to support a simple framebuffer by enabling - * CONFIG_FB_SIMPLE=y - * CONFIG_X86_SYSFB=y - * - * 2. Configure a simple framebuffer device in the device tree (currently only - * read by uvmm, linearer framebuffer at [0xf0000000 - 0xf1000000]) - * - * simplefb { - * compatible = "simple-framebuffer"; - * reg = <0x0 0xf0000000 0x0 0x1000000>; - * l4vmm,fbcap = "fb"; - * }; - * - * 3. Start a framebuffer instance and connect it to uvmm e.g. - * -- Start fb-drv (but only if we need to) - * local fbdrv_fb = L4.Env.vesa; - * if (not fbdrv_fb) then - * fbdrv_fb = l:new_channel(); - * l:start({ - * caps = { - * vbus = io_busses.fbdrv, - * fb = fbdrv_fb:svr(), - * }, - * log = { "fbdrv", "r" }, - * }, - * "rom/fb-drv"); - * end - * vmm.start_vm{ - * ext_caps = { fb = fbdrv_fb }, - * -- ... - * - * - * Requirements on the Fiasco.OC configuration on amd64 - * ---------------------------------------------------- - * - * The kernel configuration must feature `CONFIG_SYNC_TSC=y` in order for the - * emulated timers to reach a sufficiently high resolution. - * - * - * Recommended Linux configuration options for uvmm/amd64 guests - * ------------------------------------------------------------- - * - * The following options are recommended in additon to the amd64 defaults - * provided by a `make defconfig`: - * - * Virtio support is required to access virtual devices provided by uvmm: - * - * CONFIG_VIRTIO=y - * CONFIG_VIRTIO_PCI=y - * CONFIG_VIRTIO_BLK=y - * CONFIG_BLK_MQ_VIRTIO=y - * CONFIG_VIRTIO_CONSOLE=y - * CONFIG_VIRTIO_INPUT=y - * CONFIG_VIRTIO_NET=y - * - * It is highly recommended to use the X2APIC, which needs virtualization - * awareness to work under uvmm: - * - * CONFIG_X86_X2APIC=y - * CONFIG_PARAVIRT=y - * CONFIG_PARAVIRT_SPINLOCKS=y - * - * KVM clock for uvmm/amd64 guests - * ------------------------------- - * - * When executing L4Re + uvmm on QEMU, the PIT as clock source is not reliable. - * The paravirtualized KVM clock provides the guest with a stable clock source. - * - * A KVM clock device is available to the guest, if the device tree contains - * the corresponding entry: - * - * kvm_clock { - * compatible = "kvm-clock"; - * reg = <0x0 0x0 0x0 0x0>; - * }; - * - * To make use of this clock, the Linux guest must be built with the following - * configuration options: - * - * CONFIG_HYPERVISOR_GUEST=y - * CONFIG_KVM_GUEST=y - * CONFIG_PTP_1588_CLOCK_KVM is not set - * - * Note: KVM calls besides the KVM clock are unhandled and lead to failure - * in the uvmm, e.g. vmcall 0x9 for the PTP_1588_CLOCK_KVM. - * - * This is considered a development feature. The KVM clock is not required when - * running on physical hardware as TSC calibration via the PIT works as - * expected. - * - * - * Development notes for amd64 - * --------------------------- - * - * When you are developing on Linux using QEMU please note that nested - * virtualization support is necessary on your host system to run uvmm guests. - * Your host Linux version should be 4.12 or greater, **excluding 4.20**. - * - * Check if your KVM module has nested virtualization enabled via: - * - * > cat /sys/module/kvm_intel/parameters/nested - * Y - * - * In case it shows `N` instead of `Y` enable nested virtualization support - * via: - * - * modprobe kvm_intel nested=1 - * - * On AMD platforms the module name is `kvm_amd`. - * - * - * QEMU network setup for a uvmm guest on amd64 - * -------------------------------------------- - * - * qemu-system-x86_64 -M q35 -cpu host -enable-kvm -device intel-iommu - * -device e1000e,netdev=net0 -netdev bridge,id=net0,br=virbr0 - * - * where 'virbr0' is the name of the host's bridge device. The line 'allow - * virbr0' needs to be present in /etc/qemu/bridge.conf. - * The bridge can either be created via the network manager or via the command - * line: - * - * brctl addbr virbr0 - * ip addr add 192.168.124.1/24 dev virbr0 - * ip link set up dev virbr0 - * - * In the guest linux with eth0 as network device: - * - * ip a a 192.168.124.5/24 dev eth0 - * ip li se up dev eth0 - * - * Now the host and guest can ping each other using their respective IPs. - * - * Of course, uvmm needs to be connected to Io and Io needs a vbus - * configuration for the uvmm client like this: - * - * Io.add_vbusses - * { - * vm_pci = Io.Vi.System_bus(function () - * Property.num_msis = 6 - * PCI = Io.Vi.PCI_bus(function () - * pci_net = wrap(Io.system_bus():match("PCI/CC_0200")) - * end) - * end) - * } - * - * QEMU emulated VirtIO devices and IO-MMU on amd64 - * ------------------------------------------------ - * - * QEMU does not route VirtIO devices through the IO-MMU per default. To use - * QEMU emulated VirtIO devices add the - * `disable-legacy=on,disable-modern=off,iommu_platform=on` flags to the option - * list of the device. - * The e1000e card in the network example above can be replaced with an - * virtio-net-pci card like this: - * - * -device virtio-net-pci,disable-legacy=on,disable-modern=off, - * iommu_platform=on,netdev=net0 - * - * For more information on VirtIO devices and their options see - * https://wiki.qemu.org/Features/VT-d. - * - * - * - * Using the uvmm monitor interface - * -------------------------------- - * - * Uvmm implements an interface with which parts of the guest's state can be - * queried and manipulated at runtime. This monitor interface needs to be enabled - * during compilation as well as during startup of uvmm. This is described in - * detail below. - * - * ### Compiling uvmm with monitor interface support - * - * To compile uvmm with monitor interface support pass the `CONFIG_MONITOR=y`, - * option during the `make` step (or set in in the Makefile.config). This - * option is available on all architectures but note that the set of available - * monitor interface features may vary significantly between them. Also note - * that the monitor interface will always be disabled in release mode, i.e. if - * `CONFIG_RELEASE_MODE=y`. - * - * ### Enabling the monitor interface at runtime - * - * When starting a uvmm instance from inside a `ned` script using the - * `vmm.start_vm` function, the `mon` argument controls whether the monitor - * interface is enabled at runtime. There are three cases to distinguish: - * - * - `mon=true` (default): The monitor interface is enabled but no server - * implementing the client side of the monitor interface - * is started. The monitor interface can still be - * utilized via `cons` but no readline functionality will - * be available. - * - * - `mon='some_binary'`: If a string is passed as the value of `mon`, the - * monitor interface is enabled and the string is - * interpreted as the name of a server binary which - * implements the client side of the monitor interface. - * This server is automatically started and has access to - * a vcon capability named `mon` at startup through which - * it can make use of the monitor interface. Unless you - * have written your own server you should specify - * `'uvmm_cli'` which is a server implementing a simple - * readline interface. - * - * - `mon=false`: The monitor interface is disabled at runtime. - * - * ### Using the monitor interface - * - * If the monitor interface was enabled you can connect to it via `cons` under - * the name `mon` where `` is a unique integer for every uvmm instance - * that is started with the monitor interface enabled (numbered starting from - * one in order of corresponding `vmm.start_vm` calls). If `mon='uvmm_cli'` was - * specified, readline functionality such as command completion and history - * will be available. Enter a command followed by enter to run that command. - * To obtain a list of all available commands issue the `help` command, to - * obtain usage information for a specific command `foo` issue `help foo`. - * - * \note Some commands will modify the guests state. Since it should be obvious - * to which ones this applies this is usually not specifically - * highlighted. Exercise reasonable caution. - * - * ### Using the guest debugger - * - * The guest debugger provides monitoring functionality akin to a very - * bare-bone GDB interface, e.g. guest RAM and page table dumping, - * breakpointing and single stepping. Additional functionality might be added in - * the future. - * - * \note The guest debugger is currently still under development. The guest - * debugger may also not be available on all architectures. To check - * whether the guest debugger is available check if `help dbg` returns - * usage information. - * - * If the guest debugger is available, you have to manually load it at runtime - * using the monitor interface. This saves resources if the guest debugger is - * not used. To enable the guest debugger, issue the `dbg on` monitor command. - * Once enabled, the guest debugger can not be disabled again. - * - * To list available guest debugger subcommands, issue `dbg help` after `dbg on`. - * - * \note When using SMP, most guest debugger subcommands require you to - * explicitly specify a guest vcpu using an index starting from zero. - * - */ diff --git a/src/l4/pkg/uvmm/doc/uvmm_dtg.md b/src/l4/pkg/uvmm/doc/uvmm_dtg.md deleted file mode 100644 index c667d709..00000000 --- a/src/l4/pkg/uvmm/doc/uvmm_dtg.md +++ /dev/null @@ -1,81 +0,0 @@ -# uvmm_dtg The device tree generator for Uvmm {#l4re_servers_uvmm_uvmm_dtg} - -A virtual machine in Uvmm is configured with a device tree that contains -information about the VMs resources, memory layout, virtual CPUs and -peripheral devices. - -Uvmm_dtg is a tool to generate such a device tree at runtime according to its -command line. - -## Usage in L4Re - -Example lua script for Ned: - - -- Create DS holding device tree - local dt = L4.Env.user_factory:create(L4.Proto.Dataspace, 4 * 1024):m("rw"); - - -- Start the generator - L4.default_loader:start( - { - caps = { dt = dt }, - }, "rom/uvmm_dtg dt"):wait(); - - -- Start uvmm - vmm.start_vm - { - ... - ext_caps = { dt = dt }, - fdt = "dt", - ... - } - -Please notice the `:wait()` when starting `uvmm_dtg`. This makes Ned pause -until uvmm_dtg has exited and put the device tree into the dataspace such that -Uvmm can commence. - -## Usage - -`uvmm_dtg [OPTION]... |--` - -* `--` - print to stdout - -* `file` - - On L4Re, the string given as `` is interpreted as a named capability - which needs to be backed by a sufficiently large Dataspace. On - Linux, a file with the given name is created. In both cases, - uvmm_dtg will output into the named file. - -### Options - -* `-h` - - Show help. - -* `--arch ` - - Select the target architecture. Valid options are `x86`, `x86_64`, `arm32`, - `arm64`, `mips32` and `mips64`. - -* `--format ` - - Select the output format. Available formats are: - `txt`: The device tree will be printed as plain text (`dts`). - `bin`: The device tree will be output as binary (`dtb`). - -* `--mem-base ` - - Configure the start of the memory distribution. `membase` can be defined in - both decimal and hex notations. uvmm_dtg rounds the given base up to the - platforms page size. - - This value can be overridden by memory devices with fixed addresses. - -* `--device ` - - This configures a device. - - To get a list of supported devices, use `--device help`. - - To get help for a specific device, use `--device devicename:help`. diff --git a/src/l4/pkg/uvmm/server/Makefile b/src/l4/pkg/uvmm/server/Makefile deleted file mode 100644 index 04ac0da0..00000000 --- a/src/l4/pkg/uvmm/server/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -PKGDIR ?= .. -L4DIR ?= $(PKGDIR)/../.. - -include $(L4DIR)/mk/subdir.mk diff --git a/src/l4/pkg/uvmm/server/include/cell.h b/src/l4/pkg/uvmm/server/include/cell.h deleted file mode 100644 index 7328128b..00000000 --- a/src/l4/pkg/uvmm/server/include/cell.h +++ /dev/null @@ -1,333 +0,0 @@ -#pragma once - -extern "C" { -#include -} - -#include -#include - -namespace Dtb { - -/** - * Cell provides data structures and methods to handle cell based properties - * - * Device trees contain properties described by cells. The properties are - * - stored in big endian - * - the number of cells is specified by other properties like - * \#address-cells, \#size-cells, \#interrupt-cells - * - a property has at most 4 cells - * - * Cells might be translated from one domain into another. The - * translation is done by comparing regions, calculating the offset - * relative to a region in the current domain and applying this offset - * to a region in another domain. Therefore cells need relational - * operation, addition and subtraction. - */ - -class Cell -{ -public: - enum - { - Max_size = 4 /**< Maximal number of allowed cells */ - }; - - static Cell make_cell(std::initializer_list l) - { - return Cell(l); - } - - /** - * Construct a default invalid cell - * - * An invalid cell is a tuple of {~0U, ~0U, ~0U, ~0U}. - */ - Cell() - { - for (auto &v: _values) - v = ~0U; - } - - /** - * Construct a Cell object from a device tree property - * - * \param values Pointer to the property values - * \param size Number of cells in the property; Must be smaller than - * Max_size. - */ - Cell(fdt32_t const *values, size_t size) - { - assert(size <= Max_size); - for (auto &v: _values) - v = 0; - - for (unsigned i = 0, offs = Max_size - size; i < size; ++i) - _values[offs + i] = fdt32_to_cpu(values[i]); - } - - uint32_t const &operator [] (size_t idx) const - { - assert(idx < Max_size); - return _values[idx]; - } - - /** - * Check whether a Cell object is valid - * - * The default constructor set the cell to {~0U, ~0U, ~0U, ~0U}. If - * the cell object contains anything else it is considered to be - * valid. - * - * \return bool true if the cell is different from {~0U, ~0U, ~0U, ~0U} - */ - bool is_valid() const - { - for (auto x: _values) - if (x != ~0U) - return true; - return false; - } - - /** - * Add two Cell objects - * - * We assume that cells are stored as 32 bit values in big endian - * order and can be added by simply adding the invidual 32 bit - * values and any overflow from a previous addition. - * - * We do not check whether there is an overflow when adding the - * highest 32 bit values. - */ - Cell operator + (Cell const &other) const - { - Cell result; - uint32_t carry = 0; - for (int i = Max_size - 1; i >= 0; --i) - { - uint64_t a = _values[i]; - uint64_t b = other._values[i]; - uint64_t res = a + b + carry; - carry = (res >> 32) ? 1 : 0; - result._values[i] = static_cast(res); - } - // XXX no overflow check yet - return result; - } - - /** - * Subtract a Cell object from another - * - * We assume that cells are stored as 32 bit values in big endian - * order and the difference can be calculate by simply subtracting - * the invidual 32 bit values and any overflow from a previous - * subtraction. - * - * We do not check whether a is larger than b in (a - b), which - * would lead to an overflow. - */ - Cell operator - (Cell const &other) const - { - Cell result; - uint32_t carry = 0; - for (int i = Max_size - 1; i >= 0; --i) - { - uint64_t a = _values[i]; - uint64_t b = other._values[i]; - uint64_t res = a - b - carry; - carry = (res >> 32) ? 1 : 0; - result._values[i] = static_cast(res); - } - // XXX no overflow check yet - return result; - } - - Cell operator & (Cell const &other) const - { - Cell result; - for (int i = 0; i < Max_size; i++) - result._values[i] = _values[i] & other._values[i]; - return result; - } - - Cell& operator &= (Cell const &other) - { - for (int i = 0; i < Max_size; i++) - _values[i] &= other._values[i]; - return *this; - } - - /** - * Relational operator Cell A < Cell B - */ - bool operator < (Cell const &other) const - { return cmp(other) == -1; } - - /** - * Relational operator Cell A <= Cell B - */ - bool operator <= (Cell const &other) const - { return cmp(other) != 1; } - - /** - * Relational operator Cell A == Cell B - */ - bool operator == (Cell const &other) const - { return cmp(other) == 0; } - - /** - * Relational operator Cell A != Cell B - */ - bool operator != (Cell const &other) const - { return cmp(other) != 0; } - - /** - * Relational operator Cell A >= Cell B - */ - bool operator >= (Cell const &other) const - { return cmp(other) != -1; } - - /** - * Relational operator Cell A > Cell B - */ - bool operator > (Cell const &other) const - { return cmp(other) == 1; } - - /** - * Check whether the cell object contains a valid memory address - * - * We consider any 32bit or 64bit value a valid memory address. If - * the cell contains anything other than 0 in the highest order - * values, it must be something else and cannot be interpreted as a - * memory address. - * - * \return bool true, if the cell contains a 32bit or 64bit value. - */ - bool is_uint64() const - { return !_values[0] && !_values[1]; } - - /** - * Get the memory address of this cell - * - * Returns the value of the cell as 64bit value. It asserts, that - * the cell actually contains something, that can be interpreted as - * memory address. - * - * \return uint64_t the cell contents as 64bit value - */ - uint64_t get_uint64() const - { - assert(is_uint64()); - return (static_cast(_values[2]) << 32) + _values[3]; - } - -private: - - Cell(std::initializer_list l) - { - assert(l.size() <= Max_size); - for (auto &v: _values) - v = 0; - - unsigned i = Max_size - l.size(); - for (uint32_t v : l) - _values[i++] = v; - } - - /** - * Compare two cell objects - * - * We assume that cells are stored as 32 bit values in big endian - * order and that we can compare them starting at the highest order - * value. - * - * \param Cell cell object to compare with - * \retval -1 cell is smaller than other cell - * \retval 0 cells are equal - * \retval 1 cells is larger than other cell - */ - int cmp(Cell const &other) const - { - unsigned i; - for (i = 0; i < Max_size; ++i) - { - if (_values[i] < other._values[i]) - return -1; - if (_values[i] > other._values[i]) - return 1; - } - return 0; - } - - uint32_t _values[Max_size]; -}; - -/** - * Data and methods associated with a range property in a device tree - * - * Ranges in a device tree describe to translation of regions from one - * domain to another. - */ -class Range -{ -public: - /** - * Translate an address from one domain to another - * - * This function takes an address cell and a size cell and - * translates the address from one domain to another if there is a - * matching range. - * - * \param[inout] address Address cell that shall be translated - * \param[in] size Size Size cell associated with the address - */ - bool translate(Cell *address, Cell const &size) - { - assert(address); - - if (match(*address, size)) - { - *address = (*address - _child) + _parent; - return true; - } - return false; - } - - Range(Cell const &child, Cell const &parent, Cell const &length) - : _child{child}, _parent{parent}, _length{length} {}; - -private: - // ranges: child, parent, length - // child.cells == this->cells - // parent.cells == parent.cells - Cell _child; - Cell _parent; - Cell _length; - - // [address, address + size] subset of [child, child + length] ? - bool match(Cell const &address, Cell const &size) const - { - Cell address_max = address + size; - Cell child_max = _child + _length; - return (_child <= address) && (address_max <= child_max); - } -}; - -/** - * Data and methods associated with a reg property in a device tree - */ -struct Reg -{ - Cell address; - Cell size; - - Reg(Cell const &address, Cell const &size) : address{address}, size{size} {}; - - bool operator == (Reg const &other) const - { return (address == other.address) && (size == other.size); } - - bool operator != (Reg const &other) const - { return !operator == (other); } -}; - -} // namespace Dtb diff --git a/src/l4/pkg/uvmm/server/include/device_tree.h b/src/l4/pkg/uvmm/server/include/device_tree.h deleted file mode 100644 index cf05f6b7..00000000 --- a/src/l4/pkg/uvmm/server/include/device_tree.h +++ /dev/null @@ -1,1376 +0,0 @@ -/* - * Copyright (C) 2015-2024 Kernkonzept GmbH. - * Author(s): Sarah Hoffmann - * - * License: see LICENSE.spdx (in this directory or the directories above) - */ -#pragma once - -#include -#include -#include -#include - -extern "C" { -#include -} - -#include "cell.h" - -namespace Dtb { - -/** - * Meta data about reg property. - * - * Depending on the bus type additionaly information is stored about a reg - * property in the high word of the child node address. - */ -class Reg_flags -{ - // Internally stored in PCI device tree binding representation. - enum - { - Reg_flags_pci_reg_mask = 0xff, - Reg_flags_pci_func_mask = 0x07, - Reg_flags_pci_func_shift = 8, - Reg_flags_pci_device_mask = 0x1f, - Reg_flags_pci_device_shift = 11, - Reg_flags_pci_bus_mask = 0xff, - Reg_flags_pci_bus_shift = 16, - - Reg_flags_type_mask = 0x03UL << 24, - Reg_flags_type_cfgspace = 0x00UL << 24, - Reg_flags_type_ioport = 0x01UL << 24, - Reg_flags_type_mmio_32 = 0x02UL << 24, - Reg_flags_type_mmio_64 = 0x03UL << 24, - - Reg_flags_aliased = 1UL << 29, - Reg_flags_mmio_prefetchable = 1UL << 30, - Reg_flags_non_relocatable = 1UL << 31, - }; - - Reg_flags(l4_uint32_t flags) : _flags(flags) {} - -public: - Reg_flags() = default; - Reg_flags(Reg_flags const &other) : _flags(other._flags) {} - - Reg_flags &operator=(Reg_flags const &other) - { _flags = other._flags; return *this; } - - static Reg_flags pci(l4_uint32_t f) { return Reg_flags(f); } - static Reg_flags ioport() { return Reg_flags(Reg_flags_type_ioport); } - static Reg_flags mmio() { return Reg_flags(Reg_flags_type_mmio_32); } - - inline bool is_cfgspace() const - { return (_flags & Reg_flags_type_mask) == Reg_flags_type_cfgspace; } - - inline bool is_ioport() const - { return (_flags & Reg_flags_type_mask) == Reg_flags_type_ioport; } - - inline bool is_mmio32() const - { return (_flags & Reg_flags_type_mask) == Reg_flags_type_mmio_32; } - - inline bool is_mmio64() const - { return (_flags & Reg_flags_type_mask) == Reg_flags_type_mmio_64; } - - inline bool is_mmio() const - { return is_mmio32() || is_mmio64(); } - - inline unsigned pci_reg() const - { return _flags & Reg_flags_pci_reg_mask; } - - inline unsigned pci_function() const - { return (_flags >> Reg_flags_pci_func_shift) & Reg_flags_pci_func_mask; } - - inline unsigned pci_device() const - { return (_flags >> Reg_flags_pci_device_shift) & Reg_flags_pci_device_mask; } - - inline unsigned pci_bus() const - { return (_flags >> Reg_flags_pci_bus_shift) & Reg_flags_pci_bus_mask; } - -private: - l4_uint32_t _flags = 0; -}; - -/** - * Wrapper around the actual device tree memory to allow results caching of - * certain functions. 'fdt' functions altering the tree have to use the - * implemented wrapper functions. 'fdt_' functions reading the tree use dt() to - * access the device tree memory read only. - * - * Additionally this class can handle external dt memory or manage a copy - * itself. - */ -class Fdt -{ -public: - Fdt() {} - Fdt(void *dtmem) : _dtmem(dtmem) {} - Fdt(Fdt const &o, int padding = 0) - : _owned(true) - { - size_t s = o.size() + padding; - _dtmem = malloc(s); - if (!_dtmem) - L4Re::chksys(-L4_ENOMEM, "Allocating memory for device tree."); - - memcpy(_dtmem, o.dt(), o.size()); - fdt_set_totalsize(_dtmem, s); - } - - ~Fdt() - { - if (_owned && _dtmem) - { - free(_dtmem); - _dtmem = nullptr; - } - } - - void resize(l4_size_t s) - { - _dtmem = realloc(_dtmem, s); - if (!_dtmem) - L4Re::chksys(-L4_ENOMEM, "Allocating memory for device tree."); - fdt_set_totalsize(_dtmem, s); - } - - size_t size() const - { return fdt_totalsize(_dtmem); } - - // read-only access - const void *dt() const - { return _dtmem; } - - void move(void *dst) - { - fdt_move(dt_rw(), dst, size()); - if (_owned) - free(_dtmem); - - _dtmem = nullptr; - } - - void pack() - { fdt_pack(dt_rw()); } - - int overlay_apply(void *fdt_overlay) - { return fdt_overlay_apply(dt_rw(), fdt_overlay); } - - int add_subnode(int node, char const *name) - { return fdt_add_subnode(dt_rw(), node, name); } - - int del_node(int node) - { return fdt_del_node(dt_rw(), node); } - - int setprop_u32(int node, char const *name, fdt32_t value) - { return fdt_setprop_u32(dt_rw(), node, name, value); } - - int setprop_u64(int node, char const *name, fdt64_t value) - { return fdt_setprop_u64(dt_rw(), node, name, value); } - - int setprop_string(int node, char const *name, char const *value) - { - int err = fdt_setprop_inplace_namelen_partial(_dtmem, node, name, - strlen(name), 0, value, - strlen(value) + 1); - if (err >= 0) - return err; - - return fdt_setprop_string(dt_rw(), node, name, value); - } - - int setprop(int node, char const *name, void const *data, int len) - { return fdt_setprop(dt_rw(), node, name, data, len); } - - int setprop_placeholder(int node, char const *name, int len, void **prop_data) - { return fdt_setprop_placeholder(dt_rw(), node, name, len, prop_data); } - - int setprop_inplace_namelen_partial(int node, - char const *name, int name_len, - uint32_t idx, void const *val, int len) - { - // That function does not change any node offset as it just replaces the - // property without changing its size. Hence, use _dtmem as flushing the - // caches is not necessary. - return fdt_setprop_inplace_namelen_partial(_dtmem, node, name, - name_len, idx, val, len); - } - - int appendprop_u32(int node, char const *name, fdt32_t value) - { return fdt_appendprop_u32(dt_rw(), node, name, value); } - - int appendprop_u64(int node, char const *name, fdt64_t value) - { return fdt_appendprop_u64(dt_rw(), node, name, value); } - - int delprop(int node, char const *name) - { return fdt_delprop(dt_rw(), node, name); } - - fdt32_t phandle(fdt32_t prop) const - { - int offs; - auto it = _phandles.find(prop); - if (it == _phandles.end()) - { - offs = fdt_node_offset_by_phandle(_dtmem, fdt32_to_cpu(prop)); - _phandles[prop] = offs; - } - else - offs = it->second; - - return offs; - } - - int parent(int node) const - { - int offs; - auto it = _parents.find(node); - if (it == _parents.end()) - { - offs = fdt_parent_offset(_dtmem, node); - _parents[node] = offs; - } - else - offs = it->second; - return offs; - } - -private: - // private write access - void *dt_rw() - { - _phandles.clear(); - _parents.clear(); - return _dtmem; - } - - // Caches - mutable std::map _phandles; - mutable std::map _parents; - - void *_dtmem = nullptr; - bool _owned = false; -}; - -template -class Node -{ - friend class Property; - -public: - enum - { - // Defaults according to include/linux/of.h, overridden with - // address_cells = 2 for sparc - Default_address_cells = 1, - Default_size_cells = 1, - }; - /** Additional error codes */ - enum - { - ERR_BAD_INDEX = FDT_ERR_MAX + 1, /**< An index into a structured - property like "reg" or - "range" was out of range */ - ERR_RANGE, /**< A cell value does not fit - into a 64bit value */ - ERR_NOT_TRANSLATABLE, /**< A reg value could not be - translated and is a bus - local address */ - ERR_REG_INVALID /**< An invalid "reg" value */ - }; - - static char const *strerror(int errval) - { - switch (errval) - { - case -ERR_BAD_INDEX: return "Index out of range"; - case -ERR_RANGE: return "Value does not fit into 64bit value"; - case -ERR_NOT_TRANSLATABLE: return "Reg entry is not translatable"; - case -ERR_REG_INVALID: return "Reg entry is invalid"; - default: return fdt_strerror(errval); - } - } - -public: - Node() : _node(-1) {} - Node(Fdt *dt, int node) : _fdt(dt), _node(node) {} - - bool operator == (Node const &other) const - { return (_fdt == other._fdt) && (_node == other._node); } - - bool operator != (Node const &other) const - { return !operator==(other); } - - bool is_valid() const - { return _node >= 0; } - - /** - * Add a subnode - * - * \param name Name of the new subnode - * - * \return New node or an invalid node (node offset equals the - * libfdt error) - */ - Node add_subnode(char const *name) - { return Node(_fdt, _fdt->add_subnode(_node, name)); } - - /** - * Delete a node - * - * \return 0 on success, negative fdt_error otherwise - */ - int del_node() - { - int res = _fdt->del_node(_node); - if (res == 0) - _node = -1; // invalidate node - return res; - } - - /** - * Get the next node of this tree - * - * \param depth Pointer to the depth of the current node; If not - * null, depth will be updated to reflect the depth of - * the returned node (unchanged for a sibling, depth + - * 1 for a child, depth - 1 for a sibling of the - * parent). - * - * \return Next node of the tree or an invalid node (node - * offset equals the libfdt error) - */ - Node next_node(int *depth = nullptr) const - { return Node(_fdt, fdt_next_node(_fdt->dt(), _node, depth)); } - - /** - * Get the next compatible node of this tree - * - * \param compatible 'compatible' string to match against - * - * \return Next compatible node of the tree or an invalid node (node - * offset equals the libfdt error) - */ - Node next_compatible_node(char const *compatible) const - { return Node(_fdt, fdt_node_offset_by_compatible(_fdt->dt(), _node, compatible)); } - - /** - * Get the first child node - * - * \return node The first child node or an invalid node (node offset - * equals the libfdt error) - */ - Node first_child_node() const - { return Node(_fdt, fdt_first_subnode(_fdt->dt(), _node)); } - - /** - * Get the next sibling - * - * \return node The next sibling or an invalid node (node offset - * equals the libfdt error) - */ - Node sibling_node() const - { return Node(_fdt, fdt_next_subnode(_fdt->dt(), _node)); } - - Node parent_node() const - { return Node(_fdt, _fdt->parent(_node)); } - - bool is_root_node() const - { return _node == 0; }; - - bool has_children() const - { return fdt_first_subnode(_fdt->dt(), _node) >= 0; } - - int get_depth() const - { return fdt_node_depth(_fdt->dt(), _node); } - - char const *get_name() const - { - if (is_root_node()) - return "/"; - - char const *name = fdt_get_name(_fdt->dt(), _node, nullptr); - return name ? name : ""; - } - - int get_cells_attrib(char const *name) const - { - if (!is_valid()) - return -FDT_ERR_BADSTRUCTURE; - - int size; - auto *prop = get_prop(name, &size); - - if (!prop) - return size; - - int val = fdt32_to_cpu(*prop); - if ((size != 1) || (val > FDT_MAX_NCELLS)) - return -FDT_ERR_BADNCELLS; - - return val; - } - - size_t get_cells_attrib_default(const char *name, int default_cells, - Node const &parent) const - { - int val = parent.get_cells_attrib(name); - if (val >= 0) - return val; - - if (val == -FDT_ERR_NOTFOUND) - { - // The spec states, that the address/size cells attribute - // should be attached to each node that has children. If it is - // missing the caller should assume 2 for #addr-cells and 1 - // for #size-cells (passed as parameter by the caller). - // - // It looks like some device trees assume the cells attributes - // of the root node as default, so we check the root node - // here, before returning the default value. - auto root_node = Node(_fdt, 0); // Tree::first_node() - val = root_node.get_cells_attrib(name); - if (val >= 0) - return val; - - if (val == -FDT_ERR_NOTFOUND) - return default_cells; - } - - ERR(this, "Unable to lookup %s: %s", name, fdt_strerror(val)); - return default_cells; - } - - size_t get_address_cells(Node const &parent) const - { - return get_cells_attrib_default("#address-cells", Default_address_cells, - parent); - } - - size_t get_size_cells(Node const &parent) const - { - return get_cells_attrib_default("#size-cells", Default_size_cells, - parent); - } - - void setprop_u32(char const *name, l4_uint32_t value) const - { - int r = _fdt->setprop_u32(_node, name, value); - if (r < 0) - ERR(this, "cannot set property '%s' to '0x%x': %s", name, value, - fdt_strerror(r)); - } - - void setprop_u64(char const *name, l4_uint64_t value) const - { - int r = _fdt->setprop_u64(_node, name, value); - if (r < 0) - ERR(this, "cannot set property '%s' to '0x%llx': %s", name, value, - fdt_strerror(r)); - } - - void setprop(char const *name, l4_uint64_t value, unsigned cells) const - { - switch (cells) - { - case 1: - if (value >= (1ULL << 32)) - ERR(this, "Value too large for property %s", name); - - setprop_u32(name, value); - break; - - case 2: - setprop_u64(name, value); - break; - - default: - ERR(this, "Unexpected property value cell size: %u", cells); - break; - } - } - - void setprop_string(char const *name, char const *value) const - { - int r = _fdt->setprop_string(_node, name, value); - if (r < 0) - ERR(this, "cannot set property '%s' to '%s'i: %s", name, value, - fdt_strerror(r)); - } - - void setprop_data(char const *name, void const *data, int len) const - { - int r = _fdt->setprop(_node, name, data, len); - if (r < 0) - ERR(this, "cannot set property '%s': %s", name, fdt_strerror(r)); - } - - void setprop_placeholder(char const *name, int len, void **prop_data) const - { - int r = _fdt->setprop_placeholder(_node, name, len, prop_data); - if (r < 0) - ERR(this, "cannot resize property '%s' to %d bytes: %s", name, len, - fdt_strerror(r)); - } - - void appendprop_u32(char const *name, l4_uint32_t value) const - { - int r = _fdt->appendprop_u32(_node, name, value); - if (r < 0) - ERR(this, "cannot append '0x%x' to property '%s': %s", value, name, - fdt_strerror(r)); - } - - void appendprop_u64(char const *name, l4_uint64_t value) const - { - int r = _fdt->appendprop_u64(_node, name, value); - if (r < 0) - ERR(this, "cannot append '0x%llx' to property '%s': %s", value, name, - fdt_strerror(r)); - } - - void appendprop(char const *name, l4_uint64_t value, unsigned cells) const - { - switch (cells) - { - case 1: - if (value >= (1ULL << 32)) - ERR(this, "Value too large for property: %s", name); - - appendprop_u32(name, value); - break; - - case 2: - appendprop_u64(name, value); - break; - - default: - ERR(this, "Unexpected property value cell size %u", cells); - break; - } - } - - /** - * Delete a property of this node - * - * \param name Name of the property to delete - * - * \return 0 on success, libfdt error codes otherwise - */ - int delprop(char const *name) const - { return _fdt->delprop(_node, name); } - - bool is_enabled() const - { - int lenp; - char const *p = get_prop("status", &lenp); - if (!p) - return true; - - return lenp > 2 && (!strncmp(p, "okay", lenp) || !strcmp(p, "ok")); - } - - /** - * Disable a device node. - * - * Linux treats a node as enabled if - * \li \c status == "ok" - * \li \c status == "okay" - * \li \c status property does not exist - * - * Linux convention for disabling a node: - * \li \c status == "disabled" - * - * Writing "disa" instead of "disabled" would increase the chance that an - * existing status == "okay" can be replaced without changing the property - * size. A change of the property size can change node offsets requiring a - * flush of the caches. However, as the documentation is not entirely clear - * about other status words for disabled nodes, we play safe. - */ - void disable() const - { setprop_string("status", "disabled"); } - - bool has_prop(char const *name) const - { - return fdt_getprop_namelen(_fdt->dt(), _node, name, strlen(name), nullptr) - != nullptr; - } - - bool has_compatible() const - { return has_prop("compatible"); } - - bool is_compatible(char const *compatible) const - { return fdt_node_check_compatible(_fdt->dt(), _node, compatible) == 0; } - - void get_path(char *buf, int buflen) const - { - int r = fdt_get_path(_fdt->dt(), _node, buf, buflen); - if (r < 0) - ERR(this, r, "cannot get path for node"); - } - - l4_uint32_t get_phandle() const - { return fdt_get_phandle(_fdt->dt(), _node); } - - int stringlist_count(char const *property) const - { return fdt_stringlist_count(_fdt->dt(), _node, property); } - - char const *stringlist_get(char const *property, int index, int *lenp) const - { return fdt_stringlist_get(_fdt->dt(), _node, property, index, lenp); } - - l4_uint64_t get_prop_val(fdt32_t const *prop, l4_uint32_t size, - bool check_range) const - { - l4_uint64_t val; - // fdt32_t is unsigned and guaranteed to be 4 byte aligned - switch (size) - { - case 1: - val = fdt32_to_cpu(*prop); - break; - - case 2: - val = (l4_uint64_t(fdt32_to_cpu(*prop)) << 32) - + fdt32_to_cpu(*(prop + 1)); - if (check_range && (sizeof(l4_addr_t) == 4) && (val >= (1ULL << 32))) - ERR(this, "property value too large for 32bit systems"); - - break; - - default: - ERR(this, "Invalid value for address/size cell: %d", size); - val = 0; - break; - } - return val; - } - - void set_prop_partial(char const *property, uint32_t idx, - const void *val, int len) const - { - int r = _fdt->setprop_inplace_namelen_partial(_node, - property, strlen(property), - idx, val, len); - if (r < 0) - ERR(this, "cannot update property '%s' partially (idx=%u, len=%d): %s", - property, idx, len, fdt_strerror(r)); - } - - /** - * Get address/size pair from reg property. - * - * Note that in case of a PCI device the `index` is the BAR register (0..5). - * - * \param[in] index Index of pair - * \param[out] address Store address in *address if address != 0 - * \param[out] size Store size in *size if size != 0 - * \param[out] flags Store Reg_flags of address - * - * \retval -ERR_BAD_INDEX node does not have a reg entry with the - * specified index - * \retval -ERR_RANGE a reg value does not fit into a 64bit value - * \retval -ERR_NOT_TRANSLATABLE reg entry exists, but is not translatable - * \retval <0 other fdt related errors - * \retval 0 ok - */ - int get_reg_val(int index, l4_uint64_t *address, l4_uint64_t *size, - Reg_flags *flags = nullptr) const - { - auto parent = parent_node(); - size_t addr_cells = get_address_cells(parent); - size_t size_cells = get_size_cells(parent); - int rsize = addr_cells + size_cells; - - int prop_size; - auto *prop = get_prop(parent.is_pci_bus() ? "assigned-addresses" - : "reg", - &prop_size); - if (!prop && prop_size < 0) - return prop_size; - - if (!prop) - return -FDT_ERR_INTERNAL; - - if (prop_size < rsize * (index + 1)) - return -ERR_BAD_INDEX; - - prop += rsize * index; - - Reg reg{Cell{prop, addr_cells}, Cell(prop + addr_cells, size_cells)}; - bool res = translate_reg(parent, ®); - - if (!reg.address.is_uint64() || !reg.size.is_uint64()) - return -ERR_RANGE; - - if (address) - *address = reg.address.get_uint64(); - if (size) - *size = reg.size.get_uint64(); - if (flags) - *flags = parent.get_flags(prop); - - return res ? 0 : -ERR_NOT_TRANSLATABLE; - } - - /** - * Get base/size pair from IO reg property. - * - * This is a convenience method for accessing an IO reg propery. - * - * \param[in] index Index of pair - * \param[out] base Store base in *base if base != 0 - * \param[out] size Store size in *size if size != 0 - * - * \retval -ERR_REG_INVALID Node is not an IO reg property - * \retval <0 Error from #get_reg_val - * \retval 0 Success - */ - int get_reg_io(int index, l4_uint64_t *base, l4_uint64_t *size) const - { - Dtb::Reg_flags flags; - int res = get_reg_val(index, base, size, &flags); - if (res < 0) - return res; - - if (!flags.is_ioport()) - return -ERR_REG_INVALID; - - return 0; - } - - /** - * Get size and/or flags of reg entry. - * - * \param[in] index Index of reg property entry - * \param[out] size Store size in *size if size != 0 - * \param[out] flags Store Reg_flags of address if flags != 0 - * - * The reg property is not translated into the root address space. In case - * of a PCI device the `flags` will hold the information about type and - * BAR register index. - */ - int get_reg_size_flags(int index, l4_uint64_t *size, Reg_flags *flags) const - { - auto parent = parent_node(); - size_t addr_cells = get_address_cells(parent); - size_t size_cells = get_size_cells(parent); - int rsize = addr_cells + size_cells; - - int prop_size; - auto *prop = get_prop("reg", &prop_size); - if (!prop && prop_size < 0) - return prop_size; - - if (!prop) - return -FDT_ERR_INTERNAL; - - if (prop_size < rsize * (index + 1)) - return -ERR_BAD_INDEX; - - prop += rsize * index; - - Cell sz(prop + addr_cells, size_cells); - if (!sz.is_uint64()) - return -ERR_RANGE; - - if (size) - *size = sz.get_uint64(); - if (flags) - *flags = parent.get_flags(prop); - - return 0; - } - - /** - * Set address/size pair of reg property - * - * \param[in] address Address value to store in reg pair - * \param[in] size Size value to store in reg pair - * \param[in] append true, if reg val is supposed to be appended - * - * This function throws an exception if "reg" property does not exist. - */ - void set_reg_val(l4_uint64_t address, l4_uint64_t size, bool append = false) const - { - auto parent = parent_node(); - size_t addr_cells = get_address_cells(parent); - size_t size_cells = get_size_cells(parent); - - if (append) - appendprop("reg", address, addr_cells); - else - setprop("reg", address, addr_cells); - - appendprop("reg", size, size_cells); - } - - /** - * Append address/size pair to reg property - * - * \param[in] address Address value to store in reg pair - * \param[in] size Size value to store in reg pair - * - * This function throws an exception if "reg" property does not exist. - */ - void append_reg_val(l4_uint64_t address, l4_uint64_t size) const - { - set_reg_val(address, size, true); - } - - /** - * Update the address part of a reg property in-place. - * - * \param[in] idx Index of address/size pair in reg property - * \param[in] address New address value to store in reg pair - * - * This function throws an exception if "reg" property does not exist. - */ - void update_reg_address(uint32_t idx, uint64_t address) const - { update_reg_val(idx, idx, address); } - - /** - * Update the size part of a reg property in-place. - * - * \param[in] idx Index of address/size pair in reg property - * \param[in] size New size value to store in reg pair - * - * This function throws an exception if "reg" property does not exist. - */ - void update_reg_size(uint32_t idx, uint64_t size) const - { update_reg_val(idx + 1, idx, size); } - - /** - * Resize the reg property to the specified number of address/size pairs. - * - * \param[in] num_regs Number of address/size pairs to reserve space for - * - * When shrinking the property (= new size is smaller than current size) - * the existing values are preserved. When growing the property (= new size - * is larger than current size, or property does not exist yet) additional - * space is reserved but left uninitialized. - * - * This function throws an exception if the device tree cannot be resized. - */ - void resize_reg(int num_regs) const - { - auto parent = parent_node(); - size_t addr_cells = get_address_cells(parent); - size_t size_cells = get_size_cells(parent); - int len = (addr_cells + size_cells) * num_regs * sizeof(fdt32_t); - void *prop_data; - setprop_placeholder("reg", len, &prop_data); - } - - /** - * Set address value - * - * \param[in] address Address value to store - * - * This function throws an exception if "reg" property does not exist. - */ - void set_prop_address(char const *property, l4_addr_t address) const - { - switch (sizeof(address)) - { - case 4: - setprop_u32(property, address); - break; - case 8: - setprop_u64(property, address); - break; - default: - static_assert((sizeof(address) == 4) || (sizeof(address) == 8), - "Unexpected address size"); - } - } - - /** - * Check whether a node has irq resources associated - * - * This function checks whether the node has an "interrupts" - * or "interrupts-extended" property. - * - * \return True if there is an "interrupts" property. - */ - bool has_irqs() const - { return has_prop("interrupts") || has_prop("interrupts-extended"); } - - - /** - * Check whether a node has mmio resources associated - * - * This function checks whether the node has "reg" properties and - * any of the reg property values are mapped to mmio resources on - * the root bus. - * - * \return True if there are mmio resources - */ - bool has_mmio_regs() const; - - /** - * Translate a reg entry - * - * Reg entries are bus local information. To get an address valid on - * the "root bus" we have to traverse the tree and translate the reg - * entry using ranges properties. If we reach the root node, the - * translation was successful and reg contains the translated - * address. If any of the intermediate nodes is unable to translate - * the reg, the translation fails and reg is not changed. - * - * \param parent Parent node. Performance optimization. - * \param[inout] reg Pointer to reg structures which shall be - * translated. If the translation was successful, - * *reg contains the translated values. - * \return True if the translation was successful. - */ - bool translate_reg(Node const &parent, Reg *reg) const - { - if (is_root_node()) - return true; - - Cell tmp{reg->address}; - if (!translate_reg(parent, &tmp, reg->size)) - return false; - - reg->address = tmp; - return true; - } - - template - T const *get_prop(char const *name, int *size) const - { - void const *p = fdt_getprop_namelen(_fdt->dt(), _node, name, strlen(name), size); - - if (p && size) - *size /= sizeof(T); - - return reinterpret_cast(p); - } - - template - T const *check_prop(char const *name, int size) const - { - int len; - void const *prop = fdt_getprop_namelen(_fdt->dt(), _node, name, strlen(name), - &len); - if (!prop) - ERR(this, "could not get property '%s': %s", name, fdt_strerror(len)); - - if (len < static_cast(sizeof(T)) * size) - ERR(this, "property '%s' is too small (%d need %u)", - name, len, static_cast(sizeof(T) * size)); - - return reinterpret_cast(prop); - } - - Node find_phandle(fdt32_t prop) const - { return Node(_fdt, _fdt->phandle(prop)); } - - /** - * Find IRQ parent of node. - * - * \return The node of the IRQ parent or an invalid node, if no parent is - * found. - * - * Traverses the device tree upwards and tries to find the IRQ parent. If no - * IRQ parent is found or the IRQ parent is identical to the node itself an - * invalid node is returned. - */ - Node find_irq_parent() const - { - Node node = *this; - - while (node.is_valid()) - { - int size = 0; - auto *prop = node.get_prop("interrupt-parent", &size); - - if (prop) - node = (size > 0) ? find_phandle(*prop) : Node(_fdt, -1); - else - node = node.parent_node(); - - if (node.is_valid() && node.has_prop("#interrupt-cells")) - { - if (node != *this) - return node; - else - break; - } - } - - return Node(_fdt, -1); - } - - template - void scan_recursive(int depth, - PRE &&pre_order_cb, POST &&post_order_cb, - bool skip_disabled = true) const; - -private: - /** - * Update the address or size part of a reg property in-place. - * - * \param[in] addr_idx Number of address cells to skip from the beginning - * \param[in] size_idx Number of size cells to skip from the beginning - * \param[in] val New value to store in reg pair - * - * To update the address part, addr_idx should be equal to size_idx. - * To update the size part, addr_idx = size_idx + 1. - * This function throws an exception if "reg" property does not exist. - */ - void update_reg_val(uint32_t addr_idx, uint32_t size_idx, uint64_t val) const - { - auto parent = parent_node(); - size_t addr_cells = get_address_cells(parent); - size_t size_cells = get_size_cells(parent); - - unsigned poff = (addr_idx * addr_cells + size_idx * size_cells) * sizeof(fdt32_t); - unsigned cells = addr_idx > size_idx ? size_cells : addr_cells; - switch (cells) - { - case 1: - { - fdt32_t tmp = cpu_to_fdt32(val); - set_prop_partial("reg", poff, &tmp, sizeof(tmp)); - break; - } - case 2: - { - fdt64_t tmp = cpu_to_fdt64(val); - set_prop_partial("reg", poff, &tmp, sizeof(tmp)); - break; - } - default: - ERR(this, "Unexpected cell size %u", cells); - } - } - - - /** - * Translate a (address, size) cell pair - * - * Reg entries are bus local information. To get an address valid on - * the "root bus" we have to traverse the tree and translate the reg - * entry using ranges properties. If we reach the root node, the - * translation was successful and reg contains the translated - * address. If any of the intermediate nodes is unable to translate - * the reg, the translation fails and reg is not changed. - * - * \param parent Parent node. Performance optimization. - * \param[inout] address Pointer to address cell which shall be - * translated. If the translation was - * successful, *address contains the - * translated values. - * \param[in] size Size cell describing the size of the region - * \return True if the translation was successful. - */ - bool translate_reg(Node const &parent, Cell *address, Cell const &size) const; - - /** - * Get flags from reg property of a child. - * - * Depending on the bus type, the first reg property word has some - * information about the reg entry. - * - * \param[in] reg Pointer first word of reg property - */ - Reg_flags get_flags(fdt32_t const *reg) const - { - Reg_flags ret; - - l4_uint32_t addr = fdt32_to_cpu(*reg); - if (is_pci_bus()) - ret = Reg_flags::pci(addr); - else if (is_isa_bus()) - ret = (addr & 0x01U) ? Reg_flags::ioport() : Reg_flags::mmio(); - else - ret = Reg_flags::mmio(); - - return ret; - } - - bool is_pci_bus() const - { - char const *devtype = get_prop("device_type", nullptr); - return devtype && strcmp(devtype, "pci") == 0; - } - - bool is_isa_bus() const - { - char const *devtype = get_prop("device_type", nullptr); - if (!devtype) - return false; - - return strcmp(devtype, "isa") == 0 || strcmp(devtype, "eisa") == 0; - } - - Fdt *_fdt = nullptr; - int _node; -}; - -template -class Tree -{ -public: - typedef Dtb::Node Node; - explicit Tree(Fdt *dt) : _fdt(dt) {} - - void check_tree() - { - if (fdt_check_header(_fdt->dt()) < 0) - ERR("Not a device tree"); - } - - unsigned size() const - { return _fdt->size(); } - - /** - * Apply the device tree overlay at 'fdt_overlay'. - * - * \param fdt_overlay address of the device tree overlay which - * should be applied to this device tree. - * \param name name of the overlay for logging purposes. - * - * \note The overlay device tree is changed as well. Its magic value - * is invalidated on success. - */ - void apply_overlay(void *fdt_overlay, char const *name) - { - int ret = _fdt->overlay_apply(fdt_overlay); - if (ret < 0) - ERR("cannot apply overlay '%s': %s\n", name, fdt_strerror(ret)); - } - - Node first_node() const - { return Node(_fdt, 0); } - - /** - * Get the first compatible node of this tree - * - * \param compatible 'compatible' string to match against - * - * \return First compatible node of the tree or an invalid node (node - * offset equals the libfdt error) - */ - Node first_compatible_node(char const *compatible) const - { return Node(_fdt, fdt_node_offset_by_compatible(_fdt->dt(), -1, compatible)); } - - /** - * Return the node at the given path. - * - * \throws No node could be found for the path. - */ - Node path_offset(char const *path) const - { - int ret = fdt_path_offset_namelen(_fdt->dt(), path, strlen(path)); - if (ret < 0) - ERR("cannot find node '%s'", path); - - return Node(_fdt, ret); - } - - template - void scan(PRE &&pre_order_cb, POST &&post_order_cb, - bool skip_disabled = true) const; - - /** - * Delete all nodes with specific property value and status. - * - * \param prop Property to compare. - * \param value Node is deleted if `prop` has this value. - * \param delete_disabled Delete only disabled nodes if true, otherwise - * delete all - * - * \return 0 on success, negative fdt_error otherwise - */ - int remove_nodes_by_property(char const *prop, char const *value, - bool delete_disabled) const - { - Node node = first_node(); - - while (node.is_valid()) - { - int prop_size; - char const *property; - - property = node.template get_prop(prop, &prop_size); - - if ( (property && strncmp(value, property, prop_size) == 0) - && (!delete_disabled || !node.is_enabled())) - { - int err = node.del_node(); - if (err) - return err; - - // node was deleted and is invalid. The documentation - // states that some node offsets changed (without - // specifying which ones) - so we do not try anything - // clever (like continuing with the last known node) and - // simply restart at the beginning. Since we usually only - // have one or two memory nodes this seems to be ok. - node = first_node(); - } - else - node = node.next_node(); - } - - return 0; - } - -private: - Fdt *_fdt; -}; - -template -bool -Node::translate_reg(Node const &parent, Cell *address, Cell const &size) const -{ - static Cell no_reg_mask; - static Cell pci_bus_reg_mask = Cell::make_cell({0x03000000U, 0xffffffffU, 0xffffffffU}); - static Cell isa_bus_reg_mask = Cell::make_cell({0x0000'0001U, 0xffff'ffffU}); - - if (parent.is_root_node()) - return true; - - int prop_size; - auto prop = parent.template get_prop("ranges", &prop_size); - if (!prop) - return false; // no translation possible - - if (!prop_size) - return true; // Ident mapping - - auto child_addr = get_address_cells(parent); - auto parent_parent = parent.parent_node(); - auto parent_addr = parent.get_address_cells(parent_parent); - auto child_size = get_size_cells(parent); - - Cell const *mask = &no_reg_mask; - if (parent.is_pci_bus()) - { - if (child_addr != 3 || child_size != 2) - ERR(this, "Invalid reg size %u/%u", child_addr, child_size); - - mask = &pci_bus_reg_mask; - *address &= pci_bus_reg_mask; - } - else if (parent.is_isa_bus()) - { - if (child_addr != 2 || child_size != 1) - ERR(this, "Invalid reg size %u/%u", child_addr, child_size); - - mask = &isa_bus_reg_mask; - *address &= isa_bus_reg_mask; - } - - unsigned range_size = child_addr + parent_addr + child_size; - if (prop_size % range_size != 0) - ERR("%s: Unexpected property size %d/%d/%d vs %d", - get_name(), child_addr, parent_addr, child_size, - prop_size); - - for (auto end = prop + prop_size; prop < end; prop += range_size) - { - Range range{Cell(prop, child_addr) & *mask, - Cell(prop + child_addr, parent_addr), - Cell(prop + child_addr + parent_addr, child_size)}; - if (range.translate(address, size)) - return parent.translate_reg(parent_parent, address, size); - } - return false; -} - -template -bool -Node::has_mmio_regs() const -{ - int prop_size; - auto prop = get_prop("reg", &prop_size); - if (!prop) - return false; - - auto parent = parent_node(); - size_t addr_cells = get_address_cells(parent); - size_t size_cells = get_size_cells(parent); - size_t reg_size = addr_cells + size_cells; - size_t num_regs = prop_size/reg_size; - - if (prop_size % reg_size != 0) - ERR(this, "Unexpected property size %zd/%zd vs %zd", - addr_cells, size_cells, prop_size); - - for (size_t i = 0; i < num_regs; ++i, prop += reg_size) - { - Reg reg{Cell{prop, addr_cells}, Cell(prop + addr_cells, size_cells)}; - if (translate_reg(parent, ®)) - return true; - } - return false; -} - -/** - * Traverse a subtree and invoke callbacks on all nodes - * - * This function traverses the sub-tree starting at node - * and invokes a pre-order and a post-order callback on - * each node. It considers the "enabled" state (ignores - * disabled nodes by default) and does not visit children - * of a node if the pre-order callback returns false. - * - * \param node Device tree node the traversal shall start on - * \param pre_order_cb A callback function invoked before traversing - * subtrees. The callback gets two arguments: the - * current node and the current depth in the tree - * (cb(Dtb::Node const, int)). It should - * return true, if the traversal shall visit child - * nodes. - * \param post_order_cb A callback function invoked after traversing - * the subtree. It gets the same arguments as the - * pre_order_cb, return values are ignored. - */ -template -template -void -Node::scan_recursive(int depth, - PRE &&pre_order_cb, POST &&post_order_cb, - bool skip_disabled) const -{ - assert(is_valid()); - - if (skip_disabled && !is_enabled()) - return; - - if (!pre_order_cb(*this, depth)) - return; - - // scan child nodes - for (auto child_node = first_child_node(); - child_node.is_valid(); - child_node = child_node.sibling_node()) - child_node.scan_recursive(depth + 1, std::forward
(pre_order_cb),
-                              std::forward(post_order_cb),
-                              skip_disabled);
-
-  post_order_cb(*this, depth);
-}
-
-/**
- * Traverse the device tree and invoke callbacks on all nodes
- *
- * This function invokes scan_node on the root node of the tree.
- */
-template 
-template 
-inline void
-Tree::scan(PRE &&pre_order_cb, POST &&post_order_cb,
-                bool skip_disabled) const
-{
-  auto first = first_node();
-  int depth = 0;
-  first.scan_recursive(depth, std::forward
(pre_order_cb),
-                       std::forward(post_order_cb), skip_disabled);
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi.h
deleted file mode 100644
index ea68a125..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi.h
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (C) 2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Benjamin Lamowski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * \file
- * Basic ACPI tables.
- *
- * Adapted from the ACPI Specification version 6.3.
- * Currently only implements the ACPI tables necessary to make Linux find local
- * APICs for SMP.
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "guest.h"
-#include "cpu_dev_array.h"
-#include "cpu_dev.h"
-#include "ioapic.h"
-#include "virt_lapic.h"
-#include "mem_types.h"
-
-extern "C" {
-#include "platform/acenv.h"
-#include "actypes.h"
-#include "actbl.h"
-}
-
-namespace Acpi
-{
-static Dbg info(Dbg::Dev, Dbg::Info, "ACPI");
-static Dbg warn(Dbg::Dev, Dbg::Warn, "ACPI");
-static Dbg trace(Dbg::Dev, Dbg::Trace, "ACPI");
-
-class Tables;
-class Acpi_device;
-/**
- * Registry of devices that need to insert information into ACPI tables.
- *
- * Upon Uvmm startup devices will be created from the device tree. These can
- * register themselves here. The Acpi::Tables class will then call the
- * Acpi_device functions of these devices to fill the ACPI tables. It will
- * also delete the Acpi_device_hub after use.
- */
-class Acpi_device_hub
-{
-  friend class Tables;
-public:
-  static void register_device(Acpi_device const *dev)
-  { get()->_devices.push_back(dev); }
-
-private:
-  static Acpi_device_hub *get()
-  {
-    if (!_hub)
-      _hub = new Acpi_device_hub();
-    return _hub;
-  }
-
-  std::vector const &devices() const
-  {
-    return _devices;
-  }
-
-  static void destroy()
-  {
-    if (_hub)
-      delete _hub;
-    _hub = nullptr;
-  }
-
-  Acpi_device_hub() = default;
-  ~Acpi_device_hub() = default;
-  static Acpi_device_hub *_hub;
-  std::vector _devices;
-};
-
-/**
- * Devices that must register with ACPI shall implement this interface.
- */
-class Acpi_device
-{
-public:
-  explicit Acpi_device()
-  {
-    Acpi_device_hub::register_device(this);
-  }
-
-  virtual void amend_fadt(ACPI_TABLE_FADT *) const {};
-  virtual l4_size_t amend_mcfg(ACPI_MCFG_ALLOCATION *, l4_size_t) const { return 0; };
-
-  /**
-   * Amend the DSDT ACPI table (highest priority).
-   *
-   * This method is executed before all the #amend_dsdt_late methods of all
-   * ACPI devices.
-   */
-  virtual l4_size_t amend_dsdt(void *, l4_size_t) const { return 0; };
-
-  /**
-   * Amend the DSDT ACPI table (lowest priority).
-   *
-   * This method is executed after all the #amend_dsdt methods of all ACPI
-   * devices. This is especially useful if the amendment refers to a scope
-   * that needs to be already defined before.
-   */
-  virtual l4_size_t amend_dsdt_late(void *, l4_size_t) const { return 0; };
-};
-
-/**
- * Singleton for access to the FACS table.
- *
- * Used by ACPI platform to acquire the wakeup vector and zeropage to reserve
- * the FACS location in guest memory in the e820 map.
- */
-class Facs_storage
-{
-public:
-  static Facs_storage *get()
-  {
-    if (!_facs_storage)
-      _facs_storage = new Facs_storage();
-    return _facs_storage;
-  }
-
-  void set_addr(ACPI_TABLE_FACS *table) { _facs = table; }
-  void set_gaddr(l4_addr_t gaddr) { _gfacs = Vmm::Guest_addr(gaddr); }
-  l4_uint32_t waking_vector() const { return _facs->FirmwareWakingVector; }
-  Vmm::Region mem_region() const
-  {
-    assert(_gfacs.get() != 0);
-
-    return Vmm::Region::ss(_gfacs, sizeof(ACPI_TABLE_FACS),
-                           Vmm::Region_type::Ram);
-  }
-
-private:
-  Facs_storage() = default;
-  ~Facs_storage() = default;
-
-  static Facs_storage *_facs_storage;
-  ACPI_TABLE_FACS *_facs;
-  Vmm::Guest_addr _gfacs;
-};
-
-// Interrupt override data for MADT table
-// see ACPI Spec v6.3, 5.2.12.5 Interrupt Source Override Structure
-struct Madt_int_override
-{
-  l4_uint8_t src_irq;
-  l4_uint32_t gsi;
-  l4_uint16_t flags;
-};
-
-// Static storage management for interrupt override entries
-class Madt_int_override_storage
-{
-public:
-  static Madt_int_override_storage *get()
-  {
-    if (!_self)
-      _self = new Madt_int_override_storage();
-    return _self;
-  }
-
-  void add_override(Madt_int_override new_override)
-  { _overrides.push_back(new_override); }
-
-  std::vector const &overrides() const
-  { return _overrides; }
-
-private:
-  Madt_int_override_storage() = default;
-  ~Madt_int_override_storage() = default;
-
-  static Madt_int_override_storage *_self;
-  std::vector _overrides;
-};
-
-/**
- * ACPI control.
- *
- * Manage the creation of ACPI tables in guest memory.
- */
-class Tables
-{
-public:
-  ~Tables()
-  {
-    Acpi_device_hub::destroy();
-  }
-
-protected:
-  enum Table_sizes : l4_size_t
-  {
-    Header_size = sizeof(ACPI_TABLE_HEADER),
-    Rsdp_size = sizeof(ACPI_TABLE_RSDP),
-    Rsdp_v1_size = sizeof(ACPI_RSDP_COMMON),
-    Facs_size = sizeof(ACPI_TABLE_FACS)
-  };
-
-  enum class Table : unsigned
-  {
-    Rsdt,
-    Xsdt,
-    Fadt,
-    Madt,
-    Mcfg,
-    Facs,
-    Dsdt,
-    Num_values,
-  };
-
-  /**
-   * Helps with generating ACPI structures by providing abstractions for common
-   * operations, table references and checksums.
-   *
-   * Table reference fields and checksum fields are not filled in immediately,
-   * but instead a list of fixups is kept for them. Firstly, this simplifies the
-   * creation of ACPI structures, since the size and layout of the tables no
-   * longer have to be calculated in advance, which is particularly tricky for
-   * dynamically-sized tables. Secondly, this allows a more flexible use of the
-   * generated ACPI structures, since they can now be relocated to arbitrary
-   * memory addresses thanks to the fixups.
-   */
-  class Writer
-  {
-  public:
-    Writer(l4_addr_t buf_addr, unsigned buf_size)
-    : _buf_addr(buf_addr), _buf_size(buf_size), _pos(0)
-    {}
-
-    /**
-     * Return current write position.
-     */
-    unsigned pos() const
-    { return _pos; }
-
-    /**
-     * Return number of unused bytes remaining in the write buffer.
-     */
-    unsigned remaining_size() const
-    { return _buf_size - _pos; }
-
-    /**
-     * Register the given ACPI table to start at the current write position, if
-     * necessary adjusted to the tables alignment requirements. Then reserve
-     * memory for the ACPI table.
-     *
-     * \tparam T      Type of the table.
-     * \param  table  Table
-     * \param  len    Length of memory to reserve for the table.
-     * \param  align  Alignment required by the table.
-     */
-    template
-    T *start_table(Table table, unsigned len = sizeof(T), unsigned align = 8)
-    {
-      if (_pos % align != 0)
-        reserve(align - (_pos % align));
-
-      _tables[static_cast(table)] = _pos;
-      return reserve(len);
-    }
-
-    /**
-     * Reserve memory.
-     *
-     * \tparam T    Type to reserve memory for.
-     * \param  len  Length of the memory to reserve, defaults to size of T.
-     */
-    template
-    T *reserve(unsigned len = sizeof(T))
-    {
-      if (_pos + len > _buf_size)
-        {
-          Err().printf("ACPI table memory allocation exhausted. "
-                       "Please configure less ACPI devices "
-                       "or raise the ACPI table size limit.\n");
-          L4Re::throw_error(-L4_ENOMEM, "ACPI table memory allocation exhausted.");
-        }
-
-      T *base = as_ptr(_pos);
-      _pos += len;
-      return base;
-    }
-
-    /**
-     * Write an identifier with correct padding.
-     *
-     * \param dest   Pointer to the memory destination.
-     * \param value  String to write.
-     * \param len    Length of the identifier field.
-     */
-    static void write_identifier(char *dest, char const *value, l4_size_t len)
-    {
-      auto value_length = strlen(value);
-
-      assert(value_length <= len && "Supplied identifier fits into field.");
-
-      memcpy(dest, value, value_length);
-      memset(dest + value_length, ' ', len - value_length);
-    }
-
-    /**
-     * Write a common header for ACPI tables as defined in section 5.2.6 of the
-     * ACPI Specification.
-     *
-     * \param h    Table header.
-     * \param sig  Signature as described in Table 5-29.
-     * \param rev  Revision of the table.
-     * \param len  Total length of the table.
-     */
-    void write_header(ACPI_TABLE_HEADER *h, char const *sig, l4_uint8_t rev,
-                      l4_uint32_t len)
-    {
-      memcpy(h->Signature, sig, ACPI_NAMESEG_SIZE);
-      h->Length = len;
-      h->Revision = rev;
-      add_checksum(&h->Checksum, h, len);
-      write_identifier(h->OemId, "L4RE", ACPI_OEM_ID_SIZE);
-      write_identifier(h->OemTableId, "UVMM", ACPI_OEM_TABLE_ID_SIZE);
-      h->OemRevision = 1;
-      memcpy(h->AslCompilerId, "UVMM", ACPI_NAMESEG_SIZE);
-      h->AslCompilerRevision = 1;
-    }
-
-    /**
-     * Write header for a table and automatically determine size as delta
-     * between start position of the table and the current position of the
-     * writer.
-     *
-     * Useful for tables with dynamic size.
-     *
-     * \param h    Table header, must be at the very beginning of the table.
-     * \param sig  Signature as described in Table 5-29.
-     * \param rev  Revision of the table.
-     */
-    void end_table(ACPI_TABLE_HEADER *h, char const *sig, l4_uint8_t rev)
-    {
-      write_header(h, sig, rev, _pos - as_offset(h));
-    }
-
-    /**
-     * Reserve an MADT subtable and write its header.
-     *
-     * \tparam T     Type of the MADT subtable.
-     * \param  type  MADT subtable type.
-     */
-    template
-    T *reserve_madt_subtable(enum AcpiMadtType type)
-    {
-      T *subtable = reserve();
-      subtable->Header.Type = type;
-      subtable->Header.Length = sizeof(T);
-      return subtable;
-    }
-
-    /**
-     * Add fixup for table reference field.
-     *
-     * \tparam T     Type of the table reference field.
-     * \param  ref   Table reference field.
-     * \param  table Table that is referenced.
-     */
-    template
-    void add_table_ref(T const *ref, Table table)
-    {
-      _table_refs.emplace_back(Table_ref{as_offset(ref), sizeof(T), table});
-    }
-
-    /**
-     * Add fixup for checksum field.
-     *
-     * \param  checksum  Checksum field.
-     * \param  base      Pointer to start of memory area to checksum.
-     * \param  len       Length of the memory area to checksum.
-     */
-    void add_checksum(l4_uint8_t *checksum, void *base, unsigned len)
-    {
-      // Although we do not calculate the checksum here, ensure that the
-      // checksum field is zeroed, which is required for checksum computation.
-      *checksum = 0U;
-      _checksums.emplace_back(Checksum{as_offset(checksum),
-                                       as_offset(base), len});
-    }
-
-    /**
-     * Table reference placeholder.
-     */
-    struct Table_ref
-    {
-      /// Offset of table reference field in write buffer.
-      unsigned offset;
-      /// Size of table reference field.
-      unsigned size;
-      /// Table that is referenced.
-      Table table;
-    };
-
-    /**
-     * Checksum placeholder.
-     */
-    struct Checksum
-    {
-      /// Offset of checksum field in write buffer.
-      unsigned field_off;
-      /// Offset of the memory area to checksum in write buffer.
-      unsigned offset;
-      /// Length of the memory area to checksum.
-      unsigned len;
-    };
-
-    /// Return table reference placeholders.
-    std::vector const &table_refs() const { return _table_refs; }
-    /// Return checksum placeholders.
-    std::vector const &checksums() const { return _checksums; }
-
-    /**
-     * Return start offset of the given table.
-     */
-    unsigned table_offset(Table table) const
-    { return _tables[static_cast(table)]; }
-
-    /**
-     * Convert offset into virtual address.
-     */
-    l4_addr_t as_addr(unsigned offset) const
-    {
-      assert(offset < _buf_size);
-      return _buf_addr + offset;
-    }
-
-    /**
-     * Convert offset into pointer.
-     */
-    template
-    T *as_ptr(unsigned offset) const
-    { return reinterpret_cast(as_addr(offset)); }
-
-  private:
-    unsigned as_offset(void const *ptr) const
-    {
-      l4_addr_t addr = reinterpret_cast(ptr);
-      assert(addr >= _buf_addr);
-      return addr - _buf_addr;
-    }
-
-    l4_addr_t _buf_addr;
-    unsigned _buf_size;
-    unsigned _pos;
-    std::array(Table::Num_values)> _tables;
-    std::vector _table_refs;
-    std::vector _checksums;
-  }; // class Writer
-
-  /**
-   * Write a Root System Description Pointer (RSDP).
-   *
-   * Base ACPI structure as defined in section 5.2.5 of the ACPI Specification.
-   * This class includes the ACPI 2.0+ extensions.
-   */
-  static void write_rsdp(Writer &wr)
-  {
-    auto *t = wr.reserve(Rsdp_size);
-    memcpy(t->Signature, ACPI_SIG_RSDP, sizeof(t->Signature));
-    wr.add_checksum(&t->Checksum, t, Rsdp_v1_size);
-    wr.write_identifier(t->OemId, "L4RE", ACPI_OEM_ID_SIZE);
-    if (Vmm::Cpu_dev::get_max_vcpu_id() >= 0xff)
-      t->Revision = 4; // needs Local X2APIC MADT entries: ACPI 4.0+
-    else
-      t->Revision = 2; // ACPI 2.0+
-    wr.add_table_ref(&t->RsdtPhysicalAddress, Table::Rsdt);
-    wr.add_table_ref(&t->XsdtPhysicalAddress, Table::Xsdt);
-    t->Length = Rsdp_size;
-    wr.add_checksum(&t->ExtendedChecksum, t, Rsdp_size);
-  }
-
-  /**
-   * Writes all implemented ACPI tables.
-   */
-  static void write_all_tables(Writer &wr, Vdev::Device_lookup *devs)
-  {
-    write_rsdt(wr);
-    write_xsdt(wr);
-    write_fadt(wr);
-    write_madt(wr, devs->cpus()->max_cpuid() + 1, devs->cpus(),
-               Madt_int_override_storage::get()->overrides());
-    write_mcfg(wr);
-    write_facs(wr);
-    write_dsdt(wr);
-  }
-
-  /**
-   * Compute ACPI checksum for memory area.
-   *
-   * \param dest  Base address of the memory area.
-   * \param len   Length of the memory area.
-   *
-   * \return Value so that the sum of all bytes in the memory area modulo 256
-   *         is zero.
-   */
-  static l4_uint8_t compute_checksum(void *dest, unsigned len)
-  {
-    l4_uint8_t *bytes = reinterpret_cast(dest);
-    l4_uint8_t sum = 0;
-    for (unsigned i = 0; i < len; i++)
-      sum += bytes[i];
-
-    return -sum;
-  }
-
-private:
-  /**
-   * Write a Root System Description Table (RSDT) or an Extended System
-   * Description Table (XSDT).
-   *
-   * Table holding pointers to other system description tables as defined in
-   * sections 5.2.7 (RSDT) and 5.2.8 (XSDT) of the ACPI 3.0 Specification.
-   */
-  template 
-  static void write_rsdt_xsdt(Writer &wr)
-  {
-    // Tables that RSDT / XSDT refers to.
-    static constexpr std::array ref_tables = {
-      Table::Madt,
-      Table::Fadt,
-      Table::Mcfg,
-    };
-
-    // RSDT/XSDT table header plus a 32/64-bit word per table pointer.
-    constexpr auto size =
-      Header_size + ref_tables.size() * sizeof(TABLE::TableOffsetEntry[0]);
-
-    constexpr Table table
-      = (std::is_same::value)
-      ? Table::Rsdt : Table::Xsdt;
-    auto *t = wr.start_table(table, size);
-
-    // The acpi_table_{rsdt/xsdt} struct defines only one entry, but we simply
-    // use the extra space allocated in the header. Do not forget to update
-    // Num_table_refs when adding or removing a table reference here.
-    for (l4_size_t i = 0; i < ref_tables.size(); i++)
-      wr.add_table_ref(&t->TableOffsetEntry[i], ref_tables[i]);
-
-    constexpr char const *sig
-      = (std::is_same::value)
-      ? ACPI_SIG_RSDT : ACPI_SIG_XSDT;
-    wr.end_table(&t->Header, sig, 1);
-  }
-
-  /**
-   * Write a Root System Description Table (RSDT).
-   *
-   * Table holding pointers to other system description tables as defined in
-   * section 5.2.7 of the ACPI 3.0 Specification.
-   */
-  static void write_rsdt(Writer &wr)
-  {
-    write_rsdt_xsdt(wr);
-  }
-
-  /**
-   * Write an Extended System Description Table (XSDT).
-   *
-   * Table holding pointers to other system description tables as defined in
-   * section 5.2.8 of the ACPI 3.0 Specification.
-   */
-  static void write_xsdt(Writer &wr)
-  {
-    write_rsdt_xsdt(wr);
-  }
-
-  /**
-   * Write a Fixed ACPI Description Table (FADT).
-   *
-   * Table providing fixed hardware information as defined in section 5.2.8 of
-   * the ACPI Specification.
-   */
-  static void write_fadt(Writer &wr)
-  {
-    auto *t = wr.start_table(Table::Fadt);
-
-    // Switching on Hardware-Reduced ACPI has the positive effect of
-    // eliminating a lot of legacy features we do not implement.
-    // However, with that flag on Linux requires the DSDT to be properly set
-    // up for finding PCI devices.
-    // t->Flags = (1 << 20); // HW_REDUCED_ACPI
-
-    wr.add_table_ref(&t->Dsdt, Table::Dsdt);
-    t->XDsdt = 0; // For now we don't implement the extended DSDT.
-    wr.add_table_ref(&t->Facs, Table::Facs);
-    t->XFacs = 0;
-
-    // How to pick the ID?
-    t->HypervisorId = 0;
-
-    for (auto const &d : Acpi_device_hub::get()->devices())
-      d->amend_fadt(t);
-
-    // Emulate ACPI 6.3.
-    wr.end_table(&t->Header, ACPI_SIG_FADT, 6);
-    t->MinorRevision = 3;
-  }
-
-  /**
-   * Construct a Multiple APIC Description Table (MADT).
-   *
-   * The MADT lists Advanced Programmable Interrupt Controllers in the system
-   * as defined in section 5.2.12 of the ACPI Specification.
-   *
-   * \param nr_cpus  The number of enabled CPUs.
-   * \param cpus     Pointer to the CPU container.
-   */
-  static void
-  write_madt(Writer &wr, unsigned nr_cpus,
-             cxx::Ref_ptr cpus,
-             std::vector const &madt_int_overrides)
-  {
-    auto *t = wr.start_table(Table::Madt);
-
-    t->Address = Gic::Lapic_access_handler::Mmio_addr;
-    // ACPI 6.3 Specification, Table 5-44:
-    // not a PC-AT-compatible dual-8259 setup
-    t->Flags = 0;
-
-    // I/O APIC Structure.
-    // Provide information about the system's I/O APICs as defined in section
-    // 5.2.12.3 of the ACPI Specification.
-    auto *ioapic = wr.reserve_madt_subtable(
-      ACPI_MADT_TYPE_IO_APIC);
-    ioapic->Reserved = 0;
-    ioapic->Id = 0;
-    ioapic->Address = Gic::Io_apic::Mmio_addr;
-    ioapic->GlobalIrqBase = 0;
-
-    // Interrupt Override Structure.
-    // Information about overriding ISA specified interrupt numbers with new
-    // ones.
-    for (auto const &over : madt_int_overrides)
-      {
-        auto *tbl = wr.reserve_madt_subtable(
-          ACPI_MADT_TYPE_INTERRUPT_OVERRIDE);
-        tbl->Bus = 0;
-        tbl->SourceIrq = over.src_irq;
-        tbl->GlobalIrq = over.gsi;
-        tbl->IntiFlags = over.flags;
-      }
-
-    // Processor Local APIC Structure.
-    // Structure to be appended to the MADT base table for each local APIC.
-    // Defined in section 5.2.12.2 of the ACPI Specification.
-    for (unsigned i = 0; i < nr_cpus; ++i)
-      {
-        // ACPI spec 4.0 / 5.2.12.12: Processor Local x2APIC Structure: Logical
-        // processors with APIC ID values less than 255 must use the Processor
-        // Local APIC structure to convey their APIC information to OSPM.
-        unsigned vcpu_id = cpus->vcpu(i).get_vcpu_id();
-        if (vcpu_id < 0xff)
-          {
-            auto *lapic = wr.reserve_madt_subtable(
-              ACPI_MADT_TYPE_LOCAL_APIC);
-            lapic->ProcessorId = i;
-            lapic->Id = vcpu_id;
-            lapic->LapicFlags = 1; // Enable CPU.
-          }
-      }
-
-    // Processor Local X2APIC Structure.
-    // Structure to be appended to the MADT base table for each local X2APIC.
-    // Defined in section 5.2.12.12 of the ACPI 4.0 Specification.
-    for (unsigned i = 0; i < nr_cpus; ++i)
-      {
-        unsigned vcpu_id = cpus->vcpu(i).get_vcpu_id();
-        if (vcpu_id >= 0xff)
-          {
-            auto *lx2apic = wr.reserve_madt_subtable(
-              ACPI_MADT_TYPE_LOCAL_X2APIC);
-            lx2apic->LocalApicId = vcpu_id;
-            lx2apic->LapicFlags = 1; // Enable CPU.
-            lx2apic->Uid = 0;
-          }
-      }
-
-    // Finally fill the table header.
-    wr.end_table(&t->Header, ACPI_SIG_MADT, 5);
-  }
-
-  /**
-   * Write PCI Express memory mapped configuration space base address
-   * Description Table (MCFG).
-   */
-  static void write_mcfg(Writer &wr)
-  {
-    auto *t = wr.start_table(Table::Mcfg);
-
-    for (auto const &d : Acpi_device_hub::get()->devices())
-      {
-        auto *ptr = wr.as_ptr(wr.pos());
-        auto amend_size = d->amend_mcfg(ptr, wr.remaining_size());
-        wr.reserve(amend_size);
-      }
-
-    wr.end_table(&t->Header, ACPI_SIG_MCFG, 1);
-  }
-
-  /**
-   * Write a Firmware ACPI Control Structure (FACS).
-   */
-  static void write_facs(Writer &wr)
-  {
-    auto *t = wr.start_table(Table::Facs, Facs_size, 64);
-    memcpy(t->Signature, ACPI_SIG_FACS, ACPI_NAMESEG_SIZE);
-    t->Length = Facs_size;
-    t->Version = 2;
-    // other fields written by OSPM or should be zero.
-  }
-
-  /**
-   * Write Differentiated System Description Table (DSDT).
-   */
-  static void write_dsdt(Writer &wr)
-  {
-    auto *t = wr.start_table(Table::Dsdt);
-
-    // Collect the highest priority DSDT fragments of ACPI devices.
-    for (auto const &d : Acpi_device_hub::get()->devices())
-      {
-        void *ptr = wr.as_ptr(wr.pos());
-        auto amend_size = d->amend_dsdt(ptr, wr.remaining_size());
-        wr.reserve(amend_size);
-      }
-
-    // Collect the lowest priority DSDT fragments of ACPI devices.
-    for (auto const &d : Acpi_device_hub::get()->devices())
-      {
-        void *ptr = wr.as_ptr(wr.pos());
-        auto amend_size = d->amend_dsdt_late(ptr, wr.remaining_size());
-        wr.reserve(amend_size);
-      }
-
-    // The revision of DSDT controls the integer width of AML code/interpreter.
-    // Values less than two imply 32-bit integers and math, otherwise 64-bit
-    // (see also ComplianceRevision in AML DefinitionBlock)
-    wr.end_table(t, ACPI_SIG_DSDT, 1);
-  }
-};
-
-class Bios_tables : public Tables
-{
-  enum : l4_uint32_t
-  {
-    /**
-     * Physical location of the RSDP according to section 5.2.5.1 of the ACPI
-     * Specification.
-     */
-    Phys_start_addr = 0x0E0000
-  };
-
-public:
-  /**
-   * ACPI control structure.
-   *
-   * \param ram  Guest RAM.
-   */
-  Bios_tables(Vdev::Device_lookup *devs)
-  : _devs(devs)
-  {
-    info.printf("Initialize legacy BIOS ACPI tables.\n");
-    _dest_addr = _devs->ram()->guest2host(Vmm::Guest_addr(Phys_start_addr));
-  }
-
-  /**
-   * Calculate positions for each table and write them in place.
-   */
-  void write_to_guest()
-  {
-    // we allow the rsdp and all tables to take up one page
-    l4_size_t max_size = L4_PAGESIZE;
-
-    auto acpi_mem = Vmm::Region::ss(Vmm::Guest_addr(Phys_start_addr), max_size,
-                                    Vmm::Region_type::Ram);
-    // Throws an exception if the ACPI memory region isn't within guest RAM.
-    _devs->ram()->guest2host(acpi_mem);
-
-    // Clear memory because we do not rely on the DS provider to do this for
-    // us, and we must not have spurious values in ACPI tables.
-    memset(reinterpret_cast(_dest_addr), 0, max_size);
-
-    Writer wr(_dest_addr, max_size);
-    write_rsdp(wr);
-    write_all_tables(wr, _devs);
-    resolve_table_refs_and_checksums(wr);
-
-    l4_addr_t facs_off = wr.table_offset(Tables::Table::Facs);
-    Facs_storage::get()->set_addr(wr.as_ptr(facs_off));
-    Facs_storage::get()->set_gaddr(
-                           acpi_phys_addr(wr.as_addr(facs_off)));
-  }
-
-private:
-  void resolve_table_refs_and_checksums(Writer &wr)
-  {
-    for (Writer::Table_ref const &ref : wr.table_refs())
-      {
-        l4_addr_t table_addr = wr.as_addr(wr.table_offset(ref.table));
-        if (ref.size == sizeof(l4_uint32_t))
-          *wr.as_ptr(ref.offset) =
-            acpi_phys_addr(table_addr);
-        else if (ref.size == sizeof(l4_uint64_t)) // XSDT
-          *wr.as_ptr(ref.offset) =
-            acpi_phys_addr(table_addr);
-        else
-          L4Re::throw_error(-L4_EINVAL, "Unsupported table offset size.");
-      }
-
-    for (Writer::Checksum const &checksum : wr.checksums())
-      {
-        l4_uint8_t *field = wr.as_ptr(checksum.field_off);
-        // Calculate and write checksum.
-        *field = compute_checksum(wr.as_ptr(checksum.offset), checksum.len);
-      }
-  }
-
-  /**
-   * Compute guest-physical address of target table.
-   *
-   * \param virt_target_addr  Virtual address of the target table.
-   *
-   * \return 32-bit guest-physical address of the target table.
-   */
-  template 
-  T acpi_phys_addr(l4_addr_t virt_target_addr) const
-  {
-    return Phys_start_addr + static_cast(virt_target_addr - _dest_addr);
-  }
-
-  Vdev::Device_lookup *_devs;
-  l4_addr_t _dest_addr;
-};
-
-
-} // namespace Acpi
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_platform.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_platform.cc
deleted file mode 100644
index b4b3ffdd..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_platform.cc
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include "acpi.h"
-#include "device_factory.h"
-#include "irq_dt.h"
-#include "monitor/virtio_input_power_cmd_handler.h"
-#include "vbus_event.h"
-
-#include 
-#include 
-#include 
-
-namespace Acpi {
-
-/**
- * \file
- * Acpi platform support
- *
- * This implements minimal Acpi command support. Enough that Linux believes
- * that Acpi works and that it uses Acpi shutdown.
- *
- * This requires a device tree entry like this.
- *
- * \code{.dtb}
- *   acpi_platform {
- *     compatible = "virt-acpi";
- *     interrupt-parent = <&PIC>;
- *     interrupts = <9>;
- *     // Optional: Connect vcon to trigger ACPI power events.
- *     // l4vmm,pwrinput = "acpi_pwr_input";
- *   };
- * \endcode
- *
- * You may configure a different interrupt number for the system control
- * interrupt (SCI), but make sure it does not collide.
- *
- * The interrupt parent is mandatory. The SCI is currently only used during
- * Acpi probing.
- */
-
-template 
-class Vcon_pwr_input
-: public L4::Irqep_t >,
-  public Monitor::Virtio_input_power_cmd_handler>
-{
-  friend Monitor::Virtio_input_power_cmd_handler>;
-
-public:
-  Vcon_pwr_input(L4::Cap con)
-  : _con(con) {}
-
-  ~Vcon_pwr_input()
-  {
-    if (_con_irq.is_valid())
-      if (long err = l4_error(_con->unbind(0, _con_irq)) < 0)
-        warn().printf("Unbind notification IRQ from Vcon: %s\n.",
-                      l4sys_errtostr(err));
-  }
-
-  void register_obj(L4::Registry_iface *registry)
-  {
-    _con_irq = L4Re::chkcap(registry->register_irq_obj(this),
-                            "Register IRQ of Vcon-pwr-input device.");
-    L4Re::chksys(_con->bind(0, _con_irq),
-                 "Binding Vcon notification irq failed.\n");
-  }
-
-  void handle_irq();
-
-  bool inject_command(char cmd);
-
-private:
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "pwr-input"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "pwr-input"); }
-
-  DEV *dev() { return static_cast(this); }
-  L4::Cap _con;
-  L4::Cap _con_irq;
-};
-
-template
-void
-Vcon_pwr_input::handle_irq()
-{
-  while (1)
-    {
-      int r = _con->read(NULL, 0);
-
-      if (r <= 0)
-        break; // empty
-
-      char cmd;
-      r = _con->read(&cmd, sizeof(cmd));
-
-      if (r < 0)
-        {
-          Err().printf("Vcon_pwr_input: read error: %d\n", r);
-          break;
-        }
-
-      inject_command(cmd);
-      trace().printf("Vcon_pwr_input::handle_irq OK\n");
-      _con->write("OK\n", 3);
-    }
-}
-
-template
-bool
-Vcon_pwr_input::inject_command(char cmd)
-{
-  bool ret = false;
-  trace().printf("cmd=%c\n", cmd);
-
-  switch(cmd)
-  {
-    case 'a':
-    case 's':
-    case 'l':
-      ret = dev()->inject_slpbtn();
-      break;
-    case 'p':
-    case 'q':
-      ret = dev()->inject_pwrbtn();
-      break;
-    case 'h':
-      {
-        char response[] = "a: apm suspend\ns: suspend\nl: sleep\np: power\n"
-                          "q: power2\n";
-        _con->write(response, sizeof(response) - 1);
-      }
-      break;
-    default:
-      warn().printf("Unknown character '%c'\n", cmd);
-      break;
-  }
-
-  return ret;
-}
-
-
-class Acpi_platform:
-  public Vmm::Io_device,
-  public Vdev::Device,
-  public Acpi_device,
-  public Vcon_pwr_input,
-  public Vbus_stream_id_handler
-{
-private:
-  enum Command_values : l4_uint16_t
-  {
-    Acpi_enable     = 0xf2,
-    Acpi_disable    = 0xf1,
-    Acpi_shutdown   = 0x7,
-    Acpi_suspend    = 0x6,
-    Reboot          = 0x4,
-  };
-
-public:
-  enum Ports : l4_uint16_t
-  {
-    Ports_start     = 0x1800,
-    Smi_command     = Ports_start,
-    Pm1a_cmd_block  = Smi_command + 1, // 0x1801
-    Pm1a_cmd_length = 2, // 2 ports
-    Pm2_cmd_block   = Pm1a_cmd_block + Pm1a_cmd_length, // 0x1803
-    Pm2_cmd_length  = 1,  // 1 port
-    Pm1a_event_block= Pm2_cmd_block + Pm2_cmd_length,   // 0x1804
-    Pm1a_sts        = Pm1a_event_block,
-    Pm1a_en         = Pm1a_event_block + 2,
-    Pm1_event_length= 4,
-    Reset_register  = Pm1a_event_block + Pm1_event_length, // 0x1808
-    Ports_last       = Reset_register, // inclusive end
-  };
-
-  enum Events : l4_uint32_t
-  {
-    Pm1a_evt_gbl    = 1U << 5,
-    Pm1a_evt_pwrbtn = 1U << 8,
-    Pm1a_evt_slpbtn = 1U << 9,
-    Pm1a_evt_rtc    = 1U << 10,
-
-    // PM1 events we implement.
-    Pm1a_evt_supported =   Pm1a_evt_gbl | Pm1a_evt_pwrbtn | Pm1a_evt_slpbtn
-                         | Pm1a_evt_rtc,
-  };
-
-  Acpi_platform(Vdev::Device_lookup *devs, cxx::Ref_ptr const &ic, int irq,
-                L4::Cap pwr_vcon)
-  : Acpi_device(), Vcon_pwr_input(pwr_vcon),
-    _vmm(devs->vmm()),
-    _sci(ic, irq),
-    _irq(irq),
-    _acpi_enabled(false),
-    _pm1a_sts(0),
-    _pm1a_en(0)
-  {
-    if (!devs->vbus()->available())
-      return;
-
-    auto vbus = devs->vbus()->bus();
-    info().printf("Registering as event handler for vbus->root() = %lx\n",
-                  vbus->root().dev_handle());
-    Vbus_event::register_stream_id_handler(vbus->root().dev_handle(), this);
-  }
-
-  char const *dev_name() const override
-  { return "ACPI platform"; }
-
-  void amend_fadt(ACPI_TABLE_FADT *t) const override
-  {
-    t->SmiCommand  = Ports::Smi_command; // 32-bit port address of SMI command port
-    t->SciInterrupt = _irq;
-    t->AcpiEnable  = Command_values::Acpi_enable;
-    t->AcpiDisable = Command_values::Acpi_disable;
-
-    // 32-bit port address of Power Mgt 1a Control Reg Block
-    t->Pm1aControlBlock = Ports::Pm1a_cmd_block;
-    // size of block
-    t->Pm1ControlLength = Ports::Pm1a_cmd_length;
-
-    // 32-bit port address of Power Mgt 2 Control Reg Block
-    t->Pm2ControlBlock = Ports::Pm2_cmd_block;
-    // size of block
-    t->Pm2ControlLength = Ports::Pm2_cmd_length;
-
-    t->Pm1aEventBlock = Ports::Pm1a_event_block;
-    t->Pm1EventLength = Ports::Pm1_event_length;
-
-    // Indicate the presence of an i8042 keyboard controller.
-    if (_vmm->i8042_present())
-      t->BootFlags |= ACPI_FADT_8042;
-
-    // set the reset register for ACPI reboot
-    t->Flags                 |= ACPI_FADT_RESET_REGISTER;
-    t->ResetRegister.Address  = Ports::Reset_register;
-    t->ResetRegister.SpaceId  = ACPI_ADR_SPACE_SYSTEM_IO;
-    t->ResetRegister.BitWidth = ACPI_RESET_REGISTER_WIDTH;
-    t->ResetValue             = Command_values::Reboot;
-  }
-
-  /**
-   * Write an ACPI control object to the DSDT table that allows the guest to
-   * discover shutdown capability.
-   *
-   * This is described in section 7.4.2 of the ACPI specification.
-   *
-   * \param buf       The memory are where to put the object.
-   * \param max_size  Maximum available size of the designated memory area.
-   */
-  l4_size_t amend_dsdt(void *buf, l4_size_t max_size) const override
-  {
-    // _S3 == suspend to ram
-    // _S5 == shutdown
-    unsigned char dsdt_S3S5 [] =
-    {
-      0x08, 0x5F, 0x53, '3', 0x5F, 0x12, 0x08, 0x04,
-      0x0A, Command_values::Acpi_suspend,
-      0x0A, Command_values::Acpi_suspend,
-      0x00, 0x00,
-      0x08, 0x5F, 0x53, '5', 0x5F, 0x12, 0x08, 0x04,
-      0x0A, Command_values::Acpi_shutdown,
-      0x0A, Command_values::Acpi_shutdown,
-      0x00, 0x00,
-    };
-
-    l4_size_t size = sizeof(dsdt_S3S5);
-    if (max_size < size)
-      L4Re::throw_error(-L4_ENOMEM,
-                        "Not enough space in DSDT");
-    memcpy(buf, reinterpret_cast(dsdt_S3S5), size);
-    return size;
-  }
-
-  /**
-   * Handle pm1a enable register.
-   *
-   * This handles a subset of the PM1A enable register as described in section
-   * 4.8.3.1 of the ACPI specification. We support GBL_EN, PRWBTN_EN,
-   * SLPBTN_EN and the RTC_EN bits. If both the corresponding status and the
-   * enable bit is set, we inject an SCI.
-   */
-  void handle_pm1a_en()
-  {
-    if (!_acpi_enabled)
-      return;
-
-    // if sts and en bits are set we issue an SCI
-    if (_pm1a_sts & _pm1a_en & Pm1a_evt_supported)
-      {
-        trace().printf("Injecting SCI\n");
-        _sci.inject();
-      }
-
-    trace().printf("_pm1a_sts = 0x%x _pm1a_en = 0x%x\n", _pm1a_sts, _pm1a_en);
-  }
-
-  /**
-   * Handle a subset of the pm1a control register.
-   *
-   * This function handles the PM1A control register as described in section
-   * 4.8.3.2 of the ACPI specification. We only handle the SLP_EN and SLP_TYPx
-   * bits.
-   *
-   * \param value  The value written to the register.
-   */
-  void handle_pm1a_control(l4_uint32_t value)
-  {
-    enum
-    {
-      Slp_enable = 1 << 13,
-      Slp_type_shutdown = Acpi_shutdown << 10,
-      Slp_type_suspend = Acpi_suspend << 10,
-      Slp_type_mask = 0x7 << 10,
-    };
-    static_assert((Slp_type_shutdown & Slp_type_mask) == Slp_type_shutdown,
-                  "ACPI platform: Sleep type shutdown within field bounds");
-    static_assert((Slp_type_suspend & Slp_type_mask) == Slp_type_suspend,
-                  "ACPI platform: Sleep type suspend within field bounds");
-
-    if (value & Slp_enable)
-      {
-        if ((value & Slp_type_mask) == Slp_type_shutdown)
-          {
-            trace().printf("Guest requested power off. Bye\n");
-            _vmm->shutdown(Vmm::Guest::Shutdown);
-          }
-        else if ((value & Slp_type_mask) == Slp_type_suspend)
-          {
-            trace().printf("System suspend requested\n");
-            // If Uvmm loaded a guest Linux kernel itself, it emulates
-            // firmware behaviour by resuming the guest directly at the
-            // address the guest specified in the FACS.
-            // Otherwise the VM resumes at the reset vector where firmware
-            // shall take care of guest resume.
-            if (_vmm->guest_type() == Boot::Binary_type::Linux)
-              _vmm->suspend(Facs_storage::get()->waking_vector());
-            else
-              _vmm->suspend(0xffff'fff0);
-          }
-      }
-  }
-
-  /**
-   * Handle IO port reads to the device.
-   *
-   * \param      port   IO port
-   * \param[out] value  The value read from the IO port.
-   */
-  void io_in(unsigned port, Vmm::Mem_access::Width /*width*/,
-             l4_uint32_t *value) override
-  {
-    port += Smi_command;
-    *value = -1U;
-    switch (port)
-      {
-      case Smi_command:
-        *value = 0;
-        break;
-      case Pm1a_cmd_block:
-        if (_acpi_enabled)
-          *value = 1; // SMI_EN == 1
-        else
-          *value = 0;
-        break;
-      case Pm1a_sts:
-        trace().printf("read _pm1a_sts = 0x%x\n", _pm1a_sts);
-        *value = _pm1a_sts;
-        break;
-      case Pm1a_en:
-        trace().printf("read _pm1a_en = 0x%x\n", _pm1a_en);
-        *value = _pm1a_en;
-        break;
-      default:
-        trace().printf("IO IN port=%x value=%x\n", port, *value);
-        break;
-      }
-  }
-
-  /**
-   * Handle IO port writes to device IO ports.
-   *
-   * \param port   IO Port
-   * \param value  The value written to the port.
-   */
-  void io_out(unsigned port, Vmm::Mem_access::Width /*width*/,
-              l4_uint32_t value) override
-  {
-    port += Smi_command;
-    switch (port)
-      {
-      case Smi_command:
-        if (value == Acpi_enable)
-          {
-            trace().printf("Acpi enabled\n");
-            _acpi_enabled = true;
-          }
-        else if (value == Acpi_disable)
-          {
-            trace().printf("Acpi disabled\n");
-            _acpi_enabled = false;
-          }
-        break;
-      case Pm1a_cmd_block:
-        handle_pm1a_control(value);
-        break;
-      case Pm1a_sts:
-        trace().printf("write _pm1a_sts = 0x%x\n", value);
-        _pm1a_sts &= ~(value & Pm1a_evt_supported);
-        if ((_pm1a_sts & _pm1a_en) == 0U)
-          {
-            trace().printf("SCI ack\n");
-            _sci.ack();
-          }
-        break;
-      case Pm1a_en:
-        trace().printf("write _pm1a_en = 0x%x\n", value);
-        _pm1a_en = value;
-        handle_pm1a_en();
-        break;
-      case Reset_register:
-        if (value == Command_values::Reboot)
-          {
-            trace().printf("Reboot requested. Bye\n");
-            _vmm->shutdown(Vmm::Guest::Reboot);
-          }
-        break;
-      default:
-        trace().printf("IO OUT port=%x value=%x\n", port, value);
-        break;
-      }
-  }
-
-  bool inject_slpbtn()
-  {
-    if (!_acpi_enabled || !(_pm1a_en & Pm1a_evt_slpbtn))
-      return false;
-
-    _pm1a_sts |= Pm1a_evt_slpbtn;
-    _sci.inject();
-
-    return true;
-  }
-
-  bool inject_pwrbtn()
-  {
-    if (!_acpi_enabled || !(_pm1a_en & Pm1a_evt_pwrbtn))
-      return false;
-
-    _pm1a_sts |= Pm1a_evt_pwrbtn;
-    _sci.inject();
-
-    return true;
-  }
-
-  void handle_event(L4Re::Event_buffer::Event *e) override
-  {
-    // Here we handle inhibitor signals.
-    //
-    // Iff Uvmm has a vbus, it will grab inhibitor locks for suspend and
-    // shutdown. The rationale is that IO is only allowed to shutdown and/or
-    // suspend the system once all inhibitor locks are free. To that end, IO
-    // will send out inhibitor signals to its vbus clients. The clients shall
-    // suspend/shutdown their devices and free the inhibitor lock.
-    //
-    // Management of the locks itself is done in pm.{cc,h}
-
-    if (e->payload.type != L4RE_EV_PM)
-    {
-      warn().printf("Unexpected event type (0x%x). Ignoring.\n", e->payload.type);
-      return;
-    }
-
-    switch (e->payload.code)
-    {
-      case L4VBUS_INHIBITOR_SUSPEND:
-        info().printf("SUSPEND signal\n");
-        inject_slpbtn();
-        break;
-      case L4VBUS_INHIBITOR_SHUTDOWN:
-        info().printf("SHUTDOWN signal\n");
-        inject_pwrbtn();
-        break;
-      case L4VBUS_INHIBITOR_WAKEUP:
-        // The IPC for this signal will have woken Uvmm up. Nothing to do
-        // here.
-        break;
-      default:
-        warn().printf("Unknown PM event: code 0x%x.\n", e->payload.code);
-        break;
-      }
-  }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "Acpi_platform"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "Acpi_platform"); }
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "Acpi_platform"); }
-
-  Vmm::Guest *_vmm;
-  Vmm::Irq_sink _sci;
-  unsigned const _irq;
-  bool _acpi_enabled;
-  l4_uint32_t _pm1a_sts, _pm1a_en;
-};
-
-} // namespace Acpi
-
-/***********************************************************************/
-
-namespace
-{
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      L4Re::throw_error(-L4_EINVAL, "Acpi_platform requires a virtual "
-                        "interrupt controller");
-
-    auto pwr_vcon = Vdev::get_cap(node, "l4vmm,pwrinput");
-    auto dev = Vdev::make_device(devs, it.ic(),
-                                                      it.irq(), pwr_vcon);
-    if (pwr_vcon)
-      dev->register_obj(devs->vmm()->registry());
-
-    Dbg().printf("Creating Acpi_platform\n");
-
-    auto *vmm = devs->vmm();
-    auto start = Acpi::Acpi_platform::Ports::Ports_start;
-    auto end   = Acpi::Acpi_platform::Ports::Ports_last;
-    vmm->add_io_device(Vmm::Io_region(start, end, Vmm::Region_type::Virtual),
-                       dev);
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"virt-acpi", nullptr, &f};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_timer.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_timer.cc
deleted file mode 100644
index 67a34f90..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/acpi_timer.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2021-2024 Kernkonzept GmbH.
- * Author(s):  Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * The ACPI PM TIMER is documented in the ACPI Manual in Chapter 4.8.3.3
- * "Power Management Timer (PM_TMR)".
- *
- * Its IO port is 0xb008 by default.
- * "This is a 24-bit counter that runs off a 3.579545-MHz clock and counts
- *  while in the S0 working system state."
- *
- * The client has to cope with wrap arounds.
- *
- * This can be used in linux with cmdline "clocksource=acpi_pm".
- *
- * We do not support interrupt generation.
- */
-
-
-#include "device_factory.h"
-#include "guest.h"
-#include "device.h"
-#include "acpi.h"
-#include "io_device.h"
-#include 
-#include 
-
-namespace Vdev {
-
-class Acpi_timer:
-  public Vmm::Io_device,
-  public Vdev::Device,
-  public Acpi::Acpi_device
-{
-public:
-  enum
-    {
-      Frequency_hz = 3579545,
-      Port = 0xb008,
-    };
-
-  Acpi_timer()
-  : Acpi_device()
-  {
-    _timebase = l4_rdtsc();
-  }
-
-  char const *dev_name() const override
-  { return "ACPI Timer"; }
-
-  void amend_fadt(ACPI_TABLE_FADT *t) const override
-  {
-    t->PmTimerBlock = Port;
-    t->PmTimerLength = 4;
-    t->Flags |= ACPI_FADT_32BIT_TIMER;
-  }
-
-private:
-  /* IO write from the guest to device */
-  void io_out(unsigned, Vmm::Mem_access::Width, l4_uint32_t) override
-  {
-    // this is a read only field, so we can ignore that.
-    return;
-  }
-
-  /* IO read from the guest */
-  void io_in(unsigned, Vmm::Mem_access::Width, l4_uint32_t *value) override
-  {
-    l4_cpu_time_t now = l4_rdtsc();
-    l4_cpu_time_t diff_ns = l4_tsc_to_ns(now - _timebase);
-    l4_cpu_time_t period = 1000UL * 1000 * 1000 / Frequency_hz;
-    *value = diff_ns / period;
-  }
-
-  l4_cpu_time_t _timebase = 0;
-};
-
-} // namespace Vdev
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &) override
-  {
-    auto dev = Vdev::make_device();
-
-    Acpi::info.printf("Acpi timer @ 0x%x\n", Vdev::Acpi_timer::Port);
-    auto region = Vmm::Io_region(Vdev::Acpi_timer::Port,
-                                 Vdev::Acpi_timer::Port,
-                                 Vmm::Region_type::Virtual);
-    devs->vmm()->add_io_device(region, dev);
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"acpi-timer", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_linux.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_linux.cc
deleted file mode 100644
index ec4af4af..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_linux.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader_linux.h"
-#include "guest.h"
-
-namespace Boot {
-
-enum : unsigned
-{
-  Linux_kernel_start_addr = 0x100000,
-};
-
-int Linux_loader::load(char const * /*bin*/, std::shared_ptr image,
-                       Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-                       l4_addr_t *entry)
-{
-  trace().printf("Checking for Linux image...\n");
-
-  if (!image->is_valid())
-    return -L4_EINVAL;
-
-  unsigned char const *h = static_cast(image->get_data());
-  if (!(h[0x1fe] == 0x55 && h[0x1ff] == 0xaa))
-    return -L4_EINVAL;
-
-  info().printf("Linux kernel detected\n");
-
-  _64bit = true;
-
-  l4_uint8_t num_setup_sects = *(h + Vmm::Bp_setup_sects);
-  trace().printf("number of setup sections found: 0x%x\n", num_setup_sects);
-
-  // 512 is the size of a segment
-  l4_addr_t setup_sects_size = (num_setup_sects + 1) * 512;
-
-  if (Linux_kernel_start_addr < setup_sects_size)
-    L4Re::chksys(-L4_EINVAL,
-                 "Supplied kernel image contains an invalid number "
-                 " of setup sections (zeropage).");
-
-  l4_addr_t start = Linux_kernel_start_addr - setup_sects_size;
-  trace().printf("size of setup sections: 0x%lx\n", setup_sects_size);
-  trace().printf("loading binary at: 0x%lx\n", start);
-
-  // load the binary starting after the boot_params
-  *entry = image->load_as_raw(ram, ram->boot2guest_phys(start), free_list);
-  trace().printf("Loaded kernel image as raw to 0x%lx\n", *entry);
-  trace().printf("load kernel as raw entry to 0x%lx\n",
-                 ram->guest_phys2boot(
-                   Vmm::Guest_addr(Linux_kernel_start_addr)));
-
-  return L4_EOK;
-}
-
-static Linux_loader f __attribute__((init_priority(Boot::Linux)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.cc
deleted file mode 100644
index 7a35b623..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2023-2024 genua GmbH, 85551 Kirchheim, Germany
- * All rights reserved. Alle Rechte vorbehalten.
- */
-/*
- * Copyright (C) 2025 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader_openbsd.h"
-#include "guest.h"
-
-namespace Boot {
-
-bool OpenBSD_loader::is_openbsd(std::shared_ptr image) const
-{
-  bool res = false;
-  image->get_elf()->iterate_phdr([&res](Ldr::Elf_phdr ph)
-    {
-      if (ph.type() == Pt_openbsd_randomize)
-        res = true;
-    });
-  return res;
-}
-
-int OpenBSD_loader::load(char const * /*bin*/, std::shared_ptr image,
-                         Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-                         l4_addr_t *entry)
-{
-  trace().printf("Checking for OpenBSD image...\n");
-
-  if (!image->is_valid())
-    return -L4_EINVAL;
-
-  if (!image->is_elf_binary() || !image->is_elf64() || !is_openbsd(image))
-    return -L4_EINVAL;
-
-  *entry = image->load_as_elf(ram, free_list);
-  _binsize = image->loaded_size();
-  info().printf("Loaded OpenBSD kernel image to 0x%lx, size 0x%zx\n", *entry,
-                _binsize);
-
-  return L4_EOK;
-}
-
-static OpenBSD_loader f __attribute__((init_priority(Boot::OpenBSD)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.h
deleted file mode 100644
index 1a509b89..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_openbsd.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2023-2024 genua GmbH, 85551 Kirchheim, Germany
- * All rights reserved. Alle Rechte vorbehalten.
- */
-/*
- * Copyright (C) 2025 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "binary_loader.h"
-
-namespace Boot {
-
-class OpenBSD_loader : public Binary_loader
-{
-  enum { Pt_openbsd_randomize = 0x65a3dbe6 };
-
-public:
-  OpenBSD_loader()
-  : Binary_loader(OpenBSD)
-  {}
-
-  bool is_openbsd(std::shared_ptr image) const;
-  int load(char const *bin, std::shared_ptr image, Vmm::Vm_ram *ram,
-           Vmm::Ram_free_list *free_list, l4_addr_t *entry) override;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_raw.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_raw.h
deleted file mode 100644
index 48e33fe4..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/binary_loader_raw.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-namespace Boot {
-
-static int raw_load_image(std::shared_ptr image, Vmm::Vm_ram *ram,
-                          Vmm::Ram_free_list *free_list, l4_addr_t *entry)
-{
-  l4_addr_t start = *entry == ~0ul ? 0x0 : *entry;
-
-  // Get the RAM start address.
-  Vmm::Guest_addr ram_base = free_list->first_free_address();
-  *entry = image->load_as_raw(ram, ram_base + start, free_list);
-
-  return L4_EOK;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.cc
deleted file mode 100644
index 7e607486..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "cpu_dev.h"
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.h
deleted file mode 100644
index afe27705..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpu_dev.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "debug.h"
-#include "generic_cpu_dev.h"
-#include "vcpu_ptr.h"
-#include "monitor/cpu_dev_cmd_handler.h"
-
-#include 
-#include 
-
-extern __thread unsigned vmm_current_cpu_id;
-
-namespace Vmm {
-
-class Cpu_dev
-: public Generic_cpu_dev,
-  public Monitor::Cpu_dev_cmd_handler
-{
-public:
-  enum { Max_cpus = 128 };
-
-  enum Cpu_state
-  {
-    Sleeping = 1, // Startup state, Thread created but not running,
-                  // needs rescheduling.
-    Stopped,      // Waits for INIT signal, no need for rescheduling.
-    Init,         // Wait for SIPI to transition to Running.
-    Halted,       // Idle state, VMentry only on event.
-    Running
-  };
-
-private:
-  struct State_change
-  {
-    State_change(Cpu_state s) : target_state(s) {}
-    Cpu_state target_state;
-  };
-
-  struct Ipi_event
-  {
-    Ipi_event(Cpu_dev *c) : cpu(c) {}
-    void act()
-    {
-      cpu->_check_msgq = true;
-    }
-
-    void registration_failure()
-    {
-      Dbg().printf("Failed to register IRQ to for IPI; "
-                   "vCPU %u cannot be started.\n", cpu->vcpu().get_vcpu_id());
-    }
-
-    void trigger_failure(long ipc_err)
-    {
-      Dbg().printf("IPI to vCPU %u failed with error %li\n",
-                   cpu->vcpu().get_vcpu_id(), ipc_err);
-    }
-
-    Cpu_dev *cpu;
-  };
-
-public:
-  Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *)
-  : Generic_cpu_dev(idx, phys_id),
-    _ipi(Ipi_event(this))
-  {
-    _cpu_state = (idx == 0) ? Running : Sleeping;
-  }
-
-  ~Cpu_dev()
-  {
-    Vcpu_obj_registry *reg = _vcpu.get_ipc_registry();
-    _ipi.disarm(reg);
-  }
-
-  void powerup_cpu() override
-  {
-    Generic_cpu_dev::powerup_cpu();
-    _ipi.arm(_vcpu.get_ipc_registry());
-  }
-
-  /// Reset the Cpu_dev including vCPU does not return to the caller.
-  void reset() override
-  {
-    vmm_current_cpu_id = _vcpu.get_vcpu_id();
-    info().printf("[%3u] Reset called\n", vmm_current_cpu_id);
-
-    reset_common();
-    wait_until_online();
-
-    info().printf("[%3u] Resetting vCPU.\n", vmm_current_cpu_id);
-    _vcpu.reset(_protected_mode);
-  }
-
-  void hot_reset()
-  {
-    // assumption: Guest::run_vm() already called once.
-    // intention: Do not add leak stack memory.
-    reset_common();
-
-    info().printf("[%3u] Hot resetting vCPU.\n", vmm_current_cpu_id);
-    _vcpu.hot_reset();
-
-  }
-
-  /**
-   * Translate a device tree "reg" value to an internally usable CPU id.
-   *
-   * For most architectures this is NOP, but some architectures like ARM
-   * might encode topology information into this value, which needs to
-   * be translated.
-   */
-  static unsigned dtid_to_cpuid(l4_int32_t prop_val)
-  { return prop_val; }
-
-  static bool has_fixed_dt_mapping() { return true; }
-
-  Cpu_state get_cpu_state() const
-  { return _cpu_state; }
-
-  bool cpu_online() const
-  {
-    Cpu_state s = get_cpu_state();
-    return (s == Cpu_state::Running) || (s == Cpu_state::Halted);
-  }
-
-  void set_cpu_state(Cpu_state state)
-  { _cpu_state = state; }
-
-  void set_protected_mode()
-  { _protected_mode = true; }
-
-  /**
-   * Handle the stop event.
-   *
-   * The event is usually emitted cross core, but also used in CPU local
-   * error cases.
-   */
-  void stop() override
-  {
-    _stop_irq.disarm(_vcpu.get_ipc_registry());
-
-    {
-      std::lock_guard lock(_message_q_lock);
-      // Clear all pending state changes to ensure the core is stopped ASAP.
-      _message_q.clear();
-      _message_q.emplace_back(Cpu_state::Stopped);
-    }
-    _check_msgq = true;
-    // Do not do anything blocking here, we need to finish the execution of the
-    // IPC dispatching that brought us here or return to our local caller.
-  }
-
-  /// core local request to halt the CPU.
-  void halt_cpu()
-  {
-    {
-      std::lock_guard lock(_message_q_lock);
-      _message_q.emplace_back(Cpu_state::Halted);
-    }
-    _check_msgq = true;
-    // No IRQ trigger, we are already in VMexit handling
-  }
-
-  /// Send cross-core INIT signal
-  void send_init_ipi()
-  {
-    {
-      std::lock_guard lock(_message_q_lock);
-      _message_q.emplace_back(Cpu_state::Init);
-    }
-    _ipi.trigger();
-  }
-
-  /// Send cross-core SIPI signal
-  void send_sipi()
-  {
-    {
-      std::lock_guard lock(_message_q_lock);
-      _message_q.emplace_back(Cpu_state::Running);
-    }
-    _ipi.trigger();
-  }
-
-  Cpu_state next_state()
-  {
-    if (!has_message())
-      return get_cpu_state();
-
-    std::lock_guard lock(_message_q_lock);
-    if (_message_q.empty())
-      {
-        _check_msgq = false;
-        return get_cpu_state();
-      }
-    Cpu_state new_state = _message_q.front().target_state;
-    _message_q.pop_front();
-    _check_msgq = !_message_q.empty();
-
-    return new_state;
-  }
-
-  /**
-   * Wait for an IPI, unless there are still items in the message queue.
-   */
-  void wait_for_ipi()
-  {
-    if (has_message())
-      return;
-
-    _ipi.receive();
-    _check_msgq = true;
-  }
-
-private:
-  static Dbg info() { return Dbg(Dbg::Cpu, Dbg::Info, "Cpu_dev"); }
-
-  bool has_message() const { return _check_msgq; }
-
-  /// Wait until an IPI puts the CPU in online state.
-  void wait_until_online()
-  {
-    while (has_message())
-      set_cpu_state(next_state());
-
-    // wait for the SIPI to sets the `Running` state
-    while (!cpu_online())
-      {
-        wait_for_ipi();
-
-        while (has_message())
-          set_cpu_state(next_state());
-      }
-  }
-
-  /// Functionality performed to reset a vCPU.
-  void reset_common()
-  {
-    _stop_irq.arm(_vcpu.get_ipc_registry());
-
-    _vcpu->state = L4_VCPU_F_FPU_ENABLED;
-    _vcpu->saved_state = L4_VCPU_F_FPU_ENABLED | L4_VCPU_F_USER_MODE;
-  }
-
-  std::atomic _cpu_state; // core-local writes; cross-core reads;
-  bool _protected_mode = false;
-  bool _check_msgq = false; // use only in local vCPU thread.
-
-  Cpu_irq _ipi;
-  // The mutex is used in IPI cases (INIT, SIPI, STOP) and for the local HALT
-  // event. The IPIs do not happen during normal operation, HALT happens when
-  // the core has nothing to do and reacts only to IRQs. In all other VMexits,
-  // this mutex is unused.
-  std::mutex _message_q_lock;
-  std::deque _message_q;
-}; // class Cpu_dev
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid.h
deleted file mode 100644
index 3d1b501f..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid.h
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * \file
- * This file defines the x86 CPU features that we present to the guest via
- * our CPUID emulation.
- *
- * General rules:
- * - Whitelist only those CPU features that we know to support.
- * - We shall support as many features as possible because they might be there
- *   for performance.
- */
-
-namespace
-{
-
-enum Cpuid_1_ecx : l4_uint32_t
-{
-  Cpuid_1_ecx_sse3            = (1UL << 0),
-  Cpuid_1_ecx_pclmulqdq       = (1UL << 1),
-  Cpuid_1_ecx_dtes64          = (1UL << 2),
-  Cpuid_1_ecx_monitor         = (1UL << 3),
-  Cpuid_1_ecx_ds_cpl          = (1UL << 4),
-  Cpuid_1_ecx_vmx             = (1UL << 5),
-  Cpuid_1_ecx_smx             = (1UL << 6),
-  Cpuid_1_ecx_speed_step      = (1UL << 7),
-  Cpuid_1_ecx_thermal_monitor = (1UL << 8),
-  Cpuid_1_ecx_ssse3           = (1UL << 9),
-  Cpuid_1_ecx_context_id      = (1UL << 10),
-  Cpuid_1_ecx_sdbg            = (1UL << 11),
-  Cpuid_1_ecx_fma             = (1UL << 12),
-  Cpuid_1_ecx_cmpxchg16b      = (1UL << 13),
-  Cpuid_1_ecx_xtpr_update     = (1UL << 14),
-  Cpuid_1_ecx_pdcm            = (1UL << 15),
-  Cpuid_1_ecx_pcid            = (1UL << 17),
-  Cpuid_1_ecx_dca             = (1UL << 18),
-  Cpuid_1_ecx_sse4_1          = (1UL << 19),
-  Cpuid_1_ecx_sse4_2          = (1UL << 20),
-  Cpuid_1_ecx_x2apic          = (1UL << 21),
-  Cpuid_1_ecx_movbe           = (1UL << 22),
-  Cpuid_1_ecx_popcnt          = (1UL << 23),
-  Cpuid_1_ecx_tsc_deadline    = (1UL << 24),
-  Cpuid_1_ecx_aesni           = (1UL << 25),
-  Cpuid_1_ecx_xsave           = (1UL << 26),
-  Cpuid_1_ecx_osxsave         = (1UL << 27),
-  Cpuid_1_ecx_avx             = (1UL << 28),
-  Cpuid_1_ecx_f16c            = (1UL << 29),
-  Cpuid_1_ecx_rdrand          = (1UL << 30),
-  Cpuid_1_ecx_hypervisor      = (1UL << 31),
-};
-
-enum Cpuid_1_edx : l4_uint32_t
-{
-  Cpuid_1_edx_fpu   = (1UL << 0),
-  Cpuid_1_edx_vme   = (1UL << 1),
-  Cpuid_1_edx_de    = (1UL << 2),
-  Cpuid_1_edx_pse   = (1UL << 3),
-  Cpuid_1_edx_tsc   = (1UL << 4),
-  Cpuid_1_edx_msr   = (1UL << 5),
-  Cpuid_1_edx_pae   = (1UL << 6),
-  Cpuid_1_edx_mce   = (1UL << 7),
-  Cpuid_1_edx_cx8   = (1UL << 8),
-  Cpuid_1_edx_apic  = (1UL << 9),
-  Cpuid_1_edx_sep   = (1UL << 11),
-  Cpuid_1_edx_mtrr  = (1UL << 12),
-  Cpuid_1_edx_pge   = (1UL << 13),
-  Cpuid_1_edx_mca   = (1UL << 14),
-  Cpuid_1_edx_cmov  = (1UL << 15),
-  Cpuid_1_edx_pat   = (1UL << 16),
-  Cpuid_1_edx_pse_36= (1UL << 17),
-  Cpuid_1_edx_psn   = (1UL << 18),
-  Cpuid_1_edx_clfsh = (1UL << 19),
-  Cpuid_1_edx_ds    = (1UL << 21),
-  Cpuid_1_edx_acpi  = (1UL << 22),
-  Cpuid_1_edx_mmx   = (1UL << 23),
-  Cpuid_1_edx_fxsr  = (1UL << 24),
-  Cpuid_1_edx_sse   = (1UL << 25),
-  Cpuid_1_edx_sse2  = (1UL << 26),
-  Cpuid_1_edx_ss    = (1UL << 27),
-  Cpuid_1_edx_htt   = (1UL << 28),
-  Cpuid_1_edx_tm    = (1UL << 29),
-  Cpuid_1_edx_pbe   = (1UL << 31),
-
-};
-
-// thermal and power management
-enum Cpuid_6_eax : l4_uint32_t
-{
-  Cpuid_6_eax_temp_sens            = (1UL << 0),
-  Cpuid_6_eax_turbo_boost          = (1UL << 1),
-  Cpuid_6_eax_arat                 = (1UL << 2),
-  Cpuid_6_eax_pln                  = (1UL << 4),
-  Cpuid_6_eax_ecmd                 = (1UL << 5),
-  Cpuid_6_eax_ptm                  = (1UL << 6),
-  Cpuid_6_eax_hwp                  = (1UL << 7),
-  Cpuid_6_eax_hwp_notify           = (1UL << 8),
-  Cpuid_6_eax_hwp_act_win          = (1UL << 9),
-  Cpuid_6_eax_hwp_energy_perf_pref = (1UL << 10),
-  Cpuid_6_eax_hwp_package_level    = (1UL << 11),
-  Cpuid_6_eax_hdc                  = (1UL << 13),
-  Cpuid_6_eax_turbo_boost_max      = (1UL << 14),
-  Cpuid_6_eax_hwp_capabilities     = (1UL << 15),
-  Cpuid_6_eax_hwp_peci             = (1UL << 16),
-  Cpuid_6_eax_hwp_flex             = (1UL << 17),
-  Cpuid_6_eax_hwp_request_msr      = (1UL << 18),
-  Cpuid_6_eax_hw_feedback          = (1UL << 19),
-  Cpuid_6_eax_ignore_idle_cpu_hwp  = (1UL << 20),
-  Cpuid_6_eax_hwp_control_msr      = (1UL << 22),
-  Cpuid_6_eax_thread_director      = (1UL << 23),
-  Cpuid_6_eax_therm_irq_msr        = (1UL << 24),
-};
-
-enum Cpuid_7_0_ebx : l4_uint32_t
-{
-  Cpuid_7_0_ebx_fsgsbase       = (1UL << 0),
-  Cpuid_7_0_ebx_tsc_adjust_msr = (1UL << 1),
-  Cpuid_7_0_ebx_sgx            = (1UL << 2),
-  Cpuid_7_0_ebx_bmi1           = (1UL << 3),
-  Cpuid_7_0_ebx_hle            = (1UL << 4),
-  Cpuid_7_0_ebx_avx2           = (1UL << 5),
-  Cpuid_7_0_ebx_fdp_excptn_only= (1UL << 6),
-  Cpuid_7_0_ebx_smep           = (1UL << 7),
-  Cpuid_7_0_ebx_bmi2           = (1UL << 8),
-  Cpuid_7_0_ebx_movsb          = (1UL << 9),
-  Cpuid_7_0_ebx_invpcid        = (1UL << 10),
-  Cpuid_7_0_ebx_rtm            = (1UL << 11),
-  Cpuid_7_0_ebx_rdt_m          = (1UL << 12),
-  Cpuid_7_0_ebx_fpu_cs         = (1UL << 13),
-  Cpuid_7_0_ebx_mpx            = (1UL << 14),
-  Cpuid_7_0_ebx_rdt_a          = (1UL << 15),
-  Cpuid_7_0_ebx_avx_512_f      = (1UL << 16),
-  Cpuid_7_0_ebx_avx_512_dq     = (1UL << 17),
-  Cpuid_7_0_ebx_rdseed         = (1UL << 18),
-  Cpuid_7_0_ebx_adx            = (1UL << 19),
-  Cpuid_7_0_ebx_smap           = (1UL << 20),
-  Cpuid_7_0_ebx_avx_512_ifma   = (1UL << 21),
-  Cpuid_7_0_ebx_clflushopt     = (1UL << 23),
-  Cpuid_7_0_ebx_clwb           = (1UL << 24),
-  Cpuid_7_0_ebx_trace          = (1UL << 25),
-  Cpuid_7_0_ebx_avx_512_pf     = (1UL << 26),
-  Cpuid_7_0_ebx_avx_512_er     = (1UL << 27),
-  Cpuid_7_0_ebx_avx_512_cd     = (1UL << 28),
-  Cpuid_7_0_ebx_sha            = (1UL << 29),
-  Cpuid_7_0_ebx_avx_512_bw     = (1UL << 30),
-  Cpuid_7_0_ebx_avx_512_vl     = (1UL << 31),
-};
-
-enum Cpuid_7_0_ecx : l4_uint32_t
-{
-  Cpuid_7_0_ecx_prefetchwt1      = (1UL << 0),
-  Cpuid_7_0_ecx_avx_512_vbmi     = (1UL << 1),
-  Cpuid_7_0_ecx_umip             = (1UL << 2),
-  Cpuid_7_0_ecx_pku              = (1UL << 3),
-  Cpuid_7_0_ecx_ospke            = (1UL << 4),
-  Cpuid_7_0_ecx_waitpkg          = (1UL << 5),
-  Cpuid_7_0_ecx_avx_512_vbmi2    = (1UL << 6),
-  Cpuid_7_0_ecx_cet_ss           = (1UL << 7),
-  Cpuid_7_0_ecx_gfni             = (1UL << 8),
-  Cpuid_7_0_ecx_vaes             = (1UL << 9),
-  Cpuid_7_0_ecx_vpclmulqdq       = (1UL << 10),
-  Cpuid_7_0_ecx_avx_512_vnni     = (1UL << 11),
-  Cpuid_7_0_ecx_avx_512_bitalg   = (1UL << 12),
-  Cpuid_7_0_ecx_tme_en           = (1UL << 13),
-  Cpuid_7_0_ecx_avx_512_vpopcntdq= (1UL << 14),
-  Cpuid_7_0_ecx_la57             = (1UL << 16),
-  Cpuid_7_0_ecx_rdpid            = (1UL << 22),
-  Cpuid_7_0_ecx_kl               = (1UL << 23),
-  Cpuid_7_0_ecx_bus_lock_detect  = (1UL << 24),
-  Cpuid_7_0_ecx_cldemote         = (1UL << 25),
-  Cpuid_7_0_ecx_movdiri          = (1UL << 27),
-  Cpuid_7_0_ecx_movdir64b        = (1UL << 28),
-  Cpuid_7_0_ecx_enqcmd           = (1UL << 29),
-  Cpuid_7_0_ecx_sgx_lc           = (1UL << 30),
-  Cpuid_7_0_ecx_pks              = (1UL << 31),
-};
-
-enum Cpuid_7_0_edx : l4_uint32_t
-{
-  Cpuid_7_0_edx_sgx_keys            = (1UL << 1),
-  Cpuid_7_0_edx_avx_512_4vnniw      = (1UL << 2),
-  Cpuid_7_0_edx_avx_512_4fmaps      = (1UL << 3),
-  Cpuid_7_0_edx_repmov              = (1UL << 4),
-  Cpuid_7_0_edx_uintr               = (1UL << 5),
-  Cpuid_7_0_edx_avx_512_vp2intersect= (1UL << 8),
-  Cpuid_7_0_edx_srbds_ctrl          = (1UL << 9),
-  Cpuid_7_0_edx_md_clear            = (1UL << 10),
-  Cpuid_7_0_edx_rtm_always_abort    = (1UL << 11),
-  Cpuid_7_0_edx_rtm_force_abort     = (1UL << 13),
-  Cpuid_7_0_edx_serialize           = (1UL << 14),
-  Cpuid_7_0_edx_hybrid              = (1UL << 15),
-  Cpuid_7_0_edx_tsxldtrk            = (1UL << 16),
-  Cpuid_7_0_edx_pconfig             = (1UL << 18),
-  Cpuid_7_0_edx_arch_lbr            = (1UL << 19),
-  Cpuid_7_0_edx_cet_ibt             = (1UL << 20),
-  Cpuid_7_0_edx_amx_fb16            = (1UL << 22),
-  Cpuid_7_0_edx_avx_512_fp16        = (1UL << 23),
-  Cpuid_7_0_edx_amx_tile            = (1UL << 24),
-  Cpuid_7_0_edx_amx_int8            = (1UL << 25),
-  Cpuid_7_0_edx_ibrs                = (1UL << 26),
-  Cpuid_7_0_edx_stibp               = (1UL << 27),
-  Cpuid_7_0_edx_l1d_flush           = (1UL << 28),
-  Cpuid_7_0_edx_arch_cap_msr        = (1UL << 29),
-  Cpuid_7_0_edx_core_cap_msr        = (1UL << 30),
-  Cpuid_7_0_edx_ssbd                = (1UL << 31),
-};
-
-enum Cpuid_8000_0001_ecx : l4_uint32_t
-{
-  // TODO amd has several bits here
-  Cpuid_8000_0001_ecx_lahf      = (1UL << 0),
-  Cpuid_8000_0001_ecx_lzcnt     = (1UL << 5),
-  Cpuid_8000_0001_ecx_prefetchw = (1UL << 8),
-};
-
-enum Cpuid_8000_0001_edx : l4_uint32_t
-{
-  Cpuid_8000_0001_edx_syscall  = (1UL << 11),
-  Cpuid_8000_0001_edx_nx       = (1UL << 20),
-  Cpuid_8000_0001_edx_1gb      = (1UL << 26),
-  Cpuid_8000_0001_edx_rdtscp   = (1UL << 27),
-  Cpuid_8000_0001_edx_ia64     = (1UL << 29),
-};
-
-enum Cpuid_8000_0007_edx : l4_uint32_t
-{
-  Cpuid_8000_0007_edx_invariant_tsc = (1UL << 8),
-};
-
-enum Cpuid_8000_0008_ebx : l4_uint32_t
-{
-  Cpuid_8000_0008_ebx_amd_clzero         = (1UL << 0),
-  Cpuid_8000_0008_ebx_amd_instretcnt_msr = (1UL << 1),
-  Cpuid_8000_0008_ebx_amd_rstrfperrptrs  = (1UL << 2),
-  Cpuid_8000_0008_ebx_amd_invlpkg        = (1UL << 3),
-  Cpuid_8000_0008_ebx_amd_rdpru          = (1UL << 4),
-  Cpuid_8000_0008_ebx_amd_mcommit        = (1UL << 8),
-  Cpuid_8000_0008_ebx_wbnoinvd           = (1UL << 9),
-  // AMD speculation control.
-  // 0x8000'0008 EBX
-  // Whitepaper AMD64 Technology: Indirect Branch Control Extension,
-  // revision 4.10.18
-  Cpuid_8000_0008_ebx_amd_ibpb           = (1UL << 12),
-  Cpuid_8000_0008_ebx_amd_ibrs           = (1UL << 14),
-  Cpuid_8000_0008_ebx_amd_stibp          = (1UL << 15),
-  // Whitepaper AMD64 Technology: Speculative Store Bypass Disable, 5.21.18
-  Cpuid_8000_0008_ebx_amd_ssbd           = (1UL << 24),
-};
-
-}; // namespace
-
-namespace Vmm
-{
-enum Cpuid_configuration : l4_uint32_t
-{
-  // general config
-  Cpuid_max_basic_info_leaf = 0x1f,
-  Cpuid_max_ext_info_leaf   = 0x8000'0008,
-
-  // leaf config
-
-  // Unsupported:
-  //   Cpuid_1_ecx_monitor
-  //   Cpuid_1_ecx_vmx
-  //   Cpuid_1_ecx_smx
-  //   Cpuid_1_ecx_thermal_monitor
-  //   Cpuid_1_ecx_speed_step
-  //   Cpuid_1_ecx_sdbg
-  //   Cpuid_1_ecx_osxsave
-  //   Cpuid_1_ecx_xtpr_update
-  //   Cpuid_1_ecx_pdcm
-  //   Cpuid_1_ecx_context_id
-  //   Cpuid_1_ecx_dca
-  //   Cpuid_1_ecx_ds_cpl
-  //   Cpuid_1_ecx_dtes64
-
-  Cpuid_1_ecx_supported = \
-    Cpuid_1_ecx_sse3 \
-    | Cpuid_1_ecx_pclmulqdq \
-    | Cpuid_1_ecx_ssse3 \
-    | Cpuid_1_ecx_fma \
-    | Cpuid_1_ecx_cmpxchg16b \
-    | Cpuid_1_ecx_sse4_1 \
-    | Cpuid_1_ecx_sse4_2 \
-    | Cpuid_1_ecx_movbe \
-    | Cpuid_1_ecx_popcnt \
-    | Cpuid_1_ecx_tsc_deadline \
-    | Cpuid_1_ecx_aesni \
-    | Cpuid_1_ecx_xsave \
-    | Cpuid_1_ecx_avx \
-    | Cpuid_1_ecx_f16c \
-    | Cpuid_1_ecx_pcid \
-    | Cpuid_1_ecx_rdrand,
-
-  Cpuid_1_ecx_mandatory = \
-    Cpuid_1_ecx_hypervisor
-    // x2apic is emulated even if the host doesn't have it
-    | Cpuid_1_ecx_x2apic,
-
-  // Unsupported flags
-  //  Cpuid_1_edx_mca
-  //  Cpuid_1_edx_acpi
-  //  Cpuid_1_edx_ds
-  //  Cpuid_1_edx_tm
-  //  Cpuid_1_edx_htt
-  //  Cpuid_1_edx_psn
-  //  Cpuid_1_edx_pbe
-  Cpuid_1_edx_supported = \
-    Cpuid_1_edx_fpu \
-    | Cpuid_1_edx_vme \
-    | Cpuid_1_edx_de  \
-    | Cpuid_1_edx_pse \
-    | Cpuid_1_edx_tsc \
-    | Cpuid_1_edx_msr \
-    | Cpuid_1_edx_pae \
-    | Cpuid_1_edx_mce \
-    | Cpuid_1_edx_cx8 \
-    | Cpuid_1_edx_apic\
-    | Cpuid_1_edx_sep \
-    | Cpuid_1_edx_mtrr\
-    | Cpuid_1_edx_pge \
-    | Cpuid_1_edx_cmov\
-    | Cpuid_1_edx_pat \
-    | Cpuid_1_edx_pse_36 \
-    | Cpuid_1_edx_clfsh \
-    | Cpuid_1_edx_mmx \
-    | Cpuid_1_edx_fxsr \
-    | Cpuid_1_edx_sse \
-    | Cpuid_1_edx_sse2 \
-    | Cpuid_1_edx_ss,
-
-  Cpuid_6_eax_supported  = \
-    Cpuid_6_eax_arat,
-
-  Cpuid_7_0_eax_leafs = 1,
-
-  // Unsupported:
-  //   Cpuid_7_0_ebx_mpx
-  //   Cpuid_7_0_ebx_trace
-  Cpuid_7_0_ebx_supported = \
-    Cpuid_7_0_ebx_fsgsbase \
-    | Cpuid_7_0_ebx_bmi1 \
-    | Cpuid_7_0_ebx_hle \
-    | Cpuid_7_0_ebx_avx2 \
-    | Cpuid_7_0_ebx_fdp_excptn_only \
-    | Cpuid_7_0_ebx_smep \
-    | Cpuid_7_0_ebx_bmi2 \
-    | Cpuid_7_0_ebx_movsb \
-    | Cpuid_7_0_ebx_rtm \
-    | Cpuid_7_0_ebx_fpu_cs \
-    | Cpuid_7_0_ebx_avx_512_f \
-    | Cpuid_7_0_ebx_avx_512_dq \
-    | Cpuid_7_0_ebx_rdseed \
-    | Cpuid_7_0_ebx_adx \
-    | Cpuid_7_0_ebx_smap \
-    | Cpuid_7_0_ebx_avx_512_ifma \
-    | Cpuid_7_0_ebx_clflushopt \
-    | Cpuid_7_0_ebx_clwb \
-    | Cpuid_7_0_ebx_avx_512_pf \
-    | Cpuid_7_0_ebx_avx_512_er \
-    | Cpuid_7_0_ebx_avx_512_cd \
-    | Cpuid_7_0_ebx_sha \
-    | Cpuid_7_0_ebx_invpcid \
-    | Cpuid_7_0_ebx_avx_512_bw \
-    | Cpuid_7_0_ebx_avx_512_vl,
-
-  // Unsupported:
-  //   Cpuid_7_0_ecx_ospke
-  //   Cpuid_7_0_ecx_waitpkg
-  //   Cpuid_7_0_ecx_la57 (ia32e 5 level paging)
-  Cpuid_7_0_ecx_supported  = \
-    Cpuid_7_0_ecx_prefetchwt1 \
-    | Cpuid_7_0_ecx_avx_512_vbmi \
-    | Cpuid_7_0_ecx_umip \
-    | Cpuid_7_0_ecx_avx_512_vbmi2 \
-    | Cpuid_7_0_ecx_avx_512_vnni \
-    | Cpuid_7_0_ecx_avx_512_bitalg,
-
-  Cpuid_7_0_edx_supported = \
-    Cpuid_7_0_edx_avx_512_4vnniw \
-    | Cpuid_7_0_edx_avx_512_4fmaps \
-    | Cpuid_7_0_edx_repmov \
-    | Cpuid_7_0_edx_avx_512_vp2intersect \
-    | Cpuid_7_0_edx_avx_512_fp16 \
-    | Cpuid_7_0_edx_uintr \
-    | Cpuid_7_0_edx_md_clear,
-
-  Cpuid_8000_0001_ecx_supported = \
-    Cpuid_8000_0001_ecx_lahf,
-
-  Cpuid_8000_0001_edx_supported = \
-    Cpuid_8000_0001_edx_syscall \
-    | Cpuid_8000_0001_edx_nx \
-    | Cpuid_8000_0001_edx_1gb \
-    | Cpuid_8000_0001_edx_ia64,
-
-  Cpuid_8000_0007_edx_supported = \
-    Cpuid_8000_0007_edx_invariant_tsc,
-
-  // According to the Linux source code at arch/x86/kernel/cpu/common.c,
-  // "[...] a hypervisor might have set the individual AMD bits even on
-  // Intel CPUs, for finer-grained selection of what's available."
-  // Thus filter AMD bits for the case of nested virtualization.
-  Cpuid_8000_0008_ebx_supported = \
-    Cpuid_8000_0008_ebx_wbnoinvd,
-};
-
-inline void
-cpuid_reg_apply(l4_uint32_t *host_register,
-                l4_uint32_t  supported_bits,
-                l4_uint32_t  mandatory_bits = 0)
-{
-  *host_register &= supported_bits;
-  *host_register |= mandatory_bits;
-}
-
-}; // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid_device.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid_device.h
deleted file mode 100644
index 00569896..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/cpuid_device.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Jakub Jermar 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "device.h"
-
-namespace Vmm {
-
-/**
- * Interface for devices responding to guest CPUID invocations.
- */
-struct Cpuid_device : virtual Vdev::Dev_ref
-{
-  virtual ~Cpuid_device() = 0;
-
-  /**
-   * Handle the CPUID instruction.
-   *
-   * \param regs        Guest register state.
-   * \param a[out]      Output value for RAX.
-   * \param b[out]      Output value for RBX.
-   * \param c[out]      Output value for RCX.
-   * \param d[out]      Output value for RDX.
-   *
-   * \return             True if the device handled the CPUID instruction,
-   *                     false otherwise.
-   */
-  virtual bool handle_cpuid(l4_vcpu_regs_t const *regs, unsigned *a,
-                            unsigned *b, unsigned *c, unsigned *d) const = 0;
-};
-
-inline Cpuid_device::~Cpuid_device() = default;
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/debugger/guest_debugger.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/debugger/guest_debugger.h
deleted file mode 100644
index 64c6d80d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/debugger/guest_debugger.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "debugger/generic_guest_debugger.h"
-#include "monitor/dbg_cmd_handler.h"
-
-namespace Monitor {
-
-class Guest_debugger
-: public Generic_guest_debugger,
-  public Dbg_cmd_handler
-{
-public:
-  using Generic_guest_debugger::Generic_guest_debugger;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.cc
deleted file mode 100644
index d0a7f0b1..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "event_record.h"
-#include "event_record_lapic.h"
-
-namespace Vmm {
-
-bool Event_exc::inject(Vm_state *vm)
-{
-  vm->inject_event(
-    Injection_event(ev_num, 3, error_val != Invalid_error, error_val));
-  return true;
-}
-
-bool Real_mode_exc::inject(Vm_state *vm)
-{
-  vm->inject_event(Injection_event(ev_num, 3, false));
-  return true;
-}
-
-bool Event_nmi::inject(Vm_state *vms)
-{
-  if (vms->can_inject_nmi())
-    {
-      vms->disable_nmi_window();
-      lapic->next_pending_nmi();
-      vms->inject_event(Injection_event(2, 2, false)); // NMI is vector 2, type 2
-      return true;
-    }
-
-  vms->enable_nmi_window();
-  return false;
-}
-
-bool Event_irq::inject(Vm_state *vms)
-{
-  if (vms->can_inject_interrupt())
-    {
-      vms->disable_interrupt_window();
-      int irq = lapic->next_pending_irq();
-      if (irq < 0)
-        {
-          return true;
-        }
-
-      vms->inject_event(Injection_event(irq, 0, false)); // IRQ vector, type 0
-      return true;
-    }
-
-  vms->enable_interrupt_window();
-  return false;
-}
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.h
deleted file mode 100644
index c233452f..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "vm_state.h"
-
-namespace Vmm {
-
-/**
- * Event priority order
- *
- * The priortiy is specified in the Intel SDM 12/2022 Vol 3
- * Section 6.9 "Prioritization of Concurrent Events".
- */
-enum Event_prio : char
-{
-  // on instruction events
-  Abort = 0,
-  Exception,
-  Sw_int1,
-  Sw_int3,
-  Sw_intO,
-  Sw_intN,
-  Bound,
-  // potentially concurrent events raised on instructions boundaries.
-  Reset,
-  Machine_check,
-  Trap_task_switch,
-  Ext_hw_intervention,
-  Trap_dbg_except,
-  Nmi,
-  Irq,
-  Fault_dbg_except,
-  Fault_fetch_next_instr,
-  Fault_decode_next_instr,
-
-  Prio_max // must be last
-};
-
-/**
- *  Single event record, e.g. for an event raised by hardware.
- */
-struct Event_record
-{
-  explicit Event_record(Event_prio p) : prio(p) {}
-
-  virtual ~Event_record() = default;
-
-  virtual bool inject(Vm_state *vms) = 0;
-
-  constexpr bool operator < (Event_record const &o) const
-  { return prio < o.prio; }
-
-  constexpr bool operator > (Event_record const &o) const
-  { return prio > o.prio; }
-
-  constexpr bool operator == (Event_record const &o) const
-  { return prio == o.prio; }
-
-  Event_prio const prio;        ///< Type of the Event_record
-};
-
-/**
- * Exception event record.
- */
-struct Event_exc : Event_record
-{
-  enum : unsigned { Invalid_error = ~0U };
-
-  explicit Event_exc(Event_prio p, unsigned ev_num)
-  : Event_record(p), ev_num(ev_num)
-  {}
-
-  Event_exc(Event_prio p, unsigned ev_num, unsigned e_val)
-  : Event_record(p), ev_num(ev_num), error_val(e_val)
-  {}
-
-  bool inject(Vm_state *vm) override;
-
-  unsigned ev_num;                     ///< Event number to inject
-  unsigned error_val = Invalid_error;  ///< Error value to push on the stack
-};
-
-struct Real_mode_exc : Event_record
-{
-  explicit Real_mode_exc(Event_prio p, unsigned ev_num)
-  : Event_record(p), ev_num(ev_num)
-  {}
-
-  bool inject(Vm_state *vm) override;
-
-  unsigned ev_num;              ///< Event number to inject
-};
-
-/**
- * Generic software exception/interrupt event to inject into the guest.
- *
- * \tparam TYPE  Event type to use in injection.
- */
-template 
-struct Event_sw_generic : Event_record
-{
-  Event_sw_generic(Event_prio p, unsigned ev_num, unsigned insn_len)
-  : Event_record(p), ev_num(ev_num), instruction_len(insn_len)
-  {}
-
-  bool inject(Vm_state *vm) override
-  {
-    vm->inject_event(Injection_event(ev_num, TYPE, false));
-    if (vm->type() == Vm_state::Type::Vmx)
-      vm->advance_entry_ip(instruction_len);
-
-    return true;
-  }
-
-  unsigned ev_num;              ///< Event number to inject
-  unsigned instruction_len;     ///< Bytes to advance IP
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record_lapic.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record_lapic.h
deleted file mode 100644
index 2d287408..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_record_lapic.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "event_record.h"
-#include "virt_lapic.h"
-
-namespace Vmm
-{
-
-/**
- * NMI event record.
- */
-struct Event_nmi : Event_record
-{
-  explicit Event_nmi(Gic::Virt_lapic *apic)
-  : Event_record(Event_prio::Nmi), lapic(apic)
-  {}
-
-  bool inject(Vm_state *vm) override;
-
-  Gic::Virt_lapic *lapic;
-};
-
-/**
- * IRQ event record.
- */
-struct Event_irq : Event_record
-{
-  explicit Event_irq(Gic::Virt_lapic *apic)
-  : Event_record(Event_prio::Irq), lapic(apic)
-  {}
-
-  bool inject(Vm_state *vm) override;
-
-  Gic::Virt_lapic *lapic;
-};
-
-// These are necessary to correctly compute Event_memory::max_event_size().
-// The asserts ensure that these event objects don't influence the computation.
-static_assert(sizeof(Event_irq) <= sizeof(Event_exc),
-              "IRQ event objects are not the largest event object.");
-static_assert(sizeof(Event_nmi) <= sizeof(Event_exc),
-              "NMI event objects are not the largest event object.");
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.cc
deleted file mode 100644
index b92ed2b6..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "event_recorder.h"
-#include "debug.h"
-
-namespace Vmm {
-
-bool Event_recorder::inject(Vm_state *vms)
-{
-  if (empty())
-    return false;
-
-  auto top = _queue.top();
-  if (top->inject(vms))
-    {
-      _queue.pop();
-      if (top->prio == Event_prio::Exception)
-        {
-          if (_queue.empty() || _queue.top()->prio != Event_prio::Exception)
-            _has_exception = false;
-        }
-      else if (top->prio == Event_prio::Nmi)
-        _has_nmi = false;
-      else if (top->prio == Event_prio::Irq)
-        _has_irq = false;
-
-      // We have ownership. We have to free the memory!
-      free_event(top);
-      return true;
-    }
-
-  return false;
-}
-
-void Event_recorder::add(Event_record *event)
-{
-  if (event->prio == Event_prio::Exception)
-    _has_exception = true;
-  else if (event->prio == Event_prio::Nmi)
-    {
-      if (_has_nmi)
-        return;
-      else
-        _has_nmi = true;
-    }
-  else if (event->prio == Event_prio::Irq)
-    {
-      if (_has_irq)
-        return;
-      else
-        _has_irq = true;
-    }
-
-  _queue.push(std::move(event));
-}
-
-void Event_recorder::clear()
-{
-  while (!_queue.empty())
-    {
-      auto top = _queue.top();
-      _queue.pop();
-      // We have ownership. We have to free the memory!
-      free_event(top);
-    }
-
-  _has_exception = false;
-  _has_nmi = false;
-  _has_irq = false;
-}
-
-bool Event_recorder::empty() const
-{ return _queue.empty(); }
-
-void Event_recorder::dump(unsigned vcpu_id) const
-{
-  static char const *Event_prio_names[Event_prio::Prio_max] = {
-    "Abort",
-    "Exception",
-    "Sw_int1",
-    "Sw_int3",
-    "Sw_intO",
-    "Sw_intN",
-    "Bound",
-    "Reset",
-    "Machine_check",
-    "Trap_task_switch",
-    "Ext_hw_intervention",
-    "Trap_dbg_except",
-    "Nmi",
-    "Interrupt",
-    "Fault_dbg_except",
-    "Fault_fetch_next_instr",
-    "Fault_decode_next_instr",
-  };
-
-  if (_queue.empty())
-    {
-      Dbg().printf("[%3u] Ev_rec: No event recorded.\n", vcpu_id);
-      return;
-    }
-
-  auto prio = _queue.top()->prio;
-  char const *name = prio < Event_prio::Prio_max ? Event_prio_names[prio]
-                                                 : "Index out of bounds";
-  Dbg().printf("[%3u] Ev_rec: Top event has prio %i (%s); #events: %zu\n",
-               vcpu_id, prio, name, _queue.size());
-}
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.h
deleted file mode 100644
index 07eca6b5..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/event_recorder.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-#include "event_record.h"
-#include "vm_state.h"
-#include "debug.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-
-namespace Vmm {
-
-/// Recorder of all events for a core.
-class Event_recorder
-{
-public:
-  ~Event_recorder() { clear(); }
-
-  /**
-   * Inject highest priority event.
-   *
-   * \retval true   Event injected.
-   * \retval false  No event to inject or can't inject pending event.
-   */
-  bool inject(Vm_state *vms);
-
-  /**
-   * Record an event.
-   *
-   * \note Pending interrupts are recorded as placeholder item such that the
-   *       caller knows the query the local APIC. NMI and IRQs are just
-   *       recorded once.
-   *
-   * \post Ownership moves to `Event_recorder`.
-   */
-  void add(Event_record *event);
-
-  /// Clears all recorded events.
-  void clear();
-  /// True, iff no event recorded.
-  bool empty() const;
-  /// FIXME for MSR interface lacking return value tristate.
-  bool has_exception() const { return _has_exception; }
-  /// true, iff IRQ event already recorded
-  bool has_nmi() const { return _has_nmi; }
-  /// true, iff IRQ event already recorded
-  bool has_irq() const { return _has_irq; }
-
-  /// debugging aid
-  void dump(unsigned vcpu_id) const;
-
-  /// Create an Event instance and record it.
-  template 
-  void make_add_event(ARGS... args)
-  {
-    add(allocate_event(args...));
-  }
-
-private:
-  static Dbg warn() { return Dbg(Dbg::Core, Dbg::Warn, "Event recorder"); }
-
-  /**
-   * Allocate memory for an object of type `T`.
-   *
-   * \tparam T  Type derived from `Event_record`.
-   *
-   */
-  template 
-  Event_record *allocate_event(ARGS... args)
-  {
-    static bool warn_once = true;
-    char *addr = _memory.alloc(sizeof(T));
-    if (addr)
-      return new (addr) T(std::forward(args)...);
-    else
-      {
-        // Print message once, if dynamic allocation is necessary on any core.
-        if (warn_once)
-          {
-            warn_once = false;
-            warn().printf("Usage of the slow path for event allocation. Memory "
-                          "preallocation exceeded for the first time.");
-          }
-        return new T(std::forward(args)...);
-      }
-  }
-
-  /**
-   * Destruct object derived from `Event_record` and free the memory.
-   *
-   * \param object  Address of the object to destruct and free.
-   */
-  void free_event(Event_record *object)
-  {
-    if (_memory.in_memory(reinterpret_cast(object)))
-      {
-        object->~Event_record();
-        _memory.free(reinterpret_cast(object));
-      }
-    else
-      delete object;
-  }
-
-  /**
-   * Encapsulate all memory management for Event_records within this class.
-   *
-   * We want to avoid dynamic memory allocation during VM exit handling and
-   * thus preallocate the memory and create events within this memory range.
-   * The memory is split into chunks that fit all Event_records object sizes
-   * and returns one such chunk on request.
-   *
-   * It's an open question how to handle OOM situations.
-   */
-  class Event_memory
-  {
-    struct Bin_if
-    {
-      virtual ~Bin_if() = default;
-      virtual char *alloc() = 0;
-      virtual bool free(char *) = 0;
-      virtual bool managed_addr(char *addr) const = 0;
-    };
-
-    template 
-    struct Bin : Bin_if
-    {
-      Bin() { slot_used.clear_all(); }
-
-      ~Bin() = default;
-
-      char *alloc() noexcept override
-      {
-        int free_idx = slot_used.scan_zero(0);
-        if (free_idx >= 0)
-          {
-            slot_used[free_idx] = true;
-            return mem + free_idx * BIN_SIZE;
-          }
-
-        warn().printf("no space in bin left to allocate. Bin addr %p, num bins "
-                     "%u, bin size %u\n",
-                     &mem, SLOTS, BIN_SIZE);
-        return nullptr;
-      }
-
-      bool free(char *addr) noexcept override
-      {
-        unsigned bin_idx = (addr - mem) / BIN_SIZE;
-        assert(slot_used[bin_idx] == true);
-
-        slot_used[bin_idx] = false;
-        return true;
-      }
-
-      bool managed_addr(char * addr) const noexcept override
-      {
-        if (addr < mem || addr >= mem + MEM_SIZE)
-          {
-            info().printf("Address %p not in bin-managed range[%p, %p]. Bin "
-                          "size: 0x%x\n",
-                          addr, mem, mem + MEM_SIZE, BIN_SIZE);
-            return false;
-          }
-
-        return true;
-      }
-
-      static unsigned constexpr MEM_SIZE = BIN_SIZE * SLOTS;
-      cxx::Bitmap slot_used;
-      char mem[MEM_SIZE];
-    };
-
-    /**
-     * Compute maximum object size of all events.
-     *
-     * This depends on static_asserts for Event_nmi & Event_irq.
-     */
-    static unsigned constexpr max_event_size()
-    {
-      // Event types: Event_exc, Real_mode_exc, Event_sw_generic, Event_nmi,
-      // Event_irq
-
-      unsigned constexpr size =
-        cxx::max(sizeof(Event_exc), sizeof(Real_mode_exc),
-                 sizeof(Event_sw_generic<0>));
-
-      // round to next power of two to fit to cache lines.
-      return next_pow2(size);
-    }
-
-    /**
-     * Compute the next larger value which is a power of two.
-     *
-     * \param num  Number to start from.
-     */
-    static unsigned constexpr next_pow2(unsigned num)
-    {
-      static_assert(sizeof(unsigned) <= 4,
-                    "Next power of 2 algorithm only supports 32-bit numbers.");
-
-      if (num == 0U)
-        return 1;
-
-      --num;
-      num |= num >> 1;
-      num |= num >> 2;
-      num |= num >> 4;
-      num |= num >> 8;
-      num |= num >> 16;
-
-      return ++num;
-    }
-
-  public:
-    Event_memory()
-    {
-      // instead of one preallocated bin per event size, we simplify and
-      // use one bin for all events and accept the additional temporary memory
-      // usage within a bin. Only the bin size affects the total memory usage.
-      unsigned constexpr size = max_event_size();
-      _bin = new Bin();
-    }
-
-    ~Event_memory()
-    {
-      if (_bin)
-        delete _bin;
-    }
-
-    char *alloc(l4_size_t /* size */)
-    {
-      char *addr = _bin->alloc();
-      return addr;
-    }
-
-    // pre: in_memory(addr) == true
-    void free(char *addr)
-    {
-      assert(in_memory(addr));
-
-      _bin->free(addr);
-    }
-
-    bool in_memory(char *addr)
-    {
-      return _bin->managed_addr(addr);
-    }
-
-  private:
-    static Dbg warn() { return Dbg(Dbg::Core, Dbg::Warn, "Event memory"); }
-    static Dbg info() { return Dbg(Dbg::Core, Dbg::Info, "Event memory"); }
-
-    Bin_if *_bin;
-  }; // class Event_memory
-
-  using Qtype = Event_record *;
-
-  struct QGreater
-  {
-    bool operator()(Qtype const &item1, Qtype const &item2) const
-    { return *item1 > *item2; }
-  };
-
-  std::priority_queue, QGreater> _queue;
-  Event_memory _memory;
-  bool _has_exception = false;
-  bool _has_nmi = false;
-  bool _has_irq = false;
-};
-
-/// Interface to get the event recorder for a specific core.
-struct Event_recorders
-{
-  virtual Event_recorder *recorder(unsigned num) = 0;
-};
-
-/**
- * Management entity for one `Event_recorder` per core.
- */
-class Event_recorder_array : public Event_recorders
-{
-public:
-  virtual ~Event_recorder_array() = default;
-
-  void init(unsigned size)
-  { _recorders.resize(size); }
-
-  Event_recorder *recorder(unsigned num) override
-  {
-    assert(num < _recorders.size());
-    return &_recorders[num];
-  }
-
-private:
-  std::vector _recorders;
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/framebuffer.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/framebuffer.cc
deleted file mode 100644
index 6faad162..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/framebuffer.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2021-2022, 2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "guest.h"
-
-static bool fb_present = false;
-static l4_uint64_t fb_addr, fb_size;
-static L4Re::Video::View::Info fb_viewinfo;
-
-namespace Vdev {
-// Taken from linux/include/uapi/linux/screen_info.h
-struct screen_info {
-	l4_uint8_t  orig_x;		/* 0x00 */
-	l4_uint8_t  orig_y;		/* 0x01 */
-	l4_uint16_t ext_mem_k;	/* 0x02 */
-	l4_uint16_t orig_video_page;	/* 0x04 */
-	l4_uint8_t  orig_video_mode;	/* 0x06 */
-	l4_uint8_t  orig_video_cols;	/* 0x07 */
-	l4_uint8_t  flags;		/* 0x08 */
-	l4_uint8_t  unused2;		/* 0x09 */
-	l4_uint16_t orig_video_ega_bx;/* 0x0a */
-	l4_uint16_t unused3;		/* 0x0c */
-	l4_uint8_t  orig_video_lines;	/* 0x0e */
-	l4_uint8_t  orig_video_isVGA;	/* 0x0f */
-	l4_uint16_t orig_video_points;/* 0x10 */
-
-	/* VESA graphic mode -- linear frame buffer */
-	l4_uint16_t lfb_width;	/* 0x12 */
-	l4_uint16_t lfb_height;	/* 0x14 */
-	l4_uint16_t lfb_depth;	/* 0x16 */
-	l4_uint32_t lfb_base;		/* 0x18 */
-	l4_uint32_t lfb_size;		/* 0x1c */
-	l4_uint16_t cl_magic, cl_offset; /* 0x20 */
-	l4_uint16_t lfb_linelength;	/* 0x24 */
-	l4_uint8_t  red_size;		/* 0x26 */
-	l4_uint8_t  red_pos;		/* 0x27 */
-	l4_uint8_t  green_size;	/* 0x28 */
-	l4_uint8_t  green_pos;	/* 0x29 */
-	l4_uint8_t  blue_size;	/* 0x2a */
-	l4_uint8_t  blue_pos;		/* 0x2b */
-	l4_uint8_t  rsvd_size;	/* 0x2c */
-	l4_uint8_t  rsvd_pos;		/* 0x2d */
-	l4_uint16_t vesapm_seg;	/* 0x2e */
-	l4_uint16_t vesapm_off;	/* 0x30 */
-	l4_uint16_t pages;		/* 0x32 */
-	l4_uint16_t vesa_attributes;	/* 0x34 */
-	l4_uint32_t capabilities;     /* 0x36 */
-	l4_uint32_t ext_lfb_base;	/* 0x3a */
-	l4_uint8_t  _reserved[2];	/* 0x3e */
-} __attribute__((packed));
-
-enum {
-  Video_type_vlfb = 0x23
-};
-
-enum {
-  Video_capability_skip_quirks = (1 << 0),
-  /* Frame buffer base is 64-bit */
-  Video_capability_64bit_base = (1 << 1)
-};
-
-static void configure_framebuffer(void *zeropage)
-{
-  auto *si = reinterpret_cast(zeropage);
-
-  // define framebuffer type
-  si->orig_video_isVGA = Video_type_vlfb;
-  si->capabilities = Video_capability_skip_quirks | Video_capability_64bit_base;
-
-  // setup address and size of buffer
-  si->lfb_base = fb_addr & 0xffffffff;
-  si->ext_lfb_base = fb_addr >> 32;
-  // framebuffer size is in 64 KiB chunks for VLFB per historical convention
-  si->lfb_size = l4_round_size(fb_size, 16) >> 16;
-
-  // define dimensions
-  si->lfb_width  = fb_viewinfo.width;
-  si->lfb_height = fb_viewinfo.height;
-  si->lfb_linelength = fb_viewinfo.bytes_per_line;
-
-  // define color
-  si->lfb_depth  = fb_viewinfo.pixel_info.bytes_per_pixel() * 8;
-  si->red_size   = fb_viewinfo.pixel_info.r().size();
-  si->red_pos    = fb_viewinfo.pixel_info.r().shift();
-  si->green_size = fb_viewinfo.pixel_info.g().size();
-  si->green_pos  = fb_viewinfo.pixel_info.g().shift();
-  si->blue_size  = fb_viewinfo.pixel_info.b().size();
-  si->blue_pos   = fb_viewinfo.pixel_info.b().shift();
-  si->rsvd_size  = fb_viewinfo.pixel_info.padding().size();
-  si->rsvd_pos   = fb_viewinfo.pixel_info.padding().shift();
-}
-} // namespace Vdev
-
-namespace Vmm {
-bool
-Guest::register_framebuffer(l4_uint64_t addr, l4_uint64_t size,
-                            const L4Re::Video::View::Info &info)
-{
-  if (fb_present)
-    {
-      Err().printf("0x%llx: Multiple definitions of framebuffer, only one framebuffer is supported\n",
-                   addr);
-      return false;
-    }
-
-  fb_present = true;
-  fb_addr = addr;
-  fb_size = size;
-  fb_viewinfo = info;
-  Vmm::Zeropage::set_screen_callback(Vdev::configure_framebuffer);
-  return true;
-}
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-svm.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-svm.cc
deleted file mode 100644
index e0069694..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-svm.cc
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2018-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *            Benjamin Lamowski 
- *            Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "guest.h"
-#include "debug.h"
-#include "vm_state_svm.h"
-
-namespace Vmm {
-
-/**
- * Synchronize VMCB.StateSaveArea.RAX with Vcpu_regs.RAX.
- */
-class Rax_guard
-{
-public:
-  Rax_guard(Svm_state *vms, l4_vcpu_regs_t *regs) : _vms(vms), _regs(regs)
-  { _regs->ax = _vms->vmcb()->state_save_area.rax; }
-
-  ~Rax_guard()
-  { _vms->vmcb()->state_save_area.rax = _regs->ax; }
-
-private:
-  Svm_state *_vms;
-  l4_vcpu_regs_t *_regs;
-};
-
-template <>
-int
-Guest::handle_exit(Vmm::Cpu_dev *cpu, Svm_state *vms)
-{
-  Vmm::Vcpu_ptr vcpu = cpu->vcpu();
-  l4_vcpu_regs_t *regs = &vcpu->r;
-  unsigned vcpu_id = vcpu.get_vcpu_id();
-
-  // Synchronize VMCB.StateSaveArea.RAX with Vcpu_regs.RAX. This is necessary
-  // because the code shared between VMX and SVM uses the RAX in Vcpu_regs,
-  // since in VMX only RSP and RIP are stored in the "guest state save area".
-  Rax_guard rax_guard(vms, regs);
-
-  // Initially all fields are clean
-  vms->mark_all_clean();
-
-  auto *ev_rec = recorder(vcpu.get_vcpu_id());
-  using Exit = Svm_state::Exit;
-  Exit reason = vms->exit_code();
-
-  switch (reason)
-    {
-    // TODO: Lacks handlers for some of the enabled intercepts, which have not
-    // been triggered during development. If one of these interceptions is hit,
-    // first an error message is printed and then the VM is stopped.
-    case Exit::Cpuid: return handle_cpuid(vcpu);
-
-    case Exit::Vmmcall: return handle_vm_call(regs);
-
-    case Exit::Ioio:
-      {
-        Svm_state::Io_info info(vms->exit_info1());
-        bool is_read = info.type() == 1;
-        unsigned port = info.port();
-
-        trace().printf("[%3u]: VM exit: IO port access with exit info 0x%x: "
-                       "%s port 0x%x\n",
-                       vcpu_id, info.raw, is_read ? "read" : "write", port);
-
-        if (info.str())
-        {
-          warn().printf("[%3u]: String based port access is not supported!\n",
-                        vcpu_id);
-          return Jump_instr;
-        }
-
-        // rep prefix is only specified for string port access instructions,
-        // which are not yet supported anyway.
-        if (info.rep())
-        {
-          warn().printf("[%3u]: Repeated port access is not supported!\n",
-                        vcpu_id);
-          return Jump_instr;
-        }
-
-        Mem_access::Width wd = Mem_access::Wd32;
-        switch (info.data_size())
-          {
-          case 1: wd = Mem_access::Wd8; break;
-          case 2: wd = Mem_access::Wd16; break;
-          case 4: wd = Mem_access::Wd32; break;
-          }
-
-        return handle_io_access(port, is_read, wd, regs);
-      }
-
-    case Exit::Nested_page_fault:
-      {
-        l4_addr_t guest_phys_addr = vms->exit_info2();
-        Svm_state::Npf_info info(vms->exit_info1());
-
-        trace().printf(
-          "[%3u]: Nested page fault at gp_addr 0x%lx with exit info 0x%llx\n",
-          vcpu_id, guest_phys_addr, info.raw);
-
-        // TODO: Use instruction bytes provided by decode assist
-        switch(handle_mmio(guest_phys_addr, vcpu))
-          {
-          case Retry: return L4_EOK;
-          case Jump_instr:
-            {
-              // TODO: Avoid fetching and decoding the current instruction again
-              // (handle_mmio already did that once).
-              l4_uint64_t opcode;
-              try
-                {
-                  // overwrite the virtual IP with the physical OP code
-                  opcode = vcpu.get_pt_walker()->walk(vms->cr3(), vms->ip());
-                }
-              catch (L4::Runtime_error &e)
-                {
-                  warn().printf("[%3u]: Could not determine opcode for MMIO "
-                                "access\n",
-                                vcpu_id);
-                  return -L4_EINVAL;
-                }
-
-              // TODO: Check inst_buf points to valid memory and figure out its size.
-              unsigned char *inst_buf = reinterpret_cast(opcode);
-              unsigned inst_buf_len = 15;
-
-              // The next sequential instruction pointer (nRIP) is not saved for
-              // nested page faults:
-              // > nRIP is saved for instruction intercepts as well as MSR and
-              // > IOIO intercepts and exceptions caused by the INT3, INTO,
-              // > and BOUND instructions.
-              // > For all other intercepts, nRIP is reset to zero.
-              if (vms->determine_next_ip_from_ip(regs, inst_buf, inst_buf_len))
-                return Jump_instr;
-              else
-                {
-                  warn().printf("[%3u]: Could not determine next ip for MMIO "
-                                "access\n",
-                                vcpu_id);
-                  return -L4_EINVAL;
-                }
-            }
-          default: break;
-          }
-
-        warn().printf("[%3u]: Unhandled nested page fault @ 0x%lx\n", vcpu_id,
-                      vms->ip());
-        warn()
-          .printf("[%3u]: Present: %u, Type: %s, Inst.: %u Phys addr: 0x%lx\n",
-                  vcpu_id, info.present().get(),
-                  info.write() ? "Write" : "Read", info.inst().get(),
-                  guest_phys_addr);
-        return -L4_EINVAL;
-      }
-
-    case Exit::Msr:
-      {
-        bool write = vms->exit_info1() == 1;
-        bool has_already_exception = ev_rec->has_exception();
-        if (!msr_devices_rwmsr(regs, write, vcpu.get_vcpu_id()))
-          {
-            info().printf("[%3u]: %s unsupported MSR 0x%lx\n", vcpu_id,
-                          write ? "Writing" : "Reading", regs->cx);
-            ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-            return Retry;
-          }
-
-        if (!has_already_exception && ev_rec->has_exception())
-          return Retry;
-        else
-          return Jump_instr;
-      }
-
-    case Exit::Hlt:
-      trace().printf("[%3u]: HALT 0x%lx!\n", vcpu_id, vms->ip());
-      vms->halt();
-      cpu->halt_cpu();
-      return Jump_instr;
-
-    case Exit::Cr0_sel_write:
-      return vms->handle_cr0_write(regs);
-
-    case Exit::Xsetbv:
-      return vms->handle_xsetbv(regs);
-
-    case Exit::Vintr:
-      // Used as interrupt window notification, handled in run_vm().
-      return L4_EOK;
-
-    case Exit::Rdpmc:
-      ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-      return Retry;
-
-    case Exit::Dr0_read:
-    case Exit::Dr1_read:
-    case Exit::Dr2_read:
-    case Exit::Dr3_read:
-    case Exit::Dr4_read:
-    case Exit::Dr5_read:
-    case Exit::Dr6_read:
-    case Exit::Dr7_read:
-      {
-        int i = static_cast(reason) - static_cast(Exit::Dr0_read);
-        if (i == 4 || i == 5)
-          {
-            if (vms->vmcb()->state_save_area.cr4 & (1U << 3)) // CR4.DE set?
-              {
-                ev_rec->make_add_event(Event_prio::Exception, 6);
-                return Retry;
-              }
-            // else: alias to DR6 & DR7
-          }
-
-        unsigned char gp_reg = vms->vmcb()->control_area.exitinfo1 & 0xf;
-        *(&(regs->ax) - gp_reg) = 0;
-        return Jump_instr;
-      }
-    case Exit::Dr8_read:
-    case Exit::Dr9_read:
-    case Exit::Dr10_read:
-    case Exit::Dr11_read:
-    case Exit::Dr12_read:
-    case Exit::Dr13_read:
-    case Exit::Dr14_read:
-    case Exit::Dr15_read:
-      // AMD APM Vol 2 Chapter 13.1.1.5 "64-Bit-Mode Extended Debug Registers":
-      // DR8-15 are not implemented -> #UD
-      ev_rec->make_add_event(Event_prio::Exception, 6);
-      return Retry;
-
-    case Exit::Dr0_write:
-    case Exit::Dr1_write:
-    case Exit::Dr2_write:
-    case Exit::Dr3_write:
-    case Exit::Dr4_write:
-    case Exit::Dr5_write:
-    case Exit::Dr6_write:
-    case Exit::Dr7_write:
-      {
-        // Ignore the writes, except to illegal registers.
-        int i = static_cast(reason) - static_cast(Exit::Dr0_read);
-        if (i == 4 || i == 5)
-          {
-            if (vms->vmcb()->state_save_area.cr4 & (1U << 3)) // CR4.DE set?
-              {
-                ev_rec->make_add_event(Event_prio::Exception, 6);
-                return Retry;
-              }
-          }
-        return Jump_instr;
-      }
-    case Exit::Dr8_write:
-    case Exit::Dr9_write:
-    case Exit::Dr10_write:
-    case Exit::Dr11_write:
-    case Exit::Dr12_write:
-    case Exit::Dr13_write:
-    case Exit::Dr14_write:
-    case Exit::Dr15_write:
-      // AMD APM Vol 2 Chapter 13.1.1.5 "64-Bit-Mode Extended Debug Registers":
-      // DR8-15 are not implemented -> #UD
-      ev_rec->make_add_event(Event_prio::Exception, 6);
-      return Retry;
-
-    case Exit::Vmrun:
-    case Exit::Vmload:
-    case Exit::Vmsave:
-    case Exit::Stgi:
-    case Exit::Clgi:
-    case Exit::Skinit:
-    case Exit::Rdtscp:
-      // Unsupported instructions, inject undefined opcode exception
-      ev_rec->make_add_event(Event_prio::Exception, 6);
-      return Retry;
-
-    case Exit::Sw_int:
-      {
-        // exit_info1[7:0] contains vector
-        l4_uint32_t sw_int_num = vms->exit_info1() & 0xff;
-
-        using Event_sw_int = Event_sw_generic<4>;
-        ev_rec->make_add_event(Event_prio::Sw_intN, sw_int_num,
-                                             0U);
-
-        return Retry;
-      }
-
-    case Exit::Icebp:
-      // Emulating ICEBP this way leads to an additional DPL check, which INT1
-      // does not do normally, but normally, the INT1 is for HW vendors only.
-      ev_rec->make_add_event(Event_prio::Sw_int1, 1); // #DB
-
-      return Retry;
-
-    case Exit::Shutdown:
-      // Any event that triggeres a shutdown, e.g. triple fault, lands here.
-      info().printf("[%3u]: Shutdown intercept triggered at IP 0x%lx. Core in "
-                   "shutdown mode.\n",
-                   vcpu_id, vms->ip());
-      vcpu.dump_regs_t(vms->ip(), info());
-
-      // move CPU into stop state
-      cpu->stop();
-
-      return Retry;
-
-    default:
-      if (reason >= Exit::Excp_0 && reason <= Exit::Excp_31)
-      {
-        int exc_num = static_cast(reason)
-                      - static_cast(Exit::Excp_0);
-        return vms->handle_hardware_exception(ev_rec, exc_num);
-      }
-
-      warn().printf("[%3u]: Exit at guest IP 0x%lx with 0x%x (Info1: 0x%llx, "
-                    "Info2: 0x%llx)\n",
-                    vcpu_id, vms->ip(), static_cast(reason),
-                    vms->exit_info1(), vms->exit_info2());
-
-      auto str_exit_code = vms->str_exit_code(reason);
-      if (str_exit_code)
-        warn().printf("[%3u]: Unhandled exit reason: %s (%d)\n",
-                      vcpu_id, str_exit_code, static_cast(reason));
-      else
-        warn().printf("[%3u]: Unknown exit reason: 0x%x\n",
-                      vcpu_id, static_cast(reason));
-
-      return -L4_ENOSYS;
-    }
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-vmx.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-vmx.cc
deleted file mode 100644
index ee680c5b..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest-vmx.cc
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2018-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *            Benjamin Lamowski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "guest.h"
-#include "debug.h"
-#include "vm_state_vmx.h"
-#include "vmx_exit_to_str.h"
-#include "event_recorder.h"
-
-namespace Vmm {
-
-template <>
-int
-Guest::handle_io_access_string(unsigned port, bool is_in,
-                                          Mem_access::Width op_width,
-                                          bool is_rep, l4_vcpu_regs_t *regs,
-                                          Vmx_state *vms)
-{
-  auto info
-    = Vmx_state::Vmx_insn_info_field(vms->vmx_read(VMCS_VM_EXIT_INSN_INFO));
-
-  while (1)
-    {
-      if (is_rep)
-        {
-          // REP prefix: Handle loop condition.
-          bool next;
-          int rv = vms->rep_prefix_condition(regs, info, &next);
-          if (rv != Jump_instr)
-            return rv;
-
-          if (!next)
-            break;
-        }
-
-      if (is_in)
-        {
-          l4_uint32_t value = ~0U;
-          bool ret = handle_io_access_ptr(port, true, op_width, &value);
-          if (!ret)
-            {
-              Dbg(Dbg::Dev, Dbg::Trace)
-                .printf("WARNING: Unhandled string IO read port 0x%x/%u\n",
-                        port, (1U << op_width) * 8);
-              int rv = vms->store_io_value(regs, _ptw, info, op_width, ~0U);
-              if (rv != Jump_instr)
-                return rv;
-            }
-          else
-            {
-              int rv = vms->store_io_value(regs, _ptw, info, op_width, value);
-              if (rv != Jump_instr)
-                return rv;
-            }
-        }
-      else
-        {
-          l4_uint32_t value;
-          int rv = vms->load_io_value(regs, _ptw, info, op_width, &value);
-          if (rv != Jump_instr)
-            return rv;
-
-          bool ret = handle_io_access_ptr(port, false, op_width, &value);
-          if (!ret)
-            Dbg(Dbg::Dev, Dbg::Trace)
-              .printf("WARNING: Unhandled string IO write port 0x%x/%u <- "
-                      "0x%x\n",
-                      port, (1U << op_width) * 8, value);
-        }
-
-      // No REP prefix: Terminate the loop after the first iteration.
-      if (!is_rep)
-        break;
-    }
-
-  return Jump_instr;
-}
-
-template <>
-int
-Guest::handle_exit(Vmm::Cpu_dev *cpu, Vmx_state *vms)
-{
-  using Exit = Vmx_state::Exit;
-  auto reason = vms->exit_reason();
-  Vmm::Vcpu_ptr vcpu = cpu->vcpu();
-  auto *regs = &vcpu->r;
-  auto *ev_rec = recorder(vcpu.get_vcpu_id());
-  unsigned vcpu_id = vcpu.get_vcpu_id();
-
-  if (reason != Vmx_state::Exit::Exec_vmcall)
-    trace().printf("[%3u]: Exit at guest IP 0x%lx SP 0x%lx with %llu ('%s') (Qual: 0x%llx)\n",
-                   vcpu_id, vms->ip(), vms->sp(),
-                   vms->vmx_read(VMCS_EXIT_REASON),
-                   exit_reason_to_str(vms->vmx_read(VMCS_EXIT_REASON)),
-                   vms->vmx_read(VMCS_EXIT_QUALIFICATION));
-
-  switch (reason)
-    {
-    case Exit::Cpuid: return handle_cpuid(vcpu);
-
-    case Exit::Exec_vmcall: return handle_vm_call(regs);
-
-    case Exit::Io_access:
-      {
-        auto qual = vms->vmx_read(VMCS_EXIT_QUALIFICATION);
-        unsigned qwidth = qual & 7;
-        bool is_read = qual & 8;
-        bool is_string = qual & 16;
-        bool is_rep = qual & 32;
-        bool is_imm = qual & 64;
-        unsigned port = (qual >> 16) & 0xFFFFU;
-
-        Dbg(Dbg::Dev, Dbg::Trace)
-          .printf("[%3u]: VM exit @ 0x%lx: IO access with exit qualification "
-                  "0x%llx: %s port 0x%x %s%s%s\n",
-                  vcpu_id, vms->ip(), qual, is_read ? "read" : "write", port,
-                  is_imm ? "immediate" : "in DX", is_string ? " string" : "",
-                  is_rep ? " rep" : "");
-
-        if (port == 0xcfb)
-          Dbg(Dbg::Dev, Dbg::Trace)
-            .printf("[%3u]: N.B.: 0xcfb IO port access @ 0x%lx\n", vcpu_id,
-                    vms->ip());
-
-        Mem_access::Width op_width;
-        switch (qwidth)
-          {
-          // Only 0, 1, 3 are valid values in the exit qualification.
-          case 0: op_width = Mem_access::Wd8; break;
-          case 1: op_width = Mem_access::Wd16; break;
-          case 3: op_width = Mem_access::Wd32; break;
-          default:
-            warn().printf("[%3u]: Invalid IO access size %u @ 0x%lx\n",
-                          vcpu_id, qwidth, vms->ip());
-            return Invalid_opcode;
-          }
-
-        if (is_string)
-          return handle_io_access_string(port, is_read, op_width, is_rep,
-                                         regs, vms);
-
-        return handle_io_access(port, is_read, op_width, regs);
-      }
-
-    // Ept_violation needs to be checked here, as handle_mmio needs a vCPU ptr,
-    // which cannot be passed to Vm_state/Vmx_state due to dependency reasons.
-    case Exit::Ept_violation:
-      {
-        auto guest_phys_addr =
-          vms->vmx_read(VMCS_GUEST_PHYSICAL_ADDRESS);
-        auto qual = vms->vmx_read(VMCS_EXIT_QUALIFICATION);
-
-        trace().printf("[%3u]: Exit reason due to EPT violation %i;  gp_addr "
-                       "0x%llx, qualification 0x%llx\n",
-                       vcpu_id, static_cast(reason), guest_phys_addr,
-                       qual);
-
-        auto ret = handle_mmio(guest_phys_addr, vcpu);
-
-        // XXX Idt_vectoring_info could be valid.
-
-        switch(ret)
-          {
-          case Retry: return L4_EOK;
-          case Jump_instr: return Jump_instr;
-          default: break;
-          }
-
-        warn().printf("[%3u]: Unhandled pagefault @ 0x%lx\n", vcpu_id,
-                      vms->ip());
-        warn().printf("[%3u]: Read: %llu, Write: %llu, Inst.: %llu Phys addr: "
-                      "0x%llx\n",
-                      vcpu_id, qual & 1, qual & 2, qual & 4, guest_phys_addr);
-
-        if (qual & 0x80)
-          warn().printf("[%3u]: Linear address: 0x%llx\n", vcpu_id,
-                        vms->vmx_read(VMCS_GUEST_LINEAR_ADDRESS));
-        return -L4_EINVAL;
-      }
-
-    // VMX specific exits
-    case Exit::Exception_or_nmi:
-      {
-        // XXX Idt_vectoring_info could be valid.
-      }
-      // FIXME entry info might be overwritten by exception handling
-      // currently this isn't fully fletched anyways so this works for now.
-      [[fallthrough]];
-    case Exit::External_int:
-      return vms->handle_exception_nmi_ext_int(ev_rec);
-
-    case Exit::Interrupt_window:
-    case Exit::Nmi_window:
-      return Retry;
-
-    case Exit::Exec_halt:
-      if (0)
-        info().printf("[%3u]: HALT @ 0x%llx! Activity state 0x%llx\n",
-                      vcpu_id, vms->vmx_read(VMCS_GUEST_RIP),
-                      vms->vmx_read(VMCS_GUEST_ACTIVITY_STATE));
-
-      vms->halt();
-      cpu->halt_cpu();
-      return Jump_instr;
-
-    case Exit::Exec_rdpmc:
-      return General_protection;
-
-    case Exit::Cr_access:
-      return vms->handle_cr_access(regs);
-
-    case Exit::Exec_rdmsr:
-      if (!msr_devices_rwmsr(regs, false, vcpu_id))
-        {
-          warn().printf("[%3u]: Reading unsupported MSR 0x%lx\n", vcpu_id,
-                        regs->cx);
-          regs->ax = 0;
-          regs->dx = 0;
-          return General_protection;
-        }
-
-      return Jump_instr;
-
-    case Exit::Exec_wrmsr:
-      {
-        bool has_already_exception = ev_rec->has_exception();
-        if (!msr_devices_rwmsr(regs, true, vcpu.get_vcpu_id()))
-          {
-            warn().printf("[%3u]: Writing unsupported MSR 0x%lx\n", vcpu_id,
-                          regs->cx);
-            return General_protection;
-          }
-
-        // Writing an MSR e.g. IA32_EFER can lead to injection of a HW exception.
-        // In this case the instruction wasn't emulated, thus don't jump it.
-        if (!has_already_exception && ev_rec->has_exception())
-          return Retry;
-        else
-          return Jump_instr;
-      }
-    case Exit::Virtualized_eoi:
-      Dbg().printf("[%3u]: INFO: EOI virtualized for vector 0x%llx\n",
-                   vcpu_id, vms->vmx_read(VMCS_EXIT_QUALIFICATION));
-      // Trap like exit: IP already on next instruction
-      return L4_EOK;
-
-    case Exit::Exec_xsetbv:
-      if (regs->cx == 0)
-        {
-          l4_uint64_t value = (l4_uint64_t(regs->ax) & 0xFFFFFFFF)
-                              | (l4_uint64_t(regs->dx) << 32);
-          vms->vmx_write(L4_VM_VMX_VMCS_XCR0, value);
-          trace().printf("[%3u]: Setting xcr0 to 0x%llx\n", vcpu_id, value);
-          return Jump_instr;
-        }
-      Dbg().printf("[%3u]: Writing unknown extended control register %ld\n",
-                   vcpu_id, regs->cx);
-      return -L4_EINVAL;
-
-    case Exit::Apic_write:
-      // Trap like exit: IP already on next instruction
-      assert(0); // Not supported
-      return L4_EOK;
-
-    case Exit::Mov_debug_reg:
-      {
-        l4_uint64_t qual = vms->vmx_read(VMCS_EXIT_QUALIFICATION);
-        unsigned char dbg_reg = qual & 0x7;
-        bool read = qual & (1 << 4);
-        unsigned char gp_reg = (qual >> 8) & 0xf;
-        // check CR4.DE
-        if (dbg_reg == 4 || dbg_reg == 5)
-          {
-            if (vms->vmx_read(VMCS_GUEST_CR4) & (1U << 3)) // CR4.DE set?
-              return Invalid_opcode;
-            // else: alias to DR6 & DR7
-          }
-
-        if (read)
-          {
-            if (gp_reg == 0x4)
-              regs->sp = 0UL;
-            else
-              {
-                l4_umword_t *r = &(regs->ax);
-                *(r - gp_reg) = 0UL;
-              }
-          }
-        // else: ignore writes
-        trace().printf("[%3u]: MOV DR exit: %s DR%u %s GP%u. Value: 0x%lx\n",
-                       vcpu_id, read ? "read" : "write", dbg_reg,
-                       read ? "to" : "from", gp_reg, *(&(regs->ax) - gp_reg));
-        return Jump_instr;
-      }
-
-    case Exit::Exec_vmclear:
-    case Exit::Exec_vmlaunch:
-    case Exit::Exec_vmptrld:
-    case Exit::Exec_vmptrst:
-    case Exit::Exec_vmread:
-    case Exit::Exec_vmresume:
-    case Exit::Exec_vmwrite:
-    case Exit::Exec_vmxoff:
-    case Exit::Exec_vmxon:
-    case Exit::Exec_invept:
-    case Exit::Exec_invvpid:
-    case Exit::Exec_rdtscp:
-      // Unsupported instructions, inject undefined opcode exception
-      return Invalid_opcode;
-
-    case Exit::Triple_fault:
-      // Double-fault experienced exception. Set core into shutdown mode.
-      info().printf("[%3u]: Triple fault exit at IP 0x%lx. Core is in shutdown "
-                    "mode.\n",
-                    vcpu_id, vms->ip());
-      vcpu.dump_regs_t(vms->ip(), info());
-
-      // move CPU into stop state
-      cpu->stop();
-      return Retry;
-
-    case Exit::Entry_fail_invalid_guest:
-      {
-        auto qual = vms->vmx_read(VMCS_EXIT_QUALIFICATION);
-        auto reason_raw = vms->vmx_read(VMCS_EXIT_REASON);
-        auto ip = vms->ip();
-        auto insn_err = vms->vmx_read(VMCS_VM_INSN_ERROR);
-        auto entry_exc_err = vms->vmx_read(VMCS_VM_ENTRY_EXCEPTION_ERROR);
-
-        Dbg().printf("VM-entry failure due to invalid guest state:\n"
-                     "Exit reason raw: 0x%llx\n"
-                     "Exit qualification: 0x%llx\n"
-                     "IP: 0x%lx\n"
-                     "Instruction error: 0x%llx\n"
-                     "Entry exception error: 0x%llx\n",
-                     reason_raw, qual, ip, insn_err, entry_exc_err
-                     );
-      }
-      [[fallthrough]];
-
-    case Exit::Task_switch:
-    case Exit::Apic_access:
-    case Exit::Ept_misconfig:
-    case Exit::Page_mod_log_full:
-    case Exit::Spp_related_event:
-      // These cases need to check IDT-vectoring info for validity!
-
-    default:
-      {
-        Dbg().printf("[%3u]: Exit at guest IP 0x%lx SP 0x%lx with 0x%llx "
-                     "(Qual: 0x%llx)\n",
-                     vcpu_id, vms->ip(), vms->sp(),
-                     vms->vmx_read(VMCS_EXIT_REASON),
-                     vms->vmx_read(VMCS_EXIT_QUALIFICATION));
-
-        unsigned reason_u = static_cast(reason);
-        if (reason_u < sizeof(str_exit_reason) / sizeof(*str_exit_reason))
-          Dbg().printf("[%3u]: Unhandled exit reason: %s (%d)\n",
-                       vcpu_id, str_exit_reason[reason_u], reason_u);
-        else
-          Dbg().printf("[%3u]: Unknown exit reason: 0x%x\n", vcpu_id, reason_u);
-
-        return -L4_ENOSYS;
-      }
-    }
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.cc
deleted file mode 100644
index 4398acfe..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.cc
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *            Benjamin Lamowski 
- *            Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-
-#include "guest.h"
-#include "debug.h"
-#include "vm_state_vmx.h"
-#include "vm_state_svm.h"
-#include "consts.h"
-#include "vmx_exit_to_str.h"
-#include "msr_devices.h"
-#include "acpi.h"
-#include "mad.h"
-#include "event_recorder.h"
-#include "event_record.h"
-#include "event_record_lapic.h"
-#include "cpuid.h"
-#include "openbsd_bootparams.h"
-
-static cxx::Static_container guest;
-Acpi::Acpi_device_hub *Acpi::Acpi_device_hub::_hub;
-Acpi::Facs_storage *Acpi::Facs_storage::_facs_storage;
-Acpi::Madt_int_override_storage *Acpi::Madt_int_override_storage::_self;
-__thread unsigned vmm_current_cpu_id;
-
-namespace {
-
-static inline void cpuid(l4_uint32_t leaf, l4_uint32_t sub,
-                         l4_uint32_t *eax, l4_uint32_t *ebx, l4_uint32_t *ecx,
-                         l4_uint32_t *edx)
-{
-  asm volatile("cpuid"
-               : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
-               : "a"(leaf), "c"(sub));
-}
-
-}
-
-namespace Vmm {
-
-// Notification to add a stringified exit reason when Exit_reason_max changes.
-static_assert(   sizeof(str_exit_reason) / sizeof(*str_exit_reason)
-              == static_cast(Vmx_state::Exit::Exit_reason_max),
-              "One stringification exists for each VMX exit reason.");
-
-Guest *
-Guest::create_instance()
-{
-  trace().printf("creating instance\n");
-  guest.construct();
-  return guest;
-}
-
-Guest *
-Guest::get_instance()
-{
-  return guest;
-}
-
-void
-Guest::register_io_device(cxx::Ref_ptr const &dev,
-                          Region_type type,
-                          Vdev::Dt_node const &node, size_t index)
-{
-  l4_uint64_t base, size;
-  int res = node.get_reg_io(index, &base, &size);
-  if (res == -node.ERR_REG_INVALID)
-    {
-      Err().printf("Invalid 'reg' property of node %s(%lu): not an ioport\n",
-                   node.get_name(), index);
-      L4Re::throw_error(-L4_EINVAL, "Reg property contains an ioport.");
-    }
-  else if (res < 0)
-    {
-      Err().printf("Failed to read 'reg' from node %s(%lu): %s\n",
-                   node.get_name(), index, node.strerror(res));
-      L4Re::throw_error(-L4_EINVAL, "Reg value is valid.");
-    }
-
-  add_io_device(Vmm::Io_region::ss(base, size, type), dev);
-}
-
-void Guest::add_io_device(Io_region const ®ion,
-                          cxx::Ref_ptr const &dev)
-{
-  std::lock_guard g(_iomap_lock);
-
-  // Check for overlapping regions!
-  if (_iomap.count(region) != 0)
-    {
-      info().printf("IO map overlap: [0x%lx, 0x%lx]\n", region.start,
-                    region.end);
-      L4Re::chksys(-L4_EINVAL, "IO map entry overlapping.");
-    }
-
-  _iomap[region] = dev;
-
-  trace().printf("New io mapping: %p @ [0x%lx, 0x%lx]\n", dev.get(),
-                 region.start, region.end);
-}
-
-void Guest::del_io_device(Io_region const ®ion)
-{
-  std::lock_guard g(_iomap_lock);
-  trace().printf("Remove io mapping: [0x%lx, 0x%lx]\n", region.start,
-                 region.end);
-  assert(_iomap.count(region) == 1);
-  _iomap.erase(region);
-}
-
-bool Guest::i8042_present()
-{
-  std::unique_lock lock(_iomap_lock);
-
-  auto i = _iomap.find(Io_region(0x60));
-  if (i == _iomap.end())
-    return false;
-
-  i = _iomap.find(Io_region(0x64));
-  if (i == _iomap.end())
-    return false;
-
-  return true;
-}
-
-void Guest::register_msr_device(cxx::Ref_ptr const &dev)
-{
-  _msr_devices.push_back(dev);
-  trace().printf("New MSR device %p\n", dev.get());
-}
-
-void
-Guest::register_cpuid_device(cxx::Ref_ptr const &dev)
-{
-  _cpuid_devices.push_back(dev);
-  trace().printf("New CPUID device %p\n", dev.get());
-}
-
-l4_addr_t
-Guest::load_binary(Vm_ram *ram, char const *binary, Ram_free_list *free_list)
-{
-  l4_addr_t entry;
-
-  Boot::Binary_loader_factory bf;
-  bf.load(binary, ram, free_list, &entry);
-
-  _guest_size = bf.get_size();
-  _guest_t = bf.type();
-
-  // Reserve Zero-page and cmdline space: One page and 4k for the cmdline.
-  // XXX It shall move to prepare_binary_run, when the parameter set of that
-  // function is changed.
-  free_list->reserve_fixed(Vmm::Guest_addr(L4_PAGESIZE), L4_PAGESIZE + 0x1000);
-
-  return entry;
-}
-
-void
-Guest::prepare_platform(Vdev::Device_lookup *devs)
-{
-  _cpus = devs->cpus();
-  _icr_handler->register_cpus(_cpus);
-  _event_recorders.init(_cpus->size());
-  unsigned const max_cpuid = _cpus->max_cpuid();
-  _ptw = cxx::make_ref_obj(devs->ram(), get_max_physical_address_bit());
-  for (unsigned id = 0; id <= max_cpuid; ++id)
-    {
-      auto cpu = _cpus->cpu(id);
-      cpu->powerup_cpu();
-
-      Vcpu_ptr vcpu = cpu->vcpu();
-      vcpu->user_task = _task.cap();
-      vcpu.set_pt_walker(_ptw.get());
-
-      unsigned vcpu_id = vcpu.get_vcpu_id();
-      _apics->register_core(vcpu_id, cpu);
-      register_timer_device(_apics->get(vcpu_id)->timer(), vcpu_id);
-      _apics->get(vcpu_id)->attach_cpu_thread(cpu->thread_cap());
-    }
-
-  register_msr_device(Vdev::make_device(_cpus.get(),
-                      &_event_recorders));
-  register_msr_device(
-    Vdev::make_device(_cpus->vcpu(0)));
-  register_msr_device(Vdev::make_device());
-}
-
-void
-Guest::prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const * binary, char const *cmd_line,
-                          l4_addr_t dt_boot_addr)
-{
-  switch(guest_type())
-    {
-    case Boot::Binary_type::Rom:
-      {
-        auto cpus = devs->cpus();
-        Vcpu_ptr vcpu = cpus->vcpu(0);
-
-        vcpu->r.ip = entry;
-        break;
-      }
-    case Boot::Binary_type::Linux:
-    case Boot::Binary_type::Elf:
-      prepare_linux_binary_run(devs, entry, binary, cmd_line, dt_boot_addr);
-      break;
-    case Boot::Binary_type::OpenBSD:
-      prepare_openbsd_binary_run(devs, entry, binary, cmd_line, dt_boot_addr);
-      break;
-    default:
-      Err().printf("Unsupported guest binary type %i\n", _guest_t);
-      L4Re::throw_error(-L4_ENOSYS, "Unsupported binray type");
-    }
-}
-
-void
-Guest::prepare_openbsd_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                                  char const * /*binary*/,
-                                  char const * /*cmd_line*/,
-                                  l4_addr_t /*dt_boot_addr*/)
-{
-  Acpi::Bios_tables acpi_tables(devs);
-  acpi_tables.write_to_guest();
-
-  // Legacy kernels have entry set to 0xffff'ffff'8100'1000. Mask off the
-  // high bits to get the expected 0x100'1000 for the
-  // legacy kernel entry point
-  // Cloned from OpenBSD's sys/arch/amd64/stand/libsa/exec_i386.c
-  l4_addr_t masked_entry = entry & 0xfff'ffff;
-
-  // Prepare stack for the kernel parameters
-  Vmm::Openbsd::Boot_params params(Vmm::Guest_addr(
-                                     Vmm::Openbsd::Boot_params::Phys_mem_addr),
-                                   masked_entry, _guest_size);
-
-  // Write params
-  params.write(devs->ram().get());
-
-  auto cpus = devs->cpus();
-  Vcpu_ptr vcpu = cpus->vcpu(0);
-
-  vcpu->r.ip = masked_entry;
-  vcpu->r.sp = Vmm::Openbsd::Boot_params::Phys_mem_addr;
-  cpus->cpu(0)->set_protected_mode();
-}
-
-void
-Guest::prepare_linux_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                                char const * /*binary*/, char const *cmd_line,
-                                l4_addr_t dt_boot_addr)
-{
-  auto cpus = devs->cpus();
-  Vcpu_ptr vcpu = cpus->vcpu(0);
-  Vm_ram *ram = devs->ram().get();
-
-  Acpi::Bios_tables acpi_tables(devs);
-  acpi_tables.write_to_guest();
-
-  Zeropage zpage(Vmm::Guest_addr(L4_PAGESIZE), entry);
-
-  if (dt_boot_addr)
-    {
-      // read initrd addr and size from device tree
-      Vmm::Guest_addr dt_addr = ram->boot2guest_phys(dt_boot_addr);
-      Dtb::Fdt fdt(ram->guest2host(dt_addr));
-      auto dt = Vdev::Device_tree(&fdt);
-      int prop_sz1, prop_sz2;
-      auto node = dt.path_offset("/chosen");
-      auto prop_start = node.get_prop("linux,initrd-start", &prop_sz1);
-      auto prop_end = node.get_prop("linux,initrd-end", &prop_sz2);
-
-      if (prop_start && prop_end)
-        {
-          auto rd_start = node.get_prop_val(prop_start, prop_sz1, 0);
-          auto rd_end = node.get_prop_val(prop_end, prop_sz2, 0);
-          zpage.add_ramdisk(rd_start, rd_end - rd_start);
-        }
-      else
-        warn().printf("No ramdisk found in device tree.\n");
-
-      zpage.add_dtb(dt_boot_addr, dt.size());
-    }
-
-  if (cmd_line)
-    zpage.add_cmdline(cmd_line);
-
-  zpage.cfg_e820(ram);
-  // write zeropage to VM ram
-  zpage.write(ram, _guest_t);
-
-  vcpu->r.ip = zpage.entry(ram);
-  vcpu->r.sp = 0UL;
-  vcpu->r.si = zpage.addr().get();
-  cpus->cpu(0)->set_protected_mode();
-
-  trace().printf("Zeropage setup: vCPU ip: 0x%lx, si: 0x%lx\n", vcpu->r.ip,
-                 vcpu->r.si);
-}
-
-int
-Guest::handle_io_access(unsigned port, bool is_in, Mem_access::Width op_width,
-                        l4_vcpu_regs_t *regs)
-{
-  l4_umword_t op_mask = (1ULL << ((1U << op_width) * 8)) - 1;
-
-  if (is_in)
-    {
-      l4_uint32_t value = ~0U;
-      bool ret = handle_io_access_ptr(port, true, op_width, &value);
-      if (!ret)
-        {
-          trace().printf("WARNING: Unhandled IO read port 0x%x/%u\n",
-                     port, (1U << op_width) * 8);
-          regs->ax = ~0ULL & op_mask;
-          return Jump_instr;
-        }
-
-      regs->ax = (regs->ax & ~op_mask) | (value & op_mask);
-    }
-  else
-    {
-      l4_uint32_t value = regs->ax & op_mask;
-      bool ret = handle_io_access_ptr(port, false, op_width, &value);
-      if (!ret)
-        {
-          trace().printf("WARNING: Unhandled IO write port 0x%x/%u <- 0x%x\n",
-                         port, (1U << op_width) * 8, value);
-          return Jump_instr;
-        }
-    }
-
-  return Jump_instr;
-}
-
-bool
-Guest::handle_io_access_ptr(unsigned port, bool is_in,
-                            Mem_access::Width op_width, l4_uint32_t *value)
-{
-  std::unique_lock lock(_iomap_lock);
-  auto f = _iomap.find(Io_region(port));
-  if (f == _iomap.end())
-    return false;
-
-  port -= f->first.start;
-  cxx::Ref_ptr device = f->second;
-  lock.unlock();
-
-  if (is_in)
-    device->io_in(port, op_width, value);
-  else
-    device->io_out(port, op_width, *value);
-
-  return true;
-}
-
-int
-Guest::handle_cpuid(Vcpu_ptr vcpu)
-{
-  l4_vcpu_regs_t *regs = &vcpu->r;
-  unsigned id = vcpu.get_vcpu_id();
-  l4_uint32_t a,b,c,d;
-  l4_uint64_t rax = regs->ax;
-  l4_uint64_t rcx = regs->cx;
-  Vm_state *vms = vcpu.vm_state();
-
-  auto set_regs = [regs] (l4_uint32_t a, l4_uint32_t b,
-                          l4_uint32_t c, l4_uint32_t d)
-  {
-    regs->ax = a;
-    regs->bx = b;
-    regs->cx = c;
-    regs->dx = d;
-    return Jump_instr;
-  };
-
-  // handle emulated cpuid branches
-  if (rax >= 0x4000'0000 && rax <= 0x4fff'ffff)
-    {
-      if (!handle_cpuid_devices(regs, &a, &b, &c, &d))
-        // if there is no handler, return 0
-        a = b = c = d = 0;
-      return set_regs(a, b, c, d);
-    }
-
-  cpuid(rax, rcx, &a, &b, &c, &d);
-
-  if (0)
-    trace().printf("[%3u] CPUID as read 0x%llx/0x%llx: a: 0x%x, b: 0x%x, c: 0x%x, d: 0x%x\n",
-                   id, rax, rcx, a, b, c, d);
-
-  enum : unsigned long
-  {
-    // Processor Extended State Enumeration Leaf, 0xd
-    // fiasco limits to x87, SSE, AVX, AVX512 states
-    Xcr0_fiasco_feature_mask = 0xe7,
-    Xsave_opt = 1,
-    Xsave_c = (1UL << 1),
-    Xget_bv = (1UL << 2),
-    Xsave_s = (1UL << 3),
-    Xfd_bit = (1UL << 4),
-  };
-
-  if (   (rax > Cpuid_max_basic_info_leaf && rax < 0x8000'0000)
-      || (rax > Cpuid_max_ext_info_leaf))
-    {
-      info().printf("[%3u] CPUID leaf 0x%llx not supported\n", id, rax);
-      return set_regs(0, 0, 0, 0);
-    }
-
-  switch (rax)
-    {
-    case 0x0:
-      a = a < Cpuid_max_basic_info_leaf ? a : Cpuid_max_basic_info_leaf;
-      break;
-    case 0x1:
-      {
-        // Emulate Initial APIC ID
-        b &= 0x00ffffff;
-        if (id < 0x100)
-          b |= id << 24;
-
-        cpuid_reg_apply(&c, Cpuid_1_ecx_supported, Cpuid_1_ecx_mandatory);
-        cpuid_reg_apply(&d, Cpuid_1_edx_supported);
-        break;
-      }
-
-    case 0x2:
-      [[fallthrough]];
-    case 0x3:
-      [[fallthrough]];
-    case 0x4:
-      break;
-
-    case 0x5:
-      // monitor/mwait. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0x6:
-      // thermal and power management
-      cpuid_reg_apply(&a, Cpuid_6_eax_supported);
-      b = c = d = 0;
-      break;
-
-    case 0x7:
-      if (!rcx)
-        {
-          a = Cpuid_7_0_eax_leafs;
-          cpuid_reg_apply(&b, Cpuid_7_0_ebx_supported);
-          cpuid_reg_apply(&c, Cpuid_7_0_ecx_supported);
-          cpuid_reg_apply(&d, Cpuid_7_0_edx_supported);
-        }
-      else
-        a = b = c = d = 0;
-      break;
-
-    case 0x9:
-      // direct cache access information. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0xa:
-      // Performance monitoring features. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0xb: // Extended Topology Enumeration Leaf
-    case 0x1f: // v2 Extended Topology Enumeration
-      if (rcx != 0)
-        a = b = c = 0;
-      // the Local APIC ID of ACPI_MADT_TYPE_LOCAL_APIC for all sub-leafs
-      d = id;
-      // TODO: Emulate the other registers according to the intended virtual CPU
-      //       topology. Also consider ECX>=0 as input.
-      break;
-
-    case 0xd:
-      switch(rcx)
-        {
-        case 0:
-          {
-            // limit reply to what fiasco supports
-            a = a & Xcr0_fiasco_feature_mask;
-
-            if (!_xsave_layout.valid)
-              {
-                trace().printf("\n\n [%3u] building xsave cache \n\n", id);
-
-                // build cache
-                for (int i = 2; a >> i; ++i)
-                  {
-                    if (!((a >> i) & 1))
-                      continue;
-
-                    l4_uint32_t ax, bx, cx, dx;
-                    cpuid(0xd, i, &ax, &bx, &cx, &dx);
-                    _xsave_layout.feat[i].size = ax;
-                    _xsave_layout.feat[i].offset = bx;
-                  }
-                _xsave_layout.valid = true;
-                // feature offset and size does not change during runtime.
-              }
-
-            l4_uint64_t xcr0_guest_enabled = vms->xcr0();
-            l4_uint64_t offset = 0;
-            int highest_index_feat = 0; // default to x87
-            int highest_index_feat_enabled = 0; // default to x87
-
-            // Find the feature and the enabled feature with the highest
-            // offset in the Xsave state. This only works in standard format!
-            // Compact format not supported, see case 1: below.
-            for (int i = 2; i < Xsave_state_area::Num_fields; ++i)
-              {
-                if (_xsave_layout.feat[i].offset > offset)
-                  {
-                    offset = _xsave_layout.feat[i].offset;
-                    highest_index_feat = i;
-                    if (xcr0_guest_enabled & (1 << i))
-                      highest_index_feat_enabled = i;
-                  }
-              }
-
-            if (highest_index_feat == 0)
-              {
-                // x87 is always on, but we then have only the legacy area.
-                // SSE on or off is handled in the legacy area and thus doesn't
-                // affect the size computation.
-                b = c = 512 + 64; // bytes; legacy area + Xsave header
-                d = 0;
-              }
-            else
-              {
-                // report possible XSAVE state size
-                Xsave_state_area::Size_off feat =
-                  _xsave_layout.feat[highest_index_feat];
-                c = feat.offset + feat.size;
-
-                // report enabled XSAVE state size
-                if (highest_index_feat_enabled == 0)
-                  {
-                    b = 512 + 64; // bytes; legacy area + Xsave header
-                  }
-                else
-                  {
-                    feat = _xsave_layout.feat[highest_index_feat_enabled];
-                    b = feat.offset + feat.size;
-                  }
-
-                d = 0;
-              }
-
-            if (0)
-              trace().printf("\n[%3u] Return XCR0 guest state: 0x%x:0x%x b=%x c=%x, "
-                             "(guest XCR0: 0x%llx) \n\n",
-                             id, d, a, b, c, xcr0_guest_enabled);
-            break;
-          }
-
-        case 1:
-          trace().printf("[%3u] Filtering out xsave capabilities\n", id);
-          a &= ~(  Xsave_opt
-                   | Xsave_c
-                   | Xget_bv // with ECX=1
-                   | Xsave_s // XSAVES/XRSTORS and IA32_XSS MSR
-                   | Xfd_bit
-                );
-          b = 0; // Size of the state of the enabled feature bits.
-          break;
-
-        default:
-          break;
-        }
-      break;
-
-    case 0xf:
-      // Intel RDT Monitoring not supported, sub-leaf 0 and 1 report zero.
-      a = b = c = d = 0;
-      break;
-
-    case 0x10:
-      // Intel RDT Allocation not supported, sub-leaf 0 and 1 report zero.
-      a = b = c = d = 0;
-      break;
-
-    case 0x12:
-      // SGX information. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0x14:
-      // Intel Processor Trace. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0x15:
-      // time stamp counter and nominal core crystal clock information
-      [[fallthrough]];
-    case 0x16:
-      // processor frequency information
-      break;
-
-    case 0x17:
-      // system-on-chip vendor attribute enumeration. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0x18:
-      // deterministic address translation. Not supported.
-      [[fallthrough]];
-    case 0x19:
-      // key locker. Not supported.
-      [[fallthrough]];
-    case 0x1a:
-      // native model enumeration. Not supported.
-      [[fallthrough]];
-    case 0x1b:
-      // pconfig. Not supported.
-      [[fallthrough]];
-    case 0x1c:
-      // last branch records information. Not supported.
-      [[fallthrough]];
-    case 0x1d:
-      // tile information main. Not supported.
-      [[fallthrough]];
-    case 0x1e:
-      // TMUL information. Not supported.
-      a = b = c = d = 0;
-      break;
-
-    case 0x8000'0000:
-      {
-        a = Cpuid_max_ext_info_leaf;
-        b = c = d = 0; // reserved
-        break;
-      }
-
-    case 0x8000'0001:
-      {
-        // a contains extended processor signature and feature bits
-        b = 0; // reserved
-        cpuid_reg_apply(&c, Cpuid_8000_0001_ecx_supported);
-        cpuid_reg_apply(&d, Cpuid_8000_0001_edx_supported);
-        break;
-      }
-
-    // processor brand string
-    case 0x8000'0002:
-      [[fallthrough]];
-    case 0x8000'0003:
-      [[fallthrough]];
-    case 0x8000'0004:
-      [[fallthrough]];
-
-
-    // Intel: reserved
-    // AMD: L1 cache information
-    case 0x8000'0005:
-      [[fallthrough]];
-
-    // Intel: L2 cache information
-    // AMD: TLB and L2/L3 cache information
-    case 0x8000'0006:
-      break;
-
-    case 0x8000'0007:
-      a = b = c = 0; // reserved
-      cpuid_reg_apply(&d, Cpuid_8000_0007_edx_supported);
-      break;
-
-    case 0x8000'0008:
-      {
-        // a contains linear/physical address size
-        cpuid_reg_apply(&b, Cpuid_8000_0008_ebx_supported);
-        c = d = 0; // reserved
-        break;
-      }
-
-    // reserved leaves
-    case 0x8:
-      [[fallthrough]];
-    case 0xc:
-      [[fallthrough]];
-    case 0xe:
-      [[fallthrough]];
-    case 0x11:
-      [[fallthrough]];
-    case 0x13:
-      if (a || b || c || d)
-        warn().printf("Unexpected feature in reserved CPUID leaf "
-                      "(eax = 0x%llx,exc = 0x%llx) a=0x%x b=0x%x c=0x%x d=0x%x\n",
-                      rax, rcx, a, b, c, d);
-      a = b = c = d = 0;
-      break;
-
-      // For future reference:
-      //    case 0x8000001f:
-      //      {
-      //        // Memory encryption not supported.
-      //        // https://docs.kernel.org/arch/x86/amd-memory-encryption.html
-      //        a &= ~(Amd_sme_bit | Amd_sev_bit);
-      //        break;
-      //      }
-    default:
-      {
-        warn().printf("Unexpected CPUID leaf eax = 0x%llx, ecx = 0x%llx\n",
-                      rax, rcx);
-        a = b = c = d = 0;
-      }
-    }
-
-  if (0)
-    trace().printf("[%3u] CPUID as modified: a: 0x%x, b: 0x%x, c: 0x%x, d: 0x%x\n",
-                   id, a, b, c, d);
-
-  return set_regs(a, b, c, d);
-}
-
-int
-Guest::handle_vm_call(l4_vcpu_regs_t *regs)
-{
-  if (regs->ax == 0)
-    {
-       _hypcall_print.print_char(regs->cx);
-      return Jump_instr;
-    }
-
-  // NOTE: If the hypervisor bit is enabled in CPUID.01 there can be other VMCALL
-  // numbers defined for KVM, e.g. 0x9 for PTP_KVM.
-
-  // Handle KVM queries gracefully
-  if (regs->ax == 9) // KVM_HC_CLOCK_PAIRING
-    {
-      regs->ax = -1000; // KVM_ENOSYS
-      return Jump_instr;
-    }
-
-  Err().printf("Unknown VMCALL 0x%lx at 0x%lx\n", regs->ax, regs->ip);
-  return -L4_ENOSYS;
-}
-
-bool
-Guest::msr_devices_rwmsr(l4_vcpu_regs_t *regs, bool write, unsigned vcpu_no)
-{
-  auto msr = regs->cx;
-
-  for (auto &dev : _msr_devices)
-    {
-      if (write)
-        {
-          l4_uint64_t value = (l4_uint64_t(regs->ax) & 0xFFFFFFFF)
-                              | (l4_uint64_t(regs->dx) << 32);
-          if (dev->write_msr(msr, value, vcpu_no))
-            return true;
-        }
-      else
-        {
-          l4_uint64_t result = 0;
-          if (dev->read_msr(msr, &result, vcpu_no))
-            {
-              regs->ax = (l4_uint32_t)result;
-              regs->dx = (l4_uint32_t)(result >> 32);
-              return true;
-            }
-        }
-    }
-
-  return false;
-}
-
-bool
-Guest::handle_cpuid_devices(l4_vcpu_regs_t const *regs, unsigned *a,
-                            unsigned *b, unsigned *c, unsigned *d)
-{
-  for (auto &dev : _cpuid_devices)
-    {
-      if (dev->handle_cpuid(regs, a, b, c, d))
-        return true;
-    }
-  return false;
-}
-
-void
-Guest::sync_all_other_cores_off() const
-{
-  // send IPI to all cores to power off
-  for (auto cpu : *_cpus.get())
-    {
-      if (cpu && cpu->cpu_online()
-          && cpu->vcpu().get_vcpu_id() != vmm_current_cpu_id)
-        {
-          cpu->send_stop_event();
-        }
-    }
-
-  // busy-wait until all other cores are off.
-  bool all_stop = true;
-  do
-    {
-      all_stop = true;
-      for (auto cpu : *_cpus.get())
-        {
-          if (cpu && cpu->vcpu().get_vcpu_id() == vmm_current_cpu_id)
-            continue;
-
-          if (cpu && cpu->cpu_online())
-            {
-              all_stop = false;
-              break;
-            }
-        }
-    } while (!all_stop);
-}
-
-unsigned
-Guest::cores_running() const
-{
-  unsigned online = 0;
-
-  for (auto cpu : *_cpus.get())
-    if (cpu && cpu->cpu_online())
-      ++online;
-
-  return online;
-}
-
-void
-Guest::run(cxx::Ref_ptr const &cpus)
-{
-  iomap_dump(Dbg::Info);
-
-  info().printf("Starting VMM @ 0x%lx\n", cpus->vcpu(0)->r.ip);
-
-  // Additional vCPUs are initialized to run startup on the first reschedule.
-  cpus->cpu(0)->startup();
-}
-
-void L4_NORETURN
-Guest::run_vm(Vcpu_ptr vcpu)
-{
-  Vm_state *vm = vcpu.vm_state();
-  assert(vm);
-
-  if (vm->type() == Vm_state::Type::Vmx)
-    {
-      Vmx_state *vms = dynamic_cast(vm);
-      assert(vms);
-      run_vm_t(vcpu, vms);
-    }
-  else /* if (vm->type() == Vm_state::Type::Svm) */
-    {
-      Svm_state *vms = dynamic_cast(vm);
-      assert(vms);
-      run_vm_t(vcpu, vms);
-    }
-}
-
-template 
-bool
-Guest::state_transition_effects(Cpu_dev::Cpu_state const current,
-                                Cpu_dev::Cpu_state const new_state,
-                                Gic::Virt_lapic *lapic, VMS *vm,
-                                Cpu_dev *cpu)
-{
-  if (current == new_state && current != Cpu_dev::Halted)
-    return false;
-
-  if (current == Cpu_dev::Init && new_state == Cpu_dev::Running)
-    {
-      lapic->clear_irq_state();
-      vm->invalidate_pending_event();
-      cpu->hot_reset();
-    }
-  else if (   (current == Cpu_dev::Running && new_state == Cpu_dev::Halted)
-           || (current == Cpu_dev::Halted && new_state == Cpu_dev::Halted))
-    {
-      if (lapic->is_irq_pending() || lapic->is_nmi_pending())
-        return true;
-    }
-
-  return false;
-}
-
-/// returns false if we continue with VMentry
-template 
-bool
-Guest::new_state_action(Cpu_dev::Cpu_state state, bool halt_req,
-                        Cpu_dev *cpu, VMS *vm)
-{
-  // state behavior
-  //  Sleeping -- does not happen here
-  //  Stopped -- wait for INIT-IPI
-  //  Init -- wait for SIPI
-  //  Halt -- wait for IPC
-  //  Running -- do event injection & vmentry.
-
-  if (halt_req) // includes state check for halted -> halted; running -> halted
-    {
-      if (event_injection_t(cpu->vcpu(), vm))
-        {
-          cpu->set_cpu_state(Cpu_dev::Running);
-          vm->resume();
-          return false;
-        }
-      else
-        {
-          assert(state == Cpu_dev::Halted);
-          assert(cpu->get_cpu_state() == Cpu_dev::Halted);
-        }
-    }
-
-  switch(state)
-    {
-    case Cpu_dev::Stopped:
-      // we cannot recover here, when we stopped the last core.
-      if (cores_running() == 0)
-        {
-          Err().printf("[%3u] Last core stopped. Shutting down\n",
-                       cpu->vcpu().get_vcpu_id());
-          shutdown(Shutdown);
-        }
-      [[fallthrough]];
-    case Cpu_dev::Init:
-      cpu->wait_for_ipi();
-      break;
-    case Cpu_dev::Halted:
-      cpu->vcpu().wait_for_ipc(l4_utcb(), L4_IPC_NEVER);
-      break;
-    case Cpu_dev::Running:
-      event_injection_t(cpu->vcpu(), vm);
-      return false;
-    default:
-      // Sleeping is never entered once left and other states don't exist, thus
-      // this should not happen. Print the error for debugging and stop vCPU.
-      // The guest can reset the CPU with an INIT IPI.
-      Err().printf("[%3u] CPU device state %i unknown or invalid. "
-                   "Stopping core.\n",
-                   cpu->vcpu().get_vcpu_id(), state);
-      vm->additional_failure_info(cpu->vcpu().get_vcpu_id());
-      cpu->stop();
-    }
-
-  return true;
-}
-
-template
-void L4_NORETURN
-Guest::run_vm_t(Vcpu_ptr vcpu, VMS *vm)
-{
-  unsigned vcpu_id = vcpu.get_vcpu_id();
-  auto cpu = _cpus->cpu(vcpu_id);
-  auto *ev_rec = recorder(vcpu_id);
-  Gic::Virt_lapic *vapic = lapic(vcpu);
-
-  _clocks[vcpu_id].start_clock_source_thread(vcpu_id, cpu->get_phys_cpu_id());
-  for (auto &dev : _timer_devices[vcpu_id])
-    dev->ready();
-
-  L4::Cap myself;
-  trace().printf("Starting vCPU[%3u] 0x%lx\n", vcpu_id, vcpu->r.ip);
-
-  while (1)
-    {
-      l4_msgtag_t tag = myself->vcpu_resume_commit(myself->vcpu_resume_start());
-      auto e = l4_error(tag);
-
-      if (e == 1)
-      // Fiasco indicates pending IRQs (IPCs); see fiasco: resume_vcpu()
-        {
-          if (tag.has_error())
-            Dbg().printf("[%3u]: tag has error, but used as ack\n", vcpu_id);
-          vcpu.process_pending_ipc(l4_utcb());
-        }
-      else if (e)
-        {
-          Err().printf("[%3u]: Entering VM failed with error %ld\n",
-                       vcpu_id, e);
-          vm->additional_failure_info(vcpu_id);
-          halt_vm(vcpu);
-        }
-      else
-        {
-          int ret = handle_exit(cpu.get(), vm);
-          if (ret < 0)
-            {
-              Err().printf("[%3u]: Failure in VMM %i\n", vcpu_id, ret);
-              vcpu.dump_regs_t(vm->ip(), Err());
-              vm->additional_failure_info(vcpu_id);
-              halt_vm(vcpu);
-            }
-          else switch (ret)
-            {
-            case Jump_instr:
-              vm->jump_instruction();
-              vm->clear_sti_shadow();
-              break;
-            case Invalid_opcode:
-              ev_rec->make_add_event(Event_prio::Exception, 6);
-              break;
-            case Stack_fault:
-              ev_rec->make_add_event(Event_prio::Exception, 12, 0);
-              break;
-            case General_protection:
-              ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-              break;
-            }
-        }
-
-      Cpu_dev::Cpu_state new_state = Cpu_dev::Running;
-      bool halt_req = false;
-      do
-        {
-          new_state = cpu->next_state();
-          halt_req = state_transition_effects(cpu->get_cpu_state(), new_state,
-                                              vapic, vm, cpu.get());
-
-          cpu->set_cpu_state(new_state);
-        }
-      while (new_state_action(new_state, halt_req, cpu.get(), vm));
-    }
-}
-
-template
-bool
-Guest::event_injection_t(Vcpu_ptr vcpu, VMS *vm)
-{
-  Event_recorder *rec = recorder(vcpu.get_vcpu_id());
-  // XXX Record pending events in other subsystems in the event recorder
-  Gic::Virt_lapic *apic = lapic(vcpu);
-  if (!rec->has_nmi() && apic->next_pending_nmi())
-    rec->make_add_event(apic);
-
-  if (!rec->has_irq() && apic->is_irq_pending())
-    {
-      // Event_record::ev_num not used on IRQ, as we query the LAPIC for the
-      // exact value.
-      rec->make_add_event(apic);
-    }
-
-
-  // TODO reenqueue what we haven't injected.
-  Injection_event pending_event = vm->pending_event_injection();
-
-  if (pending_event.valid())
-    {
-      vm->inject_event(pending_event);
-      return true;
-    }
-  else
-    {
-      return rec->inject(static_cast(vm));
-    }
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.h
deleted file mode 100644
index 8aa5649a..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/guest.h
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-
-#include "cpu_dev_array.h"
-#include "generic_guest.h"
-#include "msr_device.h"
-#include "cpuid_device.h"
-#include "mem_access.h"
-#include "vcpu_ptr.h"
-#include "virt_lapic.h"
-#include "vmprint.h"
-#include "zeropage.h"
-#include "pt_walker.h"
-#include "vm_ram.h"
-#include "binary_loader.h"
-#include "event_recorder.h"
-#include "pm_device_if.h"
-
-namespace Vmm {
-
-class Guest : public Generic_guest
-{
-public:
-  enum { Default_rambase = 0, Boot_offset = 0 };
-
-  enum { Has_io_space = true };
-  using Io_mem = std::map>;
-
-  Guest()
-  : _apics(Vdev::make_device()),
-    _icr_handler(Vdev::make_device()),
-    _lapic_access_handler(Vdev::make_device(
-      _apics, _icr_handler, get_max_physical_address_bit()))
-  {
-    add_mmio_device(_lapic_access_handler->mmio_region(),
-                    _lapic_access_handler);
-    register_msr_device(_lapic_access_handler);
-
-    // Do this once for all TSC-based timers used in uvmm.
-    l4_calibrate_tsc(l4re_kip());
-  }
-
-  static Guest *create_instance();
-  static Guest *get_instance();
-
-  void setup_device_tree(Vdev::Device_tree) {}
-
-  void show_state_interrupts(FILE *, Vcpu_ptr) {}
-
-  void register_io_device(cxx::Ref_ptr const &dev,
-                          Region_type type,
-                          Vdev::Dt_node const &node, size_t index = 0);
-  void add_io_device(Io_region const ®ion,
-                     cxx::Ref_ptr const &dev);
-  void del_io_device(Io_region const ®ion);
-
-  /**
-   * Indicate whether the legacy i8042 keyboard controller is present.
-   *
-   * We assume that the legacy i8042 keyboard controller is present if the
-   * I/O ports 0x60 and 0x64 are registered.
-   *
-   * \retval true   The legacy i8042 keyboard controller is present.
-   * \retval false  The legacy i8042 keyboard controller is absent.
-   */
-  bool i8042_present();
-
-  bool register_framebuffer(l4_uint64_t addr, l4_uint64_t size,
-                            const L4Re::Video::View::Info &info);
-
-  /**
-   * Return IO port map.
-   *
-   * Must only be used before the guest started to run or for debugging. Might
-   * be manipulated concurrently from other vCPUs!
-   */
-  Io_mem const *iomap()
-  { return &_iomap; }
-
-  void register_msr_device(cxx::Ref_ptr const &dev);
-
-  /**
-   * Register a CPUID-handling device in a list.
-   *
-   * \param dev   CPUID-handling device to register.
-   */
-  void register_cpuid_device(cxx::Ref_ptr const &dev);
-
-  l4_addr_t load_binary(Vm_ram *ram, char const *binary,
-                        Ram_free_list *free_list);
-
-  void prepare_platform(Vdev::Device_lookup *devs);
-
-  void prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const *binary, char const *cmd_line,
-                          l4_addr_t dt_boot_addr);
-
-  void run(cxx::Ref_ptr const &cpus);
-
-  void suspend(l4_addr_t wake_vector)
-  {
-    Vdev::Pm_device_registry::suspend_devices();
-
-    if (!_pm->suspend())
-      {
-        warn().printf("System suspend not possible. Waking up immediately.\n");
-        Vdev::Pm_device_registry::resume_devices();
-        return;
-      }
-
-    auto vcpu = _cpus->cpu(0)->vcpu();
-    /* Go to sleep */
-    vcpu.wait_for_ipc(l4_utcb(), L4_IPC_NEVER);
-
-    /* Back alive */
-    _pm->resume();
-    Vdev::Pm_device_registry::resume_devices();
-
-    vcpu.vm_state()->init_state();
-    vcpu.vm_state()->setup_real_mode(wake_vector);
-    info().printf("Waking CPU %u on EIP 0x%lx\n", 0, wake_vector);
-  }
-
-  void sync_all_other_cores_off() const override;
-  // returns the number of running cores
-  unsigned cores_running() const;
-
-  void handle_entry(Vcpu_ptr vcpu);
-
-  Gic::Virt_lapic *lapic(Vcpu_ptr vcpu)
-  { return _apics->get(vcpu.get_vcpu_id()).get(); }
-
-  cxx::Ref_ptr apic_array() { return _apics; }
-  cxx::Ref_ptr icr_handler() { return _icr_handler; }
-
-  int handle_cpuid(Vcpu_ptr vcpu);
-  int handle_vm_call(l4_vcpu_regs_t *regs);
-
-  /**
-   * Access IO port and load/store the value to RAX.
-   *
-   * In case the given IO port is not handled by any device on read, the value
-   * of all ones is stored to RAX. Write errors are silently ignored.
-   *
-   * \param[in]     port      IO port to access.
-   * \param[in]     is_in     True if this is the IN (read) access.
-   * \param[in]     op_width  Width of the access (1/2/4 bytes).
-   * \param[in,out] regs      Register file. The value read/written is
-   *                          stored/loaded into RAX.
-   *
-   * \retval Jump_instr  Success, all errors are silently ignored.
-   */
-  int handle_io_access(unsigned port, bool is_in, Mem_access::Width op_width,
-                       l4_vcpu_regs_t *regs);
-
-  /**
-   * Access IO port (core implementation).
-   *
-   * Core implementation of accessing an IO port. The method looks up the
-   * device that handles the IO port and does the access.
-   *
-   * \param[in]     port      IO port to access.
-   * \param[in]     is_in     True if this is the IN (read) access.
-   * \param[in]     op_width  Width of the access (1/2/4 bytes).
-   * \param[in,out] value     Value to read/write.
-   *
-   * \retval true   The IO access was successful.
-   * \retval false  No device handles the given IO port.
-   */
-  bool handle_io_access_ptr(unsigned port, bool is_in,
-                            Mem_access::Width op_width, l4_uint32_t *value);
-
-  void run_vm(Vcpu_ptr vcpu) L4_NORETURN;
-
-  Boot::Binary_type guest_type() const
-  { return _guest_t; }
-
-private:
-  enum : unsigned
-  {
-    Max_phys_addr_bits_mask = 0xff,
-  };
-
-  struct Xsave_state_area
-  {
-    struct Size_off { l4_uint64_t size = 0, offset = 0; };
-
-    enum
-    {
-      // Some indices are valid in xcr0, some in xss.
-      x87 = 0,      // XCR0
-      sse,          // XCR0
-      avx,          // XCR0
-      mpx1,         // XCR0
-      mpx2,         // XCR0
-      avx512_1,     // XCR0
-      avx512_2,     // XCR0
-      avx512_3,     // XCR0
-      pts,          // XSS
-      pkru,         // XCR0,
-      pasid,        // XSS
-      cetu,         // XSS
-      cets,         // XSS
-      hdc,          // XSS
-      uintr,        // XSS
-      lbr,          // XSS
-      hwp,          // XSS
-      tilecfg,      // XCR0
-      tiledata,     // XCR0
-
-      Num_fields = 31,
-    };
-
-    bool valid = false;
-    // first two fields are legacy area, so always (size=0, offset=0);
-    Size_off feat[Num_fields];
-  };
-
-  void prepare_openbsd_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                                  char const *binary, char const *cmd_line,
-                                  l4_addr_t dt_boot_addr);
-  void prepare_linux_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                                char const *binary, char const *cmd_line,
-                                l4_addr_t dt_boot_addr);
-
-  template
-  void run_vm_t(Vcpu_ptr vcpu, VMS *vm) L4_NORETURN;
-
-  template 
-  bool event_injection_t(Vcpu_ptr vcpu, VMS *vm);
-
-  template 
-  int handle_exit(Cpu_dev *cpu, VMS *vm);
-
-  /**
-   * Handle IO access VM exit in case of a [REP] INS/OUTS.
-   *
-   * \tparam VMS  VM state type.
-   *
-   * \param[in]     port      IO port to access.
-   * \param[in]     is_in     True if this is the INS (read) access.
-   * \param[in]     op_width  Width of the IO access (1/2/4 bytes).
-   * \param[in]     is_rep    True if there is the REP prefix.
-   * \param[in,out] regs      Register file.
-   * \param[in,out] vms       VM state.
-   *
-   * \retval Jump_instr          [REP] INS/OUTS instruction handled
-   *                             successfully.
-   * \retval Invalid_opcode      Instruction decoding failure or unsupported
-   *                             CPU mode.
-   * \retval General_protection  Segmentation fault.
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  template 
-  int handle_io_access_string(unsigned port, bool is_in,
-                              Mem_access::Width op_width, bool is_rep,
-                              l4_vcpu_regs_t *regs, VMS *vm);
-
-  unsigned get_max_physical_address_bit() const
-  {
-    l4_umword_t ax, bx, cx, dx;
-
-    // Check for highest extended CPUID leaf
-    l4util_cpu_cpuid(0x80000000, &ax, &bx, &cx, &dx);
-
-    if (ax >= 0x80000008)
-      l4util_cpu_cpuid(0x80000008, &ax, &bx, &cx, &dx);
-    else
-      {
-        // Check for highest basic CPUID leaf
-        l4util_cpu_cpuid(0x00, &ax, &bx, &cx, &dx);
-
-        if (ax >= 0x01)
-          {
-            l4util_cpu_cpuid(0x01, &ax, &bx, &cx, &dx);
-            if (dx & (1UL << 6)) // PAE
-              ax = 36;
-            else
-              ax = 32;
-          }
-        else
-          ax = 32; // Minimum if leaf not supported
-      }
-
-    return ax & Max_phys_addr_bits_mask;
-  }
-
-  bool msr_devices_rwmsr(l4_vcpu_regs_t *regs, bool write, unsigned vcpu_no);
-  /**
-   * Attempt to handle the CPUID instruction by consecutively trying handlers
-   * of the CPUID-handling devices registered in the _cpuid_devices list. The
-   * list is traversed from the front to the back.
-   */
-  bool handle_cpuid_devices(l4_vcpu_regs_t const *regs, unsigned *a,
-                            unsigned *b, unsigned *c, unsigned *d);
-
-  Event_recorder *recorder(unsigned num)
-  { return _event_recorders.recorder(num); }
-
-  /**
-   * Perform actions necessary when changing from one Cpu_dev state to another.
-   *
-   * \tparam VMS       SVM or VMX state type
-   * \param current    Current CPU state
-   * \param new_state  CPU state to transition into
-   * \param lapic      local APIC of the current vCPU
-   * \param vm         SVM or VMX state
-   * \param cpu        current CPU device
-   */
-  template 
-  bool state_transition_effects(Cpu_dev::Cpu_state const current,
-                                Cpu_dev::Cpu_state const new_state,
-                                Gic::Virt_lapic *lapic, VMS *vm, Cpu_dev *cpu);
-
-  /**
-   * Perform actions of the state the Cpu_dev just transitioned into.
-   *
-   * \tparam VMS      SVM or VMX state type
-   * \param state     New CPU state after state transition
-   * \param halt_req  true, if `state` is the halt state and events are pending
-   * \param cpu       current CPU device
-   * \param vm        SVM or VMX state
-   */
-  template 
-  bool new_state_action(Cpu_dev::Cpu_state state, bool halt_req, Cpu_dev *cpu,
-                        VMS *vm);
-
-  void iomap_dump(Dbg::Verbosity l)
-  {
-    Dbg d(Dbg::Dev, l, "vmmap");
-    if (d.is_active())
-      {
-        d.printf("IOport map:\n");
-        std::lock_guard lock(_iomap_lock);
-        for (auto const &r : _iomap)
-          d.printf(" [%4lx:%4lx]: %s\n", r.first.start, r.first.end,
-                   r.second->dev_name());
-      }
-  }
-  std::mutex _iomap_lock;
-  Io_mem _iomap;
-
-  std::vector> _msr_devices;
-  std::vector> _cpuid_devices;
-
-  // devices
-  Guest_print_buffer _hypcall_print;
-  cxx::Ref_ptr _ptw;
-  cxx::Ref_ptr _apics;
-  cxx::Ref_ptr _icr_handler;
-  cxx::Ref_ptr _lapic_access_handler;
-  Boot::Binary_type _guest_t;
-  cxx::Ref_ptr _cpus;
-  Vmm::Event_recorder_array _event_recorders;
-  Xsave_state_area _xsave_layout;
-  l4_addr_t _guest_size;
-};
-
-/**
- * Handler for MSR read/write to a specific vCPU with its corresponding
- * VM state.
- */
-class Vcpu_msr_handler : public Msr_device
-{
-public:
-  Vcpu_msr_handler(Cpu_dev_array *cpus,
-                   Vmm::Event_recorders *ev_rec)
-  : _cpus(cpus), _ev_rec(ev_rec)
-  {};
-
-  bool read_msr(unsigned msr, l4_uint64_t *value, unsigned vcpu_no) const override
-  {
-    return _cpus->vcpu(vcpu_no).vm_state()->read_msr(msr, value);
-  }
-
-  bool write_msr(unsigned msr, l4_uint64_t value, unsigned vcpu_no) override
-  {
-    return _cpus->vcpu(vcpu_no)
-      .vm_state()
-      ->write_msr(msr, value, _ev_rec->recorder(vcpu_no));
-  }
-
-private:
-  Cpu_dev_array *_cpus;
-  Event_recorders *_ev_rec;
-};
-
-/**
- * Handler for MSR access to all MTRR registeres.
- *
- * MTRR are architectural registers and do not differ between AMD and Intel.
- * MTRRs are core specific and must be kept in sync.
- * Since all writes are ignored and reads just show the static state, we do
- * no core specific handling for these registers.
- */
-class Mtrr_msr_handler : public Msr_device
-{
-public:
-  Mtrr_msr_handler() = default;
-
-  bool read_msr(unsigned msr, l4_uint64_t *value, unsigned) const override
-  {
-    switch(msr)
-      {
-      case 0xfe:           // IA32_MTRRCAP, RO
-        *value = 1U << 10; // WriteCombining support bit.
-        break;
-      case 0x2ff:          // IA32_MTRR_DEF_TYPE
-        *value = 1U << 11; // E/MTRR enable bit
-        break;
-
-      // MTRRphysMask/Base[0-9]; only present if IA32_MTRRCAP[7:0] > 0
-      case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205:
-      case 0x206: case 0x207: case 0x208: case 0x209: case 0x20a: case 0x20b:
-      case 0x20c: case 0x20d: case 0x20e: case 0x20f: case 0x210: case 0x211:
-      case 0x212: case 0x213:
-        *value = 0;
-        break;
-
-      case 0x250:  // MTRRfix64K_0000
-        [[fallthrough]];
-      case 0x258:  // MTRRfix16K
-        [[fallthrough]];
-      case 0x259:  // MTRRfix16K
-        [[fallthrough]];
-      // MTRRfix_4K_*
-      case 0x268: case 0x269: case 0x26a: case 0x26b: case 0x26c: case 0x26d:
-      case 0x26e: case 0x26f:
-        *value = 0;
-        break;
-
-      default:
-        return false;
-      }
-
-    return true;
-  }
-
-  bool write_msr(unsigned msr, l4_uint64_t, unsigned) override
-  {
-    switch(msr)
-      {
-      case 0x2ff: // MTRRdefType
-        // We report no MTRRs in the MTRRdefType MSR. Thus we ignore writes here.
-        // MTRRs might also be disabled temporarily by the guest.
-        break;
-
-      // Ignore all writes to MTRR registers, we flagged all of them as unsupported
-      // MTRRphysMask/Base[0-9]; only present if MTRRcap[7:0] > 0
-      case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205:
-      case 0x206: case 0x207: case 0x208: case 0x209: case 0x20a: case 0x20b:
-      case 0x20c: case 0x20d: case 0x20e: case 0x20f: case 0x210: case 0x211:
-      case 0x212: case 0x213:
-        break;
-
-      case 0x250:  // MTRRfix64K_0000
-        [[fallthrough]];
-      case 0x258:  // MTRRfix16K
-        [[fallthrough]];
-      case 0x259:  // MTRRfix16K
-        [[fallthrough]];
-      // MTRRfix_4K_*
-      case 0x268: case 0x269: case 0x26a: case 0x26b: case 0x26c: case 0x26d:
-      case 0x26e: case 0x26f:
-        break;
-
-      default:
-        return false;
-      }
-
-    return true;
-  }
-}; // class Mtrr_msr_handler
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/io_port_handler_l4util.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/io_port_handler_l4util.cc
deleted file mode 100644
index ff62a7f8..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/io_port_handler_l4util.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2018, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include "io_port_handler.h"
-
-namespace Vdev {
-
-void Io_port_handler::io_in(unsigned p, Mem_access::Width width, l4_uint32_t *value)
-{
-  l4_uint16_t port = p + _base;
-
-  switch(width)
-    {
-    case Mem_access::Wd8:
-      *value = l4util_in8(port);
-      break;
-    case Mem_access::Wd16:
-      *value = l4util_in16(port);
-      break;
-    case Mem_access::Wd32:
-      *value = l4util_in32(port);
-      break;
-    case Mem_access::Wd64:
-      // architecture does not support 64bit port access
-      *value = -1;
-      break;
-    }
-}
-
-void Io_port_handler::io_out(unsigned p, Mem_access::Width width, l4_uint32_t value)
-  {
-    l4_uint16_t port = p + _base;
-
-    switch(width)
-      {
-      case Mem_access::Wd8:
-        l4util_out8(value, port);
-        break;
-
-      case Mem_access::Wd16:
-        l4util_out16(value, port);
-        break;
-
-      case Mem_access::Wd32:
-        l4util_out32(value, port);
-        break;
-
-      case Mem_access::Wd64:
-        // architecture does not support 64bit port access
-        break;
-      }
-  }
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.cc
deleted file mode 100644
index fa64d2a5..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "device_factory.h"
-#include "guest.h"
-#include "ioapic.h"
-
-namespace Gic {
-
-  l4_uint64_t Io_apic::read_reg(unsigned reg) const
-  {
-    switch (reg)
-      {
-      case Id_reg:
-        return _id;
-      case Version_reg:
-        return Io_apic_ver | ((Io_apic_num_pins - 1) << 16);
-      case Arbitration_reg:
-        return _id;
-      default:
-        {
-          unsigned index = reg - Redir_tbl_offset_reg;
-          unsigned irq = index / 2;
-          if (irq >= Io_apic_num_pins)
-            {
-              info().printf("Unimplemented MMIO read from ioregsel "
-                            "register 0x%x\n", reg);
-              return -1;
-            }
-
-          if (index % 2)
-            return _redirect_tbl[irq].load().upper_reg();
-          else
-            return _redirect_tbl[irq].load().lower_reg()
-                   & ~(1UL << Redir_tbl_entry::Nospec_level_set_bit);
-        }
-      }
-  }
-
-  void Io_apic::write_reg(unsigned reg, l4_uint64_t value)
-  {
-    if (reg == Id_reg)
-      {
-        _id = value;
-        return;
-      }
-
-    unsigned index = reg - Redir_tbl_offset_reg;
-    unsigned irq = index / 2;
-    if (irq >= Io_apic_num_pins)
-      {
-        info().printf("Unimplemented MMIO write to ioregsel register 0x%x\n",
-                      reg);
-        return;
-      }
-
-    Redir_tbl_entry e = _redirect_tbl[irq];
-    Redir_tbl_entry e_new;
-    bool was_pending = e.is_pending();
-
-     do
-       {
-         e_new = e;
-
-         if (index % 2)
-            e_new.upper_reg() = value;
-         else
-           {
-             // ignore writes to RO fields
-             value = (value & ~Redir_tbl_entry::Ro_mask)
-                     | e_new.delivery_status().get_unshifted()
-                     | e_new.remote_irr().get_unshifted();
-
-             // retain level_set bit, if entry is still masked.
-             if (   value & (1 << Redir_tbl_entry::Masked_bit)
-                 && e_new.is_pending())
-                value |= (1 << Redir_tbl_entry::Nospec_level_set_bit);
-
-             e_new.lower_reg() = value;
-           }
-        }
-      while (!_redirect_tbl[irq].compare_exchange_weak(e, e_new));
-
-      if (!e_new.masked())
-        apic_bind_irq_src_handler(irq, e_new.vector(), e_new.dest_id(),
-                                  e_new.dest_mode());
-
-      // in case of level-triggerd IRQs deliver IRQ since level is high.
-      if (!e_new.masked() && was_pending)
-        {
-          trace()
-            .printf("IRQ %i not masked anymore. send pending level irq\n",
-                    irq);
-           set(irq);
-         }
-      // no need to clear the level_set bit, we didn't write it into the new
-      // entry above.
-  }
-
-  l4_uint64_t Io_apic::read(unsigned reg, char, unsigned cpu_id)
-  {
-    switch (reg)
-      {
-      case Ioregsel:
-        return _ioregsel;
-      case Iowin:
-        return read_reg(_ioregsel.load());
-      case Eoir:
-        return 0UL;
-      default:
-        info().printf("Unimplemented MMIO read from register %d by CPU %d\n",
-                      reg, cpu_id);
-        return -1;
-      }
-  }
-
-  void Io_apic::write(unsigned reg, char, l4_uint64_t value, unsigned cpu_id)
-  {
-    switch (reg)
-      {
-      case Ioregsel:
-        _ioregsel = value & 0xff;
-        break;
-      case Iowin:
-        write_reg(_ioregsel.load(), value);
-        break;
-      case Eoir:
-        clear_all_rirr(value & 0xff);
-        break;
-      default:
-        info().printf("Unimplemented MMIO write to register %d by CPU %d\n",
-                      reg, cpu_id);
-        break;
-      }
-  }
-
-  void Io_apic::apic_bind_irq_src_handler(unsigned entry_num, unsigned vec,
-                                          unsigned dest, unsigned dest_mod)
-  {
-    Ioapic_irq_src_handler *hdlr = &_apic_irq_src[entry_num];
-    if (hdlr->vector != -1U)
-      {
-        // assumption: hdlr already bound
-        if (hdlr->vector == vec)
-          return;
-        else
-          apic_unbind_irq_src_handler(entry_num);
-      }
-
-    hdlr->vector = vec;
-    hdlr->dest = dest;
-    hdlr->dest_mod = dest_mod;
-    do_apic_bind_irq_src_handler(hdlr, true);
-  };
-
-  void Io_apic::apic_unbind_irq_src_handler(unsigned entry_num)
-  {
-    Ioapic_irq_src_handler *hdlr = &_apic_irq_src[entry_num];
-    if (hdlr->vector == -1U)
-      // don't unbind handler if not bound
-      return;
-
-    do_apic_bind_irq_src_handler(hdlr, false);
-
-    hdlr->vector = -1U;
-    hdlr->dest = -1U;
-    hdlr->dest_mod = 0U;
-  }
-
-  void Io_apic::do_apic_bind_irq_src_handler(Ioapic_irq_src_handler *hdlr,
-                                             bool bind)
-  {
-    Ioapic_irq_src_handler *new_hdlr = bind ? hdlr : nullptr;
-
-    if (hdlr->dest_mod == 0) // physical
-      {
-        auto apic = _lapics->get(hdlr->dest);
-        if (apic)
-          apic->bind_irq_src_handler(hdlr->vector, new_hdlr);
-      }
-    else
-      _lapics->apics_bind_irq_src_handler_logical(hdlr->dest, hdlr->vector,
-                                                  new_hdlr);
-  }
-
-  void Io_apic::set(unsigned irq)
-  {
-    // send to PIC. (TODO only if line is masked at IOAPIC?)
-    if (irq < 16) // PIC can handle only the first 16 lines
-      _pic->set(irq);
-
-    Redir_tbl_entry entry = redirect(irq);
-    if (entry.masked())
-      {
-        if (entry.is_level_triggered())
-          // We must save the state of the level triggered IRQ, since we get
-          // the softIRQ only once and can't query the current level.
-          // We don't notice, if the actual HW line changes to no-IRQ again,
-          // but that's better than losing an IRQ here.
-          set_level_set(irq);
-        return;
-      }
-
-    if (entry.remote_irr())
-      {
-        // ignore re-triggered level-triggered IRQs that are in-service at
-        // local APIC
-        return;
-      }
-
-    Vdev::Msix::Data_register_format data(entry.vector());
-    data.trigger_mode() = entry.trigger_mode();
-    data.trigger_level() = !entry.pin_polarity(); // it's actually inverted.
-    data.delivery_mode() = entry.delivery_mode();
-
-    Vdev::Msix::Interrupt_request_compat addr(0ULL);
-    addr.dest_id() = entry.dest_id();
-    addr.dest_mode() = entry.dest_mode();
-    addr.fixed() = Vdev::Msix::Address_interrupt_prefix;
-
-    _distr->send(addr.raw, data.raw);
-
-    // update entry if necessary
-    if (entry.is_level_triggered())
-      set_remote_irr(irq);
-  }
-
-} // namespace Gic
-
-
-namespace {
-
-  struct F : Vdev::Factory
-  {
-    cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                      Vdev::Dt_node const &node) override
-    {
-      auto msi_distr = devs->get_or_create_mc_dev(node);
-      auto apic_array = devs->vmm()->apic_array();
-      // Create the legacy PIC device here to forward legacy Interrupts.
-      auto pic = Vdev::make_device(msi_distr);
-      auto io_apic =
-        Vdev::make_device(msi_distr, apic_array, pic);
-      devs->vmm()->add_mmio_device(io_apic->mmio_region(), io_apic);
-
-      // Register legacy PIC IO-ports
-      devs->vmm()->add_io_device(Vmm::Io_region(0x20, 0x21,
-                                                Vmm::Region_type::Virtual),
-                                 pic->master());
-      devs->vmm()->add_io_device(Vmm::Io_region(0xA0, 0xA1,
-                                                Vmm::Region_type::Virtual),
-                                 pic->slave());
-      return io_apic;
-    }
-  };
-
-  static F f;
-  static Vdev::Device_type d = {"intel,ioapic", nullptr, &f};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.h
deleted file mode 100644
index 82a710a9..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/ioapic.h
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "mmio_device.h"
-#include "debug.h"
-#include "irq.h"
-#include "msi_controller.h"
-#include "msix.h"
-#include "msi_arch.h"
-#include "legacy_pic.h"
-#include "monitor/ioapic_cmd_handler.h"
-
-namespace Gic {
-
-/**
- * Virtual IOAPIC implementation of a 82093AA.
- *
- * The IOAPIC sends legacy IRQs onwards as MSI as programmed into the
- * redirection table by the guest.
- */
-class Io_apic : public Ic,
-                public Vmm::Mmio_device_t,
-                public Monitor::Ioapic_cmd_handler
-{
-  enum
-  {
-    Io_apic_id = 0,
-    Io_apic_id_offset = 24,
-    Io_apic_ver = 0x20,
-    Io_apic_num_pins = 120,
-    Io_apic_mem_size = 0x1000,
-    Irq_cells = 1, // keep in sync with virt-pc.dts
-  };
-
-  enum Ioapic_mmio_regs
-  {
-    Ioregsel = 0,
-    Iowin = 0x10,
-    Eoir = 0x40,
-  };
-
-  enum Ioapic_regs
-  {
-    Id_reg = 0,
-    Version_reg = 1,
-    Arbitration_reg = 2,
-    Redir_tbl_offset_reg = 0x10,
-  };
-
-  struct Redir_tbl_entry
-  {
-    enum
-    {
-      Delivery_status_bit = 12,
-      Remote_irr_bit = 14,
-      Masked_bit = 16,
-      Nospec_level_set_bit = 17,
-      Ro_mask = 1U << Nospec_level_set_bit | 1U << Delivery_status_bit
-                | 1U << Remote_irr_bit,
-    };
-
-    Redir_tbl_entry() noexcept = default;
-    // The IOAPIC spec mentions bit 48, which is specified as reserved, bit 16
-    // is the mask bit and I think it's sane to start out with masked vectors.
-    l4_uint64_t raw = 1ULL << 16;
-
-    bool is_level_triggered() const { return trigger_mode(); }
-    bool is_pending() { return is_level_triggered() && level_set(); }
-
-    CXX_BITFIELD_MEMBER_RO(56, 63, dest_id, raw);
-    // use reserved bit for internal state of level triggered input line.
-    // only relevant, if line is masked
-    CXX_BITFIELD_MEMBER(17, 17, level_set, raw);
-    CXX_BITFIELD_MEMBER_RO(16, 16, masked, raw);
-    CXX_BITFIELD_MEMBER_RO(15, 15, trigger_mode, raw);
-    CXX_BITFIELD_MEMBER(14, 14, remote_irr, raw);
-    CXX_BITFIELD_MEMBER_RO(13, 13, pin_polarity, raw);
-    CXX_BITFIELD_MEMBER_RO(12, 12, delivery_status, raw);
-    CXX_BITFIELD_MEMBER_RO(11, 11, dest_mode, raw);
-    CXX_BITFIELD_MEMBER_RO(8, 10, delivery_mode, raw);
-    CXX_BITFIELD_MEMBER_RO(0, 7, vector, raw);
-
-    // Redirection Table entries can only be written as DWORD.
-    CXX_BITFIELD_MEMBER(0, 31, lower_reg, raw);
-    CXX_BITFIELD_MEMBER(32, 63, upper_reg, raw);
-  };
-
-  struct Ioapic_irq_src_handler : public Irq_src_handler
-  {
-    void eoi() override
-    {
-      assert(ioapic != nullptr);
-
-      // clear state in redirection table entry
-      ioapic->entry_eoi(irq_num);
-
-      {
-        // MSI generated from the IRQ can have multiple target cores. If this
-        // IRQ/MSI is level triggered, multiple cores would send an EOI.
-        // Would be insane, but who knows.
-        std::lock_guard lock(_mtx);
-
-        // get IRQ src handler of input IRQ and forward EOI signal
-        Irq_src_handler *hdlr = ioapic->get_irq_src_handler(irq_num);
-        if (hdlr)
-          hdlr->eoi();
-      }
-    }
-
-    unsigned irq_num = 0;
-    Io_apic *ioapic = nullptr;
-    unsigned vector = -1U;
-    unsigned dest = -1U;
-    unsigned dest_mod = 0; // default: physical
-  private:
-    std::mutex _mtx;
-  };
-
-public:
-  enum
-  {
-    Mmio_addr = 0xfec00000,
-  };
-
-  Io_apic(cxx::Ref_ptr distr,
-          cxx::Ref_ptr apic_array,
-          cxx::Ref_ptr pic)
-  : _distr(distr), _lapics(apic_array),
-    _id(Io_apic_id << Io_apic_id_offset), _ioregsel(0), _iowin(0),
-    _pic(pic)
-  {
-    // initialize IRQ src handler for LAPIC communication
-    for (unsigned i = 0; i < Io_apic_num_pins; ++i)
-      {
-        _apic_irq_src[i].irq_num = i;
-        _apic_irq_src[i].ioapic = this;
-      }
-  }
-
-  // public only for monitor access
-  l4_uint64_t read_reg(unsigned reg) const;
-
-  // Mmio device interface
-  l4_uint64_t read(unsigned reg, char, unsigned cpu_id);
-  void write(unsigned reg, char, l4_uint64_t value, unsigned cpu_id);
-
-  // IC interface
-  void set(unsigned irq) override;
-  void clear(unsigned) override {}
-
-  /**
-   * Bind the IRQ src handler of a level-triggered legacy interrupt.
-   *
-   * This handler is signaled, if the IOAPIC receives an EOI signal from the
-   * local APIC for the corresponding interrupt line.
-   */
-  void bind_irq_src_handler(unsigned irq, Irq_src_handler *handler) override
-  {
-    if (irq >= Io_apic_num_pins)
-      {
-        warn().printf("Try to bind out-of-range IRQ %u. Ignoring. \n", irq);
-        return;
-      }
-    if (handler && _sources[irq])
-      L4Re::throw_error(-L4_EEXIST, "Bind IRQ src handler at IOAPIC." );
-    _sources[irq] = handler;
-  }
-
-  /**
-   * Get IRQ src handler bound for the given legacy interrupt line or
-   * `nullptr` if no handler is bound.
-   */
-  Irq_src_handler *get_irq_src_handler(unsigned irq) const override
-  {
-    if (irq >= Io_apic_num_pins)
-      {
-        warn().printf("Try to get out-of-range IRQ %u. Ignoring. \n", irq);
-        return nullptr;
-      }
-    return _sources[irq];
-  }
-
-  int dt_get_interrupt(fdt32_t const *prop, int propsz,
-                       int *read) const override
-  {
-    if (propsz < Irq_cells)
-      return -L4_ERANGE;
-
-    if (read)
-      *read = Irq_cells;
-
-    return fdt32_to_cpu(prop[0]);
-  }
-
-  Vmm::Region mmio_region() const
-  {
-    return Vmm::Region::ss(Vmm::Guest_addr(Mmio_addr), Io_apic_mem_size,
-                           Vmm::Region_type::Virtual);
-  }
-
-  char const *dev_name() const override { return "Ioapic"; }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "IOAPIC"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "IOAPIC"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "IOAPIC"); }
-
-  void write_reg(unsigned reg, l4_uint64_t value);
-
-  /// Return the redirection table entry for given `irq`.
-  Redir_tbl_entry redirect(unsigned irq) const
-  {
-    assert(irq < Io_apic_num_pins);
-    return _redirect_tbl[irq];
-  }
-
-  void entry_eoi(unsigned irq)
-  {
-    assert(irq < Io_apic_num_pins);
-
-    // clear remote_irr and for level triggered the level_set bit.
-    Redir_tbl_entry e = _redirect_tbl[irq];
-    Redir_tbl_entry e_new;
-
-    do
-      {
-        e_new = e;
-        e_new.remote_irr() = 0;
-        e_new.level_set() = 0;
-      }
-    while (!_redirect_tbl[irq].compare_exchange_weak(e, e_new));
-  }
-
-  void set_level_set(unsigned irq)
-  {
-    assert(irq < Io_apic_num_pins);
-
-    Redir_tbl_entry e = _redirect_tbl[irq];
-    Redir_tbl_entry e_new;
-
-    do
-      {
-        e_new = e;
-        e_new.level_set() = 1;
-      }
-    while (!_redirect_tbl[irq].compare_exchange_weak(e, e_new));
-  }
-
-  void set_remote_irr(unsigned irq)
-  {
-    assert(irq < Io_apic_num_pins);
-
-    Redir_tbl_entry e = _redirect_tbl[irq];
-    Redir_tbl_entry e_new;
-
-    do
-      {
-        e_new = e;
-        e_new.remote_irr() = 1;
-      }
-    while (!_redirect_tbl[irq].compare_exchange_weak(e, e_new));
-  }
-
-  void clear_all_rirr(l4_uint8_t vec)
-  {
-    for (unsigned i = 0; i < Io_apic_num_pins; ++i)
-      {
-        if (_redirect_tbl[i].load().vector() == vec)
-          entry_eoi(i);
-      }
-  }
-
-  void apic_bind_irq_src_handler(unsigned entry_num, unsigned vec,
-                                 unsigned dest, unsigned dest_mod);
-  void apic_unbind_irq_src_handler(unsigned entry_num);
-  void do_apic_bind_irq_src_handler(Ioapic_irq_src_handler *hdlr, bool bind);
-
-  cxx::Ref_ptr _distr;
-  cxx::Ref_ptr _lapics;
-  std::atomic _id;
-  std::atomic _ioregsel;
-  std::atomic _iowin;
-  std::atomic _redirect_tbl[Io_apic_num_pins];
-  Gic::Irq_src_handler *_sources[Io_apic_num_pins] = {};
-  cxx::Ref_ptr _pic;
-  Ioapic_irq_src_handler _apic_irq_src[Io_apic_num_pins];
-}; // class Io_apic
-
-} // namespace Gic
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/isa_debugport.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/isa_debugport.cc
deleted file mode 100644
index ae6c0ef1..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/isa_debugport.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2021, 2024 Kernkonzept GmbH.
- * Author(s):  Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * This implements a simple debug channel, similar to the ones implemented in
- * Qemu and Bochs.
- *
- * This can be used for low-level debugging of guests.
- *
- * Example DT:
- *
- * \code{.dtb}
- *   isa {
- *       device_type = "eisa";
- *       #address-cells = <2>;
- *       #size-cells = <1>;
- *       // The first cell of a child nodes reg property encodes the
- *       // following information. See the ISA bus device-tree binding [2]
- *       // for more details:
- *       //
- *       //  [2] 11-bit aliased (IOPORT only)
- *       //  [1] 10-bit aliased (IOPORT only)
- *       //  [0] 0=MMIO32, 1=IOPORT
- *       //
- *       // The standard ranges property defines the translation of child
- *       // reg address entries into the parent address space. Effectively
- *       // removes the upper word. For the purpose of the ISA translation,
- *       // only bit [0] is considered of the first word.
- *       ranges = <0x0 0x0 0x0 0x0 0xffffffff
- *                 0x1 0x0 0x0 0x0     0x1000>;
-
- *       isa_debugport {
- *           compatible = "l4vmm,isa-debugport";
- *           reg = <0x1 0x402 0x1>;
- *           l4vmm,vcon_cap = "debug";
- *       };
- *   };
- * \endcode
- */
-
-#include "device_factory.h"
-#include "guest.h"
-#include "device.h"
-#include "io_device.h"
-
-namespace Vdev {
-
-class Isa_debugport : public Vmm::Io_device, public Vdev::Device
-{
-  enum { Bochs_debug_port_magic = 0xe9 };
-
-public:
-  explicit Isa_debugport(L4::Cap con)
-  : _con(con)
-  {
-    l4_vcon_attr_t attr;
-    if (l4_error(con->get_attr(&attr)) != L4_EOK)
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "cons")
-          .printf("WARNING: Cannot set console attributes. "
-                  "Output may not work as expected.\n");
-        return;
-      }
-
-    attr.set_raw();
-    L4Re::chksys(con->set_attr(&attr), "console set_attr");
-  }
-
-  char const *dev_name() const override
-  { return "ISA Debugport"; }
-
-private:
-  /* IO write from the guest to device */
-  void io_out(unsigned, Vmm::Mem_access::Width, l4_uint32_t value) override
-  {
-    char s = value & 0xff;
-    _con->write(&s, 1);
-  }
-
-  /* IO read from the guest */
-  void io_in(unsigned, Vmm::Mem_access::Width, l4_uint32_t *value) override
-  {
-    *value = Bochs_debug_port_magic;
-  }
-
-  L4::Cap _con;
-};
-
-} // namespace Vdev
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    L4::Cap cap = Vdev::get_cap(node, "l4vmm,vcon_cap");
-
-    // Do not default to anything. If the cap is not there, there is no
-    // debugport.
-    if (!cap)
-      return nullptr;
-
-    auto dev = Vdev::make_device(cap);
-    devs->vmm()->register_io_device(dev, Vmm::Region_type::Virtual, node);
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"l4vmm,isa-debugport", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.cc
deleted file mode 100644
index 6fc1c3dc..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "device_factory.h"
-#include "guest.h"
-#include "kvm_clock.h"
-#include "mem_types.h"
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &) override
-  {
-    auto dev = Vdev::make_device(devs->ram(),
-                                                       devs->vmm());
-
-    devs->vmm()->register_msr_device(dev);
-    devs->vmm()->register_cpuid_device(dev);
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"kvm-clock", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.h
deleted file mode 100644
index bfa3b385..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/kvm_clock.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *            Benjamin Lamowski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "mem_types.h"
-#include "msr_device.h"
-#include "cpuid_device.h"
-#include "vm_ram.h"
-#include "ds_mmio_mapper.h"
-#include "cpu_dev.h"
-#include "guest.h"
-
-namespace Vdev {
-
-struct Vcpu_time_info
-{
-  l4_uint32_t   version;
-  l4_uint32_t   pad0;
-  l4_uint64_t   tsc_timestamp;
-  l4_uint64_t   system_time;
-  l4_uint32_t   tsc_to_system_mul;
-  l4_int8_t     tsc_shift;
-  // bit 0 is set, if all Vcpu_time_info instances show the same TSC value.
-  l4_uint8_t    flags;
-  l4_uint8_t    pad[2];
-};
-static_assert(sizeof(Vcpu_time_info) == 32,
-              "Vcpu_time_info structure is compact.");
-
-class Kvm_clock : public Vdev::Timer, public Device
-{
-
-public:
-  Kvm_clock(Vcpu_time_info *vti, bool enable)
-  {
-    configure(vti, enable);
-  }
-
-  void configure(Vcpu_time_info *vti, bool enable)
-  {
-    _vcpu_time_enable = enable;
-    vti->version = 0;
-    vti->tsc_to_system_mul = l4_scaler_tsc_to_ns;
-    vti->tsc_shift = 5;
-    vti->flags = 0;
-    _vcpu_time = vti;
-  }
-
-  void tick()
-  {
-    auto now = l4_rdtsc();
-
-    cxx::write_now(&(_vcpu_time->version), _vcpu_time->version + 1);
-    _vcpu_time->tsc_timestamp = now;
-    _vcpu_time->system_time = l4_tsc_to_ns(now);
-    cxx::write_now(&(_vcpu_time->version), _vcpu_time->version + 1);
-  }
-
-private:
-  Vcpu_time_info *_vcpu_time;
-  bool _vcpu_time_enable;
-  std::mutex _mutex;
-};
-
-class Kvm_clock_ctrl : public Vmm::Msr_device,
-                       public Vmm::Cpuid_device,
-                       public Device
-{
-  struct Wall_clock
-  {
-    l4_uint32_t version;
-    l4_uint32_t sec;
-    l4_uint32_t nsec;
-  };
-  static_assert(sizeof(Wall_clock) == 3 * 4,
-                "KVM Wall_clock struct is compact.");
-
-  enum Kvm_msrs : unsigned
-  {
-    Msr_kvm_wall_clock_new = 0x4b564d00,
-    Msr_kvm_system_time_new = 0x4b564d01,
-    Msr_kvm_async_pf_en = 0x4b564d02,
-    Msr_kvm_steal_time = 0x4b564d03,
-    Msr_kvm_eoi_en = 0x4b564d04,
-  };
-
-public:
-  Kvm_clock_ctrl(cxx::Ref_ptr const &memmap,
-                 Vmm::Guest *vmm)
-  : _boottime(l4_rdtsc()),
-    _memmap(memmap),
-    _vmm(vmm)
-  {}
-
-  bool read_msr(unsigned, l4_uint64_t *, unsigned) const override
-  {
-    // Nothing to read, above structures are memory mapped in the guest.
-    return false;
-  }
-
-  bool write_msr(unsigned msr, l4_uint64_t addr, unsigned core_no) override
-  {
-    switch (msr)
-      {
-      case Msr_kvm_wall_clock_new:
-        {
-          trace().printf("Msr_kvm_wall_clock_new with addr 0x%llx\n", addr);
-
-          // address must be 4-byte aligned
-          auto gaddr = Vmm::Guest_addr(addr & (-1UL << 2));
-          set_wall_clock(static_cast(host_addr(gaddr)));
-          break;
-        }
-
-      case Msr_kvm_system_time_new:
-        {
-          trace().printf("Msr_kvm_system_time_new to addr 0x%llx\n", addr);
-
-          bool enable = addr & 1;
-
-          // address must be 4-byte aligned
-          auto gaddr = Vmm::Guest_addr(addr & (-1UL << 2));
-          setup_vcpu_time(static_cast(host_addr(gaddr)),
-                          enable, core_no);
-          break;
-        }
-
-      // NOTE: below functions are disabled via CPUID leaf 0x4000'0001 and
-      // shouldn't be invoked by a guest.
-      case Msr_kvm_async_pf_en:
-        warn().printf("KVM async pf not implemented.\n");
-        break;
-      case Msr_kvm_steal_time:
-        warn().printf("KVM steal time not implemented.\n");
-        break;
-      case Msr_kvm_eoi_en:
-        warn().printf("KVM EIO not implemented.\n");
-        break;
-        // If the guest Linux is compiled with CONFIG_KVM and no-kvmclock is
-        // set on the command line, Linux will try to write to these MSRs on
-        // shutdown. We ignore that.
-      case 0x11:
-      case 0x12:
-        return true;
-      default:
-        return false;
-      }
-
-    return true;
-  }
-
-  bool handle_cpuid(l4_vcpu_regs_t const *regs, unsigned *a, unsigned *b,
-                    unsigned *c, unsigned *d) const override
-  {
-    enum Cpuid_kvm_constants
-    {
-      Kvm_feature_clocksource = 1UL,       // clock at msr 0x11 & 0x12
-      Kvm_feature_clocksource2 = 1UL << 3, // clock at msrs 0x4b564d00 & 01;
-      // host communicates synchronized KVM clocks via Vcpu_time_info.flags[0]
-      Kvm_feature_clocksource_stable_bit = 1UL << 24,
-    };
-
-    switch (regs->ax)
-      {
-        case 0x40000000:
-          *a = 0x40000001; // max CPUID leaf in the 0x4000'0000 range.
-          *b = 0x4b4d564b; // "KVMK"
-          *c = 0x564b4d56; // "VMKV"
-          *d = 0x4d;       // "M\0\0\0"
-          return true;
-        case 0x40000001:
-          *a = Kvm_feature_clocksource2 | Kvm_feature_clocksource_stable_bit;
-          *d = 0;
-          *b = *c = 0;
-          return true;
-        default:
-          return false;
-      }
-  }
-
-private:
-  void set_wall_clock(Wall_clock *cs) const
-  {
-    trace().printf("Set wall clock address: %p \n", cs);
-
-    cxx::write_now(&(cs->version), 1U);
-    l4_tsc_to_s_and_ns(_boottime, &(cs->sec), &(cs->nsec));
-    cxx::write_now(&(cs->version), 0U);
-  }
-
-  void setup_vcpu_time(Vcpu_time_info *vti, bool enable, unsigned core_no)
-  {
-    trace().printf("set system time address: %p: enable: %i, scaler 0x%x\n",
-                   vti, enable, l4_scaler_tsc_to_ns);
-
-    if (core_no >= _clocks.size())
-      _clocks.resize(core_no + 1);
-
-    if (_clocks[core_no])
-      _clocks[core_no]->configure(vti, enable);
-    else
-      {
-        auto clock_dev = Vdev::make_device(vti, enable);
-        _clocks[core_no] = clock_dev;
-        clock_dev->tick();
-      }
-  }
-
-  void *host_addr(Vmm::Guest_addr addr) const
-  {
-    return _memmap->guest2host(addr);
-  }
-
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "KVMclock"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "KVMclock"); }
-
-  l4_cpu_time_t _boottime;
-  std::vector> _clocks;
-  cxx::Ref_ptr _memmap;
-  Vmm::Guest *_vmm;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.cc
deleted file mode 100644
index fda45e21..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018-2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "legacy_pic.h"
-#include "device_factory.h"
-#include "guest.h"
-
-namespace
-{
-  struct F : Vdev::Factory
-  {
-    cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                      Vdev::Dt_node const &node) override
-    {
-      auto msi_distr = devs->get_or_create_mc_dev(node);
-      Dbg().printf("PIC found MSI ctrl %p\n", msi_distr.get());
-
-      auto dev = Vdev::make_device(msi_distr);
-
-      auto *vmm = devs->vmm();
-      vmm->add_io_device(Vmm::Io_region(0x20, 0x21, Vmm::Region_type::Virtual),
-                         dev->master());
-      vmm->add_io_device(Vmm::Io_region(0xA0, 0xA1, Vmm::Region_type::Virtual),
-                         dev->slave());
-
-      return dev;
-    }
-  }; // struct F
-
-  static F f;
-  static Vdev::Device_type t = {"virt-i8259-pic", nullptr, &f};
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.h
deleted file mode 100644
index f49a17f8..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/legacy_pic.h
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * Copyright (C) 2018-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "io_device.h"
-#include "device.h"
-#include "irq.h"
-#include "msi_arch.h"
-#include "msi_controller.h"
-
-#include 
-
-namespace Vdev {
-
-/**
- * Emulation of a programmable interrupt controller.
- *
- * Example of a device tree entry:
- *
- * \code{.dtb}
- *   PIC: pic {
- *       compatible = "virt-pic";
- *       reg = <0x0 0x0 0x0 0x0>;
- *       msi-parent = <&msi_ctrl>;
- *       interrupt-controller;
- *       #interrupt-cells = <1>;
- *   };
- * \endcode
- *
- * The PIC emulation provides the guest with the ability to assign the legacy
- * interrupts of the master and slave PIC to a software defined range of two
- * times eight consecutive interrupt numbers.
- * The emulation reacts to IO-ports 0x20/0x21 and 0xA0/0xA1 as Command/Data
- * port combination for the master and slave chips.
- */
-class Legacy_pic : public Gic::Ic
-{
-  enum Config
-  {
-    Num_irqs = 16 // Number of IRQs supported by PIC
-  };
-
-  enum Ports
-  {
-    Cmd_port = 0,
-    Data_port = 1,
-  };
-
-  enum class Init_words
-  {
-    ICW1 = 0,
-    ICW2,
-    ICW3,
-    ICW4,
-  };
-
-  /**
-   * Single PIC-chip emulation handling IO-port access and interrupt offsets.
-   */
-  class Chip : public Vmm::Io_device
-  {
-    // Register set
-    // We only support ICW1 == 0x11. (ICW4 | INIT).
-    struct ICW1
-    {
-      l4_uint8_t raw;
-
-      CXX_BITFIELD_MEMBER(0, 0, icw4, raw);
-      CXX_BITFIELD_MEMBER(1, 1, single, raw);           // only support 0
-      CXX_BITFIELD_MEMBER(2, 2, address_interval, raw); // only support 0
-      CXX_BITFIELD_MEMBER(3, 3, level_triggered_mode, raw); // ignore
-      CXX_BITFIELD_MEMBER(4, 4, init, raw);
-    };
-
-    struct ICW4
-    {
-      l4_uint8_t raw;
-
-      CXX_BITFIELD_MEMBER(0, 0, upm, raw); // 8086 mode, only one supported
-      /**
-       * Note from 8259a manual:
-       * 8259As with a copyright date of 1985 or later will operate in the AEOI
-       * mode as a master or a slave.
-       * In AEOI mode interrupts are acked on delivery.
-       */
-      CXX_BITFIELD_MEMBER(1, 1, aeoi, raw);
-      CXX_BITFIELD_MEMBER(2, 2, buffer_master, raw);
-      CXX_BITFIELD_MEMBER(3, 3, buffer_mode, raw);
-      CXX_BITFIELD_MEMBER(3, 3, sfnm, raw); // One iff special fully nested mode.
-    };
-
-    struct OCW2
-    {
-      l4_uint8_t raw;
-
-      CXX_BITFIELD_MEMBER(0, 2, irq, raw);
-      CXX_BITFIELD_MEMBER(5, 5, eoi, raw);
-      CXX_BITFIELD_MEMBER(6, 6, sl, raw);
-    };
-
-    struct OCW3
-    {
-      l4_uint8_t raw;
-
-      CXX_BITFIELD_MEMBER(0, 0, ris, raw);
-      CXX_BITFIELD_MEMBER(1, 1, rr, raw);
-      CXX_BITFIELD_MEMBER(2, 2, poll, raw);
-      CXX_BITFIELD_MEMBER(5, 5, smm, raw);
-      CXX_BITFIELD_MEMBER(6, 6, esmm, raw);
-    };
-
-    // Selected IRR/ISR register by OCW3 for even port reads
-    bool _read_isr = false;
-    // Interrupt service register. Stores the Irq currently being serviced.
-    l4_uint8_t _isr = 0;
-    // Interrupt request register. Stores incoming Irq requesting to be
-    // serviced.
-    l4_uint8_t _irr = 0;
-    // Interrupt mask register. Masks out interrupts.
-    l4_uint8_t _imr = 0;
-
-    // Needed to keep track of initialization sequence
-    Init_words _expect = Init_words::ICW1;
-
-    // Offset of interrupts
-    l4_uint8_t _offset = 0;
-    l4_uint8_t _slave_at = 0;
-
-    struct ICW1 _icw1 {0}; // store to keep track of single mode and icw4
-    struct ICW4 _icw4 {0}; // store to keep track of aeoi mode
-
-    bool _is_master;
-    Legacy_pic *_pic;
-
-  public:
-    Chip(bool master, Legacy_pic *pic) : _is_master(master), _pic(pic)
-    {
-      _icw4.aeoi() = 1;
-    }
-
-    char const *dev_name() const override
-    { return "PIC"; }
-
-    /// Check interrupt mask/in-service and return the IRQ number with offset.
-    int trigger(unsigned irq)
-    {
-      if (_offset == 0)
-        return -1;
-
-      unsigned irq_bit = 1U << irq;
-
-      if (_isr || _imr & irq_bit)
-        {
-          _irr |= irq_bit;
-          return -1;
-        }
-      else
-        {
-          if (!_icw4.aeoi())
-            _isr |= irq_bit;
-          _irr &= ~irq_bit;
-          return _offset + irq;
-        }
-    }
-
-  public:
-    /// Handle read accesses on the PICs command and data ports.
-    void io_in(unsigned port, Vmm::Mem_access::Width width, l4_uint32_t *value)
-      override
-    {
-      *value = -1U;
-
-      if (width != Vmm::Mem_access::Width::Wd8)
-        return;
-
-      switch (port)
-        {
-        case Cmd_port:
-          *value = _read_isr ? _isr : _irr;
-          break;
-
-        case Data_port:
-          *value = _imr;
-          trace().printf("%s read mask 0x%x\n",
-                         _is_master ? "Master:" : "Slave:", _imr);
-          break;
-        }
-
-      trace().printf("%s port in: %s - 0x%x\n",
-                     _is_master ? "Master:" : "Slave:",
-                     port == 0 ? "cmd" : "data", *value);
-    }
-
-    /// Handle write accesses on the PICs command and data ports.
-    void io_out(unsigned port, Vmm::Mem_access::Width width, l4_uint32_t value)
-      override
-    {
-      if (width != Vmm::Mem_access::Width::Wd8)
-        return;
-
-      trace().printf("%s port out: %s - 0x%x\n",
-                     _is_master ? "Master:" : "Slave:",
-                     port == 0 ? "cmd" : "data", value);
-
-      switch (port)
-        {
-        case Cmd_port:
-          handle_command_write(value);
-          break;
-
-        case Data_port:
-          handle_data_write(value);
-          break;
-        }
-    }
-
-  private:
-    /// Return the number of the first pending interrupt or -1.
-    int check_pending()
-    {
-      if (_isr || !(_irr & ~_imr))
-        // we cannot issue new interrupts
-        // if an interrupt is currently in service
-        // or if all pending interrupts (in irr) are masked
-        return -1;
-
-      for (int i = 0; _irr >> i; ++i)
-        {
-          l4_uint8_t bit = 1U << i;
-
-          if (_irr & bit)
-          {
-            _irr &= ~bit;
-            _isr |= bit;
-            return i;
-          }
-        }
-
-      return -1;
-    }
-
-    /**
-     * EOI of last issued interrupt
-     */
-    void eoi(unsigned irq = 0)
-    {
-      if (!irq)
-        _isr = 0;
-      else
-        _isr &= ~(1U << irq);
-
-      if (_is_master)
-        _pic->eoi(irq);
-      else
-        _pic->eoi(irq + 8);
-
-      issue_next_interrupt();
-    }
-
-    void issue_next_interrupt()
-    {
-      int next_irq = check_pending();
-      if (next_irq != -1)
-        _pic->send_interrupt(next_irq + _offset);
-    }
-
-
-    /**
-     * Reset to initial configuration
-     */
-    void reset()
-    {
-      _irr = _imr = _isr = 0;
-      _expect = Init_words::ICW1;
-      _offset = 0;
-      _slave_at = 0;
-      _icw1 = {0U};
-      _icw4 = {0U};
-      _icw4.aeoi() = 1;
-    }
-
-    void handle_command_write(l4_uint32_t command)
-    {
-      l4_uint8_t cmd = command;
-      if (cmd & 0x10) // ICW1
-        {
-          // start initialization sequence
-          reset();
-
-          _icw1 = {cmd};
-          if (_icw1.address_interval() || _icw1.single())
-            warn().printf("Unsupported initialization value.\n");
-
-          _expect = Init_words::ICW2;
-          return;
-        }
-
-      if (_expect != Init_words::ICW1) // are we still in initialization?
-        {
-          warn().printf("%s: PIC is in initialization and guest wrote OCW (%x). Ignoring.\n",
-                        _is_master ? "Master" : "Slave", cmd);
-          return;
-        }
-
-      // handle OCWs
-      if (cmd & 0x8)
-        {
-          struct OCW3 o{cmd};
-
-          if (o.rr())
-            {
-              _read_isr = o.ris();
-              return;
-            }
-
-          // ignore the rest
-        }
-      else // OCW2
-        {
-          struct OCW2 o{cmd};
-
-          if (o.eoi())
-            {
-              if (o.sl())
-                eoi(o.irq());
-              else
-                eoi();
-            }
-
-          // ignore the rest for now
-        }
-    }
-
-    void handle_data_write(l4_uint32_t value)
-    {
-      if (_expect != Init_words::ICW1) // we are in initialization
-        {
-          switch (_expect)
-            {
-            case Init_words::ICW1: break; // avoid compiler warning
-
-            case Init_words::ICW2:
-              _offset = value;
-              if (_icw1.single())
-                {
-                  if (_icw1.icw4())
-                    _expect = Init_words::ICW4;
-                  else
-                    _expect = Init_words::ICW1; // initialization complete
-                }
-              else
-                _expect = Init_words::ICW3;
-              warn().printf("%s: Vector offset %u\n",
-                            _is_master ? "MASTER" : "SLAVE", _offset);
-              break;
-
-            case Init_words::ICW3:
-              _slave_at = value;
-              if (_icw1.icw4())
-                _expect = Init_words::ICW4;
-              else
-                {
-                  _expect = Init_words::ICW1; // initialization complete
-                  _read_isr = false;
-                }
-              break;
-
-            case Init_words::ICW4:
-              _icw4.raw = value;
-              if (!_icw4.upm())
-                warn().printf("Guest tries to set MCS-80 mode. Unsupported.\n");
-              _expect = Init_words::ICW1; // initialization complete
-              _read_isr = false;
-              break;
-            }
-          return;
-        }
-
-      // OCW1
-      _imr = value;
-      // immediately inject pending irqs
-      issue_next_interrupt();
-    }
-
-  };
-
-public:
-  /**
-   * Create a legacy PIC consisting of a master and slave chip.
-   *
-   * \param distr  MSI-parent to send interrupts to.
-   */
-  Legacy_pic(cxx::Ref_ptr distr)
-  : _master(Vdev::make_device(true, this)),
-    _slave(Vdev::make_device(false, this)),
-    _distr(distr)
-  {
-    info().printf("Hello, Legacy_pic\n");
-  }
-
-  /// Issue a legacy interrupt in range [0, 15]
-  void set(unsigned irq) override
-  {
-    assert(irq < Num_irqs);
-
-    int num = irq < 8 ? _master->trigger(irq) : _slave->trigger(irq - 8);
-    // Do we need to set the _master line where the slave is wired to?
-    if (num >= 32)
-      send_interrupt(num);
-  };
-
-  void send_interrupt(int irq)
-  {
-    if (irq >= 32)
-      {
-        using namespace Vdev::Msix;
-
-        Interrupt_request_compat addr(0ULL);
-        // dest_id = 0, redirect_hint = 0, dest_mode = 0;
-        addr.fixed() = Address_interrupt_prefix;
-
-        Data_register_format data(0U);
-        data.vector() = irq;
-        data.delivery_mode() = Dm_extint;
-
-        _distr->send(addr.raw, data.raw);
-      }
-  }
-
-  void clear(unsigned) override {}
-
-  void bind_irq_src_handler(unsigned irq, Gic::Irq_src_handler *handler) override
-  {
-    assert(irq < Num_irqs);
-    if (handler && _sources[irq])
-      throw L4::Runtime_error(-L4_EEXIST);
-
-    _sources[irq] = handler;
-  }
-
-  Gic::Irq_src_handler *get_irq_src_handler(unsigned irq) const override
-  {
-    assert(irq < Num_irqs);
-    return _sources[irq];
-  }
-
-  void eoi(unsigned irq)
-  {
-    assert(irq < Num_irqs);
-
-    if (_sources[irq])
-      _sources[irq]->eoi();
-  }
-
-  int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const override
-  {
-    enum { Irq_cells = 1, };
-
-    if (propsz < Irq_cells)
-      return -L4_ERANGE;
-
-    if (read)
-      *read = Irq_cells;
-
-    return fdt32_to_cpu(prop[0]);
-  }
-
-  /// Obtain a pointer to the master PIC chip.
-  cxx::Ref_ptr master() const { return _master; }
-  /// Obtain a pointer to the slave PIC chip.
-  cxx::Ref_ptr slave() const { return _slave; }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "PIC"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "PIC"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "PIC"); }
-
-  cxx::Ref_ptr _master;
-  cxx::Ref_ptr _slave;
-  cxx::Ref_ptr _distr;
-  Gic::Irq_src_handler *_sources[Num_irqs] = {};
-};
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.cc
deleted file mode 100644
index b4e70c8a..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.cc
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Adam Lackorzynski 
- *            Philipp Eppelt 
- *            Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include 
-#include 
-#include 
-
-#include "mad.h"
-
-namespace L4mad
-{
-
-static const char *reg_names_x86_32[] = {
-    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
-
-static const char *reg_names_x86_16[] = {
-    "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
-
-static const char *reg_names_x86_8l[] = {
-    "al", "cl", "dl", "bl" };
-
-static const char *reg_names_x86_8h[] = {
-    "ah", "ch", "dh", "bh" };
-
-#ifdef ARCH_amd64
-enum Reg_names_amd64 { Reg_rax, Reg_rcx, Reg_rdx, Reg_rbx, Reg_rsp, Reg_rbp,
-                       Reg_rsi, Reg_rdi, Reg_r8, Reg_r9, Reg_r10, Reg_r11, Reg_r12,
-                       Reg_r13, Reg_r14, Reg_r15,
-                       Reg_eax = Reg_rax
-                     };
-
-static const char *reg_names_x86_64[]
-     = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
-         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
-
-#elif defined(ARCH_x86)
-
-enum Reg_names_x86 { Reg_eax, Reg_ecx, Reg_edx, Reg_ebx, Reg_esp, Reg_ebp,
-                     Reg_esi, Reg_edi };
-#endif
-
-static unsigned width_in_bytes(Width width)
-{
-  switch (width)
-    {
-    case Width::Wd8:  return 1;
-    case Width::Wd16: return 2;
-    case Width::Wd32: return 4;
-    case Width::Wd64: return 8;
-    }
-  L4Re::throw_error(-L4_EINVAL, "Invalid width to convert to bytes.");
-}
-
-enum Rex
-{
-  /// Operand size
-  Rex_w = 8,
-  /// ModR/M reg field
-  Rex_r = 4,
-  /// SIB index field
-  Rex_x = 2,
-  /// ModR/M r/m field
-  Rex_b = 1,
-};
-
-struct Modrm
-{
-  unsigned char raw;
-  explicit Modrm(unsigned char val) : raw(val) {}
-
-  /// Register (possibly extended by Rex_b) or an addressing mode combined with
-  /// the mod field.
-  CXX_BITFIELD_MEMBER(0, 2, rm, raw);
-  /// Register (possibly extended by Rex_r) or three additional opcode bits.
-  CXX_BITFIELD_MEMBER(3, 5, reg, raw);
-  /// Controls whether the rm field encodes a register (mod=3) or an addressing
-  /// mode.
-  CXX_BITFIELD_MEMBER(6, 7, mod, raw);
-};
-
-enum Rm
-{
-  Rm_sib = 4,
-  Rm_ripr  = 5,
-};
-
-enum Mod
-{
-  Mod_indirect        = 0,
-  Mod_indirect_disp8  = 1,
-  Mod_indirect_disp32 = 2,
-  Mod_direct          = 3,
-};
-
-struct Sib
-{
-  unsigned char raw;
-  explicit Sib(unsigned char val) : raw(val) {}
-
-  /// Base register (possibly extended by Rex_b).
-  CXX_BITFIELD_MEMBER(0, 2, base, raw);
-  /// Index register (possibly extended by Rex_x).
-  CXX_BITFIELD_MEMBER(3, 5, index, raw);
-  /// Scale factor of index field.
-  CXX_BITFIELD_MEMBER(6, 7, scale, raw);
-};
-
-struct Instruction
-{
-  /// Instruction length, only accurate after decoding of the instruction is
-  /// complete.
-  unsigned char len = 0;
-
-  /// Operand-size override
-  bool op_size_ovr = false;
-  /// REX prefix, if present
-  unsigned char rex = 0;
-
-  /// Operand size is forced to one byte
-  bool op_size_byte = false;
-
-  /// Register operand
-  unsigned char op_reg;
-  /// Shift to apply to register operand, e.g. used for accessing high byte.
-  unsigned char op_reg_shift;
-  /// Address operand
-  l4_addr_t op_addr;
-  /// Address operand is IP relative
-  bool op_addr_ripr;
-  /// Immediate operand
-  l4_umword_t op_imm;
-
-  // Assumption: If in protected mode or long compatibility mode we assume that
-  // we are in a 32-bit code segment (CS.d == 1).
-  Width op_width() const
-  {
-    // Operand-size override prefix and Rex.W have no effect on byte-specific
-    // operations.
-    if (op_size_byte)
-      return Width::Wd8;
-
-    if (rex & Rex_w)
-      return Width::Wd64;
-
-    return op_size_ovr ? Width::Wd16 : Width::Wd32;
-  }
-
-  // Assumption: If in protected mode or long compatibility mode we assume that
-  // we are in a 32-bit code segment (CS.d == 1).
-  Width imm_width() const
-  {
-    // Operand-size override prefix has no effect on byte-specific operations.
-    if (op_size_byte)
-      return Width::Wd8;
-
-    return op_size_ovr ? Width::Wd16 : Width::Wd32;
-  }
-
-  unsigned char rex_reg(unsigned char reg, Rex rex_bit) const
-  { return rex & rex_bit ? reg + 8 : reg; }
-};
-
-/**
- * Truncate value to specified width.
- *
- * \param v      Value to truncate
- * \param width  Width in bytes
- */
-static l4_umword_t
-truncate(l4_umword_t v, Width width)
-{
-  if (width_in_bytes(width) >= sizeof(l4_umword_t))
-    return v;
-  return v & ((1UL << (width * 8)) - 1);
-}
-
-/**
- * Sign-extend value from specified width.
- *
- * \param v           Value to sign-extend
- * \param from_width  Width in bytes
- */
-static l4_umword_t
-sign_extend(l4_umword_t v, Width from_width)
-{
-  if (width_in_bytes(from_width) >= sizeof(l4_umword_t))
-    return v;
-
-  l4_umword_t const msb = 1UL << (from_width * 8 - 1);
-  if (v & msb)
-    v |= ~0UL << (from_width * 8);
-  return v;
-}
-
-Decoder::Decoder(l4_exc_regs_t const *regs, l4_addr_t ip,
-                 unsigned char const *inst_buf, unsigned inst_buf_len)
-: _regs(regs), _ip(ip), _inst_buf(inst_buf), _inst_buf_len(inst_buf_len),
-#ifdef ARCH_amd64
-  // TODO: Introduce parameter to Decoder or decode(), that signifies whether
-  // CPU is in 64-bit mode or in compatibility/protected mode.
-  _long_mode_64(true)
-#else
-  _long_mode_64(false)
-#endif
-{
-}
-
-l4_umword_t
-Decoder::regval_arch(unsigned regnr) const
-{
-  switch (regnr)
-    {
-#ifdef ARCH_x86
-    case Reg_eax: return _regs->eax;
-    case Reg_ebx: return _regs->ebx;
-    case Reg_ecx: return _regs->ecx;
-    case Reg_edx: return _regs->edx;
-    case Reg_edi: return _regs->edi;
-    case Reg_esi: return _regs->esi;
-    case Reg_ebp: return _regs->ebp;
-    case Reg_esp: return _regs->sp;
-#else
-    case Reg_rax: return _regs->rax;
-    case Reg_rbx: return _regs->rbx;
-    case Reg_rcx: return _regs->rcx;
-    case Reg_rdx: return _regs->rdx;
-    case Reg_rdi: return _regs->rdi;
-    case Reg_rsi: return _regs->rsi;
-    case Reg_rbp: return _regs->rbp;
-    case Reg_rsp: return _regs->sp;
-    case Reg_r8:  return _regs->r8;
-    case Reg_r9:  return _regs->r9;
-    case Reg_r10: return _regs->r10;
-    case Reg_r11: return _regs->r11;
-    case Reg_r12: return _regs->r12;
-    case Reg_r13: return _regs->r13;
-    case Reg_r14: return _regs->r14;
-    case Reg_r15: return _regs->r15;
-#endif
-    default: return 0; // cannot happen but gcc complains
-    }
-}
-
-l4_umword_t
-Decoder::regval(unsigned regnr, unsigned shift, Width aw) const
-{
-  return truncate(regval_arch(regnr) >> shift, aw);
-}
-
-char const *
-Decoder::regname(unsigned regnr, unsigned shift, Width aw) const
-{
-#if defined(ARCH_x86) || defined(ARCH_amd64)
-  switch (aw)
-    {
-    case Width::Wd8:
-      return shift == 8 ? reg_names_x86_8h[regnr] : reg_names_x86_8l[regnr];
-    case Width::Wd16:
-      return reg_names_x86_16[regnr];
-    case Width::Wd32:
-      return reg_names_x86_32[regnr];
-    case Width::Wd64:
-#if defined(ARCH_x86)
-      return 0;
-#else
-      return reg_names_x86_64[regnr];
-#endif
-    }
-#endif
-  return 0;
-}
-
-void
-Decoder::regname_bm_snprintf(char *buf, unsigned buflen, unsigned reglist) const
-{
-  unsigned w = 0;
-  for (unsigned i = 0; i < Num_registers; ++i)
-    if (reglist & (1 << i))
-      w += snprintf(buf + w, buflen - w, "%s[%lx],",
-                    regname(i, 0, Width::Wd32), regval(i, 0, Width::Wd32));
-  if (reglist)
-    buf[w - 1] = 0;
-}
-
-char *
-Decoder::desc_s(char *buf, unsigned buflen, Desc const &d, Width aw) const
-{
-  switch (d.dtype)
-    {
-    case Desc_mem:
-      snprintf(buf, buflen, "Mem:%08lx", d.val);
-      break;
-    case Desc_reg:
-      snprintf(buf, buflen, "Reg:%s[%08lx] (s:%d,%ld,%d)",
-               regname(d.val, d.shift, aw), regval(d.val, d.shift, aw),
-               d.shift, d.val, aw);
-      break;
-    case Desc_regbitmap:
-        {
-          unsigned w = snprintf(buf, buflen, "Regs:");
-          regname_bm_snprintf(buf + w, buflen - w, d.val);
-        }
-      break;
-    case Desc_imm:
-      snprintf(buf, buflen, "Val:%08lx", d.val);
-      break;
-    }
-  buf[buflen - 1] = 0;
-  return buf;
-}
-
-void
-Decoder::print_insn_info(Op const &op, Desc const &tgt, Desc const &src) const
-{
-  char buf_s[32], buf_t[32];
-
-  warn()
-    .printf("0x%lx (%d): %s of %u bytes from %s to %s.\n",
-         _ip, op.insn_len, op.atype == Read ? "Read" : "Write",
-         op.access_width,
-         desc_s(buf_s, sizeof(buf_s), src, op.access_width),
-         desc_s(buf_t, sizeof(buf_t), tgt, op.access_width));
-}
-
-// Assumption: If in protected mode or long compatibility mode we assume that
-// we are in a 32-bit code segment (CS.d == 1).
-Width
-Decoder::addr_width(Instruction const &) const
-{
-  // TODO: Add support for address-size override prefix?
-  return _long_mode_64 ? Width::Wd64 : Width::Wd32;
-}
-
-l4_umword_t
-Decoder::peek_inst_bytes(Instruction const &inst, Width sz) const
-{
-  unsigned new_inst_len = inst.len + width_in_bytes(sz);
-  if (new_inst_len > _inst_buf_len || new_inst_len >= Max_instruction_len)
-    L4Re::throw_error(-L4_ERANGE, "Instruction out of bounds.");
-
-  unsigned char const *bytes = &_inst_buf[inst.len];
-  switch (sz)
-    {
-    case Width::Wd8: return *bytes;
-    case Width::Wd16: return *reinterpret_cast(bytes);
-    case Width::Wd32: return *reinterpret_cast(bytes);
-    case Width::Wd64: return *reinterpret_cast(bytes);
-    }
-  L4Re::throw_error(-L4_EINVAL, "Invalid instruction buffer access size.");
-}
-
-l4_umword_t
-Decoder::read_inst_bytes(Instruction &inst, Width sz) const
-{
-  l4_umword_t result = peek_inst_bytes(inst, sz);
-  inst.len += width_in_bytes(sz);
-  return result;
-}
-
-void
-Decoder::decode_legacy_prefixes(Instruction &inst)
-{
-  for(;;)
-    {
-      switch (peek_inst_bytes(inst, Width::Wd8))
-        {
-        // Group 1
-        // Lock and repeat prefixes
-        case 0xf0: // lock;
-          break;
-        case 0xf2:
-        case 0xf3:
-          trace().printf("Repeat prefix not considered\n");
-          break;
-        // Group 2
-        // Segment-Override Prefixes
-        case 0x26: // ES
-        case 0x36: // SS
-        case 0x64: // FS
-        case 0x65: // GS
-          trace().printf("Segment override not considered\n");
-          break;
-        // Branch hints
-        case 0x2e: // branch hint or CS segment override
-        case 0x3e: // branch hint or DS segment override
-          break;
-        // Group 3
-        // Operand-size override prefix
-        case 0x66:
-          inst.op_size_ovr = true;
-          break;
-        // Group 4
-        // Address-size override prefix
-        case 0x67:
-          trace().printf("Address-size override not considered\n");
-          break;
-
-        default:
-          // Not a prefix, opcode follows.
-          return;
-        };
-      ++inst.len;
-    }
-}
-
-void
-Decoder::decode_rex_prefix(Instruction &inst)
-{
-  if (!_long_mode_64)
-    return;
-
-  unsigned char ib = peek_inst_bytes(inst, Width::Wd8);
-  // REX prefix?
-  if ((ib & 0xf0) == 0x40)
-    {
-      inst.rex = ib;
-      ++inst.len;
-    }
-}
-
-bool
-Decoder::decode_modrm(Instruction &inst, unsigned char *opcode_ext)
-{
-  Modrm modrm(read_inst_bytes(inst, Width::Wd8));
-
-  // Writing into or reading from a register cannot raise a page fault,
-  // thus not relevant for our use case.
-  if (modrm.mod() == Mod_direct)
-    return false;
-
-  // Reg field encodes register if the opcode does not expect it to contain
-  // additional opcode bits.
-  if (!opcode_ext)
-    {
-      // Register operand
-      inst.op_reg = inst.rex_reg(modrm.reg(), Rex_r);
-
-      // AH to DH are only accessible if the instruction does not use a REX
-      // prefix. Then instead SPL, BPL, SIL, and DIL, which is the lower
-      // byte of the actually referenced register, would be accessed.
-      if (!inst.rex && inst.op_size_byte && inst.op_reg > 3)
-        {
-          inst.op_reg -= 4;
-          // Access the high byte (AH to DH)
-          inst.op_reg_shift = 8;
-        }
-    }
-  // Reg field encodes additional opcode bits.
-  else
-    *opcode_ext = modrm.reg();
-
-  // Memory address operand
-  if (modrm.rm() == Rm_sib)
-    {
-      inst.op_addr = decode_sib(inst, modrm);
-    }
-  else if (modrm.mod() == Mod_indirect && modrm.rm() == Rm_ripr)
-    {
-      inst.op_addr_ripr = _long_mode_64;
-      // Plus 32-bit displacement
-      inst.op_addr = sign_extend(read_inst_bytes(inst, Width::Wd32), Width::Wd32);
-    }
-  else
-    {
-      inst.op_addr = regval(inst.rex_reg(modrm.rm(), Rex_b), 0,
-                            addr_width(inst));
-    }
-
-  // Displacement
-  if (modrm.mod() == Mod_indirect_disp8 || modrm.mod() == Mod_indirect_disp32)
-  {
-    Width sz = modrm.mod() == Mod_indirect_disp8 ? Width::Wd8 : Width::Wd32;
-    inst.op_addr += sign_extend(read_inst_bytes(inst, sz), sz);
-  }
-
-  return true;
-}
-
-l4_umword_t
-Decoder::decode_sib(Instruction &inst, Modrm const &modrm)
-{
-  Sib sib(read_inst_bytes(inst, Width::Wd8));
-
-  l4_umword_t base = 0;
-  if (modrm.mod() == Mod_indirect && sib.base() == 5)
-    {
-      // No base register, instead a disp32 is specified.
-      base = sign_extend(read_inst_bytes(inst, Width::Wd32), Width::Wd32);
-    }
-  else
-    base = regval(inst.rex_reg(sib.base(), Rex_b), 0, addr_width(inst));
-
-  l4_umword_t index = 0;
-  unsigned char rindex = inst.rex_reg(sib.index(), Rex_x);
-  if (rindex != 4) // otherwise, no index register specified
-    index = regval(rindex, 0, addr_width(inst));
-
-  return base + (index << sib.scale());
-}
-
-void
-Decoder::decode_imm(Instruction &inst)
-{
-  Width imm_len = inst.imm_width();
-  inst.op_imm = read_inst_bytes(inst, imm_len);
-
-  if (_long_mode_64 && !inst.op_size_byte && (inst.rex & Rex_w))
-    // In 64-bit mode all immediates are sign-extended to 64 bits.
-    inst.op_imm = sign_extend(inst.op_imm, imm_len);
-}
-
-void
-Decoder::decode_imm_moffs(Instruction &inst)
-{
-  inst.op_imm = read_inst_bytes(inst, inst.op_width());
-}
-
-Decoder::Result
-Decoder::decode(Op *op, Desc *tgt, Desc *src)
-{
-  try
-    {
-      Decoder::Result result = decode_unsafe(op, tgt, src);
-      if (result != Result::Success)
-        warn().printf("Unsupported or invalid instruction at 0x%lx\n", _ip);
-      return result;
-    }
-  catch (L4::Runtime_error const &e)
-    {
-      warn().printf("Invalid instruction in [0x%lx, 0x%lx]: %s (%ld): %s\n",
-                    _ip, _ip + _inst_buf_len, e.str(), e.err_no(),
-                    e.extra_str() ? e.extra_str() : "");
-      return Result::Invalid;
-    }
-}
-
-Decoder::Result
-Decoder::decode_unsafe(Op *op, Desc *tgt, Desc *src)
-{
-  Instruction inst{};
-
-  // Instructions consist of the following components in the given order:
-  // - Legacy prefixes (optional)
-  // - REX prefix (optional)
-  // - Opcode (up to three bytes)
-  // - ModR/M (1 byte, if required)
-  // - SIB (1 byte, if required)
-  // - Displacement (1, 2 or 4 bytes, if required)
-  // - Immediate (1, 2, 4 or 8 bytes, if required)
-
-  decode_legacy_prefixes(inst);
-  decode_rex_prefix(inst);
-
-  // Read first opcode byte
-  unsigned char ib = read_inst_bytes(inst, Width::Wd8);
-  switch (ib)
-    {
-    case 0xc6: // mov $, a
-    case 0xc7:
-      {
-        inst.op_size_byte = !(ib & 1);
-
-        unsigned char opcode_ext;
-        if (!decode_modrm(inst, &opcode_ext))
-          return Result::Unsupported;
-
-        // Opcode extension must be zero.
-        if (opcode_ext != 0)
-          return Result::Unsupported;
-
-        decode_imm(inst);
-
-        op->set(Write, inst.op_width(), inst.len);
-        imm_from_op_imm(src, inst);
-        mem_from_op_addr(tgt, inst);
-        return Result::Success;
-      }
-
-    // read
-    case 0xa0: // mov a, %al
-    case 0xa1: // mov a, %eax
-    // write
-    case 0xa2: // mov %al, a
-    case 0xa3: // mov %eax, a
-      {
-        inst.op_size_byte = !(ib & 1);
-        bool write = (ib & 2);
-
-        decode_imm_moffs(inst);
-        op->set(write ? Write : Read, inst.op_width(), inst.len);
-        (write ? src : tgt)->set_reg(Reg_eax);
-        mem_from_op_imm(write ? tgt : src, inst);
-        return Result::Success;
-      }
-
-    // write
-    case 0x88: // mov %, a
-    case 0x89: // mov %, a
-    // read
-    case 0x8a: // mov a, %
-    case 0x8b: // mov a, %
-      {
-        inst.op_size_byte = !(ib & 1);
-        bool write = !(ib & 2);
-
-        if (!decode_modrm(inst))
-          return Result::Unsupported;
-
-        op->set(write ? Write : Read, inst.op_width(), inst.len);
-        reg_from_op_reg(write ? src : tgt, inst);
-        mem_from_op_addr(write ? tgt : src, inst);
-        return Result::Success;
-      }
-
-    default:
-      warn().printf("Unsupported opcode: 0x%x\n", ib);
-      return Result::Unsupported;
-    }
-}
-
-void
-Decoder::reg_from_op_reg(Desc *desc, Instruction const &inst) const
-{ desc->set_reg(inst.op_reg, inst.op_reg_shift); }
-
-void
-Decoder::imm_from_op_imm(Desc *desc, Instruction const &inst) const
-{ desc->set_imm(inst.op_imm); }
-
-void
-Decoder::mem_from_op_imm(Desc *desc, Instruction const &inst) const
-{ desc->set_mem(inst.op_imm); }
-
-void
-Decoder::mem_from_op_addr(Desc *desc, Instruction const &inst) const
-{
-  l4_addr_t addr = inst.op_addr;
-  if (inst.op_addr_ripr)
-    addr += _ip + inst.len;
-  // Truncate calculated address to current address width.
-  addr = truncate(addr, addr_width(inst));
-  desc->set_mem(addr);
-}
-
-} // namspace L4mad
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.h
deleted file mode 100644
index 5b35b8f1..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/mad.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2017, 2023-2024 Kernkonzept GmbH.
- * Author(s): Adam Lackorzynski 
- *            Philipp Eppelt 
- *            Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "debug.h"
-#include "mem_access.h"
-
-namespace L4mad
-{
-
-enum Desc_type { Desc_mem, Desc_imm, Desc_reg, Desc_regbitmap };
-enum Access_type { Write, Read };
-
-/// Width in bytes.
-using Width = Vmm::Mem_access::Width;
-
-struct Desc
-{
-  Desc_type dtype;
-  l4_umword_t val;
-  unsigned char shift;
-
-  void set_mem(l4_umword_t v)
-  { dtype = Desc_mem; val = v; shift = 0; }
-
-  void set_reg(l4_umword_t v, unsigned char s = 0)
-  { dtype = Desc_reg; val = v; shift = s; }
-
-  void set_regbitmap(l4_umword_t bm)
-  { dtype = Desc_regbitmap; val = bm; shift = 0; }
-
-  void set_imm(l4_umword_t v)
-  { dtype = Desc_imm; val = v; shift = 0; }
-};
-
-struct Op
-{
-  Access_type atype;
-  Width access_width;
-  unsigned char insn_len;
-
-  void set(Access_type t, Width aw, unsigned char il)
-  {
-    atype        = t;
-    access_width = aw;
-    insn_len     = il;
-  }
-};
-
-#if defined(ARCH_amd64)
-enum { Num_registers = 16, };
-#elif defined(ARCH_x86)
-enum { Num_registers = 8, };
-#endif
-
-struct Modrm;
-struct Instruction;
-
-class Decoder
-{
-public:
-  /**
-   * Create decoder for the given execution state.
-   *
-   * \param regs          General-purpose registers
-   * \param ip            Instruction pointer as guest virtual address (required
-   *                      for RIP-relative addressing)
-   * \param inst_buf      Buffer containing instruction bytes
-   * \param inst_buf_len  Length of instruction byte buffer
-   */
-  Decoder(l4_exc_regs_t const *regs, l4_addr_t ip,
-          unsigned char const *inst_buf, unsigned inst_buf_len);
-
-  enum { Max_instruction_len = 15 };
-
-  enum class Result
-  {
-    Success,
-    Unsupported,
-    Invalid,
-  };
-
-  /**
-   * Decode instruction as a read or write operation.
-   *
-   * \param[out] op   Operation
-   * \param[out] tgt  Target operand description
-   * \param[out] src  Source operation description
-   *
-   * \retval Result::Success     Instruction was decoded successfully.
-   * \retval Result::Unsupported Instruction decoding failed, because an
-   *                             unsupported instruction was encountered.
-   * \retval Result::Invalid     Instruction decoding failed, because an invalid
-   *                             or incomplete instruction was encountered, for
-   *                             example if the the instruction spans more bytes
-   *                             than available in the decoders instruction
-   *                             buffer.
-   *
-   * \note The decoder assumes that the CPU is executing in long 64-bit mode or
-   *       long compatibility / protected mode in a 32-bit code segment (i.e.
-   *       CS.d==1). Otherwise incorrect operand and address widths are
-   *       calculated.
-   */
-  Result decode(Op *op, Desc *tgt, Desc *src);
-
-  /**
-   * Print textual representation of a successfully decoded instruction.
-   */
-  void print_insn_info(Op const &op, Desc const &tgt, Desc const &src) const;
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Core, Dbg::Trace, "Mad"); }
-  static Dbg warn() { return Dbg(Dbg::Core, Dbg::Warn, "Mad"); }
-
-  Result decode_unsafe(Op *op, Desc *tgt, Desc *src);
-  void decode_legacy_prefixes(Instruction &inst);
-  void decode_rex_prefix(Instruction &inst);
-  bool decode_modrm(Instruction &inst, unsigned char *opcode_ext = nullptr);
-  l4_umword_t decode_sib(Instruction &inst, Modrm const &modrm);
-  void decode_imm(Instruction &inst);
-  void decode_imm_moffs(Instruction &inst);
-
-  char *desc_s(char *buf, unsigned buflen, Desc const &d, Width aw) const;
-  void regname_bm_snprintf(char *buf, unsigned buflen, unsigned reglist) const;
-  char const *regname(unsigned regnr, unsigned shift, Width aw) const;
-  l4_umword_t regval_arch(unsigned regnr) const;
-  l4_umword_t regval(unsigned regnr, unsigned shift, Width aw) const;
-
-  Width addr_width(Instruction const &inst) const;
-
-  l4_umword_t peek_inst_bytes(Instruction const &inst, Width sz) const;
-  l4_umword_t read_inst_bytes(Instruction &inst, Width sz) const;
-
-  void reg_from_op_reg(Desc *desc, Instruction const &inst) const;
-  void imm_from_op_imm(Desc *desc, Instruction const &inst) const;
-  void mem_from_op_imm(Desc *desc, Instruction const &inst) const;
-  void mem_from_op_addr(Desc *desc, Instruction const &inst) const;
-
-  l4_exc_regs_t const *const _regs;
-  l4_addr_t const _ip;
-  unsigned char const *const _inst_buf;
-  unsigned const _inst_buf_len;
-  bool const _long_mode_64;
-}; // class Decoder
-
-} // namespace L4mad
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/cpu_dev_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/cpu_dev_cmd_handler.h
deleted file mode 100644
index 4911e735..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/cpu_dev_cmd_handler.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2019-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "vmcs.h"
-#include "vcpu_ptr.h"
-#include "vm_state_vmx.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Cpu_dev_cmd_handler {};
-
-template
-class Cpu_dev_cmd_handler : public Cmd
-{
-public:
-  char const *help() const override
-  { return "CPU state"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'cpu  regs': dump CPU registers\n"
-               "* 'cpu  vmx': dump VMX state\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, {"regs", "vmx"}); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "regs")
-      show_regs(f);
-    else if (*args == "vmx")
-      show_vmx(f);
-    else
-      argument_error("Invalid subcommand");
-  }
-
-  void show_regs(FILE *f) const
-  {
-    auto regs = get_vcpu()->r;
-    auto *vms = get_vcpu().vm_state();
-
-    fprintf(f,
-            "RAX %lx\nRBX %lx\nRCX %lx\nRDX %lx\nRSI %lx\nRDI %lx\n"
-            "RSP %lx\nRBP %lx\nR8 %lx\nR9 %lx\nR10 %lx\nR11 %lx\n"
-            "R12 %lx\nR13 %lx\nR14 %lx\nR15 %lx\nRIP %lx\n",
-            regs.ax, regs.bx, regs.cx, regs.dx, regs.si, regs.di,
-            regs.sp, regs.bp, regs.r8, regs.r9, regs.r10, regs.r11,
-            regs.r12, regs.r13, regs.r14, regs.r15, vms->ip());
-  }
-
-  void show_vmx(FILE *f) const
-  {
-    Vmm::Vmx_state *vmx = dynamic_cast(get_vcpu().vm_state());
-
-    if (!vmx)
-      {
-        fprintf(f, "Failed to read VMX state\n");
-        return;
-      }
-
-    fprintf(f, "(C) VPID: 0x%llx\n",
-            vmx->vmx_read(VMCS_VPID));
-    fprintf(f, "(C) Int notification vector: 0x%llx\n",
-            vmx->vmx_read(VMCS_PIR_NOTIFICATION_VECTOR));
-    fprintf(f, "(C) EPTP index: 0x%llx\n",
-            vmx->vmx_read(VMCS_EPTP_INDEX));
-    fprintf(f, "(C) EPT pointer: 0x%llx\n",
-            vmx->vmx_read(VMCS_EPT_POINTER));
-    fprintf(f, "(C) Pin-based execution control: 0x%llx\n",
-            vmx->vmx_read(VMCS_PIN_BASED_VM_EXEC_CTLS));
-    fprintf(f, "(C) Primary execution control: 0x%llx\n",
-            vmx->vmx_read(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS));
-    fprintf(f, "(C) Secondary execution control: 0x%llx\n",
-            vmx->vmx_read(VMCS_SEC_PROC_BASED_VM_EXEC_CTLS));
-
-    fprintf(f, "(c) basic capabilities: 0x%llx\n",
-            vmx->cap_read(L4_VM_VMX_BASIC_REG));
-    fprintf(f, "(C) Real pin-based execution control: 0x%llx\n",
-            vmx->cap_read(L4_VM_VMX_TRUE_PINBASED_CTLS_REG));
-    fprintf(f, "(C) Real primary execution control: 0x%llx\n",
-            vmx->cap_read(L4_VM_VMX_TRUE_PROCBASED_CTLS_REG));
-    fprintf(f, "(C) Real secondary execution control: 0x%llx\n",
-            vmx->cap_read(L4_VM_VMX_PROCBASED_CTLS2_REG));
-
-    fprintf(f, "(G) ES selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_ES_SELECTOR));
-    fprintf(f, "(G) CS selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_CS_SELECTOR));
-    fprintf(f, "(G) SS selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_SS_SELECTOR));
-    fprintf(f, "(G) DS selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_DS_SELECTOR));
-    fprintf(f, "(G) FS selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_FS_SELECTOR));
-    fprintf(f, "(G) GS selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_GS_SELECTOR));
-    fprintf(f, "(G) GDTR base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_GDTR_BASE));
-    fprintf(f, "(G) IDTR base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_IDTR_BASE));
-
-    fprintf(f, "(G) LDTR selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_LDTR_SELECTOR));
-    fprintf(f, "(G) TR selector: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_TR_SELECTOR));
-    fprintf(f, "(G) interrupt status: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_INTERRUPT_STATUS));
-
-    fprintf(f, "(C) IO bitmap A: 0x%llx\n",
-            vmx->vmx_read(VMCS_ADDRESS_IO_BITMAP_A));
-    fprintf(f, "(C) IO bitmap B: 0x%llx\n",
-            vmx->vmx_read(VMCS_ADDRESS_IO_BITMAP_B));
-    fprintf(f, "(C) MSR bitmaps: 0x%llx\n",
-            vmx->vmx_read(VMCS_ADDRESS_MSR_BITMAP));
-    fprintf(f, "(C) Exit MSR store address: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_EXIT_MSR_STORE_ADDRESS));
-    fprintf(f, "(C) Exit MSR load address: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_EXIT_MSR_LOAD_ADDRESS));
-    fprintf(f, "(C) Entry MSR load address: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_ENTRY_MSR_LOAD_ADDRESS));
-
-    fprintf(f, "(C) Entry control: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_ENTRY_CTLS));
-    fprintf(f, "(C) Entry error: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_ENTRY_EXCEPTION_ERROR));
-    fprintf(f, "(C) Entry MSR load cnt: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_ENTRY_MSR_LOAD_COUNT));
-    fprintf(f, "(C) Entry interrupt info: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_ENTRY_INTERRUPT_INFO));
-    fprintf(f, "(C) VM-instruction error: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_INSN_ERROR));
-    fprintf(f, "(C) Exit control: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_EXIT_CTLS));
-    fprintf(f, "(C) Exit reason: 0x%llx\n",
-            vmx->vmx_read(VMCS_EXIT_REASON));
-    fprintf(f, "(C) Exit interrupt info: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_EXIT_INTERRUPT_INFO));
-    fprintf(f, "(C) Exit interrupt error: 0x%llx\n",
-            vmx->vmx_read(VMCS_VM_EXIT_INTERRUPT_ERROR));
-    fprintf(f, "(C) Guest interruptability: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_INTERRUPTIBILITY_STATE));
-
-    fprintf(f, "(G) ES limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_ES_LIMIT));
-    fprintf(f, "(G) CS limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_CS_LIMIT));
-    fprintf(f, "(G) SS limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_SS_LIMIT));
-    fprintf(f, "(G) DS limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_DS_LIMIT));
-    fprintf(f, "(G) FS limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_FS_LIMIT));
-    fprintf(f, "(G) GS limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_GS_LIMIT));
-    fprintf(f, "(G) GDTR limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_GDTR_LIMIT));
-    fprintf(f, "(G) IDTR limit: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_IDTR_LIMIT));
-    fprintf(f, "(G) Activity state: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_ACTIVITY_STATE));
-
-    fprintf(f, "(G) sysenter rip: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_IA32_SYSENTER_EIP));
-    fprintf(f, "(G) sysenter rsp: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_IA32_SYSENTER_ESP));
-    fprintf(f, "(G) exit qualification: 0x%llx\n",
-            vmx->vmx_read(VMCS_EXIT_QUALIFICATION));
-    fprintf(f, "(G) guest linear address: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_LINEAR_ADDRESS));
-    fprintf(f, "(G) CR0: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_CR0));
-    fprintf(f, "(G) CR3: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_CR3));
-    fprintf(f, "(G) CR4: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_CR4));
-    fprintf(f, "(G) Guest IA32 EFER: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_IA32_EFER));
-    fprintf(f, "(G) RFLAGS: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_RFLAGS));
-    fprintf(f, "(G) RIP: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_RIP));
-    fprintf(f, "(G) RSP: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_RSP));
-    fprintf(f, "(G) ES base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_ES_BASE));
-    fprintf(f, "(G) CS base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_CS_BASE));
-    fprintf(f, "(G) SS base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_SS_BASE));
-    fprintf(f, "(G) DS base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_DS_BASE));
-    fprintf(f, "(G) FS base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_FS_BASE));
-    fprintf(f, "(G) GS base: 0x%llx\n",
-            vmx->vmx_read(VMCS_GUEST_GS_BASE));
-  }
-
-private:
-  Vmm::Vcpu_ptr get_vcpu() const
-  { return static_cast(this)->vcpu(); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/ioapic_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/ioapic_cmd_handler.h
deleted file mode 100644
index 15a04a55..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/ioapic_cmd_handler.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Ioapic_cmd_handler {};
-
-template
-class Ioapic_cmd_handler : public Cmd
-{
-  enum Ioapic_regs
-  {
-    Id_reg = 0x0,
-    Version_reg = 0x1,
-    Arbitration_reg = 0x2,
-    Redir_tbl_offset_reg = 0x10,
-    Redir_tbl_last_reg = 0x3f,
-  };
-
-  struct Ioapic_reg
-  {
-    char const *name;
-    unsigned addr;
-    unsigned bytes;
-  };
-
-public:
-  Ioapic_cmd_handler()
-  { register_toplevel("ioapic"); }
-
-  char const *help() const override
-  { return "IO APIC registers"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n", help());
-  }
-
-  void exec(FILE *f, Arglist * /*args*/) override
-  {
-    show_ioapic(f);
-  }
-
-  void show_ioapic(FILE *f) const
-  {
-    Ioapic_reg ioapic_regs[] =
-      {
-        {"IOAPIC ID", Id_reg, 4},
-        {"IOAPIC Version", Version_reg, 4},
-        {"IOAPIC Arbitration ID", Arbitration_reg, 4},
-      };
-
-    fprintf(f, "|%-5s |%-5s |%-30s |%-18s |\n",
-            "Reg", "Bytes", "Name", "Value");
-
-    for (auto const ® : ioapic_regs)
-      print_row(f, reg);
-
-    print_redirection_table(f);
-  }
-
-private:
-  void print_redirection_table(FILE *f) const
-  {
-    for (unsigned reg = Redir_tbl_offset_reg; reg < Redir_tbl_last_reg;
-         reg += 2)
-      print_redir_row(f, reg, "Redirection table ",
-                      (reg - Redir_tbl_offset_reg) / 2);
-  }
-
-  void print_redir_row(FILE *f, unsigned addr, std::string name,
-                       unsigned idx) const
-  {
-    unsigned bytes = 8;
-    print_location(f, addr, bytes);
-
-    name.append(std::to_string(idx));
-    fprintf(f, "|%-30s ", name.c_str());
-
-    l4_uint64_t lower = ioapic_read(addr);
-    l4_uint64_t upper = ioapic_read(addr + 1);
-
-    fprintf(f,
-            "|0x%0*llx%.*s ",
-            bytes * 2,
-            (upper << 32) | (lower & 0xffff'ffffU),
-            (8 - bytes) * 2,
-            "        ");
-
-    fprintf(f,"|\n");
-  }
-
-  void print_row(FILE *f, Ioapic_reg const &r) const
-  {
-    print_location(f, r.addr, r.bytes);
-
-    fprintf(f, "|%-30s ", r.name);
-
-    print_value(f, r.addr, r.bytes);
-
-    fprintf(f,"|\n");
-  }
-
-  void print_location(FILE *f, unsigned reg, unsigned bytes) const
-  { fprintf(f, "|0x%03x |%-5u ", reg, bytes); }
-
-  void print_value(FILE *f, unsigned reg, unsigned bytes) const
-  {
-    l4_uint64_t value = ioapic_read(reg);
-    if (value == -1ULL)
-      {
-        fprintf(f, "Failed to read IOAPIC register\n");
-        return;
-      }
-
-    fprintf(f,
-            "|0x%0*llx%.*s ",
-            bytes * 2,
-            value,
-            (8 - bytes) * 2,
-            "        ");
-  }
-
-  T const *ioapic() const
-  { return static_cast(this); }
-
-  l4_uint64_t ioapic_read(unsigned reg) const
-  { return ioapic()->read_reg(reg); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/lapic_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/lapic_cmd_handler.h
deleted file mode 100644
index a6edb411..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/lapic_cmd_handler.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Lapic_cmd_handler {};
-
-template
-class Lapic_cmd_handler : public Cmd
-{
-  enum { Chunk_size = 4 };
-
-  struct Apic_register
-  {
-    Apic_register(char const *name, unsigned msr, unsigned bytes = 4)
-    : name(name), msr(msr), bytes(bytes)
-    {}
-
-    char const *name;
-    unsigned msr;
-    unsigned bytes;
-  };
-
-public:
-  Lapic_cmd_handler()
-  { register_toplevel("lapic"); }
-
-  char const *help() const override
-  { return "Local APIC registers"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'lapic ': dump local APIC registers for a specific cpu\n"
-               "* 'lapic all': dump local APIC registers for all cpus\n",
-            help());
-  }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "all")
-      {
-        unsigned i = 0;
-        while (lapic_check(i))
-          {
-            fprintf(f, "LAPIC %u\n", i);
-            show_lapic(f, i);
-            fprintf(f, "\n");
-            ++i;
-          }
-      }
-    else
-      {
-        unsigned lapic_no =
-          args->pop("Failed to parse local APIC number.");
-
-        if (!lapic_check(lapic_no))
-          argument_error("No such CPU or no local APIC registers found");
-
-        show_lapic(f, lapic_no);
-      }
-  }
-
-  void show_lapic(FILE *f, unsigned lapic_no) const
-  {
-    static Apic_register registers[] = {
-      { "Local APIC ID",                           0x802 },
-      { "Local APIC Version",                      0x803 },
-      { "Task Priority",                           0x808 },
-      { "Process Priority",                        0x80a },
-      { "Logical Destination",                     0x80d },
-      { "Destination Format",                      0x80e },
-      { "Spurious Vector",                         0x80f },
-      { "In-Service",                              0x810, 32 },
-      { "Trigger Mode",                            0x818, 32 },
-      { "Interrupt Request",                       0x820, 32 },
-      { "Error Status",                            0x828 },
-      { "Corrected Machine Check Error Interrupt", 0x82f },
-      { "Interrupt Command",                       0x830, 8 },
-      { "LVT Timer",                               0x832 },
-      { "LVT Thermal Sensor",                      0x833 },
-      { "LVT Performance Monitoring Counters",     0x834 },
-      { "LVT LINT0",                               0x835 },
-      { "LVT LINT1",                               0x836 },
-      { "LVT Error",                               0x837 },
-      { "Initial Count",                           0x838 },
-      { "Current Count",                           0x839 },
-      { "TSC Deadline",                            0x6e0 }
-    };
-
-    fprintf(f, "|%-5s |%-5s |%-40s |%-18s |\n",
-            "MSR", "Bytes", "Name", "Value");
-
-    for (auto const &r : registers)
-      {
-        if (r.bytes <= 8)
-          {
-            print_row(f, lapic_no, r);
-          }
-        else
-          {
-            for (unsigned chunk = 0; chunk < r.bytes / Chunk_size; ++chunk)
-              print_row(f, lapic_no, r, chunk);
-          }
-      }
-    print_row(f, "Is NMI pending",
-              static_cast(this)->get(lapic_no)->is_nmi_pending());
-  }
-
-private:
-  void print_row(FILE *f, char const *name, l4_uint64_t value) const
-  {
-    fprintf(f, "|0x%03x |%-5u ", 0, 0);
-    fprintf(f, "|%-40s ", name);
-
-    unsigned bytes = 4;
-    fprintf(f,
-            "|0x%0*llx%.*s ",
-            bytes * 2,
-            value,
-            (8 - bytes) * 2,
-            "        ");
-    fprintf(f,"|\n");
-  }
-
-  void print_row(FILE *f, unsigned lapic_no, Apic_register const &r) const
-  {
-    print_location(f, r.msr, r.bytes);
-
-    fprintf(f, "|%-40s ", r.name);
-
-    print_value(f, lapic_no, r.msr, r.bytes);
-
-    fprintf(f,"|\n");
-  }
-
-  void print_row(FILE *f,
-                 unsigned lapic_no,
-                 Apic_register const &r,
-                 unsigned chunk) const
-  {
-    print_location(f, r.msr, Chunk_size);
-
-    fprintf(f,
-            "|[%3u:%3u] %-30s ",
-            chunk * Chunk_size * 8,
-            (chunk + 1) * Chunk_size * 8 - 1,
-            r.name);
-
-    print_value(f, lapic_no, r.msr + chunk, Chunk_size);
-
-    fprintf(f,"|\n");
-  }
-
-  void print_location(FILE *f, unsigned msr, unsigned bytes) const
-  { fprintf(f, "|0x%03x |%-5u ", msr, bytes); }
-
-  void print_value(FILE *f,
-                   unsigned lapic_no,
-                   unsigned msr,
-                   unsigned bytes) const
-  {
-    l4_uint64_t value;
-    if (!lapic_read_msr(lapic_no, msr, &value))
-      {
-        fprintf(f, "Failed to read Local APIC register\n");
-        return;
-      }
-
-    fprintf(f,
-            "|0x%0*llx%.*s ",
-            bytes * 2,
-            value,
-            (8 - bytes) * 2,
-            "        ");
-  }
-
-  bool lapic_check(unsigned lapic_no) const
-  { return static_cast(this)->get(lapic_no) != nullptr; }
-
-  bool lapic_read_msr(unsigned lapic_no, unsigned msr, l4_uint64_t *value) const
-  {
-    return lapic_check(lapic_no)
-           && static_cast(this)->get(lapic_no)->read_msr(msr, value);
-  }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/monitor_arch.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/monitor_arch.h
deleted file mode 100644
index f69e5261..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/monitor/monitor_arch.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-constexpr bool has_iomap()
-{ return true; }
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/msi_arch.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/msi_arch.h
deleted file mode 100644
index dcc22029..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/msi_arch.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-namespace Vdev { namespace Msix {
-
-enum Table_entry_const_arch
-{
-  Data_vector_mask = 0xff,
-  Address_interrupt_prefix = 0xfee,
-};
-
-/// MSI-X address: Interrupt request compatibility format (Intel)
-struct Interrupt_request_compat
-{
-  l4_uint64_t raw;
-  CXX_BITFIELD_MEMBER(40, 63, dest_id_upper, raw);
-  CXX_BITFIELD_MEMBER(32, 39, reserved0_2, raw);
-  CXX_BITFIELD_MEMBER(20, 31, fixed, raw);
-  CXX_BITFIELD_MEMBER(12, 19, dest_id, raw);
-  CXX_BITFIELD_MEMBER(4, 11, reserved0_1, raw);
-  CXX_BITFIELD_MEMBER(3, 3, redirect_hint, raw);
-  CXX_BITFIELD_MEMBER(2, 2, dest_mode, raw);
-  CXX_BITFIELD_MEMBER(0, 1, reserved_0, raw);
-
-  explicit Interrupt_request_compat(l4_uint64_t addr) : raw(addr)
-  {}
-};
-
-enum Delivery_mode : l4_uint8_t
-{
-  Dm_fixed = 0,
-  Dm_lowest_prio = 1,
-  Dm_smi = 2,
-  Dm_nmi = 4,
-  Dm_init = 5,
-  Dm_startup = 6,
-  Dm_extint = 7,
-};
-
-/// MSI-X data format (Intel)
-struct Data_register_format
-{
-  // Intel SDM Vol. 3A 10-35, October 2017
-  l4_uint64_t raw;
-  CXX_BITFIELD_MEMBER(15, 15, trigger_mode, raw);
-  CXX_BITFIELD_MEMBER(14, 14, trigger_level, raw);
-  CXX_BITFIELD_MEMBER(8, 10, delivery_mode, raw);
-  CXX_BITFIELD_MEMBER(0, 7, vector, raw);
-
-  explicit Data_register_format(l4_uint64_t data) : raw(data)
-  {}
-};
-
-}} // namespace Vdev::Msix
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/msr_devices.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/msr_devices.h
deleted file mode 100644
index 89540238..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/msr_devices.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "msr_device.h"
-#include "vcpu_ptr.h"
-
-namespace Vdev {
-
-/**
- * MSR device handling read access to IA32_BIOS_SIGN_ID.
- *
- * This MSR provides the currently loaded microcode revision in bit [32:63].
- * As MSR access is a priviledged instruction this data can only be read with
- * support from the kernel. By default, the kernel provides the relevant 32
- * bits of IA32_BIOS_SIGN_ID in the last user_data register of the vCPU state.
- */
-class Microcode_revision : public Vmm::Msr_device
-{
-  enum { Ia32_bios_sign_id = 0x8b };
-
-public:
-  Microcode_revision(Vmm::Vcpu_ptr vcpu)
-  : _ucode_revision((l4_uint64_t)vcpu.ucode_revision() << 32)
-  {
-    // Fiasco reports just the upper 32-bit aka microcode revision. To recreate
-    // the complete MSR, we need to shift it to the upper 32-bit of the 64-bit
-    // MSR.
-  }
-
-  bool read_msr(unsigned msr, l4_uint64_t *value, unsigned) const override
-  {
-    if (msr != Ia32_bios_sign_id)
-      return false;
-
-    *value = _ucode_revision;
-    return true;
-  }
-
-  bool write_msr(unsigned, l4_uint64_t, unsigned) override
-  { return false; }
-
-private:
-  l4_uint64_t const _ucode_revision;
-}; // Microcode_revision
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.cc
deleted file mode 100644
index 1bc27e32..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2023-2024 genua GmbH, 85551 Kirchheim, Germany
- * All rights reserved. Alle Rechte vorbehalten.
- */
-/*
- * Copyright (C) 2025 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "openbsd_bootparams.h"
-#include "acpi.h"
-
-namespace Vmm::Openbsd {
-
-void Boot_params::dump()
-{
-  info().printf("OpenBSD Boot Parameters: =============================== \n");
-  info().printf("  howto: 0x%x\n", _params.howto);
-  info().printf("  apiversion: 0x%x\n", _params.apiversion);
-  info().printf("  ac: %d\n", _params.ac);
-  info().printf("  av: 0x%x\n", _params.av);
-  info().printf("  bootdev: 0x%x\n", _params.bootdev);
-  info().printf("  end: 0x%x\n", _params.end);
-}
-
-void Boot_params::add_to_memmap(Bios_memmap **map, size_t const num,
-                                l4_uint32_t type, l4_uint64_t addr,
-                                l4_uint64_t size)
-{
-  assert(num > 0); // we expect to allocate something and not free everything
-
-  *map = static_cast(realloc(*map, num * sizeof(Bios_memmap)));
-  if (*map == nullptr)
-    L4Re::throw_error(-L4_ENOMEM, "Failed to setup memmap!");
-
-  // Fill allocated map entry
-  Bios_memmap &entry = (*map)[num - 1];
-  entry.addr = static_cast(addr);
-  entry.size = size;
-  entry.type = type;
-
-  std::string typestr;
-  switch (type)
-    {
-    case Bios_map_free: typestr = "Adding free";     break;
-    case Bios_map_res:  typestr = "Adding reserved"; break;
-    case Bios_map_acpi: typestr = "Adding ACPI";     break;
-    case Bios_map_nvs:  typestr = "Adding ACPI NVS"; break;
-    default:            typestr = "Adding unknown";  break;
-    }
-
-  trace().printf("%s memory to map: addr=0x%llx size=0x%llx\n", typestr.c_str(),
-                 addr, size);
-}
-
-void Boot_params::setup_memmap(Vm_ram *ram)
-{
-  Bios_memmap *bios_memmap = nullptr;
-  size_t num = 0;
-
-  // Loop over all regions and add them to guest RAM
-  ram->foreach_region([&bios_memmap, &num, this](Vmm::Ram_ds const &r) mutable {
-    if (r.writable())
-      {
-        if (r.vm_start().get() < Iom_end
-            && (r.vm_start().get() + r.size()) > Iom_end)
-          {
-            // Split conventional and extended memory
-            add_to_memmap(&bios_memmap, ++num, Bios_map_free,
-                          r.vm_start().get(), Iom_end - r.vm_start().get());
-            add_to_memmap(&bios_memmap, ++num, Bios_map_free, Iom_end,
-                          r.size() - Iom_end + r.vm_start().get());
-          }
-        else
-          {
-            add_to_memmap(&bios_memmap, ++num, Bios_map_free,
-                          r.vm_start().get(), r.size());
-          }
-      }
-    else
-      {
-        add_to_memmap(&bios_memmap, ++num, Bios_map_res, r.vm_start().get(),
-                      r.size());
-      }
-  });
-
-  auto facs = Acpi::Facs_storage::get()->mem_region();
-  add_to_memmap(&bios_memmap, ++num, Bios_map_acpi, facs.start.get(),
-                facs.end - facs.start + 1);
-
-  add_to_memmap(&bios_memmap, ++num, Bios_map_end, 0, 0);
-
-  if (bios_memmap != nullptr)
-    {
-      info().printf("Add BIOS memmap at %p.\n", bios_memmap);
-      add_bootarg(Bootarg_memmap, num * sizeof(Bios_memmap), bios_memmap);
-      free(bios_memmap);
-    }
-}
-
-void Boot_params::write(Vm_ram *ram)
-{
-  // Prepare BIOS ram regions
-  setup_memmap(ram);
-
-  // Add default uart console
-  Bios_consdev cons;
-  cons.consdev = makedev_obsd(8, 0); // com0
-  cons.conspeed = 115200;
-  cons.consaddr = 0x3f8;
-  add_bootarg(Bootarg_consdev, sizeof(cons), &cons);
-
-  // Finalize and write boot arguments to guest memory
-  add_bootarg(Bootarg_end, 0, nullptr);
-  Vmm::Guest_addr bootargs_pos = Vmm::Guest_addr(Phys_mem_addr * 9);
-  memset(ram->guest2host(bootargs_pos), 0, _bootargs_size);
-  memcpy(ram->guest2host(bootargs_pos), _bootargs, _bootargs_size);
-  _params.av = bootargs_pos.get();
-  _params.ac = _bootargs_size;
-
-  // Write entry stack
-  memset(ram->guest2host(_gp_addr), 0, Phys_mem_addr);
-  memcpy(ram->guest2host(_gp_addr), &_params,
-         sizeof(Openbsd_entry_stack));
-
-  dump();
-}
-
-void Boot_params::add_bootarg(int type, size_t length, void const *data)
-{
-  // Prepare header
-  Boot_args next;
-  next.ba_type = type;
-  next.ba_size = sizeof(next) - sizeof(next.ba_arg) + length;
-
-  // Extend memory allocation
-  size_t newsize = _bootargs_size + next.ba_size;
-  if (newsize > L4_PAGESIZE)
-      L4Re::throw_error(-L4_EINVAL, "OpenBSD bootargs: Too many arguments!");
-
-  _bootargs = realloc(_bootargs, newsize);
-  if (_bootargs == nullptr)
-    L4Re::throw_error(-L4_ENOMEM, "Failed to add bootarg!");
-
-  auto ptr_byte_add = [](void *ptr, l4_uint8_t param) {
-      return static_cast(static_cast(ptr) + param);
-  };
-  // Paste header and content to memory
-  memcpy(ptr_byte_add(_bootargs, _bootargs_size), &next,
-         sizeof(next) - sizeof(next.ba_arg));
-  _bootargs_size = newsize;
-
-  if (data)
-    memcpy(ptr_byte_add(_bootargs, _bootargs_size - length), data, length);
-}
-
-} // namespace Vmm::Openbsd
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.h
deleted file mode 100644
index 88b30199..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/openbsd_bootparams.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2023-2024 genua GmbH, 85551 Kirchheim, Germany
- * All rights reserved. Alle Rechte vorbehalten.
- */
-/*
- * Copyright (C) 2025 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-
-#include "debug.h"
-#include "vm_ram.h"
-
-namespace Vmm::Openbsd {
-
-// See OpenBSD: sys/stand/boot/bootarg.h
-enum
-{
-  Bapiv_ancient  = 0x00000000,      /* MD old i386 bootblocks */
-  Bapiv_vars     = 0x00000001,      /* MD structure w/ add info passed */
-  Bapiv_vector   = 0x00000002,      /* MI vector of MD structures passed */
-  Bapiv_env      = 0x00000004,      /* MI environment vars vector */
-  Bapiv_bmemmap  = 0x00000008,      /* MI memory map passed is in bytes */
-  Bootarg_apiver = (Bapiv_vector|Bapiv_env|Bapiv_bmemmap),
-  Bootarg_end    = -1,
-  Bootarg_memmap = 0,
-};
-
-struct Boot_args
-{
-  l4_int32_t ba_type;
-  l4_int32_t ba_size;
-  l4_int32_t ba_next;
-   //struct _boot_args *ba_next;
-  char ba_arg[1];
-} __attribute__((packed));
-static_assert(sizeof(Boot_args) == 13,
-              "Size of packed Boot_args struct is as expected.");
-
-// See OpenBSD: sys/arch/amd64/include/biosvar.h
-enum
-{
-  Bios_map_end  = 0x00,   /* End of array XXX - special */
-  Bios_map_free = 0x01,   /* Usable memory */
-  Bios_map_res  = 0x02,   /* Reserved memory */
-  Bios_map_acpi = 0x03,   /* ACPI Reclaim memory */
-  Bios_map_nvs  = 0x04,   /* ACPI NVS memory */
-};
-
-struct Bios_memmap
-{
-  l4_uint64_t addr;          /* Beginning of block */
-  l4_uint64_t size;          /* Size of block */
-  l4_uint32_t type;          /* Type of block */
-} __attribute__((packed));
-static_assert(sizeof(Bios_memmap) == 20,
-              "Size of packed Bios_memmap struct is as expected.");
-
-enum
-{
-  Bootarg_consdev = 5,
-};
-
-struct Bios_consdev
-{
-  l4_int32_t  consdev;
-  l4_int32_t  conspeed;
-  l4_uint64_t consaddr;
-  l4_int32_t  consfreq;
-  l4_uint32_t flags;
-  l4_int32_t  reg_width;
-  l4_int32_t  reg_shift;
-} __attribute__((packed));
-static_assert(sizeof(Bios_consdev) == 32,
-              "Size of packed Bios_consdev struct is as expected.");
-
-// See OpenBSD: sys/dev/isa/isareg.h
-enum
-{
-  Iom_end = 0x100000 /* End of I/O Memory "hole" */
-};
-
-// See OpenBSD: sys/sys/types.h
-static constexpr unsigned makedev_obsd(unsigned x, unsigned y)
-{
-  return ((((x) & 0xff) << 8) | ((y) & 0xff) | (((y) & 0xffff00) << 8));
-}
-
-// Memory layout for kernel entry function stack with parameters
-// This assembles the memory stack for the legacy exec call in OpenBSD
-// file sys/arch/amd64/stand/libsa/exec_i386.c
-struct Openbsd_entry_stack
-{
-  l4_uint32_t returnaddr; // unused
-  l4_uint32_t howto; // int
-  l4_uint32_t bootdev; // dev_t
-  l4_uint32_t apiversion; // api version of /boot
-  l4_uint32_t end; // End address of loaded kernel binary
-  l4_uint32_t extmem; // extended memory, unused
-  l4_uint32_t cnvmem; // base memory reported by bios
-  l4_uint32_t ac; // Length of bootargs
-  l4_uint32_t av; // Offset of bootargs
-} __attribute__((packed));
-static_assert(sizeof(Openbsd_entry_stack) == 36,
-              "Size of packed Openbsd_entry_stack struct is as expected.");
-
-class Boot_params
-{
-public:
-  enum
-  {
-    Phys_mem_addr = L4_PAGESIZE, ///< Location of the OpenBSD boot parameters
-  };
-
-  Boot_params(Vmm::Guest_addr addr, l4_addr_t kernel,
-                     l4_addr_t kernel_size)
-  : _gp_addr(addr), _bootargs(nullptr), _bootargs_size(0)
-  {
-    info().printf("Boot_params @ 0x%lx, Kernel @ 0x%lx (size=%ld)\n",
-                  addr.get(), kernel, kernel_size);
-    memset(static_cast(&_params), 0, sizeof(Openbsd_entry_stack));
-    _params.apiversion = Bootarg_apiver;
-
-    _params.cnvmem = Iom_end;
-    _params.ac = 0;
-    _params.av = 0;
-
-    _params.end = kernel + kernel_size;
-  }
-
-  /**
-   * Print OpenBSD Boot Parameters on console
-   */
-  void dump();
-
-  /**
-   * Write boot parameters into guest memory
-   */
-  void write(Vm_ram *ram);
-
-private:
-  /**
-   * Add memory to memory map
-   */
-  void add_to_memmap(Bios_memmap **map, size_t const num, l4_uint32_t type,
-                     l4_uint64_t addr, l4_uint64_t size);
-
-  /**
-   * Prepare memory map for OpenBSD guest
-   */
-  void setup_memmap(Vm_ram *ram);
-
-  /**
-   * Get guest physical address
-   */
-  Vmm::Guest_addr addr() const { return _gp_addr; }
-
-  /**
-   * Add boot argument to linked list.
-   *
-   * \note The data is copied into an internal buffer.
-   *       The caller retains ownership of p.
-   */
-  void add_bootarg(int t, size_t l, void const *p);
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Core, Dbg::Trace, "OpenBSDBoot"); }
-  static Dbg info() { return Dbg(Dbg::Core, Dbg::Info, "OpenBSDBoot"); }
-
-  /**
-   * Guest physical address of first page
-   */
-  Vmm::Guest_addr _gp_addr;
-
-  /**
-   * Entry stack
-   */
-  Openbsd_entry_stack _params;
-
-  /**
-   * Blob containing chained boot argument structs of varying sizes
-   */
-  void *_bootargs;
-
-  /**
-   * Size of `_bootargs` in bytes
-   */
-  size_t _bootargs_size;
-};
-
-} // namespace Vmm::Openbsd
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.cc
deleted file mode 100644
index f51e1bef..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include "irq_dt.h"
-#include "pit.h"
-#include "acpi.h"
-
-namespace Vdev {
-
-Pit_timer::Pit_timer(cxx::Ref_ptr const &ic, unsigned irq)
-: _irq(ic, irq)
-{
-  _channel[0] = cxx::make_unique_ptr(new Channel(this));
-  _channel[1] = cxx::make_unique_ptr(new Channel(this, true));
-  _port61 = make_device(_channel[1].get());
-
-  if (irq != Pit_isa_irq)
-    {
-      info().printf("Timer IRQ configured to be %u, default is %u. Adding an "
-                    "override in MADT.\n", irq, Pit_isa_irq);
-      Acpi::Madt_int_override_storage::get()->add_override(
-        {Pit_isa_irq, irq, 0U});
-    }
-}
-
-void Pit_timer::io_out(unsigned port, Vmm::Mem_access::Width width,
-                       l4_uint32_t value)
-{
-  if (width != Vmm::Mem_access::Width::Wd8)
-    return;
-
-  std::lock_guard lock(_mutex);
-
-  switch (port)
-    {
-    case Mode_command: // PIC_MODE
-      {
-        Control_reg control_reg(value);
-        unsigned channel_select = control_reg.channel();
-        if (channel_select == 1)
-          {
-            warn().printf("set mode for channel 1 unsupported\n");
-            break;
-          }
-        // select either channel 0 or 2
-        channel_select = (channel_select >> 1) & 0x1;
-
-        if (control_reg.is_read_back_cmd())
-          {
-            // read-back command
-            if (control_reg.raw & (1U << 1)) // channel 0
-              {
-                if (control_reg.is_latch_status())
-                  _channel[0]->latch_status();
-                if (control_reg.is_latch_count())
-                  _channel[0]->latch_count();
-              }
-            if (control_reg.raw & (1U << 3)) // channel 2
-              {
-                if (control_reg.is_latch_status())
-                  _channel[2]->latch_status();
-                if (control_reg.is_latch_count())
-                  _channel[2]->latch_count();
-              }
-            trace().printf("Read-back command: 0x%x\n", control_reg.raw);
-            break;
-          }
-
-        _channel[channel_select]->write_status(control_reg.raw
-                                                            & 0x3f);
-        trace().printf("Mode command on channel %d: 0x%x\n", channel_select,
-                       control_reg.raw);
-        break;
-      }
-    case Channel_0_data:
-    case Channel_2_data:
-      {
-        trace().printf("Writing 0x%x for channel %d\n", value, port);
-
-        unsigned channel_select = port2idx(port);
-        _channel[channel_select]->write_count(value & 0xff);
-        break;
-      }
-    default:
-      warn().printf("write to unimplemented channel 1\n");
-      break;
-  }
-}
-
-void Pit_timer::io_in(unsigned port, Vmm::Mem_access::Width width,
-                      l4_uint32_t *value)
-{
-  // *value contains the value returned to the guest. It defaults to -1 from
-  // Guest::handle_io_access(). Therefore we do not set it here in case of an
-  // unhandled path.
-
-  if (width != Vmm::Mem_access::Width::Wd8)
-    return;
-
-  switch (port)
-    {
-    case Mode_command: /* Register is write only. Ignore read. */ break;
-
-    case Channel_0_data:
-    case Channel_2_data:
-      {
-        unsigned ch = port2idx(port);
-        std::lock_guard lock(_mutex);
-        *value = _channel[ch]->read();
-        break;
-      }
-    default:
-      warn().printf("PIT read from unimplemented channel 1\n");
-      break;
-    }
-}
-
-void Pit_timer::Channel::write_count(l4_uint8_t value)
-{
-  _count_latch.reset();
-  _status_latch.reset();
-
-  if (_status.is_mode0())
-    {
-      // when writing a new count, out goes low.
-      set_output(false);
-    }
-
-  switch(_status.access())
-    {
-    case Access_lobyte:
-      _reload = set_low_byte(_reload, value);
-      check_start_counter();
-      break;
-    case Access_hibyte:
-      _reload = set_high_byte(_reload, value);
-      check_start_counter();
-      break;
-    case Access_lohi:
-      write_lo_hi(value);
-      break;
-    default:
-      warn().printf("Invalid access value for write to counter: counter "
-                    "%u, status 0x%x\n",
-                    _is_channel2 ? 2U : 0U, _status.raw);
-      return;
-    }
-  trace().printf("Written new counter value to channel %i: reload: 0x%x, value "
-                 "0x%x\n",
-                 _is_channel2 ? 2U : 0U, _reload, value);
-}
-
-void Pit_timer::Channel::check_start_counter()
-{
-  // Assumption: only called after the full write of a counter
-  if (!_gate)
-    {
-      warn().printf("count written, but gate not high: Counter %i\n",
-                    _is_channel2 ? 2 : 0);
-      return;
-    }
-
-  if (_status.is_mode0() || _status.is_mode4())
-    {
-      if (_running)
-        stop_counter();
-      start_counter();
-    }
-  else if (!_running && (_status.is_mode2() || _status.is_mode3()))
-    start_counter();
-
-  // modes 1, 2, 3, 5 do not change their counter value on a new reload value.
-}
-
-void Pit_timer::Channel::write_status(l4_uint8_t value)
-{
-  if ((value & 0x30U) == 0) // latch command
-    {
-      latch_count();
-      return;
-    }
-
-  // Spec states: When writing to control word, all control logic resets.
-  stop_counter();
-  _count_latch.reset();
-  _status_latch.reset();
-  _read_lo = true;
-  _write_lo = true;
-
-  _status.write(value);
-  // initial output level depends on the mode. Only mode0 is initially low.
-  set_output(!_status.is_mode0());
-
-  trace().printf("New status on channel %i: 0x%x (mode %u)\n",
-                 _is_channel2 ? 2 : 0, _status.raw, _status.opmode().get());
-}
-
-l4_uint8_t Pit_timer::Channel::read()
-{
-  if (_status_latch.valid)
-    {
-      _status_latch.valid = false;
-      return _status_latch.value & 0xff;
-    }
-
-  if (_count_latch.valid)
-    {
-      switch (_status.access())
-        {
-        case Access_lobyte:
-          _count_latch.valid = false;
-          return low_byte(_count_latch.value);
-        case Access_hibyte:
-          _count_latch.valid = false;
-          return high_byte(_count_latch.value);
-        case Access_lohi:
-          if (_count_latch.read_lo == false) // reading 2nd byte invalidates
-            _count_latch.valid = false;
-          return read_lo_hi(&_count_latch.read_lo, _count_latch.value);
-        default:
-          warn().printf("Read latch with invalid access mode: counter "
-                        "%u, status 0x%x\n",
-                        _is_channel2 ? 2U : 0U, _status.raw);
-          return 0;
-        }
-    }
-
-  // read counter
-  l4_uint16_t curr = current();
-  switch (_status.access())
-    {
-    case Access_lobyte: return low_byte(curr);
-    case Access_hibyte: return high_byte(curr);
-    case Access_lohi: return read_lo_hi(&_read_lo, curr);
-    default:
-      warn().printf("Read counter with invalid access mode: counter "
-                    "%u, status 0x%x\n",
-                    _is_channel2 ? 2U : 0U, _status.raw);
-      return 0;
-    }
-}
-
-} // namespace Vdev
-
-#include "device_factory.h"
-#include "guest.h"
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      L4Re::chksys(-L4_EINVAL, "PIT requires a virtual interrupt controller");
-
-    auto dev = Vdev::make_device(it.ic(), it.irq());
-
-    auto *vmm = devs->vmm();
-    auto region = Vmm::Io_region(0x40, 0x43, Vmm::Region_type::Virtual);
-    vmm->add_io_device(region, dev);
-    region = Vmm::Io_region(0x61, 0x61, Vmm::Region_type::Virtual);
-    vmm->add_io_device(region, dev->port61());
-    vmm->register_timer_device(dev);
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"virt-pit", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.h
deleted file mode 100644
index a5d81c96..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/pit.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "device.h"
-#include "io_device.h"
-#include "irq.h"
-#include "timer.h"
-
-namespace Vdev {
-
-/**
- * Limited implementation of 8254 PROGRAMMABLE INTERVAL TIMER.
- *
- * Supports only channel 0 and 2.
- * After a read-back command with status field, the following bits in the
- * status field latched are not supported: OUTPUT [7], NULL COUNT [6].
- *
- * Modes 0-3 are supported for both counters.
- * Mode 4 is only useable on counter 0, for the triggered interrupt.
- * Mode 5 is not supported.
- *
- * Modes 4 and 5 are not supported for counter 2, because the single tick
- * change in output is not emulated and its questionable, if the emulation
- * would be precise enough to allow visiblity to the guest.
- *
- * \note This timer model uses the KIP clock as time base. You need to
- *       configure the Microkernel with CONFIG_SYNC_TSC in order to achieve
- *       sufficient granularity.
- */
-class Pit_timer
-: public Vmm::Io_device,
-  public Vdev::Device,
-  public Vdev::Timer
-{
-  enum : l4_uint8_t { Pit_isa_irq = 0, };
-
-  enum
-  {
-    Channels = 2,
-    Pit_tick_rate = 1193182, // given in Herz
-    Microseconds_per_second = 1000000ULL,
-    Channel_0_data = 0,
-    Channel_2_data = 2,
-    Mode_command = 3,
-
-    Low_byte_mask = 0xff,
-    High_byte_mask = 0xff00,
-    High_byte_shift = 0x8,
-    Latch_cmd_null_mask = 0x3f,
-    Latch_cmd_channel_mask = 0xc0,
-
-    Access_latch = 0,
-    Access_lobyte = 1,
-    Access_hibyte = 2,
-    Access_lohi = 3,
-
-    Mode_terminal_count = 0,
-    Mode_hw_oneshot = 1,
-    Mode_rate_gen = 2,
-    Mode_rate_gen2 = 6,
-    Mode_square_wave = 3,
-    Mode_square_wave2 = 7,
-    Mode_sw_triggerd_strobe = 4,
-    // mode 5 unsupported.
-    Mode_periodic_mask = 0x2,
-  };
-
-  class Channel: public L4::Ipc_svr::Timeout_queue::Timeout
-  {
-    struct Status
-    {
-      Status() : raw(0) {}
-      Status(l4_uint8_t v) : raw(v) {}
-
-      l4_uint8_t raw = 0;
-      CXX_BITFIELD_MEMBER(7, 7, output, raw);
-      CXX_BITFIELD_MEMBER(6, 6, count, raw);
-      CXX_BITFIELD_MEMBER(4, 5, access, raw);
-      CXX_BITFIELD_MEMBER(1, 3, opmode, raw);
-      CXX_BITFIELD_MEMBER(0, 0, bcd, raw);
-
-      enum
-      {
-        // Bits not changed on mode command
-        Retain_mask = output_bfm_t::Mask | count_bfm_t::Mask
-      };
-
-      void write(l4_uint8_t val)
-      { raw = (val & ~Retain_mask) | (raw & Retain_mask); }
-
-      bool is_periodic_mode() const { return opmode() > Mode_hw_oneshot; }
-      bool is_one_shot_mode() const { return !is_periodic_mode(); }
-
-      bool is_mode0() const { return opmode() == Mode_terminal_count; }
-      bool is_mode1() const { return opmode() == Mode_hw_oneshot; }
-      bool is_mode2() const
-      { return opmode() == Mode_rate_gen || opmode() == Mode_rate_gen2; }
-      bool is_mode3() const
-      { return opmode() == Mode_square_wave || opmode() == Mode_square_wave2; }
-      bool is_mode4() const
-      { return opmode() == Mode_sw_triggerd_strobe; }
-    };
-
-    struct Latch
-    {
-      void reset()
-      {
-        value = 0;
-        valid = false;
-        read_lo = true;
-      }
-
-      l4_uint16_t value = 0;
-      bool valid = false;
-      bool read_lo = true;
-    };
-
-  public:
-    Channel(Pit_timer *pit, bool is_channel2 = false)
-    : _is_channel2(is_channel2), _gate(!is_channel2), _pit(pit)
-    {}
-
-    // called in the context of the timer thread, be careful with locking!
-    void expired()
-    {
-      // Unimplemented: mode2, 4, 5: output shall be low for one tick
-      // the single-tick output change in modes 2, 4 & 5 is not emulated
-      if (_status.is_mode3())
-        {
-          // Toggle output
-          set_output(!_status.output());
-        }
-      else
-        set_output(true);
-
-      if(!_is_channel2)
-        _pit->_irq.inject();
-
-      if (_status.is_mode2() || _status.is_mode3())
-        {
-          _reload_kip_clock = l4_kip_clock(l4re_kip());
-          if (_reload)
-            _pit->requeue_timeout(this, next_timeout_us());
-        }
-      else
-        {
-          // The timer in the non periodic modes does not stop, but rolls over
-          // and continues counting until gate is low or counter is set to 0.
-          // Mode0 would not fire an interrupt again, since out is high until
-          // reprogrammed. We don't emulate any of this and just stop.
-          _running = false;
-        }
-    }
-
-    void latch_count()
-    {
-      // ignore all but the first latch command
-      if (_count_latch.valid)
-        return;
-
-      _count_latch.value = current();
-      _count_latch.valid = true;
-      _count_latch.read_lo = true;
-    }
-
-    void latch_status()
-    {
-      if (_status_latch.valid)
-        return;
-
-      _status_latch.value = _status.raw;
-      _status_latch.valid = true;
-    }
-
-    void write_count(l4_uint8_t value);
-    void write_status(l4_uint8_t value);
-    l4_uint8_t read();
-
-    bool gate() const { return _gate; }
-    void gate(bool high)
-    {
-      // We know we are on channel 2, as only channel 2's gate can change.
-      trace().printf("Channel 2: set gate to %i from %i\n", high, _gate);
-
-      if (_status.is_mode0())
-        {
-          if (!high && _gate)
-            stop_counter();
-          else if (high && !_gate)
-            start_counter();
-          // XXX this reloads the counter, but it should stop counting and
-          // continue after gate goes high again, unless output is high;
-        }
-      else if (_status.is_mode1())
-        {
-          if (high && !_gate) // retrigger
-            {
-              stop_counter();
-              start_counter();
-              set_output(false);
-            }
-        }
-      else if (_status.is_mode2() || _status.is_mode3())
-        {
-          // the single-tick output change in modes 2, 4 & 5 is not emulated
-          if (high && !_gate)
-            {
-              start_counter();
-              set_output(true);
-            }
-          else if (!high && _gate)
-            stop_counter();
-        }
-      // modes 4 & 5 not supported
-
-      _gate = high;
-    }
-
-  private:
-    static l4_uint8_t low_byte(l4_uint16_t v)
-    { return v & Low_byte_mask; }
-
-    static l4_uint8_t high_byte(l4_uint16_t v)
-    { return (v >> High_byte_shift) & Low_byte_mask; }
-
-    static l4_uint16_t set_high_byte(l4_uint16_t reg, l4_uint8_t value)
-    { return (reg & Low_byte_mask) | (value << High_byte_shift); }
-
-    static l4_uint16_t set_low_byte(l4_uint16_t reg, l4_uint8_t value)
-    { return (reg & High_byte_mask) | value; }
-
-    static l4_uint8_t read_lo_hi(bool *read_lo, l4_uint16_t count)
-    {
-      l4_uint8_t ret = 0;
-      if (*read_lo)
-          ret = low_byte(count);
-      else
-          ret = high_byte(count);
-
-      *read_lo = !*read_lo;
-      return ret;
-    }
-
-    void write_lo_hi(l4_uint8_t value)
-    {
-      if (_write_lo)
-        _reload = set_low_byte(_reload, value);
-      else
-        {
-          _reload = set_high_byte(_reload, value);
-          check_start_counter();
-        }
-
-      _write_lo = !_write_lo;
-    }
-
-    void set_output(bool out)
-    {
-      _status.output() = out;
-      if (_is_channel2)
-        out ? _pit->_port61->set_out() : _pit->_port61->clear_out();
-    }
-
-    void start_counter()
-    {
-      _reload_kip_clock = l4_kip_clock(l4re_kip());
-      if (_reload)
-        {
-          _pit->enqueue_timeout(this, next_timeout_us());
-          trace().printf("start counter for channel %i (was %s)\n",
-                         _is_channel2 ? 2 : 0,
-                         _running ? "running" : "not running");
-          _running = true;
-        }
-    }
-
-    void stop_counter()
-    {
-      trace().printf("stop counter for channel %i (was %s), reload: 0x%x\n",
-                     _is_channel2 ? 2 : 0, _running ? "running" : "not running",
-                     _reload);
-      _pit->dequeue_timeout(this);
-      _running = false;
-    }
-
-    void check_start_counter();
-
-    /**
-     * Next absolute timeout in microseconds.
-     */
-    inline l4_cpu_time_t next_timeout_us() const
-    {
-      assert(_reload != 0);
-
-      l4_kernel_clock_t kip = l4_kip_clock(l4re_kip());
-      l4_cpu_time_t timeout_us =
-        _reload * Microseconds_per_second / Pit_tick_rate;
-
-      // square wave with half-time toggle
-      if (_status.is_mode3())
-        timeout_us /= 2;
-
-      return kip + timeout_us;
-    }
-
-    /**
-     * Calculate the current value of the counter.
-     *
-     * The counters count down from _reload with the fixed Pit_tick_rate.
-     *
-     * Our Pit model does not update the tick value by itself. Instead it only
-     * calculates the tick count when the guest reads the counter register. We
-     * use the TSC as time basis.
-     *
-     * returns the current counter value of this channel
-     */
-    l4_uint32_t current()
-    {
-      // current time in microseconds
-      l4_kernel_clock_t kip_us = l4_kip_clock(l4re_kip());
-      // time that has gone by since _reload was set
-      l4_cpu_time_t diff_us =  kip_us - _reload_kip_clock;
-      // return current counter value
-      l4_uint32_t ticks = diff_us * Pit_tick_rate / Microseconds_per_second;
-      if (_status.is_mode3())
-        {
-          // in mode3 the counter decrements by two on each tick, since we
-          // compare to _reload, we have to double the number of counter
-          // decrements. expired() is called on each half-period, where
-          // _reload_kip_clock is adapted to track only the time since the last
-          // reload.
-          ticks *= 2;
-        }
-
-      if (ticks >= _reload)
-        return 0;
-      return _reload - ticks;
-    }
-
-    l4_uint16_t _reload = 0U;
-    Status _status;
-    bool _is_channel2;
-    bool _gate; //< 0 = low
-    bool _running = false;
-    Latch _count_latch;
-    Latch _status_latch;
-    Pit_timer *_pit;
-    l4_cpu_time_t _reload_kip_clock = 0ULL;
-    bool _read_lo = true;
-    bool _write_lo = true;
-  };
-
-  struct Port61 : public Vmm::Io_device
-  {
-    Port61(Channel *ch2) : _ch2(ch2) {}
-
-    char const *dev_name() const override
-    { return "PIT port 61"; }
-
-    void io_in(unsigned, Vmm::Mem_access::Width, l4_uint32_t *value) override
-    {
-      *value = val;
-      val &= ~(1 << 5); // destructive read
-    }
-
-    void io_out(unsigned, Vmm::Mem_access::Width, l4_uint32_t value) override
-    {
-      _ch2->gate(value & 0x1);
-      val = value & 0xff;
-    }
-
-    bool channel_2_on() const { return val & 0x1; }
-    void set_out() { val |= (1 << 5); }
-    void clear_out() { val &= ~(1 << 5); }
-
-    l4_uint8_t val = 0;
-    Channel *_ch2;
-  };
-
-  struct Control_reg
-  {
-    Control_reg(l4_uint8_t val) : raw(val) {}
-
-    l4_uint8_t raw;
-    CXX_BITFIELD_MEMBER(6, 7, channel, raw);
-    CXX_BITFIELD_MEMBER(4, 5, access, raw);
-    CXX_BITFIELD_MEMBER(1, 3, opmode, raw);
-    CXX_BITFIELD_MEMBER(0, 0, bcd, raw);
-
-    bool is_read_back_cmd() const { return channel() == 3; }
-    bool is_latch_status() const { return !(raw & (1U << 4)); }
-    bool is_latch_count() const { return !(raw & (1U << 5)); }
-  };
-
-  static constexpr int port2idx(int port) { return port >> 1; }
-
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "PIT"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "PIT"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "PIT"); }
-
-public:
-  Pit_timer(cxx::Ref_ptr const &ic, unsigned irq);
-  virtual ~Pit_timer() = default;
-
-  char const *dev_name() const override
-  { return "PIT"; }
-
-  cxx::Ref_ptr const port61() const { return _port61; }
-
-  void io_out(unsigned port, Vmm::Mem_access::Width width,
-              l4_uint32_t value) override;
-  void io_in(unsigned port, Vmm::Mem_access::Width width,
-             l4_uint32_t *value) override;
-
-private:
-  Vmm::Irq_edge_sink _irq;
-  cxx::unique_ptr _channel[Channels];
-  std::mutex _mutex;
-  cxx::Ref_ptr _port61;
-};
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/pt_walker.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/pt_walker.h
deleted file mode 100644
index 51f0596f..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/pt_walker.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "ds_mmio_mapper.h"
-#include "vcpu_ptr.h"
-#include "vm_ram.h"
-
-namespace Vmm {
-
-class Pt_walker : public cxx::Ref_obj
-{
-public:
-  Pt_walker(cxx::Ref_ptr mmap, unsigned max_phys_addr_bit)
-  : _mmap(mmap),
-    _levels {{Pml4_shift, Pml4_mask},
-             {Pdpt_shift, Pdpt_mask},
-             {Pd_shift, Pd_mask},
-             {Pt_shift, Pt_mask}
-            },
-    _max_phys_addr_mask((1UL << max_phys_addr_bit) - 1)
-  {
-    trace().printf("PT_walker: MAXPHYSADDR bits %i\n", max_phys_addr_bit);
-
-    _phys_addr_mask_4k = _max_phys_addr_mask & ~((1UL << Phys_addr_4k) - 1);
-    _phys_addr_mask_2m = _max_phys_addr_mask & ~((1UL << Phys_addr_2m) - 1);
-    _phys_addr_mask_1g = _max_phys_addr_mask & ~((1UL << Phys_addr_1g) - 1);
-  }
-
-  l4_uint64_t walk(l4_uint64_t cr3, l4_uint64_t virt_addr)
-  {
-    // mask everything besides the 4K-aligned PML4 table address
-    l4_uint64_t *tbl = translate_to_table_base(cr3 & _phys_addr_mask_4k);
-    l4_uint64_t entry = _levels[0].get_entry(tbl, virt_addr);
-
-    if (0)
-      trace().printf("cr3 0x%llx, entry 0x%llx, vaddr 0x%llx\n", cr3, entry,
-                     virt_addr);
-
-    if (!(entry & Present_bit))
-      L4Re::chksys(-L4_EINVAL, "PML4 table is present\n");
-
-    for (unsigned i = 1; i < Pt_levels; ++i)
-      {
-        // PML4Entry: no PAT bit (12) --> mask everything except [M-1:12]
-        tbl = translate_to_table_base(entry & _phys_addr_mask_4k);
-        entry = _levels[i].get_entry(tbl, virt_addr);
-
-        if (!(entry & Present_bit))
-          {
-            char buf[78];
-            snprintf(buf, sizeof(buf),
-                     "Found entry is present. Actual: Entry 0x%llx not "
-                     "present.\n",
-                     entry);
-
-            L4Re::chksys(-L4_EINVAL, buf);
-          }
-
-        // check for PS = 0 in PDPT & PD entries
-        if (i < 3 && entry & Pagesize_bit)
-          {
-            if (i == 1)
-              return add_voffset(translate_to_table_base(entry & _phys_addr_mask_1g),
-                                 virt_addr & G1_offset_mask);
-            if (i == 2)
-              return add_voffset(translate_to_table_base(entry & _phys_addr_mask_2m),
-                                 virt_addr & M2_offset_mask);
-          }
-      }
-
-    return add_voffset(translate_to_table_base(entry & _phys_addr_mask_4k),
-                       virt_addr & K4_offset_mask);
-  }
-
-private:
-  l4_uint64_t *translate_to_table_base(l4_uint64_t addr)
-  {
-    auto *ret = _mmap->guest2host(Guest_addr(addr));
-    if (0)
-      trace().printf("Ram_addr: addr 0x%llx --> %p\n", addr, ret);
-    return ret;
-  }
-
-  l4_uint64_t add_voffset(l4_uint64_t *addr, l4_uint64_t offset)
-  {
-    return reinterpret_cast(addr) + offset;
-  }
-
-  void dump_level(l4_uint64_t *tbl)
-  {
-    trace().printf("Dumping page table %p\n", tbl);
-    for (int i = 0; i < 512; ++i)
-      if (tbl[i] != 0 && tbl[i] & Present_bit)
-        trace().printf("%i :: 0x%16llx\n", i, tbl[i]);
-  }
-
-  void dump_all_valid_entries(l4_uint64_t base_ptr)
-  {
-    trace().printf(" +++++ Dumping all entries ++++ \n");
-    l4_uint64_t *tbl = reinterpret_cast(base_ptr);
-    for (int i = 0; i < 512; ++i)
-      {
-        if (tbl[i] != 0 && tbl[i] & Present_bit)
-          {
-            trace().printf("%i :: 0x%16llx\n", i, tbl[i]);
-            dump_level(translate_to_table_base(tbl[i] & _phys_addr_mask_4k));
-          }
-      }
-    trace().printf(" +++++ Dumped all entries ++++ \n");
-  }
-
-  struct Level
-  {
-    Level(int s, l4_uint64_t m) : shift(s), mask(m) {}
-
-    l4_uint64_t get_entry(l4_uint64_t *tbl, l4_uint64_t vaddr) const
-    {
-      if (0)
-        trace().printf("next level idx: %llu\n", (vaddr & mask) >> shift);
-      return tbl[(vaddr & mask) >> shift];
-    }
-
-    int const shift;
-    l4_uint64_t const mask;
-  };
-
-  static Dbg trace() { return Dbg(Dbg::Mmio, Dbg::Trace, "PTW"); }
-
-  enum
-  {
-    Table_index_size = 9,
-    Table_index_mask = (1UL << Table_index_size) - 1,
-
-    K4_offset_size = 12,
-    K4_offset_mask = (1UL << K4_offset_size) - 1,
-
-    M2_offset_size = 21,
-    M2_offset_mask = (1UL << M2_offset_size) - 1,
-
-    G1_offset_size = 30,
-    G1_offset_mask = (1UL << G1_offset_size) - 1,
-
-    Pt_shift = 12,
-    Pt_mask = Table_index_mask << Pt_shift,
-
-    Pd_shift = 21,
-    Pd_mask = Table_index_mask << Pd_shift,
-
-    Pdpt_shift = 30,
-    Pdpt_mask = Table_index_mask << Pdpt_shift,
-
-    Pml4_shift = 39,
-    Pml4_mask = Table_index_mask << Pml4_shift,
-
-    Present_bit = 1UL,
-    RW_bit = 2UL,
-    US_bit = 4UL,
-    Pagesize_bit = 1UL << 7,
-
-    Phys_addr_4k = 12,
-    Phys_addr_2m = 21,
-    Phys_addr_1g = 30,
-
-    XD_bit_shift = 63,
-    XD_bit = 1UL << XD_bit_shift,
-
-    Pt_levels = 4,
-  };
-
-  cxx::Ref_ptr _mmap;
-  Level const _levels[Pt_levels];
-  l4_uint64_t _phys_addr_mask_4k;
-  l4_uint64_t _phys_addr_mask_2m;
-  l4_uint64_t _phys_addr_mask_1g;
-  l4_uint64_t _max_phys_addr_mask;
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_acpi.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_acpi.cc
deleted file mode 100644
index 2c1c174f..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_acpi.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *            Jan Klötzke 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "acpi.h"
-#include "device/qemu_fw_cfg.h"
-
-namespace {
-
-using namespace Acpi;
-
-/**
- * Provide tables via the Qemu_fw_cfg to the guest firmware.
- *
- * The details of the interface are documented in the Qemu sources in
- * hw/acpi/bios-linker-loader.c. It is actively used by firmwares such as
- * Tianocore, so it can be considered stable.
- *
- * Because the final address of the tables is not known here, a more flexible
- * interface is used. The guest firmware is instructed by the
- * "etc/table-loader" commands file how to install the tables correctly. It
- * holds the commands to allocate space for the tables, patch the pointers
- * between the different tables and how to compute the checksums.
- */
-class Acpi_tables : public Tables
-{
-  enum
-  {
-    Tables_reservation = 8192,
-    Loader_commands_reservation = 512,
-  };
-
-  enum
-  {
-    // Commands
-    Qemu_loader_allocate = 1,
-    Qemu_loader_add_pointer = 2,
-    Qemu_loader_add_checksum = 3,
-
-    Qemu_loader_zone_high = 1,
-    Qemu_loader_zone_fseg = 2,
-
-    Qemu_loader_file_name_size = Qemu_fw_cfg::File_name_size,
-  };
-
-  struct Qemu_loader_entry
-  {
-    l4_uint32_t type;
-    union
-    {
-      struct Allocate
-      {
-        char file_name[Qemu_loader_file_name_size];
-        l4_uint32_t alignment;
-        l4_uint8_t zone;
-      } allocate;
-      struct Add_pointer
-      {
-        char dst_file_name[Qemu_loader_file_name_size];
-        char src_file_name[Qemu_loader_file_name_size];
-        l4_uint32_t dst_pointer_offset;
-        l4_uint8_t dst_pointer_size;
-      } add_pointer;
-      struct Add_checksum
-      {
-        char file_name[Qemu_loader_file_name_size];
-        l4_uint32_t checksum_offset;
-        l4_uint32_t start;
-        l4_uint32_t size;
-      } add_checksum;
-
-      l4_uint8_t pad[124];
-    } cmd;
-  };
-
-  static_assert(sizeof(Qemu_loader_entry) == 128,
-                "Invalid size of Qemu_loader_entry");
-
-public:
-  static char const constexpr *Rsdp_file_name = "etc/acpi/rsdp";
-  static char const constexpr *Tables_file_name = "etc/acpi/tables";
-  static char const constexpr *Loader_commands_file_name = "etc/table-loader";
-  static char const constexpr *System_states_file_name = "etc/system-states";
-
-  Acpi_tables(Vdev::Device_lookup *devs)
-  : _system_states_file(6)
-  {
-    info.printf("Initialize Qemu IF ACPI tables.\n");
-    _tables.resize(Tables_reservation);
-    _loader_cmds.reserve(Loader_commands_reservation);
-
-    cmd_add_alloc(Tables_file_name, 64 /* FACS requirement */, false);
-    Writer table_wr(reinterpret_cast(_tables.data()), _tables.size());
-    write_all_tables(table_wr, devs);
-    _tables.resize(table_wr.pos());
-    resolve_table_refs_and_checksums(Tables_file_name, table_wr, table_wr);
-
-    cmd_add_alloc(Rsdp_file_name, 16, true /* EBDA area */);
-    _rsdp.resize(Rsdp_size);
-    Writer rdsp_wr(reinterpret_cast(_rsdp.data()), _rsdp.size());
-    write_rsdp(rdsp_wr);
-    resolve_table_refs_and_checksums(Rsdp_file_name, rdsp_wr, table_wr);
-
-    // This is a qemu <-> EFI Interface. It is "documented" in
-    // edk2/Ovmf/Library/QemuFwCfgS3Lib/QemuFwCfgS3PeiDxe.c
-    // QemuFwCfgS3Enabled()
-    // We only implement the bit needed for EFI to signal S3 support.
-    _system_states_file[3] = (1 << 7); // S3 supported
-  }
-
-  std::vector const &rsdp() const
-  { return _rsdp; };
-  std::vector const &tables() const
-  { return _tables; }
-  std::string const & loader_cmds() const
-  { return _loader_cmds; }
-  std::vector const &system_states_file() const
-  { return _system_states_file; }
-
-private:
-  void resolve_table_refs_and_checksums(char const *fn, Writer &wr,
-                                        Writer &table_wr)
-  {
-    for (Writer::Table_ref const &ref : wr.table_refs())
-      {
-        if (ref.size == 4)
-          *wr.as_ptr(ref.offset) = table_wr.table_offset(ref.table);
-        else if (ref.size == 8) // XSDT
-          *wr.as_ptr(ref.offset) = table_wr.table_offset(ref.table);
-        else
-          L4Re::throw_error(-L4_EINVAL, "Unsupported table offset size.");
-        cmd_add_pointer(fn, ref.offset, ref.size, Tables_file_name);
-      }
-
-    for (Writer::Checksum const &checksum : wr.checksums())
-      cmd_add_checksum(fn, checksum.offset, checksum.len, checksum.field_off);
-  }
-
-  void cmd_add_checksum(char const *fn, l4_size_t start, l4_size_t size,
-                        l4_size_t checksum)
-  {
-    Qemu_loader_entry e;
-    std::memset(&e, 0, sizeof(e));
-
-    e.type = Qemu_loader_add_checksum;
-    std::strncpy(e.cmd.add_checksum.file_name, fn,
-                 sizeof(e.cmd.add_checksum.file_name) - 1U);
-    e.cmd.add_checksum.checksum_offset = checksum;
-    e.cmd.add_checksum.start = start;
-    e.cmd.add_checksum.size = size;
-
-    _loader_cmds.append((char*)&e, sizeof(e));
-  }
-
-  /**
-   * Add the pointer value to `src_fn` in the file `dst_fn` at offset
-   * `dst_off`. The patched pointer size is `dst_size`.
-   */
-  void cmd_add_pointer(char const *dst_fn, l4_size_t dst_off, l4_size_t dst_size,
-                       char const *src_fn)
-  {
-    Qemu_loader_entry e;
-    std::memset(&e, 0, sizeof(e));
-
-    e.type = Qemu_loader_add_pointer;
-    std::strncpy(e.cmd.add_pointer.dst_file_name, dst_fn,
-                 sizeof(e.cmd.add_pointer.dst_file_name) - 1U);
-    std::strncpy(e.cmd.add_pointer.src_file_name, src_fn,
-                 sizeof(e.cmd.add_pointer.src_file_name) - 1U);
-    e.cmd.add_pointer.dst_pointer_offset = dst_off;
-    e.cmd.add_pointer.dst_pointer_size = dst_size;
-
-    _loader_cmds.append((char*)&e, sizeof(e));
-  }
-
-  void cmd_add_alloc(char const *fn, l4_size_t align, bool fseg_zone)
-  {
-    Qemu_loader_entry e;
-    std::memset(&e, 0, sizeof(e));
-
-    e.type = Qemu_loader_allocate;
-    std::strncpy(e.cmd.allocate.file_name, fn,
-                 sizeof(e.cmd.allocate.file_name) - 1U);
-    e.cmd.allocate.alignment = align;
-    e.cmd.allocate.zone = fseg_zone ? Qemu_loader_zone_fseg
-                                    : Qemu_loader_zone_high;
-
-    _loader_cmds.append((char*)&e, sizeof(e));
-  }
-
-  std::vector _rsdp;
-  std::vector _tables;
-  std::vector _system_states_file;
-  std::string _loader_cmds;
-};
-
-struct Qemu_fw_cfg_tables : public Qemu_fw_cfg::Provider
-{
-  void init_late(Vdev::Device_lookup *devs) override
-  {
-    Acpi_tables tables(devs);
-    Qemu_fw_cfg::put_file(Acpi_tables::Rsdp_file_name, tables.rsdp());
-    Qemu_fw_cfg::put_file(Acpi_tables::Tables_file_name, tables.tables());
-    Qemu_fw_cfg::put_file(Acpi_tables::Loader_commands_file_name, tables.loader_cmds());
-    Qemu_fw_cfg::put_file(Acpi_tables::System_states_file_name,
-                          tables.system_states_file());
-  }
-};
-
-static Qemu_fw_cfg_tables f;
-
-}; // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_boot.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_boot.cc
deleted file mode 100644
index e92597f4..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/qemu_fw_cfg_boot.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *            Jan Klötzke 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "cpu_dev_array.h"
-#include "guest.h"
-#include "device/qemu_fw_cfg.h"
-
-#include 
-#include 
-
-namespace {
-
-/**
- * Device to forward boot data over the qemu fw configuration interface.
- *
- * The qemu_fw_cfg node must have l4vmm,kernel, l4vmm,ramdisk and l4vmm,cmdline
- * as additional properties. Their value can be an empty string.
- *
- * \code{.dtb}
- *   qemu_fw_if {
- *       compatible = "l4vmm,qemu-fw-cfg";
- *       reg = <0x1 0x510 0x0c>;
- *       l4vmm,kernel = "linux";
- *       l4vmm,ramdisk = "ramdisk";
- *       l4vmm,cmdline = "console=TTY0";
- *   };
- * \endcode
- */
-class Qemu_fw_cfg_boot : public Qemu_fw_cfg::Provider
-{
-  enum Fw_cfg_item_selectors
-  {
-    // Item selectors defined by Qemu
-    Fw_cfg_cpu_count          = 0x05,
-    Fw_cfg_kernel_size        = 0x08,
-    Fw_cfg_initrd_size        = 0x0b,
-    Fw_cfg_boot_menu          = 0x0e,
-    Fw_cfg_kernel_data        = 0x11,
-    Fw_cfg_commandline_size   = 0x14,
-    Fw_cfg_commandline_data   = 0x15,
-    Fw_cfg_kernel_setup_size  = 0x17,
-    Fw_cfg_kernel_setup_data  = 0x18,
-    Fw_cfg_initrd_data        = 0x12,
-
-    // Added by KK
-    Fw_cfg_uvmm_dt            = 0xe0,
-  };
-
-  void init(Vdev::Device_lookup * /*devs*/, Vdev::Dt_node const &node) override
-  {
-    _kernel = node.get_prop("l4vmm,kernel", nullptr);
-    _ramdisk = node.get_prop("l4vmm,ramdisk", nullptr);
-    _cmdline = node.get_prop("l4vmm,cmdline", nullptr);
-    auto c = node.stringlist_count("l4vmm,items");
-    if (c > 0)
-      for (int i = 0; i < c; i++)
-        {
-          std::string arg(node.stringlist_get("l4vmm,items", i, NULL));
-          // Find the comma delimiter between "[name=]name" and "string=string".
-          // The name component should not be empty.
-          auto pos = arg.find(',');
-          if (pos == std::string::npos || pos == 0)
-            L4Re::throw_error(-L4_EINVAL, "fw_cfg items needs name");
-
-          // Strip the optional "name=" label from the name component.
-          auto name = arg.substr(0, pos);
-          if (name.substr(0, 5) == std::string("name="))
-            name = name.substr(5);
-
-          // Strip the required "string=" label from the string component.
-          auto string = arg.substr(pos);
-          if (string.substr(0, 8) != std::string(",string="))
-            L4Re::throw_error(-L4_EINVAL, "fw_cfg items only support strings");
-
-          string = string.substr(8);
-          _items.push_back(std::make_tuple(name, string));
-        }
-  };
-
-  void init_late(Vdev::Device_lookup *devs) override
-  {
-    if (!_kernel.empty())
-      {
-        _kernel_binary = cxx::make_unique(_kernel.c_str());
-
-        if (!_kernel_binary->is_valid())
-          L4Re::throw_error(-L4_EINVAL, "Kernel dataspace not found.");
-
-        if (_kernel_binary->is_elf_binary())
-          L4Re::throw_error(-L4_EINVAL, "Elf files not supported for qemu fw.");
-
-        l4_uint8_t num_setup_sects =
-          *((char *)_kernel_binary->get_data() + Vmm::Bp_setup_sects);
-
-        add_kernel(_kernel_binary->ds(), (num_setup_sects + 1) * 512);
-      }
-
-    if (!_ramdisk.empty())
-      {
-        _ramdisk_ds = L4Re::Util::Unique_cap(
-          L4Re::chkcap(L4Re::Util::Env_ns().query(
-                         _ramdisk.c_str()),
-                       "Ramdisk dataspace not found"));
-        add_initrd(_ramdisk_ds.get());
-      }
-
-    if (!_cmdline.empty())
-        add_cmdline(_cmdline.c_str());
-
-    for (auto const &s: _items)
-      Qemu_fw_cfg::put_file(std::get<0>(s).c_str(), std::get<1>(s));
-
-    add_dt_addr(devs->vmm()->dt_addr());
-
-    add_cpu_count(devs->cpus()->max_cpuid() + 1);
-  };
-
-  void add_cmdline(char const *cmdline)
-  {
-    size_t len = strlen(cmdline) + 1U;
-    Qemu_fw_cfg::set_item_u32le(Fw_cfg_commandline_size, len);
-    Qemu_fw_cfg::set_item(Fw_cfg_commandline_data, cmdline, len);
-  }
-
-  void add_kernel(L4::Cap kernel, l4_size_t setup_size)
-  {
-    size_t image_size = kernel->size();
-    Qemu_fw_cfg::set_item_u32le(Fw_cfg_kernel_setup_size, setup_size);
-    Qemu_fw_cfg::set_item(Fw_cfg_kernel_setup_data, kernel, 0, setup_size);
-    Qemu_fw_cfg::set_item_u32le(Fw_cfg_kernel_size, image_size - setup_size);
-    Qemu_fw_cfg::set_item(Fw_cfg_kernel_data, kernel, setup_size);
-  }
-
-  void add_initrd(L4::Cap initrd)
-  {
-    Qemu_fw_cfg::set_item_u32le(Fw_cfg_initrd_size, initrd->size());
-    Qemu_fw_cfg::set_item(Fw_cfg_initrd_data, initrd);
-  }
-
-  void add_dt_addr(l4_addr_t addr)
-  {
-    l4_uint64_t addr_le = htole64(addr);
-    Qemu_fw_cfg::set_item(Fw_cfg_uvmm_dt, &addr_le, sizeof(addr_le));
-  }
-
-  void add_cpu_count(l4_uint16_t num)
-  {
-    Qemu_fw_cfg::set_item_u16le(Fw_cfg_cpu_count, num);
-  }
-
-  std::string _kernel;
-  cxx::unique_ptr _kernel_binary;
-  std::string _ramdisk;
-  L4Re::Util::Unique_cap _ramdisk_ds;
-  std::string _cmdline;
-  std::vector> _items;
-};
-
-static Qemu_fw_cfg_boot f;
-
-}; // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/rtc.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/rtc.cc
deleted file mode 100644
index aed4f8e1..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/rtc.cc
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (C) 2017-2019, 2021-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * Minimal viable implementation of a CMOS RTC (Motorola MC146818A).
- *
- * We do not support setting new time values.
- * We only support 24h mode (it is hard-wired).
- * We do not support the century byte.
- *
- * On amd64 linux will assume the rtc is in BCD mode even when the format is
- * set to binary.
- *
- * Example device tree entry:
- *
- * \code{.dtb}
- *   rtc {
- *       compatible = "virt-rtc";
- *       reg = <0x0 0x0 0x0 0x0>;
- *       interrupt-parent = <&IOAPIC>;
- *       interrupts = <8>;
- *   };
- * \endcode
- *
- * Optionally this emulation can use wallclock-time from an external source.
- */
-#include "device_factory.h"
-#include "guest.h"
-#include "device.h"
-#include "io_device.h"
-#include "timer.h"
-#include "irq_dt.h"
-
-#include "../device/rtc-hub.h"
-
-#include 
-#include 
-
-#include 
-
-namespace Vdev {
-
-class Rtc :
-  public Vdev::Timer,
-  public Vdev::Pm_device,
-  public Vmm::Io_device,
-  public Vdev::Device
-{
-  enum Register : unsigned
-  {
-    Seconds = 0,
-    Seconds_alarm,
-    Minutes,
-    Minutes_alarm,
-    Hours,
-    Hours_alarm,
-    Weekday,
-    Day_of_month,
-    Month,
-    Year,
-    Status_a = 0xa,
-    Status_b = 0xb,
-    Reg_c = 0xc,
-    Reg_d = 0xd,
-
-    // Cmos_ram
-    Ram_start = 0xe,
-    Ram_end = 0x80,
-    Ram_size = Ram_end - Ram_start,
-  };
-
-  enum Status_reg_c : l4_uint8_t
-  {
-    Interrupt_request           = 0x80,
-    Periodic_interrupt_flag     = 0x40,
-    Alarm_interrupt_flag        = 0x20,
-    Update_ended_interrupt_flag = 0x10,
-  };
-
-  enum Status_reg_d : l4_uint8_t
-  {
-    Valid_ram_and_time = 0x80,
-  };
-
-  struct Status_reg_a
-  {
-    l4_uint8_t reg = 0;
-    CXX_BITFIELD_MEMBER(0, 3, rate_selection_bits, reg);
-    CXX_BITFIELD_MEMBER(4, 6, divider_selection_bits, reg);
-    CXX_BITFIELD_MEMBER(7, 7, update_in_progress, reg);
-  };
-
-  struct Status_reg_b
-  {
-    l4_uint8_t reg = 0x2; // mode_24 == 1
-    CXX_BITFIELD_MEMBER(0, 0, daylight_savings_enable, reg);
-    CXX_BITFIELD_MEMBER(1, 1, mode_24, reg);
-    CXX_BITFIELD_MEMBER(2, 2, data_mode, reg);
-    CXX_BITFIELD_MEMBER(3, 3, square_wave_enable, reg);
-    CXX_BITFIELD_MEMBER(4, 4, update_ended_interrupt_enable, reg);
-    CXX_BITFIELD_MEMBER(5, 5, alarm_interrupt_enable, reg);
-    CXX_BITFIELD_MEMBER(6, 6, periodic_interrupt_enable, reg);
-    CXX_BITFIELD_MEMBER(7, 7, set, reg);
-  };
-
-  struct Alarm : public L4::Ipc_svr::Timeout_queue::Timeout
-  {
-    Rtc *_rtc;
-
-    Alarm(Rtc *rtc) : _rtc(rtc) {}
-
-    /**
-     * Handle expired alarms.
-     *
-     * This function is called from the timer thread.
-     */
-    void expired() override
-    {
-      if (!_rtc->_reg_b.alarm_interrupt_enable())
-        {
-          trace().printf("Alarm interrupt but alarm interrupt enable not set.\n");
-          return;
-        }
-      {
-        std::lock_guard lock(_rtc->_mutex);
-
-        _rtc->_reg_c |= Alarm_interrupt_flag;
-        _rtc->_reg_c |= Interrupt_request;
-      }
-      trace().printf("RTC Irq due to alarm expired()\n");
-      _rtc->_sink.inject();
-    }
-  }; // struct Alarm
-
-  // allow Alarm access to private Rtc members.
-  friend struct Alarm;
-
-  // convert internal binary representation to BCD if needed
-  l4_uint32_t convert_to_guest(int val)
-  {
-    if (_reg_b.data_mode())
-      return val;
-
-    // See https://de.wikipedia.org/wiki/BCD-Code
-    return (val % 10) + ((val / 10) << 4);
-  }
-
-  // convert what the guest gave us to internal binary representation
-  l4_uint8_t convert_from_guest(l4_uint8_t val)
-  {
-    if (_reg_b.data_mode()) // we are using binary mode
-      return val;
-
-    return (val & 0xf) + ((val & 0xf0) >> 4) * 10;
-  }
-
-  void handle_set_time(Status_reg_b r)
-  {
-    // As long as the set() bit is set, the guest assumes that the clock does
-    // not update. We redirect all writes to shadow registers, and those
-    // never get updated.
-
-    // The strategy for updating is:
-    // - the guest sets the set bit to 1
-    // - the guest writes the new time value to the shadow registers
-    // - the guest sets the set bit to 0
-    // - once the set bit is 0, Uvmm retrieves the new time value from the
-    //   shadow registers and updates its internal time.
-    bool old_set_bit = _reg_b.set().get();
-    bool new_set_bit = r.set().get();
-
-    if (!old_set_bit || new_set_bit)
-      return;
-
-    time_t seconds = ns_to_s(L4rtc_hub::ns_since_epoch());
-    struct tm *t = gmtime(&seconds);
-    if (!t)
-      {
-        warn().printf("Could not determine time.\n");
-        return;
-      }
-    t->tm_sec = _shadow_registers[Seconds];
-    t->tm_min = _shadow_registers[Minutes];
-    t->tm_hour = _shadow_registers[Hours];
-    t->tm_mday = _shadow_registers[Day_of_month];
-    t->tm_mon = _shadow_registers[Month] - 1;   // months start at '1'
-    int centuries_since_1900 = t->tm_year / 100 * 100;
-    // tm_year is defined as 'years since 1900'. The RTC spec instead
-    // specifies the Year register as 'year in the range of 0-99'. Here we use
-    // the previous centuries since 1900 (as calculated from "seconds since
-    // epoch") and add them to the register value from the guest.
-    t->tm_year = _shadow_registers[Year] + centuries_since_1900;
-
-    _seconds = timegm(t);
-    L4rtc_hub::set_ns_since_epoch(s_to_ns(_seconds));
-
-    trace().printf("set time to %04d-%02d-%02d %02d:%02d:%02d\n",
-                   t->tm_year + 1900, t->tm_mon, t->tm_mday,
-                   t->tm_hour, t->tm_min, t->tm_sec);
-  }
-
-  // return next timeout in seconds
-  time_t calc_next_alarm()
-  {
-    time_t seconds = ns_to_s(L4rtc_hub::ns_since_epoch());
-    struct tm *alarm_time = gmtime(&seconds);
-    struct tm *current_time = gmtime(&seconds);
-
-    if (dont_care_not_set(_shadow_registers[Seconds_alarm]))
-      alarm_time->tm_sec = _shadow_registers[Seconds_alarm];
-    else
-      {
-        trace().printf("wildcard seconds\n");
-        alarm_time->tm_sec += 1;
-        alarm_time->tm_sec %= 60;
-      }
-    if (dont_care_not_set(_shadow_registers[Minutes_alarm]))
-      alarm_time->tm_min = _shadow_registers[Minutes_alarm];
-    else
-      {
-        trace().printf("wildcard minutes\n");
-        alarm_time->tm_min += 1;
-        alarm_time->tm_min %= 60;
-      }
-    if (dont_care_not_set(_shadow_registers[Hours_alarm]))
-      alarm_time->tm_hour = _shadow_registers[Hours_alarm];
-    else
-      {
-        trace().printf("wildcard hours\n");
-        alarm_time->tm_hour += 1;
-        alarm_time->tm_hour %= 24;
-      }
-
-    time_t alarm_seconds = mktime(alarm_time);
-    if (alarm_seconds == -1)
-      trace().printf("error calculating alarm_seconds. Errno %i\n", errno);
-
-    time_t current_seconds = mktime(current_time);
-    if (current_seconds == -1)
-      trace().printf("error calculating current_seconds. Errno %i\n", errno);
-
-    if (alarm_seconds < current_seconds)
-      {
-        trace().printf("Alarm is in the past\n");
-        return ~0L;
-      }
-
-    trace().printf("alarm_seconds=%ld current_seconds=%ld\n", alarm_seconds,
-                   current_seconds);
-    return (alarm_seconds - current_seconds);
-  }
-
-  void handle_alarms(Status_reg_b r)
-  {
-    time_t next_alarm = 0;
-    {
-      std::lock_guard lock(_mutex);
-
-      if (r.update_ended_interrupt_enable())
-        {
-          trace().printf("Guest wants an update interrupt.\n");
-          l4_cpu_time_t current_second = ns_to_s(l4_tsc_to_ns(l4_rdtsc()));
-          _reg_c |= Update_ended_interrupt_flag;
-          if (current_second > _previous_alarm_second)
-            {
-              _previous_alarm_second = current_second;
-              _reg_c |= Interrupt_request;
-              _sink.inject();
-              trace().printf("Update ended interrupt injected immediately\n");
-            }
-        }
-
-      if (!r.alarm_interrupt_enable())
-        return;
-
-      trace().printf("Guest wants an alarm interrupt.\n");
-
-      next_alarm = calc_next_alarm();
-      if (next_alarm == ~0L) // do not fire for alarms of the past
-        return;
-
-      if (next_alarm == 0) // guest wants an alarm right now
-        {
-          l4_cpu_time_t current_second = ns_to_s(l4_tsc_to_ns(l4_rdtsc()));
-          _reg_c |= Alarm_interrupt_flag;
-          _reg_c |= Interrupt_request;
-          if (current_second > _previous_alarm_second)
-            {
-              _previous_alarm_second = current_second;
-              _sink.inject();
-              trace().printf("Alarm interrupt injected immediately\n");
-            }
-          return;
-        }
-    }
-
-    // guest alarm is at least 1 second in the future
-    // must not hold the lock when doing the IPC to the timer thread
-    enqueue_timeout(&_alarm_timeout,
-                    l4_kip_clock(l4re_kip()) + s_to_us(next_alarm));
-    trace().printf("enqueue timeout %ld\n", next_alarm);
-  }
-
-  void handle_write(l4_uint32_t value)
-  {
-    trace().printf("write reg %d value = 0x%x\n", _reg_sel, value & 0xff);
-    l4_uint8_t val = value & 0xff;
-    switch (_reg_sel)
-      {
-      case Status_a:
-        {
-          std::lock_guard lock(_mutex);
-          trace().printf("reg a: 0x%x\n", val);
-          _reg_a.reg = val;
-        }
-        break;
-      case Status_b:
-        {
-          trace().printf("reg b: 0x%x\n", val);
-          Status_reg_b r;
-          r.reg = val;
-
-          // set_time() and alarms() handle the lock themselves
-          handle_set_time(r);
-          handle_alarms(r);
-          {
-            std::lock_guard lock(_mutex);
-            _reg_b.reg = val;
-            // we only allow mode_24
-            _reg_b.mode_24().set(1);
-          }
-        }
-        break;
-      case Reg_c:
-      case Reg_d:
-        warn().printf("Write to RO reg (%u)\n", _reg_sel);
-        break;
-      default:
-        if (_reg_sel <= Year)
-          _shadow_registers[_reg_sel] = convert_from_guest(val);
-        else if (_reg_sel >= Ram_start && _reg_sel < Ram_end)
-          cmos_write(_reg_sel - Ram_start, val);
-        else
-          warn().printf("Register write not handled (%u)\n", _reg_sel);
-        break;
-      }
-  }
-
-  l4_uint32_t handle_read()
-  {
-    trace().printf("read reg %d\n", _reg_sel);
-    // these registers need to always work
-    switch (_reg_sel)
-      {
-      case Status_a:
-        {
-          std::lock_guard lock(_mutex);
-          return _reg_a.reg;
-        }
-      case Status_b:
-        {
-          std::lock_guard lock(_mutex);
-          return _reg_b.reg;
-        }
-      case Reg_c:
-        {
-          std::lock_guard lock(_mutex);
-          unsigned ret = _reg_c;
-          trace().printf("reg c: %x\n", _reg_c);
-          // reading clears the status bits
-          _reg_c = 0;
-          _sink.ack();
-          return ret;
-        }
-      case Reg_d:
-        return Valid_ram_and_time;
-      }
-
-    // only update time if guest does not currently try to set a new time
-    if (!_reg_b.set())
-      _seconds = ns_to_s(L4rtc_hub::ns_since_epoch());
-
-    struct tm *t = gmtime(&_seconds);
-    if (!t)
-      {
-        warn().printf("Could not determine time.\n");
-        return 0;
-      }
-
-    l4_uint32_t ret = 0;
-    switch (_reg_sel)
-      {
-      case Seconds:
-        ret = convert_to_guest(t->tm_sec);
-        break;
-      case Seconds_alarm:
-        ret = convert_to_guest(_shadow_registers[Seconds_alarm]);
-        break;
-      case Minutes:
-        ret = convert_to_guest(t->tm_min);
-        break;
-      case Minutes_alarm:
-        ret = convert_to_guest(_shadow_registers[Minutes_alarm]);
-        break;
-      case Hours:
-        ret = convert_to_guest(t->tm_hour);
-        break;
-      case Hours_alarm:
-        ret = convert_to_guest(_shadow_registers[Hours_alarm]);
-        break;
-      case Weekday:
-        ret = convert_to_guest(t->tm_wday);
-        break;
-      case Day_of_month:
-        ret = convert_to_guest(t->tm_mday);
-        break;
-      case Month:
-        ret = convert_to_guest(t->tm_mon + 1); // gmtime returns months counting from zero
-        break;
-      case Year:
-        ret = convert_to_guest(t->tm_year % 100);
-        break;
-      default:
-        if (Ram_start > _reg_sel || _reg_sel > Ram_end)
-          warn().printf("Unknown register read (%d)\n", _reg_sel);
-        else
-          ret = cmos_read(_reg_sel - Ram_start);
-        break;
-      }
-    return ret;
-  }
-
-public:
- Rtc(cxx::Ref_ptr const &ic, int irq)
- : Pm_device(), _alarm_timeout(this), _sink(ic, irq), _previous_alarm_second(0)
-  {
-    info().printf("Hello from RTC. Irq=%d\n", irq);
-#if !defined(CONFIG_UVMM_EXTERNAL_RTC) and !(CONFIG_RELEASE_MODE)
-    warn().printf(
-      "No external clock source. Rtc time will not represent wallclock time.\n"
-      "Set CONFIG_UVMM_EXTERNAL_RTC = y if you have an external clock "
-      "source.\n");
-#endif
-
-    _seconds = ns_to_s(L4rtc_hub::ns_since_epoch());
-  }
-
-  void pm_suspend() override
-  {}
-
-  void pm_resume() override
-  {
-    // tell the guest that the machine has resumed from suspend
-    // use the PS/2 shutdown status byte as expected by firmware
-    cmos_write(1, 0xfe);
-  }
-
-  char const *dev_name() const override
-  { return "RTC"; }
-
-  /* IO write from the guest to device */
-  void io_out(unsigned port, Vmm::Mem_access::Width, l4_uint32_t value) override
-  {
-    switch (port)
-      {
-      case 0:
-        _reg_sel = value & 0x7f;
-        break;
-      case 1:
-        handle_write(value);
-        break;
-      default:
-        warn().printf("Unknown port written (%u).\n", port);
-        break;
-      }
-  }
-
-  /* IO read from the guest */
-  void io_in(unsigned port, Vmm::Mem_access::Width, l4_uint32_t *value) override
-  {
-    switch (port)
-      {
-      case 0:
-        *value = _reg_sel;
-        break;
-      case 1:
-        *value = handle_read();
-        break;
-      default:
-        warn().printf("Unknown port read (%u).\n", port);
-        break;
-      };
-  }
-
-  ~Rtc()
-  {
-    dequeue_timeout(&_alarm_timeout);
-  }
-
-private:
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "RTC"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "RTC"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "RTC"); }
-
-  static l4_uint64_t ns_to_s(l4_uint64_t ns) { return ns / 1'000'000'000; }
-  static l4_uint64_t s_to_us(l4_uint64_t s) { return s * 1'000'000; }
-  static l4_uint64_t s_to_ns(l4_uint64_t s) { return s * 1'000'000'000; }
-
-  /// Alarm registers with the highest bits set (0xC0 - 0xFF) are don't care.
-  static bool dont_care_not_set(l4_uint8_t reg)
-  {
-    enum { Dont_care_bits = 0xC0 };
-    return (reg & Dont_care_bits) != Dont_care_bits;
-  }
-
-  void cmos_write(l4_uint8_t regsel, l4_uint16_t value)
-  {
-    assert(regsel < Ram_size);
-    trace().printf("cmos write(%u, 0x%x)\n", regsel, value);
-    _cmos[regsel] = value;
-  }
-
-  l4_uint16_t cmos_read(l4_uint8_t regsel)
-  {
-    assert(regsel < Ram_size);
-    trace().printf("cmos read(%u) = 0x%x\n", regsel, _cmos[regsel]);
-    return _cmos[regsel];
-  }
-
-  l4_uint8_t _reg_sel = 0;
-  Status_reg_a _reg_a;
-  Status_reg_b _reg_b;
-  l4_uint8_t _reg_c = 0;
-  l4_uint8_t _reg_d = 0;
-
-  // These are written to by the guest.
-  l4_uint8_t _shadow_registers[Year + 1];
-
-  // protect members from concurrent access
-  std::mutex _mutex;
-
-  Alarm _alarm_timeout; //< Object handling timeout expired events.
-
-  // seconds since epoch as determined by external clock source
-  time_t _seconds;
-
-  l4_uint16_t _cmos[Ram_size];
-
-  Vmm::Irq_sink _sink;
-  l4_cpu_time_t _previous_alarm_second;
-}; // class Rtc
-
-} // namespace Vdev
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "RTC"); }
-
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      {
-        info().printf("RTC requires a virtual interrupt controller.");
-        return nullptr;
-      }
-
-    if (it.irq() != 8)
-      {
-        info().printf("DT Node must specify IRQ 8 for the RTC.");
-        return nullptr;
-      }
-
-    auto dev = Vdev::make_device(it.ic(), it.irq());
-
-    auto region = Vmm::Io_region(0x70, 0x71, Vmm::Region_type::Virtual);
-    devs->vmm()->add_io_device(region, dev);
-    devs->vmm()->register_timer_device(dev);
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"virt-rtc", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.cc
deleted file mode 100644
index 89c31df7..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2017, 2019, 2021-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Benjamin Lamowski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "vcpu_ptr.h"
-#include "vm_state_svm.h"
-#include "vm_state_vmx.h"
-#include "pt_walker.h"
-#include "mad.h"
-#include "guest.h"
-
-namespace Vmm {
-
-void
-Vcpu_ptr::create_state(Vm_state::Type type)
-{
-  if (type == Vm_state::Type::Vmx)
-    {
-      auto state = reinterpret_cast(_s);
-      auto vmx = new Vmx_state(state);
-      _s->user_data[Reg_vmm_type] = reinterpret_cast(vmx);
-    }
-  else if (type == Vm_state::Type::Svm)
-    _s->user_data[Reg_vmm_type] =
-      reinterpret_cast(new Svm_state(extended_state()));
-
-  else
-    throw L4::Runtime_error(-L4_ENOSYS, "Unsupported HW virtualization type.");
-}
-
-Vm_state::Type
-Vcpu_ptr::determine_vmm_type()
-{
-  if (!l4util_cpu_has_cpuid())
-    throw L4::Runtime_error(-L4_ENOSYS,
-                            "Platform does not support CPUID. Aborting!\n");
-
-  l4_umword_t ax, bx, cx, dx;
-  l4util_cpu_cpuid(0, &ax, &bx, &cx, &dx);
-
-  if (bx == 0x756e6547 && cx == 0x6c65746e && dx == 0x49656e69)
-    return Vm_state::Type::Vmx;
-  // AuthenticAMD
-  else if (bx == 0x68747541 && cx == 0x444d4163 && dx == 0x69746e65)
-    {
-      warn().printf(">>> CAUTION: Support for AMD SVM is experimental, use at your own risk! <<<\n");
-
-      // Check if the SVM features we need are present.
-      l4util_cpu_cpuid(0x8000000a, &ax, &bx, &cx, &dx);
-
-      if (!(dx & Svm_state::Cpuid_svm_feature_nrips))
-        L4Re::throw_error(-L4_ENOSYS,
-                          "SVM does not support next_rip save. Aborting!\n");
-
-      // It should be safe to assume that the decode assists feature is
-      // present, since all modern AMD CPUs (starting with Bulldozer)
-      // implement it. However, QEMU or rather KVM-based nested virtualization
-      // does not report that the feature is present (see svm_set_cpu_caps()),
-      // but still provides decode assist information, e.g. for writes to CR0.
-      if (!(dx & Svm_state::Cpuid_svm_feature_decode_assists))
-        warn().printf("Platform does not support SVM decode assists (misreported on QEMU).\n");
-
-      return Vm_state::Type::Svm;
-    }
-  else
-    throw L4::Runtime_error(-L4_ENOSYS, "Platform not supported. Aborting!\n");
-}
-
-/// Mem_access::Kind::Other symbolises failure to decode.
-Mem_access
-Vcpu_ptr::decode_mmio() const
-{
-  Mem_access m;
-  m.access = Mem_access::Other;
-
-  auto *vms = vm_state();
-  l4_uint64_t opcode;
-  try
-    {
-      // overwrite the virtual IP with the physical OP code
-      opcode = get_pt_walker()->walk(vms->cr3(), vms->ip());
-    }
-  catch (L4::Runtime_error &e)
-    {
-      warn().printf("[%3u] Could not determine opcode for MMIO access. Page table "
-                    "walking failed for IP 0x%lx and reports: %s\n",
-                    get_vcpu_id(), vms->ip(),
-                    e.extra_str() ? e.extra_str() : "");
-      return m;
-    }
-
-  // amd64: vcpu regs == exc_regs
-  l4_exc_regs_t *reg = reinterpret_cast(&_s->r);
-  using namespace L4mad;
-  unsigned char *inst_buf = reinterpret_cast(opcode);
-  // TODO: Limit inst_buf_len to size until the next non-contiguous page
-  //       boundary if it is < Decoder::Max_instruction_len.
-  unsigned inst_buf_len = Decoder::Max_instruction_len;
-  Decoder decoder(reg, vms->ip(), inst_buf, inst_buf_len);
-
-  bool decoded = false;
-  Op op;
-  Desc tgt, src;
-  switch (decoder.decode(&op, &tgt, &src))
-    {
-    case Decoder::Result::Success: decoded = true; break;
-    case Decoder::Result::Unsupported: break;
-    case Decoder::Result::Invalid:
-      // TODO: If size of instruction buffer is < Decoder::Max_instruction_len,
-      //       because instruction lies on a non-contiguous page boundary,
-      //       use a temporary buffer to hold instruction bytes from both pages
-      //       and retry decoding from that.
-      break;
-    }
-
-  if (!decoded)
-    {
-      unsigned char const *text = reinterpret_cast(opcode);
-      Dbg().printf("[%3u] Decoding failed at 0x%lx: %02x %02x %02x %02x %02x "
-                   "%02x %02x <%02x> %02x %02x %02x %02x %02x %02x %02x %02x\n",
-                   get_vcpu_id(), vms->ip(),
-                   text[-7], text[-6], text[-5], text[-4], text[-3],
-                   text[-2], text[-1], text[0], text[1], text[2], text[3],
-                   text[4], text[5], text[6], text[7], text[8]);
-      return m;
-    }
-
-  if (0)
-    decoder.print_insn_info(op, tgt, src);
-
-  m.width = op.access_width;
-
-  if (tgt.dtype != L4mad::Desc_reg && tgt.dtype != L4mad::Desc_mem)
-    {
-      Dbg().printf("[%3u] tgt type invalid %i\n", get_vcpu_id(), tgt.dtype);
-      return m;
-    }
-
-  // SRC and TGT.val contain the register number of the MMIO access. In case of
-  // write, this register can be decoded to the value.
-  // In case of read I need to save the register number and write to this
-  // register in writeback_mmio.
-
-  // translate to Mem_access;
-  if (op.atype == L4mad::Read)
-    {
-      m.access = Mem_access::Load;
-      _s->user_data[Reg_mmio_read] = tgt.val >> tgt.shift;
-    }
-  else if (op.atype == L4mad::Write)
-    {
-      m.access = Mem_access::Store;
-      switch (src.dtype)
-        {
-        case L4mad::Desc_reg:
-          // src.val is the register number in MAD order; which is inverse to
-          // register order in l4_vcpu_regs_t.
-          m.value = *decode_reg_ptr(src.val) >> src.shift;
-          break;
-        case L4mad::Desc_imm:
-          m.value = src.val;
-          break;
-        default:
-          assert(false);
-          m.value = 0;
-          break;
-        }
-    }
-  // else unknown; Other already set.
-
-  return m;
-}
-
-l4_umword_t *
-Vcpu_ptr::decode_reg_ptr(int value) const
-{
-  return reinterpret_cast(&_s->r)
-         + (L4mad::Num_registers - 1 - value);
-}
-
-void
-Vcpu_ptr::reset(bool protected_mode)
-{
-  vm_state()->init_state();
-
-  // If Uvmm is to boot a Linux kernel directly, it will do so in protected
-  // mode as is required in Linux' boot protocol. Otherwise the Boot and
-  // Application Processors are expected to come up in Real Mode.
-  if (protected_mode)
-    vm_state()->setup_linux_protected_mode(_s->r.ip, _s->r.sp);
-  else
-    vm_state()->setup_real_mode(_s->r.ip);
-
-  Guest::get_instance()->run_vm(*this);
-}
-
-void
-Vcpu_ptr::hot_reset()
-{
-  // assumption: reset while we already went through the normal reset once.
-  // intention: Do not call Guest::run_vm() again.
-
-  vm_state()->init_state();
-  vm_state()->setup_real_mode(_s->r.ip);
-}
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.h
deleted file mode 100644
index 09965bcc..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vcpu_ptr.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "generic_vcpu_ptr.h"
-#include "mem_access.h"
-#include "vm_state.h"
-
-namespace Vmm {
-
-class Pt_walker;
-
-class Vcpu_ptr : public Generic_vcpu_ptr
-{
-public:
-  enum User_data_regs_arch
-  {
-    Reg_vmm_type = Reg_arch_base,
-    Reg_mmio_read,
-    // 
-    Reg_must_be_last_before_ucode,
-    Reg_ucode_rev = 6, // must be in sync with Fiasco
-  };
-  static_assert(Reg_ucode_rev >= Reg_must_be_last_before_ucode,
-                "Last user data register is reserved for microcode revision.");
-
-  explicit Vcpu_ptr(l4_vcpu_state_t *s) : Generic_vcpu_ptr(s)
-  {
-    if (s)
-      create_state(determine_vmm_type());
-  }
-
-  bool pf_write() const
-  {
-    return vm_state()->pf_write();
-  }
-
-  void thread_attach()
-  {
-    control_ext(L4::Cap());
-  }
-
-  Vm_state *vm_state() const
-  { return reinterpret_cast(_s->user_data[Reg_vmm_type]);}
-
-  Mem_access decode_mmio() const;
-
-  void writeback_mmio(Mem_access const m)
-  {
-    // used to write read value back to register it is read to.
-    *decode_reg_ptr(_s->user_data[Reg_mmio_read]) = m.value;
-  }
-
-  void reset(bool protected_mode);
-  void hot_reset();
-
-  l4_umword_t ucode_revision() const
-  { return _s->user_data[Reg_ucode_rev]; }
-
-  template 
-  void dump_regs_t(l4_addr_t vm_ip, ERR_DBG out) const
-  {
-    unsigned vcpu_id = get_vcpu_id();
-    l4_vcpu_regs_t *regs = &_s->r;
-
-    out.printf("[%3u] RAX 0x%lx\nRBX 0x%lx\nRCX 0x%lx\nRDX 0x%lx\nRSI 0x%lx\n"
-               "RDI 0x%lx\nRSP 0x%lx\nRBP 0x%lx\nR8 0x%lx\nR9 0x%lx\n"
-               "R10 0x%lx\nR11 0x%lx\nR12 0x%lx\nR13 0x%lx\nR14 0x%lx\n"
-               "R15 0x%lx\nRIP 0x%lx\nvCPU RIP 0x%lx\n",
-               vcpu_id, regs->ax, regs->bx, regs->cx, regs->dx, regs->si,
-               regs->di, regs->sp, regs->bp, regs->r8, regs->r9, regs->r10,
-               regs->r11, regs->r12, regs->r13, regs->r14, regs->r15, vm_ip,
-               regs->ip);
-  }
-
-private:
-  void *extended_state() const
-  {
-    return (void *)(((char *)_s) + L4_VCPU_OFFSET_EXT_STATE);
-  }
-
-  Vm_state::Type determine_vmm_type();
-  void create_state(Vm_state::Type type);
-  l4_umword_t *decode_reg_ptr(int value) const;
-
-}; // class Vcpu_ptr
-
-} // namespace Vmm
-
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.cc
deleted file mode 100644
index 283a6181..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.cc
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include "debug.h"
-#include "virt_lapic.h"
-#include "mad.h"
-#include "guest.h"
-
-
-namespace Gic {
-
-using L4Re::chkcap;
-using L4Re::chksys;
-
-Virt_lapic::Virt_lapic(unsigned id, cxx::Ref_ptr cpu)
-: _lapic_irq(chkcap(L4Re::Util::make_unique_cap(),
-                    "Allocate local APIC notification IRQ.")),
-  _lapic_x2_id(id),
-  _lapic_version(Lapic_version),
-  _x2apic_enabled(false),
-  _nmi_pending(false),
-  _cpu(cpu),
-  _registry(cpu->vcpu().get_ipc_registry())
-{
-  trace().printf("Virt_lapic ctor; ID 0x%x\n", id);
-
-  chksys(L4Re::Env::env()->factory()->create(_lapic_irq.get()),
-         "Create APIC IRQ.");
-
-  // Set reset values of the LAPIC registers
-  memset(&_regs, 0, sizeof(_regs));
-  _regs.dfr = -1U;
-  _regs.cmci = _regs.therm = _regs.perf = 0x00010000;
-  _regs.lint[0] = _regs.lint[1] = _regs.err = 0x00010000;
-  _regs.svr = 0x000000ff;
-
-  _apic_timer = Vdev::make_device(this);
-}
-
-void
-Virt_lapic::set(unsigned irq)
-{
-  irq_trigger(irq);
-}
-
-void
-Virt_lapic::set(Vdev::Msix::Data_register_format data)
-{
-  //  assumption 1: delivery_mode lowest prio already arbitrated
-  //  assumption 2: only called if this APIC is destination
-  using namespace Vdev::Msix;
-
-  switch (data.delivery_mode())
-    {
-    case Dm_fixed: [[fallthrough]];
-    case Dm_lowest_prio:
-      irq_trigger(data.vector(), data.trigger_mode(), true);
-      break;
-    case Dm_smi: info().printf("SMI dropped at LAPIC 0x%x\n", id()); break;
-    case Dm_nmi: nmi(); break;
-    case Dm_init: init_ipi(); break;
-    case Dm_startup: startup_ipi(data); break;
-    case Dm_extint: irq_trigger(data.vector(), false, false); break;
-    default:
-      info().printf("LAPIC 0x%x drops unknown MSI. Delivery mode 0x%x, Vector "
-                    "0x%x, data: 0x%llx\n",
-                    id(), data.delivery_mode().get(), data.vector().get(),
-                    data.raw);
-      break;
-    };
-}
-
-void
-Virt_lapic::init_ipi()
-{
-  // Only sleeping vCPUs must be rescheduled
-  if (_cpu->get_cpu_state() == Vmm::Cpu_dev::Sleeping)
-    _cpu->reschedule();
-
-  _cpu->send_init_ipi();
-  _sipi_cnt = 0;
-}
-
-void
-Virt_lapic::startup_ipi(Vdev::Msix::Data_register_format data)
-{
-  // only act on the first SIPI
-  if (_sipi_cnt++)
-    return;
-
-  enum : l4_uint32_t
-  {
-    Icr_startup_page_shift = 12
-  };
-
-  l4_addr_t start_eip = data.vector() << Icr_startup_page_shift;
-  start_cpu(start_eip);
-  _cpu->send_sipi();
-}
-
-void
-Virt_lapic::start_cpu(l4_addr_t entry)
-{
-  Vmm::Vcpu_ptr vcpu = _cpu->vcpu();
-  vcpu->r.sp = 0;
-  vcpu->r.ip = entry; // r.ip used to communicate entry to Vcpu_ptr.reset()
-
-  info().printf("Starting CPU %u on EIP 0x%lx\n", _lapic_x2_id, entry);
-}
-
-void
-Virt_lapic::bind_irq_src_handler(unsigned irq, Irq_src_handler *handler)
-{
-  assert (irq < 256); // sources array length
-  if(handler && _sources[irq] && handler != _sources[irq])
-    info().printf("[LAPIC 0x%x] IRQ src handler for IRQ %u already set to "
-                  "%p, new %p\n",
-                  _lapic_x2_id, irq, _sources[irq], handler);
-
-  _sources[irq] = handler;
-}
-
-Irq_src_handler *
-Virt_lapic::get_irq_src_handler(unsigned irq) const
-{
-  assert (irq < 256); // sources array length
-  return _sources[irq];
-}
-
-int
-Virt_lapic::dt_get_interrupt(fdt32_t const *, int, int *) const
-{ return 1; }
-
-void
-Virt_lapic::nmi()
-{
-  _nmi_pending.store(true, std::memory_order_release);
-  _lapic_irq->trigger();
-}
-
-/**
- * Enqueue an interrupt and trigger an IPC in the vCPU.
- *
- * \param irq  Interrupt to inject.
- */
-void
-Virt_lapic::irq_trigger(l4_uint32_t irq, bool level, bool irr)
-{
-  bool trigger = true;
-  {
-    std::lock_guard lock(_int_mutex);
-
-    if (irr)
-      {
-        // don't trigger lapic_irq, if the IRR has this IRQ already queued.
-        trigger = !_regs.irr.set_irq(irq);
-        if (level)
-          _regs.tmr.set_irq(irq);
-        else
-          _regs.tmr.clear_irq(irq);
-      }
-    else
-      {
-        // don't trigger lapic_irq again, if an IRQ is already queued.
-        trigger = _non_irr_irqs.empty();
-        _non_irr_irqs.push(irq);
-      }
-  }
-
-  if (trigger)
-    _lapic_irq->trigger();
-}
-
-bool
-Virt_lapic::next_pending_nmi()
-{
-  bool expected = true;
-  return _nmi_pending.compare_exchange_strong(expected, false,
-                                              std::memory_order_acquire,
-                                              std::memory_order_relaxed);
-}
-
-bool
-Virt_lapic::is_nmi_pending()
-{ return _nmi_pending.load(std::memory_order_relaxed); }
-
-int
-Virt_lapic::next_pending_irq()
-{
-  std::lock_guard lock(_int_mutex);
-
-  if (!_non_irr_irqs.empty())
-    {
-      unsigned irq = _non_irr_irqs.front();
-      _non_irr_irqs.pop();
-      return irq;
-    }
-
-  auto highest_irr = _regs.irr.get_highest_irq();
-  if (highest_irr >= 0)
-    {
-      auto highest_isr = _regs.isr.get_highest_irq();
-      if (highest_irr > highest_isr)
-        {
-          _regs.isr.set_irq(highest_irr);
-          _regs.irr.clear_irq(highest_irr);
-          return highest_irr;
-        }
-    }
-  return -1;
-}
-
-bool
-Virt_lapic::is_irq_pending()
-{
-  std::lock_guard lock(_int_mutex);
-  return !_non_irr_irqs.empty() || _regs.irr.has_irq();
-}
-
-bool
-Virt_lapic::read_msr(unsigned msr, l4_uint64_t *value) const
-{
-  switch (msr)
-    {
-    case Msr_ia32_apic_base: // APIC base, Vol. 3A 10.4.4
-      *value = Lapic_access_handler::Mmio_addr | Apic_base_enabled;
-
-      if (_lapic_x2_id == 0)
-        *value |= Apic_base_bsp_processor;
-
-      if (_x2apic_enabled)
-        *value |= Apic_base_x2_enabled;
-      break;
-    case Msr_ia32_tsc_deadline:
-      *value = _apic_timer->read_tsc_deadline_msr();
-      break;
-    case Msr_ia32_x2apic_apicid:
-      *value = _x2apic_enabled
-                 ? _lapic_x2_id
-                 : (_lapic_x2_id << Xapic_mode_local_apic_id_shift);
-      break;
-    case Msr_ia32_x2apic_version: *value = _lapic_version; break;
-    case Msr_ia32_x2apic_tpr: *value = _regs.tpr; break;
-    case Msr_ia32_x2apic_ppr: *value = _regs.ppr; break;
-    case Msr_ia32_x2apic_ldr: *value = _regs.ldr; break;
-    case Mmio_apic_destination_format_register:
-      // not existent in x2apic mode
-      if (!_x2apic_enabled)
-        *value = _regs.dfr;
-      break;
-    case Msr_ia32_x2apic_sivr: *value = _regs.svr; break;
-    case 0x810:
-    case 0x811:
-    case 0x812:
-    case 0x813:
-    case 0x814:
-    case 0x815:
-    case 0x816:
-    case Msr_ia32_x2apic_isr7:
-      *value = _regs.isr.get_reg(msr - 0x810);
-      break;
-    case 0x818:
-    case 0x819:
-    case 0x81a:
-    case 0x81b:
-    case 0x81c:
-    case 0x81d:
-    case 0x81e:
-    case Msr_ia32_x2apic_tmr7:
-      *value = _regs.tmr.get_reg(msr - 0x818);
-      break;
-    case 0x820:
-    case 0x821:
-    case 0x822:
-    case 0x823:
-    case 0x824:
-    case 0x825:
-    case 0x826:
-    case Msr_ia32_x2apic_irr7:
-      *value = _regs.irr.get_reg(msr - 0x820);
-      break;
-    case Msr_ia32_x2apic_esr: *value = _regs.esr; break;
-    case Msr_ia32_x2apic_lvt_cmci: *value = _regs.cmci; break;
-    // 0x830 handled by Icr_handler
-    case Msr_ia32_x2apic_lvt_timer:
-      *value = _apic_timer->read_lvt_timer_reg();
-      break;
-    case Msr_ia32_x2apic_lvt_thermal: *value = _regs.therm; break;
-    case Msr_ia32_x2apic_lvt_pmi: *value = _regs.perf; break;
-    case Msr_ia32_x2apic_lvt_lint0: *value = _regs.lint[0]; break;
-    case Msr_ia32_x2apic_lvt_lint1: *value = _regs.lint[1]; break;
-    case Msr_ia32_x2apic_lvt_error: *value = _regs.err; break;
-    case Msr_ia32_x2apic_init_count:
-      *value = _apic_timer->read_tmr_init();
-      break;
-    case Msr_ia32_x2apic_cur_count: *value = _apic_timer->read_tmr_cur(); break;
-    case Msr_ia32_x2apic_div_conf:
-      *value = _apic_timer->read_divide_configuration_reg();
-      break;
-
-    default: return false;
-    }
-
-  if (0)
-    Dbg().printf("ReadAPIC MSR 0x%x. Result: 0x%x\n", (unsigned)msr,
-                 (unsigned)*value);
-  return true;
-}
-
-bool
-Virt_lapic::write_msr(unsigned msr, l4_uint64_t value)
-{
-  switch(msr)
-    {
-    case Msr_ia32_apic_base:
-      _x2apic_enabled = value & Apic_base_x2_enabled;
-      if (_x2apic_enabled)
-        {
-          Dbg().printf("------ x2APIC enabled\n");
-          // from Intel SDM (October 2017)
-          // Logical x2APIC ID = [(x2APIC ID[19:4] « 16) | (1 « x2APIC ID[3:0])]
-          _regs.ldr =
-            (_lapic_x2_id & 0xffff0) << 16 | 1U << (_lapic_x2_id & 0xf);
-        }
-
-      // APIC Base field, Vol. 3A 10.4.4
-      if (!((value >> 12) & (Lapic_access_handler::Mmio_addr >> 12)))
-        // Vol. 3A 10.4.5
-        warn().printf(
-          "Relocating the Local APIC Registers is not supported.\n");
-      break;
-    case Msr_ia32_tsc_deadline:
-      _apic_timer->write_tsc_deadline_msr(value);
-      break;
-    case Msr_ia32_x2apic_version: break; // RO register: ignore write
-    case Msr_ia32_x2apic_tpr: _regs.tpr = value; break;
-    case Msr_ia32_x2apic_ldr:
-      // not writable in x2apic mode
-      if (!_x2apic_enabled)
-        _regs.ldr = value;
-      break;
-    case Mmio_apic_destination_format_register:
-      // not existent in x2apic mode; writes by system software only in
-      // disabled APIC state; which currently isn't supported. => write ignored
-      break;
-    case Msr_ia32_x2apic_sivr:
-      _regs.svr = value; break; // TODO react on APIC SW en/disable
-    case Msr_ia32_x2apic_eoi:
-      {
-        std::lock_guard lock(_int_mutex);
-        int irq_num = _regs.isr.clear_highest_irq();
-        if (irq_num > 0)
-          {
-            Irq_src_handler *hdlr = get_irq_src_handler(irq_num);
-            if (hdlr)
-              hdlr->eoi();
-          }
-      }
-      if (value != 0)
-        {
-          Dbg().printf("WARNING: write to EOI not zero, 0x%llx\n", value);
-        }
-      break;
-    case Msr_ia32_x2apic_esr: _regs.esr = 0; break;
-    case Msr_ia32_x2apic_lvt_cmci: _regs.cmci = value; break;
-    // 0x830 handled by Icr_handler
-    case Msr_ia32_x2apic_lvt_timer:
-      _apic_timer->write_lvt_timer_reg(value);
-      break;
-    case Msr_ia32_x2apic_lvt_thermal: _regs.therm = value; break;
-    case Msr_ia32_x2apic_lvt_pmi: _regs.perf = value; break;
-    case Msr_ia32_x2apic_lvt_lint0: _regs.lint[0] = value; break;
-    case Msr_ia32_x2apic_lvt_lint1: _regs.lint[1] = value; break;
-    case Msr_ia32_x2apic_lvt_error: _regs.err = value; break;
-    case Msr_ia32_x2apic_init_count:
-      _apic_timer->write_tmr_init(value);
-      break;
-    case Msr_ia32_x2apic_div_conf:
-      _apic_timer->write_divide_configuration_reg(value);
-      break;
-    case Msr_ia32_x2apic_self_ipi:
-      if (_x2apic_enabled)
-        irq_trigger(value & 0xff);
-      else
-        // if X2APIC is not enabled, writing IA32_SELF_IPI incurs a #GP
-        return false;
-      break;
-
-    default: return false;
-    }
-
-  if (0 && msr != 0x80b)
-    Dbg().printf("WARNING: APIC write to 0x%x: 0x%llx\n", msr, value);
-
-  return true;
-}
-
-} // namepace Gic
-
-#include "device_factory.h"
-#include "guest.h"
-
-namespace {
-
-  struct F : Vdev::Factory
-  {
-    cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                      Vdev::Dt_node const &) override
-    {
-      auto apics = devs->vmm()->apic_array();
-      auto msix_ctrl = Vdev::make_device(apics);
-      devs->vmm()->icr_handler()->register_msix_ctrl(msix_ctrl);
-      return msix_ctrl;
-    }
-  };
-
-  static F f;
-  static Vdev::Device_type e = {"intel,msi-controller", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.h
deleted file mode 100644
index fd6843ab..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/virt_lapic.h
+++ /dev/null
@@ -1,1207 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Benjamin Lamowski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "irq.h"
-#include "timer.h"
-#include "mem_access.h"
-#include "vm_state.h"
-#include "pt_walker.h"
-#include "ram_ds.h"
-#include "msi_controller.h"
-#include "msr_device.h"
-#include "mem_types.h"
-#include "mmio_device.h"
-#include "msix.h"
-#include "msi_arch.h"
-#include "monitor/lapic_cmd_handler.h"
-#include "cpu_dev.h"
-#include "cpu_dev_array.h"
-
-using L4Re::Rm;
-
-namespace Gic {
-
-class Apic_timer;
-
-class Virt_lapic : public Ic
-{
-  // These MSRs correspond to the xAPIC MMIO registers.
-  // see reg2msr for reference
-  enum : l4_uint32_t
-  {
-    Msr_ia32_apic_base = 0x1b,
-    Msr_ia32_tsc_deadline = 0x6e0,
-    Msr_ia32_x2apic_apicid = 0x802,
-    Msr_ia32_x2apic_version = 0x803,
-    Msr_ia32_x2apic_tpr = 0x808,
-    Msr_ia32_x2apic_ppr = 0x80a,
-    Msr_ia32_x2apic_eoi = 0x80b,
-    Msr_ia32_x2apic_ldr = 0x80d,
-    // This is only available in xapic mode
-    // It is documented in the intel manual chapter 10.6.2.2
-    Mmio_apic_destination_format_register = 0x80e,
-    Msr_ia32_x2apic_sivr = 0x80f,
-    Msr_ia32_x2apic_isr7 = 0x817,
-    Msr_ia32_x2apic_tmr7 = 0x81f,
-    Msr_ia32_x2apic_irr7 = 0x827,
-    Msr_ia32_x2apic_esr = 0x828,
-    Msr_ia32_x2apic_lvt_cmci = 0x82f,
-    Msr_ia32_x2apic_lvt_timer = 0x832,
-    Msr_ia32_x2apic_lvt_thermal = 0x833,
-    Msr_ia32_x2apic_lvt_pmi = 0x834,
-    Msr_ia32_x2apic_lvt_lint0 = 0x835,
-    Msr_ia32_x2apic_lvt_lint1 = 0x836,
-    Msr_ia32_x2apic_lvt_error = 0x837,
-    Msr_ia32_x2apic_init_count = 0x838,
-    Msr_ia32_x2apic_cur_count = 0x839,
-    Msr_ia32_x2apic_div_conf = 0x83e,
-    Msr_ia32_x2apic_self_ipi = 0x83f,
-  };
-
-  class Irq_register
-  {
-    enum : l4_uint8_t
-    {
-      Reg_no = 256 / sizeof(l4_uint64_t),
-      Reg_bits = sizeof(l4_uint64_t) * 8
-    };
-
-  public:
-    /**
-     * Returns true, if IRQ was set before.
-     */
-    bool set_irq(l4_uint8_t irq)
-    {
-      l4_uint8_t idx = irq / Reg_bits;
-      l4_uint64_t bit = 1ULL << (irq % Reg_bits);
-      bool already_set = _reg.u64[idx] & bit;
-      _reg.u64[idx] |= bit;
-      return already_set;
-    }
-
-    void clear_irq(l4_uint8_t irq)
-    {
-      l4_uint8_t idx = irq / Reg_bits;
-      _reg.u64[idx] &= ~(1ULL << (irq % Reg_bits));
-    }
-
-    int get_highest_irq() const
-    {
-      for (l4_int8_t i = Reg_no - 1; i >= 0; --i)
-        {
-          if (!_reg.u64[i])
-            continue;
-
-          for (l4_int8_t j = Reg_bits - 1; j >= 0; --j)
-            if (_reg.u64[i] & (1ULL << j))
-              return i * Reg_bits + j;
-        }
-      return -1;
-    }
-
-    void clear()
-    {
-      memset(_reg.u64, 0, sizeof(l4_uint64_t) * Reg_no);
-    }
-
-    /// returns the IRQ number of the cleared IRQ. -1 if none found.
-    int clear_highest_irq()
-    {
-      int highest = get_highest_irq();
-      if (highest != -1)
-        clear_irq(highest);
-      return highest;
-    }
-
-    bool has_irq() const
-    {
-      for (auto r: _reg.u64)
-        if (r)
-          return true;
-
-      return false;
-    }
-
-    l4_uint32_t get_reg(l4_uint32_t idx) const
-    {
-      assert(idx < (256 / sizeof(l4_uint32_t)));
-      return _reg.u32[idx];
-    }
-
-  private:
-    union
-    {
-      l4_uint64_t u64[Reg_no];
-      l4_uint32_t u32[Reg_no * 2];
-    } _reg;
-  };
-
-  struct LAPIC_registers
-  {
-    l4_uint32_t tpr;
-    l4_uint32_t ppr;
-    l4_uint32_t ldr; ///< logical destination register
-    l4_uint32_t dfr; ///< destination format register not existent in x2APIC
-    l4_uint32_t svr; ///< Spurious vector register
-    Irq_register isr;
-    Irq_register tmr;
-    Irq_register irr;
-    l4_uint32_t esr;
-    l4_uint32_t cmci;
-    l4_uint32_t therm;
-    l4_uint32_t perf;
-    l4_uint32_t lint[2];
-    l4_uint32_t err;
-    l4_uint32_t tmr_init;
-    l4_uint32_t tmr_cur;
-  };
-
-  enum XAPIC_consts : unsigned
-  {
-    Xapic_mode_local_apic_id_shift = 24,
-    Xapic_mode_logical_apic_id_shift = 24,
-    Xapic_dfr_model_shift = 28,
-    Xapic_dfr_flat_model = 0x0fU,
-    Xapic_dfr_cluster_model = 0x00U,
-
-    Apic_base_bsp_processor = 1UL << 8,
-    Apic_base_x2_enabled = 1UL << 10,
-    Apic_base_enabled = 1U << 11,
-
-    Lapic_version = 0x60014, /// 14 = xAPIC, 6 = max LVT entries - 1
-
-    X2apic_ldr_logical_apic_id_mask = 0xffff,
-    X2apic_ldr_logical_cluster_id_shift = 16,
-  };
-
-public:
-  Virt_lapic(unsigned id, cxx::Ref_ptr cpu);
-
-  void attach_cpu_thread(L4::Cap vthread)
-  {
-    L4Re::chksys(_lapic_irq->bind_thread(vthread, 0),
-                 "Attaching local APIC IRQ to vCPU thread");
-  }
-
-  /**
-   * Clear all APIC irqs. This shall be used when entering INIT state.
-   */
-  void clear_irq_state()
-  {
-    std::lock_guard lock(_int_mutex);
-
-    _regs.irr.clear();
-    _regs.tmr.clear();
-    _regs.isr.clear();
-  }
-
-  // IC interface
-  void clear(unsigned) override {}
-
-  void set(unsigned irq) override;
-  // Overload for MSIs
-  void set(Vdev::Msix::Data_register_format data);
-
-  void bind_irq_src_handler(unsigned irq, Irq_src_handler *handler) override;
-  Irq_src_handler *get_irq_src_handler(unsigned irq) const override;
-
-  int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const override;
-
-  /**
-   * APIC soft Irq to force VCPU to handle IRQs.
-   *
-   * \param irq    Interrupt vector to send to the guest.
-   * \param level  Iff true, the interrupt vector is level triggerd; default:
-   *               edge triggered;
-   * \param irr    Iff true, the interrupt is to be enqueued in the IRR.
-   */
-  void irq_trigger(l4_uint32_t irq, bool level = false, bool irr = true);
-  void nmi();
-
-  // vCPU expected interface
-  bool is_nmi_pending();
-  int next_pending_irq();
-  bool is_irq_pending();
-  bool next_pending_nmi();
-
-  // X2APIC MSR interface
-  bool read_msr(unsigned msr, l4_uint64_t *value) const;
-  bool write_msr(unsigned msr, l4_uint64_t value);
-
-  l4_uint32_t logical_apic_id() const
-  {
-    return _x2apic_enabled ? _regs.ldr
-                           : _regs.ldr >> Xapic_mode_logical_apic_id_shift;
-  }
-
-  /**
-   * Match a destination ID bitmask against this LAPIC's unique logical ID.
-   */
-  bool match_ldr(l4_uint32_t did) const
-  {
-    l4_uint32_t logical_id = logical_apic_id();
-
-    if (_x2apic_enabled)
-      {
-        // x2APIC supports only cluster mode
-        // [31:16] cluster ID, [15:0] Sub-ID-bitmap
-        l4_uint32_t did_cluster = did >> X2apic_ldr_logical_cluster_id_shift;
-        l4_uint32_t lid_cluster =
-          logical_id >> X2apic_ldr_logical_cluster_id_shift;
-        return (did_cluster == lid_cluster)
-               && (logical_id & did & X2apic_ldr_logical_apic_id_mask);
-      }
-    else
-      {
-        switch (_regs.dfr >> Xapic_dfr_model_shift)
-          {
-          case Xapic_dfr_flat_model:
-            // flat address mode: dfr[31:28] = 0b1111;
-            return logical_id & did;
-          case Xapic_dfr_cluster_model:
-            // cluster addressing mode:
-            // DID & logical APIC ID: [7:4]: Cluster, [3:0]: Sub-ID-bitmap
-            return (logical_id & 0xf0) == (did & 0xf0)
-                   && (logical_id & did & 0xf);
-          default:
-            return false;
-          }
-      }
-  }
-
-  l4_uint32_t id() const { return _lapic_x2_id; }
-  l4_uint32_t task_prio_class() const { return _regs.tpr & 0xf0; }
-
-  cxx::Ref_ptr timer()
-  { return _apic_timer; }
-
-  bool x2apic_mode() const { return _x2apic_enabled; }
-
-  Vcpu_obj_registry *registry() const { return _registry; }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "LAPIC"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "LAPIC"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "LAPIC"); }
-
-  /// An incoming INIT IPI will place the CPU in INIT mode.
-  void init_ipi();
-
-  /**
-   * Handle STARTUP IPIs
-   *
-   * Intel specifies that the correct sequence is INIT, STARTUP, STARTUP.
-   * So we make sure to only act on the second STARTUP IPI.
-   */
-  void startup_ipi(Vdev::Msix::Data_register_format data);
-
-  /**
-   * Start an Application Processor.
-   *
-   * \param entry  Real Mode entry address.
-   */
-  void start_cpu(l4_addr_t entry);
-
-  cxx::Ref_ptr _apic_timer;
-  L4Re::Util::Unique_cap _lapic_irq; /// IRQ to notify VCPU
-  l4_uint32_t _lapic_x2_id;
-  unsigned _lapic_version;
-  std::mutex _int_mutex;
-  LAPIC_registers _regs;
-  bool _x2apic_enabled;
-  std::atomic _nmi_pending;
-  Irq_src_handler *_sources[256] = {};
-  std::queue _non_irr_irqs;
-  cxx::Ref_ptr _cpu;
-  Vcpu_obj_registry * const _registry;
-  unsigned _sipi_cnt = 0;
-}; // class Virt_lapic
-
-
-class Lapic_array
-: public Vdev::Device,
-  public Monitor::Lapic_cmd_handler
-{
-public:
-  /**
-   * Process MSI data and destination ID in physical addressing mode.
-   *
-   * \param did   Destination ID as defined in the MSI/-X address.
-   * \param data  MSI/-X data value.
-   *
-   * \return The destination vCPU IPC registry or nullptr.
-   *
-   * \pre MSI addressing format is physical.
-   */
-  Vcpu_obj_registry *physical_mode(l4_uint32_t did,
-                                   Vdev::Msix::Data_register_format data)
-  {
-    if (handle_broadcast(did, data))
-      return nullptr;
-
-    auto lapic = get(did);
-    if (lapic)
-      lapic->set(data);
-    else
-      info().printf("No LAPIC for DID 0x%x with physical addressing. Data "
-                    "0x%llx\n",
-                    did, data.raw);
-
-    return lapic ? lapic->registry() : nullptr;
-  }
-
-  /**
-   * Process MSI data and destination ID in logical addressing mode.
-   *
-   * \param did   Destination ID as defined in the MSI/-X address.
-   * \param data  MSI/-X data value.
-   * \param lp    MSI requests lowest priority arbitration.
-   *
-   * \return The destination vCPU IPC registry or nullptr.
-   *
-   * \pre MSI addressing format is logical.
-   */
-  Vcpu_obj_registry *logical_mode(l4_uint32_t did,
-                                  Vdev::Msix::Data_register_format data,
-                                  bool lowest_prio)
-  {
-    if (lowest_prio)
-      return logical_mode_lp(did, data);
-
-    if (handle_broadcast(did, data))
-      return nullptr;
-
-    Vcpu_obj_registry *reg = nullptr;
-    for (auto &lapic : _lapics)
-      if (lapic && lapic->match_ldr(did))
-        {
-          lapic->set(data);
-          reg = lapic->registry();
-        }
-
-    if (!reg)
-      info().printf("No matching logical DestID: 0x%x, data 0x%llx\n", did,
-                    data.raw);
-
-    return reg;
-  }
-
-  cxx::Ref_ptr get(unsigned core_no) const
-  {
-    return (core_no < _lapics.size()) ? _lapics[core_no] : nullptr;
-  }
-
-  void register_core(unsigned core_no, cxx::Ref_ptr cpu)
-  {
-    if (core_no < _lapics.size() && _lapics[core_no])
-      {
-        Dbg().printf("Local APIC for core %u already registered\n", core_no);
-        return;
-      }
-
-    if (core_no >= _lapics.size())
-      _lapics.resize(core_no + 1);
-
-    _lapics[core_no] = Vdev::make_device(core_no, cpu);
-  }
-
-  /// bind an EOI handler to all local APICS
-  void apics_bind_irq_src_handler_logical(unsigned did, unsigned irq,
-                                          Irq_src_handler *hdlr)
-  {
-    for (auto &lapic : _lapics)
-      if (lapic && lapic->match_ldr(did))
-        lapic->bind_irq_src_handler(irq, hdlr);
-  }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "LAPIC_array"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "LAPIC_array"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "LAPIC_array"); }
-
-  /// true, iff `did` is a broadcast in the current LAPIC mode.
-  bool is_broadcast(l4_uint32_t did) const
-  {
-    bool x2apic_mode = _lapics[0]->x2apic_mode();
-    if (x2apic_mode)
-      return 0xffffffffU == did;
-    else
-      return 0xffU == did;
-  }
-
-  /**
-   * Handle broadcast MSI for logical and physical destination mode.
-   *
-   * \return True, iff `did` indicated a broadcast.
-   */
-  bool handle_broadcast(l4_uint32_t did, Vdev::Msix::Data_register_format data)
-  {
-    if (is_broadcast(did))
-      {
-        for (auto &lapic : _lapics)
-          if (lapic)
-            lapic->set(data);
-
-        return true;
-      }
-
-    return false;
-  }
-
-  /// Handle logical mode MSI with lowest priority arbitration.
-  Vcpu_obj_registry *logical_mode_lp(l4_uint32_t did,
-                                     Vdev::Msix::Data_register_format data)
-  {
-    Virt_lapic *lowest = nullptr;
-    for (auto &lapic : _lapics)
-      {
-        if (lapic && lapic->match_ldr(did))
-          {
-            if (!lowest)
-              lowest = lapic.get();
-            else if (lapic->task_prio_class() < lowest->task_prio_class())
-              lowest = lapic.get();
-          }
-      }
-    if (lowest)
-      lowest->set(data);
-    else
-      warn().printf("Lowest priority aribitration for MSI failed. DestId 0x%x, "
-                    "Data 0x%llx\n",
-                    did, data.raw);
-
-    // The assumption is that rebinding the interrupt is just not worth the
-    // effort because the target changes dynamically.
-    return nullptr;
-  }
-
-  std::vector> _lapics;
-}; // class Lapic_array
-
-/**
- * Handle Inter-processor interrupts via the Interrupt Command Register (ICR).
- *
- * For details, consult Vol. 3A 10.6.1 of the Intel SDM.
- */
-class Icr_handler : public Vdev::Device
-{
-  enum : l4_uint32_t
-  {
-    Icr_startup = 0x6,
-    Icr_startup_page_shift = 12
-  };
-
-  struct Icr
-  {
-    l4_uint64_t raw;
-    CXX_BITFIELD_MEMBER_RO(56, 63, dest_field_mmio, raw);
-    CXX_BITFIELD_MEMBER_RO(32, 63, dest_field_x2apic, raw);
-    CXX_BITFIELD_MEMBER_RO(20, 31, reserved3, raw);
-    CXX_BITFIELD_MEMBER_RO(18, 19, dest_shorthand, raw);
-    CXX_BITFIELD_MEMBER_RO(16, 17, reserved2, raw);
-    CXX_BITFIELD_MEMBER_RO(15, 15, trigger_mode, raw);
-    CXX_BITFIELD_MEMBER_RO(14, 14, trigger_level, raw);
-    CXX_BITFIELD_MEMBER_RO(13, 13, reserved1, raw);
-    CXX_BITFIELD_MEMBER_RO(12, 12, delivery_status, raw);
-    CXX_BITFIELD_MEMBER_RO(11, 11, dest_mode, raw);
-    CXX_BITFIELD_MEMBER_RO(8, 10, delivery_mode, raw);
-    CXX_BITFIELD_MEMBER_RO(0, 7, vector, raw);
-    CXX_BITFIELD_MEMBER_RO(0, 31, lower, raw);
-
-    Icr() : raw(0U) {}
-    Icr(uint64_t val) : raw(val) {}
-  };
-
-  enum Destination_shorthand
-  {
-    No_shorthand = 0,
-    Self = 1,
-    All_including_self = 2,
-    All_excluding_self = 3
-  };
-
-public:
-  enum : unsigned
-  {
-    Icr_msr = 0x830,
-    Icr_mmio_ext = 0x831
-  };
-
-  bool read(unsigned msr, l4_uint64_t *value, unsigned vcpu_no) const
-  {
-    assert(vcpu_no < _icr.size());
-
-    switch (msr)
-      {
-      case Icr_msr:
-        *value = _icr[vcpu_no];
-        return true;
-      case Icr_mmio_ext:
-        *value = _icr[vcpu_no] >> 32;
-        return true;
-      default:
-        return false;
-      }
-  }
-
-  bool write(unsigned msr, l4_uint64_t value, unsigned vcpu_no, bool mmio)
-  {
-    assert(vcpu_no < _icr.size());
-
-    switch (msr)
-      {
-      case Icr_msr:
-        // If the write originates from an MMIO access, only the lower 32bit of
-        // the ICR should be written.
-        if (mmio)
-          _icr[vcpu_no] =
-            (_icr[vcpu_no] & 0xffffffff00000000ULL) | (value & 0xffffffffULL);
-        else
-          _icr[vcpu_no] = value;
-        // Vol. 3A 10.6.1: "The act of writing to the low doubleword of the ICR
-        // causes the IPI to be sent."
-        send_ipi(_icr[vcpu_no], vcpu_no, !mmio);
-        return true;
-      case Icr_mmio_ext:
-        _icr[vcpu_no] = (_icr[vcpu_no] & 0xffffffffULL) | (value << 32);
-        return true;
-      default:
-        return false;
-      }
-  }
-
-  /**
-   * Register the CPU device array with the IPI handler.
-   *
-   * \param cpus  Pointer to the CPU container.
-   *
-   * \pre The `cpus` array has already been populated.
-   */
-  void register_cpus(cxx::Ref_ptr const &cpus)
-  {
-    _cpus = cpus;
-    _icr.resize(cpus->size());
-  }
-
-  /**
-   * Register the MSI-X Controller with the IPI handler.
-   *
-   * \param msix_ctrl  Pointer to the MSI-X Controller.
-   */
-  void register_msix_ctrl(cxx::Ref_ptr const &msix_ctrl)
-  { _msix_ctrl = msix_ctrl; }
-
-private:
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "IPI"); }
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "IPI"); }
-
-  enum : l4_uint32_t { Data_register_format_mask = 0x0000c7ffU };
-
-  /**
-   * Send an Inter-Processor Interrupt message.
-   *
-   * This function handles the INIT-SIPI-SIPI sequence (cf. Vol. 3A 8.4.3 of
-   * the Intel 64 and IA-32 Architectures Software Developer's Manual) and
-   * forwards all other IPIs to the MSI-X Controller for distribution.
-   *
-   * \param icr_reg  Content of the ICR register.
-   * \param vcpu_no  Current vCPU ID.
-   * \param x2apic   Indicate if X2APIC mode is in use.
-   */
-  void send_ipi(l4_uint64_t icr_reg, unsigned vcpu_no, bool x2apic) const
-  {
-    Icr icr(icr_reg);
-
-    using namespace Vdev::Msix;
-
-    // cf. ICR format: Vol. 3A 10.6.1 / Figure 10-12 vs.
-    // the MSI data format: Vol. 3A 10.11.2 / Figure 10-25
-    Data_register_format const data(icr.lower() & Data_register_format_mask);
-
-    // Cf. Vol 3A 10.6.1 / Figure 10-12 vs. Vol 3A 10.12.9 / Figure 10-28
-    l4_uint32_t id = x2apic ? icr.dest_field_x2apic() : icr.dest_field_mmio();
-
-    if (data.delivery_mode() == Vdev::Msix::Delivery_mode::Dm_init
-        || data.delivery_mode() == Vdev::Msix::Delivery_mode::Dm_startup)
-      {
-        // filter deassert IPIs; HW does not support these since Pentium D.
-        if (data.delivery_mode() == Vdev::Msix::Delivery_mode::Dm_init
-            && icr.trigger_mode() == 1 && icr.trigger_level() == 0)
-          {
-            trace().printf("{INIT,STARTUP} IPI: INIT deassert filtered. ICR: "
-                           "0x%llx\n", icr.raw);
-            return;
-          }
-
-        // filter unsupported destination modes
-        switch (icr.dest_shorthand())
-          {
-          case Destination_shorthand::Self:
-          case Destination_shorthand::All_including_self:
-            info().printf(
-              "{INIT,STARTUP} IPI: unsupported destination shorthand. Ignoring.\n");
-            return;
-          default:
-            break;
-          }
-      }
-
-    Interrupt_request_compat addr(0ULL);
-    addr.fixed() = Address_interrupt_prefix;
-    addr.dest_mode() = icr.dest_mode();
-
-    assert(_msix_ctrl != nullptr);
-
-    switch (icr.dest_shorthand())
-      {
-      case Destination_shorthand::No_shorthand:
-        addr.dest_id() = id & 0xffU;
-        addr.dest_id_upper() = x2apic ? id >> 8 : 0U;
-        _msix_ctrl->send(addr.raw, data.raw);
-        break;
-      case Destination_shorthand::Self:
-        addr.dest_id() = vcpu_no & 0xffU;
-        addr.dest_id_upper() = x2apic ? vcpu_no >> 8 : 0U;
-        addr.dest_mode() = 0; // physical addressing
-        _msix_ctrl->send(addr.raw, data.raw);
-        break;
-      case Destination_shorthand::All_including_self:
-        // specify a physical broadcast MSI to be handled by Lapic_array
-        addr.dest_id() = 0xffU;
-        addr.dest_id_upper() = x2apic ? 0xfffffffUL : 0x0UL;
-        addr.dest_mode() = 0;
-        _msix_ctrl->send(addr.raw, data.raw);
-        break;
-      case Destination_shorthand::All_excluding_self:
-        // Intel SDM: Translates to physical destination mode broadcast IPI.
-        // Emulate the broadcast with single MSI for each vCPU.
-        for (unsigned i = 0; i <= _cpus->max_cpuid(); ++i)
-          {
-            if (i == vcpu_no)
-              continue;
-            addr.dest_id() = i & 0xffU;
-            addr.dest_id_upper() = x2apic ? i >> 8 : 0U;
-            addr.dest_mode() = 0; // physical addressing
-            _msix_ctrl->send(addr.raw, data.raw);
-          }
-        break;
-      }
-  }
-
-  std::vector _icr;
-  cxx::Ref_ptr _cpus;
-  cxx::Ref_ptr _msix_ctrl;
-}; // class Icr_handler
-
-class Lapic_access_handler
-: public Vmm::Mmio_device_t,
-  public Vmm::Msr_device,
-  public Vdev::Device
-{
-  enum
-  {
-    X2apic_msr_base = 0x800,
-    Lapic_mem_size = 0x1000,
-  };
-
-public:
-  enum { Mmio_addr = 0xfee00000 };
-  static_assert(!(Mmio_addr & 0xfff), "LAPIC memory is 4k-aligned.");
-
-  Lapic_access_handler(cxx::Ref_ptr apics,
-                       cxx::Ref_ptr icr_handler,
-                       unsigned max_phys_addr_bit)
-  : _max_phys_addr_mask((1UL << max_phys_addr_bit) - 1),
-    _apics(apics),
-    _icr_handler(icr_handler)
-  {
-    assert((Mmio_addr & _max_phys_addr_mask) == Mmio_addr);
-  }
-
-  // Msr device interface
-  bool read_msr(unsigned msr, l4_uint64_t *value,
-                unsigned vcpu_no) const override
-  {
-    if (msr == Icr_handler::Icr_msr || msr == Icr_handler::Icr_mmio_ext)
-      return _icr_handler->read(msr, value, vcpu_no);
-
-    auto lapic = _apics->get(vcpu_no);
-
-    assert((lapic != nullptr) && "Local APIC found at vcpu_no.");
-
-    return lapic->read_msr(msr, value);
-  };
-
-  bool write_msr(unsigned msr, l4_uint64_t value, unsigned vcpu_no) override
-  {
-    return dispatch_msr(msr, value, vcpu_no, false);
-  }
-
-  // Mmio device interface
-  l4_umword_t read(unsigned reg, char, unsigned cpu_id) const
-  {
-    l4_uint64_t val = -1;
-    read_msr(reg2msr(reg), &val, cpu_id);
-    return val;
-  }
-
-  void write(unsigned reg, char, l4_umword_t value, unsigned cpu_id)
-  {
-    dispatch_msr(reg2msr(reg), value, cpu_id, true);
-  }
-
-
-  Vmm::Region mmio_region() const
-  {
-    return Vmm::Region::ss(Vmm::Guest_addr(Mmio_addr), Lapic_mem_size,
-                           Vmm::Region_type::Virtual);
-  }
-
-  char const *dev_name() const override { return "Lapic_access_handler"; }
-
-private:
-  /**
-   * Forward an MSR-encoded write to the ICR handler or to a local APIC.
-   *
-   * \param msr      Number of the MSR written.
-   * \param value    Value written.
-   * \param vcpu_no  vCPU that the write originates from.
-   * \param mmio     Indicates if the write originates from an MMIO write that
-   *                 was converted to a MSR write.
-   *
-   * \return  True if the write was handled successfully, false otherwise.
-   */
-  bool dispatch_msr(unsigned msr, l4_uint64_t value, unsigned vcpu_no,
-                    bool mmio)
-  {
-    if (msr == Icr_handler::Icr_msr || msr == Icr_handler::Icr_mmio_ext)
-      return _icr_handler->write(msr, value, vcpu_no, mmio);
-
-    auto lapic = _apics->get(vcpu_no);
-
-    assert((lapic != nullptr) && "Local APIC found at vcpu_no.");
-
-    return lapic->write_msr(msr, value);
-  }
-
-  static unsigned reg2msr(unsigned reg)
-  { return (reg >> 4) | X2apic_msr_base; }
-
-  l4_uint64_t _max_phys_addr_mask;
-  cxx::Ref_ptr _apics;
-  cxx::Ref_ptr _icr_handler;
-}; // class Lapic_access_handler
-
-/**
- * MSI-X control for MSI routing.
- *
- * This class checks if the Redirection Hint is set, then it selects the LAPIC
- * with the lowest interrupt priority as recipient and rewrites the DID field
- * according to the Destination Mode.
- * If RH=0 the MSI is sent to the specified LAPIC(s) according to the DM.
- *
- * Design wise, this class is located between IOMMU and all LAPICs.
- */
-class Msix_control : public Msix_controller, public Vdev::Device
-{
-public:
-  Msix_control(cxx::Ref_ptr apics) : _apics(apics) {}
-
-  /// Analyse the MSI-X message and send it to the specified local APIC.
-  Vcpu_obj_registry *send(l4_uint64_t msix_addr, l4_uint64_t msix_data,
-                          l4_uint32_t) const override
-  {
-    Vdev::Msix::Interrupt_request_compat addr(msix_addr);
-    Vdev::Msix::Data_register_format data(msix_data);
-
-    // Always use the extended MSI-X format. If not in use, the upper bits will
-    // simply be 0. cf.  Intel Virtualization Technology for Directed I/O
-    // Architecture Specification (June 2019) 5.1.8
-    l4_uint32_t id = (addr.dest_id_upper() << 8) | addr.dest_id();
-
-    if (addr.fixed() != Vdev::Msix::Address_interrupt_prefix)
-      {
-        trace().printf("Interrupt request prefix invalid; MSI dropped.\n");
-        return nullptr;
-      }
-
-  // If RH is set, we do lowest priority arbitration!
-  // We can only do lowest prio arbitration in logical addressing mode.
-  // Therefore, we ignore the RH bit in physical addressing mode.
-  // The same is true when the delivery mode is set to lowest priority.
-  // The encoding physical mode, broadcast ID and lowest priority is
-  // forbidden/undefined. Process it as physical broadcast just in case.
-  if (addr.dest_mode())
-    {
-      bool lowest_prio =
-        addr.redirect_hint()
-        || (data.delivery_mode() == Vdev::Msix::Dm_lowest_prio);
-
-      return _apics->logical_mode(id, data, lowest_prio);
-    }
-  else
-    return _apics->physical_mode(id, data);
-  }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "MSI-CTLR"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "MSI-CTLR"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "MSI-CTLR"); }
-
-  cxx::Ref_ptr _apics;
-}; // class Msix_control
-
-/**
- * Apic_timer; emulates a local APIC timer.
- *
- * Be aware that expired() is run on the timer thread with higher priority
- * than the vcpu thread, which handles everything else. So whenever an IPC is
- * involved, such as in enqueue_timeout(), dequeue_timeout() or irq_tigger()
- * you must not hold the mutex.
- */
-class Apic_timer: public Vdev::Timer,
-                  public L4::Ipc_svr::Timeout_queue::Timeout
-{
-  enum Timer
-  {
-    Frequency_hz = 1000000000ULL, // 1Ghz
-    Microseconds_per_second = 1000000ULL,
-  };
-
-  /// Divide Configuration Register
-  struct Divide_configuration_reg
-  {
-    l4_uint32_t raw;
-    CXX_BITFIELD_MEMBER_RO(3, 3, upper, raw);
-    CXX_BITFIELD_MEMBER_RO(0, 1, lower, raw);
-
-    Divide_configuration_reg() : raw(0U) {}
-    Divide_configuration_reg(l4_uint32_t val) : raw(val) {}
-    Divide_configuration_reg(Divide_configuration_reg const &o) : raw(o.raw) {}
-
-    Divide_configuration_reg &operator= (const Divide_configuration_reg &)
-      = default;
-
-    unsigned divisor() const
-    {
-      unsigned shift = lower() + (upper() << 2);
-
-      return shift == 7 ? 1 : 2u << shift;
-    }
-  };
-
-  /// LVT Timer Register
-  struct Lvt_timer_reg
-  {
-    l4_uint32_t raw;
-    CXX_BITFIELD_MEMBER(17, 18, mode, raw);
-    CXX_BITFIELD_MEMBER(16, 16, masked, raw);
-    CXX_BITFIELD_MEMBER(12, 12, pending, raw);
-    CXX_BITFIELD_MEMBER(0, 7, vector, raw);
-
-    Lvt_timer_reg() : raw(0x00010000) {}
-    explicit Lvt_timer_reg(l4_uint32_t t) : raw(t) {}
-
-    Lvt_timer_reg &operator = (l4_uint32_t t) { raw = t; return *this; }
-
-    bool one_shot() const { return !mode(); }
-    bool periodic() const { return mode() == 1; }
-    bool tsc_deadline() const { return mode() == 2; }
-    void disarm() { masked() = 1; }
-    char const *mode_string()
-    {
-      if (one_shot())
-        return "one shot";
-      if (periodic())
-        return "periodic";
-      if (tsc_deadline())
-        return "tsc deadline";
-      return "unknown";
-    }
-
-    void print()
-    {
-      warn().printf("timer: %s %s %s vector: %u\n",
-                    mode_string(),
-                    masked() ? "masked" : "unmasked",
-                    pending() ? "pending" : "",
-                    vector().get());
-    }
-  };
-
-public:
-  Apic_timer(Virt_lapic *lapic)
-  : _tmr_cur(0), _tmr_init(0), _div_reg(0), _lvt_reg(0x10000),
-    _virt_lapic(lapic)
-  {}
-
-  l4_uint64_t read_tmr_cur()
-  {
-    std::lock_guard lock(_tmr_mutex);
-
-    // In deadline mode the current count register always returns 0
-    if (_lvt_reg.tsc_deadline())
-      return 0;
-
-    if (_tmr_init == 0)
-      return 0;
-
-    l4_cpu_time_t now = l4_rdtsc();
-    l4_cpu_time_t diff_us = l4_tsc_to_us(now - _tsc_base);
-    l4_cpu_time_t frequency = Timer::Frequency_hz / _div_reg.divisor();
-    l4_cpu_time_t diff_ticks =
-      diff_us * frequency / Timer::Microseconds_per_second;
-
-    if (_lvt_reg.periodic())
-      {
-        _tmr_cur = (_tmr_init - diff_ticks) % _tmr_init;
-        return _tmr_cur;
-      }
-
-    if (diff_ticks >= _tmr_init)
-      _tmr_cur = 0;
-    else
-      _tmr_cur = _tmr_init - diff_ticks;
-
-    /// we do not inject interrupts here, but let them be injected from the
-    /// timer thread (expired())
-
-    return _tmr_cur;
-  }
-
-  /**
-   * Reads the tmr_init field.
-   *
-   * _tmr_init is only used on the vcpu thread, therefore we do not need to
-   * grab a lock.
-   **/
-  l4_uint64_t read_tmr_init()
-  {
-    return _tmr_init;
-  }
-
-  /**
-   * Calculate the next timeout in periodic and one_shot modes.
-   *
-   * The result is given in micro seconds (10^-6 seconds). The APIC timer runs
-   * with Timer::Frequency_hz. This function is also used in expired(),
-   * therefore we must take care of the mutex.
-   *
-   * \param ticks The requested amount of ticks of the APIC timer.
-   */
-  l4_uint64_t next_timeout_us(l4_uint64_t ticks)
-  {
-    l4_uint64_t divisor;
-    {
-      std::lock_guard lock(_tmr_mutex);
-      divisor = _div_reg.divisor();
-    }
-
-    l4_kernel_clock_t kip = l4_kip_clock(l4re_kip());
-    l4_cpu_time_t frequency = Timer::Frequency_hz / divisor;
-    l4_cpu_time_t timeout_us =
-      ticks * Timer::Microseconds_per_second / frequency;
-
-    return kip + timeout_us;
-  }
-
-  void write_tmr_init(l4_uint64_t value)
-  {
-    // in tsc deadline mode writes to tmr_init are ignored
-    if (_lvt_reg.tsc_deadline())
-      return;
-
-    // reset old timeouts
-    dequeue_timeout(this);
-
-    Lvt_timer_reg lvt;
-    {
-      std::lock_guard lock(_tmr_mutex);
-
-      lvt = Lvt_timer_reg(_lvt_reg);
-      _tmr_init = value;
-      _tmr_cur = value;
-      _tsc_base = l4_rdtsc();
-    }
-
-    if (value)
-      enqueue_timeout(this, next_timeout_us(value));
-  }
-
-  // _div_reg is only manipulated on the vcpu thread
-  // therefore we don't need a lock
-  l4_uint32_t read_divide_configuration_reg()
-  { return _div_reg.raw; }
-
-  void write_divide_configuration_reg(l4_uint32_t value)
-  {
-    l4_uint64_t init;
-    Lvt_timer_reg lvt;
-    {
-      std::lock_guard lock(_tmr_mutex);
-
-      lvt = Lvt_timer_reg(_lvt_reg);
-      _div_reg.raw = value;
-      init = _tmr_init;
-    }
-
-    // changing this value modifies the speed of the APIC timer
-    // so we must reset the timeouts that we set up with the
-    // previous value
-
-    // the TSC Deadline timer is not affected by this
-    if (!lvt.tsc_deadline())
-      dequeue_timeout(this);
-
-    // only iff the guest programmed the timer do we need to set it up
-    if (init)
-      enqueue_timeout(this, next_timeout_us(init));
-  }
-
-  l4_uint32_t read_lvt_timer_reg()
-  { return _lvt_reg.raw; }
-
-  void write_lvt_timer_reg(l4_uint64_t value)
-  {
-    Lvt_timer_reg old_lvt(0);
-    Lvt_timer_reg new_lvt(value);
-
-    {
-      std::lock_guard lock(_tmr_mutex);
-      old_lvt.raw = _lvt_reg.raw;
-      _lvt_reg.raw = value;
-    }
-
-    if (old_lvt.pending() && !new_lvt.masked()
-        && old_lvt.vector() == new_lvt.vector())
-      irq_trigger(old_lvt.vector());
-
-    // setting a new timer mode disarms the timer
-    if (old_lvt.mode() != new_lvt.mode())
-      dequeue_timeout(this);
-  }
-
-  // timeout has expired
-  // inject interrupt iff periodic reenqueue to receive the next interrupt
-  // Note: this function is called on the timer thread
-  void expired()
-  {
-    bool periodic = false;
-    bool masked = false;
-    unsigned vector;
-    l4_uint64_t init;
-
-    {
-      std::lock_guard lock(_tmr_mutex);
-      if (_lvt_reg.masked())
-        _lvt_reg.pending() = 1;
-
-      if (_lvt_reg.one_shot())
-        _tmr_cur = 0;
-
-      if (_lvt_reg.periodic())
-        {
-          periodic = true;
-          _tmr_cur = _tmr_init;
-        }
-
-      init = _tmr_init;
-      vector = _lvt_reg.vector();
-      masked = _lvt_reg.masked();
-      _tsc_deadline = 0;
-    }
-
-    if (!masked)
-      irq_trigger(vector);
-
-    if (periodic)
-      requeue_timeout(this, next_timeout_us(init));
-  }
-
-  l4_uint64_t read_tsc_deadline_msr()
-  {
-    std::lock_guard lock(_tmr_mutex);
-    if (!_lvt_reg.tsc_deadline())
-      return 0ULL;
-    return _tsc_deadline;
-  }
-
-  void write_tsc_deadline_msr(l4_uint64_t target_tsc)
-  {
-    // a fresh TSC deadline value always resets previous timeouts
-    dequeue_timeout(this);
-
-    bool tsc_deadline_mode;
-    bool masked = false;
-    {
-      std::lock_guard lock(_tmr_mutex);
-      tsc_deadline_mode = _lvt_reg.tsc_deadline();
-      masked = _lvt_reg.masked();
-      _tsc_deadline = target_tsc;
-
-    }
-
-    if (!tsc_deadline_mode)
-      {
-        if (!masked)
-          warn()
-            .printf("guest programmed tsc deadline, but tsc deadline mode not "
-                    "set. new_tsc 0x%llx, LVT: %s\n",
-                    target_tsc, _lvt_reg.mode_string());
-        return;
-      }
-
-    // writing a zero disarms the timer
-    if (target_tsc == 0)
-      return;
-
-    l4_kernel_clock_t tsc_diff;
-    l4_cpu_time_t tsc = l4_rdtsc();
-    if (target_tsc <= tsc)
-      tsc_diff = 0;
-    else
-      tsc_diff = target_tsc - tsc;
-
-    if (0)
-      Dbg()
-        .printf("New TSC deadline: 0x%llx (now: 0x%llx) timer status: %x\n",
-                target_tsc, tsc, _lvt_reg.raw);
-
-    l4_kernel_clock_t t = l4_tsc_to_us(tsc_diff);
-    l4_kernel_clock_t kip = l4_kip_clock(l4re_kip());
-    enqueue_timeout(this, kip + t);
-  }
-
-private:
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "LAPIC-Timer"); }
-
-  void irq_trigger(l4_uint32_t irq)
-  { _virt_lapic->irq_trigger(irq); }
-
-  l4_uint64_t _tmr_cur, _tmr_init, _tsc_base;
-  Divide_configuration_reg _div_reg;
-  Lvt_timer_reg _lvt_reg;
-  Virt_lapic *_virt_lapic;
-  l4_uint64_t _tsc_deadline;
-  std::mutex _tmr_mutex;
-}; // class Apic_timer
-
-} // namespace Gic
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state.h
deleted file mode 100644
index fe5f344b..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2017-2019, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-namespace Vmm {
-
-/// Abstraction of the VMX and SVM event injection format.
-struct Injection_event
-{
-  l4_uint64_t raw = 0;
-  CXX_BITFIELD_MEMBER(0, 31, event, raw);
-  CXX_BITFIELD_MEMBER(32, 63, error, raw);
-  // SVM and VMX both use the same bit encoding in the lower 11 bits.
-  CXX_BITFIELD_MEMBER(0, 7, vector, raw);
-  CXX_BITFIELD_MEMBER(8, 10, type, raw);
-  CXX_BITFIELD_MEMBER(11, 11, error_valid, raw);
-  // SVM and VMX both use bit 31 to indicate validity of the value.
-  CXX_BITFIELD_MEMBER(31, 31, valid, raw);
-
-  Injection_event(l4_uint32_t ev, l4_uint32_t err)
-  {
-    event() = ev;
-    error() = err;
-  }
-
-  Injection_event(unsigned char v, unsigned char t, bool err_valid = false,
-                  l4_uint32_t err_code = 0)
-  {
-    vector() = v;
-    type() = t;
-    error_valid() = err_valid;
-    error() = err_code;
-    valid() = 1;
-  }
-
-  explicit Injection_event(l4_uint64_t val) : raw(val) {}
-};
-
-class Event_recorder;
-
-class Vm_state
-{
-public:
-  enum class Type { Vmx, Svm };
-
-  virtual ~Vm_state() = 0;
-
-  virtual Type type() const = 0;
-
-  virtual void init_state() = 0;
-  virtual void setup_linux_protected_mode(l4_addr_t entry,
-                                          l4_addr_t stack_addr) = 0;
-  virtual void setup_real_mode(l4_addr_t entry) = 0;
-
-  virtual l4_umword_t ip() const = 0;
-  virtual l4_umword_t sp() const = 0;
-  virtual bool pf_write() const = 0;
-  virtual l4_umword_t cr3() const = 0;
-  virtual l4_uint64_t xcr0() const = 0;
-
-  virtual bool read_msr(unsigned msr, l4_uint64_t *value) const = 0;
-  virtual bool write_msr(unsigned msr, l4_uint64_t value, Event_recorder *ev_rec) = 0;
-
-  virtual Injection_event pending_event_injection() = 0;
-  virtual void inject_event(Injection_event const &ev) = 0;
-
-  virtual bool can_inject_nmi() const = 0;
-  virtual bool can_inject_interrupt() const = 0;
-  virtual void disable_interrupt_window() = 0;
-  virtual void enable_interrupt_window() = 0;
-  virtual void disable_nmi_window() = 0;
-  virtual void enable_nmi_window() = 0;
-
-  // must only be called once per VM entry
-  virtual void advance_entry_ip(unsigned bytes) = 0;
-};
-
-} // namespace Vmm
-
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.cc
deleted file mode 100644
index 2624d54f..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.cc
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Copyright (C) 2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "vm_state_svm.h"
-#include "consts.h"
-#include "mad.h"
-
-namespace Vmm {
-
-void
-Svm_state::init_state()
-{
-    // Does not matter, Linux overwrites it...
-  _vmcb->state_save_area.ldtr.selector = 0;
-  _vmcb->state_save_area.ldtr.attrib = 0;
-  _vmcb->state_save_area.ldtr.limit = 0;
-  _vmcb->state_save_area.ldtr.base = 0;
-
-  // TODO: Setup GDTR, IDTR? (not done on VMX)
-
-  // Always use nested paging!
-  _vmcb->control_area.np_enable = 1;
-  // Initiated to default values at reset: WB,WT,WC,UC,WB,WT,UC-,UC
-  _vmcb->state_save_area.g_pat = 0x0007040600010406ULL;
-  // Reset value of XCR0
-  _vmcb->state_save_area.xcr0 = 1ULL;
-
-  _vmcb->state_save_area.rflags = 0;
-  _vmcb->state_save_area.cr3 = 0;
-  _vmcb->state_save_area.dr6 = 0;
-  _vmcb->state_save_area.dr7 = 0;
-
-  _vmcb->control_area.eventinj = 0;
-
-  // Enable SVM
-  _vmcb->state_save_area.efer = Efer_svme_enable;
-
-  // Intercept DR accesses.
-  // The kernel enforces 0xff3f, to keep the behavior consistent with VMX, we
-  // intercept all DR accesses.
-  _vmcb->control_area.intercept_rd_drX = 0xffff;
-  _vmcb->control_area.intercept_wr_drX = 0xffff;
-
-  _vmcb->control_area.intercept_exceptions = 0;
-
-  _vmcb->control_area.intercept_instruction0 =
-      Intercept_intr | Intercept_nmi | Intercept_smi | Intercept_init
-    | Intercept_vintr | Intercept_cr0_sel_write | Intercept_rdpmc
-    | Intercept_cpuid | Intercept_invd | Intercept_hlt | Intercept_ioio
-    | Intercept_msr | Intercept_task_switch | Intercept_freeze
-    | Intercept_shutdown;
-
-  // TODO: These are the instructions intercepts that Fiasco enforces. Check
-  // if we intercept too less or too much...
-  _vmcb->control_area.intercept_instruction1 =
-      Intercept_vmrun | Intercept_vmmcall | Intercept_vmload
-    | Intercept_vmsave | Intercept_stgi | Intercept_clgi | Intercept_skinit
-    | Intercept_rdtscp | Intercept_monitor | Intercept_mwait
-    | Intercept_xsetbv;
-
-  mark_all_dirty();
-}
-
-void
-Svm_state::setup_linux_protected_mode(l4_addr_t entry, l4_addr_t stack_addr)
-{
-  _vmcb->state_save_area.cs.selector = 0x10;
-  _vmcb->state_save_area.cs.attrib = 0xc9a; // TYPE=10=Read/Execute, S, P, DB, G
-  _vmcb->state_save_area.cs.limit = 0xffffffff;
-  _vmcb->state_save_area.cs.base = 0;
-
-  _vmcb->state_save_area.ss.selector = 0x18;
-  _vmcb->state_save_area.ss.attrib = 0xc92; // TYPE=2=Read/Write, S, P, DB, G
-  _vmcb->state_save_area.ss.limit = 0xffffffff;
-  _vmcb->state_save_area.ss.base = 0;
-
-  _vmcb->state_save_area.ds.selector = 0x18;
-  _vmcb->state_save_area.ds.attrib = 0xc92;
-  _vmcb->state_save_area.ds.limit = 0xffffffff;
-  _vmcb->state_save_area.ds.base = 0;
-
-  _vmcb->state_save_area.es.selector = 0x18;
-  _vmcb->state_save_area.es.attrib = 0xc92;
-  _vmcb->state_save_area.es.limit = 0xffffffff;
-  _vmcb->state_save_area.es.base = 0;
-
-  _vmcb->state_save_area.fs.selector = 0x0;
-  _vmcb->state_save_area.fs.attrib = 0xcf3; // Equivalent to VMX
-  _vmcb->state_save_area.fs.limit = 0xffffffff;
-  _vmcb->state_save_area.fs.base = 0;
-
-  _vmcb->state_save_area.gs.selector = 0x0;
-  _vmcb->state_save_area.gs.attrib = 0xcf3;
-  _vmcb->state_save_area.gs.limit = 0xffffffff;
-  _vmcb->state_save_area.gs.base = 0;
-
-  _vmcb->state_save_area.tr.selector = 0x28;
-  _vmcb->state_save_area.tr.attrib = 0x8b; // TYPE=11, P
-  _vmcb->state_save_area.tr.limit = 0x67; // TODO: VMX uses 67 here
-  _vmcb->state_save_area.tr.base = 0;
-
-  _vmcb->state_save_area.rip = entry;
-  _vmcb->state_save_area.rsp = stack_addr;
-  _vmcb->state_save_area.cr0 = 0x10031;
-  _vmcb->state_save_area.cr4 = 0x690;
-}
-
-/**
- * Setup the Real Mode startup procedure for AP startup and BSP resume.
- *
- * This follows the hardware reset behavior described in AMD APM "14.1.5
- * Fetching the first instruction".
- */
-void
-Svm_state::setup_real_mode(l4_addr_t entry)
-{
-  if (entry == 0xfffffff0U)
-    {
-      // Bootstrap Processor (BSP) boot
-      _vmcb->state_save_area.cs.selector = 0xf000U;
-      _vmcb->state_save_area.cs.base = 0xffff0000U;
-      _vmcb->state_save_area.rip = 0xfff0U;
-    }
-  else
-    {
-      // Application Processor (AP) boot via Startup IPI (SIPI) or resume
-      // from suspend.
-      // cs_base contains the cached address computed from cs_selector. After
-      // reset cs_base contains what we set until the first cs selector is
-      // loaded. We use the waking vector or SIPI vector directly, because
-      // tianocore cannot handle the CS_BASE + IP split.
-      _vmcb->state_save_area.cs.selector = entry >> 4;
-      _vmcb->state_save_area.cs.base = entry;
-      _vmcb->state_save_area.rip = 0;
-    }
-
-  _vmcb->state_save_area.cs.attrib = 0x9b; // TYPE=11, S, P
-  _vmcb->state_save_area.cs.limit = 0xffff;
-
-  _vmcb->state_save_area.ss.selector = 0x18;
-  _vmcb->state_save_area.ss.attrib = 0x93; // TYPE=3, S, P
-  _vmcb->state_save_area.ss.limit = 0xffff;
-  _vmcb->state_save_area.ss.base = 0;
-
-  _vmcb->state_save_area.ds.selector = 0x18;
-  _vmcb->state_save_area.ds.attrib = 0x93;
-  _vmcb->state_save_area.ds.limit = 0xffff;
-  _vmcb->state_save_area.ds.base = 0;
-
-  _vmcb->state_save_area.es.selector = 0x18;
-  _vmcb->state_save_area.es.attrib = 0x93;
-  _vmcb->state_save_area.es.limit = 0xffff;
-  _vmcb->state_save_area.es.base = 0;
-
-  _vmcb->state_save_area.fs.selector = 0x0;
-  _vmcb->state_save_area.fs.attrib = 0x93;
-  _vmcb->state_save_area.fs.limit = 0xffff;
-  _vmcb->state_save_area.fs.base = 0;
-
-  _vmcb->state_save_area.gs.selector = 0x0;
-  _vmcb->state_save_area.gs.attrib = 0x93;
-  _vmcb->state_save_area.gs.limit = 0xffff;
-  _vmcb->state_save_area.gs.base = 0;
-
-  _vmcb->state_save_area.tr.selector = 0x0;
-  _vmcb->state_save_area.tr.attrib = 0x8b; // TYPE=11, P
-  _vmcb->state_save_area.tr.limit = 0xffff;
-  _vmcb->state_save_area.tr.base = 0;
-
-  _vmcb->state_save_area.rsp = 0;
-  _vmcb->state_save_area.cr0 = 0x10030;
-  _vmcb->state_save_area.cr4 = 0x680;
-
-  // clear in SW state to prevent injection of pending events from before
-  // INIT/STARTUP IPI.
-  _vmcb->control_area.exitintinfo = 0ULL;
-}
-
-bool
-Svm_state::determine_next_ip_from_ip(l4_vcpu_regs_t *regs,
-                                     unsigned char *inst_buf,
-                                     unsigned inst_buf_len)
-{
-  using namespace L4mad;
-  Op op;
-  Desc tgt, src;
-  Decoder decoder(reinterpret_cast(regs), ip(), inst_buf,
-                  inst_buf_len);
-  if (decoder.decode(&op, &tgt, &src) != Decoder::Result::Success)
-    {
-      warn().printf("Could not decode instruction for current ip\n");
-      return false;
-    }
-
-  trace().printf("Advance instruction pointer n_rip = 0x%lx + 0x%x\n",
-                 ip(), op.insn_len);
-
-  _vmcb->control_area.n_rip = ip() + op.insn_len;
-  return true;
-}
-
-bool
-Svm_state::read_msr(unsigned msr, l4_uint64_t *value) const
-{
-  switch (msr)
-    {
-    case 0x8b: // IA32_BIOS_SIGN_ID
-    case 0x1a0: // IA32_MISC_ENABLE
-      *value = 0U;
-      break;
-    case 0x3a: // IA32_FEATURE_CONTROL
-      // Lock register so the guest does not try to enable anything.
-      *value = 1U;
-      break;
-    case 0x277: // PAT
-      *value =_vmcb->state_save_area.g_pat;
-      break;
-    case 0xc0000080: // efer
-      // Hide SVME bit
-      *value = _vmcb->state_save_area.efer & ~Efer_svme_enable;
-      break;
-    case 0xc0010140: // OSVW_ID_Length
-      // TODO: Report errata to the guest? Allow direct read access to OSVW
-      //       register in msrpm in Fiasco?
-      *value = 0U;
-      break;
-
-    case 0xc001001f: // MSR_AMD64_NB_CFG
-      // can all be savely ignored
-      *value = 0;
-      break;
-
-    default:
-      return false;
-    }
-  return true;
-}
-
-bool
-Svm_state::write_msr(unsigned msr, l4_uint64_t value, Event_recorder *ev_rec)
-{
-  switch (msr)
-    {
-    case 0x277: // PAT
-      // sanitization of 7 PAT values
-      // 0xF8 are reserved bits
-      // 0x2 and 0x3 are reserved encodings
-      // usage of reserved bits and encodings results in a #GP
-      if (value & 0xF8F8F8F8F8F8F8F8ULL)
-        {
-          ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-          break;
-        }
-
-      for (unsigned i = 0; i < 7; ++i)
-        {
-          l4_uint64_t const PAi_mask = (value & (0x7ULL << i * 8)) >> i * 8;
-          if ((PAi_mask == 0x2ULL) || (PAi_mask == 0x3ULL))
-            {
-              ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-              break;
-            }
-        }
-
-      _vmcb->state_save_area.g_pat = value;
-      break;
-    case 0xc0000080: // efer
-      {
-        // Force the SVME bit
-        l4_uint64_t efer = (value & Efer_guest_write_mask) | Efer_svme_enable;
-        l4_uint64_t old_efer = _vmcb->state_save_area.efer;
-        l4_uint64_t cr0 = _vmcb->state_save_area.cr0;
-
-        trace().printf("cr0: 0x%llx old efer 0x%llx new efer 0x%llx\n",
-                       cr0, old_efer, efer);
-
-        // There is no going back from enabling long mode.
-        efer |= old_efer & Efer_lme;
-
-        if ((efer & Efer_lme) && (cr0 & Cr0_pg))
-          {
-            // indicate that long mode is active
-            efer |= Efer_lma;
-          }
-
-        trace().printf("efer: 0x%llx\n", efer);
-        _vmcb->state_save_area.efer = efer;
-        mark_dirty(Vmcb_crx);
-        break;
-      }
-    case 0xc001001f: // MSR_AMD64_NB_CFG
-      // can all be savely ignored
-      break;
-
-    default:
-      return false;
-    }
-
-  return true;
-}
-
-int
-Svm_state::handle_cr0_write(l4_vcpu_regs_t *regs)
-{
-  l4_uint64_t info1 = exit_info1();
-  if (!(info1 & Cr_valid))
-    {
-      // No decode assist information was provided for the access:
-      // "If the instruction is LMSW no additional information is provided."
-      Err().printf("LMSW write to CR0 not supported.\n");
-      return -1;
-    }
-
-  l4_umword_t newval = read_gpr(regs, info1 & Cr_gpr_mask);
-
-  auto old_cr0 = _vmcb->state_save_area.cr0;
-  trace().printf("Write to cr0: 0x%llx -> 0x%lx\n", old_cr0, newval);
-  // 0x10 => Extension Type; hardcoded to 1 see manual
-  _vmcb->state_save_area.cr0 = newval | 0x10;
-  mark_dirty(Vmcb_crx);
-
-  if ((newval & Cr0_pg)
-      && (old_cr0 & Cr0_pg) == 0
-      && (_vmcb->state_save_area.efer & Efer_lme))
-    {
-      // indicate that long mode is active
-      info().printf("Enable long mode\n");
-      _vmcb->state_save_area.efer |= Efer_lma;
-    }
-
-  if ((newval & Cr0_pg) == 0
-      && (old_cr0 & Cr0_pg))
-    {
-      trace().printf("Disabling paging ...\n");
-
-      if (_vmcb->state_save_area.efer & Efer_lme)
-        _vmcb->state_save_area.efer &= ~Efer_lma;
-    }
-
-  return Jump_instr;
-}
-
-int
-Svm_state::handle_xsetbv(l4_vcpu_regs_t *regs)
-{
-  // TODO: We have to check that the current privilege level is 0, and inject
-  // a general protection exception into the guest otherwise!
-  if (_vmcb->state_save_area.cpl != 0)
-    {
-      warn().printf(
-        "Ignoring write to extended control register %ld from CPL %d.\n",
-        regs->cx, _vmcb->state_save_area.cpl);
-      return Jump_instr;
-    }
-
-  if (regs->cx == 0)
-    {
-      l4_uint64_t value = (l4_uint64_t(regs->ax) & 0xFFFFFFFF)
-                          | (l4_uint64_t(regs->dx) << 32);
-      _vmcb->state_save_area.xcr0 = value;
-      trace().printf("Setting xcr0 to 0x%llx\n", value);
-      return Jump_instr;
-    }
-
-  info().printf("Writing unknown extended control register %ld\n", regs->cx);
-  return -L4_EINVAL;
-}
-
-int
-Svm_state::handle_hardware_exception(Event_recorder *ev_rec, unsigned num)
-{
-  Err err;
-
-  // Besides #DB and #AC all hardware exceptions are reflected to the guest.
-  // The print statements serve as (paranoid) debug help in case the reflection
-  // does not happen.
-  switch (num)
-  {
-    case 0: err.printf("Hardware exception: Divide error\n"); break;
-
-    case 1: // #DB
-      {
-        ev_rec->make_add_event(Event_prio::Exception, num);
-        // #DB exceptions are either of fault type or of trap type. We reflect
-        // both to the guest, without changing state, thus don't change the IP.
-        return Retry;
-      }
-
-    case 3: err.printf("Hardware exception: Breakpoint\n"); break;
-    case 4: err.printf("Hardware exception: Overflow\n"); break;
-    case 5: err.printf("Hardware exception: Bound range\n"); break;
-    case 6: err.printf("Hardware exception: Invalid opcode\n"); break;
-    case 7: err.printf("Hardware exception: Device not available\n"); break;
-    case 8: err.printf("Hardware exception: Double fault\n"); break;
-    case 10: err.printf("Hardware exception: Invalid TSS\n"); break;
-    case 11: err.printf("Hardware exception: Segment not present\n"); break;
-    case 12: err.printf("Hardware exception: Stack-segment fault\n"); break;
-    case 13: err.printf("Hardware exception: General protection\n"); break;
-    case 14: err.printf("Hardware exception: Page fault\n"); break;
-    case 16: err.printf("Hardware exception: FPU error\n"); break;
-
-    case 17: // #AC
-      {
-        l4_uint64_t err_code = exit_info1();
-        ev_rec->make_add_event(Event_prio::Exception, num, err_code);
-        return Retry;
-      }
-    case 18: err.printf("Hardware exception: Machine check\n"); break;
-    case 19: err.printf("Hardware exception: SIMD error\n"); break;
-    default: err.printf("Hardware exception: Unknown exception\n"); break;
-  }
-
-  return -L4_EINVAL;
-}
-
-l4_umword_t
-Svm_state::read_gpr(l4_vcpu_regs_t *regs, unsigned reg) const
-{
-  switch(reg)
-    {
-    case 0: return regs->ax;
-    case 1: return regs->cx;
-    case 2: return regs->dx;
-    case 3: return regs->bx;
-    case 4: return _vmcb->state_save_area.rsp;
-    case 5: return regs->bp;
-    case 6: return regs->si;
-    case 7: return regs->di;
-    case 8: return regs->r8;
-    case 9: return regs->r9;
-    case 10: return regs->r10;
-    case 11: return regs->r11;
-    case 12: return regs->r12;
-    case 13: return regs->r13;
-    case 14: return regs->r14;
-    case 15: return regs->r15;
-    default: L4Re::throw_error(-L4_EINVAL, "Invalid register num.");
-    }
-}
-
-const char *
-Svm_state::str_exit_code(Exit exit)
-{
-  l4_uint32_t code = static_cast(exit);
-
-  if (/* code >= 0x00 && */ code <= 0x0f)
-    return "Read of CR 0-15";
-
-  if (code >= 0x10 && code <= 0x1f)
-    return "Write of CR 0-15";
-
-  if (code >= 0x20 && code <= 0x2f)
-    return "Read of DR 0-15";
-
-  if (code >= 0x30 && code <= 0x3f)
-    return "Write of DR 0-15";
-
-  if (code >= 0x40 && code <= 0x5f)
-    return "Exception vector 0-31";
-
-  if (code >= 0x90 && code <= 0x9f)
-    return "Write of CR 0-15 (trap)";
-
-  switch (code)
-  {
-    case 0x60: return "Physical INTR (maskable interrupt)";
-    case 0x61: return "Physical NMI";
-    case 0x62: return "Physical SMI";
-    case 0x63: return "Physical INIT";
-    case 0x64: return "Virtual INTR";
-    case 0x65: return "Write of CR0 that changed any bits other than CR0.TS or CR0.MP";
-    case 0x66: return "Read of IDTR";
-    case 0x67: return "Read of GDTR";
-    case 0x68: return "Read of LDTR";
-    case 0x69: return "Read of TR";
-    case 0x6A: return "Write of IDTR";
-    case 0x6B: return "Write of GDTR";
-    case 0x6C: return "Write of LDTR";
-    case 0x6D: return "Write of TR";
-    case 0x6E: return "RDTSC instruction";
-    case 0x6F: return "RDPMC instruction";
-    case 0x70: return "PUSHF instruction";
-    case 0x71: return "POPF instruction";
-    case 0x72: return "CPUID instruction";
-    case 0x73: return "RSM instruction";
-    case 0x74: return "IRET instruction";
-    case 0x75: return "Software interrupt (INTn instructions)";
-    case 0x76: return "INVD instruction";
-    case 0x77: return "PAUSE instruction";
-    case 0x78: return "HLT instruction";
-    case 0x79: return "INVLPG instructions";
-    case 0x7A: return "INVLPGA instruction";
-    case 0x7B: return "IN or OUT accessing protected port";
-    case 0x7C: return "RDMSR or WRMSR access to protected MSR";
-    case 0x7D: return "Task switch";
-    case 0x7E: return "FP error freeze";
-    case 0x7F: return "Shutdown";
-    case 0x80: return "VMRUN instruction";
-    case 0x81: return "VMMCALL instruction";
-    case 0x82: return "VMLOAD instruction";
-    case 0x83: return "VMSAVE instruction";
-    case 0x84: return "STGI instruction";
-    case 0x85: return "CLGI instruction";
-    case 0x86: return "SKINIT instruction";
-    case 0x87: return "RDTSCP instruction";
-    case 0x88: return "ICEBP instruction";
-    case 0x89: return "WBINVD or WBNOINVD instruction";
-    case 0x8A: return "MONITOR or MONITORX instruction";
-    case 0x8B: return "MWAIT or MWAITX instruction";
-    case 0x8C: return "MWAIT or MWAITX instruction, if monitor hardware is armed.";
-    case 0x8E: return "RDPRU instruction";
-    case 0x8D: return "XSETBV instruction";
-    case 0x8F: return "Write of EFER MSR";
-    case 0xA3: return "MCOMMIT instruction";
-    case 0x400: return "Nested paging host-level page fault";
-    case 0x401: return "AVIC Virtual IPI delivery not completed";
-    case 0x402: return "AVIC Access to unaccelerated vAPIC register";
-    case 0x403: return "VMGEXIT instruction";
-    case -1U: return "Invalid guest state in VMCB";
-    default: return nullptr;
-  }
-}
-
-void
-Svm_state::dump(l4_vcpu_regs_t const *regs) const
-{
-  warn().printf("Registers:\n");
-  warn().printf("r15=0x%lx\n", regs->r15);     /**< r15 register */
-  warn().printf("r14=0x%lx\n", regs->r14);     /**< r14 register */
-  warn().printf("r13=0x%lx\n", regs->r13);     /**< r13 register */
-  warn().printf("r12=0x%lx\n", regs->r12);     /**< r12 register */
-  warn().printf("r11=0x%lx\n", regs->r11);     /**< r11 register */
-  warn().printf("r10=0x%lx\n", regs->r10);     /**< r10 register */
-  warn().printf("r9=0x%lx\n", regs->r9);      /**< r9 register */
-  warn().printf("r8=0x%lx\n", regs->r8);      /**< r8 register */
-
-  warn().printf("di=0x%lx\n", regs->di);      /**< rdi register */
-  warn().printf("si=0x%lx\n", regs->si);      /**< rsi register */
-  warn().printf("bp=0x%lx\n", regs->bp);      /**< rbp register */
-  warn().printf("pfa=0x%lx\n", regs->pfa);     /**< page fault address */
-  warn().printf("bx=0x%lx\n", regs->bx);      /**< rbx register */
-  warn().printf("dx=0x%lx\n", regs->dx);      /**< rdx register */
-  warn().printf("cx=0x%lx\n", regs->cx);      /**< rcx register */
-  warn().printf("ax=0x%lx\n", regs->ax);      /**< rax register */
-
-  warn().printf("trapno=0x%lx\n", regs->trapno);  /**< trap number */
-  warn().printf("err=0x%lx\n", regs->err);     /**< error code */
-
-  warn().printf("ip=0x%lx\n", regs->ip);      /**< instruction pointer */
-  warn().printf("cs=0x%lx\n", regs->cs);      /**< dummy \internal */
-  warn().printf("flags=0x%lx\n", regs->flags);   /**< eflags */
-  warn().printf("sp=0x%lx\n", regs->sp);      /**< stack pointer */
-  warn().printf("ss=0x%lx\n", regs->ss);
-  warn().printf("fs_base=0x%lx\n", regs->fs_base);
-  warn().printf("gs_base=0x%lx\n", regs->gs_base);
-  warn().printf("ds=0x%x\n", regs->ds);
-  warn().printf("es=0x%x\n", regs->es);
-  warn().printf("fs=0x%x\n", regs->fs);
-  warn().printf("gs=0x%x\n", regs->gs);
-
-
-  warn().printf("Control area:\n");
-  warn().printf("intercept_rd_crX=0x%x\n", _vmcb->control_area.intercept_rd_crX);
-  warn().printf("intercept_wr_crX=0x%x\n", _vmcb->control_area.intercept_wr_crX);
-
-  warn().printf("intercept_rd_drX=0x%x\n", _vmcb->control_area.intercept_rd_drX);
-  warn().printf("intercept_wr_drX=0x%x\n", _vmcb->control_area.intercept_wr_drX);
-
-  warn().printf("intercept_exceptions=0x%x\n", _vmcb->control_area.intercept_exceptions);
-
-  warn().printf("intercept_instruction0=0x%x\n", _vmcb->control_area.intercept_instruction0);
-  warn().printf("intercept_instruction1=0x%x\n", _vmcb->control_area.intercept_instruction1);
-
-
-  warn().printf("pause_filter_threshold=0x%x\n", _vmcb->control_area.pause_filter_threshold);
-  warn().printf("pause_filter_count=0x%x\n", _vmcb->control_area.pause_filter_count);
-
-  warn().printf("iopm_base_pa=0x%llx\n", _vmcb->control_area.iopm_base_pa);
-  warn().printf("msrpm_base_pa=0x%llx\n", _vmcb->control_area.msrpm_base_pa);
-  warn().printf("tsc_offset=0x%llx\n", _vmcb->control_area.tsc_offset);
-  warn().printf("guest_asid_tlb_ctl=0x%llx\n", _vmcb->control_area.guest_asid_tlb_ctl);
-  warn().printf("interrupt_ctl=0x%llx\n", _vmcb->control_area.interrupt_ctl);
-  warn().printf("interrupt_shadow=0x%llx\n", _vmcb->control_area.interrupt_shadow);
-  warn().printf("exitcode=0x%llx\n", _vmcb->control_area.exitcode);
-  warn().printf("exitinfo1=0x%llx\n", _vmcb->control_area.exitinfo1);
-  warn().printf("exitinfo2=0x%llx\n", _vmcb->control_area.exitinfo2);
-  warn().printf("exitintinfo=0x%llx\n", _vmcb->control_area.exitintinfo);
-  warn().printf("np_enable=0x%llx\n", _vmcb->control_area.np_enable);
-
-
-  warn().printf("eventinj=0x%llx\n", _vmcb->control_area.eventinj);
-  warn().printf("n_cr3=0x%llx\n", _vmcb->control_area.n_cr3);
-  warn().printf("lbr_virtualization_enable=0x%llx\n", _vmcb->control_area.lbr_virtualization_enable);
-  warn().printf("clean_bits=0x%llx\n", _vmcb->control_area.clean_bits);
-  warn().printf("n_rip=0x%llx\n", _vmcb->control_area.n_rip);
-
-
-  warn().printf("State save area:\n");
-  warn().printf("es: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.es.selector,
-                _vmcb->state_save_area.es.attrib,
-                _vmcb->state_save_area.es.limit,
-                _vmcb->state_save_area.es.base);
-  warn().printf("cs: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.cs.selector,
-                _vmcb->state_save_area.cs.attrib,
-                _vmcb->state_save_area.cs.limit,
-                _vmcb->state_save_area.cs.base);
-  warn().printf("ss: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.ss.selector,
-                _vmcb->state_save_area.ss.attrib,
-                _vmcb->state_save_area.ss.limit,
-                _vmcb->state_save_area.ss.base);
-  warn().printf("ds: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.ds.selector,
-                _vmcb->state_save_area.ds.attrib,
-                _vmcb->state_save_area.ds.limit,
-                _vmcb->state_save_area.ds.base);
-  warn().printf("fs: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.fs.selector,
-                _vmcb->state_save_area.fs.attrib,
-                _vmcb->state_save_area.fs.limit,
-                _vmcb->state_save_area.fs.base);
-  warn().printf("gs: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.gs.selector,
-                _vmcb->state_save_area.gs.attrib,
-                _vmcb->state_save_area.gs.limit,
-                _vmcb->state_save_area.gs.base);
-  warn().printf("gdtr: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.gdtr.selector,
-                _vmcb->state_save_area.gdtr.attrib,
-                _vmcb->state_save_area.gdtr.limit,
-                _vmcb->state_save_area.gdtr.base);
-  warn().printf("ldtr: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.ldtr.selector,
-                _vmcb->state_save_area.ldtr.attrib,
-                _vmcb->state_save_area.ldtr.limit,
-                _vmcb->state_save_area.ldtr.base);
-  warn().printf("idtr: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.idtr.selector,
-                _vmcb->state_save_area.idtr.attrib,
-                _vmcb->state_save_area.idtr.limit,
-                _vmcb->state_save_area.idtr.base);
-  warn().printf("tr: selector=0x%x, attrib=0x%x, limit=0x%x, base=0x%llx)\n",
-                _vmcb->state_save_area.tr.selector,
-                _vmcb->state_save_area.tr.attrib,
-                _vmcb->state_save_area.tr.limit,
-                _vmcb->state_save_area.tr.base);
-
-
-  warn().printf("cpl=0x%x\n", _vmcb->state_save_area.cpl);
-
-
-  warn().printf("efer=0x%llx\n", _vmcb->state_save_area.efer);
-
-
-  warn().printf("cr4=0x%llx\n", _vmcb->state_save_area.cr4);
-  warn().printf("cr3=0x%llx\n", _vmcb->state_save_area.cr3);
-  warn().printf("cr0=0x%llx\n", _vmcb->state_save_area.cr0);
-  warn().printf("dr7=0x%llx\n", _vmcb->state_save_area.dr7);
-  warn().printf("dr6=0x%llx\n", _vmcb->state_save_area.dr6);
-  warn().printf("rflags=0x%llx\n", _vmcb->state_save_area.rflags);
-  warn().printf("rip=0x%llx\n", _vmcb->state_save_area.rip);
-
-
-  warn().printf("rsp=0x%llx\n", _vmcb->state_save_area.rsp);
-
-
-  warn().printf("rax=0x%llx\n", _vmcb->state_save_area.rax);
-  warn().printf("star=0x%llx\n", _vmcb->state_save_area.star);
-  warn().printf("lstar=0x%llx\n", _vmcb->state_save_area.lstar);
-  warn().printf("cstar=0x%llx\n", _vmcb->state_save_area.cstar);
-  warn().printf("sfmask=0x%llx\n", _vmcb->state_save_area.sfmask);
-  warn().printf("kernelgsbase=0x%llx\n", _vmcb->state_save_area.kernelgsbase);
-  warn().printf("sysenter_cs=0x%llx\n", _vmcb->state_save_area.sysenter_cs);
-  warn().printf("sysenter_esp=0x%llx\n", _vmcb->state_save_area.sysenter_esp);
-  warn().printf("sysenter_eip=0x%llx\n", _vmcb->state_save_area.sysenter_eip);
-  warn().printf("cr2=0x%llx\n", _vmcb->state_save_area.cr2);
-
-
-  warn().printf("g_pat=0x%llx\n", _vmcb->state_save_area.g_pat);
-  warn().printf("dbgctl=0x%llx\n", _vmcb->state_save_area.dbgctl);
-  warn().printf("br_from=0x%llx\n", _vmcb->state_save_area.br_from);
-  warn().printf("br_to=0x%llx\n", _vmcb->state_save_area.br_to);
-  warn().printf("lastexcpfrom=0x%llx\n", _vmcb->state_save_area.lastexcpfrom);
-  warn().printf("last_excpto=0x%llx\n", _vmcb->state_save_area.last_excpto);
-
-  // this field is _NOT_ part of the official VMCB specification
-  // a (userlevel) VMM needs this for proper FPU state virtualization
-  warn().printf("xcr0=0x%llx\n", _vmcb->state_save_area.xcr0);
-}
-
-} //namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.h
deleted file mode 100644
index 5fd072d1..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_svm.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (C) 2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "vm_state.h"
-#include "debug.h"
-#include "pt_walker.h"
-#include "event_recorder.h"
-
-namespace Vmm {
-
-class Svm_state : public Vm_state
-{
-public:
-  enum Cpuid_svm
-  {
-    /// Indicates support for NEXT_RIP save on #VMEXIT.
-    Cpuid_svm_feature_nrips          = 1UL << 3,
-    /// Indicates support for the decode assists.
-    Cpuid_svm_feature_decode_assists = 1UL << 7,
-  };
-
-  enum class Exit
-  {
-    Cr0_read = 0x00, // Cr_access
-    Cr15_read = 0x0f, // Cr_access
-    Cr0_write = 0x10, // Cr_access
-    Cr15_write = 0x1f, // Cr_access
-    Dr0_read = 0x20,   // DR access
-    Dr1_read,
-    Dr2_read,
-    Dr3_read,
-    Dr4_read,
-    Dr5_read,
-    Dr6_read,
-    Dr7_read,
-    Dr8_read,
-    Dr9_read,
-    Dr10_read,
-    Dr11_read,
-    Dr12_read,
-    Dr13_read,
-    Dr14_read,
-    Dr15_read = 0x2f,  // DR access
-    Dr0_write = 0x30,  // DR access
-    Dr1_write,
-    Dr2_write,
-    Dr3_write,
-    Dr4_write,
-    Dr5_write,
-    Dr6_write,
-    Dr7_write,
-    Dr8_write,
-    Dr9_write,
-    Dr10_write,
-    Dr11_write,
-    Dr12_write,
-    Dr13_write,
-    Dr14_write,
-    Dr15_write = 0x3f, // DR access
-    Excp_0 = 0x40, // Exception_or_nmi
-    Excp_31 = 0x5f, // Exception_or_nmi
-    Intr = 0x60, // ??? Physical interrupt (maskable) -> directly handled by Fiasco!
-    Nmi = 0x61, // ??? Exception_or_nmi
-    Vintr = 0x64, // ??? Virtual interrupt
-    Cr0_sel_write = 0x65, // Cr_access
-    Rdpmc = 0x6f,  // RDPMC instruction
-    Cpuid = 0x72, // Cpuid
-    Sw_int = 0x75, // INTn instruction
-    Hlt = 0x78, // Exec_halt
-    Ioio = 0x7b, // Io_access
-    Msr = 0x7c, // Exec_rdmsr and Exec_wrmsr
-    Shutdown = 0x7f, // Shutdown event
-    Vmrun = 0x80,   // VMRUN instruction
-    Vmmcall = 0x81, // Exec_vmcall
-    Vmload = 0x82,  // VMLOAD instruction
-    Vmsave = 0x83,  // VMSAVE instruction
-    Stgi = 0x84,    // STGI instruction
-    Clgi = 0x85,    // CLGI instruction
-    Skinit = 0x86,    // SKINIT instruction
-    Rdtscp = 0x87,    // RDTSCP instruction
-    Icebp = 0x88, // INT1 instruction
-    Xsetbv = 0x8d, // Exec_xsetbv, write to xcr0 field in guest_state
-    Cr0_write_trap = 0x90, // Cr_access
-    Cr15_write_trap = 0x9f, // Cr_access
-
-    Nested_page_fault = 0x400, // Ept_violation
-
-    // TODO: intercept FERR_FREEZE event
-    // TODO: intercept INTR/NMI/SMI/INIT
-    // TODO: intercept INVD
-    // TODO: intercept task switch
-    // TODO: intercept iopm and msrpm
-    // TODO: intercept MONITOR/MWAIT
-    // TODO: intercept #AC and #DB (expections)
-  };
-
-  enum Intercept_inst0
-  {
-    Intercept_intr          = 1 << 0,
-    Intercept_nmi           = 1 << 1,
-    Intercept_smi           = 1 << 2,
-    Intercept_init          = 1 << 3,
-    Intercept_vintr         = 1 << 4,
-    Intercept_cr0_sel_write = 1 << 5,
-    Intercept_rdpmc         = 1 << 15,
-    Intercept_cpuid         = 1 << 18,
-    Intercept_invd          = 1 << 22,
-    Intercept_hlt           = 1 << 24,
-    Intercept_ioio          = 1 << 27,
-    Intercept_msr           = 1 << 28,
-    Intercept_task_switch   = 1 << 29,
-    Intercept_freeze        = 1 << 30,
-    Intercept_shutdown      = 1 << 31,
-  };
-
-  enum Intercept_inst1
-  {
-    Intercept_vmrun           = 1 << 0,
-    Intercept_vmmcall         = 1 << 1,
-    Intercept_vmload          = 1 << 2,
-    Intercept_vmsave          = 1 << 3,
-    Intercept_stgi            = 1 << 4,
-    Intercept_clgi            = 1 << 5,
-    Intercept_skinit          = 1 << 6,
-    Intercept_rdtscp          = 1 << 7,
-    Intercept_icebp           = 1 << 8,
-    Intercept_wbinvd_wbnoinvd = 1 << 9,
-    Intercept_monitor         = 1 << 10,
-    Intercept_mwait           = 1 << 11,
-    Intercept_mwait_mon       = 1 << 12,
-    Intercept_xsetbv          = 1 << 13,
-    Intercept_rdpru           = 1 << 14,
-    Intercept_efer_write      = 1 << 15,
-    Intercept_cr0_cr15_write  = 0xffff << 16,
-  };
-
-  enum Efer
-  {
-    Efer_lme         = 1 << 8,
-    Efer_lma         = 1 << 10,
-    Efer_svme_enable = 1 << 12,
-
-    // TODO: Efer has some additional bits above on AMD
-    Efer_guest_write_mask = 0xd01,
-  };
-
-  enum Cr0 : unsigned long
-  {
-    Cr0_pe = 1UL << 0,
-    Cr0_pg = 1UL << 31,
-  };
-
-  enum Decode_assist : unsigned long long
-  {
-    Cr_gpr_mask = 0xf,
-    Cr_valid    = 1ULL << 63,
-  };
-
-  enum Flags : unsigned long
-  {
-    Interrupt_enabled = (1UL << 9),
-    Virtual_8086_mode = (1UL << 17),
-  };
-
-  struct Io_info
-  {
-    l4_uint32_t raw;
-    explicit Io_info(l4_uint32_t val) : raw(val) {}
-
-    CXX_BITFIELD_MEMBER( 0,  0, type, raw);
-    CXX_BITFIELD_MEMBER( 2,  2, str, raw);
-    CXX_BITFIELD_MEMBER( 3,  3, rep, raw);
-    CXX_BITFIELD_MEMBER( 4,  4, sz8, raw);
-    CXX_BITFIELD_MEMBER( 5,  5, sz16, raw);
-    CXX_BITFIELD_MEMBER( 6,  6, sz32, raw);
-    CXX_BITFIELD_MEMBER( 7,  7, a16, raw);
-    CXX_BITFIELD_MEMBER( 8,  8, a32, raw);
-    CXX_BITFIELD_MEMBER( 9,  9, a64, raw);
-    CXX_BITFIELD_MEMBER( 4,  6, data_size, raw);
-    CXX_BITFIELD_MEMBER( 7,  9, addr_size, raw);
-    CXX_BITFIELD_MEMBER(10, 12, seg, raw);
-    CXX_BITFIELD_MEMBER(16, 31, port, raw);
-  };
-
-  struct Npf_info
-  {
-    l4_uint64_t raw;
-    explicit Npf_info(l4_uint64_t val) : raw(val) {}
-
-    CXX_BITFIELD_MEMBER(0, 0, present, raw);
-    CXX_BITFIELD_MEMBER(1, 1, write, raw);
-    CXX_BITFIELD_MEMBER(2, 2, user, raw);
-    CXX_BITFIELD_MEMBER(4, 4, inst, raw);
-  };
-
-  struct Interrupt_ctl
-  {
-    l4_uint64_t raw;
-    explicit Interrupt_ctl(l4_uint64_t val) : raw(val) {}
-
-    CXX_BITFIELD_MEMBER( 0,  7, v_tpr, raw);
-    CXX_BITFIELD_MEMBER( 8,  8, v_irq, raw);
-    CXX_BITFIELD_MEMBER(16, 19, v_intr_prio, raw);
-    CXX_BITFIELD_MEMBER(20, 20, v_ign_tpr, raw);
-    CXX_BITFIELD_MEMBER(32, 39, v_intr_vector, raw);
-  };
-
-  Svm_state(void *vmcb) : _vmcb(static_cast(vmcb)) {}
-  ~Svm_state() = default;
-
-  Type type() const override
-  { return Type::Svm; }
-
-  enum Clean_bits
-  {
-    Vmcb_i    = 1 << 0,  // Intercepts: all the intercept vectors, TSC offset, Pause Filter Count
-    Vmcb_iopm = 1 << 1,  // IOMSRPM: IOPM_BASE, MSRPM_BASE
-    Vmcb_asid = 1 << 2,  // ASID
-    Vmcb_tpr  = 1 << 3,  // V_TPR, V_IRQ, V_INTR_PRIO, V_IGN_TPR, V_INTR_MASKING, V_INTR_VECTOR (Offset 60h–67h)
-    Vmcb_np   = 1 << 4,  // Nested Paging: NCR3, PAT, Nested_Paging_En
-    Vmcb_crx  = 1 << 5,  // CR0, CR3, CR4, EFER
-    Vmcb_drx  = 1 << 6,  // DR6, DR7
-    Vmcb_dt   = 1 << 7,  // GDT/IDT Limit and Base
-    Vmcb_seg  = 1 << 8,  // CS/DS/SS/ES Sel/Base/Limit/Attr, CPL
-    Vmcb_cr2  = 1 << 9,  // CR2
-    Vmcb_lbr  = 1 << 10, // DbgCtlMsr, br_from/to, lastint_from/to
-    Vmcb_avic = 1 << 11, // AVIC APIC_BAR; AVIC APIC_BACKING_PAGE, AVIC PHYSICAL_TABLE and AVIC LOGICAL_TABLE Pointers
-  };
-
-  void mark_all_clean()
-  { _vmcb->control_area.clean_bits = ~0U; }
-
-  void mark_all_dirty()
-  { _vmcb->control_area.clean_bits = 0U; }
-
-  void mark_dirty(Clean_bits bits)
-  { _vmcb->control_area.clean_bits &= ~bits; }
-
-  void init_state() override;
-  void setup_linux_protected_mode(l4_addr_t entry,
-                                  l4_addr_t stack_addr) override;
-  void setup_real_mode(l4_addr_t entry) override;
-
-  Injection_event pending_event_injection() override
-  {
-    return Injection_event(_vmcb->control_area.exitintinfo);
-  }
-
-  void invalidate_pending_event()
-  {
-    _vmcb->control_area.exitintinfo &=
-      ~(1 << Injection_event::valid_bfm_t::Lsb);
-  }
-
-  bool pf_write() const override
-  { return Npf_info(_vmcb->control_area.exitinfo1).write(); }
-
-  l4_umword_t ip() const override
-  { return _vmcb->state_save_area.rip; }
-
-  l4_umword_t sp() const override
-  { return _vmcb->state_save_area.rsp; }
-
-  l4_umword_t cr3() const override
-  { return _vmcb->state_save_area.cr3; }
-
-  l4_uint64_t xcr0() const override
-  { return _vmcb->state_save_area.xcr0; }
-
-  bool determine_next_ip_from_ip(l4_vcpu_regs_t *regs, unsigned char *inst_buf,
-                                 unsigned inst_buf_len);
-
-  void jump_instruction()
-  {
-    if (_vmcb->control_area.n_rip == 0)
-      warn().printf("Next instruction pointer is zero: rip=0x%llx -> nrip=0x%llx\n",
-                    _vmcb->state_save_area.rip, _vmcb->control_area.n_rip);
-
-    _vmcb->state_save_area.rip = _vmcb->control_area.n_rip;
-  }
-
-  Exit exit_code() const
-  { return Exit(_vmcb->control_area.exitcode); }
-
-  l4_uint64_t exit_info1() const
-  { return _vmcb->control_area.exitinfo1; }
-
-  l4_uint64_t exit_info2() const
-  { return _vmcb->control_area.exitinfo2; }
-
-  l4_vm_svm_vmcb_t *vmcb() const
-  { return _vmcb; }
-
-  bool is_halted() const
-  { return halted; }
-
-  void halt()
-  { halted = true; }
-
-  void resume()
-  { halted = false; }
-
-  bool interrupts_enabled() const
-  {
-    // TODO: Instead we could use interrupt_shadow bit 1 here = GUEST_INTERRUPT_MASK
-    return (_vmcb->state_save_area.rflags & Interrupt_enabled)
-           && !(_vmcb->control_area.interrupt_shadow & 1);
-  }
-
-  void clear_sti_shadow()
-  { _vmcb->control_area.interrupt_shadow &= (-1ULL << 1); }
-
-  /**
-   * Check if there is an event currently being injected.
-   *
-   * \return true  iff an event is in the process of being injected
-   */
-  bool event_injected() const
-  { return Svm_event_info(_vmcb->control_area.eventinj).valid(); }
-
-  /**
-   * This function checks if interrupts are enabled and no event injection is
-   * in flight.
-   *
-   * \return true  iff we can inject in an interrupt into the guest
-   */
-  bool can_inject_interrupt() const override
-  { return interrupts_enabled() && !event_injected(); }
-
-  void disable_interrupt_window() override
-  {
-    // Disable dummy virtual interrupt
-    Interrupt_ctl int_ctl(_vmcb->control_area.interrupt_ctl);
-    int_ctl.v_irq() = 0;
-    int_ctl.v_ign_tpr() = 0;
-    _vmcb->control_area.interrupt_ctl = int_ctl.raw;
-    mark_dirty(Vmcb_tpr);
-  }
-
-  void enable_interrupt_window() override
-  {
-    // Add dummy virtual interrupt, so that we get notified via the VINTR
-    // intercept, once the guest is ready to receive interrupts.
-    Interrupt_ctl int_ctl(_vmcb->control_area.interrupt_ctl);
-    int_ctl.v_irq() = 1;
-    int_ctl.v_intr_vector() = 0;
-    int_ctl.v_ign_tpr() = 1;
-    _vmcb->control_area.interrupt_ctl = int_ctl.raw;
-    mark_dirty(Vmcb_tpr);
-  }
-
-
-  /**
-   * Injecting NMIs is currently not supported on SVM, as in case something
-   * prevents an NMI from being injected (for example interrupt shadow), we
-   * would have to single-step the guest until the NMI injection is possible.
-   * In addition, we would have to intercept IRET to track NMI completion.
-   *
-   * Starting with Zen4, AMD SVM supports VNMI for efficient injection of NMIs.
-   */
-  bool can_inject_nmi() const override
-  { /* TODO */ return false; }
-
-  void disable_nmi_window() override
-  { /* TODO */ }
-
-  void enable_nmi_window() override
-  { /* TODO */ }
-
-  struct Svm_event_info
-  {
-    enum class Int_type : unsigned
-    {
-      External_interrupt = 0,
-      NMI = 2,
-      Exception = 3,
-      Software_interrupt = 4,
-    };
-
-    l4_uint64_t field;
-    CXX_BITFIELD_MEMBER(0, 7, vector, field);
-    CXX_BITFIELD_MEMBER(8, 10, type, field);
-    CXX_BITFIELD_MEMBER(11, 11, error_valid, field);
-    CXX_BITFIELD_MEMBER(31, 31, valid, field);
-    CXX_BITFIELD_MEMBER(32, 63, error_code, field);
-
-    Svm_event_info(l4_uint64_t raw) : field(raw) {}
-
-    Svm_event_info(unsigned i, Int_type t, unsigned err_valid = 0,
-                       l4_uint32_t err_code = 0, unsigned v = 1)
-    : field(0)
-    {
-      vector() = i;
-      type() = static_cast(t);
-      error_valid() = err_valid;
-      valid() = v;
-      error_code() = err_code;
-    }
-  };
-
-  enum Deliver_error_code : unsigned
-  {
-    No_error_code = 0,
-    Push_error_code = 1,
-  };
-
-  void inject_event(Injection_event const &ev) override
-  {
-    assert(ev.valid());
-    _vmcb->control_area.eventinj = ev.raw;
-  }
-
-  void inject_event(int event_num, Svm_event_info::Int_type type,
-                    Deliver_error_code deliver_err = No_error_code,
-                    l4_uint32_t err_code = 0)
-  {
-    Svm_event_info info(event_num, type, deliver_err, err_code);
-
-    if (0)
-      warn().printf(
-        "-------------- Injecting interrupt/event 0x%x -> (0x%llx)\n",
-        event_num, info.field);
-
-    _vmcb->control_area.eventinj = info.field;
-  }
-
-  int handle_cr0_write(l4_vcpu_regs_t *regs);
-  int handle_xsetbv(l4_vcpu_regs_t *regs);
-
-  bool read_msr(unsigned msr, l4_uint64_t *value) const override;
-  bool write_msr(unsigned msr, l4_uint64_t value, Event_recorder *) override;
-
-  int handle_hardware_exception(Event_recorder *ev_rec, unsigned num);
-
-  l4_umword_t read_gpr(l4_vcpu_regs_t *regs, unsigned reg) const;
-
-  static const char *str_exit_code(Exit exit);
-
-  void dump(l4_vcpu_regs_t const *regs) const;
-
-  void advance_entry_ip(unsigned bytes) override
-  { _vmcb->control_area.n_rip += bytes; }
-
-  void additional_failure_info(unsigned /* vcpu_id */) {}
-
-private:
-  static Dbg warn()
-  { return Dbg(Dbg::Cpu, Dbg::Warn, "SVM"); }
-
-  static Dbg info()
-  { return Dbg(Dbg::Cpu, Dbg::Info, "SVM"); }
-
-  static Dbg trace()
-  { return Dbg(Dbg::Cpu, Dbg::Trace, "SVM"); }
-
-  l4_vm_svm_vmcb_t *_vmcb;
-  bool halted = false;
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.cc
deleted file mode 100644
index e29dd999..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.cc
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2020-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include "vm_state_vmx.h"
-#include "consts.h"
-#include "event_recorder.h"
-
-namespace Vmm {
-
-Vm_state::~Vm_state() = default;
-
-enum : unsigned long
-{
-  Misc_enable_fast_string = 1UL,
-
-  Cr0_pe_bit = 1UL,
-  Cr0_pg_bit = 1UL << 31,
-
-  Cr4_pae_bit = 1UL << 5,
-  Cr4_la57_bit = 1UL << 12,
-
-  Efer_syscall_enable_bit = 1UL,
-  Efer_lme_bit = 1UL << 8,
-  Efer_lma_bit = 1UL << 10,
-  Efer_nxe_bit = 1UL << 11,
-  // EFER.LMA writes are ignored. Other bits reserved.
-  Efer_write_mask = Efer_syscall_enable_bit | Efer_lme_bit | Efer_nxe_bit,
-
-  Entry_ctrl_ia32e_bit = 1UL << 9,
-};
-
-Vmx_state::Vmx_state(l4_vm_vmx_vcpu_state_t *state)
-: _state(state),
-  _vmcs(&state->vmcs),
-  _hw_vmcs(L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                        "Failed to allocate hardware VMCS capability."))
-{
-  // Create the hardware VMCS
-  auto *env = L4Re::Env::env();
-  auto ret = env->factory()->create(_hw_vmcs.get(), L4_PROTO_VCPU_CONTEXT);
-  if (l4_error(ret) < 0)
-    L4Re::chksys(ret, "Cannot create guest VM hardware VMCS. Virtualization "
-                      "support may be missing.");
-
-  if (nested_abi_revision() != 0)
-    info().printf("vCPU interface supports nested virtualization. However, "
-                  "uvmm does not implement nested virtualization.\n");
-}
-
-/**
- * Handle exits due to HW/SW exceptions, NMIs, and external interrupts.
- *
- * Bit 11, error_valid, is not set if, an external interrupt occurred and
- * 'acknowledge interrupt on exit' is not set in the exit controls.
- */
-int
-Vmx_state::handle_exception_nmi_ext_int(Event_recorder *ev_rec)
-{
-  Vm_exit_int_info interrupt_info = exit_int_info();
-
-  l4_uint32_t interrupt_error = 0;
-  if (interrupt_info.error_valid())
-    interrupt_error =
-      (l4_uint32_t)vmx_read(VMCS_VM_EXIT_INTERRUPT_ERROR);
-
-  trace().printf("Exception, NMI or external interrupt exit: 0x%x/0x%x\n",
-                 interrupt_info.field, (unsigned)interrupt_error);
-
-  switch ((interrupt_info.type()))
-    {
-    // Pin-based controlls not set, Ext_int and NMI should not happen.
-    case 0x0: warn().printf("External interrupt\n"); break;
-    case 0x2: warn().printf("NMI\n"); break;
-
-    case 0x3:
-      return handle_hardware_exception(ev_rec, interrupt_info.vector(),
-                                       interrupt_error);
-
-    case 0x4: // software interrupt: INT n
-      // Software interrupt event record
-      using Event_sw_int = Event_sw_generic<4>;
-
-      ev_rec->make_add_event(Event_prio::Sw_intN,
-                                           interrupt_info.vector(),
-                                           2U); // opcode + operand
-      return Retry;
-
-    case 0x5: // priviledged software exception: INT1
-      // Priveledged software exception event record
-      using Event_priv_sw_exc = Event_sw_generic<5>;
-
-      ev_rec->make_add_event(Event_prio::Sw_int1, 1, 1U);
-      return Retry;
-
-    case 0x6: // software exception: INT3, INTO
-      {
-        // Software exception event record
-        using Event_sw_exc = Event_sw_generic<6>;
-
-        unsigned vec = interrupt_info.vector();
-        if (vec == 3)
-          {
-            ev_rec->make_add_event(Event_prio::Sw_int3, vec, 1U);
-            return Retry;
-          }
-        else if (vec == 4)
-          {
-            ev_rec->make_add_event(Event_prio::Sw_intO, vec, 1U);
-            return Retry;
-          }
-        else
-          // not defined in Intel SDM; leave this here as debug hint.
-          warn().printf("Unknown software exception %u\n", vec);
-
-      break;
-        }
-    default:
-      warn().printf("Unknown interrupt type: %u, vector: %u\n",
-                    interrupt_info.type().get(), interrupt_info.vector().get());
-      break;
-    }
-
-  return -L4_ENOSYS;
-}
-
-bool
-Vmx_state::read_msr(unsigned msr, l4_uint64_t *value) const
-{
-  unsigned shadow = msr_shadow_reg(msr);
-  if (shadow > 0)
-    {
-      *value = vmx_read(shadow);
-    }
-  else
-    {
-      switch (msr)
-        {
-        case 0x17: // IA32_PLATFORM_ID
-          *value = 0U;
-          break;
-        case 0x1a0: // IA32_MISC_ENABLE
-          *value = Misc_enable_fast_string;
-          break;
-        case 0x3a: // IA32_FEATURE_CONTROL
-          // Lock register so the guest does not try to enable anything.
-          *value = 1U;
-          break;
-        case 0x277: // IA32_PAT
-          *value = vmx_read(VMCS_GUEST_IA32_PAT);
-          break;
-        case 0xc0000080: // efer
-          *value = vmx_read(VMCS_GUEST_IA32_EFER);
-          break;
-
-        /*
-         * Non-architectural MSRs known to be probed by Linux that can be
-         * safely ignored:
-         *   0xce // MSR_PLATFORM_INFO
-         *   0x33 // TEST_CTRL
-         *   0x34 // MSR_SMI_COUNT
-         *  0x140 // MISC_FEATURE_ENABLES
-         *  0x64e // MSR_PPERF
-         *  0x639 // MSR_PP0_ENERGY_STATUS
-         *  0x611 // MSR_PKG_ENERGY_STATUS
-         *  0x619 // MSR_DRAM_ENERGY_STATUS
-         *  0x641 // MSR_PP1_ENERGY_STATUS
-         *  0x64d // MSR_PLATFORM_ENERGY_COUNTER
-         *  0x606 // MSR_RAPL_POWER_UNIT
-         */
-        default:
-          return false;
-        }
-    }
-
-  return true;
-}
-
-bool
-Vmx_state::write_msr(unsigned msr, l4_uint64_t value, Event_recorder *ev_rec)
-{
-  unsigned shadow = msr_shadow_reg(msr);
-  if (shadow > 0)
-    {
-      vmx_write(shadow, value);
-      return true;
-    }
-
-  switch (msr)
-    {
-    case 0x277: // IA32_PAT
-      // sanitization of 7 PAT values
-      // 0xF8 are reserved bits
-      // 0x2 and 0x3 are reserved encodings
-      // usage of reserved bits and encodings results in a #GP
-      if (value & 0xF8F8F8F8F8F8F8F8ULL)
-        {
-          ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-          break;
-        }
-
-      for (unsigned i = 0; i < 7; ++i)
-        {
-          l4_uint64_t const PAi_mask = (value & (0x7ULL << i * 8)) >> i * 8;
-          if ((PAi_mask == 0x2ULL) || (PAi_mask == 0x3ULL))
-            {
-              ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-              break;
-            }
-        }
-
-      vmx_write(VMCS_GUEST_IA32_PAT, value);
-      break;
-    case 0xc0000080: // efer
-      {
-        l4_uint64_t old_efer = vmx_read(VMCS_GUEST_IA32_EFER);
-        // LMA writes are ignored.
-        l4_uint64_t efer = (value & Efer_write_mask) | (old_efer & Efer_lma_bit);
-        l4_uint64_t cr0 = vmx_read(VMCS_GUEST_CR0);
-
-        trace().printf("IA32_EFER write: CR0: 0x%llx, old efer 0x%llx, "
-                      "new efer 0x%llx\n",
-                      cr0, old_efer, efer);
-
-        if (cr0 & Cr0_pg_bit)
-          {
-            // Can't change LME while CR0.PG is set. SDM vol 3. 4.1
-            if ((efer & Efer_lme_bit) != (old_efer & Efer_lme_bit))
-              {
-                // Inject GPF and do not write IA32_EFER
-                ev_rec->make_add_event(Event_prio::Exception, 13, 0);
-                break;
-              }
-          }
-
-        vmx_write(VMCS_GUEST_IA32_EFER, efer);
-        break;
-      }
-    case 0x8b: // IA32_BIOS_SIGN_ID
-    case 0x140:  // unknown in Intel 6th gen, but MISC_FEATURE register for xeon
-      break;
-    case 0x1a0:
-      warn().printf("Writing MSR 0x%x IA32_MISC_ENABLED 0x%llx\n", msr, value);
-      break;
-    case 0xe01: // MSR_UNC_PERF_GLOBAL_CTRL
-      // can all be savely ignored
-      break;
-
-    default:
-      return false;
-    }
-
-  return true;
-}
-
-int
-Vmx_state::handle_cr_access(l4_vcpu_regs_t *regs)
-{
-  auto qual = vmx_read(VMCS_EXIT_QUALIFICATION);
-  int crnum;
-  l4_umword_t newval;
-
-  switch ((qual >> 4) & 3)
-    {
-    case 0: // mov to cr
-      crnum = qual & 0xF;
-      switch ((qual >> 8) & 0xF)
-        {
-        case 0: newval = regs->ax; break;
-        case 1: newval = regs->cx; break;
-        case 2: newval = regs->dx; break;
-        case 3: newval = regs->bx; break;
-        case 4: newval = vmx_read(VMCS_GUEST_RSP); break;
-        case 5: newval = regs->bp; break;
-        case 6: newval = regs->si; break;
-        case 7: newval = regs->di; break;
-        case 8: newval = regs->r8; break;
-        case 9: newval = regs->r9; break;
-        case 10: newval = regs->r10; break;
-        case 11: newval = regs->r11; break;
-        case 12: newval = regs->r12; break;
-        case 13: newval = regs->r13; break;
-        case 14: newval = regs->r14; break;
-        case 15: newval = regs->r15; break;
-        default:
-          warn().printf("Loading CR from unknown register\n");
-          return -L4_EINVAL;
-        }
-      break;
-    case 2: // clts
-      crnum = 0;
-      newval = vmx_read(VMCS_GUEST_CR0) & ~(1ULL << 3);
-      break;
-    default:
-      warn().printf("Unknown CR action %lld.\n", (qual >> 4) & 3);
-      return -L4_EINVAL;
-    }
-
-  switch (crnum)
-    {
-    case 0:
-      {
-        auto old_cr0 = vmx_read(VMCS_GUEST_CR0);
-        trace().printf("Write to cr0: 0x%llx -> 0x%lx\n", old_cr0, newval);
-
-        l4_uint64_t cr4 = vmx_read(VMCS_GUEST_CR4);
-        l4_uint64_t efer = vmx_read(VMCS_GUEST_IA32_EFER);
-
-        // enable paging
-        if ((newval & Cr0_pg_bit) && !(old_cr0 & Cr0_pg_bit))
-          {
-            if (   (!(cr4 & Cr4_pae_bit) && (efer & Efer_lme_bit))
-                || (!(efer & Efer_lme_bit) && (cr4 & Cr4_la57_bit)))
-              {
-                // inject GPF and do not write CR0
-                return General_protection;
-              }
-
-            // LA57:   Cr4.PAE,  EFER.LME,  Cr4.LA57
-            // IA32e:  Cr4.PAE,  EFER.LME, !Cr4.LA57
-            // PAE:    Cr4.PAE, !EFER.LME, !Cr4.LA57
-            // 32bit: !Cr4.PAE, !EFER.LME, !Cr4.LA57
-            if ((cr4 & Cr4_pae_bit) && (efer & Efer_lme_bit))
-              {
-                if (cr4 & Cr4_la57_bit)
-                  info().printf("Enable LA57 paging\n");
-                else
-                  info().printf("Enable IA32e paging\n");
-
-                vmx_write(VMCS_VM_ENTRY_CTLS,
-                          vmx_read(VMCS_VM_ENTRY_CTLS) | Entry_ctrl_ia32e_bit);
-                // Contrary to SDM Vol 3, 24.8.1. IA32_EFER.LMA is not set to
-                // the value of ENTRY_CTLS.IA32e on VMentry.
-                vmx_write(VMCS_GUEST_IA32_EFER, efer | Efer_lma_bit);
-              }
-            else if (cr4 & Cr4_pae_bit) // && !EFER.LME
-                trace().printf("Enable PAE paging.\n");
-            else
-                trace().printf("Enable 32-bit paging\n");
-          }
-
-        // disable paging
-        if (!(newval & Cr0_pg_bit) && (old_cr0 & Cr0_pg_bit))
-          {
-            trace().printf("Disabling paging ...\n");
-
-            vmx_write(VMCS_VM_ENTRY_CTLS,
-                      vmx_read(VMCS_VM_ENTRY_CTLS) & ~Entry_ctrl_ia32e_bit);
-            // Contrary to SDM Vol 3, 24.8.1. IA32_EFER.LMA is not set to
-            // the value of ENTRY_CTLS.IA32e on VMentry.
-            vmx_write(VMCS_GUEST_IA32_EFER, efer & ~Efer_lma_bit);
-          }
-
-        // 0x10 => Extension Type; hardcoded to 1 see manual
-        vmx_write(VMCS_GUEST_CR0, newval | 0x10);
-        vmx_write(VMCS_CR0_READ_SHADOW, newval);
-        break;
-      }
-    case 4:
-      {
-        trace().printf("mov to cr4: 0x%lx, RIP 0x%lx\n", newval, ip());
-        l4_uint64_t old_cr4 = vmx_read(VMCS_GUEST_CR4);
-
-        if (vmx_read(VMCS_GUEST_CR0) & Cr0_pg_bit)
-          {
-            if ((newval & Cr4_la57_bit) != (old_cr4 & Cr4_la57_bit))
-              {
-                // inject GPF and do not write CR4
-                return General_protection;
-              }
-
-            l4_uint64_t efer = vmx_read(VMCS_GUEST_IA32_EFER);
-            if (!(newval & Cr4_pae_bit) && (efer & Efer_lme_bit))
-              {
-                // inject GPF and do not write CR4
-                return General_protection;
-              }
-            // !EFER.LME means either PAE or 32-bit paging. Transitioning
-            // between these two while Cr0.PG is set is allowed.
-          }
-
-        // We don't support 5-level page tables, be quirky and don't allow
-        // setting this bit. (Or fix page-table walker.)
-        if (newval & Cr4_la57_bit)
-          {
-            info().printf("Cr4 Guest wants to enable LA57. Filtering...\n");
-            newval &= ~Cr4_la57_bit;
-          }
-
-        // CR4 0x2000  = VMXEnable bit
-        // force VMXEnable bit, but hide it from guest
-        vmx_write(VMCS_GUEST_CR4, newval | 0x2000);
-        vmx_write(VMCS_CR4_READ_SHADOW, newval);
-        break;
-      }
-
-    default:
-      warn().printf("Unknown CR access.\n");
-      return -L4_EINVAL;
-    }
-
-  return Jump_instr;
-}
-
-int
-Vmx_state::handle_hardware_exception(Event_recorder *ev_rec, unsigned num,
-                                     l4_uint32_t err_code)
-{
-  if (in_real_mode())
-    {
-      // In real mode, exceptions do not push an error code.
-      ev_rec->make_add_event(Event_prio::Exception, num);
-      return Retry;
-    }
-
-  // Reflect all hardware exceptions to the guest. Exceptions pushing an error
-  // code are handled specially.
-  switch (num)
-    {
-    case 8:  // #DF
-    case 10: // #TS
-    case 11: // #NP
-    case 12: // #SS
-    case 13: // #GP
-    case 14: // #PF
-    case 17: // #AC
-    case 21: // #CP
-      ev_rec->make_add_event(Event_prio::Exception, num, err_code);
-      break;
-
-    case 1: // #DB
-      // #DB exceptions are either of fault type or of trap type. We reflect
-      // both to the guest, without changing state, thus don't change the IP.
-      [[fallthrough]];
-    default:
-      ev_rec->make_add_event(Event_prio::Exception, num);
-      break;
-    }
-
-  return Retry;
-}
-
-int
-Vmx_state::store_io_value(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                          Vmx_insn_info_field info, Mem_access::Width op_width,
-                          l4_uint32_t value)
-{
-  switch (op_width)
-    {
-    case Mem_access::Wd8:
-      return store_io_value_t(regs, ptw, info, value);
-    case Mem_access::Wd16:
-      return store_io_value_t(regs, ptw, info, value);
-    case Mem_access::Wd32:
-      return store_io_value_t(regs, ptw, info, value);
-    default:
-      break;
-    }
-
-  return Invalid_opcode;
-}
-
-int
-Vmx_state::load_io_value(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                         Vmx_insn_info_field info, Mem_access::Width op_width,
-                         l4_uint32_t *value)
-{
-  switch (op_width)
-    {
-    case Mem_access::Wd8:
-      return load_io_value_t(regs, ptw, info, value);
-    case Mem_access::Wd16:
-      return load_io_value_t(regs, ptw, info, value);
-    case Mem_access::Wd32:
-      return load_io_value_t(regs, ptw, info, value);
-    default:
-      break;
-    }
-
-  return Invalid_opcode;
-}
-
-int
-Vmx_state::rep_prefix_condition(l4_vcpu_regs_t *regs, Vmx_insn_info_field info,
-                                bool *next)
-{
-  // Prepare a mask for the register size.
-  l4_uint64_t mask;
-  int ret = address_size_mask(info.address_size(), &mask);
-  if (ret != Jump_instr)
-    return ret;
-
-  // Check the condition.
-  *next = (regs->cx & mask) != 0;
-
-  // Decrement the register.
-  if (*next)
-    regs->cx = (regs->cx & ~mask) | ((regs->cx - 1) & mask);
-
-  return Jump_instr;
-}
-
-bool
-Vmx_state::is_paging_enabled() const
-{
-  return vmx_read(VMCS_GUEST_CR0) & Cr0_pg_bit;
-}
-
-bool
-Vmx_state::in_real_mode() const
-{
-  return (vmx_read(VMCS_GUEST_CR0) & Cr0_pe_bit) == 0;
-}
-
-bool
-Vmx_state::in_long_mode() const
-{
-  return vmx_read(VMCS_GUEST_IA32_EFER) & Efer_lma_bit;
-}
-
-template 
-int
-Vmx_state::store_io_value_t(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                            Vmx_insn_info_field info, l4_uint32_t value)
-{
-  // Get the INS instruction argument and the offset register.
-  unsigned offset_reg;
-  TYPE *ptr;
-  int ret = get_io_argument(regs, ptw, info, true, &offset_reg, &ptr);
-  if (ret != Jump_instr)
-    return ret;
-
-  // Store the IO value to memory.
-  *ptr = value;
-
-  // Update the instruction argument (i.e. advance the offset register).
-  return advance_gpr(regs, offset_reg, info.address_size(), sizeof(TYPE));
-}
-
-template 
-int
-Vmx_state::load_io_value_t(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                           Vmx_insn_info_field info, l4_uint32_t *value)
-{
-  // Get the INS instruction argument and the offset register.
-  unsigned offset_reg;
-  TYPE *ptr;
-  int ret = get_io_argument(regs, ptw, info, false, &offset_reg, &ptr);
-  if (ret != Jump_instr)
-    return ret;
-
-  // Load the IO value from memory.
-  *value = *ptr;
-
-  // Update the instruction argument (i.e. advance the offset register).
-  return advance_gpr(regs, offset_reg, info.address_size(), sizeof(TYPE));
-}
-
-template 
-int
-Vmx_state::get_io_argument(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                           Vmx_insn_info_field info, bool store,
-                           unsigned *offset_reg, TYPE **ptr)
-{
-  // Non-paged modes are not supported.
-  if (!is_paging_enabled())
-    return Invalid_opcode;
-
-  unsigned segment_reg;
-
-  if (store)
-    {
-      // For INS, the address is always determined by ES:DI, ES:EDI or
-      // RDI.
-      segment_reg = 0;
-      *offset_reg = 7;
-    }
-  else
-    {
-      // For OUTS, the address offset is determined by SI, ESI or RSI. The
-      // segment register can be overriden by a segment prefix.
-      segment_reg = info.segment();
-      *offset_reg = 6;
-    }
-
-  l4_uint64_t offset;
-  int ret = read_gpr(regs, *offset_reg, &offset);
-  if (ret != Jump_instr)
-    return ret;
-
-  // Truncate the effective address according to the operand size.
-  switch (info.address_size())
-    {
-    case 0:
-      offset &= 0xffffU;
-      break;
-    case 1:
-      offset &= 0xffffffffU;
-      break;
-    case 2:
-      /* No op */
-      break;
-    default:
-      return Invalid_opcode;
-    }
-
-  // Compute the linear (guest-virtual) address (taking segmentation into
-  // account).
-  l4_uint64_t addr;
-  ret = compute_linear_addr(segment_reg, offset, true, &addr);
-  if (ret != Jump_instr)
-    return ret;
-
-  // Walk the page tables to convert the guest-virtual address to the
-  // host-virtual address.
-  *ptr = reinterpret_cast(ptw->walk(cr3(), addr));
-  return Jump_instr;
-}
-
-int
-Vmx_state::read_gpr(l4_vcpu_regs_t *regs, unsigned reg, l4_uint64_t *value)
-{
-  if (reg > 15)
-    return Invalid_opcode;
-
-  if (reg == 4)
-    *value = vmx_read(VMCS_GUEST_RSP);
-  else
-    *value = *(&(regs->ax) - reg);
-
-  return Jump_instr;
-}
-
-int
-Vmx_state::write_gpr(l4_vcpu_regs_t *regs, unsigned reg, l4_uint64_t value)
-{
-  if (reg > 15)
-    return Invalid_opcode;
-
-  if (reg == 4)
-    vmx_write(VMCS_GUEST_RSP, value);
-  else
-    *(&(regs->ax) - reg) = value;
-
-  return Jump_instr;
-}
-
-int
-Vmx_state::advance_gpr(l4_vcpu_regs_t *regs, unsigned reg,
-                       unsigned address_size, size_t advancement)
-{
-  // Determine the direction of the advancement.
-  bool decrement = vmx_read(VMCS_GUEST_RFLAGS) & Direction_bit;
-
-  // Prepare a mask for the register size.
-  l4_uint64_t mask;
-  int ret = address_size_mask(address_size, &mask);
-  if (ret != Jump_instr)
-    return ret;
-
-  // Advance the register value.
-  l4_uint64_t value;
-  ret = read_gpr(regs, reg, &value);
-  if (ret != Jump_instr)
-    return ret;
-
-  if (decrement)
-    value = (value & ~mask) | ((value - advancement) & mask);
-  else
-    value = (value & ~mask) | ((value + advancement) & mask);
-
-  return write_gpr(regs, reg, value);
-}
-
-template 
-int
-Vmx_state::compute_linear_addr(unsigned segment, l4_uint64_t offset,
-                               bool store, l4_uint64_t *linear)
-{
-  if (in_real_mode())
-    return Invalid_opcode;
-
-  bool valid;
-
-  if (in_long_mode())
-    {
-      // In long mode, segmentation is essentially non-existent except for the
-      // potentially non-zero base of the FS and GS segments.
-
-      l4_uint64_t sgbase;
-
-      switch (segment)
-        {
-        case 0:
-        case 1:
-        case 2:
-        case 3:
-          sgbase = 0;
-          break;
-        case 4:
-          sgbase = vmx_read(VMCS_GUEST_FS_BASE);
-          break;
-        case 5:
-          sgbase = vmx_read(VMCS_GUEST_GS_BASE);
-          break;
-        default:
-          return Invalid_opcode;
-        }
-
-        *linear = sgbase + offset;
-
-        // Guard against non-canonical addresses.
-        valid = is_cannonical_addr(*linear);
-    }
-  else
-    {
-      // In compatibility mode and protected mode, standard segmentation
-      // rules apply.
-
-      l4_uint64_t sgbase;
-      l4_uint32_t access;
-      l4_uint32_t slimit;
-
-      switch (segment)
-        {
-        case 0:
-          sgbase = vmx_read(VMCS_GUEST_ES_BASE);
-          access = vmx_read(VMCS_GUEST_ES_ACCESS_RIGHTS);
-          slimit = vmx_read(VMCS_GUEST_ES_LIMIT);
-          break;
-        case 1:
-          sgbase = vmx_read(VMCS_GUEST_CS_BASE);
-          access = vmx_read(VMCS_GUEST_CS_ACCESS_RIGHTS);
-          slimit = vmx_read(VMCS_GUEST_CS_LIMIT);
-          break;
-        case 2:
-          sgbase = vmx_read(VMCS_GUEST_SS_BASE);
-          access = vmx_read(VMCS_GUEST_SS_ACCESS_RIGHTS);
-          slimit = vmx_read(VMCS_GUEST_SS_LIMIT);
-          break;
-        case 3:
-          sgbase = vmx_read(VMCS_GUEST_DS_BASE);
-          access = vmx_read(VMCS_GUEST_DS_ACCESS_RIGHTS);
-          slimit = vmx_read(VMCS_GUEST_DS_LIMIT);
-          break;
-        case 4:
-          sgbase = vmx_read(VMCS_GUEST_FS_BASE);
-          access = vmx_read(VMCS_GUEST_FS_ACCESS_RIGHTS);
-          slimit = vmx_read(VMCS_GUEST_FS_LIMIT);
-          break;
-        case 5:
-          sgbase = vmx_read(VMCS_GUEST_GS_BASE);
-          access = vmx_read(VMCS_GUEST_GS_ACCESS_RIGHTS);
-          slimit = vmx_read(VMCS_GUEST_GS_LIMIT);
-          break;
-        default:
-          return Invalid_opcode;
-        }
-
-        // Linear addresses are truncated to 32 bits.
-        *linear = (sgbase + offset) & 0xffffffffU;
-
-        if (store)
-          {
-            // Guard against read-only data segments and code segments.
-            if (((access & 0x0a) == 0) || (access & 0x08))
-              return General_protection;
-          }
-        else
-          {
-            // Guard against execute-only code segments.
-            if ((access & 0x0a) == 0x08)
-              return General_protection;
-          }
-
-        // Guard against unusable segments.
-        valid = ((access & 0x10000U) == 0);
-
-        // Unless the segment is flat (i.e. having base 0 with maximal limit,
-        // being any code segment or a non-expand-down data segment), guard
-        // against memory operands outside the segment limit.
-        if ((valid) && ((sgbase != 0) || (slimit != 0xffffffffU)
-                        || (!(access & 0x08) && (access & 0x04))))
-          valid = (*linear + sizeof(TYPE) - 1 <= slimit);
-    }
-
-  if (!valid)
-    {
-      if (segment == 2) // SS
-        return Stack_fault;
-      else
-        return General_protection;
-    }
-
-  return Jump_instr;
-}
-
-l4_uint64_t
-Vmx_state::extend_cannonical_addr(l4_uint64_t addr) const
-{
-  unsigned int bits = (vmx_read(VMCS_GUEST_CR4) & Cr4_la57_bit) ? 7 : 16;
-  return extend_sign64(addr, bits);
-}
-
-bool
-Vmx_state::is_cannonical_addr(l4_uint64_t addr) const
-{
-  return extend_cannonical_addr(addr) == addr;
-}
-
-int
-Vmx_state::address_size_mask(unsigned address_size, l4_uint64_t *mask)
-{
-  switch (address_size)
-    {
-    case 0:
-      *mask = 0xffffU;
-      break;
-    case 1:
-      *mask = 0xffffffffU;
-      break;
-    case 2:
-      *mask = ~0UL;
-      break;
-    default:
-      return Invalid_opcode;
-    }
-
-  return Jump_instr;
-}
-
-l4_uint64_t
-Vmx_state::extend_sign64(l4_uint64_t value, unsigned extension)
-{
-  return static_cast(value << extension) >> extension;
-}
-
-} //namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.h
deleted file mode 100644
index df740718..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vm_state_vmx.h
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "vmcs.h"
-#include "vm_state.h"
-#include "debug.h"
-#include "pt_walker.h"
-#include "event_recorder.h"
-
-#include 
-#include 
-
-namespace Vmm {
-
-class Vmx_state : public Vm_state
-{
-public:
-  enum class Exit {
-      Exception_or_nmi = 0,
-      External_int = 1,
-      Triple_fault = 2,
-      Init_signal = 3,
-      Sipi = 4,
-      Io_smi = 5,
-      Other_smi = 6,
-      Interrupt_window = 7,
-      Nmi_window = 8,
-      Task_switch = 9,
-      Cpuid = 10,
-      Exec_getsec = 11,
-      Exec_halt = 12,
-      Exec_invalid = 13,
-      Exec_invlpg = 14,
-      Exec_rdpmc = 15,
-      Exec_rdtsc = 16,
-      Exec_rsm = 17,
-      Exec_vmcall = 18,
-      Exec_vmclear = 19,
-      Exec_vmlaunch = 20,
-      Exec_vmptrld = 21,
-      Exec_vmptrst = 22,
-      Exec_vmread = 23,
-      Exec_vmresume = 24,
-      Exec_vmwrite = 25,
-      Exec_vmxoff = 26,
-      Exec_vmxon = 27,
-      Cr_access = 28,
-      Mov_debug_reg = 29,
-      Io_access = 30,
-      Exec_rdmsr = 31,
-      Exec_wrmsr = 32,
-      Entry_fail_invalid_guest = 33,
-      Entry_fail_msr = 34,
-      // 35 unused
-      Exec_mwait = 36,
-      Monitor_trap_flag = 37,
-      // 38 unused
-      Exec_monitor = 39,
-      Exec_pause = 40,
-      Entry_fail_machine_check = 41,
-      // 42 unsued
-      Tpr_threshold = 43,
-      Apic_access = 44,
-      Virtualized_eoi = 45,
-      Access_gdtr_idtr = 46,
-      Access_ldtr_tr = 47,
-      Ept_violation = 48,
-      Ept_misconfig = 49,
-      Exec_invept = 50,
-      Exec_rdtscp = 51,
-      Vmx_preempt_timer = 52,
-      Exec_invvpid = 53,
-      Exec_wbinvd = 54,
-      Exec_xsetbv = 55,
-      Apic_write = 56,
-      Exec_rdrand = 57,
-      Exec_invpcid = 58,
-      Vmfunc = 59,
-      Exec_encls = 60,
-      Exec_rdseed = 61,
-      Page_mod_log_full = 62,
-      Exec_xsaves = 63,
-      Exec_xrstors = 64,
-      // 65 unused
-      Spp_related_event = 66,
-      Exec_umwait = 67,
-      Exec_tpause = 68,
-      Exec_loadiwkey = 69,
-      Exit_reason_max
-  };
-
-  enum Activity_state : unsigned
-  {
-    Active = 0,
-    Halt = 1,
-    Shutdown = 2,
-    Wait_sipi = 3
-  };
-
-  enum Vmx_pin_based_vm_execution_controls : unsigned
-  {
-    Ext_int_exiting_bit = (1U << 0),
-    Nmi_exiting_bit = (1U << 3),
-    Virtual_nmis_bit = (1U << 5),
-    Activate_vmx_preemption_timer_bit = (1U << 6),
-    Process_posted_ints = (1U << 7),
-  };
-
-  enum Vmx_primary_vm_execution_controls : unsigned long
-  {
-    Int_window_exit_bit = (1UL << 2),
-    Hlt_exit_bit = (1UL << 7),
-    Rdpmc_exit_bit = (1UL << 11),
-    Tpr_shadow_bit = (1UL << 21),
-    Nmi_window_exit_bit = (1UL << 22),
-    Mov_dr_exit_bit = (1UL << 23),
-    Enable_secondary_ctls_bit = (1UL << 31),
-  };
-
-  enum Vmx_secondary_vm_execution_controls : unsigned long
-  {
-    Virt_apic_access_bit = 1UL,
-    Ept_enable_bit = (1UL << 1),
-    X2apic_virt_bit = (1UL << 4),
-    Unrestricted_guest_bit = (1UL << 7),
-    Apic_reg_virt_bit = (1UL << 8),
-    Apic_virt_int_bit = (1UL << 9),
-    Enable_invpcid_bit = (1UL << 12),
-  };
-
-  enum Vmx_exit_execution_controls : unsigned long
-  {
-    Ack_interrupt_on_exit_bit = (1UL << 15),
-  };
-
-  enum Flags_bits : unsigned long
-  {
-    Interrupt_enabled_bit = (1UL << 9),
-    Direction_bit = (1UL << 10),
-    Virtual_8086_mode_bit = (1UL << 17),
-  };
-
-  enum Vmx_vm_entry_ctls : unsigned long
-  {
-    Vm_entry_load_ia32_pat = (1UL << 14),
-    Vm_entry_load_ia32_efer = (1UL << 15),
-    Ia32e_mode_guest = (1UL << 9),
-  };
-
-  enum Vmx_vm_exit_ctls : unsigned long
-  {
-    Vm_exit_save_ia32_pat = (1UL << 18),  ///< save guest PAT
-    Vm_exit_load_ia32_pat = (1UL << 19),  ///< load host PAT
-    Vm_exit_save_ia32_efer = (1UL << 20), ///< save guest EFER
-    Vm_exit_load_ia32_efer = (1UL << 21), ///< load host EFER
-    Host_address_space_size = (1UL << 9),
-  };
-
-  Vmx_state(l4_vm_vmx_vcpu_state_t *state);
-  ~Vmx_state() = default;
-
-  Type type() const override
-  { return Type::Vmx; }
-
-  void set_activity_state(Activity_state s)
-  { vmx_write(VMCS_GUEST_ACTIVITY_STATE, s); }
-
-  l4_uint32_t activity_state() const
-  { return vmx_read(VMCS_GUEST_ACTIVITY_STATE); }
-
-  void init_state() override
-  {
-    set_hw_vmcs();
-
-    // The reset values are taken from Intel SDM Vol.3 10.1.1;
-    set_activity_state(Active);
-    // reflect all guest exceptions back to the guest.
-    // #DB and #AC are enforced by the microkernel to always exit the VMM
-    // We also set theses bits here to enforce this behaviour
-    vmx_write(VMCS_EXCEPTION_BITMAP, 0x00020002);
-
-    // PAT reset value
-    vmx_write(VMCS_GUEST_IA32_PAT, 0x0007040600070406ULL);
-
-    // XCR0 reset value;
-    vmx_write(L4_VM_VMX_VMCS_XCR0, 0x1ULL);
-
-    vmx_write(VMCS_PIN_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_PIN_BASED_VM_EXEC_CTLS)
-              | Nmi_exiting_bit
-              | Virtual_nmis_bit);
-
-    vmx_write(VMCS_VM_ENTRY_CTLS,
-              (vmx_read(VMCS_VM_ENTRY_CTLS)
-               | Vm_entry_load_ia32_pat
-               | Vm_entry_load_ia32_efer)
-                & ~Ia32e_mode_guest); // disable long mode
-
-    // Guest PAT & EFER are emulated on each access, no need to additionally
-    // store them on VMexit.
-    vmx_write(VMCS_VM_EXIT_CTLS,
-              vmx_read(VMCS_VM_EXIT_CTLS)
-              | Vm_exit_load_ia32_pat
-              | Vm_exit_load_ia32_efer
-              | Host_address_space_size);
-
-    vmx_write(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS)
-                | Hlt_exit_bit
-                | Rdpmc_exit_bit // kernel enforced. keep in sync here.
-                | Mov_dr_exit_bit // kernel enforced. keep in sync here.
-                | Enable_secondary_ctls_bit
-              );
-
-    vmx_write(VMCS_SEC_PROC_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_SEC_PROC_BASED_VM_EXEC_CTLS)
-                | Ept_enable_bit
-                | Unrestricted_guest_bit
-                | Enable_invpcid_bit
-              );
-
-    // System descriptor described in Intel SDM Vol.3 Chapter 3.5
-    vmx_write(VMCS_GUEST_LDTR_SELECTOR, 0x0);
-    vmx_write(VMCS_GUEST_LDTR_ACCESS_RIGHTS, 0x82);
-    vmx_write(VMCS_GUEST_LDTR_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_LDTR_BASE, 0);
-
-    vmx_write(VMCS_GUEST_RFLAGS, 0x02);
-
-    vmx_write(VMCS_GUEST_CR3, 0);
-    vmx_write(VMCS_GUEST_DR7, 0x300);
-    vmx_write(VMCS_GUEST_IA32_EFER, 0x0);
-  }
-
-  bool pf_write() const override
-  { return vmx_read(VMCS_EXIT_QUALIFICATION) & 0x2; }
-
-  l4_umword_t ip() const override
-  { return l4_vm_vmx_read_nat(_vmcs, VMCS_GUEST_RIP); }
-
-  l4_umword_t sp() const override
-  { return l4_vm_vmx_read_nat(_vmcs, VMCS_GUEST_RSP); }
-
-  l4_umword_t cr3() const override
-  { return l4_vm_vmx_read_nat(_vmcs, VMCS_GUEST_CR3); }
-
-  l4_uint64_t xcr0() const override
-  { return vmx_read(L4_VM_VMX_VMCS_XCR0); }
-
-  void jump_instruction()
-  {
-    vmx_write(VMCS_GUEST_RIP,
-              vmx_read(VMCS_GUEST_RIP)
-                + vmx_read(VMCS_VM_EXIT_INSN_LENGTH));
-  }
-
-  void setup_linux_protected_mode(l4_addr_t entry, l4_addr_t stack_addr) override
-  {
-    vmx_write(VMCS_GUEST_CS_SELECTOR, 0x10);
-    vmx_write(VMCS_GUEST_CS_ACCESS_RIGHTS, 0xd09b);
-    vmx_write(VMCS_GUEST_CS_LIMIT, 0xffffffff);
-    vmx_write(VMCS_GUEST_CS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_SS_SELECTOR, 0x18);
-    vmx_write(VMCS_GUEST_SS_ACCESS_RIGHTS, 0xc093);
-    vmx_write(VMCS_GUEST_SS_LIMIT, 0xffffffff);
-    vmx_write(VMCS_GUEST_SS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_DS_SELECTOR, 0x18);
-    vmx_write(VMCS_GUEST_DS_ACCESS_RIGHTS, 0xc093);
-    vmx_write(VMCS_GUEST_DS_LIMIT, 0xffffffff);
-    vmx_write(VMCS_GUEST_DS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_ES_SELECTOR, 0x18);
-    vmx_write(VMCS_GUEST_ES_ACCESS_RIGHTS, 0xc093);
-    vmx_write(VMCS_GUEST_ES_LIMIT, 0xffffffff);
-    vmx_write(VMCS_GUEST_ES_BASE, 0);
-
-    vmx_write(VMCS_GUEST_FS_SELECTOR, 0x0);
-    vmx_write(VMCS_GUEST_FS_ACCESS_RIGHTS, 0x1c0f3);
-    vmx_write(VMCS_GUEST_FS_LIMIT, 0xffffffff);
-    vmx_write(VMCS_GUEST_FS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_GS_SELECTOR, 0x0);
-    vmx_write(VMCS_GUEST_GS_ACCESS_RIGHTS, 0x1c0f3);
-    vmx_write(VMCS_GUEST_GS_LIMIT, 0xffffffff);
-    vmx_write(VMCS_GUEST_GS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_TR_SELECTOR, 0x28);
-    vmx_write(VMCS_GUEST_TR_ACCESS_RIGHTS, 0x108b);
-    vmx_write(VMCS_GUEST_TR_LIMIT, 67);
-    vmx_write(VMCS_GUEST_TR_BASE, 0);
-
-    vmx_write(VMCS_GUEST_RIP, entry);
-    vmx_write(VMCS_GUEST_RSP, stack_addr);
-    vmx_write(VMCS_GUEST_CR0, 0x10031);
-    vmx_write(VMCS_CR0_READ_SHADOW, 0x10031);
-    vmx_write(VMCS_CR0_GUEST_HOST_MASK, ~0ULL);
-
-    vmx_write(VMCS_GUEST_CR4, 0x2690);
-    vmx_write(VMCS_CR4_READ_SHADOW, 0x0690);
-    vmx_write(VMCS_CR4_GUEST_HOST_MASK, ~0ULL);
-  }
-
-  /**
-   * Setup the Real Mode startup procedure for AP startup and BSP resume.
-   *
-   * This follows the hardware reset behavior described in Intel SDM "10.1.4
-   * First Instruction Executed".
-   */
-  void setup_real_mode(l4_addr_t entry) override
-  {
-    if (entry == 0xfffffff0U)
-      {
-        // Bootstrap Processor (BSP) boot
-        vmx_write(VMCS_GUEST_CS_SELECTOR, 0xf000U);
-        vmx_write(VMCS_GUEST_CS_BASE, 0xffff0000U);
-        vmx_write(VMCS_GUEST_RIP, 0xfff0U);
-      }
-    else
-      {
-        // Application Processor (AP) boot via Startup IPI (SIPI) or resume
-        // from suspend.
-        // CS_BASE contains the cached address computed from CS_SELECTOR. After
-        // reset CS_BASE contains what we set until the first CS SELECTOR is
-      // loaded. We use the waking vector or SIPI vector directly, because
-      // tianocore cannot handle the CS_BASE + IP split.
-        vmx_write(VMCS_GUEST_CS_SELECTOR, entry >> 4);
-        vmx_write(VMCS_GUEST_CS_BASE, entry);
-        vmx_write(VMCS_GUEST_RIP, 0);
-      }
-
-    vmx_write(VMCS_GUEST_CS_ACCESS_RIGHTS, 0x9b);
-    vmx_write(VMCS_GUEST_CS_LIMIT, 0xffff);
-
-    vmx_write(VMCS_GUEST_SS_SELECTOR, 0);
-    vmx_write(VMCS_GUEST_SS_ACCESS_RIGHTS, 0x93);
-    vmx_write(VMCS_GUEST_SS_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_SS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_DS_SELECTOR, 0);
-    vmx_write(VMCS_GUEST_DS_ACCESS_RIGHTS, 0x93);
-    vmx_write(VMCS_GUEST_DS_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_DS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_ES_SELECTOR, 0);
-    vmx_write(VMCS_GUEST_ES_ACCESS_RIGHTS, 0x93);
-    vmx_write(VMCS_GUEST_ES_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_ES_BASE, 0);
-
-    vmx_write(VMCS_GUEST_FS_SELECTOR, 0x0);
-    vmx_write(VMCS_GUEST_FS_ACCESS_RIGHTS, 0x93);
-    vmx_write(VMCS_GUEST_FS_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_FS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_GS_SELECTOR, 0x0);
-    vmx_write(VMCS_GUEST_GS_ACCESS_RIGHTS, 0x93);
-    vmx_write(VMCS_GUEST_GS_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_GS_BASE, 0);
-
-    vmx_write(VMCS_GUEST_TR_SELECTOR, 0x0);
-    vmx_write(VMCS_GUEST_TR_ACCESS_RIGHTS, 0x8b);
-    vmx_write(VMCS_GUEST_TR_LIMIT, 0xffff);
-    vmx_write(VMCS_GUEST_TR_BASE, 0);
-
-    vmx_write(VMCS_GUEST_RSP, 0);
-    vmx_write(VMCS_GUEST_CR0, 0x60000010UL);
-    vmx_write(VMCS_CR0_READ_SHADOW, 0x60000010UL);
-    vmx_write(VMCS_CR0_GUEST_HOST_MASK, ~0ULL);
-
-    vmx_write(VMCS_GUEST_CR4, 0x2680);
-    vmx_write(VMCS_CR4_READ_SHADOW, 0x0680);
-    vmx_write(VMCS_CR4_GUEST_HOST_MASK, ~0ULL);
-
-    // clear in SW state to prevent injection of pending events from before
-    // INIT/STARTUP IPI.
-    vmx_write(VMCS_IDT_VECTORING_ERROR, 0ULL);
-  }
-
-  Injection_event pending_event_injection() override
-  {
-    Vmx_state::Idt_vectoring_info vinfo = idt_vectoring_info();
-    if (vinfo.valid() && vinfo.error_valid())
-      {
-        return Injection_event(vinfo.field, vmx_read(VMCS_IDT_VECTORING_ERROR)
-                                              & 0xffffffffUL);
-      }
-    else
-      return Injection_event(vinfo.field, 0U);
-  }
-
-  void invalidate_pending_event()
-  {
-    Vmx_state::Idt_vectoring_info vinfo = idt_vectoring_info();
-    if (vinfo.valid())
-      {
-        vinfo.valid().set(0);
-        vmx_write(VMCS_IDT_VECTORING_INFO, vinfo.field);
-      }
-  }
-
-  Exit exit_reason() const
-  {
-    return Exit(vmx_read(VMCS_EXIT_REASON) & 0xffffU);
-  }
-
-  unsigned msr_shadow_reg(l4_umword_t msr) const
-  {
-    switch (msr)
-    {
-      case 0x00000174: return VMCS_GUEST_IA32_SYSENTER_CS;
-      case 0x00000175: return VMCS_GUEST_IA32_SYSENTER_ESP;
-      case 0x00000176: return VMCS_GUEST_IA32_SYSENTER_EIP;
-      case 0xc0000081: return L4_VM_VMX_VMCS_MSR_STAR;
-      case 0xc0000082: return L4_VM_VMX_VMCS_MSR_LSTAR;
-      case 0xc0000083: return L4_VM_VMX_VMCS_MSR_CSTAR;
-      case 0xc0000084: return L4_VM_VMX_VMCS_MSR_SYSCALL_MASK;
-#ifdef ARCH_amd64
-      case 0xc0000100: return VMCS_GUEST_FS_BASE;
-      case 0xc0000101: return VMCS_GUEST_GS_BASE;
-      case 0xc0000102: return L4_VM_VMX_VMCS_MSR_KERNEL_GS_BASE;
-#endif
-      default: return 0;
-    }
-  }
-
-  bool is_halted() const
-  {
-    return activity_state() == Activity_state::Halt;
-  }
-
-  void halt()
-  {
-    set_activity_state(Vmx_state::Activity_state::Halt);
-  }
-
-  void resume()
-  {
-    set_activity_state(Vmx_state::Activity_state::Active);
-  }
-
-  class Interruptibility_state
-  {
-    l4_uint32_t _state;
-
-  public:
-    Interruptibility_state(l4_uint32_t int_state)
-    : _state(int_state)
-    {}
-
-    bool irq_enabled() { return !sti() && !mov_ss() && !nmi(); }
-    // STI may block NMIs as well. VMX entry may fail, so check STI bit as well.
-    bool nmi_enabled() { return !sti() && !mov_ss() && !nmi(); }
-
-    void clear_sti() { sti().set(0); }
-
-    l4_uint32_t state() const { return _state; }
-
-    CXX_BITFIELD_MEMBER(0, 0, sti, _state);
-    CXX_BITFIELD_MEMBER(1, 1, mov_ss, _state);
-    CXX_BITFIELD_MEMBER(2, 2, smi, _state);
-    CXX_BITFIELD_MEMBER(3, 3, nmi, _state);
-    CXX_BITFIELD_MEMBER(4, 4, enclave, _state);
-  };
-
-  Interruptibility_state interrupt_state() const
-  { return Interruptibility_state(vmx_read(VMCS_GUEST_INTERRUPTIBILITY_STATE)); }
-
-  bool interrupts_enabled() const
-  {
-    return (vmx_read(VMCS_GUEST_RFLAGS) & Interrupt_enabled_bit)
-           && interrupt_state().irq_enabled();
-  }
-
-  /**
-   * Clear the STI interrupt shadow in the interruptibility state.
-   *
-   * This must be called when we emulate an instruction to ensure subsequent
-   * event injection can happen.
-   */
-  void clear_sti_shadow()
-  {
-    auto int_state = interrupt_state();
-    if (!int_state.sti())
-      return;
-
-    int_state.clear_sti();
-    vmx_write(VMCS_GUEST_INTERRUPTIBILITY_STATE, int_state.state());
-  }
-
-  /**
-   * Check if there is an event currently being injected.
-   *
-   * This could happen, e.g. if the vmx_resume was interrupted before entering
-   * the guest.
-   *
-   * \return true  iff an event is in the process of being injected
-   */
-  bool event_injected() const
-  {
-    return entry_int_info().valid();
-  }
-
-  /**
-   * This function checks if interrupts are enabled and no event injection is
-   * in flight and the core's activity state allows interrupts.
-   *
-   * \return true  iff we can inject in an interrupt into the guest
-   */
-  bool can_inject_interrupt() const override
-  {
-    return interrupts_enabled() && !event_injected()
-           && activity_state() < Activity_state::Shutdown;
-  }
-
-  void disable_interrupt_window() override
-  {
-    vmx_write(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS)
-                & ~Int_window_exit_bit);
-  }
-
-  void enable_interrupt_window() override
-  {
-    vmx_write(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS)
-                | Int_window_exit_bit);
-  }
-
-  bool can_inject_nmi() const override
-  {
-    return interrupt_state().nmi_enabled()
-           && !event_injected()
-           && activity_state() < Activity_state::Shutdown;
-  }
-
-  void disable_nmi_window() override
-  {
-    vmx_write(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS)
-                & ~Nmi_window_exit_bit);
-  }
-
-  void enable_nmi_window() override
-  {
-    vmx_write(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS,
-              vmx_read(VMCS_PRI_PROC_BASED_VM_EXEC_CTLS)
-                | Nmi_window_exit_bit);
-  }
-
-
-  /**
-   * The interrupt information for VM entry and exit have the same layout. Some
-   * fields are used only for event injection on entry and some are only used
-   * during interrupt exit. See the Intel manual for details: 24.8.3, 24.9.2.
-   */
-  struct Vmx_int_info_field
-  {
-    enum class Int_type : unsigned {
-        External_interrupt = 0,
-        NMI = 2,
-        Hardware_exception = 3,
-        Software_interrupt = 4,
-        Priviledged_sw_exception = 5,
-        Software_exception = 6,
-        Other_event = 7,
-    };
-
-    l4_uint32_t field;
-    CXX_BITFIELD_MEMBER(0, 7, vector, field);
-    CXX_BITFIELD_MEMBER(8, 10, type, field);
-    CXX_BITFIELD_MEMBER(11, 11, error_valid, field);
-    CXX_BITFIELD_MEMBER(12, 12, nmi_iret, field); // VM exit info only.
-    CXX_BITFIELD_MEMBER(13, 30, reserved, field);
-    CXX_BITFIELD_MEMBER(31, 31, valid, field);
-
-    Vmx_int_info_field(l4_uint32_t raw) : field(raw) {}
-
-    Vmx_int_info_field(unsigned i, Int_type t, unsigned err_valid = 0,
-                       unsigned v = 1)
-    : field(0)
-    {
-      vector().set(i);
-      type().set(static_cast(t));
-      error_valid().set(err_valid);
-      valid().set(v);
-    }
-  };
-
-  /**
-   * Structure representing the VM Exit Instruction Information.
-   *
-   * Note that the instruction information defines different valid bitfields
-   * for different instructions, but the location of those bitfields is mostly
-   * consistent.
-   */
-  struct Vmx_insn_info_field
-  {
-    l4_uint32_t field;
-    CXX_BITFIELD_MEMBER(0, 1, scaling, field);
-    // Bit 2 is undefined.
-    CXX_BITFIELD_MEMBER(3, 6, gpr, field);
-    CXX_BITFIELD_MEMBER(7, 9, address_size, field);
-    CXX_BITFIELD_MEMBER(10, 10, mem_reg, field);
-    CXX_BITFIELD_MEMBER(11, 12, operand_size, field);
-    // Bit 13 is undefined.
-    // Bit 14 is undefined.
-    CXX_BITFIELD_MEMBER(15, 17, segment, field);
-    CXX_BITFIELD_MEMBER(18, 21, index, field);
-    CXX_BITFIELD_MEMBER(22, 22, index_valid_bit, field);
-    CXX_BITFIELD_MEMBER(23, 26, base, field);
-    CXX_BITFIELD_MEMBER(27, 27, base_valid_bit, field);
-    CXX_BITFIELD_MEMBER(28, 31, gpr2, field);
-
-    Vmx_insn_info_field() = delete;
-    Vmx_insn_info_field(l4_uint32_t raw) : field(raw) {}
-
-    bool index_valid() const
-    { return index_valid_bit() == 0; }
-
-    bool base_valid() const
-    { return base_valid_bit() == 0; }
-  };
-
-  /// Type alias to handle VM-exit interrupt data.
-  using Vm_exit_int_info = Vmx_int_info_field;
-  /// Type alias to handle VM-entry event injection data.
-  using Vm_entry_int_info = Vmx_int_info_field;
-  /// Type alias to handle event data stored in IDT-vectoring information.
-  using Idt_vectoring_info = Vmx_int_info_field;
-
-  /// Get VM-exit interrupt information data.
-  Vm_exit_int_info exit_int_info() const
-  { return Vm_exit_int_info(vmx_read(VMCS_VM_EXIT_INTERRUPT_INFO)); }
-
-  /// Get the current VM-entry interrupt information data.
-  Vm_entry_int_info entry_int_info() const
-  { return Vm_entry_int_info(vmx_read(VMCS_VM_ENTRY_INTERRUPT_INFO)); }
-
-  /// Get a description of the VMCS' IDT-vectoring information field.
-  Idt_vectoring_info idt_vectoring_info() const
-  { return Idt_vectoring_info(vmx_read(VMCS_IDT_VECTORING_INFO)); }
-
-  /**
-   * Inject an event stored in IDT-vectoring information format.
-   *
-   * \param info  IDT-vectoring information field value.
-   */
-  void inject_event(Idt_vectoring_info const &info)
-  {
-    assert(info.valid());
-
-    vmx_write(VMCS_VM_ENTRY_INTERRUPT_INFO, info.field);
-    if (info.error_valid())
-      vmx_write(VMCS_VM_ENTRY_EXCEPTION_ERROR,
-                vmx_read(VMCS_IDT_VECTORING_ERROR));
-  }
-
-  void inject_event(Injection_event const &ev) override
-  {
-    assert(ev.valid());
-
-    vmx_write(VMCS_VM_ENTRY_INTERRUPT_INFO, ev.event());
-    if (ev.error_valid())
-      vmx_write(VMCS_VM_ENTRY_EXCEPTION_ERROR, ev.error());
-  }
-
-  enum Deliver_error_code : unsigned
-  {
-    No_error_code = 0,
-    Push_error_code = 1,
-  };
-
-  void inject_event(int event_num, Vmx_int_info_field::Int_type type,
-                    Deliver_error_code deliver_err = No_error_code,
-                    l4_uint32_t err_code = 0)
-  {
-    Vmx_int_info_field info(event_num, type, deliver_err);
-
-    if (0)
-      warn().printf(
-        "-------------- Injecting interrupt/event 0x%x (%p) -> (0x%x)\n",
-        event_num,
-        l4_vm_vmx_field_ptr(_vmcs, VMCS_VM_ENTRY_INTERRUPT_INFO),
-        info.field);
-
-    if (deliver_err == Push_error_code)
-      vmx_write(VMCS_VM_ENTRY_EXCEPTION_ERROR, err_code);
-
-    vmx_write(VMCS_VM_ENTRY_INTERRUPT_INFO, info.field);
-  }
-
-  l4_uint64_t vmx_read(unsigned int field) const
-  { return l4_vm_vmx_read(_vmcs, field); }
-
-  void vmx_write(unsigned field, l4_uint64_t val)
-  { l4_vm_vmx_write(_vmcs, field, val); }
-
-  l4_uint64_t cap_read(enum L4_vm_vmx_caps_regs caps_reg) const
-  { return l4_vm_vmx_get_caps(_state, caps_reg); }
-
-  void set_hw_vmcs()
-  {
-    l4_vm_vmx_set_hw_vmcs(_vmcs, _hw_vmcs.cap());
-  }
-
-  int handle_cr_access(l4_vcpu_regs_t *regs);
-  int handle_exception_nmi_ext_int(Event_recorder *ev_rec);
-
-  bool read_msr(unsigned msr, l4_uint64_t *value) const override;
-  bool write_msr(unsigned msr, l4_uint64_t value, Event_recorder *ev_rec) override;
-
-  int handle_hardware_exception(Event_recorder *ev_rec, unsigned num,
-                                l4_uint32_t err_code);
-
-  void advance_entry_ip(unsigned bytes) override
-  { vmx_write(VMCS_VM_ENTRY_INSN_LEN, bytes); }
-
-  void additional_failure_info(unsigned vcpu_id)
-  {
-    Err().printf("[%3u] VM instruction error: 0x%llx\n", vcpu_id,
-                 vmx_read(VMCS_VM_INSN_ERROR));
-  }
-
-  /**
-   * Store an IO value to memory.
-   *
-   * This is part of the INS instruction emulation. The IO value is stored to
-   * the memory location defined by the INS instruction operand (i.e. RDI,
-   * ES:EDI or ES:DI) and the memory location is advanced to the next record
-   * according to the instruction information.
-   *
-   * \param[in,out] regs      Register file.
-   * \param[in]     ptw       Page table walker.
-   * \param[in]     info      Instruction information.
-   * \param[in]     op_width  Width of the IO access (1/2/4 bytes).
-   * \param[in]     value     Value to store to memory.
-   *
-   * \retval Jump_instr          INS instruction handled successfully.
-   * \retval Invalid_opcode      Instruction decoding failure or unsupported
-   *                             CPU mode.
-   * \retval General_protection  Segmentation fault.
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  int store_io_value(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                     Vmx_insn_info_field info, Mem_access::Width op_width,
-                     l4_uint32_t value);
-
-  /**
-   * Load an IO value from memory.
-   *
-   * This is part of the OUTS instruction emulation. The IO value is loaded
-   * from the memory location defined by the OUTS instruction operand (i.e.
-   * RSI, DS:ESI or DS:SI, with possible segment override using a segment
-   * prefix) and the memory location is advanced to the next record according
-   * to the instruction information.
-   *
-   * \param[in,out] regs      Register file.
-   * \param[in]     ptw       Page table walker.
-   * \param[in]     info      Instruction information.
-   * \param[in]     op_width  Width of the IO access (1/2/4 bytes).
-   * \param[out]    value     Value to load from memory.
-   *
-   * \retval Jump_instr          OUTS instruction handled successfully.
-   * \retval Invalid_opcode      Instruction decoding failure or unsupported
-   *                             CPU mode.
-   * \retval General_protection  Segmentation fault.
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  int load_io_value(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                    Vmx_insn_info_field info, Mem_access::Width op_width,
-                    l4_uint32_t *value);
-
-  /**
-   * Evalutate the condition of the REP prefix.
-   *
-   * This evaluates the REP prefix condition (i.e. CX/ECX/RCX != 0) and if the
-   * condition is satisfied, it decrements the CX/ECX/RCX register.
-   *
-   * \param[in,out] regs  Register file.
-   * \param[in]     info  Instruction information.
-   * \param[out]    next  True if the REP prefix condition is satisfied.
-   *
-   * \retval Jump_instr      Evaluation successful.
-   * \retval Invalid_opcode  Unsupported register size.
-   */
-  int rep_prefix_condition(l4_vcpu_regs_t *regs, Vmx_insn_info_field info,
-                           bool *next);
-
-private:
-  using Hw_vmcs = L4Re::Util::Unique_cap;
-
-  static Dbg warn()
-  { return Dbg(Dbg::Cpu, Dbg::Warn, "VMX"); }
-
-  static Dbg info()
-  { return Dbg(Dbg::Cpu, Dbg::Info, "VMX"); }
-
-  static Dbg trace()
-  { return Dbg(Dbg::Cpu, Dbg::Trace, "VMX"); }
-
-  /**
-   * Get kernel nested virtualization ABI revision.
-   *
-   * If the revision is 0, then no nested virtualization is supported.
-   *
-   * \return Kernel nested virtualization ABI revision.
-   */
-  l4_uint32_t nested_abi_revision() const
-  {
-    return cap_read(L4_VM_VMX_NESTED_REVISION);
-  }
-
-  /**
-   * Check that the guest has paging enabled.
-   *
-   * \retval true   Guest has paging enabled.
-   * \retval false  Guest does not have paging enabled.
-   */
-  bool is_paging_enabled() const;
-
-  /**
-   * Check that the guest is running in real mode.
-   *
-   * \retval true   Guest is running in real mode.
-   * \retval false  Guest is not running in real mode.
-   */
-  bool in_real_mode() const;
-
-  /**
-   * Check that the guest is running in long mode.
-   *
-   * \retval true   Guest is running in long mode.
-   * \retval false  Guest is not running in long mode.
-   */
-  bool in_long_mode() const;
-
-  /**
-   * Store an IO value to memory (core implementation).
-   *
-   * \tparam TYPE  Memory record type.
-   *
-   * \param[in,out] regs   Register file.
-   * \param[in]     ptw    Page table walker.
-   * \param[in]     info   Instruction information.
-   * \param[in]     value  Value to store to memory.
-   *
-   * \retval Jump_instr          INS instruction handled successfully.
-   * \retval Invalid_opcode      Instruction decoding failure or unsupported
-   *                             CPU mode.
-   * \retval General_protection  Segmentation fault.
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  template 
-  int store_io_value_t(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                       Vmx_insn_info_field info, l4_uint32_t value);
-
-  /**
-   * Load an IO value from memory (core implementation).
-   *
-   * \tparam TYPE  Memory record type.
-   *
-   * \param[in,out] regs   Register file.
-   * \param[in]     ptw    Page table walker.
-   * \param[in]     info   Instruction information.
-   * \param[out]    value  Value to load from memory.
-   *
-   * \retval Jump_instr          OUTS instruction handled successfully.
-   * \retval Invalid_opcode      Instruction decoding failure or unsupported
-   *                             CPU mode.
-   * \retval General_protection  Segmentation fault.
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  template 
-  int load_io_value_t(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                      Vmx_insn_info_field info, l4_uint32_t *value);
-
-  /**
-   * Get the INS/OUTS instruction argument address.
-   *
-   * Get the address of the INS/OUTS instruction argument based on the VM Exit
-   * Instruction Information.
-   *
-   * The address is encoded in the ES:DI, ES:EDI or RDI registers (in case of
-   * the INS instruction); in the DS:SI, DS:ESI or RSI registers with potential
-   * segment override (in case of the OUTS instruction).
-   *
-   * \note We only support the guest running in paged protected mode. Non-paged
-   *       modes are not implemented.
-   *
-   * \tparam TYPE  Type of the argument.
-   *
-   * \param[in]  regs        Guest general-purpose registers.
-   * \param[in]  ptw         Page table walker.
-   * \param[in]  info        Instruction information.
-   * \param[in]  store       True if we perform a write access.
-   * \param[out] offset_reg  Decoded offset register. The value is later used
-   *                         for advancing the offset.
-   * \param[out] ptr         Address of the instruction argument (of type
-   *                         #TYPE).
-   *
-   * \retval Jump_instr          Argument address decoded successfully.
-   * \retval Invalid_opcode      Instruction decoding failure.
-   * \retval General_protection  Segmentation fault.
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  template 
-  int get_io_argument(l4_vcpu_regs_t *regs, cxx::Ref_ptr ptw,
-                      Vmx_insn_info_field info, bool store,
-                      unsigned *offset_reg, TYPE **ptr);
-
-  /**
-   * Get the value of a guest register.
-   *
-   * \param[in]  regs   Guest registers.
-   * \param[in]  reg    Guest register index to access (as defined by the Intel
-   *                    specification of the VM exit instruction information).
-   * \param[out] value  Register value.
-   *
-   * \retval Jump_instr      Register index decoded successfully.
-   * \retval Invalid_opcode  Unknown register index.
-   */
-  int read_gpr(l4_vcpu_regs_t *regs, unsigned reg, l4_uint64_t *value);
-
-  /**
-   * Set the value of a guest register.
-   *
-   * \param regs   Guest registers.
-   * \param reg    Guest register index to access (as defined by the Intel
-   *               specification of the VM exit instruction information).
-   * \param value  Register value to set.
-   *
-   * \retval Jump_instr      Register index decoded successfully.
-   * \retval Invalid_opcode  Unknown register index.
-   */
-  int write_gpr(l4_vcpu_regs_t *regs, unsigned reg, l4_uint64_t value);
-
-  /**
-   * Advance an offset register while handling an INS/OUTS instruction.
-   *
-   * \param[in,out] regs          Register file.
-   * \param[in]     reg           Offset register to advance.
-   * \param[in]     address_size  Size of the register (16/32/64 bit).
-   * \param[in]     advancement   Byte size of the record (1/2/4 bytes).
-   *
-   * \retval Jump_instr      Success.
-   * \retval Invalid_opcode  Unknown register index.
-   */
-  int advance_gpr(l4_vcpu_regs_t *regs, unsigned reg, unsigned address_size,
-                  size_t advancement);
-
-  /**
-   * Compute linear (virtual) address from an offset in a guest segment.
-   *
-   * \note We only support the guest running in protected mode. Real mode
-   *       support is not implemented.
-   *
-   * \tparam TYPE  Type of the data the address represents (for the purpose of
-   *               the segment limit check).
-   *
-   * \param[in]  segment  Guest segment index (as defined by the Intel
-   *                      specification of the VM exit instruction
-   *                      information).
-   * \param[in]  offset   Offset within the segment.
-   * \param[in]  store    True if we perform a write access.
-   * \param[out] linear   Linear (virtual) address.
-   *
-   * \retval Jump_instr          Computation successful.
-   * \retval Invalid_opcode      Unknown segment index or unsupported CPU mode.
-   * \retval General_protection  Segmentation fault (non-canonical linear
-   *                             address in 64-bit mode, segmentation violation
-   *                             in 32-bit protected mode).
-   * \retval Stack_fault         Segmentation fault in the SS segment.
-   */
-  template 
-  int compute_linear_addr(unsigned segment, l4_uint64_t offset, bool store,
-                          l4_uint64_t *linear);
-
-  /**
-   * Extend address to cannonical address.
-   *
-   * Sign-extend a 48-bit or 57-bit address (depending on the guest's mode of
-   * operation) to a 64-bit cannonical address.
-   *
-   * \param addr  Address to extended.
-   *
-   * \return Sign-extended cannonical address.
-   */
-  l4_uint64_t extend_cannonical_addr(l4_uint64_t addr) const;
-
-  /**
-   * Check that an address is a cannonical address.
-   *
-   * \param addr  Address to check.
-   *
-   * \retval true   Address is cannonical.
-   * \retval false  Address is not cannonical.
-   */
-  bool is_cannonical_addr(l4_uint64_t addr) const;
-
-  /**
-   * Compute a mask for the given register size.
-   *
-   * \param[in]  address_size  Register size (16/32/64 bits).
-   * \param[out] mask          Mask for the register size.
-   *
-   * \retval Jump_instr      Computation successful.
-   * \retval Invalid_opcode  Unsupported register size.
-   */
-  static int address_size_mask(unsigned address_size, l4_uint64_t *mask);
-
-  /**
-   * Sign-extend a value to 64 bits.
-   *
-   * \param value      Value to be sign-extended.
-   * \param extension  Number of sign-extended bits (i.e. a complement to 64
-   *                   of the number of significant bits).
-   *
-   * \return Sign-extended value.
-   */
-  static l4_uint64_t extend_sign64(l4_uint64_t value, unsigned bits);
-
-  l4_vm_vmx_vcpu_state_t *_state;
-  l4_vm_vmx_vcpu_vmcs_t *_vmcs;
-  Hw_vmcs _hw_vmcs;
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vmcs.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vmcs.h
deleted file mode 100644
index 149cbfdb..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vmcs.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2017, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-/*
- * The constants are defined in the Intel Software Developer Manual Volume 3,
- * Appendix B.
- */
-
-/**
- * 16-bit width VMCS fields
- */
-enum Vmx_vmcs_16bit_fields
-{
-  /* Control fields */
-
-  VMCS_VPID                         = 0x0000,
-  VMCS_PIR_NOTIFICATION_VECTOR      = 0x0002,
-  VMCS_EPTP_INDEX                   = 0x0004,
-  VMCS_HLAT_PREFIX_SIZE             = 0x0006,
-  VMCS_LAST_PID_PTR_INDEX           = 0x0008,
-
-  /* Guest-state fields */
-
-  VMCS_GUEST_ES_SELECTOR            = 0x0800,
-  VMCS_GUEST_CS_SELECTOR            = 0x0802,
-  VMCS_GUEST_SS_SELECTOR            = 0x0804,
-  VMCS_GUEST_DS_SELECTOR            = 0x0806,
-  VMCS_GUEST_FS_SELECTOR            = 0x0808,
-  VMCS_GUEST_GS_SELECTOR            = 0x080a,
-  VMCS_GUEST_LDTR_SELECTOR          = 0x080c,
-  VMCS_GUEST_TR_SELECTOR            = 0x080e,
-  VMCS_GUEST_INTERRUPT_STATUS       = 0x0810,
-  VMCS_GUEST_PML_INDEX              = 0x0812,
-  VMCS_GUEST_UINV                   = 0x0814,
-
-  /* Host-state fields */
-
-  VMCS_HOST_ES_SELECTOR             = 0x0c00,
-  VMCS_HOST_CS_SELECTOR             = 0x0c02,
-  VMCS_HOST_SS_SELECTOR             = 0x0c04,
-  VMCS_HOST_DS_SELECTOR             = 0x0c06,
-  VMCS_HOST_FS_SELECTOR             = 0x0c08,
-  VMCS_HOST_GS_SELECTOR             = 0x0c0a,
-  VMCS_HOST_TR_SELECTOR             = 0x0c0c,
-};
-
-/**
- * 32-bit width VMCS fields
- */
-enum Vmx_vmcs_32bit_fields
-{
-  /* Control fields */
-
-  VMCS_PIN_BASED_VM_EXEC_CTLS       = 0x4000,
-  VMCS_PRI_PROC_BASED_VM_EXEC_CTLS  = 0x4002,
-  VMCS_EXCEPTION_BITMAP             = 0x4004,
-  VMCS_PAGE_FAULT_ERROR_MASK        = 0x4006,
-  VMCS_PAGE_FAULT_ERROR_MATCH       = 0x4008,
-  VMCS_CR3_TARGET_COUNT             = 0x400a,
-
-  VMCS_VM_EXIT_CTLS                 = 0x400c,
-  VMCS_VM_EXIT_MSR_STORE_COUNT      = 0x400e,
-  VMCS_VM_EXIT_MSR_LOAD_COUNT       = 0x4010,
-
-  VMCS_VM_ENTRY_CTLS                = 0x4012,
-  VMCS_VM_ENTRY_MSR_LOAD_COUNT      = 0x4014,
-  VMCS_VM_ENTRY_INTERRUPT_INFO      = 0x4016,
-  VMCS_VM_ENTRY_EXCEPTION_ERROR     = 0x4018,
-  VMCS_VM_ENTRY_INSN_LEN            = 0x401a,
-
-  VMCS_TPR_THRESHOLD                = 0x401c,
-  VMCS_SEC_PROC_BASED_VM_EXEC_CTLS  = 0x401e,
-  VMCS_PLE_GAP                      = 0x4020,
-  VMCS_PLE_WINDOW                   = 0x4022,
-  VMCS_INSTRUCTION_TIMEOUT_CTRL     = 0x4024,
-
-  /* Read-only data fields */
-
-  VMCS_VM_INSN_ERROR                = 0x4400,
-  VMCS_EXIT_REASON                  = 0x4402,
-  VMCS_VM_EXIT_INTERRUPT_INFO       = 0x4404,
-  VMCS_VM_EXIT_INTERRUPT_ERROR      = 0x4406,
-  VMCS_IDT_VECTORING_INFO           = 0x4408,
-  VMCS_IDT_VECTORING_ERROR          = 0x440a,
-  VMCS_VM_EXIT_INSN_LENGTH          = 0x440c,
-  VMCS_VM_EXIT_INSN_INFO            = 0x440e,
-
-  /* Guest-state fields */
-
-  VMCS_GUEST_ES_LIMIT               = 0x4800,
-  VMCS_GUEST_CS_LIMIT               = 0x4802,
-  VMCS_GUEST_SS_LIMIT               = 0x4804,
-  VMCS_GUEST_DS_LIMIT               = 0x4806,
-  VMCS_GUEST_FS_LIMIT               = 0x4808,
-  VMCS_GUEST_GS_LIMIT               = 0x480a,
-  VMCS_GUEST_LDTR_LIMIT             = 0x480c,
-  VMCS_GUEST_TR_LIMIT               = 0x480e,
-  VMCS_GUEST_GDTR_LIMIT             = 0x4810,
-  VMCS_GUEST_IDTR_LIMIT             = 0x4812,
-
-  VMCS_GUEST_ES_ACCESS_RIGHTS       = 0x4814,
-  VMCS_GUEST_CS_ACCESS_RIGHTS       = 0x4816,
-  VMCS_GUEST_SS_ACCESS_RIGHTS       = 0x4818,
-  VMCS_GUEST_DS_ACCESS_RIGHTS       = 0x481a,
-  VMCS_GUEST_FS_ACCESS_RIGHTS       = 0x481c,
-  VMCS_GUEST_GS_ACCESS_RIGHTS       = 0x481e,
-  VMCS_GUEST_LDTR_ACCESS_RIGHTS     = 0x4820,
-  VMCS_GUEST_TR_ACCESS_RIGHTS       = 0x4822,
-
-  VMCS_GUEST_INTERRUPTIBILITY_STATE = 0x4824,
-  VMCS_GUEST_ACTIVITY_STATE         = 0x4826,
-  VMCS_GUEST_SMBASE                 = 0x4828,
-  VMCS_GUEST_IA32_SYSENTER_CS       = 0x482a,
-  VMCS_PREEMPTION_TIMER_VALUE       = 0x482e,
-
-  /* Host-state fields */
-
-  VMCS_HOST_IA32_SYSENTER_CS        = 0x4c00,
-};
-
-/**
- * Natural-width VMCS fields
- */
-enum Vmx_vmcs_natural_fields
-{
-  /* Control fields */
-
-  VMCS_CR0_GUEST_HOST_MASK          = 0x6000,
-  VMCS_CR4_GUEST_HOST_MASK          = 0x6002,
-  VMCS_CR0_READ_SHADOW              = 0x6004,
-  VMCS_CR4_READ_SHADOW              = 0x6006,
-  VMCS_CR3_TARGET_VALUE0            = 0x6008,
-  VMCS_CR3_TARGET_VALUE1            = 0x600a,
-  VMCS_CR3_TARGET_VALUE2            = 0x600c,
-  VMCS_CR3_TARGET_VALUE3            = 0x600e,
-
-  /* Read-only data fields */
-
-  VMCS_EXIT_QUALIFICATION           = 0x6400,
-  VMCS_IO_RCX                       = 0x6402,
-  VMCS_IO_RSI                       = 0x6404,
-  VMCS_IO_RDI                       = 0x6406,
-  VMCS_IO_RIP                       = 0x6408,
-  VMCS_GUEST_LINEAR_ADDRESS         = 0x640a,
-
-  /* Guest-state fields */
-
-  VMCS_GUEST_CR0                    = 0x6800,
-  VMCS_GUEST_CR3                    = 0x6802,
-  VMCS_GUEST_CR4                    = 0x6804,
-  VMCS_GUEST_ES_BASE                = 0x6806,
-  VMCS_GUEST_CS_BASE                = 0x6808,
-  VMCS_GUEST_SS_BASE                = 0x680a,
-  VMCS_GUEST_DS_BASE                = 0x680c,
-  VMCS_GUEST_FS_BASE                = 0x680e,
-  VMCS_GUEST_GS_BASE                = 0x6810,
-  VMCS_GUEST_LDTR_BASE              = 0x6812,
-  VMCS_GUEST_TR_BASE                = 0x6814,
-  VMCS_GUEST_GDTR_BASE              = 0x6816,
-  VMCS_GUEST_IDTR_BASE              = 0x6818,
-  VMCS_GUEST_DR7                    = 0x681a,
-  VMCS_GUEST_RSP                    = 0x681c,
-  VMCS_GUEST_RIP                    = 0x681e,
-  VMCS_GUEST_RFLAGS                 = 0x6820,
-  VMCS_GUEST_PENDING_DBG_EXCEPTIONS = 0x6822,
-  VMCS_GUEST_IA32_SYSENTER_ESP      = 0x6824,
-  VMCS_GUEST_IA32_SYSENTER_EIP      = 0x6826,
-  VMCS_GUEST_IA32_S_CET             = 0x6828,
-  VMCS_GUEST_SSP                    = 0x682a,
-  VMCS_GUEST_IA32_INTR_SSP_TBL_ADDR = 0x682c,
-
-  /* Host-state fields */
-
-  VMCS_HOST_CR0                     = 0x6c00,
-  VMCS_HOST_CR3                     = 0x6c02,
-  VMCS_HOST_CR4                     = 0x6c04,
-  VMCS_HOST_FS_BASE                 = 0x6c06,
-  VMCS_HOST_GS_BASE                 = 0x6c08,
-  VMCS_HOST_TR_BASE                 = 0x6c0a,
-  VMCS_HOST_GDTR_BASE               = 0x6c0c,
-  VMCS_HOST_IDTR_BASE               = 0x6c0e,
-  VMCS_HOST_IA32_SYSENTER_ESP       = 0x6c10,
-  VMCS_HOST_IA32_SYSENTER_EIP       = 0x6c12,
-  VMCS_HOST_RSP                     = 0x6c14,
-  VMCS_HOST_RIP                     = 0x6c16,
-  VMCS_HOST_IA32_S_CET              = 0x6c18,
-  VMCS_HOST_SSP                     = 0x6c1a,
-  VMCS_HOST_IA32_INTR_SSP_TBL_ADDR  = 0x6c1c,
-};
-
-/**
- * 64-bit width VMCS fields
- */
-enum Vmx_vmcs_64bit_fields
-{
-  /* Control fields */
-
-  VMCS_ADDRESS_IO_BITMAP_A          = 0x2000,
-  VMCS_ADDRESS_IO_BITMAP_B          = 0x2002,
-  VMCS_ADDRESS_MSR_BITMAP           = 0x2004,
-  VMCS_VM_EXIT_MSR_STORE_ADDRESS    = 0x2006,
-  VMCS_VM_EXIT_MSR_LOAD_ADDRESS     = 0x2008,
-  VMCS_VM_ENTRY_MSR_LOAD_ADDRESS    = 0x200a,
-  VMCS_EXECUTIVE_VMCS_POINTER       = 0x200c,
-  VMCS_TSC_OFFSET                   = 0x2010,
-  VMCS_VIRTUAL_APIC_ADDRESS         = 0x2012,
-  VMCS_APIC_ACCESS_ADDRESS          = 0x2014,
-  VMCS_PIR_DESCRIPTOR               = 0x2016,
-  VMCS_VM_FUNCTION_CONTROL          = 0x2018,
-  VMCS_EPT_POINTER                  = 0x201a,
-  VMCS_EOI_EXIT_BITMAP0             = 0x201c,
-  VMCS_EOI_EXIT_BITMAP1             = 0x201e,
-  VMCS_EOI_EXIT_BITMAP2             = 0x2020,
-  VMCS_EOI_EXIT_BITMAP3             = 0x2022,
-  VMCS_EPTP_LIST_ADDRESS            = 0x2024,
-  VMCS_VMREAD_BITMAP_ADDRESS        = 0x2026,
-  VMCS_VMWRITE_BITMAP_ADDRESS       = 0x2028,
-  VMCS_VIRT_EXCP_INFO_ADDRESS       = 0x202a,
-  VMCS_XSS_EXITING_BITMAP           = 0x202c,
-  VMCS_ENCLS_EXITING_BITMAP         = 0x202e,
-  VMCS_SUBPAGE_PERMISSION_TBL_PTR   = 0x2030,
-  VMCS_TSC_MULTIPLIER               = 0x2032,
-  VMCS_TER_PROC_BASED_VM_EXEC_CTLS  = 0x2034,
-  VMCS_ENCLV_EXITING_BITMAP         = 0x2036,
-  VMCS_LOW_PASID_DIR_ADDRESS        = 0x2038,
-  VMCS_HIGH_PASID_DIR_ADDRESS       = 0x203a,
-  VMCS_SHARED_EPT_POINTER           = 0x203c,
-  VMCS_PCONFIG_EXITING_BITMAP       = 0x203e,
-  VMCS_HLATP                        = 0x2040,
-  VMCS_PID_POINTER_TABLE_ADDRESS    = 0x2042,
-  VMCS_SEC_VM_EXIT_CTLS             = 0x2044,
-  VMCS_IA32_SPEC_CTRL_MASK          = 0x204a,
-  VMCS_IA32_SPEC_CTRL_SHADOW        = 0x204c,
-
-  /* Read-only data fields */
-
-  VMCS_GUEST_PHYSICAL_ADDRESS       = 0x2400,
-
-  /* Guest-state fields */
-
-  VMCS_LINK_POINTER                 = 0x2800,
-  VMCS_GUEST_IA32_DEBUGCTL          = 0x2802,
-  VMCS_GUEST_IA32_PAT               = 0x2804,
-  VMCS_GUEST_IA32_EFER              = 0x2806,
-  VMCS_GUEST_IA32_PERF_GLOBAL_CTRL  = 0x2808,
-  VMCS_GUEST_PDPTE0                 = 0x280a,
-  VMCS_GUEST_PDPTE1                 = 0x280c,
-  VMCS_GUEST_PDPTE2                 = 0x280e,
-  VMCS_GUEST_PDPTE3                 = 0x2810,
-  VMCS_GUEST_IA32_BNDCFGS           = 0x2812,
-  VMCS_GUEST_IA32_RTIT_CTL          = 0x2814,
-  VMCS_GUEST_IA32_LBR_CTL           = 0x2816,
-  VMCS_GUEST_IA32_PKRS              = 0x2818,
-
-  /* Host-state fields */
-
-  VMCS_HOST_IA32_PAT                = 0x2c00,
-  VMCS_HOST_IA32_EFER               = 0x2c02,
-  VMCS_HOST_IA32_PERF_GLOBAL_CTRL   = 0x2c04,
-  VMCS_HOST_IA32_PKRS               = 0x2c06,
-};
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vmx_exit_to_str.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/vmx_exit_to_str.h
deleted file mode 100644
index 36d0294d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/vmx_exit_to_str.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2017, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-namespace Vmm {
-
-static const char *str_exit_reason[] =
-{
-  /*  0 */ "Exception or NMI",
-  /*  1 */ "External interrupt",
-  /*  2 */ "Triple fault",
-  /*  3 */ "INIT signal",
-  /*  4 */ "Start-up IPI",
-  /*  5 */ "I/O system-management interrupt",
-  /*  6 */ "Other SMI",
-  /*  7 */ "Interrupt window",
-  /*  8 */ "NMI window",
-  /*  9 */ "Task switch",
-  /* 10 */ "CPUID instruction",
-  /* 11 */ "GETSEC instruction",
-  /* 12 */ "HLT instruction",
-  /* 13 */ "INVD instruction",
-  /* 14 */ "INVLPG instruction",
-  /* 15 */ "RDPMC instruction",
-  /* 16 */ "RDTSC instruction",
-  /* 17 */ "RSM instruction",
-  /* 18 */ "VMCALL instruction",
-  /* 19 */ "VMCLEAR instruction",
-  /* 20 */ "VMLAUNCH instruction",
-  /* 21 */ "VMPTRLD instruction",
-  /* 22 */ "VMPTRST instruction",
-  /* 23 */ "VMREAD instruction",
-  /* 24 */ "VMRESUME instruction",
-  /* 25 */ "VMWRITE instruction",
-  /* 26 */ "VMXOFF instruction",
-  /* 27 */ "VMXON instruction",
-  /* 28 */ "Control-register accesses",
-  /* 29 */ "MOV DR",
-  /* 30 */ "I/O instruction",
-  /* 31 */ "RDMSR instruction",
-  /* 32 */ "WRMSR instruction",
-  /* 33 */ "VM-entry failure due to invalid guest state",
-  /* 34 */ "VM-entry failure due to MSR loading",
-  /* 35 */ "",
-  /* 36 */ "MWAIT instruction",
-  /* 37 */ "Monitor trap flag",
-  /* 38 */ "",
-  /* 39 */ "MONITOR instruction",
-  /* 40 */ "PAUSE instruction",
-  /* 41 */ "VM-entry failure due to machine-check event",
-  /* 42 */ "",
-  /* 43 */ "TPR below threshold",
-  /* 44 */ "APIC access",
-  /* 45 */ "Virtualized EOI",
-  /* 46 */ "Access to GDTR or IDTR",
-  /* 47 */ "Access to LDTR or TR",
-  /* 48 */ "EPT violation",
-  /* 49 */ "EPT misconfiguration",
-  /* 50 */ "INVEPT instruction",
-  /* 51 */ "RDTSCP instruction",
-  /* 52 */ "VMX-preemption timer expired",
-  /* 53 */ "INVVPID instruction",
-  /* 54 */ "WBINVD instruction",
-  /* 55 */ "XSETBV instruction",
-  /* 56 */ "APIC write",
-  /* 57 */ "RDRAND instruction",
-  /* 58 */ "INVPCID instruction",
-  /* 59 */ "VM function invoked",
-  /* 60 */ "ENCLS instruction",
-  /* 61 */ "RDSEED instruction",
-  /* 62 */ "Page-modification log full event",
-  /* 63 */ "XSAVES instruction",
-  /* 64 */ "XRSTORS instruction",
-  /* 65 */ "",
-  /* 66 */ "SPP-related event",
-  /* 67 */ "UMWAIT instruction",
-  /* 68 */ "TPAUSE instruction",
-  /* 69 */ "LOADIWKEY instruction"
-};
-
-// Returns a human readable string for any given exit reason.
-inline char const *exit_reason_to_str(l4_uint64_t exit_reason)
-{
-  if (exit_reason < (sizeof(str_exit_reason) / sizeof(char const *)))
-    return str_exit_reason[exit_reason];
-  return "Unknown";
-}
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.cc b/src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.cc
deleted file mode 100644
index 13791dbb..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2017, 2021-2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "zeropage.h"
-#include "acpi.h"
-
-namespace Vmm {
-
-void Zeropage::add_cmdline(char const *line)
-{
-  info().printf("Cmd_line: %s\n", line);
-
-  // strlen excludes the terminating '\0', strcpy copies it. The length check
-  // must care for that additional byte.
-  if (strlen(line) >= Max_cmdline_size - 1)
-    L4Re::chksys(-L4_EINVAL, "Maximal command line size is 4095 characters.");
-
-  strcpy(_cmdline, line);
-}
-
-void Zeropage::add_ramdisk(l4_uint64_t start, l4_uint64_t sz)
-{
-  _ramdisk_start = start;
-  _ramdisk_size = sz;
-}
-
-void Zeropage::cfg_e820(Vm_ram *ram)
-{
-  l4_addr_t last_addr = 0;
-  ram->foreach_region([this, &last_addr](Vmm::Ram_ds const &r)
-  {
-    if (_e820_idx < Max_e820_entries)
-      add_e820_entry(r.vm_start().get(), r.size(),
-                     r.writable() ? E820_ram : E820_reserved);
-    last_addr = r.vm_start().get() + r.size();
-  });
-
-  auto facs = Acpi::Facs_storage::get()->mem_region();
-  add_e820_entry(facs.start.get(), facs.end - facs.start + 1,
-                 E820_reserved);
-
-  // e820 memory map: Linux expects at least two entries to be present to
-  // qualify as a e820 map. From our side, the second entry is currently
-  // unused and has no backing memory. see linux/boot/x86/kernel/e820.c
-  if (last_addr && _e820_idx < 2)
-    add_e820_entry(last_addr, L4_PAGESIZE , E820_reserved);
-}
-
-void Zeropage::add_dtb(l4_addr_t dt_addr, l4_size_t size)
-{
-  _dtb_boot_addr = dt_addr;
-  _dtb_size = size;
-}
-
-void Zeropage::set_screen_callback(std::function cb)
-{
-  assert(!_screen_cb);
-  _screen_cb = cb;
-}
-
-void Zeropage::write(Vm_ram *ram, Boot::Binary_type const gt)
-{
-  memset(ram->guest2host(_gp_addr), 0, L4_PAGESIZE);
-
-  // boot_params are setup according to v.2.07
-  unsigned boot_protocol_version = 0x207;
-
-  switch (gt)
-    {
-    case Boot::Binary_type::Elf:
-      // Note: The _kbinary variable contains the ELF binary entry
-      write_dtb(ram);
-      set_header(ram, Bp_code32_start, _kbinary.get());
-      set_header(ram, Bp_signature, 0x53726448); // "HdrS"
-
-      boot_protocol_version = 0x209; // DTS needs v.2.09
-
-      info().printf("Elf guest zeropage: dtb 0x%llx, entry 0x%lx\n",
-                    get_header(ram, Bp_setup_data),
-                    get_header(ram, Bp_code32_start));
-      break;
-
-    case Boot::Binary_type::Linux:
-      {
-        // Note: The _kbinary variable contains start of the kernel binary
-
-        // constants taken from $lx_src/Documentation/x86/boot.txt
-        l4_uint8_t hsz = *ram->guest2host(_kbinary + 0x0201);
-
-        // calculate size of the setup_header in the zero page/boot params
-        l4_size_t boot_hdr_size = (0x0202 + hsz) - Bp_boot_header;
-
-        memcpy(ram->guest2host(_gp_addr + Bp_boot_header),
-               ram->guest2host(_kbinary + Bp_boot_header),
-               boot_hdr_size);
-        break;
-      }
-    default:
-      L4Re::throw_error(-L4_EINVAL, "Unsupported binary type.");
-      break;
-    }
-
-  write_cmdline(ram);
-
-  // write e820
-  assert(_e820_idx > 0);
-  memcpy(ram->guest2host(_gp_addr + Bp_e820_map), _e820,
-         sizeof(E820_entry) * _e820_idx);
-  set_header(ram, Bp_e820_entries, _e820_idx);
-
-  // write RAM disk
-  set_header(ram, Bp_ramdisk_image, _ramdisk_start);
-  set_header(ram, Bp_ramdisk_size, _ramdisk_size);
-  if ((_ramdisk_start + _ramdisk_size) >> 32 > 0)
-    {
-      Xloadflags xlf;
-      xlf.can_be_loaded_above_4g() = 1;
-      set_header(ram, Bp_xloadflags, xlf.raw);
-      set_header(ram, Bp_ext_ramdisk_image, _ramdisk_start >> 32);
-      set_header(ram, Bp_ext_ramdisk_size, _ramdisk_size >> 32);
-
-      boot_protocol_version = 0x212; // xloadflags needs v.2.12
-    }
-
-  // misc stuff in the boot header
-  set_header(ram, Bp_type_of_loader, 0xff);
-  set_header(ram, Bp_version, boot_protocol_version);
-
-  set_header(ram, Bp_loadflags,
-                         get_header(ram, Bp_loadflags)
-                         | Bp_loadflags_keep_segments_bit);
-
-  // add screen info if necessary
-  if (_screen_cb)
-    _screen_cb(ram->guest2host(addr()));
-}
-
-void Zeropage::add_e820_entry(l4_uint64_t addr, l4_uint64_t size, l4_uint32_t type)
-{
-  assert(_e820_idx < Max_e820_entries);
-  _e820[_e820_idx].addr = addr;
-  _e820[_e820_idx].size = size;
-  _e820[_e820_idx].type = type;
-
-  _e820_idx++;
-}
-
-// add an entry to the single-linked list of Setup_data
-void Zeropage::add_setup_data(Vm_ram *ram, Setup_data *sd, l4_addr_t guest_addr)
-{
-  sd->next = get_header(ram, Bp_setup_data);
-  set_header(ram, Bp_setup_data, guest_addr);
-}
-
-void Zeropage::write_cmdline(Vm_ram *ram)
-{
-  if (*_cmdline == 0)
-    return;
-
-  // place the command line behind the boot parameters
-  auto cmdline_addr = (_gp_addr + Bp_end).round_page();
-
-  strcpy(ram->guest2host(cmdline_addr), _cmdline);
-  set_header(ram, Bp_cmdline_ptr, cmdline_addr.get());
-  set_header(ram, Bp_cmdline_size, strlen(_cmdline));
-
-  info().printf("cmdline check: %s\n", ram->guest2host(cmdline_addr));
-}
-
-void Zeropage::write_dtb(Vm_ram *ram)
-{
-  if (_dtb_boot_addr == 0 || _dtb_size == 0)
-    return;
-
-  // dt_boot_addr is the guest address of the DT memory; Setup_data.data
-  // must be the first byte of the DT. The rest of the Setup_data struct
-  // must go right before it. Hopefully, there is space.
-  unsigned sd_hdr_size = sizeof(Setup_data) + sizeof(Setup_data::data);
-  auto dtb = ram->boot2guest_phys(_dtb_boot_addr);
-  auto *sd = ram->guest2host(dtb - sd_hdr_size);
-
-  for (unsigned i = sd_hdr_size; i > 0; i -= sizeof(char))
-    {
-      auto *sd_ptr = reinterpret_cast(sd);
-      if (*sd_ptr)
-        L4Re::chksys(-L4_EEXIST, "DTB Setup_data header memory in use.");
-      sd_ptr++;
-    }
-
-  sd->type = Setup_dtb;
-  sd->len = _dtb_size;
-  // sd->data is the first DT byte.
-  add_setup_data(ram, sd, _dtb_boot_addr - sd_hdr_size);
-}
-
-std::function Zeropage::_screen_cb;
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.h b/src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.h
deleted file mode 100644
index f705b0bc..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-amd64/zeropage.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2021-2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "debug.h"
-#include "vm_ram.h"
-#include "binary_loader.h"
-
-namespace Vmm {
-
-enum Boot_param
-{
-  Bp_ext_ramdisk_image = 0x0c0,
-  Bp_ext_ramdisk_size = 0x0c4,
-  Bp_ext_cmd_line_ptr = 0x0c8,
-  Bp_e820_entries = 0x1e8,
-  Bp_boot_header = 0x1f1,
-  Bp_setup_sects = 0x1f1,
-  Bp_signature = 0x202,
-  Bp_version = 0x206,
-  Bp_type_of_loader = 0x210,
-  Bp_loadflags = 0x211,
-  Bp_code32_start = 0x214,
-  Bp_ramdisk_image = 0x218,
-  Bp_ramdisk_size = 0x21c,
-  Bp_ext_loader_ver = 0x226,
-  Bp_ext_loader_type = 0x227,
-  Bp_cmdline_ptr = 0x228,
-  Bp_xloadflags = 0x236,
-  Bp_cmdline_size = 0x238,
-  Bp_setup_data = 0x250,
-  Bp_init_size = 0x260,
-  Bp_e820_map = 0x2d0,
-  Bp_end = 0xeed, // after EDD data array
-};
-
-class Zeropage
-{
-  struct Setup_data
-  {
-    l4_uint64_t next;
-    l4_uint32_t type;
-    l4_uint32_t len;
-    l4_uint8_t data[0];
-  };
-
-  enum Setup_data_types
-  {
-    Setup_none = 0,
-    Setup_e820_ext,
-    Setup_dtb,
-    Setup_pci,
-    Setup_efi,
-  };
-
-  enum E820_types
-  {
-    E820_ram = 1,
-    E820_reserved = 2
-  };
-
-  struct E820_entry
-  {
-    l4_uint64_t addr; // start of segment
-    l4_uint64_t size;
-    l4_uint32_t type;
-  } __attribute__((packed));
-
-  struct Xloadflags
-  {
-    l4_uint16_t raw = 0;
-    /// Kernel has the legacy 64-bit entry point at 0x200.
-    CXX_BITFIELD_MEMBER(0, 0, kernel_64, raw);
-    /// Kernel/Boot_params/cmdline/ramdisk can be above 4G
-    CXX_BITFIELD_MEMBER(1, 1, can_be_loaded_above_4g, raw);
-    // bits 4:2 are EFI related; the remaining bits are unused;
-  };
-
-  enum
-  {
-    Max_cmdline_size = 4096,
-    Max_e820_entries = 5,
-
-    Bp_loadflags_keep_segments_bit = 0x40
-  };
-
-  Vmm::Guest_addr _gp_addr; ///< VM physical address of the zero page
-  Vmm::Guest_addr const _kbinary; // VM physical address of the kernel binary
-
-  char _cmdline[Max_cmdline_size];
-  E820_entry _e820[Max_e820_entries];
-  unsigned _e820_idx = 0;
-  l4_uint64_t _ramdisk_start = 0;
-  l4_uint64_t _ramdisk_size = 0;
-  l4_addr_t _dtb_boot_addr = 0;
-  l4_size_t _dtb_size = 0;
-
-public:
-  Zeropage(Vmm::Guest_addr addr, l4_addr_t kernel)
-  : _gp_addr(addr), _kbinary(kernel)
-  {
-    info().printf("Zeropage @ 0x%lx, Kernel @ 0x%lx\n", addr.get(), kernel);
-    memset(_cmdline, 0, Max_cmdline_size);
-    memset(_e820, 0, Max_e820_entries * sizeof(E820_entry));
-  }
-
-  void add_cmdline(char const *line);
-  void add_ramdisk(l4_uint64_t start, l4_uint64_t sz);
-
-  void cfg_e820(Vm_ram *ram);
-
-  /**
-   * Add a device tree.
-   *
-   * \param dt_addr  Address of the device tree in guest RAM.
-   * \param size     Size of the device tree.
-   */
-  void add_dtb(l4_addr_t dt_addr, l4_size_t size);
-
-  static void set_screen_callback(std::function cb);
-  void write(Vm_ram *ram, Boot::Binary_type const gt);
-
-  Vmm::Guest_addr addr() const { return _gp_addr; }
-
-  l4_uint32_t entry(Vm_ram *ram)
-  { return get_header(ram, Bp_code32_start); }
-
-private:
-  static std::function _screen_cb;
-
-  static Dbg trace() { return Dbg(Dbg::Core, Dbg::Trace); }
-  static Dbg info() { return Dbg(Dbg::Core, Dbg::Info); }
-
-  void add_e820_entry(l4_uint64_t addr, l4_uint64_t size, l4_uint32_t type);
-
-  // add an entry to the single-linked list of Setup_data
-  void add_setup_data(Vm_ram *ram, Setup_data *sd, l4_addr_t guest_addr);
-
-  void write_cmdline(Vm_ram *ram);
-
-  void write_dtb(Vm_ram *ram);
-
-  template 
-  void set_header(Vm_ram *ram, unsigned field, T value)
-  { *ram->guest2host(_gp_addr + field) = value; }
-
-  template 
-  T get_header(Vm_ram *ram, unsigned field)
-  { return *ram->guest2host(_gp_addr + field); }
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/aarch32_hyp.h b/src/l4/pkg/uvmm/server/src/ARCH-arm/aarch32_hyp.h
deleted file mode 100644
index b67da63c..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/aarch32_hyp.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include 
-#include 
-
-inline void arm_subarch_setup(void *vcpu, bool, bool pmsa)
-{
-  unsigned long id_mmfr0;
-  asm ("mrc p15, 0, %0, c0, c1, 4": "=r" (id_mmfr0));
-
-  // VPIDR default: Use MIDR of this host CPU.
-  unsigned long midr;
-  asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (midr));
-  l4_vcpu_e_write_32(vcpu, L4_VCPU_E_VPIDR, midr);
-
-  if (pmsa && (id_mmfr0 & 0xf0) == 0)
-    L4Re::throw_error(-L4_ENOSYS, "CPU does not support PMSA");
-  else if (!pmsa && (id_mmfr0 & 0x0f) == 0)
-    L4Re::throw_error(-L4_ENOSYS, "CPU does not support VMSA");
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev.cc b/src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev.cc
deleted file mode 100644
index 929481fb..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright (C) 2017-2021, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev_subarch.h b/src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev_subarch.h
deleted file mode 100644
index c6bec791..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/cpu_dev_subarch.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017, 2019-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-extern "C" void vcpu_entry(l4_vcpu_state_t *vcpu);
-asm
-(
- "vcpu_entry:                     \n"
- "  mov    r4, r0                 \n"  // r4: save r0
- "  mrc    p15, 0, r5, c13, c0, 2 \n"  // r5: save TPIDRURW
- "  ldr    r2, [r0, #0x140]       \n"  // l4_vcpu_e_info_user()[0]
- "  ldr    r3, [r0, #0x24]        \n"  // vcpu->r.err
- "  mcr    p15, 0, r2, c13, c0, 2 \n"
- "  lsr    r3, r3, #24            \n"
- "  bic    r3, r3, #3             \n"
-#ifdef __PIC__
- "  ldr    r12, 2f                \n" // load offset to vcpu_entries
- "1:add    r12, pc, r12           \n" // convert to absolute address
-#else
- "  movw   r12, #:lower16:vcpu_entries      \n"
- "  movt   r12, #:upper16:vcpu_entries      \n"
-#endif
- "  add    r12, r12, r3           \n"
- "  ldr    r12, [r12]             \n"
- "  blx    r12                    \n"
- "  mov    r0, r4                 \n"
- "  bl     prepare_guest_entry    \n"  // sets MR[0] = L4_THREAD_VCPU_RESUME_OP
- "  movw   r2, #0xf803            \n"  // and tag(L4_PROTO_THREAD, 1, 0, 0)
- "  movt   r2, #0xffff            \n"  // dest = L4_INVALID_CAP, flags = call
- "  mov    r3, #0                 \n"  // timeout never
- "  mcr    p15, 0, r5, c13, c0, 2 \n"  // restore TPIDRURW from r5
- "  mov    r5, #" L4_stringify(L4_SYSCALL_INVOKE) " \n"
- "  hvc    #0                     \n"
- "                                \n"
-#ifdef __PIC__
- "2: .word vcpu_entries - (1b + 8)\n"
-#endif
-);
-
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_arm_exc.cc b/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_arm_exc.cc
deleted file mode 100644
index f51e5bd4..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_arm_exc.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2021, 2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "arm_exc.h"
-#include "guest.h"
-
-namespace Vmm {
-
-namespace {
-
-using namespace Arm;
-
-void enter_exception(Vcpu_ptr vcpu, unsigned mode, Aarch32::Exc_offset off)
-{
-  l4_uint32_t spsr = vcpu->r.flags;
-
-  vcpu->r.flags = Aarch32::get_except_flags(vcpu, mode);
-
-  l4_addr_t return_addr =
-    vcpu->r.ip + Aarch32::get_return_offset(off, spsr & Aarch32::Psr_t);
-
-  // SPSR and LR are banked registers for the PE mode the exception is taken to.
-  if (mode == Aarch32::Psr_m_und)
-    {
-      asm volatile("msr SPSR_und, %0" : : "r"(spsr));
-      asm volatile("msr LR_und, %0" : : "r"(return_addr));
-    }
-  else if (mode == Aarch32::Psr_m_abt)
-    {
-      asm volatile("msr SPSR_abt, %0" : : "r"(spsr));
-      asm volatile("msr LR_abt, %0" : : "r"(return_addr));
-    }
-
-  l4_uint32_t vbar;
-  if (l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_SCTLR) & Aarch32::Sctlr_v)
-    // The guest uses high exception vectors.
-    vbar = 0xffff0000;
-  else
-    asm volatile ("mrc p15, 0, %0, c12, c0, 0" : "=r"(vbar)); // VBAR
-
-  vcpu->r.ip = vbar + static_cast(off);
-}
-
-}
-
-bool Guest::fault_mode_supported(Fault_mode mode)
-{
-  return mode == Fault_mode::Inject
-         || Generic_guest::fault_mode_supported(mode);
-}
-
-bool Guest::inject_abort(Vcpu_ptr vcpu, bool inst, l4_addr_t addr)
-{
-  l4_uint32_t ttbcr;
-#ifdef CONFIG_MMU
-  asm volatile ("mrc p15, 0, %0, c2, c0, 2" : "=r"(ttbcr)); // TTBCR
-#else
-  ttbcr = Ttbcr_eae;
-#endif
-  l4_uint32_t fsr = Aarch32::get_abort_fsr(ttbcr);
-
-  Aarch32::Exc_offset off;
-  if (inst)
-    {
-      off = Aarch32::Exc_offset::Prefetch_abort;
-      asm volatile("mcr p15, 0, %0, c6, c0, 2 " : : "r"(addr)); // IFAR
-      asm volatile("mcr p15, 0, %0, c5, c0, 1 " : : "r"(fsr)); // IFSR
-    }
-  else
-    {
-      off = Aarch32::Exc_offset::Data_abort;
-      asm volatile("mcr p15, 0, %0, c6, c0, 0 " : : "r"(addr)); // DFAR
-      asm volatile("mcr p15, 0, %0, c5, c0, 0 " : : "r"(fsr)); // DFSR
-    }
-
-  enter_exception(vcpu, Aarch32::Psr_m_abt, off);
-  return true;
-}
-
-bool Guest::inject_undef(Vcpu_ptr vcpu)
-{
-  enter_exception(vcpu, Aarch32::Psr_m_und,
-                  Aarch32::Exc_offset::Undefined_inst);
-  return true;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.cc b/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.cc
deleted file mode 100644
index e1ae581a..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017, 2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include "guest.h"
-
-L4RE_ELF_AUX_ELEM_T(l4re_elf_aux_mword_t, __ex_regs_flags,
-                    L4RE_ELF_AUX_T_EX_REGS_FLAGS,
-                    L4_THREAD_EX_REGS_ARM_SET_EL_EL1);
-
-// Override the syscall symbol from the l4sys library. Relies on the ELF
-// linking behaviour which ignores symbols from libraries that are already
-// defined by the program or some other library before (in link order).
-asm (
-  ".global __l4_sys_syscall\n"
-  ".type __l4_sys_syscall, #function\n"
-  "__l4_sys_syscall:\n"
-  "   hvc #0\n"
-  "   bx lr\n"
-);
-
-namespace Vmm {
-
-void
-Guest::add_sys_reg_aarch64(unsigned, unsigned,
-                           unsigned, unsigned,
-                           unsigned,
-                           cxx::Ref_ptr const &)
-{}
-
-void
-Guest::subarch_init()
-{}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.h b/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.h
deleted file mode 100644
index ac7659fa..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/guest_subarch.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-namespace Vmm {
-
-enum { Guest_64bit_supported = false };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/monitor/cpu_dev_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-arm/monitor/cpu_dev_cmd_handler.h
deleted file mode 100644
index f42fabed..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/monitor/cpu_dev_cmd_handler.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019, 2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "vcpu_ptr.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Cpu_dev_cmd_handler {};
-
-template
-class Cpu_dev_cmd_handler : public Cmd
-{
-public:
-  char const *help() const override
-  { return "CPU state"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'cpu  regs': dump CPU registers\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, "regs"); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "regs")
-      show_regs(f);
-    else
-      argument_error("Invalid subcommand");
-  }
-
-  void show_regs(FILE *f) const
-  {
-    auto vcpu = get_vcpu();
-    auto regs = vcpu->r;
-
-    fprintf(f, "pc=%08lx lr=%08lx sp=%08lx flags=%08lx\n",
-            regs.ip, vcpu.get_lr(), vcpu.get_sp(), regs.flags);
-    fprintf(f, " r0=%08lx  r1=%08lx  r2=%08lx  r3=%08lx\n",
-            regs.r[0], regs.r[1], regs.r[2], regs.r[3]);
-    fprintf(f, " r4=%08lx  r5=%08lx  r6=%08lx  r7=%08lx\n",
-            regs.r[4], regs.r[5], regs.r[6], regs.r[7]);
-    fprintf(f, " r8=%08lx  r9=%08lx r10=%08lx r11=%08lx\n",
-            vcpu.get_gpr(8), vcpu.get_gpr(9), vcpu.get_gpr(10),
-            vcpu.get_gpr(11));
-    fprintf(f, "r12=%08lx\n", vcpu.get_gpr(12));
-  }
-
-private:
-  Vmm::Vcpu_ptr get_vcpu() const
-  { return static_cast(this)->vcpu(); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm/vcpu_ptr.h b/src/l4/pkg/uvmm/server/src/ARCH-arm/vcpu_ptr.h
deleted file mode 100644
index 9591d5bc..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm/vcpu_ptr.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2015-2021, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "aarch32_hyp.h"
-#include "generic_vcpu_ptr.h"
-#include "mem_access.h"
-
-namespace Vmm {
-
-class Vcpu_ptr : public Generic_vcpu_ptr
-{
-public:
-  explicit Vcpu_ptr(l4_vcpu_state_t *s) : Generic_vcpu_ptr(s) {}
-
-  bool pf_write() const
-  { return hsr().pf_write(); }
-
-  static l4_uint32_t cntfrq()
-  {
-    l4_uint32_t x;
-    asm volatile("mrc  p15, 0, %0, c14, c0, 0" : "=r" (x));
-    return x;
-  }
-
-  static l4_uint64_t cntvct()
-  {
-    l4_uint64_t x;
-    asm volatile ("mrrc p15, 1, %Q0, %R0, c14" : "=r"(x));
-    return x;
-  }
-
-  static l4_uint64_t cntv_cval()
-  {
-    l4_uint64_t x;
-    asm volatile ("mrrc p15, 3, %Q0, %R0, c14" : "=r"(x));
-    return x;
-  }
-
-  void thread_attach()
-  {
-    control_ext(L4::Cap());
-    reinterpret_cast(l4_vcpu_e_info_user(_s))[0] = l4_utcb();
-  }
-
-  Arm::Hsr hsr() const
-  { return Arm::Hsr(_s->r.err); }
-
-  void jump_instruction() const
-  { _s->r.ip += 2 << hsr().il(); }
-
-  /**
-   * Check whether register 'x' is a user mode register for the current mode
-   *
-   * \retval true   Register is a normal register accessible in l4_vcpu_state_t
-   * \retval false  Register is a banked register which needs special treatment
-   */
-  bool use_ureg(unsigned x) const
-  {
-    // registers < 8 are always the user registers
-    if (x < 8)
-      return true;
-
-    // one byte for each (legal) mode, where a set bit (x - 8) means
-    // register r[x] is a user register, modes are
-    //
-    //   usr,  fiq,  irq,  svc,
-    //      ,     ,  mon,  abt,
-    //      ,     ,  hyp,  und,
-    //      ,     ,     ,  sys
-    //
-    // fiq is handled separately, mon/hyp are invalid (trap to el2/el3).
-    static l4_uint8_t const i[] =
-      { 0xff, 0x00, 0x3f, 0x3f,
-        0x00, 0x00, 0x00, 0x3f,
-        0x00, 0x00, 0x00, 0x3f,
-        0x00, 0x00, 0x00, 0xff };
-
-    return i[_s->r.flags & 0x0f] & (1 << (x - 8));
-  }
-
-  /**
-   * Caculate jump offset used for accessing non-user SP and LR in
-   * 'irq', 'svc', 'abt' or 'und' mode
-   *
-   * The calculation does not check whether the mode is valid.
-   *
-   * \return  Jump offset
-   */
-  unsigned mode_offs() const
-  {
-    // mode (lower 5bits of flags):
-    //
-    //   0x12 -> 0, irq
-    //   0x13 -> 2, svc
-    //   0x17 -> 4, abt
-    //   0x1b -> 6, und
-    //
-    // all other (non hyp) modes use all user registers, are handled
-    // separately (fiq) or are illegal
-    return ((_s->r.flags + 1) >> 1) & 0x6;
-  }
-
-  l4_umword_t get_gpr(unsigned x) const
-  {
-    if (L4_UNLIKELY(x > 14))
-      return 0;
-
-    if (use_ureg(x))
-      switch (x)
-        {
-        case 14: return _s->r.lr;
-        case 13: return _s->r.sp;
-        default: return _s->r.r[x];
-        }
-
-    if (0)
-      printf("SPECIAL GET GPR: m=%2lx x=%u\n", (_s->r.flags & 0x1f), x);
-
-    l4_umword_t res;
-    if ((_s->r.flags & 0x1f) == 0x11) // FIQ
-      {
-        switch (x - 8)
-          {
-          case 0: asm ("mrs %[res], R8_fiq " : [res]"=r"(res)); break;
-          case 1: asm ("mrs %[res], R9_fiq " : [res]"=r"(res)); break;
-          case 2: asm ("mrs %[res], R10_fiq" : [res]"=r"(res)); break;
-          case 3: asm ("mrs %[res], R11_fiq" : [res]"=r"(res)); break;
-          case 4: asm ("mrs %[res], R12_fiq" : [res]"=r"(res)); break;
-          case 5: asm ("mrs %[res], SP_fiq " : [res]"=r"(res)); break;
-          case 6: asm ("mrs %[res], LR_fiq " : [res]"=r"(res)); break;
-          default: __builtin_unreachable();
-          }
-        return res;
-      }
-
-    // Should we check whether we have a valid mode (irq, svc, abt, und) here?
-    switch (x - 13 + mode_offs())
-      {
-      case 0: asm ("mrs %[res], SP_irq" : [res]"=r"(res)); break;
-      case 1: asm ("mrs %[res], LR_irq" : [res]"=r"(res)); break;
-      case 2: asm ("mrs %[res], SP_svc" : [res]"=r"(res)); break;
-      case 3: asm ("mrs %[res], LR_svc" : [res]"=r"(res)); break;
-      case 4: asm ("mrs %[res], SP_abt" : [res]"=r"(res)); break;
-      case 5: asm ("mrs %[res], LR_abt" : [res]"=r"(res)); break;
-      case 6: asm ("mrs %[res], SP_und" : [res]"=r"(res)); break;
-      case 7: asm ("mrs %[res], LR_und" : [res]"=r"(res)); break;
-      default: __builtin_unreachable();
-      }
-
-    return res;
-  }
-
-  void set_gpr(unsigned x, l4_umword_t value) const
-  {
-    if (L4_UNLIKELY(x > 14))
-      return;
-
-    if (use_ureg(x))
-      switch (x)
-        {
-        case 14: _s->r.lr = value; return;
-        case 13: _s->r.sp = value; return;
-        default: _s->r.r[x] = value; return;
-        }
-
-    if (0)
-      printf("SPECIAL SET GPR: m=%2lx x=%u\n", (_s->r.flags & 0x1f), x);
-
-    if ((_s->r.flags & 0x1f) == 0x11) // FIQ
-      {
-        switch (x - 8)
-          {
-          case 0: asm ("msr R8_fiq,  %[v]" : : [v]"r"(value)); break;
-          case 1: asm ("msr R9_fiq,  %[v]" : : [v]"r"(value)); break;
-          case 2: asm ("msr R10_fiq, %[v]" : : [v]"r"(value)); break;
-          case 3: asm ("msr R11_fiq, %[v]" : : [v]"r"(value)); break;
-          case 4: asm ("msr R12_fiq, %[v]" : : [v]"r"(value)); break;
-          case 5: asm ("msr SP_fiq,  %[v]" : : [v]"r"(value)); break;
-          case 6: asm ("msr LR_fiq,  %[v]" : : [v]"r"(value)); break;
-          default: __builtin_unreachable();
-          }
-        return;
-      }
-
-    // Should we check whether we have a valid mode (irq, svc, abt, und) here?
-    switch (x - 13 + mode_offs())
-      {
-      case 0: asm ("msr SP_irq, %[v]" : : [v]"r"(value)); break;
-      case 1: asm ("msr LR_irq, %[v]" : : [v]"r"(value)); break;
-      case 2: asm ("msr SP_svc, %[v]" : : [v]"r"(value)); break;
-      case 3: asm ("msr LR_svc, %[v]" : : [v]"r"(value)); break;
-      case 4: asm ("msr SP_abt, %[v]" : : [v]"r"(value)); break;
-      case 5: asm ("msr LR_abt, %[v]" : : [v]"r"(value)); break;
-      case 6: asm ("msr SP_und, %[v]" : : [v]"r"(value)); break;
-      case 7: asm ("msr LR_und, %[v]" : : [v]"r"(value)); break;
-      default: __builtin_unreachable();
-      }
-  }
-
-  l4_umword_t get_sp() const
-  {
-    return get_gpr(13);
-  }
-
-  l4_umword_t get_lr() const
-  {
-    return get_gpr(14);
-  }
-
-  Mem_access decode_mmio() const
-  {
-    Mem_access m;
-
-    if (!hsr().pf_isv() || hsr().pf_srt() > 14)
-      {
-        m.access = Mem_access::Other;
-        return m;
-      }
-
-    m.width = hsr().pf_sas();
-    m.access = hsr().pf_write() ? Mem_access::Store : Mem_access::Load;
-
-    if (m.access == Mem_access::Store)
-      m.value = get_gpr(hsr().pf_srt());
-
-    return m;
-  }
-
-  void writeback_mmio(Mem_access const &m) const
-  {
-    assert(m.access == Mem_access::Load);
-
-    l4_umword_t v = reg_extend_width(m.value, hsr().pf_sas(), hsr().pf_sse());
-    set_gpr(hsr().pf_srt(), v);
-  }
-
-  Arm::Gic_h::Vcpu_ppi_cfg vtmr() const
-  {
-    return Arm::Gic_h::Vcpu_ppi_cfg(l4_vcpu_e_read_32(_s, L4_VCPU_E_VTMR_CFG));
-  }
-
-  void vtmr(Arm::Gic_h::Vcpu_ppi_cfg cfg)
-  { l4_vcpu_e_write_32(_s, L4_VCPU_E_VTMR_CFG, cfg.raw); }
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/aarch64_hyp.h b/src/l4/pkg/uvmm/server/src/ARCH-arm64/aarch64_hyp.h
deleted file mode 100644
index fa04fc6e..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/aarch64_hyp.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2021, 2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-inline void arm_subarch_setup(void *vcpu, bool guest_64bit, bool pmsa)
-{
-  if (guest_64bit)
-    {
-      l4_umword_t hcr = l4_vcpu_e_read(vcpu, L4_VCPU_E_HCR);
-      hcr |= 1UL << 18; // TID3: Trap ID Group 3 (feature system registers)
-      hcr |= 1UL << 31; // set RW bit
-      l4_vcpu_e_write(vcpu, L4_VCPU_E_HCR, hcr);
-    }
-
-  unsigned long id_aa64mmfr0_el1;
-  asm("mrs %0, S3_0_C0_C7_0" : "=r"(id_aa64mmfr0_el1));
-  unsigned msa = (id_aa64mmfr0_el1 >> 48) & 0x0fU;
-  unsigned msa_frac = (id_aa64mmfr0_el1 >> 52) & 0x0fU;
-
-  // See Armv8-R AArch64 supplement (ARM DDI 0600A)
-  if (pmsa && (msa == 0 || msa != 0xf || (msa_frac != 1 && msa_frac != 2)))
-    L4Re::throw_error(-L4_ENOSYS, "CPU does not support PMSA");
-  else if (!pmsa && !(msa == 0 || (msa == 0xf && msa_frac == 2)))
-    L4Re::throw_error(-L4_ENOSYS, "CPU does not support VMSA");
-
-  l4_vcpu_e_write_64(vcpu, L4_VCPU_E_VTCR, pmsa ? 0 : (1ULL << 31));
-
-  // VPIDR default: Use MIDR_EL1 of this host CPU.
-  l4_uint64_t midr_el1;
-  asm volatile ("mrs %0, midr_el1" : "=r"(midr_el1));
-  l4_vcpu_e_write_32(vcpu, L4_VCPU_E_VPIDR, midr_el1);
-}
-
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev.cc b/src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev.cc
deleted file mode 100644
index 8e5fd4a2..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev_subarch.h b/src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev_subarch.h
deleted file mode 100644
index 5835c063..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/cpu_dev_subarch.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2017, 2019-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-extern "C" void vcpu_entry(l4_vcpu_state_t *vcpu);
-asm
-(
- "vcpu_entry:                     \n"
- "  mrs    x20, TPIDR_EL0         \n"
- "  mov    x21, x0                \n"
- "  ldr    x8, [x0, #0x248]         \n"  // l4_vcpu_e_info_user()[1]
- "  ldr    w9, [x0, #0x148]         \n"  // vcpu->r.err
- "  msr    TPIDR_EL0, x8            \n"
- "  lsr    x9, x9, #23              \n"
- "  bic    x9, x9, #7               \n"
-#ifdef __PIC__
- "  adrp   x10, vcpu_entries        \n"
- "  add    x10, x10, :lo12:vcpu_entries\n"
-#else
- "  ldr    x10, =vcpu_entries       \n"
-#endif
- "  add    x10, x10, x9             \n"
- "  ldr    x11, [x10]               \n"
- "  blr    x11                      \n"
- "  mov    x0, x21                  \n"
- "  bl     prepare_guest_entry      \n" // sets MR[0] = L4_THREAD_VCPU_RESUME_OP
-                                        // and tag(L4_PROTO_THREAD, 1, 0, 0)
- "  mov    x2, #0xfffffffffffff803  \n" // dest = L4_INVALID_CAP, flags = call
- "  mov    x3, #0                   \n" // timeout never
-
- "  msr    TPIDR_EL0, x20           \n"
- "  hvc    #0                       \n"
-);
-
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_arm_exc.cc b/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_arm_exc.cc
deleted file mode 100644
index c8ebd92b..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_arm_exc.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "arm_exc.h"
-#include "guest.h"
-
-namespace Vmm {
-
-namespace {
-
-using namespace Arm;
-
-void enter_exception64(Vcpu_ptr vcpu)
-{
-  l4_umword_t old_flags = vcpu->r.flags;
-  l4_umword_t target_mode = Aarch64::Spsr_m_el1h;
-
-  vcpu->r.flags = Aarch64::get_except_flags(vcpu, target_mode);
-  asm volatile("msr SPSR_EL1, %0" : : "r"(old_flags));
-
-  l4_umword_t mode = old_flags & Aarch64::Spsr_m_mask;
-  unsigned exc_offset = Aarch64::get_except_offset(mode, target_mode);
-
-  // Save current instruction pointer
-  asm volatile("msr ELR_EL1, %0" : : "r"(vcpu->r.ip));
-
-  // Set exception vector instruction pointer
-  l4_umword_t vbar;
-  asm volatile ("mrs %0, VBAR_EL1" : "=r"(vbar));
-  vcpu->r.ip = vbar + exc_offset;
-}
-
-void enter_exception32(Vcpu_ptr vcpu, unsigned mode, Aarch32::Exc_offset off)
-{
-  l4_uint32_t spsr = vcpu->r.flags;
-
-  vcpu->r.flags = Aarch32::get_except_flags(vcpu, mode);
-
-  l4_addr_t return_addr =
-    vcpu->r.ip + Aarch32::get_return_offset(off, spsr & Aarch32::Psr_t);
-  // SPSR and LR are banked registers for the PE mode the exception is taken to.
-  if (mode == Aarch32::Psr_m_und)
-    {
-      // TODO: The SPSR_und register can only be accessed from EL2 mode...
-      asm volatile("msr SPSR_und, %x0" : : "r"(spsr));
-      // LR_und is mapped to GPR X22 on Aarch64
-      vcpu->r.r[22] = return_addr;
-    }
-  else if (mode == Aarch32::Psr_m_abt)
-    {
-      // TODO: The SPSR_abt register can only be accessed from EL2 mode...
-      asm volatile("msr SPSR_abt, %x0" : : "r"(spsr));
-      // LR_abt is mapped to GPR X20 on Aarch64
-      vcpu->r.r[20] = return_addr;
-    }
-
-  l4_uint32_t vbar;
-  if (l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_SCTLR) & Aarch32::Sctlr_v)
-    // The guest uses high exception vectors.
-    vbar = 0xffff0000;
-  else
-    asm volatile ("mrs %x0, VBAR_EL1" : "=r"(vbar)); // VBAR
-
-  vcpu->r.ip = vbar + static_cast(off);
-}
-
-/* Inject abort into Aarch32 guest on Aarch64 host */
-__attribute__ ((unused))
-void inject_abort32(Vcpu_ptr vcpu, bool inst, l4_uint32_t addr)
-{
-  l4_uint32_t ttbcr;
-  asm volatile ("mrs %x0, TCR_EL1" : "=r"(ttbcr));
-  l4_uint32_t fsr = Aarch32::get_abort_fsr(ttbcr);
-
-  l4_uint64_t far;
-  asm volatile ("mrs %0, FAR_EL1" : "=r"(far));
-
-  Aarch32::Exc_offset off;
-  if (inst)
-    {
-      off = Aarch32::Exc_offset::Prefetch_abort;
-
-      // IFAR is mapped to FAR_EL1 bits [63:32]
-      far &= (~0xffffffffULL) << 32;
-      far |= static_cast(addr) << 32;
-
-      // TODO: The IFSR32_EL2 register can only be accessed from EL2 mode...
-      asm volatile("msr IFSR32_EL2, %x0" : : "r"(fsr));
-    }
-  else
-    {
-      off = Aarch32::Exc_offset::Data_abort;
-
-      // DFAR is mapped to FAR_EL1 bits [31:0]
-      far &= ~0xffffffffULL;
-      far |= addr;
-
-      asm volatile("msr ESR_EL1, %x0" : : "r"(fsr));
-    }
-  asm volatile("msr FAR_EL1, %0" : : "r"(far));
-
-  enter_exception32(vcpu, Aarch32::Psr_m_abt, off);
-}
-
-/* Inject abort into Aarch64 guest on Aarch64 host */
-void inject_abort64(Vcpu_ptr vcpu, bool inst, l4_addr_t addr)
-{
-  asm volatile("msr FAR_EL1, %0" : : "r"(addr));
-
-  Hsr esr = Aarch64::get_abort_esr(vcpu, inst);
-  asm volatile("msr ESR_EL1, %x0" : : "r"(esr.raw()));
-
-  enter_exception64(vcpu);
-}
-
-__attribute__ ((unused))
-void inject_undef32(Vcpu_ptr vcpu)
-{
-  enter_exception32(vcpu, Aarch32::Psr_m_und,
-                    Aarch32::Exc_offset::Undefined_inst);
-}
-
-void inject_undef64(Vcpu_ptr vcpu)
-{
-  Hsr esr { 0 };
-  esr.il() = vcpu.hsr().il();
-  esr.ec() = Hsr::Ec_unknown;
-  asm volatile("msr ESR_EL1, %x0" : : "r"(esr.raw()));
-
-  enter_exception64(vcpu);
-}
-
-}
-
-bool Guest::fault_mode_supported(Fault_mode mode)
-{
-  return mode == Fault_mode::Inject
-         || Generic_guest::fault_mode_supported(mode);
-}
-
-bool
-Guest::inject_abort(Vcpu_ptr vcpu, bool inst, l4_addr_t addr)
-{
-  if (Aarch64::is_aarch32(vcpu->r.flags))
-    // TODO: inject_abort32(vcpu, inst, addr);
-    return false;
-  else
-    inject_abort64(vcpu, inst, addr);
-
-  return true;
-}
-
-bool
-Guest::inject_undef(Vcpu_ptr vcpu)
-{
-  if (Aarch64::is_aarch32(vcpu->r.flags))
-    // TODO: inject_undef32(vcpu);
-    return false;
-  else
-    inject_undef64(vcpu);
-
-  return true;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.cc b/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.cc
deleted file mode 100644
index d99ac80d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.cc
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include "guest.h"
-
-L4RE_ELF_AUX_ELEM_T(l4re_elf_aux_mword_t, __ex_regs_flags,
-                    L4RE_ELF_AUX_T_EX_REGS_FLAGS,
-                    L4_THREAD_EX_REGS_ARM64_SET_EL_EL1);
-
-asm (
-  ".global __l4_sys_syscall\n"
-  ".type __l4_sys_syscall, @function\n"
-  "__l4_sys_syscall:\n"
-  "   hvc #0\n"
-  "   ret\n"
-);
-
-namespace {
-
-bool
-has_aarch32()
-{
-  l4_uint64_t aa64pfr0;
-  asm ("mrs %0, ID_AA64PFR0_EL1" : "=r"(aa64pfr0));
-  return (aa64pfr0 & 0x0f) == 2;
-}
-
-}
-
-namespace Vmm {
-
-void
-Guest::add_sys_reg_aarch64(unsigned op0, unsigned op1,
-                           unsigned crn, unsigned crm,
-                           unsigned op2,
-                           cxx::Ref_ptr const &r)
-{
-  _sys_regs[Vmm::Arm::Sys_reg::Key::sr(op0, op1, crn, crm, op2)] = r;
-}
-
-#define CP(coproc,opc1,CRn,CRm,opc2) "S" #coproc "_" #opc1 "_C" #CRn "_C" #CRm "_" #opc2
-#define ADD_FEAT_REG(coproc, opc1, CRn, CRm, opc2, ...) \
-  add_sys_reg_aarch64(coproc, opc1, CRn, CRm, opc2, cxx::make_ref_obj([](){ \
-    l4_uint64_t regval; \
-    asm volatile("mrs %0, " CP(coproc, opc1, CRn, CRm, opc2) : "=r"(regval)); \
-    return regval & (__VA_ARGS__); \
-  }))
-
-
-void
-Guest::subarch_init()
-{
-  using namespace Arm;
-
-  // Registers sorted according to encoding. See chapter
-  //
-  //   D22.3.1 Instructions for accessing non-debug System registers
-  //
-  // in Arm Architecture Reference Manual ARM DDI 0487K.a.
-
-  if (has_aarch32())
-    {
-      // ID_PFR0_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 0,
-                     (  0UL << 28)  // Mask RAS
-                   | (0xfUL << 24)  // DIT
-                   | (  0UL << 20)  // Mask AMU
-                   | (0xfUL << 16)  // CSV2
-                   | (0xfUL << 12)  // State3 (T32EE)
-                   | (0xfUL <<  8)  // State2 (Jazelle)
-                   | (0xfUL <<  4)  // State1 (T32)
-                   | (0xfUL <<  0)  // State0 (A32)
-      );
-
-      // ID_PFR1_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 1,
-                     (0xfUL << 28)  // GIC
-                   | (0xfUL << 24)  // Virt_frac
-                   | (0xfUL << 20)  // Sec_frac
-                   | (0xfUL << 16)  // GenTimer
-                   | (0xfUL << 12)  // Virtualization
-                   | (0xfUL <<  8)  // MProgMod
-                   | (0xfUL <<  4)  // Security
-                   | (0xfUL <<  0)  // ProgMod
-      );
-
-      // ID_DFR0_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 2,
-                     (  0UL << 28)  // Mask TraceFilt
-                   | (  0UL << 24)  // Mask PerfMon
-                   | (  0UL << 20)  // Mask MProfDbg
-                   | (  0UL << 16)  // Mask MMapTrc
-                   | (  0UL << 12)  // Mask CopTrc
-                   | (  0UL <<  8)  // Mask MMapDbg
-                   | (  0UL <<  4)  // Mask CopSDbg
-                   | (0xfUL <<  0)  // CopDbg
-      );
-
-      // ID_AFR0_EL1 skipped intentionally
-
-      // ID_MMFR0_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 4,
-                     (0xfUL << 28)  // InnerShr
-                   | (0xfUL << 24)  // FCSE
-                   | (0xfUL << 20)  // AuxReg
-                   | (0xfUL << 16)  // TCM
-                   | (0xfUL << 12)  // ShareLvl
-                   | (0xfUL <<  8)  // OuterShr
-                   | (0xfUL <<  4)  // PMSA
-                   | (0xfUL <<  0)  // VMSA
-      );
-
-      // ID_MMFR1_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 5,
-                     (0xfUL << 28)  // BPred
-                   | (0xfUL << 24)  // L1TstCln
-                   | (0xfUL << 20)  // L1Uni
-                   | (0xfUL << 16)  // L1Hvd
-                   | (0xfUL << 12)  // L1UniSW
-                   | (0xfUL <<  8)  // L1HvdSW
-                   | (0xfUL <<  4)  // L1UniVA
-                   | (0xfUL <<  0)  // L1HvdVA
-      );
-
-      // ID_MMFR2_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 6,
-                     (0xfUL << 28)  // HWAccFlg
-                   | (0xfUL << 24)  // WFIStall
-                   | (0xfUL << 20)  // MemBarr
-                   | (0xfUL << 16)  // UniTLB
-                   | (0xfUL << 12)  // HvdTLB
-                   | (0xfUL <<  8)  // L1HvdRng
-                   | (0xfUL <<  4)  // L1HvdBG
-                   | (0xfUL <<  0)  // L1HvdFG
-      );
-
-      // ID_MMFR3_EL1
-      ADD_FEAT_REG(3, 0, 0, 1, 7,
-                     (0xfUL << 28)  // Supersec
-                   | (0xfUL << 24)  // CMemSz
-                   | (0xfUL << 20)  // CohWalk
-                   | (0xfUL << 16)  // PAN
-                   | (0xfUL << 12)  // MaintBcst
-                   | (0xfUL <<  8)  // BPMaint
-                   | (0xfUL <<  4)  // CMaintSW
-                   | (0xfUL <<  0)  // CMaintVA
-      );
-
-      // ID_ISAR0_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 0,
-                     (  0UL << 28)  // RES0
-                   | (0xfUL << 24)  // Divide
-                   | (0xfUL << 20)  // Debug
-                   | (0xfUL << 16)  // Coproc
-                   | (0xfUL << 12)  // CmpBranch
-                   | (0xfUL <<  8)  // BitField
-                   | (0xfUL <<  4)  // BitCount
-                   | (0xfUL <<  0)  // Swap
-      );
-
-      // ID_ISAR1_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 1,
-                     (0xfUL << 28)  // Jazelle
-                   | (0xfUL << 24)  // Interwork
-                   | (0xfUL << 20)  // Immediate
-                   | (0xfUL << 16)  // IfThen
-                   | (0xfUL << 12)  // Extend
-                   | (0xfUL <<  8)  // Except_AR
-                   | (0xfUL <<  4)  // Except
-                   | (0xfUL <<  0)  // Endian
-      );
-
-      // ID_ISAR2_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 2,
-                     (0xfUL << 28)  // Reversal
-                   | (0xfUL << 24)  // PSR_AR
-                   | (0xfUL << 20)  // MultU
-                   | (0xfUL << 16)  // MultS
-                   | (0xfUL << 12)  // Mult
-                   | (0xfUL <<  8)  // MultiAccessInt
-                   | (0xfUL <<  4)  // MemHint
-                   | (0xfUL <<  0)  // LoadStore
-      );
-
-      // ID_ISAR3_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 3,
-                     (0xfUL << 28)  // T32EE
-                   | (0xfUL << 24)  // TrueNOP
-                   | (0xfUL << 20)  // T32Copy
-                   | (0xfUL << 16)  // TabBranch
-                   | (0xfUL << 12)  // SynchPrim
-                   | (0xfUL <<  8)  // SVC
-                   | (0xfUL <<  4)  // SIMD
-                   | (0xfUL <<  0)  // Saturate
-      );
-
-      // ID_ISAR4_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 4,
-                     (0xfUL << 28)  // SWP_frac
-                   | (0xfUL << 24)  // PSR_M
-                   | (0xfUL << 20)  // SynchPrim_frac
-                   | (0xfUL << 16)  // Barrier
-                   | (0xfUL << 12)  // SMC
-                   | (0xfUL <<  8)  // Writeback
-                   | (0xfUL <<  4)  // WithShifts
-                   | (0xfUL <<  0)  // Unpriv
-      );
-
-      // ID_ISAR5_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 5,
-                     (0xfUL << 28)  // VCMA
-                   | (0xfUL << 24)  // RDM
-                   | (  0UL << 20)  // RES0
-                   | (0xfUL << 16)  // CRC32
-                   | (0xfUL << 12)  // SHA2
-                   | (0xfUL <<  8)  // SHA1
-                   | (0xfUL <<  4)  // AES
-                   | (0xfUL <<  0)  // SEVL
-      );
-
-      // ID_MMFR4_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 6,
-                     (0xfUL << 28)  // EVT
-                   | (0xfUL << 24)  // CCIDX
-                   | (0xfUL << 20)  // LSM
-                   | (0xfUL << 16)  // HPDS
-                   | (0xfUL << 12)  // CnP
-                   | (0xfUL <<  8)  // XNX
-                   | (0xfUL <<  4)  // AC2
-                   | (  0UL <<  0)  // Mask SpecSEI (RAS)
-      );
-
-      // ID_ISAR6_EL1
-      ADD_FEAT_REG(3, 0, 0, 2, 7,
-                     (0xfUL << 28)  // CLRBHB
-                   | (0xfUL << 24)  // I8MM
-                   | (0xfUL << 20)  // BF16
-                   | (0xfUL << 16)  // SPECRES
-                   | (0xfUL << 12)  // SB
-                   | (0xfUL <<  8)  // FHM
-                   | (0xfUL <<  4)  // DP
-                   | (0xfUL <<  0)  // JSCVT
-      );
-
-      // ID_MVFR0_EL1
-      ADD_FEAT_REG(3, 0, 0, 3, 0,
-                     (0xfUL << 28)  // FPRound
-                   | (0xfUL << 24)  // FPShVec
-                   | (0xfUL << 20)  // FPSqrt
-                   | (0xfUL << 16)  // FPDivide
-                   | (0xfUL << 12)  // FPTrap
-                   | (0xfUL <<  8)  // FPDP
-                   | (0xfUL <<  4)  // FPSP
-                   | (0xfUL <<  0)  // SIMDReg
-      );
-
-      // ID_MVFR1_EL1
-      ADD_FEAT_REG(3, 0, 0, 3, 1,
-                     (0xfUL << 28)  // SIMDFMAC
-                   | (0xfUL << 24)  // FPHP
-                   | (0xfUL << 20)  // SIMDHP
-                   | (0xfUL << 16)  // SIMDSP
-                   | (0xfUL << 12)  // SIMDInt
-                   | (0xfUL <<  8)  // SIMDLS
-                   | (0xfUL <<  4)  // FPDNaN
-                   | (0xfUL <<  0)  // FPFtZ
-      );
-
-      // ID_MVFR2_EL1
-      ADD_FEAT_REG(3, 0, 0, 3, 2,
-                     (0xfUL <<  4)  // FPMisc
-                   | (0xfUL <<  0)  // SIMDMisc
-      );
-
-      // ID_PFR2_EL1
-      ADD_FEAT_REG(3, 0, 0, 3, 4,
-                     (  0UL <<  8)  // Mask RAS_frac (RAS)
-                   | (0xfUL <<  4)  // SSBS
-                   | (0xfUL <<  0)  // CSV3
-      );
-
-      // ID_DFR1_EL1
-      ADD_FEAT_REG(3, 0, 0, 3, 5,
-                     (  0UL <<  4)  // Mask HPMN0 (PMU)
-                   | (  0UL <<  0)  // Mask MTPMU (PMU)
-      );
-
-      // ID_MMFR5_EL1
-      ADD_FEAT_REG(3, 0, 0, 3, 6,
-                     (0xfUL <<  4)  // nTLBPA
-                   | (0xfUL <<  0)  // ETS
-      );
-    }
-
-  // ID_AA64PFR0_EL1
-  ADD_FEAT_REG(3, 0, 0, 4, 0,
-                 (0xfUL << 60)  // CSV3
-               | (0xfUL << 56)  // CSV2
-               | (  0UL << 52)  // Mask RME
-               | (0xfUL << 48)  // DIT
-               | (  0UL << 44)  // Mask AMU
-               | (  0UL << 40)  // Mask MPAM
-               | (0xfUL << 36)  // SEL2
-               | (  0UL << 32)  // Mask SVE
-               | (  0UL << 28)  // Mask RAS
-               | (0xfUL << 24)  // GIC
-               | (0xfUL << 20)  // AdvSIMD
-               | (0xfUL << 16)  // FP
-               | (0xfUL << 12)  // EL3
-               | (0xfUL <<  8)  // EL2
-               | (0xfUL <<  4)  // EL1
-               | (0xfUL <<  0)  // EL0
-  );
-
-  // ID_AA64PFR1_EL1
-  ADD_FEAT_REG(3, 0, 0, 4, 1,
-                 (  0UL << 60)  // Mask PFAR
-               | (  0UL << 56)  // Mask DF2 (RAS related)
-               | (  0UL << 52)  // Mask MTEX
-               | (  0UL << 48)  // Mask THE
-               | (  0UL << 44)  // Mask GCS
-               | (  0UL << 40)  // Mask MTE_frac
-               | (0xfUL << 36)  // NMI
-               | (0xfUL << 32)  // CSV2_frac
-               | (0xfUL << 28)  // RNDR_trap
-               | (  0UL << 24)  // Mask SME
-               | (  0UL << 20)  // RES0
-               | (  0UL << 16)  // Mask MPAM_frac
-               | (  0UL << 12)  // Mask RAS_frac
-               | (  0UL <<  8)  // Mask MTE
-               | (0xfUL <<  4)  // SSBS
-               | (0xfUL <<  0)  // BT
-  );
-
-  // ID_AA64PFR2_EL1
-  ADD_FEAT_REG(3, 0, 0, 4, 2,
-                 (0xfUL <<  8)  // Mask MTEFAR (MTE)
-               | (0xfUL <<  4)  // Mask MTESTOREONLY (MTE)
-               | (0xfUL <<  0)  // Mask MTEPERM (MTE)
-  );
-
-  // ID_AA64ZFR0_EL1 skipped intentionally (SVE Feature ID Register 0)
-  // ID_AA64SMFR0_EL1 skipped intentionally (SME Feature ID Register 0)
-
-  // ID_AA64DFR0_EL1
-  ADD_FEAT_REG(3, 0, 0, 5, 0,
-                 (  0UL << 60)  // Mask HPMN0
-               | (  0UL << 56)  // Mask ExtTrcBuff
-               | (  0UL << 52)  // Mask BRBE
-               | (  0UL << 48)  // Mask MTPMU
-               | (  0UL << 44)  // Mask TraceBuffer
-               | (  0UL << 40)  // Mask TraceFilt
-               | (  0UL << 36)  // Mask DoubleLock
-               | (  0UL << 32)  // Mask PMSVer
-               | (  0UL << 28)  // Mask CTX_CMPs
-               | (  0UL << 24)  // Mask SEBEP
-               | (  0UL << 20)  // Mask WRPs
-               | (  0UL << 16)  // Mask PMSS
-               | (  0UL << 12)  // Mask BRPs
-               | (  0UL <<  8)  // Mask PMUVer
-               | (  0UL <<  4)  // Mask TraceVer
-               | (0xfUL <<  0)  // DebugVer
-  );
-
-  // ID_AA64DFR1_EL1
-  ADD_FEAT_REG(3, 0, 0, 5, 1,
-                 (  0UL << 56)  // Mask ABL_CMPs
-               | (  0UL << 52)  // Mask DPFZS
-               | (  0UL << 48)  // Mask EBEP
-               | (  0UL << 44)  // Mask ITE
-               | (  0UL << 40)  // Mask ABLE
-               | (  0UL << 36)  // Mask PMICNTR
-               | (  0UL << 32)  // Mask SPMU
-               | (  0UL << 24)  // Mask CTX_CMPs
-               | (  0UL << 16)  // Mask WRPs
-               | (  0UL <<  8)  // Mask BRPs
-               | (  0UL <<  0)  // Mask SYSPMUID
-  );
-
-  // ID_AA64AFR0_EL1 skipped intentionally
-  // ID_AA64AFR1_EL1 skipped intentionally
-
-  // ID_AA64ISAR0_EL1
-  ADD_FEAT_REG(3, 0, 0, 6, 0,
-                 (0xfUL << 60)  // RNDR
-               | (0xfUL << 56)  // TLB
-               | (0xfUL << 52)  // TS
-               | (0xfUL << 48)  // FHM
-               | (0xfUL << 44)  // DP
-               | (0xfUL << 40)  // SM4
-               | (0xfUL << 36)  // SM3
-               | (0xfUL << 32)  // SHA3
-               | (0xfUL << 28)  // RDM
-               | (0xfUL << 24)  // TME
-               | (0xfUL << 20)  // Atomic
-               | (0xfUL << 16)  // CRC32
-               | (0xfUL << 12)  // SHA2
-               | (0xfUL <<  8)  // SHA1
-               | (0xfUL <<  4)  // AES
-               | (  0UL <<  0)  // RES0
-  );
-
-  // ID_AA64ISAR1_EL1
-  ADD_FEAT_REG(3, 0, 0, 6, 1,
-                 (0xfUL << 60)  // LS64
-               | (0xfUL << 56)  // XS
-               | (0xfUL << 52)  // I8MM
-               | (0xfUL << 48)  // DGH
-               | (0xfUL << 44)  // BF16
-               | (0xfUL << 40)  // SPECRES
-               | (0xfUL << 36)  // SB
-               | (0xfUL << 32)  // FRINTTS
-               | (  0UL << 28)  // Mask GPI (FEAT_PAuth)
-               | (  0UL << 24)  // Mask GPA (FEAT_PAuth)
-               | (  0UL << 20)  // Mask LRCPC (FEAT_LRCPC)
-               | (0xfUL << 16)  // FCMA
-               | (0xfUL << 12)  // JSCVT
-               | (  0UL <<  8)  // Mask API (FEAT_PAuth)
-               | (  0UL <<  4)  // Mask APA (FEAT_PAuth)
-               | (0xfUL <<  0)  // DPB
-  );
-
-  // ID_AA64ISAR2_EL1
-  ADD_FEAT_REG(3, 0, 0, 6, 2,
-                 (0xfUL << 60)  // ATS1A
-               | (  0UL << 56)  // RES0
-               | (0xfUL << 52)  // CSSC
-               | (0xfUL << 48)  // RPRFM
-               | (  0UL << 44)  // RES0
-               | (0xfUL << 40)  // PRFMSLC
-               | (0xfUL << 36)  // SYSINSTR_128
-               | (0xfUL << 32)  // SYSREG_128
-               | (0xfUL << 28)  // CLRBHB
-               | (  0UL << 24)  // Mask PAC_frac (FEAT_PAuth2)
-               | (0xfUL << 20)  // BC
-               | (0xfUL << 16)  // MOPS
-               | (  0UL << 12)  // Mask APA3 (FEAT_PAuth)
-               | (  0UL <<  8)  // Mask GPA3 (FEAT_PAuth)
-               | (0xfUL <<  4)  // RPRES
-               | (0xfUL <<  0)  // WFxT
-  );
-
-  // ID_AA64MMFR0_EL1
-  ADD_FEAT_REG(3, 0, 0, 7, 0,
-                 (0xfUL << 60)  // ECV
-               | (0xfUL << 56)  // FGT
-               | (0xfUL << 52)  // MSA_frac
-               | (0xfUL << 48)  // MSA
-               | (0xfUL << 44)  // ExS
-               | (0xfUL << 40)  // TGran4_2
-               | (0xfUL << 36)  // TGran64_2
-               | (0xfUL << 32)  // TGran16_2
-               | (0xfUL << 28)  // TGran4
-               | (0xfUL << 24)  // TGran64
-               | (0xfUL << 20)  // TGran16
-               | (0xfUL << 16)  // BigEndEL0
-               | (0xfUL << 12)  // SNSMem
-               | (0xfUL <<  8)  // BigEnd
-               | (0xfUL <<  4)  // ASIDBits
-               | (0xfUL <<  0)  // PARange
-  );
-
-  // ID_AA64MMFR1_EL1
-  ADD_FEAT_REG(3, 0, 0, 7, 1,
-                 (0xfUL << 60)  // ECBHB
-               | (0xfUL << 56)  // CMOW
-               | (0xfUL << 52)  // TIDCP1
-               | (0xfUL << 48)  // nTLBPA
-               | (0xfUL << 44)  // AFP
-               | (0xfUL << 40)  // HCX
-               | (0xfUL << 36)  // ETS
-               | (0xfUL << 32)  // TWED
-               | (0xfUL << 28)  // XNX
-               | (  0UL << 24)  // Mask SpecSEI (RAS)
-               | (0xfUL << 20)  // PAN
-               | (  0UL << 16)  // Mask LO (FEAT_LOR)
-               | (0xfUL << 12)  // HPDS
-               | (0xfUL <<  8)  // VH
-               | (0xfUL <<  4)  // VMIDBits
-               | (0xfUL <<  0)  // HAFDBS
-  );
-
-  // ID_AA64MMFR2_EL1
-  ADD_FEAT_REG(3, 0, 0, 7, 2,
-                 (0xfUL << 60)  // E0PD
-               | (0xfUL << 56)  // EVT
-               | (0xfUL << 52)  // BBM
-               | (0xfUL << 48)  // TTL
-               | (  0UL << 44)  // RES0
-               | (0xfUL << 40)  // FWB
-               | (0xfUL << 36)  // IDS
-               | (0xfUL << 32)  // AT
-               | (0xfUL << 28)  // ST
-               | (0xfUL << 24)  // NV
-               | (0xfUL << 20)  // CCIDX
-               | (0xfUL << 16)  // VARange
-               | (  0UL << 12)  // Mask IESB (FEAT_IESB + FEAT_RAS)
-               | (0xfUL <<  8)  // LSM
-               | (0xfUL <<  4)  // UAO
-               | (0xfUL <<  0)  // CnP
-  );
-
-  // ID_AA64MMFR3_EL1
-  ADD_FEAT_REG(3, 0, 0, 7, 3,
-                 (  0UL << 60)  // Mask Spec_FPACC (FEAT_PAuth++)
-               | (  0UL << 56)  // Mask ADERR (RASv2)
-               | (  0UL << 52)  // Mask SDERR (RASv2)
-               | (  0UL << 48)  // RES0
-               | (  0UL << 44)  // Mask ANERR (RASv2)
-               | (  0UL << 40)  // Mask SNERR (RASv2)
-               | (0xfUL << 36)  // D128_2
-               | (0xfUL << 32)  // D128
-               | (  0UL << 28)  // Mask MEC
-               | (0xfUL << 24)  // AIE
-               | (0xfUL << 20)  // S2POE
-               | (0xfUL << 16)  // S1POE
-               | (0xfUL << 12)  // S2PIE
-               | (0xfUL <<  8)  // S1PIE
-               | (0xfUL <<  4)  // SCTLRX
-               | (0xfUL <<  0)  // TCRX
-  );
-
-  // ID_AA64MMFR4_EL1
-  ADD_FEAT_REG(3, 0, 0, 7, 4,
-               0UL << 4  // EIESB (RAS)
-  );
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.h b/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.h
deleted file mode 100644
index dc57a848..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/guest_subarch.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-namespace Vmm {
-
-enum { Guest_64bit_supported = true };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/monitor/cpu_dev_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-arm64/monitor/cpu_dev_cmd_handler.h
deleted file mode 100644
index 39d57eb6..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/monitor/cpu_dev_cmd_handler.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "vcpu_ptr.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Cpu_dev_cmd_handler {};
-
-template
-class Cpu_dev_cmd_handler : public Cmd
-{
-public:
-  char const *help() const override
-  { return "CPU state"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'cpu  regs': dump CPU registers\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, "regs"); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "regs")
-      show_regs(f);
-    else
-      argument_error("Invalid subcommand");
-  }
-
-  void show_regs(FILE *f) const
-  {
-    auto vcpu = get_vcpu();
-    auto regs = vcpu->r;
-
-    for (unsigned i = 0; i < 31; ++i)
-      fprintf(f, "x%2d:%16lx%s", i, regs.r[i], (i % 4) == 3 ? "\n" : "  ");
-
-    fprintf(f, "\npc=%lx  sp=%lx  psr=%lx  sctlr=%x\n",
-            regs.ip, regs.sp, regs.flags,
-            l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_SCTLR));
-  }
-
-private:
-  Vmm::Vcpu_ptr get_vcpu() const
-  { return static_cast(this)->vcpu(); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-arm64/vcpu_ptr.h b/src/l4/pkg/uvmm/server/src/ARCH-arm64/vcpu_ptr.h
deleted file mode 100644
index 574cc653..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-arm64/vcpu_ptr.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2015-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "aarch64_hyp.h"
-#include "generic_vcpu_ptr.h"
-#include "mem_access.h"
-
-namespace Vmm {
-
-class Vcpu_ptr : public Generic_vcpu_ptr
-{
-public:
-  explicit Vcpu_ptr(l4_vcpu_state_t *s) : Generic_vcpu_ptr(s) {}
-
-  bool pf_write() const
-  { return hsr().pf_write(); }
-
-  static l4_uint32_t cntfrq()
-  {
-    l4_uint32_t x;
-    asm volatile ("mrs %x0, CNTFRQ_EL0" : "=r"(x));
-    return x;
-  }
-
-  static l4_uint64_t cntvct()
-  {
-    l4_uint64_t x;
-    asm volatile ("mrs %0, CNTVCT_EL0" : "=r"(x));
-    return x;
-  }
-
-  static l4_uint64_t cntv_cval()
-  {
-    l4_uint64_t x;
-    asm volatile ("mrs %0, CNTV_CVAL_EL0" : "=r"(x));
-    return x;
-  }
-
-  void *saved_tls() const
-  { return reinterpret_cast(l4_vcpu_e_info_user(_s)[1]); }
-
-  l4_utcb_t *restore_on_entry() const
-  {
-    asm volatile("msr TPIDR_EL0, %0" : : "r"(saved_tls()));
-    return reinterpret_cast(l4_vcpu_e_info_user(_s)[0]);
-  }
-
-  void thread_attach()
-  {
-    control_ext(L4::Cap());
-    void **x = reinterpret_cast(l4_vcpu_e_info_user(_s));
-    x[0] = l4_utcb();
-    asm volatile ("mrs %0, TPIDR_EL0" : "=r"(x[1]));
-  }
-
-  Arm::Hsr hsr() const
-  { return Arm::Hsr(_s->r.err); }
-
-  void jump_instruction() const
-  { _s->r.ip += 2 << hsr().il(); }
-
-  l4_umword_t get_gpr(unsigned x) const
-  {
-    if (x < 31)
-      return _s->r.r[x];
-    else
-      return 0;
-  }
-
-  void set_gpr(unsigned x, l4_umword_t value) const
-  {
-    if (x < 31)
-      _s->r.r[x] = value;
-  }
-
-  l4_umword_t get_lr() const
-  {
-    return _s->r.r[30];
-  }
-
-  Mem_access decode_mmio() const
-  {
-    Mem_access m;
-
-    if (!hsr().pf_isv())
-      {
-        m.access = Mem_access::Other;
-        return m;
-      }
-
-    m.width = hsr().pf_sas();
-    m.access = hsr().pf_write() ? Mem_access::Store : Mem_access::Load;
-
-    if (m.access == Mem_access::Store)
-      m.value = get_gpr(hsr().pf_srt());
-
-    return m;
-  }
-
-  void writeback_mmio(Mem_access const &m) const
-  {
-    assert(m.access == Mem_access::Load);
-
-    l4_umword_t v = reg_extend_width(m.value, hsr().pf_sas(), hsr().pf_sse());
-    set_gpr(hsr().pf_srt(), v);
-  }
-
-  Arm::Gic_h::Vcpu_ppi_cfg vtmr() const
-  {
-    return Arm::Gic_h::Vcpu_ppi_cfg(l4_vcpu_e_read_32(_s, L4_VCPU_E_VTMR_CFG));
-  }
-
-  void vtmr(Arm::Gic_h::Vcpu_ppi_cfg cfg)
-  { l4_vcpu_e_write_32(_s, L4_VCPU_E_VTMR_CFG, cfg.raw); }
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/binary_loader_raw.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/binary_loader_raw.h
deleted file mode 100644
index fcd4dd1c..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/binary_loader_raw.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-namespace Boot {
-
-static int raw_load_image(std::shared_ptr image, Vmm::Vm_ram *ram,
-                          Vmm::Ram_free_list *free_list, l4_addr_t *entry)
-{
-  l4_addr_t start = *entry == ~0ul ? 0x100000 : *entry;
-
-  image->load_as_raw(ram, Vmm::Guest_addr(start), free_list);
-  *entry = ram->guest_phys2boot(Vmm::Guest_addr(0x100400));
-
-  return L4_EOK;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/cm.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/cm.h
deleted file mode 100644
index 9db7fcd7..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/cm.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2017-2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "mmio_device.h"
-#include "vm_memmap.h"
-#include "cpc.h"
-
-namespace Vdev {
-
-/**
- * Virtual Mips coherency manager.
- *
- * This device only implements the global registers of the CM and
- * only emulatates functionality necessary for SMP support.
- * Access to the CPU-local registers are forwarded to the
- * CPC.
- *
- * Each VCPU is reported as a separate core with exactly one VPE.
- */
-class Coherency_manager : public Vmm::Mmio_device_t
-{
-  enum Memmap
-  {
-    Base_address = 0x1fbf8000,
-    Cm_size = 0x10000,
-    Control_block_size = 0x2000,
-    Core_local_base = 0x2000,
-    Core_other_base = 0x4000
-  };
-
-  enum Global_control_block
-  {
-    Gcr_config = 0x0,
-    Gcr_base = 0x8,
-    Gcr_control = 0x10,
-    Gcr_rev = 0x30,
-    Gcr_gic_base = 0x80,
-    Gcr_cpc_base = 0x88,
-    Gcr_gic_status = 0xd0,
-    Gcr_cpc_status = 0xf0,
-    Gcr_sys_config2 = 0x150,
-    Gcr_bev_base = 0x680
-  };
-
-public:
-  struct Cpc_base_addr_reg
-  {
-    Cpc_base_addr_reg() = default;
-    explicit Cpc_base_addr_reg(l4_umword_t value) : raw(value) {}
-
-    l4_umword_t raw;
-
-    CXX_BITFIELD_MEMBER(0, 0, enable, raw);
-#ifdef __mips64
-    CXX_BITFIELD_MEMBER_UNSHIFTED_RO(15, 47, base_addr, raw);
-#else
-    CXX_BITFIELD_MEMBER_UNSHIFTED_RO(15, 31, base_addr, raw);
-#endif
-  };
-
-  Coherency_manager(Vmm::Vm_mem *memmap)
-  : _memmap(memmap), _gic_base(0), _cpc_base(0)
-  {}
-
-  static Vmm::Region mem_region()
-  {
-    return Vmm::Region::ss(Vmm::Guest_addr(Base_address), Cm_size,
-                           Vmm::Region_type::Virtual);
-  }
-
-  void register_cpc(cxx::Ref_ptr const &cpc) { _cpc = cpc; }
-
-  l4_umword_t read(unsigned reg, char, unsigned cpuid)
-  {
-    Dbg dbg(Dbg::Cpu, Dbg::Info, "CM");
-
-    if (reg >= Core_local_base && reg < Core_local_base + Control_block_size)
-      {
-        if (!_cpc)
-          return 0;
-
-        return _cpc->cm_read_core(reg - Core_local_base, cpuid, false);
-      }
-
-    if (reg >= Core_other_base && reg < Core_other_base + Control_block_size)
-      {
-        if (!_cpc)
-          return 0;
-
-        return _cpc->cm_read_core(reg - Core_other_base, cpuid, true);
-      }
-
-    Dbg(Dbg::Cpu, Dbg::Trace, "CM").printf("reading GCR @ 0x%x\n", reg);
-    switch (reg)
-      {
-      case Gcr_config:
-        return _cpc->max_cpuid(); // no ICUs
-      case Gcr_base:
-        return Base_address;
-      case Gcr_rev:
-        return 8 << 8; // CM3
-      case Gcr_gic_base:
-        return _gic_base;
-      case Gcr_cpc_base:
-        return _cpc_base.raw;
-      case Gcr_gic_status:
-        return 1; // GIC is CM-controlled
-      case Gcr_cpc_status:
-        return 1; // CPC enabled
-      case Gcr_sys_config2:
-        return 1; // maximum 1 VP per core
-      case Gcr_bev_base:
-        return _cpc ? _cpc->bev_base() : 0;
-      }
-
-    Dbg(Dbg::Cpu, Dbg::Info, "CM").printf("reading @ 0x%x ignored.\n", reg);
-    return 0;
-  }
-
-  void write(unsigned reg, char, l4_umword_t value, unsigned cpuid)
-  {
-    if (reg >= Core_local_base && reg < Core_local_base + Control_block_size)
-      {
-        if (_cpc)
-          _cpc->cm_write_core(reg - Core_local_base, value, cpuid, false);
-        return;
-      }
-
-    if (reg >= Core_other_base && reg < Core_other_base + Control_block_size)
-      {
-        if (_cpc)
-          _cpc->cm_write_core(reg - Core_other_base, value, cpuid, true);
-        return;
-      }
-
-    Dbg(Dbg::Cpu, Dbg::Trace, "CM")
-      .printf("writing GCR 0x%lx @ 0x%x\n", value, reg);
-    switch (reg)
-      {
-      case Gcr_gic_base:
-        // XXX check that this address is expected
-        _gic_base = value;
-        break;
-      case Gcr_cpc_base:
-        {
-          Cpc_base_addr_reg newbase(value);
-
-          if (_cpc_base.base_addr())
-            {
-              _cpc_base.enable() = (unsigned)newbase.enable();
-
-              if (newbase.enable()
-                  && _cpc_base.base_addr() != newbase.base_addr())
-                Dbg(Dbg::Cpu, Dbg::Warn, "CM")
-                  .printf("WARNING: change of CPC base address ignored.\n");
-            }
-          else
-            {
-              _cpc_base.raw = newbase.raw;
-
-              assert(_cpc);
-
-              Dbg(Dbg::Cpu, Dbg::Info, "CM")
-                .printf("Mapping CPC @ 0x%lx\n",
-                        (l4_addr_t)_cpc_base.base_addr());
-
-              (*_memmap)[Vmm::Region::ss(Vmm::Guest_addr(_cpc_base.base_addr()),
-                                         Mips_cpc::Cpc_size,
-                                         Vmm::Region_type::Virtual)] = _cpc;
-            }
-          break;
-        }
-      case Gcr_bev_base:
-        if (_cpc)
-          _cpc->set_bev_base(value);
-        break;
-      default:
-        Dbg(Dbg::Cpu, Dbg::Info, "CM")
-          .printf("writing GCR 0x%lx @ 0x%x ignored.\n", value, reg);
-      }
-  }
-
-  char const *dev_name() const override { return "Coherency_manager"; }
-
-private:
-  cxx::Ref_ptr _cpc;
-  Vmm::Vm_mem *_memmap;
-  l4_addr_t _gic_base;
-  Cpc_base_addr_reg _cpc_base;
-};
-
-} // name space
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/core_ic.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/core_ic.h
deleted file mode 100644
index fcaaa7d8..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/core_ic.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2016-2018, 2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-
-#include "irq.h"
-#include "vcpu_ptr.h"
-
-namespace Gic {
-
-/**
- * Interrupt handler for core interrupts for a single VCPU.
- *
- * The Mips core interrupts are line-triggered and can be connected
- * to multiple devices. This is implemented by a pending counter for
- * each interrupt. Only connect stateful IRQ sinks to ensure the counting
- * is correct.
- *
- * Only handles the hardware interrupts 2 - 7.
- */
-class Vcpu_ic : public Ic
-{
-  enum
-  {
-    Min_irq = 2,
-    Max_irq = 7
-  };
-
-public:
-  Vcpu_ic()
-  : _cpu_irq(L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                          "allocate vcpu notification interrupt")),
-    _irqvec(0)
-  {
-    for (size_t i = Min_irq; i <= Max_irq; ++i)
-      _pending[i - Min_irq] = 0;
-
-    L4Re::Env::env()->factory()->create(_cpu_irq.get());
-  }
-
-  void attach_cpu_thread(L4::Cap thread)
-  {
-    L4Re::chksys(_cpu_irq->bind_thread(thread, 0),
-                 "Bind vCPU IRQ-notification IRQ.");
-  }
-
-  void set(unsigned irq) override
-  {
-    assert(Min_irq <= irq && irq <= Max_irq);
-    std::lock_guard lock(_lock);
-    if (++_pending[irq - Min_irq] == 1)
-      {
-        _irqvec |= 1UL << (irq - Min_irq);
-        _cpu_irq->trigger();
-      }
-  }
-
-  void clear(unsigned irq) override
-  {
-    assert(Min_irq <= irq && irq <= Max_irq);
-    std::lock_guard lock(_lock);
-    if (--_pending[irq - Min_irq] == 0)
-      {
-        _irqvec &= ~(1UL << (irq - Min_irq));
-        _cpu_irq->trigger();
-      }
-  }
-
-  void bind_irq_src_handler(unsigned, Irq_src_handler *) override
-  {
-    L4Re::chksys(-L4_ENOSYS, "unmask not supported for Core IC. "
-                             "Use GIC for devices that require EOI via IC.");
-  }
-
-  Irq_src_handler *get_irq_src_handler(unsigned) const override
-  { return nullptr; }
-
-  int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const override
-  {
-    if (propsz < 1)
-      return -L4_ERANGE;
-
-    int irq = fdt32_to_cpu(prop[0]);
-
-    if (read)
-      *read = 1;
-
-    return irq;
-  }
-
-  l4_uint32_t irq_vector()
-  {
-    std::lock_guard lock(_lock);
-    return _irqvec;
-  }
-
-  void show_state(FILE *f, Vmm::Vcpu_ptr vcpu)
-  {
-    auto *s = vcpu.state();
-    s->update_state(L4_VM_MOD_STATUS);
-    unsigned imask = s->g_status >> 8;
-    unsigned ipending = s->g_cause >> 8;
-
-    for (unsigned i = Min_irq; i <= Max_irq; ++i)
-      fprintf(f, " Int %d: %d (HW: %s/%s)\n", i,
-              _pending[i - Min_irq],
-              imask & (1 << i) ? "on" : "off",
-              ipending & (1 << i) ? "pending" : "low");
-  }
-
-private:
-  L4Re::Util::Unique_cap _cpu_irq;
-  /// Cached output pending array.
-  l4_uint32_t _irqvec;
-  /// Count for each interrupt the number of incomming sources.
-  int _pending[Max_irq - Min_irq + 1];
-  std::mutex _lock;
-};
-
-/**
- * Device for all core interrupts.
- *
- * This device is not an interrupt handler itself, it just holds
- * an array of core interrupt handlers, one for each core.
- */
-class Mips_core_ic : public virtual Vdev::Dev_ref
-{
-  enum { Max_ics = 32 };
-
-  struct Hw_int_reg
-  {
-    l4_umword_t raw;
-    CXX_BITFIELD_MEMBER(10, 15, hw_ints, raw);
-
-    Hw_int_reg(l4_umword_t r) : raw(r) {}
-  };
-
-public:
-  Mips_core_ic()
-  {
-    // there always is an IC for CPU 0
-    _core_ics[0] = Vdev::make_device();
-  }
-
-  virtual ~Mips_core_ic() = default;
-
-  void create_ic(unsigned i, L4::Cap thread)
-  {
-    assert(i <= Max_ics);
-    // start up one core IC per vcpu
-    if (!_core_ics[i])
-      _core_ics[i] = Vdev::make_device();
-    _core_ics[i]->attach_cpu_thread(thread);
-  }
-
-  cxx::Ref_ptr get_ic(unsigned cpuid) const
-  {
-    assert(cpuid < Max_ics);
-    return _core_ics[cpuid];
-  }
-
-  static bool has_pending(Vmm::Vcpu_ptr vcpu)
-  {
-    return Hw_int_reg(vcpu.state()->guest_ctl_2).hw_ints();
-  }
-
-  void update_vcpu(Vmm::Vcpu_ptr vcpu)
-  {
-    unsigned cpuid = vcpu.get_vcpu_id();
-
-    assert(cpuid < Max_ics);
-    assert(_core_ics[cpuid]);
-
-    auto irqvec = _core_ics[cpuid]->irq_vector();
-
-    Hw_int_reg *gc2 = (Hw_int_reg *) &vcpu.state()->guest_ctl_2;
-    l4_uint32_t oldvec = gc2->hw_ints();
-
-    if (oldvec == irqvec)
-      return;
-
-    gc2->hw_ints() = irqvec;
-    vcpu.state()->set_modified(L4_VM_MOD_GUEST_CTL_2);
-  }
-
-  void show_state(FILE *f, Vmm::Vcpu_ptr vcpu)
-  {
-    unsigned cpuid = vcpu.get_vcpu_id();
-    if (_core_ics[cpuid])
-      _core_ics[cpuid]->show_state(f, vcpu);
-  }
-
-private:
-  cxx::Ref_ptr _core_ics[Max_ics];
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.cc b/src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.cc
deleted file mode 100644
index b9ba8935..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2017, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "cpc.h"
-
-namespace Vdev {
-
-static Dbg warn(Dbg::Cpu, Dbg::Warn, "CPC");
-static Dbg info(Dbg::Cpu, Dbg::Info, "CPC");
-static Dbg trace(Dbg::Cpu, Dbg::Trace, "CPC");
-
-l4_umword_t
-Mips_cpc::read(unsigned reg, char, unsigned cpuid)
-{
-  trace.printf("reading CPC @ 0x%x\n", reg);
-
-  if (reg >= Core_local_base && reg < Core_local_base + Control_block_size)
-    return cpc_read_core(reg - Core_local_base, cpuid);
-
-  if (reg >= Core_other_base && reg < Core_other_base + Control_block_size)
-    {
-      if ((cpuid >= _cpus->size()) || !_cpus->vcpu_exists(cpuid))
-        {
-          info.printf("read on unknown other core %d. Ignored.\n", cpuid);
-          return 0;
-        }
-
-      return cpc_read_core(reg - Core_other_base, _cpus->cpu(cpuid)->core_other());
-    }
-
-  info.printf("reading unknown register @ 0x%x ignored.\n", reg);
-  return 0;
-}
-
-void
-Mips_cpc::write(unsigned reg, char, l4_umword_t value, unsigned cpuid)
-{
-  trace.printf("writing CPC 0x%lx @ 0x%x\n", value, reg);
-
-  if (reg >= Core_local_base && reg < Core_local_base + Control_block_size)
-    cpc_write_core(reg - Core_local_base, value, cpuid);
-  else if (reg >= Core_other_base && reg < Core_other_base + Control_block_size)
-    {
-      if ((cpuid < _cpus->size()) && _cpus->vcpu_exists(cpuid))
-        cpc_write_core(reg - Core_other_base, value, _cpus->cpu(cpuid)->core_other());
-      else
-        info.printf("read on unknown other core %d. Ignored.\n", cpuid);
-    }
-  else
-    info.printf("writing unknown register 0x%lx @ 0x%x ignored.\n", value, reg);
-}
-
-l4_umword_t
-Mips_cpc::cpc_read_core(unsigned reg, unsigned cpuid)
-{
-  if (cpuid >= _cpus->size() || !_cpus->vcpu_exists(cpuid))
-    {
-      info.printf("CPC reading from uninitialised core %d ignored.\n", cpuid);
-      return 0;
-    }
-
-  trace.printf("core %d: reading CPC @ 0x%x\n", cpuid, reg);
-
-  switch (reg)
-    {
-    case Cpc_cl_stat_conf_reg:
-      return _cpus->cpu(cpuid)->cpc_status();
-    default:
-      info.printf("core %d: reading CPC @ 0x%x ignored.\n", cpuid, reg);
-    }
-
-  return 0;
-}
-
-void
-Mips_cpc::cpc_write_core(unsigned reg, l4_umword_t value, unsigned cpuid)
-{
-  if (cpuid >= _cpus->size() || !_cpus->vcpu_exists(cpuid))
-    {
-      info.printf("CPC writing to uninitialised core %d ignored.\n", cpuid);
-      return;
-    }
-
-  trace.printf("core %d: writing CPC 0x%lx @ 0x%x\n", cpuid, value, reg);
-
-  switch (reg)
-    {
-    case Cpc_cl_cmd_reg:
-      {
-        unsigned cmd = value & 0x7;
-        _cpus->cpu(cpuid)->set_last_command(cmd);
-
-        switch (cmd)
-          {
-          case Cpc_cmd_pwr_down:
-            _cpus->cpu(cpuid)->stop_vcpu();
-            break;
-          case Cpc_cmd_pwr_up:
-          case Cpc_cmd_reset:
-            _cpus->cpu(cpuid)->start_vcpu(_bev_base);
-            break;
-          }
-        break;
-      }
-    default:
-      info.printf("core %d: writing 0x%lx @ 0x%x ignored.\n",
-                  cpuid, value, reg);
-    }
-}
-
-
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.h
deleted file mode 100644
index 139bbe0d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpc.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "debug.h"
-#include "mmio_device.h"
-#include "cpu_dev_array.h"
-
-namespace Vdev {
-
-class Mips_cpc :  public Vmm::Mmio_device_t
-{
-private:
-  enum Cpc_local_registers
-  {
-    Cpc_cl_cmd_reg = 0x0,
-    Cpc_cl_stat_conf_reg = 0x8
-  };
-
-  enum Cpc_commands
-  {
-    Cpc_cmd_clock_off = 1,
-    Cpc_cmd_pwr_down = 2,
-    Cpc_cmd_pwr_up = 3,
-    Cpc_cmd_reset = 4
-  };
-
-public:
-  enum Memmap
-  {
-    Cpc_size = 0x6000,
-    Core_local_base = 0x2000,
-    Core_other_base = 0x4000,
-    Control_block_size = 0x2000
-  };
-
-  void register_cpus(cxx::Ref_ptr cpus)
-  { _cpus = cpus; }
-
-  void set_bev_base(l4_umword_t value)
-  { _bev_base = value; }
-
-  l4_umword_t bev_base() const
-  { return _bev_base; }
-
-  l4_umword_t read(unsigned reg, char size, unsigned cpuid);
-  void write(unsigned reg, char size, l4_umword_t value, unsigned cpuid);
-
-  l4_umword_t cm_read_core(unsigned reg, unsigned cpuid, bool other)
-  {
-    if (cpuid >= _cpus->size() || !_cpus->vcpu_exists(cpuid))
-      return 0;
-
-    if (other)
-      {
-        cpuid = _cpus->cpu(cpuid)->core_other();
-        if (cpuid >= _cpus->size() || !_cpus->vcpu_exists(cpuid))
-          {
-            Dbg(Dbg::Cpu, Dbg::Info, "CMloc").printf(
-                "CM reading from uninitialised core %d ignored.\n", cpuid);
-            return 0;
-          }
-      }
-
-    Dbg(Dbg::Cpu, Dbg::Trace, "CMloc").printf(
-        "core %d: reading CM @ 0x%x\n", cpuid, reg);
-
-    return _cpus->cpu(cpuid)->read_cm_reg(reg);
-  }
-
-  void cm_write_core(unsigned reg, l4_umword_t value, unsigned cpuid,
-                     bool other)
-  {
-    if (cpuid >= _cpus->size()|| !_cpus->vcpu_exists(cpuid))
-      return;
-
-    if (other)
-      {
-        cpuid = _cpus->cpu(cpuid)->core_other();
-        if (cpuid >= _cpus->size() || !_cpus->vcpu_exists(cpuid))
-          {
-            Dbg(Dbg::Cpu, Dbg::Info, "CMloc").printf(
-                "CM writing to uninitialised core %d ignored.\n", cpuid);
-            return;
-          }
-      }
-
-    Dbg(Dbg::Cpu, Dbg::Trace, "CMloc").printf(
-        "core %d: writing CM 0x%lx @ 0x%x.\n", cpuid, value, reg);
-
-    _cpus->cpu(cpuid)->write_cm_reg(reg, value);
-  }
-
-  /// Return the maximum CPU id in use.
-  unsigned max_cpuid() const
-  { return _cpus->max_cpuid(); }
-
-  char const *dev_name() const override { return "Mips_cpc"; }
-
-private:
-  l4_umword_t cpc_read_core(unsigned reg, unsigned cpuid);
-  void cpc_write_core(unsigned reg, l4_umword_t value, unsigned cpuid);
-
-  l4_umword_t _bev_base;
-  cxx::Ref_ptr _cpus;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.cc b/src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.cc
deleted file mode 100644
index cf313142..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2017, 2019, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "cpu_dev.h"
-#include "guest_entry.h"
-
-static const std::pair MIPS_PROC_IDS[] =
-  {{0x0001a700, "mips,m5150"},
-   {0x0001a800, "mips,p5600"},
-   {0x0001a900, "mips,i6400"},
-   {0x0001b024, "mips,i6500"},
-   {0, nullptr}};
-
-static Dbg warn(Dbg::Cpu, Dbg::Warn, "CPU");
-static Dbg info(Dbg::Cpu, Dbg::Info, "CPU");
-static Dbg trace(Dbg::Cpu, Dbg::Trace, "CPU");
-
-namespace Vmm
-{
-
-static l4_umword_t
-get_proc_type(char const *compatible)
-{
-  if (!compatible)
-    return Cpu_dev::Default_procid;
-
-  for (auto *row = MIPS_PROC_IDS; row->second; ++row)
-    if (strcmp(row->second, compatible) == 0)
-      return row->first;
-
-  return Cpu_dev::Default_procid;
-}
-
-Cpu_dev::Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *node)
-: Generic_cpu_dev(idx, phys_id), _status(0), _core_other(0)
-{
-  // If a compatible property exists, it may be used to specify
-  // the reported CPU type (if supported by architecture). Without
-  // compatible property, the default is used.
-  char const *compatible = node ? node->get_prop("compatible", nullptr)
-                                : nullptr;
-  _vcpu.set_proc_id(get_proc_type(compatible));
-  _vcpu.alloc_fpu_state();
-  _status.seq_state() = Seq_non_coherent;
-}
-
-void
-Cpu_dev::reset()
-{
-  l4_umword_t sp;
-  asm ("move %0, $sp" : "=r" (sp));
-
-  _vcpu->saved_state = L4_VCPU_F_FPU_ENABLED
-                       | L4_VCPU_F_USER_MODE
-                       | L4_VCPU_F_IRQ
-                       | L4_VCPU_F_PAGE_FAULTS
-                       | L4_VCPU_F_EXCEPTIONS;
-  _vcpu->entry_ip = (l4_umword_t)&c_vcpu_entry;
-  _vcpu->entry_sp = sp & ~0xfUL;
-  _vcpu->r.status |= 8;
-
-  auto *s = _vcpu.state();
-  // disable trapping of CF1&2, CG and GT, enable ctl2
-  s->guest_ctl_0 |= 0x3000083;
-  s->guest_ctl_0_ext |= 0x10; // CGI
-  l4_umword_t cca = s->g_cfg[0] & 7UL;
-  s->g_seg_ctl[0] = 0x00200010;
-  s->g_seg_ctl[1] = 0x00000002 | (cca << 16);
-  s->g_seg_ctl[2] = 0x04300030 | (cca << 16) | cca;
-  s->g_ebase = (s->g_ebase & ~0x3ffUL) | _vcpu.get_vcpu_id();
-  s->set_modified(L4_VM_MOD_GUEST_CTL_0
-                  | L4_VM_MOD_GUEST_CTL_0_EXT
-                  | L4_VM_MOD_CFG
-                  | L4_VM_MOD_EBASE
-                  | L4_VM_MOD_XLAT);
-
-  Dbg(Dbg::Core, Dbg::Info)
-    .printf("Starting vcpu %d @ 0x%lx (handler @ %lx with stack @ %lx)\n",
-            _vcpu.get_vcpu_id(), _vcpu->r.ip, _vcpu->entry_ip, _vcpu->entry_sp);
-
-  L4::Cap myself;
-  auto e = l4_error(myself->vcpu_resume_commit(myself->vcpu_resume_start()));
-
-  Err().printf("VMM exited with %ld\n", e);
-}
-
-void
-Cpu_dev::start_vcpu(l4_addr_t bev_base)
-{
-  info.printf("Start of vcpu %d requested.\n", _vcpu.get_vcpu_id());
-
-  // setup vcpu state
-  if (_reset_base & 1)
-    {
-      _vcpu->r.ip = bev_base;
-      trace.printf("Using BEV reset base 0x%lx\n", bev_base);
-    }
-  else
-    {
-      _vcpu->r.ip = _reset_base & Cm_loc_reset_base_addr_mask;
-      trace.printf("Using Core reset base 0x%lx\n", _reset_base);
-    }
-
-  _vcpu.state()->g_status |= (1 << 2) | (1 << 22); // ERL, BEV
-
-  reschedule();
-
-  // consider it officially done
-  // XXX should that be done in reset code?
-  set_coherent();
-}
-
-void
-Cpu_dev::stop_vcpu()
-{
-  warn.printf("Stop of vcpu %d requested. NOT IMPLEMENTED.\n",
-              _vcpu.get_vcpu_id());
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.h
deleted file mode 100644
index a2dcee8d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/cpu_dev.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "generic_cpu_dev.h"
-#include "monitor/cpu_dev_cmd_handler.h"
-
-namespace Vmm {
-
-class Cpu_dev
-: public Generic_cpu_dev,
-  public Monitor::Cpu_dev_cmd_handler
-{
-public:
-  // Maximum number of CPUs that are addressable.
-  enum { Max_cpus = 32 };
-
-  enum { Default_procid = 0x00010000 };
-
-  enum Cm_local_registers
-  {
-    Cm_loc_coh_en = 0x08,
-    Cm_loc_config = 0x10,
-    Cm_loc_other = 0x18,
-    Cm_loc_reset_base = 0x20,
-    Cm_loc_id = 0x28,
-    Cm_loc_reset_ext_base = 0x30
-  };
-
-  // Mask of valid bits for various CM registers
-  enum Cm_register_masks
-  {
-    Cm_loc_other_mask = 0x3f,
-    Cm_loc_reset_base_mask = ~0xffcUL,
-    Cm_loc_reset_base_addr_mask = ~0xfffUL,
-    Cm_loc_reset_ext_base_mask = 0xcff000ff
-  };
-
-  enum Sequencer_state
-  {
-    Seq_pwr_down = 0x00,
-    Seq_reset = 0x04,
-    Seq_non_coherent = 0x06,
-    Seq_coherent = 0x07,
-  };
-
-  struct Local_status_reg
-  {
-    l4_uint32_t raw;
-    Local_status_reg() = default;
-    explicit Local_status_reg(l4_uint32_t raw) : raw(raw) {}
-
-    CXX_BITFIELD_MEMBER(23, 23, pwrup_event, raw);
-    CXX_BITFIELD_MEMBER(19, 22, seq_state, raw);
-    CXX_BITFIELD_MEMBER(17, 17, clkgat_impl, raw);
-    CXX_BITFIELD_MEMBER(16, 16, pwrdn_impl, raw);
-    CXX_BITFIELD_MEMBER(15, 15, jtag_probe, raw);
-    CXX_BITFIELD_MEMBER(14, 14, ci_pwrup, raw);
-    CXX_BITFIELD_MEMBER(13, 13, ci_vddok, raw);
-    CXX_BITFIELD_MEMBER(12, 12, ci_rail_stable, raw);
-    CXX_BITFIELD_MEMBER(11, 11, coh_en, raw);
-    CXX_BITFIELD_MEMBER(10, 10, lpack, raw);
-    CXX_BITFIELD_MEMBER(8, 9, pwup_policy, raw);
-    CXX_BITFIELD_MEMBER(7, 7, reset_hold, raw);
-    CXX_BITFIELD_MEMBER(4, 4, io_trffc_en, raw);
-    CXX_BITFIELD_MEMBER(0, 3, cmd, raw);
-  };
-
-  Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *node);
-
-  /**
-   * Translate a device tree "reg" value to an internally usable CPU id.
-   *
-   * For most architectures this is NOP, but some archictures like ARM
-   * might encode topology information into this value, which needs to
-   * be translated.
-   */
-  static unsigned dtid_to_cpuid(l4_int32_t prop_val)
-  { return prop_val; }
-
-  static bool has_fixed_dt_mapping() { return true; }
-
-  unsigned core_other() const
-  { return _core_other; }
-
-  l4_uint32_t cpc_status() const
-  { return _status.raw; }
-
-  void set_last_command(unsigned cmd)
-  { _status.cmd() = cmd; }
-
-  l4_umword_t read_cm_reg(unsigned reg)
-  {
-    switch(reg)
-    {
-    case Cm_loc_coh_en: return _status.coh_en();
-    case Cm_loc_config: return 0; // one VP per core
-    case Cm_loc_other: return _core_other << 8;
-    case Cm_loc_reset_base: return _reset_base;
-    case Cm_loc_id: return _vcpu.get_vcpu_id();
-    case Cm_loc_reset_ext_base: return _ext_reset_base;
-    }
-
-    return 0;
-  }
-
-  void write_cm_reg(unsigned reg, l4_umword_t value)
-  {
-    switch(reg)
-      {
-      case Cm_loc_coh_en:
-        _status.coh_en() = value & 1;
-        break;
-      case Cm_loc_other:
-        _core_other = (value >> 8) & Cm_loc_other_mask;
-        break;
-      case Cm_loc_reset_base:
-        _reset_base = value & Cm_loc_reset_base_mask;
-        break;
-      case Cm_loc_reset_ext_base:
-        _ext_reset_base = value & Cm_loc_reset_ext_base_mask;
-        break;
-      }
-  }
-
-  void set_coherent()
-  {
-    _status.seq_state() = Seq_coherent;
-    _status.coh_en() = 1;
-  }
-
-  void start_vcpu(l4_addr_t bev_base);
-  void stop_vcpu();
-
-  void reset() override;
-  void stop() override { stop_vcpu(); }
-
-private:
-  /// CPC state: local status register
-  Local_status_reg _status;
-  /// CM state: reset address register
-  l4_umword_t _reset_base;
-  /// CM state: extension to reset address register
-  l4_umword_t _ext_reset_base;
-  /// CM/CPC state: selected other core.
-  /// Note that starting with CM3, CM selects the other CPU for CM _and_ CPC.
-  unsigned char _core_other;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/debugger/guest_debugger.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/debugger/guest_debugger.h
deleted file mode 100644
index 143e8620..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/debugger/guest_debugger.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-namespace Vmm {
-  class Vm;
-}
-
-namespace Monitor {
-
-class Guest_debugger
-{
-public:
-  explicit Guest_debugger(Vmm::Vm *)
-  {}
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/gic.cc b/src/l4/pkg/uvmm/server/src/ARCH-mips/gic.cc
deleted file mode 100644
index 513db64d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/gic.cc
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2016-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-
-#include 
-
-#include "guest.h"
-#include "device_factory.h"
-#include "device_tree.h"
-#include "debug.h"
-#include "gic.h"
-
-static Dbg trace(Dbg::Irq, Dbg::Trace, "GIC");
-static Dbg warn(Dbg::Irq, Dbg::Warn, "GIC");
-static Dbg dbg(Dbg::Irq, Dbg::Info, "GIC");
-
-namespace Gic {
-
-Dist::Dist(Mips_core_ic *core_ic)
-: Read_mapped_mmio_device_t("Dist", Gic_shared_size),
-  _core_ic(core_ic)
-{
-  static_assert(L4_PAGESIZE <= 16 * 1024, "Maximum supported page size is 16k");
-
-  // set up shared section
-  auto *cfg = gic_mem(Gic_sh_config);
-  cfg->raw = 0;
-  cfg->numint() = (Num_irqs >> 3) - 1;
-  cfg->pvps() = Num_vpes;
-
-  // set revision to 4.0, as reported by Baikal board
-  *gic_mem(Gic_sh_revision) = 4 << 8;
-
-  auto *sh = gic_mem(0);
-
-  memset(sh + Gic_sh_int_avail, 0xff, Num_irqs >> 3);
-  memset(sh + Gic_sh_pend, 0, Num_irqs >> 3);
-}
-
-l4_umword_t
-Dist::read(unsigned reg, char size, unsigned cpu_id)
-{
-  assert(cpu_id < Num_vpes);
-
-  if (size < 2)
-    {
-      warn.printf("WARNING: read @0x%x with unsupported width %d ignored\n",
-                  reg, 8 << size);
-      return 0;
-    }
-
-  if (reg < Gic_shared_base + Gic_shared_size)
-    {
-      if (size == 3)
-        return *gic_mem(reg);
-      else
-        return *gic_mem(reg);
-    }
-
-  if (reg >= Gic_core_local_base && reg < Gic_core_other_base)
-    return read_cpu(reg - Gic_core_local_base, size, cpu_id);
-  if (reg >= Gic_core_other_base && reg < Gic_user_visible_base)
-    return read_cpu(reg - Gic_core_other_base, size,
-                    _vcpu_info[cpu_id].other_cpu);
-
-  dbg.printf("Reading unknown register @ 0x%x (%d)\n", reg, size);
-  return 0;
-}
-
-void
-Dist::write(unsigned reg, char size, l4_umword_t value, unsigned cpu_id)
-{
-  assert(cpu_id < Num_vpes);
-
-  if (size < 2)
-    {
-      warn.printf("WARNING: write @0x%x with unsupported width %d ignored\n",
-                  reg, 8 << size);
-      return;
-    }
-
-  if (reg >= Gic_core_local_base && reg < Gic_core_other_base)
-    {
-      write_cpu(reg - Gic_core_local_base, size, value, cpu_id);
-      return;
-    }
-  if (reg >= Gic_core_other_base && reg < Gic_user_visible_base)
-    {
-      write_cpu(reg - Gic_core_other_base, size, value,
-                _vcpu_info[cpu_id].other_cpu);
-      return;
-    }
-
-  // write must be to shared section
-  if (reg == Gic_sh_wedge)
-    {
-      Gic_wedge_reg wedge(value);
-      if (wedge.irq() < Num_irqs)
-        {
-          if (wedge.rw())
-            set(wedge.irq());
-          else
-            clear(wedge.irq());
-        }
-    }
-  else if (reg >= Gic_sh_rmask && reg < Gic_sh_rmask + Num_irqs / 8)
-    {
-      reset_mask(reg - Gic_sh_rmask, size, value);
-    }
-  else if (reg >= Gic_sh_smask && reg < Gic_sh_smask + Num_irqs / 8)
-    {
-      set_mask(reg - Gic_sh_smask, size, value);
-    }
-  else if (reg >= Gic_sh_pol && reg < Gic_sh_wedge)
-    {
-      // polarity, edge, dual configuration ignored
-      gic_mem_set(reg, size, value);
-    }
-  else if (reg >= Gic_sh_pin && reg < irq_to_pinreg(Num_irqs))
-    {
-      gic_mem_set(reg, size, value);
-      setup_source(pinreg_to_irq(reg));
-    }
-  else if (reg >= Gic_sh_map && reg < irq_to_mapreg(Num_irqs))
-    {
-      gic_mem_set(reg, size, value);
-      setup_source(mapreg_to_irq(reg));
-    }
-  else
-    dbg.printf("Writing ignored 0x%lx @ 0x%x (%d)\n", value, reg, size);
-}
-
-l4_umword_t
-Dist::read_cpu(unsigned reg, char, unsigned cpu_id)
-{
-  if (cpu_id >= 32)
-    {
-      dbg.printf("unknown VPE id %d. Read ignored @ 0x%x\n", cpu_id, reg);
-      return 0;
-    }
-
-  switch (reg)
-    {
-    case Gic_loc_other_addr:
-      return _vcpu_info[cpu_id].other_cpu;
-    case Gic_loc_ident:
-      return cpu_id;
-    }
-
-  trace.printf("Local read from cpu %d ignored @ 0x%x\n", cpu_id, reg);
-  return 0;
-}
-
-void
-Dist::write_cpu(unsigned reg, char, l4_umword_t value, unsigned cpu_id)
-{
-  if (cpu_id >= 32)
-    {
-      dbg.printf("unknown VPE id %d. Write ignored 0x%lx @ 0x%x\n", cpu_id,
-                 value, reg);
-      return;
-    }
-
-  switch (reg)
-    {
-    case Gic_loc_other_addr:
-      if (value < Num_vpes)
-        _vcpu_info[cpu_id].other_cpu = value;
-      return;
-    }
-
-  trace.printf("Local write to cpu %d ignored 0x%lx @ 0x%x\n", cpu_id, value,
-               reg);
-}
-
-/** disable interrupts */
-void
-Dist::reset_mask(unsigned reg, char size, l4_umword_t mask)
-{
-  assert(reg * 8 < Num_irqs);
-
-  l4_umword_t pending;
-
-  std::lock_guard lock(_lock);
-
-  if (size == 3)
-    {
-      *gic_mem(Gic_sh_mask + reg) &= ~mask;
-      pending = mask & *gic_mem(Gic_sh_pend + reg);
-    }
-  else
-    {
-      *gic_mem(Gic_sh_mask + reg) &= ~mask;
-      pending = ((l4_uint32_t) mask) & *gic_mem(Gic_sh_pend + reg);
-    }
-
-  int irq = reg * 8;
-
-  while (pending)
-    {
-      if (pending & 1)
-        _irq_array[irq]->ack();
-
-      ++irq;
-      pending >>= 1;
-    }
-}
-
-/** enable interrupts */
-void
-Dist::set_mask(unsigned reg, char size, l4_umword_t mask)
-{
-  assert(reg * 8 < Num_irqs);
-  int irq = reg * 8;
-
-  // narrow mask down to register width
-  if ((8UL << size) < 8 * sizeof(l4_umword_t))
-    mask &= (1UL << (8 << size)) - 1;
-
-  // Notify interrupt sources where necessary.
-  // Needs to be done before taking the lock as the IRQ source
-  // may want to clear a pending interrupt.
-  l4_umword_t eoibits = mask;
-  for (int i = 0; eoibits; ++i)
-    {
-      if ((eoibits & 1) && _sources[irq + i])
-        _sources[irq + i]->eoi();
-      eoibits >>= 1;
-    }
-
-  std::lock_guard lock(_lock);
-
-  if (size == 3)
-    *gic_mem(Gic_sh_mask + reg) |= mask;
-  else
-    *gic_mem(Gic_sh_mask + reg) |= mask;
-
-  l4_umword_t pending = mask;
-  if (size == 3)
-    pending &= *gic_mem(Gic_sh_pend + reg);
-  else
-    pending &= *gic_mem(Gic_sh_pend + reg);
-
-  // reinject any interrupts that are still pending
-  for (int i = 0; pending; ++i)
-    {
-      if (pending & 1)
-        _irq_array[irq + i]->inject();
-      pending >>= 1;
-    }
-}
-
-void
-Dist::setup_source(unsigned irq)
-{
-  assert(irq < Num_irqs);
-
-  std::lock_guard lock(_lock);
-
-  auto vp = *gic_mem(irq_to_mapreg(irq));
-  if (!(vp & 0x1f))
-    {
-      _irq_array[irq].reset();
-      return;
-    }
-
-  unsigned cpuid = 0;
-  for (; !(vp & 1); ++cpuid, vp >>= 1)
-    ;
-
-  auto ic = _core_ic->get_ic(cpuid);
-  auto pin = *gic_mem(irq_to_pinreg(irq));
-
-  trace.printf("GIC irq 0x%x: setting source for CPU %d to pin 0x%x (IC %p)\n",
-               irq, cpuid, pin.raw, ic.get());
-
-  // only int pins at the moment
-  if (ic && pin.pin() && pin.map() < 6)
-    _irq_array[irq] = cxx::make_unique(ic, pin.map() + 2);
-  else
-    _irq_array[irq].reset();
-}
-
-void
-Dist::show_state(FILE *f)
-{
-  fprintf(f, " Interrupts available: %d\n", Num_irqs);
-
-  for (unsigned i = 0; i < Num_irqs; ++i)
-    {
-      if (_irq_array[i])
-        fprintf(f, " Int %d => core IC %u  %s/%s\n",
-                i, gic_mem(Gic_sh_pin + i * 4)->map() + 2,
-                irq_mask()[i] ? "on" : "off",
-                irq_pending()[i] ? "pending" : "low");
-    }
-}
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    l4_uint64_t size;
-
-    int res = node.get_reg_val(0, nullptr, &size);
-    if (res < 0)
-      {
-        Err().printf("Failed to read 'reg' from node %s: %s\n",
-                     node.get_name(), node.strerror(res));
-        throw L4::Runtime_error(-L4_EINVAL);
-      }
-
-    auto g = Vdev::make_device(devs->vmm()->core_ic().get());
-    devs->vmm()->register_mmio_device(g, Vmm::Region_type::Virtual, node);
-    return g;
-  }
-
-};
-
-static F f;
-static Vdev::Device_type t = { "mti,gic", nullptr, &f };
-
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/gic.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/gic.h
deleted file mode 100644
index cfb2da09..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/gic.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2015-2018, 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "irq.h"
-#include "core_ic.h"
-#include "device_tree.h"
-#include "mmio_device.h"
-
-namespace Gic {
-
-class Dist
-: public Vmm::Read_mapped_mmio_device_t,
-  public Ic
-{
-  enum Config
-  {
-    Num_irqs = 128, // maximum irq supported by Linux 3.19
-    Cfg_words = Num_irqs >> 5, // 32 irq config bits per word
-    Num_vpes = 32  // number of VPEs the GIC can handle
-  };
-
-  // The P5600 spec says there is a maximum of 256 irqs but the
-  // data structures can accomodate up to 512. Only then the system breaks.
-  static_assert(Num_irqs <= 512, "Maximum supported irqs is 512");
-  static_assert(Num_irqs % 8 == 0, "Number of IRQs must be a multipe of 8");
-
-  enum Mips_gic_registers
-  {
-    Gic_shared_base = 0,
-    Gic_shared_size = 32 * 1024,
-    Gic_core_local_base = 0x8000,
-    Gic_core_other_base = 0xc000,
-    Gic_local_size = 16 * 1024,
-    Gic_user_visible_base = 0x16000,
-    Gic_user_size = 64 * 1024,
-
-    Gic_sh_config = 0x0,
-    Gic_sh_counter = 0x10,
-    Gic_sh_counter_lo = 0x10,
-    Gic_sh_counter_hi = 0x14,
-    Gic_sh_revision = 0x20,
-    Gic_sh_int_avail = 0x28,
-    Gic_sh_gid_config = 0x80,
-    Gic_sh_pol = 0x100,
-    Gic_sh_trig = 0x180,
-    Gic_sh_dual = 0x200,
-    Gic_sh_wedge = 0x280,
-    Gic_sh_rmask = 0x300,
-    Gic_sh_smask = 0x380,
-    Gic_sh_mask = 0x400,
-    Gic_sh_pend = 0x480,
-    Gic_sh_pin = 0x500,
-    Gic_sh_map = 0x2000,
-
-    Gic_loc_other_addr = 0x80,
-    Gic_loc_ident = 0x88,
-  };
-
-  struct Gic_config_reg
-  {
-    l4_uint32_t raw;
-    CXX_BITFIELD_MEMBER(31, 31, vzp, raw);
-    CXX_BITFIELD_MEMBER(30, 30, vze, raw);
-    CXX_BITFIELD_MEMBER(29, 29, irc, raw);
-    CXX_BITFIELD_MEMBER(28, 28, countstop, raw);
-    CXX_BITFIELD_MEMBER(24, 27, countbits, raw);
-    CXX_BITFIELD_MEMBER(16, 23, numint, raw);
-    CXX_BITFIELD_MEMBER(8, 15, irgid, raw);
-    CXX_BITFIELD_MEMBER(0, 6, pvps, raw);
-  };
-
-  struct Gic_pin_reg
-  {
-    l4_uint32_t raw;
-    CXX_BITFIELD_MEMBER(31, 31, pin, raw);
-    CXX_BITFIELD_MEMBER(30, 30, nmi, raw);
-    CXX_BITFIELD_MEMBER(8, 15, gid, raw);
-    CXX_BITFIELD_MEMBER(0, 5, map, raw);
-  };
-
-  struct Gic_wedge_reg
-  {
-    l4_umword_t raw;
-    CXX_BITFIELD_MEMBER(31, 31, rw, raw);
-    CXX_BITFIELD_MEMBER(0, 7, irq, raw);
-
-    explicit Gic_wedge_reg(l4_umword_t value) : raw(value) {}
-  };
-
-  struct Cpu_info
-  {
-    unsigned other_cpu = 0;
-  };
-
-public:
-  Dist(Mips_core_ic *core_ic);
-
-  l4_umword_t read(unsigned reg, char size, unsigned cpu_id);
-  void write(unsigned reg, char size, l4_umword_t value, unsigned cpu_id);
-
-  void set(unsigned irq) override
-  {
-    assert(irq < Num_irqs);
-    std::lock_guard lock(_lock);
-
-    if (!_irq_array[irq])
-      return;
-
-    irq_pending().set_bit(irq);
-
-    if (irq_mask()[irq])
-      _irq_array[irq]->inject();
-  }
-
-  void clear(unsigned irq) override
-  {
-    assert(irq < Num_irqs);
-    std::lock_guard lock(_lock);
-
-    if (!_irq_array[irq])
-      return;
-
-    irq_pending().clear_bit(irq);
-
-    if (irq_mask()[irq])
-      _irq_array[irq]->ack();
-  }
-
-  void bind_irq_src_handler(unsigned irq, Irq_src_handler *handler) override
-  {
-    assert(irq < Num_irqs);
-
-    if (handler && _sources[irq])
-      throw L4::Runtime_error(-L4_EEXIST);
-
-    _sources[irq] = handler;
-  }
-
-  Irq_src_handler *get_irq_src_handler(unsigned irq) const override
-  { return _sources[irq]; }
-
-  int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const override
-  {
-    if (propsz < 3)
-      return -L4_ERANGE;
-
-    int irq = fdt32_to_cpu(prop[1]);
-
-    if (read)
-      *read = 3;
-
-    return irq;
-  }
-
-  void reset_mask(unsigned reg, char size, l4_umword_t mask);
-  void set_mask(unsigned reg, char size, l4_umword_t mask);
-  void setup_source(unsigned irq);
-
-  void show_state(FILE *);
-
-private:
-  /**
-   * Return offset of map register for the given IRQ.
-   *
-   * Map registers spaced at 0x20 byte intervals.
-   */
-  unsigned irq_to_mapreg(unsigned irq) const
-  { return Gic_sh_map + irq * 0x20; }
-
-  unsigned mapreg_to_irq(unsigned offset) const
-  { return (offset - Gic_sh_map) / 0x20; }
-
-  cxx::Bitmap_base irq_mask() const
-  { return cxx::Bitmap_base(gic_mem(Gic_sh_mask)); }
-
-  cxx::Bitmap_base irq_pending() const
-  { return cxx::Bitmap_base(gic_mem(Gic_sh_pend)); }
-
-  /**
-   * Return offset of pin register for the given IRQ.
-   *
-   * Pin registers spaced at 4 byte intervals.
-   */
-  unsigned irq_to_pinreg(unsigned irq) const
-  { return Gic_sh_pin + irq * 4; }
-
-  unsigned pinreg_to_irq(unsigned offset) const
-  { return (offset - Gic_sh_pin) / 4; }
-
-  template 
-  T *gic_mem(unsigned offset) const
-  { return reinterpret_cast(mmio_local_addr() + offset); }
-
-  void gic_mem_set(unsigned offset, char size, l4_umword_t value) const
-  {
-    if (size == 3)
-      *gic_mem(offset) = value;
-    else
-      *gic_mem(offset) = value;
-  }
-
-  l4_umword_t read_cpu(unsigned reg, char size, unsigned cpu_id);
-  void write_cpu(unsigned reg, char size, l4_umword_t value,
-                 unsigned cpu_id);
-
-  Mips_core_ic *_core_ic;
-  // array of IRQ connections towards core IC
-  cxx::unique_ptr _irq_array[Num_irqs];
-  // registered device callbacks for configuration and eoi
-  Irq_src_handler *_sources[Num_irqs] = {};
-  Cpu_info _vcpu_info[Num_vpes];
-  std::mutex _lock;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest.cc b/src/l4/pkg/uvmm/server/src/ARCH-mips/guest.cc
deleted file mode 100644
index 7a185a47..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2015-2018, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "guest_entry.h"
-
-namespace Vmm {
-
-Guest::Guest()
-: _core_ic(Vdev::make_device()),
-  _cm(Vdev::make_device(&_memmap)),
-  _cpc(Vdev::make_device())
-{
-  _memmap[_cm->mem_region()] = _cm;
-  _cm->register_cpc(_cpc);
-}
-
-void
-Guest::setup_device_tree(Vdev::Device_tree dt)
-{
-  // advertise CPU core timer frequency in DTS
-  auto node = dt.path_offset("/cpus");
-  node.setprop_u32("mips-hpt-frequency", l4re_kip()->frequency_cpu * 1000);
-}
-
-l4_addr_t
-Guest::load_binary(Vm_ram *ram, char const *binary, Ram_free_list *free_list)
-{
-  l4_addr_t entry;
-
-  Boot::Binary_loader_factory bf;
-  bf.load(binary, ram, free_list, &entry);
-
-  return entry;
-}
-
-void
-Guest::prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const *binary, char const *cmd_line,
-                          l4_addr_t dt_boot_addr)
-{
-  Vcpu_ptr vcpu = devs->cpus()->vcpu(0);
-  Vm_ram *ram = devs->ram().get();
-
-  /*
-   * Setup arguments for Mips boot protocol
-   */
-  Guest_addr prom_tab(L4_PAGESIZE);
-
-  size_t size = 2 * sizeof(l4_addr_t);
-  auto prom_buf = prom_tab + size;
-
-  size += strlen(binary) + 1;
-  strcpy(ram->guest2host(prom_buf), binary);
-  ram->guest2host(prom_tab)[0] = ram->guest_phys2boot(prom_buf);
-
-  if (cmd_line)
-    {
-      strcpy(ram->guest2host(prom_tab + size), cmd_line);
-      ram->guest2host(prom_tab)[1] = ram->guest_phys2boot(prom_tab + size);
-      size += strlen(cmd_line) + 1;
-    }
-
-  l4_cache_clean_data(ram->guest2host(prom_tab),
-                      ram->guest2host(prom_tab) + size);
-
-  // Initial register setup:
-  //  a0 - number of kernel arguments
-  //  a1 - address of kernel arguments
-  //  a2 - unused
-  //  a3 - address of DTB
-  vcpu->r.a0 = cmd_line ? 2 : 1;
-  vcpu->r.a1 = ram->guest_phys2boot(prom_tab);
-  vcpu->r.a2 = 0;
-  vcpu->r.a3 = dt_boot_addr;
-  vcpu->r.status = 8;
-  // UHI boot protocol spec says that at least KX should be set when the
-  // boot loader passes in 64bit addresses for the command line parameters.
-  if (sizeof(l4_addr_t) == 8)
-    vcpu->r.status |= 0xe0;
-  vcpu->r.ip = entry;
-}
-
-void
-Guest::run(cxx::Ref_ptr const &cpus)
-{
-  _cpc->register_cpus(cpus);
-
-  for (auto cpu: *cpus.get())
-    {
-      if (!cpu)
-        continue;
-
-      cpu->vcpu()->user_task = _task.cap();
-      cpu->powerup_cpu();
-
-      // attach the core IC
-      _core_ic->create_ic(cpu->vcpu().get_vcpu_id(), cpu->thread_cap());
-    }
-
-  cpus->cpu(0)->set_coherent();
-  cpus->cpu(0)->startup();
-}
-
-int
-Guest::dispatch_hypcall(Hypcall_code hypcall_code, Vcpu_ptr vcpu)
-{
-  switch (hypcall_code)
-  {
-  case Hypcall_outchar:
-    _hypcall_print.print_char(vcpu->r.a0);
-    return Jump_instr;
-
-  };
-
-  return -L4_ENOSYS;
-}
-
-void
-Guest::handle_entry(Vcpu_ptr vcpu)
-{
-  auto *utcb = l4_utcb();
-  unsigned cause = (vcpu->r.cause >> 2) & 0x1F;
-  // XXX The above statement treats all Fiasco exception codes (0x100-0x102)
-  //     equally as 0. In case of 0x101 (ex_regs triggered exception) this
-  //     might be an issue as handle_ipc() might evaluate stale IPC regs.
-  //     0x102 is defined but not used.
-  assert((vcpu->r.cause & 0x1FF) <= 0x100);
-
-  auto *s = vcpu.state();
-  unsigned exccode = (s->guest_ctl_0 >> 2) & 0x1f;
-
-  if ((cause != 27 || exccode != 2) && trace().is_active())
-    trace().printf("VCPU %d Entry. IP = 0x%lx, cause: 0x%lx(%d), ctl0: 0x%lx\n",
-                   vcpu.get_vcpu_id(), vcpu->r.ip, vcpu->r.cause, cause,
-                   s->guest_ctl_0);
-
-  switch (cause)
-    {
-    case 0:
-      vcpu.handle_ipc(vcpu->i.tag, vcpu->i.label, utcb);
-      break;
-    case 1: // TLB modify
-    case 2: // TLB load/fetch
-    case 3: // TLB store
-      if (Mips::Instruction(vcpu->r.bad_instr).is_cache_op())
-        {
-          // FIXME: cache coherency currently not handled
-          // We assume that the memory will be coherent when mapped into
-          // the guest on first access.
-          info().printf("Cache operation on unmapped memory requested. Ignored. (Opcode: 0x%lx, address: 0x%lx)\n",
-                        vcpu->r.bad_instr, vcpu->r.pfa);
-          vcpu.jump_instruction();
-          break;
-        }
-      switch (handle_mmio(vcpu->r.pfa, vcpu))
-        {
-        case Retry: break;
-        case Jump_instr: vcpu.jump_instruction(); break;
-        default:
-          Err().printf(
-            "Bad page fault (%s) 0x%lx (GExcCode=0x%x) @0x%lx. Halting.\n",
-            cause == 2 ? "read" : "write", vcpu->r.pfa, exccode, vcpu->r.ip);
-          halt_vm(vcpu);
-          break;
-        }
-      break;
-    case 27: // guest exception
-      {
-        Mips::Instruction insn(vcpu->r.bad_instr);
-        if (!insn.raw)
-          {
-            Err().printf("Cannot decode faulting instruction @ IP 0x%lx\n",
-                         vcpu->r.ip);
-            halt_vm(vcpu);
-          }
-
-        int ret = -L4_ENOSYS;
-        switch (exccode)
-          {
-          case 0: // sensitive instruction
-            if (insn.is_mfc0())
-              ret = handle_gpsi_mfc0(vcpu, insn);
-            else if (insn.is_mtc0())
-              ret = handle_gpsi_mtc0(vcpu, insn);
-            else if (insn.is_wait())
-              ret = handle_wait(vcpu, utcb);
-            else if (insn.is_cache_op())
-              {
-                // Index Store Tag must only be used to initialise caches, ignore.
-                if (insn.cache_optype() != 2)
-                  info().printf("Unhandled cache operation 0x%lx. Ignored.\n",
-                                vcpu->r.bad_instr);
-                // FIXME: assuming that cache coherency is guaranteed by Fiasco
-                ret = Jump_instr;
-              }
-            break;
-
-          case 1: // software field change
-            if (insn.is_mtc0())
-              ret = handle_software_field_change(vcpu, insn);
-            break;
-
-          case 2: // hypcall
-            if (insn.is_hypcall())
-              ret = dispatch_hypcall((Hypcall_code)(unsigned)insn.hypcall_code(), vcpu);
-            break;
-
-          case 9: // hardware field change
-            info().printf("Hardware change ignored @ IP 0x%lx\n", vcpu->r.ip);
-            ret = 0; // ignored
-            break;
-          case 10:
-            Err().printf("Bad TLB root access 0x%lx @0x%lx. Halting.\n",
-                         vcpu->r.pfa, vcpu->r.ip);
-            break;
-          }
-
-        if (ret < 0)
-          {
-            Err().printf("Guest exception %d, error: %d, inst: 0x%x @ IP 0x%lx\n",
-                         exccode, ret, insn.raw, vcpu->r.ip);
-            halt_vm(vcpu);
-          }
-        if (ret == Jump_instr)
-          vcpu.jump_instruction();
-        break;
-      }
-    default:
-      Err().printf("Unknown cause of VMM entry: %d. Halting.\n", cause);
-      halt_vm(vcpu);
-    }
-
-  vcpu.process_pending_ipc(utcb);
-  _core_ic->update_vcpu(vcpu);
-}
-
-namespace {
-
-using namespace Vdev;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                                    Vdev::Dt_node const &) override
-  {
-    // Device tree only sees the IC for core 0.
-    return devs->vmm()->core_ic()->get_ic(0);
-  }
-};
-
-static F f;
-static Vdev::Device_type t = { "mti,cpu-interrupt-controller", nullptr, &f };
-
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/guest.h
deleted file mode 100644
index 01d4bafc..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2015-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "cpc.h"
-#include "cm.h"
-#include "core_ic.h"
-#include "debug.h"
-#include "device_tree.h"
-#include "generic_guest.h"
-#include "cpu_dev_array.h"
-#include "irq.h"
-#include "vmprint.h"
-#include "mips_instructions.h"
-#include "vm_ram.h"
-
-constexpr l4_addr_t sign_ext(l4_uint32_t addr)
-{ return (l4_addr_t) ((l4_mword_t) ((l4_int32_t) addr)); }
-
-namespace Vmm {
-
-class Guest : public Generic_guest
-{
-  enum Hypcall_code
-  {
-    Hypcall_base     = 0x160,
-    Hypcall_outchar  = Hypcall_base + 0,
-  };
-
-  struct Cp0_config4
-  {
-    l4_uint32_t _v;
-    Cp0_config4() = default;
-    Cp0_config4(l4_uint32_t v) : _v(v) {}
-    CXX_BITFIELD_MEMBER( 0,  7, mmu_sz_ext, _v);
-    CXX_BITFIELD_MEMBER( 0,  3, ftlb_sets, _v);
-    CXX_BITFIELD_MEMBER( 4,  7, ftlb_ways, _v);
-    CXX_BITFIELD_MEMBER( 0,  7, ftlb_info, _v);
-    CXX_BITFIELD_MEMBER( 8, 12, ftlb_page_size2, _v);
-    CXX_BITFIELD_MEMBER( 8, 10, ftlb_page_size1, _v);
-    CXX_BITFIELD_MEMBER(14, 15, mmu_ext_def, _v);
-    CXX_BITFIELD_MEMBER(16, 23, k_scr_num, _v);
-    CXX_BITFIELD_MEMBER(24, 27, vtlb_sz_ext, _v);
-    CXX_BITFIELD_MEMBER(28, 28, ae, _v);
-    CXX_BITFIELD_MEMBER(29, 30, ie, _v);
-
-    static Cp0_config4 *vcpu(Vcpu_ptr vcpu)
-    { return reinterpret_cast(&vcpu.state()->g_cfg[4]); }
-  };
-
-  struct Cp0_config5
-  {
-    l4_uint32_t _v;
-    Cp0_config5() = default;
-    Cp0_config5(l4_uint32_t v) : _v(v) {}
-    CXX_BITFIELD_MEMBER( 0,  0, nf_exists, _v);
-    CXX_BITFIELD_MEMBER( 2,  2, ufr, _v);
-    CXX_BITFIELD_MEMBER( 3,  3, mrp, _v);
-    CXX_BITFIELD_MEMBER( 4,  4, llb, _v);
-    CXX_BITFIELD_MEMBER( 5,  5, mvh, _v);
-    CXX_BITFIELD_MEMBER( 6,  6, sbri, _v);
-    CXX_BITFIELD_MEMBER( 7,  7, vp, _v);
-    CXX_BITFIELD_MEMBER( 8,  8, fre, _v);
-    CXX_BITFIELD_MEMBER( 9,  9, ufe, _v);
-    CXX_BITFIELD_MEMBER(10, 10, l2c, _v);
-    CXX_BITFIELD_MEMBER(11, 11, dec, _v);
-    CXX_BITFIELD_MEMBER(13, 13, xnp, _v);
-    CXX_BITFIELD_MEMBER(27, 27, msa_en, _v);
-    CXX_BITFIELD_MEMBER(28, 28, eva, _v);
-    CXX_BITFIELD_MEMBER(29, 29, cv, _v);
-    CXX_BITFIELD_MEMBER(30, 30, k, _v);
-
-    static Cp0_config5 *vcpu(Vcpu_ptr vcpu)
-    { return reinterpret_cast(&vcpu.state()->g_cfg[5]); }
-  };
-
-
-public:
-  enum
-  {
-    Default_rambase = 0,
-    Boot_offset = sign_ext(0x80000000)
-  };
-
-  Guest();
-  cxx::Ref_ptr core_ic() const  { return _core_ic; }
-
-  void setup_device_tree(Vdev::Device_tree dt);
-
-  l4_addr_t load_binary(Vm_ram *ram, char const *binary,
-                        Ram_free_list *free_list);
-
-  void prepare_platform(Vdev::Device_lookup *)
-  {}
-
-  void prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const *binary, char const *cmd_line,
-                          l4_addr_t dt_boot_addr);
-
-  void run(cxx::Ref_ptr const &cpus);
-
-  int dispatch_hypcall(Hypcall_code hypcall_code, Vcpu_ptr vcpu);
-  void handle_entry(Vcpu_ptr vcpu);
-
-  void show_state_interrupts(FILE *f, Vcpu_ptr vcpu)
-  {
-    if (_core_ic)
-      _core_ic->show_state(f, vcpu);
-  }
-
-  static Guest *create_instance();
-
-private:
-  int handle_gpsi_mfc0(Vcpu_ptr vcpu, Mips::Instruction insn)
-  {
-    l4_umword_t val;
-    unsigned reg = (insn.rd() << 3) | (insn.func() & 0x7);
-
-    trace().printf("MFC0 for 0x%x in register %d\n",
-                   reg, (unsigned) insn.rt());
-
-    switch (reg)
-      {
-      case L4_VM_CP0_GLOBAL_NUMBER:
-        val = vcpu.get_vcpu_id() << 8;
-        break;
-      case L4_VM_CP0_PROC_ID:
-        val = vcpu.proc_id();
-        break;
-      case L4_VM_CP0_SRS_CTL:
-        val = 0;
-        break;
-      case L4_VM_CP0_CMGCR_BASE:
-        val = Vdev::Coherency_manager::mem_region().start.get() >> 4;
-        break;
-      case L4_VM_CP0_MAAR_0:
-      case L4_VM_CP0_MAAR_1:
-      case L4_VM_CP0_ERR_CTL:
-      case L4_VM_CP0_CONFIG_6:
-      case L4_VM_CP0_CONFIG_7:
-        val = 0; break;
-      default: return -L4_ENOSYS;
-      }
-
-    if (sizeof(l4_addr_t) == 4 || insn.rs() == Mips::Op::Cop0_dmf)
-      vcpu->r.r[insn.rt()] = val;
-    else
-      vcpu->r.r[insn.rt()] = sign_ext((l4_uint32_t) val);
-    return Jump_instr;
-  }
-
-  int handle_gpsi_mtc0(Vcpu_ptr vcpu, Mips::Instruction insn)
-  {
-    unsigned reg = (insn.rd() << 3) | (insn.func() & 0x7);
-
-    trace().printf("MTC0 for 0x%x in register %u\n", reg, (unsigned) insn.rt());
-
-    switch (reg)
-      {
-      case L4_VM_CP0_COUNT:
-        {
-          l4_uint32_t newcnt = vcpu->r.r[insn.rt()];
-          l4_uint32_t kcnt;
-          asm volatile("rdhwr\t%0, $2" : "=r"(kcnt)); // timer counter
-
-          vcpu.state()->guest_timer_offset = (l4_int32_t) (newcnt - kcnt);
-          vcpu.state()->set_modified(L4_VM_MOD_GTOFFSET);
-          return Jump_instr;
-        }
-      case L4_VM_CP0_CONFIG_0:
-      case L4_VM_CP0_CONFIG_1:
-      case L4_VM_CP0_CONFIG_2:
-      case L4_VM_CP0_CONFIG_3:
-      case L4_VM_CP0_CONFIG_6:
-      case L4_VM_CP0_CONFIG_7:
-        return Jump_instr; // XXX config registers are read-only atm
-      case L4_VM_CP0_CONFIG_4:
-        {
-          // allow setting of ftlb size
-          auto *cfg4 = Cp0_config4::vcpu(vcpu);
-          Cp0_config4 newcfg(vcpu->r.r[insn.rt()]);
-          if (cfg4->ftlb_page_size2() != newcfg.ftlb_page_size2())
-            {
-              cfg4->ftlb_page_size2().set(newcfg.ftlb_page_size2());
-              vcpu.state()->set_modified(L4_VM_MOD_CFG);
-            }
-          return Jump_instr;
-        }
-      case L4_VM_CP0_CONFIG_5:
-        {
-          auto *cfg5 = Cp0_config5::vcpu(vcpu);
-          Cp0_config5 newcfg(vcpu->r.r[insn.rt()]);
-          // allow setting of FRE
-          if (cfg5->fre() != newcfg.fre())
-            {
-              cfg5->fre().set(newcfg.fre());
-              vcpu.state()->set_modified(L4_VM_MOD_CFG);
-            }
-          return Jump_instr;
-        }
-      case L4_VM_CP0_LOAD_LINKED_ADDR:
-        if (!(vcpu->r.r[insn.rt()] & 1))
-          vcpu.state()->set_modified(L4_VM_MOD_LLBIT);
-        return Jump_instr;
-      case L4_VM_CP0_MAAR_0: // XXX MAAR and parity are not supported
-      case L4_VM_CP0_MAAR_1:
-      case L4_VM_CP0_ERR_CTL:
-      case L4_VM_CP0_TAG_LO_0: // cache tagging ignored
-      case L4_VM_CP0_DATA_LO_0:
-      case L4_VM_CP0_TAG_LO_1:
-      case L4_VM_CP0_DATA_LO_1:
-      case L4_VM_CP0_TAG_HI_0:
-      case L4_VM_CP0_DATA_HI_0:
-      case L4_VM_CP0_TAG_HI_1:
-      case L4_VM_CP0_DATA_HI_1:
-        return Jump_instr;
-      }
-
-    return -L4_EINVAL;
-  }
-
-  int handle_software_field_change(Vcpu_ptr vcpu, Mips::Instruction insn)
-  {
-    l4_umword_t val = vcpu->r.r[insn.rt()];
-    unsigned reg = (insn.rd() << 3) | (insn.func() & 0x7);
-    auto *s = vcpu.state();
-
-    trace().printf("MTC0(soft) for 0x%x in register %d (0x%lx) \n",
-                   reg, (unsigned) insn.rt(), val);
-
-    switch (reg)
-      {
-      case L4_VM_CP0_STATUS:
-        s->g_status = val;
-        s->set_modified(L4_VM_MOD_STATUS);
-        return Jump_instr;
-
-      case L4_VM_CP0_CAUSE:
-        enum { Cause_mask = 0x8c00ff00UL };
-        s->get_state(L4_VM_MOD_CAUSE);
-        s->g_cause &= ~Cause_mask;
-        s->g_cause |= val & Cause_mask;
-        s->set_modified(L4_VM_MOD_CAUSE);
-        return Jump_instr;
-      }
-
-    return -L4_EINVAL;
-  }
-
-  int handle_wait(Vcpu_ptr vcpu, l4_utcb_t *utcb)
-  {
-    if (Gic::Mips_core_ic::has_pending(vcpu))
-      return Jump_instr;
-
-    auto *s = vcpu.state();
-    auto *kip = l4re_kip();
-
-    l4_cpu_time_t kip_time;
-    // get kip time and hardware in sync
-    do
-      {
-        kip_time = l4_kip_clock(kip);
-        s->update_state(L4_VM_MOD_CAUSE | L4_VM_MOD_COMPARE);
-
-        if (s->g_cause & (1UL << 30))
-          return Jump_instr; // there was a timer interrupt
-
-        l4_mb();
-      }
-    while (kip_time != l4_kip_clock(kip));
-
-    l4_uint32_t gcnt = s->saved_cause_timestamp
-                       + (l4_int32_t) s->guest_timer_offset;
-    l4_uint32_t diff;
-    l4_uint32_t cmp = s->g_compare;
-    if (gcnt < cmp)
-      diff = cmp - gcnt;
-    else
-      diff = (0xffffffff - gcnt) + cmp;
-
-    auto freq = kip->frequency_cpu / 2;
-    diff = ((diff + freq - 1) / freq) * 1000;
-    // make sure the timer interrupt has passed on the Fiasco clock tick
-    diff += kip->scheduler_granularity;
-
-    l4_timeout_t to;
-    l4_rcv_timeout(l4_timeout_abs_u(kip_time + diff, 8, utcb), &to);
-
-    vcpu.wait_for_ipc(utcb, to);
-
-    return Jump_instr;
-  }
-
-  Guest_print_buffer _hypcall_print;
-  cxx::Ref_ptr _core_ic;
-  cxx::Ref_ptr _cm;
-  cxx::Ref_ptr _cpc;
-};
-
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.cc b/src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.cc
deleted file mode 100644
index 86f06b24..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "guest.h"
-#include "guest_entry.h"
-#include "vcpu_ptr.h"
-
-/// The singleton instance of the VMM.
-static cxx::Static_container guest;
-
-static void
-save_fpu(Vmm::Fpu_state *s)
-{
-  asm volatile(".set   push\n");
-  asm volatile(".set   hardfloat\n");
-#if __mips_fpr == 64
-  asm volatile("sdc1 $f0, %0" : : "m"(s->regs[0]));
-  asm volatile("sdc1 $f1, %0" : : "m"(s->regs[1]));
-  asm volatile("sdc1 $f2, %0" : : "m"(s->regs[2]));
-  asm volatile("sdc1 $f3, %0" : : "m"(s->regs[3]));
-  asm volatile("sdc1 $f4, %0" : : "m"(s->regs[4]));
-  asm volatile("sdc1 $f5, %0" : : "m"(s->regs[5]));
-  asm volatile("sdc1 $f6, %0" : : "m"(s->regs[6]));
-  asm volatile("sdc1 $f7, %0" : : "m"(s->regs[7]));
-  asm volatile("sdc1 $f8, %0" : : "m"(s->regs[8]));
-  asm volatile("sdc1 $f9, %0" : : "m"(s->regs[9]));
-  asm volatile("sdc1 $f10, %0" : : "m"(s->regs[10]));
-  asm volatile("sdc1 $f11, %0" : : "m"(s->regs[11]));
-  asm volatile("sdc1 $f12, %0" : : "m"(s->regs[12]));
-  asm volatile("sdc1 $f13, %0" : : "m"(s->regs[13]));
-  asm volatile("sdc1 $f14, %0" : : "m"(s->regs[14]));
-  asm volatile("sdc1 $f15, %0" : : "m"(s->regs[15]));
-  asm volatile("sdc1 $f16, %0" : : "m"(s->regs[16]));
-  asm volatile("sdc1 $f17, %0" : : "m"(s->regs[17]));
-  asm volatile("sdc1 $f18, %0" : : "m"(s->regs[18]));
-  asm volatile("sdc1 $f19, %0" : : "m"(s->regs[19]));
-  asm volatile("sdc1 $f20, %0" : : "m"(s->regs[20]));
-  asm volatile("sdc1 $f21, %0" : : "m"(s->regs[21]));
-  asm volatile("sdc1 $f22, %0" : : "m"(s->regs[22]));
-  asm volatile("sdc1 $f23, %0" : : "m"(s->regs[23]));
-  asm volatile("sdc1 $f24, %0" : : "m"(s->regs[24]));
-  asm volatile("sdc1 $f25, %0" : : "m"(s->regs[25]));
-  asm volatile("sdc1 $f26, %0" : : "m"(s->regs[26]));
-  asm volatile("sdc1 $f27, %0" : : "m"(s->regs[27]));
-  asm volatile("sdc1 $f28, %0" : : "m"(s->regs[28]));
-  asm volatile("sdc1 $f29, %0" : : "m"(s->regs[29]));
-  asm volatile("sdc1 $f30, %0" : : "m"(s->regs[30]));
-  asm volatile("sdc1 $f31, %0" : : "m"(s->regs[31]));
-#else
-  asm volatile("sdc1 $f0, %0" : : "m"(s->regs[0]));
-  asm volatile("sdc1 $f2, %0" : : "m"(s->regs[1]));
-  asm volatile("sdc1 $f4, %0" : : "m"(s->regs[2]));
-  asm volatile("sdc1 $f6, %0" : : "m"(s->regs[3]));
-  asm volatile("sdc1 $f8, %0" : : "m"(s->regs[4]));
-  asm volatile("sdc1 $f10, %0" : : "m"(s->regs[5]));
-  asm volatile("sdc1 $f12, %0" : : "m"(s->regs[6]));
-  asm volatile("sdc1 $f14, %0" : : "m"(s->regs[7]));
-  asm volatile("sdc1 $f16, %0" : : "m"(s->regs[8]));
-  asm volatile("sdc1 $f18, %0" : : "m"(s->regs[9]));
-  asm volatile("sdc1 $f20, %0" : : "m"(s->regs[10]));
-  asm volatile("sdc1 $f22, %0" : : "m"(s->regs[11]));
-  asm volatile("sdc1 $f24, %0" : : "m"(s->regs[12]));
-  asm volatile("sdc1 $f26, %0" : : "m"(s->regs[13]));
-  asm volatile("sdc1 $f28, %0" : : "m"(s->regs[14]));
-  asm volatile("sdc1 $f30, %0" : : "m"(s->regs[15]));
-#endif
-  asm volatile("cfc1 %0, $31" : "=r"(s->status));
-  asm volatile(".set   pop\n");
-}
-
-static void
-restore_fpu(Vmm::Fpu_state const *s)
-{
-  asm volatile(".set   push\n");
-  asm volatile(".set   hardfloat\n");
-#if __mips_fpr == 64
-  asm volatile("ldc1 $f0, %0" : : "m"(s->regs[0]));
-  asm volatile("ldc1 $f1, %0" : : "m"(s->regs[1]));
-  asm volatile("ldc1 $f2, %0" : : "m"(s->regs[2]));
-  asm volatile("ldc1 $f3, %0" : : "m"(s->regs[3]));
-  asm volatile("ldc1 $f4, %0" : : "m"(s->regs[4]));
-  asm volatile("ldc1 $f5, %0" : : "m"(s->regs[5]));
-  asm volatile("ldc1 $f6, %0" : : "m"(s->regs[6]));
-  asm volatile("ldc1 $f7, %0" : : "m"(s->regs[7]));
-  asm volatile("ldc1 $f8, %0" : : "m"(s->regs[8]));
-  asm volatile("ldc1 $f9, %0" : : "m"(s->regs[9]));
-  asm volatile("ldc1 $f10, %0" : : "m"(s->regs[10]));
-  asm volatile("ldc1 $f11, %0" : : "m"(s->regs[11]));
-  asm volatile("ldc1 $f12, %0" : : "m"(s->regs[12]));
-  asm volatile("ldc1 $f13, %0" : : "m"(s->regs[13]));
-  asm volatile("ldc1 $f14, %0" : : "m"(s->regs[14]));
-  asm volatile("ldc1 $f15, %0" : : "m"(s->regs[15]));
-  asm volatile("ldc1 $f16, %0" : : "m"(s->regs[16]));
-  asm volatile("ldc1 $f17, %0" : : "m"(s->regs[17]));
-  asm volatile("ldc1 $f18, %0" : : "m"(s->regs[18]));
-  asm volatile("ldc1 $f19, %0" : : "m"(s->regs[19]));
-  asm volatile("ldc1 $f20, %0" : : "m"(s->regs[20]));
-  asm volatile("ldc1 $f21, %0" : : "m"(s->regs[21]));
-  asm volatile("ldc1 $f22, %0" : : "m"(s->regs[22]));
-  asm volatile("ldc1 $f23, %0" : : "m"(s->regs[23]));
-  asm volatile("ldc1 $f24, %0" : : "m"(s->regs[24]));
-  asm volatile("ldc1 $f25, %0" : : "m"(s->regs[25]));
-  asm volatile("ldc1 $f26, %0" : : "m"(s->regs[26]));
-  asm volatile("ldc1 $f27, %0" : : "m"(s->regs[27]));
-  asm volatile("ldc1 $f28, %0" : : "m"(s->regs[28]));
-  asm volatile("ldc1 $f29, %0" : : "m"(s->regs[29]));
-  asm volatile("ldc1 $f30, %0" : : "m"(s->regs[30]));
-  asm volatile("ldc1 $f31, %0" : : "m"(s->regs[31]));
-#else
-  asm volatile("ldc1 $f0, %0" : : "m"(s->regs[0]));
-  asm volatile("ldc1 $f2, %0" : : "m"(s->regs[1]));
-  asm volatile("ldc1 $f4, %0" : : "m"(s->regs[2]));
-  asm volatile("ldc1 $f6, %0" : : "m"(s->regs[3]));
-  asm volatile("ldc1 $f8, %0" : : "m"(s->regs[4]));
-  asm volatile("ldc1 $f10, %0" : : "m"(s->regs[5]));
-  asm volatile("ldc1 $f12, %0" : : "m"(s->regs[6]));
-  asm volatile("ldc1 $f14, %0" : : "m"(s->regs[7]));
-  asm volatile("ldc1 $f16, %0" : : "m"(s->regs[8]));
-  asm volatile("ldc1 $f18, %0" : : "m"(s->regs[9]));
-  asm volatile("ldc1 $f20, %0" : : "m"(s->regs[10]));
-  asm volatile("ldc1 $f22, %0" : : "m"(s->regs[11]));
-  asm volatile("ldc1 $f24, %0" : : "m"(s->regs[12]));
-  asm volatile("ldc1 $f26, %0" : : "m"(s->regs[13]));
-  asm volatile("ldc1 $f28, %0" : : "m"(s->regs[14]));
-  asm volatile("ldc1 $f30, %0" : : "m"(s->regs[15]));
-#endif
-  asm volatile("ctc1 %0, $31" : : "r"(s->status));
-
-  asm volatile(".set   pop\n");
-}
-
-void
-c_vcpu_entry(l4_vcpu_state_t *vcpu)
-{
-  Vmm::Vcpu_ptr c(vcpu);
-  if (!(vcpu->r.status & (1UL << 3)))
-    {
-      Err().printf("Exception in entry handler. Halting. IP = 0x%lx\n",
-                   vcpu->r.ip);
-      guest->halt_vm(c);
-    }
-
-  save_fpu(c.fpu_state());
-
-  guest->handle_entry(c);
-
-  restore_fpu(c.fpu_state());
-
-  L4::Cap myself;
-  auto e = l4_error(myself->vcpu_resume_commit(myself->vcpu_resume_start()));
-
-  Err().printf("VM restart failed with %ld\n", e);
-  guest->halt_vm(c);
-}
-
-Vmm::Guest *
-Vmm::Guest::create_instance()
-{
-  guest.construct();
-  return guest;
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.h
deleted file mode 100644
index 22eef6ba..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/guest_entry.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-/// Entry point for guest exits.
-void c_vcpu_entry(l4_vcpu_state_t *vcpu);
-/// Entry point for newly created vcpu threads.
-void *powerup_handler(void *vcpu);
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/mips_instructions.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/mips_instructions.h
deleted file mode 100644
index 5b496df4..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/mips_instructions.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2015-2017, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-namespace Mips {
-
-namespace Op {
-
-enum Opcode
-{
-  Special = 0, Regimm, J, Jal, Beq, Bne, Blez, Bgtz,
-  Pop10 = 8, Addiu, Slti, Sltiu, Andi, Ori, Xori, Lui,
-  Cop0 = 16, Cop1, Cop2, Cop1x, Beql, Bnel, Blezl, Bgtzl,
-  Pop30 = 24, Special2 = 28, Jalx, Msa, Special3,
-  Lb = 32, Lh, Lwlw, Lw, Lbu, Lhu, Lwr,
-  Sb = 40, Sh, Swl, Sw, Swr = 46, Cache,
-  Ll = 48, Lwc1, Lwc2, Pref, Ldc1 = 53, Pop66, Ld,
-  Sc = 56, Swc1, Swc2, Pcrel, Sdc1 = 61, Pop76, Sd
-};
-
-enum Cop0_rs
-{
-  Cop0_mfc0 = 0, Cop0_dmf = 1, Cop0_mfh = 2, Cop0_mtc0 = 4, Cop0_dmt,
-  Cop0_mth = 6, Cop0_hypcall = 0x28,
-};
-
-enum Special
-{
-  Sp_jr = 8, Sp_jalr = 9
-};
-
-enum Special3
-{
-  Sp3_cachee = 0x1b,
-  Sp3_cache = 0x25
-};
-
-enum Regimm
-{
-  Bltz = 0, Bgez, Bltzl, Bgezl,
-  Tgei = 8, Tgeiu, Tlti, Tltiu, Teqi,
-  Nal =16, Bal, Bltzall, Bgezall
-};
-
-}
-
-struct Instruction
-{
-  l4_uint32_t raw;
-  // generic fields
-  CXX_BITFIELD_MEMBER_RO(26, 31, opcode, raw);
-  CXX_BITFIELD_MEMBER_RO(21, 25, rs, raw);
-  CXX_BITFIELD_MEMBER_RO(16, 20, rt, raw);
-  CXX_BITFIELD_MEMBER_RO( 0, 15, imm, raw);
-  CXX_BITFIELD_MEMBER_RO( 0,  5, func, raw);
-  CXX_BITFIELD_MEMBER_RO( 6, 10, sa, raw);
-  CXX_BITFIELD_MEMBER_RO(11, 15, rd, raw);
-  // HYPCALL fields
-  CXX_BITFIELD_MEMBER_RO(11, 20, hypcall_code, raw);
-  // opcode for load/store instructions
-  // Note that not all combinations are valid.
-  CXX_BITFIELD_MEMBER_RO(31, 31, opcode_mem, raw);
-  CXX_BITFIELD_MEMBER_RO(30, 30, op_mem_atomic, raw);
-  CXX_BITFIELD_MEMBER_RO(29, 29, op_mem_store, raw);
-  CXX_BITFIELD_MEMBER_RO(28, 28, op_mem_unsigned, raw);
-  CXX_BITFIELD_MEMBER_RO(26, 27, op_mem_width, raw);
-  // for Cop0
-  CXX_BITFIELD_MEMBER_RO(25, 25, cop0_co, raw);
-  // for J/JAL
-  CXX_BITFIELD_MEMBER_RO( 0, 25, instr_index, raw);
-  // for FP ops
-  CXX_BITFIELD_MEMBER_RO(28, 28, op_fp_dc1, raw);
-  // for cache ops
-  CXX_BITFIELD_MEMBER_RO(18, 20, cache_optype, raw);
-
-  Instruction(l4_uint32_t inst) : raw(inst) {}
-
-  bool is_mfc0() const
-  {
-    return opcode() == Op::Cop0
-             && (rs() == Op::Cop0_mfc0 || rs() == Op::Cop0_dmf);
-  }
-
-  bool is_mtc0() const
-  {
-    return opcode() == Op::Cop0
-             && (rs() == Op::Cop0_mtc0 || rs() == Op::Cop0_dmt);
-  }
-
-  bool is_hypcall() const
-  { return opcode() == Op::Cop0 && func() == Op::Cop0_hypcall; }
-
-  bool is_wait() const
-  { return opcode() == Op::Cop0 && cop0_co() && func() == 0x20 ; }
-
-  bool is_cache_op() const
-  {
-    return opcode() == Op::Cache
-           || (sizeof(l4_umword_t) == 8 && opcode() == Op::Special3
-               && (func() == Op::Sp3_cache || func() == Op::Sp3_cachee));
-  }
-
-  bool is_simple_load_store() const
-  {
-    return (opcode_mem() && !op_mem_atomic()
-            && op_mem_width() != 2
-            && !(op_mem_unsigned() && op_mem_store()))
-           || ((opcode() & 0x37) == 0x37);
-  }
-
-  bool is_fp_load_store() const
-  {
-    return opcode() == Op::Lwc1 || opcode() == Op::Sdc1
-           || opcode() == Op::Ldc1 || opcode() == Op::Sdc1;
-  }
-
-  /**
-   * Return width of a load/store operation.
-   *
-   * \pre The instruction is a load/store operation.
-   *
-   * \retval 0  Byte width (8bit).
-   * \retval 1  Half-word width (16bit).
-   * \retval 2  Word width (32bit).
-   * \retval 3  Double-word width (64bit).
-   */
-  char load_store_width() const
-  {
-    switch (opcode())
-      {
-      case Op::Lb:
-      case Op::Lbu:
-      case Op::Sb:
-        return 0;
-      case Op::Lh:
-      case Op::Lhu:
-      case Op::Sh:
-        return 1;
-      case Op::Ld:
-      case Op::Sd:
-      case Op::Ldc1:
-      case Op::Sdc1:
-        return 3;
-      default:
-        return 2;
-      }
-  }
-
-  int branch_offset() const
-  { return ((int) ((l4_int16_t) imm())) << 2; }
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/cpu_dev_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/cpu_dev_cmd_handler.h
deleted file mode 100644
index d28243b1..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/cpu_dev_cmd_handler.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "vcpu_ptr.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Cpu_dev_cmd_handler {};
-
-template
-class Cpu_dev_cmd_handler : public Cmd
-{
-public:
-  char const *help() const override
-  { return "CPU state"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'cpu  regs': dump CPU registers\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, "regs"); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "regs")
-      show_regs(f);
-    else
-      argument_error("Invalid subcommand");
-  }
-
-  void show_regs(FILE *f) const
-  {
-    auto v = get_vcpu();
-
-    fprintf(f, "EPC=%08lx SP=%08lx\n",
-            v->r.ip, v->r.sp);
-    fprintf(f, "Status=%08lx  Cause=%08lx\n",
-            v->r.status, v->r.cause);
-    fprintf(f, "ULR=%08lx  Hi=%08lx Lo=%08lx\n",
-            v->r.ulr, v->r.hi, v->r.lo);
-    fprintf(f, "at/ 1=%08lx v0/ 2=%08lx v1/ 3=%08lx\n",
-            v->r.r[1], v->r.r[2], v->r.r[3]);
-    fprintf(f, "a0/ 4=%08lx a1/ 5=%08lx a1/ 6=%08lx a4/ 7=%08lx\n",
-            v->r.r[4], v->r.r[5], v->r.r[6], v->r.r[7]);
-    fprintf(f, "t0/ 8=%08lx t1/ 9=%08lx t2/10=%08lx t3/11=%08lx\n",
-            v->r.r[8], v->r.r[9], v->r.r[10], v->r.r[11]);
-    fprintf(f, "t4/12=%08lx t5/13=%08lx t6/14=%08lx t7/15=%08lx\n",
-            v->r.r[12], v->r.r[13], v->r.r[14], v->r.r[15]);
-    fprintf(f, "s0/16=%08lx s1/17=%08lx s2/18=%08lx s3/19=%08lx\n",
-            v->r.r[16], v->r.r[17], v->r.r[18], v->r.r[19]);
-    fprintf(f, "s4/20=%08lx s5/21=%08lx s6/22=%08lx s7/23=%08lx\n",
-            v->r.r[20], v->r.r[21], v->r.r[22], v->r.r[23]);
-    fprintf(f, "t8/24=%08lx t9/25=%08lx k0/26=%08lx k1/27=%08lx\n",
-            v->r.r[24], v->r.r[25], v->r.r[26], v->r.r[27]);
-    fprintf(f, "gp/28=%08lx sp/29=%08lx s8/30=%08lx ra/31=%08lx\n",
-            v->r.r[28], v->r.r[29], v->r.r[30], v->r.r[31]);
-
-    auto *s = v.state();
-
-    s->update_state(~0UL);
-
-    fprintf(f, "\nGuestCtl0= %08lx  Guestctl0_ext= %08lx\n",
-            s->guest_ctl_0, s->guest_ctl_0_ext);
-    fprintf(f, "GuestCtl1= %08lx  Guestctl2    = %08lx\n",
-            s->guest_ctl_1, s->guest_ctl_2);
-    fprintf(f, "\nGuest CP0:\n");
-    fprintf(f, "Status   = %08lx  Cause    = %08lx\n",
-            s->g_status, s->g_cause);
-    fprintf(f, "Index    = %08lx  EBase    = %08lx\n",
-            s->g_index, s->g_ebase);
-    fprintf(f, "EntryLo0 = %08lx  EntryLo1 = %08lx\n",
-            s->g_entry_lo[0], s->g_entry_lo[1]);
-    fprintf(f, "Context  = %08lx  EntryHi  = %08lx\n",
-            s->g_context, s->g_entry_hi);
-    fprintf(f, "PageMask = %08lx  PageGrain= %08lx\n",
-            s->g_page_mask, s->g_page_grain);
-    fprintf(f, "ULR      = %08lx  Wired    = %08lx\n",
-            s->g_ulr, s->g_wired);
-    fprintf(f, "SegCtl0  = %08lx  SegCtl1  = %08lx\n",
-            s->g_seg_ctl[0], s->g_seg_ctl[1]);
-    fprintf(f, "SegCtl2  = %08lx  HWRena   = %08lx\n",
-            s->g_seg_ctl[2], s->g_hwrena);
-    fprintf(f, "PWBase   = %08lx  PWField  = %08lx\n",
-            s->g_pw_base, s->g_pw_field);
-    fprintf(f, "PWSize   = %08lx  PWCtl    = %08lx\n",
-            s->g_pw_size, s->g_pw_ctl);
-    fprintf(f, "BadVAddr = %08lx  BadInstr = %08lx\n",
-            s->g_bad_v_addr, s->g_bad_instr);
-    fprintf(f, "BadInstrP= %08lx  Compare  = %08lx\n",
-            s->g_bad_instr_p, s->g_compare);
-    fprintf(f, "IntCtl   = %08lx  EPC      = %08lx\n",
-            s->g_intctl, s->g_epc);
-    fprintf(f, "Config0  = %08lx  Config1  = %08lx\n",
-            s->g_cfg[0], s->g_cfg[1]);
-    fprintf(f, "Config2  = %08lx  Config3  = %08lx\n",
-            s->g_cfg[2], s->g_cfg[3]);
-    fprintf(f, "Config4  = %08lx  Config5  = %08lx\n",
-            s->g_cfg[4], s->g_cfg[5]);
-  }
-
-private:
-  Vmm::Vcpu_ptr get_vcpu() const
-  { return static_cast(this)->vcpu(); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/monitor_arch.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/monitor_arch.h
deleted file mode 100644
index 92a0445d..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/monitor/monitor_arch.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-constexpr bool has_iomap()
-{ return false; }
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-mips/vcpu_ptr.h b/src/l4/pkg/uvmm/server/src/ARCH-mips/vcpu_ptr.h
deleted file mode 100644
index 5b7269e9..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-mips/vcpu_ptr.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2015-2017, 2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#include "generic_vcpu_ptr.h"
-#include "mem_access.h"
-#include "mips_instructions.h"
-
-namespace Vmm {
-
-struct Fpu_state
-{
-#if __mips_fpr == 64
-  l4_uint64_t read(unsigned fpnr)
-  { return regs[fpnr]; }
-
-  void write(unsigned fpnr, char, l4_uint64_t value)
-  { regs[fpnr] = value; }
-
-  l4_uint64_t regs[32];
-#else
-
-  l4_uint64_t read(unsigned fpnr)
-  {
-    // registers are numbered by 32bit but saved in 64bit
-    // so for odd FPU register numbers return the upper 32bits.
-    return regs[fpnr >> 1] >> (32 * (fpnr & 1));
-  }
-
-  void write(unsigned fpnr, char size, l4_uint64_t value)
-  {
-    if (size == 3)
-      regs[fpnr >> 1] = value;
-    else
-      {
-        // write the 32bit value in the upper or lower part of the
-        // saved 64bit value
-        value &= 0xffffffff;
-        // Mask for the 64bit register: upper 32 bit for even FPU registers,
-        // lower 32 bit for odd FPU registers.
-        l4_uint64_t regmask = (0xffffffffULL << (32 * (~fpnr & 1)));
-        regs[fpnr >> 1] = (regmask & regs[fpnr >> 1])
-                          | (value << (32 * (fpnr & 1)));
-      }
-  }
-
-  l4_uint64_t regs[16];
-#endif
-  l4_umword_t status;
-};
-
-struct State : l4_vm_state_t
-{
-  void set_modified(l4_umword_t bits)
-  { modified_cp0_map |= bits; }
-
-  void get_state(l4_umword_t bits)
-  {
-    if ((clean_cp0_map & bits) != bits)
-      l4_thread_mips_save_vm_state(L4_INVALID_CAP, bits);
-  }
-
-  void update_state(l4_umword_t bits)
-  { l4_thread_mips_save_vm_state(L4_INVALID_CAP, bits); }
-};
-
-class Vcpu_ptr : public Generic_vcpu_ptr
-{
-public:
-  explicit Vcpu_ptr(l4_vcpu_state_t *s) : Generic_vcpu_ptr(s) {}
-
-  bool pf_write() const
-  { return _s->r.cause & 4; }
-
-  void thread_attach()
-  {
-    control_ext(L4::Cap());
-  }
-
-  void jump_instruction()
-  {
-    auto *r = &_s->r;
-    if (!(r->cause & (1 << 31)))
-      {
-        r->ip += 4;
-        return;
-      }
-
-    // emulate the branch instruction
-    Mips::Instruction insn(r->bad_instr_p);
-
-    switch (insn.opcode())
-      {
-      case Mips::Op::Special:
-        switch (insn.func())
-          {
-          case Mips::Op::Sp_jr:
-            r->ip = r->r[insn.rs()];
-            return;
-          case Mips::Op::Sp_jalr:
-            auto ra = r->ip + 8;
-            r->ip = r->r[insn.rs()];
-            r->r[insn.rd()] = ra;
-            return;
-          }
-        break;
-      case Mips::Op::Regimm:
-        switch (insn.rt())
-          {
-          case Mips::Op::Bal:
-          case Mips::Op::Bgezall:
-            r->r[31] = r->ip + 8;
-          case Mips::Op::Bgez:
-          case Mips::Op::Bgezl:
-            if ((long) r->r[insn.rs()] >= 0)
-              r->ip += insn.branch_offset() + 4;
-            else
-              r->ip += 8;
-            return;
-          case Mips::Op::Nal:
-          case Mips::Op::Bltzall:
-            r->r[31] = r->ip + 8;
-          case Mips::Op::Bltz:
-          case Mips::Op::Bltzl:
-            if ((long) r->r[insn.rs()] < 0)
-              r->ip += insn.branch_offset() + 4;
-            else
-              r->ip += 8;
-            return;
-          }
-        break;
-      case Mips::Op::Beql:
-      case Mips::Op::Bnel:
-      case Mips::Op::Bgtzl:
-      case Mips::Op::Blezl:
-        if (insn.rt() == 0)
-          r->ip += insn.branch_offset() + 4;
-        else
-          r->ip += 8; // R6 compact branch instruction
-        return;
-      case Mips::Op::Beq:
-        if (r->r[insn.rs()] == r->r[insn.rt()])
-          r->ip += insn.branch_offset() + 4;
-        else
-          r->ip += 8;
-        return;
-      case Mips::Op::Bne:
-        if (r->r[insn.rs()] != r->r[insn.rt()])
-          r->ip += insn.branch_offset() + 4;
-        else
-          r->ip += 8;
-        return;
-      case Mips::Op::Bgtz:
-        if (insn.rt() == 0 && (long) r->r[insn.rs()] > 0)
-          r->ip += insn.branch_offset() + 4;
-        else
-          r->ip += 8;
-        return;
-      case Mips::Op::Blez:
-        if (insn.rt() == 0 && (long) r->r[insn.rs()] <= 0)
-          r->ip += insn.branch_offset() + 4;
-        else
-          r->ip += 8;
-        return;
-      case Mips::Op::Jal:
-        r->ra = r->ip + 8;
-        [[fallthrough]];
-      case Mips::Op::J:
-        r->ip = (r->ip & ~((1UL << 28) - 1)) | (insn.instr_index() << 2);
-        return;
-      // compact branch instructions on R6
-      case Mips::Op::Pop10:
-      case Mips::Op::Pop30:
-      case Mips::Op::Pop66:
-      case Mips::Op::Pop76:
-          r->ip += 8;
-          return;
-      }
-
-    Err().printf("Guest exception in branch delay slot. Instruction not implemented @ IP 0x%lx\n", _s->r.ip);
-    enter_kdebug("STOP");
-  }
-
-  Mem_access decode_mmio() const
-  {
-    Mips::Instruction insn(_s->r.bad_instr);
-    Mem_access m;
-
-    m.access = insn.op_mem_store() ? Mem_access::Store : Mem_access::Load;
-
-    if (insn.is_simple_load_store())
-      {
-        m.width = insn.load_store_width();
-
-        if (m.access == Mem_access::Store)
-          m.value = _s->r.r[insn.rt()];
-      }
-    else if (insn.is_fp_load_store())
-      {
-        m.width = insn.op_fp_dc1() ? Mem_access::Wd64 : Mem_access::Wd32;
-
-        if (m.access == Mem_access::Store)
-          m.value = fpu_state()->read(insn.rt());
-      }
-    else
-      m.access = Mem_access::Other;
-
-    return m;
-  }
-
-  void writeback_mmio(Mem_access const &m) const
-  {
-    assert(m.access == Mem_access::Load);
-
-    Mips::Instruction insn(_s->r.bad_instr);
-
-    if (insn.is_simple_load_store())
-      _s->r.r[insn.rt()]
-        = reg_extend_width(m.value, m.width, insn.op_mem_unsigned());
-    else
-      fpu_state()->write(insn.rt(), m.width, m.value);
-  }
-
-  Fpu_state *fpu_state() const
-  { return reinterpret_cast(_s->user_data[Reg_fpu_state]); }
-
-  void alloc_fpu_state() const
-  {
-    _s->user_data[Reg_fpu_state]
-      = reinterpret_cast(new Fpu_state());
-  }
-
-  void free_fpu_state() const
-  {
-    if (fpu_state())
-      {
-        delete fpu_state();
-        _s->user_data[Reg_fpu_state] = 0;
-      }
-  }
-
-  l4_umword_t proc_id() const
-  { return _s->user_data[Reg_proc_id]; }
-
-  void set_proc_id(l4_umword_t id) const
-  { _s->user_data[Reg_proc_id] = id; }
-
-  State *state()
-  { return reinterpret_cast((char *)_s + L4_VCPU_OFFSET_EXT_STATE); }
-
-private:
-  enum Arch_data_regs {
-      Reg_fpu_state = Reg_arch_base,
-      Reg_proc_id,
-      Reg_arch_end
-  };
-
-  static_assert(Reg_arch_end <= 7, "Too many user_data registers used");
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_linux.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_linux.cc
deleted file mode 100644
index 66aa39e7..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_linux.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader_linux.h"
-
-namespace Boot {
-
-int Linux_loader::load(char const * /*bin*/, std::shared_ptr image,
-                       Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-                       l4_addr_t *entry)
-{
-  trace().printf("Checking for Linux image...\n");
-
-  if (!image->is_valid())
-    return -L4_EINVAL;
-
-  Vmm::Guest_addr ram_base = free_list->first_free_address();
-  unsigned char const *h = static_cast(image->get_data());
-
-  if (   h[0x38] == 'R' && h[0x39] == 'S'
-      && h[0x3A] == 'C' && h[0x3B] == 0x05) // Linux header RSC\x05
-  {
-    l4_uint64_t l = *reinterpret_cast(&h[8]);
-    *entry = image->load_as_raw(ram, ram_base + l, free_list);
-    // TODO: Can we detect the bitness of the Linux image? Currently the _64bit
-    //       field is not used by uvmm on RISC-V, but still.
-    _64bit = true;
-  }
-  else
-    return -L4_EINVAL;
-
-  info().printf("Linux kernel detected\n");
-
-  return L4_EOK;
-}
-
-static Linux_loader f __attribute__((init_priority(Boot::Linux)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_raw.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_raw.h
deleted file mode 100644
index eae804ab..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/binary_loader_raw.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-namespace Boot {
-
-enum
-{
-#if __riscv_xlen == 32
-  Kernel_boot_address = 0x80400000,
-#else
-  Kernel_boot_address = 0x80200000,
-#endif
-};
-
-static int raw_load_image(std::shared_ptr image, Vmm::Vm_ram *ram,
-                          Vmm::Ram_free_list *free_list, l4_addr_t *entry)
-{
-  *entry = image->load_as_raw(ram, Vmm::Guest_addr(Kernel_boot_address),
-                              free_list);
-  return L4_EOK;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.cc
deleted file mode 100644
index 71467145..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *            Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include 
-
-#include "cpu_dev.h"
-#include "guest.h"
-#include "riscv_arch.h"
-
-namespace Vmm
-{
-
-Cpu_dev::Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *node)
-: Generic_cpu_dev(idx, phys_id)
-{
-  char const *prop_isa_str = node ? node->get_prop("riscv,isa", nullptr)
-                                  : nullptr;
-  if (!prop_isa_str)
-    return;
-
-  std::string isa_str = prop_isa_str;
-  bool has_ext_sstc = l4_kip_has_isa_ext(l4re_kip(), L4_riscv_isa_ext_sstc);
-  if (has_ext_sstc && isa_str.find("_sstc") == std::string::npos)
-    {
-      // Indicate in the device tree that the SSTC extension is available.
-      isa_str += "_sstc";
-      node->setprop_string("riscv,isa", isa_str.c_str());
-    }
-}
-
-bool
-Cpu_dev::start_vcpu()
-{
-  if (online_state() != Cpu_state::On_pending)
-    {
-      // Should we convert this to an assert()?
-      Err().printf("%s: CPU%d not in On_pending state", __func__, _phys_cpu_id);
-      return false;
-    }
-
-    Dbg(Dbg::Cpu, Dbg::Info)
-      .printf("Initiating cpu startup @ 0x%lx\n", _vcpu->r.ip);
-
-    if (_vcpu->entry_sp && !restart_vcpu())
-      {
-        mark_off();
-        return false;
-      }
-    else
-      reschedule();
-
-    return true;
-}
-
-void L4_NORETURN
-Cpu_dev::stop_vcpu()
-{
-  mark_off();
-  while (online_state() != Cpu_state::On_prepared)
-    _vcpu.wait_for_ipc(l4_utcb(), L4_IPC_NEVER);
-
-  reset();
-}
-
-bool
-Cpu_dev::restart_vcpu()
-{
-  assert(_vcpu->entry_sp);
-
-  mark_on_prepared();
-
-  l4_msgtag_t res = _restart_event.obj_cap()->trigger();
-  if (!l4_msgtag_has_error(res))
-    return true;
-
-  Err().printf("Error waking Cpu%d: %lx\n", _vcpu.get_vcpu_id(), l4_error(res));
-  return false;
-}
-
-void
-Cpu_dev::powerup_cpu()
-{
-  Generic_cpu_dev::powerup_cpu();
-
-  // Now the vCPU thread exists and the IPC registry is setup.
-
-  auto *registry = vcpu().get_ipc_registry();
-  L4Re::chkcap(registry->register_irq_obj(&_restart_event),
-               "Cannot register CPU restart event");
-
-  _stop_irq.arm(registry);
-}
-
-void
-Cpu_dev::reset()
-{
-  using namespace Riscv;
-
-  // set thread local cpu id
-  vmm_current_cpu_id = _vcpu.get_vcpu_id();
-
-  _vcpu->entry_ip = reinterpret_cast(&Guest::vcpu_entry);
-
-  if (!_vcpu->entry_sp)
-    {
-      l4_umword_t sp;
-      asm volatile ("mv %0, sp" : "=r" (sp));
-      _vcpu->entry_sp = sp & ~0xful;
-    }
-
-  _vcpu->saved_state =   L4_VCPU_F_FPU_ENABLED
-                       | L4_VCPU_F_USER_MODE
-                       | L4_VCPU_F_IRQ
-                       | L4_VCPU_F_PAGE_FAULTS
-                       | L4_VCPU_F_EXCEPTIONS;
-
-  _vcpu->r.hstatus = L4_vm_hstatus_spvp | L4_vm_hstatus_vtw;
-#if __riscv_xlen == 64
-  _vcpu->r.hstatus |= static_cast(L4_vm_hstatus_vsxl_64)
-                      << L4_vm_hstatus_vsxl_shift;
-#endif
-
-  auto *vm_state = _vcpu.vm_state();
-  vm_state->hedeleg =   1 << Exc_inst_misaligned
-                      | 1 << Exc_inst_access
-                      | 1 << Exc_illegal_inst
-                      | 1 << Exc_breakpoint
-                      | 1 << Exc_load_acesss
-                      | 1 << Exc_store_acesss
-                      | 1 << Exc_ecall
-                      | 1 << Exc_inst_page_fault
-                      | 1 << Exc_load_page_fault
-                      | 1 << Exc_store_page_fault;
-  vm_state->hideleg =   1 << (Int_virtual_supervisor_software & ~Msb)
-                      | 1 << (Int_virtual_supervisor_timer & ~Msb)
-                      | 1 << (Int_virtual_supervisor_external & ~Msb);
-
-  vm_state->hvip = 0;
-  vm_state->hip = 0;
-  vm_state->hie = 0;
-
-  vm_state->htimedelta = 0;
-
-  vm_state->htval = 0;
-  vm_state->htinst = 0;
-
-  Dbg(Dbg::Core, Dbg::Info)
-    .printf("Starting vcpu %d @ 0x%lx (handler @ %lx with stack @ %lx)\n",
-            _vcpu.get_vcpu_id(), _vcpu->r.ip, _vcpu->entry_ip, _vcpu->entry_sp);
-
-  mark_on();
-
-  L4::Cap self;
-  auto e = l4_error(self->vcpu_resume_commit(self->vcpu_resume_start()));
-
-  Err().printf("VMM exited with %ld\n", e);
-  stop_vcpu();
-
-  // Failed to take vCPU offline. Should not happend but play safe.
-  l4_sleep_forever();
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.h
deleted file mode 100644
index 1cbb7cee..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/cpu_dev.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2020-2024, 2023-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *            Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "generic_cpu_dev.h"
-#include "vcpu_ic.h"
-#include "monitor/cpu_dev_cmd_handler.h"
-
-namespace Vmm {
-
-extern __thread unsigned vmm_current_cpu_id;
-
-class Cpu_dev
-: public Generic_cpu_dev,
-  public Monitor::Cpu_dev_cmd_handler
-{
-public:
-  // Maximum number of CPUs that are addressable.
-  enum { Max_cpus = 8 };
-
-  Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *node);
-
-  /**
-   * CPU states
-   */
-  enum class Cpu_state
-  {
-    Off,
-    On_pending,
-    On_prepared,
-    On,
-    Suspended,
-  };
-
-  /**
-   * Translate a device tree "reg" value to an internally usable CPU id.
-   *
-   * For most architectures this is NOP, but some archictures like ARM
-   * might encode topology information into this value, which needs to
-   * be translated.
-   */
-  static unsigned dtid_to_cpuid(l4_int32_t prop_val)
-  { return prop_val; }
-
-  static bool has_fixed_dt_mapping() { return true; }
-
-  unsigned get_phys_cpu_id() const noexcept
-  { return _phys_cpu_id; }
-
-  // TODO: Starting and stopping of vCPUs is adopted from ARM,
-  //       merging this functionality probably would be benefitial.
-  bool start_vcpu();
-  void L4_NORETURN stop_vcpu();
-  bool restart_vcpu();
-
-
-  void powerup_cpu() override;
-
-  void L4_NORETURN reset() final override;
-  void L4_NORETURN stop() override { stop_vcpu(); };
-
-  /**
-   * Get the online state of a CPU.
-   */
-  Cpu_state online_state() const
-  { return std::atomic_load(&_cpu_state); }
-
-  /**
-   * Is the CPU online?
-   */
-  bool online() const
-  { return online_state() != Cpu_state::Off; }
-
-  /**
-   * Cpu_state changes
-   * * Off -> On_pending:          concurrent execution
-   * * On_pending  -> On:          CPU local, no concurrency (initial startup)
-   * * On_pending  -> On_prepared: CPU local, no concurrency (restart)
-   * * On_prepared -> On:          CPU local, no concurrency (restart)
-   * * On* -> Off:                 CPU local, no concurrency
-   * * On -> Suspended:            CPU local, no concurrency
-   * * Suspended -> On:            CPU local, no concurrency
-   *
-   * The only state change that requires protection against concurrent access
-   * is the change from Off to On_pending. Therefore mark_pending() uses
-   * compare/exchange, the other operation use a simple store.
-   */
-
-  /**
-   * Mark CPU as On_pending.
-   *
-   * \retval True  Successfully changed state from Off to On_pending
-   * \retval False  Failed to change the state from Off to On_pending,
-   *                the state was already changed by someone else.
-   */
-  bool mark_on_pending()
-  {
-    // Atomically change state from Off to On_pending, see above
-    Cpu_state expected{Cpu_state::Off};
-    return std::atomic_compare_exchange_strong(&_cpu_state, &expected,
-                                               Cpu_state::On_pending);
-  }
-
-  /**
-   * Mark CPU as On_prepared.
-   *
-   * The vCPU entry has been setup and the guest is about to be entered
-   * again. This state is only used when restarting a CPU that was previously
-   * powered off.
-   */
-  void mark_on_prepared()
-  {
-    assert(online_state() == Cpu_state::On_pending);
-    std::atomic_store(&_cpu_state, Cpu_state::On_prepared);
-  }
-
-  /**
-   * Mark CPU as Off.
-   *
-   * Marks the CPU as Off. The current state has to be either On (CPU is
-   * switched off) or On_pending (we failed to get the CPU up and fall
-   * back to Off)
-   */
-  void mark_off()
-  {
-    assert(online_state() != Cpu_state::Off);
-    std::atomic_store(&_cpu_state, Cpu_state::Off);
-  }
-
-  /**
-   * Mark CPU as On.
-   *
-   * Marks the CPU as On. The current state has to be On_pending or On_prepared.
-   */
-  void mark_on()
-  {
-    assert(online_state() == Cpu_state::On_pending ||
-           online_state() == Cpu_state::On_prepared ||
-           online_state() == Cpu_state::Suspended);
-    std::atomic_store(&_cpu_state, Cpu_state::On);
-  }
-
-  /**
-   * Mark CPU as Suspended.
-   *
-   * Marks the CPU as Suspended. The current state has to be On.
-   */
-  void mark_suspended()
-  {
-    assert(online_state() == Cpu_state::On);
-    std::atomic_store(&_cpu_state, Cpu_state::Suspended);
-  }
-
-  void set_vcpu_ic(cxx::Ref_ptr vcpu_ic)
-  {
-    _vcpu_ic = vcpu_ic;
-  }
-
-private:
-  /**
-   * Trivial interrupt to wakeup stopped vCPU.
-   */
-  struct Restart_event : public L4::Irqep_t
-  {
-  public:
-    void handle_irq() {}
-  };
-
-  cxx::Ref_ptr _vcpu_ic;
-  std::atomic _cpu_state{Cpu_state::Off};
-  Restart_event _restart_event;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/debugger/guest_debugger.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/debugger/guest_debugger.h
deleted file mode 100644
index 47fc5ba0..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/debugger/guest_debugger.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-namespace Vmm {
-  class Vm;
-}
-
-namespace Monitor {
-
-class Guest_debugger
-{
-public:
-  explicit Guest_debugger(Vmm::Vm *)
-  {}
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.cc
deleted file mode 100644
index 56b30368..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.cc
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "binary_loader.h"
-#include "guest.h"
-#include "riscv_arch.h"
-
-namespace Vmm {
-
-// The singleton instance of the VMM.
-static cxx::Static_container guest;
-
-__thread unsigned vmm_current_cpu_id;
-
-Guest *
-Guest::create_instance()
-{
-  guest.construct();
-  return guest;
-}
-
-Guest::Guest()
-: _sbi(Sbi::create_instance(this))
-{
-  _has_vstimecmp = l4_kip_has_isa_ext(l4re_kip(), L4_riscv_isa_ext_sstc);
-}
-
-void
-Guest::setup_device_tree(Vdev::Device_tree dt)
-{
-  // Provide frequency of platform timer in DTS
-  auto node = dt.path_offset("/cpus");
-  node.setprop_u32("timebase-frequency",
-                   l4re_kip()->platform_info.arch.timebase_frequency);
-}
-
-l4_addr_t
-Guest::load_binary(Vm_ram *ram, char const *binary, Ram_free_list *free_list)
-{
-  l4_addr_t entry;
-
-  Boot::Binary_loader_factory bf;
-  bf.load(binary, ram, free_list, &entry);
-
-  return entry;
-}
-
-void
-Guest::prepare_platform(Vdev::Device_lookup *devs)
-{
-  _cpus = devs->cpus();
-  _ram = devs->ram();
-}
-
-void
-Guest::prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const *, char const *, l4_addr_t dt_boot_addr)
-{
-  Vcpu_ptr vcpu = devs->cpus()->vcpu(0);
-
-  // Arguments as provided by firmware (e.g. OpenSBI)
-  // a0: Hart ID
-  vcpu->r.a0 = vcpu.get_vcpu_id();
-  // a1: Flattened Device Tree
-  vcpu->r.a1 = dt_boot_addr;
-
-  vcpu->r.ip = entry;
-}
-
-void
-Guest::run(cxx::Ref_ptr const &cpus)
-{
-  if (!_plic)
-    {
-       Err().printf("No PLIC found.\n");
-       L4Re::throw_error(-L4_ENODEV, "No PLIC found.");
-    }
-
-  Vdev::Virtual_timer::init_frequency();
-
-  for (auto cpu: *cpus.get())
-    {
-      if (!cpu)
-        continue;
-
-      auto vcpu = cpu->vcpu();
-      auto vcpu_id = vcpu.get_vcpu_id();
-
-      vcpu->user_task = _task.cap();
-      cpu->powerup_cpu();
-      info().printf("Powered up cpu%d [%p]\n", vcpu_id, cpu.get());
-
-      if (vcpu_id >= _vcpu_ics.size())
-        _vcpu_ics.resize(vcpu_id + 1);
-
-      _vcpu_ics[vcpu_id] = Vdev::make_device(vcpu, registry());
-      _vcpu_ics[vcpu_id]->attach_cpu_thread(cpu->thread_cap());
-      cpu->set_vcpu_ic(_vcpu_ics[vcpu_id]);
-
-      if (!_has_vstimecmp)
-        {
-          if (vcpu_id >= _timers.size())
-            _timers.resize(vcpu_id + 1);
-
-          _timers[vcpu_id] = Vdev::make_device(
-            vcpu, cpu->thread_cap(), _vcpu_ics[vcpu_id]);
-          _timers[vcpu_id]->start_timer_thread(cpu->get_phys_cpu_id());
-        }
-
-      _plic->setup_target(vcpu, _vcpu_ics[vcpu_id]);
-    }
-
-  cpus->cpu(0)->mark_on_pending();
-  cpus->cpu(0)->startup();
-}
-
-void
-Guest::sync_all_other_cores_off() const
-{
-  bool all_stop = true;
-  do
-    {
-      all_stop = true;
-      for (auto cpu : *_cpus.get())
-        {
-          if (cpu && cpu->vcpu().get_vcpu_id() == vmm_current_cpu_id)
-            continue;
-
-          if (cpu && cpu->online())
-            {
-              all_stop = false;
-              break;
-            }
-        }
-    } while (!all_stop);
-};
-
-void L4_NORETURN
-Guest::halt_vm(Vcpu_ptr current_vcpu)
-{
-  stop_cpus();
-  sync_all_other_cores_off();
-  Generic_guest::halt_vm(current_vcpu);
-}
-
-void L4_NORETURN
-Guest::shutdown(int val)
-{
-  stop_cpus();
-  Generic_guest::shutdown(val);
-}
-
-void
-Guest::stop_cpus()
-{
-  // Exit all vCPU threads into the vmm and stop the vCPUs.
-  for (auto cpu: *_cpus.get())
-    {
-      if (   cpu && cpu->online()
-          && cpu->vcpu().get_vcpu_id() != vmm_current_cpu_id)
-        cpu->send_stop_event();
-    }
-}
-
-void
-Guest::wfi(Vcpu_ptr vcpu)
-{
-  bool pending_irq = vcpu.has_pending_irq();
-  // If Sstc extension is used there is no timer-thread to wake us up, so we
-  // have to set up a receive timeout according to the next timer event the
-  // guest configured in vstimecmp.
-  l4_timeout_t wait_timeout = L4_IPC_NEVER;
-  if (!pending_irq && _has_vstimecmp && (vcpu.vm_state()->hie & L4_vm_hvip_vstip))
-    pending_irq = !Vdev::Virtual_timer::setup_event_rcv_timeout(
-                    l4_utcb(), &wait_timeout, vcpu.vm_state()->vstimecmp);
-
-  if (!pending_irq)
-    vcpu.wait_for_ipc(l4_utcb(), wait_timeout);
-}
-
-void
-Guest::handle_entry(Vcpu_ptr vcpu)
-{
-  switch (vcpu->r.cause)
-    {
-      case Riscv::Exc_hcall:
-        handle_ecall(vcpu);
-        break;
-      case Riscv::Exc_guest_inst_page_fault:
-      case Riscv::Exc_guest_load_page_fault:
-      case Riscv::Exc_guest_store_page_fault:
-        handle_page_fault(vcpu);
-        break;
-      case Riscv::Exc_virtual_inst:
-        handle_virtual_inst(vcpu);
-        break;
-      case Riscv::L4_ipc_upcall:
-        handle_ipc_upcall(vcpu);
-        break;
-      case Riscv::L4_exregs_exception:
-        handle_exregs_exception(vcpu);
-        break;
-      case Riscv::Exc_illegal_inst:
-        // Fiasco prevents delegation of illegal instruction exception if lazy
-        // FPU switching is enabled.
-        redirect_trap(vcpu);
-        break;
-      default:
-        {
-          auto *vm_state = vcpu.vm_state();
-          Err().printf("[%3u] Unexpected VMM entry!\n", vcpu.get_vcpu_id());
-          Err().printf("=== l4 vCPU state ===\n"
-                        "pc: 0x%lx\n"
-                        "ra: 0x%lx\n"
-                        "cause: 0x%lx\n"
-                        "pfa: 0x%lx\n"
-                        "state: 0x%x\n"
-                        "saved_state: 0x%x\n"
-                        "=== extended vCPU state ===\n"
-                        "hstatus: 0x%lx\n"
-                        "htval: 0x%lx\n"
-                        "htinst: 0x%lx\n",
-                        vcpu->r.ip, vcpu->r.ra, vcpu->r.cause, vcpu->r.pfa,
-                        vcpu->state, vcpu->saved_state,
-                        vcpu->r.hstatus, vm_state->htval, vm_state->htinst);
-
-          halt_vm(vcpu);
-        }
-    }
-
-  vcpu.process_pending_ipc(l4_utcb());
-}
-
-void
-Guest::handle_ipc_upcall(Vcpu_ptr vcpu)
-{
-  vcpu.handle_ipc(vcpu->i.tag, vcpu->i.label, l4_utcb());
-}
-
-void
-Guest::handle_exregs_exception(Vcpu_ptr vcpu)
-{
-  warn().printf("[%3u] Ex_regs exception exit received. Nothing to do!\n",
-                vcpu.get_vcpu_id());
-}
-
-void
-Guest::handle_ecall(Vcpu_ptr vcpu)
-{
-  if(!_sbi->handle(vcpu))
-    halt_vm(vcpu);
-
-  // Advance ip to continue execution after ecall instruction
-  vcpu.jump_system_instruction();
-}
-
-void
-Guest::handle_page_fault(Vcpu_ptr vcpu)
-{
-  auto *vm_state = vcpu.vm_state();
-
-  assert(vcpu->r.hstatus & L4_vm_hstatus_gva);
-  // htval is either zero or the guest physical address shifted to
-  // the right by 2 bits, to allow addresses wider than the current XLEN.
-  // The least-significant two bits can be taken from stval.
-  l4_addr_t gpa_addr = (vm_state->htval << 2) + (vcpu->r.tval & 0b11);
-
-  if (vcpu->r.cause == Riscv::Exc_guest_inst_page_fault)
-    {
-      Err().printf(
-        "cannot handle VM instruction page fault @ 0x%lx "
-        "ip=0x%lx ra=0x%lx cause=0x%lx tval=0x%lx htval=0x%lx\n",
-        gpa_addr, vcpu->r.ip, vcpu->r.ra, vcpu->r.cause,
-        vcpu->r.tval, vcpu.vm_state()->htval);
-      guest->halt_vm(vcpu);
-    }
-
-  fetch_guest_inst(vcpu);
-
-  switch (handle_mmio(gpa_addr, vcpu))
-    {
-    case Retry: break;
-    case Jump_instr: vcpu.jump_trap_instruction(); break;
-    default:
-      Err().printf(
-        "cannot handle VM memory access @ 0x%lx "
-        "ip=0x%lx ra=0x%lx cause=0x%lx tval=0x%lx htval=0x%lx\n",
-        gpa_addr, vcpu->r.ip, vcpu->r.ra, vcpu->r.cause,
-        vcpu->r.tval, vcpu.vm_state()->htval);
-      guest->halt_vm(vcpu);
-      break;
-    }
-}
-
-void
-Guest::handle_virtual_inst(Vcpu_ptr vcpu)
-{
-  fetch_guest_inst(vcpu);
-  Riscv::Instruction inst(vcpu.vm_state()->htinst);
-  if (inst.is_wfi())
-    {
-      // Resume with instruction following wfi
-      vcpu.jump_system_instruction();
-      wfi(vcpu);
-    }
-  else
-    {
-      Err().printf("Unsupported virtual instruction @ 0x%lx: 0x%x\n",
-                   vcpu->r.pc, inst.inst);
-      guest->halt_vm(vcpu);
-    }
-}
-
-void
-Guest::vcpu_entry(l4_vcpu_state_t *vcpu)
-{
-  Vmm::Vcpu_ptr c(vcpu);
-  if (!(vcpu->saved_state & L4_VCPU_F_USER_MODE)
-      && vcpu->r.cause != Riscv::L4_exregs_exception)
-    {
-      Err().printf("Exception in entry handler. Halting. "
-                   "ip=0x%lx cause=0x%lx pfa=0x%lx\n",
-                   vcpu->r.ip, vcpu->r.cause, vcpu->r.pfa);
-      guest->halt_vm(c);
-    }
-
-  guest->handle_entry(c);
-
-  L4::Cap self;
-  auto e = l4_error(self->vcpu_resume_commit(self->vcpu_resume_start()));
-
-  Err().printf("VM resume failed with %ld\n", e);
-  guest->halt_vm(c);
-}
-
-/**
- * Lookup CPU for untrusted vCPU ID, i.e. it might be provided by the guest, and
- * thus might not refer to an existing CPU.
- */
-Cpu_dev *
-Guest::lookup_cpu(l4_umword_t vcpu_id) const
-{
-  if (_cpus->vcpu_exists(vcpu_id))
-    return _cpus->cpu(vcpu_id).get();
-
-  return nullptr;
-}
-
-/**
- * Fetches and decodes the instruction at the current instruction pointer if
- * necessary.
- *
- * To emulate MMIO accesses and handle virtual instruction exceptions, we need
- * to decode the faulting instruction. The htinst register might contain
- * information about this instruction, but this is an optional feature. In case
- * htinst does not contain information, we have to fetch the instruction by
- * manually reading from guest memory at the current instruction pointer.
- */
-void
-Guest::fetch_guest_inst(Vcpu_ptr vcpu)
-{
-  auto vm_state = vcpu.vm_state();
-
-  // Hardware did not provide trapped instruction in htinst, try to read the
-  // instruction from memory.
-  if (vm_state->htinst == 0)
-    {
-      bool failed = false;
-      l4_uint32_t inst = read_guest_mem_inst(vcpu->r.pc, vm_state, &failed);
-      if (!failed)
-        {
-          if (!Riscv::is_compressed_inst(inst))
-            {
-              // Not a compressed instruction, so read the remaining 16 bit.
-              inst |= read_guest_mem_inst(vcpu->r.pc + 2, vm_state, &failed) << 16;
-            }
-          else
-            {
-              // Transform compressed instruction according to the RISC-V privileged spec.
-              Riscv::C_instruction c_inst(inst);
-              inst = c_inst.transformed().inst;
-              trace().printf(
-                "Transformed compressed instruction @ 0x%lx: 0x%x -> 0x%x\n",
-                vcpu->r.pc, c_inst.inst, inst);
-            }
-        }
-
-      if (failed)
-        {
-          warn().printf(
-            "Failed to read guest instruction @ 0x%lx\n", vcpu->r.pc);
-          return;
-        }
-
-      vm_state->htinst = inst;
-    }
-}
-
-/**
- * Read the instruction at the given guest virtual address.
- *
- * Reads the instruction with a hypervisor virtual-machine load instruction,
- * which allows to access guest memory with the same address translation
- * conditions that would apply for the guest, so fortunately no need to
- * manually walk the guest page tables.
- */
-l4_uint16_t
-Guest::read_guest_mem_inst(l4_addr_t guest_virt_addr,
-                           l4_vm_state_t *vm_state, bool *failed)
-{
-  // Fiasco catches failed HLV/HLVX/HSV instructions,
-  // skips them and sets vm_state->hlsi_failed to true.
-  vm_state->hlsi_failed = false;
-
-  register l4_umword_t tmp asm("a0") = guest_virt_addr;
-  /*
-   * HLVX.HU a0, (a0)
-   * 0110010 00011 01010 100 01010 1110011
-   */
-  asm volatile (".word 0x64354573" : "+r" (tmp) : : "memory");
-
-  *failed = vm_state->hlsi_failed;
-  return tmp;
-}
-
-void
-Guest::redirect_trap(Vcpu_ptr vcpu)
-{
-  auto *vm_state = vcpu.vm_state();
-
-  // Record privilege level before trap.
-  if (vcpu->r.hstatus & Riscv::Hstatus_spvp)
-    vm_state->vsstatus |= Riscv::Sstatus_spp;
-  else
-    vm_state->vsstatus &= ~Riscv::Sstatus_spp;
-
-  // Disable interrupts on trap.
-  if (vm_state->vsstatus & Riscv::Sstatus_sie)
-    {
-      vm_state->vsstatus |= Riscv::Sstatus_spie;
-      vm_state->vsstatus &= ~Riscv::Sstatus_sie;
-    }
-  else
-    vm_state->vsstatus &= ~Riscv::Sstatus_spie;
-
-  // Setup registers with trap info.
-  vm_state->vsepc = vcpu->r.pc;
-  vm_state->vscause = vcpu->r.cause;
-  vm_state->vstval = vcpu->r.tval;
-
-  // Jump to guest exception vector.
-  vcpu->r.pc = vm_state->vstvec & ~Riscv::Stvec_mode_mask;
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.h
deleted file mode 100644
index bc2510f4..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/guest.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "cpu_dev_array.h"
-#include "generic_guest.h"
-#include "plic.h"
-#include "sbi.h"
-#include "vcpu_ic.h"
-#include "virtual_timer.h"
-#include "vm_ram.h"
-
-namespace Vmm {
-
-class Guest : public Generic_guest
-{
-public:
-  enum
-  {
-    Default_rambase = 0,
-    Boot_offset = 0
-  };
-
-  static Guest *create_instance();
-
-  Guest();
-
-  void setup_device_tree(Vdev::Device_tree);
-
-  void set_plic(cxx::Ref_ptr &plic)
-  { _plic = plic; }
-
-  l4_addr_t load_binary(Vm_ram *ram, char const *binary,
-                        Ram_free_list *free_list);
-
-  void prepare_platform(Vdev::Device_lookup *devs);
-
-  void prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const *binary, char const *cmd_line,
-                          l4_addr_t dt_boot_addr);
-
-  void run(cxx::Ref_ptr const &cpus);
-
-  void sync_all_other_cores_off() const override;
-
-  void L4_NORETURN halt_vm(Vcpu_ptr current_vcpu) override;
-  void L4_NORETURN shutdown(int val) override;
-
-  void wfi(Vcpu_ptr vcpu);
-
-  void handle_entry(Vcpu_ptr vcpu);
-  void handle_ipc_upcall(Vcpu_ptr vcpu);
-  void handle_exregs_exception(Vcpu_ptr vcpu);
-  void handle_ecall(Vcpu_ptr vcpu);
-  void handle_page_fault(Vcpu_ptr vcpu);
-  void handle_virtual_inst(Vcpu_ptr vcpu);
-
-  static void vcpu_entry(l4_vcpu_state_t *vcpu);
-
-  cxx::Ref_ptr cpus() const
-  { return _cpus; }
-
-  cxx::Ref_ptr ram() const
-  { return _ram; }
-
-  Cpu_dev *lookup_cpu(l4_umword_t vcpu_id) const;
-
-  cxx::Ref_ptr get_vcpu_ic(Vcpu_ptr vcpu)
-  { return _vcpu_ics[vcpu.get_vcpu_id()]; }
-
-  bool has_vstimecmp() const
-  { return _has_vstimecmp; }
-
-  cxx::Ref_ptr get_timer(Vcpu_ptr vcpu)
-  { return _timers[vcpu.get_vcpu_id()]; }
-
-  void register_sbi_ext_handler(l4_int32_t ext_id, cxx::Ref_ptr handler)
-  { _sbi->register_ext(ext_id, handler); }
-
-private:
-  void stop_cpus();
-
-  void redirect_trap(Vcpu_ptr vcpu);
-
-  static void fetch_guest_inst(Vcpu_ptr vcpu);
-  static l4_uint16_t read_guest_mem_inst(l4_addr_t guest_virt_addr,
-                                         l4_vm_state_t *vm_state,
-                                         bool *failed);
-
-  bool _has_vstimecmp;
-
-  cxx::Ref_ptr _cpus;
-  cxx::Ref_ptr _ram;
-  std::vector> _vcpu_ics;
-  std::vector> _timers;
-  cxx::Ref_ptr _plic;
-  Sbi *_sbi;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/cpu_dev_cmd_handler.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/cpu_dev_cmd_handler.h
deleted file mode 100644
index 7d6b7367..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/cpu_dev_cmd_handler.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "vcpu_ptr.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Cpu_dev_cmd_handler {};
-
-template
-class Cpu_dev_cmd_handler : public Cmd
-{
-public:
-  char const *help() const override
-  { return "CPU state"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'cpu  regs': dump CPU registers\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, "regs"); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "regs")
-      show_regs(f);
-    else
-      argument_error("Invalid subcommand");
-  }
-
-  void show_regs(FILE *f) const
-  {
-    auto v = get_vcpu();
-    fprintf(f, "pc     = " l4_addr_fmt "\n", v->r.pc);
-    fprintf(f, "sp     = " l4_addr_fmt "\n", v->r.sp);
-    fprintf(f, "ra     = " l4_addr_fmt "\n", v->r.ra);
-    fprintf(f, "status = " l4_addr_fmt "\n", v->r.status);
-    fprintf(f, "cause  = " l4_addr_fmt "\n", v->r.cause);
-    fprintf(f, "pfa    = " l4_addr_fmt "\n", v->r.pfa);
-    fprintf(f, "\n");
-    fprintf(f, "gp = " l4_addr_fmt "  tp = " l4_addr_fmt "\n",
-            v->r.gp, v->r.tp);
-    fprintf(f, "t0 = " l4_addr_fmt "  t1 = " l4_addr_fmt
-             "  t2 = " l4_addr_fmt " \n", v->r.t0, v->r.t1, v->r.t2);
-    fprintf(f, "t3 = " l4_addr_fmt "  t4 = " l4_addr_fmt
-             "  t5 = " l4_addr_fmt "  t6 = " l4_addr_fmt " \n",
-            v->r.t3, v->r.t4, v->r.t5, v->r.t6);
-    fprintf(f, "s0 = " l4_addr_fmt "  s1 = " l4_addr_fmt
-             "  s2 = " l4_addr_fmt "  s3 = " l4_addr_fmt " \n",
-            v->r.s0, v->r.s1, v->r.s2, v->r.s3);
-    fprintf(f, "s4 = " l4_addr_fmt "  s5 = " l4_addr_fmt
-             "  s6 = " l4_addr_fmt "  s7 = " l4_addr_fmt " \n",
-            v->r.s4, v->r.s5, v->r.s6, v->r.s7);
-    fprintf(f, "s8 = " l4_addr_fmt "  s9 = " l4_addr_fmt
-             " s10 = " l4_addr_fmt " s11 = " l4_addr_fmt " \n",
-            v->r.s8, v->r.s9, v->r.s10, v->r.s11);
-    fprintf(f, "a0 = " l4_addr_fmt "  a1 = " l4_addr_fmt
-             "  a2 = " l4_addr_fmt "  a3 = " l4_addr_fmt " \n",
-            v->r.a0, v->r.a1, v->r.a2, v->r.a3);
-    fprintf(f, "a4 = " l4_addr_fmt "  a5 = " l4_addr_fmt
-             "  a6 = " l4_addr_fmt "  a7 = " l4_addr_fmt " \n",
-            v->r.a4, v->r.a5, v->r.a6, v->r.a7);
-    fprintf(f, "\n");
-
-    auto s = v.vm_state();
-    fprintf(f, "hstatus    = " l4_addr_fmt "\n", v->r.hstatus);
-    fprintf(f, "htval      = " l4_addr_fmt "\n", s->htval);
-    fprintf(f, "htinst     = " l4_addr_fmt "\n", s->htinst);
-    fprintf(f, "hedeleg    = " l4_addr_fmt "\n", s->hedeleg);
-    fprintf(f, "hideleg    = " l4_addr_fmt "\n", s->hideleg);
-    fprintf(f, "hvip       = " l4_addr_fmt "\n", s->hvip);
-    fprintf(f, "hip        = " l4_addr_fmt "\n", s->hip);
-    fprintf(f, "hie        = " l4_addr_fmt "\n", s->hie);
-    fprintf(f, "htimedelta = %016llx\n", s->htimedelta);
-    fprintf(f, "\n");
-    fprintf(f, "vsepc      = " l4_addr_fmt "\n", s->vsepc);
-    fprintf(f, "vsstatus   = " l4_addr_fmt "\n", s->vsstatus);
-    fprintf(f, "vscause    = " l4_addr_fmt "\n", s->vscause);
-    fprintf(f, "vstval     = " l4_addr_fmt "\n", s->vstval);
-    fprintf(f, "vstvec     = " l4_addr_fmt "\n", s->vstvec);
-    fprintf(f, "vsscratch  = " l4_addr_fmt "\n", s->vsscratch);
-    fprintf(f, "vsatp      = " l4_addr_fmt "\n", s->vsatp);
-  }
-
-private:
-  Vmm::Vcpu_ptr get_vcpu() const
-  { return static_cast(this)->vcpu(); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/monitor_arch.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/monitor_arch.h
deleted file mode 100644
index ea9c2ed3..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/monitor/monitor_arch.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-constexpr bool has_iomap()
-{ return false; }
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.cc
deleted file mode 100644
index 60f01ccd..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.cc
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "plic.h"
-
-static Dbg warn(Dbg::Irq, Dbg::Warn, "plic");
-static Dbg info(Dbg::Irq, Dbg::Info, "plic");
-static Dbg trace(Dbg::Irq, Dbg::Trace, "plic");
-
-namespace Gic {
-
-Plic::Plic_target::Plic_target(Plic *plic, Vmm::Vcpu_ptr vcpu,
-                               cxx::Ref_ptr vcpu_ic)
-: _plic(plic),
-  _vcpu(vcpu),
-  _vcpu_ic(vcpu_ic),
-  _threshold(0)
-{
-}
-
-void Plic::Plic_target::enable(l4_uint32_t offset, l4_uint32_t value,
-                               Vmm::Vcpu_ptr current_vcpu)
-{
-  assert(offset < Num_irqs / 32);
-  _enable.set_word32(offset, value);
-  update_ext_int_pending(pending_irq(), current_vcpu);
-}
-
-l4_uint32_t Plic::Plic_target::enabled(l4_uint32_t offset) const
-{
-  assert(offset < Num_irqs / 32);
-  return _enable.word32(offset);
-}
-
-l4_uint32_t Plic::Plic_target::claim(Vmm::Vcpu_ptr current_vcpu)
-{
-  for (;;)
-    {
-      unsigned best_irq = 0;
-      unsigned nr_pending = 0;
-      if (!find_best_irq(best_irq, nr_pending))
-        {
-          // No pending interrupt.
-          update_ext_int_pending(false, current_vcpu);
-          return 0;
-        }
-
-      if (_plic->claim_irq(best_irq))
-        {
-          // Update the external interrupt pending state of this target
-          update_ext_int_pending(nr_pending > 1, current_vcpu);
-          return best_irq;
-        }
-      // Already claimed, retry with next interrupt.
-    }
-}
-
-void Plic::Plic_target::complete(l4_uint32_t irq, Vmm::Vcpu_ptr current_vcpu)
-{
-  assert(irq < Num_irqs);
-
-  // Interrupt has to be enabled, otherwise complete has no effect.
-  if (_enable[irq])
-    {
-      if (auto handler = _plic->get_irq_src_handler(irq))
-        handler->eoi();
-
-      if (_plic->_gateways[irq].complete())
-        // Interrupt still pending, update for all targets.
-        _plic->set_irq(irq, current_vcpu);
-    }
-}
-
-l4_uint32_t Plic::Plic_target::threshold() const
-{
-  return _threshold;
-}
-
-void Plic::Plic_target::threshold(l4_uint32_t threshold,
-                                  Vmm::Vcpu_ptr current_vcpu)
-{
-  _threshold = threshold;
-  update_ext_int_pending(pending_irq(), current_vcpu);
-}
-
-void Plic::Plic_target::update_ext_int_pending(bool pending,
-                                               Vmm::Vcpu_ptr current_vcpu)
-{
-  _vcpu_ic->set_external_pending(pending, current_vcpu);
-}
-
-bool Plic::Plic_target::find_best_irq(unsigned &best_irq,
-                                      unsigned &nr_pending) const
-{
-  nr_pending = 0;
-  best_irq = 0;
-  unsigned best_irq_priority = 0;
-  Per_irq_bitmap::for_set_bits([&](unsigned irq)
-    {
-      unsigned irq_priority = _plic->_priorities[irq];
-      if (irq_priority > _threshold)
-        {
-          ++nr_pending;
-          // Smaller interrupts identifiers take precedence over larger ones,
-          // if both have the same priority assigned.
-          if (irq_priority > best_irq_priority)
-            {
-              best_irq = irq;
-              best_irq_priority = irq_priority;
-            }
-        }
-    }, _plic->_pending, _enable);
-
-  return best_irq != 0;
-}
-
-bool Plic::Plic_target::pending_irq() const
-{
-  bool pending = false;
-  Per_irq_bitmap::for_set_bits([&](unsigned irq)
-    {
-      if (_plic->_priorities[irq] > _threshold)
-        {
-          pending = true;
-          // Found pending interrupt, stop iteration.
-          return Per_irq_bitmap::Break;
-        }
-      else
-        return Per_irq_bitmap::Continue;
-    }, _plic->_pending, _enable);
-  return pending;
-}
-
-Plic::Plic(Vdev::Dt_node const &node, unsigned num_dt_interrupt_targets)
-: _num_dt_interrupt_targets(num_dt_interrupt_targets)
-{
-  node.setprop_u32("riscv,ndev", Num_irqs);
-}
-
-void Plic::setup_target(Vmm::Vcpu_ptr vcpu, cxx::Ref_ptr vcpu_ic)
-{
-  if (_num_dt_interrupt_targets == _num_targets_created)
-    L4Re::throw_error(-L4_EINVAL,
-                      "The interrupts-extended property in the device tree refers "
-                      "to fewer interrupt targets than there are vCPUs.\n");
-
-  if(vcpu.get_vcpu_id() >= _targets.size())
-    _targets.resize(vcpu.get_vcpu_id() + 1);
-
-  _targets[vcpu.get_vcpu_id()] = cxx::make_unique(this, vcpu,
-                                                               vcpu_ic);
-  ++_num_targets_created;
-}
-
-Vmm::Vcpu_ptr Plic::get_vcpu(unsigned cpu_id)
-{
-  assert(cpu_id < _targets.size());
-  return _targets[cpu_id]->vcpu();
-}
-
-bool Plic::check_access(unsigned reg, char size, char const *operation)
-{
-  if (size != Vmm::Mem_access::Wd32)
-    {
-      warn.printf("%s @0x%x with unsupported width %d ignored\n",
-                  operation, reg, 8 << size);
-      return false;
-    }
-
-  if (reg % 4 != 0)
-    {
-      warn.printf("misaligned %s @0x%x with width %d ignored\n",
-                  operation, reg, 8 << size);
-      return false;
-    }
-
-  return true;
-}
-
-bool Plic::check_irq(unsigned irq, char const *operation)
-{
-  if (irq < 1 || irq >= Num_irqs)
-    {
-      warn.printf("attempt to %s of not implemented irq %u ignored\n",
-                  operation, irq);
-      return false;
-    }
-
-  return true;
-}
-
-bool Plic::check_irq_range(unsigned offset, char const *operation)
-{
-  unsigned first_irq = offset * 32;
-  unsigned last_irq = first_irq + 31;
-  if (last_irq >= Num_irqs)
-    {
-      warn.printf("attempt to %s of not implemented irq range [%u, %u] ignored\n",
-                  operation, first_irq, last_irq);
-      return false;
-    }
-
-  return true;
-}
-
-bool Plic::check_target(unsigned target_id)
-{
-  if (target_id >= _targets.size() || !get_target(target_id))
-    {
-      warn.printf("attempt to access non existing target %u ignored\n",
-                  target_id);
-      return false;
-    }
-
-  return true;
-}
-
-bool Plic::claim_irq(unsigned irq)
-{
-  if (_gateways[irq].claim())
-    {
-      _pending.clear_bit(irq);
-      return true;
-    }
-  else
-    return false;
-}
-
-void Plic::set_irq(unsigned irq, Vmm::Vcpu_ptr current_vcpu)
-{
-  _pending.set_bit(irq);
-
-  for(auto &target : _targets)
-    if (target)
-      target->update_ext_int_pending(target->pending_irq(), current_vcpu);
-}
-
-l4_umword_t Plic::read(unsigned reg, char size, unsigned cpu_id)
-{
-  if (!check_access(reg, size, "read"))
-    return 0;
-
-  // TODO: More fine grained locking?
-  std::lock_guard lock(_lock);
-
-  if (/*reg >= Priority_base && */ reg < Pending_base)
-    {
-      unsigned irq = (reg - Priority_base) / 4;
-      if (check_irq(irq, "read priority register"))
-        return _priorities[irq];
-    }
-  else if (reg >= Pending_base && reg < Enable_base)
-    {
-      unsigned offset = (reg - Pending_base) / 4;
-      if (check_irq_range(offset, "read pending register"))
-        return _pending.word32(offset);
-    }
-  else if (reg >= Enable_base && reg < Context_base)
-    {
-      unsigned target_id = (reg - Enable_base) / Enable_per_hart;
-      unsigned offset = (reg & Enable_mask) / 4;
-      if (   check_target(target_id)
-          && check_irq_range(offset, "read enable register"))
-        return get_target(target_id)->enabled(offset);
-    }
-  else if (reg >= Context_base)
-    {
-      unsigned target_id = (reg - Context_base) / Context_per_hart;
-      unsigned offset = (reg & Context_mask);
-      if (check_target(target_id))
-        {
-          if (offset == Context_threshold)
-            return get_target(target_id)->threshold();
-          else if (offset == Context_claim)
-            return get_target(target_id)->claim(get_vcpu(cpu_id));
-          else
-              warn.printf("attempt to read non existing target offset 0x%x ignored\n",
-                          offset);
-        }
-    }
-  else
-    {
-      info.printf("Reading unknown register @ 0x%x (%d)\n", reg, size);
-    }
-
-  return 0;
-}
-
-void Plic::write(unsigned reg, char size, l4_umword_t value, unsigned cpu_id)
-{
-  if (!check_access(reg, size, "write"))
-    return;
-
-  // TODO: More fine grained locking?
-  std::lock_guard lock(_lock);
-
-  if (/*reg >= Priority_base && */ reg < Pending_base)
-    {
-      unsigned irq = (reg - Priority_base) / 4;
-      if (check_irq(irq, "write priority register"))
-        _priorities[irq] = value;
-    }
-  else if (reg >= Enable_base && reg < Context_base)
-    {
-      unsigned target_id = (reg - Enable_base) / Enable_per_hart;
-      unsigned offset = (reg & Enable_mask) / 4;
-      if (   check_target(target_id)
-          && check_irq_range(offset, "write enable register"))
-        get_target(target_id)->enable(offset, value, get_vcpu(cpu_id));
-    }
-  else if (reg >= Context_base)
-    {
-      unsigned target_id = (reg - Context_base) / Context_per_hart;
-      unsigned offset = (reg & Context_mask);
-      if (check_target(target_id))
-        {
-          if (offset == Context_threshold)
-            get_target(target_id)->threshold(value, get_vcpu(cpu_id));
-          else if (offset == Context_claim)
-            get_target(target_id)->complete(value, get_vcpu(cpu_id));
-          else
-            warn.printf("attempt to write non existing target offset 0x%x ignored\n",
-                        offset);
-        }
-    }
-  else
-    info.printf("Writing ignored 0x%lx @ 0x%x (%d)\n", value, reg, size);
-}
-
-void Plic::set(unsigned irq)
-{
-  assert(irq >= 1);
-  trace.printf("Set irq %u\n", irq);
-  if (_gateways[irq].set())
-    {
-      std::lock_guard lock(_lock);
-      set_irq(irq, get_vcpu(Vmm::vmm_current_cpu_id));
-    }
-}
-
-void Plic::clear(unsigned)
-{
-  // Interrupt request cannot be retracted once forwarded to PLIC.
-}
-
-void Plic::bind_irq_src_handler(unsigned irq, Irq_src_handler *handler)
-{
-    assert(irq >= 1);
-    assert(irq < Num_irqs);
-
-    info.printf("Bind IRQ source handler %p to irq %u.\n", handler, irq);
-
-    if (handler && _sources[irq])
-      L4Re::throw_error(-L4_EEXIST, "IRQ already has IRQ source handler.");
-
-    _sources[irq] = handler;
-}
-
-Irq_src_handler *Plic::get_irq_src_handler(unsigned irq) const
-{
-  return _sources[irq];
-}
-
-int Plic::dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const
-{
-  if (propsz < 1)
-      return -L4_ERANGE;
-
-    int irq = fdt32_to_cpu(prop[0]);
-
-    if (read)
-      *read = 1;
-
-    return irq;
-}
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    auto irq_cells = node.get_prop("#interrupt-cells", nullptr);
-    if (!irq_cells || fdt32_to_cpu(*irq_cells) != 1)
-      L4Re::throw_error(-L4_EINVAL, "Missing or invalid interrupt-cells property.");
-
-    int size_interrupts;
-    if (!node.get_prop("interrupts-extended", &size_interrupts))
-      L4Re::throw_error(-L4_EINVAL, "Missing interrupts-extended property.");
-
-    auto plic = Vdev::make_device(node, size_interrupts / 2);
-    devs->vmm()->register_mmio_device(plic, Vmm::Region_type::Virtual, node);
-    devs->vmm()->set_plic(plic);
-    return plic;
-  }
-};
-
-static F f;
-static Vdev::Device_type t = {"riscv,plic0", nullptr, &f};
-
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.h
deleted file mode 100644
index b79a9d90..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/plic.h
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "cpu_dev_array.h"
-#include "irq.h"
-#include "mmio_device.h"
-#include "vcpu_ic.h"
-
-namespace Gic {
-
-/**
- * The platform-level interrupt controller (PLIC) distributes external
- * interrupts asserted by peripheral devices to the CPUs in the system.
- *
- * This class emulates a virtual PLIC for the guest that supports all the
- * features mandated by the RISC-V specification, such as claiming and
- * acknowledging interrupts, prioritizing interrupt sources or disabling
- * certain interrupts on certain vCPUs. The virtual PLIC toggles the external
- * interrupt of a vCPU via the corresponding Vcpu_ic, thereby signaling that
- * external interrupts are pending in the PLIC.
- */
-class Plic
-: public Vmm::Mmio_device_t,
-  public Ic
-{
-public:
-  enum Config
-  {
-    /// Configures the maximum number of interrupts the PLIC implements.
-    Num_irqs = 32,
-  };
-  static_assert(Num_irqs % 32 == 0, "Number of IRQs must be a multiple of 32.");
-
-  explicit Plic(Vdev::Dt_node const &node, unsigned num_dt_interrupt_targets);
-
-  /**
-   * Setup PLIC state for the given vCPU.
-   */
-  void setup_target(Vmm::Vcpu_ptr vcpu, cxx::Ref_ptr vcpu_ic);
-
-  /**
-   * Read memory-mapped register.
-   *
-   * \param reg     Register offset.
-   * \param size    Access size.
-   * \param cpu_id  The ID of the vCPU making the read.
-   *
-   * \return  Value read from the register.
-   */
-  l4_umword_t read(unsigned reg, char size, unsigned cpu_id);
-
-  /**
-   * Write memory-mapped register.
-   *
-   * \param reg     Register offset.
-   * \param size    Access size.
-   * \param value   Value to write.
-   * \param cpu_id  The ID of the vCPU making the write.
-   */
-  void write(unsigned reg, char size, l4_umword_t value, unsigned cpu_id);
-
-  // The following functions implement the Ic interface.
-  void set(unsigned irq) override;
-  void clear(unsigned irq) override;
-  void bind_irq_src_handler(unsigned irq, Irq_src_handler *handler) override;
-  Irq_src_handler *get_irq_src_handler(unsigned irq) const override;
-  int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const override;
-
-  char const *dev_name() const override { return "Plic"; }
-
-private:
-  /**
-   * Thread-safe gateway for an interrupt source connected to the PLIC. The
-   * gateway manages the state changes that an interrupt may undergo.
-   *
-   * The gateway ensures that an interrupt can only be triggered again
-   * when the previous interrupt has been completed. Furthermore, it ensures
-   * that once an interrupt has been forwarded, it can no longer be retracted.
-   */
-  class Irq_gateway
-  {
-  public:
-    /**
-     * Set interrupt as pending.
-     *
-     * \return True if interrupt was not already in pending or claimed state.
-     */
-    bool set()
-    {
-      l4_uint8_t prev = _state.fetch_or(State_pending);
-      return !(prev & (State_pending | State_claimed));
-    };
-
-    /**
-     * Claim interrupt.
-     *
-     * \return True if interrupt was successfully claimed.
-     */
-    bool claim()
-    {
-      l4_uint8_t expected = State_pending;
-      return _state.compare_exchange_strong(expected, State_claimed);
-    }
-
-    /**
-     * Complete interrupt.
-     *
-     * \return True if interrupt is again pending.
-     */
-    bool complete()
-    {
-      l4_uint8_t prev = _state.fetch_and(~State_claimed);
-      return prev & State_pending;
-    };
-
-  private:
-    /**
-     * Possible state changes:
-     *
-     * NONE            -- set()      -> Pending
-     * Pending         -- claim()    -> Claimed
-     * Claimed         -- set()      -> Claimed_Pending
-     * Claimed         -- complete() -> NONE
-     * Claimed_Pending -- complete() -> Pending
-     */
-    enum : l4_uint8_t
-    {
-      // Pending state of interrupt.
-      State_pending     = 1 << 0,
-      // Pending interrupt was claimed by CPU and is currently handled.
-      State_claimed     = 1 << 1,
-    };
-
-    std::atomic _state = 0;
-  };
-
-  /**
-   * Bitmap sized to provide a bit for each interrupt implemented by the PLIC.
-   */
-  class Per_irq_bitmap : public cxx::Bitmap_base
-  {
-  public:
-    Per_irq_bitmap() throw() : Bitmap_base(_words) {}
-
-    static unsigned words()
-    {
-      return Bitmap_base::words(Num_irqs);
-    }
-
-    static constexpr unsigned Word32_size = sizeof(l4_uint32_t);
-
-    static_assert(   sizeof(Bitmap_base::word_type) == Word32_size
-                  || sizeof(Bitmap_base::word_type) == (Word32_size * 2));
-
-    void set_word32(unsigned index, l4_uint32_t word)
-    {
-      if constexpr (sizeof(Bitmap_base::word_type) == Word32_size)
-        _words[index] = word;
-
-      unsigned word32_shift = (index & 1) ? Word32_size : 0;
-      auto mask32 = ~(Bitmap_base::word_type{0xffff'ffff} << word32_shift);
-      _words[index / 2] = (_words[index / 2] & mask32) | (word << word32_shift);
-    }
-
-    l4_uint32_t word32(unsigned index) const
-    {
-      if constexpr (sizeof(Bitmap_base::word_type) == Word32_size)
-        return _words[index];
-
-      unsigned word32_shift = (index & 1) ? Word32_size : 0;
-      return _words[index / 2] >> word32_shift;
-    }
-
-    /**
-     * Optional return value to control callback-driven loops.
-     */
-    enum Cb
-    {
-      Break,
-      Continue,
-    };
-
-    template
-    inline static Cb invoke_cb(F f, Args... args)
-    {
-      if constexpr (std::is_void_v>)
-        {
-          f(args...);
-          return Continue;
-        }
-      else
-        return f(args...);
-    }
-
-    /**
-     * Iterate over all set bits in the intersection of the given bitmaps.
-     *
-     * \param f        Callback to invoke for each set bit.
-     * \param bitmaps  The bitmaps to work on.
-     */
-    template
-    inline static void for_set_bits(F f, Bitmaps const &... bitmaps)
-    {
-      for (unsigned word_index = 0; word_index < words(); word_index++)
-        {
-          l4_uint32_t cur_word = (bitmaps._words[word_index] & ...);
-          if (!cur_word)
-            // Skip empty words.
-            continue;
-
-          for (unsigned i = 0; i < W_bits; i++)
-            {
-              l4_uint32_t bit = cur_word & (1UL << i);
-              if (bit && invoke_cb(f, word_index * W_bits + i) == Break)
-                // Stop iteration of set bits
-                return;
-            }
-        }
-    }
-
-  private:
-    Bitmap_base::word_type _words[Bitmap_base::Word::Size] = {};
-  };
-
-  /**
-   * This class holds per vCPU PLIC state and implements signaling, claiming
-   * and completion of interrupts.
-   *
-   * The flow of an interrupt is as follows:
-   * 1. Interrupt is marked pending via `set()`.
-   * 2. Pending interrupt is claimed by a vCPU via `claim()`.
-   * 3. vCPU handles the interrupt and once finished completes it via `complete()`.
-   *    Note: In between steps 2 and 3, the interrupt might have been `set()`
-   *          again, in which case `complete()` immediately transitions it into
-   *          Pending state again.
-   *
-   * \note For calling any of the functions on this class, except `vcpu()`, the
-   *       PLIC lock must be held.
-   */
-  class Plic_target
-  {
-  public:
-    Plic_target(Plic *plic, Vmm::Vcpu_ptr vcpu, cxx::Ref_ptr vcpu_ic);
-
-    Vmm::Vcpu_ptr vcpu() const
-    {
-      return _vcpu;
-    }
-
-    /**
-     * Write register in enable register array.
-     *
-     * Also reevaluates the external interrupt pending bit of the vCPU this
-     * Plic_target belongs to.
-     *
-     * \param offset        Offset of the register, must be `<= Num_irqs / 32`.
-     * \param value         The value to write to the register.
-     * \param current_vcpu  The current vCPU.
-     */
-    void enable(l4_uint32_t offset, l4_uint32_t value, Vmm::Vcpu_ptr current_vcpu);
-
-    /**
-     * Read register from enable register array.
-     *
-     * \param offset Offset of the register, must be `<= Num_irqs / 32`.
-     *
-     * \return  Register value.
-     */
-    l4_uint32_t enabled(l4_uint32_t offset) const;
-
-    /**
-     * Claim the pending interrupt with highest priority if any.
-     *
-     * On success, also reevaluates the external interrupt pending bit of the
-     * vCPU this Plic_target belongs to.
-     *
-     * \param current_vcpu  The current vCPU.
-     *
-     * \return  The claimed interrupt, 0 if non was claimed.
-     */
-    l4_uint32_t claim(Vmm::Vcpu_ptr current_vcpu);
-
-    /**
-     * Complete handling of interrupt.
-     *
-     * \param irq           The interrupt to complete, must be `< Num_irqs`.
-     * \param current_vcpu  The current vCPU.
-     */
-    void complete(l4_uint32_t irq, Vmm::Vcpu_ptr current_vcpu);
-
-    /**
-     * Read the priority threshold.
-     *
-     * \return Priority threshold.
-     */
-    l4_uint32_t threshold() const;
-
-    /**
-     * Write the priority threshold.
-     *
-     * Also reevaluates the external interrupt pending bit of the vCPU this
-     * Plic_target belongs to.
-     *
-     * \param threshold     The priority threshold to write.
-     * \param current_vcpu  The current vCPU.
-     */
-    void threshold(l4_uint32_t threshold, Vmm::Vcpu_ptr current_vcpu);
-
-    /**
-     * Set the external interrupt pending bit of the vCPU this Plic_target
-     * belongs to.
-     *
-     * \param pending       The new state of the external interrupt.
-     * \param current_vcpu  The current vCPU.
-     */
-    void update_ext_int_pending(bool pending, Vmm::Vcpu_ptr current_vcpu);
-
-    /**
-     * Find the pending interrupt with highest priority.
-     *
-     * Interrupts that are not enabled for this PLIC target or whose priority is
-     * below its priority threshold are not considered.
-     *
-     * \param[out]  best_irq    The pending interrupt with highest priority.
-     * \param[out]  nr_pending  Number of interrupts pending for this target.
-     *
-     * \retval false  No pending interrupt with sufficient priority found.
-     * \retval true   Pending interrupt found.
-     */
-    bool find_best_irq(unsigned &best_irq, unsigned &nr_pending) const;
-
-    /**
-     * Check if this PLIC target has pending interrupts with sufficient priority.
-     */
-    bool pending_irq() const;
-
-    Plic *_plic;                    //< PLIC that this Plic_target is part of
-    Vmm::Vcpu_ptr _vcpu;            //< vCPU that this Plic_target belongs to
-    cxx::Ref_ptr _vcpu_ic; //< Interrupt controller of vCPU
-    Per_irq_bitmap _enable;         //< Per-IRQ enable state
-    l4_uint32_t _threshold;         //< Priority threshold
-  };
-
-  enum : unsigned
-  {
-    Priority_base     = 0x0,
-    Pending_base      = 0x1000,
-
-    Enable_base       = 0x2000,
-    Enable_per_hart   = 0x80,
-    Enable_mask       = 0x7f,
-
-    Context_base      = 0x200000,
-    Context_threshold = 0x0,
-    Context_claim     = 0x4,
-    Context_per_hart  = 0x1000,
-    Context_mask      = 0xfff,
-  };
-
-  Vmm::Vcpu_ptr get_vcpu(unsigned cpu_id);
-  bool check_access(unsigned reg, char size, char const *operation);
-  bool check_irq(unsigned irq, char const *operation);
-  bool check_irq_range(unsigned offset, char const *operation);
-  bool check_target(unsigned target_id);
-
-  Plic_target *get_target(unsigned target)
-  {
-    return _targets[target].get();
-  }
-
-  /**
-   * Claim the given interrupt, i.e. update its state accordingly.
-   */
-  bool claim_irq(unsigned irq);
-
-  /**
-   * Set the given interrupt as pending, i.e. update its state accordingly.
-   *
-   * Also updates the external interrupt pending bit of all targeted vCPUs.
-   *
-   * \param irq           The interrupt to set pending.
-   * \param current_vcpu  The current vCPU.
-   */
-  void set_irq(unsigned irq, Vmm::Vcpu_ptr current_vcpu);
-
-  // Only used for debugging purposes, to warn if less interrupt targets were
-  // referenced in the device tree than there are vCPUs.
-  unsigned _num_dt_interrupt_targets;
-  unsigned _num_targets_created = 0;
-
-  Irq_gateway _gateways[Num_irqs];                    //< Per-IRQ state machine
-  l4_uint32_t _priorities[Num_irqs] = {};             //< Per-IRQ priority
-  /// Per-IRQ pending flag, duplicates information stored in Irq_gateway, but
-  /// used as an optimization for querying and selecting pending IRQs.
-  Per_irq_bitmap _pending;
-  Irq_src_handler *_sources[Num_irqs] = {};           //< Per-IRQ source handler
-  std::vector> _targets; //< Per-vCPU PLIC state
-
-  std::mutex _lock;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_arch.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_arch.h
deleted file mode 100644
index cf12aaad..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_arch.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-
-namespace Riscv {
-
-enum : l4_umword_t {
-  Msb = static_cast(1) << (L4_MWORD_BITS - 1),
-};
-
-enum : l4_umword_t {
-  Int_user_software               =  0 | Msb,
-  Int_virtual_supervisor_software =  2 | Msb,
-  Int_supervisor_software         =  1 | Msb,
-  Int_user_timer                  =  4 | Msb,
-  Int_supervisor_timer            =  5 | Msb,
-  Int_virtual_supervisor_timer    =  6 | Msb,
-  Int_user_external               =  8 | Msb,
-  Int_supervisor_external         =  9 | Msb,
-  Int_virtual_supervisor_external = 10 | Msb,
-};
-
-enum : l4_umword_t
-{
-  Exc_inst_misaligned        = 0,
-  Exc_inst_access            = 1,
-  Exc_illegal_inst           = 2,
-  Exc_breakpoint             = 3,
-  Exc_load_acesss            = 5,
-  Exc_store_acesss           = 7,
-  Exc_ecall                  = 8,
-  Exc_hcall                  = 10,
-  Exc_inst_page_fault        = 12,
-  Exc_load_page_fault        = 13,
-  Exc_store_page_fault       = 15,
-  Exc_guest_inst_page_fault  = 20,
-  Exc_guest_load_page_fault  = 21,
-  Exc_virtual_inst           = 22,
-  Exc_guest_store_page_fault = 23,
-};
-
-enum : l4_umword_t
-{
-  L4_ipc_upcall       = 0x18,
-  L4_exregs_exception = 0x19,
-};
-
-enum : l4_umword_t
-{
-  Sstatus_sie  = 1 << 1,
-  Sstatus_spie = 1 << 5,
-  Sstatus_spp  = 1 << 8,
-};
-
-enum : l4_umword_t
-{
-  Hstatus_spvp  = 1 << 8,
-};
-
-enum : l4_umword_t
-{
-  Stvec_mode_direct   = 0,
-  Stvec_mode_vectored = 1,
-  Stvec_mode_mask     = 3,
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_instruction.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_instruction.h
deleted file mode 100644
index 47813cd8..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/riscv_instruction.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "mem_access.h"
-
-namespace Riscv {
-
-namespace Op {
-
-  enum
-  {
-    Lb  = 0x3,
-    Lbu = 0x4003,
-    Lh  = 0x1003,
-    Lhu = 0x5003,
-    Lw  = 0x2003,
-    Lwu = 0x6003,
-    Ld  = 0x3003,
-    Sb  = 0x23,
-    Sh  = 0x1023,
-    Sw  = 0x2023,
-    Sd  = 0x3023,
-  };
-
-  enum
-  {
-    Opcode_mask = 0x707f,
-  };
-
-  enum
-  {
-    C_lw   = 0x4000,
-    C_ld   = 0x6000,
-    C_lwsp = 0x4002,
-    C_ldsp = 0x6002,
-    C_sw   = 0xc000,
-    C_sd   = 0xe000,
-    C_swsp = 0xc002,
-    C_sdsp = 0xe002,
-  };
-
-  enum
-  {
-    C_opcode_mask = 0xe003,
-  };
-
-}
-
-namespace Inst {
-
-  enum
-  {
-    Wfi = 0x10500073,
-  };
-
-}
-
-namespace Reg {
-
-  enum
-  {
-    Sp = 0x02,
-  };
-
-}
-
-
-static bool is_compressed_inst(l4_uint32_t inst)
-{
-  // Instructions wider than 16 bits have the two least-significant bits set.
-  return (inst & 0b11) != 0b11;
-}
-
-// Holds instructions transformed according to RISC-V privileged spec.
-struct Instruction
-{
-  l4_uint32_t inst;
-  // Generic fields
-  CXX_BITFIELD_MEMBER(7, 11, rd, inst);
-  CXX_BITFIELD_MEMBER(15, 19, rs1, inst);
-  CXX_BITFIELD_MEMBER(20, 24, rs2, inst);
-
-  Instruction(l4_uint32_t inst) : inst(inst) {}
-
-  l4_uint32_t opcode()
-  {
-    // Transformed instructions are uncompressed instructions,
-    // but use bit 1 to indicate that the raw instruction was compressed.
-    return (inst | 0b10) & Op::Opcode_mask;
-  }
-
-  bool is_load()
-  {
-    switch(opcode())
-    {
-      case Op::Lb:
-      case Op::Lbu:
-      case Op::Lh:
-      case Op::Lhu:
-      case Op::Lw:
-      case Op::Lwu:
-      case Op::Ld:
-        return true;
-      default:
-        return false;
-    }
-  }
-
-  bool is_unsigned_load()
-  {
-    switch(opcode())
-    {
-      case Op::Lbu:
-      case Op::Lhu:
-      case Op::Lwu:
-        return true;
-      default:
-        return false;
-    }
-  }
-
-  bool is_store()
-  {
-    switch(opcode())
-    {
-      case Op::Sb:
-      case Op::Sh:
-      case Op::Sw:
-      case Op::Sd:
-        return true;
-      default:
-        return false;
-    }
-  }
-
-  Vmm::Mem_access::Width load_store_width()
-  {
-    switch(opcode())
-    {
-      case Op::Lb:
-      case Op::Lbu:
-      case Op::Sb:
-        return Vmm::Mem_access::Wd8;
-      case Op::Lh:
-      case Op::Lhu:
-      case Op::Sh:
-        return Vmm::Mem_access::Wd16;
-      case Op::Lw:
-      case Op::Lwu:
-      case Op::Sw:
-        return Vmm::Mem_access::Wd32;
-      case Op::Ld:
-      case Op::Sd:
-        return Vmm::Mem_access::Wd64;
-      default:
-        return Vmm::Mem_access::Wd32;
-    }
-  }
-
-  bool is_wfi()
-  {
-    return inst == Inst::Wfi;
-  }
-
-  bool is_compressed()
-  {
-    return is_compressed_inst(inst);
-  }
-
-  l4_uint32_t inst_size()
-  {
-    return is_compressed() ? 2 : 4;
-  }
-};
-
-// Compressed instruction.
-struct C_instruction
-{
-  l4_uint32_t inst;
-
-  // CL+CS format
-  CXX_BITFIELD_MEMBER_RO(7, 9, rs1_c, inst);
-  // CL format
-  CXX_BITFIELD_MEMBER_RO(2, 4, rd_c, inst);
-  // CS format
-  CXX_BITFIELD_MEMBER_RO(2, 4, rs2_c, inst);
-  // CI format
-  CXX_BITFIELD_MEMBER_RO(7, 11, rd, inst);
-  // CSS format
-  CXX_BITFIELD_MEMBER_RO(2, 6, rs2, inst);
-
-  C_instruction(l4_uint32_t inst) : inst(inst) {}
-
-  Instruction transformed()
-  {
-    Instruction tinst(0);
-    switch (inst & Op::C_opcode_mask)
-    {
-      case Op::C_lw:
-        tinst = Op::Lw;
-        tinst.rs1() = map_reg(rs1_c());
-        tinst.rd() = map_reg(rd_c());
-        break;
-      case Op::C_ld:
-        tinst = Op::Ld;
-        tinst.rs1() = map_reg(rs1_c());
-        tinst.rd() = map_reg(rd_c());
-        break;
-      case Op::C_lwsp:
-        // C.LWSP is only valid when rd=x0
-        if (rd() != 0)
-          {
-            tinst = Op::Lw;
-            tinst.rs1() = Reg::Sp;
-            tinst.rd() = rd();
-          }
-        break;
-      case Op::C_ldsp:
-        // C.LDSP is only valid when rd=x0
-        if (rd() != 0)
-          {
-            tinst = Op::Ld;
-            tinst.rs1() = Reg::Sp;
-            tinst.rd() = rd();
-          }
-        break;
-      case Op::C_sw:
-        tinst = Op::Sw;
-        tinst.rs1() = map_reg(rs1_c());
-        tinst.rs2() = map_reg(rs2_c());
-        break;
-      case Op::C_sd:
-        tinst = Op::Sd;
-        tinst.rs1() = map_reg(rs1_c());
-        tinst.rs2() = map_reg(rs2_c());
-        break;
-      case Op::C_swsp:
-        tinst = Op::Sw;
-        tinst.rs1() = Reg::Sp;
-        tinst.rs2() = rs2();
-        break;
-      case Op::C_sdsp:
-        tinst = Op::Sd;
-        tinst.rs1() = Reg::Sp;
-        tinst.rs2() = rs2();
-        break;
-    }
-
-    // Replace bit 1 with a 0.
-    return tinst.inst & ~static_cast(0b10);
-  }
-
-  static l4_uint32_t map_reg(l4_uint32_t reg_c)
-  {
-    assert(reg_c <= 0b111);
-    return reg_c + 8;
-  }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.cc
deleted file mode 100644
index fcd059ce..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.cc
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "debug.h"
-#include "guest.h"
-#include "sbi.h"
-
-static Dbg warn(Dbg::Core, Dbg::Warn, "sbi");
-static Dbg info(Dbg::Core, Dbg::Info, "sbi");
-static Dbg trace(Dbg::Core, Dbg::Trace, "sbi");
-
-namespace Vmm {
-
-namespace {
-
-enum : l4_int32_t
-{
-  Sbi_ext_legacy_set_timer              = 0,
-  Sbi_ext_legacy_console_putchar        = 1,
-  Sbi_ext_legacy_console_getchar        = 2,
-  Sbi_ext_legacy_clear_ipi              = 3,
-  Sbi_ext_legacy_send_ipi               = 4,
-  Sbi_ext_legacy_remote_fence_i         = 5,
-  Sbi_ext_legacy_remote_sfence_vma      = 6,
-  Sbi_ext_legacy_remote_sfence_vma_asid = 7,
-  Sbi_ext_legacy_shutdown               = 8,
-};
-
-enum : l4_int32_t
-{
-  Sbi_ext_base    = 0x10,
-  Sbi_ext_time    = 0x54494D45,
-  Sbi_ext_ipi     = 0x735049,
-  Sbi_ext_rfnc    = 0x52464E43,
-  Sbi_ext_hsm     = 0x48534D,
-  Sbi_ext_dbcn    = 0x4442434E,
-};
-
-}
-
-// The singleton instance of the VMM.
-static cxx::Static_container sbi;
-
-Sbi *
-Sbi::create_instance(Guest *guest)
-{
-  sbi.construct(guest);
-  return sbi;
-}
-
-Sbi::Sbi(Guest *guest)
-: _guest(guest)
-{
-  register_ext(Sbi_ext_legacy_set_timer, Sbi_ext_legacy_shutdown,
-               Vdev::make_device());
-  register_ext(Sbi_ext_base, Vdev::make_device());
-  register_ext(Sbi_ext_time, Vdev::make_device());
-  register_ext(Sbi_ext_ipi, Vdev::make_device());
-  register_ext(Sbi_ext_rfnc, Vdev::make_device());
-  register_ext(Sbi_ext_hsm, Vdev::make_device());
-  register_ext(Sbi_ext_dbcn, Vdev::make_device());
-}
-
-void
-Sbi::register_ext(l4_int32_t ext_id_start, l4_int32_t ext_id_end,
-                  cxx::Ref_ptr handler)
-{
-  if (ext_id_start > ext_id_end)
-    {
-      Err().printf("Invalid extension ID range [0x%x, 0x%x].\n",
-                     ext_id_start, ext_id_end);
-      L4Re::throw_error(-L4_EINVAL, "Register SBI extension");
-    }
-
-  for (auto const &ext : _extensions)
-    {
-      if (ext_id_start <= ext.ext_id_end && ext_id_end >= ext.ext_id_start)
-      {
-        Err().printf("Extension ID range [0x%x, 0x%x] overlaps with [0x%x, 0x%x].\n",
-                     ext_id_start, ext_id_end, ext.ext_id_start, ext.ext_id_end);
-        L4Re::throw_error(-L4_EINVAL, "Register SBI extension");
-      }
-    }
-
-  _extensions.push_back({ext_id_start, ext_id_end, handler});
-}
-
-bool
-Sbi::handle(Vcpu_ptr vcpu)
-{
-  l4_int32_t sbi_ext = vcpu->r.a7;
-  l4_int32_t sbi_func = vcpu->r.a6;
-  Sbi_ext *ext = find_ext(sbi_ext);
-  if (ext)
-    {
-      Sbi_ret ret = ext->handle(sbi_ext, sbi_func, vcpu);
-      if(ret.error == Sbi_err_v1_spec)
-        {
-          // Return value is passed in a0
-          vcpu->r.a0 = ret.value;
-          return true;
-        }
-      else if(ret.error != Sbi_err_unsupported_func)
-        {
-          // Sbi_ret is passed in a0/a1
-          vcpu->r.a0 = ret.error;
-          vcpu->r.a1 = ret.value;
-          return true;
-        }
-    }
-
-  warn.printf("Unsupported SBI call: ext=0x%x, func=0x%x, ip=0x%lx -> %s\n",
-              sbi_ext, sbi_func, vcpu->r.ip,
-              ext ? "function unknown" : "extension unknown");
-
-  return false;
-}
-
-Sbi_ext *
-Sbi::find_ext(l4_int32_t ext_id) const
-{
-  for (auto const &ext : _extensions)
-    {
-      if (ext_id >= ext.ext_id_start && ext_id <= ext.ext_id_end)
-        return ext.handler.get();
-    }
-
-  return nullptr;
-}
-
-Sbi_ret Sbi_base::get_spec_version()
-{
-  // SBI specification v2.0
-  return sbi_value(2 << 24 | 0);
-}
-
-Sbi_ret Sbi_base::get_impl_id()
-{
-  // "uvmm" = 0x75766d6d
-  return sbi_value(0x75766d6d);
-}
-
-Sbi_ret Sbi_base::get_impl_version()
-{
-  return sbi_value(1);
-}
-
-Sbi_ret Sbi_base::probe_extension(long ext_id)
-{
-  bool present = sbi->find_ext(ext_id) != nullptr;
-  return sbi_value(present);
-}
-
-Sbi_ret Sbi_base::get_mvendorid()
-{
-  return sbi_value(0);
-}
-
-Sbi_ret Sbi_base::get_marchid()
-{
-  return sbi_value(0);
-}
-
-Sbi_ret Sbi_base::get_mimpid()
-{
-  return sbi_value(0);
-}
-
-Sbi_ret Sbi_base::handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu)
-{
-  switch(func_id)
-    {
-      case Sbi_fid_get_sbi_spec_version:
-        return call(vcpu, &Sbi_base::get_spec_version);
-      case Sbi_fid_get_sbi_impl_id:
-        return call(vcpu, &Sbi_base::get_impl_id);
-      case Sbi_fid_get_sbi_impl_version:
-        return call(vcpu, &Sbi_base::get_impl_version);
-      case Sbi_fid_probe_extension:
-        return call(vcpu, &Sbi_base::probe_extension);
-      case Sbi_fid_get_mvendorid:
-        return call(vcpu, &Sbi_base::get_mvendorid);
-      case Sbi_fid_get_marchid:
-        return call(vcpu, &Sbi_base::get_marchid);
-      case Sbi_fid_get_mimpid:
-        return call(vcpu, &Sbi_base::get_mimpid);
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-}
-
-Sbi_ret Sbi_time::set_timer(Vcpu_ptr vcpu, l4_uint64_t stime_value)
-{
-  if (sbi->guest()->has_vstimecmp())
-    {
-      vcpu.vm_state()->vstimecmp = stime_value;
-    }
-  else
-    {
-      // Clear pending timer interrupt
-      sbi->guest()->get_vcpu_ic(vcpu)->clear_timer();
-
-      // Set next timer interrup
-      sbi->guest()->get_timer(vcpu)->set_next_event(stime_value);
-    }
-
-  return sbi_void();
-}
-
-Sbi_ret Sbi_time::handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu)
-{
-  switch(func_id)
-    {
-      case Sbi_fid_set_timer:
-        return call(vcpu, &Sbi_time::set_timer);
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-}
-
-Sbi_ret Sbi_ipi::send_ipi(Vcpu_ptr vcpu, l4_umword_t hart_mask,
-                          l4_umword_t hart_mask_base)
-{
-  if (hart_mask_base == -1UL)
-    {
-      trace.printf("Sending IPI from %u to all vCPUs\n", vcpu.get_vcpu_id());
-      for (auto const &target : *sbi->guest()->cpus().get())
-        {
-          sbi->guest()->get_vcpu_ic(target->vcpu())->notify_ipi(vcpu);
-        }
-    }
-  else
-    {
-      for (unsigned i = 0; i < sizeof(hart_mask) * 8; i++)
-        {
-          if (hart_mask & (1UL << i))
-            {
-              unsigned hartid = hart_mask_base + i;
-              Cpu_dev *target = sbi->guest()->lookup_cpu(hartid);
-              if (!target)
-                return sbi_error(Sbi_err_invalid_param);
-
-              trace.printf("Sending IPI from %u to vCPU %u\n",
-                           vcpu.get_vcpu_id(), hartid);
-              sbi->guest()->get_vcpu_ic(target->vcpu())->notify_ipi(vcpu);
-            }
-        }
-    }
-
-  return sbi_void();
-}
-
-Sbi_ret Sbi_ipi::handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu)
-{
-  switch(func_id)
-    {
-      case Sbi_fid_send_ipi:
-        return call(vcpu, &Sbi_ipi::send_ipi);
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-}
-
-Sbi_ret Sbi_rfnc::remote_fence_i(Vcpu_ptr vcpu,
-  l4_umword_t hart_mask, l4_umword_t hart_mask_base)
-{
-  return remote_fence(vcpu, L4_vm_rfnc_fence_i, hart_mask, hart_mask_base);
-}
-
-Sbi_ret Sbi_rfnc::remote_sfence_vma(Vcpu_ptr vcpu,
-  l4_umword_t hart_mask, l4_umword_t hart_mask_base,
-  l4_umword_t start_addr, l4_umword_t size)
-{
-  return remote_fence(vcpu, L4_vm_rfnc_fence_i, hart_mask, hart_mask_base,
-                      start_addr, size);
-}
-
-Sbi_ret Sbi_rfnc::remote_sfence_vma_asid(Vcpu_ptr vcpu,
-  l4_umword_t hart_mask, l4_umword_t hart_mask_base,
-  l4_umword_t start_addr, l4_umword_t size, l4_umword_t asid)
-{
-  return remote_fence(vcpu, L4_vm_rfnc_fence_i, hart_mask, hart_mask_base,
-                      start_addr, size, asid);
-}
-
-Sbi_ret Sbi_rfnc::remote_fence(
-    Vcpu_ptr vcpu, L4_vm_rfnc remote_fence,
-    l4_umword_t hart_mask, l4_umword_t hart_mask_base,
-    l4_umword_t start_addr, l4_umword_t size, l4_umword_t asid)
-{
-  auto vm_state = vcpu.vm_state();
-
-  // Translate vCPU mask into physical cpu mask
-  l4_umword_t host_hart_mask = 0;
-  if (hart_mask_base == -1UL)
-    {
-      for (auto const &target : *sbi->guest()->cpus().get())
-        {
-          host_hart_mask |= 1UL << target->get_phys_cpu_id();
-        }
-    }
-  else
-    {
-      for (unsigned i = 0; i < sizeof(hart_mask) * 8; i++)
-        {
-          if (hart_mask & (1UL << i))
-            {
-              unsigned hartid = hart_mask_base + i;
-              Cpu_dev *target = sbi->guest()->lookup_cpu(hartid);
-              if (!target)
-                return sbi_error(Sbi_err_invalid_param);
-
-              host_hart_mask |= 1UL << target->get_phys_cpu_id();
-            }
-        }
-    }
-
-  trace.printf("Sending remote fence %u to harts 0x%lx (0x%lx) from %u\n",
-             remote_fence, host_hart_mask, hart_mask, vcpu.get_vcpu_id());
-  vm_state->remote_fence = remote_fence;
-  vm_state->remote_fence_hart_mask = host_hart_mask;
-  vm_state->remote_fence_start_addr = start_addr;
-  vm_state->remote_fence_size = size;
-  vm_state->remote_fence_asid = asid;
-
-  return sbi_void();
-}
-
-Sbi_ret Sbi_rfnc::handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu)
-{
-  switch(func_id)
-    {
-      case Sbi_fid_remote_fence_i:
-        return call(vcpu, &Sbi_rfnc::remote_fence_i);
-      case Sbi_fid_remote_sfence_vma:
-        return call(vcpu, &Sbi_rfnc::remote_sfence_vma);
-      case Sbi_fid_remote_sfence_vma_asid:
-        return call(vcpu, &Sbi_rfnc::remote_sfence_vma_asid);
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-}
-
-Sbi_ret Sbi_hsm::hart_start(l4_umword_t hartid, l4_umword_t start_addr,
-                            l4_umword_t priv)
-{
-  Cpu_dev *hart = sbi->guest()->lookup_cpu(hartid);
-  if (!hart)
-    return sbi_error(Sbi_err_invalid_param);
-
-  if (!hart->online() && hart->mark_on_pending())
-    {
-      Vcpu_ptr vcpu = hart->vcpu();
-      vcpu->r.ip = start_addr;
-      vcpu->r.a0 = vcpu.get_vcpu_id();
-      vcpu->r.a1 = priv;
-
-      // Prepare_vcpu_startup
-      if (hart->start_vcpu())
-        return sbi_error(Sbi_success);
-      else
-        return sbi_error(Sbi_err_failed);
-    }
-  else
-    return sbi_error(Sbi_err_already_available);
-}
-
-Sbi_ret Sbi_hsm::hart_stop(Vcpu_ptr vcpu)
-{
-  sbi->guest()->lookup_cpu(vcpu.get_vcpu_id())->stop_vcpu();
-  __builtin_unreachable();
-}
-
-Sbi_ret Sbi_hsm::hart_status(l4_umword_t hartid)
-{
-  Cpu_dev *hart = sbi->guest()->lookup_cpu(hartid);
-  if (!hart)
-    return sbi_error(Sbi_err_invalid_param);
-
-  switch (hart->online_state())
-    {
-      case Cpu_dev::Cpu_state::Off:
-        return sbi_value(Hart_stopped);
-      case Cpu_dev::Cpu_state::On_pending:
-      case Cpu_dev::Cpu_state::On_prepared:
-        return sbi_value(Hart_start_request_pending);
-      case Cpu_dev::Cpu_state::On:
-        return sbi_value(Hart_started);
-      case Cpu_dev::Cpu_state::Suspended:
-        return sbi_value(Hart_suspended);
-    }
-
-  __builtin_unreachable();
-}
-
-Sbi_ret Sbi_hsm::hart_suspend(Vcpu_ptr vcpu, l4_uint32_t suspend_type,
-                              l4_umword_t, l4_umword_t)
-{
-  if (suspend_type == 0) // Default retentive suspend
-    {
-      auto guest = sbi.get()->guest();
-      Cpu_dev *hart = guest->lookup_cpu(vcpu.get_vcpu_id());
-      hart->mark_suspended();
-      guest->wfi(vcpu);
-      hart->mark_on();
-      return sbi_void();
-    }
-
-  if (suspend_type == 0x80000000) // Default non-retentive suspend
-    return sbi_error(Sbi_err_not_supported);
-
-  return sbi_error(Sbi_err_invalid_param);
-}
-
-Sbi_ret Sbi_hsm::handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu)
-{
-  switch(func_id)
-    {
-      case Sbi_fid_hart_start:
-        return call(vcpu, &Sbi_hsm::hart_start);
-      case Sbi_fid_hart_stop:
-        return call(vcpu, &Sbi_hsm::hart_stop);
-      case Sbi_fid_hart_get_status:
-        return call(vcpu, &Sbi_hsm::hart_status);
-      case Sbi_fid_hart_suspend:
-        return call(vcpu, &Sbi_hsm::hart_suspend);
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-}
-
-Sbi_dbcn::Sbi_dbcn()
-: _con(L4Re::Env::env()->log())
-{
-}
-
-Sbi_ret
-Sbi_dbcn::debug_console_write(l4_umword_t num_bytes, l4_umword_t base_addr_lo,
-                              l4_umword_t base_addr_hi)
-{
-  // Although in theory the RISC-V hypervisor extension allows to provide up to
-  // 34-bit of guest physical memory, we never provide more than 32-bit.
-  if (base_addr_hi != 0)
-    return sbi_error(Sbi_err_invalid_param);
-
-  auto phys_region = Region::ss(Vmm::Guest_addr(base_addr_lo), num_bytes,
-                                Region_type::Ram);
-  char const *data;
-  try
-    {
-      data = sbi->guest()->ram()->guest2host(phys_region);
-    }
-  catch (L4::Runtime_error &)
-    {
-      warn.printf("dbcn: Invalid write buffer address.\n");
-      return sbi_error(Sbi_err_invalid_param);
-    }
-
-  // No need for cache maintenance before reading the data, because handling of
-  // an SBI call always happens on the same vCPU that made the call.
-
-  l4_umword_t num_written = 0;
-  while (num_written < num_bytes)
-    {
-      unsigned write_size = cxx::min(num_bytes - num_written,
-                                               L4_VCON_WRITE_SIZE);
-      long res = _con->write(data + num_written, write_size);
-      if (res < 0)
-        return sbi_error(Sbi_err_failed);
-
-      num_written += res;
-      if (res < static_cast(write_size))
-        // The SBI call is non-blocking, if the console is saturated only do a
-        // partial write.
-        break;
-    }
-
-  return sbi_value(num_written);
-}
-
-Sbi_ret
-Sbi_dbcn::debug_console_read(l4_umword_t num_bytes, l4_umword_t base_addr_lo,
-                             l4_umword_t base_addr_hi)
-{
-  // Although in theory the RISC-V hypervisor extension allows to provide up to
-  // 34-bit of guest physical memory, we never provide more than 32-bit.
-  if (base_addr_hi != 0)
-    return sbi_error(Sbi_err_invalid_param);
-
-  auto phys_region = Region::ss(Vmm::Guest_addr(base_addr_lo), num_bytes,
-                                Region_type::Ram);
-  char *data;
-  try
-    {
-      // Note: We assume RAM is always writable.
-      data = sbi->guest()->ram()->guest2host(phys_region);
-    }
-  catch (L4::Runtime_error &)
-    {
-      warn.printf("dbcn: Invalid read buffer address.\n");
-      return sbi_error(Sbi_err_invalid_param);
-    }
-
-  l4_umword_t num_read = 0;
-  while (num_read < num_bytes)
-    {
-      unsigned read_size = cxx::min(num_bytes - num_read,
-                                              L4_VCON_READ_SIZE);
-      long res = _con->read(data + num_read, read_size);
-      if (res < 0)
-        return sbi_error(Sbi_err_failed);
-
-      num_read += res;
-      if (res < static_cast(read_size))
-        // The SBI call is non-blocking, if the console currently has no more
-        // data to read only do a partial read.
-        break;
-    }
-
-  // No need for cache maintenance after writing the data, because handling of
-  // an SBI call always happens on the same vCPU that made the call.
-
-  return sbi_value(num_read);
-}
-
-Sbi_ret Sbi_dbcn::debug_console_write_byte(l4_uint8_t byte)
-{
-  char const c = byte;
-  long res = _con->write(&c, 1);
-  if (res < 0)
-    return sbi_error(Sbi_err_failed);
-
-  // Char was written successfully.
-  return sbi_void();
-}
-
-Sbi_ret Sbi_dbcn::handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu)
-{
-  switch(func_id)
-    {
-      case Sbi_fid_debug_console_write:
-        return call(vcpu, &Sbi_dbcn::debug_console_write);
-      case Sbi_fid_debug_console_read:
-        return call(vcpu, &Sbi_dbcn::debug_console_read);
-      case Sbi_fid_debug_console_write_byte:
-        return call(vcpu, &Sbi_dbcn::debug_console_write_byte);
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-}
-
-Sbi_legacy::Sbi_legacy()
-: _con(L4Re::Env::env()->log())
-{
-}
-
-Sbi_ret Sbi_legacy::console_putchar(int ch)
-{
-  char const c = ch;
-  _con->write(&c, 1);
-
-  return sbi_void();
-}
-
-Sbi_ret Sbi_legacy::console_getchar()
-{
-  char buf;
-  int err = _con->read(&buf, 1);
-  return sbi_value(err < 0 ? -1 : buf);
-}
-
-Sbi_ret Sbi_legacy::shutdown()
-{
-  info.printf("Received request to shutdown the guest.\n");
-  sbi->guest()->shutdown(Guest::Shutdown);
-  return sbi_void();
-}
-
-Sbi_ret Sbi_legacy::handle(l4_int32_t ext_id, l4_int32_t, Vcpu_ptr vcpu)
-{
-  Sbi_ret ret;
-  switch(ext_id)
-    {
-      case Sbi_ext_legacy_console_putchar:
-        ret = call(vcpu, &Sbi_legacy::console_putchar);
-        break;
-      case Sbi_ext_legacy_console_getchar:
-        ret = call(vcpu, &Sbi_legacy::console_getchar);
-        break;
-      case Sbi_ext_legacy_shutdown:
-        ret = call(vcpu, &Sbi_legacy::shutdown);
-        break;
-      default:
-        return sbi_error(Sbi_err_unsupported_func);
-    }
-  return {Sbi_err_v1_spec, ret.value};
-}
-
-} //namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.h
deleted file mode 100644
index 64bc4c58..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/sbi.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "cpu_dev.h"
-
-namespace Vmm {
-
-struct Sbi_ret
-{
-  long error;
-  long value;
-};
-
-enum Sbi_error : long
-{
-  Sbi_success               =  0,
-  Sbi_err_failed            = -1,
-  Sbi_err_not_supported     = -2,
-  Sbi_err_invalid_param     = -3,
-  Sbi_err_denied            = -4,
-  Sbi_err_invalid_address   = -5,
-  Sbi_err_already_available = -6,
-  // Custom internal error codes
-  Sbi_err_unsupported_func  = -64,
-  Sbi_err_v1_spec           = -65,
-};
-
-/**
- * Base class for all SBI extensions implemented in uvmm.
- */
-class Sbi_ext : public Vdev::Device
-{
-public:
-  /**
-   * Dispatch method, which is overriden by the SBI extension implementations
-   * derived from this base class. The method receives SBI calls targeted at
-   * the SBI extension. Usually it is implemented as a switch-case that
-   * delegates handling the SBI call to the method corresponding to the given
-   * SBI function id.
-   */
-  virtual Sbi_ret handle(l4_int32_t ext_id, l4_int32_t func_id, Vcpu_ptr vcpu) = 0;
-
-  /**
-   * Extract argument from vCPU state and cast it to the expected type.
-   */
-  template
-  static inline A map_arg(l4_umword_t **args)
-  {
-    static_assert(
-      sizeof(A) <= sizeof(l4_umword_t) || sizeof(A) == sizeof(l4_uint64_t),
-      "Unexpected argument size");
-
-    if constexpr (sizeof(A) <= sizeof(l4_umword_t))
-      {
-        return *(*args)++;
-      }
-    // 64-bit integers on 32-bit architecture
-    else if constexpr (sizeof(A) == sizeof(l4_uint64_t))
-      {
-        A arg = *(*args)++;
-        arg += static_cast(*(*args)++) << 32;
-        return arg;
-      }
-  }
-
-  template
-  inline Sbi_ret call(Vcpu_ptr vcpu, R(C::*f)(Vcpu_ptr))
-  {
-    return (static_cast(this)->*f)(vcpu);
-  }
-
-  template
-  inline Sbi_ret call(Vcpu_ptr vcpu, R(C::*f)(Vcpu_ptr, Args ...))
-  {
-    l4_umword_t *args = &vcpu->r.a0;
-    return (static_cast(this)->*f)(vcpu, map_arg(&args)...);
-  }
-
-  template
-  inline Sbi_ret call(Vcpu_ptr, R(C::*f)())
-  {
-    return (static_cast(this)->*f)();
-  }
-
-  template
-  inline Sbi_ret call(Vcpu_ptr vcpu, R(C::*f)(Args ...))
-  {
-    l4_umword_t *args = &vcpu->r.a0;
-    return (static_cast(this)->*f)(map_arg(&args)...);
-  }
-
-  static Sbi_ret sbi_error(Sbi_error error)
-  {
-    return { error, 0 };
-  }
-
-  static Sbi_ret sbi_value(long value)
-  {
-    return { Sbi_success, value };
-  }
-
-  static Sbi_ret sbi_void()
-  {
-    return sbi_value(0);
-  }
-};
-
-class Sbi
-{
-public:
-  static Sbi *create_instance(Guest *guest);
-
-  Sbi(Guest *guest);
-
-  /**
-   * Register the given SBI extension for the given range of extension ids.
-   */
-  void register_ext(l4_int32_t ext_id_start, l4_int32_t ext_id_end,
-                    cxx::Ref_ptr handler);
-
-  /**
-   * Register the given SBI extension for the given extension id.
-   */
-  void register_ext(l4_int32_t ext_id, cxx::Ref_ptr handler)
-  { register_ext(ext_id, ext_id, handler); }
-
-  /**
-   * Find SBI extension registered for the given extension id.
-   */
-  Sbi_ext *find_ext(l4_int32_t ext_id) const;
-
-  /**
-   * Handle SBI call from the guest.
-   */
-  bool handle(Vcpu_ptr vcpu);
-
-  Guest *guest()
-  { return _guest; }
-
-private:
-  Guest * _guest;
-
-  struct Extension
-  {
-    l4_int32_t ext_id_start;
-    l4_int32_t ext_id_end;
-    cxx::Ref_ptr handler;
-  };
-  std::vector _extensions;
-};
-
-class Sbi_base : public Sbi_ext
-{
-public:
-  Sbi_ret handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu) override;
-
-private:
-  enum : long
-  {
-    Sbi_fid_get_sbi_spec_version = 0,
-    Sbi_fid_get_sbi_impl_id      = 1,
-    Sbi_fid_get_sbi_impl_version = 2,
-    Sbi_fid_probe_extension      = 3,
-    Sbi_fid_get_mvendorid        = 4,
-    Sbi_fid_get_marchid          = 5,
-    Sbi_fid_get_mimpid           = 6,
-  };
-
-  Sbi_ret get_spec_version();
-  Sbi_ret get_impl_id();
-  Sbi_ret get_impl_version();
-  Sbi_ret probe_extension(long ext_id);
-  Sbi_ret get_mvendorid();
-  Sbi_ret get_marchid();
-  Sbi_ret get_mimpid();
-};
-
-class Sbi_time : public Sbi_ext
-{
-public:
-  Sbi_ret handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu) override;
-
-private:
-  enum : long
-  {
-    Sbi_fid_set_timer = 0,
-  };
-
-  Sbi_ret set_timer(Vcpu_ptr vcpu, l4_uint64_t stime_value);
-};
-
-class Sbi_ipi : public Sbi_ext
-{
-public:
-  Sbi_ret handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu) override;
-
-private:
-  enum : long
-  {
-    Sbi_fid_send_ipi = 0,
-  };
-
-  Sbi_ret send_ipi(Vcpu_ptr vcpu, l4_umword_t hart_mask,
-                   l4_umword_t hart_mask_base);
-};
-
-class Sbi_rfnc : public Sbi_ext
-{
-public:
-  Sbi_ret handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu) override;
-
-private:
-  enum : long
-  {
-    Sbi_fid_remote_fence_i         = 0,
-    Sbi_fid_remote_sfence_vma      = 1,
-    Sbi_fid_remote_sfence_vma_asid = 2,
-  };
-
-  Sbi_ret remote_fence_i(
-    Vcpu_ptr vcpu, l4_umword_t hart_mask, l4_umword_t hart_mask_base);
-
-  Sbi_ret remote_sfence_vma(
-    Vcpu_ptr vcpu, l4_umword_t hart_mask, l4_umword_t hart_mask_base,
-    l4_umword_t start_addr, l4_umword_t size);
-
-  Sbi_ret remote_sfence_vma_asid(
-    Vcpu_ptr vcpu, l4_umword_t hart_mask, l4_umword_t hart_mask_base,
-    l4_umword_t start_addr, l4_umword_t size, l4_umword_t asid);
-
-  Sbi_ret remote_fence(
-    Vcpu_ptr vcpu, L4_vm_rfnc remote_fence,
-    l4_umword_t hart_mask, l4_umword_t hart_mask_base,
-    l4_umword_t start_addr = 0, l4_umword_t size = 0, l4_umword_t asid = 0);
-};
-
-class Sbi_hsm : public Sbi_ext
-{
-public:
-  Sbi_ret handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu) override;
-
-private:
-  enum : long
-  {
-    Sbi_fid_hart_start      = 0,
-    Sbi_fid_hart_stop       = 1,
-    Sbi_fid_hart_get_status = 2,
-    Sbi_fid_hart_suspend    = 3,
-  };
-
-  Sbi_ret hart_start(l4_umword_t hartid, l4_umword_t start_addr,
-                     l4_umword_t priv);
-
-  Sbi_ret hart_stop(Vcpu_ptr vcpu);
-
-  enum Hart_status
-  {
-    Hart_started               = 0,
-    Hart_stopped               = 1,
-    Hart_start_request_pending = 2,
-    Hart_stop_request_pending  = 3,
-    Hart_suspended             = 4,
-  };
-
-  Sbi_ret hart_status(l4_umword_t hartid);
-
-  Sbi_ret hart_suspend(Vcpu_ptr vcpu, l4_uint32_t suspend_type,
-                       l4_umword_t resume_addr, l4_umword_t opaque);
-};
-
-class Sbi_dbcn : public Sbi_ext
-{
-public:
-  Sbi_dbcn();
-  Sbi_ret handle(l4_int32_t, l4_int32_t func_id, Vcpu_ptr vcpu) override;
-
-private:
-  enum : long
-  {
-    Sbi_fid_debug_console_write      = 0,
-    Sbi_fid_debug_console_read       = 1,
-    Sbi_fid_debug_console_write_byte = 2,
-  };
-
-  Sbi_ret debug_console_write(l4_umword_t num_bytes, l4_umword_t base_addr_lo,
-                              l4_umword_t base_addr_hi);
-
-  Sbi_ret debug_console_read(l4_umword_t num_bytes, l4_umword_t base_addr_lo,
-                             l4_umword_t base_addr_hi);
-
-  Sbi_ret debug_console_write_byte(l4_uint8_t byte);
-
-  L4::Cap _con;
-};
-
-class Sbi_legacy : public Sbi_ext
-{
-public:
-  Sbi_legacy();
-  Sbi_ret handle(l4_int32_t ext_id, l4_int32_t, Vcpu_ptr vcpu) override;
-
-private:
-  Sbi_ret console_putchar(int ch);
-  Sbi_ret console_getchar();
-  Sbi_ret shutdown();
-
-  L4::Cap _con;
-};
-
-} //namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.cc
deleted file mode 100644
index 2468d847..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "vcpu_ic.h"
-
-namespace Gic {
-
-Vcpu_ic::Vcpu_ic(Vmm::Vcpu_ptr vcpu, L4Re::Util::Object_registry *registry)
-: _vcpu(vcpu),
-  _cpu_irq(L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                        "Allocate vcpu notification irq.")),
-  _registry(registry)
-{
-  L4Re::chksys(L4Re::Env::env()->factory()->create(_cpu_irq.get()),
-                 "Create vcpu notification irq.");
-
-  _registry->register_obj(this);
-}
-
-Vcpu_ic::~Vcpu_ic()
-{
-  _registry->unregister_obj(this);
-}
-
-void Vcpu_ic::attach_cpu_thread(L4::Cap thread)
-{
-  L4Re::chksys(
-    _cpu_irq->bind_thread(thread, reinterpret_cast(this)),
-    "Bind vcpu notification irq.");
-}
-
-void Vcpu_ic::notify_ipi(Vmm::Vcpu_ptr current_vcpu)
-{
-  if (current_vcpu != _vcpu)
-    notify(Interrupt_ipi);
-  else
-    set_ipi();
-}
-
-void Vcpu_ic::notify_timer()
-{
-  notify(Interrupt_timer);
-}
-
-void Vcpu_ic::notify_external(Vmm::Vcpu_ptr current_vcpu)
-{
-  if (current_vcpu != _vcpu)
-    notify(Interrupt_external);
-  else
-    update_external();
-}
-
-void Vcpu_ic::notify(Interrupt interrupt)
-{
-  // Mark that interrupt has a update pending
-  // TODO: Memory order?
-  if (_update_pending.fetch_or(interrupt) == 0)
-    // Notify vCPU in case no interrupt update was pending before.
-    _cpu_irq->trigger();
-}
-
-void Vcpu_ic::set_external_pending(bool pending, Vmm::Vcpu_ptr current_vcpu)
-{
-  // TODO: Memory order?
-  if (_external_pending.exchange(pending) != pending)
-    // Notify vCPU in case the external interrupt pending state has changed
-    notify_external(current_vcpu);
-}
-
-void Vcpu_ic::set_ipi()
-{
-  _vcpu.vm_state()->hvip |= L4_vm_hvip_vssip;
-}
-
-void Vcpu_ic::set_timer()
-{
-  _vcpu.vm_state()->hvip |= L4_vm_hvip_vstip;
-}
-
-void Vcpu_ic::clear_timer()
-{
-  _vcpu.vm_state()->hvip &= ~L4_vm_hvip_vstip;
-}
-
-void Vcpu_ic::update_external()
-{
-  // TODO: Memory order?
-  if (_external_pending.load())
-    _vcpu.vm_state()->hvip |= L4_vm_hvip_vseip;
-  else
-    _vcpu.vm_state()->hvip &= ~L4_vm_hvip_vseip;
-}
-
-void Vcpu_ic::handle_irq()
-{
-  // Fetch pending interrupt updates
-  l4_uint32_t updates = _update_pending.exchange(0);
-
-  if (updates & Interrupt_ipi)
-    set_ipi();
-
-  if (updates & Interrupt_timer)
-    set_timer();
-
-  if (updates & Interrupt_external)
-    update_external();
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.h
deleted file mode 100644
index 9aeb05ad..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ic.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-
-#include "irq.h"
-#include "vcpu_ptr.h"
-
-namespace Gic {
-
-/**
- * The Vcpu_ic class implements core local interrupt controller, which keeps
- * track of a vCPU’s pending interrupts and updates the vCPU state
- * accordingly.
- *
- * Vcpu_ic encapsulates the interrupt state of its vCPU, exposing thread-safe
- * methods to modify it. This is important because the case where uvmm modifies
- * the state from the local vCPU thread itself must be handled differently than
- * a modification from another vCPU thread, for example a vCPU sending an IPI
- * to another vCPU. In the first case the affected vCPU is currently executing
- * uvmm code inside the entry handler, so the Vcpu_ic can update the vCPU state
- * immediately. In the second case we do not know whether the affected vCPU is
- * currently executing guest or uvmm code, so instead we send an IRQ
- * notification to the target vCPU thread. Thereupon, the target vCPU enters
- * the uvmm entry handler and processes the updates for its Vcpu_ic in the
- * corresponding IRQ handling routine (Vcpu_ic::handle_irq()).
- */
-class Vcpu_ic
-: public L4::Irqep_t,
-  public virtual Vdev::Dev_ref
-{
-public:
-  Vcpu_ic(Vmm::Vcpu_ptr vcpu, L4Re::Util::Object_registry *registry);
-  ~Vcpu_ic();
-
-  void attach_cpu_thread(L4::Cap thread);
-  void handle_irq();
-
-  /**
-   * Notify vCPU that a software interrupt is pending.
-   */
-  void notify_ipi(Vmm::Vcpu_ptr current_vcpu);
-
-  /**
-   * Notify vCPU that a timer interrupt is pending.
-   */
-  void notify_timer();
-
-  /**
-   * Notify vCPU that the external interrupt pending state has changed.
-   */
-  void notify_external(Vmm::Vcpu_ptr current_vcpu);
-
-  /**
-   * Updates the external interrupt pending state.
-   */
-  void set_external_pending(bool pending, Vmm::Vcpu_ptr current_vcpu);
-
-  // Must only be called from the vCPU thread
-  void set_ipi();
-  void set_timer();
-  void clear_timer();
-  void update_external();
-
-private:
-
-  enum Interrupt : l4_uint32_t
-  {
-    Interrupt_ipi      = 1 << 0,
-    Interrupt_timer    = 1 << 1,
-    Interrupt_external = 1 << 2,
-  };
-
-  void notify(Interrupt interrupt);
-
-  Vmm::Vcpu_ptr _vcpu;
-
-  // The vCPU notification IRQ
-  L4Re::Util::Unique_cap _cpu_irq;
-
-  // Interrupt classes that have an update pending
-  std::atomic _update_pending = 0;
-
-  // Whether at least one external interrupt is pending.
-  // Should be a bool, but RISC-V has only word sized atomic instructions.
-  std::atomic _external_pending = 0;
-
-  L4Re::Util::Object_registry *_registry;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ptr.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ptr.h
deleted file mode 100644
index ee51b2c3..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/vcpu_ptr.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "generic_vcpu_ptr.h"
-#include "mem_access.h"
-#include "riscv_arch.h"
-#include "riscv_instruction.h"
-
-namespace Vmm {
-
-class Vcpu_ptr : public Generic_vcpu_ptr
-{
-public:
-  explicit Vcpu_ptr(l4_vcpu_state_t *s) : Generic_vcpu_ptr(s) {}
-
-  bool operator == (Vcpu_ptr const &other) const
-  { return _s == other._s; }
-
-  bool operator != (Vcpu_ptr const &other) const
-  { return !operator==(other); }
-
-  void thread_attach()
-  {
-    control_ext(L4::Cap());
-  }
-
-  bool pf_write() const
-  {
-    return _s->r.cause == Riscv::Exc_guest_store_page_fault;
-  }
-
-  void jump_instruction(unsigned inst_size)
-  {
-    _s->r.ip += inst_size;
-  }
-
-  void jump_trap_instruction()
-  {
-    Riscv::Instruction insn(vm_state()->htinst);
-    jump_instruction(insn.inst_size());
-  }
-
-  void jump_system_instruction()
-  {
-    jump_instruction(4);
-  }
-
-  Mem_access decode_mmio() const
-  {
-    Riscv::Instruction insn(vm_state()->htinst);
-    Mem_access m;
-
-    if (insn.is_load())
-      {
-        m.access = Mem_access::Load;
-        m.width = insn.load_store_width();
-      }
-    else if(insn.is_store())
-      {
-        m.access = Mem_access::Store;
-        m.width = insn.load_store_width();
-        m.value = reg_read(insn.rs2());
-      }
-    else
-      m.access = Mem_access::Other;
-
-    return m;
-  }
-
-  void writeback_mmio(Mem_access const &m)
-  {
-    assert(m.access == Mem_access::Load);
-
-    Riscv::Instruction insn(vm_state()->htinst);
-    if(insn.is_load())
-      reg_write(insn.rd(),
-                reg_extend_width(m.value, m.width, !insn.is_unsigned_load()));
-  }
-
-  l4_vm_state_t *vm_state() const
-  { return l4_vm_state(_s); }
-
-  bool has_pending_irq()
-  {
-    // At least one interrupt is enabled and pending
-    return vm_state()->hie & vm_state()->hvip;
-  }
-
-private:
-  l4_umword_t reg_read(l4_uint32_t reg) const
-  {
-    assert(reg < 32);
-    // x0: zero register
-    if (reg != 0)
-      return _s->r.r[reg - 1];
-    else
-      return 0;
-  }
-
-  void reg_write(l4_uint32_t reg, l4_umword_t value)
-  {
-    assert(reg < 32);
-    if (reg != 0)
-      _s->r.r[reg - 1] = value;
-  }
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.cc b/src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.cc
deleted file mode 100644
index a71cb748..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "virtual_timer.h"
-
-static Dbg info(Dbg::Cpu, Dbg::Info, "vtimer");
-
-namespace Vdev {
-
-namespace
-{
-  enum : l4_uint32_t
-  {
-    Microsec_per_sec = 1000000,
-  };
-}
-
-l4_uint32_t Virtual_timer::_us_to_ticks;
-
-void Virtual_timer::init_frequency()
-{
-  // TODO: Rework frequency conversion and get_cur_time(), maybe use kernel
-  // provided time accessor functions like on other architectures? Or scaling
-  // math similar to arm/core_timer.h?
-  l4_uint32_t frequency = l4re_kip()->platform_info.arch.timebase_frequency;
-  assert(Microsec_per_sec <= frequency);
-  assert(frequency % Microsec_per_sec == 0);
-  _us_to_ticks = frequency / Microsec_per_sec;
-  info.printf("Virtual_timer: us_to_ticks = %u\n", _us_to_ticks);
-}
-
-void Virtual_timer::run_timer(unsigned vcpu_no, unsigned phys_cpu_id)
-{
-  // Assign a higher priority to the timer thread so that it can interrupt the
-  // vCPU thread to timely deliver timer interrupts.
-  l4_sched_param_t sp = l4_sched_param(3);
-  sp.affinity = l4_sched_cpu_set(phys_cpu_id, 0);
-  auto sched = L4Re::Env::env()->scheduler();
-  L4Re::chksys(sched->run_thread(Pthread::L4::cap(pthread_self()), sp),
-               "Run timer thread.");
-
-  info.printf("Hello Timer on CPU %u\n", vcpu_no);
-  char buf[17];
-  snprintf(buf, sizeof(buf), "vtimer%u", vcpu_no);
-  l4_debugger_set_object_name(Pthread::L4::cap(pthread_self()).cap(), buf);
-
-  // Wait for initial wakeup (timer is set the first time)
-  auto e = l4_error(_wakeup_irq->receive(L4_IPC_NEVER));
-
-  info.printf("Received initial timer thread wakeup on CPU %u! (%ld)\n",
-               vcpu_no, e);
-
-  // now loop forever
-  while(1)
-    {
-      l4_timeout_t wait_timeout = L4_IPC_NEVER;
-
-      l4_uint64_t next_event = next_event_exchange(Invalid_timer_value);
-      // Woken up because the receive timeout expired
-      if(L4_LIKELY(next_event == Invalid_timer_value))
-        {
-          _vcpu_ic->notify_timer();
-        }
-      else
-        {
-          // vCPU updated _next_event while we were sleeping.
-          if (!setup_event_rcv_timeout(l4_utcb(), &wait_timeout, next_event))
-            {
-              // Next event already expired.
-              _vcpu_ic->notify_timer();
-            }
-        }
-
-      _wakeup_irq->receive(wait_timeout);
-    }
-}
-
-void Virtual_timer::start_timer_thread(unsigned phys_cpu_id)
-{
-  _wakeup_irq = L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                             "Allocate timer wakeup irq.");
-  L4Re::chksys(L4Re::Env::env()->factory()->create(_wakeup_irq.get()),
-               "Create timer wakeup irq.");
-
-  next_event_store(Invalid_timer_value);
-  _thread = std::thread(&Virtual_timer::run_timer, this,
-                        _vcpu.get_vcpu_id(), phys_cpu_id);
-
-  L4Re::chksys(_wakeup_irq->bind_thread(std::L4::thread_cap(_thread), 0),
-               "Bind timer wakeup irq.");
-}
-
-void Virtual_timer::set_next_event(l4_uint64_t next_event)
-{
-  // Clamp next event to Max_timer_value
-  if(next_event == Invalid_timer_value)
-    next_event = Max_timer_value;
-
-  next_event_store(next_event);
-
-  // Notify timer thread that next_event was changed.
-  _wakeup_irq->trigger();
-}
-
-bool Virtual_timer::setup_event_rcv_timeout(l4_utcb_t *utcb,
-                                            l4_timeout_t *wait_timeout,
-                                            l4_uint64_t event_time)
-{
-  l4_cpu_time_t cur_time_us = get_cur_time();
-  l4_uint64_t next_event_us = event_time / _us_to_ticks;
-  if (L4_LIKELY(next_event_us > cur_time_us))
-    {
-      // Program next timeout
-      l4_rcv_timeout(l4_timeout_abs_u(next_event_us, 8, utcb), wait_timeout);
-      return true;
-    }
-  else
-    return false;
-}
-
-l4_cpu_time_t Virtual_timer::get_cur_time()
-{
-  // TODO: Directly read the time csr to get a more up-to-date reading?
-  // Could save some unecessary IPC sleep operations, and we do not
-  // have to convert the next_event to micro seconds in run_timer()
-  // before testing.
-  return l4_kip_clock(l4re_kip());
-}
-
-#if __riscv_xlen == 32
-// We don't have 64-bit atomic instructions on RV32.
-void Virtual_timer::next_event_store(l4_uint64_t next_event)
-{
-  acquire_lock(std::L4::thread_cap(_thread));
-  _next_event = next_event;
-  release_lock();
-}
-
-l4_uint64_t Virtual_timer::next_event_exchange(l4_uint64_t next_event)
-{
-  acquire_lock(_vcpu_thread);
-  l4_uint64_t prev_next_event = _next_event;
-  _next_event = next_event;
-  release_lock();
-  return prev_next_event;
-}
-
-void Virtual_timer::acquire_lock(L4::Cap contender)
-{
-  // Acquire lock
-  while (L4_UNLIKELY(_next_event_lock.test_and_set(std::memory_order_acquire)))
-    {
-      // Both the vCPU and the timer thread run on the same physical cpu,
-      // therefore we switch immediately to the contending thread.
-      contender->switch_to();
-    }
-}
-
-void Virtual_timer::release_lock()
-{
-  // Release lock
-  _next_event_lock.clear(std::memory_order_release);
-}
-#else
-void Virtual_timer::next_event_store(l4_uint64_t next_event)
-{
-  _next_event.store(next_event, std::memory_order_relaxed);
-}
-
-l4_uint64_t Virtual_timer::next_event_exchange(l4_uint64_t next_event)
-{
-  return _next_event.exchange(next_event, std::memory_order_relaxed);
-}
-#endif
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.h b/src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.h
deleted file mode 100644
index 0205c4ba..00000000
--- a/src/l4/pkg/uvmm/server/src/ARCH-riscv/virtual_timer.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "vcpu_ic.h"
-
-namespace Vdev {
-
-/**
- * Per-vCPU virtual timer that uses a separate timer thread that blocks on an
- * IRQ receive operation with a timeout equal to the next timer event. When the
- * timeout expires, the timer thread notifies the Vcpu_ic of the vCPU that a
- * timer interrupt is pending.
- *
- * When the guest reconfigures the next event of its timer, the wakeup IRQ of
- * the timer thread is triggered, whereupon the timer thread is woken up, only
- * to block again in the IRQ receive operation with a timeout adjusted
- * according to the new next event.
- */
-class Virtual_timer : public virtual Vdev::Dev_ref
-{
-public:
-  Virtual_timer(Vmm::Vcpu_ptr vcpu, L4::Cap vcpu_thread,
-                cxx::Ref_ptr vcpu_ic)
-  : _vcpu(vcpu),
-    _vcpu_thread(vcpu_thread),
-    _vcpu_ic(vcpu_ic)
-  {
-  }
-
-  virtual ~Virtual_timer() = default;
-
-  static void init_frequency();
-
-  /**
-   * Start a new thread to run the timer loop.
-   *
-   * \param vcpu_no      Number of the vCPU to run the timer for.
-   * \param phys_cpu_id  Scheduler id of the physical core to run on.
-   */
-  void start_timer_thread(unsigned phys_cpu_id);
-
-  /**
-   * Program the next timer event.
-   *
-   * \param next_event Next timer event in real-time clock cycles,
-   *                   as for example returned by the rdtime instruction.
-   */
-  void set_next_event(l4_uint64_t next_event);
-
-  /**
-   * Setup receive timeout in UTCB for given time.
-   *
-   * \param event_time  Event time in real-time clock cycles.
-   *
-   * \retval true  if event successfully programmed.
-   * \retval false if event time already expired.
-   */
-  static bool setup_event_rcv_timeout(l4_utcb_t *utcb, l4_timeout_t *wait_timeout,
-                                      l4_uint64_t event_time);
-
-private:
-  static l4_cpu_time_t get_cur_time();
-
-  /**
-   * Migrate a vCPU's timer thread to its physical core and run the timer loop.
-   *
-   * \param vcpu_no      Number of the vCPU to run the timer for.
-   * \param phys_cpu_id  Scheduler id of the physical core to run on.
-   */
-  void run_timer(unsigned vcpu_no, unsigned phys_cpu_id);
-
-  /**
-   * Atomically write the _next_event member.
-   *
-   * \param next_event  Value to store.
-   *
-   * \note Only called by vCPU thread.
-   */
-  void next_event_store(l4_uint64_t next_event);
-
-  /**
-   * Atomically exchange the value of _next_event member.
-   *
-   * \param next_event  New value.
-   *
-   * \return Old value.
-   *
-   * \note Only called by timer thread.
-   */
-  l4_uint64_t next_event_exchange(l4_uint64_t next_event);
-
-  static l4_uint32_t _us_to_ticks;
-
-  Vmm::Vcpu_ptr _vcpu;
-  L4::Cap _vcpu_thread;
-  cxx::Ref_ptr _vcpu_ic;
-
-
-  // The timer thread
-  std::thread _thread;
-  // Wakeup irq for the timer thread
-  L4Re::Util::Unique_cap _wakeup_irq;
-
-  enum : l4_uint64_t
-  {
-    Invalid_timer_value  = ~0ULL,
-    Max_timer_value      = Invalid_timer_value - 1,
-  };
-
-#if __riscv_xlen == 32
-  /**
-   * RV32 does not have 64-bit atomic instructions, thus a lock is needed to
-   * ensure atomic modifications of _next_event.
-   *
-   * _next_event is only accessed by two threads, the vCPU thread and the
-   *  virtual timer thread for the vCPU. As both threads run on the same CPU,
-   *  this lock implementation simply switches to the contending thread if it
-   *  encounters a taken lock.
-   *
-   * \param contender Contending thread to switch to if the lock is already
-   *                  taken.
-   */
-  void acquire_lock(L4::Cap contender);
-  void release_lock();
-
-  std::atomic_flag _next_event_lock = ATOMIC_FLAG_INIT;
-  l4_uint64_t _next_event;
-#else
-  std::atomic _next_event;
-#endif
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/Makefile b/src/l4/pkg/uvmm/server/src/Makefile
deleted file mode 100644
index 1048ee3d..00000000
--- a/src/l4/pkg/uvmm/server/src/Makefile
+++ /dev/null
@@ -1,150 +0,0 @@
-PKGDIR ?= ../..
-L4DIR  ?= $(PKGDIR)/../..
-
-include $(L4DIR)/mk/Makeconf
-
-SYSTEMS         = arm-l4f mips-l4f arm64-l4f amd64-l4f riscv-l4f
-TARGET          = uvmm
-VARIANTS        = nofpu
-
-REQUIRES_LIBS   = libstdc++ libio-vbus libfdt libpthread
-REQUIRES_LIBS_amd64-l4f = acpica
-
-SRC_CC          = main.cc ram_ds.cc generic_guest.cc \
-                  cpu_dev_array.cc generic_cpu_dev.cc \
-                  ARCH-$(ARCH)/cpu_dev.cc \
-                  host_dt.cc device_factory.cc \
-                  virt_bus.cc io_proxy.cc \
-                  mmio_device.cc \
-                  pm.cc vbus_event.cc vm_memmap.cc vm_ram.cc vm.cc \
-                  address_space_manager.cc \
-                  device/rtc-hub.cc pm_device_if.cc
-
-SRC_CC-$(CONFIG_RELEASE_MODE)y          += debug.cc
-SRC_CC-$(CONFIG_UVMM_MONITOR)           += monitor/monitor.cc
-SRC_CC_amd64-l4f-$(CONFIG_UVMM_MONITOR) += debugger/generic_guest_debugger.cc
-
-SRC_CC_arm-common-$(CONFIG_UVMM_VDEV_GIC_V2) += arm/gic-v2.cc
-SRC_CC_arm-common-$(CONFIG_UVMM_VDEV_GIC_V3) += arm/gic-v3.cc
-SRC_CC_arm-common-$(CONFIG_UVMM_VDEV_GIC_ITS) += arm/gic-v3_its.cc
-SRC_CC_arm-common-$(CONFIG_UVMM_FAULT_INJECT)  += ARCH-$(ARCH)/guest_arm_exc.cc
-SRC_CC_arm-common-$(CONFIG_UVMM_FAULT_INJECT)y += arm/guest_arm_noexc.cc
-
-SRC_CC_arm-common = arm/gic_cpu.cc arm/gic_iface.cc \
-                    arm/guest_arm.cc arm/cpu_dev_arm.cc \
-                    io_port_handler_noop.cc ARCH-$(ARCH)/guest_subarch.cc
-
-SRC_CC_arm-l4f   = $(SRC_CC_arm-common) $(SRC_CC_arm-common-y)
-SRC_CC_arm64-l4f = $(SRC_CC_arm-common) $(SRC_CC_arm-common-y)
-SRC_CC_mips-l4f  = ARCH-mips/gic.cc ARCH-mips/cpc.cc ARCH-mips/guest.cc \
-                   io_port_handler_noop.cc
-SRC_CC_riscv-l4f = ARCH-riscv/guest.cc ARCH-riscv/sbi.cc \
-                   ARCH-riscv/virtual_timer.cc ARCH-riscv/vcpu_ic.cc \
-                   ARCH-riscv/plic.cc io_port_handler_noop.cc
-SRC_CC_amd64-l4f = ARCH-amd64/guest.cc ARCH-amd64/mad.cc ARCH-amd64/pit.cc \
-                   ARCH-amd64/rtc.cc ARCH-amd64/virt_lapic.cc \
-                   ARCH-amd64/ioapic.cc \
-                   ARCH-amd64/vcpu_ptr.cc \
-                   ARCH-amd64/kvm_clock.cc \
-                   ARCH-amd64/legacy_pic.cc ARCH-amd64/acpi_platform.cc \
-                   ARCH-amd64/acpi_timer.cc ARCH-amd64/zeropage.cc \
-                   ARCH-amd64/openbsd_bootparams.cc \
-                   ARCH-amd64/io_port_handler_l4util.cc \
-                   ARCH-amd64/vm_state_vmx.cc ARCH-amd64/vm_state_svm.cc \
-                   ARCH-amd64/guest-vmx.cc ARCH-amd64/guest-svm.cc \
-                   ARCH-amd64/event_recorder.cc ARCH-amd64/event_record.cc
-
-SRC_CC_amd64-l4f-$(CONFIG_UVMM_VDEV_DEVICE_FRAMEBUFFER) += ARCH-amd64/framebuffer.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_ISA_DEBUG_PORT) += ARCH-amd64/isa_debugport.cc
-
-SRC_CC_arm-l4f-$(CONFIG_UVMM_VDEV_PSCI)   += device/arm/psci.cc
-SRC_CC_arm64-l4f-$(CONFIG_UVMM_VDEV_PSCI) += device/arm/psci.cc
-SRC_CC_arm-l4f-$(CONFIG_UVMM_VDEV_SMCCC_PROXY)   += device/arm/smccc_proxy.cc
-SRC_CC_arm64-l4f-$(CONFIG_UVMM_VDEV_SMCCC_PROXY) += device/arm/smccc_proxy.cc
-
-SRC_CC-$(CONFIG_UVMM_VDEV_8250)  += device/uart_8250.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_CONSOLE) += virtio_console.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_PROXY) += virtio_proxy.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_PL011) += device/pl011.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_OPTEE) += device/optee.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_PL031) += device/arm/pl031.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_INPUT)   += device/virtio_input_event.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_POWER)   += device/virtio_input_power.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_VIRQ) += device/virq.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_MMIO_PROXY) += device/mmio_proxy.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_SYSCTL) += device/sysctl.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_DEVICE_PROXY) += device/virtio_device_mem_pool.cc \
-                                           device/virtio_device_proxy.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_CFI_FLASH) +=  device/cfi.cc
-SRC_CC-$(CONFIG_UVMM_EXTERNAL_RTC) += device/l4rtc.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_DEVICE_FRAMEBUFFER) += device/framebuffer.cc
-SRC_CC-$(CONFIG_UVMM_VDEV_ROM) += device/rom.cc
-
-SRC_CC-$(CONFIG_UVMM_VDEV_BCM2835_MBOX) += device/bcm2835_mbox.cc
-
-SRC_CC-$(CONFIG_UVMM_QEMU_FW_IF) += device/qemu_fw_cfg.cc
-SRC_CC_amd64-l4f-$(CONFIG_UVMM_QEMU_FW_IF) += \
-	ARCH-amd64/qemu_fw_cfg_acpi.cc \
-	ARCH-amd64/qemu_fw_cfg_boot.cc
-
-ifeq ($(CONFIG_UVMM_PCI_SUPPORT),y)
-    SRC_CC   += pci_device.cc virt_pci_device.cc
-
-    SRC_CC_amd64-l4f += device/pci_host_bridge.cc device/pci_host_generic.cc \
-
-    SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_CONSOLE) += virtio_console_pci.cc
-    SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_PROXY) += virtio_proxy_pci.cc
-    SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_INPUT) += device/virtio_input_event_pci.cc
-    SRC_CC-$(CONFIG_UVMM_VDEV_VIRTIO_POWER) += device/virtio_input_power_pci.cc
-    SRC_CC-$(CONFIG_UVMM_VDEV_DEVICE_PROXY) += device/virtio_device_proxy_pci.cc
-    SRC_CC-$(CONFIG_UVMM_VDEV_DEVICE_PCI_HOST_ECAM_GENERIC) += device/pci_host_bridge.cc \
-                                                             device/pci_host_ecam_generic.cc
-endif
-
-SRC_CC += binary_loader.cc
-SRC_CC-$(CONFIG_UVMM_LOADER_RAW) += binary_loader_raw.cc
-SRC_CC-$(CONFIG_UVMM_LOADER_ELF) += binary_loader_elf.cc
-SRC_CC-$(CONFIG_UVMM_LOADER_PE)  += binary_loader_pe.cc
-SRC_CC-$(CONFIG_UVMM_LOADER_ROM) += binary_loader_rom.cc
-SRC_CC_amd64-l4f-$(CONFIG_UVMM_LOADER_LINUX)  += ARCH-amd64/binary_loader_linux.cc
-SRC_CC_amd64-l4f-$(CONFIG_UVMM_LOADER_OPENBSD)  += ARCH-amd64/binary_loader_openbsd.cc
-SRC_CC_arm-common-$(CONFIG_UVMM_LOADER_LINUX) += arm/binary_loader_linux.cc
-SRC_CC_riscv-$(CONFIG_UVMM_LOADER_LINUX) += ARCH-riscv/binary_loader_linux.cc
-SRC_CC-$(CONFIG_UVMM_LOADER_GZIP) += binary_loader_linux_compressed.cc
-REQUIRES_LIBS-$(CONFIG_UVMM_LOADER_GZIP) += zlib
-
-include $(wildcard $(PKGDIR)/server/src/Makefile.devs.*)
-
-ifeq ($(ARCH),mips)
-SRC_CC        += ARCH-$(ARCH)/guest_entry.cc
-CXXFLAGS_guest_entry.cc = -msoft-float
-
-LDFLAGS       += --no-warn-mismatch
-endif
-
-ifeq ($(ARCH),riscv)
-# Prevent the compiler from assembling instructions that use the floating-point
-# registers (Limitation: does not apply to libraries we link against).
-# But this option will alert us in case we add floating point instructions to
-# uvmm or the RISC-V compiler should start to use FPU state automatically, such
-# as for optimization purposes.
-# uvmm then must save and restore the fpu in the entry handler.
-CXXFLAGS      += -Wa,-march=$(subst d,,$(subst f,,$(CPU)))
-endif
-
-PRIVATE_INCDIR  = $(SRC_DIR)/../include $(SRC_DIR) $(SRC_DIR)/ARCH-$(ARCH)
-PRIVATE_INCDIR_arm-l4f   += $(SRC_DIR)/arm $(SRC_DIR)/device/arm
-PRIVATE_INCDIR_arm64-l4f += $(SRC_DIR)/arm $(SRC_DIR)/device/arm
-PRIVATE_INCDIR += $(SRC_DIR)/../../tools/uvmm_cli
-
-include $(L4DIR)/mk/prog.mk
-
-# Force armv7+ve on pre-armv8 AArch32 build trees.
-ifeq ($(ARCH),arm)
-ifeq ($(CONFIG_CPU_ARMV8PLUS),)
-CARCHFLAGS := $(filter-out -march%,$(CARCHFLAGS)) $(GCCARMV7VEFPOPT_arm)
-endif
-endif
-
-# We do not want to have -fno-strict-aliasing
-OPTS := $(OPTS_DEBUG) -O3
diff --git a/src/l4/pkg/uvmm/server/src/address_space_manager.cc b/src/l4/pkg/uvmm/server/src/address_space_manager.cc
deleted file mode 100644
index 0febc07b..00000000
--- a/src/l4/pkg/uvmm/server/src/address_space_manager.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2021-2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include "address_space_manager.h"
-#include "batch_unmapper.h"
-#include "consts.h"
-
-namespace Vmm {
-
-int Address_space_manager::get_phys_mapping(L4::Cap ds,
-                                            l4_addr_t offset,
-                                            L4Re::Dma_space::Dma_addr *dma_start,
-                                            l4_size_t *size)
-{
-  assert(_dma_space);
-
-  int err = _dma_space->map(L4::Ipc::make_cap(ds, L4_CAP_FPAGE_RW), offset,
-                            size, L4Re::Dma_space::Attributes::None,
-                            L4Re::Dma_space::Bidirectional, dma_start);
-
-  return err;
-}
-
-void Address_space_manager::add_ram_iommu(Guest_addr vm_start, l4_addr_t src_start,
-                                          l4_size_t size)
-{
-  l4_addr_t src_end   = src_start + size;
-  l4_addr_t dst_start = vm_start.get();
-  l4_addr_t dst_end   = dst_start + size;
-
-  // Must be page aligned
-  assert(l4_trunc_page(src_start) == src_start);
-  assert(l4_trunc_page(dst_start) == dst_start);
-
-  warn().printf("Add RAM Iommu: [0x%lx, 0x%lx] -> [0x%lx, 0x%lx]\n", src_start,
-                src_end - 1, dst_start, dst_end - 1);
-
-  // map all pages of region into DMA space
-  while (src_start < src_end - 1)
-    {
-      // Make sure the order fits both send and receive address
-      unsigned char order = cxx::min(
-        L4::max_order(L4_LOG2_PAGESIZE, src_start, src_start, src_end),
-        L4::max_order(L4_LOG2_PAGESIZE, dst_start, dst_start, dst_end));
-      L4Re::chksys(_kdma_space->map(L4Re::This_task,
-                                    l4_fpage(src_start, order, L4_FPAGE_RW),
-                                    dst_start),
-                   "Map guest RAM into KDMA space");
-      src_start += 1UL << order;
-      dst_start += 1UL << order;
-    }
-}
-
-void Address_space_manager::del_ram_iommu(Guest_addr dest, l4_size_t size)
-{
-  l4_addr_t dst_start = dest.get();
-  l4_addr_t dst_end = dst_start + size - 1;
-  l4_addr_t offs = 0;
-
-  // Must be page aligned
-  assert(l4_trunc_page(dst_start) == dst_start);
-
-  warn().printf("Remove RAM Iommu: [0x%lx, 0x%lx]\n", dst_start, dst_end);
-
-  Vmm::Batch_unmapper b(_kdma_space.get(), 0);
-  while (offs < size)
-    {
-      auto doffs = dst_start + offs;
-      char ps = Vmm::get_page_shift(doffs, dst_start, dst_end, offs);
-      b.unmap(l4_fpage(doffs, ps, L4_FPAGE_RWX));
-      offs += static_cast(1) << ps;
-    }
-}
-
-void Address_space_manager::detect_sys_info(Virt_bus *vbus,
-                                            bool force_identity_mode)
-{
-#ifndef CONFIG_MMU
-  info().printf("No-MMU platform. Forcing identity mapping mode.\n");
-  force_identity_mode = true;
-#endif
-  _info.force_identity() = force_identity_mode;
-  if (force_identity_mode)
-    {
-      auto dma_space =
-        L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                     "Allocate DMA space capability");
-      L4Re::chksys(L4Re::Env::env()->user_factory()->create(dma_space.get()),
-                   "Create DMA space.");
-
-      if (dma_space->associate(L4::Ipc::Cap(),
-                               L4Re::Dma_space::Phys_space)
-          >= 0)
-        _info.dma_phys_addr() = 1;
-
-      _dma_space = std::move(dma_space);
-    }
-
-  if (!vbus->available())
-    return;
-
-  _info.vbus_present() = 1;
-
-  // We have a vBus, can we create the KDMA space and assign it to the vbus'
-  // DMA domain?
-  auto kdma = L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                           "Allocate KDMA Task capability");
-
-  // If we cannot create a KDMA space, we don't have an IO-MMU.
-  int err = l4_error(
-    L4Re::Env::env()->factory()->create(kdma.get(), L4_PROTO_DMA_SPACE));
-
-  if (err >= L4_EOK)
-    {
-      _info.io_mmu() = 1;
-      _kdma_space = std::move(kdma);
-
-      // If we cannot assign DMA Domain ~0U, the vBus has no DMA capable devices.
-      err = vbus->bus()->assign_dma_domain(~0U,
-                                           L4VBUS_DMAD_BIND
-                                             | L4VBUS_DMAD_KERNEL_DMA_SPACE,
-                                           _kdma_space.get());
-      if (err >= L4_EOK)
-        _info.vbus_has_dma_devs() = 1;
-      else
-        info().printf("Can not assign KDMA space to vBus (%i). No DMA capable "
-                      "devices configured.\n", err);
-    }
-  else
-    {
-      // if we already have a _dma_space due to the force flag, use it.
-      if (!_info.force_identity())
-        {
-          auto dma_space =
-            L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                         "Allocate DMA space capability");
-          err =
-            l4_error(L4Re::Env::env()->user_factory()->create(dma_space.get()));
-
-          if (err >= L4_EOK)
-            {
-              if (dma_space->associate(L4::Ipc::Cap(),
-                                       L4Re::Dma_space::Phys_space)
-                  >= 0)
-                _info.dma_phys_addr() = 1;
-
-              _dma_space = std::move(dma_space);
-            }
-          else
-            info().printf("DMA space creation failed (%i).\n", err);
-        }
-
-      if (_dma_space)
-        {
-          // If we cannot assign DMA Domain ~0U, the vBus has no DMA capable
-          // devices.
-          err = vbus->bus()->assign_dma_domain(~0U,
-                                               L4VBUS_DMAD_BIND
-                                                 | L4VBUS_DMAD_L4RE_DMA_SPACE,
-                                               _dma_space.get());
-
-          if (err >= L4_EOK)
-            _info.vbus_has_dma_devs() = 1;
-          else
-            info()
-              .printf("Can not assign KDMA space to vBus (%i). No DMA capable "
-                      "devices configured.\n", err);
-        }
-    }
-}
-
-void Address_space_manager::mode_selection()
-{
-  if (_mode_selected)
-    return;
-
-  _info.dump();
-  _mode_selected = true;
-
-  if (_info.force_identity() || _info.dma_phys_addr())
-    {
-      // The _dma_space is either Phys_space associated or Io associated it.
-      // We need the Phys_space association.
-      assert(_dma_space);
-      L4Re::chksys(_dma_space->associate(L4::Ipc::Cap(),
-                                        L4Re::Dma_space::Phys_space),
-                   "Access physical address space mappings.");
-    }
-
-  if (_info.force_identity())
-    {
-      _mode = _info.io_mmu() ? Mode::Iommu_identity : Mode::Identity;
-      info().printf("Operating mode: %s (Identity forced)\n",
-                    mode_to_str(_mode));
-      return;
-    }
-
-  if (!_info.vbus_present())
-    {
-      _mode = Mode::No_dma;
-      info().printf("Operating mode: %s\n", mode_to_str(_mode));
-      return;
-    }
-
-  if (_info.io_mmu())
-    {
-      if (_info.vbus_has_dma_devs())
-        _mode = Mode::Iommu;
-      else
-        _mode = Mode::No_dma;
-    }
-  else
-    {
-      if (_info.vbus_has_dma_devs())
-        _mode = _info.dt_dma_ranges() ? Mode::Dma_offset : Mode::Identity;
-      else
-        _mode = Mode::No_dma;
-    }
-
-  info().printf("Operating mode: %s\n", mode_to_str(_mode));
-}
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/address_space_manager.h b/src/l4/pkg/uvmm/server/src/address_space_manager.h
deleted file mode 100644
index 504e280b..00000000
--- a/src/l4/pkg/uvmm/server/src/address_space_manager.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "device.h"
-#include "mem_types.h"
-#include "virt_bus.h"
-#include "debug.h"
-
-namespace Vmm {
-
-class Address_space_manager : public Vdev::Device
-{
-  /// Operating modes
-  enum class Mode { No_dma, Identity, Iommu, Dma_offset, Iommu_identity };
-
-  /// Information collected to base the operating mode decision on.
-  struct Info
-  {
-    unsigned raw;
-
-    CXX_BITFIELD_MEMBER(0, 0, vbus_present, raw);
-    CXX_BITFIELD_MEMBER(1, 1, vbus_has_dma_devs, raw);
-    CXX_BITFIELD_MEMBER(2, 2, io_mmu, raw);
-    CXX_BITFIELD_MEMBER(3, 3, force_identity, raw);
-    CXX_BITFIELD_MEMBER(4, 4, dma_phys_addr, raw);
-    CXX_BITFIELD_MEMBER(5, 5, dt_dma_ranges, raw);
-
-    void dump() const
-    {
-      info().printf("Sys Info:\n"
-                    "\tvBus:            %i\n"
-                    "\tDMA devs:        %i\n"
-                    "\tIO-MMU:          %i\n"
-                    "\tIdentity forced: %i\n"
-                    "\tDMA phys addr:   %i\n"
-                    "\tDT dma-ranges:   %i\n",
-                    vbus_present().get(), vbus_has_dma_devs().get(),
-                    io_mmu().get(),
-                    force_identity().get(),
-                    dma_phys_addr().get(), dt_dma_ranges().get());
-    }
-  };
-
-public:
-  /**
-   * Register a piece of RAM with the manager for use with an IO-MMU.
-   *
-   * \param vm_start  Start of the RAM region in VM memory.
-   * \param start     Start of the local mapping of the RAM region.
-   * \param size      Size of the RAM region.
-   */
-  void add_ram_iommu(Guest_addr vm_start, l4_addr_t start, l4_size_t size);
-
-  /**
-   * Delete a piece of RAM from the manager and the IO-MMU.
-   *
-   * \param dest      Start of the RAM region in VM memory.
-   * \param size      Size of the RAM region.
-   */
-  void del_ram_iommu(Guest_addr dest, l4_size_t size);
-
-  /**
-   * Register a piece of RAM for identity mapping and get the host physical
-   * address and size.
-   *
-   * \param start       Start of the local mapping of the RAM region.
-   * \param ds          Dataspace of the backing memory.
-   * \param offset      Offset of the start address within the dataspace.
-   * \param[out] start  corresponding host-physical address
-   * \param[out] size   size of the corrsponding host-physical region.
-   *
-   * \return Error value of `dma_map()` operation.
-   *
-   * If identity mode was forced and an IO-MMU was detected, the KDMA space for
-   * the IO-MMU is set up as well.
-   */
-  int get_phys_mapping(L4::Cap ds, l4_addr_t offset,
-                       L4Re::Dma_space::Dma_addr *dma_start,
-                       l4_size_t *size);
-
-  /// Is the operating mode `Iommu`?
-  bool is_iommu_mode() const { return _mode == Mode::Iommu; }
-  /// Is the operating mode `Identity`?
-  bool is_identity_mode() const { return _mode == Mode::Identity; }
-  /// Is the operating mode `Dma_offset`?
-  bool is_dma_offset_mode() const { return _mode == Mode::Dma_offset; }
-  /// Is the operating mode `Iommu_identity`?
-  bool is_iommu_identity_mode() const { return _mode == Mode::Iommu_identity; }
-  /// Is the operating mode any of the indentity modes?
-  bool is_any_identity_mode() const
-  { return is_identity_mode() || is_iommu_identity_mode(); }
-
-  /// Return the string representation of the current operating mode.
-  char const *mode() const
-  { return mode_to_str(_mode); }
-
-  /**
-   * Detect system information.
-   *
-   * \param vbus                 The vbus containing hardware devices.
-   * \param force_identity_mode  true, if we must operate in identity mode.
-   */
-  void detect_sys_info(Virt_bus *vbus, bool force_identity_mode);
-
-  /// True: the devie tree memory node has a 'dma-ranges' property.
-  void info_add_dma_ranges() { _info.dt_dma_ranges() = 1; }
-
-  /**
-   * Start the mode selection based on the collected information.
-   *
-   * No DMA mode is selected, if the is no vBus or there are no DMA capable
-   * devices on the vBus.
-   *
-   * DMA offset mode is used, if there is a DMA ranges property in the device
-   * tree's memory node and DMA capable devices on the vBus. Forced identity
-   * mappings supercede this mode.
-   *
-   * Identity mode is used if either forced or when there are DMA capable
-   * devices and there is no DMA ranges property in the memory node of
-   * the device tree.
-   *
-   * IO-MMU mode is selected, when there is an IO-MMU present in the system
-   * and there are DMA capable devices on the vBus.
-   * If this is the case and identity mappings are forced, the IO-MMU+Identity
-   * mode is selected.
-   *
-   * \note The mode selection is just performed once. Subsequent calls do not
-   *       change the selected mode.
-   */
-  void mode_selection();
-
-private:
-  static ::Dbg warn() { return {::Dbg::Mmio, ::Dbg::Warn, "ASM"}; }
-  static ::Dbg info() { return {::Dbg::Mmio, ::Dbg::Info, "ASM"}; }
-  static ::Dbg trace() { return {::Dbg::Mmio, ::Dbg::Trace, "ASM"}; }
-
-  static char const *mode_to_str(Mode m)
-  {
-    switch(m)
-      {
-      case Mode::No_dma: return "No DMA";
-      case Mode::Identity: return "Identity";
-      case Mode::Iommu: return "IO-MMU";
-      case Mode::Dma_offset: return "DMA-offset";
-      case Mode::Iommu_identity: return "IO-MMU+identity";
-      default: return "Invalid mode value";
-      }
-  }
-
-  Info _info{0};
-  bool _mode_selected = false;
-  Mode _mode = Mode::No_dma;
-  L4Re::Util::Unique_cap _kdma_space;
-  L4Re::Util::Unique_cap _dma_space;
-}; // class Address_space_manager
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/arm/arm_exc.h b/src/l4/pkg/uvmm/server/src/arm/arm_exc.h
deleted file mode 100644
index cf421e09..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/arm_exc.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2021, 2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "arm_hyp.h"
-#include "vcpu_ptr.h"
-
-namespace Vmm {
-namespace Arm {
-
-namespace Aarch32 {
-
-enum Psr
-{
-  Psr_t     = 1UL << 5,
-  Psr_f     = 1UL << 6,
-  Psr_i     = 1UL << 7,
-  Psr_a     = 1UL << 8,
-  Psr_e     = 1UL << 9,
-
-  Psr_ge_mask = 0xfUL << 16,
-
-  // Shared with ARM64
-  Psr_pan  = 1UL << 22,
-  Psr_ssbs = 1UL << 23,
-  Psr_dit  = 1UL << 24,
-
-  // Shared with ARM64
-  Psr_q = 1UL << 27,
-  Psr_v = 1UL << 28,
-  Psr_c = 1UL << 29,
-  Psr_z = 1UL << 30,
-  Psr_n = 1UL << 31,
-
-  Psr_m_fiq = 0x11,
-  Psr_m_svc = 0x13,
-  Psr_m_abt = 0x17,
-  Psr_m_und = 0x1b,
-};
-
-enum class Exc_offset
-{
-  Undefined_inst = 4,
-  Prefetch_abort = 12,
-  Data_abort     = 16,
-};
-
-enum Fsr
-{
-  Fsr_fs_ext_abort_nlpae = 0x08,
-  Fsr_fs_ext_abort_lpae  = 0x10,
-  Fsr_lpae               = 1UL << 9,
-};
-
-enum Sctlr
-{
-  Sctlr_v     = 1UL << 13,
-  Sctlr_span  = 1UL << 23,
-  Sctlr_ee    = 1UL << 25,
-  Sctlr_te    = 1UL << 30,
-  Sctlr_dssbs = 1UL << 31,
-};
-
-/**
- * On exception entry, the preferred return address for the exception is saved
- * in the link register of the mode the exception is taken to. If the exception
- * is taken to a non-EL2 mode, additionally an instruction-specific offset must
- * be added to the preferred return address.
- *
- * \param off    Exception to be taken
- * \param thumb  Indicates whether the trapped instruction is a Thumb
- *               instruction.
- *
- * \return The adjustment for the preferred return offset.
- */
-inline unsigned get_return_offset(Exc_offset off, bool thumb)
-{
-  switch (off)
-    {
-    case Exc_offset::Undefined_inst:
-      return thumb ? 2 : 4;
-    case Exc_offset::Prefetch_abort:
-      return 4;
-    case Exc_offset::Data_abort:
-      return 8;
-    }
-  return 0;
-}
-
-/**
- * Derive the PSTATE flags for an Aarch32 exception handler handling an
- * exception taken from Aarch32 state.
- *
- * \param vcpu  vCPU on which the exception is taken
- * \param mode  Mode to which the exception is taken
- *
- * \return PSTATE flags for the exception handler.
- */
-inline l4_uint32_t get_except_flags(Vcpu_ptr vcpu, unsigned mode)
-{
-  l4_uint32_t sctlr = l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_SCTLR);
-  l4_umword_t old_flags = vcpu->r.flags;
-  l4_uint32_t new_flags = 0;
-
-  // The condition flags are preserved
-  new_flags = old_flags & (Psr_n | Psr_z | Psr_c | Psr_v | Psr_q | Psr_ge_mask);
-
-  // CPSR.DIT is preserved
-  new_flags |= old_flags & Psr_dit;
-
-  // CPSR.SSBS is set to SCTLR_ELx.DSSBS
-  if (sctlr & Sctlr_dssbs)
-    new_flags |= Psr_ssbs;
-
-  // CPSR.PAN is preserved unless overridden by SCTLR_ELx.SPAN
-  new_flags |= (old_flags & Psr_pan);
-  if (!(sctlr & Sctlr_span))
-    new_flags |= Psr_pan;
-
-  // CPSR.E is set to SCTLR.EE
-  if (sctlr & Sctlr_ee)
-    new_flags |= Psr_e;
-
-  // CPSR.A is preserved on an exception to Supervisor or Undefined mode, for
-  // other modes it is set to 1
-  if (mode == Psr_m_und || mode == Psr_m_svc)
-    new_flags |= (old_flags & Psr_a);
-  else
-    new_flags |= Psr_a;
-
-  // CPSR.I is set to 1
-  new_flags |= Psr_i;
-
-  // CPSR.F is set on an exception to FIQ mode, for other modes it is preserved
-  if (mode == Psr_m_fiq)
-    new_flags |= Psr_f;
-  else
-    new_flags |= (old_flags & Psr_f);
-
-  // CPSR.T is set to SCTLR.TE
-  if (sctlr & Sctlr_te)
-    new_flags |= Psr_t;
-
-  // CPSR.M is set to the mode to which the exception is taken
-  new_flags |= mode;
-
-  return new_flags;
-}
-
-/**
- * Generate fault status information for prefetch and data aborts.
- *
- * IFSR and DFSR use the same bit assignment for the bits that are relevant for
- * us.
- */
-inline l4_uint32_t get_abort_fsr(l4_uint32_t ttbcr)
-{
-  if (ttbcr & Ttbcr_eae)
-    // LPAE is enabled
-    return Fsr_lpae | Fsr_fs_ext_abort_lpae;
-  else
-    // LPAE is not enabled
-    return Fsr_fs_ext_abort_nlpae;
-}
-
-}
-
-namespace Aarch64 {
-
-enum Spsr
-{
-  Spsr_m_sp      = 1UL << 0,
-  Spsr_m_el0t    = 0,
-  Spsr_m_el1h    = (1UL << 2) | Spsr_m_sp,
-  Spsr_m_aarch32 = 1UL << 4,
-  Spsr_m_mask    = 0x1f,
-
-  Spsr_f = 1UL << 6,
-  Spsr_i = 1UL << 7,
-  Spsr_a = 1UL << 8,
-  Spsr_d = 1UL << 9,
-
-  Spsr_ssbs = 1UL << 12,
-  Spsr_pan  = 1UL << 22,
-  Spsr_dit  = 1UL << 24,
-
-  Spsr_v = 1UL << 28,
-  Spsr_c = 1UL << 29,
-  Spsr_z = 1UL << 30,
-  Spsr_n = 1UL << 31,
-};
-
-enum Sctlr_el1
-{
-  Sctlr_el1_span = 1ULL << 23,
-  Sctlr_el1_dssbs = 1ULL << 44,
-};
-
-enum Vector
-{
-  Vector_current_el_sp_el0 = 0,
-  Vector_current_el_sp_elx = 0x200,
-  Vector_lower_el_aarch64  = 0x400,
-  Vector_lower_el_aarch32  = 0x600,
-};
-
-inline bool is_aarch32(unsigned mode)
-{
-  return mode & Spsr_m_aarch32;
-}
-
-/**
- * Derive the PSTATE flags for an Aarch64 exception handler handling an
- * exception taken from Aarch32 or Aarch64 state.
- *
- * The layout of SPSR differs slightly depending on whether the exception is
- * taken from Aarch32 or Aarch64 state. However, we do not need to differentiate
- * between these two scenarios here, as the differences are limited to flags
- * that are not relevant for deriving the PSTATE flags for an Aarch64 exception
- * handler.
- *
- * \param vcpu  vCPU on which the exception is taken
- * \param mode  Mode to which the exception is taken
- *
- * \return PSTATE flags for the exception handler.
- */
-inline l4_umword_t get_except_flags(Vcpu_ptr vcpu, l4_umword_t mode)
-{
-  // TODO: Fiasco only saves/restores the lower 32-bit of SCTRL, thus the below
-  //       test for Sctlr_el1_dssbs will always fail.
-  l4_umword_t sctlr = l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_SCTLR);
-  l4_umword_t old_flags = vcpu->r.flags;
-  l4_umword_t new_flags = 0;
-
-  // The condition flags are preserved
-  new_flags |= old_flags & (Spsr_n | Spsr_z | Spsr_c | Spsr_v);
-
-  // PSTATE.DIT is preserved
-  new_flags |= old_flags & Spsr_dit;
-
-  // PSTATE.UAO is set to 0
-
-  // PSTATE.PAN is preserved unless overridden by SCTLR_ELx.SPAN
-  new_flags |= (old_flags & Spsr_pan);
-  if (!(sctlr & Sctlr_el1_span))
-    new_flags |= Spsr_pan;
-
-  // PSTATE.SS and PSTATE.IL are set to 0
-
-  // PSTATE.SSBS is set to SCTLR_ELx.DSSBS
-  if (sctlr & Sctlr_el1_dssbs)
-    new_flags |= Spsr_ssbs;
-
-  // PSTATE.BTYPE is set to 0
-
-  // The exception mask bits are set
-  new_flags |= Spsr_d | Spsr_a |  Spsr_i | Spsr_f;
-
-  // PSTATE.M is set to the mode to which the exception is taken
-  new_flags |= mode;
-
-  return new_flags;
-}
-
-/**
- * Get the offset in the vector table depending on both the mode in which the
- * exception occurred and the mode to which it is taken.
- *
- * \param mode         Mode in which the exception occurred
- * \param target_mode  Mode to which the exception is taken
- *
- * \return Vector table offset
- */
-inline unsigned get_except_offset(l4_umword_t mode, l4_umword_t target_mode)
-{
-  if (mode == target_mode)
-    return Vector_current_el_sp_elx;
-  else if ((mode | Spsr_m_sp) == target_mode)
-    return Vector_current_el_sp_el0;
-  else if (!is_aarch32(mode))
-    return Vector_lower_el_aarch64;
-  else
-    return Vector_lower_el_aarch32;
-}
-
-inline Hsr get_abort_esr(Vcpu_ptr vcpu, bool inst)
-{
-  Hsr esr { 0 };
-  esr.il() = vcpu.hsr().il();
-
-  l4_umword_t mode = vcpu->r.flags & Spsr_m_mask;
-  bool from_lower = is_aarch32(mode) || (mode == Spsr_m_el0t);
-  if (inst)
-    esr.ec() = from_lower ? Hsr::Ec_iabt_low : Hsr::Ec_iabt_cur;
-  else
-    esr.ec() = from_lower ? Hsr::Ec_dabt_low : Hsr::Ec_dabt_cur;
-
-  esr.pf_fsc() = Hsr::Fsc_sync_ext_abt;
-  return esr;
-}
-
-}
-
-}
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/arm_hyp.h b/src/l4/pkg/uvmm/server/src/arm/arm_hyp.h
deleted file mode 100644
index d2386222..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/arm_hyp.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2013-2021, 2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-namespace Vmm {
-namespace Arm {
-
-class Hsr
-{
-public:
-  Hsr() = default;
-  explicit Hsr(l4_uint32_t ec) : _raw(ec) {}
-  l4_uint32_t _raw;
-
-  l4_uint32_t raw() const { return _raw; }
-
-  enum Fsc
-  {
-    Fsc_sync_ext_abt = 0x10,
-  };
-
-  enum Ec
-  {
-    Ec_unknown  = 0x0,
-    Ec_iabt_low = 0x20,
-    Ec_iabt_cur = 0x21,
-    Ec_dabt_low = 0x24,
-    Ec_dabt_cur = 0x25,
-  };
-
-  CXX_BITFIELD_MEMBER(26, 31, ec, _raw);
-  CXX_BITFIELD_MEMBER(25, 25, il, _raw);
-  CXX_BITFIELD_MEMBER(24, 24, cv, _raw);
-  CXX_BITFIELD_MEMBER(20, 23, cond, _raw);
-
-  /** \pre ec == 0x01 */
-  CXX_BITFIELD_MEMBER( 0,  0, wfe_trapped, _raw);
-
-  CXX_BITFIELD_MEMBER(17, 19, mcr_opc2, _raw);
-  CXX_BITFIELD_MEMBER(16, 19, mcrr_opc1, _raw);
-  CXX_BITFIELD_MEMBER(14, 16, mcr_opc1, _raw);
-  CXX_BITFIELD_MEMBER(10, 13, mcr_crn, _raw);
-  CXX_BITFIELD_MEMBER(10, 13, mcrr_rt2, _raw);
-  CXX_BITFIELD_MEMBER( 5,  9, mcr_rt, _raw);  // bit 9 reserved in AArch32
-  CXX_BITFIELD_MEMBER( 1,  4, mcr_crm, _raw);
-  CXX_BITFIELD_MEMBER( 0,  0, mcr_read, _raw);
-
-  CXX_BITFIELD_MEMBER(20, 21, msr_op0, _raw);
-  CXX_BITFIELD_MEMBER(17, 19, msr_op2, _raw);
-  CXX_BITFIELD_MEMBER(14, 16, msr_op1, _raw);
-  CXX_BITFIELD_MEMBER(10, 13, msr_crn, _raw);
-  CXX_BITFIELD_MEMBER( 5,  9, msr_rt, _raw);
-  CXX_BITFIELD_MEMBER( 1,  4, msr_crm, _raw);
-  CXX_BITFIELD_MEMBER( 0,  0, msr_read, _raw);
-  unsigned msr_sysreg() const { return _raw & 0x00fffc1e; }
-  static constexpr unsigned
-  msr_sysreg(unsigned op0, unsigned op1, unsigned crn,
-             unsigned crm, unsigned op2)
-  {
-    return   (op0 << 20) | (op2 << 17) | (op1 << 14)
-           | (crn << 10) | (crm << 1);
-  }
-
-  unsigned msr_sysreg_n() const { return _raw & 0x00fffc00; }
-  static constexpr unsigned
-  msr_sysreg_n(unsigned op0, unsigned op1, unsigned crn,
-             unsigned op2)
-  {
-    return   (op0 << 20) | (op2 << 17) | (op1 << 14)
-           | (crn << 10);
-  }
-
-  CXX_BITFIELD_MEMBER(12, 19, ldc_imm, _raw);
-  CXX_BITFIELD_MEMBER( 5,  8, ldc_rn, _raw);
-  CXX_BITFIELD_MEMBER( 4,  4, ldc_offset_form, _raw);
-  CXX_BITFIELD_MEMBER( 1,  3, ldc_addressing_mode, _raw);
-
-  CXX_BITFIELD_MEMBER( 5,  5, cpt_simd, _raw);
-  CXX_BITFIELD_MEMBER( 0,  3, cpt_cpnr, _raw);
-
-  CXX_BITFIELD_MEMBER( 0,  3, bxj_rm, _raw);
-
-  CXX_BITFIELD_MEMBER( 0, 15, svc_imm, _raw);
-
-  CXX_BITFIELD_MEMBER(24, 24, pf_isv, _raw);
-  CXX_BITFIELD_MEMBER(22, 23, pf_sas, _raw);
-  CXX_BITFIELD_MEMBER(21, 21, pf_sse, _raw);
-  CXX_BITFIELD_MEMBER(16, 20, pf_srt, _raw);
-  CXX_BITFIELD_MEMBER(15, 15, pf_sf, _raw);
-  CXX_BITFIELD_MEMBER(14, 14, pf_ar, _raw);
-  CXX_BITFIELD_MEMBER( 9,  9, pf_ea, _raw);
-  CXX_BITFIELD_MEMBER( 8,  8, pf_cache_maint, _raw);
-  CXX_BITFIELD_MEMBER( 7,  7, pf_s1ptw, _raw);
-  CXX_BITFIELD_MEMBER( 6,  6, pf_write, _raw);
-  CXX_BITFIELD_MEMBER( 0,  5, pf_fsc, _raw);
-};
-
-enum Ttbcr
-{
-  Ttbcr_eae = 1UL << 31,
-};
-
-namespace Gic_h {
-
-  struct Hcr
-  {
-    l4_uint32_t raw;
-    Hcr() = default;
-    explicit Hcr(l4_uint32_t v) : raw(v) {}
-    CXX_BITFIELD_MEMBER(  0,  0, en, raw);
-    CXX_BITFIELD_MEMBER(  1,  1, uie, raw);
-    CXX_BITFIELD_MEMBER(  2,  2, lr_en_pie, raw);
-    CXX_BITFIELD_MEMBER(  3,  3, n_pie, raw);
-    CXX_BITFIELD_MEMBER(  4,  4, vgrp0_eie, raw);
-    CXX_BITFIELD_MEMBER(  5,  5, vgrp0_die, raw);
-    CXX_BITFIELD_MEMBER(  6,  6, vgrp1_eie, raw);
-    CXX_BITFIELD_MEMBER(  7,  7, vgrp1_die, raw);
-    CXX_BITFIELD_MEMBER( 27, 31, eoi_cnt, raw);
-  };
-
-  struct Vtr
-  {
-    l4_uint32_t raw;
-    Vtr() = default;
-    explicit Vtr(l4_uint32_t v) : raw(v) {}
-    CXX_BITFIELD_MEMBER(  0,  5, list_regs, raw);
-    CXX_BITFIELD_MEMBER( 26, 28, pre_bits, raw);
-    CXX_BITFIELD_MEMBER( 29, 31, pri_bits, raw);
-  };
-
-  struct Vmcr
-  {
-    l4_uint32_t raw;
-    Vmcr() = default;
-    explicit Vmcr(l4_uint32_t v) : raw(v) {}
-    CXX_BITFIELD_MEMBER(  0,  0, grp0_en, raw);
-    CXX_BITFIELD_MEMBER(  1,  1, grp1_en, raw);
-    CXX_BITFIELD_MEMBER(  2,  2, ack_ctl, raw);
-    CXX_BITFIELD_MEMBER(  3,  3, fiq_en, raw);
-    CXX_BITFIELD_MEMBER(  4,  4, cbpr, raw);
-    CXX_BITFIELD_MEMBER(  9,  9, vem, raw);
-    CXX_BITFIELD_MEMBER( 18, 20, abp, raw);
-    CXX_BITFIELD_MEMBER( 21, 23, bp, raw);
-    CXX_BITFIELD_MEMBER( 27, 31, pri_mask, raw);
-  };
-
-  struct Misr
-  {
-    l4_uint32_t raw;
-    Misr() = default;
-    explicit Misr(l4_uint32_t v) : raw(v) {}
-    CXX_BITFIELD_MEMBER(  0,  0, eoi, raw);
-    CXX_BITFIELD_MEMBER(  1,  1, u, raw);
-    CXX_BITFIELD_MEMBER(  2,  2, lrenp, raw);
-    CXX_BITFIELD_MEMBER(  3,  3, np, raw);
-    CXX_BITFIELD_MEMBER(  4,  4, grp0_e, raw);
-    CXX_BITFIELD_MEMBER(  5,  5, grp0_d, raw);
-    CXX_BITFIELD_MEMBER(  6,  6, grp1_e, raw);
-    CXX_BITFIELD_MEMBER(  7,  7, grp1_d, raw);
-  };
-
-  struct Lr
-  {
-    enum State
-    {
-      Empty              = 0,
-      Pending            = 1,
-      Active             = 2,
-      Active_and_pending = 3
-    };
-
-    l4_uint32_t raw;
-    Lr() = default;
-    explicit Lr(l4_uint32_t v) : raw(v) {}
-    CXX_BITFIELD_MEMBER(  0,  9, vid, raw);
-    CXX_BITFIELD_MEMBER( 10, 19, pid, raw);
-    CXX_BITFIELD_MEMBER( 10, 12, cpuid, raw);
-    CXX_BITFIELD_MEMBER( 19, 19, eoi, raw);
-    CXX_BITFIELD_MEMBER( 23, 27, prio, raw);
-    CXX_BITFIELD_MEMBER( 28, 29, state, raw);
-    CXX_BITFIELD_MEMBER( 28, 28, pending, raw);
-    CXX_BITFIELD_MEMBER( 29, 29, active, raw);
-    CXX_BITFIELD_MEMBER( 30, 30, grp1, raw);
-    CXX_BITFIELD_MEMBER( 31, 31, hw, raw);
-
-    void set_cpuid(unsigned cpu) { cpuid() = cpu; }
-  };
-
-  struct Vcpu_irq_cfg
-  {
-    l4_umword_t raw;
-    Vcpu_irq_cfg() = default;
-    explicit Vcpu_irq_cfg(l4_umword_t v) : raw(v) {}
-
-    CXX_BITFIELD_MEMBER(  0, 19,  vid, raw);
-    CXX_BITFIELD_MEMBER( 23, 23, grp1, raw);
-    CXX_BITFIELD_MEMBER( 24, 31, prio, raw);
-  };
-
-  struct Vcpu_ppi_cfg
-  {
-    l4_uint32_t raw;
-    Vcpu_ppi_cfg() = default;
-    explicit Vcpu_ppi_cfg(l4_uint32_t v) : raw(v) {}
-
-    CXX_BITFIELD_MEMBER(  0,  4, vid, raw);       ///< PPI irq id in LR
-    CXX_BITFIELD_MEMBER( 16, 16, direct, raw);    ///< directly inject into vcpu
-    CXX_BITFIELD_MEMBER( 17, 17, enabled, raw);   ///< vtimer ppi enabled
-    CXX_BITFIELD_MEMBER( 18, 18, pending, raw);   ///< vtimer ppi pending
-    CXX_BITFIELD_MEMBER( 19, 19, active, raw);    ///< vtimer ppi active
-    CXX_BITFIELD_MEMBER( 23, 23, grp1, raw);      ///< set if group1 irq
-    CXX_BITFIELD_MEMBER( 24, 31, vgic_prio, raw); ///< Prio value in vgic LR
-  };
-
-  /**
-   * Initialize the vCPU state for virtual GIC support.
-   */
-  inline void init_vcpu(void *vcpu)
-  {
-    Vmcr vmcr(0);
-    vmcr.bp() = 2; // lowest possible value for 32 prios
-    vmcr.abp() = 2;
-    l4_vcpu_e_write_32(vcpu, L4_VCPU_E_GIC_VMCR, vmcr.raw);
-
-    // enable the interface and some maintenance settings
-    Hcr hcr(0);
-    hcr.en() = 1;
-    hcr.vgrp0_eie() = 1;
-    hcr.vgrp1_eie() = 1;
-    l4_vcpu_e_write_32(vcpu, L4_VCPU_E_GIC_HCR, hcr.raw);
-  }
-}
-
-}
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/atomic_fwd_list.h b/src/l4/pkg/uvmm/server/src/arm/atomic_fwd_list.h
deleted file mode 100644
index dd6810ef..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/atomic_fwd_list.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2021-2024 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-/**
- * Item on an Atomic_fwd_list.
- */
-class Atomic_fwd_list_item
-{
-  template
-  friend class Atomic_fwd_list;
-
-  enum {
-    // Element is not in a list. Distinct from nullptr which is is the end of
-    // list.
-    Not_in_list = 1,
-  };
-
-public:
-  Atomic_fwd_list_item()
-  : _next(reinterpret_cast(Not_in_list)) {}
-
-  bool in_list() const
-  {
-    return _next != reinterpret_cast(Not_in_list);
-  }
-
-private:
-  explicit Atomic_fwd_list_item(Atomic_fwd_list_item *n) : _next(n) {}
-
-  Atomic_fwd_list_item *_next;
-};
-
-/**
- * A lock-free, multi producer list.
- *
- * Items that are stored on the list must be derived from Atomic_fwd_list_item.
- * The only supported concurrent methods are push() and swap(). Multiple
- * threads may push(), even the same element, onto a list. On the consumer
- * side, swap() must be used to atomically take ownership of the list and
- * replace it with an empty one. All other methods are *not* thread safe and
- * must only be used after swap() was used to have exclusive access to the
- * list. Internally it is a single linked list.
- */
-template
-class Atomic_fwd_list
-{
-public:
-  Atomic_fwd_list() : _head(nullptr) {}
-
-  class Iterator
-  {
-    friend class Atomic_fwd_list;
-
-  public:
-    Iterator() : _elem(nullptr), _prev_next_ptr(nullptr) {}
-
-    Iterator operator++()
-    {
-      _prev_next_ptr = &_elem->_next;
-      _elem = _elem->_next;
-      return *this;
-    }
-
-    T *operator*() const { return static_cast(_elem); }
-    T *operator->() const { return static_cast(_elem); }
-
-    bool operator==(Iterator const &other) const
-    { return other._elem == _elem; }
-    bool operator!=(Iterator const &other) const
-    { return other._elem != _elem; }
-
-  private:
-    Iterator(Atomic_fwd_list_item **prev_next_ptr, Atomic_fwd_list_item *elem)
-    : _elem(elem), _prev_next_ptr(prev_next_ptr)
-    {}
-
-    /**
-     * Construct iterator to first element on the list.
-     *
-     * \param head_next_ptr Pointer to the _next-pointer of the list head.
-     */
-    explicit Iterator(Atomic_fwd_list_item **head_next_ptr)
-    : _elem(*head_next_ptr), _prev_next_ptr(head_next_ptr)
-    {}
-
-    /**
-     * Construct (invalid) iterator that points to before the first element.
-     *
-     * \param head Pointer to list head.
-     */
-    explicit Iterator(Atomic_fwd_list_item *head)
-    : _elem(head), _prev_next_ptr(nullptr)
-    {}
-
-    /// The current element to which the iterator points.
-    Atomic_fwd_list_item *_elem;
-
-    /**
-     * Pointer to _next pointer of previous element that points to _elem.
-     *
-     * For valid iterators "*_prev_next_ptr == _elem" holds.
-     */
-    Atomic_fwd_list_item **_prev_next_ptr;
-  };
-
-  Iterator before_begin() { return Iterator(&_head); }
-  Iterator begin() { return Iterator(&_head._next); }
-  Iterator end() { return Iterator(); }
-
-  /**
-   * Add element to front of list.
-   *
-   * It is safe against concurrent insert attempts, even of the same element.
-   * This is achieved by synchronizing on the _next pointer. Elements that are
-   * not on a list are marked as "logically deleted" (Not_in_list), as done by
-   * erase(). This guarantees that the object is currently not visible on the
-   * list. If setting that pointer fails, some other thread was faster and the
-   * element is being inserted currently.
-   *
-   * We do *not* wait until being inserted if the _next pointer could not be
-   * set. It is the responsibility of the caller to cope with the possibility
-   * that the element is not yet visible on the list on such concurrent
-   * inserts.
-   */
-  void push(T *e)
-  {
-    Atomic_fwd_list_item *old_next = __atomic_load_n(&e->_next, __ATOMIC_ACQUIRE);
-    if (old_next !=
-        reinterpret_cast(Atomic_fwd_list_item::Not_in_list))
-      return;
-
-    Atomic_fwd_list_item *first = __atomic_load_n(&_head._next, __ATOMIC_ACQUIRE);
-    if (!__atomic_compare_exchange_n(&e->_next, &old_next, first,
-                                     false, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
-      return;
-
-    // We now "own" the element and must complete the insert. It's not yet
-    // visible on the list. There could still be other concurrent inserts on
-    // the same list for different elements, though.
-    while (!__atomic_compare_exchange_n(&_head._next, &first,
-                                        static_cast(e),
-                                        true, __ATOMIC_ACQ_REL,
-                                        __ATOMIC_ACQUIRE))
-      __atomic_store_n(&e->_next, first, __ATOMIC_RELEASE);
-  }
-
-  /**
-   * Atomically swap this and the other list.
-   *
-   * The content of this instance must no be manipulated concurrently.
-   * Atomicity is only guaranteed wrt. the \a other list.
-   */
-  void swap(Atomic_fwd_list &other)
-  {
-    Atomic_fwd_list_item *cur = _head._next;
-    Atomic_fwd_list_item *o = __atomic_load_n(&other._head._next,
-                                              __ATOMIC_RELAXED);
-    while (!__atomic_compare_exchange_n(&other._head._next, &o, cur, false,
-                                        __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
-      ;
-
-    _head._next = o;
-  }
-
-  /**
-   * Remove item from list.
-   *
-   * This method is *not* thread safe. There must be no concurrent
-   * manipulations of the list!
-   */
-  static Iterator erase(Iterator const &e)
-  {
-    Iterator ret(e._prev_next_ptr, e._elem->_next);
-    *e._prev_next_ptr = e._elem->_next;
-    __atomic_store_n(&e._elem->_next,
-                     reinterpret_cast(Atomic_fwd_list_item::Not_in_list),
-                     __ATOMIC_RELEASE);
-    return ret;
-  }
-
-  /**
-   * Move item from \a other list to this one after \a pos.
-   *
-   * The moved element is always seen as if it is on a list. Protects against
-   * concurrent push() calls for the element that is moved between the lists.
-   * This method is *not* thread safe.
-   *
-   * \return Iterator pointing to element after \a e on the \a other list.
-   */
-  static Iterator move_after(Iterator const &pos, Atomic_fwd_list& /*other*/,
-                             Iterator const &e)
-  {
-    Iterator ret(e._prev_next_ptr, e._elem->_next);
-
-    *e._prev_next_ptr = e._elem->_next;
-    e._elem->_next = pos._elem->_next;
-    pos._elem->_next = e._elem;
-
-    return ret;
-  }
-
-private:
-  Atomic_fwd_list_item _head;
-};
diff --git a/src/l4/pkg/uvmm/server/src/arm/binary_loader_linux.cc b/src/l4/pkg/uvmm/server/src/arm/binary_loader_linux.cc
deleted file mode 100644
index b3000509..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/binary_loader_linux.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader_linux.h"
-#include "guest_subarch.h"
-
-namespace Boot {
-
-int Linux_loader::load(char const * /*bin*/, std::shared_ptr image,
-                       Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-                       l4_addr_t *entry)
-{
-  trace().printf("Checking for Linux image...\n");
-
-  if (!image->is_valid())
-    return -L4_EINVAL;
-
-  Vmm::Guest_addr ram_base = free_list->first_free_address();
-  unsigned char const *h = static_cast(image->get_data());
-
-  if (Vmm::Guest_64bit_supported
-      && h[0x38] == 0x41 && h[0x39] == 0x52
-      && h[0x3A] == 0x4d && h[0x3B] == 0x64) // Linux header ARM\x64
-  {
-    l4_uint64_t l = *reinterpret_cast(&h[8]);
-    *entry = image->load_as_raw(ram, ram_base + l, free_list);
-    _64bit = true;
-  }
-  else if (   h[0x24] == 0x18 && h[0x25] == 0x28
-           && h[0x26] == 0x6f && h[0x27] == 0x01) // Linux magic
-  {
-    l4_uint32_t l = *reinterpret_cast(&h[0x28]);
-    // Bytes 0x2c-0x2f have the zImage size
-    *entry = image->load_as_raw(ram, ram_base + l, free_list);
-  }
-  else if (h[0] == 0x1f && h[1] == 0x8b && h[2] == 0x08)
-    {
-    // Gzip compressed kernel images are not self-decompressing on ARM
-    L4Re::throw_error(-L4_EINVAL,
-      "Cannot boot compressed images! Unzip first or enable uvmm gzip support.");
-    }
-  else
-    return -L4_EINVAL;
-
-  info().printf("Linux kernel detected\n");
-
-  return L4_EOK;
-}
-
-static Linux_loader f __attribute__((init_priority(Boot::Linux)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/binary_loader_raw.h b/src/l4/pkg/uvmm/server/src/arm/binary_loader_raw.h
deleted file mode 100644
index a7531997..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/binary_loader_raw.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-namespace Boot {
-
-static int raw_load_image(std::shared_ptr image, Vmm::Vm_ram *ram,
-                          Vmm::Ram_free_list *free_list,
-                          l4_addr_t *entry)
-{
-  if (*entry == ~0ul)
-    *entry = 0x208000;
-
-  // Get the RAM start address.
-  Vmm::Guest_addr ram_base = free_list->first_free_address();
-  *entry = image->load_as_raw(ram, ram_base + *entry, free_list);
-
-  return L4_EOK;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/core_timer.h b/src/l4/pkg/uvmm/server/src/arm/core_timer.h
deleted file mode 100644
index d6951e2b..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/core_timer.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2016-2018, 2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-
-#include "device.h"
-#include "gic_iface.h"
-#include "irq.h"
-#include "vcpu_ptr.h"
-
-namespace Vdev {
-
-class Cpu_timer_irq : public Gic::Irq_src_handler
-{
-  Vmm::Vcpu_ptr _vcpu;
-
-public:
-  Cpu_timer_irq(Vmm::Vcpu_ptr vcpu) : _vcpu(vcpu) {}
-
-  void configure(l4_umword_t cfg) override
-  {
-    Vmm::Arm::Gic_h::Vcpu_irq_cfg c(cfg);
-
-    Vmm::Arm::Gic_h::Vcpu_ppi_cfg v = _vcpu.vtmr();
-    v.grp1() = c.grp1();
-    v.vgic_prio() = c.prio();
-    _vcpu.vtmr(v);
-  }
-
-  bool enable() override
-  {
-    Vmm::Arm::Gic_h::Vcpu_ppi_cfg v = _vcpu.vtmr();
-    v.enabled() = 1;
-    _vcpu.vtmr(v);
-
-    // We don't really know if Fiasco will take care because it's an optional
-    // feature. But if it does then we'll never see an guest_ppi(1) so this is
-    // safe...
-    return false;
-  }
-
-  void disable() override
-  {
-    Vmm::Arm::Gic_h::Vcpu_ppi_cfg v = _vcpu.vtmr();
-    v.enabled() = 0;
-    _vcpu.vtmr(v);
-  }
-};
-
-
-struct Core_timer : public Device, public Vmm::Irq_edge_sink
-{
-  Core_timer(cxx::Ref_ptr const &ic, int irq, Dt_node const &self)
-  : Irq_edge_sink(ic, irq)
-  {
-    init_tick_conversion(self);
-  }
-  /*
-   * We use "scaling math" as described in a comment in
-   * linux/arch/x86/kernel/tsc.c. We use micro seconds instead of nano
-   * seconds and adjust the math accordingly.
-   *
-   * convert from cycles(32bits) => microseconds (32Bit), ms 64Bit
-   *   basic equation:
-   *              ms = cycles / (freq / ms_per_sec)
-   *              ms = cycles * (ms_per_sec / freq)
-   *              ms = cycles * (10^6 / (timer_khz * 10^3))
-   *              ms = cycles * (10^3 / timer_khz)
-   *
-   *      Then we use scaling math (suggested by george@mvista.com) to get:
-   *              ms = cycles * (10^3 * 2^SC / timer_khz) / 2^SC
-   *
-   *              cyc2ms_scale = (10^3 * 2^SC / timer_khz)
-   *              ms = cycles * cyc2ms_scale / 2^SC
-   *
-   *
-   * We select SC so that cyc2ms_scale is the largest scaling factor
-   * fitting into a 32Bit und use a simple shift for the division by
-   * 2^SC.
-   */
-
-  /**
-   * Convert timer ticks into micro seconds
-   *
-   * \param ticks Number of timer ticks
-   * \return Number of microseconds
-   */
-  l4_uint64_t get_micro_seconds(l4_uint64_t ticks)
-  {
-    if (L4_LIKELY((ticks >> 32) == 0))
-      {
-        /*
-         * With a time tick rate of 1GHz this will cover up to 49
-         * days. On Arm we have timer rates specified in MHz, so this
-         * will last even longer.
-         *
-         * The calculation rounds down and delivers a timeout that
-         * triggers up to 1 microsecond early.
-         */
-        l4_uint64_t tmp = static_cast(ticks);
-        return ((tmp * _cyc2ms_scale) >> _shift);
-      }
-
-    /*
-     * We divide first to prevent overflows. This will make it a little bit less
-     * precise, but this path should not be taken anyway.
-     */
-    return (ticks / _scaled_ticks_per_us) * _scale;
-  }
-
-  /**
-   * Calculate constants used to convert timer ticks (> 2^32) into
-   * micro seconds. Sets member variables _scaled_ticks_per_us and
-   * _scale. Assumes a timer rate >= 1Mhz
-   *
-   * \param freq Rate of the timer (e.g. 12.5Mhz = 12500000)
-   */
-  void init_large_scale(l4_uint32_t freq)
-  {
-    // Scale factors for numbers >= 2^32
-    _scale = 1000000; // micro seconds per second
-    _scaled_ticks_per_us = freq;
-    assert(_scale <= _scaled_ticks_per_us);
-
-    while ((_scale > 1) && (_scaled_ticks_per_us % 10 == 0))
-      {
-        _scale /= 10;
-        _scaled_ticks_per_us /= 10;
-      }
-    if ((_scale > 1) && (_scaled_ticks_per_us % 10 == 5))
-      {
-        _scale /= 5;
-        _scaled_ticks_per_us /= 5;
-      }
-  }
-
-  /**
-   * Calculate constants used to convert timer ticks (< 2^32) into
-   * micro seconds. Sets member variables _cyc2ms_scale and
-   * _shift. Assumes a timer rate >= 1Khz
-   *
-   * \param freq Rate of the timer (e.g. 12.5Mhz = 12500000)
-   */
-  void init_normal_scale(l4_uint32_t freq)
-  {
-    assert(freq >= 1000);
-    l4_uint32_t timer_khz = freq / 1000;
-    for (int i = 12; i < 30; ++i)
-      {
-        l4_uint64_t scale = (1000ULL << i) / timer_khz;
-        if (scale >= (1ULL << 32))
-          return;
-
-        _cyc2ms_scale = static_cast(scale);
-        _shift = i;
-      }
-  }
-
-  void init_tick_conversion(Dt_node const &self)
-  {
-    char const * frq_prop = "clock-frequency";
-    unsigned int cntfrq;
-    int size;
-
-    auto prop = self.get_prop(frq_prop, &size);
-    cntfrq = Vmm::Vcpu_ptr::cntfrq();
-
-    if (prop)
-      {
-        unsigned int freq = fdt32_to_cpu(*prop);
-        if (freq != cntfrq)
-          {
-            /* Arm ref manual, CNTFRQ{,_EL0}: This register is
-             * provided so that software can discover the frequency of
-             * the system counter. It must be programmed with this
-             * value as part of system initialization. The value of
-             * the register is not interpreted by hardware.
-             *
-             * We assume, that the system initialization sets the
-             * register correctly and update the device tree
-             * accordingly. We warn about this, since this might
-             * indicate that the device tree currently used does not
-             * match the actual hardware.
-             */
-            Dbg(Dbg::Cpu, Dbg::Warn, "Timer")
-              .printf("Updating %s.%s : %u -> %u\n"
-                      "\tDevice tree might not match used hardware.\n",
-                      self.get_name(), frq_prop, freq, cntfrq);
-            self.setprop_u32(frq_prop, cntfrq);
-          }
-      }
-
-    init_large_scale(cntfrq);
-    init_normal_scale(cntfrq);
-
-    Dbg(Dbg::Cpu, Dbg::Info, "Timer")
-      .printf("Guest timer frequency is %d\n"
-              "using (%d/%d), (%d/%d) to calculate timeouts\n",
-              cntfrq, _scale, _scaled_ticks_per_us, _cyc2ms_scale, _shift);
-  }
-
-  void add_cpu(Vmm::Vcpu_ptr vcpu)
-  {
-    Vmm::Arm::Gic_h::Vcpu_ppi_cfg cfg(0);
-    cfg.vid() = irq();
-    cfg.direct() = 1;
-    vcpu.vtmr(cfg);
-
-    auto timer = cxx::make_unique(vcpu);
-
-    dynamic_cast(ic())
-      ->bind_cpulocal_irq_src_handler(vcpu.get_vcpu_id(), irq(), timer.get());
-    _per_cpu_timers[vcpu.get_vcpu_id()] = cxx::move(timer);
-  }
-
-private:
-  l4_uint32_t _scale, _scaled_ticks_per_us;
-  l4_uint32_t _cyc2ms_scale, _shift;
-  std::map> _per_cpu_timers;
-};
-
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/cpu_dev.h b/src/l4/pkg/uvmm/server/src/arm/cpu_dev.h
deleted file mode 100644
index eb9c067c..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/cpu_dev.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "generic_cpu_dev.h"
-#include "monitor/cpu_dev_cmd_handler.h"
-
-extern __thread unsigned vmm_current_cpu_id;
-
-namespace Vmm {
-
-class Cpu_dev
-: public Generic_cpu_dev,
-  public Monitor::Cpu_dev_cmd_handler
-{
-  /**
-   * Trivial interrupt to wakeup stopped vCPU.
-   */
-  struct Restart_event : public L4::Irqep_t
-  {
-  public:
-    void handle_irq() {}
-  };
-
-public:
-  // CPU 255 is used as "invalid CPU" by the GIC code...
-  enum { Max_cpus = 254 };
-
-  enum
-  {
-    Flags_default_32 = 0x1d3,
-    Flags_default_64 = 0x1c5,
-    Flags_mode_32 = (1 << 4)
-  };
-
-  /**
-   * CPU states according to the PSCI spec
-   */
-  enum class Cpu_state
-  {
-    Off,
-    On_pending,
-    On_prepared,
-    On
-  };
-
-  Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *);
-
-  void powerup_cpu() override;
-
-  bool
-  start_vcpu()
-  {
-    if (online_state() != Cpu_state::On_pending)
-      {
-        // Should we convert this to an assert()?
-        Err().printf("%s: CPU%d not in On_pending state", __func__, _phys_cpu_id);
-        return false;
-      }
-
-    Dbg(Dbg::Cpu, Dbg::Info)
-      .printf("Initiating cpu startup @ 0x%lx\n", _vcpu->r.ip);
-
-    if (_vcpu->entry_sp && !restart())
-      {
-        mark_off();
-        return false;
-      }
-    else
-      reschedule();
-
-    return true;
-  }
-
-  /**
-   * Enter the virtual machine
-   *
-   * We assume an already setup register state that can be used as is
-   * to enter the virtual machine (it was not changed by
-   * vcpu_control_ext()). The virtualization related state is set to
-   * default values, therefore we have to initialize this state here.
-   */
-  void L4_NORETURN reset() final override;
-
-  /**
-   * Restart a CPU
-   *
-   * Restarts a stopped CPU and enters the virtual machine using reset().
-   *
-   * \return Returns true if restart was successful, false otherwise.
-   */
-  bool restart();
-
-  /**
-   * Stop a CPU
-   */
-  void L4_NORETURN stop() override;
-
-  /**
-   * Get the online state of a CPU.
-   */
-  Cpu_state online_state() const
-  { return std::atomic_load(&_online); }
-
-  /**
-   * Is the CPU online?
-   */
-  bool online() const
-  { return online_state() != Cpu_state::Off; }
-
-  /**
-   * Cpu_state changes
-   * * Off -> On_pending:          concurrent execution
-   * * On_pending  -> On:          CPU local, no concurrency (initial startup)
-   * * On_pending  -> On_prepared: CPU local, no concurrency (restart)
-   * * On_prepared -> On:          CPU local, no concurrency (restart)
-   * * On* -> Off:                 CPU local, no concurrency
-   *
-   * The only state change that requires protection against concurrent access
-   * is the change from Off to On_pending. Therefore mark_pending() uses
-   * compare/exchange, the other operation use a simple store.
-   */
-
-  /**
-   * Mark CPU as On_pending.
-   *
-   * \retval True  Successfully changed state from Off to On_pending
-   * \retval False  Failed to change the state from Off to On_pending,
-   *                the state was already changed by someone else.
-   */
-  bool mark_on_pending()
-  {
-    // Atomically change state from Off to On_pending, see above
-    Cpu_state expected{Cpu_state::Off};
-    return std::atomic_compare_exchange_strong(&_online, &expected,
-                                               Cpu_state::On_pending);
-  }
-
-  /**
-   * Mark CPU as On_prepared.
-   *
-   * The vCPU entry has been setup and the guest is about to be entered
-   * again. This state is only used when restarting a CPU that was previously
-   * powered off.
-   */
-  void mark_on_prepared()
-  {
-    assert(online_state() == Cpu_state::On_pending);
-    std::atomic_store(&_online, Cpu_state::On_prepared);
-  }
-
-  /**
-   * Mark CPU as Off.
-   *
-   * Marks the CPU as Off. The current state has to be either On (CPU is
-   * switched off) or On_pending (we failed to get the CPU up and fall
-   * back to Off)
-   */
-  void mark_off()
-  {
-    assert(online_state() != Cpu_state::Off);
-    std::atomic_store(&_online, Cpu_state::Off);
-  }
-
-  /**
-   * Mark CPU as On.
-   *
-   * Marks the CPU as On. The current state has to be On_pending or On_prepared.
-   */
-  void mark_on()
-  {
-    assert(online_state() == Cpu_state::On_pending ||
-           online_state() == Cpu_state::On_prepared);
-    std::atomic_store(&_online, Cpu_state::On);
-  }
-
-  /**
-   * Translate a device tree "reg" value to an internally usable CPU id.
-   *
-   * For most architectures this is NOP, but some archictures like ARM
-   * might encode topology information into this value, which needs to
-   * be translated.
-   */
-  static unsigned dtid_to_cpuid(l4_umword_t) { return 0; }
-  static bool has_fixed_dt_mapping() { return false; }
-
-  bool matches(l4_umword_t hwid)
-  { return hwid == _dt_affinity; }
-
-  bool matches(l4_umword_t hwid, char lvl)
-  {
-    l4_umword_t mask = ~0UL << (lvl * 8);
-    return ((hwid ^ _dt_affinity) & mask) == 0;
-  }
-
-  l4_umword_t affinity() const
-  { return _dt_affinity; }
-
-private:
-  enum
-  {
-    // define bits as 64 bit constants to make them usable in both
-    // 32/64 contexts
-    Mpidr_mp_ext    = 1ULL << 31,
-    Mpidr_up_sys    = 1ULL << 30,
-    Mpidr_mt_sys    = 1ULL << 24,
-    // Affinity Aff{0,1,2} in [23-0], Aff3 in [39-32]
-    Mpidr_aff_mask  = (0xffULL << 32) | 0xffffffULL,
-  };
-  l4_umword_t _dt_affinity;
-  l4_umword_t _dt_vpidr = 0;
-  std::atomic _online{Cpu_state::Off};
-  Restart_event _restart_event;
-  bool _pmsa = false;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/cpu_dev_arm.cc b/src/l4/pkg/uvmm/server/src/arm/cpu_dev_arm.cc
deleted file mode 100644
index 73ff30d5..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/cpu_dev_arm.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "cpu_dev.h"
-#include "cpu_dev_subarch.h"
-#include "arm_hyp.h"
-#include "guest.h"
-
-#include 
-#include 
-
-namespace Vmm {
-
-Cpu_dev::Cpu_dev(unsigned idx, unsigned phys_id, Vdev::Dt_node const *node)
-: Generic_cpu_dev(idx, phys_id)
-{
-  // use idx as default affinity, overwritten by device tree
-  _dt_affinity = idx;
-
-  if (node)
-    {
-      int prop_size;
-      auto *prop = node->get_prop("reg", &prop_size);
-      if (prop && prop_size > 0)
-        {
-          _dt_affinity = node->get_prop_val(prop, prop_size, true)
-            & Mpidr_aff_mask;
-        }
-
-      prop = node->get_prop("l4vmm,vpidr", &prop_size);
-      if (prop && prop_size > 0)
-        _dt_vpidr = node->get_prop_val(prop, prop_size, true);
-
-      char const *msa = node->get_prop("l4vmm,msa", nullptr);
-      if (!msa)
-        msa = node->parent_node().get_prop("l4vmm,msa", nullptr);
-
-      if (!msa || strcmp("vmsa", msa) == 0)
-        _pmsa = false;
-      else if (strcmp("pmsa", msa) == 0)
-        _pmsa = true;
-      else
-        L4Re::throw_error(-L4_EINVAL, "invalid l4vmm,msa property");
-    }
-}
-
-void
-Cpu_dev::powerup_cpu()
-{
-  Generic_cpu_dev::powerup_cpu();
-
-  // Now the vCPU thread exists and the IPC registry is setup.
-
-  auto *registry = vcpu().get_ipc_registry();
-  L4Re::chkcap(registry->register_irq_obj(&_restart_event),
-               "Cannot register CPU restart event");
-
-  _stop_irq.arm(registry);
-}
-
-void
-Cpu_dev::reset()
-{
-  // set thread local cpu id
-  vmm_current_cpu_id = _vcpu.get_vcpu_id();
-
-  //
-  // initialize hardware related virtualization state
-  //
-  Vmm::Arm::Gic_h::init_vcpu(*_vcpu);
-
-  // we set FB, and BSU to inner sharable to tolerate migrations
-  l4_umword_t hcr = 0x30023f; // VM, PTW, AMO, IMO, FMO, FB, SWIO, TIDCP, TAC
-  hcr |= 1UL << 10; // BUS = inner sharable
-  hcr |= 3UL << 13; // Trap WFI and WFE
-  l4_vcpu_e_write(*_vcpu, L4_VCPU_E_HCR, hcr);
-
-  // enable data and instruction cache (set C, I)
-  l4_umword_t sctlr = (1UL << 2) | (1UL << 12);
-  if (_vcpu->r.flags & Flags_mode_32)
-    // In AArch32 state the reset value is defined in the specification.
-    // Set SBOP bits and bits that should reset to 1 according to the ARMv7
-    // manual. Note that e.g. bit 11 is not set here because it is RES1 only
-    // in the ARMv8 manual. On ARMv7 bit 11 might be writable and resets to 0.
-    sctlr |= (1UL << 23) | (1UL << 22) | (1UL << 18) | (1UL << 16)
-          |  (1UL << 6)  | (1UL << 5)  | (1UL << 4)  | (1UL << 3);
-  // In AArch64 state the reset value is "architecturally UNKNOWN"
-  // and should be initialized properly by the guest.
-  l4_vcpu_e_write_32(*_vcpu, L4_VCPU_E_SCTLR, sctlr);
-
-  // The type of vmpidr differs between ARM32 and ARM64, so we use 64
-  // bit here as a superset.
-  l4_uint64_t vmpidr = l4_vcpu_e_read(*_vcpu, L4_VCPU_E_VMPIDR);
-
-  if (! (vmpidr &  Mpidr_mp_ext))
-    Dbg(Dbg::Cpu, Dbg::Info)
-      .printf("Vmpidr: %llx - Missing multiprocessing extension\n", vmpidr);
-
-  // remove mt/up bit and replace affinity with value from device tree
-  l4_vcpu_e_write(*_vcpu, L4_VCPU_E_VMPIDR,
-                  (vmpidr & ~(Mpidr_up_sys | Mpidr_mt_sys | Mpidr_aff_mask))
-                  | _dt_affinity);
-
-  arm_subarch_setup(*_vcpu, !(_vcpu->r.flags & Flags_mode_32), _pmsa);
-
-  if (_dt_vpidr)
-    {
-      // Override default value set by subarch_setup().
-      l4_uint32_t vpidr = l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_VPIDR);
-      Dbg().printf("Using VPIDR %lx instead of %x\n", _dt_vpidr, vpidr);
-      l4_vcpu_e_write_32(*_vcpu, L4_VCPU_E_VPIDR, _dt_vpidr);
-    }
-
-  //
-  // Initialize vcpu state
-  //
-  _vcpu->saved_state =   L4_VCPU_F_FPU_ENABLED
-                       | L4_VCPU_F_USER_MODE
-                       | L4_VCPU_F_IRQ
-                       | L4_VCPU_F_PAGE_FAULTS
-                       | L4_VCPU_F_EXCEPTIONS;
-  _vcpu->entry_ip = reinterpret_cast(&vcpu_entry);
-
-  if (!_vcpu->entry_sp)
-    {
-      // entry_sp is derived from thread local stack pointer
-      asm volatile ("mov %0, sp" : "=r"(_vcpu->entry_sp));
-    }
-  else
-    Dbg().printf("Re-using stack address %lx\n", _vcpu->entry_sp);
-
-  Dbg().printf("Starting Cpu%d @ 0x%lx in %dBit mode (handler @ %lx,"
-               " stack: %lx, task: %lx, mpidr: %llx (orig: %llx)\n",
-               vmm_current_cpu_id, _vcpu->r.ip,
-               _vcpu->r.flags & Flags_mode_32 ? 32 : 64,
-               _vcpu->entry_ip, _vcpu->entry_sp, _vcpu->user_task,
-               static_cast(l4_vcpu_e_read(*_vcpu, L4_VCPU_E_VMPIDR)),
-               vmpidr);
-
-  mark_on();
-  Vmm::Guest::instance()->cpu_online(this);
-
-  L4::Cap myself;
-  auto res = myself->vcpu_resume_commit(myself->vcpu_resume_start());
-
-  // Could not enter guest! Take us offline...
-  Err().printf("vcpu_resume_commit error %lx\n", l4_error(res));
-  stop();
-
-  // Failed to take vCPU offline. Should not happend but play safe.
-  l4_sleep_forever();
-}
-
-bool
-Cpu_dev::restart()
-{
-  assert(_vcpu->entry_sp);
-
-  mark_on_prepared();
-
-  l4_msgtag_t res = _restart_event.obj_cap()->trigger();
-  if (!l4_msgtag_has_error(res))
-    return true;
-
-  Err().printf("Error waking Cpu%d: %lx\n", _vcpu.get_vcpu_id(), l4_error(res));
-  return false;
-}
-
-void
-Cpu_dev::stop()
-{
-  mark_off();
-  Vmm::Guest::instance()->cpu_offline(this);
-
-  while (online_state() != Cpu_state::On_prepared)
-    _vcpu.wait_for_ipc(l4_utcb(), L4_IPC_NEVER);
-
-  reset();
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/debugger/guest_debugger.h b/src/l4/pkg/uvmm/server/src/arm/debugger/guest_debugger.h
deleted file mode 100644
index 143e8620..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/debugger/guest_debugger.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-namespace Vmm {
-  class Vm;
-}
-
-namespace Monitor {
-
-class Guest_debugger
-{
-public:
-  explicit Guest_debugger(Vmm::Vm *)
-  {}
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic-v2.cc b/src/l4/pkg/uvmm/server/src/arm/gic-v2.cc
deleted file mode 100644
index da3f3e79..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic-v2.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "gic_cpu.h"
-#include "gic_mixin.h"
-#include "guest.h"
-#include "mem_types.h"
-
-namespace {
-
-using namespace Vdev;
-
-/**
- * Mmio access handler that maps the GICC page.
- *
- * This handler maps the page during the eager-mapping stage before the
- * guest is started. It is also able to respond to page faults in the region
- * and will map the page again. Note, however, that this should normally
- * not happen because the page is pinned in the VM task during its life time.
- * Therefore a warning is printed when the access() function is called.
- */
-class Gicc_region_mapper : public Vmm::Mmio_device
-{
-public:
-  Gicc_region_mapper(l4_addr_t base)
-  : _fp(l4_fpage(base, L4_PAGESHIFT, L4_FPAGE_RW))
-  {}
-
-  int access(l4_addr_t, l4_addr_t, Vmm::Vcpu_ptr,
-             L4::Cap vm, l4_addr_t, l4_addr_t) override
-  {
-    Dbg(Dbg::Core, Dbg::Warn)
-      .printf("Access to GICC page trapped into guest handler. Restoring mapping.\n");
-
-    remap_page(vm);
-
-    return Vmm::Retry;
-  }
-
-  void map_eager(L4::Cap vm, Vmm::Guest_addr, Vmm::Guest_addr) override
-  { remap_page(vm); }
-
-  static l4_uint64_t
-  verify_node(Vdev::Dt_node const &node)
-  {
-    l4_uint64_t base, size;
-    int res = node.get_reg_val(1, &base, &size);
-    if (res < 0)
-      {
-        Err().printf("Failed to read 'reg[1]' from node %s: %s\n",
-                     node.get_name(), node.strerror(res));
-        throw L4::Runtime_error(-L4_EINVAL,
-                                "Reading device tree entry for GIC");
-      }
-
-    // Check the alignment of the GICC page
-    if (base & (L4_PAGESIZE - 1))
-      {
-        Err().printf("%s:The GICC page is not page aligned: <%llx, %llx>.\n",
-                     node.get_name(), base, size);
-        L4Re::chksys(-L4_EINVAL, "Setting up GICC page");
-      }
-
-    if (size > L4_PAGESIZE)
-      {
-        Dbg(Dbg::Irq, Dbg::Info, "GIC")
-          .printf("GIC %s.reg update: Adjusting GICC size from %llx to %lx\n",
-                  node.get_name(), size, L4_PAGESIZE);
-        node.update_reg_size(1, L4_PAGESIZE);
-      }
-
-    // Check if there are more than two "reg" entries (VGIC registers)
-    if (node.get_reg_size_flags(2, nullptr, nullptr) == 0)
-      {
-        Dbg(Dbg::Irq, Dbg::Info, "GIC")
-          .printf("GIC %s.reg update: Stripping superfluous entries\n",
-                  node.get_name());
-        node.resize_reg(2);
-      }
-
-    return base;
-  }
-
-  char const *dev_name() const override { return "Gicc"; };
-
-  static void map_gicc(Device_lookup *devs, Vdev::Dt_node const &node)
-  {
-    l4_uint64_t base = Gicc_region_mapper::verify_node(node);
-    auto gerr = Vdev::make_device(base);
-    devs->vmm()->register_mmio_device(cxx::move(gerr), Vmm::Region_type::Kernel,
-                                      node, 1);
-  }
-
-private:
-  void remap_page(L4::Cap vm) const
-  {
-    Dbg(Dbg::Mmio, Dbg::Info, "mmio")
-      .printf("\tMapping [GICC] -> [%lx - %lx]\n", l4_fpage_memaddr(_fp),
-              l4_fpage_memaddr(_fp) + L4_PAGESIZE - 1);
-    L4Re::chksys(vm->vgicc_map(_fp), "Mapping VGICC area into guest task");
-  }
-
-  l4_fpage_t _fp;
-};
-
-using namespace Gic;
-
-/**
- * GICv2 Distributor implementation.
- */
-class Dist_v2 : public Dist_mixin
-{
-private:
-  using Dist = Dist_mixin;
-
-public:
-
-  /// SGIR implemenation
-  struct Sgir
-  {
-  private:
-    l4_uint32_t _raw;
-
-  public:
-    explicit Sgir(l4_uint32_t val) : _raw(val) {}
-    l4_uint32_t raw() const { return _raw; }
-
-    CXX_BITFIELD_MEMBER(24, 25, target_list_filter, _raw);
-    CXX_BITFIELD_MEMBER(16, 23, cpu_target_list, _raw);
-    CXX_BITFIELD_MEMBER(15, 15, nsatt, _raw);
-    CXX_BITFIELD_MEMBER( 0,  3, sgi_int_id, _raw);
-  };
-
-  /// GICv2 has per source CPU SGI pending bits per CPU
-  static bool sgi_pend_regs() { return true; }
-
-  /// GICv2 specific vGIC list register (LR) access
-  struct Cpu_if
-  {
-    using Lr = Vmm::Arm::Gic_h::Lr;
-    static Lr read_lr(Vmm::Vcpu_ptr vcpu, unsigned idx)
-    {
-      return Lr(l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_GIC_V2_LR0 + idx * 4));
-    }
-
-    static void write_lr(Vmm::Vcpu_ptr vcpu, unsigned idx, Lr lr)
-    { l4_vcpu_e_write_32(*vcpu, L4_VCPU_E_GIC_V2_LR0 + idx * 4, lr.raw); }
-
-    static unsigned pri_mask(Vmm::Vcpu_ptr vcpu)
-    {
-      l4_uint32_t v = l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_GIC_VMCR);
-      return (v >> 24) & 0xf8;
-    }
-  };
-
-  /// create a GICv2 instance
-  Dist_v2(unsigned tnlines) : Dist(tnlines, 8) {}
-
-  void setup_cpu(Vmm::Vcpu_ptr vcpu, l4_umword_t) override
-  {
-    auto *c = Dist::add_cpu(vcpu);
-    if (!c)
-      return;
-
-    unsigned id = vcpu.get_vcpu_id();
-    for (unsigned i = 0; i < 32; ++i)
-      c->local_irq(i).target(1u << id, c);
-  }
-
-  /// setup the mappings for a GICv2 distributor and CPU interface in the VM
-  cxx::Ref_ptr
-  setup_gic(Vdev::Device_lookup *devs, Vdev::Dt_node const &node) override
-  {
-    cxx::Ref_ptr self(this);
-    // attach GICD to VM
-    devs->vmm()->register_mmio_device(self, Vmm::Region_type::Virtual, node);
-    // attach GICC to VM
-    Gicc_region_mapper::map_gicc(devs, node);
-
-    node.setprop_string("compatible", "arm,gic-400");
-    return self;
-  }
-
-  /// MMIO write to the GICD_SGIR
-  void sgir_write(l4_uint32_t value)
-  {
-    Sgir sgir(value);
-    unsigned long targets = 0;
-    switch (sgir.target_list_filter())
-      {
-      case 0:
-        targets = sgir.cpu_target_list();
-        break;
-      case 1:
-        targets = ~(1UL << vmm_current_cpu_id);
-        break;
-      case 2:
-        // Since "case 0" could target the local cpu too we do not
-        // handle this case seperately
-        targets = 1UL << vmm_current_cpu_id;
-        break;
-      case 3:
-        // reserved value
-        return;
-      default:
-        assert(0);
-      }
-
-    unsigned irq = sgir.sgi_int_id();
-    unsigned cpus = _cpu.size();
-    for (unsigned cpu = 0; cpu < cpus && targets; ++cpu, targets >>= 1)
-      if (targets & 1)
-        {
-          if (cpu != vmm_current_cpu_id)
-            _cpu[cpu]->ipi(irq);
-          else
-            set(irq);
-        }
-  }
-
-  /// MMIO read to GICD registers
-  l4_uint64_t read(unsigned reg, char size, unsigned cpu_id)
-  {
-    l4_uint64_t res = 0;
-    if (dist_read(reg, size, cpu_id, &res))
-      return res;
-
-    if (reg >= 0xf10 && reg < 0xf30)
-      return _cpu[cpu_id]->read_sgi_pend((reg >> 2) & 3);
-
-    return 0;
-  }
-
-  /// Read a CoreSight IIDR
-  l4_uint32_t iidr_read(unsigned r) const override
-  {
-    if (r == 0x18)
-      return 2 << 4; // GICv2
-
-    return 0;
-  }
-
-  /// MMIO write to GICD registers
-  void write(unsigned reg, char size, l4_uint32_t value, unsigned cpu_id)
-  {
-    if (dist_write(reg, size, value, cpu_id))
-      return;
-
-    unsigned r = reg & ~3;
-    if (r == SGIR)
-      sgir_write(value);
-    else if (r >= 0xf10 && r < 0xf20)
-      _cpu[cpu_id]->write_clear_sgi_pend((r - 0xf10) / 4, value);
-    else if (r >= 0xf20 && r < 0xf40)
-      _cpu[cpu_id]->write_set_sgi_pend((r - 0xf20) / 4, value);
-    else
-      Dbg(Dbg::Mmio, Dbg::Warn, "Dist")
-        .printf("Ignoring write access to %x, %x\n", r, value);
-  }
-
-  char const *dev_name() const override { return "Dist_v2"; }
-};
-
-struct DF : Dist::Factory
-{
-  DF() : Factory(2) {}
-  cxx::Ref_ptr create(unsigned tnlines) const
-  {
-    return Vdev::make_device(tnlines);
-  }
-};
-
-static DF df;
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic-v3.cc b/src/l4/pkg/uvmm/server/src/arm/gic-v3.cc
deleted file mode 100644
index 6411fa3a..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic-v3.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "gic-v3.h"
-
-namespace Gic {
-
-class Redist : public Vmm::Mmio_device_t
-{
-private:
-  Dist_v3 *_dist;
-
-  std::mutex _lock;
-  std::vector _redist_cpu;
-
-  enum
-  {
-    IID  = 0x43b,
-    IID2 = 3 << 4,
-    // All but proc_num and affinity and last.
-    // CommonLPIAff = 0 -> All redistributors must share LPI config table.
-    // DirectLPI = 0 -> Direct injection of LPIs not supported.
-    TYPE = 0,
-  };
-
-  l4_uint32_t status() const
-  { return 0; }
-
-  void status(l4_uint32_t) const
-  {}
-
-  l4_uint32_t type() const
-  {
-    l4_uint32_t type = TYPE;
-    if (_dist->_lpis)
-      type |= 1 << 0; // Physical LPIs are supported
-    return type;
-  }
-
-  enum
-  {
-    CTLR      = 0x0,
-    IIDR      = 0x4,
-    TYPER     = 0x8,
-    STATUSR   = 0x10,
-    WAKER     = 0x14,
-    PROPBASER = 0x70,
-    PENDBASER = 0x78,
-    IIDR2     = 0xffe8,
-  };
-
-  l4_uint64_t read_rd(Cpu *cif, unsigned reg, char size, bool last)
-  {
-    unsigned r32 = reg & ~3u;
-    using Ma = Vmm::Mem_access;
-
-    switch (r32)
-      {
-      case CTLR:
-        {
-          std::lock_guard lock(_lock);
-          return _redist_cpu[cif->vcpu_id()].ctlr();
-        }
-
-      case IIDR:
-        return IID;
-
-      case IIDR2:
-        return IID2;
-
-      case TYPER:
-      case TYPER + 4:
-        return Ma::read(type() | cif->get_typer() | (last ? 0x10 : 0x00),
-                        reg, size);
-      case STATUSR:
-        return status();
-
-      case WAKER:
-        return 0;
-
-      case PROPBASER:
-      case PROPBASER + 4:
-        {
-          std::lock_guard lock(_lock);
-          return Ma::read(_redist_cpu[cif->vcpu_id()].propbase(), reg, size);
-        }
-
-      case PENDBASER:
-      case PENDBASER + 4:
-        {
-          std::lock_guard lock(_lock);
-          return Ma::read(_redist_cpu[cif->vcpu_id()].pendbase(), reg, size);
-        }
-
-      default:
-        break;
-      }
-
-    return 0;
-  }
-
-  void write_rd(Cpu *cif, unsigned reg, char size, l4_uint64_t value)
-  {
-    unsigned r32 = reg & ~3u;
-
-    switch (r32)
-      {
-      case CTLR:
-        {
-          std::lock_guard lock(_lock);
-          _redist_cpu[cif->vcpu_id()].ctlr(_dist->num_lpi_bits(),
-                                           *_dist->_ram.get(), value);
-          return;
-        }
-
-      case STATUSR:
-        status(value);
-        return;
-
-      case WAKER:
-        return;
-
-      case PROPBASER:
-      case PROPBASER + 4:
-        {
-          std::lock_guard lock(_lock);
-          _redist_cpu[cif->vcpu_id()].propbase(reg, size, value);
-          return;
-        }
-
-      case PENDBASER:
-      case PENDBASER + 4:
-        {
-          std::lock_guard lock(_lock);
-          _redist_cpu[cif->vcpu_id()].pendbase(reg, size, value);
-          return;
-        }
-
-      default:
-        break;
-      }
-    return;
-  }
-
-public:
-  enum
-  {
-    Stride = 17, // 17bit stride -> 2 64K regions RD + SGI
-  };
-
-  explicit Redist(Dist_v3 *dist)
-  : _dist(dist),
-    _redist_cpu(_dist->_cpu.capacity())
-  {
-  }
-
-  Redist_cpu *cpu(unsigned cpu_id)
-  {
-    return cpu_id < _redist_cpu.size() ? &_redist_cpu[cpu_id] : nullptr;
-  }
-
-  Redist_cpu const *cpu(unsigned cpu_id) const
-  {
-    return cpu_id < _redist_cpu.size() ? &_redist_cpu[cpu_id] : nullptr;
-  }
-
-  l4_uint64_t read(unsigned reg, char size, unsigned)
-  {
-    unsigned cpu_id = reg >> Stride;
-    if (cpu_id >= _dist->_cpu.size())
-      return 0;
-
-    unsigned blk = (reg >> 16) & ~((~0u) << (Stride - 16));
-    reg &= 0xffff;
-
-    l4_uint64_t res = 0;
-    switch (blk)
-      {
-        case 0:
-          return read_rd(_dist->_cpu[cpu_id].get(), reg, size,
-                         cpu_id + 1 == _dist->_cpu.size());
-        case 1:
-          _dist->read_multi_irq(reg, size, cpu_id, &res);
-          return res;
-        default:
-          return 0;
-      }
-  }
-
-  void write(unsigned reg, char size, l4_uint64_t value, unsigned)
-  {
-    unsigned cpu_id = reg >> Stride;
-    if (cpu_id >= _dist->_cpu.size())
-      return;
-
-    unsigned blk = (reg >> 16) & ~((~0u) << (Stride - 16));
-    reg &= 0xffff;
-    switch (blk)
-      {
-        case 0:
-          return write_rd(_dist->_cpu[cpu_id].get(), reg, size, value);
-        case 1:
-          _dist->write_multi_irq(reg, size, value, cpu_id);
-          return;
-        default:
-          break;
-      }
-  }
-
-  char const *dev_name() const override { return "Redist"; }
-};
-
-// ICC_SRE_EL1
-class Sre1_sysreg : public Vmm::Arm::Sys_reg
-{
-public:
-  l4_uint64_t read(Vmm::Vcpu_ptr, Key) override
-  {
-    return 0x7; // SRE (System Register Access Enable) + DIB + DFB
-  }
-
-  void write(Vmm::Vcpu_ptr, Key, l4_uint64_t) override
-  {}
-};
-
-class Sgir_sysreg : public Vmm::Arm::Sys_reg
-{
-private:
-  void bcast(unsigned intid)
-  {
-    auto const &cc = dist->_cpu[vmm_current_cpu_id];
-    for (auto const &c: dist->_cpu)
-      if (c != cc)
-        dist->inject_irq(c->local_irq(intid), cc.get());
-  }
-
-  void sgi_tgt(unsigned intid, l4_uint64_t target)
-  {
-    unsigned const aff = ((target >> 16) & 0xff)
-                         | ((target >> 24) & 0xff00)
-                         | ((target >> 32) & 0xff0000);
-
-    unsigned const tgtlist = target & 0xffff;
-
-    auto const &cc = dist->_cpu[vmm_current_cpu_id];
-    for (auto const &c: dist->_cpu)
-      {
-        unsigned a = c->affinity();
-        if ((a >> 8) != aff || ((a & 0xff) > 0xf))
-          continue;
-
-        if (!((1u << (a & 0xf)) & tgtlist))
-          continue;
-
-        if (cc != c)
-          dist->inject_irq(c->local_irq(intid), cc.get());
-        else
-          dist->inject_irq_local(c->local_irq(intid), cc.get());
-      }
-  }
-
-public:
-  Dist_v3 *dist;
-
-  explicit Sgir_sysreg(Dist_v3 *d) : dist(d) {}
-
-  l4_uint64_t read(Vmm::Vcpu_ptr, Key) override
-  { return 0; }
-
-  void write(Vmm::Vcpu_ptr, Key, l4_uint64_t val) override
-  {
-    unsigned const intid = (val >> 24) & 0xf;
-
-    if (! (val & (1ull << 40)))
-      sgi_tgt(intid, val);
-    else
-      bcast(intid);
-  }
-};
-
-Dist_v3::Dist_v3(unsigned tnlines)
-: Dist(tnlines, Num_cpus),
-  _router(cxx::make_unique(32 * tnlines)),
-  _redist(new Redist(this)),
-  _redist_size(0),
-  _sre1(new Sre1_sysreg()),
-  _sgir(new Sgir_sysreg(this))
-{
-  ctlr = Gicd_ctlr_must_set;
-}
-
-void
-Dist_v3::setup_cpu(Vmm::Vcpu_ptr vcpu, l4_umword_t mpidr)
-{
-  auto *c = Dist::add_cpu(vcpu);
-  if (!c)
-    return;
-
-  if ((_redist_size >> Redist::Stride) < _cpu.size())
-    {
-      Err().printf("GICR mmio is too small for %u+ cpus: 0x%llx.\n",
-                   _cpu.size(), _redist_size);
-      L4Re::throw_error(-L4_EINVAL, "Setup GICv3 redistributor");
-    }
-
-  if ((mpidr & 0xffU) > 0x0f)
-    {
-      Err().printf("MPIDR.Aff0 value out of range [0-15]: (%lu)."
-                   " Not addressable by GIC SGIs!.\n", mpidr & 0xffU);
-      L4Re::throw_error(-L4_EINVAL, "Setup GICv3 redistributor");
-    }
-
-  for (unsigned i = 0; i < Cpu::Num_local; ++i)
-    c->local_irq(i).target(0, c);
-
-  redist(vcpu.get_vcpu_id())->ipc_registry(vcpu.get_ipc_registry());
-}
-
-l4_uint32_t
-Dist_v3::get_typer() const
-{
-  // CPUNumber: ARE always enabled, see also GICD_CTLR.
-  // No1N:      1 of N SPI routing model not supported
-  l4_uint32_t type = tnlines | (0 << 5) | (1 << 25);
-
-  unsigned lpi_bits = num_lpi_bits();
-  if (lpi_bits > 0)
-    {
-      // IDBits: 14+ (IDs 0-1019, 1020-1023 are reserved,
-      //              LPIs 8192-(8192 + 2^lpi_bits)).
-      unsigned id_bits = 13 + cxx::max(1, static_cast(lpi_bits) - 12);
-      type |= ((lpi_bits - 1) << 11) // Number of supported LPI bits minus one.
-              | (1 << 17)            // LPIs are supported
-              | ((id_bits - 1) << 19); // Number of IDBits minus one.
-    }
-  else
-    {
-      // IDBits: 10 (IDs 0-1019, 1020-1023 are reserved).
-      type |= (9 << 19);
-    }
-  return type;
-}
-
-Redist_cpu *
-Dist_v3::redist(unsigned cpu_id)
-{
-  return static_cast(_redist.get())->cpu(cpu_id);
-}
-
-Redist_cpu const *
-Dist_v3::redist(unsigned cpu_id) const
-{
-  return static_cast(_redist.get())->cpu(cpu_id);
-}
-
-cxx::Ref_ptr
-Dist_v3::setup_gic(Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-{
-  _ram = devs->ram();
-
-  cxx::Ref_ptr self(this);
-  l4_uint64_t base;
-
-  int res = node.get_reg_val(1, &base, &_redist_size);
-  if (res < 0)
-    {
-      Err().printf("Failed to read 'reg[1]' from node %s: %s\n",
-                   node.get_name(), node.strerror(res));
-      L4Re::throw_error(-L4_EINVAL, "Setup GICv3");
-    }
-
-  if (base & 0xffff)
-    {
-      Err().printf("%s: GICR mmio is not 64K aligned: <%llx, %llx>.\n",
-                   node.get_name(), base, _redist_size);
-      L4Re::throw_error(-L4_EINVAL, "Setup GICv3");
-    }
-
-  devs->vmm()->register_mmio_device(_redist, Vmm::Region_type::Virtual, node,
-                                    1);
-  devs->vmm()->register_mmio_device(self, Vmm::Region_type::Virtual, node);
-
-  devs->vmm()->add_sys_reg_both(3, 0, 12, 12, 5, _sre1);
-
-  devs->vmm()->add_sys_reg_aarch64(3, 0, 12, 11, 5, _sgir);
-  devs->vmm()->add_sys_reg_aarch32_cp64(15, 0, 12, _sgir);
-
-  node.setprop_string("compatible", "arm,gic-v3");
-
-  return self;
-}
-
-namespace {
-
-struct DF : Dist::Factory
-{
-  DF() : Factory(3) {}
-  cxx::Ref_ptr create(unsigned tnlines) const
-  {
-    return Vdev::make_device(tnlines);
-  }
-};
-
-static DF df;
-
-}
-
-} // Gic
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic-v3.h b/src/l4/pkg/uvmm/server/src/arm/gic-v3.h
deleted file mode 100644
index d887d8dd..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic-v3.h
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "gic_cpu.h"
-#include "gic_mixin.h"
-#include "guest.h"
-#include "mem_types.h"
-#include "mem_access.h"
-
-namespace Gic {
-
-/**
- * Abstraction for a GIC register that allows the guest to setup a shared memory
- * area with the GIC. This class provides the following functionality:
- *  - Enforce the memory attributes in the register to be inner shareable and
- *    cacheable.
- *  - Allow also non-64-bit sized accesses to the register.
- *  - Custom read-only fields.
- */
-template
-struct Gic_mem_reg : public REG
-{
-  enum
-  {
-    Share_inner_shareable        = 1,
-    Inner_cache_cacheable_rawawb = 7,
-    Outer_cache_same_as_inner    = 0,
-
-    Ro_mask = REG::Ro_mask | REG::share_bfm_t::Mask
-              | REG::inner_cache_bfm_t::Mask | REG::outer_cache_bfm_t::Mask,
-  };
-
-  template
-  Gic_mem_reg(Args &&... args)
-  : REG(cxx::forward(args)...)
-  {
-    REG::share() = Share_inner_shareable;
-    REG::inner_cache() = Inner_cache_cacheable_rawawb;
-    REG::outer_cache() = Outer_cache_same_as_inner;
-  }
-
-  l4_uint64_t read(unsigned reg, unsigned size)
-  {
-    return Vmm::Mem_access::read(REG::raw, reg, size);
-  }
-
-  void write(l4_uint64_t value, unsigned reg, char size)
-  {
-    l4_uint64_t tmp = REG::raw;
-    Vmm::Mem_access::write(&tmp, value, reg, size);
-    REG::raw = (REG::raw & Ro_mask) | (tmp & ~Ro_mask);
-  }
-};
-
-/**
- * Per vCPU redistributor state.
- */
-class Redist_cpu
-{
-private:
-  enum
-  {
-    GICR_CTRL_enable_lpi = 1 << 0,
-  };
-
-  struct Lpi_config
-  {
-    l4_uint8_t raw;
-    CXX_BITFIELD_MEMBER          (0, 0, enable, raw);
-    CXX_BITFIELD_MEMBER_UNSHIFTED(2, 7, priority, raw);
-  };
-
-  struct Propbaser
-  {
-    l4_uint64_t raw = 0;
-    CXX_BITFIELD_MEMBER          ( 0,  4, id_bits, raw);
-    CXX_BITFIELD_MEMBER          ( 7,  9, inner_cache, raw);
-    CXX_BITFIELD_MEMBER          (10, 11, share, raw);
-    CXX_BITFIELD_MEMBER_UNSHIFTED(12, 51, pa, raw);
-    CXX_BITFIELD_MEMBER          (56, 58, outer_cache, raw);
-
-    enum { Ro_mask = 0 };
-
-    unsigned num_lpis()
-    {
-      unsigned lpis = (1 << (id_bits() + 1));
-      return lpis > Cpu::Lpi_base ? lpis - Cpu::Lpi_base : 0;
-    }
-  };
-
-  struct Pendbaser
-  {
-    l4_uint64_t raw = 0;
-    CXX_BITFIELD_MEMBER          ( 7,  9, inner_cache, raw);
-    CXX_BITFIELD_MEMBER          (10, 11, share, raw);
-    CXX_BITFIELD_MEMBER_UNSHIFTED(16, 51, pa, raw);
-    CXX_BITFIELD_MEMBER          (56, 58, outer_cache, raw);
-    CXX_BITFIELD_MEMBER          (62, 62, ptz, raw);
-
-    enum { Ro_mask = 0 };
-  };
-
-public:
-  l4_uint32_t ctlr() const
-  { return lpis_enabled() ? GICR_CTRL_enable_lpi : 0; }
-
-  void ctlr(unsigned num_lpi_bits, Vmm::Vm_ram const &ram, l4_uint32_t ctrl)
-  {
-    // Once LPI support has been enabled, it cannot be disabled again.
-    if (num_lpi_bits > 0 && !lpis_enabled() && (ctrl & GICR_CTRL_enable_lpi))
-      enable_lpis(num_lpi_bits, ram);
-  }
-
-  l4_uint64_t propbase() const
-  { return _propbase.raw; }
-
-  void propbase(unsigned reg, char size, l4_uint64_t value)
-  {
-    if (!lpis_enabled())
-      _propbase.write(value, reg, size);
-  }
-
-  l4_uint64_t pendbase() const
-  { return _pendbase.raw; }
-
-  void pendbase(unsigned reg, char size, l4_uint64_t value)
-  {
-    if (!lpis_enabled())
-      _pendbase.write(value, reg, size);
-  }
-
-  bool lpis_enabled() const
-  { return _lpis_enabled.load(std::memory_order_acquire); }
-
-  /**
-   * Return whether the LPI is enabled in the LPI configuration table.
-   *
-   * \pre Must only be called after checking lpis_enabled() == true.
-   */
-  bool lpi_enabled(unsigned lpi) const
-  { return lpi < _num_lpis && _config_table[lpi].enable(); }
-
-  /**
-   * Return the priority configured for LPI in the LPI configuration table.
-   *
-   * \pre Must only be called after checking lpis_enabled() == true.
-   */
-  l4_uint8_t lpi_priority(unsigned lpi) const
-  {
-    return lpi < _num_lpis ? _config_table[lpi].priority() : 0;
-  }
-
-  Vcpu_obj_registry *ipc_registry() const
-  { return _registry; }
-
-  void ipc_registry(Vcpu_obj_registry *registry)
-  { _registry = registry; }
-
-private:
-  void enable_lpis(unsigned num_lpi_bits, Vmm::Vm_ram const &ram)
-  {
-    // If number of LPIs configured in Propbaser is larger the number of LPIs
-    // supported by the distributor, the distributor's limit applies.
-    _num_lpis = cxx::min(_propbase.num_lpis(), 1u << num_lpi_bits);
-    _config_table = ram.guest2host(
-      Vmm::Region::ss(Vmm::Guest_addr(_propbase.pa()), _num_lpis,
-                      Vmm::Region_type::Ram));
-
-    // Incomplete: For now, we do not support setting the initial pending
-    // state of LPIs via the pendbase register.
-
-    _lpis_enabled.store(true, std::memory_order_release);
-  }
-
-  Vcpu_obj_registry *_registry = nullptr;
-  std::atomic _lpis_enabled = { false };
-  Gic_mem_reg _propbase;
-  Gic_mem_reg _pendbase;
-  unsigned _num_lpis = 0;
-  Lpi_config *_config_table = nullptr;
-};
-
-struct Cpu_if_v3
-{
-  struct Lr
-  {
-    enum State
-    {
-      Empty              = 0,
-      Pending            = 1,
-      Active             = 2,
-      Active_and_pending = 3
-    };
-
-    l4_uint64_t raw;
-    Lr() = default;
-    explicit Lr(l4_uint64_t v) : raw(v) {}
-    CXX_BITFIELD_MEMBER(  0, 31, vid, raw);
-    CXX_BITFIELD_MEMBER( 32, 41, pid, raw);
-    CXX_BITFIELD_MEMBER( 41, 41, eoi, raw);
-    CXX_BITFIELD_MEMBER( 48, 55, prio, raw);
-    CXX_BITFIELD_MEMBER( 60, 60, grp1, raw);
-    CXX_BITFIELD_MEMBER( 61, 61, hw, raw);
-    CXX_BITFIELD_MEMBER( 62, 63, state, raw);
-    CXX_BITFIELD_MEMBER( 62, 62, pending, raw);
-    CXX_BITFIELD_MEMBER( 63, 63, active, raw);
-
-    void set_cpuid(unsigned) {}
-  };
-
-  static Lr read_lr(Vmm::Vcpu_ptr vcpu, unsigned idx)
-  {
-    return Lr(l4_vcpu_e_read_64(*vcpu, L4_VCPU_E_GIC_V3_LR0 + idx * 8));
-  }
-
-  static void write_lr(Vmm::Vcpu_ptr vcpu, unsigned idx, Lr lr)
-  { l4_vcpu_e_write_64(*vcpu, L4_VCPU_E_GIC_V3_LR0 + idx * 8, lr.raw); }
-
-  static unsigned pri_mask(Vmm::Vcpu_ptr vcpu)
-  {
-    l4_uint32_t v = l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_GIC_VMCR);
-    return (v >> 24);
-  }
-};
-
-class Dist_v3 : public Dist_mixin
-{
-private:
-  using Dist = Dist_mixin;
-  friend class Redist;
-  friend class Sgir_sysreg;
-
-private:
-  cxx::Ref_ptr _ram;
-  cxx::unique_ptr _router;
-  cxx::Ref_ptr _redist;
-  l4_uint64_t _redist_size;
-  cxx::Ref_ptr _sre1;
-  cxx::Ref_ptr _sgir;
-
-  enum { Gicd_ctlr_must_set = 5UL << 4 }; // DS, ARE
-
-public:
-  using Cpu_if = Cpu_if_v3;
-
-  static bool sgi_pend_regs() { return false; }
-
-  enum { Num_cpus = 255 };
-
-  explicit Dist_v3(unsigned tnlines);
-
-  void setup_cpu(Vmm::Vcpu_ptr vcpu, l4_umword_t mpidr) override;
-
-  unsigned num_lpi_bits() const
-  {
-    if (_lpis && _lpis->size() >= 2)
-      // Number of supported LPI bits is the log2 of the LPI array size.
-      return (sizeof(unsigned) * 8) - __builtin_clz(_lpis->size()) - 1;
-    else
-      return 0;
-  }
-
-  l4_uint32_t get_typer() const override;
-
-  Redist_cpu *redist(unsigned cpu_id);
-  Redist_cpu const *redist(unsigned cpu_id) const;
-
-  cxx::Ref_ptr setup_gic(Vdev::Device_lookup *devs,
-                                       Vdev::Dt_node const &node) override;
-
-  void sgir_write(l4_uint32_t)
-  {}
-
-  unsigned char find_cpu(l4_uint32_t affinity)
-  {
-    for (unsigned i = 0; i < _cpu.size(); ++i)
-      if (_cpu[i] && _cpu[i]->affinity() == affinity)
-        return i;
-
-    return Irq::Invalid_cpu;
-  }
-
-  l4_uint64_t read(unsigned reg, char size, unsigned cpu_id)
-  {
-    l4_uint64_t res = 0;
-    if (dist_read(reg, size, cpu_id, &res))
-      return res;
-
-    if (reg >= 0x6100
-        && (reg < (0x6100 + 8 * 32 * static_cast(tnlines))))
-      {
-        unsigned const r = (reg - 0x6100) >> 3;
-        return Vmm::Mem_access::read(_router[r], reg & 7, size);
-      }
-
-    return 0;
-  }
-
-  l4_uint32_t iidr_read(unsigned r) const override
-  {
-    if (r == 0x18)
-      return 3 << 4; // GICv3
-
-    return 0;
-  }
-
-  void write(unsigned reg, char size, l4_uint64_t value, unsigned cpu_id)
-  {
-    if (dist_write(reg, size, value, cpu_id))
-      return;
-
-    // GICD_IROUTERn
-    if (reg >= 0x6100
-        && (reg < (0x6100 + 8 * 32 * static_cast(tnlines))))
-      {
-        std::lock_guard lock(_target_lock);
-
-        unsigned const r = (reg - 0x6100) >> 3;
-        Vmm::Mem_access::write(&_router[r], value, reg & 7, size);
-        _router[r] &= ~(1ull << 31); // IRM always 0: no 1 of N routing
-        l4_uint32_t aff =   (_router[r] & 0x00ffffff)
-                          | ((_router[r] >> 32) & 0xff000000);
-        spi(r).target(0, cpu(find_cpu(aff)));
-      }
-  }
-
-  void write_ctlr(l4_uint32_t val) override
-  {
-    ctlr = (val & 3U) | Gicd_ctlr_must_set;
-  }
-
-  char const *dev_name() const override { return "Dist_v3"; }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic-v3_its.cc b/src/l4/pkg/uvmm/server/src/arm/gic-v3_its.cc
deleted file mode 100644
index a569587e..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic-v3_its.cc
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include 
-
-#include "device_factory.h"
-#include "gic-v3.h"
-#include "msi_controller.h"
-
-namespace {
-using namespace Gic;
-
-/**
- * In the GICv3 architecture the Interrupt Translation Service (ITS) provides
- * support for message-based interrupts, e.g. Message Signaled Interrupts (MSI).
- *
- * The guest configures the ITS to map the combination of a DeviceID and an
- * EventID to a Locality-specific Peripheral Interrupt (LPI) directed to a
- * redistributor (i.e. to a vCPU).
- *
- * To trigger an LPI, a device has to write the corresponding EventID to the
- * GITS_TRANSLATER register of the ITS. In our virtualized ITS, devices perform
- * this write access via the Msix_controller interface.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   its: msi-controller@f10c0000 {
- *       #msi-cells = <1>;
- *       compatible = "arm,gic-v3-its";
- *       reg = <0x0 0xf10c0000 0x0 0x20000>; // GITS
- *       msi-controller;
- *   };
- * \endcode
- */
-class Its :
-  public Msix_controller,
-  public Vdev::Device,
-  public Vmm::Mmio_device_t
-{
-private:
-  using Icid = l4_uint16_t;
-  using Dev_id = l4_uint32_t;
-  using Event_id = l4_uint32_t;
-
-  enum
-  {
-    Lpi_base       = Cpu::Lpi_base,
-    Num_lpis       = 512,
-
-    /**
-     * The GITS_TYPER.HCC (Hardware Collection Count) mechanism for holding
-     * collections inside the ITS supports up to 256 collections. This matches
-     * the value range of the Irq_info target field, which we use to store for
-     * each LPI the collection ID (ICID) of the collection it is assigned to.
-     * In order to handle the case where an LPI is not assigned to any
-     * collection, we reserve the ICID 255 as the invalid collection.
-     */
-    Num_cols       = 255,
-    Invalid_col    = Num_cols,
-
-    Device_id_bits = 9,
-    Num_devices    = 1 << Device_id_bits,
-    /**
-     * Our ITS model does not use the ITTs provided by the guest, therefore use
-     * the minimum possible entry size.
-     */
-    Itt_entry_size = 1,
-
-    Event_id_bits  = sizeof(l4_uint16_t) * 8,
-    Num_events     = 1 << Event_id_bits,
-  };
-
-  enum
-  {
-    IID  = 0x43b,
-    IID2 = 3 << 4,
-    TYPE =   1 << 0 // ITS supports physical LPIs.
-           | (Itt_entry_size - 1) << 4 // Bytes per ITT entry minus one.
-           | (Event_id_bits - 1) << 8 // Supported EventID bits minus one.
-           | (Device_id_bits - 1) << 13 // Supported DeviceID bits minus one.
-           | 0 << 19 // Redist target address corresponds to the PE number.
-           | (Num_cols - 1) << 24, // Supported interrupt collections minus one.
-  };
-
-  enum
-  {
-    GITS_CTLR         = 0x0000,
-    GITS_IIDR         = 0x0004,
-    GITS_TYPER        = 0x0008,
-    GITS_CBASER       = 0x0080,
-    GITS_CWRITER      = 0x0088,
-    GITS_CREADR       = 0x0090,
-    GITS_BASER        = 0x0100,
-    GITS_PIDR2        = 0xffe8,
-    GITS_ITS_BASE     = 0x10000,
-    GITS_TRANSLATER   = GITS_ITS_BASE + 0x0040,
-
-    GITS_CTLR_enabled   = 1U << 0,
-    GITS_CTLR_quiescent = 1U << 31,
-
-    GITS_cmd_queue_offset_mask = 0xfffe0,
-  };
-
-  struct Cbaser
-  {
-    l4_uint64_t raw = 0;
-    CXX_BITFIELD_MEMBER          ( 0,  7, size, raw);
-    CXX_BITFIELD_MEMBER          (10, 11, share, raw);
-    CXX_BITFIELD_MEMBER_UNSHIFTED(12, 51, pa, raw);
-    CXX_BITFIELD_MEMBER          (53, 55, outer_cache, raw);
-    CXX_BITFIELD_MEMBER          (59, 61, inner_cache, raw);
-    CXX_BITFIELD_MEMBER          (63, 63, valid, raw);
-
-    enum { Ro_mask = 0 };
-
-    unsigned size_bytes()
-    { return (size() + 1) * 0x1000; }
-  };
-
-  struct Baser
-  {
-    l4_uint64_t raw = 0;
-
-    CXX_BITFIELD_MEMBER          ( 0,  7, size, raw);
-    CXX_BITFIELD_MEMBER          ( 8,  9, page_size, raw);
-    CXX_BITFIELD_MEMBER          (10, 11, share, raw);
-    CXX_BITFIELD_MEMBER_UNSHIFTED(12, 47, pa, raw);
-    CXX_BITFIELD_MEMBER          (48, 52, entry_size, raw);
-    CXX_BITFIELD_MEMBER          (53, 55, outer_cache, raw);
-    CXX_BITFIELD_MEMBER          (56, 58, type, raw);
-    CXX_BITFIELD_MEMBER          (59, 61, inner_cache, raw);
-    CXX_BITFIELD_MEMBER          (62, 62, indirect, raw);
-    CXX_BITFIELD_MEMBER          (63, 63, valid, raw);
-
-    enum
-    {
-      Ro_mask = entry_size_bfm_t::Mask | type_bfm_t::Mask | indirect_bfm_t::Mask
-    };
-
-    enum Type
-    {
-      Type_none       = 0,
-      Type_device     = 1,
-      Type_vpe        = 2,
-      Type_collection = 4,
-    };
-
-    explicit Baser(Type t)
-    {
-      type() = t;
-      entry_size() = 0;
-      indirect() = false;
-    }
-  };
-
-public:
-  explicit Its(Vdev::Device_lookup *devs)
-  : _gic(dynamic_cast(devs->vmm()->gic().get())),
-    _ram(devs->ram()),
-    _lpis(Num_lpis, Lpi_base)
-  {
-    if (!_gic)
-      L4Re::throw_error(-L4_EINVAL, "ITS requires GICv3");
-
-    // Initially all collections are unmapped.
-    _cols.fill(nullptr);
-
-    for (unsigned i = 0; i < _lpis.size(); i++)
-      {
-        // LPIs have initially no collection or redistributor assigned.
-        _lpis[i].target(Invalid_col, nullptr);
-        // LPIs are always group 1 interrupts.
-        _lpis[i].group(true);
-      }
-
-    _gic->register_lpis(&_lpis);
-  }
-
-  // Msix_controller interface
-  Vcpu_obj_registry *send(l4_uint64_t, l4_uint64_t msix_data, l4_uint32_t src_id) const override
-  {
-    Dev_id dev_id = src_id;
-    Event_id event_id = msix_data;
-
-    Irq *lpi;
-    {
-      std::lock_guard lock(_lock);
-      // LPI lookup has to be protected with ITS lock.
-      lpi = lookup_lpi(dev_id, event_id);
-      if (!lpi)
-        {
-          warn().printf("LPI lookup for DeviceID %u and EventID %u failed!\n",
-                        dev_id, event_id);
-          return nullptr;
-        }
-    }
-
-    return trigger_lpi(lpi);
-  }
-
-  l4_uint64_t read(unsigned reg, char size, unsigned)
-  {
-    unsigned r32 = reg & ~3u;
-
-    std::lock_guard lock(_lock);
-
-    switch (r32)
-      {
-      case GITS_CTLR:
-        return _enabled ? GITS_CTLR_enabled : GITS_CTLR_quiescent;
-
-      case GITS_IIDR:
-        return IID;
-
-      case GITS_PIDR2:
-        return IID2;
-
-      case GITS_TYPER:
-      case GITS_TYPER + 4:
-        return Vmm::Mem_access::read((unsigned)TYPE, reg, size);
-
-      case GITS_CBASER:
-      case GITS_CBASER + 4:
-        return _cmd_queue_baser.read(reg, size);
-
-      case GITS_CWRITER:
-        return _cmd_queue_write_off;
-
-      case GITS_CREADR:
-        return _cmd_queue_read_off;
-
-      case GITS_BASER:
-      case GITS_BASER + 4:
-        return _device_table_baser.read(reg, size);
-
-      default:
-        return 0;
-      }
-  }
-
-  void write(unsigned reg, char size, l4_uint64_t value, unsigned)
-  {
-    unsigned r32 = reg & ~3u;
-
-    std::lock_guard lock(_lock);
-
-    switch (r32)
-      {
-      case GITS_CTLR:
-        // For now, we do not support disabling the ITS (would require writing
-        // all mapping data to the external memory provided by the guest, for
-        // example the device table).
-        if (!(value & GITS_CTLR_enabled))
-          break;
-
-        // Enabling the ITS is UNPREDICTABLE, if device table, collection table
-        // or command queue are not valid.
-        if (!_device_table_baser.valid() || !_cmd_queue_baser.valid())
-          break;
-
-        _enabled = true;
-        process_its_cmds();
-        break;
-
-      case GITS_CBASER:
-      case GITS_CBASER + 4:
-        if (_enabled)
-          break;
-
-        _cmd_queue_baser.write(value, reg, size);
-        // CREADER is reset to 0 when a value is written to GITS_CBASER.
-        _cmd_queue_read_off = 0;
-
-        if (_cmd_queue_baser.valid())
-          {
-            // Cache size and address of command queue
-            _cmd_queue_size = _cmd_queue_baser.size_bytes();
-            _cmd_queue_base = _ram->guest2host(
-              Vmm::Region::ss(Vmm::Guest_addr(_cmd_queue_baser.pa()),
-                              _cmd_queue_size, Vmm::Region_type::Ram));
-          }
-        break;
-
-      case GITS_CWRITER:
-        _cmd_queue_write_off = value & GITS_cmd_queue_offset_mask;
-        process_its_cmds();
-        break;
-
-      case GITS_CREADR:
-        if (_enabled)
-          break;
-
-        _cmd_queue_read_off = value & GITS_cmd_queue_offset_mask;
-        // Ensure command queue read offset is within command queue bounds.
-        if (_cmd_queue_size != 0)
-          _cmd_queue_read_off %= _cmd_queue_size;
-        break;
-
-      // Baser0: Device table
-      case GITS_BASER:
-      case GITS_BASER + 4:
-        if (!_enabled)
-          _device_table_baser.write(value, reg, size);
-        break;
-
-      // Baser1: Collection table - not present, to store collection mappings we
-      // instead use the ITS internal storage mechanism (GITS_TYPER.HCC).
-
-      default:
-        break;
-      }
-  }
-
-  char const *dev_name() const override { return "Its"; }
-
-private:
-  class Cmd
-  {
-  private:
-    l4_uint64_t raw0 = 0;
-    l4_uint64_t raw1 = 0;
-    l4_uint64_t raw2 = 0;
-    l4_uint64_t raw3 = 0;
-
-  public:
-    enum : unsigned { Size = 32 };
-
-    enum Op
-    {
-      Op_movi    = 0x01,
-      Op_int     = 0x03,
-      Op_clear   = 0x04,
-      Op_sync    = 0x05,
-      Op_mapd    = 0x08,
-      Op_mapc    = 0x09,
-      Op_mapti   = 0x0a,
-      Op_mapi    = 0x0b,
-      Op_inv     = 0x0c,
-      Op_invall  = 0x0d,
-      Op_discard = 0x0f,
-    };
-
-    enum Err
-    {
-      Err_ok                         = 0,
-
-      Err_movi_unmapped_interrupt    = 0x010107,
-      Err_movi_unmapped_collection   = 0x010109,
-      Err_int_unmapped_interrupt     = 0x010307,
-      Err_clear_unmapped_interrupt   = 0x010507,
-      Err_mapd_device_oor            = 0x010801,
-      Err_mapd_ittsize_oor           = 0x010802,
-      Err_mapc_collection_oor        = 0x010903,
-      Err_mapti_device_oor           = 0x010A01,
-      Err_mapti_collection_oor       = 0x010A03,
-      Err_mapti_id_oor               = 0x010A05,
-      Err_mapti_physicalid_oor       = 0x010A06,
-      Err_inv_unmapped_interrupt     = 0x010C07,
-      Err_invall_unmapped_collection = 0x010D09,
-      Err_discard_device_oor         = 0x010F01,
-      Err_discard_id_oor             = 0x010F05,
-      Err_discard_unmapped_interrupt = 0x010F07,
-    };
-
-    Cmd() = default;
-
-    CXX_BITFIELD_MEMBER          ( 0,  7, op, raw0);
-    CXX_BITFIELD_MEMBER          (32, 63, dev_id, raw0);
-
-    CXX_BITFIELD_MEMBER          ( 0, 31, event_id, raw1);
-    CXX_BITFIELD_MEMBER          (32, 63, intid, raw1);
-    CXX_BITFIELD_MEMBER          ( 0,  4, itt_size, raw1);
-
-    CXX_BITFIELD_MEMBER          ( 0, 15, icid, raw2);
-    CXX_BITFIELD_MEMBER          (16, 50, rd_base, raw2);
-    CXX_BITFIELD_MEMBER_UNSHIFTED( 8, 51, itt_addr, raw2);
-    CXX_BITFIELD_MEMBER          (63, 63, valid, raw2);
-  };
-  static_assert(sizeof(Cmd) == Cmd::Size, "Check sizeof(cmd)");
-
-  // FIXME: We have to ensure that pending interrupts already written into a
-  // list register are pulled out of it when their pending state or target
-  // changes (e.g. movi, mapc, clear, discard, mapd)!
-
-  /**
-   * This command retargets an already mapped event to a different
-   * redistributor.
-   */
-  Cmd::Err handle_cmd_movi(Dev_id dev_id, Event_id event_id, Icid icid)
-  {
-    trace().printf("CMD movi: dev_id=%u event_id=%u icid=%u\n",
-                   dev_id, event_id, icid);
-
-    Irq *lpi = lookup_lpi(dev_id, event_id);
-    if (!lpi)
-      return Cmd::Err_movi_unmapped_interrupt;
-
-    Cpu *cpu = lookup_col(icid);
-    if (!cpu)
-      return Cmd::Err_movi_unmapped_collection;
-
-    // Change the target ICID and CPU of the LPI to which the event is mapped.
-    lpi->target(icid, cpu);
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command sets the pending state of the specified LPI.
-   */
-  Cmd::Err handle_cmd_int(Dev_id dev_id, Event_id event_id)
-  {
-    trace().printf("CMD int: dev_id=%u event_id=%u\n", dev_id, event_id);
-
-    Irq *lpi = lookup_lpi(dev_id, event_id);
-    if (!lpi)
-      return Cmd::Err_int_unmapped_interrupt;
-
-    return trigger_lpi(lpi) ? Cmd::Err_ok : Cmd::Err_int_unmapped_interrupt;
-  }
-
-  /**
-   * This command clears the pending state of the specified LPI.
-   */
-  Cmd::Err handle_cmd_clear(Dev_id dev_id, Event_id event_id)
-  {
-    trace().printf("CMD clear: dev_id=%u event_id=%u\n", dev_id, event_id);
-
-    Irq *lpi = lookup_lpi(dev_id, event_id);
-    if (!lpi)
-      return Cmd::Err_clear_unmapped_interrupt;
-
-    lpi->pending(false);
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command ensures that the effects of all previous physical commands
-   * associated with the specified redistributor are globally observable.
-   */
-  Cmd::Err handle_cmd_sync(unsigned rd_base)
-  {
-    trace().printf("CMD sync: rd_base=%u\n", rd_base);
-
-    // Our ITS model is always in sync, thus we don't have to do anything here.
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command maps a DeviceID to an interrupt translation table (ITT).
-   */
-  Cmd::Err handle_cmd_mapd(Dev_id dev_id, bool valid, l4_uint64_t itt_addr,
-                           unsigned itt_size)
-  {
-    trace().printf("CMD mapd: dev_id=%u valid=%u itt_addr=0x%llx itt_size=%u\n",
-                   dev_id, valid, itt_addr, itt_size);
-
-    if (dev_id >= Num_devices)
-      return Cmd::Err_mapd_device_oor;
-
-    if (valid)
-      {
-        if (itt_size >= Event_id_bits)
-          return Cmd::Err_mapd_ittsize_oor;
-
-        // We don't have a dedicated per device ITT table, but instead use
-        // an ITT table indexed by a composite DeviceID and EventID key.
-        // Therefore, we don't have to do anything here.
-        return Cmd::Err_ok;
-      }
-    else
-      {
-        unmap_device(dev_id);
-        return Cmd::Err_ok;
-      }
-  }
-
-  /**
-   * This command maps a collection to a redistributor.
-   */
-  Cmd::Err handle_cmd_mapc(Icid icid, bool valid, unsigned rd_base)
-  {
-    trace().printf("CMD mapc: icid=%u valid=%u rd_base=%u\n",
-                   icid, valid, rd_base);
-
-    if (icid >= Num_cols)
-      return Cmd::Err_mapc_collection_oor;
-
-    if (valid)
-      {
-        Cpu *cpu = _gic->cpu(rd_base);
-        if (!cpu)
-          {
-            // Mapping an invalid redistributor is UNPREDICTABLE, ignore this
-            // mapping attempt!
-            warn().printf("RDbase %u does not represent valid redistributor!\n",
-                          rd_base);
-            return Cmd::Err_ok;
-          }
-
-        // Map collection to redistributor (CPU)
-        _cols[icid] = cpu;
-
-        // Update target CPU of all LPIs mapped at this collection.
-        lpis_for_col(icid, [=](Irq *lpi) { lpi->target(icid, cpu); });
-      }
-    else
-      {
-        // Unmap collection
-        _cols[icid] = nullptr;
-
-        // Untarget all LPIs that were targeted at this collection.
-        lpis_for_col(icid, [=](Irq *lpi) { lpi->target(icid, nullptr); });
-      }
-
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command maps an event to an LPI targeted at the specified
-   * redistributor.
-   */
-  Cmd::Err handle_cmd_mapti(Dev_id dev_id, Event_id event_id, unsigned intid,
-                            Icid icid)
-  {
-    trace().printf("CMD mapti: dev_id=%u event_id=%u intid=%u icid=%u\n",
-                   dev_id, event_id, intid, icid);
-
-    if (dev_id >= Num_devices)
-      return Cmd::Err_mapti_device_oor;
-
-    if (icid >= Num_cols)
-      return Cmd::Err_mapti_collection_oor;
-
-    if (event_id >= Num_events)
-      return Cmd::Err_mapti_device_oor;
-
-    if (intid < Lpi_base || intid >= (Lpi_base + Num_lpis))
-      return Cmd::Err_mapti_physicalid_oor;
-
-    // Mapping an already mapped DeviceID-EventID combination is UNPREDICTABLE,
-    // ignore this mapping attempt.
-    if (lookup_lpi(dev_id, event_id))
-      return Cmd::Err_ok;
-
-    Irq *lpi = &_lpis[intid - Lpi_base];
-    // LPI is already mapped for a different DeviceID-EventID
-    // combination. Mapping multiple DeviceID-EventID combinations to
-    // the same LPI is UNPREDICTABLE, ignore this mapping attempt.
-    if (lpi->target() != Invalid_col)
-      return Cmd::Err_ok;
-
-    // Target CPU can be nullptr, if the ICID has not yet been mapped to a
-    // redistributor.
-    Cpu *cpu = lookup_col(icid);
-    // First set the new target ICID and CPU.
-    lpi->target(icid, cpu);
-    // Then update the LPI config (might send a notify IRQ to the target vCPU).
-    update_lpi_config(lpi);
-    map_lpi(dev_id, event_id, lpi);
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command ensures that any caching done by the redistributors
-   * associated with the specified event is consistent with the LPI
-   * configuration tables held in memory.
-   */
-  Cmd::Err handle_cmd_inv(Dev_id dev_id, Event_id event_id)
-  {
-    trace().printf("CMD inv: dev_id=%u event_id=%u\n", dev_id, event_id);
-
-    Irq *lpi = lookup_lpi(dev_id, event_id);
-    if (!lpi)
-      return Cmd::Err_inv_unmapped_interrupt;
-
-    update_lpi_config(lpi);
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command ensures that any caching done by the redistributors
-   * associated with the specified collection is consistent with the LPI
-   * configuration tables held in memory.
-   */
-  Cmd::Err handle_cmd_invall(Icid icid)
-  {
-    trace().printf("CMD invall: icid=%u\n", icid);
-
-    Cpu *cpu = lookup_col(icid);
-    if (!cpu)
-      return Cmd::Err_invall_unmapped_collection;
-
-    lpis_for_col(icid, [=](Irq *lpi) { update_lpi_config(lpi); });
-
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * This command removes the mapping for the specified event from the ITT and
-   * resets the pending state of the corresponding LPI.
-   */
-  Cmd::Err handle_cmd_discard(Dev_id dev_id, Event_id event_id)
-  {
-    trace().printf("CMD discard: dev_id=%u event_id=%u\n", dev_id, event_id);
-
-    if (dev_id >= Num_devices)
-      return Cmd::Err_discard_device_oor;
-
-    if (event_id >= Num_events)
-      return Cmd::Err_discard_id_oor;
-
-    if (!unmap_lpi(dev_id, event_id))
-      return Cmd::Err_discard_unmapped_interrupt;
-
-    return Cmd::Err_ok;
-  }
-
-  /**
-   * Execute all commands pending in the ITS command queue.
-   */
-  void process_its_cmds()
-  {
-    if (!_enabled)
-      return;
-
-    while (_cmd_queue_read_off != _cmd_queue_write_off)
-      {
-        Cmd cmd = cxx::access_once(
-          reinterpret_cast(_cmd_queue_base + _cmd_queue_read_off));
-
-        Cmd::Err res;
-        switch(cmd.op())
-          {
-          case Cmd::Op_movi:
-            res = handle_cmd_movi(cmd.dev_id(), cmd.event_id(), cmd.icid());
-            break;
-          case Cmd::Op_int:
-            res = handle_cmd_int(cmd.dev_id(), cmd.event_id());
-            break;
-          case Cmd::Op_clear:
-            res = handle_cmd_clear(cmd.dev_id(), cmd.event_id());
-            break;
-          case Cmd::Op_sync:
-            res = handle_cmd_sync(cmd.rd_base());
-            break;
-          case Cmd::Op_mapd:
-            res = handle_cmd_mapd(cmd.dev_id(), cmd.valid(), cmd.itt_addr(),
-                                  cmd.itt_size() + 1);
-            break;
-          case Cmd::Op_mapc:
-            res = handle_cmd_mapc(cmd.icid(), cmd.valid(), cmd.rd_base());
-            break;
-          case Cmd::Op_mapi:
-            res = handle_cmd_mapti(cmd.dev_id(), cmd.event_id(), cmd.event_id(),
-                                   cmd.icid());
-            break;
-          case Cmd::Op_mapti:
-            res = handle_cmd_mapti(cmd.dev_id(), cmd.event_id(), cmd.intid(),
-                                   cmd.icid());
-            break;
-          case Cmd::Op_inv:
-            res = handle_cmd_inv(cmd.dev_id(), cmd.event_id());
-            break;
-          case Cmd::Op_invall:
-            res = handle_cmd_invall(cmd.icid());
-            break;
-          case Cmd::Op_discard:
-            res = handle_cmd_discard(cmd.dev_id(), cmd.event_id());
-            break;
-          default:
-            warn().printf(
-              "Skipped execution of unsupported command %u at offset 0x%x.\n",
-              cmd.op().get(), _cmd_queue_read_off);
-            res = Cmd::Err_ok;
-            break;
-          }
-
-        if (res != Cmd::Err_ok)
-          warn().printf(
-            "Execution of command %u at offset 0x%x failed with error 0x%x.\n",
-            cmd.op().get(), _cmd_queue_read_off, res);
-
-        _cmd_queue_read_off = (_cmd_queue_read_off + Cmd::Size) % _cmd_queue_size;
-      }
-  }
-
-  Cpu *lookup_col(Icid icid)
-  {
-    return icid < _cols.size() ? _cols[icid] : nullptr;
-  }
-
-  Irq *lookup_lpi(Dev_id dev_id, Event_id event_id) const
-  {
-    if (dev_id >= Num_devices || event_id >= Num_events)
-      return nullptr;
-
-    auto ite = _itt.find(Itt_key(dev_id, event_id));
-    return ite != _itt.end() ? ite->second : nullptr;
-  }
-
-  void map_lpi(Dev_id dev_id, Event_id event_id, Irq *irq)
-  {
-    _itt[Itt_key(dev_id, event_id)] = irq;
-  }
-
-  bool unmap_lpi(Dev_id dev_id, Event_id event_id)
-  {
-    auto ite = _itt.find(Itt_key(dev_id, event_id));
-    if (ite != _itt.end())
-      {
-        reset_lpi(ite->second);
-        _itt.erase(ite);
-        return true;
-      }
-    else
-      return false;
-  }
-
-  /**
-   * Unmap and reset all LPIs mapped for the given device.
-   */
-  void unmap_device(Dev_id dev_id)
-  {
-    for (auto ite = _itt.lower_bound(Itt_key(dev_id, 0)); ite != _itt.end();)
-    {
-        // ITT entries are ordered so that all entries of a device are
-        // consecutive.
-        if (ite->first.dev_id != dev_id)
-          break;
-
-        reset_lpi(ite->second);
-        ite = _itt.erase(ite);
-    }
-  }
-
-  /**
-   * Updates the enable state and priority of the LPI from configuration
-   * table of the redistributor it is mapped to.
-   *
-   * If the redistributor does not have LPIs enabled, the LPI is disabled.
-   *
-   * \pre LPI is mapped to a collection that is mapped to a valid redistributor.
-   */
-  void update_lpi_config(Irq *lpi)
-  {
-    assert(lpi->cpu() != Irq::Invalid_cpu);
-
-    auto redist = _gic->redist(lpi->cpu());
-    if (!redist || !redist->lpis_enabled())
-      {
-        lpi->enable(false);
-        lpi->pending(false);
-        return;
-      }
-
-    unsigned lpi_nr = lpi->id() - Lpi_base;
-
-    lpi->prio(redist->lpi_priority(lpi_nr));
-
-    Vcpu_handler *dest_cpu = lpi->enable(redist->lpi_enabled(lpi_nr));
-    if (dest_cpu)
-      dest_cpu->notify_irq();
-  }
-
-  void reset_lpi(Irq *lpi)
-  {
-    lpi->target(Invalid_col, nullptr);
-    lpi->enable(false);
-    lpi->pending(false);
-  }
-
-  Vcpu_obj_registry *trigger_lpi(Irq *lpi) const
-  {
-    // If the LPI does not target a valid CPU (e.g. the ICID assigned to the LPI
-    // has not been mapped to a redistributor) or if the targeted redistributor
-    // has LPIs disabled, ignore this attempt to make the LPI pending.
-    auto redist = _gic->redist(lpi->cpu());
-    if (!redist || !redist->lpis_enabled())
-      return nullptr;
-
-    _gic->set(lpi->id());
-    return redist->ipc_registry();
-  }
-
-  template
-  void lpis_for_col(Icid icid, C callback)
-  {
-    for (auto const &ite : _itt)
-    {
-      auto lpi = ite.second;
-      if (lpi->target() == icid)
-        callback(lpi);
-    }
-  }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "ITS"); }
-  static Dbg info() { return Dbg(Dbg::Irq, Dbg::Info, "ITS"); }
-  static Dbg warn() { return Dbg(Dbg::Irq, Dbg::Warn, "ITS"); }
-
-  cxx::Ref_ptr _gic;
-  cxx::Ref_ptr _ram;
-
-  /// Protects all operations performed on the ITS (MMIO accesses, command
-  /// execution and LPI lookups). Also protects Irq migration, because
-  /// Irq::target() relies on the caller to guard against concurrent calls.
-  mutable std::mutex _lock;
-
-  /// LPI IRQ array
-  /// - Irq::target() stores the ICID to which the LPI is assigned.
-  /// - Irq::cpu() refers to the vCPU targeted by the LPI, i.e. the
-  ///   redistributor to which the ICID assigned to the LPI is mapped.
-  Irq_array _lpis;
-
-  /// Indicates whether the ITS is enabled.
-  bool _enabled = false;
-
-  /// BASER for command queue
-  Gic_mem_reg _cmd_queue_baser;
-  l4_addr_t _cmd_queue_base = 0;
-  l4_uint32_t _cmd_queue_size = 0;
-  l4_uint32_t _cmd_queue_read_off = 0;
-  l4_uint32_t _cmd_queue_write_off = 0;
-
-  /// BASER for device table
-  Gic_mem_reg _device_table_baser = { Baser::Type_device };
-
-  /// Internal collection table, maps collection to redistributor (vCPU),
-  /// indexed by ICID.
-  std::array _cols;
-
-  /// Orders ITT entries so that all entries of a device are consecutive.
-  struct alignas(l4_uint32_t) Itt_key
-  {
-    Itt_key(Dev_id dev_id, Event_id event_id)
-    : event_id(event_id), dev_id(dev_id)
-    {
-      // DeviceID fits into l4_uint16_t
-      assert(dev_id <= 0xffffu);
-      // EventID fits into l4_uint16_t
-      assert(event_id <= 0xffffu);
-    }
-
-    const l4_uint16_t event_id;
-    const l4_uint16_t dev_id;
-
-    bool operator < (const Itt_key &o) const
-    {
-      // Allow the compiler to optimize this into a single comparison instruction.
-      return   static_cast(dev_id << 16 | event_id)
-             < static_cast(o.dev_id << 16 | o.event_id);
-    }
-  };
-
-  /// Interrupt translation table, maps DeviceID and EventID to LPI.
-  /// Invariant: Iff LPI in _itt then Irq:target() != Invalid_col
-  std::map _itt;
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    auto its = Vdev::make_device(devs);
-    devs->vmm()->register_mmio_device(its, Vmm::Region_type::Virtual, node);
-    return its;
-  }
-};
-
-static F f;
-static Vdev::Device_type e = {"arm,gic-v3-its", nullptr, &f};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic_cpu.cc b/src/l4/pkg/uvmm/server/src/arm/gic_cpu.cc
deleted file mode 100644
index 07f20888..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic_cpu.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2013-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "gic_cpu.h"
-
-namespace Gic {
-
-static bool atomic_set_bits(uint32_t *addr, uint32_t mask)
-{
-  l4_uint32_t old = __atomic_load_n(addr, __ATOMIC_ACQUIRE);
-  l4_uint32_t nv;
-
-  do
-    {
-      nv = old | mask;
-      if (nv == old)
-        return false;
-    }
-  while (!__atomic_compare_exchange_n(addr, &old, nv, true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-
-  return true;
-}
-
-static void atomic_clear_bits(uint32_t *addr, uint32_t bits)
-{
-  l4_uint32_t old = __atomic_load_n(addr, __ATOMIC_ACQUIRE);
-  l4_uint32_t mask = ~bits;
-  l4_uint32_t nv;
-  do
-    {
-      nv = old & mask;
-      if (nv == old)
-        return;
-    }
-  while (!__atomic_compare_exchange_n(addr, &old, nv, true,
-                                      __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-}
-
-void Vcpu_handler::handle_migrations()
-{
-  fetch_pending_irqs();
-  for (auto it = _owned_pend_irqs.begin(); it != _owned_pend_irqs.end();)
-    {
-      if (!it->is_pending_and_enabled() || !it->is_for_cpu(vcpu_id()))
-        {
-          Irq *removed = *it;
-          it = _owned_pend_irqs.erase(it);
-          if (removed->is_pending_and_enabled())
-            {
-              // Irq is pending&enabled after we removed it from our list.
-              // Make sure it is queued again on the right target cpu.
-              Vcpu_handler *cpu = removed->vcpu_handler();
-              cpu->queue(removed);
-              cpu->notify_irq();
-            }
-        }
-      else
-        ++it;
-    }
-}
-
-void Vcpu_handler::fetch_pending_irqs()
-{
-  // Atomically move newly pending Irqs here so that we can work on them
-  // without having to bother about concurrent list modifications.
-  Atomic_fwd_list tmp;
-  tmp.swap(_pending_irqs);
-
-  // Move newly arrived pending IRQs to our own, sorted list. A remove-insert
-  // sequence is not possible because there must be no point in time where a
-  // pending&enabled IRQ is not on a list.
-  for (auto n = tmp.begin(); n != tmp.end();)
-    {
-      auto pos = _owned_pend_irqs.before_begin();
-      for (;;)
-        {
-          auto next = pos;
-          ++next;
-          if (next == _owned_pend_irqs.end() || next->prio() > n->prio())
-            break;
-          pos = next;
-        }
-
-      n = _owned_pend_irqs.move_after(pos, tmp, n);
-    }
-
-  // We could sort the list again if the guest changed the priorities. But
-  // this overhead would be payed always which it not worth this corner case.
-}
-
-bool Cpu::set_sgi(unsigned irq)
-{
-  unsigned reg = irq / 4;
-  unsigned field_off = irq % 4;
-  l4_uint32_t bit = 1UL << (field_off * 8 + vmm_current_cpu_id);
-
-  return atomic_set_bits(&_sgi_pend[reg], bit);
-}
-
-void Cpu::clear_sgi(unsigned irq, unsigned src)
-{
-  unsigned reg = irq / 4;
-  unsigned field_off = irq % 4;
-  l4_uint32_t bit = (1UL << (field_off * 8 + src));
-
-  atomic_clear_bits(&_sgi_pend[reg], bit);
-}
-
-void
-Cpu::dump_sgis() const
-{
-  for (auto const &pending : _sgi_pend)
-    printf("%02x ", pending);
-  puts("");
-}
-
-} // Gic
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic_cpu.h b/src/l4/pkg/uvmm/server/src/arm/gic_cpu.h
deleted file mode 100644
index 28513abb..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic_cpu.h
+++ /dev/null
@@ -1,1100 +0,0 @@
-/*
- * Copyright (C) 2013-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-
-#include "atomic_fwd_list.h"
-#include "cpu_dev.h"
-#include "irq.h"
-#include "vcpu_ptr.h"
-
-#include "monitor/gic_cmd_handler.h"
-
-extern __thread unsigned vmm_current_cpu_id;
-
-namespace Gic {
-
-class Irq;
-
-/**
- * Base class for GIC CPU interface to handle pending guest interrupts.
- *
- * Each vCPU that is visible on the GIC has a corresponding CPU-interface
- * object that is derived from this class. This serves two purposes:
- *
- * - Enable cross-vCPU thread notifications if a guest IRQ is queued from a
- *   different thread. This is used to interrupt the guest so that the
- *   destination vCPU thread can pick up the interrupt and inject it into the
- *   vGIC LRs.
- * - Handle guest IRQ migrations. If the guest re-targets an IRQ that is
- *   pending, the thread that is in charge of maintaining the _owned_pend_irqs
- *   list must push the IRQ to the right destination.
- *
- * The X-CPU Irq notification handler is always bound to the corresponding vCPU
- * thread. As long as the vCPU is online the migration handler is bound there
- * too. Only in case a CPU is offline the migration handler will be bound to
- * the boot CPU to keep IRQ migration working.
- *
- * In any case, it must be guaranteed that only one thread will ever handle the
- * queued Irqs on this object! Only queuing Irqs is thread safe.
- */
-class Vcpu_handler : public L4::Irqep_t
-{
-  /**
-   * Dummy handler for Irqs.
-   *
-   * Only exists so that
-   *
-   *  - X-CPU IPIs trap the target vCPU into uvmm, and
-   *  - doorbell interrupts wake the vCPU from wait_for_ipc().
-   *
-   * Is always bound to the target vCPU thread even when the CPU is offline.
-   */
-  struct Irq_event_receiver : public L4::Irqep_t
-  {
-  public:
-    void handle_irq() {}
-  };
-
-public:
-  Vcpu_handler(Vmm::Vcpu_ptr vcpu, Vmm::Vcpu_ptr sentinel_vcpu)
-  : _vcpu(vcpu)
-  {
-    auto *registry = vcpu.get_ipc_registry();
-    L4Re::chkcap(registry->register_irq_obj(&_irq_event),
-                 "Cannot register X-CPU irq event");
-
-    _migration_event = L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                                   "allocate migration event");
-    L4Re::chksys(L4Re::Env::env()->factory()->create(_migration_event.get()),
-                 "create migration event");
-    rebind(sentinel_vcpu.get_ipc_registry());
-
-    L4Re::chkcap(registry->register_irq_obj(&_doorbell_irq),
-                 "Cannot create doorbell irq");
-    int err = l4_error(registry->server()
-                ->register_doorbell_irq(_doorbell_irq.obj_cap()));
-    if (err < 0 && err != -L4_ENOSYS)
-      L4Re::throw_error(err, "Cannot register doorbell irq");
-  }
-
-  /// Send a notification to this vCPU that an Irq is pending.
-  void notify_irq()
-  { _irq_event.obj_cap()->trigger(); }
-
-  /// Signal that migration maintenance is necessary
-  void notify_migration()
-  { _migration_event->trigger(); }
-
-  /**
-   * Queue Irq as pending on this vCPU.
-   *
-   * The vCPU is not notified. It is the responsibility of the caller to
-   * trigger X-CPU notifications if necessary.
-   */
-  void queue(Irq *e)
-  {
-    _pending_irqs.push(e);
-  }
-
-  inline bool online() const { return _online; }
-
-  /**
-   * Mark CPU interface as online.
-   *
-   * Transfers the responsibility of the migration work back to the actual
-   * vcpu. This must of course not be done for the VCPU that acts as sentinel.
-   * Must be called from the vCPU that comes online.
-   */
-  void online(Vmm::Vcpu_ptr vcpu, bool boot_cpu)
-  {
-    _online = true;
-
-    // The vCPU is about to take over IRQ injection and migration. The old
-    // sentinel vCPU must reliquish its ownership and pass it to us.
-    if (!boot_cpu)
-      {
-        std::unique_lock lock(_migration_lock);
-        _migration_rebind = vcpu;
-        notify_migration();
-        while (*_migration_rebind != nullptr)
-          _migration_cv.wait(lock);
-      }
-  }
-
-  /**
-   * Mark CPU interface as offline.
-   *
-   * Most importantly it pushes the migration handling to the sentinel vCPU
-   * (read: the boot CPU). Because this must be called from the vCPU that goes
-   * offline there can be no migration handling running. Hence there is no need
-   * to synchronize the rebinding.
-   */
-  void offline(Vmm::Vcpu_ptr sentinel_vcpu)
-  {
-    rebind(sentinel_vcpu.get_ipc_registry());
-    _online = false;
-  }
-
-  /**
-   * Push away Irqs that are on our pending list but that do not belong here.
-   */
-  void handle_migrations();
-
-  // L4::Irqep_t<> callback for _migration_event
-  void handle_irq()
-  {
-    handle_migrations();
-
-    // relinquish migration responsibility if requested
-    std::lock_guard lock(_migration_lock);
-    if (*_migration_rebind != nullptr)
-      {
-        rebind(_migration_rebind.get_ipc_registry());
-        _migration_rebind = Vmm::Vcpu_ptr(nullptr);
-        _migration_cv.notify_one();
-      }
-  }
-
-  Vmm::Vcpu_ptr vcpu() const { return _vcpu; }
-  unsigned vcpu_id() const { return _vcpu.get_vcpu_id(); }
-
-protected:
-  /// Priority sorted list of pending IRQs owned by this vCPU.
-  Atomic_fwd_list _owned_pend_irqs;
-
-  /// The VCPU
-  Vmm::Vcpu_ptr _vcpu;
-
-  /**
-   * Move all new pending Irqs to our priority sorted _owned_pend_irqs
-   * list.
-   */
-  void fetch_pending_irqs();
-
-private:
-  /// The list of pending IRQs for this (or an invalid) vCPU.
-  Atomic_fwd_list _pending_irqs;
-
-  /// The x-CPU pending IRQ notification
-  Irq_event_receiver _irq_event;
-
-  /// The pending migration signal
-  L4Re::Util::Unique_cap _migration_event;
-
-  /// Mutex protecting the migration handler rebinding
-  std::mutex _migration_lock;
-
-  /// Condition variable to sync the transition of the migration handler
-  std::condition_variable _migration_cv;
-
-  /// The new migration handler (or nullptr if ownership is kept)
-  Vmm::Vcpu_ptr _migration_rebind = Vmm::Vcpu_ptr(nullptr);
-
-  /// Is the corresponding vCPU online?
-  bool _online = false;
-
-  /// The doorbell interrupt that a guest interrupt is pending
-  Irq_event_receiver _doorbell_irq;
-
-  void rebind(Vcpu_obj_registry *registry)
-  {
-    L4Re::chkcap(registry->register_obj(this, _migration_event.get()),
-                 "Cannot register migration event");
-  }
-};
-
-class Irq_info
-{
-private:
-  template
-  friend class Monitor::Gic_cmd_handler;
-
-  using State = l4_uint32_t;
-  State _state = 0;
-
-public:
-  CXX_BITFIELD_MEMBER_RO( 0,  0, pending,     _state); // GICD_I[SC]PENDRn
-  CXX_BITFIELD_MEMBER_RO( 1,  1, active,      _state); // GICD_I[SC]ACTIVERn
-  CXX_BITFIELD_MEMBER_RO( 3,  3, enabled,     _state); // GICD_I[SC]ENABLERn
-  CXX_BITFIELD_MEMBER_RO( 4, 11, cpu,         _state); // the owning vcpu
-
-  CXX_BITFIELD_MEMBER_RO(12, 19, target,      _state); // GICD_ITARGETSRn ...
-  CXX_BITFIELD_MEMBER_RO(20, 27, prio,        _state); // GICD_IPRIORITYRn
-  CXX_BITFIELD_MEMBER_RO(28, 29, config,      _state); // GICD_ICFGRn
-  CXX_BITFIELD_MEMBER_RO(30, 30, group,       _state); // GICD_IGROUPRn
-
-  enum : unsigned { Invalid_cpu = 0xff }; // special case for cpu field
-  static_assert(Invalid_cpu >= static_cast(Vmm::Cpu_dev::Max_cpus),
-                "Invalid_cpu must not collide with available CPUs");
-
-private:
-  template
-  static bool atomic_set(STATET *state, VALT v)
-  {
-    State old = __atomic_load_n(state, __ATOMIC_ACQUIRE);
-    State nv;
-    do
-      {
-        nv = BFM::set_dirty(old, v);
-        if (old == nv)
-          return false;
-      }
-    while (!__atomic_compare_exchange_n(state, &old, nv,
-                                        true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-    return true;
-  }
-
-  enum
-  {
-    Pending_and_enabled = pending_bfm_t::Mask | enabled_bfm_t::Mask,
-  };
-
-  static bool is_pending_and_enabled(State state)
-  { return (state & Pending_and_enabled) == Pending_and_enabled; }
-
-  static bool is_pending_or_enabled(State state)
-  { return state & Pending_and_enabled; }
-
-  static bool is_active(State state)
-  { return state & active_bfm_t::Mask; }
-
-  Irq_info(Irq_info const &) = delete;
-  Irq_info operator = (Irq_info const &) = delete;
-
-  /**
-   * Set the pending or enabled bit.
-   *
-   * \param set Set bit. Either enabled_bfm_t::Mask or enabled_bfm_t::Mask.
-   * \return True if we made the IRQ pending&enabled. False if the IRQ was
-   *         already pending&enabled or is not yet pending&enabled.
-   */
-  bool set_pe(unsigned char set)
-  {
-    State old = __atomic_load_n(&_state, __ATOMIC_ACQUIRE);
-    do
-      {
-        if (old & set)
-          return false;
-      }
-    while (!__atomic_compare_exchange_n(&_state, &old, old | set,
-                                        true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-
-    // Note that we test the *old* value here. Above loop stops only if a bit
-    // has been set (otherwise it would have returned from the function). Here
-    // we test if the other bit was already set.
-    return is_pending_or_enabled(old);
-  }
-
-  /**
-   * Clear the pending or enabled flag.
-   */
-  void clear_pe(unsigned char clear)
-  {
-    State old = __atomic_load_n(&_state, __ATOMIC_ACQUIRE);
-    do
-      {
-        if (!(old & clear))
-          return;
-      }
-    while (!__atomic_compare_exchange_n(&_state, &old, old & ~clear,
-                                        true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-  }
-
-public:
-  Irq_info() = default;
-
-  bool enable()
-  { return set_pe(enabled_bfm_t::Mask); }
-
-  void disable()
-  { return clear_pe(enabled_bfm_t::Mask); }
-
-  bool set_pending()
-  { return set_pe(pending_bfm_t::Mask); }
-
-  void clear_pending()
-  { return clear_pe(pending_bfm_t::Mask); }
-
-  class Take_result
-  {
-  public:
-    enum Result { Ok, Drop, Keep };
-    constexpr Take_result(Result r) : _r(r) {}
-    explicit constexpr operator bool() const { return _r == Ok; }
-    constexpr bool drop() const { return _r == Drop; }
-    constexpr bool keep() const { return _r == Keep; }
-  private:
-    Result _r;
-  };
-
-  /**
-   * Try to atomically take a pending&enabled Irq for injection on \a cpu.
-   *
-   * Depending on the status this might succeed or, if failed, requires
-   * different actions. Either the Irq is still relevant for the cpu. In this
-   * case Take_result::Keep is returned. Or the Irq should be removed from the
-   * pending list of the \a cpu. This might be because the Irq is not p&e any
-   * more or needs to be pushed to a different CPU.
-   */
-  Take_result take_on_cpu(unsigned cpu)
-  {
-    State old = __atomic_load_n(&_state, __ATOMIC_ACQUIRE);
-    State nv;
-    do
-      {
-        if (!is_pending_and_enabled(old))
-          return Take_result::Drop;
-
-        // Pending&enabled IRQs are always queued on the right CPU even if they
-        // are still active on the old cpu. If the target CPU is invalid the
-        // original CPU retains the burden of coping with this rogue IRQ.
-        if (cpu_bfm_t::get(old) != cpu)
-          return cpu_bfm_t::get(old) == Invalid_cpu ? Take_result::Keep
-                                                    : Take_result::Drop;
-
-        // Already active? Cannot take twice!
-        if (is_active(old))
-          return Take_result::Keep;
-
-        nv = (old & ~pending_bfm_t::Mask) | active_bfm_t::Mask;
-      }
-    while (!__atomic_compare_exchange_n(&_state, &old, nv,
-                                        true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-    return Take_result::Ok;
-  }
-
-  bool eoi()
-  {
-    State old = __atomic_load_n(&_state, __ATOMIC_ACQUIRE);
-    while (!__atomic_compare_exchange_n(&_state, &old,
-                                        old & ~active_bfm_t::Mask,
-                                        true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
-      ;
-
-    return is_pending_and_enabled(old);
-  }
-
-  bool prio(unsigned char p)
-  { return atomic_set(&_state, p); }
-
-  bool active(bool a)
-  { return atomic_set(&_state, a); }
-
-  bool group(bool grp1)
-  { return atomic_set(&_state, grp1); }
-
-  bool config(unsigned cfg)
-  { return atomic_set(&_state, cfg); }
-
-  void target(unsigned char reg, unsigned cpu)
-  {
-    State old = __atomic_load_n(&_state, __ATOMIC_ACQUIRE);
-    State nv;
-    do
-      {
-        nv = target_bfm_t::set_dirty(old, reg);
-        nv = cpu_bfm_t::set_dirty(nv, cpu);
-        if (old == nv)
-          return;
-      }
-    while (!__atomic_compare_exchange_n(&_state, &old, nv, true,
-                                        __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
-  }
-
-  bool is_pending_and_enabled() const
-  {
-    State state = __atomic_load_n(&_state, __ATOMIC_ACQUIRE);
-    return is_pending_and_enabled(state);
-  }
-};
-
-class Irq : public Atomic_fwd_list_item
-{
-public:
-  Irq() = default;
-
-  Irq(const Irq &) = delete;
-  Irq(Irq &&) noexcept = delete;
-  Irq& operator=(const Irq &) = delete;
-  Irq& operator=(Irq &&) noexcept = delete;
-
-  enum : unsigned { Invalid_cpu = Irq_info::Invalid_cpu };
-
-  /**
-   * Initialize state for SPIs.
-   *
-   * By default SPIs target no CPU. But the guest can make an SPI
-   * pending&enabled _before_ setting the target CPU. This requires a sentinel
-   * _vcpu where the Irq is queued so that the Irq can be pushed to the right
-   * vCPU once the guest sets the target.
-   *
-   * This setup is only required for SPIs. PPIs have a fixed target that is
-   * initialized in Dist_if::setup_cpu(). LPIs cannot be made pending unless
-   * the LPI already targets a valid CPU.
-   */
-  void init_spi(Vcpu_handler *sentinel)
-  {
-    _vcpu = sentinel;
-    _irq.target(0, Invalid_cpu);
-  }
-
-  bool enabled() const { return _irq.enabled(); }
-  bool pending() const { return _irq.pending(); }
-  bool active() const { return _irq.active(); }
-  bool group() const { return _irq.group(); }
-  unsigned char config() const { return _irq.config(); }
-  unsigned char prio() const { return _irq.prio(); }
-  unsigned char target() const { return _irq.target(); }
-
-  Irq_src_handler *get_irq_src_handler() const { return _src; }
-
-  bool is_pending_and_enabled() const { return _irq.is_pending_and_enabled(); }
-  bool is_for_cpu(unsigned char cpu_id)
-  { return _irq.cpu() == cpu_id || _irq.cpu() == Invalid_cpu; }
-
-  unsigned cpu() const { return _irq.cpu(); }
-  unsigned id() const { return _id; }
-  unsigned lr() const { return _lr; }
-
-  void set_irq_src(Irq_src_handler *src)
-  {
-    _src = src;
-    if (src)
-      src->configure(vcpu_irq_cfg());
-  }
-
-  void set_id(uint16_t id) { _id = id; }
-
-  Vcpu_handler *enable(bool ena)
-  {
-    Vcpu_handler *dest_vcpu = nullptr;
-    if (ena)
-      {
-        if (_irq.enable())
-          dest_vcpu = vcpu_handler();
-        if (_src && _src->enable())
-          return nullptr;
-      }
-    else
-      {
-        _irq.disable();
-        if (_src)
-          _src->disable();
-      }
-
-    if (dest_vcpu)
-      dest_vcpu->queue(this);
-
-    return dest_vcpu;
-  }
-
-  Vcpu_handler *pending(bool pend)
-  {
-    Vcpu_handler *dest_vcpu = nullptr;
-    if (pend)
-      {
-        if (_irq.set_pending())
-          dest_vcpu = vcpu_handler();
-      }
-    else
-      _irq.clear_pending();
-
-    if (dest_vcpu)
-      dest_vcpu->queue(this);
-
-    return dest_vcpu;
-  }
-
-  Irq_info::Take_result take_on_cpu(unsigned cpu)
-  {
-    return _irq.take_on_cpu(cpu);
-  }
-
-  void eoi()
-  {
-    if (_irq.eoi())
-      vcpu_handler()->notify_irq();
-    if (_src)
-      _src->eoi();
-  }
-
-  void prio(unsigned char p)
-  {
-    _irq.prio(p);
-    if (_src)
-      _src->configure(vcpu_irq_cfg());
-  }
-
-  void group(bool grp1)
-  {
-    _irq.group(grp1);
-    if (_src)
-      _src->configure(vcpu_irq_cfg());
-  }
-
-  void active(bool act) { _irq.active(act); }
-  void config(unsigned char cfg) { _irq.config(cfg); }
-
-  void set_lr(unsigned idx) { _lr = idx; }
-  void clear_lr() { set_lr(0); }
-
-  /**
-   * Change target of Irq to potentially different vCPU.
-   *
-   * *Must* not be called concurrently from multiple CPUs. Other operations
-   * can still be invoked in parallel from other CPUs.
-   *
-   * \param reg    The field value in GICD_ITARGETSRn register.
-   * \param vcpu   The new vCPU that handles pending Irqs. May be nullptr in
-   *               case the irq targets no valid vCPU (e.g. only offline or
-   *               non-exiting vCPUs).
-   *
-   * If there is no valid target for the Irq the old vCPU still has to cope
-   * with the pending Irqs. This is considered an error of the guest because an
-   * enabled Irq should always target a valid CPU.
-   */
-  void target(unsigned char reg, Vcpu_handler *vcpu)
-  {
-    Vcpu_handler *old = vcpu_handler();
-    if (vcpu)
-      set_vcpu_handler(vcpu);
-
-    // New queues and notifications will already go to the new vCPU. It cannot
-    // be taken there yet because the cpu field is not updated. But even then
-    // it will stay on the right list.
-
-    _irq.target(reg,
-                vcpu ? vcpu->vcpu_id() : static_cast(Invalid_cpu));
-
-    // If the IRQ is queued it must most likely be evicted from the old list.
-    // It might also got queued during migration but waking the old vCPU does
-    // not harm.
-    if (in_list() && old != vcpu)
-      old->notify_migration();
-
-    // Inform handler of new CPU
-    if (vcpu && _src)
-      _src->irq_src_target(vcpu->vcpu());
-  }
-
-  Vcpu_handler *vcpu_handler() const
-  { return __atomic_load_n(&_vcpu, __ATOMIC_ACQUIRE); }
-
-private:
-  Vcpu_handler *_vcpu = nullptr;
-  Irq_src_handler *_src = nullptr;
-  Irq_info _irq;
-  uint16_t _id = 0;
-
-  /*
-   * Keeps track of the used lr, uses 0 for "no link register
-   * assigned" (see #get_empty_lr())
-   */
-  unsigned char _lr = 0;
-
-  void set_vcpu_handler(Vcpu_handler *vcpu)
-  { __atomic_store_n(&_vcpu, vcpu, __ATOMIC_RELEASE); }
-
-  l4_umword_t vcpu_irq_cfg() const
-  {
-     Vmm::Arm::Gic_h::Vcpu_irq_cfg cfg(0);
-     cfg.vid() = id();
-     cfg.grp1() = group();
-     cfg.prio() = prio();
-     return cfg.raw;
-  }
-};
-
-class Irq_array
-{
-public:
-  using Irq = ::Gic::Irq;
-
-  explicit Irq_array(unsigned irqs, unsigned first_irq)
-  : _size(irqs)
-  {
-    _irqs = cxx::make_unique(irqs);
-    for (unsigned i = 0; i < irqs; i++)
-      _irqs.get()[i].set_id(i + first_irq);
-  }
-
-  Irq &operator [] (unsigned i)
-  { return _irqs.get()[i]; }
-
-  Irq const &operator [] (unsigned i) const
-  { return _irqs.get()[i]; }
-
-  unsigned size() const { return _size; }
-
-private:
-  cxx::unique_ptr _irqs;
-  unsigned _size;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// GIC CPU interface
-class Cpu : public Vcpu_handler
-{
-  template
-  friend class Monitor::Gic_cmd_handler;
-
-public:
-  using Irq = ::Gic::Irq;
-
-  enum { Num_local = 32 };
-  enum { Num_lrs = 4, Lr_mask = (1UL << Num_lrs) - 1U };
-  enum { Lpi_base = 8192 };
-
-  static_assert(Num_lrs <= 32, "Can only handle up to 32 list registers.");
-
-  Cpu(Vmm::Vcpu_ptr vcpu, Vmm::Vcpu_ptr sentinel_vcpu, Irq_array *spis)
-  : Vcpu_handler(vcpu, sentinel_vcpu), _local_irq(Num_local, 0)
-  {
-    memset(&_sgi_pend, 0, sizeof(_sgi_pend));
-
-    _vcpu = vcpu;
-    _spis = spis;
-  }
-
-  /// Get the number of CPU local IRQs
-  static unsigned num_local() { return Num_local; }
-
-  /// Get if this is a valid CPU interface (with a vCPU.
-  bool is_valid() const { return *_vcpu; }
-
-  /**
-   * Get the Processor_Number + Affinity_Value of GICv3+ GICR_TYPER.
-   *
-   * If this his not a valid CPU interface affinity willbe 0xffffffff.
-   */
-  l4_uint64_t get_typer() const
-  {
-    if (is_valid())
-      return (static_cast(_vcpu.get_vcpu_id()) << 8)
-             | (static_cast(affinity()) << 32);
-
-    return 0xffffffff00000000;
-  }
-
-  /// get the local IRQ for irqn (irqn < 32)
-  Irq& local_irq(unsigned irqn) { return _local_irq[irqn]; }
-  /// get the array of local IRQs of this CPU
-  Irq_array &local_irqs() { return _local_irq; }
-
-  /// Set the array of GICv3+ LPIs.
-  void register_lpis(Irq_array *lpis) { _lpis = lpis; }
-
-  /*
-   * Get empty list register
-   *
-   * We might try to preempt a lower priority interrupt from the
-   * link registers here. But since our main guest does not use
-   * priorities we ignore this possibility.
-   *
-   * \return Returns 0 if no empty list register is available, (lr_idx
-   *         + 1) otherwise
-   */
-  unsigned get_empty_lr() const
-  { return __builtin_ffs(_elsr()); }
-
-  /// return if there are pending IRQs in the LRs
-  bool pending_irqs() const
-  { return _elsr() != Lr_mask; }
-
-  /// Get in Irq for the given `intid`, works for SGIs, PPIs, and SPIs
-  Irq& irq_from_intid(unsigned intid)
-  {
-    if (intid < Num_local)
-      return _local_irq[intid];
-    else if (intid < Lpi_base)
-      return (*_spis)[intid - Num_local];
-    else
-      return (*_lpis)[intid - Lpi_base];
-  }
-
-  /// Get the associated vCPU
-  Vmm::Vcpu_ptr vcpu() const { return _vcpu; }
-
-  /**
-   * Set a GICv2 SGI pending and notify this vCPU.
-   * \pre `irq` < 16.
-   */
-  void ipi(unsigned irq)
-  {
-    if (set_sgi(irq))
-      notify_irq();
-  }
-
-  /// Read GICv2 GICD_[SC]PENDSGIR
-  l4_uint32_t read_sgi_pend(unsigned reg)
-  { return _sgi_pend[reg]; }
-
-  /// Write GICv2 GICD_SPENDSGIR
-  void write_set_sgi_pend(unsigned reg, l4_uint32_t value);
-  /// Write GICv2 GICD_CPENDSGIR
-  void write_clear_sgi_pend(unsigned reg, l4_uint32_t value);
-
-  /// Handle pending EOIs
-  template
-  void handle_eois();
-
-  /// Handle pending GICv2 SGIs
-  template
-  void handle_ipis();
-
-  /// Add a pending IRQ into a list register (LR).
-  template
-  void add_pending_irq(unsigned lr, Irq &irq, unsigned src_cpu = 0);
-
-  /// Try to inject an SPI on this CPU
-  template
-  bool inject(Irq &irq, unsigned src_cpu = 0);
-
-  /// Handle pending vGIC maintenance IRQs
-  template
-  void handle_maintenance_irq()
-  { handle_eois(); }
-
-  /**
-   * Find and take a pending&enabled IRQ targeting this CPU.
-   *
-   * If an Irq is returned it *must* be added to a Lr. The Irq will already be
-   * marked as active.
-   */
-  Irq *take_pending_irq(unsigned char min_prio)
-  {
-    bool rescan;
-    do
-      {
-        rescan = false;
-        fetch_pending_irqs();
-
-        for (auto it = _owned_pend_irqs.begin(); it != _owned_pend_irqs.end();)
-          {
-            if (it->prio() >= min_prio)
-              break;
-
-            auto took = it->take_on_cpu(vcpu_id());
-            if (took)
-              {
-                Irq *ret = *it;
-                _owned_pend_irqs.erase(it);
-                if (ret->is_pending_and_enabled())
-                  queue_and_notify(ret);
-                return ret;
-              }
-            else if (took.drop())
-              {
-                Irq *removed = *it;
-                it = _owned_pend_irqs.erase(it);
-                if (removed->is_pending_and_enabled())
-                  rescan = queue_and_notify(removed) || rescan;
-              }
-            else
-              ++it;
-          }
-      }
-    while (rescan);
-
-    return nullptr;
-  }
-
-
-  /**
-   * Set a GICv2 SGI for this CPU pending
-   * \pre `irq` < 16.
-   */
-  bool set_sgi(unsigned irq);
-
-  /**
-   * Clear a pending GICv2 SGI from `src` on this CPU.
-   * \pre `irq` < 16.
-   */
-  void clear_sgi(unsigned irq, unsigned src);
-
-  /**
-   * Dump GICv2 SGI state.
-   */
-  void dump_sgis() const;
-
-  /// read GICV_HCR / ICH_HCR_EL2
-  Vmm::Arm::Gic_h::Hcr hcr() const
-  {
-    using Vmm::Arm::Gic_h::Hcr;
-    return Hcr(l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_GIC_HCR));
-  }
-
-  /// write GICV_HCR / ICH_HCR_EL2
-  void write_hcr(Vmm::Arm::Gic_h::Hcr hcr) const
-  { l4_vcpu_e_write_32(*_vcpu, L4_VCPU_E_GIC_HCR, hcr.raw); }
-
-  /// read GICV_MISR / ICH_MISR_EL2
-  Vmm::Arm::Gic_h::Misr misr() const
-  {
-    using Vmm::Arm::Gic_h::Misr;
-    return Misr(l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_GIC_MISR));
-  }
-
-  /// read GICH_VTR / ICH_VTR_EL2
-  Vmm::Arm::Gic_h::Vtr vtr() const
-  {
-    using Vmm::Arm::Gic_h::Vtr;
-    return Vtr(l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_GIC_VTR));
-  }
-
-  /**
-   * Get the affinity from the vCPU MPIDR.
-   * \pre the CPU interface must be initialized (see initialize()).
-   */
-  l4_uint32_t affinity() const
-  {
-    l4_uint64_t mpidr = l4_vcpu_e_read(*_vcpu, L4_VCPU_E_VMPIDR);
-    return (mpidr & 0x00ffffff) | ((mpidr >> 8) & 0xff000000);
-  }
-
-private:
-  /// GICv2 SGI pending registers
-  l4_uint32_t _sgi_pend[4]; // 4 * 4 == 16 SGIs a 8 bits
-
-  /// SGI and PPI IRQ array
-  Irq_array _local_irq;
-
-  /// SPI IRQ array from distributor
-  Irq_array *_spis;
-
-  /// GICv3+ LPI IRQ array
-  Irq_array *_lpis;
-
-  /// The associated vCPU
-  Vmm::Vcpu_ptr _vcpu = Vmm::Vcpu_ptr(nullptr);
-
-  l4_uint32_t _elsr() const
-  { return l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_GIC_ELSR) & Lr_mask; }
-
-  void _set_elsr(l4_uint32_t bits) const
-  {
-    unsigned id = L4_VCPU_E_GIC_ELSR;
-    l4_uint32_t e = l4_vcpu_e_read_32(*_vcpu, id);
-    l4_vcpu_e_write_32(*_vcpu, id, e | bits);
-  }
-
-  void _clear_elsr(l4_uint32_t bits) const
-  {
-    unsigned id = L4_VCPU_E_GIC_ELSR;
-    l4_uint32_t e = l4_vcpu_e_read_32(*_vcpu, id);
-    l4_vcpu_e_write_32(*_vcpu, id, e & ~bits);
-  }
-
-  bool queue_and_notify(Irq *irq)
-  {
-    Vcpu_handler *cpu = irq->vcpu_handler();
-    cpu->queue(irq);
-    if (cpu == this)
-      return true;
-
-    cpu->notify_irq();
-    return false;
-  }
-};
-
-inline void
-Cpu::write_set_sgi_pend(unsigned reg, l4_uint32_t value)
-{
-  l4_uint32_t o = _sgi_pend[reg];
-  l4_uint32_t n = o | value;
-  if (o == n)
-    return;
-
-  _sgi_pend[reg] = n;
-
-  for (unsigned i = 0; i < 4; ++i)
-    {
-      if ((o ^ n) & 0xff)
-        local_irq(i + (reg * 4)).pending(true);
-
-      o >>= 8;
-      n >>= 8;
-    }
-}
-
-inline void
-Cpu::write_clear_sgi_pend(unsigned reg, l4_uint32_t value)
-{
-  l4_uint32_t o = _sgi_pend[reg];
-  l4_uint32_t n = o & ~value;
-  if (o == n)
-    return;
-
-  _sgi_pend[reg] = n;
-  for (unsigned i = 0; i < 4; ++i)
-    {
-      if ((o ^ n) & 0xff)
-        local_irq(i + (reg * 4)).pending(false);
-
-      o >>= 8;
-      n >>= 8;
-    }
-}
-
-template
-inline void
-Cpu::handle_eois()
-{
-  using Lr = typename CPU_IF::Lr;
-  using namespace Vmm::Arm;
-  Gic_h::Misr misr(l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_GIC_MISR));
-
-  if (!misr.eoi())
-    return;
-
-  l4_uint32_t eisr = l4_vcpu_e_read_32(*_vcpu, L4_VCPU_E_GIC_EISR);
-  if (!eisr)
-    return;
-
-  for (unsigned i = 0; i < Num_lrs; ++i, eisr >>= 1)
-    {
-      if (!(eisr & 1))
-        continue;
-
-      Lr lr = CPU_IF::read_lr(_vcpu, i);
-      Irq &c = irq_from_intid(lr.vid());
-      assert(lr.state() == Lr::Empty);
-
-      c.clear_lr();
-      c.eoi();
-      CPU_IF::write_lr(_vcpu, i, Lr(0));
-      _set_elsr(1U << i);
-    }
-
-  // all EOIs are handled
-  l4_vcpu_e_write_32(*_vcpu, L4_VCPU_E_GIC_EISR, 0);
-  misr.eoi() = 0;
-  l4_vcpu_e_write_32(*_vcpu, L4_VCPU_E_GIC_MISR, misr.raw);
-}
-
-template
-inline void
-Cpu::add_pending_irq(unsigned lr, Irq &irq, unsigned src_cpu)
-{
-  using Lr = typename CPU_IF::Lr;
-  Lr new_lr(0);
-  new_lr.state() = Lr::Pending;
-  new_lr.eoi()   = 1; // need an EOI IRQ
-  new_lr.vid()   = irq.id();
-  new_lr.set_cpuid(src_cpu);
-  new_lr.prio()  = irq.prio();
-  new_lr.grp1()  = irq.group();
-
-  // uses 0 for "no link register assigned" (see #get_empty_lr())
-  irq.set_lr(lr + 1);
-  CPU_IF::write_lr(_vcpu, lr, new_lr);
-  _clear_elsr(1U << lr);
-}
-
-template
-inline bool
-Cpu::inject(Irq &irq, unsigned src_cpu)
-{
-  // free LRs if there are inactive LRs
-  handle_eois();
-
-  unsigned lr_idx = get_empty_lr();
-  if (!lr_idx)
-    return false;
-
-  if (!irq.take_on_cpu(vcpu_id()))
-    return false;
-
-  add_pending_irq(lr_idx - 1, irq, src_cpu);
-  return true;
-}
-
-class Cpu_vector
-{
-private:
-  using Cpu_ptr = cxx::unique_ptr;
-
-  cxx::unique_ptr _cpu;
-  unsigned _n = 0;
-  unsigned _c = 0;
-
-public:
-  using Irq = Cpu::Irq;
-
-  explicit Cpu_vector(unsigned capacity)
-  : _cpu(cxx::make_unique(capacity)),
-    _c(capacity)
-  {}
-
-  unsigned capacity() const { return _c; }
-  unsigned size() const { return _n; }
-  Cpu_ptr const *begin() const { return &_cpu[0]; }
-  Cpu_ptr const *end() const { return &_cpu[_n]; }
-  Cpu_ptr const &operator [] (unsigned idx) const { return _cpu[idx]; }
-
-  bool set_at(unsigned idx, Cpu_ptr &&cpu)
-  {
-    if (idx >= capacity())
-      return false;
-
-    if ((idx + 1) > _n)
-      _n = idx + 1;
-
-    _cpu[idx] = cxx::move(cpu);
-    return true;
-  }
-};
-
-template
-void
-Cpu::handle_ipis()
-{
-  if (!GIC_IMPL::sgi_pend_regs())
-    return;
-
-  using Cpu_if = typename GIC_IMPL::Cpu_if;
-
-  for (unsigned irq_num = 0; irq_num < 16; ++irq_num)
-    {
-      using Ma = Vmm::Mem_access;
-      unsigned char const cpu_bits
-        = Ma::read(_sgi_pend[irq_num / 4], irq_num, Ma::Wd8);
-
-      if (!cpu_bits)
-        continue;
-
-      // inject one IPI, if another CPU posted the same IPI we keep it
-      // pending
-      unsigned src = __builtin_ffs(static_cast(cpu_bits)) - 1;
-      Irq &irq = local_irq(irq_num);
-
-      // set irq pending and try to inject
-      if (irq.pending(true))
-        {
-          if (!inject(irq, src))
-            {
-              // Can happen if no LR was free. Will try again on next guest
-              // entry before other iterrupts are injected.
-              irq.pending(false);
-              return;
-            }
-          clear_sgi(irq_num, src);
-        }
-    }
-}
-
-}
-
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic_dist.h b/src/l4/pkg/uvmm/server/src/arm/gic_dist.h
deleted file mode 100644
index 56bce94d..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic_dist.h
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Copyright (C) 2013-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "debug.h"
-#include "gic_cpu.h"
-#include "gic_iface.h"
-
-namespace Gic {
-
-template
-class Dist
-: public Dist_if,
-  public Ic,
-  public Monitor::Gic_cmd_handler>
-{
-  friend Monitor::Gic_cmd_handler>;
-
-protected:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "GICD"); }
-
-public:
-  using Irq = Cpu::Irq;
-
-  enum Regs
-  {
-    CTLR  = 0x000,
-    TYPER = 0x004, // RO
-    IIDR  = 0x008, // RO
-    SGIR  = 0xf00, // WO
-  };
-
-  l4_uint32_t ctlr;
-  unsigned char tnlines;
-
-  Dist(unsigned tnlines, unsigned max_cpus)
-  : ctlr(0), tnlines(tnlines),
-    _cpu(max_cpus),
-    _spis(tnlines * 32, Cpu::Num_local),
-    _prio_mask(0),
-    _lpis(nullptr)
-  {
-  }
-
-  Irq &ppi(unsigned cpu, unsigned ppi)
-  {
-    assert (ppi < Cpu::Num_local);
-    return _cpu[cpu]->local_irqs()[ppi];
-  }
-
-  Irq const &ppi(unsigned cpu, unsigned ppi) const
-  {
-    assert (ppi < Cpu::Num_local);
-    return _cpu[cpu]->local_irqs()[ppi];
-  }
-
-  Irq &spi(unsigned spi)
-  {
-    assert (spi < _spis.size());
-    return _spis[spi];
-  }
-
-  Irq const &spi(unsigned spi) const
-  {
-    assert (spi < _spis.size());
-    return _spis[spi];
-  }
-
-  void register_lpis(Irq_array *lpis)
-  {
-    // Ensure that once set, the LPI array cannot be changed.
-    if (_lpis)
-      L4Re::chksys(-L4_EEXIST, "Assigning LPIs to GIC");
-
-    _lpis = lpis;
-    for (auto const &cpu : _cpu)
-      {
-        if (cpu)
-          cpu->register_lpis(_lpis);
-      }
-  }
-
-  Irq &lpi(unsigned lpi)
-  {
-    assert (_lpis && lpi < _lpis->size());
-    return (*_lpis)[lpi];
-  }
-
-  Irq const &lpi(unsigned lpi) const
-  {
-    assert (_lpis && lpi < _lpis->size());
-    return (*_lpis)[lpi];
-  }
-
-  void bind_cpulocal_irq_src_handler(unsigned cpu, unsigned irq,
-                                     Irq_src_handler *handler) override
-  {
-    auto &pin = ppi(cpu, irq);
-
-    if (handler && pin.get_irq_src_handler())
-      L4Re::chksys(-L4_EEXIST, "Assigning IRQ src handler to PPI");
-
-    pin.set_irq_src(handler);
-  }
-
-
-  /// \group Implementation of Ic functions
-  /// \{
-  void clear(unsigned) override {}
-
-  void bind_irq_src_handler(unsigned irq, Irq_src_handler *handler) override
-  {
-    Irq &pin = spi(irq - Cpu::Num_local);
-
-    if (handler && pin.get_irq_src_handler())
-      L4Re::chksys(-L4_EEXIST, "Assigning IRQ src handler to GIC");
-
-    pin.set_irq_src(handler);
-  }
-
-  Irq_src_handler *get_irq_src_handler(unsigned irq) const override
-  { return spi(irq - Cpu::Num_local).get_irq_src_handler(); }
-
-  int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const override
-  {
-    enum Irq_types
-    {
-      Irq_ppi_base = 16,
-      Irq_ppi_max = 16,
-      Irq_spi_base = 32,
-    };
-
-    enum Dts_interrupt_cells
-    {
-      Irq_cell_type = 0,
-      Irq_cell_number = 1,
-      Irq_cell_flags = 2,
-      Irq_cells = 3
-    };
-
-    if (propsz < Irq_cells)
-      return -L4_ERANGE;
-
-    int irqnr = fdt32_to_cpu(prop[Irq_cell_number]);
-
-    if (fdt32_to_cpu(prop[Irq_cell_type]) == 0)
-      irqnr += Irq_spi_base;
-    else
-      {
-        if (irqnr >= Irq_ppi_max)
-          L4Re::chksys(-L4_EINVAL, "Only 16 PPI interrupts allowed");
-
-        irqnr += Irq_ppi_base;
-      }
-
-    if (read)
-      *read = Irq_cells;
-
-    return irqnr;
-  }
-  /// \} end of Ic implementation
-
-  /// \group abstract GIC interface for different GIC versions
-  /// \{
-
-  /// Setup the CPU interface for the given `vcpu` running on `thread`.
-  Cpu *add_cpu(Vmm::Vcpu_ptr vcpu)
-  {
-    unsigned cpu = vcpu.get_vcpu_id();
-    if (cpu >= _cpu.capacity())
-      return nullptr;
-
-    // The boot CPU is the sentinel for all CPUs, including itself.
-    // Nevertheless a special case for the boot CPU is needed here, because
-    // the entry for the boot CPU is not yet set up in the _cpu vector.
-    Vmm::Vcpu_ptr sentinel_vcpu = cpu != 0 ? _cpu[0]->vcpu() : vcpu;
-
-    trace().printf("set CPU interface for CPU %02d (%p) to %p\n",
-                   cpu, &_cpu[cpu], *vcpu);
-    _cpu.set_at(cpu, cxx::make_unique(vcpu, sentinel_vcpu, &_spis));
-    Cpu *ret = _cpu[cpu].get();
-    ret->register_lpis(_lpis);
-    if (cpu == 0)
-      {
-        _prio_mask = ~((1U << (7 - ret->vtr().pri_bits())) - 1U);
-
-        // Our implementation assumes that there is always a valid
-        // Irq::vcpu_handler() for interrupts that can get pending&enabled. To
-        // make things easy, all SPIs use the boot CPU as Vcpu_handler
-        // sentinel.
-        for (unsigned i = 0; i < _spis.size(); i++)
-          _spis[i].init_spi(ret);
-      }
-
-    return ret;
-  }
-
-  /// write to the GICD_CTLR.
-  virtual void write_ctlr(l4_uint32_t val)
-  {
-    ctlr = val;
-  }
-
-  /// read to the GICD_TYPER.
-  virtual l4_uint32_t get_typer() const
-  {
-    return tnlines | (static_cast(_cpu.size() - 1) << 5);
-  }
-
-  /// read to the CoreSight IIDRs.
-  virtual l4_uint32_t iidr_read(unsigned offset) const = 0;
-  /// \}
-
-  Cpu *cpu(unsigned id)
-  { return id < _cpu.capacity() ? _cpu[id].get() : nullptr; }
-
-protected:
-  /**
-   * Check targets of SPIs and possibly divert them to a different vCPU.
-   *
-   * When affinity routing is not used the target vCPU of a SPI might change
-   * if the set of online vCPUs changes.
-   */
-  void retarget_spis()
-  {
-    if (AFF_ROUTING)
-      return;
-
-    std::lock_guard lock(_target_lock);
-    for (unsigned i = 0; i < _spis.size(); i++)
-      {
-        Irq &irq = _spis[i];
-        unsigned vcpu = find_cpu_for_target(irq.target());
-        if (vcpu != irq.cpu())
-          irq.target(irq.target(), cpu(vcpu));
-      }
-  }
-
-private:
-  /**
-   * Get the first usable vCPU number from the given GICD_ITARGETSRn field.
-   *
-   * Might be Irq::Invalid_cpu if the irq targets no CPU or only offline CPUs.
-   */
-  unsigned find_cpu_for_target(unsigned char tgt)
-  {
-    while (tgt)
-      {
-        unsigned first = __builtin_ffs(tgt) - 1;
-        if (first >= _cpu.capacity())
-          return Irq::Invalid_cpu;
-
-        Vcpu_handler *cpu = _cpu[first].get();
-        if (cpu && cpu->online())
-          return first;
-
-        tgt &= ~(1U << first);
-      }
-
-    return Irq::Invalid_cpu;
-  }
-
-  /// \group Per IRQ register interfaces
-  /// \{
-  enum Reg_group_idx
-  {
-    R_group = 0,
-    R_isenable,
-    R_icenable,
-    R_ispend,
-    R_icpend,
-    R_isactive,
-    R_icactive,
-    R_prio,
-    R_target,
-    R_cfg,
-    R_grpmod,
-    R_nsacr,
-    R_route
-  };
-
-  l4_uint32_t irq_mmio_read(Irq const &irq, unsigned rgroup)
-  {
-    switch (rgroup)
-      {
-      case R_group:    return irq.group();
-      case R_isenable:
-      case R_icenable: return irq.enabled();
-      case R_ispend:
-      case R_icpend:   return irq.pending();
-      case R_isactive:
-      case R_icactive: return irq.active();
-      case R_prio:     return irq.prio();
-      case R_target:   return AFF_ROUTING ? 0 : irq.target();
-      case R_cfg:      return irq.config();
-      case R_grpmod:   return 0;
-      case R_nsacr:    return 0;
-      default:         assert (false); return 0;
-      }
-  }
-
-  void irq_mmio_write(Irq &irq, unsigned rgroup, l4_uint32_t value)
-  {
-    switch (rgroup)
-      {
-      case R_group:    irq.group(value);               return;
-      case R_isenable:
-        if (value)
-          {
-            Vcpu_handler *dest_cpu = irq.enable(true);
-            if (dest_cpu)
-              dest_cpu->notify_irq();
-          }
-          return;
-      case R_icenable:
-        if (value)
-          irq.enable(false);
-        return;
-      case R_ispend:
-        if (value)
-          {
-            Vcpu_handler *dest_cpu = irq.pending(true);
-            if (dest_cpu)
-              dest_cpu->notify_irq();
-          }
-          return;
-      case R_icpend:
-        if (value)
-          irq.pending(false);
-        return;
-      case R_isactive:
-        if (value)
-          irq.active(true);
-        return;
-      case R_icactive:
-        if (value)
-          irq.active(false);
-        return;
-      case R_prio:     irq.prio(value & _prio_mask);   return;
-      case R_target:
-        if (!AFF_ROUTING && irq.id() >= Cpu::Num_local)
-          {
-            std::lock_guard lock(_target_lock);
-            irq.target(value, cpu(find_cpu_for_target(value)));
-          }
-        return;
-      case R_cfg:      irq.config(value);              return;
-      case R_grpmod:   /* GICD_CTRL.DS=1 -> RAZ/WI */  return;
-      case R_nsacr:    /* GICD_CTRL.DS=1 -> RAZ/WI */  return;
-      default:         assert (false);                 return;
-      }
-  }
-  /// \} end of per IRQ registers
-
-  /**
-   * Helper to demux multiple IRQs-per register accesses.
-   * \note Local IRQs vs SPIs must be resolved already.
-   */
-  template
-  void _demux_irq_reg(Irq_array &irqs,
-                      unsigned s, unsigned n,
-                      unsigned reg, OP &&op)
-  {
-    unsigned const rshift = 8 >> SHIFT;
-    l4_uint32_t const mask = 0xff >> (8 - rshift);
-    for (unsigned x = 0; x < n; ++x)
-      {
-        unsigned const i = x + s;
-        op(irqs[i], reg, mask, rshift * x);
-      }
-  }
-
-  /**
-   * Helper to demux multiple IRQs-per register accesses.
-   * \note Local IRQs vs SPIs must be resolved already.
-   */
-  template
-  void _demux_irq_reg(unsigned reg, unsigned offset,
-                      unsigned size,
-                      unsigned cpu_id, OP &&op)
-  {
-    unsigned const irq_s = (offset & (~0U) << size) << SHIFT;
-    unsigned const nirq = (1 << size) << SHIFT;
-
-    if (irq_s < Cpu::Num_local)
-      _demux_irq_reg(_cpu[cpu_id]->local_irqs(), irq_s, nirq, reg, op);
-    else if (irq_s - Cpu::Num_local < _spis.size())
-      _demux_irq_reg(_spis, irq_s - Cpu::Num_local, nirq, reg, op);
-  }
-
-  /**
-   * Helper to demux a complete range of multi IRQ registers with
-   * equal number of IRQs per register (given by SHIFT).
-   * \pre `reg` >= `START`
-   * \retval false if `reg` >= END
-   * \retval true if `reg` < END;
-   */
-  template
-  bool _demux_irq_block(unsigned reg, unsigned size, unsigned cpu_id, OP &&op)
-  {
-    unsigned const rsh = 10 - SHIFT;
-    static_assert((START & ((1U << rsh) - 1)) == 0U, "low bits of START zero");
-    static_assert((END   & ((1U << rsh) - 1)) == 0U, "low bits of END zero");
-    if (reg < END)
-      {
-        unsigned const x = reg >> rsh;
-        _demux_irq_reg(x - (START >> rsh) + BLK,
-                              reg & ~((~0U) << rsh), size, cpu_id, op);
-        return true;
-      }
-    return false;
-  }
-
-  /**
-   * Demux the access to the whole multi-IRQ register range of the
-   * GIC distributor.
-   */
-  template
-  bool _demux_per_irq(unsigned reg, unsigned size, unsigned cpu_id, OP &&op)
-  {
-    if (reg < 0x80)
-      return false;
-
-    if (_demux_irq_block(reg, size, cpu_id, op))
-      return true;
-
-    if (_demux_irq_block(reg, size, cpu_id, op))
-      return true;
-
-    if (_demux_irq_block(reg, size, cpu_id, op))
-      return true;
-
-    if (_demux_irq_block(reg, size, cpu_id, op))
-      return true;
-
-    if (_demux_irq_block(reg, size, cpu_id, op))
-      return true;
-
-    return false;
-  }
-
-  /**
-   * Helper to access the IIDR register range of CoreSight GICs
-   * This helper forwards to the iidr_read interface.
-   * \retval true if `reg` is in the IIDR range of the device.
-   * \retval false otherwise
-   */
-  bool _iidr_try_read(unsigned reg, char size, l4_uint64_t *val)
-  {
-    if (size == 2 && reg >= 0xffd0 && reg <= 0xfffc)
-      {
-        *val = iidr_read(reg - 0xffd0);
-        return true;
-      }
-
-    return false;
-  }
-
-  /**
-   * Helper for reads in the GICD header area 0x00 - 0x10
-   */
-  l4_uint32_t _read_gicd_header(unsigned reg)
-  {
-    unsigned r = reg >> 2;
-    switch (r)
-      {
-      case 0: return ctlr;        // GICD_CTRL
-      case 1: return get_typer(); // GICD_TYPER
-      case 2: return 0x43b;       // GICD_IIDR
-      default: break;             // includes GICD_TYPER2
-      }
-    return 0;
-  }
-
-protected:
-
-  /**
-   * Read a register in the multi IRQs register range of GICD.
-   * \retval true  if `reg` is handled by the function.
-   * \retval false otherwise.
-   */
-  bool
-  read_multi_irq(unsigned reg, char size, unsigned cpu_id, l4_uint64_t *res)
-  {
-    auto rd = [this,res](Irq const &irq, unsigned r, l4_uint32_t mask,
-                        unsigned shift)
-      {
-        *res |= (this->irq_mmio_read(irq, r) & mask) << shift;
-      };
-
-    return _demux_per_irq(reg, size, cpu_id, rd);
-  }
-
-  /**
-   * Write a register in the multi IRQs register range of GICD.
-   * \retval true  if `reg` is handled by the function.
-   * \retval false otherwise.
-   */
-  bool
-  write_multi_irq(unsigned reg, char size, l4_uint32_t value, unsigned cpu_id)
-  {
-    auto wr = [this,value](Irq &irq, unsigned r, l4_uint32_t mask,
-                           unsigned shift)
-      {
-        this->irq_mmio_write(irq, r, (value >> shift) & mask);
-      };
-
-    return _demux_per_irq(reg, size, cpu_id, wr);
-  }
-
-  /**
-   * Read for generic GICD registers.
-   *
-   * \retval true  if `reg` is handled by the function.
-   * \retval false otherwise.
-   *
-   * This function is a helper for specific GICD mmio read implementations.
-   */
-  bool dist_read(unsigned reg, char size, unsigned cpu_id, l4_uint64_t *res)
-  {
-    if (reg < 0x10) // GICD_CTRL..GICD_TYPER2
-      {
-        *res = _read_gicd_header(reg);
-        return true;
-      }
-
-    if (reg == 0x10) // GICD_STATUS
-      {
-        *res = 0;
-        return true;
-      }
-
-    if (reg < 0x80) // < GICD_IGROUPR
-      return true;
-
-    if (read_multi_irq(reg, size, cpu_id, res))
-      return true;
-
-    return _iidr_try_read(reg, size, res);
-  }
-
-  /**
-   * Write for generic GICD registers.
-   *
-   * \retval true  if `reg` is handled by the function.
-   * \retval false otherwise.
-   *
-   * This function is a helper for specific GICD mmio write implementations.
-   */
-  bool dist_write(unsigned reg, char size, l4_uint32_t value, unsigned cpu_id)
-  {
-    if (reg == 0 && size == 2)
-      {
-        write_ctlr(value);
-        return true;
-      }
-
-    if (reg < 0x80) // < GICD_IGROUPR
-      return true; // all RO, WI, WO or not implemented
-
-    return write_multi_irq(reg, size, value, cpu_id);
-  }
-
-protected:
-  Cpu_vector _cpu;
-  Irq_array _spis;
-  l4_uint8_t _prio_mask;
-
-  /**
-   * Protect IRQ migration calls from concurrent invocations.
-   *
-   * IRQ migration is not thread safe. See Irq::target() for details. Also
-   * Dist_v3::_router must be kept in sync. Because migrations should happen
-   * rarely, a single lock for all Irqs should suffice.
-   */
-  std::mutex _target_lock;
-
-  Irq_array *_lpis;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic_iface.cc b/src/l4/pkg/uvmm/server/src/arm/gic_iface.cc
deleted file mode 100644
index 8d08e9bf..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic_iface.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2013-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "debug.h"
-#include "gic_iface.h"
-
-namespace Gic {
-
-static Dist_if::Factory const *_factory[Dist_if::Factory::Max_version + 1];
-
-Dist_if::Factory::Factory(unsigned version)
-{
-  if (version < (Max_version + 1))
-    _factory[version] = this;
-}
-
-Dist_if::Factory::~Factory()
-{
-  for (auto &f: _factory)
-    if (f == this)
-      f = nullptr;
-}
-
-cxx::Ref_ptr
-Dist_if::Factory::create(unsigned version, unsigned tnlines)
-{
-  Dbg(Dbg::Irq, Dbg::Info, "GIC").printf("create ARM GICv%u\n", version);
-
-  if (version <= Max_version && _factory[version])
-    return _factory[version]->create(tnlines);
-
-  Err().printf("could not create GIC, unknown version: %u\n", version);
-
-  return nullptr;
-}
-
-} // Gic
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic_iface.h b/src/l4/pkg/uvmm/server/src/arm/gic_iface.h
deleted file mode 100644
index 89238631..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic_iface.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "device.h"
-#include "vcpu_ptr.h"
-
-namespace Gic {
-
-struct Irq_src_handler;
-
-/**
- * Abstract GIC interface for the ARM VMM
- */
-class Dist_if : public virtual Vdev::Dev_ref
-{
-public:
-  /**
-   * Factory for the central GIC Distributor, hanceforth for the whole GIC.
-   *
-   * This abstract class needs to be implemented to ceate a GIC (Distributor)
-   * object for a given GIC version from the vCPU info.
-   */
-  class Factory
-  {
-  public:
-    enum { Max_version = 3 };
-    /// initialize, and register this factory
-    explicit Factory(unsigned version);
-
-    /// create a GIC (Distributor)
-    virtual cxx::Ref_ptr
-    create(unsigned tnline) const = 0;
-
-    /// destroy and deregister this factory
-    virtual ~Factory();
-
-    /// Create a GIC (Distributor) of the given version.
-    static cxx::Ref_ptr
-    create(unsigned version, unsigned tnlines);
-
-  private:
-    friend class Dist_if;
-  };
-
-  /// Create a GIC (Distributor) of the given version.
-  static cxx::Ref_ptr
-  create_dist(unsigned version, unsigned tnlines)
-  {
-    return Factory::create(version, tnlines);
-  }
-
-  /// schedule pending IRQs to CPUs (default implementation in Dist_mixin)
-  virtual bool schedule_irqs(unsigned current_cpu) = 0;
-
-  /// handle vGIC maintanance IRQs (default implementation in Dist_mixin)
-  virtual void handle_maintenance_irq(unsigned current_cpu) = 0;
-
-  /// Setup the GIC when a GIC node is found in the device tree.
-  virtual cxx::Ref_ptr
-  setup_gic(Vdev::Device_lookup *devs, Vdev::Dt_node const &node) = 0;
-
-  /// Setup the CPU interface for the given `vcpu`.
-  virtual void setup_cpu(Vmm::Vcpu_ptr vcpu, l4_umword_t mpidr) = 0;
-
-  /**
-   * Signal that CPU came online and is ready to receive IRQs.
-   *
-   * *Must* be called from target CPU!
-   */
-  virtual void cpu_online(Vmm::Vcpu_ptr vcpu) = 0;
-
-  /**
-   * Signal that CPU goes offline.
-   *
-   * *Must* be called from target CPU!
-   */
-  virtual void cpu_offline(Vmm::Vcpu_ptr vcpu) = 0;
-
-  /**
-   * Register an Irq_src_handler for a PPI on a vCPU.
-   *
-   * @param cpu     The CPU number
-   * @param irq     The PPI number (0..31)
-   * @param handler The Irq_src_handler.
-   *
-   * Note that the vCPU must have been created already.
-   */
-  virtual void bind_cpulocal_irq_src_handler(unsigned cpu, unsigned irq,
-                                             Irq_src_handler *handler) = 0;
-
-  virtual ~Dist_if() = 0;
-};
-
-inline Dist_if::~Dist_if() = default;
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/gic_mixin.h b/src/l4/pkg/uvmm/server/src/arm/gic_mixin.h
deleted file mode 100644
index e0bb2f90..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/gic_mixin.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2020-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "gic_cpu.h"
-#include "gic_dist.h"
-#include "mmio_device.h"
-
-namespace Gic {
-
-template
-class Dist_mixin
-: public Dist,
-  public Vmm::Mmio_device_t
-{
-private:
-  GIC_IMPL *self() { return static_cast(this); }
-  GIC_IMPL const *self() const { return static_cast(this); }
-
-public:
-  Dist_mixin(unsigned tnlines, unsigned char cpus)
-  : Dist(tnlines, cpus)
-  {}
-
-  void inject_irq_local(Irq &irq, Cpu *current_cpu)
-  {
-    if (irq.pending(true))
-      current_cpu->inject(irq);
-  }
-
-  void inject_irq(Irq &irq, Cpu *current_cpu)
-  {
-    Vcpu_handler *dest_cpu = irq.pending(true);
-    if (dest_cpu)
-      {
-        if (current_cpu == dest_cpu)
-          current_cpu->inject(irq);
-        else
-          dest_cpu->notify_irq();
-      }
-  }
-
-  void set(unsigned irq) override
-  {
-    Cpu *current_cpu = this->_cpu[vmm_current_cpu_id].get();
-    if (irq < Cpu::Num_local)
-      inject_irq_local(current_cpu->local_irq(irq), current_cpu);
-    else if (irq < Cpu::Lpi_base)
-      inject_irq(this->spi(irq - Cpu::Num_local), current_cpu); // SPI
-    else
-      inject_irq(this->lpi(irq - Cpu::Lpi_base), current_cpu); // LPI
-  }
-
-  bool schedule_irqs(unsigned current_cpu) override
-  {
-    using Cpu_if = typename GIC_IMPL::Cpu_if;
-
-    assert (current_cpu < this->_cpu.size());
-    Cpu *c = this->_cpu[current_cpu].get();
-
-    c->handle_eois();
-    c->handle_ipis();
-    c->handle_migrations();
-
-    if (!(this->ctlr & 3U))
-      return false;
-
-    unsigned pmask = this->_prio_mask;
-
-    for (;;)
-      {
-        unsigned empty_lr = c->get_empty_lr();
-
-        if (!empty_lr)
-          return true;
-
-        Irq *irq = c->take_pending_irq(pmask);
-        if (!irq)
-          return c->pending_irqs();
-
-        if (0)
-          this->trace().printf("Inject: irq=%u on cpu=%d... ",
-                               irq->id(), current_cpu);
-        c->add_pending_irq(empty_lr - 1, *irq);
-      }
-  }
-
-  void handle_maintenance_irq(unsigned current_cpu) override
-  {
-    assert (current_cpu < this->_cpu.size());
-    Cpu *c = this->_cpu[current_cpu].get();
-    auto misr = c->misr();
-    auto hcr = c->hcr();
-    if (misr.grp0_e())
-      {
-        hcr.vgrp0_eie() = 0;
-        hcr.vgrp0_die() = 1;
-      }
-
-    if (misr.grp0_d())
-      {
-        hcr.vgrp0_eie() = 1;
-        hcr.vgrp0_die() = 0;
-      }
-
-    if (misr.grp1_e())
-      {
-        hcr.vgrp1_eie() = 0;
-        hcr.vgrp1_die() = 1;
-      }
-
-    if (misr.grp1_d())
-      {
-        hcr.vgrp1_eie() = 1;
-        hcr.vgrp1_die() = 0;
-      }
-
-    c->write_hcr(hcr);
-
-    c->handle_maintenance_irq();
-  }
-
-  void cpu_online(Vmm::Vcpu_ptr vcpu) override
-  {
-    unsigned current_cpu = vcpu.get_vcpu_id();
-    Cpu *c = this->_cpu[current_cpu].get();
-    assert(!c->online());
-    c->online(vcpu, current_cpu == 0);
-    this->retarget_spis();
-  }
-
-  void cpu_offline(Vmm::Vcpu_ptr vcpu) override
-  {
-    unsigned current_cpu = vcpu.get_vcpu_id();
-    Cpu *c = this->_cpu[current_cpu].get();
-
-    assert(c->online());
-    c->offline(this->_cpu[0]->vcpu());
-    this->retarget_spis();
-  }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/guest.h b/src/l4/pkg/uvmm/server/src/arm/guest.h
deleted file mode 100644
index 826a3a89..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/guest.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2015-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-#include 
-
-#include "core_timer.h"
-#include "device.h"
-#include "device_tree.h"
-#include "generic_guest.h"
-#include "gic_iface.h"
-#include "vm_ram.h"
-#include "cpu_dev_array.h"
-#include "smccc_device.h"
-#include "sys_reg.h"
-#include "vmprint.h"
-
-namespace Vmm {
-
-/**
- * ARM virtual machine monitor.
- */
-class Guest : public Generic_guest
-{
-public:
-  enum
-  {
-    Default_rambase = 0,
-    Boot_offset = 0
-  };
-
-  Guest();
-
-  static bool fault_mode_supported(Fault_mode mode);
-
-  void setup_device_tree(Vdev::Device_tree) {}
-
-  l4_addr_t load_binary(Vm_ram *ram, char const *binary,
-                        Ram_free_list *free_list);
-
-  void prepare_platform(Vdev::Device_lookup *devs)
-  { _cpus = devs->cpus(); }
-
-  void prepare_vcpu_startup(Vcpu_ptr vcpu, l4_addr_t entry) const;
-
-  void prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const *binary, char const *cmd_line,
-                          l4_addr_t dt_boot_addr);
-  void run(cxx::Ref_ptr cpus);
-
-  void cpu_online(Cpu_dev *cpu);
-  void cpu_offline(Cpu_dev *cpu);
-  void sync_all_other_cores_off() const override;
-
-  void L4_NORETURN halt_vm(Vcpu_ptr current_vcpu) override
-  {
-    stop_cpus();
-    sync_all_other_cores_off();
-    Generic_guest::halt_vm(current_vcpu);
-  }
-
-  void L4_NORETURN shutdown(int val) override
-  {
-    stop_cpus();
-    Generic_guest::shutdown(val);
-  }
-
-  l4_msgtag_t handle_entry(Vcpu_ptr vcpu);
-
-  static Guest *create_instance();
-  static Guest *instance();
-
-  void show_state_interrupts(FILE *, Vcpu_ptr) {}
-
-  cxx::Ref_ptr gic() const
-  { return _gic; }
-
-  void set_timer(cxx::Ref_ptr &timer)
-  { _timer = timer; }
-
-  void wait_for_timer_or_irq(Vcpu_ptr vcpu);
-
-  enum Smccc_method
-  {
-    Smc,
-    Hvc,
-    Num_smcc_methods
-  };
-
-  void register_vm_handler(Smccc_method method,
-                           cxx::Ref_ptr const &handler)
-  {
-    _smccc_handlers[method].push_back(handler);
-  }
-
-  template 
-  void handle_smccc_call(Vcpu_ptr vcpu)
-  {
-    bool res = false;
-
-    // Skip HVC/SMC instruction here. Some vm_call() methods like
-    // Psci_device::vm_call() might set it to a completly different value, which
-    // we can not change without breaking things.
-    vcpu->r.ip += 4;
-
-    // Check if this is a valid/supported SMCCC call
-    if (Smccc_device::is_valid_call(vcpu->r.r[0]))
-      {
-        unsigned imm = vcpu.hsr().svc_imm();
-        for (auto const &h: _smccc_handlers[METHOD])
-          if ((res = h->vm_call(imm, vcpu)))
-            break;
-      }
-
-    if (!res)
-      {
-        // Strip register values if the guest is executed in 32-bit mode.
-        l4_umword_t mask = (vcpu->r.flags & 0x10) ? ~0U : ~0UL;
-        warn().printf("No handler for %s call: imm=%x a0=%lx a1=%lx ip=%lx "
-                      "lr=%lx\n",
-                      (METHOD == Smc) ? "SMC" : "HVC",
-                      static_cast(vcpu.hsr().svc_imm()),
-                      vcpu->r.r[0] & mask, vcpu->r.r[1] & mask,
-                      (vcpu->r.ip - 4) & mask, vcpu.get_lr() & mask);
-        vcpu->r.r[0] = Smccc_device::Not_supported;
-      }
-  }
-
-  void handle_wfx(Vcpu_ptr vcpu);
-  void handle_ppi(Vcpu_ptr vcpu);
-
-  bool inject_abort(Vcpu_ptr vcpu, bool inst, l4_addr_t addr);
-  bool inject_undef(Vcpu_ptr vcpu);
-
-  using Sys_reg = Vmm::Arm::Sys_reg;
-
-  cxx::Weak_ptr sys_reg(Sys_reg::Key k)
-  { return _sys_regs.at(k); }
-
-  void add_sys_reg_aarch32(unsigned cp, unsigned op1,
-                           unsigned crn, unsigned crm,
-                           unsigned op2,
-                           cxx::Ref_ptr const &r)
-  {
-    _sys_regs[Sys_reg::Key::cp_r(cp, op1, crn, crm, op2)] = r;
-  }
-
-  void add_sys_reg_aarch32_cp64(unsigned cp, unsigned op1,
-                                unsigned crm,
-                                cxx::Ref_ptr const &r)
-  {
-    _sys_regs[Sys_reg::Key::cp_r_64(cp, op1, crm)] = r;
-  }
-
-  void add_sys_reg_aarch64(unsigned op0, unsigned op1,
-                           unsigned crn, unsigned crm,
-                           unsigned op2,
-                           cxx::Ref_ptr const &r);
-
-  void add_sys_reg_both(unsigned op0, unsigned op1,
-                        unsigned crn, unsigned crm,
-                        unsigned op2,
-                        cxx::Ref_ptr const &r)
-  {
-    add_sys_reg_aarch64(op0, op1, crn, crm, op2, r);
-    // op0 == 3 -> cp15, op0 == 2 -> cp14
-    add_sys_reg_aarch32(op0 + 12, op1, crn, crm, op2, r);
-  }
-
-protected:
-  bool inject_abort(l4_addr_t addr, Vcpu_ptr vcpu) override;
-
-private:
-  void subarch_init();
-
-  void check_guest_constraints(l4_addr_t ram_base) const;
-  void arm_update_device_tree();
-  void stop_cpus();
-
-  cxx::Ref_ptr _gic;
-  cxx::Ref_ptr _timer;
-  cxx::Ref_ptr _cpus;
-  bool _guest_64bit = false;
-
-  std::vector> _smccc_handlers[Num_smcc_methods];
-  std::map> _sys_regs;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/arm/guest_arm.cc b/src/l4/pkg/uvmm/server/src/arm/guest_arm.cc
deleted file mode 100644
index e5fc2ef4..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/guest_arm.cc
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- * Copyright (C) 2015-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "binary_loader.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "guest_subarch.h"
-#include "irq.h"
-#include "irq_dt.h"
-#include "sys_reg.h"
-#include "virt_bus.h"
-
-#include "vm_print.h"
-
-static cxx::unique_ptr guest;
-
-__thread unsigned vmm_current_cpu_id;
-
-typedef void (*Entry)(Vmm::Vcpu_ptr vcpu);
-
-namespace Vmm {
-
-namespace {
-
-using namespace Arm;
-
-struct DCCSR : Sys_reg_ro
-{
-  l4_uint32_t flip = 0;
-
-  l4_uint64_t read(Vmm::Vcpu_ptr, Key) override
-  {
-    // printascii in Linux is doing busyuart which wants to see a
-    // busy flag to quit its loop while waituart does not want to
-    // see a busy flag; this little trick makes it work
-    flip ^= 1 << 29;
-    return flip;
-  }
-};
-
-struct DBGDTRxX : Sys_reg_const<0>
-{
-  void write(Vmm::Vcpu_ptr, Key, l4_uint64_t v) override
-  {
-    putchar(v);
-  }
-};
-
-// Helper for logging read/write accesses to groups of known system registers
-// where the 'n' value is encoded by the 'CRm'.
-// Write accesses are not performed. Read accesses return 0.
-struct Sys_reg_log_n : Sys_reg
-{
-  Sys_reg_log_n(char const *name)
-  : name(name)
-  {}
-
-  void write(Vmm::Vcpu_ptr vcpu, Key k, l4_uint64_t v) override
-  {
-    Dbg(Dbg::Core, Dbg::Info)
-      .printf("%08lx: msr %s%d_EL1 = %08llx (ignored)\n",
-              vcpu->r.ip, name, static_cast(k.crm()), v);
-  }
-
-  l4_uint64_t read(Vmm::Vcpu_ptr vcpu, Key k) override
-  {
-    Dbg(Dbg::Core, Dbg::Info)
-      .printf("%08lx: mrs %s%d_EL1 (read 0)\n",
-              vcpu->r.ip, name, static_cast(k.crm()));
-    return 0;
-  }
-
-  char const *name;
-};
-
-// Helper for logging read/write accesses to dedicated known system registers.
-// Write accesses are not performed. Read accesses return 0.
-struct Sys_reg_log : Sys_reg
-{
-  Sys_reg_log(char const *name)
-  : name(name)
-  {}
-
-  void write(Vmm::Vcpu_ptr vcpu, Key, l4_uint64_t v) override
-  {
-    Dbg(Dbg::Core, Dbg::Info)
-      .printf("%08lx: msr %s = %08llx (ignored)\n", vcpu->r.ip, name, v);
-  }
-
-  l4_uint64_t read(Vmm::Vcpu_ptr vcpu, Key) override
-  {
-    Dbg(Dbg::Core, Dbg::Info)
-      .printf("%08lx: mrs %s (read 0)\n", vcpu->r.ip, name);
-    return 0;
-  }
-
-  char const *name;
-};
-
-}
-
-Guest::Guest()
-: _gic(Gic::Dist_if::create_dist(l4_vcpu_e_info(*Cpu_dev::main_vcpu())->gic_version,
-                                 31))
-{
-  cxx::Ref_ptr r = cxx::make_ref_obj();
-  add_sys_reg_aarch32(14, 0, 0, 1, 0, r); // DBGDSCRint
-  add_sys_reg_aarch64( 2, 3, 0, 1, 0, r);
-  // MDSCR_EL1 (we can map this to DBGSCRint as long as we only implement bit 29..30
-  add_sys_reg_aarch64( 2, 0, 0, 2, 2, r);
-
-  // DBGIDR
-  add_sys_reg_aarch32(14, 0, 0, 0, 0, cxx::make_ref_obj>());
-
-  r = cxx::make_ref_obj();
-  add_sys_reg_aarch32(14, 0, 0, 5, 0, r);
-  add_sys_reg_aarch64( 2, 3, 0, 5, 0, r);
-
-  // Log miscellaneous debug / non-debug registers
-  r = cxx::make_ref_obj("DBGBVR");
-  for (unsigned i = 0; i < 16; ++i)
-    add_sys_reg_aarch64(2, 0, 0, i, 4, r);
-
-  r = cxx::make_ref_obj("DBGBCR");
-  for (unsigned i = 0; i < 16; ++i)
-    add_sys_reg_aarch64(2, 0, 0, i, 5, r);
-
-  r = cxx::make_ref_obj("DBGWVR");
-  for (unsigned i = 0; i < 16; ++i)
-    add_sys_reg_aarch64(2, 0, 0, i, 6, r);
-
-  r = cxx::make_ref_obj("DBGWCR");
-  for (unsigned i = 0; i < 16; ++i)
-    add_sys_reg_aarch64(2, 0, 0, i, 7, r);
-
-  r = cxx::make_ref_obj("OSLAR_EL1");
-  add_sys_reg_aarch64(2, 0, 1, 0, 4, r);
-
-  r = cxx::make_ref_obj("OSDLR_EL1");
-  add_sys_reg_aarch64(2, 0, 1, 3, 4, r);
-
-  r = cxx::make_ref_obj("PMUSERENR_EL0");
-  add_sys_reg_aarch64(3, 3, 9, 14, 0, r);
-
-  subarch_init();
-}
-
-Guest *
-Guest::create_instance()
-{
-  guest = cxx::make_unique();
-  return guest.get();
-}
-
-Guest *
-Guest::instance()
-{
-  return guest.get();
-}
-
-namespace {
-
-using namespace Vdev;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    auto gic = devs->vmm()->gic();
-    return gic->setup_gic(devs, node);
-  }
-};
-
-static F f;
-static Vdev::Device_type t1 = { "arm,cortex-a9-gic", nullptr, &f };
-static Vdev::Device_type t2 = { "arm,cortex-a15-gic", nullptr, &f };
-static Vdev::Device_type t3 = { "arm,cortex-a7-gic", nullptr, &f };
-static Vdev::Device_type t4 = { "arm,gic-400", nullptr, &f };
-static Vdev::Device_type t5 = { "arm,gic-v3", nullptr, &f };
-
-struct F_timer : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    int timer_irq_idx = -1;
-
-    int p_sz;
-    const char *p = node.get_prop("interrupt-names", &p_sz);
-    if (p)
-      {
-        int i = 0;
-        while (p_sz > 0)
-          {
-            int namelen = strlen(p);
-            if (!strcmp(p, "virt"))
-              {
-                timer_irq_idx = i + 1;
-                break;
-              }
-            p    += namelen + 1;
-            p_sz -= namelen + 1;
-            ++i;
-          }
-
-        if (timer_irq_idx == -1)
-          L4Re::chksys(-L4_EINVAL, "No 'virt' interrupt in arm timer node");
-      }
-    else
-      timer_irq_idx = 3; // convention is that the third number is "virt"
-
-    // now we want to see up to timer_irq_idx interrupts
-    for (int i = 0; i < timer_irq_idx; ++i)
-      L4Re::chksys(it.next(devs), "Parsing timer interrupt");
-
-    if (!it.ic_is_virt())
-      L4Re::chksys(-L4_EINVAL, "Timer not connected to virtual interrupt controller");
-
-    auto timer = Vdev::make_device(it.ic(), it.irq(), node);
-
-    devs->vmm()->set_timer(timer);
-    return timer;
-  }
-};
-
-static F_timer ftimer;
-static Vdev::Device_type tt1 = { "arm,armv7-timer", nullptr, &ftimer };
-static Vdev::Device_type tt2 = { "arm,armv8-timer", nullptr, &ftimer };
-
-} // namespace
-
-
-void
-Guest::sync_all_other_cores_off() const
-{
-  bool all_stop = true;
-  do
-    {
-      all_stop = true;
-      for (auto cpu : *_cpus.get())
-        {
-          if (cpu && cpu->vcpu().get_vcpu_id() == vmm_current_cpu_id)
-            continue;
-
-          if (cpu && cpu->online())
-            {
-              all_stop = false;
-              break;
-            }
-        }
-    } while (!all_stop);
-};
-
-void
-Guest::check_guest_constraints(l4_addr_t base) const
-{
-  Dbg warn(Dbg::Mmio, Dbg::Warn, "ram");
-
-  if (_guest_64bit)
-    {
-      if (base & ((1UL << 21) - 1))
-        warn.printf(
-          "\033[01;31mWARNING: Guest memory not 2MB aligned!\033[m\n"
-          "       If you run a 64bit-Linux as a guest,\n"
-          "       Linux will likely fail to boot as it expects\n"
-          "       a 2MB alignment of its memory.\n"
-          "       Current guest RAM alignment is only 0x%x\n",
-          1 << __builtin_ctz(base));
-
-      return;
-    }
-
-  if (base & ((1UL << 27) - 1))
-    warn.printf(
-      "\033[01;31mWARNING: Guest memory not 128MB aligned!\033[m\n"
-      "       If you run a 32bit-Linux as a guest,\n"
-      "       Linux will likely fail to boot as it assumes\n"
-      "       a 128MB alignment of its memory.\n"
-      "       Current guest RAM alignment is only 0x%x\n",
-      1 << __builtin_ctz(base));
-
-  if (base & ~0xf0000000)
-    warn.printf(
-      "WARNING: Guest memory not 256MB aligned!\n"
-      "       If you run a 32bit-Linux as a guest, you might hit a bug\n"
-      "       in the arch/arm/boot/compressed/head.S code\n"
-      "       that misses an ISB after code has been relocated.\n"
-      "       According to the internet a fix for this issue\n"
-      "       is floating around.\n");
-}
-
-l4_addr_t
-Guest::load_binary(Vm_ram *ram, char const *binary, Ram_free_list *free_list)
-{
-  l4_addr_t entry;
-  Vmm::Guest_addr ram_base = free_list->first_free_address();
-
-  Boot::Binary_loader_factory bf;
-  bf.load(binary, ram, free_list, &entry);
-
-  _guest_64bit = bf.is_64bit();
-
-  check_guest_constraints(ram_base.get());
-
-  char const *n = strrchr(binary, '/');
-  l4_debugger_set_object_name(_task.get().cap(), n ? n+1 : binary);
-
-  return entry;
-}
-
-  /*
-   * Prepare a clean vcpu register state before entering the VM
-   *
-   * Initializes the VCPU register state according to the mode the
-   * VCPU is supposed to run in. Registers related to virtualization
-   * (control registers, vcpu state registers) are initialized in the
-   * context of the thread handling this virtual CPU.
-   * We assume that this state is not changed by invoking
-   * vcpu_control_ext().
-   */
-void
-Guest::prepare_vcpu_startup(Vcpu_ptr vcpu, l4_addr_t entry) const
-{
-  if (Guest_64bit_supported && _guest_64bit)
-    vcpu->r.flags = Cpu_dev::Flags_default_64;
-  else
-    {
-      vcpu->r.flags = Cpu_dev::Flags_default_32;
-      if (entry & 1)
-        {
-          // set thumb mode, remove thumb bit from address
-          vcpu->r.flags |= 1 << 5;
-          entry &= ~1;
-        }
-    }
-
-  vcpu->r.sp    = 0;
-  vcpu->r.ip    = entry;
-}
-
-void
-Guest::prepare_binary_run(Vdev::Device_lookup *devs, l4_addr_t entry,
-                          char const * /*kernel*/, char const * /*cmd_line*/,
-                          l4_addr_t dt_boot_addr)
-{
-  Vcpu_ptr vcpu = devs->cpus()->vcpu(0);
-  prepare_vcpu_startup(vcpu, entry);
-
-  // Set up the VCPU state as expected by Linux entry
-  if (Guest_64bit_supported && _guest_64bit)
-    {
-      vcpu->r.r[0]  = dt_boot_addr;
-      vcpu->r.r[1]  = 0;
-      vcpu->r.r[2]  = 0;
-    }
-  else
-    {
-      vcpu->r.r[0]  = 0;
-      vcpu->r.r[1]  = ~0UL;
-      vcpu->r.r[2]  = dt_boot_addr;
-    }
-  vcpu->r.r[3]  = 0;
-}
-
-void
-Guest::run(cxx::Ref_ptr cpus)
-{
-  if (!_timer)
-    warn().printf("WARNING: No timer found. Your guest will likely not work properly!\n");
-
-  register_vm_handler(Hvc, Vdev::make_device(cpus->size()));
-
-  for (auto cpu: *cpus.get())
-    {
-      if (!cpu)
-        continue;
-
-      auto vcpu = cpu->vcpu();
-
-      vcpu->user_task = _task.cap();
-      cpu->powerup_cpu();
-      info().printf("Powered up cpu%d [%p]\n", vcpu.get_vcpu_id(),
-                    cpu.get());
-
-      _gic->setup_cpu(vcpu, cpu->affinity());
-      if (_timer)
-        _timer->add_cpu(vcpu);
-
-      unsigned vcpu_id = vcpu.get_vcpu_id();
-      _clocks[vcpu_id].start_clock_source_thread(vcpu_id,
-                                                 cpu->get_phys_cpu_id());
-      for (auto &dev : _timer_devices[vcpu_id])
-        dev->ready();
-    }
-  cpus->cpu(0)->mark_on_pending();
-  cpus->cpu(0)->startup();
-}
-
-void
-Guest::cpu_online(Cpu_dev *cpu)
-{
-  _gic->cpu_online(cpu->vcpu());
-}
-
-void
-Guest::cpu_offline(Cpu_dev *cpu)
-{
-  _gic->cpu_offline(cpu->vcpu());
-}
-
-void Guest::stop_cpus()
-{
-  // Exit all vCPU threads into the vmm and stop the vCPUs.
-  for (auto cpu: *_cpus.get())
-    {
-      if (   cpu && cpu->online()
-          && cpu->vcpu().get_vcpu_id() != vmm_current_cpu_id)
-        cpu->send_stop_event();
-
-      // asumption: only called when all cores shall stop eventually,
-      // so stop all clocksource threads even the one on initiating core.
-      _clocks[cpu->vcpu().get_vcpu_id()].stop_clock_source_thread();
-    }
-}
-
-l4_msgtag_t
-Guest::handle_entry(Vcpu_ptr vcpu)
-{
-  auto *utcb = l4_utcb();
-
-  vcpu.process_pending_ipc(utcb);
-  _gic->schedule_irqs(vmm_current_cpu_id);
-
-  L4::Cap myself;
-  return myself->vcpu_resume_start(utcb);
-}
-
-static void dispatch_vm_call(Vcpu_ptr vcpu)
-{
-  guest->handle_smccc_call(vcpu);
-}
-
-static void dispatch_smc(Vcpu_ptr vcpu)
-{
-  guest->handle_smccc_call(vcpu);
-}
-
-static void
-guest_unknown_fault(Vcpu_ptr vcpu)
-{
-  // Strip register values if the guest is executed in 32-bit mode.
-  l4_umword_t mask = (vcpu->r.flags & 0x10) ? ~0U : ~0UL;
-  Err().printf("[%3u] unknown trap: err=%lx ec=0x%x ip=%lx lr=%lx\n",
-               vcpu.get_vcpu_id(),
-               vcpu->r.err, static_cast(vcpu.hsr().ec()),
-               vcpu->r.ip & mask, vcpu.get_lr() & mask);
-  if (!guest->inject_undef(vcpu))
-    guest->halt_vm(vcpu);
-}
-
-static void
-guest_memory_fault(Vcpu_ptr vcpu)
-{
-  switch (guest->handle_mmio(vcpu->r.pfa, vcpu))
-    {
-    case Retry: break;
-    case Jump_instr: vcpu.jump_instruction(); break;
-    default:
-      {
-        // Strip register values if the guest is executed in 32-bit mode.
-        l4_umword_t mask = (vcpu->r.flags & 0x10) ? ~0U : ~0UL;
-        Err().printf("cannot handle VM memory access @ %lx ip=%lx lr=%lx\n",
-                     vcpu->r.pfa & mask, vcpu->r.ip & mask, vcpu.get_lr() & mask);
-        guest->halt_vm(vcpu);
-        break;
-      }
-    }
-}
-
-bool
-Vmm::Guest::inject_abort(l4_addr_t addr, Vcpu_ptr vcpu)
-{
-  // Inject an instruction abort?
-  bool inst = vcpu.hsr().ec() == Hsr::Ec_iabt_low;
-  return inject_abort(vcpu, inst, addr);
-}
-
-void
-Vmm::Guest::wait_for_timer_or_irq(Vcpu_ptr vcpu)
-{
-  if (_gic->schedule_irqs(vmm_current_cpu_id))
-    return;
-
-  l4_timeout_t to = L4_IPC_NEVER;
-
-  auto *utcb = l4_utcb();
-  if (_timer
-      && (l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_CNTVCTL) & 3) == 1) // timer enabled and not masked
-    {
-      // calculate the timeout based on the VTIMER values !
-      auto cnt = vcpu.cntvct();
-      auto cmp = vcpu.cntv_cval();
-
-      if (cmp <= cnt)
-        return;
-
-      l4_uint64_t diff = _timer->get_micro_seconds(cmp - cnt);
-      if (0)
-        printf("diff=%lld\n", diff);
-      l4_rcv_timeout(l4_timeout_abs_u(l4_kip_clock(l4re_kip()) + diff, 8, utcb), &to);
-    }
-
-  vcpu.wait_for_ipc(utcb, to);
-}
-
-void
-Vmm::Guest::handle_wfx(Vcpu_ptr vcpu)
-{
-  vcpu->r.ip += 2 << vcpu.hsr().il();
-  if (vcpu.hsr().wfe_trapped()) // WFE
-    return;
-
-  wait_for_timer_or_irq(vcpu);
-}
-
-static void
-guest_wfx(Vcpu_ptr vcpu)
-{ guest->handle_wfx(vcpu); }
-
-
-void
-Vmm::Guest::handle_ppi(Vcpu_ptr vcpu)
-{
-  switch (vcpu.hsr().svc_imm())
-    {
-    case 0: // VGIC IRQ
-      _gic->handle_maintenance_irq(vmm_current_cpu_id);
-      break;
-    case 1: // VTMR IRQ
-      if (_timer)
-        _timer->inject();
-      break;
-    default:
-      Err().printf("unknown virtual PPI: %d\n",
-                   static_cast(vcpu.hsr().svc_imm()));
-      break;
-    }
-}
-
-static void
-guest_ppi(Vcpu_ptr vcpu)
-{ guest->handle_ppi(vcpu); }
-
-static void guest_irq(Vcpu_ptr vcpu)
-{
-  vcpu.handle_ipc(vcpu->i.tag, vcpu->i.label, l4_utcb());
-}
-
-template
-static void guest_mcrr_access_cp(Vcpu_ptr vcpu)
-{
-  using Vmm::Arm::Sys_reg;
-  using Key = Sys_reg::Key;
-  auto hsr = vcpu.hsr();
-
-  try
-    {
-      Key k = Key::cp_r_64(CP, hsr.mcrr_opc1(), hsr.mcr_crm());
-
-      auto r = guest->sys_reg(k);
-      if (hsr.mcr_read())
-        {
-          l4_uint64_t v = r->read(vcpu, k);
-          vcpu.set_gpr(hsr.mcr_rt(), v & 0xffffffff);
-          vcpu.set_gpr(hsr.mcrr_rt2(), v >> 32);
-        }
-      else
-        {
-          l4_uint64_t v
-            = (vcpu.get_gpr(hsr.mcr_rt()) & 0xffffffff)
-              | (static_cast(vcpu.get_gpr(hsr.mcrr_rt2())) << 32);
-
-          r->write(vcpu, k, v);
-        }
-
-      vcpu.jump_instruction();
-    }
-  catch (...)
-    {
-      Err().printf("%08lx: %s p%u, %d, r%d, c%d, c%d, %d (hsr=%08lx)\n",
-                   vcpu->r.ip, hsr.mcr_read() ? "MRC" : "MCR", CP,
-                   static_cast(hsr.mcr_opc1()),
-                   static_cast(hsr.mcr_rt()),
-                   static_cast(hsr.mcr_crn()),
-                   static_cast(hsr.mcr_crm()),
-                   static_cast(hsr.mcr_opc2()),
-                   static_cast(hsr.raw()));
-
-      if (!guest->inject_undef(vcpu))
-        {
-          if (hsr.mcr_read())
-            {
-              vcpu.set_gpr(hsr.mcr_rt(), 0);
-              vcpu.set_gpr(hsr.mcrr_rt2(), 0);
-            }
-
-          vcpu.jump_instruction();
-        }
-    }
-}
-template
-static void guest_mcr_access_cp(Vcpu_ptr vcpu)
-{
-  using Vmm::Arm::Sys_reg;
-  using Key = Sys_reg::Key;
-  auto hsr = vcpu.hsr();
-
-  try
-    {
-      Key k = Key::cp_r(CP, hsr.mcr_opc1(),
-                        hsr.mcr_crn(),
-                        hsr.mcr_crm(),
-                        hsr.mcr_opc2());
-
-      auto r = guest->sys_reg(k);
-      if (hsr.mcr_read())
-        vcpu.set_gpr(hsr.mcr_rt(), r->read(vcpu, k));
-      else
-        r->write(vcpu, k, vcpu.get_gpr(hsr.mcr_rt()));
-
-      vcpu.jump_instruction();
-    }
-  catch (...)
-    {
-      // The ID register range is RAZ. See the "AArch32 System Register
-      // Encoding" chapter in the Arm Architecture Reference Manual.
-      if (hsr.mcr_read() && hsr.mcr_crn() == 0 && hsr.mcr_opc1() == 0)
-        {
-          vcpu.set_gpr(hsr.mcr_rt(), 0);
-          vcpu.jump_instruction();
-        }
-      else
-        {
-          Err().printf("%08lx: %s p%u, %d, r%d, c%d, c%d, %d (hsr=%08lx)\n",
-                       vcpu->r.ip, hsr.mcr_read() ? "MRC" : "MCR", CP,
-                       static_cast(hsr.mcr_opc1()),
-                       static_cast(hsr.mcr_rt()),
-                       static_cast(hsr.mcr_crn()),
-                       static_cast(hsr.mcr_crm()),
-                       static_cast(hsr.mcr_opc2()),
-                       static_cast(hsr.raw()));
-
-          if (!guest->inject_undef(vcpu))
-            {
-              if (hsr.mcr_read())
-                vcpu.set_gpr(hsr.mcr_rt(), 0);
-              vcpu.jump_instruction();
-            }
-        }
-    }
-}
-
-static void guest_msr_access(Vcpu_ptr vcpu)
-{
-  using Vmm::Arm::Sys_reg;
-  using Key = Sys_reg::Key;
-  auto hsr = vcpu.hsr();
-
-  try
-    {
-      Key k = Key::sr(hsr.msr_op0(),
-                      hsr.msr_op1(),
-                      hsr.msr_crn(),
-                      hsr.msr_crm(),
-                      hsr.msr_op2());
-
-      auto r = guest->sys_reg(k);
-      if (hsr.msr_read())
-        vcpu.set_gpr(hsr.msr_rt(), r->read(vcpu, k));
-      else
-        r->write(vcpu, k, vcpu.get_gpr(hsr.msr_rt()));
-
-      vcpu.jump_instruction();
-    }
-  catch (...)
-    {
-      if (hsr.msr_read())
-        {
-          // The ID register range is RAZ. See the "AArch64 System Register
-          // Encoding" chapter in the Arm Architecture Reference Manual.
-          // Interestingly, ARM DDI 0487K.a _excludes_ CRm == 1 but there are
-          // obviously AArch32 ID registers in this range.
-          if (hsr.msr_op0() == 3 && hsr.msr_op1() == 0 && hsr.msr_crn() == 0
-              && hsr.msr_crm() >= 1 && hsr.msr_crm() <= 7)
-            {
-              vcpu.set_gpr(hsr.msr_rt(), 0);
-              vcpu.jump_instruction();
-            }
-          else
-            {
-              Err().printf("%08lx: mrs r%u, S%u_%u_C%u_C%u_%u (hsr=%08lx)\n",
-                           vcpu->r.ip, static_cast(hsr.msr_rt()),
-                           static_cast(hsr.msr_op0()),
-                           static_cast(hsr.msr_op1()),
-                           static_cast(hsr.msr_crn()),
-                           static_cast(hsr.msr_crm()),
-                           static_cast(hsr.msr_op2()),
-                           static_cast(hsr.raw()));
-              if (!guest->inject_undef(vcpu))
-                {
-                  vcpu.set_gpr(hsr.msr_rt(), 0);
-                  vcpu.jump_instruction();
-                }
-            }
-        }
-      else
-        {
-          Err().printf("%08lx: msr S%u_%u_C%u_C%u_%u = %08lx (hsr=%08lx)\n",
-                       vcpu->r.ip,
-                       static_cast(hsr.msr_op0()),
-                       static_cast(hsr.msr_op1()),
-                       static_cast(hsr.msr_crn()),
-                       static_cast(hsr.msr_crm()),
-                       static_cast(hsr.msr_op2()),
-                       vcpu.get_gpr(hsr.msr_rt()),
-                       static_cast(hsr.raw()));
-
-          if (!guest->inject_undef(vcpu))
-            vcpu.jump_instruction();
-        }
-    }
-}
-
-static void ex_regs_exception(Vcpu_ptr)
-{
-  Dbg warn(Dbg::Cpu, Dbg::Warn, "CPU");
-  warn.printf("Ex_regs exception exit received. Nothing to do!\n");
-}
-
-extern "C" l4_msgtag_t prepare_guest_entry(Vcpu_ptr vcpu);
-l4_msgtag_t prepare_guest_entry(Vcpu_ptr vcpu)
-{ return guest->handle_entry(vcpu); }
-
-} // namespace
-
-using namespace Vmm;
-Entry vcpu_entries[64] =
-{
-  [0x00] = guest_unknown_fault,
-  [0x01] = guest_wfx,
-  [0x02] = guest_unknown_fault,
-  [0x03] = guest_mcr_access_cp<15>,
-  [0x04] = guest_mcrr_access_cp<15>,
-  [0x05] = guest_mcr_access_cp<14>,
-  [0x06] = guest_unknown_fault,
-  [0x07] = guest_unknown_fault,
-  [0x08] = guest_unknown_fault,
-  [0x09] = guest_unknown_fault,
-  [0x0a] = guest_unknown_fault,
-  [0x0b] = guest_unknown_fault,
-  [0x0c] = guest_mcrr_access_cp<14>,
-  [0x0d] = guest_unknown_fault,
-  [0x0e] = guest_unknown_fault,
-  [0x0f] = guest_unknown_fault,
-  [0x10] = guest_unknown_fault,
-  [0x11] = guest_unknown_fault,
-  [0x12] = dispatch_vm_call,
-  [0x13] = dispatch_smc,
-  [0x14] = guest_unknown_fault,
-  [0x15] = guest_unknown_fault,
-  [0x16] = dispatch_vm_call,
-  [0x17] = dispatch_smc,
-  [0x18] = guest_msr_access,
-  [0x19] = guest_unknown_fault,
-  [0x1a] = guest_unknown_fault,
-  [0x1b] = guest_unknown_fault,
-  [0x1c] = guest_unknown_fault,
-  [0x1d] = guest_unknown_fault,
-  [0x1e] = guest_unknown_fault,
-  [0x1f] = guest_unknown_fault,
-  [0x20] = guest_memory_fault,
-  [0x21] = guest_unknown_fault,
-  [0x22] = guest_unknown_fault,
-  [0x23] = guest_unknown_fault,
-  [0x24] = guest_memory_fault,
-  [0x25] = guest_unknown_fault,
-  [0x26] = guest_unknown_fault,
-  [0x27] = guest_unknown_fault,
-  [0x28] = guest_unknown_fault,
-  [0x29] = guest_unknown_fault,
-  [0x2a] = guest_unknown_fault,
-  [0x2b] = guest_unknown_fault,
-  [0x2c] = guest_unknown_fault,
-  [0x2d] = guest_unknown_fault,
-  [0x2e] = guest_unknown_fault,
-  [0x2f] = guest_unknown_fault,
-  [0x30] = guest_unknown_fault,
-  [0x31] = guest_unknown_fault,
-  [0x32] = guest_unknown_fault,
-  [0x33] = guest_unknown_fault,
-  [0x34] = guest_unknown_fault,
-  [0x35] = guest_unknown_fault,
-  [0x36] = guest_unknown_fault,
-  [0x37] = guest_unknown_fault,
-  [0x38] = guest_unknown_fault,
-  [0x39] = guest_unknown_fault,
-  [0x3a] = guest_unknown_fault,
-  [0x3b] = guest_unknown_fault,
-  [0x3c] = guest_unknown_fault,
-  [0x3d] = guest_ppi,
-  [0x3e] = ex_regs_exception,
-  [0x3f] = guest_irq
-};
diff --git a/src/l4/pkg/uvmm/server/src/arm/guest_arm_noexc.cc b/src/l4/pkg/uvmm/server/src/arm/guest_arm_noexc.cc
deleted file mode 100644
index ff782d15..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/guest_arm_noexc.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2021, 2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "guest.h"
-
-namespace Vmm {
-
-bool Guest::fault_mode_supported(Fault_mode mode)
-{
-  return Generic_guest::fault_mode_supported(mode);
-}
-
-bool Guest::inject_abort(Vcpu_ptr, bool, l4_addr_t)
-{
-  return false;
-}
-
-bool Guest::inject_undef(Vcpu_ptr)
-{
-  return false;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/monitor/gic_cmd_handler.h b/src/l4/pkg/uvmm/server/src/arm/monitor/gic_cmd_handler.h
deleted file mode 100644
index 38737222..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/monitor/gic_cmd_handler.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter 
- *            Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Gic_cmd_handler {};
-
-template
-class Gic_cmd_handler : public Cmd
-{
-public:
-  Gic_cmd_handler()
-  { register_toplevel("gic"); }
-
-  char const *help() const override
-  { return "GIC distributor"; }
-
-  void exec(FILE *f, Arglist *) override
-  {
-    fprintf(f, "#\n# Spis\n#\n");
-    fprintf(f, "Irq ena pen act pri con grp -> tar vcpu\n");
-    for (unsigned i = 0; i < dist()->tnlines * 32; ++i)
-      show_irq(f, dist()->_spis[i], i);
-  }
-
-private:
-  template
-  void show_irq(FILE *f, I const &irq, int num)
-  {
-    if (!irq.enabled() && !irq.pending() && !irq.active())
-      return;
-
-    fprintf(f, "%3d   %c   %c   %c %3d %3d %3d    %3d %4d\n",
-            num,
-            irq.enabled() ? 'y' : 'n',
-            irq.pending() ? 'y' : 'n',
-            irq.active()  ? 'y' : 'n',
-            static_cast(irq.prio()),
-            static_cast(irq.config()),
-            static_cast(irq.group()),
-            static_cast(irq.target()),
-            static_cast(irq.cpu())
-            );
-  }
-
-  T *dist()
-  { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/arm/monitor/monitor_arch.h b/src/l4/pkg/uvmm/server/src/arm/monitor/monitor_arch.h
deleted file mode 100644
index 92a0445d..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/monitor/monitor_arch.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-constexpr bool has_iomap()
-{ return false; }
diff --git a/src/l4/pkg/uvmm/server/src/arm/sys_reg.h b/src/l4/pkg/uvmm/server/src/arm/sys_reg.h
deleted file mode 100644
index 38e7ec73..00000000
--- a/src/l4/pkg/uvmm/server/src/arm/sys_reg.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2020, 2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "arm_hyp.h"
-#include "vcpu_ptr.h"
-#include 
-#include 
-
-namespace Vmm {
-namespace Arm {
-
-class Sys_reg : public cxx::Ref_obj
-{
-public:
-  struct Key
-  {
-    l4_uint32_t k;
-
-    enum
-    {
-      CP_64 = 1u << 24,
-    };
-
-    constexpr Key(unsigned cp, unsigned op0, unsigned op1,
-                  unsigned crn , unsigned crm, unsigned op2, unsigned flags = 0)
-    : k(  ((cp  & 0xf) << 18)
-        | ((op0 & 0x3) << 16)
-        | ((op1 & 0xf) << 12)
-        | ((crn & 0xf) << 8)
-        | ((crm & 0xf) << 4)
-        | ((op2 & 0x7) << 0)
-        | flags)
-     {}
-
-    static constexpr Key
-    sr(unsigned op0, unsigned op1, unsigned crn, unsigned crm, unsigned op2)
-    { return Key(0, op0, op1, crn, crm, op2); }
-
-    static constexpr Key
-    cp_r(unsigned cp, unsigned op1, unsigned crn, unsigned crm, unsigned op2)
-    { return Key(cp, 0, op1, crn, crm, op2); }
-
-    static constexpr Key
-    cp_r_64(unsigned cp, unsigned op1, unsigned crm)
-    { return Key(cp, 0, op1, 0, crm, 0, CP_64); }
-
-    friend constexpr bool operator == (Key l, Key r)
-    { return l.k == r.k; }
-
-    CXX_BITFIELD_MEMBER(12, 14, op1, k);
-    CXX_BITFIELD_MEMBER( 8, 11, crn, k);
-    CXX_BITFIELD_MEMBER( 4,  7, crm, k);
-    CXX_BITFIELD_MEMBER( 0,  2, op2, k);
-  };
-
-  virtual l4_uint64_t read(Vmm::Vcpu_ptr cpu, Key reg) = 0;
-  virtual void write(Vmm::Vcpu_ptr cpu, Key reg, l4_uint64_t val) = 0;
-  virtual ~Sys_reg() = default;
-};
-
-class Sys_reg_ro : public Sys_reg
-{
-public:
-  void write(Vmm::Vcpu_ptr, Key, l4_uint64_t) override
-  {}
-};
-
-class Sys_reg_wo : public Sys_reg
-{
-public:
-  l4_uint64_t read(Vmm::Vcpu_ptr, Key) override
-  { return 0; }
-};
-
-template
-class Sys_reg_const : public Sys_reg_ro
-{
-public:
-  l4_uint64_t read(Vmm::Vcpu_ptr, Key) override
-  { return VAL; }
-};
-
-class Sys_reg_feat : public Sys_reg_ro {
-public:
-  Sys_reg_feat(std::function value) : Sys_reg_ro()
-  { cached_value = value(); }
-
-  l4_uint64_t read(Vmm::Vcpu_ptr, Key) override
-  { return cached_value; }
-
-private:
-  l4_uint64_t cached_value;
-};
-
-}
-}
-
-namespace std {
-  template<>
-  struct less
-  {
-    bool operator () (const Vmm::Arm::Sys_reg::Key &k1, const Vmm::Arm::Sys_reg::Key &k2) const
-    { return k1.k < k2.k; }
-  };
-}
diff --git a/src/l4/pkg/uvmm/server/src/batch_unmapper.h b/src/l4/pkg/uvmm/server/src/batch_unmapper.h
deleted file mode 100644
index dc67a6e5..00000000
--- a/src/l4/pkg/uvmm/server/src/batch_unmapper.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2021 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-
-namespace Vmm {
-
-template
-class Batch_unmapper
-{
-  enum { Batch_size = L4_UTCB_GENERIC_DATA_SIZE - 2 };
-
-  L4::Cap _task;
-  l4_fpage_t _fpages[Batch_size];
-  unsigned _num = 0;
-  l4_umword_t _mask;
-
-  void flush()
-  {
-    if (_num > 0)
-      L4Re::chksys(_task->unmap_batch(_fpages, _num, _mask),
-                   "unmap_batch failed");
-    _num = 0;
-  }
-
-public:
-  explicit Batch_unmapper(L4::Cap task, l4_umword_t mask)
-  : _task(task), _mask(mask)
-  {}
-
-  ~Batch_unmapper()
-  { flush(); }
-
-  void unmap(l4_fpage_t fpage)
-  {
-    if (_num >= Batch_size)
-      flush();
-
-    _fpages[_num++] = fpage;
-  }
-};
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader.cc b/src/l4/pkg/uvmm/server/src/binary_loader.cc
deleted file mode 100644
index d2ead662..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader.h"
-
-namespace Boot {
-
-l4_addr_t
-Binary_ds::load_as_elf(Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list)
-{
-  Vmm::Guest_addr img_start(-1UL);
-  Vmm::Guest_addr img_end(0);
-
-  _elf.iterate_phdr([this,ram,free_list,&img_start,&img_end](Ldr::Elf_phdr ph) {
-    if (ph.type() == PT_LOAD)
-      {
-        auto gstart = ram->boot2guest_phys(ph.paddr());
-        // Note that we need to reserve all the memory, this block will
-        // occupy in memory, even though only filesz() will be copied
-        // later.
-        if (!free_list->reserve_fixed(gstart, ph.memsz()))
-          {
-            Err().printf("Failed to load ELF kernel binary. "
-                         "Region [0x%lx/0x%lx] not in RAM.\n",
-                         ph.paddr(), ph.filesz());
-            L4Re::chksys(-L4_ENOMEM, "Loading ELF binary.");
-          }
-
-        if (img_start > gstart)
-          img_start = gstart;
-        if (img_end.get() < gstart.get() + ph.filesz())
-          img_end = gstart + ph.filesz();
-
-        Dbg(Dbg::Mmio, Dbg::Info, "bin")
-          .printf("Copy in ELF binary section @0x%lx from 0x%lx/0x%lx\n",
-                  ph.paddr(), ph.offset(), ph.filesz());
-
-        ram->copy_from_ds(_ds.get(), ph.offset(), gstart, ph.filesz());
-      }
-  });
-
-  if (img_start >= img_end)
-    {
-      Err().printf("ELF binary does not have any PT_LOAD sections.\n");
-      L4Re::chksys(-L4_ENOMEM, "Loading ELF binary.");
-    }
-
-  _loaded_range_start = ram->guest2host(img_start);
-  _loaded_range_end = ram->guest2host(img_end);
-
-  return _elf.entry();
-}
-
-l4_addr_t
-Binary_ds::load_as_raw(Vmm::Vm_ram *ram, Vmm::Guest_addr start,
-                       Vmm::Ram_free_list *free_list)
-{
-  l4_size_t sz = _ds->size();
-
-  if (!free_list->reserve_fixed(start, sz))
-    {
-      Err().printf("Failed to load kernel binary. Region [0x%lx/0x%llx] not in RAM.\n",
-                   start.get(), _ds->size());
-      L4Re::chksys(-L4_ENOMEM, "Loading kernel binary.");
-    }
-
-  ram->load_file(_ds.get(), start, sz);
-
-  _loaded_range_start = ram->guest2host(start);
-  _loaded_range_end = _loaded_range_start + sz;
-
-  return ram->guest_phys2boot(start);
-}
-
-int
-Binary_loader_factory::load(char const *bin, Vmm::Vm_ram *ram,
-                            Vmm::Ram_free_list *free_list,
-                            l4_addr_t *entry)
-{
-  // Reverse search for the last ':'
-  char const *file = bin;
-  if (char const *t = strrchr(file, ':'))
-    file = t + 1;
-
-  std::shared_ptr image = std::make_shared(file);
-  int res = -L4_EINVAL;
-  for (auto *t: Binary_loader::types)
-    {
-      res = t->load(bin, image, ram, free_list, entry);
-      if (res == L4_EOK)
-        {
-          _loader = t;
-          break;
-        }
-    }
-
-  if (res != L4_EOK)
-    {
-      // If we didn't find a loader, check if the image is valid at all.
-      // Check this late to avoid a special check for rom:/raw: arguments.
-      if (!image->is_valid())
-        {
-          Err().printf("File not found: filename: '%s' / cmdline arg: '%s'\n",
-                       file, bin);
-          L4Re::throw_error(-L4_ENOENT,
-                            "Binary file / Kernel image not found.");
-        }
-      else
-        L4Re::throw_error(res, "No loader found for provided image.");
-    }
-
-  return res;
-}
-
-cxx::H_list_t Binary_loader::types(true);
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader.h b/src/l4/pkg/uvmm/server/src/binary_loader.h
deleted file mode 100644
index c5cf1c60..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2015-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include "debug.h"
-#include "vm_ram.h"
-
-namespace Boot {
-
-class Binary_ds
-{
-  static L4Re::Rm::Unique_region attach_ds(L4::Cap ds)
-  {
-    if (!ds.is_valid())
-      return {};
-
-    // Map the whole dataspace. Use superpage alignment to lower TLB pressure
-    // when mapping large images, like the Linux kernel.
-    auto *e = L4Re::Env::env();
-    L4Re::Rm::Unique_region ret;
-    L4Re::chksys(e->rm()->attach(&ret, ds->size(),
-                                 L4Re::Rm::F::Search_addr | L4Re::Rm::F::R,
-                                 L4::Ipc::make_cap_rw(ds), 0,
-                                 L4_SUPERPAGESHIFT),
-                 "Attach binary dataspace.");
-
-    return ret;
-  }
-
-public:
-  Binary_ds(char const *name)
-  : _ds(L4Re::Util::Env_ns().query(name)),
-    _data(attach_ds(_ds.get())),
-    _elf(this, _ds.get())
-  {}
-
-  Binary_ds(L4::Cap d)
-  : _ds(d),
-    _data(attach_ds(d)),
-    _elf(this, _ds.get())
-  {}
-
-  Ldr::Elf_binary *get_elf()
-  { return &_elf; }
-
-  bool is_valid()
-  { return _ds.is_valid(); }
-
-  bool is_elf_binary()
-  {
-    return _elf.is_valid();
-  }
-
-  bool is_elf64()
-  {
-    return _elf.is_64();
-  }
-
-  size_t loaded_size()
-  { return _loaded_range_end - _loaded_range_start; }
-
-  l4_addr_t load_as_elf(Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list);
-
-  l4_addr_t load_as_raw(Vmm::Vm_ram *ram, Vmm::Guest_addr start,
-                        Vmm::Ram_free_list *free_list);
-
-  void const *get_data() const
-  { return _data.get(); }
-
-  size_t size() const
-  { return _ds->size(); }
-
-  L4::Cap ds() const
-  { return _ds.get(); }
-
-  ~Binary_ds()
-  {
-    if (_loaded_range_start != 0 && _loaded_range_end != 0)
-      l4_cache_coherent(_loaded_range_start, _loaded_range_end);
-  }
-
-  // App_model API
-  typedef L4::Cap Const_dataspace;
-  l4_addr_t local_attach_ds(Const_dataspace,
-                            l4_size_t, l4_addr_t offset) const
-  {
-    return reinterpret_cast(_data.get()) + offset;
-  }
-
-  void local_detach_ds(l4_addr_t, l4_size_t) const
-  {}
-  // end of App_model API
-
-private:
-  L4Re::Util::Unique_cap _ds;
-  L4Re::Rm::Unique_region _data;
-  Ldr::Elf_binary _elf;
-  l4_addr_t _loaded_range_start = 0;
-  l4_addr_t _loaded_range_end = 0;
-};
-
-/* Loader type
- *
- * Note: This list also defines the default priority in which the image format
- *       is detected. Raw should always be first. This ensures it will be
- *       processed last.
- */
-enum Binary_type
-{
-  Invalid = 1000,
-  Raw,
-  Rom,
-  Pe,
-  Linux,
-  LinuxGzip,
-  Elf,
-  OpenBSD, // Must be checked before ELF, since an OpenBSD image is also an ELF
-};
-
-class Binary_loader : public cxx::H_list_item_t
-{
-public:
-  Binary_loader(Binary_type type)
-  : _type(type)
-  { types.push_front(this); }
-
-  virtual int load(char const *bin, std::shared_ptr image,
-                   Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-                   l4_addr_t *entry) = 0;
-
-  bool is_64bit() const
-  { return _64bit; }
-
-  Binary_type type() const
-  { return _type; }
-
-  size_t size() const
-  { return _binsize; }
-
-  static Dbg warn()
-  { return Dbg(Dbg::Core, Dbg::Warn, "loader"); }
-
-  static Dbg info()
-  { return Dbg(Dbg::Core, Dbg::Info, "loader"); }
-
-  static Dbg trace()
-  { return Dbg(Dbg::Core, Dbg::Trace, "loader"); }
-
-  static cxx::H_list_t types;
-
-protected:
-  bool _64bit = false;
-  Binary_type _type = Invalid;
-  size_t _binsize = 0;
-};
-
-struct Binary_loader_factory
-{
-  int load(char const *bin, Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-           l4_addr_t *entry);
-
-  bool is_64bit() const
-  { return _loader ? _loader->is_64bit() : false; }
-
-  Binary_type type() const
-  { return _loader ? _loader->type() : Invalid; }
-
-  size_t get_size() const
-  { return _loader ? _loader->size() : 0UL; }
-
-private:
-  Binary_loader *_loader = nullptr;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader_elf.cc b/src/l4/pkg/uvmm/server/src/binary_loader_elf.cc
deleted file mode 100644
index 1f9224b6..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader_elf.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader.h"
-
-namespace Boot {
-
-class Elf_loader : public Binary_loader
-{
-public:
-  Elf_loader()
-  : Binary_loader(Elf)
-  {}
-
-  int load(char const * /*bin*/, std::shared_ptr image,
-           Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-           l4_addr_t *entry) override
-  {
-    trace().printf("Checking for elf image...\n");
-
-    if (!image->is_valid() || !image->is_elf_binary())
-      return -L4_EINVAL;
-
-    info().printf("Elf image detected\n");
-
-    _64bit = image->is_elf64();
-    *entry = image->load_as_elf(ram, free_list);
-
-    return L4_EOK;
-  }
-};
-
-static Elf_loader f __attribute__((init_priority(Boot::Elf)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader_linux.h b/src/l4/pkg/uvmm/server/src/binary_loader_linux.h
deleted file mode 100644
index 58711f7e..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader_linux.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "binary_loader.h"
-
-namespace Boot {
-
-class Linux_loader : public Binary_loader
-{
-public:
-  Linux_loader()
-  : Binary_loader(Linux)
-  {}
-
-  int load(char const *bin, std::shared_ptr image, Vmm::Vm_ram *ram,
-           Vmm::Ram_free_list *free_list, l4_addr_t *entry) override;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader_linux_compressed.cc b/src/l4/pkg/uvmm/server/src/binary_loader_linux_compressed.cc
deleted file mode 100644
index a4d32914..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader_linux_compressed.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-
-#include "binary_loader_linux.h"
-
-namespace Boot {
-
-class Linux_zip_loader : public Linux_loader
-{
-public:
-  int load(char const *bin, std::shared_ptr image,
-           Vmm::Vm_ram *ram, Vmm::Ram_free_list *free_list,
-           l4_addr_t *entry) override
-  {
-    trace().printf("Checking for compressed Linux image...\n");
-
-    if (!image->is_valid())
-      return -L4_EINVAL;
-
-    unsigned char const *h =
-      static_cast(image->get_data());
-    if (h[0] == 0x1f && h[1] == 0x8b && h[2] == 0x08)
-      {
-        const L4Re::Env *e = L4Re::Env::env();
-        L4Re::Rm::Unique_region imager_dst;
-        size_t compr_sz = image->size();
-        uint32_t uncompr_sz = *(uint32_t *)&h[compr_sz - 4];
-
-        info().printf("Detected gzip compressed image: uncompressing (%zd -> %u)\n",
-                      compr_sz, uncompr_sz);
-
-        L4::Cap f =
-          L4Re::chkcap(L4Re::Util::cap_alloc.alloc(),
-                       "Allocate DS cap for uncompressed memory.");
-
-        // The Linux kernel image is expected to be big so use a superpage
-        // alignment for mapping the extracted image and use contiguous
-        // superpages for the dataspace for storing the extracted image. This
-        // wastes some memory at the dataspace provider and some virtual memory
-        // regions -- but only until the Linux kernel image was loaded into the
-        // guest RAM.
-
-        L4Re::chksys(e->mem_alloc()->alloc(uncompr_sz, f,
-                                           L4Re::Mem_alloc::Continuous
-                                           | L4Re::Mem_alloc::Super_pages,
-                                           L4_SUPERPAGESHIFT),
-                     "Allocate memory in dataspace.");
-
-        L4Re::chksys(e->rm()->attach(&imager_dst, uncompr_sz,
-                                     L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
-                                     L4::Ipc::make_cap_rw(f),
-                                     0, L4_SUPERPAGESHIFT),
-                     "Attach DS for uncompressed data.");
-
-        z_stream strm = {};
-        strm.next_in  = const_cast(h);
-        strm.avail_in = compr_sz;
-
-        int err = inflateInit2(&strm, 47);
-        if (err == Z_OK)
-          {
-            strm.next_out = imager_dst.get();
-            strm.avail_out = uncompr_sz;
-            err = inflate(&strm, Z_NO_FLUSH);
-
-            // Should finish in one round
-            if (err != Z_STREAM_END)
-              {
-                Err().printf("zlib decompression error(%d): %s\n", err, strm.msg);
-                L4Re::throw_error(-L4_EINVAL);
-              }
-            else
-              {
-                imager_dst.reset();
-                image.reset(new Boot::Binary_ds(f));
-              }
-          }
-        else
-          {
-            Err().printf("zlib init error: %d\n", err);
-            L4Re::throw_error(-L4_EINVAL);
-          }
-      }
-
-    return Linux_loader::load(bin, image, ram, free_list, entry);
-  }
-};
-
-static Linux_zip_loader f __attribute__((init_priority(Boot::LinuxGzip)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader_pe.cc b/src/l4/pkg/uvmm/server/src/binary_loader_pe.cc
deleted file mode 100644
index 80774786..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader_pe.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader.h"
-
-namespace Boot {
-
-class Pe_loader : public Binary_loader
-{
-public:
-  Pe_loader()
-  : Binary_loader(Pe)
-  {}
-
-  int load(char const * /*bin*/, std::shared_ptr image, Vmm::Vm_ram * /*ram*/,
-           Vmm::Ram_free_list * /*free_list*/, l4_addr_t * /*entry*/) override
-  {
-    trace().printf("Checking for pe image...\n");
-
-    if (!image->is_valid())
-      return -EINVAL;
-
-    unsigned char const *h = static_cast(image->get_data());
-
-    if (h[0] == 0x4d && h[1] == 0x5a /* "MZ */)
-      {
-        l4_uint32_t o = *reinterpret_cast(&h[0x3c]);
-        if (o <= L4_PAGESIZE - 4
-            && h[o+0] == 0x50 && h[o+1] == 0x45
-            && h[o+2] == 0x00 && h[o+3] == 0x00 /* "PE\0\0" */)
-          L4Re::throw_error(-L4_EINVAL,
-                            "Cannot boot EFI images! Was the ARM header stripped?");
-        else
-          L4Re::throw_error(-L4_EINVAL,
-                            "Cannot boot images with 'MZ' header.");
-      }
-
-    return -EINVAL;
-  }
-};
-
-// The raw loader should always be last
-static Pe_loader f __attribute__((init_priority(Boot::Pe)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader_raw.cc b/src/l4/pkg/uvmm/server/src/binary_loader_raw.cc
deleted file mode 100644
index e1e64c33..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader_raw.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader.h"
-#include "binary_loader_raw.h"
-
-namespace Boot {
-
-class Raw_loader : public Binary_loader
-{
-public:
-  Raw_loader()
-  : Binary_loader(Raw)
-  {}
-
-  int load(char const *bin, std::shared_ptr image, Vmm::Vm_ram *ram,
-           Vmm::Ram_free_list *free_list, l4_addr_t *entry) override
-  {
-    trace().printf("Checking for raw image...\n");
-
-    if (!image->is_valid())
-      return -EINVAL;
-
-    *entry = ~0ul;
-
-    if (strstr(bin, "raw:"))
-      {
-        char const *e = strstr(bin, "addr=");
-        if (e)
-          *entry = strtol(e + 5, NULL, 16);
-      }
-
-    return raw_load_image(image, ram, free_list, entry);
-  }
-};
-
-// The raw loader should always be last
-static Raw_loader f __attribute__((init_priority(Boot::Raw)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/binary_loader_rom.cc b/src/l4/pkg/uvmm/server/src/binary_loader_rom.cc
deleted file mode 100644
index eff956ad..00000000
--- a/src/l4/pkg/uvmm/server/src/binary_loader_rom.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "binary_loader.h"
-
-namespace Boot {
-
-/**
- * Binary loader which starts binary out of a guest memory location.
- *
- * Use rom:addr=0xXXXXXX as uvmm's --kernel parameter.
- */
-class Rom_loader : public Binary_loader
-{
-public:
-  Rom_loader()
-  : Binary_loader(Rom)
-  {}
-
-  int load(char const *bin, std::shared_ptr /*image*/,
-           Vmm::Vm_ram * /*ram*/, Vmm::Ram_free_list * /*free_list*/,
-           l4_addr_t *entry) override
-  {
-    trace().printf("Checking for rom start...\n");
-
-    if (!strstr(bin, "rom:"))
-      return -L4_EINVAL;
-
-    char const *e = strstr(bin, "addr=");
-    if (!e)
-      {
-        warn().printf("Start address for rom missing.");
-        return -L4_EINVAL;
-      }
-
-    *entry = strtol(e + 5, NULL, 0);
-
-    e = strstr(bin, "64bit");
-    if (e)
-      _64bit = true;
-
-    info().printf("Rom start detected\n");
-    warn().printf("Rom start address: 0x%lx mode: %sbit\n", *entry,
-                  _64bit ? "64" : "32");
-
-    return L4_EOK;
-  }
-};
-
-static Rom_loader f __attribute__((init_priority(Boot::Rom)));
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/consts.h b/src/l4/pkg/uvmm/server/src/consts.h
deleted file mode 100644
index 460b8943..00000000
--- a/src/l4/pkg/uvmm/server/src/consts.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2021, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-namespace Vmm {
-
-enum Handler_return_codes
-{
-  Retry = 0,
-  Jump_instr = 1,
-  Invalid_opcode = 2,     // Handled on amd64 only.
-  Stack_fault = 3,        // Handled on amd64 only.
-  General_protection = 4, // Handled on amd64 only.
-};
-
-enum
-{
-  Ram_hugepageshift  = 24,
-  Ram_hugepagesize   = 1UL << Ram_hugepageshift,
-};
-
-/**
- * Check whether a log2-sized page containing address is inside a region
- *
- * \param align    log2 of the page alignment.
- * \param addr     Address to check.
- * \param start    Start of region.
- * \param end      Last byte of region; do not check end of region if zero.
- * \return true if there is a log2-aligned page containing the address
- *                 inside the region
- */
-inline bool log2_page_in_range(unsigned char align, l4_addr_t addr,
-                               l4_addr_t start, l4_addr_t end)
-{
-  auto log2page = l4_trunc_size(addr, align);
-  return    start <= log2page
-         && (!end || (log2page + (1UL << align) - 1) <= end);
-}
-
-inline bool log2_alignment_compatible(unsigned char align, l4_addr_t addr1,
-                                      l4_addr_t addr2)
-{ return (addr1 & ((1UL << align) - 1)) == (addr2 & ((1UL << align) - 1)); }
-
-/**
- * Calculate log_2(pagesize) for a location in a region
- *
- * \param addr     Guest-physical address where the access occurred.
- * \param start    Guest-physical address of start of memory region.
- * \param end      Guest-physical address of last byte of memory region.
- * \param offset   Accessed address relative to the beginning of the region.
- * \param l_start  Local address of start of memory region, default 0.
- * \param l_end    Local address of end of memory region, default 0.
- *
- * \return largest possible pageshift.
- */
-inline char get_page_shift(l4_addr_t addr, l4_addr_t start, l4_addr_t end,
-                           l4_addr_t offset, l4_addr_t l_start = 0,
-                           l4_addr_t l_end = 0)
-{
-  if (end <= start)
-    return L4_PAGESHIFT;
-
-  // Start with a reasonable maximum value: log2 of the memory region size
-  l4_addr_t const size = end - start + 1;
-  unsigned char align = sizeof(l4_addr_t) * 8 - (__builtin_clzl(size) + 1);
-  for (; align > L4_PAGESHIFT; --align)
-    {
-      // Check whether a log2-sized page is inside the regions
-      if (   !log2_page_in_range(align, addr, start, end)
-          || !log2_page_in_range(align, l_start + offset, l_start, l_end))
-        continue;
-
-      if (!log2_alignment_compatible(align, start, l_start))
-        continue;
-
-      return align;
-    }
-
-  return L4_PAGESHIFT;
-}
-
-} // namespace Vmm
diff --git a/src/l4/pkg/uvmm/server/src/cpu_dev_array.cc b/src/l4/pkg/uvmm/server/src/cpu_dev_array.cc
deleted file mode 100644
index 564c393a..00000000
--- a/src/l4/pkg/uvmm/server/src/cpu_dev_array.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-namespace Vmm {
-
-static
-unsigned get_dt_cpuid(Vdev::Dt_node const *node)
-{
-  // fallback to 0 if do DT node given
-  if (!node)
-    return Cpu_dev::dtid_to_cpuid(0);
-
-  auto *prop = node->get_prop("reg", nullptr);
-  if (!prop)
-    {
-      Err().printf("Cpu node '%s' has missing reg property. Ignored.\n",
-                   node->get_name());
-      return ~0u;
-    }
-
-  return Cpu_dev::dtid_to_cpuid(fdt32_to_cpu(*prop));
-}
-
-cxx::Ref_ptr
-Cpu_dev_array::create_vcpu(Vdev::Dt_node const *node)
-{
-  unsigned id;
-  if (Cpu_dev::has_fixed_dt_mapping())
-    {
-      id = get_dt_cpuid(node);
-      if (id < _cpus.size() && _cpus[id])
-        {
-          Dbg(Dbg::Cpu, Dbg::Warn)
-            .printf("Duplicate definitions for Cpu%d\n", id);
-
-          return _cpus[id];
-        }
-    }
-  else
-    id = _cpus.size();
-
-  if (id >= Cpu_dev::Max_cpus)
-    {
-      Err().printf("Too many virtual CPUs. Ignored.\n");
-      return nullptr;
-    }
-
-  unsigned cpu_mask = _placement.next_free();
-  if (cpu_mask == Vcpu_placement::Invalid_id)
-    return nullptr;
-
-  if (id >= _cpus.size())
-    _cpus.resize(id + 1);
-
-  _cpus[id] = Vdev::make_device(id, cpu_mask, node);
-
-  return _cpus[id];
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/cpu_dev_array.h b/src/l4/pkg/uvmm/server/src/cpu_dev_array.h
deleted file mode 100644
index aea1ad13..00000000
--- a/src/l4/pkg/uvmm/server/src/cpu_dev_array.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "cpu_dev.h"
-#include "monitor/cpu_dev_array_cmd_handler.h"
-
-namespace Vmm {
-
-/**
- * Abstract CPU container.
- */
-class Cpu_dev_array
-: public virtual Vdev::Dev_ref,
-  public Monitor::Cpu_dev_array_cmd_handler
-{
-  friend Cpu_dev_array_cmd_handler;
-  typedef std::vector> Cpu_dev_vector;
-
-  /**
-   * Helper class that distributes threads evenly to all available
-   * physical CPUs.
-   *
-   * Exactly one VCPU is assigned per physical CPU. If more VCPUs
-   * are requested, they remain disabled.
-   */
-  class Vcpu_placement
-  {
-  public:
-    enum : unsigned { Invalid_id = ~0U };
-
-    Vcpu_placement() : _next_id(0), _offset(0)
-    {
-      update_cpu_set(0);
-    }
-
-    unsigned next_free()
-    {
-      if (_next_id >= _max_cpus)
-        return Invalid_id;
-
-      while (true)
-        {
-          unsigned next_id_offset = _next_id % _bits_in_cpu_map;
-          if ((_next_id - _offset) >= _bits_in_cpu_map)
-            update_cpu_set(_next_id - next_id_offset);
-
-          if (_cs.map & (1UL << next_id_offset))
-            return _next_id++;
-
-          ++_next_id;
-
-          if (_next_id >= _max_cpus)
-            return Invalid_id;
-        }
-
-    }
-
-  private:
-    void update_cpu_set(l4_umword_t new_offset)
-    {
-      _offset = new_offset;
-      _cs = l4_sched_cpu_set(_offset, 0);
-
-      auto scheduler = L4Re::Env::env()->scheduler();
-      L4Re::chksys(scheduler->info(&_max_cpus, &_cs),
-                   "Get scheduler info for next batch of cores.");
-    }
-
-    l4_sched_cpu_set_t _cs;
-    unsigned _next_id;
-    unsigned const _bits_in_cpu_map = sizeof(_cs.map) * 8;
-    l4_umword_t _offset;
-    l4_umword_t _max_cpus;
-  };
-
-public:
-  virtual ~Cpu_dev_array() = default;
-
-  bool vcpu_exists(unsigned cpuid) const
-  {
-    return cpuid < _cpus.size() && !!_cpus[cpuid];
-  }
-
-  Vcpu_ptr vcpu(unsigned cpuid) const
-  {
-    assert(vcpu_exists(cpuid));
-    return _cpus[cpuid]->vcpu();
-  }
-
-  cxx::Ref_ptr cpu(unsigned cpuid) const
-  {
-    assert(vcpu_exists(cpuid));
-    return _cpus[cpuid];
-  }
-
-  /// Return the maximum CPU id in use.
-  unsigned max_cpuid() const
-  { return _cpus.size() - 1; }
-
-  /**
-   * Add a CPU to the array.
-   */
-  cxx::Ref_ptr
-  create_vcpu(Vdev::Dt_node const *node);
-
-  Cpu_dev_vector::iterator begin() { return _cpus.begin(); }
-  Cpu_dev_vector::const_iterator begin() const { return _cpus.begin(); }
-
-  Cpu_dev_vector::iterator end() { return _cpus.end(); }
-  Cpu_dev_vector::const_iterator end() const { return _cpus.end(); }
-
-  unsigned size() const { return _cpus.size(); }
-
-protected:
-  Vcpu_placement _placement;
-  Cpu_dev_vector _cpus;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/debug.cc b/src/l4/pkg/uvmm/server/src/debug.cc
deleted file mode 100644
index a4368e01..00000000
--- a/src/l4/pkg/uvmm/server/src/debug.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2015, 2019-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include "debug.h"
-
-namespace {
-
-struct Verbosity_level {
-  char const *name;
-  unsigned mask;
-};
-
-Verbosity_level const verbosity_levels[] = {
-  { "quiet", Dbg::Quiet },
-  { "warn", Dbg::Warn },
-  { "info", Dbg::Warn | Dbg::Info },
-  { "trace", Dbg::Warn | Dbg::Info | Dbg::Trace }
-};
-
-char const *const verbosity_level_names[] =
-  { "quiet", "warn", "info", "trace", nullptr };
-
-static_assert(std::extent::value + 1
-              == std::extent::value,
-              "Verbosity level name size mismatch");
-
-bool verbosity_mask_from_string(char const *str, unsigned *mask)
-{
-  for (auto const &verbosity_level : verbosity_levels)
-    {
-      if (strcmp(verbosity_level.name, str) == 0)
-        {
-          *mask = verbosity_level.mask;
-          return true;
-        }
-    }
-
-  return false;
-}
-
-bool verbosity_mask_to_string(unsigned mask, char const **str)
-{
-  for (auto const &verbosity_level : verbosity_levels)
-    {
-      if (verbosity_level.mask == mask)
-        {
-          *str = verbosity_level.name;
-          return true;
-        }
-    }
-
-  return false;
-}
-
-char const *const component_names[] =
-  { "core", "cpu", "mmio", "irq", "dev", "pci", "pm", "vbus_event", nullptr };
-
-static_assert(std::extent::value
-              == Dbg::Max_component + 1,
-              "Component names must match 'enum Component'.");
-
-bool component_from_string(char const *str, size_t len, unsigned *c)
-{
-  for (unsigned i = 0; i < Dbg::Max_component; ++i)
-    {
-      if (len == strlen(component_names[i])
-          && memcmp(component_names[i], str, len) == 0)
-        {
-          *c = i;
-          return true;
-        }
-    }
-
-  return false;
-}
-
-} // namespace
-
-char const *const *
-Dbg::valid_verbosity_levels()
-{ return verbosity_level_names; }
-
-char const *const *
-Dbg::valid_components()
-{ return component_names; }
-
-int
-Dbg::get_verbosity(unsigned c, char const **str)
-{
-  unsigned shift = Verbosity_shift * c;
-  unsigned mask = (level & (Verbosity_mask << shift)) >> shift;
-
-  if (!verbosity_mask_to_string(mask, str))
-    return -L4_EINVAL;
-
-  return L4_EOK;
-}
-
-int
-Dbg::get_verbosity(char const *c, char const **str)
-{
-  unsigned cu;
-  if (!component_from_string(c, strlen(c), &cu))
-    return -L4_EINVAL;
-
-  return get_verbosity(cu, str);
-}
-
-int
-Dbg::set_verbosity(char const *str)
-{
-  unsigned mask = 0;
-
-  // ignore leading whitespace
-  while(*str && *str == ' ')
-    ++str;
-
-  if (verbosity_mask_from_string(str, &mask))
-    {
-      set_verbosity(mask);
-      return L4_EOK;
-    }
-
-  char const *eq = strchr(str, '=');
-  if (!eq)
-    return -L4_EINVAL;
-
-  unsigned c;
-  if (!component_from_string(str, eq - str, &c)
-      || !verbosity_mask_from_string(eq + 1, &mask))
-    {
-      return -L4_EINVAL;
-    }
-
-  set_verbosity(c, mask);
-
-  return L4_EOK;
-}
diff --git a/src/l4/pkg/uvmm/server/src/debug.h b/src/l4/pkg/uvmm/server/src/debug.h
deleted file mode 100644
index 06bcb37f..00000000
--- a/src/l4/pkg/uvmm/server/src/debug.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-struct Err : L4Re::Util::Err
-{
-  Err(Level l = Fatal) : L4Re::Util::Err(l, "VMM") {}
-};
-
-class Dbg : public L4Re::Util::Dbg
-{
-public:
-  /// Verbosity level per component.
-  enum Verbosity : unsigned long
-  {
-    Quiet = 0,
-    Warn = 1,
-    Info = 2,
-    Trace = 4,
-  };
-
-  /**
-   * Different components for which the verbosity can be set independently.
-   */
-  enum Component
-  {
-    Core = 0,
-    Cpu,
-    Mmio,
-    Irq,
-    Dev,
-    Pci,
-    Pm,
-    Vbus_event,
-    Max_component
-  };
-
-#ifndef NDEBUG
-  enum
-  {
-    Verbosity_shift = 3, /// Bits per component for verbosity
-    Verbosity_mask = (1UL << Verbosity_shift) - 1
-  };
-
-  static_assert(Max_component * Verbosity_shift <= sizeof(level) * 8,
-                "Too many components for level mask");
-
-
-  /**
-   * Get the current verbosity level for a single component.
-   *
-   * \param c         Component for which to query verbosity.
-   * \param[out] str  Pointer to the name of the current verbosity level for the
-   *                  given component (if the operation succeeded).
-   *
-   * \retval L4_EOK      Operation succeeded.
-   * \retval -L4_EINVAL  Invalid component.
-   */
-  static int get_verbosity(unsigned c, char const **str);
-
-  /**
-   * Get the current verbosity level for a single component.
-   *
-   * \param c         Name of the component for which to query verbosity.
-   * \param[out] str  Pointer to the name of the current verbosity level for the
-   *                  given component (if the operation succeeded).
-   *
-   * \retval L4_EOK      Operation succeeded.
-   * \retval -L4_EINVAL  Invalid component name.
-   */
-  static int get_verbosity(char const *c, char const **str);
-
-  /**
-   * Obtain an array of valid verbosity levels.
-   *
-   * \return  Pointer to array containing verbosity level strings, terminated by
-   *          a null pointer.
-   */
-  static char const *const *valid_verbosity_levels();
-
-  /**
-   * Obtain an array of valid components for which the verbosity can be set.
-   *
-   * \return  Pointer to array containing component identifier strings,
-   *          terminated by a null pointer.
-   */
-  static char const *const *valid_components();
-
-  /**
-   * Set the verbosity for all components to the given levels.
-   *
-   * \param mask  Mask of verbosity levels.
-   */
-  static void set_verbosity(unsigned mask)
-  {
-    for (unsigned i = 0; i < Max_component; ++i)
-      set_verbosity(i, mask);
-  }
-
-  /**
-   * Set the verbosity of a single component to the given level.
-   *
-   * \param c     Component for which to set verbosity.
-   * \param mask  Mask of verbosity levels.
-   */
-  static void set_verbosity(unsigned c, unsigned mask)
-  {
-    level &= ~(Verbosity_mask << (Verbosity_shift * c));
-    level |= (mask & Verbosity_mask) << (Verbosity_shift * c);
-  }
-
-  Dbg(Component c = Core, Verbosity v = Warn, char const *subsys = nullptr)
-  : L4Re::Util::Dbg(v << (Verbosity_shift * c), "VMM", subsys)
-  {}
-
-  /**
-   * Set debug level according to a verbosity string.
-   *
-   * The string may either set a global verbosity level:
-   *   quiet, warn, info, trace
-   *
-   * Or it may set the verbosity level for a component:
-   *
-   *   =
-   *
-   * where component is one of: core, cpu, mmio, irq, dev, pm, vbus_event
-   * and level the same as above.
-   *
-   * To change the verbosity of multiple components repeat
-   * the verbosity switch.
-   *
-   * \retval L4_EOK      operation succeeded
-   * \retval -L4_EINVAL  invalid verbosity string
-   *
-   * Example:
-   *
-   *  uvmm -D info -D irq=trace
-   *
-   *    Sets verbosity for all components to info except for
-   *    IRQ handling which is set to trace.
-   *
-   *  uvmm -D trace -D dev=warn -D mmio=warn
-   *
-   *    Enables tracing for all components except devices
-   *    and mmio.
-   *
-   */
-  static int set_verbosity(char const *str);
-
-#else
-  static int get_verbosity(unsigned, char const **)
-  { return -L4_EINVAL; }
-  static int get_verbosity(char const *, char const **)
-  { return -L4_EINVAL; }
-  static void set_verbosity(unsigned, unsigned) {}
-  static void set_verbosity(unsigned) {}
-  static int set_verbosity(char const *)
-  { return -L4_EINVAL; }
-
-  Dbg(Component /* c */ = Core, Verbosity /* v */ = Warn ,
-      char const * /* subsys */ = nullptr)
-  {}
-#endif
-};
diff --git a/src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.cc b/src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.cc
deleted file mode 100644
index 32807aa8..00000000
--- a/src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-
-#include 
-#include 
-
-#include "cpu_dev.h"
-#include "device.h"
-#include "pt_walker.h"
-#include "vcpu_ptr.h"
-#include "debugger/generic_guest_debugger.h"
-#include "monitor/mem_dump.h"
-
-namespace Monitor {
-
-void
-Generic_guest_debugger::dump_memory(FILE *f,
-                                    Mem_dumper *mem_dumper,
-                                    Vmm::Vcpu_ptr vcpu)
-{
-  l4_addr_t gvirt_start = mem_dumper->addr_start();
-  l4_addr_t gvirt_end = mem_dumper->addr_end();
-
-  l4_addr_t hvirt_start = walk_page_table(gvirt_start, vcpu);
-
-  mem_dumper->dump(f, hvirt_start, l4_round_page(gvirt_end) - gvirt_start);
-}
-
-Vmm::Vcpu_ptr
-Generic_guest_debugger::vcpu_ptr(unsigned vcpu) const
-{ return vcpu_valid(vcpu) ? _devs->cpus()->vcpu(vcpu) : Vmm::Vcpu_ptr(nullptr); }
-
-bool
-Generic_guest_debugger::vcpu_valid(unsigned vcpu) const
-{ return vcpu < _devs->cpus()->size() && _devs->cpus()->vcpu_exists(vcpu); }
-
-bool
-Generic_guest_debugger::vcpu_smp_active() const
-{ return _devs->cpus()->max_cpuid() > 0; }
-
-l4_addr_t
-Generic_guest_debugger::walk_page_table(l4_addr_t gvirt, Vmm::Vcpu_ptr vcpu)
-{ return vcpu.get_pt_walker()->walk(vcpu.vm_state()->cr3(), gvirt); }
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.h b/src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.h
deleted file mode 100644
index a572432e..00000000
--- a/src/l4/pkg/uvmm/server/src/debugger/generic_guest_debugger.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "vcpu_ptr.h"
-#include "vm.h"
-
-namespace Vdev {
-  struct Device_lookup;
-}
-
-namespace Monitor {
-
-class Mem_dumper;
-
-class Generic_guest_debugger
-{
-public:
-  Generic_guest_debugger(Vmm::Vm *vm)
-  : _devs(vm)
-  {}
-
-  virtual ~Generic_guest_debugger() = default;
-
-  // memory dumping
-  void dump_memory(FILE *f, Mem_dumper *mem_dumper, Vmm::Vcpu_ptr vcpu);
-
-  // convenience methods
-  Vmm::Vcpu_ptr vcpu_ptr(unsigned vcpu) const;
-  bool vcpu_valid(unsigned vcpu) const;
-  bool vcpu_smp_active() const;
-
-private:
-  l4_addr_t walk_page_table(l4_addr_t gvirt, Vmm::Vcpu_ptr vcpu);
-
-  Vdev::Device_lookup *_devs;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device.h b/src/l4/pkg/uvmm/server/src/device.h
deleted file mode 100644
index 66e74ad1..00000000
--- a/src/l4/pkg/uvmm/server/src/device.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2016-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "device_tree.h"
-#include "debug.h"
-
-namespace Gic {
-  struct Ic;
-  struct Msix_controller;
-}
-namespace Vmm {
-  class Guest;
-  class Vm_ram;
-  class Virt_bus;
-  class Cpu_dev_array;
-  class Pm;
-}
-
-namespace Vdev {
-
-struct Dt_error_hdl
-{
-  template
-  Dt_error_hdl(Dtb::Node const *n, char const *fmt, Args ...args)
-  {
-    Err().printf("%s: ", n->get_name());
-    Err().cprintf(fmt, args...);
-    Err().cprintf("\n");
-    throw L4::Runtime_error(-L4_EINVAL);
-  }
-
-  template
-  Dt_error_hdl(Dtb::Node const *n, char const *msg)
-  {
-    Err().printf("%s: %s", n->get_name(), msg);
-    throw L4::Runtime_error(-L4_EINVAL);
-  }
-
-  template
-  Dt_error_hdl(Dtb::Node const *n, int error, char const *fmt, Args ...args)
-  {
-    Err().printf("%s: ", n->get_name());
-    Err().cprintf(fmt, args...);
-    Err().cprintf(": %s\n", fdt_strerror(error));
-    throw L4::Runtime_error(-L4_EINVAL);
-  }
-
-  template
-  Dt_error_hdl(Dtb::Node const *n, int error, char const *msg)
-  {
-    Err().printf("%s: %s: %s", n->get_name(), msg, fdt_strerror(error));
-    throw L4::Runtime_error(-L4_EINVAL);
-  }
-
-  template
-  Dt_error_hdl(char const *fmt, Args ...args)
-  {
-    Err().cprintf(fmt, args...);
-    Err().cprintf("\n");
-    throw L4::Runtime_error(-L4_EINVAL);
-  }
-
-  template
-  Dt_error_hdl(char const *msg)
-  {
-    Err().printf("%s\n", msg);
-    throw L4::Runtime_error(-L4_EINVAL);
-  }
-};
-typedef Dtb::Node Dt_node;
-typedef Dtb::Tree Device_tree;
-
-class Dev_ref
-{
-private:
-  mutable int _ref_cnt = 0;
-
-public:
-  void add_ref() const noexcept
-  { __atomic_add_fetch(&_ref_cnt, 1, __ATOMIC_ACQUIRE); }
-
-  int remove_ref() const noexcept
-  { return __atomic_sub_fetch(&_ref_cnt, 1, __ATOMIC_RELEASE); }
-};
-
-template< typename T, typename... Args >
-cxx::Ref_ptr
-make_device(Args &&... args)
-{ return cxx::make_ref_obj(cxx::forward(args)...); }
-
-struct Device_lookup;
-
-/**
- * Base class for all devices in the system.
- */
-struct Device : public virtual Dev_ref
-{
-  virtual ~Device() = 0;
-};
-
-inline Device::~Device() = default;
-
-/**
- * Interface with functions for finding device objects.
- */
-struct Device_lookup
-{
-  virtual void add_device(Vdev::Dt_node const &node,
-                          cxx::Ref_ptr dev,
-                          std::string const &path = std::string()) = 0;
-  virtual cxx::Ref_ptr device_from_node(Dt_node const &node,
-                                                std::string *path = nullptr)
-                                                const = 0;
-  virtual Vmm::Guest *vmm() const = 0;
-  virtual cxx::Ref_ptr ram() const = 0;
-  virtual cxx::Ref_ptr vbus() const = 0;
-  virtual cxx::Ref_ptr cpus() const = 0;
-  virtual cxx::Ref_ptr pm() const = 0;
-
-  /// Result values for get_or_create_ic()
-  enum Ic_error
-  {
-    Ic_ok,           ///< There is a valid interrupt parent device
-    Ic_e_no_iparent, ///< Node does not have an interrupt parent property
-    Ic_e_disabled,   ///< Node is disabled
-    Ic_e_no_virtic,  ///< Interrupt parent is not a virtual interrupt controller
-    Ic_e_failed,     ///< Creation of an interrupt parent failed
-  };
-
-  /**
-   * Get a textual description for an Ic_error value.
-   *
-   * \param res  The error a textual description is looked for.
-   *
-   * \return Pointer to error string.
-   *
-   */
-  static const char * ic_err_str(Vdev::Device_lookup::Ic_error res)
-  {
-    char const *err[] = {
-        "ok",
-        "no interrupt parent found",
-        "interrupt parent node disabled",
-        "interrupt parent is not a virtual interrupt controller",
-        "creation of interrupt parent failed"
-    };
-    return (res < sizeof(err)/sizeof(err[0])) ? err[res] : "unknown error";
-  }
-
-  /**
-   * Get the interrupt controller for a given node.
-   *
-   * \param node         The device tree node an interrupt parent is looked for.
-   * \param[out] ic_ptr  A pointer to the virtual device of the interrupt parent
-   *                     if there is one.
-   *
-   * \retval Ic_ok            interrupt parent was returned in ic_ptr
-   * \retval Ic_e_no_iparent  node does not have an interrupt parent property
-   * \retval Ic_e_disabled    interrupt parent node is
-   * \retval Ic_e_no_virtic   interrupt parent is not a virtual interrupt
-   *                          controller
-   * \retval Ic_e_failed      creation of an interrupt parent failed
-   *
-   * This method tries to fetch and return the interrupt parent of the node. If
-   * the device doesn't exist yet and is a virtual device it tries to create it.
-   * It walks the interrupt tree up and creates the missing devices starting
-   * with the top most missing device. On success it returns Ic_ok and ic_ptr
-   * points to the virtual device of the interrupt parent. Otherwise one of the
-   * remaining return codes describes the error.
-   */
-  virtual Ic_error get_or_create_ic(Vdev::Dt_node const &node,
-                                    cxx::Ref_ptr *ic_ptr) = 0;
-
-  /// Result values for get_or_create_mc()
-  enum Mc_error
-  {
-    Mc_ok,             ///< There is a valid MSI parent device.
-    Mc_e_no_msiparent, ///< Node does not have an MSI parent property.
-    Mc_e_disabled,     ///< Node is disabled.
-    Mc_e_no_msictrl,   ///< Interrupt parent is not a virtual interrupt controller.
-    Mc_e_failed,       ///< Creation of an MSI parent failed.
-  };
-
-  /**
-   * Get a textual description for an Mc_error value.
-   *
-   * \param res  The error a textual description is looked for.
-   *
-   * \return Pointer to error string.
-   *
-   */
-  static const char *mc_err_str(Mc_error res)
-  {
-    char const *err[] = {
-        "ok",
-        "no MSI parent found",
-        "MSI parent node disabled",
-        "MSI parent is not an MSI controller",
-        "creation of MSI parent failed"
-    };
-    return (res < sizeof(err)/sizeof(err[0])) ? err[res] : "unknown error";
-  }
-
-  /**
-   * Get the virtual MSI controller device for a given node.
-   *
-   * \param node         The device tree node to look up the MSI parent for.
-   * \param[out] mc_ptr  A pointer to the virtual device of the MSI parent
-   *                     if there is one.
-   *
-   * \retval Mc_ok              MSI parent was returned in mc_ptr.
-   * \retval Mc_e_no_msiparent  Node does not have an MSI parent property.
-   * \retval Mc_e_disabled      MSI parent node is disabled.
-   * \retval Mc_e_no_msictrl    MSI parent is not a virtual MSI controller.
-   * \retval Mc_e_failed        Creation of an MSI parent failed.
-   */
-  virtual Mc_error
-  get_or_create_mc(Vdev::Dt_node const &node,
-                   cxx::Ref_ptr *mc_ptr) = 0;
-
-  /**
-   * Get the virtual MSI controller device for a given node.
-   *
-   * \param node  The device tree node to look up the MSI parent for.
-   *
-   * \returns  A virtual MSI controller device or an exception is thrown.
-   */
-  virtual cxx::Ref_ptr
-  get_or_create_mc_dev(Vdev::Dt_node const &node) = 0;
-};
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/arm/pl031.cc b/src/l4/pkg/uvmm/server/src/device/arm/pl031.cc
deleted file mode 100644
index f2e4876d..00000000
--- a/src/l4/pkg/uvmm/server/src/device/arm/pl031.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2021-2022,2024, 2023-2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-/**
- * Emulation of the PL031 real-time clock device.
- *
- * Based on the ARM PrimeCell Real Time Clock (PL031) Revision: r1p3
- * specification.
- *
- * Configure this device using the following device tree node adapted to your
- * platform needs.
- *
- * \code{.dtb}
- *   virt_pl031 {
- *       compatible = "arm,pl031", "arm,primecell";
- *       reg = <0x13000 0x1000>;
- *       interrupts = <0x00 0x02 0x04>;
- *       clocks = <&apb_dummy_pclk>;
- *       clock-names = "apb_pclk";
- *   };
- * \endcode
-
- * Linux also wants to have an entry for clocks like this:
- *
- * \code{.dtb}
- *   apb_dummy_pclk: dummy_clk {
- *       compatible = "fixed-clock";
- *       #clock-cells = <0>;
- *       clock-frequency = <1000000>;
- *   };
- * \endcode
- *
- */
-#include "debug.h"
-#include "device.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "mmio_device.h"
-#include "irq_dt.h"
-
-#include "../rtc-hub.h"
-
-namespace Vdev {
-
-class Pl031
-: public Vmm::Mmio_device_t,
-  public Vdev::Timer,
-  public Vdev::Device
-{
-  struct Alarm_timeout : public L4::Ipc_svr::Timeout_queue::Timeout
-  {
-    Alarm_timeout(Pl031 *pl031) : _pl031(pl031) {}
-
-    /**
-     * Handle expired alarms.
-     *
-     * This function is called from the timer thread.
-     */
-    void expired() override
-    {
-      trace().printf("PL031 IRQ due to alarm expired()\n");
-      _pl031->set_irq();
-    }
-
-    Pl031 *_pl031;
-  }; // struct Alarm_timeout
-
-  enum Registers
-  {
-    Dr = 0x0,    ///< Data register, RO
-    Mr = 0x4,    ///< Match register, RW
-    Lr = 0x8,    ///< Load register, RW
-    Cr = 0xC,    ///< Control register, RW
-    Imsc = 0x10, ///< Interrupt mask set or clear register, RW
-    Ris = 0x14,  ///< Raw interrupt status register, RO
-    Mis = 0x18,  ///< Masked interrupt status register, RO
-    Icr = 0x1C,  ///< Interrupt clear register, WO
-
-    // 0x020 - 0xFDF Reserved and undefined areas
-
-    // Read-only
-    Periph_id0 = 0xFE0, ///< Peripheral ID register 7:0
-    Periph_id1 = 0xFE4, ///< Peripheral ID register 15:8
-    Periph_id2 = 0xFE8, ///< Peripheral ID register 23:16
-    Periph_id3 = 0xFEC, ///< Peripheral ID register 31:24
-
-    // Read-only
-    Pcell_id0 = 0xFF0,  ///< PrimeCell ID register 7:0
-    Pcell_id1 = 0xFF4,  ///< PrimeCell ID register 15:8
-    Pcell_id2 = 0xFF8,  ///< PrimeCell ID register 23:16
-    Pcell_id3 = 0xFFC,  ///< PrimeCell ID register 31:24
-  };
-
-public:
-  Pl031(cxx::Ref_ptr const &ic, int irq) : _irq(ic, irq), _alarm(this)
-  {
-    reset();
-#if !defined(CONFIG_UVMM_EXTERNAL_RTC) and !(CONFIG_RELEASE_MODE)
-    warn().printf(
-      "No external clock source. Rtc time will not represent wallclock time.\n"
-      "Set CONFIG_UVMM_EXTERNAL_RTC = y if you have an external clock "
-      "source.\n");
-#endif
-  }
-
-  l4_uint32_t read(unsigned reg, char size, unsigned /*cpu_id*/)
-  {
-    if (size != Vmm::Mem_access::Width::Wd32)
-    {
-      warn().printf("Read access width not 32-bit, ignoring access: "
-                    "Reg: 0x%x, Wd: %i\n", reg, size);
-      return 0;
-    }
-
-    l4_umword_t retval = 0;
-
-    switch (reg)
-      {
-      case Registers::Dr: retval = counter(); break;
-      case Registers::Mr: retval = _match_reg; break;
-      case Registers::Lr: retval = _load_reg; break;
-      case Registers::Cr: retval = 1U; break; // always on.
-      case Registers::Imsc: retval = _imsc & 1U; break;
-      case Registers::Ris: retval = _intr; break;
-      case Registers::Mis: retval = _intr & (_imsc & 1U); break;
-
-      case Registers::Icr: // error: read of WO register
-        warn().printf("Reading write-only ICR register\n");
-        break;
-
-      case Registers::Periph_id0: [[fallthrough]];
-      case Registers::Periph_id1: [[fallthrough]];
-      case Registers::Periph_id2: [[fallthrough]];
-      case Registers::Periph_id3:
-        retval = periph_id[(reg - Periph_id0) >> 2];
-        break;
-
-      case Registers::Pcell_id0: [[fallthrough]];
-      case Registers::Pcell_id1: [[fallthrough]];
-      case Registers::Pcell_id2: [[fallthrough]];
-      case Registers::Pcell_id3:
-        retval = pcell_id[(reg - Pcell_id0) >> 2];
-        break;
-
-      default: break;
-      }
-
-    return retval;
-  }
-
-  void write(unsigned reg, char size, l4_umword_t value, unsigned /*cpu_id*/)
-  {
-    if (size != Vmm::Mem_access::Width::Wd32)
-      {
-        info().printf("Write access width not 32-bit, ignoring access: "
-                      "Reg: 0x%x, Wd: %i\n",
-                      reg, size);
-        return;
-      }
-
-    trace().printf("Writing 0x%lx to reg 0x%x\n", value, reg);
-
-    switch (reg)
-      {
-      case Registers::Dr:
-        info().printf("Writing read-only register DR. Ignoring.\n");
-        break;
-
-      case Registers::Mr:
-        _match_reg = value;
-        update_alarm();
-        break;
-
-      case Registers::Lr:
-        _load_reg = value;
-        update_load();
-        break;
-
-      case Registers::Cr:
-        // writing resets -- not implemented -- always on;
-        break;
-
-      case Registers::Imsc: _imsc = value & 1U; break;
-
-      case Registers::Ris: [[fallthrough]];
-      case Registers::Mis:
-        warn().printf("Writing read-only register 0x%x. Ignoring.\n", reg);
-        break;
-
-      case Registers::Icr:
-        if (value & 0x1U && _intr)
-          {
-            _intr = 0;
-            _irq.ack();
-          }
-        break;
-
-      default:
-        info()
-          .printf("Writing read-only register or unspecified register 0x%x\n",
-                  reg);
-      }
-  }
-
-  char const *dev_name() const override { return "PL031"; }
-
-private:
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "PL031"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "PL031"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "PL031"); }
-
-  static l4_uint64_t ns_to_s(l4_uint64_t ns) { return ns / 1'000'000'000; }
-  static l4_uint64_t s_to_us(l4_uint64_t s) { return s * 1'000'000; }
-  static l4_uint64_t s_to_ns(l4_uint64_t s) { return s * 1'000'000'000; }
-
-  /// Return current counter value with 1Hz granularity. Wraps after 136 years.
-  static l4_uint32_t counter()
-  { return ns_to_s(L4rtc_hub::ns_since_epoch()) & 0xffff'ffffU; }
-
-  /// Flag the IRQ and if not masked also send it.
-  void set_irq()
-  {
-    _intr = 1U;
-
-    if (_imsc == 0U)
-      _irq.inject();
-  }
-
-  /**
-   * Update the alarm timeout or inject IRQ if timeout already passed.
-   *
-   * \param counter_val  Counter value, if already queried from L4rtc.
-   */
-  void update_alarm(l4_uint32_t const counter_val = counter())
-  {
-    if (_match_reg <=  counter_val)
-      set_irq();
-    else
-      {
-        l4_uint64_t next_alarm = _match_reg - counter_val;
-
-        trace().printf("enqueue alarm for %lli seconds from now. (counter: %u,"
-                       " 0x%u)\n",
-                      next_alarm, counter_val, _match_reg);
-        enqueue_timeout(&_alarm, l4_kip_clock(l4re_kip()) + s_to_us(next_alarm));
-      }
-  }
-
-  void update_load()
-  {
-    L4rtc_hub::set_ns_since_epoch(s_to_ns(_load_reg));
-    update_alarm();
-  }
-
-  void reset()
-  {
-    _load_reg = 0;
-    _match_reg = 0;
-    _imsc = 0;
-    _intr = 0;
-    _irq.ack();
-  }
-
-  l4_uint8_t const periph_id[4] = {0x31, 0x10, 0x04, 0x00};
-  l4_uint8_t const pcell_id[4] = {0x0D, 0xF0, 0x05, 0xB1};
-
-  Vmm::Irq_sink _irq;
-  Alarm_timeout _alarm;
-
-  l4_uint32_t _match_reg;
-  l4_uint32_t _load_reg;
-  l4_uint8_t _imsc; // 1 = masked, 0 = clear
-  l4_uint8_t _intr; // interrupt status
-};
-
-} // namespace Vdev
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    Dbg info = Dbg(Dbg::Dev, Dbg::Info, "PL031");
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      {
-        info.printf("PL031 requires a virtual interrupt controller.");
-        return nullptr;
-      }
-
-    auto dev = Vdev::make_device(it.ic(), it.irq());
-
-    devs->vmm()->register_mmio_device(dev, Vmm::Region_type::Virtual, node);
-    devs->vmm()->register_timer_device(dev);
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t1 = { "arm,pl031", nullptr, &f };
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/arm/psci.cc b/src/l4/pkg/uvmm/server/src/device/arm/psci.cc
deleted file mode 100644
index 6cabb83a..00000000
--- a/src/l4/pkg/uvmm/server/src/device/arm/psci.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2015-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Jean Wolter 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "cpu_dev_array.h"
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-
-#include "smccc_device.h"
-
-namespace {
-
-using namespace Vdev;
-
-static Dbg warn(Dbg::Dev, Dbg::Warn, "psci");
-static Dbg info(Dbg::Dev, Dbg::Info, "psci");
-
-class Psci_device : public Vdev::Device, public Vmm::Smccc_device
-{
-  enum Psci_error_codes
-  {
-    Success            = 0,
-    Not_supported      = -1,
-    Invalid_parameters = -2,
-    Denied             = -3,
-    Already_on         = -4,
-    On_pending         = -5,
-    Internal_failure   = -6,
-    Not_present        = -7,
-    Disabled           = -8,
-    Invalid_address    = -9,
-  };
-
-  enum Psci_functions
-  {
-    Psci_version          = 0,
-    Cpu_suspend           = 1,
-    Cpu_off               = 2,
-    Cpu_on                = 3,
-    Affinity_info         = 4,
-    Migrate               = 5,
-    Migrate_info_type     = 6,
-    Migrate_info_up_cpu   = 7,
-    System_off            = 8,
-    System_reset          = 9,
-    Psci_features         = 10,
-    Cpu_freeze            = 11,
-    Cpu_default_suspend   = 12,
-    Node_hw_state         = 13,
-    System_suspend        = 14,
-    Psci_set_suspend_mode = 15,
-    Psci_stat_residency   = 16,
-    Psci_stat_count       = 17,
-  };
-
-  enum Psci_migrate_info
-  {
-    Tos_up_mig_cap     = 0,
-    Tos_not_up_mig_cap = 1,
-    Tos_not_present_mp = 2,
-  };
-
-  enum Psci_affinity_info
-  {
-    Aff_info_on         = 0,
-    Aff_info_off        = 1,
-    Aff_info_on_pending = 2,
-  };
-
-  inline l4_mword_t affinity(l4_mword_t reg, bool smccc_64)
-  {
-    if ((sizeof(reg) == 4) || smccc_64)
-      return reg;
-
-    l4_uint32_t aff3_mask_32 = 0xffU << 24;
-
-    // Delete [63-32] by applying a 32bit mask
-    // Move aff3 from [31-24] to [39-32]
-    return ((reg & aff3_mask_32) << 8) | (reg & ~aff3_mask_32);
-  }
-
-public:
-  Psci_device(Vmm::Guest *vmm, cxx::Ref_ptr pm,
-              cxx::Ref_ptr cpus)
-  : _vmm(vmm),
-    _pm(pm),
-    _cpus(cpus)
-  {}
-
-  bool vm_call(unsigned imm, Vmm::Vcpu_ptr vcpu) override
-  {
-    if (imm != 0)
-      return false;
-
-    // Check this is a supported PSCI function call id.
-    if (!is_valid_func_id(vcpu->r.r[0]))
-      return false;
-
-    l4_uint8_t func = vcpu->r.r[0] & 0x1f;
-    switch (func)
-      {
-      case Psci_version:
-        vcpu->r.r[0] = 0x00010000; // v1.0
-        break;
-      case Cpu_suspend:
-        psci_cpu_suspend(vcpu);
-        break;
-      case Cpu_off:
-        psci_cpu_off(vcpu);
-        break;
-      case Cpu_on:
-        psci_cpu_on(vcpu);
-        break;
-      case Affinity_info:
-        psci_affinity_info(vcpu);
-        break;
-      case Migrate_info_type:
-        vcpu->r.r[0] = Tos_not_present_mp;
-        break;
-      case System_off:
-        _vmm->shutdown(Vmm::Guest::Shutdown);
-        break;
-      case System_reset:
-        _vmm->shutdown(Vmm::Guest::Reboot);
-        break;
-      case Psci_features:
-        psci_features(vcpu);
-       break;
-      case System_suspend:
-        psci_system_suspend(vcpu);
-        break;
-      default:
-        warn.printf("... Not supported PSCI function 0x%x called\n",
-                    static_cast(func));
-        vcpu->r.r[0] = Not_supported;
-        break;
-      };
-
-    return true;
-  }
-
-private:
-  void psci_cpu_suspend(Vmm::Vcpu_ptr vcpu)
-  {
-    /*
-     * Ignore the power state. We do not implement any special behavior for low-
-     * power, but behave the same like in the non low-power case. According to
-     * the PSCI spec. section 5.4.5 point 3. it is allowed for the PSCI
-     * implementer to downgrade to a standby state. In this case we just return
-     * from this function without jumping to the entry_point_address.
-     */
-    _vmm->wait_for_timer_or_irq(vcpu);
-
-    vcpu->r.r[0] = Success;
-  }
-
-  void psci_cpu_off(Vmm::Vcpu_ptr vcpu)
-  {
-    Vmm::Cpu_dev *target = current_cpu();
-    target->stop();
-    // should never return
-    vcpu->r.r[0] = Internal_failure;
-  }
-
-  void psci_cpu_on(Vmm::Vcpu_ptr vcpu)
-  {
-    l4_mword_t hwid = affinity(vcpu->r.r[1], is_64bit_call(vcpu->r.r[0]));
-    Vmm::Cpu_dev *target = lookup_cpu(hwid);
-
-    if (target)
-      {
-        // XXX There is currently no way to detect error conditions like
-        // INVALID_ADDRESS
-        if (!target->online() && target->mark_on_pending())
-          {
-            l4_mword_t ip = vcpu->r.r[2];
-            l4_mword_t context =  vcpu->r.r[3];
-            target->vcpu()->r.r[0] = context;
-            _vmm->prepare_vcpu_startup(target->vcpu(), ip);
-            if (target->start_vcpu())
-              vcpu->r.r[0] = Success;
-            else
-              vcpu->r.r[0] = Internal_failure;
-          }
-        else
-          vcpu->r.r[0] = target->online_state() == Vmm::Cpu_dev::Cpu_state::On
-            ? Already_on : On_pending;
-      }
-    else
-      vcpu->r.r[0] = Invalid_parameters;
-  }
-
-  void psci_affinity_info(Vmm::Vcpu_ptr vcpu)
-  {
-    // parameters:
-    // * target_affinity
-    // * lowest affinity level
-    l4_mword_t hwid = affinity(vcpu->r.r[1], is_64bit_call(vcpu->r.r[0]));
-    l4_umword_t lvl = vcpu->r.r[2];
-
-    // Default to invalid in case we do not find a matching CPU
-    vcpu->r.r[0] = Invalid_parameters;
-
-    // There are at most 3 affinity levels
-    if (lvl > 3)
-      return;
-
-    for (auto const &cpu : *_cpus.get())
-      if (cpu && cpu->matches(hwid, lvl))
-        {
-          if (cpu->online())
-            {
-              vcpu->r.r[0] = Aff_info_on;
-              return;
-            }
-          vcpu->r.r[0] = Aff_info_off;
-        }
-  }
-
-  void psci_features(Vmm::Vcpu_ptr vcpu)
-  {
-    // Check this uses an allowed SMCCC bitness and is a valid PSCI
-    // function id.
-    if (!(   is_valid_call(vcpu->r.r[1])
-          && is_valid_func_id(vcpu->r.r[1])))
-      {
-        vcpu->r.r[0] = Not_supported;
-        return;
-      }
-
-    l4_uint8_t feat_func = vcpu->r.r[1] & 0x1f;
-    switch (feat_func)
-      {
-      case Cpu_suspend:
-        vcpu->r.r[0] = 1 << 1;
-        break;
-      case Psci_version:
-      case Cpu_on:
-      case Cpu_off:
-      case Affinity_info:
-      case Migrate_info_type:
-      case System_off:
-      case System_reset:
-      case Psci_features:
-      case System_suspend:
-        vcpu->r.r[0] = Success;
-        break;
-      default:
-        vcpu->r.r[0] = Not_supported;
-        break;
-      };
-  }
-
-  void psci_system_suspend(Vmm::Vcpu_ptr vcpu)
-  {
-    l4_addr_t entry_gpa = vcpu->r.r[1];
-    l4_umword_t context_id = vcpu->r.r[2];
-
-    // Check preconditions:
-    //   * Request has to be executed on CPU0 (requirement imposed
-    //     by us)
-    //   * all other CPUs have to be off (specification requirement)
-    //   * powermanagement allows suspend operation
-    if (    current_cpu()->vcpu().get_vcpu_id() != 0
-        || !cpus_off() || !_pm->suspend())
-      {
-        vcpu->r.r[0] = Denied;
-        return;
-      }
-
-    /* Go to sleep */
-    vcpu.wait_for_ipc(l4_utcb(), L4_IPC_NEVER);
-    /* Back alive */
-    _pm->resume();
-
-    memset(&vcpu->r, 0, sizeof(vcpu->r));
-    _vmm->prepare_vcpu_startup(vcpu, entry_gpa);
-    vcpu->r.r[0]  = context_id;
-    l4_vcpu_e_write_32(*vcpu, L4_VCPU_E_SCTLR,
-        l4_vcpu_e_read_32(*vcpu, L4_VCPU_E_SCTLR) & ~1U);
-  }
-
-  Vmm::Cpu_dev *current_cpu() const
-  { return _cpus->cpu(vmm_current_cpu_id).get(); }
-
-  Vmm::Cpu_dev *lookup_cpu(l4_umword_t hwid) const
-  {
-    for (auto const &cpu : *_cpus.get())
-      if (cpu && cpu->matches(hwid))
-        return cpu.get();
-
-    return nullptr;
-  }
-
-  bool cpus_off() const
-  {
-    bool first = true;
-    for (auto const &cpu : *_cpus.get())
-      {
-        // ignore boot cpu
-        if (first)
-          {
-            first = false;
-            continue;
-          }
-
-        if (cpu && cpu->online())
-          return false;
-      }
-
-    return true;
-  }
-
-  bool is_valid_func_id(l4_umword_t reg) const
-  {
-    // Check for the correct SMC calling convention:
-    // - this must be a fast call (bit 31)
-    // - it is within the Standard Secure Service range (bits 29:24)
-    // - it is within the PSCI range (bits 4:0)
-    // - the rest must be zero
-    return (reg & 0xbfffffe0) == 0x84000000;
-  }
-
-  Vmm::Guest *_vmm;
-  cxx::Ref_ptr _pm;
-  cxx::Ref_ptr _cpus;
-};
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    auto c = make_device(devs->vmm(), devs->pm(), devs->cpus());
-    Vmm::Guest::Smccc_method smccc_method = Vmm::Guest::Hvc;
-
-    char const *method = node.get_prop("method", nullptr);
-    if (method)
-      {
-        if (strcmp(method, "smc") == 0)
-          smccc_method = Vmm::Guest::Smc;
-        else if (strcmp(method, "hvc") != 0)
-          warn.printf("Method '%s' is not supported. Must be hvc or smc!\n",
-                      method);
-      }
-
-    info.printf("Register PSCI device: %s mode\n",
-                smccc_method == Vmm::Guest::Hvc ? "hvc" : "smc");
-
-    devs->vmm()->register_vm_handler(smccc_method, c);
-
-    return c;
-  }
-};
-
-static F f;
-static Device_type t1 = { "arm,psci", nullptr, &f };
-static Device_type t2 = { "arm,psci-0.2", nullptr, &f };
-static Device_type t3 = { "arm,psci-1.0", nullptr, &f };
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/arm/smccc_device.h b/src/l4/pkg/uvmm/server/src/device/arm/smccc_device.h
deleted file mode 100644
index 0cd08bb3..00000000
--- a/src/l4/pkg/uvmm/server/src/device/arm/smccc_device.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "device.h"
-#include "vcpu_ptr.h"
-
-namespace Vmm {
-
-/**
- * Base class for all devices implementing the SMC calling convention.
- */
-struct Smccc_device : public virtual Vdev::Dev_ref
-{
-  enum
-  {
-    Not_supported = -1
-  };
-
-  virtual ~Smccc_device() = 0;
-
-  /**
-   * Method called by the vmm on either a SMC/HVC call.
-   *
-   * \param imm   Immediate value of the SMC/HVC instruction.
-   * \param vcpu  The cpu pointer when trapped. vcpu->r.ip points to the
-   *              instruction after the trapped SMC/HVC instruction
-   *
-   * \return  True when the call was handled by the implementation and false
-   *          otherwise.
-   */
-  virtual bool vm_call(unsigned imm, Vcpu_ptr vcpu) = 0;
-
-  static constexpr bool is_64bit_call(l4_umword_t reg)
-  {
-    // Bit 30 must be set for 64 bit calls
-    return reg & (1 << 30);
-  }
-
-  static constexpr bool is_fast_call(l4_umword_t reg)
-  {
-    // Bit 31 must be set for fastcalls
-    return reg & (1 << 31);
-  }
-
-  static constexpr bool is_valid_call(l4_umword_t reg)
-  {
-    // Check for SMC calling convention bitness:
-    // 64 bit SMCCC is only allowed on a 64 bit host
-    return !(is_64bit_call(reg) && sizeof(long) == 4);
-  }
-};
-
-inline Smccc_device::~Smccc_device() = default;
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/arm/smccc_proxy.cc b/src/l4/pkg/uvmm/server/src/device/arm/smccc_proxy.cc
deleted file mode 100644
index 244c144a..00000000
--- a/src/l4/pkg/uvmm/server/src/device/arm/smccc_proxy.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2025 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-
-#include "device_factory.h"
-#include "smccc_device.h"
-#include "guest.h"
-
-/**
- * Forwards smccc calls from the guest to an external entity. This proxy does
- * not do any filtering, so it is the responsibility of the external entity to
- * do this.
- *
- * Configure this device using the following device tree node adapted to your
- * platform needs.
- *
- * \code{.dtb}
- *   smccc_proxy {
- *       compatible = "l4vmm,smccc_proxy";
- *       l4vmm,smccc_cap = "smc";
- *       method = "smc";
- *   };
- * \endcode
- *
- * The default cap name for l4vmm,smccc_cap is "smc". Method can be "smc" or
- * "hvc".
- */
-
-static Dbg warn(Dbg::Dev, Dbg::Warn, "smccc_proxy");
-
-namespace {
-
-using namespace Vdev;
-
-class Smccc_proxy : public Device, public Vmm::Smccc_device
-{
-public:
-  Smccc_proxy(L4::Cap smc)
-  : _smc(smc)
-  {}
-
-  bool vm_call(unsigned imm, Vmm::Vcpu_ptr vcpu) override
-  {
-    if (imm != 0)
-      return false;
-
-    _smc->call(vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3],
-               vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6],
-               &vcpu->r.r[0], &vcpu->r.r[1], &vcpu->r.r[2], &vcpu->r.r[3], 0);
-
-    return true;
-  }
-
-private:
-  L4Re::Util::Unique_cap _smc;
-};
-
-class F : public Factory
-{
-public:
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    warn.printf("smccc_proxy\n");
-
-    auto smc = Vdev::get_cap(node, "l4vmm,smccc_cap",
-                 L4Re::Env::env()->get_cap("smc"));
-    if (!smc)
-      return nullptr;
-
-    Vmm::Guest::Smccc_method smccc_method = Vmm::Guest::Smc;
-
-    char const *method = node.get_prop("method", nullptr);
-    if (method)
-      {
-        if (strcmp(method, "hvc") == 0)
-          smccc_method = Vmm::Guest::Hvc;
-        else if (strcmp(method, "smc") != 0)
-          warn.printf("Method '%s' is not supported. Must be hvc or smc!\n",
-                      method);
-      }
-
-    auto c = Vdev::make_device(smc);
-
-    devs->vmm()->register_vm_handler(smccc_method, c);
-
-    return c;
-  }
-};
-
-static F f;
-static Device_type t1 = { "l4vmm,smccc_proxy", nullptr, &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/arm/vm_print.h b/src/l4/pkg/uvmm/server/src/device/arm/vm_print.h
deleted file mode 100644
index d12906da..00000000
--- a/src/l4/pkg/uvmm/server/src/device/arm/vm_print.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "smccc_device.h"
-#include "vmprint.h"
-
-namespace {
-
-static Dbg warn(Dbg::Dev, Dbg::Warn, "vm_print");
-static Dbg info(Dbg::Dev, Dbg::Info, "vm_print");
-
-class Vm_print_device : public Vdev::Device, public Vmm::Smccc_device
-{
-  enum Vm_print_error_codes
-  {
-    Success = 0,
-  };
-
-public:
-  explicit Vm_print_device(unsigned max_cpus)
-  : _guest_print(max_cpus)
-  {}
-
-  bool vm_call(unsigned imm, Vmm::Vcpu_ptr vcpu) override
-  {
-    if (imm != 1)
-      return false;
-
-    if (!is_valid_func_id(vcpu->r.r[0]))
-      return false;
-
-    assert(vmm_current_cpu_id < _guest_print.size());
-
-    _guest_print[vmm_current_cpu_id].print_char(vcpu->r.r[1]);
-    vcpu->r.r[0] = Success;
-
-    return true;
-  }
-
-private:
-  bool is_valid_func_id(l4_umword_t reg) const
-  {
-    // Check for the correct SMC calling convention:
-    // - this must be a fast call (bit 31)
-    // - it is within the uvmm range (bits 29:24)
-    // - the rest must be zero
-    return (reg & 0xbfffffff) == 0x86000000;
-  }
-
-  std::vector _guest_print;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/bcm2835_mbox.cc b/src/l4/pkg/uvmm/server/src/device/bcm2835_mbox.cc
deleted file mode 100644
index b347284f..00000000
--- a/src/l4/pkg/uvmm/server/src/device/bcm2835_mbox.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Frank Mehnert 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-/**
- * \file
- */
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "device_factory.h"
-#include "guest.h"
-#include "irq_dt.h"
-#include "irq_svr.h"
-#include "mmio_device.h"
-#include "vm_ram.h"
-
-namespace {
-
-using namespace Vdev;
-
-/**
- * Device for connecting to the bcm2835 mailbox service.
- *
- * This device emulation proxies guest accesses to this device to the bcm2835
- * mailbox to the 'mbox' service. A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   mailbox: mailbox@7e00b880 {
- *       compatible = "brcm,bcm2835-mbox";
- *       reg = <0x7e00b880 0x40>;
- *       interrupts = <0 1>;
- *       #mbox-cells = <0>;
- *   };
- * \endcode
- *
- * This is the same layout as used by native Linux.
- */
-
-static Dbg trace(Dbg::Dev, Dbg::Trace, "bcm2835");
-static Dbg warn(Dbg::Dev, Dbg::Warn, "bcm2835");
-
-struct Io_irq_svr : public Irq_svr
-{
-  using Irq_svr::Irq_svr;
-};
-
-class Bcm2835_mbox_dev
-: public Vdev::Device,
-  public Vmm::Mmio_device_t,
-  public Bcm2835_mbox
-{
-  struct alignas(16) Shm_block
-  {
-    l4_uint32_t phys;
-    l4_uint32_t _align[3];
-    l4_uint32_t msg_size;
-  };
-
-public:
-  Bcm2835_mbox_dev(L4::Cap vbus, Vmm::Vm_ram *ram,
-               Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-  : Bcm2835_mbox(vbus, warn),
-    _ram(ram)
-  {
-    L4vbus::Icu icu_dev;
-    L4Re::chksys(vbus->root().device_by_hid(&icu_dev, "L40009"), "Request ICU");
-    auto icu = L4Re::chkcap(L4Re::Util::cap_alloc.alloc(),
-                            "Allocate ICU cap");
-    L4Re::chksys(icu_dev.vicu(icu), "Request ICU cap");
-
-    // Match the interrupt resource provided by the IO vbus device with the
-    // corresponding device tree entry. The other resources were already handled
-    // by Bcm2835_mbox().
-    for (unsigned i = 0; i < _mbox_num_resources; ++i)
-      {
-        l4vbus_resource_t res;
-        L4Re::chksys(_mbox.get_resource(i, &res), "Get mbox device info");
-        if (res.type == L4VBUS_RESOURCE_IRQ)
-          {
-            Vdev::Irq_dt_iterator it(devs, node);
-            if (it.next(devs) < 0)
-              L4Re::throw_error(
-                -L4_EINVAL, "No device tree entry for interrupt resource");
-            if (!it.ic_is_virt())
-              L4Re::throw_error(
-                -L4_EINVAL, "Bcm2835 requires a virtual interrupt controller");
-            int io_irq = res.start;
-            int dt_irq = it.irq();
-            cxx::Ref_ptr const &ic = it.ic();
-            auto *irq_source = ic->get_irq_src_handler(dt_irq);
-            if (irq_source)
-              L4Re::throw_error_fmt(
-                -L4_EINVAL, "IO device '%s': irq 0x%x -> 0x%x already registered",
-                node.get_name(), io_irq, dt_irq);
-            // forward interrupt generated by IO device at pin `io_irq` to the
-            // guest at pin `dt_irq`
-            auto irq_svr =
-              cxx::make_ref_obj(devs->vmm()->registry(),
-                                            icu, io_irq, ic, dt_irq);
-            irq_svr->eoi();
-            _irq = std::move(irq_svr);
-          }
-      }
-
-    detect_dma_offset();
-  }
-
-  virtual ~Bcm2835_mbox_dev() = default;
-
-  char const *dev_name() const override { return "Bcm2835_mbox"; }
-
-  /**
-   * Detect the DMA offset as required by the device.
-   *
-   * This value is important because guest Linux makes use of it.
-   */
-  void detect_dma_offset()
-  {
-    Soc_rev board_rev = get_board_rev();
-    if (board_rev.new_style())
-      {
-        switch (board_rev.type())
-          {
-          case 0x11: // 4B
-            if (board_rev.revision() <= 2)
-              break;
-            _dma_offset = 0ULL;
-            break;
-          case 0x13: // 400
-            _dma_offset = 0ULL;
-            break;
-          }
-      }
-
-    warn.printf("DMA offset = %08llx\n", _dma_offset);
-  }
-
-  l4_uint32_t read(unsigned reg, char size, unsigned /* cpu_id */)
-  {
-    trace.printf("\033[32mBcm2835::read offset=%02x size=%u\033[m\n", reg, size);
-    if (size != 2)
-      L4Re::throw_error(-L4_EINVAL, "Can only handle 32-bit reads");
-
-    l4_uint32_t value = _regs[reg];
-    if (reg == Mbox0_read && value != 0)
-      {
-        // We trust the service that it returned us the pointer to a message
-        // which we submitted in the write() function below.
-        l4_uint32_t shared_offs = (value & ~Channel_mask) - 16;
-        l4_uint32_t channel = value & Channel_mask;
-        l4_uint8_t *shared_addr = _data_virt + shared_offs;
-        l4_uint32_t *shared_words = reinterpret_cast(shared_addr);
-        l4_uint32_t msg_gst_phys_addr = shared_words[0] - _dma_offset;
-        Vmm::Guest_addr msg_gst_phys{msg_gst_phys_addr};
-        auto *msg_gst = _ram->guest2host(msg_gst_phys);
-        auto *msg = reinterpret_cast *>(msg_gst);
-        // Copy letter content from shared area to guest RAM; actual message
-        // starts at 4th word.
-        l4_uint32_t msg_size = shared_words[1];
-        msg->from_mbox_after_dma(shared_words + 4, shared_words[2]);
-        l4_cache_flush_data(reinterpret_cast(msg_gst),
-                            reinterpret_cast(msg_gst) + msg_size);
-        value = shared_words[0] & channel;
-        // Free the region allocated in the write() function.
-        free_shared_data(shared_offs, msg_size + 16);
-      }
-
-    return value;
-  }
-
-  void write(unsigned reg, char size, l4_umword_t value, unsigned /* cpu_id */)
-  {
-    trace.printf("\033[32mBcm2835::write offset=%02x size=%u value=%0lx\033[m\n",
-                 reg, size, value);
-    if (size != 2)
-      L4Re::throw_error(-L4_EINVAL, "Can only handle 32-bit writes");
-
-    if (reg == Mbox1_write)
-      {
-        l4_uint32_t msg_gst_phys_addr =
-          (static_cast(value) & ~Channel_mask) - _dma_offset;
-        l4_uint32_t channel = value & Channel_mask;
-        Vmm::Guest_addr msg_gst_phys{msg_gst_phys_addr};
-        auto const *msg_gst = _ram->guest2host(msg_gst_phys);
-        auto const *msg = reinterpret_cast const *>(msg_gst);
-        l4_uint32_t msg_size = msg->hdr.bytes;
-        // Allocate a region on the shared data for this request. The guest can
-        // performs multiple requests in parallel. Freeing is done in the read()
-        // function.
-        // The +16 is for storing the physical letter address before the letter!
-        l4_size_t shared_offs = alloc_shared_data(msg_size + 16);
-        l4_uint8_t *shared_addr =
-          static_cast(_data_virt + shared_offs);
-        l4_uint32_t *shared_words = reinterpret_cast(shared_addr);
-        // Remember physical letter address, entire size and "out size".
-        shared_words[0] = value & ~Channel_mask;
-        shared_words[1] = msg_size;
-        shared_words[2] = msg->tag.size_out;
-        // Copy letter content from guest RAM to shared area; actual message
-        // starts at 4th word.
-        msg->to_mbox_before_dma(shared_words + 4);
-        value = (shared_offs + 16) | channel;
-      }
-
-    _regs[reg] = value;
-  }
-
-private:
-  // Need to access mailbox data from the guest address space.
-  Vmm::Vm_ram *_ram;
-  // IRQ server to forward the IRQ from the external mbox device to the guest.
-  cxx::Ref_ptr _irq;
-  // DMA offset
-  l4_uint64_t _dma_offset = 0xc0000000ULL;
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    // Use a dedicated vbus capability because the mbox service implements the
-    // vbus protocol -- like the IO server.
-    auto cap = Vdev::get_cap(node, "l4vmm,vbus-dev");
-    if (!cap)
-      return nullptr;
-
-    auto c = Vdev::make_device(cap, devs->ram().get(), devs, node);
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node, 0);
-    return c;
-  }
-};
-
-static F f;
-static Vdev::Device_type t = { "brcm,bcm2835-mbox", nullptr, &f };
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/cfi.cc b/src/l4/pkg/uvmm/server/src/device/cfi.cc
deleted file mode 100644
index 6950b2f0..00000000
--- a/src/l4/pkg/uvmm/server/src/device/cfi.cc
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "mmio_device.h"
-
-namespace {
-
-/**
- * Simple CFI compliant flash with Intel command set.
- *
- * Example device tree:
- *
- * \code{.dtb}
- *   flash@ffc00000 {
- *       compatible = "cfi-flash";
- *       reg = <0x0 0xffc00000 0x0 0x84000>;
- *       l4vmm,dscap = "capname";
- *       erase-size = <0x10000>; // must be power of two
- *       bank-width = <4>;
- *       device-width = <2>; // optional, equal to bank-width by default
- *   };
- * \endcode
- *
- * 'bank-width' configures the total bus width of the flash (in bytes).
- * It is typically equal to the 'device-width', unless multiple flash chips
- * share the bus. In this case 'device-width' refers to the width of a single
- * chip. The example above configures a 32-bit wide flash that consists of
- * two 16-bit chips.
- *
- * The optional "read-only" property will make the device read-only. If the
- * dataspace 'capname' is read-only but the 'read-only' property is not set,
- * this emulation will make the flash device read-only as well (but give a
- * warning about it).
- *
- * How to make the dscap writable:
- * 1. Load the bootmodule (modules.list):
- *    module OVMF_VARS.fd :rw
- * 2. Add the bootmodule to the caps table of uvmm:
- *    uvmm_caps = {
- *      capname = L4.Env.rwfs:query("OVMF_VARS.fd", 7),
- *    }
- *    L4.Env.loader:startv(caps=uvmm_caps, "rom/uvmm")
- *
- * Notes about the CFI emulation.
- * - CFI operates in either read or write-mode
- * - in read-mode the flash acts like RAM and Linux will use the full
- *   instruction set to read it(*)
- * - in write mode Linux handles the device like an MMIO device
- * - read-mode is emulated by mapping the DS in read-only fashion to the guest
- * - if switched to write mode, we unmap the DS and emulate individual accesses
- * (*) Full emulation of read-mode would not be very performant and
- *     require a full instruction decoder, which --for x86-- we do not have
- *     and do not want.
- * - multiple chips emulated on the same bus (bank-width != device-width)
- *   are not independent: they must always receive the same commands
- */
-class Cfi_flash
-: public Vmm::Mmio_device,
-  public Vdev::Device
-{
-  enum
-  {
-    Cmd_write_byte = 0x10,
-    Cmd_block_erase = 0x20,
-    Cmd_write_byte2 = 0x40,
-    Cmd_clear_status = 0x50,
-    Cmd_read_status = 0x70,
-    Cmd_read_device_id = 0x90,
-    Cmd_cfi_query = 0x98,
-    Cmd_program_erase_suspend = 0xb0,
-    Cmd_block_confirm = 0xd0,
-    Cmd_write_block = 0xe8,
-    Cmd_read_array = 0xff,
-
-    Status_ready = 1 << 7,
-    Status_erase_error = 1 << 5,
-    Status_program_error = 1 << 4,
-
-    Cfi_table_size = 0x40,
-    Block_buffer_shift = 10, // 1 KiB
-    Block_buffer_size = 1 << Block_buffer_shift,
-  };
-
-public:
-  Cfi_flash(L4::Cap ds, l4_addr_t base, size_t size,
-            size_t erase_size, bool ro, unsigned int bank_width,
-            unsigned int device_width)
-  : _base(base), _size(size), _erase_size(erase_size), _ro(ro),
-    _bank_width(bank_width), _device_width(device_width)
-  {
-    unsigned int chip_shift = 8 * sizeof(unsigned int)
-                              - __builtin_clz(bank_width / device_width) - 1;
-    _mgr = cxx::make_unique("Cfi_flash", ds, 0, _size,
-                                             ro ? L4Re::Rm::F::R : L4Re::Rm::F::RW);
-
-    // Fill CFI table. See JESD6801...
-    _cfi_table[0x10] = 'Q';
-    _cfi_table[0x11] = 'R';
-    _cfi_table[0x12] = 'Y';
-    _cfi_table[0x13] = 0x01; // Intel command set
-    _cfi_table[0x15] = 0x31; // Address of "PRI" below
-    // Typical/maximum timeout for buffer write in 2^n
-    // This must be set because all zero means "not supported"
-    _cfi_table[0x20] = 1; // 2us
-    _cfi_table[0x24] = 1; // 4us (2^1 multiplied by typical time above)
-    _cfi_table[0x27] = 8 * sizeof(unsigned long) - __builtin_clzl(_size - 1U)
-                       - chip_shift;
-    // Block buffer size in 2^n (divided by number of chips)
-    auto block_buf_shift = Block_buffer_shift - chip_shift;
-    _cfi_table[0x2a] = cxx::min(block_buf_shift, device_width * 8);
-    _cfi_table[0x2c] = 1; // one erase block region
-
-    // Erase block region 1 (our only one)
-    size_t num_blocks = (_size + erase_size - 1U) / erase_size;
-    _cfi_table[0x2d] = num_blocks - 1U;
-    _cfi_table[0x2e] = (num_blocks - 1U) >> 8;
-    // Divide erase size by number of chips
-    erase_size >>= chip_shift;
-    _cfi_table[0x2f] = erase_size >> 8;
-    _cfi_table[0x30] = erase_size >> 16;
-
-    // Intel Primary Algorithm Extended Query Table
-    _cfi_table[0x31] = 'P';
-    _cfi_table[0x32] = 'R';
-    _cfi_table[0x33] = 'I';
-    _cfi_table[0x34] = '1';
-    _cfi_table[0x35] = '0';
-
-    info().printf("CFI flash (size %zu, %s, bank width: %u, device width: %u, erase size = %zu)\n",
-                  _size, _ro ? "ro" : "rw", _bank_width, _device_width, _erase_size);
-  }
-
-  ~Cfi_flash()
-  {}
-
-  int access(l4_addr_t pfa, l4_addr_t offset, Vmm::Vcpu_ptr vcpu,
-             L4::Cap vm_task, l4_addr_t, l4_addr_t) override
-  {
-    auto insn = vcpu.decode_mmio();
-
-    if (insn.access == Vmm::Mem_access::Store)
-      {
-        write(vm_task, offset, insn.width, insn.value);
-        return Vmm::Jump_instr;
-      }
-    else if (_cmd == Cmd_read_array)
-      {
-        map_mem_ro(vm_task);
-        return Vmm::Retry;
-      }
-    else if (insn.access == Vmm::Mem_access::Load)
-      {
-        insn.value = read(offset, insn.width);
-        vcpu.writeback_mmio(insn);
-        return Vmm::Jump_instr;
-      }
-    else
-      {
-        warn().printf("MMIO access @ 0x%lx: unknown instruction. Ignored.\n",
-                      pfa);
-        return -L4_ENXIO;
-      }
-  }
-
-  void map_eager(L4::Cap, Vmm::Guest_addr, Vmm::Guest_addr) override
-  {}
-
-  char const *dev_name() const override { return _mgr->dev_name(); }
-
-private:
-  void set_mode(L4::Cap vm_task, uint8_t cmd)
-  {
-    if (_cmd == Cmd_read_array && cmd != Cmd_read_array)
-      unmap_mem(vm_task);
-
-    _cmd = cmd;
-
-    // Proactively map the flash memory, to avoid instruction decoding on reads.
-    if (cmd == Cmd_read_array)
-      map_mem_ro(vm_task);
-  }
-
-  void map_mem_ro(L4::Cap vm_task)
-  {
-    auto local = reinterpret_cast(local_addr());
-    map_guest_range(vm_task, Vmm::Guest_addr(_base), local, _size, L4_FPAGE_RX);
-  }
-
-  void unmap_mem(L4::Cap vm_task)
-  {
-    unmap_guest_range(vm_task, Vmm::Guest_addr(_base), _size);
-  }
-
-  char *local_addr() const
-  { return _mgr->local_addr(); }
-
-  l4_size_t mapped_size() const
-  { return _mgr->size(); }
-
-  l4_umword_t device_mask() const
-  { return ~0UL >> ((sizeof(l4_umword_t) - _device_width) * 8); }
-
-  l4_umword_t chip_shift(l4_umword_t device_val, char size)
-  {
-    // Duplicate the device value shifted for the other chips on the same bus
-    l4_umword_t val = 0;
-    for (auto shift = 0U; shift < _bank_width; shift += _device_width)
-      val |= device_val << (shift * 8);
-    // Clear bits not visible for the access width
-    return Vmm::Mem_access::read(val, 0, size);
-  }
-
-  bool check_chip_shift(l4_umword_t val)
-  {
-    auto device_val = val & device_mask();
-    for (auto shift = _device_width; shift < _bank_width; shift += _device_width)
-      {
-        if (device_val != ((val >> (shift * 8)) & device_mask()))
-          {
-            Err().printf("Invalid command: 0x%lx, must be the same for all chips\n", val);
-            return false;
-          }
-      }
-    return true;
-  }
-
-  l4_umword_t read(unsigned reg, char size)
-  {
-    if (reg + (1U << size) > _size)
-      return -1;
-
-    switch (_cmd)
-      {
-      case Cmd_read_array:
-        {
-          auto addr = reinterpret_cast(local_addr() + reg);
-          return Vmm::Mem_access::read_width(addr, size);
-        }
-      case Cmd_read_device_id:
-        // Currently not implemented. Add once needed.
-        return 0;
-      case Cmd_cfi_query:
-        {
-          if (reg % _bank_width)
-            {
-              warn().printf("Unaligned read of CFI query: 0x%x\n", reg);
-              return 0;
-            }
-          reg /= _bank_width;
-
-          // Calculate number of elements to be read from the CFI query.
-          // Multiple elements are read when the access width is larger than
-          // the bank width. Rounding up is necessary in case a smaller access
-          // width is used (e.g. 8-bit reads on a 32-bit flash).
-          auto nregs = ((1U << size) + _bank_width - 1) / _bank_width;
-          if (reg + nregs > sizeof(_cfi_table))
-            return 0;
-
-          // Fill the value using the _cfi_table...
-          l4_umword_t val = 0;
-          for (auto i = 0U; i < nregs; i++)
-            val |= _cfi_table[reg + i] << (i * _bank_width * 8);
-          // ... and duplicate it for all chips
-          return chip_shift(val, size);
-        }
-      default:
-        // read status
-        return chip_shift(_status, size);
-      }
-  }
-
-  void write(L4::Cap vm_task, unsigned reg, char size, l4_umword_t value)
-  {
-    if (reg + (1U << size) > _size)
-      return;
-
-    l4_uint8_t cmd = value;
-    switch (_cmd)
-      {
-      case Cmd_write_byte:
-      case Cmd_write_byte2:
-        if (_ro)
-          _status |= Status_program_error;
-        else
-          {
-            auto addr = reinterpret_cast(local_addr() + reg);
-            auto before = Vmm::Mem_access::read_width(addr, size);
-            Vmm::Mem_access::write_width(addr, before & value, size);
-          }
-        _status |= Status_ready;
-        set_mode(vm_task, Cmd_read_status);
-        break;
-      case Cmd_block_erase:
-        if (!check_chip_shift(value))
-          {
-            _status |= Status_program_error | Status_erase_error;
-            return;
-          }
-        switch (cmd)
-          {
-            case Cmd_block_confirm:
-              _status |= Status_ready;
-              if (_ro)
-                _status |= Status_erase_error;
-              else
-                {
-                  reg &= ~(_erase_size - 1U);
-                  memset(local_addr() + reg, 0xff, _erase_size);
-                }
-              break;
-            default:
-              info().printf("Invalid command after Cmd_block_erase: 0x%02x\n",
-                            cmd);
-              _status |= Status_program_error | Status_erase_error;
-              return;
-          }
-        set_mode(vm_task, Cmd_read_status);
-        break;
-
-      case Cmd_write_block:
-        if (!write_block(vm_task, reg, size, value))
-          {
-            _status |= Status_program_error;
-            set_mode(vm_task, Cmd_read_status);
-          }
-        break;
-
-      case Cmd_read_status:
-      case Cmd_read_device_id:
-      case Cmd_cfi_query:
-      case Cmd_read_array:
-      case Cmd_program_erase_suspend:
-        trace().printf("Command 0x%02x @ %u\n", cmd, reg);
-        if (!check_chip_shift(value))
-          return;
-        switch (cmd)
-          {
-          case Cmd_clear_status:
-            _status = 0;
-            break;
-          case Cmd_program_erase_suspend:
-            _status |= Status_ready;
-            [[fallthrough]];
-          case Cmd_write_byte:
-          case Cmd_write_byte2:
-          case Cmd_block_erase:
-          case Cmd_read_status:
-          case Cmd_read_device_id:
-          case Cmd_cfi_query:
-          case Cmd_read_array:
-            set_mode(vm_task, cmd);
-            break;
-          case Cmd_write_block:
-            if (_ro)
-              {
-                _status |= Status_program_error;
-                break;
-              }
-            _buf_len = 0;
-            _status |= Status_ready;
-            set_mode(vm_task, cmd);
-            break;
-          default:
-            warn().printf("Unsupported command: %02x\n", cmd);
-            break;
-          }
-        break;
-      }
-  }
-
-  bool write_block(L4::Cap vm_task, unsigned reg, char size, l4_umword_t value)
-  {
-    if (!_buf_len)
-      { // start of block write
-        if (!check_chip_shift(value))
-          return false;
-
-        auto count = (value & device_mask()) + 1; // value = words - 1
-        count *= _bank_width; // convert to bytes
-        if (count > Block_buffer_size)
-          {
-            Err().printf("Invalid block write size: %lu val 0x%lx\n", count, value);
-            return false;
-          }
-
-        _buf_len = count;
-        _buf_written = 0;
-        return true;
-      }
-
-    if (!_buf_written)
-      { // set start address on the first write
-        trace().printf("Start block write at 0x%x with %u bytes\n", reg, _buf_len);
-        if (reg + _buf_len > _size)
-          {
-            Err().printf("Block write out of bounds: 0x%x + %u\n", reg, _buf_len);
-            return false;
-          }
-        // fill temporary buffer with original values
-        // this is necessary because writes can only clear bits (bitwise AND)
-        _buf_start = reg;
-        memcpy(&_buffer, local_addr() + reg, _buf_len);
-      }
-
-    if (_buf_written >= _buf_len)
-      { // all words written, write confirmed?
-        if (!check_chip_shift(value))
-          return false;
-
-        trace().printf("Confirm buffer write with 0x%lx\n", value);
-
-        if ((value & device_mask()) != Cmd_block_confirm)
-          return false;
-
-        // write back buffer
-        memcpy(local_addr() + _buf_start, _buffer, _buf_len);
-        set_mode(vm_task, Cmd_read_status);
-        return true;
-      }
-
-    if (_buf_start <= reg && (reg + (1 << size)) <= (_buf_start + _buf_len))
-      { // write into buffer
-        auto addr = reinterpret_cast(&_buffer[reg - _buf_start]);
-        auto before = Vmm::Mem_access::read_width(addr, size);
-        Vmm::Mem_access::write_width(addr, before & value, size);
-        _buf_written += 1 << size;
-        return true;
-      }
-
-    // write out of bounds
-    trace().printf("Out of bounds write to buffer; abort: 0x%x = 0x%lx\n",
-                   reg, value);
-    return false;
-  }
-
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "CFI"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "CFI"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "CFI"); }
-
-  cxx::unique_ptr _mgr;
-  l4_addr_t _base;
-  size_t _size, _erase_size;
-  bool _ro;
-  unsigned int _bank_width, _device_width;
-
-  l4_uint8_t _cmd = Cmd_read_array;
-  l4_uint8_t _status = 0;
-
-  l4_uint8_t _cfi_table[Cfi_table_size] = { 0 };
-
-  l4_uint8_t _buffer[Block_buffer_size];
-  unsigned int _buf_start = 0;
-  unsigned int _buf_len = 0;
-  unsigned int _buf_written = 0;
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    auto warn = Dbg(Dbg::Dev, Dbg::Warn, "CFI");
-    auto dscap = Vdev::get_cap(node, "l4vmm,dscap");
-    if (!dscap)
-      {
-        warn.printf("Missing 'l4vmm,dscap' property!\n");
-        return nullptr;
-      }
-
-    l4_uint64_t base, size;
-    int res = node.get_reg_val(0, &base, &size);
-    if (res < 0)
-      {
-        warn.printf("Missing 'reg' property for node %s\n", node.get_name());
-        return nullptr;
-      }
-
-    auto erase_size = fdt32_to_cpu(*node.check_prop("erase-size", 1));
-    if (erase_size & (erase_size - 1))
-      {
-        warn.printf("erase-size must be a power of two: %u\n", erase_size);
-        return nullptr;
-      }
-
-    if (size < erase_size || size % erase_size)
-      {
-        warn.printf("Wrong device size! Must be a multiple of erase block size.\n");
-        return nullptr;
-      }
-
-    bool ro = node.has_prop("read-only");
-
-    if (!ro && !dscap->flags().w())
-      {
-        warn.printf(
-          "DT configures flash to be writable, but dataspace is read-only. "
-          "Defaulting to read-only operation.\n");
-        ro = true;
-      }
-
-    if (size > dscap->size())
-      {
-        warn.printf("Dataspace smaller than reg window. Unsupported.\n");
-        return nullptr;
-      }
-
-    auto bank_width = fdt32_to_cpu(*node.check_prop("bank-width", 1));
-    if (bank_width & (bank_width - 1) || bank_width > sizeof(l4_umword_t))
-      {
-        warn.printf("Invalid bank-width value: %u\n", bank_width);
-        return nullptr;
-      }
-
-    int prop_size;
-    auto prop = node.get_prop("device-width", &prop_size);
-    auto device_width = bank_width;
-    if (prop)
-      {
-        if (prop_size != 1)
-          {
-            warn.printf("Invalid device-width property size: %d\n", prop_size);
-            return nullptr;
-          }
-        device_width = fdt32_to_cpu(*prop);
-      }
-    if (device_width & (device_width - 1) || device_width > bank_width)
-      {
-        warn.printf("Invalid device-width value: %u\n", device_width);
-        return nullptr;
-      }
-
-    auto c = Vdev::make_device(dscap, base, size, erase_size, ro,
-                                          bank_width, device_width);
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-
-    return c;
-  }
-};
-
-}
-
-static F f;
-static Vdev::Device_type t = { "cfi-flash", nullptr, &f };
diff --git a/src/l4/pkg/uvmm/server/src/device/framebuffer.cc b/src/l4/pkg/uvmm/server/src/device/framebuffer.cc
deleted file mode 100644
index 244257cf..00000000
--- a/src/l4/pkg/uvmm/server/src/device/framebuffer.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2021-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter 
- *            Stephan Gerhold 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-
-#include "device.h"
-#include "device_factory.h"
-#include "device_tree.h"
-
-#include "ds_mmio_mapper.h"
-#include "ds_manager.h"
-#include "timer.h"
-#include "guest.h"
-
-#ifdef CONFIG_UVMM_QEMU_FW_IF
-#include "qemu_fw_cfg.h"
-#endif
-
-namespace Vdev {
-
-/**
- * Simple framebuffer device.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   simplefb {
- *       compatible = "simple-framebuffer";
- *       reg = <0x0 0xf0000000 0x0 0x1000000>;
- *       l4vmm,fbcap = "fb";
- *   };
- * \endcode
- *
- * The `l4vmm,fbcap` property is mandatory and needs to point to a capability
- * implementing an L4Re::Util::Video::Goos_fb interface. If there is no
- * capability with the given name, then the device will be disabled.
- *
- * The `reg` property is also mandatory and defines the physical address and
- * the size (in bytes) of the linear framebuffer. The size of the framebuffer
- * is updated according to the actual framebuffer properties provided by the
- * capability.
- *
- * Furthermore, the `width`, `height`, `stride` and `format` properties are
- * added to the device tree entry according to the actual framebuffer
- * properties provided by the capability.
- *
- * If the framebuffer capability does not implement the auto-refresh feature,
- * the framebuffer is actively refreshed with a refresh rate of 30 Hz. This
- * default refresh rate can be overrided by the optional `l4vmm,refresh_rate`
- * property.
- */
-class Framebuffer : public Vdev::Device,
-                    public Vdev::Timer,
-                    public L4::Ipc_svr::Timeout_queue::Timeout
-{
-public:
-  /// Default refresh rate of 30 Hz.
-  static constexpr unsigned Default_refresh_rate = 30;
-
-  /**
-   * Framebuffer device constructor.
-   *
-   * \param[in] gfb             Goos framebuffer.
-   * \param[in] width           Framebuffer width in pixels.
-   * \param[in] height          Framebuffer height in pixels.
-   * \param[in] active_refresh  If true then the framebuffer requires active
-   *                            refresh (it does not have the auto-refresh
-   *                            feature).
-   * \param[in] refresh_rate    Framebuffer refresh rate (used primarily for
-   *                            the active refresh, but could be used for other
-   *                            purposes as well). Defaults to
-   *                            #Default_refresh_rate if unspecified.
-   */
-  Framebuffer(cxx::unique_ptr gfb,
-              unsigned long width, unsigned long height,
-              bool active_refresh,
-              unsigned refresh_rate = Default_refresh_rate) :
-    _gfb(cxx::move(gfb)), _width(width), _height(height),
-    _active_refresh(active_refresh), _refresh_rate(refresh_rate)
-  {
-    assert(_refresh_rate > 0);
-  }
-
-  ~Framebuffer() {}
-
-  /**
-   * Start the active refresh (if necessary) by enqueuing a refresh timeout.
-   */
-  void ready() override
-  {
-    if (_active_refresh)
-      enqueue_timeout(this, next_timeout_us());
-  }
-
-  /**
-   * Actively refresh the framebuffer and enqueue the next refresh timeout
-   * (if necessary).
-   */
-  void expired() override
-  {
-    _gfb->refresh(0, 0, _width, _height);
-
-    if (_active_refresh)
-      requeue_timeout(this, next_timeout_us());
-  }
-
-private:
-  enum
-  {
-    Microseconds_per_second = 1000000ULL,
-  };
-
-  /**
-   * Next absolute timeout in microseconds.
-   */
-  inline l4_kernel_clock_t next_timeout_us() const
-  {
-    assert(_active_refresh);
-
-    l4_kernel_clock_t clock = l4_kip_clock(l4re_kip());
-    l4_kernel_clock_t period = Microseconds_per_second / _refresh_rate;
-
-    return clock + period;
-  }
-
-  cxx::unique_ptr _gfb;
-  unsigned long _width;
-  unsigned long _height;
-  bool _active_refresh;
-  unsigned _refresh_rate;
-};
-} // namespace Vmm
-
-// Factory section
-namespace {
-struct {
-  const char *name;
-  L4Re::Video::Pixel_info pixel_info;
-} simplefb_formats[] = {
-  { "r5g6b5", {2, 5, 11, 6, 5, 5, 0} },
-  { "r5g5b5a1", {2, 5, 11, 5, 6, 5, 1, 1, 0} },
-  { "x1r5g5b5", {2, 5, 10, 5, 5, 5, 0} },
-  { "a1r5g5b5", {2, 5, 10, 5, 5, 5, 0, 1, 15} },
-  { "r8g8b8", {3, 8, 16, 8, 8, 8, 0} },
-  { "x8r8g8b8", {4, 8, 16, 8, 8, 8, 0} },
-  { "a8r8g8b8", {4, 8, 16, 8, 8, 8, 0, 8, 24} },
-  { "a8b8g8r8", {4, 8, 0, 8, 8, 8, 16, 8, 24} },
-  { "x2r10g10b10", {4, 10, 20, 10, 10, 10, 0} },
-  { "a2r10g10b10", {4, 10, 20, 10, 10, 10, 0, 2, 30} },
-};
-
-const char *find_simplefb_format(const L4Re::Video::Pixel_info &pixel_info)
-{
-  for (auto &f : simplefb_formats)
-    if (f.pixel_info == pixel_info)
-      return f.name;
-  return nullptr;
-}
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    int psize;
-    char const *prop = "l4vmm,fbcap";
-    char const *cap_name = node.get_prop(prop, &psize);
-    auto warn = Dbg(Dbg::Dev, Dbg::Warn, "FB");
-    if (!cap_name)
-      {
-        warn.printf("%s: Failed to get property '%s': %s\n", node.get_name(),
-                    prop, fdt_strerror(psize));
-        return 0;
-      }
-
-    l4_uint64_t fb_addr;
-    int res = node.get_reg_val(0, &fb_addr, nullptr);
-    if (res)
-      {
-        warn.printf("Invalid reg entry '%s'.reg[0]: %s\n",
-                    node.get_name(), fdt_strerror(res));
-        return 0;
-      }
-
-    auto gfb = cxx::make_unique();
-    if (auto err = gfb->init(cap_name))
-      {
-        warn.printf("fbdrv initialization failed: %s\n", l4sys_errtostr(err));
-        return 0;
-      }
-
-    L4Re::Video::Goos::Info info;
-    if (auto err = gfb->goos()->info(&info))
-      {
-        warn.printf("Failed to get framebuffer information: %s\n",
-                    l4sys_errtostr(err));
-        return 0;
-      }
-
-    L4Re::Video::View::Info fb_viewinfo = {};
-    if (auto err = gfb->view_info(&fb_viewinfo))
-      {
-        warn.printf("Failed to get view information: %s\n",
-                    l4sys_errtostr(err));
-        return 0;
-      }
-
-    l4_uint64_t fb_size = gfb->buffer()->size();
-    if (!devs->vmm()->register_framebuffer(fb_addr, fb_size, fb_viewinfo))
-      return 0;
-
-    node.update_reg_size(0, fb_size);
-    node.setprop_u32("width", fb_viewinfo.width);
-    node.setprop_u32("height", fb_viewinfo.height);
-    node.setprop_u32("stride", fb_viewinfo.bytes_per_line);
-
-    auto format = find_simplefb_format(fb_viewinfo.pixel_info);
-    if (format)
-      node.setprop_string("format", format);
-    else
-      warn.printf("Framebuffer format is unsupported by simple-framebuffer\n");
-
-    bool auto_refresh = info.auto_refresh();
-    unsigned refresh_rate = Vdev::Framebuffer::Default_refresh_rate;
-
-    // Allow to override the refresh rate by the l4vmm,refresh_rate property.
-    int refresh_size;
-    auto *refresh_prop = node.get_prop("l4vmm,refresh_rate", &refresh_size);
-    if (refresh_prop)
-      {
-        refresh_rate = node.get_prop_val(refresh_prop, refresh_size, 0);
-        if (refresh_rate == 0)
-          {
-            refresh_rate = 1;
-            warn.printf("Forcing framebuffer refresh rate to %u Hz.\n",
-                        refresh_rate);
-          }
-      }
-    else if (!auto_refresh)
-      warn.printf("Using default framebuffer refresh rate of %u Hz.\n",
-                  refresh_rate);
-
-    auto mgr = cxx::make_ref_obj("Framebuffer", gfb->buffer(),
-                                                 0, gfb->buffer()->size());
-    auto handler = Vdev::make_device(mgr);
-    auto dev = Vdev::make_device(cxx::move(gfb), info.width,
-                                                    info.height,
-                                                    !info.auto_refresh(),
-                                                    refresh_rate);
-
-    devs->vmm()->add_mmio_device(
-                   Vmm::Region::ss(Vmm::Guest_addr(fb_addr), fb_size,
-                                   Vmm::Region_type::Vbus), handler);
-    devs->vmm()->register_timer_device(dev);
-
-#ifdef CONFIG_UVMM_QEMU_FW_IF
-    struct
-    {
-      l4_uint64_t    address;
-      l4_uint32_t    width;
-      l4_uint32_t    height;
-      l4_uint32_t    bytes_per_line;
-      l4_uint32_t    bytes_per_pixel;
-      l4_uint8_t     red_size;
-      l4_uint8_t     red_shift;
-      l4_uint8_t     green_size;
-      l4_uint8_t     green_shift;
-      l4_uint8_t     blue_size;
-      l4_uint8_t     blue_shift;
-      l4_uint8_t     reserved_size;
-      l4_uint8_t     reserved_shift;
-    } ramfb_config =
-      {
-        Vmm::Guest_addr(fb_addr).get(),
-        (l4_uint32_t)fb_viewinfo.width,
-        (l4_uint32_t)fb_viewinfo.height,
-        (l4_uint32_t)fb_viewinfo.bytes_per_line,
-        fb_viewinfo.pixel_info.bytes_per_pixel(),
-        fb_viewinfo.pixel_info.r().size(),
-        fb_viewinfo.pixel_info.r().shift(),
-        fb_viewinfo.pixel_info.g().size(),
-        fb_viewinfo.pixel_info.g().shift(),
-        fb_viewinfo.pixel_info.b().size(),
-        fb_viewinfo.pixel_info.b().shift(),
-        fb_viewinfo.pixel_info.padding().size(),
-        fb_viewinfo.pixel_info.padding().shift(),
-      };
-
-    static_assert(sizeof(ramfb_config) == 8 * 4,
-                  "Size mismatch in e2dk_ramfb_config");
-    Qemu_fw_cfg::put_file("etc/ramfb", (const char *)&ramfb_config,
-                          sizeof(ramfb_config));
-#endif // CONFIG_UVMM_QEMU_FW_IF
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"simple-framebuffer", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/l4rtc.cc b/src/l4/pkg/uvmm/server/src/device/l4rtc.cc
deleted file mode 100644
index 40788f5b..00000000
--- a/src/l4/pkg/uvmm/server/src/device/l4rtc.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2021-2022, 2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * This driver retrieves wallclock time from the L4Re rtc server.
- *
- * It is optional and needs to be enabled in the configuration.
- *
- * Example device tree entry:
- *
- * \code{.dtb}
- *   external_rtc {
- *       compatible = "l4rtc";
- *       l4vmm,rtccap = "rtc";
- *   };
- * \endcode
- *
- * A capability with the name "rtc" needs to point to the rtc server. In the
- * event of the guest programming the rtc, the device model will also try to
- * set the time at the rtc server. The "rtc" cap requires 'write' permission
- * for this operation. Conversely, if the rtc server has a new wallclock time,
- * it notifies its clients. Uvmm will react to this notification by retrieving
- * the new wallclock time. There is no way to inform the guest, however.
- */
-#include "rtc-hub.h"
-#include "device_factory.h"
-#include "device.h"
-#include "guest.h"
-
-#include 
-#include 
-#include 
-#include 
-
-namespace Vdev {
-
-class External_rtc:
-  public Vdev::L4rtc_adapter,
-  public Vdev::Device,
-  public L4::Irqep_t
-{
-  L4::Cap _rtc;
-  L4::Registry_iface *_registry;
-
-public:
-  External_rtc(L4::Cap cap, L4::Registry_iface *registry)
-  : _rtc(cap), _registry(registry)
-  {
-    L4rtc_hub::register_adapter(this);
-    if (_rtc->get_timer_offset(&_ns_offset))
-      {
-        warn().printf("Could not read time from RTC server.\n");
-        _ns_offset = 0;
-      }
-
-    auto irq = L4Re::Util::make_unique_del_cap();
-    if (!irq)
-      {
-        warn().printf("Could not allocate capability for "
-                      "notification IRQ from RTC server. "
-                      "Uvmm will not be notified of new time values.\n");
-        return;
-      }
-    if (l4_error(L4Re::Env::env()->factory()->create(irq.get())))
-      {
-        warn().printf("Could not create IRQ object for notifications from "
-                      "RTC server. "
-                      "Uvmm will not be notified of new time values.\n");
-        return;
-      }
-    if (l4_error(_rtc->bind(0, irq.get())))
-      {
-        warn().printf("Could not bind IRQ to RTC server. "
-                      "Uvmm will not be notified of new time values.\n");
-        return;
-      }
-
-    auto res = registry->register_obj(this, irq.get());
-    if (!res)
-      {
-        warn().printf("Could not register RTC IRQ handler. "
-                      "Uvmm will not be notified of new time values.\n");
-        _rtc->unbind(0, irq.get());
-        return;
-      }
-
-    _irq = std::move(irq);
-  }
-
-  ~External_rtc()
-  {
-    _rtc->unbind(0, _irq.get());
-    // Do not unmap the IRQ object in unregister_obj() because we need the
-    // capability to delete the kernel object in the dtor of _irq.
-    _registry->unregister_obj(this, false);
-    // Remove a potential reference to this object.
-    L4rtc_hub::invalidate();
-  }
-
-  l4_uint64_t ns_since_epoch() override
-  {
-    return _ns_offset + l4_kip_clock_ns(l4re_kip());
-  }
-
-  void set_ns_since_epoch(l4_uint64_t ns_offset) override
-  {
-    int err;
-    _ns_offset = ns_offset - l4_kip_clock_ns(l4re_kip());
-    if ((err = _rtc->set_timer_offset(_ns_offset)))
-      trace().printf("Failed at setting the time @rtc. Errorcode %d. "
-                     "Did you add write permission to the rtc cap?\n",
-                     err);
-  }
-
-  // rtc server tells us that the time has changed
-  // e.g. a suspend/resume cycle happened or a component set a new time
-  void handle_irq()
-  {
-    if (_rtc->get_timer_offset(&_ns_offset))
-      warn().printf("Could not read time @rtc.\n");
-  }
-
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "RTC"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "RTC"); }
-
-private:
-  // offset of kip_clock to epoch (wallclock time)
-  l4_uint64_t _ns_offset;
-  L4Re::Util::Unique_del_cap _irq;
-};
-
-}
-
-namespace {
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    L4::Cap cap = Vdev::get_cap(node, "l4vmm,rtccap");
-    if (!cap)
-      {
-        Vdev::External_rtc::warn().printf("l4vmm,rtccap not valid. Will not have wallclock time.\n");
-        return nullptr;
-      }
-
-    auto dev = Vdev::make_device(cap,
-                                                     devs->vmm()->registry());
-
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Vdev::Device_type t = {"l4rtc", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/mmio_proxy.cc b/src/l4/pkg/uvmm/server/src/device/mmio_proxy.cc
deleted file mode 100644
index caecaa68..00000000
--- a/src/l4/pkg/uvmm/server/src/device/mmio_proxy.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-
-#include "device_factory.h"
-#include "mmio_space_handler.h"
-#include "ds_mmio_mapper.h"
-#include "guest.h"
-
-static Dbg warn(Dbg::Dev, Dbg::Warn, "mmio-proxy");
-
-namespace Vdev
-{
-  /**
-   * Device that proxies memory accesses to an external dataspace
-   * or mmio space.
-   *
-   * If the capability supports the dataspace protocol, the memory
-   * from the dataspace is mapped directly into the guest address space.
-   * The region(s) defined in reg must be aligned to page boundaries.
-   *
-   * For the mmio space protocol, all accesses are forwarded via IPC.
-   * Mmio spaces support arbitrary reg regions.
-   *
-   * Device tree compatible: l4vmm,l4-mmio
-   *
-   * Device tree parameters:
-   *   l4vmm,mmio-cap    - Capability that provides the dataspace or
-   *                       mmio space interface. The capability is probed
-   *                       for support of the two interfaces via the meta
-   *                       protocol. If both interfaces are available
-   *                       the dataspace protocol is used.
-   *   reg               - Regions that cover the device.
-   *   l4vmm,mmio-offset - Address in the dataspace/mmio space that
-   *                       corresponds to the first base address in `reg`.
-   *                       Default: 0.
-   *   dma-ranges        - When present, uvmm adds the physical memory addresses
-   *                       of the dataspace. If the addresses cannot be determined
-   *                       because the dataspace does not have the appropriate
-   *                       properties, then startup of uvmm fails with an error.
-   *                       Note: ranges are added, so the property should be
-   *                       initially empty.
-   *   l4vmm,physmap     - When present, export the complete dataspace starting
-   *                       from an optional `l4vmm,mmio-offset`. The `reg`
-   *                       property will be overwritten with the appropriate
-   *                       region. `dma-ranges` must not be set at the same time.
-   */
-  struct Mmio_proxy : public Device
-  {
-    friend class F;
-
-    void set_dma_space(L4Re::Util::Unique_cap &&dma)
-    { _dma = cxx::move(dma); }
-
-    /// container for DMA mapping, if applicable.
-    L4Re::Util::Unique_cap _dma;
-  };
-}
-
-namespace {
-
-using namespace Vdev;
-
-class F : public Factory
-{
-public:
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    auto cap = Vdev::get_cap(node, "l4vmm,mmio-cap");
-    if (!cap)
-      return nullptr;
-
-    auto dscap = L4::cap_dynamic_cast(cap);
-    if (dscap)
-      {
-        L4Re::Util::Unique_cap dma;
-        bool physmap = node.has_prop("l4vmm,physmap");
-
-        if (physmap || node.has_prop("dma-ranges"))
-          {
-            dma = L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                               "Create capability for DMA space for memory region.");
-
-            L4Re::chksys(L4Re::Env::env()->user_factory()->create(dma.get()),
-                         "Create DMA space for MMIO proxy region");
-
-            L4Re::chksys(dma->associate(L4::Ipc::Cap(),
-                                        L4Re::Dma_space::Phys_space),
-                         "Associate with physical address space");
-          }
-
-        auto mgr = cxx::make_ref_obj("Mmio_proxy", dscap, 0,
-                                                      dscap->size());
-
-        if (physmap)
-          register_physmap_region(mgr, devs, node, dma.get());
-        else
-          register_mmio_regions(mgr, devs, node, dma.get());
-        auto dev = Vdev::make_device();
-        dev->set_dma_space(cxx::move(dma));
-
-        return dev;
-      }
-
-    auto mmcap = L4::cap_dynamic_cast(cap);
-    if (mmcap)
-      {
-        register_mmio_regions(mmcap, devs, node);
-        return Vdev::make_device();
-      }
-
-    warn.printf("No known IPC protocol supported.\n");
-    return nullptr;
-  }
-
-private:
-  void register_physmap_region(cxx::Ref_ptr const &mgr,
-                               Device_lookup const *devs,
-                               Dt_node const &node, L4::Cap dma)
-  {
-    l4_size_t sz = mgr->size();
-    l4_uint64_t offset = get_offset_from_node(node);
-
-    if (offset > sz)
-      L4Re::chksys(-L4_EINVAL, "l4vmm,mmio-offset outside dataspace");
-
-    sz -= offset;
-
-    auto phys = get_phys_mapping(mgr->dataspace().get(), dma,
-                                 mgr->offset() + offset,
-                                 sz, node.get_name());
-
-    node.set_reg_val(phys, sz, false);
-
-    auto handler = Vdev::make_device(mgr, L4_FPAGE_RW, offset);
-    devs->vmm()->register_mmio_device(handler, Vmm::Region_type::Ram, node, 0);
-  }
-
-  void register_mmio_regions(cxx::Ref_ptr mgr, Device_lookup const *devs,
-                             Dt_node const &node, L4::Cap dma)
-  {
-    l4_size_t dssize = mgr->size();
-    l4_uint64_t regbase, base, size;
-    l4_uint64_t offset = get_offset_from_node(node);
-    auto parent = node.parent_node();
-    size_t addr_cells = node.get_address_cells(parent);
-    size_t size_cells = node.get_size_cells(parent);
-
-    if (node.get_reg_val(0, ®base, &size) < 0)
-      L4Re::chksys(-L4_EINVAL, "reg property not found or invalid");
-
-    for (size_t index = 0; node.get_reg_val(index, &base, &size) >= 0; ++index)
-      {
-        if (base < regbase)
-          {
-            Err().printf("%s: reg%zd: %llx smaller than base of %llx\n"
-                         "Smallest address must come first in 'reg' list.\n",
-                         node.get_name(), index, base, regbase);
-            L4Re::throw_error(-L4_ERANGE,
-                              "Register list sorted in ascending order.");
-          }
-
-        l4_uint64_t sz = size;
-        l4_uint64_t offs = offset + (base - regbase);
-        if (offs + sz > dssize)
-          {
-            sz = offs < dssize ? dssize - offs : 0;
-            node.update_reg_size(index, sz);
-          }
-
-        if (sz)
-          {
-            auto handler = Vdev::make_device(mgr, L4_FPAGE_RW, offs);
-            devs->vmm()->register_mmio_device(handler, Vmm::Region_type::Virtual, node, index);
-
-            if (dma.is_valid())
-              {
-                auto phys = get_phys_mapping(mgr->dataspace().get(), dma,
-                                             mgr->offset() + offs,
-                                             sz, node.get_name());
-
-                node.appendprop("dma-ranges", phys, addr_cells);
-                node.appendprop("dma-ranges", base, addr_cells);
-                node.appendprop("dma-ranges", sz, size_cells);
-              }
-          }
-      }
-  }
-
-  void register_mmio_regions(L4::Cap cap,
-                             Device_lookup const *devs, Dt_node const &node)
-  {
-    l4_uint64_t regbase, base, size;
-    l4_uint64_t offset = get_offset_from_node(node);
-
-    if (node.get_reg_val(0, ®base, &size) < 0)
-      L4Re::chksys(-L4_EINVAL, "reg property not found or invalid");
-
-    for (size_t index = 0; node.get_reg_val(index, &base, &size) >= 0; ++index)
-      {
-        if (base < regbase)
-          {
-            Err().printf("%s: reg%zd: %llx smaller than base of %llx\n"
-                         "Smallest address must come first in 'reg' list.\n",
-                         node.get_name(), index, base, regbase);
-            L4Re::throw_error(-L4_ERANGE,
-                              "Register list sorted in ascending order.");
-          }
-
-        l4_uint64_t offs = offset + (base - regbase);
-
-        if (size)
-          {
-            auto handler = Vdev::make_device(cap, 0, size, offs);
-            devs->vmm()->register_mmio_device(handler, Vmm::Region_type::Virtual, node, index);
-          }
-      }
-  }
-
-  static L4Re::Dma_space::Dma_addr get_phys_mapping(L4::Cap cap,
-                                                    L4::Cap dma,
-                                                    l4_addr_t offset, l4_size_t size,
-                                                    char const *node_name)
-  {
-    L4Re::Dma_space::Dma_addr phys_ram;
-    l4_size_t phys_size = size;
-    long err = dma->map(L4::Ipc::make_cap(cap, L4_CAP_FPAGE_RW),
-                        offset, &phys_size,
-                        L4Re::Dma_space::Attributes::None,
-                        L4Re::Dma_space::Bidirectional, &phys_ram);
-
-    if (err < 0)
-      {
-        Err().printf("%s: Cannot resolve physical address of dataspace. "
-                     "Dataspace needs to be contiguous.\n",
-                     node_name);
-        L4Re::chksys(err, "Resolve physical address of dataspace.");
-      }
-    else if (phys_size < size)
-      {
-        Err().printf("%s: Cannot resolve physical address of complete area. "
-                     "Dataspace not contiguous.\n"
-                     "(dataspace size = 0x%zx, contiguous size = 0x%zx).\n",
-                     node_name, size, phys_size);
-        L4Re::chksys(-L4_ENOMEM, "Resolve dma-range of dataspace.");
-      }
-
-    return phys_ram;
-  }
-
-
-  static l4_size_t get_offset_from_node(Dt_node const &node)
-  {
-    int propsz;
-    auto *prop = node.get_prop("l4vmm,mmio-offset", &propsz);
-
-    if (prop)
-      return node.get_prop_val(prop, propsz, true);
-
-    return 0;
-  }
-};
-
-
-static F f;
-static Device_type t = { "l4vmm,l4-mmio", nullptr, &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/optee.cc b/src/l4/pkg/uvmm/server/src/device/optee.cc
deleted file mode 100644
index 4ccd8f31..00000000
--- a/src/l4/pkg/uvmm/server/src/device/optee.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-
-#include "device_factory.h"
-#include "ds_mmio_mapper.h"
-#include "guest.h"
-#include "irq_dt.h"
-#include "irq_svr.h"
-#include "smccc_device.h"
-
-namespace {
-
-Dbg info(Dbg::Dev, Dbg::Info, "optee");
-Dbg warn(Dbg::Dev, Dbg::Warn, "optee");
-Dbg trace(Dbg::Dev, Dbg::Warn, "optee");
-
-/**
- * Provides an interface to the OP-TEE secure OS.
- *
- * The device maps the static shared memory to the appropriate address
- * that is advertised by the SMC interface and forwards any trapped SMC
- * via IPC.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   firmware {
- *       optee {
- *           compatible = "linaro,optee-tz";
- *           method = "smc";
- *           l4vmm,cap = "smccc";
- *           l4vmm,dscap = "vbus";
- *           interrupts = <0 140 4>;
- *       };
- *   };
- * \endcode
- *
- * `l4vmm,cap` is mandatory and needs to point to a capability providing
- * an L4::Arm_smccc interface. If there is no capability with the given name
- * the device will be disabled.
- *
- * The optional `l4vmm,dscap` may point to an alternative provider of the
- * static shared memory. If omitted, memory will be mapped from `l4vmm,cap`.
- *
- * To give direct access to Optee to a VM, set `l4vmm,cap` to the smccc
- * capability provided by Fiasco and point `l4vmm,dscap` to an appropriately
- * configured IO. When using a proxy, set `l4vmm,cap` only.
- */
-class Optee : public Vdev::Device, public Vmm::Smccc_device
-{
-  enum
-  {
-    Smc_call_trusted_os_uid      = 0xbf00ff01,
-    Smc_call_trusted_os_revision = 0xbf00ff03,
-    Optee_call_get_shm_config    = 0xb2000007,
-    Optee_call_exchange_caps     = 0xb2000009,
-
-    Optee_uuid_word0 = 0x384fb3e0,
-    Optee_uuid_word1 = 0xe7f811e3,
-    Optee_uuid_word2 = 0xaf630002,
-    Optee_uuid_word3 = 0xa5d5c51b,
-
-    Optee_api_major = 2,
-    Optee_api_minor = 0
-  };
-
-public:
-  Optee(L4::Cap optee) : _optee(optee) {}
-
-  bool vm_call(unsigned imm, Vmm::Vcpu_ptr vcpu) override
-  {
-    if (imm != 0)
-      return false;
-
-    if (   _optee.is_valid()
-        && is_valid_func_id(vcpu->r.r[0]))
-      {
-        _optee->call(vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3],
-                     vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6],
-                     &vcpu->r.r[0], &vcpu->r.r[1], &vcpu->r.r[2], &vcpu->r.r[3], 0);
-        return true;
-      }
-    return false;
-  }
-
-  int map_optee_memory(Vmm::Guest *vmm, L4::Cap iods)
-  {
-    l4_umword_t p[4] = {};
-
-    // check for OP-TEE OS
-    long ret = fast_call(Smc_call_trusted_os_uid, p);
-
-    if (ret < 0 || p[0] != Optee_uuid_word0 || p[1] != Optee_uuid_word1 ||
-        p[2] != Optee_uuid_word2 || p[3] != Optee_uuid_word3)
-      {
-        warn.printf("OP-TEE not running.\n");
-        return -L4_ENODEV;
-      }
-
-    // check for correct API version
-    ret = fast_call(Smc_call_trusted_os_revision, p);
-
-    if (ret < 0 || p[0] != Optee_api_major || p[1] != Optee_api_minor)
-      {
-        warn.printf("OP-TEE has wrong API (%ld.%ld). Need %x.%x.\n",
-                    p[0], p[1], Optee_api_major, Optee_api_minor);
-        return -L4_EINVAL;
-      }
-
-    // check if OP-TEE exports memory
-    ret = fast_call(Optee_call_exchange_caps, p);
-
-    if (ret < 0 || p[0] != 0 || !(p[1] & 1))
-      {
-        warn.printf("OP-TEE does not export shared memory.\n");
-        return -L4_ENODEV;
-      }
-
-    // get the memory area
-    ret = fast_call(Optee_call_get_shm_config, p);
-
-    if (ret < 0 || p[0] != 0)
-      {
-        warn.printf("Failed to get shared memory configuration.\n");
-        return -L4_ENODEV;
-      }
-
-    trace.printf("OP-TEE start = 0x%lx  size = 0x%lx\n", p[1], p[2]);
-    auto handler = Vdev::make_device(
-        cxx::make_ref_obj("Optee", iods, p[1], p[2])
-      );
-    // XXX should check that the resource is actually available
-    vmm->add_mmio_device(Vmm::Region(Vmm::Guest_addr(p[1]),
-                                     Vmm::Guest_addr(p[1] + p[2] - 1),
-                                     Vmm::Region_type::Virtual), handler);
-
-    return L4_EOK;
-  }
-
-  void set_notification_irq(cxx::Ref_ptr &&irq)
-  { _irq = std::move(irq); }
-
-private:
-  long fast_call(l4_umword_t func, l4_umword_t out[])
-  {
-    return l4_error(_optee->call(func, 0, 0, 0, 0, 0, 0,
-                                 out, out + 1, out + 2, out + 3, 0));
-  }
-
-  bool is_valid_func_id(l4_umword_t reg) const
-  {
-    // Check this is in the trusted application/OS range
-    reg &= 0x3f00ffff;
-    return (reg >= 0x30000000 && reg <= 0x3f00ffff);
-  }
-
-  L4::Cap _optee;
-  cxx::Ref_ptr _irq;
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    info.printf("Create OP-TEE device\n");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,cap");
-    if (!cap)
-      return nullptr;
-
-    auto dscap = Vdev::get_cap(node, "l4vmm,dscap", cap);
-    if (!dscap)
-      return nullptr;
-
-    auto c = Vdev::make_device(cap);
-    if (c->map_optee_memory(devs->vmm(), dscap) < 0)
-      return nullptr;
-
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) >= 0)
-      {
-        auto icu = L4::cap_dynamic_cast(cap);
-
-        if (icu)
-          {
-            if (!it.ic_is_virt())
-              L4Re::chksys(-L4_EINVAL, "OP-TEE device requires a virtual interrupt controller");
-
-            // XXX Using a standard IO interrupt here. Possibly better to
-            // write our own non-masking irq svr.
-            auto irq_svr =
-              cxx::make_ref_obj(devs->vmm()->registry(), icu, 0,
-                                               it.ic(), it.irq());
-
-            c->set_notification_irq(std::move(irq_svr));
-          }
-        else
-          // When no proxy is used, there is also no notification available.
-          // So it is not necessarily an error, when no ICU can be found.
-          warn.printf("SMC device does not support notification interrupts.\n");
-      }
-
-    Vmm::Guest::Smccc_method smccc_method = Vmm::Guest::Smc;
-    char const *method = node.get_prop("method", nullptr);
-    if (method)
-      {
-        if (strcmp(method, "hvc") == 0)
-          smccc_method = Vmm::Guest::Hvc;
-        else if (strcmp(method, "smc") != 0)
-          warn.printf("Method '%s' is not supported. Must be hvc or smc!\n",
-                      method);
-      }
-
-    info.printf("Register OP-TEE device: %s mode\n",
-                smccc_method == Vmm::Guest::Hvc ? "hvc" : "smc");
-
-    devs->vmm()->register_vm_handler(smccc_method, c);
-
-    return c;
-  }
-};
-
-}
-
-static F f;
-static Vdev::Device_type t = { "linaro,optee-tz", nullptr, &f };
diff --git a/src/l4/pkg/uvmm/server/src/device/pci_bridge_windows.h b/src/l4/pkg/uvmm/server/src/device/pci_bridge_windows.h
deleted file mode 100644
index 231bc9d4..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pci_bridge_windows.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "device_tree.h"
-#include "debug.h"
-#include "pci_device.h"
-
-namespace Vdev { namespace Pci {
-
-/**
- * Allocator for a consecutive range of a PCI window resource.
- */
-class Pci_window_alloc
-{
-public:
-  enum : unsigned
-  {
-    Invalid_addr = 0xf ///< Unaligned address, never allocated
-  };
-
-  Pci_window_alloc() = default;
-
-  Pci_window_alloc(l4_addr_t base, l4_size_t size)
-  : _base(base), _size(size), _free_addr(base)
-  {}
-
-  /**
-   * Initialize allocator with area to manage.
-   */
-  void init(l4_addr_t base, l4_size_t size, char const *type_info)
-  {
-    _base = base;
-    _size = size;
-    _free_addr = _base;
-    info().printf("Init PCI window with range [0x%lx, 0x%lx %s]\n", _base,
-                  end(), type_info);
-  }
-
-  /**
-   * Allocate a consecutive chunk of memory from the MMIO resource window.
-   *
-   * \param size   Size of the allocation.
-   *
-   * \return `Invalid_addr` if the allocation failed, otherwise a valid address.
-   *
-   * Allocations must be naturally aligned and the size must be power of 2.
-   * Sub-page allocations and alignments are rounded up.
-   */
-  l4_addr_t alloc_mmio(l4_size_t size)
-  {
-    if (_base == Invalid_addr) // allocator not initialized
-      return Invalid_addr;
-
-    // at least 4KB allocations
-    auto rounded_size = l4_round_page(size);
-    // make sure the size is always power of 2 and return order
-    auto order = cxx::arith::log2u_ceil(rounded_size);
-
-    return alloc(l4_round_size(_free_addr, order), size);
-  }
-
-  /**
-   * Allocate a consecutive chunk of IO ports from the IO resource window.
-   *
-   * \param size   Size of the allocation.
-   *
-   * \return `Invalid_addr` if the allocation failed, otherwise a valid IO port.
-   *
-   * Allocations adhere to the PCI BAR size and alignmnet requirements.
-   */
-  l4_addr_t alloc_io(l4_size_t size)
-  {
-    if (_base == Invalid_addr) // allocator not initialized
-      return Invalid_addr;
-
-    // check for power of two alignment and compute the next aligned size.
-    while ((size & (size - 1)) != 0)
-      ++size;
-
-    // Pad the start addr to be size aligned.
-    unsigned align = 0;
-    while ((((size >> align) & 1) == 0))
-      ++align;
-
-    return alloc(l4_round_size(_free_addr, align), size);
-  }
-
-  /// Return a tuple (start, size) describing the allocator area.
-  std::pair area() const
-  { return {_base, _size}; }
-
-  /// Free an area described by `start` and `size`.
-  // TODO void free(l4_addr_t start, l4_size_t size);
-
-  /// dump current memory status
-  void dump_state(char const *type_info) const
-  {
-    warn()
-      .printf("State[%s]: base 0x%lx, first free address 0x%lx, end 0x%lx\n",
-              type_info, _base, _free_addr, end());
-  }
-
-private:
-  static Dbg warn() { return Dbg(Dbg::Pci, Dbg::Warn, "Pci_window_alloc"); }
-  static Dbg info() { return Dbg(Dbg::Pci, Dbg::Info, "Pci_window_alloc"); }
-  static Dbg trace() { return Dbg(Dbg::Pci, Dbg::Trace, "Pci_window_alloc"); }
-
-  /// compute the inclusive end of the area
-  l4_addr_t end() const { return _base + _size - 1; }
-
-  /**
-   * Allocate a consecutive chunk from the resource window.
-   *
-   * \param start  Aligned allocation start address.
-   * \param size   Aligned allocation size request.
-   *
-   * \return `Invalid_addr` if the allocation failed, otherwise a valid
-   *         allocation start address.
-   */
-  l4_addr_t alloc(l4_addr_t start, l4_size_t size)
-  {
-    l4_addr_t alloc_end = start + size - 1;
-    if (alloc_end > end())
-      return Invalid_addr;
-
-    l4_addr_t ret = start;
-    _free_addr = alloc_end + 1;
-    return ret;
-  };
-
-  // assumptions: single-threaded, consecutive allocation, no free
-  l4_addr_t _base = Invalid_addr;
-  l4_addr_t _size = Invalid_addr;
-  l4_addr_t _free_addr = Invalid_addr;
-};
-
-/**
- * Manager for all types of PCI bridge window resources.
- *
- * This class parses the DT node of the PCI bridge and sets up all resource
- * windows. This is currently limited to one window per resource type.
- * If multiple resource windows of the same type are specified in th DT node,
- * the last resource window is selected.
- */
-class Pci_bridge_windows
-{
-  enum Type
-  {
-    MMIO32 = Pci_cfg_bar::Type::MMIO32,
-    MMIO64 = Pci_cfg_bar::Type::MMIO64,
-    IO = Pci_cfg_bar::Type::IO
-  };
-
-public:
-  Pci_bridge_windows(Dt_node const &node)
-  {
-    init_bridge_window(node);
-  }
-
-  /**
-   * Retrieve bridge MMIO and I/O windows from ranges property.
-   */
-  void init_bridge_window(Dt_node const &node)
-  {
-    int prop_size;
-    auto prop = node.get_prop("ranges", &prop_size);
-    if (!prop)
-      L4Re::throw_error(-L4_EINVAL,
-                        "PCI bridge: Missing ranges property in DT node");
-
-    auto parent = node.parent_node();
-    size_t parent_addr_cells = node.get_address_cells(parent);
-    size_t child_addr_cells = node.get_address_cells(node);
-    size_t child_size_cells = node.get_size_cells(node);
-
-    unsigned range_size =
-      child_addr_cells + parent_addr_cells + child_size_cells;
-    if (prop_size % range_size != 0)
-      {
-        Err().printf("Ranges property size: %i, Range entry size %u, "
-                     "#child cells %zu, #parent cells %zu, #size cells %zu\n",
-                     prop_size, range_size, child_addr_cells, parent_addr_cells,
-                     child_size_cells);
-        L4Re::throw_error(-L4_EINVAL,
-                          "PCI bridge: Invalid ranges property: Property size not a multiple of entry size.");
-      }
-
-    for (auto end = prop + prop_size; prop < end; prop += range_size)
-      {
-        auto flags = Dtb::Reg_flags::pci(fdt32_to_cpu(*prop));
-        Dtb::Cell dt_parent_base(prop + child_addr_cells, parent_addr_cells);
-        Dtb::Cell dt_size(prop + child_addr_cells + parent_addr_cells,
-                       child_size_cells);
-
-        l4_uint64_t base = dt_parent_base.get_uint64();
-        l4_uint64_t size = dt_size.get_uint64();
-        if (flags.is_mmio32())
-          _mmio_alloc.init(base, size, type_to_str(Type::MMIO32));
-        else if (flags.is_mmio64())
-          _mmio64_alloc.init(base, size, type_to_str(Type::MMIO64));
-        else if (flags.is_ioport())
-          _io_alloc.init(base, size, type_to_str(Type::IO));
-      }
-  }
-
-
-  /**
-   * Request the area description of the resource window of Type `t`.
-   *
-   * \param t  Type of the window resource.
-   *
-   * \return  A tuple (base, size) describing the window area.
-   */
-  std::pair get_window(Pci_cfg_bar::Type t) const
-  {
-    Type type = to_type(t);
-
-    std::pair ret;
-    ret = window(type).area();
-    return ret;
-  }
-
-  /**
-   * Allocate a `size` chunk within a resouce window of type `t`.
-   *
-   * \param size  Size of the allocation.
-   * \param t     Type of the resource window to allocate from.
-   *
-   * \return Base address of the new allocation or zero in case of failure.
-   */
-  l4_addr_t alloc_bar_resource(l4_size_t size, Pci_cfg_bar::Type t)
-  {
-    Type type = to_type(t);
-    unsigned constexpr Invalid_addr = Pci_window_alloc::Invalid_addr;
-
-    l4_addr_t ret = alloc_type(window(type), type, size);
-
-    if (ret == Invalid_addr)
-      {
-        Err().printf("Allocation of type '%s' for 0x%zx bytes failed.\n",
-                     type_to_str(type), size);
-        window(type).dump_state(type_to_str(type));
-        L4Re::throw_error(-L4_ENOMEM, "PCI bridge: Not enough free memory in PCI window.");
-      }
-
-    info().printf("[%s] allocated [0x%lx, 0x%lx]\n", type_to_str(type), ret,
-                  ret + size - 1);
-    return ret;
-  }
-
-private:
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "Pci_bridge_windows"); }
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "Pci_bridge_windows"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "Pci_bridge_windows"); }
-
-  static char const *type_to_str(Type t)
-  {
-    switch(t)
-      {
-      case Type::MMIO32: return "MMIO32";
-      case Type::MMIO64: return "MMIO64";
-      case Type::IO: return "IO";
-      default: return "Invalid Type";
-      }
-  }
-
-  static Type to_type(Pci_cfg_bar::Type t)
-  {
-    switch(t)
-      {
-      case Pci_cfg_bar::Type::MMIO32: return Type::MMIO32;
-      case Pci_cfg_bar::Type::MMIO64: return Type::MMIO64;
-      case Pci_cfg_bar::Type::IO: return Type::IO;
-      default: L4Re::throw_error(-L4_ERANGE, "Invalid PCI MMIO window type.");
-      }
-  }
-
-  l4_addr_t alloc_type(Pci_window_alloc &win, Type t, l4_size_t size)
-  {
-    if (t == Type::IO)
-      return win.alloc_io(size);
-    else
-      return win.alloc_mmio(size);
-  }
-
-  Pci_window_alloc &window(Type type)
-  {
-    switch(type)
-      {
-      case Type::MMIO32: return _mmio_alloc;
-      case Type::MMIO64: return _mmio64_alloc;
-      case Type::IO: return _io_alloc;
-      default: L4Re::throw_error(-L4_ERANGE, "Invalid PCI MMIO window type.");
-      }
-  }
-
-  Pci_window_alloc const &window(Type type) const
-  {
-    switch(type)
-      {
-      case Type::MMIO32: return _mmio_alloc;
-      case Type::MMIO64: return _mmio64_alloc;
-      case Type::IO: return _io_alloc;
-      default: L4Re::throw_error(-L4_ERANGE, "Invalid PCI MMIO window type.");
-      }
-  }
-
-  /// IO window, maximum size 16bit
-  Pci_window_alloc _io_alloc;
-  /// maximum size 32bit, non-prefetchable
-  Pci_window_alloc _mmio_alloc;
-  /// maximum size min(64bit, HW addressable bits), prefetchable
-  Pci_window_alloc _mmio64_alloc;
-}; // class Pci_bridge_windows
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/device/pci_bus_cfg_ecam.h b/src/l4/pkg/uvmm/server/src/device/pci_bus_cfg_ecam.h
deleted file mode 100644
index 7979db90..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pci_bus_cfg_ecam.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Georg Kotheimer 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "pci_host_bridge.h"
-
-namespace Vdev { namespace Pci {
-
-/**
- * Interface to handle ECAM access to the PCI configuration space and
- * translate it to an internal protocol.
- */
-class Pci_bus_cfg_ecam : public Vmm::Mmio_device_t
-{
-private:
-  /**
-   * ECAM configuration space offset.
-   *
-   * This allows decoding of raw configuration space offsets into bus/device id's,
-   * function number and register offsets.
-   */
-  struct Cfg_addr
-  {
-    l4_uint32_t raw = 0;
-    CXX_BITFIELD_MEMBER(20, 31, bus, raw);  /// Bus id
-    CXX_BITFIELD_MEMBER(15, 19, dev, raw);  /// Device id
-    CXX_BITFIELD_MEMBER(12, 14, func, raw); /// Function number
-    CXX_BITFIELD_MEMBER( 0, 11, reg, raw);  /// Register offset
-
-    explicit Cfg_addr(l4_uint32_t r) : raw(r) {}
-  };
-
-public:
-  Pci_bus_cfg_ecam(cxx::Ref_ptr const &bus) : _bus(bus) {}
-
-  /**
-   * Read PCI configuration space.
-   *
-   * Device 0 is always the virtual host controller. Access to other regions is
-   * forwarded to the corresponding device.
-   */
-  l4_uint32_t read(unsigned reg, char width, unsigned)
-  {
-    Cfg_addr cfg(reg);
-    if (cfg.bus().get() > 0 || cfg.func().get() > 0)
-      return -1U;
-    return _bus->cfg_space_read(cfg.dev().get(), cfg.reg().get(),
-                                (Vmm::Mem_access::Width)width);
-  }
-
-  /**
-   * Write PCI configuration space.
-   *
-   * Device 0 is always the virtual host controller. Access to other regions is
-   * forwarded to the corresponding device.
-   */
-  void write(unsigned reg, char width, l4_uint32_t val, unsigned)
-  {
-    Cfg_addr cfg(reg);
-    if (cfg.bus().get() > 0 || cfg.func().get() > 0)
-      return;
-    _bus->cfg_space_write(cfg.dev().get(), cfg.reg().get(),
-                          (Vmm::Mem_access::Width)width, val);
-  }
-
-  char const *dev_name() const override { return "Pci_bus_cfg_ecam"; }
-
-  cxx::Ref_ptr _bus;
-};
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/device/pci_host_bridge.cc b/src/l4/pkg/uvmm/server/src/device/pci_host_bridge.cc
deleted file mode 100644
index 2950520b..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pci_host_bridge.cc
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * Copyright (C) 2021-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-
-#include "pci_host_bridge.h"
-#include "mem_access.h"
-#include "pci_device.h"
-#include "ds_mmio_mapper.h"
-#include "ds_mmio_handling.h"
-#include "msi_memory.h"
-#include "io_port_handler.h"
-
-namespace Vdev { namespace Pci {
-
-bool
-parse_bus_range(Dt_node const &node, unsigned char *start, unsigned char *end)
-{
-  auto info = Dbg(Dbg::Dev, Dbg::Info, "PCI bus");
-  auto trace = Dbg(Dbg::Dev, Dbg::Trace, "PCI bus");
-
-  int sz;
-  if (!node.has_prop("bus-range"))
-    {
-      info.printf("Bus range not specified in device tree.\n");
-      return false;
-    }
-
-  auto bus_range = node.get_prop("bus-range", &sz);
-  if (sz != 2)
-    {
-      info.printf("Bus range property of Pci_host_bridge has invalid size\n");
-      return false;
-    }
-
-  *start = (l4_uint8_t)fdt32_to_cpu(bus_range[0]);
-  *end = (l4_uint8_t)fdt32_to_cpu(bus_range[1]);
-
-  trace.printf("Init host bridge: Found 'bus-range' 0x%x - 0x%x\n",
-               *start, *end);
-
-  return true;
-}
-
-void
-Pci_host_bridge::Hw_pci_device::add_decoder_resources(Vmm::Guest *,
-                                                      l4_uint32_t access)
-{
-  int bir = has_msix ? msix_cap.tbl.bir()
-                     : Pci_config_consts::Bar_num_max_type0;
-
-  for (int i = 0; i < Pci_config_consts::Bar_num_max_type0; ++i)
-    {
-      switch (bars[i].type)
-        {
-        case Pci_cfg_bar::Type::IO:
-          if (Vmm::Guest::Has_io_space && access & Io_space_bit)
-            add_io_bar_resources(bars[i]);
-          break;
-
-        case Pci_cfg_bar::Type::MMIO32:
-        case Pci_cfg_bar::Type::MMIO64:
-          if (!(access & Memory_space_bit))
-            break;
-
-          if (i == bir)
-            add_msix_bar_resources(bars[i]);
-          else
-            add_mmio_bar_resources(bars[i]);
-          break;
-
-        default: break;
-        }
-    }
-
-  if (access & Memory_space_bit && exp_rom.virt_enabled)
-    add_exp_rom_resource();
-}
-
-l4_size_t
-Legacy_irq_router::amend_dsdt_with_prt(void *buf, l4_size_t max_size) const
-{
-  // _PRT table prefix.
-  unsigned char dsdt_prt_prefix[] = {
-    /* 0x00 */ 0x10,
-    /* 0x01 */ 0xc0, 0x00, 0x00, 0x00, // Total size
-    /* 0x05 */ 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x50,
-    /* 0x0b */ 0x43, 0x49, 0x30, 0x08, 0x5f, 0x50, 0x52, 0x54,
-    /* 0x13 */ 0x13,
-    /* 0x14 */ 0xc0, 0x00, 0x00, 0x00, // Package size
-    /* 0x18 */ 0x0b,
-    /* 0x19 */ 0x00, 0x00 // Count
-  };
-
-  // _PRT table entry.
-  unsigned char dsdt_prt_entry[] = {
-    // Package
-    /* 0x00 */ 0x12, 0x0f, 0x04, 0x0c,
-    /* 0x04 */ 0x00, 0x00, 0x00, 0x00, // Address
-    /* 0x08 */ 0x0a,
-    /* 0x09 */ 0x00, // Pin
-    /* 0x0a */ 0x00, // Source (zero constant)
-    /* 0x0b */ 0x0c,
-    /* 0x0c */ 0x00, 0x00, 0x00, 0x00 // Global System Interrupt
-  };
-
-  auto count = _routes.size();
-  if (count > 0xffffU)
-    L4Re::throw_error(-L4_ENOMEM,
-                      "Too many entries in DSDT _PRT ACPI table.");
-
-  l4_size_t prefix_size = sizeof(dsdt_prt_prefix);
-  l4_size_t entry_size = sizeof(dsdt_prt_entry);
-  l4_size_t entries_size = entry_size * count;
-
-  if (max_size < prefix_size + entries_size)
-    L4Re::throw_error(-L4_ENOMEM,
-                      "Not enough space in DSDT ACPI table for _PRT table.");
-
-  // Update _PRT table prefix. The size fields are computed relative to
-  // their own offset. See ACPI Specification, Revision 6.5, Section 5.4.1 (AML
-  // Encoding).
-  encode_pkg_length_4b(dsdt_prt_prefix + 0x01,
-                       prefix_size + entries_size - 0x01);
-  encode_pkg_length_4b(dsdt_prt_prefix + 0x14,
-                       prefix_size + entries_size - 0x14);
-  *reinterpret_cast(&dsdt_prt_prefix[0x19]) = count;
-
-  unsigned char *output = static_cast(buf);
-
-  std::memcpy(output, &dsdt_prt_prefix, prefix_size);
-  output += prefix_size;
-
-  // Update table entries.
-  for (auto const &i : _routes)
-    {
-      // PCI device address has the form of 0xnnnnFFFF where nnnn is the PCI
-      // device ID.
-      *reinterpret_cast(&dsdt_prt_entry[0x04])
-        = 0xffffU | (std::get<1>(i.first) << 16);
-
-      // Contrary to the PCI Configuration Space, the _PRT entries encode the
-      // PCI interrupt pins as zero-based.
-      dsdt_prt_entry[0x09] = std::get<2>(i.first) - 1;
-
-      // Guest IRQ as Global System Interrupt.
-      *reinterpret_cast(&dsdt_prt_entry[0x0c]) = i.second;
-
-      std::memcpy(output, &dsdt_prt_entry, entry_size);
-      output += entry_size;
-    }
-
-  return prefix_size + entries_size;
-}
-
-void Pci_host_bridge::Hw_pci_device::add_exp_rom_resource()
-{
-  auto region =
-    Vmm::Region::ss(Vmm::Guest_addr(exp_rom.map_addr), exp_rom.size,
-                    Vmm::Region_type::Vbus, Vmm::Region_flags::Moveable);
-  info().printf("Register expansion ROM region: [0x%lx, 0x%lx], vbus base "
-                "0x%llx\n",
-                region.start.get(), region.end.get(), exp_rom.io_addr);
-
-  auto m = cxx::make_ref_obj("Pci_host_bridge: rom",
-                                         parent->_vbus->io_ds(),
-                                         exp_rom.io_addr, exp_rom.size);
-  parent->_vmm->add_mmio_device(region, make_device(m));
-}
-
-void
-Pci_host_bridge::Hw_pci_device::add_io_bar_resources(Pci_cfg_bar const &bar)
-{
-  Vmm::Guest_addr addr(bar.map_addr);
-  l4_size_t size = bar.size;
-  auto region = Vmm::Io_region::ss(addr.get(), size, Vmm::Region_type::Vbus,
-                                   Vmm::Region_flags::Moveable);
-  warn().printf("Register IO region: [0x%lx, 0x%lx], vbus base 0x%llx\n",
-                region.start, region.end, bar.io_addr);
-
-  l4vbus_resource_t res;
-  res.type = L4VBUS_RESOURCE_PORT;
-  res.start = bar.io_addr;
-  res.end = res.start + size - 1U;
-  res.provider = 0;
-  res.id = 0;
-  L4Re::chksys(parent->_vbus->bus()->request_ioport(&res),
-               "Request IO port resource from vBus.");
-  parent->_vmm->add_io_device(region,
-                              make_device(bar.io_addr));
-}
-
-void
-Pci_host_bridge::Hw_pci_device::add_mmio_bar_resources(Pci_cfg_bar const &bar)
-{
-  Vmm::Guest_addr addr(bar.map_addr);
-  l4_size_t size = bar.size;
-  auto region = Vmm::Region::ss(addr, size, Vmm::Region_type::Vbus,
-                                Vmm::Region_flags::Moveable);
-  warn().printf("Register MMIO region: [0x%lx, 0x%lx], vbus base 0x%llx\n",
-                region.start.get(), region.end.get(), bar.io_addr);
-
-  auto m = cxx::make_ref_obj("Pci_host_bridge: mmio bar",
-                                         parent->_vbus->io_ds(), bar.io_addr,
-                                         size);
-  parent->_vmm->add_mmio_device(region, make_device(m));
-}
-
-/**
- * Add MMIO resources of the BAR that holds the MSI-X table.
- *
- * Usually the BAR does not only hold the MSIX-table but other resources too.
- * Everything in the BAR before and after the table is mapped pass-through to
- * the guest. If the table is not page aligned the affected parts of the pages
- * are trapped and forwarded.
- *
- * The virtual MSI-X table is always registered, even if the bridge lacks a
- * virtual MSI-X controller. The guest might still access the MSI-X table
- * and we must support that even though the interrupt will not be deliverd.
- */
-void
-Pci_host_bridge::Hw_pci_device::add_msix_bar_resources(Pci_cfg_bar const &bar)
-{
-  unsigned max_msis = msix_cap.ctrl.max_msis() + 1;
-  unsigned table_offset = msix_cap.tbl.offset();
-
-  // the virtual MSI-X table
-  l4_addr_t msix_table_start = bar.map_addr + table_offset;
-  l4_addr_t msix_table_size = max_msis * Msix::Entry_size;
-
-  // whole pages mapped to guest at start of BAR
-  l4_addr_t before_pages_start = bar.map_addr;
-  l4_addr_t before_pages_size = l4_trunc_page(table_offset);
-
-  // partial page mapped to guest immediately before MSI-X table
-  l4_addr_t before_partial_start = before_pages_start + before_pages_size;
-  l4_addr_t before_partial_size = msix_table_start - before_partial_start;
-
-  // whole pages mapped to guest at end of BAR
-  l4_addr_t after_pages_start = l4_round_page(msix_table_start + msix_table_size);
-  l4_addr_t after_pages_size = bar.size - (after_pages_start - bar.map_addr);
-
-  // partial page mapped to guest immediately after MSI-X table
-  l4_addr_t after_partial_start = msix_table_start + msix_table_size;
-  l4_addr_t after_partial_size = after_pages_start - after_partial_start;
-
-  // now add everything
-
-  cxx::Ref_ptr m;
-  if (before_pages_size || after_pages_size)
-    m = cxx::make_ref_obj("Pci_host_bridge: io mem",
-                                           parent->_vbus->io_ds(),
-                                           bar.io_addr, bar.size);
-
-  if (before_pages_size)
-    {
-      auto region = Region::ss(Vmm::Guest_addr(before_pages_start),
-                               before_pages_size, Vmm::Region_type::Vbus,
-                               Vmm::Region_flags::Moveable);
-      warn().printf("Register MMIO region in MSI-X bar: [0x%lx, 0x%lx]\n",
-                    region.start.get(), region.end.get());
-      parent->_vmm->add_mmio_device(region, make_device(m));
-    }
-
-  if (before_partial_size)
-    {
-      auto region = Region::ss(Vmm::Guest_addr(before_partial_start),
-                               before_partial_size, Vmm::Region_type::Vbus,
-                               Vmm::Region_flags::Moveable);
-      warn().printf("Register MMIO region in MSI-X bar: [0x%lx, 0x%lx]\n",
-                    region.start.get(), region.end.get());
-      auto con = make_device(msix_table_page_mgr, 0);
-      parent->_vmm->add_mmio_device(region, con);
-    }
-
-  auto region = Region::ss(Vmm::Guest_addr(msix_table_start), msix_table_size,
-                           Vmm::Region_type::Vbus, Vmm::Region_flags::Moveable);
-  warn().printf("Register MSI-X MMIO table: [0x%lx, 0x%lx]\n",
-                region.start.get(), region.end.get());
-  parent->_vmm->add_mmio_device(region, msix_table);
-
-  if (after_partial_size)
-    {
-      auto region = Region::ss(Vmm::Guest_addr(after_partial_start),
-                               after_partial_size, Vmm::Region_type::Vbus,
-                               Vmm::Region_flags::Moveable);
-      warn().printf("Register MMIO region in MSI-X bar: [0x%lx, 0x%lx]\n",
-                    region.start.get(), region.end.get());
-      l4_addr_t mgr_offset = after_partial_start - before_partial_start;
-      auto con = make_device(msix_table_page_mgr, mgr_offset);
-      parent->_vmm->add_mmio_device(region, con);
-    }
-
-  if (after_pages_size)
-    {
-      auto region = Region::ss(Vmm::Guest_addr(after_pages_start),
-                               after_pages_size, Vmm::Region_type::Vbus,
-                               Vmm::Region_flags::Moveable);
-      warn().printf("Register MMIO region in MSI-X bar: [0x%lx, 0x%lx]\n",
-                    region.start.get(), region.end.get());
-      l4_addr_t mgr_offset = after_pages_start - before_pages_start;
-      parent->_vmm->add_mmio_device(region,
-                                    make_device(m, L4_FPAGE_RW,
-                                                            mgr_offset));
-    }
-}
-
-void
-Pci_host_bridge::Hw_pci_device::del_decoder_resources(Vmm::Guest *,
-                                                      l4_uint32_t access)
-{
-  int bir = has_msix ? msix_cap.tbl.bir()
-                     : Pci_config_consts::Bar_num_max_type0;
-
-  for (int i = 0; i < Pci_config_consts::Bar_num_max_type0; ++i)
-    {
-      switch (bars[i].type)
-        {
-        case Pci_cfg_bar::Type::IO:
-          if (Vmm::Guest::Has_io_space && access & Io_space_bit)
-            del_io_bar_resources(bars[i]);
-          break;
-
-        case Pci_cfg_bar::Type::MMIO32:
-        case Pci_cfg_bar::Type::MMIO64:
-          if (!(access & Memory_space_bit))
-            break;
-
-          if (i == bir)
-            del_msix_bar_resources(bars[i]);
-          else
-            del_mmio_bar_resources(bars[i]);
-          break;
-
-        default: break;
-        }
-    }
-
-  if (access & Memory_space_bit && exp_rom.virt_enabled)
-    del_exp_rom_resource();
-}
-
-void Pci_host_bridge::Hw_pci_device::del_exp_rom_resource()
-{
-  auto region =
-    Vmm::Region::ss(Vmm::Guest_addr(exp_rom.map_addr), exp_rom.size,
-                    Vmm::Region_type::Virtual, Vmm::Region_flags::Moveable);
-  info().printf("Removing expansion ROM region: [0x%lx, 0x%lx]\n",
-                region.start.get(), region.end.get());
-
-  parent->_vmm->del_mmio_device(region);
-}
-
-void
-Pci_host_bridge::Hw_pci_device::del_io_bar_resources(Pci_cfg_bar const &bar)
-{
-  auto region = Vmm::Io_region::ss(bar.map_addr, bar.size,
-                                   Vmm::Region_type::Vbus);
-  warn().printf("Unregister IO region: [0x%lx, 0x%lx]\n",
-                region.start, region.end);
-  parent->_vmm->del_io_device(region);
-}
-
-void
-Pci_host_bridge::Hw_pci_device::del_mmio_bar_resources(Pci_cfg_bar const &bar)
-{
-  auto region = Vmm::Region::ss(Vmm::Guest_addr(bar.map_addr), bar.size,
-                                Vmm::Region_type::Vbus);
-  warn().printf("Unregister MMIO region: [0x%lx, 0x%lx]\n",
-                region.start.get(), region.end.get());
-  parent->_vmm->del_mmio_device(region);
-}
-
-void
-Pci_host_bridge::Hw_pci_device::del_msix_bar_resources(Pci_cfg_bar const &bar)
-{
-  auto region = Region::ss(Vmm::Guest_addr(bar.map_addr), bar.size,
-                           Vmm::Region_type::Vbus);
-  warn().printf("Unregister MSI-X bar MMIO region: [0x%lx, 0x%lx]\n",
-                region.start.get(), region.end.get());
-  parent->_vmm->del_mmio_devices(region);
-}
-
-bool Pci_host_bridge::Hw_pci_device::msi_cap_read(unsigned reg,
-                                                  l4_uint32_t *value,
-                                                  Vmm::Mem_access::Width width)
-{
-  if (reg < msi_cap.offset || reg >= msi_cap.cap_end())
-    return false;
-
-  unsigned offset = reg - msi_cap.offset;
-  trace().printf("msi_cap_read: devid = 0x%x offset = 0x%x width = %d\n",
-                 dev_id, offset, width);
-
-  // guard against multiple threads accessing the device
-  std::lock_guard lock(_mutex);
-
-  bool sixtyfour = msi_cap.ctrl.sixtyfour();
-  switch (offset)
-    {
-    case 0x0:
-      if (width <= Vmm::Mem_access::Width::Wd16)
-        // access only to non-emulated part, forward to hardware
-        break;
-      else
-        {
-          // read lower 16 bits from hardware
-          l4_uint32_t val;
-          L4Re::chksys(dev.cfg_read(reg, &val, mem_access_to_bits(width)),
-                       "PCI MSI cap access: read");
-          // and combine with emulated upper 16 bits.
-          *value = (msi_cap.ctrl.raw << 16) | (val & 0xffff);
-          return true;
-        }
-    case 0x2:
-      *value = msi_cap.ctrl.raw;
-      return true;
-
-    case 0x4:
-      *value = msi_cap.address;
-      return true;
-
-    case 0x8:
-      if (sixtyfour)
-        *value = msi_cap.upper_address;
-      else
-        *value = msi_cap.data;
-      return true;
-
-    case 0xc:
-      if (sixtyfour)
-        {
-          *value = msi_cap.data;
-          return true;
-        }
-      // mask bits or non-existent
-      break;
-
-    default:
-      // Forward to hardware. No register that we emulate.
-      break;
-    }
-
-  return false;
-}
-
-void
-Pci_host_bridge::Hw_pci_device::msi_cap_write_ctrl(l4_uint16_t ctrl)
-{
-  bool was_enabled = msi_cap.ctrl.msi_enable();
-  msi_cap.write_ctrl(ctrl);
-
-  if (!was_enabled && msi_cap.ctrl.msi_enable())
-    {
-      if (parent->_msi_src_factory)
-        {
-          info().printf("MSI enabled: devid = 0x%x, ctrl = 0x%x\n", dev_id,
-                        msi_cap.ctrl.raw);
-          l4_icu_msi_info_t msiinfo;
-          msi_src = parent->_msi_src_factory
-            ->configure_msi_route(msi_cap, parent->msix_dest(dev_id),
-                                  src_id(), &msiinfo);
-          if (msi_src)
-            cfg_space_write_msi_cap(&msiinfo);
-        }
-      else
-        warn().printf("MSI enabled, but bridge lacks support: devid = 0x%x "
-                      "ctrl = 0x%x.\n Your device will probably not work!\n",
-                      dev_id, msi_cap.ctrl.raw);
-    }
-  else if (was_enabled && !msi_cap.ctrl.msi_enable())
-    {
-      if (parent->_msi_src_factory)
-        cfg_space_write_msi_cap();
-      msi_src = nullptr;
-
-      trace().printf("MSI disabled: devid = 0x%x ctrl = 0x%x\n", dev_id,
-                     msi_cap.ctrl.raw);
-    }
-}
-
-bool Pci_host_bridge::Hw_pci_device::msi_cap_write(unsigned reg,
-                                                   l4_uint32_t value,
-                                                   Vmm::Mem_access::Width width)
-{
-  if (reg < msi_cap.offset || reg >= msi_cap.cap_end())
-    return false;
-
-  unsigned offset = reg - msi_cap.offset;
-  trace().printf("msi_cap_write: devid = 0x%x offset = 0x%x width = %d value = 0x%x\n",
-                 dev_id, offset, width, value);
-  if (   (width == Vmm::Mem_access::Width::Wd8 && offset != 0)
-      || (offset % (mem_access_to_bits(width) / 8) != 0))
-    warn().printf("Unaligned or partial write to MSI cap fields not supported. "
-                  "State might become inconsistent.\n");
-
-  // guard against multiple threads accessing the device
-  std::lock_guard lock(_mutex);
-
-  bool sixtyfour = msi_cap.ctrl.sixtyfour();
-  bool per_vector_mask = msi_cap.ctrl.per_vector_masking();
-  bool consume_write = true;
-  switch (offset)
-    {
-    case 0x0:
-      if (width <= Vmm::Mem_access::Width::Wd16)
-        // access only to non-emulated part, forward to hardware
-        consume_write = false;
-      else
-        {
-          // write lower 16 bits to hardware
-          L4Re::chksys(dev.cfg_write(reg, value & 0xffff, 16),
-                       "PCI MSI cap access: write");
-
-          msi_cap_write_ctrl(value >> 16);
-        }
-      break;
-
-    case 0x2:
-      {
-        msi_cap_write_ctrl(value);
-        break;
-      }
-
-    case 0x4: // message address
-      msi_cap.address = value;
-      break;
-
-    case 0x8:
-      if (sixtyfour)
-        msi_cap.upper_address = value;
-      else
-        msi_cap.data = value;
-      break;
-
-    case 0xc:
-      if (sixtyfour)
-        msi_cap.data = value;
-      else if (per_vector_mask)
-        consume_write = false; // mask bits
-      break;
-
-    case 0x10:
-      if (sixtyfour && per_vector_mask)
-        consume_write = false; // mask bits
-      else if (!sixtyfour && per_vector_mask)
-        warn().printf("write to RO field: pending bits. Ignored\n");
-      break;
-
-    case 0x14:
-      warn().printf("write to RO field: pending bits. Ignored\n");
-      break;
-
-    default:
-      warn().printf("Write to unhandled MSI CAP register: devid = 0x%x offset "
-                    "= 0x%x width = %d value = 0x%x\n",
-                    dev_id, offset, width, value);
-      break;
-    }
-
-  return consume_write;
-}
-
-void Pci_host_bridge::Hw_pci_device::cfg_space_write_msi_cap(
-  l4_icu_msi_info_t *msiinfo)
-{
-  unsigned msi_cap_addr = msi_cap.offset;
-
-  if (msiinfo)
-    {
-      trace().printf("msi address: 0x%llx, data 0x%x\n", msiinfo->msi_addr,
-                     msiinfo->msi_data);
-
-      // write MSI address
-      L4Re::chksys(dev.cfg_write(msi_cap_addr + 0x4,
-                                 static_cast(msiinfo->msi_addr),
-                                 32),
-                   "Write HW PCI device MSI cap message address");
-
-      // write MSI data
-      unsigned data_addr =
-        msi_cap_addr + (msi_cap.ctrl.sixtyfour() ? 0xC : 0x8);
-      L4Re::chksys(dev.cfg_write(data_addr, msiinfo->msi_data, 16),
-                   "Write HW PCI device MSI cap message data");
-
-      // write MSI upper address
-      if (msi_cap.ctrl.sixtyfour())
-        L4Re::chksys(dev.cfg_write(msi_cap_addr + 0x8,
-                                   static_cast(msiinfo->msi_addr
-                                                            >> 32),
-                                   32),
-                     "Write HW PCI device MSI cap upper message address");
-    }
-
-  // write MSI control
-  L4Re::chksys(dev.cfg_write(msi_cap_addr + 0x2, msi_cap.ctrl.raw, 16),
-               "Write HW PCI device MSI cap ctrl.");
-}
-
-void Pci_host_bridge::Hw_pci_device::setup_msix_table()
-{
-  if (!has_msix)
-    return;
-
-  unsigned bir = msix_cap.tbl.bir();
-  if (bir < Pci_config_consts::Bar_num_max_type0)
-    {
-      Gic::Msix_dest _msix_dest = parent->msix_dest(dev_id);
-      if (!_msix_dest.is_present())
-        warn().printf(
-          "No MSI-X controller available for MSI-X device %s (devid=%u).\n",
-          dinfo.name, dev_id);
-
-      unsigned max_msis = msix_cap.ctrl.max_msis() + 1;
-      unsigned table_size = max_msis * Msix::Entry_size;
-
-      // Cover MSI-X table with page granularity
-      l4_addr_t io_table_addr =
-        bars[bir].io_addr + msix_cap.tbl.offset();
-      l4_addr_t io_table_ds_base = l4_trunc_page(io_table_addr);
-      l4_addr_t io_table_ds_size =
-        l4_round_page(io_table_addr + table_size) - io_table_ds_base;
-
-      msix_table_page_mgr =
-        cxx::make_ref_obj(parent->_vbus->io_ds(),
-                                         io_table_ds_base, io_table_ds_size);
-      auto con =
-        make_device(msix_table_page_mgr,
-                                       io_table_addr - io_table_ds_base);
-
-      msix_table = make_device(
-        std::move(con), cxx::static_pointer_cast(parent->_vbus),
-        parent->_vmm->registry(), src_id(), max_msis, _msix_dest);
-    }
-  else
-    warn().printf("Device %s (devid=%u) has invalid MSI-X bar: %u\n",
-                  dinfo.name, dev_id, bir);
-}
-
-bool Pci_host_bridge::Hw_pci_device::sriov_cap_read(unsigned reg,
-                                                    l4_uint32_t *value,
-                                                    Vmm::Mem_access::Width width)
-{
-  if (reg < sriov_cap.offset || reg >= sriov_cap.cap_end())
-    return false;
-
-  unsigned offset = reg - sriov_cap.offset;
-  trace().printf("sriov_cap_read: devid = 0x%x offset = 0x%x width = %d\n",
-                 dev_id, offset, width);
-
-  switch (offset)
-    {
-    case 0x12: // Fcn Dep Link
-      // If a PF is independent from other PFs of a Device, this field shall
-      // contain its own Function Number. The function number on hardware
-      // differs from the one we assigned to the device on our virtual PCI bus,
-      // so we have to emulate the register.
-      // We do not support device function, therefore the following shift
-      // accounts for the 3 bits allocated for the function number.
-      *value = dev_id << 3;
-      return true;
-
-    default:
-      // Forward to hardware. No register that we emulate.
-      break;
-    }
-
-  return false;
-}
-
-void Pci_host_bridge::Hw_pci_device::map_additional_iomem_resources(
-  Vmm::Guest *vmm, L4::Cap io_ds)
-{
-  for (unsigned i = 0; i < dinfo.num_resources; ++i)
-    {
-      l4vbus_resource_t res;
-      L4Re::chksys(dev.get_resource(i, &res), "Cannot get vbus resource.");
-
-      // we only handle iomem resources
-      if (res.type != L4VBUS_RESOURCE_MEM)
-        continue;
-
-      unsigned mmio_space_rw =
-        L4VBUS_RESOURCE_F_MEM_MMIO_READ | L4VBUS_RESOURCE_F_MEM_MMIO_WRITE;
-      bool is_mmio_space = res.flags & mmio_space_rw;
-
-      // we only handle mmio resources (not spaces)
-      if (is_mmio_space)
-        continue;
-
-      auto size = res.end - res.start + 1;
-      // we only handle resources that are not handled via PCI BARs
-      bool is_pci_bar = false;
-      for (unsigned j = 0; j < Bar_num_max_type0; ++j)
-        {
-          if (bars[j].type == Pci_cfg_bar::Unused_empty
-              || bars[j].type == Pci_cfg_bar::Reserved_mmio64_upper
-              || bars[j].type == Pci_cfg_bar::IO)
-            continue;
-          if (res.start == bars[j].io_addr && size == bars[j].size)
-            is_pci_bar = true;
-        }
-      if (is_pci_bar)
-        continue;
-
-      // ignore ROM resource. If supported the expansion ROM BAR is
-      // already set up.
-      if (res.id == 0x4d4f52) // "ROM"
-        continue;
-
-      // Default to 1:1 mapping of additional resources, e.g. for i915.
-      l4_addr_t map_addr = res.start;
-
-      info().printf("Additional MMIO resource %s.%.4s : "
-                    "[0x%lx - 0x%lx] -> [0x%lx, 0x%lx] flags = 0x%x\n",
-                    dinfo.name, reinterpret_cast(&res.id),
-                    res.start, res.end, map_addr, map_addr + size - 1,
-                    res.flags);
-
-      auto region = Vmm::Region::ss(Vmm::Guest_addr(map_addr), size,
-                                    Vmm::Region_type::Vbus);
-      l4_uint32_t rights = 0;
-      if (res.flags & L4VBUS_RESOURCE_F_MEM_R)
-        rights |= L4_FPAGE_RO;
-      if (res.flags & L4VBUS_RESOURCE_F_MEM_W)
-        rights |= L4_FPAGE_W;
-      auto rm_flags = static_cast(rights);
-      if (res.flags & L4VBUS_RESOURCE_F_MEM_CACHEABLE)
-        rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_normal;
-      else if (res.flags & L4VBUS_RESOURCE_F_MEM_PREFETCHABLE)
-        rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_buffered;
-      else
-        rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_uncached;
-      auto ds_mgr = cxx::make_ref_obj(
-        "Pci_host_bridge: additional IO mem", io_ds, res.start, size, rm_flags);
-      auto handler = Vdev::make_device(
-        ds_mgr, static_cast(rights));
-      vmm->add_mmio_device(region, handler);
-    }
-}
-}} // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/device/pci_host_bridge.h b/src/l4/pkg/uvmm/server/src/device/pci_host_bridge.h
deleted file mode 100644
index fabf1492..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pci_host_bridge.h
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * Copyright (C) 2021-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Christian Pötzsch 
- *            Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "virt_bus.h"
-#include "irq_svr.h"
-#include "guest.h"
-#include "pci_device.h"
-#include "virt_pci_device.h"
-#include "msi.h"
-#include "msi_controller.h"
-#include "msi_memory.h"
-#include "ds_mmio_handling.h"
-#include "pci_bridge_windows.h"
-
-namespace Vdev { namespace Pci {
-
-/**
- * PCI legacy interrupt to guest IRQ forwarder.
- *
- * Forwards L4Re interrupts to an Vmm::Irq_sink. We cannot just forward vbus
- * interrupts directly to guest interrupts via Vdev::Irq_svr because:
- *
- *   - There might be multiple devices sharing the same IRQ on the vbus vicu.
- *     We can only bind once to the vicu interrupt.
- *   - There might be multiple devices that are mapped to the same guest IRQ
- *     by the interrupt-map. These devices do not necessarily share the same
- *     IRQ on the vicu!
- *
- * Effectively this amounts to an n:m mapping. When acknowledging interrupts we
- * can rely on the fact that all are level triggered. If interrupt sources are
- * acknowledged incorrectly, they will re-trigger immediately.
- */
-class Legacy_irq_router
-{
-  class Guest_pci_irq;
-
-  class Host_pci_irq : public L4::Irqep_t
-  {
-    std::vector _sinks;
-    L4::Cap _eoi;
-    unsigned _irq;
-    l4_uint32_t _source_mask;
-    std::atomic _triggered = false;
-
-  public:
-    Host_pci_irq(L4Re::Util::Object_registry *registry, L4::Cap icu,
-                 unsigned host_irq, unsigned index)
-    : _irq(host_irq), _source_mask(1U << (index & 31U))
-    {
-      L4Re::chkcap(registry->register_irq_obj(this), "Cannot register IRQ");
-
-      int ret = L4Re::chksys(icu->bind(host_irq, obj_cap()),
-                             "Cannot bind to IRQ");
-      switch (ret)
-        {
-        case 0:
-          Dbg(Dbg::Dev, Dbg::Info, "irq_svr")
-            .printf("IRQ %u will be unmasked directly\n", host_irq);
-          _eoi = obj_cap();
-          break;
-        case 1:
-          Dbg(Dbg::Dev, Dbg::Info, "irq_svr")
-            .printf("IRQ %u will be unmasked at ICU\n", host_irq);
-          _eoi = icu;
-          break;
-        default:
-          L4Re::throw_error(-L4_EINVAL, "Invalid return code from bind to IRQ");
-          break;
-        }
-
-      _eoi->unmask(_irq);
-    }
-
-    void handle_irq()
-    {
-      _triggered.store(true, std::memory_order_relaxed);
-      for (auto *s : _sinks)
-        s->inject(_source_mask);
-    }
-
-    void eoi(unsigned source_mask)
-    {
-      if ((_source_mask & source_mask) == 0)
-        return;
-
-      bool has_triggered = true;
-      if (_triggered.compare_exchange_strong(has_triggered, false,
-                                             std::memory_order_relaxed))
-        _eoi->unmask(_irq);
-    }
-
-    void add_sink(Guest_pci_irq *dst)
-    {
-      for (auto *i : _sinks)
-        if (i == dst)
-          return;
-
-      _sinks.push_back(dst);
-    }
-  };
-
-  class Guest_pci_irq : public Gic::Irq_src_handler
-  {
-    std::vector _sources;
-    Vmm::Irq_sink _irq;
-    std::atomic _triggers = 0;
-
-  public:
-    /**
-     * Construct guest PCI IRQ.
-     *
-     * \param ic         Interrupt controller.
-     * \param guest_irq  Guest IRQ.
-     */
-    Guest_pci_irq(cxx::Ref_ptr const &ic, unsigned guest_irq)
-    {
-      if (ic->get_irq_src_handler(guest_irq))
-        L4Re::throw_error(-L4_EEXIST, "Bind IRQ for Guest_pci_irq object.");
-
-      _irq.rebind(ic, guest_irq);
-      _irq.set_irq_src_handler(this);
-    }
-
-    void inject(l4_uint32_t source_trigger)
-    {
-      l4_uint32_t prev_triggers =
-        _triggers.fetch_or(source_trigger, std::memory_order_relaxed);
-
-      // Inject (again) if a new source has triggered.
-      if ((prev_triggers & source_trigger) != source_trigger)
-        _irq.inject();
-    }
-
-    void eoi() override
-    {
-      _irq.ack();
-
-      l4_uint32_t triggers = _triggers.load(std::memory_order_relaxed);
-      while (!_triggers.compare_exchange_weak(triggers, 0,
-                                              std::memory_order_relaxed))
-        ;
-
-      // EOI all sources with the collected triggers. Only the affected sources
-      // will actually issue an EOI to the hardware interrupt.
-      for (auto *s : _sources)
-        s->eoi(triggers);
-    }
-
-    void add_source(Host_pci_irq *src)
-    {
-      for (auto *i : _sources)
-        if (i == src)
-          return;
-
-      _sources.push_back(src);
-    }
-  };
-
-public:
-  Legacy_irq_router(L4Re::Util::Object_registry *registry,
-                      L4::Cap icu)
-  : _registry(registry), _icu(icu)
-  {}
-
-  /**
-   * Add PCI legacy interrupt to guest IRQ forwarding route.
-   *
-   * \param host_irq   Host IRQ.
-   * \param ic         Interrupt controller.
-   * \param dev_id     PCI device ID.
-   * \param pin        PCI interrupt pin (1 = A, 2 = B, 3 = C, 4 = D).
-   * \param guest_irq  Guest IRQ.
-   */
-  void add_route(unsigned host_irq, cxx::Ref_ptr const &ic,
-                 unsigned dev_id, unsigned pin, unsigned guest_irq)
-  {
-    Host_pci_irq *source = get_source(host_irq);
-    Guest_pci_irq *sink = get_sink(ic, guest_irq);
-    unsigned guest_irq_prev = get_route(ic, dev_id, pin, guest_irq);
-
-    if (guest_irq_prev != guest_irq)
-      L4Re::throw_error(-L4_EINVAL,
-                        "Contradictory PCI legacy interrupt routing.");
-
-    source->add_sink(sink);
-    sink->add_source(source);
-  }
-
-  /**
-   * Generate the _PRT interrupt routing table for ACPI DSDT.
-   *
-   * Generate a _PRT interrupt routing table based on the PCI legacy interrupt
-   * routes. Each PCI device, interrupt pin and guest IRQ tuple generates an
-   * entry in the table. The guest IRQs are considered Global System
-   * Interrupts.
-   *
-   * See ACPI Specification, Revision 6.5, Section 6.2.13 (PCI Routing Table).
-   *
-   * The AML templates are based on the following ASL:
-   *
-   * DefinitionBlock ("_prt.aml", "DSDT", 1, "UVMM  ", "KERNKONZ", 4) {
-   *   Scope (\_SB.PCI0) {
-   *     Name(_PRT, Package{
-   *       Package{0x0FFFFFFF, 3, 0, 0x0FFAFAFA}
-   *     })
-   *   }
-   * }
-   *
-   * Conversion (save above as _prt.asl):
-   *   $ iasl _prt.aml
-   *   $ xxd -i -s 0x24 -c 8 _prt.aml
-   *
-   * However, the AML templates which are actually used here have been manually
-   * altered to use a 4-byte PkgLength encoding for the Total size (offset
-   * 0x01) and Package size (offset 0x14) fields, as well as a WordConst
-   * encoding for the Count (offset 0x19) field.
-   *
-   * \param[out] buf       Output buffer.
-   * \param      max_size  Size of the buffer in bytes.
-   *
-   * \return Number of bytes generated.
-   */
-  l4_size_t amend_dsdt_with_prt(void *buf, l4_size_t max_size) const;
-
-private:
-  Host_pci_irq *get_source(unsigned host_irq)
-  {
-    auto it = _sources.find(host_irq);
-    if (it != _sources.end())
-      return it->second.get();
-
-    auto *ret = new Host_pci_irq(_registry, _icu, host_irq, _sources.size());
-    _sources[host_irq].reset(ret);
-    return ret;
-  }
-
-  Guest_pci_irq *get_sink(cxx::Ref_ptr const &ic, unsigned guest_irq)
-  {
-    auto idx = std::make_tuple(ic.get(), guest_irq);
-    auto it = _sinks.find(idx);
-    if (it != _sinks.end())
-      return it->second.get();
-
-    auto *ret = new Guest_pci_irq(ic, guest_irq);
-    _sinks[idx].reset(ret);
-    return ret;
-  }
-
-  unsigned get_route(cxx::Ref_ptr const &ic, unsigned dev_id,
-                     unsigned pin, unsigned guest_irq)
-  {
-    auto idx = std::make_tuple(ic.get(), dev_id, pin);
-    auto it = _routes.find(idx);
-    if (it != _routes.end())
-      return it->second;
-
-    _routes[idx] = guest_irq;
-    return guest_irq;
-  }
-
-  /**
-   * Encode a 4-byte ACPI PkgLength field.
-   *
-   * See ACPI Specification, Revision 6.5, Section 20.2.4 (Package Length
-   * Encoding).
-   *
-   * \note The output buffer is assumed to contain space for at least 4 bytes.
-   *
-   * \param[out] buf    Output buffer.
-   * \param      value  Value to encode.
-   */
-  static void encode_pkg_length_4b(unsigned char *buf, unsigned value)
-  {
-    assert(value <= 0x0fffffff);
-
-    // Bits 6 & 7 set in the leading byte indicate the 4-byte encoding.
-    // The leading byte also uses bits 0 to 3 for the least significant bits
-    // of the value.
-    buf[0] = 0xc0U | (value & 0x0fU);
-    buf[1] = (value >> 4) & 0xffU;
-    buf[2] = (value >> 12) & 0xffU;
-    buf[3] = (value >> 20) & 0xffU;
-  }
-
-  L4Re::Util::Object_registry *_registry;
-  L4::Cap _icu;
-  std::map> _sources;
-  std::map,
-           cxx::unique_ptr> _sinks;
-  std::map,
-           unsigned> _routes;
-};
-
-/**
- * Parse the bus-range property of the device tree node of the PCI host bridge.
- *
- * \param node        Device tree node.
- * \param start[out]  Returns the start of the handled bus range.
- * \param end[out]    Returns the inclusive end of the handled bus range.
- *
- * \retval true   bus-range property found and `start` and `end` valid.
- * \retval false  bus-range property not found or faulty. `start` and `end`
- *                invalid.
- */
-bool
-parse_bus_range(Dt_node const &node, unsigned char *start, unsigned char *end);
-
-/**
- * PCI bus managing devices 'plugged' into it.
- */
-class Pci_bus
-{
-  enum
-  {
-    Max_num_devs = 32,
-    Invalid_dev_id = 0xffffffff,
-  };
-
-public:
-  // Create a PCI bus with the specified bus number.
-  explicit Pci_bus(unsigned char num) : _bus_num(num) {}
-
-  /**
-   * Return the hw device referred to in the configuration address.
-   */
-  Pci_device *device(l4_uint32_t devid)
-  { return _devices[devid].get(); }
-
-  /// Number of registered devices on this bus.
-  size_t num_devices() const
-  { return _devices.size(); }
-
-  /// Number of this bus.
-  unsigned char bus_num() const
-  { return _bus_num; };
-
-  /**
-   * Register a UVMM emulated device.
-   *
-   * Disables the device to meet the required reset state. We also have not yet
-   * registered any MMIO/IO resources for the guest.
-   *
-   * \param dev     Device to register.
-   * \param dev_id  Device ID to register the device with, must be allocated via
-   *                `alloc_dev_id()`, with the exception of `Invalid_dev_id`,
-   *                which instead instructs this method to allocate a device ID.
-   *
-   * \throws L4::Bounds_error   If an out-of-range device ID is provided.
-   * \throws L4::Out_of_memory  If `Invalid_dev_id` was passed for `dev_id`, but
-   *                            allocating a device ID failed because there was
-   *                            no more free device ID.
-   */
-  void register_device(cxx::Ref_ptr const &dev,
-                       unsigned dev_id = Invalid_dev_id)
-  {
-    if (dev_id == Invalid_dev_id)
-      dev_id = alloc_dev_id();
-    else if (dev_id >= Max_num_devs)
-      L4Re::throw_error(-L4_ERANGE,
-                        "Provided device ID is in the range [0, 31].");
-
-    info().printf("Registering PCI device %.02x:%.02x.0\n", _bus_num, dev_id);
-
-    if (dev_id >= _devices.size())
-      _devices.resize(dev_id + 1);
-
-    dev->disable_access(Access_mask); // PCI devices are disabled by default.
-    _devices[dev_id] = dev;
-  }
-
-  /**
-   * Allocate a device ID, which can be used to register a PCI device on this
-   * bus.
-   *
-   * \return Allocated device ID.
-   *
-   * \throws L4::Out_of_memory  If the allocation failed because there is no
-   *                            more free device ID.
-   */
-  unsigned alloc_dev_id()
-  {
-    long dev_id = _dev_id_alloc.scan_zero();
-    if (dev_id < 0)
-      L4Re::throw_error(-L4_ENOMEM,
-                        "PCI bus can accommodate no more than 32 devices. "
-                        "Consider putting the device on another PCI bus.");
-    _dev_id_alloc.set_bit(dev_id);
-    return dev_id;
-  }
-
-private:
-  static Dbg warn() { return Dbg(Dbg::Pci, Dbg::Warn, "PCI bus"); }
-  static Dbg info() { return Dbg(Dbg::Pci, Dbg::Info, "PCI bus"); }
-  static Dbg trace() { return Dbg(Dbg::Pci, Dbg::Trace, "PCI bus"); }
-
-  unsigned char _bus_num;
-  // used for device lookup on PCI config space access
-  // may contain physical and virtual devices
-  std::vector> _devices;
-  cxx::Bitmap _dev_id_alloc;
-};
-
-/*
- * PCI host bridge managing device accesses from the guest OS.
- *
- * It also iterates all PCI the vBus and places them on the virtual PCI bus to
- * make them visible to the guest.
- */
-class Pci_host_bridge : public Virt_pci_device
-{
-public:
-  /**
-   * Create a PCI host bridge for the given PCI bus number.
-   */
-  Pci_host_bridge(Device_lookup *devs, Dt_node const &node,
-                  unsigned char bus_num,
-                  cxx::Ref_ptr msix_ctrl)
-  : _vmm(devs->vmm()),
-    _vbus(devs->vbus()),
-    _irq_router(_vmm->registry(), _vbus->icu()),
-    _bus(bus_num),
-    _msix_ctrl(msix_ctrl),
-    _windows(node)
-  {
-    if (msix_ctrl)
-      _msi_src_factory = make_device<
-        Vdev::Msi::Msi_src_factory>(cxx::static_pointer_cast(
-                                      devs->vbus()),
-                                    devs->vmm()->registry());
-  }
-
-  /// provide access to the bus
-  Pci_bus *bus() { return &_bus; }
-
-  /// access to bridge window management
-  Pci_bridge_windows *bridge_windows() { return &_windows; }
-  /// access to bridge window management
-  Pci_bridge_windows const *bridge_windows() const { return &_windows; }
-
-  /**
-   * A hardware PCI device present on the vBus.
-   */
-  struct Hw_pci_device : public Pci_device
-  {
-    explicit Hw_pci_device(Pci_host_bridge *parent, L4vbus::Pci_dev d,
-                           unsigned dev_id, l4vbus_device_t const &dinfo)
-    : parent(parent),
-      dev_id(dev_id),
-      dev(d),
-      dinfo(dinfo)
-    {}
-
-    l4_uint64_t src_id() const override
-    { return dev.dev_handle() | L4vbus::Icu::Src_dev_handle; }
-
-    /**
-     * Convert Mem_access, which is given in bytes, into bits.
-     *
-     * The same as (8 << width), but we let the compiler do the optimization.
-     */
-    inline l4_uint32_t mem_access_to_bits(Vmm::Mem_access::Width width) const
-    {
-      switch (width)
-        {
-        case Vmm::Mem_access::Width::Wd8:
-          return 8;
-        case Vmm::Mem_access::Width::Wd16:
-          return 16;
-        case Vmm::Mem_access::Width::Wd32:
-          return 32;
-        case Vmm::Mem_access::Width::Wd64:
-          return 64;
-        default:
-          L4Re::throw_error(-L4_EINVAL, "Cannot convert value to bits.\n");
-        }
-    }
-
-    void cfg_write_raw(unsigned reg, l4_uint32_t value,
-                       Vmm::Mem_access::Width width) override
-    {
-      if (has_msi && msi_cap_write(reg, value, width))
-        return;
-
-      L4Re::chksys(dev.cfg_write(reg, value, mem_access_to_bits(width)),
-                   "PCI config space access: write\n");
-    }
-
-    void cfg_read_raw(unsigned reg, l4_uint32_t *value,
-                      Vmm::Mem_access::Width width) override
-    {
-      if (has_msi && msi_cap_read(reg, value, width))
-        return;
-
-      if (has_sriov && sriov_cap_read(reg, value, width))
-        return;
-
-      L4Re::chksys(dev.cfg_read(reg, value, mem_access_to_bits(width)),
-                   "PCI config space access: read\n");
-    }
-
-    /**
-     * For some devices IO adds additional resources to the vbus device.
-     *
-     * Uvmm handles PCI resources via the PCI BAR registers.
-     * In this function we discover all mem resources from the vbus and map
-     * those that are not yet handled through PCI BARs.
-     */
-    void map_additional_iomem_resources(Vmm::Guest *vmm,
-                                        L4::Cap io_ds);
-
-    /**
-     * Check if the read access is in the range of the MSI cap and needs to be
-     * emulated.
-     *
-     * \return true, iff read was to the MSI cap and is emulated.
-     */
-    bool msi_cap_read(unsigned reg, l4_uint32_t *value,
-                       Vmm::Mem_access::Width width);
-
-    /**
-     * Check if the write access is in the range of the MSI cap and needs to be
-     * emulated.
-     *
-     * \return true, iff write was to the MSI cap and is handled.
-     *
-     * If the MSI capability supports per-vector masking, writes to the mask
-     * bits of the capability needs to be written to the HW device as well.
-     */
-    bool msi_cap_write(unsigned reg, l4_uint32_t value,
-                       Vmm::Mem_access::Width width);
-
-    /// write MSI cap of hardware device
-    void cfg_space_write_msi_cap(l4_icu_msi_info_t *msiinfo = nullptr);
-
-    /// Setup virtual MSI-X table and map vbus resources as needed.
-    void setup_msix_table();
-
-    /**
-     * Check if the read access is in the range of the SR-IOV cap and needs to
-     * be emulated.
-     *
-     * \return true, iff read was to the SR-IOV cap and is emulated.
-     */
-    bool sriov_cap_read(unsigned reg, l4_uint32_t *value,
-                        Vmm::Mem_access::Width width);
-
-    /**
-     * Allocate BAR memory from the bridge windows.
-     *
-     * \pre BAR size already read from hardware device.
-     */
-    void alloc_bars_in_windows()
-    {
-      for (int i = 0; i < Bar_num_max_type0; ++i)
-        {
-          Pci_cfg_bar &bar = bars[i];
-
-          if (bar.type >= Pci_cfg_bar::MMIO32 && bar.type <= Pci_cfg_bar::IO)
-            bar.map_addr =
-              parent->bridge_windows()->alloc_bar_resource(bar.size, bar.type);
-          else
-            continue;
-
-          info().printf("  bar[%u] hw_addr=0x%llx map_addr=0x%llx size=0x%llx "
-                        "type=%s\n",
-                        i, bar.io_addr, bar.map_addr, bar.size,
-                        bar.to_string());
-        }
-
-      // check if IO supports the expansion ROM, if so set it up.
-      if (exp_rom.io_addr > 0 && exp_rom.size > 0)
-        {
-          exp_rom.map_addr =
-            parent->bridge_windows()
-              ->alloc_bar_resource(exp_rom.size, Pci_cfg_bar::Type::MMIO32);
-
-          info().printf("  exp_rom hw_addr=0x%llx map_addr=0x%llx size=0x%llx "
-                        "type=%s\n",
-                        exp_rom.io_addr, exp_rom.map_addr, exp_rom.size,
-                        "MMIO32");
-        }
-    }
-
-    Pci_host_bridge *parent;             /// Parent host bridge of device
-    unsigned dev_id;                     /// Virtual device id
-    L4vbus::Pci_dev dev;                 /// Reference to vbus PCI device
-    l4vbus_device_t dinfo;               /// vbus device info
-    // HW IRQ resource managed in Legacy_irq_router;
-    cxx::Ref_ptr msix_table_page_mgr;
-    cxx::Ref_ptr msix_table;
-    cxx::Ref_ptr msi_src;
-
-  protected:
-    void add_decoder_resources(Vmm::Guest *, l4_uint32_t access) override;
-    void del_decoder_resources(Vmm::Guest *, l4_uint32_t access) override;
-
-    void add_exp_rom_resource() override;
-    void del_exp_rom_resource() override;
-
-  private:
-    void add_io_bar_resources(Pci_cfg_bar const &bar);
-    void add_mmio_bar_resources(Pci_cfg_bar const &bar);
-    void add_msix_bar_resources(Pci_cfg_bar const &bar);
-    void del_io_bar_resources(Pci_cfg_bar const &bar);
-    void del_mmio_bar_resources(Pci_cfg_bar const &bar);
-    void del_msix_bar_resources(Pci_cfg_bar const &bar);
-
-    void msi_cap_write_ctrl(l4_uint16_t ctrl);
-
-    static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "HW PCI dev"); }
-    static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "HW PCI dev"); }
-    static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "HW PCI dev"); }
-
-    std::mutex _mutex;                   /// Protect MSI cap reads/writes
-  }; // struct Hw_pci_device
-
-  /**
-   * Handle incoming config space read
-   *
-   * \returns read value
-   */
-  l4_uint32_t cfg_space_read(l4_uint32_t devid, unsigned reg, Vmm::Mem_access::Width width)
-  {
-    l4_uint32_t value = -1U;
-    if (devid >= _bus.num_devices())
-      return value;
-
-    if (auto dev = _bus.device(devid))
-      dev->cfg_read(reg, &value, width);
-
-    if (0)
-      trace().printf("read cfg dev=%u width=%d raw=0x%x val=0x%x\n",
-                     devid, (int)width, reg, value);
-    return value;
-  }
-
-  /**
-   * Handle incoming config space write
-   */
-  void cfg_space_write(l4_uint32_t devid, unsigned reg, Vmm::Mem_access::Width width, l4_uint32_t value)
-  {
-    if (devid >= _bus.num_devices())
-      return;
-
-    // Pass-through to device
-    if (auto dev = _bus.device(devid))
-      dev->cfg_write(_vmm, reg, value, width);
-
-    if (0)
-      info().printf("write cfg dev=%u width=%d reg=0x%x, value=0x%x\n",
-                     devid, (int)width, reg, value);
-  }
-
-protected:
-  /**
-   * Setup and register devices, i.e. the host bridge itself and any PCI devices
-   * discovered on the root bus.
-   *
-   * This must be a separate method called from the constructor of classes
-   * derived from Pci_host_bridge, since iterate_pci_root_bus() calls virtual
-   * methods.
-   */
-  void setup_devices()
-  {
-    unsigned dev_id = _bus.alloc_dev_id();
-    iterate_pci_root_bus();
-
-    // Registering the host bridge itself must be the last operation, otherwise
-    // an exception thrown in the rest of the constructor would result in double
-    // destruction of the host bridge (exception unwind destroys the
-    // half-constructed host bridge, host bridge itself is removed from
-    // _devices, drops its _refcount to zero, which destroys the host bridge in
-    // destruction again).
-    _bus.register_device(cxx::Ref_ptr(this), dev_id);
-  }
-
-  /**
-   * Iterate the root bus and setup any PCI devices found.
-   */
-  void iterate_pci_root_bus()
-  {
-    if (!_vbus.get() || !_vbus->available())
-      return;
-
-    auto root = _vbus->bus()->root();
-    L4vbus::Pci_dev pdev;
-    l4vbus_device_t dinfo;
-    info().printf("Scanning PCI devices...\n");
-    while (root.next_device(&pdev, L4VBUS_MAX_DEPTH, &dinfo) == L4_EOK)
-      {
-        if (!l4vbus_subinterface_supported(dinfo.type, L4VBUS_INTERFACE_PCIDEV))
-          continue;
-
-        l4_uint32_t vendor_device = 0;
-        if (pdev.cfg_read(Pci_hdr_vendor_id_offset, &vendor_device, 32) != L4_EOK)
-          continue;
-
-        if (vendor_device == Pci_invalid_vendor_id)
-          continue;
-
-        Hw_pci_device *h =
-          new Hw_pci_device(this, pdev, _bus.alloc_dev_id(), dinfo);
-        info().printf("Found PCI device: name='%s', vendor/device=%04x:%04x\n",
-                      dinfo.name, vendor_device & 0xffff, vendor_device >> 16);
-
-        h->parse_device_bars();
-        h->alloc_bars_in_windows();
-        h->parse_device_exp_rom();
-        h->parse_msix_cap();
-        h->parse_msi_cap();
-        h->setup_msix_table();
-        h->parse_sriov_cap();
-        h->map_additional_iomem_resources(_vmm, _vbus->io_ds());
-        init_dev_resources(h);
-
-        _bus.register_device(cxx::Ref_ptr(h), h->dev_id);
-      }
-  }
-
-  virtual void init_dev_resources(Hw_pci_device *) = 0;
-
-public:
-  /**
-   * Return the virtual source ID for a PCI device registered on this host
-   * bridge.
-   *
-   * This default implementation returns the plain Requester ID (bus, device and
-   * function number). Derived implementations overriding this method might
-   * want to apply a mapping to the Requester ID.
-   */
-  virtual l4_uint32_t msi_vsrc_id(unsigned dev_id) const
-  {
-    // The Requester ID consists of the bus number, device number and function
-    // number. We do not support device function, therefore the following shift
-    // accounts for the 3 bits allocated for the function number.
-    return ((l4_uint32_t)_bus.bus_num()) << 8 | dev_id << 3;
-  }
-
-  /**
-   * Return the MSI-X destination for a PCI device registered on this host
-   * bridge.
-   */
-  Gic::Msix_dest msix_dest(unsigned dev_id) const
-  {
-    return Gic::Msix_dest(_msix_ctrl, msi_vsrc_id(dev_id));
-  }
-
-  /**
-   * Generate the _PRT interrupt routing table for ACPI DSDT.
-   *
-   * \param[out] buf       Output buffer.
-   * \param      max_size  Size of the buffer in bytes.
-   *
-   * \return Number of bytes generated.
-   */
-  l4_size_t amend_dsdt_with_prt(void *buf, l4_size_t max_size) const
-  {
-    return _irq_router.amend_dsdt_with_prt(buf, max_size);
-  }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Pci, Dbg::Trace, "PCI hbr"); }
-  static Dbg warn() { return Dbg(Dbg::Pci, Dbg::Warn, "PCI hbr"); }
-  static Dbg info() { return Dbg(Dbg::Pci, Dbg::Info, "PCI hbr"); }
-
-protected:
-  Vmm::Guest *_vmm;
-  cxx::Ref_ptr _vbus;
-  Legacy_irq_router _irq_router;
-  Pci_bus _bus;
-  /// MSI-X controller responsible for the devices of this PCIe host bridge,
-  /// may be nullptr since MSI-X support is an optional feature.
-  cxx::Ref_ptr _msix_ctrl;
-  Pci_bridge_windows _windows;
-
-  cxx::Ref_ptr _msi_src_factory;
-};
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/device/pci_host_ecam_generic.cc b/src/l4/pkg/uvmm/server/src/device/pci_host_ecam_generic.cc
deleted file mode 100644
index 7364f93d..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pci_host_ecam_generic.cc
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Copyright (C) 2019-2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * Device for emulating a generic PCIe host bridge.
- *
- * On device creation it will scan the vbus for any PCI devices and add them to
- * its internal representation. Please note that device ids will appear in
- * increasing order, as found on the vbus, to the guest. This needs to be
- * reflected in the device tree entries when referring to any devices.
- *
- * Also note that the bridge has some limitations:
- * - Only one bus (0) is supported
- * - Bridges as devices are not supported
- * - Interrupt sharing is not supported
- * - IO configuration space access is not supported
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   pcie@10000000 {
- *       // Interrupt map for two devices
- *       interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
- *       interrupt-map = < 0x800 0x00 0x00 0x01 &gic 0x0 0x04 0x04
- *                         0x800 0x00 0x00 0x02 &gic 0x0 0x05 0x04
- *                         0x800 0x00 0x00 0x03 &gic 0x0 0x06 0x04
- *                         0x800 0x00 0x00 0x04 &gic 0x0 0x07 0x04
- *                         0x1000 0x00 0x00 0x01 &gic 0x0 0x05 0x04
- *                         0x1000 0x00 0x00 0x02 &gic 0x0 0x06 0x04
- *                         0x1000 0x00 0x00 0x03 &gic 0x0 0x07 0x04
- *                         0x1000 0x00 0x00 0x04 &gic 0x0 0x08 0x04
- *                         >;
- *       #interrupt-cells = <0x01>;
- *       // Optional: Map MSIs to GICv3 (if ITS emulation is enabled)
- *       // msi-map = <0x0 &its 0x0 0x10000>;
- *       ranges = <0x1000000 0x00 0x00000000 0x00 0x3eff0000 0x00 0x00010000
- *                 0x2000000 0x00 0x10000000 0x00 0x10000000 0x00 0x2eff0000
- *                 0x3000000 0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>;
- *       reg = <0x40 0x10000000 0x00 0x10000000>;
- *       bus-range = <0x00 0x00>;
- *       #address-cells = <0x03>;
- *       #size-cells = <0x02>;
- *       device_type = "pci";
- *       compatible = "pci-host-ecam-generic";
- *   };
- * \endcode
- *
- * Note: If you don't want Linux to remap the bars add linux,pci-probe-only=<1>
- * to the /chosen node of your device tree.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "device_factory.h"
-#include "ds_mmio_mapper.h"
-#include "irq.h"
-#include "irq_dt.h"
-#include "mem_types.h"
-#include "pci_bus_cfg_ecam.h"
-#include "pci_device.h"
-#include "pci_host_bridge.h"
-
-namespace {
-
-using namespace Vmm;
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-/**
- * Internal interrupt map representation.
- *
- * The interrupt-map entry will be scanned once and this map will be used on
- * PCI device creation.
- */
-struct Interrupt_map
-{
-  /**
-   * Interrupt mapping for one specific device and all available pins.
-   */
-  struct Dev_mapping
-  {
-    /**
-     * Interrupt - Interrupt controller pair.
-     */
-    struct Irq_target
-    {
-      int irq;                  /// Interrupt to map to
-      cxx::Ref_ptr ic; /// Interrupt controller to use
-    };
-    Irq_target targets[Pci_hdr_interrupt_pin_max];
-  };
-  l4_uint32_t dev_id_mask;                /// Mask for device id's
-  l4_uint32_t pin_mask;                   /// Mask for interrupt pins
-  std::map map; /// Device id - Interrupt map
-};
-
-
-class Pci_host_ecam_generic
-: public Pci_host_bridge,
-  public Device
-{
-public:
-  explicit Pci_host_ecam_generic(Interrupt_map const &irq_map,
-                                 unsigned char bus_num,
-                                 Device_lookup *devs,
-                                 Dt_node const &node,
-                                 cxx::Ref_ptr msix_ctrl)
-  : Pci_host_bridge(devs, node, bus_num, msix_ctrl),
-    _irq_map(irq_map)
-  {
-    header()->vendor_id = 0x1b36;        // PCI vendor id Redhat
-    header()->device_id = 0x0008;        // PCI device id Redhat PCIe host
-    header()->subsystem_vendor = 0x1af4; // PCI sub vendor id Redhat Qumranet (QEMU)
-    header()->subsystem_id = 0x1100;     // PCI sub device id QEMU
-    header()->classcode[1] = Pci_subclass_code_host;
-    header()->classcode[2] = Pci_class_code_bridge_device;
-
-    setup_devices();
-  }
-
-protected:
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned) override
-  {
-    assert(false); // Must not be called. No BARs set up.
-    return nullptr;
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  {
-    assert(false); // Must not be called. No BARs set up.
-    return nullptr;
-  }
-
-private:
-  /**
-   * Return type 0 PCI header for the virtual PCIe host controller.
-   */
-  Pci_header::Type0 *header()
-  { return get_header(); }
-
-  void setup_device_irq(Hw_pci_device *hw_dev)
-  {
-    l4vbus_device_t dinfo = hw_dev->dinfo;
-    unsigned pin = 0;
-    hw_dev->cfg_read(Pci_hdr_interrupt_pin_offset, &pin, Vmm::Mem_access::Width::Wd8);
-    if (pin == 0) // No legacy interrupt messages enabled
-      return;
-
-    if (pin < Pci_hdr_interrupt_pin_min || pin > Pci_hdr_interrupt_pin_max)
-      L4Re::chksys(-L4_EINVAL, "Invalid interrupt pin encoding %u\n", pin);
-
-    // Apply interrupt pin mask
-    pin &= _irq_map.pin_mask;
-
-    // Apply device id mask
-    unsigned dev_id = (hw_dev->dev_id << 11) & _irq_map.dev_id_mask;
-    if (!_irq_map.map.count(dev_id))
-      L4Re::chksys(-L4_EINVAL, "PCI device not found in interrupt map.");
-
-    // Query the corresponding irq/ic entry based on the device id and irq pin
-    int map_irq = _irq_map.map.at(dev_id).targets[pin - 1].irq;
-    cxx::Ref_ptr ic = _irq_map.map.at(dev_id).targets[pin - 1].ic;
-
-    // If the ic is empty this means it is unmanaged and we just skip the
-    // setup.
-    if (!ic)
-      return;
-
-    l4vbus_resource_t res[6];
-    int io_irq = -1;
-    for (unsigned i = 0; i < dinfo.num_resources; ++i)
-      {
-        if (hw_dev->dev.get_resource(i, &res[i]) != L4_EOK)
-          continue;
-
-        if (res[i].type == L4VBUS_RESOURCE_IRQ)
-          {
-            io_irq = res[i].start;
-            break; // We only support one interrupt
-          }
-      }
-
-    assert(io_irq != -1);
-
-    // Create the io->guest irq mapping
-    _irq_router.add_route(io_irq, ic, dev_id, pin, map_irq);
-    info().printf("  IRQ mapping: %d -> %d\n", io_irq, map_irq);
-  }
-
-  void init_dev_resources(Hw_pci_device *hwdev) override
-  {
-    setup_device_irq(hwdev);
-  }
-
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "PCIe ctl"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "PCIe ctl"); }
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "PCIe ctl"); }
-private:
-  Interrupt_map const _irq_map;
-};
-
-struct F : Factory
-{
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "PCIe ctl"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "PCIe ctl"); }
-
-  /*
-   * Parses the interrupt map and create an internal representation.
-   *
-   * The map has to be parsed from the beginning to the end, because in theory
-   * every entry could have a different amount of fields depending on the ic
-   * used.
-   *
-   * An interrupt-map entry is defined as follow:
-   * child id                   irq slot  ic phandle  irq spec
-   * phys.hi phys.mid phys.low
-   * 0x800   0x00     0x00      0x01      &gic        0x0 0x04 0x04
-   *
-   * The amount of cells to read is specified in the #xxxx-cells entries of the
-   * corresponding node as follow:
-   * child id: amount of #address-cells entries of pci node
-   * irq slot: amount of #interrupt-cells entries of pci node
-   * irq spec: amount of #interrupt-cells entries of ic node
-   * There also may be a #address-cells entry for the ic, which we ignore.
-   *
-   * Before a device is looked up in the map the interrupt-map-mask needs to be
-   * applied. The format is the same as for the child id and irq slot mappings.
-   *
-   * Every device can have up to Pci_hdr_interrupt_pin_max slot entries.
-   */
-  static void parse_interrupt_map(Interrupt_map *map, Device_lookup *devs,
-                                  Dt_node const &node)
-  {
-    int map_addr_cells = node.get_cells_attrib("#address-cells");
-    int map_int_cells = node.get_cells_attrib("#interrupt-cells");
-    if (map_addr_cells != 3 || map_int_cells != 1)
-      L4Re::chksys(-L4_EINVAL, "Cell attributes have wrong size.");
-
-    int i = 0, sz;
-    fdt32_t const *p = node.get_prop("interrupt-map-mask", &sz);
-    if (!p || sz < map_addr_cells + map_int_cells)
-      L4Re::chksys(-L4_EINVAL, "interrupt-map-mask attribute invalid.");
-    map->dev_id_mask = cpu_to_fdt32(*p);
-    p += map_addr_cells;
-    map->pin_mask = cpu_to_fdt32(*p);
-
-    p = node.get_prop("interrupt-map", &sz);
-    i = 0;
-    while (p && i < sz)
-      {
-        // Read child address
-        unsigned dev = cpu_to_fdt32(p[i]);
-        i += map_addr_cells;
-
-        // Read child interrupt specifier
-        unsigned irq_map = cpu_to_fdt32(p[i]);
-        if (irq_map > Pci_hdr_interrupt_pin_max)
-          L4Re::chksys(-L4_EINVAL, "Invalid value for interrupt pin.");
-        i += map_int_cells;
-
-        // Query dt node for ic
-        Dt_node const pn = node.find_phandle(p[i++]);
-        if (!pn.is_valid())
-          L4Re::chksys(-L4_EINVAL, "Can't find node for phandle while "
-                       "parsing interrupt-map");
-
-        if (pn.has_prop("#address-cells")) // skip ic address cells
-          i += pn.get_cells_attrib("#address-cells");
-
-        // In case this is an unmanaged ic we have to skip its entries.
-        if (!Vdev::Factory::is_vdev(pn))
-          {
-            if (pn.has_prop("#interrupt-cells")) // skip ic interrupt cells
-              i += pn.get_cells_attrib("#interrupt-cells");
-
-            Interrupt_map::Dev_mapping &m = map->map[dev];
-            m.targets[irq_map - 1].irq = 0;
-            m.targets[irq_map - 1].ic = nullptr;
-
-            continue;
-          }
-
-        if (!pn.is_enabled())
-          L4Re::chksys(-L4_EINVAL, "Interrupt parent is disabled.");
-
-        cxx::Ref_ptr ic = cxx::dynamic_pointer_cast(
-                Vdev::Factory::create_dev(devs, pn));
-        if (!ic)
-          L4Re::chksys(-L4_EINVAL, "Can't create device for interrupt parent.");
-
-        int int_cells;
-        int irq = ic->dt_get_interrupt(&p[i], sz-i, &int_cells);
-        if (irq < 0)
-          L4Re::chksys(-L4_EINVAL, "Can't translate interrupt.");
-        i += int_cells;
-
-        // Done parsing this entry; fetch or create map entry for this device
-        Interrupt_map::Dev_mapping &m = map->map[dev];
-        m.targets[irq_map - 1].irq = irq;
-        m.targets[irq_map - 1].ic = ic;
-      }
-  }
-
-  /**
-   * Parse the MSI map and ensure that it describes an identity mapping targeted
-   * at a single MSI controller.
-   *
-   * The purpose of the MSI map is to map devices via their Requester ID
-   * (Bus number, Device number and Function number) to an MSI controller,
-   * optionally applying an offset to the Requester ID.
-   *
-   * For now we only support the simple case, where the map contains one entry
-   * that identity maps all requester IDs to a single MSI controller.
-   */
-  void parse_msi_map(Dt_node const &node)
-  {
-    int sz;
-    fdt32_t const *map = node.get_prop("msi-map", &sz);
-    if (!map)
-      // In the absence of an msi-map assume identity mapping of Requester IDs.
-      return;
-
-    if (sz != 4)
-      L4Re::chksys(-L4_EINVAL, "msi-map must have exactly one entry.");
-
-    unsigned rid_base = cpu_to_fdt32(map[0]);
-    unsigned msi_base = cpu_to_fdt32(map[2]);
-    if (rid_base != 0 || msi_base != 0)
-      L4Re::chksys(-L4_EINVAL,
-                   "msi-map must describe a zero-based identity mapping.");
-  }
-
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    info().printf("Creating PCIe host bridge\n");
-
-    // Parse the interrupt map once
-    Interrupt_map irq_map;
-    parse_interrupt_map(&irq_map, devs, node);
-
-    parse_msi_map(node);
-
-    cxx::Ref_ptr msix_ctrl;
-    // MSI controller is optional
-    Device_lookup::Mc_error res = devs->get_or_create_mc(node, &msix_ctrl);
-    if (res != Device_lookup::Mc_ok && res != Device_lookup::Mc_e_no_msiparent)
-      warn().printf(
-        "PCIe host bridge %s refers to invalid MSI controller: %s\n",
-        node.get_name(), Device_lookup::mc_err_str(res));
-
-    unsigned char bus_start = 0, bus_end = 0;
-    if (!parse_bus_range(node, &bus_start, &bus_end))
-      {
-        warn().printf(
-          "Bus range invalid in device tree. Device not created.\n");
-        return nullptr;
-      }
-
-    auto dev = make_device(irq_map, bus_start, devs,
-                                                  node, msix_ctrl);
-
-    auto ecam_cfg_connector = make_device(dev);
-    devs->vmm()->register_mmio_device(ecam_cfg_connector,
-                                      Vmm::Region_type::Virtual, node);
-
-    info().printf("Created & registered the PCIe host bridge\n");
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Device_type t = {"pci-host-ecam-generic", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/pci_host_generic.cc b/src/l4/pkg/uvmm/server/src/device/pci_host_generic.cc
deleted file mode 100644
index c9a0ca49..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pci_host_generic.cc
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * Copyright (C) 2018, 2021-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-
-#include "acpi.h"
-#include "debug.h"
-#include "device.h"
-#include "pci_bus_cfg_ecam.h"
-#include "pci_host_bridge.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "ds_mmio_mapper.h"
-#include "io_port_handler.h"
-
-namespace Vdev { namespace Pci {
-
-/**
- * PCI bus emulation.
- *
- * The emulated host bridge handles the PCI bus transaction initialized by the
- * guest OS. Linux detects the virtual host bridge and queries the root bus for
- * devices present.
- * If hardware devices are supplied via Vbus, the virtio devices are merged
- * into Vbus' PCI root bus.
- */
-class Pci_host_generic:
-  public Pci_host_bridge,
-  public Device,
-  public Acpi::Acpi_device
-{
-  Pci_header::Type0 *header()
-  { return get_header(); }
-
-  Pci_header::Type0 const *header() const
-  { return get_header(); }
-
-  void read_ecam_area(Dt_node const &node);
-
-public:
-  explicit Pci_host_generic(Device_lookup *devs, Dt_node const &node,
-                            unsigned char bus_num,
-                            unsigned char subordinate_num,
-                            cxx::Ref_ptr msix_ctrl,
-                            cxx::Ref_ptr ic)
-  : Pci_host_bridge(devs, node, bus_num, msix_ctrl),
-    _ic(ic),
-    _secondary_bus_num(bus_num),
-    _subordinate_bus_num(subordinate_num)
-  {
-    read_ecam_area(node);
-
-    // Linux' x86 PCI_direct code sanity checks for a device with class code
-    // PCI_CLASS_DISPLAY_VGA(0x0300) or PCI_CLASS_BRIDGE_HOST(0x0600) or for a
-    // device of vendor INTEL or COMPAQ.
-    // see linux/arch/x86/pci/direct.c
-    header()->classcode[2] = Pci_class_code_bridge_device;
-    header()->classcode[1] = Pci_subclass_code_host;
-    header()->header_type = 0; // host bridge is a device not a bridge
-
-    header()->vendor_id = 0x1b36;        // PCI vendor id Redhat
-    header()->device_id = 0x0008;        // PCI device id Redhat PCIe host
-    header()->subsystem_vendor = 0x1af4; // PCI sub vendor id Redhat Qumranet (QEMU)
-    header()->subsystem_id = 0x1100;     // PCI sub device id QEMU
-
-    setup_devices();
-  }
-
-  void init_dev_resources(Hw_pci_device *hw_dev) override;
-
-  bool has_ecam() const
-  { return _ecam_mcfg_size != 0; }
-
-  /**
-   * Add a MCFG allocation for the ECAM MCFG window of the PCI host bridge.
-   */
-  l4_size_t amend_mcfg(ACPI_MCFG_ALLOCATION *alloc, l4_size_t max_size) const override
-  {
-    if (!has_ecam())
-      return 0;
-
-    if (max_size < sizeof(ACPI_MCFG_ALLOCATION))
-      L4Re::throw_error(-L4_ENOMEM,
-        "Not enough space in ACPI MCFG table for PCI host bridge.");
-
-    alloc->Address = _ecam_mcfg_base;
-    alloc->PciSegment = 0;
-    alloc->StartBusNumber = _secondary_bus_num;
-    alloc->EndBusNumber = _subordinate_bus_num;
-    alloc->Reserved = 0;
-
-    return sizeof(ACPI_MCFG_ALLOCATION);
-  };
-
-  /**
-   * Add a minimal DSDT system bus so that the PCI bridge is discoverable via
-   * ACPI. Generated from the following ASL:
-   *
-   * DefinitionBlock ("Dsdt.aml", "DSDT", 1, "UVMM  ", "KERNKONZ", 4) {
-   *   //
-   *   //  System Bus
-   *   //
-   *   Scope (\_SB) {
-   *     //
-   *     // PCI Root Bridge
-   *     //
-   *     Device (PCI0) {
-   *       Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
-   *       Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
-   *       Name (_ADR, 0x00000000)
-   *       Name (_BBN, 0x00)
-   *       Name (_UID, 0x00)
-   *
-   *       //
-   *       // BUS, I/O, and MMIO resources
-   *       //
-   *       Name (_CRS, ResourceTemplate () {
-   *         WORDBusNumber (          // Bus number resource (0); the bridge produces bus numbers for its subsequent buses
-   *           ResourceProducer,      // bit 0 of general flags is 1
-   *           MinFixed,              // Range is fixed
-   *           MaxFixed,              // Range is fixed
-   *           PosDecode,             // PosDecode
-   *           0x0000,                // Granularity
-   *           0xAAAA,                // Min
-   *           0xBBBB,                // Max
-   *           0x0000,                // Translation
-   *           0x1112                 // Range Length = Max-Min+1
-   *           )
-   *
-   *         IO (Decode16, 0xCF8, 0xCF8, 0x01, 0x08)       //Consumed resource (0xCF8-0xCFF)
-   *
-   *         WORDIO (                 // Consumed-and-produced resource (I/O window 0x8000 - 0xFFFF)
-   *           ResourceProducer,      // bit 0 of general flags is 0
-   *           MinFixed,              // Range is fixed
-   *           MaxFixed,              // Range is fixed
-   *           PosDecode,
-   *           EntireRange,
-   *           0x0000,                // Granularity
-   *           0x8000,                // Min
-   *           0xFFFF,                // Max
-   *           0x0000,                // Translation
-   *           0x8000                 // Range Length
-   *           )
-   *
-   *         DWORDMEMORY (            // Descriptor for 32-bit MMIO
-   *           ResourceProducer,      // bit 0 of general flags is 0
-   *           PosDecode,
-   *           MinFixed,              // Range is fixed
-   *           MaxFixed,              // Range is Fixed
-   *           NonCacheable,
-   *           ReadWrite,
-   *           0x00000000,            // Granularity
-   *           0xAAAAAAAA,            // Min
-   *           0xBBBBBBBB,            // Max
-   *           0x00000000,            // Translation
-   *           0x11111112,            // Range Length
-   *           )
-   *
-   *         QWORDMEMORY (            // Descriptor for 64-bit MMIO
-   *           ResourceProducer,      // bit 0 of general flags is 0
-   *           PosDecode,
-   *           MinFixed,              // Range is fixed
-   *           MaxFixed,              // Range is Fixed
-   *           NonCacheable,
-   *           ReadWrite,
-   *           0x00000000,            // Granularity
-   *           0xAAAAAAAAAAAAAAAA,    // Min
-   *           0xBBBBBBBBBBBBBBBB,    // Max
-   *           0x0000000000000000,    // Translation
-   *           0x1111111111111112,    // Range Length
-   *           )
-   *       })
-   *     }
-   *   }
-   * }
-   *
-   * Conversion (save above as Dsdt.asl):
-   *   $ iasl Dsdt.asl
-   *   $ xxd -i -s 0x24 -c 8 Dsdt.aml
-   */
-  l4_size_t amend_dsdt(void *buf, l4_size_t max_size) const override
-  {
-    unsigned char dsdt_pci[] = {
-      /* 0x00 */ 0x10, 0x40, 0x0b, 0x5f, 0x53, 0x42, 0x5f, 0x5b,
-      /* 0x08 */ 0x82, 0x48, 0x0a, 0x50, 0x43, 0x49, 0x30, 0x08,
-      /* 0x10 */ 0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41, 0xd0, 0x0a,
-      /* 0x18 */ 0x08, 0x08, 0x5f, 0x43, 0x49, 0x44, 0x0c, 0x41,
-      /* 0x20 */ 0xd0, 0x0a, 0x03, 0x08, 0x5f, 0x41, 0x44, 0x52,
-      /* 0x28 */ 0x00, 0x08, 0x5f, 0x42, 0x42, 0x4e, 0x00, 0x08,
-      /* 0x30 */ 0x5f, 0x55, 0x49, 0x44, 0x00, 0x08, 0x5f, 0x43,
-      /* 0x38 */ 0x52, 0x53, 0x11, 0x46, 0x07, 0x0a, 0x72, 0x88,
-      /* 0x40 */ 0x0d, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00,
-
-      // bus range
-      /* 0x47 */ 0xaa, 0xaa, // Min
-      /* 0x49 */ 0xbb, 0xbb, // Max
-      /* 0x4b */ 0x00, 0x00, // Translation
-      /* 0x4d */ 0x12, 0x11, // Range Length
-
-      /* 0x4f */ 0x47,
-      /* 0x50 */ 0x01, 0xf8, 0x0c, 0xf8, 0x0c, 0x01, 0x08, 0x88,
-      /* 0x58 */ 0x0d, 0x00, 0x01, 0x0c, 0x03, 0x00, 0x00,
-
-      // I/O window
-      /* 0x5f */ 0x00, 0x80, // Min
-      /* 0x61 */ 0xff, 0xff, // Max
-      /* 0x63 */ 0x00, 0x00, // Translation
-      /* 0x65 */ 0x00, 0x80, // Range Length
-
-      /* 0x67 */ 0x87,
-      /* 0x68 */ 0x17, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00,
-      /* 0x70 */ 0x00,
-
-      // MMIO window
-      /* 0x71 */ 0xaa, 0xaa, 0xaa, 0xaa, // Min
-      /* 0x75 */ 0xbb, 0xbb, 0xbb, 0xbb, // Max
-      /* 0x79 */ 0x00, 0x00, 0x00, 0x00, // Translation
-      /* 0x7d */ 0x12, 0x11, 0x11, 0x11, // Range Length
-
-      /* 0x81 */ 0x8a, 0x2b, 0x00, 0x00, 0x0c, 0x01, 0x00,
-      /* 0x88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-      // MMIO64 window
-      /* 0x8f */ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // Min
-      /* 0x97 */ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, // Max
-      /* 0x9f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Translation
-      /* 0xa7 */ 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // Range Length
-
-      /* 0xaf */ 0x79, 0x00
-    };
-
-    // Update "bus range" with actual values from device tree
-    *reinterpret_cast(&dsdt_pci[0x47]) = _secondary_bus_num;
-    *reinterpret_cast(&dsdt_pci[0x49]) = _subordinate_bus_num;
-    *reinterpret_cast(&dsdt_pci[0x4d]) =
-      _subordinate_bus_num - _secondary_bus_num + 1U;
-
-    Pci_bridge_windows const *wnds = bridge_windows();
-    auto win = wnds->get_window(Pci_cfg_bar::Type::IO);
-    // Update "I/O window" with actual values from device tree
-    *reinterpret_cast(&dsdt_pci[0x5f]) = win.first & 0xffffu;
-    *reinterpret_cast(&dsdt_pci[0x61]) = (win.first + win.second - 1U) & 0xffffu;
-    *reinterpret_cast(&dsdt_pci[0x65]) = win.second & 0xffffu;
-
-    win = wnds->get_window(Pci_cfg_bar::Type::MMIO32);
-    // Update "MMIO window" with actual values from device tree
-    *reinterpret_cast(&dsdt_pci[0x71]) = win.first & 0xffff'ffffu;
-    *reinterpret_cast(&dsdt_pci[0x75]) = (win.first + win.second - 1U) & 0xffff'ffffu;
-    *reinterpret_cast(&dsdt_pci[0x7d]) = win.second & 0xffff'ffffu;
-
-    win = wnds->get_window(Pci_cfg_bar::Type::MMIO64);
-    // Update "MMIO64 window" with actual values from device tree
-    *reinterpret_cast(&dsdt_pci[0x8f]) = win.first;
-    *reinterpret_cast(&dsdt_pci[0x97]) = win.first + win.second - 1U;
-    *reinterpret_cast(&dsdt_pci[0xa7]) = win.second;
-
-    l4_size_t size = sizeof(dsdt_pci);
-    if (max_size < size)
-      L4Re::throw_error(-L4_ENOMEM,
-        "Not enough space in DSDT ACPI table for PCI host bridge.");
-    std::memcpy(buf, &dsdt_pci, size);
-
-    if (has_ecam())
-      size += amend_dsdt_with_mcfg(static_cast(buf) + size,
-                                   max_size - size);
-
-    size += amend_dsdt_with_prt(static_cast(buf) + size,
-                                max_size - size);
-    return size;
-  }
-
-  /**
-   * Reserve ECAM MCFG window. Generated from the following ASL:
-   *
-   * DefinitionBlock ("Dsdt.aml", "DSDT", 1, "UVMM  ", "KERNKONZ", 4) {
-   *   //
-   *   //  System Bus
-   *   //
-   *   Scope (\_SB) {
-   *     //
-   *     // Reserved resources
-   *     //
-   *     Device (RES0) {
-   *       Name (_HID, EISAID ("PNP0C02")) // ID used for reserving resources
-   *       Name (_UID, 0x00)
-   *
-   *       //
-   *       // Reserved MMIO resources
-   *       //
-   *       Name (_CRS, ResourceTemplate () {
-   *         QWordMemory (            // Descriptor for ECAM MCFG
-   *            ResourceConsumer,     // The value of this should not matter for the reservation,
-   *                                  // but conceptully the PCI root bridge consumes memory access
-   *                                  // converting them into a PCI configuration space access.
-   *            PosDecode,
-   *            MinFixed,             // Range is fixed
-   *            MaxFixed,             // Range is fixed
-   *            NonCacheable,
-   *            ReadWrite,
-   *            0x0000000000000000,   // Granularity
-   *            0xAAAAAAAAAAAAAAAA,   // Min
-   *            0xBBBBBBBBBBBBBBBB,   // Max
-   *            0x0000000000000000,   // Translation
-   *            0x1111111111111112,   // Range Length
-   *            )
-   *        })
-   *      }
-   *   }
-   * }
-   *
-   * Conversion (save above as Dsdt.asl):
-   *   $ iasl Dsdt.asl
-   *   $ xxd -i -s 0x24 -c 8 Dsdt.aml
-   */
-  l4_size_t amend_dsdt_with_mcfg(void *buf, l4_size_t max_size) const
-  {
-    unsigned char dsdt_pci_mcfg[] = {
-      /* 0x00 */ 0x10, 0x47, 0x05, 0x5f, 0x53, 0x42, 0x5f, 0x5b,
-      /* 0x08 */ 0x82, 0x4f, 0x04, 0x52, 0x45, 0x53, 0x30, 0x08,
-      /* 0x10 */ 0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41, 0xd0, 0x0c,
-      /* 0x18 */ 0x02, 0x08, 0x5f, 0x55, 0x49, 0x44, 0x00, 0x08,
-      /* 0x20 */ 0x5f, 0x43, 0x52, 0x53, 0x11, 0x33, 0x0a, 0x30,
-      /* 0x28 */ 0x8a, 0x2b, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00,
-      /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-      // ECAM MCFG window
-      /* 0x36 */ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // Min
-      /* 0x3e */ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, // Max
-      /* 0x46 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Translation
-      /* 0x4e */ 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // Range Length
-
-      /* 0x56 */ 0x79, 0x00
-    };
-
-    // Update "ECAM MCFG window" with actual values from device tree
-    *reinterpret_cast(&dsdt_pci_mcfg[0x36]) = _ecam_mcfg_base;
-    auto ecam_mcfg_max = _ecam_mcfg_base + _ecam_mcfg_size - 1U;
-    *reinterpret_cast(&dsdt_pci_mcfg[0x3e]) = ecam_mcfg_max;
-    *reinterpret_cast(&dsdt_pci_mcfg[0x4e]) = _ecam_mcfg_size;
-
-    l4_size_t size = sizeof(dsdt_pci_mcfg);
-    if (max_size < size)
-      L4Re::throw_error(-L4_ENOMEM,
-        "Not enough space in DSDT ACPI for PCI host bridge MCFG reservation.");
-    std::memcpy(buf, &dsdt_pci_mcfg, size);
-    return size;
-  }
-
-protected:
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned) override
-  {
-    assert(false); // Must not be called. No BARs set up.
-    return nullptr;
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  {
-    assert(false); // Must not be called. No BARs set up.
-    return nullptr;
-  }
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Pci, Dbg::Trace, "PCI bus"); }
-  static Dbg warn() { return Dbg(Dbg::Pci, Dbg::Warn, "PCI bus"); }
-  static Dbg info() { return Dbg(Dbg::Pci, Dbg::Info, "PCI bus"); }
-
-  cxx::Ref_ptr irq_ic() { return _ic; }
-
-  /// IC to route legacy IRQs of PCI devices behind this host bridge.
-  cxx::Ref_ptr _ic;
-  l4_uint64_t _ecam_mcfg_base = 0;
-  l4_uint64_t _ecam_mcfg_size = 0;
-  unsigned char _secondary_bus_num = 0;
-  unsigned char _subordinate_bus_num = 0;
-}; // class Pci_host_generic
-
-/**
- * Interface to handle IO port access to the PCI configuration space and
- * translate it to an internal protocol.
- */
-class Pci_bus_cfg_io : public Vmm::Io_device
-{
-  struct Config_address
-  {
-    l4_uint32_t raw = 0;
-    CXX_BITFIELD_MEMBER(31, 31, enabled, raw);
-    CXX_BITFIELD_MEMBER(24, 27, reghi, raw);
-    CXX_BITFIELD_MEMBER(16, 23, bus, raw);
-    CXX_BITFIELD_MEMBER(11, 15, dev, raw);
-    CXX_BITFIELD_MEMBER( 8, 10, func, raw);
-    CXX_BITFIELD_MEMBER( 2,  7, reglo, raw);
-    CXX_BITFIELD_MEMBER( 0,  1, type, raw);
-
-    unsigned reg() const
-    {
-      // the PCI standard requests the lowest two bits to be 0;
-      return (static_cast(reghi()) << 8) | (reglo() << 2);
-    }
-  };
-  Config_address _cfg_addr;
-  cxx::Ref_ptr _bus;
-
-  static Dbg trace() { return Dbg(Dbg::Pci, Dbg::Trace, "PCI bus io"); }
-  static Dbg warn() { return Dbg(Dbg::Pci, Dbg::Warn, "PCI bus io"); }
-  static Dbg info() { return Dbg(Dbg::Pci, Dbg::Info, "PCI bus io"); }
-
-  enum
-  {
-    Pci_bus_config_address    = 0,
-    Pci_bus_fwd_register      = 2,
-    Pci_bus_config_mechanism  = 3,
-    Pci_bus_config_data       = 4,
-    Pci_bus_config_data_15_8  = 5,
-    Pci_bus_config_data_31_16 = 6,
-    Pci_bus_config_data_31_24 = 7,
-  };
-
-public:
-  Pci_bus_cfg_io(cxx::Ref_ptr const &pci_bus) : _bus(pci_bus) {}
-
-  char const *dev_name() const override
-  { return "PCI bus cfg"; }
-
-  void io_out(unsigned port, Vmm::Mem_access::Width width,
-              l4_uint32_t value) override
-  {
-    using Vmm::Mem_access;
-    trace().printf("OUT access @0x%x/%d => 0x%x\n", port, width, value);
-
-    switch (port)
-      {
-      case Pci_bus_config_mechanism:
-        if (width == Mem_access::Wd8)
-          {
-            // if 1 -> PCI conf mechanism 1
-            // if 0 -> PCI conf mechanism 2 (deprecated 1992)
-            // PCI v.3 does not support mechanism 2, hence ignore and return.
-            // XXX Probing can be suppressed by adding 'pci=conf1' to the
-            // cmdline
-            return;
-          }
-        break;
-      case Pci_bus_fwd_register:
-        // identifies 1 of 256 possible PCI busses
-        // used in deprecated PCI conf mechansim 2; only byte width access
-        break;
-
-      case Pci_bus_config_address: // Configuration Space Enable - CSE
-        if (width == Mem_access::Wd32)
-          {
-            _cfg_addr.raw = value;
-            return;
-          }
-        // non 32bit width access is normal IO transaction.
-        break;
-
-      case Pci_bus_config_data_31_24:
-        [[fallthrough]];
-      case Pci_bus_config_data_15_8:
-        if (width != Mem_access::Wd8)
-          break;
-        [[fallthrough]];
-      case Pci_bus_config_data_31_16:
-        if (width == Mem_access::Wd32)
-          break;
-        [[fallthrough]];
-      case Pci_bus_config_data:
-        {
-          if (!_cfg_addr.enabled())
-            return;
-
-          unsigned reg = _cfg_addr.reg() + (port - Pci_bus_config_data);
-          if (_cfg_addr.bus() > 0 || _cfg_addr.func() > 0)
-            return;
-          _bus->cfg_space_write(_cfg_addr.dev().get(), reg, width, value);
-          return;
-        }
-      }
-
-    trace().printf("Unhandled OUT access @0x%x/%d => 0x%x\n", port,
-                   width, value);
-  }
-
-  void io_in(unsigned port, Vmm::Mem_access::Width width,
-             l4_uint32_t *value) override
-  {
-    using Vmm::Mem_access;
-    trace().printf("IN access to @0x%x/%d\n", port, width);
-
-    *value = -1;
-
-    switch (port)
-      {
-      case Pci_bus_fwd_register: // identifies 1 of 256 possible PCI busses
-        break;
-
-      case Pci_bus_config_address:
-        if (width == Mem_access::Wd32)
-          {
-            *value = _cfg_addr.raw;
-            trace().printf("IN access to PCI config space @0x%x/%d => 0x%x\n",
-                           port, width, *value);
-            return;
-          }
-        break;
-      case Pci_bus_config_data_31_24:
-        [[fallthrough]];
-      case Pci_bus_config_data_15_8:
-        if (width != Mem_access::Wd8)
-          break;
-        [[fallthrough]];
-      case Pci_bus_config_data_31_16:
-        if (width == Mem_access::Wd32)
-          break;
-        [[fallthrough]];
-      case Pci_bus_config_data:
-        {
-          if (!_cfg_addr.enabled())
-            return;
-
-          unsigned reg = _cfg_addr.reg() + (port - Pci_bus_config_data);
-          if (_cfg_addr.bus() > 0 || _cfg_addr.func() > 0)
-            {
-              *value = ~0;
-              return;
-            }
-          trace().printf("io_in: dev = %d\n", _cfg_addr.dev().get());
-          assert(_bus != nullptr);
-          *value = _bus->cfg_space_read(_cfg_addr.dev().get(),
-                                        reg, width);
-          trace().printf("IN access @0x%x/%d reg: 0x%x --> 0x%x\n", port, width,
-                         reg, *value);
-          return;
-        }
-      }
-    trace().printf("Unhandled IN access @0x%x/%d\n", port, width);
-  }
-}; // Pci_bus_cfg_io
-
-/**
- * Retrieve bridge ECAM MCFG area from the DT node's reg property.
- */
-void
-Pci_host_generic::read_ecam_area(Dt_node const &node)
-{
-
-  int res = node.get_reg_val(0, &_ecam_mcfg_base, &_ecam_mcfg_size);
-  if (res < 0)
-    {
-      _ecam_mcfg_size = 0;
-      info().printf("No ECAM MCFG window provided via reg property, "
-                    "thus ECAM is not going to be available to the guest.\n");
-    }
-
-  if (has_ecam())
-    {
-      trace().printf("ECAM MCFG window at [0x%llx, 0x%llx]\n", _ecam_mcfg_base,
-                     _ecam_mcfg_base + _ecam_mcfg_size - 1U);
-      if (_ecam_mcfg_base >= 0x100000000ULL)
-        // Linux does not accept MCFG addresses above 4GB unless a
-        // BIOS year >= 2010 is provided via DMI (see acpi_mcfg_check_entry()).
-        warn().printf(
-          "Linux will ignore ECAM MCFG window because it is above 4GB.\n");
-    }
-}
-
-void
-Pci_host_generic::init_dev_resources(Hw_pci_device *hw_dev)
-{
-  // deal with legacy IRQs
-  unsigned pin = Pci_config_consts::Interrupt_pin_unused;
-  hw_dev->cfg_read(Pci_hdr_interrupt_pin_offset, &pin,
-                   Vmm::Mem_access::Width::Wd8);
-  if (pin == Pci_config_consts::Interrupt_pin_unused)
-    {
-      info().printf("Device 0x%x has no legacy IRQs.\n", hw_dev->dev_id);
-      return;
-    }
-  if (pin < Pci_hdr_interrupt_pin_min || pin > Pci_hdr_interrupt_pin_max)
-    {
-      warn().printf("Invalid interrupt pin encoding %u\n", pin);
-      return;
-    }
-
-  unsigned line = Pci_config_consts::Interrupt_line_unknown;
-  hw_dev->cfg_read(Pci_hdr_interrupt_line_offset, &line,
-                   Vmm::Mem_access::Width::Wd8);
-  if (line == Pci_config_consts::Interrupt_line_unknown)
-    {
-      info().printf("Device 0x%x uses no legacy IRQs.\n", hw_dev->dev_id);
-      return;
-    }
-
-  int io_irq = -1;
-  unsigned char edge_triggered = 0;
-  unsigned char dummy;
-  if ((io_irq = hw_dev->dev.irq_enable(&edge_triggered, &dummy)) < 0)
-    {
-      warn().printf("Could not enable and acquire PCI device IRQ: %i\n", io_irq);
-      return;
-    }
-
-  info().printf("Device 0x%x: io provides legacy IRQ resource %i\n",
-                hw_dev->dev_id, io_irq);
-
-  _irq_router.add_route(io_irq, irq_ic(), hw_dev->dev_id, pin, line);
-
-  info().printf("  legacy IRQ mapping: %d -> %u (pin %c)\n", io_irq, line,
-                'A' + (pin - 1));
-}
-
-} } // namespace Vdev::Pci
-
-namespace {
-
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    auto warn = Dbg(Dbg::Dev, Dbg::Warn, "PCI bus");
-    auto info = Dbg(Dbg::Dev, Dbg::Info, "PCI bus");
-    info.printf("Creating host bridge\n");
-
-    unsigned char bus_start = 0, bus_end = 0;
-    if (!parse_bus_range(node, &bus_start, &bus_end))
-      {
-        warn.printf("Bus range invalid in device tree. Device not created.\n");
-        return nullptr;
-      }
-
-    cxx::Ref_ptr ic;
-    devs->get_or_create_ic(node, &ic);
-    if (!ic)
-      {
-        warn.printf("No valid interrupt controller or no 'interrupt-parent' "
-                    "property provided.\n");
-        return nullptr;
-      }
-
-    auto dev = make_device(devs, node, bus_start, bus_end,
-                                             devs->get_or_create_mc_dev(node),
-                                             ic);
-    if (!dev)
-      {
-        warn.printf("Failed to create PCI host bridge.");
-        return nullptr;
-      }
-
-    auto io_cfg_connector = make_device(dev);
-    auto region = Vmm::Io_region(0xcf8, 0xcff, Vmm::Region_type::Virtual);
-    devs->vmm()->add_io_device(region, io_cfg_connector);
-
-    if (dev->has_ecam())
-      {
-        auto ecam_cfg_connector = make_device(dev);
-        devs->vmm()->register_mmio_device(ecam_cfg_connector,
-                                          Vmm::Region_type::Virtual, node);
-      }
-
-    info.printf("Created & Registered the PCI host bridge\n");
-    return dev;
-  }
-}; // struct F
-
-static F f;
-static Device_type t = {"virt-pci-bridge", nullptr, &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/pl011.cc b/src/l4/pkg/uvmm/server/src/device/pl011.cc
deleted file mode 100644
index 05f67adf..00000000
--- a/src/l4/pkg/uvmm/server/src/device/pl011.cc
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Phillip Raffeck 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "irq.h"
-#include "irq_dt.h"
-#include "mmio_device.h"
-#include "vcon_device.h"
-
-namespace {
-
-/**
- * Emulation of a PrimeCell UART pl011.
- *
- * Baud rate, FIFO setup and DMA setup are ignored.
- *
- * To use this device e.g. under Linux add something like the following to the
- * device tree:
- * \code{.dtb}
- *   uart0: pl011_uart@30018000 {
- *       compatible = "arm,primecell", "arm,pl011";
- *       reg = <... 0x1000>;
- *       interrupts = <0 ... 4>;
- *       clocks = <&apb_dummy_pclk>;
- *       clock-names = "apb_pclk";
- *       l4vmm,vcon_cap = "log";
- *   };
- *
- *   apb_dummy_pclk: dummy_clk {
- *       compatible = "fixed-clock";
- *       #clock-cells = <0>;
- *       clock-frequency = <1000000>;
- *   };
- * \endcode
- *
- * "arm,pl011" is the compatible string used by this device. "arm,primecell" is
- * one of those in linux/Documentation/devicetree/bindings/serial/pl011.yaml.
- * Although the linux documentation states that the clock properties are
- * optional, it's impossible to add the device, if these are missing (see add
- * and probe code in linux/drivers/amba/bus.c).
- *
- * You may add 'l4vmm,vcon_cap = "log";' to the pl011 node to use a
- * different vcon. Per default the standard uvmm console is used.
- *
- * For running this successfully in Linux (around 4.19 - 5.5 era), consider
- * the required settings:
- * - The size of the reg must be 0x1000
- * - The clock must be named "apb_pclk"
- * - The clock-frequency value of apb_dummy_pclk must be at least 1000000
- *
- * On the Linux command line, add "console=ttyAMA0" to use it as the
- * console.
- *
- * For earlycon (at least with arm64), add the following to the device tree
- * (typically in the very beginning of the device tree):
- *
- * \code{.dtb}
- *   chosen {
- *       stdout-path = "serial0";
- *   };
- *   aliases {
- *     serial0 = &uart0;
- *   };
- * \endcode
- *
- * And add "earlycon" to your Linux command line.
- */
-class Pl011_mmio
-: public Vmm::Mmio_device_t,
-  public Vdev::Device,
-  public Vcon_device,
-  public L4::Irqep_t
-{
-public:
-  enum Regs
-  {
-    DR        = 0x000,
-    RSR_ECR   = 0x004,
-    FR        = 0x018,
-    IBRD      = 0x024,
-    FBRD      = 0x028,
-    LCR_H     = 0x02c,
-    CR        = 0x030,
-    IFLS      = 0x034,
-    IMSC      = 0x038,
-    RIS       = 0x03c,
-    ICR       = 0x044,
-    DMACR     = 0x048,
-    PeriphID0 = 0xfe0,
-    PeriphID1 = 0xfe4,
-    PeriphID2 = 0xfe8,
-    PeriphID3 = 0xfec,
-    PCellID0  = 0xff0,
-    PCellID1  = 0xff4,
-    PCellID2  = 0xff8,
-    PCellID3  = 0xffc,
-  };
-
-  struct Rsr_ecr_reg
-  {
-    // Reset value: 0x0
-    l4_uint32_t raw;
-    Rsr_ecr_reg() : raw(0) {}
-    explicit Rsr_ecr_reg(l4_uint32_t v) : raw(v) {}
-
-    CXX_BITFIELD_MEMBER(3, 3, oe, raw);
-    CXX_BITFIELD_MEMBER(2, 2, be, raw);
-    CXX_BITFIELD_MEMBER(1, 1, pe, raw);
-    CXX_BITFIELD_MEMBER(0, 0, fe, raw);
-  };
-
-  struct Fr_reg
-  {
-    // Reset value: 0bX10010XXX
-    // TXFE is ignored and only set here to adhere to the specification.
-    l4_uint32_t raw;
-    Fr_reg() : raw(0)
-      {
-        txfe().set(1);
-        rxfe().set(1);
-      }
-    explicit Fr_reg(l4_uint32_t v) : raw(v) {}
-
-    CXX_BITFIELD_MEMBER(7, 7, txfe, raw);
-    CXX_BITFIELD_MEMBER(4, 4, rxfe, raw);
-  };
-
-  struct Cr_reg
-  {
-    // Reset value: 0x0300
-    l4_uint32_t raw;
-    Cr_reg() : raw(0)
-      {
-        rxe().set(1);
-        txe().set(1);
-      }
-    explicit Cr_reg(l4_uint32_t v) : raw(v) {}
-
-    CXX_BITFIELD_MEMBER(9, 9, rxe, raw);
-    CXX_BITFIELD_MEMBER(8, 8, txe, raw);
-    CXX_BITFIELD_MEMBER(0, 0, enable, raw);
-  };
-
-  struct Ris_reg
-  {
-    // Reset value: 0x00-
-    l4_uint32_t raw;
-    Ris_reg()  : raw(0) {}
-    explicit Ris_reg(l4_uint32_t v) : raw(v) {}
-
-    CXX_BITFIELD_MEMBER(4, 4, rx, raw);
-  };
-
-  Pl011_mmio(cxx::Ref_ptr const &ic, int irq, L4::Cap con)
-  : Vcon_device(con), _sink(ic, irq)
-  {
-    l4_vcon_attr_t attr;
-    if (l4_error(con->get_attr(&attr)) != L4_EOK)
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "pl011")
-          .printf("WARNING: Cannot set console attributes. "
-                  "Output may not work as expected.\n");
-        return;
-      }
-
-    attr.set_raw();
-    L4Re::chksys(con->set_attr(&attr), "console set_attr");
-  }
-
-  void handle_irq()
-  {
-    _fr.rxfe().set(0);
-    _ris.rx().set(1);
-    _sink.inject();
-  }
-
-  l4_uint32_t read(unsigned reg, char size, unsigned cpu_id)
-  {
-    l4_uint32_t ret = 0;
-    int err;
-    char buf;
-    switch (reg)
-      {
-      case DR:
-        err = _con->read(&buf, 1);
-        if (err < 0)
-          {
-            Dbg(Dbg::Dev, Dbg::Warn, "pl011")
-              .printf("WARNING: Error while reading from vcon: %d\n", err);
-            _rsr_ecr.raw = 0xf; // set error code
-            ret |= (_rsr_ecr.raw & 0xf) << 8;
-            break;
-          }
-        ret = buf;
-
-        // bits 11-8 of DR are status flags
-        ret |= (_rsr_ecr.raw & 0xf) << 8;
-
-        _ris.rx().set(0);
-        _sink.ack();
-        if (err <= 1)
-          _fr.rxfe().set(1);
-        break;
-      case RSR_ECR:
-        ret = _rsr_ecr.raw;
-        break;
-      case FR:
-        // Right now only the RXFE bit is considered. All other bits are
-        // reported as 0, indicating the UART is not busy and we always accept
-        // writes.
-        ret = _fr.raw;
-        break;
-      case LCR_H:
-        // Ignore FIFO (always use character mode) and word length (use 8 bits).
-        ret = 0x60;
-        break;
-      case CR:
-        ret = _cr.raw;
-        break;
-      case IMSC:
-        ret = _imsc;
-        break;
-      case RIS:
-        ret = _ris.raw;
-        break;
-      case PeriphID0:
-        // Is also accessible as 32 bit register.
-        if (size == 4)
-          {
-            ret = 0x341011;
-            break;
-          }
-
-        ret = 0x11;
-        break;
-      case PeriphID1:
-        ret = 0x10;
-        break;
-      case PeriphID2:
-        ret = 0x34;
-        break;
-      case PeriphID3:
-        ret = 0x0;
-        break;
-      case PCellID0:
-        // Is also accessible as 32 bit register.
-        if (size == 4)
-          {
-            ret = 0xb105f00d;
-            break;
-          }
-
-        ret = 0x0d;
-        break;
-      case PCellID1:
-        ret = 0xf0;
-        break;
-      case PCellID2:
-        ret = 0x05;
-        break;
-      case PCellID3:
-        ret = 0xb1;
-        break;
-      default:
-        Dbg(Dbg::Dev, Dbg::Warn, "pl011")
-          .printf("Unhandled read: register: %x size: %u cpu: %u\n",
-                  reg, size, cpu_id);
-        break;
-      };
-
-    return ret;
-  }
-
-  void write(unsigned reg, char size, l4_uint32_t value, unsigned cpu_id)
-  {
-    char buf;
-    switch (reg)
-      {
-      case DR:
-        buf = (char)value;
-        _con->write(&buf, 1);
-        break;
-      case RSR_ECR:
-        _rsr_ecr.raw = 0x0;
-        break;
-      case IBRD:
-      case FBRD:
-        // Ignore baud rate.
-        break;
-      case LCR_H:
-        // Ignore FIFO (always use character mode) and word length (use 8 bits).
-        break;
-      case CR:
-        _cr.raw = value;
-        if (_cr.enable() && _cr.rxe())
-          attach_con_irq("pl011 device");
-        break;
-      case IFLS:
-        // FIFO setup is ignored, so just ignore the interrupt trigger level.
-        break;
-      case IMSC:
-        _imsc = value;
-        break;
-      case ICR:
-        _ris.raw &= ~value;
-        break;
-      case DMACR:
-        // Ignore DMA stuff.
-        break;
-      default:
-        Dbg(Dbg::Dev, Dbg::Warn, "pl011")
-          .printf("Unhandled write: register: %x value: %x size: %u cpu: %u\n",
-                  reg, value, size, cpu_id);
-        break;
-      };
-  }
-
-  char const *dev_name() const override { return "Pl011_mmio"; }
-
-private:
-  Vmm::Irq_sink _sink;
-
-  Rsr_ecr_reg _rsr_ecr;
-  Fr_reg _fr;
-  Cr_reg _cr;
-  l4_uint32_t _imsc = 0;
-  Ris_reg _ris;
-
-  Device *dev() { return static_cast(this); }
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info).printf("Create virtual pl011 console\n");
-
-    L4::Cap cap = Vdev::get_cap(node, "l4vmm,vcon_cap",
-                                                    L4Re::Env::env()->log());
-    if (!cap)
-      return nullptr;
-
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      L4Re::chksys(-L4_EINVAL, "PL011 requires a virtual interrupt controller");
-
-    auto c = Vdev::make_device(it.ic(), it.irq(), cap);
-    c->register_obj(devs->vmm()->registry());
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-    return c;
-  }
-};
-
-}
-
-static F f;
-static Vdev::Device_type t1 = { "arm,pl011", nullptr, &f };
-static Vdev::Device_type t2 = { "arm,sbsa-uart", nullptr, &f };
diff --git a/src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.cc b/src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.cc
deleted file mode 100644
index a25877b7..00000000
--- a/src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.cc
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright (C) 2020-2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *            Jan Klötzke 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- *
- * See docs/specs/fw_cfg.txt in Qemu sources for reference.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "io_device.h"
-#include "mem_access.h"
-#include "mmio_device.h"
-#include "qemu_fw_cfg.h"
-
-#ifdef CONFIG_BUILD_ARCH_amd64
-#include "acpi.h"
-#endif
-
-namespace {
-
-/**
- * Qemu firmware configuration device.
- *
- * The device allows guests to gain access to the hv's configuration or any
- * kind of data like boot/kernel images in a defined way. Some bootloaders make
- * use of this to setup the platform and start the guest OS.
- *
- * To enable it use a device tree entry like this:
- *
- * io:
- * \code{.dtb}
- *   qemu_fw_cfg {
- *       compatible = "l4vmm,qemu-fw-cfg";
- *       reg = <0x1 0x510 0x0c>;
- *   };
- * \endcode
- *
- * mmio:
- * \code{.dtb}
- *   qemu_fw_cfg {
- *       compatible = "qemu,fw-cfg-mmio";
- *       reg = <0x0 0xf10000 0x0 0x10>;
- *   };
- * \endcode
- *
- * The code here only implements the device serving the fw cfg data. The data
- * provider itself are implemented in separate entities. See
- * qemu_fw_cfg_boot.cc for example.
- */
-
-static Dbg warn(Dbg::Dev, Dbg::Warn, "qemu_fw_cfg");
-static Dbg info(Dbg::Dev, Dbg::Info, "qemu_fw_cfg");
-static Dbg trace(Dbg::Dev, Dbg::Trace, "qemu_fw_cfg");
-
-enum Fw_cfg_item_selectors
-{
-  // Item selectors defined by Qemu
-  Fw_cfg_signature     = 0x00,
-  Fw_cfg_if_version    = 0x01,
-  Fw_cfg_uuid          = 0x02,
-  Fw_cfg_file_dir      = 0x19,
-
-  // dynamically added entries found through Fw_cfg_file_dir start here
-  Fw_cfg_dynamic_start = 0x20,
-};
-
-enum
-{
-  Fw_cfg_version_traditional   = 1,
-  Fw_cfg_version_dma_supported = 2,
-
-  Fw_cfg_reg_selector_mmio     = 0x08,
-  Fw_cfg_reg_data_mmio         = 0x00,
-  Fw_cfg_reg_dma_addr_mmio     = 0x10,
-
-  Fw_cfg_reg_selector_io       = 0x00,
-  Fw_cfg_reg_data_io           = 0x01,
-  Fw_cfg_reg_dma_addr_io       = 0x04,
-
-  Fw_cfg_dma_control_error     = 0x01,
-  Fw_cfg_dma_control_read      = 0x02,
-  Fw_cfg_dma_control_skip      = 0x04,
-  Fw_cfg_dma_control_select    = 0x08,
-  Fw_cfg_dma_control_write     = 0x10,
-};
-
-class Fw_item
-{
-public:
-  virtual ~Fw_item() = default;
-
-  virtual char const *data() const = 0;
-  virtual size_t size() const = 0;
-};
-
-class Fw_item_ds : public Fw_item
-{
-  l4_size_t _size;
-  l4_addr_t _offset;
-  L4Re::Rm::Unique_region _ds_region;
-
-public:
-  Fw_item_ds(L4::Cap ds, size_t offset = 0, size_t size = -1)
-  {
-    auto ds_size = ds->size();
-    if (offset > ds_size)
-      offset = ds_size;
-    if (ds_size - offset < size)
-      size = ds_size - offset;
-
-    l4_addr_t pg_offset = l4_trunc_page(offset);
-    l4_addr_t in_pg_offset = offset - pg_offset;
-    size_t pg_size = l4_round_page(size + in_pg_offset);
-
-    _size = size;
-    _offset = in_pg_offset;
-    auto *e = L4Re::Env::env();
-    L4Re::chksys(e->rm()->attach(&_ds_region, pg_size,
-                                 L4Re::Rm::F::Search_addr | L4Re::Rm::F::RWX,
-                                 L4::Ipc::make_cap_rw(ds), pg_offset),
-                 "Could not attach Fw_item_ds");
-  }
-
-  char const *data() const override
-  { return _ds_region.get() + _offset; }
-
-  size_t size() const override
-  { return _size; }
-};
-
-class Fw_item_blob : public Fw_item
-{
-  std::string _blob;
-
-public:
-  Fw_item_blob() = default;
-  Fw_item_blob(std::string const &blob) : _blob(blob) {}
-  Fw_item_blob(std::string &&blob) : _blob(std::move(blob)) {}
-
-  char const *data() const override
-  { return _blob.data(); }
-
-  size_t size() const override
-  { return _blob.size(); }
-};
-
-class Fw_item_directory : public Fw_item
-{
-  struct Entry
-  {
-    l4_uint32_t size;    // big endian
-    l4_uint16_t select;  // selector key for fw_cfg item, big endian
-    l4_uint16_t reserved;
-    char name[Qemu_fw_cfg::File_name_size]; // NUL-terminated ascii
-  };
-
-  std::string _dir;
-  l4_uint16_t _num_files = 0;
-
-public:
-  Fw_item_directory() : _dir(4, '\0') {}
-
-  l4_uint16_t add_file(char const *filename, l4_uint32_t size)
-  {
-    l4_uint16_t selector = Fw_cfg_dynamic_start + _num_files++;
-
-    // append directory entry
-    Entry e;
-    e.size = htobe32(size);
-    e.select = htobe16(selector);
-    std::strncpy(e.name, filename, sizeof(e.name) - 1U);
-    _dir.append(reinterpret_cast(&e), sizeof(e));
-
-    // update header (files count)
-    l4_uint32_t num_files = htobe32(_num_files);
-    std::memcpy(&_dir[0], &num_files, sizeof(num_files));
-
-    return selector;
-  }
-
-  char const *data() const override
-  { return _dir.data(); }
-
-  size_t size() const override
-  { return _dir.size(); }
-};
-
-class Item_directory
-{
-public:
-  Item_directory()
-  {
-    _directory = new Fw_item_directory();
-    _blobs.emplace(Fw_cfg_file_dir, std::unique_ptr(_directory));
-  }
-
-  void set_item(l4_uint16_t selector, void const *data, size_t length)
-  {
-    std::string blob((char const *)data, length);
-    _blobs[selector].reset(new Fw_item_blob(std::move(blob)));
-  }
-
-  void set_item(l4_uint16_t selector, std::string const &blob)
-  {
-    _blobs[selector].reset(new Fw_item_blob(blob));
-  }
-
-  void set_item(l4_uint16_t selector, L4::Cap ds,
-                size_t offset = 0, size_t size = -1)
-  {
-    _blobs[selector].reset(new Fw_item_ds(ds, offset, size));
-  }
-
-  void set_item_u16le(l4_uint16_t selector, l4_uint16_t data)
-  {
-    data = htole16(data);
-    set_item(selector, &data, sizeof(data));
-  }
-
-  void set_item_u32le(l4_uint16_t selector, l4_uint32_t data)
-  {
-    data = htole32(data);
-    set_item(selector, &data, sizeof(data));
-  }
-
-  void add_file(char const *filename, std::string &&blob)
-  {
-    l4_uint16_t selector = _directory->add_file(filename, blob.size());
-    _blobs.emplace(selector,
-                   std::unique_ptr(new Fw_item_blob(std::move(blob))));
-  }
-
-  bool exists(l4_uint16_t selector)
-  {
-    return _blobs.count(selector) != 0;
-  }
-
-  Fw_item const *get_item(l4_uint16_t selector)
-  {
-    return _blobs[selector].get();
-  }
-
-private:
-  std::map> _blobs;
-  Fw_item_directory *_directory;
-};
-
-class Qemu_fw_if : public Vdev::Device
-{
-  struct FWCfgDmaAccess
-  {
-    // everything is given in big endian!
-    l4_uint32_t control;
-    l4_uint32_t length;
-    l4_uint64_t address;
-  };
-
-public:
-  static Qemu_fw_if *get()
-  {
-    return _if;
-  }
-
-  Qemu_fw_if(Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-  : _devs(devs), _ram(devs->ram())
-  {
-    if (_if)
-      L4Re::throw_error(-L4_EEXIST, "Only one Qemu_fw_if allowed");
-    _if = this;
-
-    _items.set_item(Fw_cfg_signature, "QEMU");
-    _items.set_item_u32le(Fw_cfg_if_version, Fw_cfg_version_traditional |
-                                             Fw_cfg_version_dma_supported);
-
-    for (auto *t: Qemu_fw_cfg::Provider::types)
-      t->init(_devs, node);
-  }
-
-  void init_late()
-  {
-    if (_devs)
-      {
-        for (auto *t: Qemu_fw_cfg::Provider::types)
-          t->init_late(_devs);
-        _devs = nullptr;
-      }
-  }
-
-  ~Qemu_fw_if()
-  {
-    _if = nullptr;
-  }
-
-  void set_item(l4_uint16_t selector, void const *data, size_t length)
-  { _items.set_item(selector, data, length); }
-
-  void set_item(l4_uint16_t selector, std::string const &blob)
-  { _items.set_item(selector, blob); }
-
-  void set_item(l4_uint16_t selector, L4::Cap ds,
-                size_t offset = 0, size_t size = -1)
-  { _items.set_item(selector, ds, offset, size); }
-
-  void put_file(char const *fn, char const *blob, size_t size)
-  {
-    std::string b(blob, size);
-    _items.add_file(fn, std::move(b));
-  }
-
-protected:
-  Vdev::Device_lookup *_devs;
-  cxx::Ref_ptr _ram;
-  int _selector = Fw_cfg_signature;
-  l4_size_t _offset = 0;
-  l4_uint64_t _dma_addr = 0; // big-endian!
-  Item_directory _items;
-
-  void handle_dma_access()
-  {
-    l4_addr_t dma_addr = be64toh(_dma_addr);
-    volatile struct FWCfgDmaAccess *dma
-      = _ram
-      ->guest2host(Vmm::Guest_addr(dma_addr));
-    _dma_addr = 0;
-
-    l4_uint32_t control = be32toh(dma->control);
-    l4_uint32_t length  = be32toh(dma->length);
-    l4_addr_t   address = be64toh(dma->address);
-
-    l4_addr_t target_address =
-      _ram->guest2host(Vmm::Guest_addr(address));
-
-    trace.printf("DMA Transfer Control @ 0x%lx: %x, Length: %d, Address: 0x%lx\n",
-                 dma_addr, control, length, address);
-
-    if (control & Fw_cfg_dma_control_select)
-      {
-        _selector = control >> 16;
-        _offset = 0;
-      }
-    else if (control & Fw_cfg_dma_control_write)
-      {
-        warn.printf("DMA command: writes not supported\n");
-        dma->control = htobe32(Fw_cfg_dma_control_error);
-      }
-    else // read/skip
-      {
-        Fw_item const *item = nullptr;
-        if (_items.exists(_selector))
-          {
-            item = _items.get_item(_selector);
-            l4_size_t size = item->size();
-            if (size - _offset < length)
-              length = size - _offset;
-          }
-        else
-          warn.printf("DMA transfer: unknown selector: 0x%x\n", _selector);
-
-        if (control & Fw_cfg_dma_control_read)
-          {
-            if (item)
-              memcpy(reinterpret_cast(target_address),
-                     item->data() + _offset, length);
-            else
-              memset(reinterpret_cast(target_address), 0, length);
-          }
-
-        _offset += length;
-        dma->control = 0;
-      }
-  }
-
-  l4_umword_t handle_pio_access(char size)
-  {
-    if (!_items.exists(_selector))
-      {
-        warn.printf("PIO transfer: unsupported selector: 0x%x\n", _selector);
-        return 0;
-      }
-
-    auto const *item = _items.get_item(_selector);
-    l4_size_t read_size = 1U << size;
-    l4_size_t item_size = item->size();
-    if (item_size - _offset < read_size)
-      read_size = item_size - _offset;
-
-    // Use bounce buffer because of potentially unaligned and/or truncated
-    // access. Out-of-bounds reads return 0.
-    union {
-      l4_uint8_t u8;
-      l4_uint16_t u16;
-      l4_uint32_t u32;
-      l4_uint64_t u64;
-    } buf;
-    memset(&buf, 0, sizeof(buf));
-    memcpy(&buf, item->data() + _offset, read_size);
-    _offset += read_size;
-
-    switch (size)
-      {
-        case 0: return buf.u8;
-        case 1: return buf.u16;
-        case 2: return buf.u32;
-        case 3: return buf.u64;
-        default: assert(false); break;
-      }
-
-    return 0; // not reached
-  }
-
-private:
-  static Qemu_fw_if *_if; /// singleton instance
-};
-
-Qemu_fw_if *Qemu_fw_if::_if;
-
-class Qemu_fw_if_mmio
-: public Qemu_fw_if,
-  public Vmm::Mmio_device_t
-{
-public:
-  Qemu_fw_if_mmio(Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-  : Qemu_fw_if(devs, node)
-  {}
-
-  l4_umword_t read(unsigned reg, char size, unsigned /* cpu_id */)
-  {
-    trace.printf("read reg=%x size=%d\n", reg, size);
-
-    init_late();
-
-    l4_uint32_t value = 0;
-    switch (reg)
-      {
-      case Fw_cfg_reg_selector_mmio:
-        value = htobe16(_selector);
-        break;
-      case Fw_cfg_reg_data_mmio:
-        value = handle_pio_access(size);
-        break;
-      case Fw_cfg_reg_dma_addr_mmio:
-        value =
-          Vmm::Mem_access::read_width(reinterpret_cast("QEMU CFG"),
-                                      size);
-        break;
-      default:
-        warn.printf("Unknown register: %u\n", reg);
-        break;
-      }
-
-    return value;
-  }
-
-  void write(unsigned reg, char size, l4_umword_t value, unsigned /* cpu_id */)
-  {
-    trace.printf("write reg=%x size=%d value=0x%lx\n", reg, size, value);
-
-    init_late();
-
-    switch (reg)
-      {
-      case Fw_cfg_reg_selector_mmio:
-        _selector = be16toh(value);
-        _offset = 0;
-        break;
-      case Fw_cfg_reg_dma_addr_mmio:
-        Vmm::Mem_access::write_width(reinterpret_cast(&_dma_addr),
-                                     value, size);
-        if (size >= 3)
-          handle_dma_access();
-        break;
-      case Fw_cfg_reg_dma_addr_mmio + 4:
-        Vmm::Mem_access::write_width(reinterpret_cast(&_dma_addr) + 4U,
-                                     value, size);
-        handle_dma_access();
-        break;
-      case Fw_cfg_reg_data_mmio:
-        // writes not supported
-        break;
-      default:
-        warn.printf("Unknown register: %u\n", reg);
-        break;
-      }
-  }
-
-  char const *dev_name() const override { return "Qemu_fw_if_mmio"; }
-};
-
-class Qemu_fw_if_io
-: public Qemu_fw_if,
-#ifdef CONFIG_BUILD_ARCH_amd64
-  public Acpi::Acpi_device,
-#endif
-  public Vmm::Io_device
-{
-public:
-  Qemu_fw_if_io(Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-  : Qemu_fw_if(devs, node)
-  {
-    int res = node.get_reg_io(0, &_base, &_size);
-    if (res < 0)
-      L4Re::throw_error(-L4_EINVAL, "Reg value is valid.");
-  }
-
-  char const *dev_name() const override
-  { return "Firmware interface"; }
-
-  /* IO write from the guest to device */
-  void io_out(unsigned port, Vmm::Mem_access::Width width, l4_uint32_t value) override
-  {
-    trace.printf("OUT port=%d width=%d value=0x%x\n", port, width, value);
-
-    init_late();
-
-    switch (port)
-      {
-      case Fw_cfg_reg_selector_io:
-
-        _selector = value;
-        _offset = 0;
-        break;
-      case Fw_cfg_reg_dma_addr_io:
-        Vmm::Mem_access::write_width(reinterpret_cast(&_dma_addr),
-                                     value, width);
-        break;
-      case Fw_cfg_reg_dma_addr_io + 4:
-        Vmm::Mem_access::write_width(reinterpret_cast(&_dma_addr) + 4U,
-                                     value, width);
-        handle_dma_access();
-        break;
-      case Fw_cfg_reg_data_io:
-        // writes not supported
-        break;
-      default:
-        warn.printf("Unknown port: %u\n", port);
-      }
-  }
-
-  /* IO read from the guest */
-  void io_in(unsigned port, Vmm::Mem_access::Width width, l4_uint32_t *value) override
-  {
-    trace.printf("IN port=%d width=%d\n", port, width);
-
-    init_late();
-
-    switch (port)
-      {
-      case Fw_cfg_reg_selector_io:
-        *value = _selector;
-        break;
-      case Fw_cfg_reg_data_io:
-        *value = handle_pio_access(width);
-        break;
-      default:
-        warn.printf("Unknown port: %u\n", port);
-        *value= -1U;
-      }
-  }
-
-#ifdef CONFIG_BUILD_ARCH_amd64
-  /**
-   * Expose the device via DSDT to be discoverable via ACPI. Generated from the
-   * following ASL:
-   *
-   * DefinitionBlock ("qemu0002.aml", "DSDT", 1, "UVMM  ", "KERNKONZ", 4) {
-   *   Scope (\_SB.PCI0) {
-   *     Device (FWCF) {
-   *       Name (_HID, "QEMU0002")
-   *       Name (_STA, 0x0B)
-   *       Name (_CRS, ResourceTemplate () {
-   *         IO (Decode16, 0x510, 0x510, 0x01, 0x0c)
-   *       })
-   *     }
-   *   }
-   * }
-   *
-   * Conversion (save above as qemu0002.asl):
-   *   $ iasl qemu0002.aml
-   *   $ xxd -i -s 0x24 -c 8 qemu0002.aml
-   *
-   * \note Because of the (\_SB.PCI0) scope, this needs to be a late amendment.
-   *       The PCI0 device is defined in device/pci_host_generic.cc.
-   */
-  l4_size_t amend_dsdt_late(void *buf, l4_size_t max_size) const override
-  {
-    unsigned char dsdt_fwcf[] = {
-      /* 0x00 */ 0x10, 0x3a, 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x50,
-      /* 0x08 */ 0x43, 0x49, 0x30, 0x5b, 0x82, 0x2e, 0x46, 0x57,
-      /* 0x10 */ 0x43, 0x46, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0d,
-      /* 0x18 */ 0x51, 0x45, 0x4d, 0x55, 0x30, 0x30, 0x30, 0x32,
-      /* 0x20 */ 0x00, 0x08, 0x5f, 0x53, 0x54, 0x41, 0x0a, 0x0b,
-      /* 0x28 */ 0x08, 0x5f, 0x43, 0x52, 0x53, 0x11, 0x0d, 0x0a,
-      /* 0x30 */ 0x0a, 0x47, 0x01,
-
-      // I/O resource
-      /* 0x33 */ 0x10, 0x05, // AddressMin
-      /* 0x35 */ 0x10, 0x05, // AddressMax
-      /* 0x37 */ 0x01,       // AddressAlignment
-      /* 0x38 */ 0x0c,       // RangeLength
-
-      /* 0x39 */ 0x79, 0x00
-    };
-
-    l4_size_t size = sizeof(dsdt_fwcf);
-    if (max_size < size)
-      L4Re::throw_error(-L4_ENOMEM,
-        "Not enough space in DSDT ACPI table for firmware configuration device.");
-
-    // Update the I/O resource
-    *reinterpret_cast(&dsdt_fwcf[0x33]) = _base;
-    *reinterpret_cast(&dsdt_fwcf[0x35]) = _base;
-    dsdt_fwcf[0x38] = _size;
-
-    std::memcpy(buf, &dsdt_fwcf, size);
-    return size;
-  }
-#endif
-
-private:
-  l4_uint64_t _base;
-  l4_uint64_t _size;
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    cxx::Ref_ptr ret;
-
-    if (Vmm::Guest::Has_io_space)
-      {
-        auto dev = cxx::Ref_ptr(new Qemu_fw_if_io(devs, node));
-        devs->vmm()->register_io_device(dev, Vmm::Region_type::Virtual, node);
-        ret = dev;
-      }
-    else
-      {
-        auto dev = cxx::Ref_ptr(new Qemu_fw_if_mmio(devs, node));
-        devs->vmm()->register_mmio_device(dev, Vmm::Region_type::Virtual, node);
-        ret = dev;
-      }
-
-    return ret;
-  }
-};
-
-static F f;
-static Vdev::Device_type t = { Vmm::Guest::Has_io_space ? "l4vmm,qemu-fw-cfg"
-                                                        : "qemu,fw-cfg-mmio",
-                               nullptr, &f};
-} // namespace
-
-// Public interface
-cxx::H_list_t Qemu_fw_cfg::Provider::types(true);
-
-void
-Qemu_fw_cfg::set_item(l4_uint16_t selector, std::string const &blob)
-{
-  if (auto *d = Qemu_fw_if::get())
-    d->set_item(selector, blob);
-}
-
-void
-Qemu_fw_cfg::set_item(l4_uint16_t selector, L4::Cap ds,
-                  size_t offset, size_t size)
-{
-  if (auto *d = Qemu_fw_if::get())
-    d->set_item(selector, ds, offset, size);
-}
-
-void
-Qemu_fw_cfg::set_item(l4_uint16_t selector, void const *data, size_t length)
-{ set_item(selector, std::string((char const *)data, length)); }
-
-void
-Qemu_fw_cfg::set_item_u16le(l4_uint16_t selector, l4_uint16_t data)
-{
-  data = htole16(data);
-  set_item(selector, &data, sizeof(data));
-}
-
-void
-Qemu_fw_cfg::set_item_u32le(l4_uint16_t selector, l4_uint32_t data)
-{
-  data = htole32(data);
-  set_item(selector, &data, sizeof(data));
-}
-
-void
-Qemu_fw_cfg::put_file(char const *fn, char const *blob, size_t size)
-{
-  if (auto *d = Qemu_fw_if::get())
-    d->put_file(fn, blob, size);
-  else
-    warn.printf("Warning: Did not add '%s' because the Qemu_fw_if device does "
-                "not exist yet. Please ensure the device node of Qemu_fw_if "
-                "comes before the device serving '%s' in the device tree.\n",
-                fn, fn);
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.h b/src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.h
deleted file mode 100644
index df059d7e..00000000
--- a/src/l4/pkg/uvmm/server/src/device/qemu_fw_cfg.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020-2022, 2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *            Jan Klötzke 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "vm.h"
-
-#include 
-#include 
-
-/**
- * Qemu standardized interface to supply information from VMM to guest.
- */
-namespace Qemu_fw_cfg {
-
-struct Provider : public cxx::H_list_item_t
-{
-  Provider()
-  { types.push_front(this); }
-
-  virtual void init(Vdev::Device_lookup * /*devs*/, Vdev::Dt_node const & /*node*/) {};
-  virtual void init_late(Vdev::Device_lookup * /*devs*/) {};
-
-  static cxx::H_list_t types;
-};
-
-enum { File_name_size = 56 };
-
-void set_item(l4_uint16_t selector, std::string const &blob);
-void set_item(l4_uint16_t selector, L4::Cap ds,
-              size_t offset = 0, size_t size = -1);
-void set_item(l4_uint16_t selector, void const *data, size_t length);
-void set_item_u16le(l4_uint16_t selector, l4_uint16_t data);
-void set_item_u32le(l4_uint16_t selector, l4_uint32_t data);
-
-void put_file(char const *fn, char const *blob, size_t size);
-template
-void put_file(char const *fn, T &blob)
-{ put_file(fn, blob.data(), blob.size()); }
-
-};
diff --git a/src/l4/pkg/uvmm/server/src/device/rom.cc b/src/l4/pkg/uvmm/server/src/device/rom.cc
deleted file mode 100644
index 4d362bcb..00000000
--- a/src/l4/pkg/uvmm/server/src/device/rom.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-
-namespace {
-
-/**
- * Device for adding dataspaces readonly to the guest.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   rom@ffc84000 {
- *       compatible = "l4vmm,rom";
- *       reg = <0x0 0xffc84000 0x0 0x37c000>;
- *       l4vmm,dscap = "bios";
- *   };
- * \endcode
- *
- * l4vmm,dscap is mandatory and points to the dataspace cap to use.
- */
-class Rom
-: public Vdev::Device
-{};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    auto warn = Dbg(Dbg::Dev, Dbg::Warn, "ROM");
-    auto dscap = Vdev::get_cap(node, "l4vmm,dscap");
-    if (!dscap)
-      {
-        warn.printf("Missing 'l4vmm,dscap' property!\n");
-        return nullptr;
-      }
-
-    l4_uint64_t base, size;
-    int res = node.get_reg_val(0, &base, &size);
-    if (res < 0)
-      {
-        warn.printf("Missing 'reg' property for node %s\n", node.get_name());
-        return nullptr;
-      }
-
-    if (size > dscap->size())
-      {
-        warn.printf("Dataspace smaller than reg window. Unsupported.\n");
-        return nullptr;
-      }
-
-    devs->ram()->add_memory_region(dscap, Vmm::Guest_addr(base), 0, size,
-                                   devs->vmm()->memmap(), L4Re::Rm::F::RX);
-
-    return Vdev::make_device();
-  }
-};
-
-}
-
-static F f;
-static Vdev::Device_type t = { "l4vmm,rom", nullptr, &f };
diff --git a/src/l4/pkg/uvmm/server/src/device/rtc-hub.cc b/src/l4/pkg/uvmm/server/src/device/rtc-hub.cc
deleted file mode 100644
index e53765f2..00000000
--- a/src/l4/pkg/uvmm/server/src/device/rtc-hub.cc
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2022, 2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "rtc-hub.h"
-Vdev::L4rtc_adapter *Vdev::L4rtc_hub::_adapter = nullptr;
-l4_uint64_t Vdev::L4rtc_hub::_offset = 0;
diff --git a/src/l4/pkg/uvmm/server/src/device/rtc-hub.h b/src/l4/pkg/uvmm/server/src/device/rtc-hub.h
deleted file mode 100644
index c56e0c2b..00000000
--- a/src/l4/pkg/uvmm/server/src/device/rtc-hub.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2021-2022, 2024 Kernkonzept GmbH.
- * Author(s): Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-/**
- * Central hub that allows to connect external wallclock time source.
- */
-#pragma once
-
-#include 
-#include  // l4_kip_clock_ns()
-#include  // l4re_kip()
-
-namespace Vdev {
-
-class L4rtc_adapter
-{
-public:
-  virtual l4_uint64_t ns_since_epoch() = 0;
-  virtual void set_ns_since_epoch(l4_uint64_t ns_offset) = 0;
-};
-
-class L4rtc_hub
-{
-  static L4rtc_adapter *_adapter;
-  static l4_uint64_t _offset;
-
-public:
-  static void invalidate()
-  { _adapter = nullptr; }
-
-  static l4_uint64_t ns_since_epoch()
-  {
-    if (_adapter)
-      return _adapter->ns_since_epoch();
-    return _offset + l4_kip_clock_ns(l4re_kip());
-  }
-
-  static void set_ns_since_epoch(l4_uint64_t ns)
-  {
-    if (_adapter)
-      {
-        _adapter->set_ns_since_epoch(ns);
-        return;
-      }
-    _offset = ns - l4_kip_clock_ns(l4re_kip());
-  }
-
-  static void register_adapter(L4rtc_adapter *adapter)
-  { _adapter = adapter; }
-};
-
-} // Vdev
diff --git a/src/l4/pkg/uvmm/server/src/device/sysctl.cc b/src/l4/pkg/uvmm/server/src/device/sysctl.cc
deleted file mode 100644
index b86cfcbf..00000000
--- a/src/l4/pkg/uvmm/server/src/device/sysctl.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2016-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include "mmio_device.h"
-#include "debug.h"
-#include "device.h"
-#include "device_factory.h"
-#include "guest.h"
-
-namespace {
-
-using namespace Vdev;
-
-/**
- * A simple system controller with the following functions:
- *
- *   0x00 - On write exit with the given value as exit code.
- *
- * This device can be used with the generic syscon device from
- * Linux as follows:
- *
- * \code{.dtb}
- *   vmm-syscon {
- *       #address-cells = <1>;
- *       #size-cells = <1>;
- *       compatible = "simple-bus";
- *       ranges = <0x0 0x30030000 0x4>;
- *
- *       l4syscon: syscon {
- *           compatible = "syscon", "syscon-l4vmm";
- *           reg = <0x0 0x4>;
- *           little-endian;
- *       };
- *
- *       reboot {
- *           compatible = "syscon-reboot";
- *           regmap = <&l4syscon>;
- *           offset = <0x0>;
- *           mask = <0x66>;
- *       };
- *
- *       poweroff {
- *           compatible = "syscon-poweroff";
- *           regmap = <&l4syscon>;
- *           offset = <0x0>;
- *           mask = <0x0>;
- *       };
- *   };
- * \endcode
- *
- * The `l4syscon` entry defines this system controller device itself
- * and the additional entries the exact return code with which to exit
- * the uvmm.
- *
- * Note that reboot does not really reinitialise uvmm. This
- * still needs to be done by the application that started the uvmm (usually
- * ned). The exit code is simply used as a means to notify the starter that
- * a reboot was requested.
- */
-struct System_controller : public Device
-{
-  System_controller(Vmm::Guest *vmm)
-  : _vmm(vmm)
-  {}
-
-  l4_uint32_t read(unsigned, char, unsigned)
-  { return 0; }
-
-  void write(unsigned reg, char, l4_uint32_t value, unsigned)
-  {
-    switch (reg)
-      {
-      case 0:
-        Dbg(Dbg::Dev, Dbg::Info, "sysctl")
-          .printf("Shutdown (%d) requested\n", value);
-        _vmm->shutdown(value);
-      }
-  }
-
-private:
-  Vmm::Guest *_vmm;
-};
-
-struct System_controller_mmio
-: public System_controller,
-  public Vmm::Mmio_device_t
-{
-  System_controller_mmio(Vmm::Guest *vmm)
-  : System_controller(vmm)
-  {}
-
-  char const *dev_name() const override { return "System_controller_mmio"; }
-};
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    auto syscon = make_device(devs->vmm());
-    devs->vmm()->register_mmio_device(syscon, Vmm::Region_type::Virtual, node);
-    return syscon;
-  }
-};
-
-static F f;
-static Vdev::Device_type t = { "syscon-l4vmm", nullptr, &f };
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/uart_8250.cc b/src/l4/pkg/uvmm/server/src/device/uart_8250.cc
deleted file mode 100644
index 31582af1..00000000
--- a/src/l4/pkg/uvmm/server/src/device/uart_8250.cc
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Phillip Raffeck 
- *            Steffen Liebergeld 
- *            Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "irq.h"
-#include "irq_dt.h"
-#include "io_device.h"
-#include "mmio_device.h"
-#include "vcon_device.h"
-#include "pm_device_if.h"
-
-static Dbg warn(Dbg::Mmio, Dbg::Warn, "uart_8250");
-
-namespace {
-
-/**
- * Emulation of a 8250 serial device.
- *
- * Modem status and FIFO controls are ignored.
- *
- * On x86, to use this device e.g. under Linux add something like the
- * following to the device tree:
- *
- * \code{.dtb}
- *   uart8250 {
- *       compatible = "ns8250", "uart,8250";
- *       reg = <0x0 0x0 0x0 0x0>;
- *       interrupt-parent = <&PIC>;
- *       interrupts = <4>;
- *       l4vmm,vcon_cap = "uart";
- *   };
- * \endcode
- *
- * This emulates COM0 (irq = 4, ioports 0x3f8-0x400).
- *
- * On non-x86, e.g., on Arm, use the following in the device tree:
- *
- * \code{.dtb}
- *   uart8250@30018000 {
- *       compatible = "ns8250", "uart,8250";
- *       reg = <...>;
- *       clocks = <&sysclk>;
- *       clock-names = "apb_pclk";
- *       interrupts = <0 xxx 4>;
- *       l4vmm,vcon_cap = "uart";
- *   };
- * \endcode
- *
- * "uart,8250" and "ns16550a" are the compatible string used by this
- * device. "ns8250" is one of the ones given in
- * linux/Documentation/devicetree/bindings/serial/8250.txt.
- * Instead of specifying an actual clock, a "clock-frequency" property with an
- * arbitrary value also suffices.
- *
- * The 'uart' cap is optional. If it is not there output will be through
- * uvmm log cap.
- */
-
-class Uart_8250_base
-: public Vdev::Device,
-  public Vcon_device,
-  public L4::Irqep_t,
-  public Vdev::Pm_device
-{
-  enum Regs
-  {
-    Rbr_thr_dll = 0,
-    Ier_dlm     = 1,
-    Iir         = 2,
-    Lcr         = 3,
-    Mcr         = 4,
-    Lsr         = 5,
-    Msr         = 6,
-    Scr         = 7,
-  };
-
-  /// Interrupt Enable Register. The upper 4 bits are always 0.
-  struct Ier_reg
-  {
-    l4_uint8_t raw;
-    Ier_reg() : raw(0) {}
-    explicit Ier_reg(l4_uint32_t v) : raw(v & 0xf) {}
-    void set(l4_uint8_t v) { raw = v & 0xf; }
-
-    /// Modem status interrupt. Stored but not emulated.
-    CXX_BITFIELD_MEMBER(3, 3, msi, raw);
-    /// Receive interrupt on error.
-    CXX_BITFIELD_MEMBER(2, 2, rls, raw);
-    /// Receive interrupt when data can be written.
-    CXX_BITFIELD_MEMBER(1, 1, thre, raw);
-    /// Receive interrupt when data is available for reading.
-    CXX_BITFIELD_MEMBER(0, 0, rda, raw);
-  };
-
-  /// Interrupt Identification Register.
-  struct Iir_reg
-  {
-    l4_uint8_t raw;
-    Iir_reg() : raw(1) {}
-    explicit Iir_reg(l4_uint8_t v) : raw(v) {}
-
-    /// Interrupt IDs.
-    enum Iir_id
-    {
-      Thre = 1, ///< Transmitter Holding Register is empty.
-      Rda  = 2, ///< Receiver Data is available.
-      Rls  = 3, ///< An error occurred.
-    };
-
-    /// Interrupt ID.
-    CXX_BITFIELD_MEMBER(1, 2, id, raw);
-    /// 0: interrupt is pending, 1: no interrupt pending. Set to 1 by clear().
-    CXX_BITFIELD_MEMBER(0, 0, not_pending, raw);
-
-    void set_data_irq()
-    {
-      id() = Rda;
-      not_pending() = 0;
-    }
-    bool data_irq() const { return id() == Rda; }
-
-    void set_error_irq()
-    {
-      id() = Rls;
-      not_pending() = 0;
-    }
-    bool error_irq() const { return id() == Rls; }
-
-    void set_write_irq()
-    {
-      id() = Thre;
-      not_pending() = 0;
-    }
-    bool write_irq() const { return id() == Thre; }
-
-    void clear() { raw = 1; }
-    bool cleared() const { return raw == 1; }
-  };
-
-  /// Line Control Register.
-  struct Lcr_reg
-  {
-    l4_uint8_t raw;
-    Lcr_reg() : raw(0) {}
-    explicit Lcr_reg(l4_uint8_t v) : raw(v) {}
-
-    /**
-     * Divisor Latch Access Bit.
-     *
-     * If 0, read/writes to registers 0 and 1 access RBR/THR/IER.
-     * If 1, read/writes to registers 0 and 1 access DLL/DLM.
-     */
-    CXX_BITFIELD_MEMBER(7, 7, dlab, raw);
-  };
-
-  /// Line Status Register.
-  struct Lsr_reg
-  {
-    l4_uint8_t raw;
-    Lsr_reg() : raw(0x60) {}
-    explicit Lsr_reg(l4_uint8_t v) : raw(v) {}
-
-    /// Set, when no transmission is running; clear by reading LSR.
-    CXX_BITFIELD_MEMBER(6, 6, temt, raw);
-    /// Set, when data can be written.
-    CXX_BITFIELD_MEMBER(5, 5, thre, raw);
-    /// Break interrupt.
-    CXX_BITFIELD_MEMBER(4, 4, bi, raw);
-    /// Framing error.
-    CXX_BITFIELD_MEMBER(3, 3, fe, raw);
-    /// Parity error.
-    CXX_BITFIELD_MEMBER(2, 2, pe, raw);
-    /// Overrun error.
-    CXX_BITFIELD_MEMBER(1, 1, oe, raw);
-    /// Set, when data is available for reading.
-    CXX_BITFIELD_MEMBER(0, 0, dr, raw);
-
-    void set_error()
-    {
-      bi() = 1;
-      fe() = 1;
-      pe() = 1;
-      oe() = 1;
-    }
-
-    void clear_error()
-    {
-      bi() = 0;
-      fe() = 0;
-      pe() = 0;
-      oe() = 0;
-    }
-
-    void reset() { raw = 0x40; }
-  };
-
-public:
-  Uart_8250_base(L4::Cap con, l4_uint64_t regshift,
-                 cxx::Ref_ptr const &ic, int irq)
-  : Vcon_device(con), _regshift(regshift), _sink(ic, irq),
-    _scr(0), _dll(0), _dlm(0)
-  {
-    l4_vcon_attr_t attr;
-    if (l4_error(con->get_attr(&attr)) != L4_EOK)
-      {
-        warn.printf("WARNING: Cannot set console attributes. "
-                    "Output may not work as expected.\n");
-        return;
-      }
-
-    attr.set_raw();
-    L4Re::chksys(con->set_attr(&attr), "console set_attr");
-  }
-
-  void handle_irq()
-  {
-    _lsr.dr() = 1;
-    if (!_iir.error_irq()) // error has higher prio. Don't overwrite.
-      signal_readable();
-  }
-
-  l4_uint32_t read(unsigned reg, char size, unsigned)
-  {
-    l4_uint32_t ret = 0;
-    switch (reg >> _regshift)
-      {
-      case Rbr_thr_dll:
-        ret = _lcr.dlab() ? _dll : read_char();
-        break;
-      case Ier_dlm:
-        ret = _lcr.dlab() ? _dlm : _ier.raw;
-        break;
-      case Iir:
-        ret = _iir.raw;
-        if (_iir.write_irq())
-          _iir.clear();
-
-        // The IIR may already have been clear before: This handles a rare case
-        // where the IRQ was not acknowledged but the IIR reports that no IRQ is
-        // pending.
-        if (_iir.cleared())
-          _sink.ack();
-        break;
-      case Lcr:
-        ret = _lcr.raw;
-        break;
-      case Mcr:
-        // Ignore modem control.
-        break;
-      case Lsr:
-        ret = _lsr.raw;
-        _lsr.clear_error();
-        if (_iir.error_irq())
-          {
-            _iir.clear();
-            _sink.ack();
-            // If we got input while in error state, we need to tell the guest
-            // about it.
-            if (_lsr.dr())
-              signal_readable();
-            else
-              signal_writeable();
-          }
-        break;
-      case Msr:
-        // Ignore modem status.
-        break;
-      case Scr:
-        ret = _scr;
-        break;
-      default:
-        warn.printf("Unhandled read: reg: %x size: %d\n", reg, size);
-        break;
-      };
-
-    return ret;
-  }
-
-  void write(unsigned reg, char size, l4_uint32_t value, unsigned)
-  {
-    if (!_enabled)
-      {
-        attach_con_irq("UART 8250");
-        _enabled = true;
-      }
-
-    switch (reg >> _regshift)
-      {
-      case Rbr_thr_dll:
-        if (_lcr.dlab())
-          _dll = value;
-        else
-          write_char((char)value);
-        break;
-      case Ier_dlm:
-        if (_lcr.dlab())
-          _dlm = value;
-        else
-          {
-            _ier.set(value);
-
-            if (_lsr.dr())
-              signal_readable();
-            else
-              signal_writeable();
-          }
-        break;
-      case Iir:
-        // Used by 16550 as FCR. Ignore for now.
-        break;
-      case Lcr:
-        _lcr.raw = value;
-        break;
-      case Mcr:
-        // Ignore modem control.
-        break;
-      case Lsr:
-        // LSR is intended for RO-operation. Just ignore writes.
-        break;
-      case Msr:
-        // Ignore modem status.
-        break;
-      case Scr:
-        _scr = value;
-        break;
-      default:
-        warn.printf("Unhandled write: reg: %x value: %x size: %u\n",
-                    reg, value, size);
-        break;
-      };
-  }
-
-  void pm_suspend() override
-  {
-    flush_cons();
-  }
-
-  void pm_resume() override
-  {
-    reset();
-  }
-
-private:
-  l4_uint32_t read_char()
-  {
-    _sink.ack(); // always ack the sink to allow new IRQs to pass-through it.
-
-    int err;
-    char buf = 0;
-
-    err = _con->read(&buf, 1);
-    if (err < 0)
-      {
-        warn.printf("Error while reading from vcon: %d\n", err);
-        signal_error();
-        return 0;
-      }
-
-    if (err <= 1)
-      {
-        _iir.clear();
-        _lsr.dr() = 0;
-      }
-
-    return buf;
-  }
-
-  void write_char(char c)
-  {
-    _sink.ack(); // always ack the sink to allow new IRQs to pass-through it.
-
-    if (_iir.write_irq())
-      _iir.clear(); // if the IIR got overwritten, do not change it
-
-    _con->write(&c, 1);
-
-    // check if IIR shows read data available, it has higher priority.
-    if (!_iir.cleared() && _iir.data_irq())
-      {
-        // IIR got overwritten between IIR read and THR write
-        if (_ier.rda())
-          _sink.inject();
-      }
-    else if (_iir.cleared())
-      {
-        // Nothing there to read, write has highest prio.
-        signal_writeable();
-      }
-  }
-
-  void signal_writeable()
-  {
-    _lsr.thre() = 1;
-    if (!_ier.thre())
-      return;
-
-    _iir.set_write_irq();
-    _sink.inject();
-  }
-
-  void signal_readable()
-  {
-    _lsr.dr() = 1;
-    if (!_ier.rda())
-      return;
-
-    _iir.set_data_irq();
-    _sink.inject();
-  }
-
-  void signal_error()
-  {
-    _lsr.set_error();
-    if (!_ier.rls())
-      return;
-
-    _iir.set_error_irq();
-    _sink.inject();
-  }
-
-  // Flush cons channel and drop the data to receive an IRQ on next input.
-  void flush_cons()
-  {
-    int const sz = 100;
-    char dummy[sz];
-    while (_con->read(dummy, sz) > sz)
-      ;
-
-    // clear IRQ sink
-    _sink.ack();
-  }
-
-  /**
-   * Reset the UART state.
-   *
-   * Write reset values to the registers, flush the cons channel and set the
-   * IRQ sink into cleared state.
-   */
-  void reset()
-  {
-    _ier.raw = 0;
-    _iir.clear();
-    _lsr.reset();
-    _lcr.raw = 0;
-    _scr = 0;
-    _dll = 0;
-    _dlm = 0;
-
-    flush_cons();
-  }
-
-  l4_uint64_t _regshift;
-  Vmm::Irq_sink _sink;
-  bool _enabled = false;
-
-  Ier_reg _ier;
-  Iir_reg _iir;
-  Lcr_reg _lcr;
-  Lsr_reg _lsr;
-  l4_uint8_t _scr;
-  l4_uint8_t _dll;
-  l4_uint8_t _dlm;
-
-  Device *dev() { return static_cast(this); }
-};
-
-class Uart_8250_mmio
-: public Vmm::Mmio_device_t,
-  public Uart_8250_base
-{
-public:
-  Uart_8250_mmio(L4::Cap con, l4_uint64_t regshift,
-                 cxx::Ref_ptr const &ic, int irq)
-  : Uart_8250_base(con, regshift, ic, irq)
-  {}
-
-  char const *dev_name() const override { return "Uart_8250_mmio"; }
-};
-
-class Uart_8250_io
-: public Vmm::Io_device,
-  public Uart_8250_base
-{
-public:
-  Uart_8250_io(L4::Cap con, cxx::Ref_ptr const &ic, int irq)
-  : Uart_8250_base(con, 0, ic, irq)
-  {}
-
-  char const *dev_name() const override
-  { return "UART 8250"; }
-
-  void io_in(unsigned reg, Vmm::Mem_access::Width width, l4_uint32_t *value) override
-  {
-    *value = read(reg, 1 << width, 0);
-  }
-
-  void io_out(unsigned reg, Vmm::Mem_access::Width width, l4_uint32_t value) override
-  {
-    write(reg, 1 << width, value, 0);
-  }
-};
-
-struct F : Vdev::Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info, "uart_8250").printf("Create virtual 8250 console\n");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,vcon_cap",
-                                       L4Re::Env::env()->log());
-    if (!cap)
-      return nullptr;
-
-    int regshift_size;
-    fdt32_t const *regshift_prop = node.get_prop("reg-shift",
-                                                          ®shift_size);
-    l4_uint64_t regshift = 0;
-    if (regshift_prop)
-      regshift = node.get_prop_val(regshift_prop, regshift_size, true);
-
-
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      L4Re::chksys(-L4_EINVAL, "Uart 8250 requires a virtual interrupt controller");
-
-    if (Vmm::Guest::Has_io_space) // Differentiate node types (MMIO or port-IO) here
-      {
-        auto region = Vmm::Io_region(0x3f8, 0x3ff, Vmm::Region_type::Virtual);
-        auto c = Vdev::make_device(cap, it.ic(), it.irq());
-        c->register_obj(devs->vmm()->registry());
-        devs->vmm()->add_io_device(region, c);
-        return c;
-      }
-    else
-      {
-        auto c = Vdev::make_device(cap, regshift, it.ic(),
-                                                   it.irq());
-        c->register_obj(devs->vmm()->registry());
-        devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-        return c;
-      }
-  }
-};
-
-static F f;
-static Vdev::Device_type t1 = { "uart,8250", nullptr, &f };
-static Vdev::Device_type t2 = { "ns16550a", nullptr, &f };
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/virq.cc b/src/l4/pkg/uvmm/server/src/device/virq.cc
deleted file mode 100644
index 32ccd251..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virq.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter ,
- *            Alexander Warg ,
- *            Frank Mehnert 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-
-#include "device_factory.h"
-#include "guest.h"
-#include "irq.h"
-#include "irq_dt.h"
-#include "mmio_device.h"
-
-namespace {
-
-using namespace Vdev;
-
-/**
- * Device for relaying L4 interrupts into the guest.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   virq {
- *       compatible = "l4vmm,virq-rcv";
- *       l4vmm,virqcap = "irqcap";
- *       interrupts = <0 140 4>;
- *   };
- * \endcode
- *
- * `l4vmm,virqcap` is mandatory and needs to point to a capability
- * implementing an L4::Irq interface. If there is no capability with
- * the given name, then the device will be disabled.
- *
- * The device tree also must define exactly one interrupt in the
- * usual way.
- *
- * Interrupt relayed in this way do not need to be acknowledged by the
- * guest.
- */
-class Irq_rcv
-: public L4::Irqep_t,
-  public Device
-{
-public:
-  Irq_rcv(cxx::Ref_ptr const &ic, unsigned irq) : _sink(ic, irq) {}
-
-  void handle_irq()
-  { _sink.inject(); }
-
-private:
-  // Use an edge sink since we do not need any EOI handling and do not want to
-  // explicitly ACK interrupts on the Irq_*_sink
-  Vmm::Irq_edge_sink _sink;
-};
-
-
-struct F_rcv : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    auto cap = Vdev::get_cap(node, "l4vmm,virqcap");
-    if (!cap)
-      return nullptr;
-
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0)
-      return nullptr;
-
-    if (!it.ic_is_virt())
-      L4Re::chksys(-L4_EINVAL, "Irq_rcv requires a virtual interrupt controller");
-
-    auto c = make_device(it.ic(), it.irq());
-    auto res = devs->vmm()->registry()->register_obj(c.get(), cap);
-    if (!res.is_valid())
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "Virq")
-          .printf("Failed to register Virq on %s.l4vmm,virqcap: %s\n",
-                  node.get_name(), l4sys_errtostr(res.cap()));
-        L4Re::chkcap(res, "Register object", -L4_EINVAL); // does not return
-      }
-    return c;
-  }
-};
-
-static F_rcv f_rcv;
-static Device_type t_rcv = { "l4vmm,virq-rcv", nullptr, &f_rcv };
-
-/**
- * Device for triggering L4 interrupts from the guest.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   virq@0x10000000 {
- *       compatible = "l4vmm,virq-snd";
- *       reg = <0x10000000 0x4>;
- *       l4vmm,virqcap = "irqcap";
- *   };
- * \endcode
- *
- * `l4vmm,virqcap` is mandatory and needs to point to a capability
- * implementing an L4::Irq interface. If there is no capability with
- * the given name, then the device will be disabled.
- *
- * The interrupt is triggered by writing to any address in the region
- * specified by the first `reg` entry.
- */
-
-class Irq_snd : public Device, public Vmm::Mmio_device_t
-{
-public:
-  explicit Irq_snd(L4::Cap irq) : _irq(irq) {}
-
-  void write(unsigned /*reg*/, char /*size*/, l4_uint64_t /*value*/, unsigned)
-  {
-    /* address does no matter */
-    _irq->trigger();
-  }
-
-  l4_uint32_t read(unsigned /*reg*/, char /*size*/, unsigned /*cpu_id*/)
-  {
-    return 0;
-  }
-
-  char const *dev_name() const override { return "Irq_snd"; }
-
-private:
-  L4::Cap _irq;
-};
-
-struct F_snd : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    auto cap = Vdev::get_cap(node, "l4vmm,virqcap");
-    if (!cap)
-      return nullptr;
-
-    auto c = make_device(cap);
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-    return c;
-  }
-};
-
-static F_snd f_snd;
-static Device_type t_snd = { "l4vmm,virq-snd", nullptr, &f_snd };
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.cc b/src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.cc
deleted file mode 100644
index e3efde05..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "device_factory.h"
-#include "virtio_device_mem_pool.h"
-
-namespace {
-
-using namespace Vdev;
-
-class F : public Factory
-{
-public:
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    Dbg info(Dbg::Dev, Dbg::Info, "viodev-mp");
-
-    l4_uint64_t phys, size;
-    if (node.get_reg_val(0, &phys, &size) < 0)
-      L4Re::throw_error(-L4_EINVAL, "reg property not found or invalid");
-
-    auto c = Vdev::make_device(devs, phys, size);
-
-    info.printf("%s: virtio device memory pool registered [0x%llx:0x%llx]\n",
-                node.get_name(), phys, size);
-
-    return c;
-  }
-};
-
-static F f;
-static Device_type t1 = { "l4vmm,mempool", nullptr, &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.h b/src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.h
deleted file mode 100644
index fc970315..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_device_mem_pool.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include "debug.h"
-#include 
-#include 
-#include 
-#include "guest.h"
-
-#include 
-
-namespace Vdev
-{
-
-/**
- * Memory pool for foreign guest memory used by virtio device proxy devices.
- *
- * If multiple virtio device proxy devices from the same guest are used in one
- * uvmm instance we only want to map the foreign guest memory once. Therefore
- * every virtio device proxy device needs to be registered with one virtio
- * memory pool. The virtio memory pool describes a region in guest RAM where
- * the foreign guest memory will be mapped to. Multiple guests can use the same
- * memory pool. However, multiple memory pools are also possible.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   viodev_mp: viodev_mp@1600000000 {
- *       compatible = "l4vmm,mempool";
- *       reg = <0x16 0x0 0x20 0x0>;
- *   };
- * \endcode
- *
- * A virtio device proxy device needs to refer to the pool it wants to use,
- * like this:
- *
- * \code{.dtb}
- *   viodev@80000000 {
- *       compatible = "virtio-dev,mmio";
- *       ...
- *       l4vmm,mempool = <&viodev_mp>;
- *       ...
- *   }
- * \endcode
- *
- * Note, the memory pool node has to be defined before any other nodes using
- * it.
- */
-
-class Virtio_device_mem_pool : public Device
-{
-public:
-  Virtio_device_mem_pool(Vdev::Device_lookup *devs,
-                         l4_uint64_t phys, l4_uint64_t size)
-  : _devs(devs), _phys(phys), _size(size)
-  {}
-
-  Vmm::Region register_ds(L4::Cap const &ds,
-                          l4_uint64_t ds_base, l4_umword_t offset, l4_umword_t sz)
-  {
-    // Check if we know this region already
-    for (auto const &c: _regions)
-      if (c.ds_base == ds_base && c.offset == offset && c.sz == sz &&
-          L4Re::Env::env()->task()->cap_equal(c.ds.get(), ds).label() == 1)
-        return c.region;
-
-    // This is a very simple memory manager. It always adds a new region behind
-    // the last known region. It does not look at any requirements for
-    // alignment or tries to fill holes. As we do not support unmapping right
-    // now, this is ok. Should be easily possible to convert this to a stl map
-    // like tree. See vm_memmap.* for inspiration.
-    Vmm::Guest_addr new_mapping = _phys;
-    if (!_regions.empty())
-      {
-        new_mapping = _regions.back().region.end + 1;
-        if (new_mapping + sz - 1 > _phys + _size - 1)
-          L4Re::throw_error(-L4_EINVAL, "New region doesn't fit into mempool");
-      }
-    info.printf("Add region: 0x%lx:0x%lx\n", new_mapping.get(), sz);
-
-    auto region = Vmm::Region::ss(new_mapping, sz, Vmm::Region_type::Virtual);
-    auto ds_mgr = cxx::make_ref_obj("Virtio_mem_pool", ds,
-                                                     offset, sz);
-    _devs->vmm()->add_mmio_device(region,
-                                  Vdev::make_device(ds_mgr));
-
-    if (_devs->ram()->as_mgr()->is_iommu_mode())
-      _devs->ram()->as_mgr()->add_ram_iommu(region.start,
-                                            ds_mgr->local_addr(),
-                                            sz);
-
-    _regions.emplace_back(ds, region, ds_base, offset, sz);
-
-    return region;
-  }
-
-private:
-  Dbg info = {Dbg::Dev, Dbg::Info, "viodev-mp"};
-
-  Vdev::Device_lookup *_devs;
-
-  struct GuestMemRegion
-  {
-    GuestMemRegion(L4::Cap const &ds, Vmm::Region const ®ion,
-                   l4_uint64_t ds_base, l4_umword_t offset, l4_umword_t sz)
-    : ds(ds),
-      region(region),
-      ds_base(ds_base),
-      offset(offset),
-      sz(sz)
-    {}
-
-    L4Re::Util::Ref_cap::Cap ds;
-    Vmm::Region region;
-    l4_uint64_t ds_base;
-    l4_umword_t offset;
-    l4_umword_t sz;
-  };
-
-  std::vector _regions;
-  Vmm::Guest_addr _phys;
-  l4_uint64_t _size;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.cc b/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.cc
deleted file mode 100644
index 6360a7b0..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "debug.h"
-#include "device_factory.h"
-#include "irq_dt.h"
-#include "virtio_device_proxy.h"
-
-namespace Vdev {
-
-/**
- * Virtio proxy for a device exported from the VMM.
- *
- * Device for emulating a virtio device for the guest. Needs a special l4
- * driver running within the guest OS.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   viodev@80000000 {
- *       compatible = "virtio-dev,mmio";
- *       // The first row holds the virtio config space. The second row is for
- *       // the l4 config space.
- *       reg = <0x0 0x82000000 0x0 0x1000>,
- *             <0x0 0x82001000 0x0 0x1000>;
- *       interrupts = <0 145 4>;
- *       l4vmm,virtiocap = "viodev0";
- *       l4vmm,mempool = <&viodev_mp>;
- *   };
- * \endcode
- *
- * viodev_mp points to the node containing the memory pool for the foreign
- * guest memory. See the virtio mem pool documentation for details.
- */
-
-class Virtio_device_proxy : public Virtio_device_proxy_base
-{
-public:
-  Virtio_device_proxy(cxx::Ref_ptr const &ic, int irq,
-                      L4::Cap ep, l4_size_t cfg_size,
-                      l4_uint64_t l4cfg_addr, l4_uint64_t l4cfg_size,
-                      Vmm::Guest *vmm,
-                      cxx::Ref_ptr mempool)
-  : Virtio_device_proxy_base(ep, cfg_size, l4cfg_size, vmm, mempool),
-   _irq_sink(ic, irq)
-  {
-    l4virtio_set_feature(mmio_local_addr()->dev_features_map,
-                         L4VIRTIO_FEATURE_VERSION_1);
-    l4virtio_set_feature(mmio_local_addr()->dev_features_map,
-                         L4VIRTIO_FEATURE_CMD_CONFIG);
-
-    // Add l4 config page to vmm map
-    vmm->add_mmio_device(Vmm::Region::ss(Vmm::Guest_addr(l4cfg_addr),
-                                         l4cfg_size, Vmm::Region_type::Virtual),
-                         _l4cfg.ds_hdlr);
-  }
-
-  void irq_kick() override
-  { _irq_sink.inject(); }
-
-  void irq_ack() override
-  { _irq_sink.ack(); }
-
-private:
-  Vmm::Irq_sink _irq_sink;
-};
-
-} // namespace Vdev
-
-namespace {
-
-using namespace Vdev;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    Dbg info(Dbg::Dev, Dbg::Info, "viodev");
-    Dbg warn(Dbg::Dev, Dbg::Warn, "viodev");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,virtiocap");
-    if (!cap)
-      {
-        warn.printf("%s: failed to read 'l4vmm,virtiocap'\n", node.get_name());
-        return nullptr;
-      }
-
-    l4_uint64_t cfg_addr, cfg_size;
-    if (node.get_reg_val(0, &cfg_addr, &cfg_size) < 0)
-      {
-        warn.printf("%s: reg entry for config window not found\n",
-                    node.get_name());
-        return nullptr;
-      }
-
-    l4_uint64_t l4cfg_addr, l4cfg_size;
-    if (node.get_reg_val(1, &l4cfg_addr, &l4cfg_size) < 0)
-      {
-        warn.printf("%s: reg entry for l4 config window not found\n",
-                    node.get_name());
-        return nullptr;
-      }
-
-    Vdev::Irq_dt_iterator it(devs, node);
-    if (it.next(devs) < 0)
-      {
-        warn.printf("%s: virtio device proxy requires interrupt setup\n",
-                    node.get_name());
-        return nullptr;
-      }
-
-    if (!it.ic_is_virt())
-      {
-        warn.printf("%s: virtio device proxy requires a virtual interrupt controller\n",
-                    node.get_name());
-        return nullptr;
-      }
-
-    cxx::Ref_ptr mempool;
-    int size = 0;
-    auto *prop = node.get_prop("l4vmm,mempool", &size);
-    if (prop && size > 0)
-      {
-        auto mp_node = node.find_phandle(*prop);
-        if (mp_node.is_valid())
-          mempool =
-            cxx::dynamic_pointer_cast(
-              devs->device_from_node(mp_node));
-      }
-
-    if (!mempool)
-      {
-        warn.printf("%s: virtio device memory pool device not found\n",
-                    node.get_name());
-        return nullptr;
-      }
-
-    auto c = make_device(it.ic(),
-                                              it.irq(),
-                                              cap, cfg_size,
-                                              l4cfg_addr, l4cfg_size,
-                                              devs->vmm(),
-                                              mempool);
-
-    // register as mmio device for config space
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node, 0);
-
-    info.printf("%s: virtio device proxy registered\n", node.get_name());
-    return c;
-  }
-};
-
-static F f;
-static Device_type t = { "virtio-dev,mmio", nullptr, &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.h b/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.h
deleted file mode 100644
index 61472272..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "irq_dt.h"
-#include "mmio_device.h"
-#include "virtio_device_mem_pool.h"
-
-namespace Vdev {
-
-/**
- * Virtio proxy for a device exported from the VMM.
- *
- * The device allocates a page for the L4virtio config page and maps it
- * read-only into the guest at the first reg address configured in the
- * device tree. The page is initially empty. The guest is expected to fill
- * in the initial device information and at the very end write the magic
- * value indicating that the config page is ready. At this point the
- * proxy will allow a client to register itself.
- *
- * The device tree must provide a second address for a l4 specific config page.
- * This will be used for the guest memory configuration.
- *
- * set_status and config_queue use the standard cmd configuration interface
- * of the L4virtio protocol.
- *
- * Kicks by the driver are forwarded as notification interrupts to the guest.
- * The guest must acknowledge all interrupts by writing 0 to the cmd field
- * in the config page.
- *
- * The guest device may notify the driver about queue changes by writing
- * the appropriate driver_notify_index of the queue to the queue_notify field.
- */
-class Virtio_device_proxy_base
-: public Vmm::Read_mapped_mmio_device_t,
-  public L4::Epiface_t,
-  public Vdev::Device
-{
-  enum
-  {
-    L4VHOST_MAX_MEM_REGIONS = 8
-  };
-
-  struct Host_irq : public L4::Irqep_t
-  {
-    explicit Host_irq(Virtio_device_proxy_base *s) : s(s) {}
-    Virtio_device_proxy_base *s;
-    void handle_irq() { s->irq_kick(); }
-  };
-
-  struct L4_region_config
-  {
-    // C type shared with guest
-    struct Region_config_t
-    {
-      l4_uint32_t num;
-      struct
-      {
-        l4_uint64_t phys;
-        l4_uint64_t size;
-        l4_uint64_t base;
-      } region[L4VHOST_MAX_MEM_REGIONS];
-    };
-
-    L4_region_config(l4_uint64_t size)
-    {
-      auto *e = L4Re::Env::env();
-      auto ds = L4Re::chkcap(L4Re::Util::make_unique_del_cap(),
-                             "Allocate Virtio::Dev dataspace capability.");
-
-      L4Re::chksys(e->mem_alloc()->alloc(size, ds.get()),
-                   "Allocate Virtio::Dev configuration memory.");
-
-      ds_mgr = cxx::make_ref_obj("Virtio_device_proxy: l4 cfg",
-                                                  ds.get(), 0, size,
-                                                  L4Re::Rm::F::RW |
-                                                  L4Re::Rm::F::Cache_uncached);
-      ds_hdlr = Vdev::make_device(ds_mgr, L4_FPAGE_RO);
-
-      cfg_ds = std::move(ds);
-
-      get()->num = 0;
-    }
-
-    Region_config_t *get()
-    { return ds_mgr->local_addr(); }
-
-    int add_region(Vmm::Region const ®ion, l4_uint64_t base)
-    {
-      auto c = get();
-      if (c->num >= L4VHOST_MAX_MEM_REGIONS)
-        return -L4_EINVAL;
-
-      c->region[c->num].phys = region.start.get();
-      c->region[c->num].size = region.end - region.start + 1;
-      c->region[c->num].base = base;
-      ++(c->num);
-
-      return L4_EOK;
-    }
-
-    cxx::Ref_ptr ds_hdlr;
-    cxx::Ref_ptr ds_mgr;
-    L4Re::Util::Unique_del_cap cfg_ds;
-  };
-
-public:
-  Virtio_device_proxy_base(L4::Cap ep,
-                           l4_size_t cfg_size, l4_uint64_t l4cfg_size,
-                           Vmm::Guest *vmm,
-                           cxx::Ref_ptr mempool)
-  : Read_mapped_mmio_device_t("Virtio_device_proxy: vio cfg", cfg_size,
-                              L4Re::Rm::F::Cache_normal),
-    _host_irq(this), _ep(ep),
-    _vmm(vmm),
-    _l4cfg(l4cfg_size),
-    _mempool(mempool)
-  {
-    // Make sure the receive window of the main cpu server loop is large
-    // enough. Other VMs may already wait in the kernel to connect to this vio
-    // cap. We have to make sure the receive window has enough space for the
-    // RAM cap before we ever call wait_for_ipc.
-    Vmm::Generic_cpu_dev::main_vcpu().get_bm()->alloc_buffer_demand(
-      get_buffer_demand());
-  }
-
-  virtual void irq_kick() = 0;
-  virtual void irq_ack() {}
-
-  void write(unsigned reg, char width, l4_umword_t value, unsigned cpu_id)
-  {
-    (void) cpu_id;
-
-    l4_addr_t l = (l4_addr_t) mmio_local_addr() + reg;
-
-    // only naturally aligned 32bit accesses are allowed
-    if (L4_UNLIKELY(l & ((1UL << width) - 1)))
-      return;
-
-    l4_uint32_t old_value = 0;
-    if (reg == offsetof(l4virtio_config_hdr_t, cmd) ||
-        reg == offsetof(l4virtio_config_hdr_t, magic))
-      old_value = *reinterpret_cast(l);
-    else if (reg == offsetof(l4virtio_config_hdr_t, queue_notify))
-      {
-        // Acknowledge earlier queue irqs
-        irq_ack();
-        // Now kick the driver
-        mmio_local_addr()->irq_status |= L4VIRTIO_IRQ_STATUS_VRING;
-        _kick_guest_irq->trigger();
-        return; // do not actually write the value
-      }
-
-    Vmm::Mem_access::write_width(l, value, width);
-
-    if (reg >= 0x100)
-      {
-        // The guest accessed the device specific config. Make sure the cache
-        // is cleaned.
-        Vmm::Mem_access::cache_clean_data_width(l, width);
-        return;
-      }
-
-    switch (reg)
-      {
-      case offsetof(l4virtio_config_hdr_t, magic):
-        if (old_value == L4VIRTIO_MAGIC)
-          {
-            warn.printf("Virtio magic value overwritten. Reset is not handled.\n");
-            return;
-          }
-
-        if (value == L4VIRTIO_MAGIC)
-          {
-            trace.printf("Starting up vio server\n");
-            _vmm->registry()->register_irq_obj(&_host_irq);
-            _vmm->registry()->register_obj(this, _ep);
-          }
-        break;
-      case offsetof(l4virtio_config_hdr_t, cmd):
-        if (value == 0)
-          {
-            if (old_value & L4VIRTIO_CMD_MASK)
-              {
-                L4virtio::wmb();
-                mmio_local_addr()->irq_status |= L4VIRTIO_IRQ_STATUS_VRING;
-                _kick_guest_irq->trigger();
-              }
-
-            irq_ack();
-          }
-        break;
-      }
-  }
-
-  long op_register_ds(L4virtio::Device::Rights,
-                      L4::Ipc::Snd_fpage ds_cap_fp, l4_uint64_t ds_base,
-                      l4_umword_t offset, l4_umword_t sz)
-  {
-    trace.printf("Registering dataspace from 0x%llx with %lu KiB, offset 0x%lx\n",
-                 ds_base, sz >> 10, offset);
-
-    if (!ds_cap_fp.cap_received())
-      return -L4_EINVAL;
-
-    auto ds = L4::Epiface::server_iface()->rcv_cap(0);
-    if (!ds.is_valid())
-      return -L4_EINVAL;
-
-    long err = L4::Epiface::server_iface()->realloc_rcv_cap(0);
-    if (err < 0)
-      return err;
-
-    return _l4cfg.add_region(_mempool->register_ds(ds, ds_base, offset, sz),
-                             ds_base);
-  }
-
-  long op_set_status(L4virtio::Device::Rights, unsigned)
-  {
-    warn.printf("Client uses IPC notification protocol. Not supported.\n");
-    return -L4_EINVAL;
-  }
-
-  long op_config_queue(L4virtio::Device::Rights, unsigned)
-  {
-    warn.printf("Client uses IPC notification protocol. Not supported.\n");
-    return -L4_EINVAL;
-  }
-
-  long op_device_config(L4virtio::Device::Rights,
-                        L4::Ipc::Cap &config_ds,
-                        l4_addr_t &ds_offset)
-  {
-    config_ds = L4::Ipc::make_cap(mmio_ds(), L4_CAP_FPAGE_RW);
-    ds_offset = 0;
-    return L4_EOK;
-  }
-
-  long op_device_notification_irq(L4virtio::Device::Rights,
-                                  unsigned index,
-                                  L4::Ipc::Cap &irq)
-  {
-    if (index != 0)
-      return -L4_EINVAL;
-
-    irq = L4::Ipc::make_cap(_host_irq.obj_cap(), L4_CAP_FPAGE_RO);
-    return L4_EOK;
-  }
-
-  int op_bind(L4::Icu::Rights, l4_umword_t idx, L4::Ipc::Snd_fpage irq_cap_fp)
-  {
-    if (idx != 0)
-      return -L4_EINVAL;
-
-    if (!irq_cap_fp.cap_received())
-      return -L4_EINVAL;
-
-    _kick_guest_irq = L4Re::Util::Unique_cap(
-      server_iface()->rcv_cap(0));
-    if (!_kick_guest_irq.is_valid())
-      return -L4_EINVAL;
-
-    return server_iface()->realloc_rcv_cap(0);
-  }
-
-  int op_unbind(L4::Icu::Rights, l4_umword_t, L4::Ipc::Snd_fpage)
-  { return -L4_ENOSYS; }
-
-  int op_info(L4::Icu::Rights, L4::Icu::_Info &icu_info)
-  {
-    icu_info.features = 0;
-    icu_info.nr_irqs = 1;
-    icu_info.nr_msis = 0;
-
-    return L4_EOK;
-  }
-
-  int op_msi_info(L4::Icu::Rights, l4_umword_t, l4_uint64_t, l4_icu_msi_info_t &)
-  { return -L4_ENOSYS; }
-
-  int op_mask(L4::Icu::Rights, l4_umword_t)
-  { return -L4_ENOSYS; }
-
-  int op_unmask(L4::Icu::Rights, l4_umword_t)
-  { return -L4_ENOREPLY; }
-
-  int op_set_mode(L4::Icu::Rights, l4_umword_t, l4_umword_t)
-  { return -L4_ENOSYS; }
-
-protected:
-  L4Re::Util::Unique_cap _kick_guest_irq;
-  Host_irq _host_irq;
-
-  L4::Cap _ep;
-
-  Vmm::Guest *_vmm; // needed for registering DS handlers
-  L4_region_config _l4cfg;
-  cxx::Ref_ptr _mempool;
-
-private:
-  Dbg trace = {Dbg::Dev, Dbg::Trace, "viodev"};
-  Dbg warn = {Dbg::Dev, Dbg::Warn, "viodev"};
-  Dbg info = {Dbg::Dev, Dbg::Info, "viodev"};
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy_pci.cc b/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy_pci.cc
deleted file mode 100644
index 5891d1e8..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_device_proxy_pci.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "debug.h"
-#include "device_factory.h"
-#include "pci_device.h"
-#include "pci_host_bridge.h"
-#include "virtio_pci_connector.h"
-#include "event_connector_pci.h"
-
-#include "virtio_device_proxy.h"
-
-namespace Vdev {
-
-using namespace Pci;
-
-enum
-{
-  Cfg_bar = 1,
-  L4Cfg_bar = 2
-};
-
-/**
- * PCI Virtio proxy for a device exported from the VMM.
- *
- * PCI Device for emulating a virtio device for the guest. Needs a special l4
- * driver running within the guest os.
- *
- * A device tree entry needs to look like this:
- *
- * \code{.dtb}
- *   pci0: pci@aa000000 {
- *       compatible = "virt-pci-bridge";
- *       ...
- *       ranges = <0x01000000 0x0 0x00006000 0x0 0x00006000 0x0     0xa000
- *                 0x02000000 0x0 0x8a000000 0x0 0x8a000000 0x0 0x20000000
- *                 0x03000000 0x2 0x00000000 0x2 0x00000000 0x1 0x00000000>;
- *       ...
- *       virtio_dev_proxy@3 {
- *           compatible = "virtio,pci";
- *           // The reg property requirements are described in virtio_uart.
- *           // The third row holds the virtio config space.
- *           // The forth row is for the l4 config space.
- *           reg = <0x00001800 0x0 0x0 0x0 0x0000
- *                  0x02001810 0x0 0x0 0x0 0x2000
- *                  0x02001814 0x0 0x0 0x0 0x1000
- *                  0x02001818 0x0 0x0 0x0 0x1000>;
- *           msi-parent = <&msi_ctrl>;
- *           l4vmm,virtiocap = "viodev";
- *           l4vmm,vdev = "device-proxy";
- *           l4vmm,mempool = <&viodev_mp>;
- *       };
- *       ...
- *   };
- * \endcode
- *
- * viodev_mp points to the node containing the memory pool for the foreign
- * guest memory. See the virtio mem pool documentation for details.
- */
-class Virtio_device_proxy_pci
-: public Pci::Virt_pci_device,
-  public Virtio_device_proxy_base
-{
-  struct L4host_pci_cap : Pci::Vendor_specific_cap
-  {
-    explicit L4host_pci_cap()
-    : Vendor_specific_cap(sizeof(*this))
-    {}
-
-    l4_uint8_t cfg_type = 1;
-    l4_uint8_t cfg_bar;
-    l4_uint8_t l4cfg_bar;
-  };
-
-  enum
-  {
-    // PCI device id is L4Re specific
-    Virtio_pci_device_id_vhost = 50
-  };
-
-public:
-  Virtio_device_proxy_pci(Vdev::Dt_node const &node,
-                          unsigned num_msix_entries,
-                          Gic::Msix_dest const &msix_dest,
-                          Vdev::Pci::Pci_bridge_windows *wnds,
-                          L4::Cap ep,
-                          l4_size_t cfg_size, l4_uint64_t l4cfg_size,
-                          Vmm::Guest *vmm,
-                          cxx::Ref_ptr mempool)
-  : Pci::Virt_pci_device(node, wnds),
-    Virtio_device_proxy_base(ep, cfg_size, l4cfg_size, vmm, mempool),
-    _evcon(num_msix_entries, msix_dest)
-  {
-    Pci_msix_cap *cap    = create_pci_cap();
-    cap->ctrl.enabled()  = 1;
-    cap->ctrl.masked()   = 0;
-    cap->ctrl.max_msis() = num_msix_entries - 1;
-    cap->tbl.bir()       = 0;
-    cap->pba.offset()    = Vdev::Msix::msix_table_mem_size(num_msix_entries) >> 3;
-    cap->pba.bir()       = 0;
-
-    L4host_pci_cap *cap1 = create_pci_cap();
-    cap1->cfg_bar = Cfg_bar;
-    cap1->l4cfg_bar = L4Cfg_bar;
-
-    auto * const hdr = get_header();
-    hdr->vendor_id = Virtio_pci_device_vendor_id;
-    // PCI device_id is calculated by Virtio Device ID + 0x1040
-    // (see virtio 1.0 cs4)
-    hdr->device_id = Virtio_pci_device_id_base + Virtio_pci_device_id_vhost;
-    hdr->revision_id = Non_transitional_device_pci_revision_id;
-    hdr->subsystem_id = Virtio_pci_subsystem_id_minimum;
-    // hdr->subsystem_id && hdr->subsystem_vendor: virtio spec 1.0 cs4: optional
-    hdr->status = Interrupt_status_bit | Capability_list_bit;
-    hdr->header_type = Multi_func_bit;
-    hdr->classcode[2] = Pci_class_code_other_device;
-  }
-
-private:
-  Virtio::Event_connector_msix *event_connector() { return &_evcon; }
-
-  void irq_kick() override
-  { _evcon.send_event(0); }
-
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned i) override
-  {
-    if (i == 0)
-      return event_connector()->make_mmio_device();
-    else if (i == Cfg_bar)
-      return cxx::Ref_ptr(this);
-    else if (i == L4Cfg_bar)
-      return cxx::Ref_ptr(_l4cfg.ds_hdlr);
-
-    return nullptr;
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  { return nullptr; }
-
-  Virtio::Event_connector_msix _evcon;
-};
-
-} // namespace Vdev
-
-namespace {
-
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-struct Pci_factory : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    Dbg info(Dbg::Dev, Dbg::Info, "VioDevProxy");
-    Dbg warn(Dbg::Dev, Dbg::Warn, "VioDevProxy");
-
-    auto *pci = dynamic_cast(
-      devs->device_from_node(node.parent_node()).get());
-    if (!pci)
-      {
-        warn.printf("%s: no PCI bus found\n", node.get_name());
-        return nullptr;
-      }
-
-    auto cap = Vdev::get_cap(node, "l4vmm,virtiocap");
-    if (!cap)
-      {
-        warn.printf("%s: failed to read 'l4vmm,virtiocap'\n", node.get_name());
-        return nullptr;
-      }
-
-    l4_uint64_t cfg_size;
-    Dtb::Reg_flags cfg_flags;
-    auto res = node.get_reg_size_flags(Cfg_bar + 1, &cfg_size, &cfg_flags);
-    if (res < 0)
-      {
-        warn.printf("%s: failed to read 'reg[%u] = virtio cfg': %s\n",
-                      node.get_name(), Cfg_bar + 1, node.strerror(res));
-        return nullptr;
-      }
-
-    if (!cfg_flags.is_mmio())
-      {
-        warn.printf("%s: virtio cfg bar must be mmio\n", node.get_name());
-        return nullptr;
-      }
-
-    l4_uint64_t l4cfg_size;
-    Dtb::Reg_flags l4cfg_flags;
-    res = node.get_reg_size_flags(L4Cfg_bar + 1, &l4cfg_size, &l4cfg_flags);
-    if (res < 0)
-      {
-        warn.printf("%s: failed to read 'reg[%u] = l4 cfg': %s\n",
-                    node.get_name(), L4Cfg_bar + 1, node.strerror(res));
-        return nullptr;
-      }
-
-    if (!l4cfg_flags.is_mmio())
-      {
-        warn.printf("%s: l4 cfg bar must be mmio\n", node.get_name());
-        return nullptr;
-      }
-
-    cxx::Ref_ptr mempool;
-    int size = 0;
-    auto *prop = node.get_prop("l4vmm,mempool", &size);
-    if (prop && size > 0)
-      {
-        auto mp_node = node.find_phandle(*prop);
-        if (mp_node.is_valid())
-          mempool =
-            cxx::dynamic_pointer_cast(
-              devs->device_from_node(mp_node));
-      }
-
-    if (!mempool)
-      {
-        warn.printf("%s: virtio device memory pool device not found\n",
-                    node.get_name());
-        return nullptr;
-      }
-
-    auto dev_id = pci->bus()->alloc_dev_id();
-    unsigned num_msix = 1;
-    auto c =
-      make_device(node, num_msix,
-                                           pci->msix_dest(dev_id),
-                                           pci->bridge_windows(),
-                                           cap,
-                                           cfg_size, l4cfg_size,
-                                           devs->vmm(),
-                                           mempool);
-
-    pci->bus()->register_device(c, dev_id);
-
-    info.printf("%s: virtio device proxy (PCI) registered\n", node.get_name());
-    return c;
-  }
-};
-
-static Pci_factory pci_factory;
-static Vdev::Device_type pci_dt = { "virtio,pci", "device-proxy", &pci_factory };
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_input_event.cc b/src/l4/pkg/uvmm/server/src/device/virtio_input_event.cc
deleted file mode 100644
index e335dbd4..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_input_event.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2015-2018, 2022-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter  (virtio_input_power.cc)
- *            Stephan Gerhold 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#include "device_factory.h"
-#include "guest.h"
-#include "mmio_device.h"
-#include "virtio_input.h"
-
-#include "virtio_input_event.h"
-
-namespace Vdev {
-
-Event_demux &
-Event_demux::init(L4::Cap cap, L4::Registry_iface ®istry,
-                  cxx::Ref_ptr consumer)
-{
-  auto it = std::find_if(_events.begin(), _events.end(),
-                         [cap] (Event_demux &d) { return d._cap == cap; });
-  if (it == _events.end())
-    {
-      _events.emplace_front(cap, registry);
-      it = _events.begin();
-    }
-
-  it->_consumers.emplace_back(consumer);
-  return *it;
-}
-
-std::forward_list Event_demux::_events;
-
-/**
- * Virtio input device bridge for L4Re::Event. The device reads input events
- * provided by a L4Re::Event server and forwards them with virtio-input to the
- * virtual machine.
- *
- * Example device tree:
- *
- * \code{.dtb}
- *   virtio@ff900000 {
- *       compatible = "virtio,mmio";
- *       reg = <0xff900000 0x200>;
- *       interrupts = ;
- *       dma-coherent;
- *       l4vmm,vdev = "input-event";
- *       l4vmm,eventcap = "input";
- *       l4vmm,stream-id = <42>; // optional
- *   };
- * \endcode
- *
- * 'l4vmm,eventcap' must point to the name of the L4Re::Event capability
- * (or L4Re::Console if it is provided by a framebuffer server). Each virtio
- * input device can only forward events from one stream provided by the
- * L4Re::Event server (typically there is one stream for each input device,
- * such as mouse and keyboard).
- *
- * 'l4vmm,stream-id' can be used to configure a specific input stream based
- * on its stream ID. If omitted, the virtio input device is assigned the next
- * unused stream of the event capability.
- *
- * Since virtio input devices are currently not hotpluggable, uvmm needs to
- * wait during startup until all specified input devices are available.
- */
-class Virtio_input_event_mmio
-: public Virtio_input_event,
-  public Virtio_input,
-  public Vmm::Ro_ds_mapper_t,
-  public Virtio::Mmio_connector
-{
-public:
-  explicit Virtio_input_event_mmio(Vmm::Vm_ram *ram, L4::Cap cap)
-  : Virtio_input_event(cap),
-    Virtio_input(ram)
-  {}
-
-  Virtio::Event_connector_irq *event_connector()
-  { return &_evcon; }
-
-  bool queue_ready()
-  { return _vqs[0].ready(); }
-
-  void virtio_device_config_written(unsigned reg)
-  {
-    auto *dev_cfg = virtio_device_config();
-
-    switch (reg)
-      {
-      case 0:
-        break;
-      case 1:
-        virtio_input_cfg_written(dev_cfg);
-        break;
-      default:
-        Dbg(Dbg::Dev, Dbg::Warn, "input")
-          .printf("%s: Unexpected reg %d written\n", __func__, reg);
-      }
-  }
-
-  char const *dev_name() const override
-  { return "Virtio_input_event_mmio"; }
-
-private:
-  Virtio::Event_connector_irq _evcon;
-};
-
-} // namespace Vdev
-
-namespace {
-
-using namespace Vdev;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info).printf("Create virtual input event device (Mmio_factory)\n");
-    auto cap = get_cap(node, "l4vmm,eventcap");
-    if (!cap)
-      return nullptr;
-
-    int prop_size;
-    auto id_prop = node.get_prop("l4vmm,stream-id", &prop_size);
-    if (id_prop && prop_size != 1)
-      {
-        Err().printf("Invalid l4vmm,stream-id property size: %d\n", prop_size);
-        return nullptr;
-      }
-
-    auto dev = make_device(devs->ram().get(), cap);
-    if (dev->init_irqs(devs, node) < 0)
-      return nullptr;
-
-    dev->init_demux(cap, devs, dev, id_prop);
-    devs->vmm()->register_mmio_device(dev, Vmm::Region_type::Virtual, node);
-    return dev;
-  }
-};
-
-static F f;
-static Device_type t = { "virtio,mmio", "input-event", &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_input_event.h b/src/l4/pkg/uvmm/server/src/device/virtio_input_event.h
deleted file mode 100644
index 5f372974..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_input_event.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2015-2018, 2022-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter  (virtio_input_power.cc)
- *            Stephan Gerhold 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#include "virtio_input.h"
-
-namespace Vdev {
-
-/*
- * L4Re::Event bundles events from multiple "streams" (typically devices).
- * Since virtio-input always refers to a single input device, the events from
- * L4Re::Event must be de-multiplexed to one of multiple emulated virtio-input
- * devices.
- */
-
-struct Event_consumer : public virtual Vdev::Dev_ref
-{
-  virtual ~Event_consumer() {}
-  virtual void consume(L4Re::Event_buffer::Event &e) = 0;
-  virtual void notify() = 0;
-};
-
-class Event_demux : public L4::Irqep_t
-{
-public:
-  explicit Event_demux(L4::Cap cap, L4::Registry_iface ®istry)
-    : _cap(cap), _ev(), _consumers()
-  {
-    L4Re::chksys(_ev.init(cap), "Initialize event buffer");
-    L4Re::chkcap(registry.register_obj(this, irq()));
-  }
-
-  L4::Cap irq() const
-  { return L4::cap_reinterpret_cast(_ev.irq()); }
-
-  unsigned num_consumers() const
-  { return _consumers.size(); }
-
-  void wait_and_discard()
-  {
-    L4Re::chksys(irq()->receive(), "Wait for input events");
-
-    L4Re::Event_buffer::Event *e;
-    while ((e = _ev.buffer().next()))
-      e->free();
-  }
-
-  void handle_irq()
-  {
-    L4Re::Event_buffer::Event *e;
-    while ((e = _ev.buffer().next()))
-      {
-        for (auto &c : _consumers)
-          c->consume(*e);
-
-        e->free();
-      }
-
-    for (auto &c : _consumers)
-      c->notify();
-  }
-
-  static Event_demux &init(L4::Cap cap, L4::Registry_iface ®istry,
-                           cxx::Ref_ptr consumer);
-
-private:
-  L4::Cap _cap;
-  L4Re::Util::Event _ev;
-  std::vector> _consumers;
-
-  static std::forward_list _events;
-};
-
-template 
-class Virtio_input_event
-: public Event_consumer
-{
-public:
-  Virtio_input_event(L4::Cap cap)
-  : _cap(cap), _sinfo(), dirty(false)
-  {}
-
-  int init_irqs(Vdev::Device_lookup *devs, Vdev::Dt_node const &self)
-  { return dev()->event_connector()->init_irqs(devs, self); }
-
-  void init_demux(L4::Cap cap, Device_lookup *devs,
-                  cxx::Ref_ptr consumer,
-                  fdt32_t const *id_prop);
-
-  void consume(L4Re::Event_buffer::Event &e) override;
-  void notify() override;
-
-  void virtio_queue_notify(unsigned val)
-  {
-    // We do not handle the status queue and we do not keep pending events. So
-    // we do not need to do anything if queue 0 is notified (signalling the
-    // addition of buffers to the queue). We could disable notifications here
-    // but are not doing it at the moment.
-    if (val)
-      Dbg(Dbg::Dev, Dbg::Info).printf("Pending request in queue %u\n", val);
-  }
-
-  bool queue_ready();
-
-protected:
-  void virtio_input_cfg_written(l4virtio_input_config_t *dev_cfg);
-
-private:
-  DEV *dev()
-  { return static_cast(this); }
-
-  long init_idx(int idx)
-  { return _cap->get_stream_info(idx, &_sinfo); }
-
-  long init_stream_id(l4_umword_t id)
-  { return _cap->get_stream_info_for_id(id, &_sinfo); }
-
-  L4::Cap _cap;
-  L4Re::Event_stream_info _sinfo;
-  bool dirty;
-};
-
-template
-void
-Virtio_input_event::init_demux(L4::Cap cap,
-                                    Device_lookup *devs,
-                                    cxx::Ref_ptr consumer,
-                                    fdt32_t const *id_prop)
-{
-  auto &demux = Event_demux::init(cap, *devs->vmm()->registry(), consumer);
-
-  /*
-   * virtio devices are currently not hotpluggable, which means that all
-   * the information about the input device must be available before the VM
-   * is started. Depending on the L4Re::Event server this might be
-   * immediately or only once the first input event has been handled.
-   *
-   * The loops below wait until the necessary stream info are available,
-   * discarding incoming events inbetween to avoid overflowing the queue.
-   */
-  long ret;
-  if (id_prop)
-    {
-      auto id = fdt32_to_cpu(*id_prop);
-      while ((ret = init_stream_id(id)) == -L4_EINVAL)
-        demux.wait_and_discard();
-    }
-  else
-    {
-      // Use next index number
-      while ((ret = init_idx(demux.num_consumers() - 1)) == -L4_EINVAL)
-        demux.wait_and_discard();
-    }
-
-  L4Re::chksys(ret, "Initialize event stream info");
-}
-
-template
-void
-Virtio_input_event::consume(L4Re::Event_buffer::Event &e)
-{
-  if (e.payload.stream_id != _sinfo.stream_id || !dev()->queue_ready())
-    return;
-
-  l4virtio_input_event_t event{e.payload.type, e.payload.code,
-                               static_cast(e.payload.value)};
-  dev()->inject_event(event);
-  dirty = true;
-}
-
-template
-void
-Virtio_input_event::notify()
-{
-  if (!dirty)
-    return;
-
-  dev()->notify_events();
-  dirty = false;
-}
-
-template
-void
-Virtio_input_event::virtio_input_cfg_written(l4virtio_input_config_t *dev_cfg)
-{
-  switch (dev_cfg->select)
-    {
-    case L4VIRTIO_INPUT_CFG_ID_NAME:
-      static_assert(sizeof(dev_cfg->u.string) > sizeof(_sinfo.name),
-                    "virtio name smaller than L4Re one");
-      strncpy(dev_cfg->u.string, _sinfo.name, sizeof(_sinfo.name));
-      dev_cfg->size = strnlen(dev_cfg->u.string, sizeof(_sinfo.name));
-      break;
-    case L4VIRTIO_INPUT_CFG_ID_SERIAL:
-      {
-        char const id[] = "1337";
-        strncpy(dev_cfg->u.string, id, sizeof(dev_cfg->u.string));
-        dev_cfg->size = strlen(id);
-        break;
-      }
-    case L4VIRTIO_INPUT_CFG_ID_DEVIDS:
-      dev_cfg->u.ids = { _sinfo.id.bustype, _sinfo.id.vendor,
-                         _sinfo.id.product, _sinfo.id.version };
-      dev_cfg->size = sizeof(l4virtio_input_devids_t);
-      break;
-    case L4VIRTIO_INPUT_CFG_PROP_BITS:
-      memset(dev_cfg->u.bitmap, 0, sizeof(dev_cfg->u.bitmap));
-
-      static_assert(sizeof(dev_cfg->u.bitmap) >= sizeof(_sinfo.propbits),
-                    "Bitmap too small for propbits");
-      memcpy(dev_cfg->u.bitmap, _sinfo.propbits, sizeof(_sinfo.propbits));
-      dev_cfg->size = sizeof(dev_cfg->u.bitmap);
-      break;
-    case L4VIRTIO_INPUT_CFG_EV_BITS:
-      memset(dev_cfg->u.bitmap, 0, sizeof(dev_cfg->u.bitmap));
-      dev_cfg->size = 0;
-
-      if (!_sinfo.get_evbit(dev_cfg->subsel))
-        break;
-
-      switch (dev_cfg->subsel)
-        {
-        case L4RE_EV_KEY:
-          static_assert(sizeof(dev_cfg->u.bitmap) >= sizeof(_sinfo.keybits),
-                        "Bitmap too small for keybits");
-          memcpy(dev_cfg->u.bitmap, _sinfo.keybits, sizeof(_sinfo.keybits));
-          dev_cfg->size = sizeof(dev_cfg->u.bitmap);
-          break;
-        case L4RE_EV_REL:
-          static_assert(sizeof(dev_cfg->u.bitmap) >= sizeof(_sinfo.relbits),
-                        "Bitmap too small for relbits");
-          memcpy(dev_cfg->u.bitmap, _sinfo.relbits, sizeof(_sinfo.relbits));
-          dev_cfg->size = sizeof(dev_cfg->u.bitmap);
-          break;
-        case L4RE_EV_ABS:
-          static_assert(sizeof(dev_cfg->u.bitmap) >= sizeof(_sinfo.absbits),
-                        "Bitmap too small for absbits");
-          memcpy(dev_cfg->u.bitmap, _sinfo.absbits, sizeof(_sinfo.absbits));
-          dev_cfg->size = sizeof(dev_cfg->u.bitmap);
-          break;
-        case L4RE_EV_SW:
-          static_assert(sizeof(dev_cfg->u.bitmap) >= sizeof(_sinfo.swbits),
-                        "Bitmap too small for swbits");
-          memcpy(dev_cfg->u.bitmap, _sinfo.swbits, sizeof(_sinfo.swbits));
-          dev_cfg->size = sizeof(dev_cfg->u.bitmap);
-          break;
-        }
-      break;
-    case L4VIRTIO_INPUT_CFG_ABS_INFO:
-      dev_cfg->size = 0;
-      if (!_sinfo.get_evbit(L4RE_EV_ABS) || !_sinfo.get_absbit(dev_cfg->subsel))
-        break;
-
-      {
-        L4Re::Event_absinfo info{};
-        unsigned int axis = dev_cfg->subsel;
-        long ret = _cap->get_axis_info(_sinfo.stream_id, 1, &axis, &info);
-        if (ret < 0)
-          {
-            Err().printf("Failed to get axis info: %ld\n", ret);
-            break;
-          }
-
-        dev_cfg->u.abs.min = info.min;
-        dev_cfg->u.abs.max = info.max;
-        dev_cfg->u.abs.fuzz = info.fuzz;
-        dev_cfg->u.abs.flat = info.flat;
-        dev_cfg->u.abs.res = info.resolution;
-        dev_cfg->size = sizeof(dev_cfg->u.abs);
-      }
-      break;
-    default:
-      dev_cfg->size = 0;
-      break;
-  }
-
-  // Flush the complete structure instead of selectively flushing the actually
-  // used area.
-  dev()->writeback_cache(dev_cfg);
-}
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_input_event_pci.cc b/src/l4/pkg/uvmm/server/src/device/virtio_input_event_pci.cc
deleted file mode 100644
index 88f16ce3..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_input_event_pci.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2024 Kernkonzept GmbH.
- * Author(s): Martin Decky 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "pci_device.h"
-#include "pci_virtio_device.h"
-#include "pci_host_bridge.h"
-#include "virtio_pci_connector.h"
-#include "event_connector_pci.h"
-#include "virtio_input_event.h"
-
-namespace Vdev {
-
-/**
- * Virtio input device bridge for L4Re::Event. The device reads input events
- * provided by a L4Re::Event server and forwards them with virtio-input to the
- * virtual machine.
- *
- * Example device tree:
- *
- * \code{.dtb}
- *   virtio@0 {
- *       compatible = "virtio,pci";
- *       reg = <0x00000800 0x0 0x0 0x0 0x0000
- *              0x02000810 0x0 0x0 0x0 0x2000
- *              0x01000814 0x0 0x0 0x0 0x100>;
- *       msi-parent = <&msi_ctrl>;
- *       l4vmm,vdev = "input-event";
- *       l4vmm,eventcap = "input";
- *       l4vmm,stream-id = <42>; // optional
- *   };
- * \endcode
- *
- * 'l4vmm,eventcap' must point to the name of the L4Re::Event capability
- * (or L4Re::Console if it is provided by a framebuffer server). Each virtio
- * input device can only forward events from one stream provided by the
- * L4Re::Event server (typically there is one stream for each input device,
- * such as mouse and keyboard).
- *
- * 'l4vmm,stream-id' can be used to configure a specific input stream based
- * on its stream ID. If omitted, the virtio input device is assigned the next
- * unused stream of the event capability.
- *
- * Since virtio input devices are currently not hotpluggable, uvmm needs to
- * wait during startup until all specified input devices are available.
- */
-class Virtio_input_event_pci
-: public Virtio_input_event,
-  public Virtio_input,
-  public Pci::Virtio_device_pci,
-  public Virtio::Pci_connector
-{
-public:
-  explicit Virtio_input_event_pci(Vdev::Dt_node const &node,
-                                  unsigned num_msix_entries, Vmm::Vm_ram *ram,
-                                  L4::Cap cap,
-                                  Gic::Msix_dest const &msix_dest,
-                                  Vdev::Pci::Pci_bridge_windows *wnds)
-  : Virtio_input_event(cap),
-    Virtio_input(ram),
-    Virtio_device_pci(node, num_msix_entries, wnds),
-    Virtio::Pci_connector(),
-    _evcon(num_msix_entries, msix_dest)
-  {
-    init_virtio_pci_device();
-    if (device_config_len() < sizeof(l4virtio_input_config_t))
-      L4Re::throw_error(-L4_EINVAL, "device config can hold input cfg");
-  }
-
-  Virtio::Event_connector_msix *event_connector()
-  { return &_evcon; }
-
-  bool queue_ready()
-  { return _vqs[0].ready(); }
-
-  void virtio_device_config_written(unsigned)
-  {
-    l4virtio_input_config_t *dev_cfg = virtio_device_config();
-    virtio_input_cfg_written(dev_cfg);
-  }
-
-protected:
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned idx) override
-  {
-    if (idx == 0)
-      return event_connector()->make_mmio_device();
-
-    return cxx::Ref_ptr(this);
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  {
-    return cxx::Ref_ptr(this);
-  }
-
-private:
-  Virtio::Event_connector_msix _evcon;
-};
-
-} // namespace Vdev
-
-namespace {
-
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-struct Pci_factory : Factory
-{
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "Input-event-pci"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "Input-event-pci"); }
-
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info).printf("Create virtual input device (Pci factory)\n");
-
-    auto *pci = dynamic_cast(
-      devs->device_from_node(node.parent_node()).get());
-
-    if (!pci)
-      {
-        info().printf("No PCI bus found.\n");
-        return nullptr;
-      }
-
-    auto cap = get_cap(node, "l4vmm,eventcap");
-    if (!cap)
-      return nullptr;
-
-    int prop_size;
-    auto id_prop = node.get_prop("l4vmm,stream-id", &prop_size);
-    if (id_prop && prop_size != 1)
-      {
-        Err().printf("Invalid l4vmm,stream-id property size: %d\n", prop_size);
-        return nullptr;
-      }
-
-    auto dev_id = pci->bus()->alloc_dev_id();
-    unsigned num_msix = 5;
-    auto dev =
-      make_device(node, num_msix, devs->ram().get(),
-                                          cap, pci->msix_dest(dev_id),
-                                          pci->bridge_windows());
-
-    dev->init_demux(cap, devs, dev, id_prop);
-    pci->bus()->register_device(dev, dev_id);
-
-    info().printf("Input-event registered\n");
-    return dev;
-  }
-};
-
-static Pci_factory pci_factory;
-static Vdev::Device_type pci_dt = { "virtio,pci", "input-event", &pci_factory };
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_input_power.cc b/src/l4/pkg/uvmm/server/src/device/virtio_input_power.cc
deleted file mode 100644
index 8e13f509..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_input_power.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2015-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "virtio_input_power.h"
-
-namespace Vdev {
-
-//
-// Helper functions for monitor interface
-//
-static L4Re_events_key transtab[] = {
-    L4RE_KEY_0,
-    L4RE_KEY_1,
-    L4RE_KEY_2,
-    L4RE_KEY_3,
-    L4RE_KEY_4,
-    L4RE_KEY_5,
-    L4RE_KEY_6,
-    L4RE_KEY_7,
-    L4RE_KEY_8,
-    L4RE_KEY_9,
-    L4RE_KEY_A,
-    L4RE_KEY_B,
-    L4RE_KEY_C,
-    L4RE_KEY_D,
-    L4RE_KEY_E,
-    L4RE_KEY_F,
-    L4RE_KEY_G,
-    L4RE_KEY_H,
-    L4RE_KEY_I,
-    L4RE_KEY_J,
-    L4RE_KEY_K,
-    L4RE_KEY_L,
-    L4RE_KEY_M,
-    L4RE_KEY_N,
-    L4RE_KEY_O,
-    L4RE_KEY_P,
-    L4RE_KEY_Q,
-    L4RE_KEY_R,
-    L4RE_KEY_S,
-    L4RE_KEY_T,
-    L4RE_KEY_U,
-    L4RE_KEY_V,
-    L4RE_KEY_W,
-    L4RE_KEY_X,
-    L4RE_KEY_Y,
-    L4RE_KEY_Z
-};
-
-l4_uint16_t
-translate_char(unsigned char c)
-{
-  l4_uint16_t res;
-
-  if ('0' <= c && c <= '9')
-    res = transtab[c - '0'];
-  else if ('A' <= c && c <= 'Z')
-    res = transtab[c + 10U - 'A' ];
-  else if ('a' <= c && c <= 'z')
-    res = transtab[c + 10U - 'a'];
-  else
-    // map everything to space as default
-    res = L4RE_KEY_SPACE;
-
-  return res;
-}
-
-class Virtio_input_power_mmio
-: public Virtio_input_power,
-  public Virtio_input,
-  public Vmm::Ro_ds_mapper_t,
-  public Virtio::Mmio_connector
-{
-public:
-  explicit Virtio_input_power_mmio(Vmm::Vm_ram *iommu, L4::Cap con)
-  : Virtio_input_power(con),
-    Virtio_input(iommu)
-  {}
-
-  Virtio::Event_connector_irq *event_connector() { return &_evcon; }
-
-  int inject_events(l4virtio_input_event_t *events, size_t num)
-  { return Virtio_input::inject_events(events, num); }
-
-  void virtio_device_config_written(unsigned reg)
-  {
-    l4virtio_input_config_t *dev_cfg =
-      virtio_device_config();
-
-    switch(reg)
-      {
-      case 0:
-        break;
-      case 1:
-        virtio_input_cfg_written(dev_cfg);
-        break;
-      default:
-        Dbg(Dbg::Dev, Dbg::Warn, "input")
-          .printf("%s: Unexpected reg %d written\n", __func__, reg);
-      }
-  }
-
-  char const *dev_name() const override { return "Virtio_input_power_mmio"; }
-
-private:
-  Virtio::Event_connector_irq _evcon;
-};
-
-} // namespace Vdev
-
-namespace {
-
-using namespace Vdev;
-
-struct Mmio_factory : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info).printf("Create virtual input power device (Mmio_factory)\n");
-    bool monitor = node.has_prop("l4vmm,monitor");
-
-    /* Deprecation warning, added 2021-08 */
-    if (node.has_prop("l4vmm,virtiocap"))
-      Dbg(Dbg::Dev, Dbg::Warn).printf("Device tree node for Virtio console"
-                                      " contains old property 'l4vmm,virtiocap',"
-                                      " which has been renamed to 'l4vmm,vcon_cap'\n");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,vcon_cap");
-    if (!cap && !monitor)
-      return nullptr;
-
-    auto c = make_device(devs->ram().get(), cap);
-    if (c->init_irqs(devs, node) < 0)
-      return nullptr;
-
-    if (cap)
-      c->register_obj(devs->vmm()->registry());
-
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-
-    return c;
-  }
-};
-
-static Mmio_factory mmio_factory;
-static Device_type t = { "virtio,mmio", "input-power", &mmio_factory };
-}
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_input_power.h b/src/l4/pkg/uvmm/server/src/device/virtio_input_power.h
deleted file mode 100644
index 601e0275..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_input_power.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2015-2022, 2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-
-#include "virtio_input.h"
-#include "mmio_device.h"
-#include "irq.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "monitor/virtio_input_power_cmd_handler.h"
-
-#include 
-#include 
-
-#include 
-
-#include 
-#include 
-
-namespace Vdev {
-
-l4_uint16_t translate_char(unsigned char c);
-
-template 
-class Virtio_input_power
-: public L4::Irqep_t >,
-  public Monitor::Virtio_input_power_cmd_handler>
-{
-  friend Monitor::Virtio_input_power_cmd_handler>;
-
-public:
-  Virtio_input_power(L4::Cap con)
-  : _con(con) {}
-
-  int
-  init_irqs(Vdev::Device_lookup *devs, Vdev::Dt_node const &self)
-  { return dev()->event_connector()->init_irqs(devs, self); }
-
-  void register_obj(L4::Registry_iface *registry)
-  {
-    _con->bind(0, L4Re::chkcap(registry->register_irq_obj(this),
-                               "Register IRQ of Virtio-input-power device."));
-  }
-
-  void handle_irq();
-
-  void virtio_queue_notify(unsigned val)
-  {
-    // We do not handle the status queue and we do not keep pending events. So
-    // we do not need to do anything if queue 0 is notified (signalling the
-    // addition of buffers to the queue). We could disable notifications here
-    // but are not doing it at the moment.
-    if (val)
-      Dbg(Dbg::Dev, Dbg::Info).printf("Pending request in queue %d\n", val);
-  }
-
-  int inject_events(l4virtio_input_event_t *events, size_t num);
-
-  bool inject_command(unsigned char c);
-
-protected:
-  void virtio_input_cfg_written(l4virtio_input_config_t *dev_cfg);
-private:
-  void set_bit(l4virtio_input_config_t *dev_cfg, unsigned bit)
-  {
-    size_t elem_size = sizeof(dev_cfg->u.bitmap[0]) * 8;
-    dev_cfg->u.bitmap[bit / elem_size] |= (1 << bit % elem_size);
-  }
-
-  void inject_events(l4virtio_input_event_t *events, size_t num, char const *msg)
-  {
-    int res = dev()->inject_events(events, num);
-    if (res != static_cast(num))
-      Dbg(Dbg::Dev, Dbg::Warn, "virtio")
-        .printf("Virtio_input:%s Injected only %d/%zd events\n", msg, res, num);
-  }
-
-  void inject_apm_suspend();
-  void inject_event(l4_uint16_t event, const char*);
-
-  DEV *dev() { return static_cast(this); }
-  L4::Cap _con;
-};
-
-template
-void
-Virtio_input_power::virtio_input_cfg_written(l4virtio_input_config_t *dev_cfg)
-{
-  switch(dev_cfg->select)
-  {
-    case L4VIRTIO_INPUT_CFG_ID_NAME:
-      {
-        char const *name = "Uvmm-power-notification";
-        strncpy(dev_cfg->u.string, name, sizeof(dev_cfg->u.string));
-        dev_cfg->size = std::min(strlen(name) + 1, sizeof(dev_cfg->u.string));
-      }
-      break;
-    case L4VIRTIO_INPUT_CFG_ID_SERIAL:
-      {
-        char const *id = "0815";
-        strncpy(dev_cfg->u.string, id, sizeof(dev_cfg->u.string));
-        dev_cfg->size = std::min(strlen(id) + 1, sizeof(dev_cfg->u.string));
-      }
-      break;
-    case L4VIRTIO_INPUT_CFG_ID_DEVIDS:
-      dev_cfg->u.ids = { 1, 1, 1, 1 };
-      dev_cfg->size = sizeof(l4virtio_input_devids_t);
-      break;
-    case L4VIRTIO_INPUT_CFG_EV_BITS:
-      memset(dev_cfg->u.bitmap, 0, sizeof(dev_cfg->u.bitmap));
-      dev_cfg->size = 0;
-      if (dev_cfg->subsel == L4RE_EV_KEY)
-        {
-          // We are able to generate key events for [A-Za-z0-9 ] and a selected
-          // set of power related events even though the Virtio_input_power
-          // device only generate power related events.
-          //
-          // Other events like leftalt or sysrq are needed to support the
-          // injection of alt sysrq events to the guest.
-          for (char c = '0'; c <= '9'; ++c)
-            set_bit(dev_cfg, translate_char(c));
-          for (char c = 'A'; c <= 'Z'; ++c)
-            set_bit(dev_cfg, translate_char(c));
-          for (char c = 'a'; c <= 'z'; ++c)
-            set_bit(dev_cfg, translate_char(c));
-
-          l4_uint16_t events[] = {
-              L4RE_KEY_POWER,
-              L4RE_KEY_POWER2,
-              L4RE_KEY_SLEEP,
-              L4RE_KEY_SUSPEND,
-              L4RE_KEY_LEFTALT,
-              L4RE_KEY_SYSRQ,
-              L4RE_KEY_SPACE,
-          };
-          for (auto ev : events)
-            set_bit(dev_cfg, ev);
-
-          dev_cfg->size = sizeof(dev_cfg->u.bitmap);
-        }
-      else if (dev_cfg->subsel == L4RE_EV_PWR)
-        {
-          // Current Linux versions do not query events for EV_PWR.
-          // Here we guard against changes in this regard and generate an error
-          // message.
-          Dbg(Dbg::Dev, Dbg::Warn, "virtio")
-            .printf("Virtio_input: Guest queries EV_PWR events "
-                    "- not handled yet.\n");
-        }
-      break;
-    default:
-      dev_cfg->size = 0;
-      break;
-  }
-  // flush the complete structure instead of selectively flushing the actually
-  // used area
-  dev()->writeback_cache(dev_cfg);
-}
-
-template
-void
-Virtio_input_power::handle_irq()
-{
-  int const q_idx = 0;
-  auto *q = dev()->virtqueue(q_idx);
-
-  while (1)
-    {
-      int r = _con->read(NULL, 0);
-
-      if (r <= 0)
-        break; // empty
-
-      char cmd;
-      r = _con->read(&cmd, sizeof(cmd));
-
-      if (r < 0)
-        {
-          Err().printf("Virtio_console: read error: %d\n", r);
-          break;
-        }
-
-      if (!q->ready())
-        {
-          char response[] = "NotReady\n";
-          _con->write(response, sizeof(response) - 1);
-          break;
-        }
-
-      if (!q->desc_avail())
-        {
-          char response[] = "NoMem\n";
-          _con->write(response, sizeof(response) - 1);
-          break;
-        }
-
-      switch(cmd)
-      {
-        case 'a': inject_apm_suspend(); break;
-        case 's': inject_event(L4RE_KEY_SUSPEND, "inject suspend"); break;
-        case 'l': inject_event(L4RE_KEY_SLEEP, "inject sleep"); break;
-        case 'p': inject_event(L4RE_KEY_POWER, "inject power"); break;
-        case 'q': inject_event(L4RE_KEY_POWER2, "inject power2"); break;
-        case 'h':
-          {
-            char response[] = "a: apm suspend\ns: suspend\nl: sleep\np: power\n"
-                              "q: power2\n";
-            _con->write(response, sizeof(response) - 1);
-          }
-          break;
-        default:
-          Dbg(Dbg::Dev, Dbg::Warn, "pwr-input")
-            .printf("Unknown character '%c'\n", cmd);
-          break;
-      }
-      _con->write("OK\n", 3);
-    }
-}
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
-
-template
-void
-Virtio_input_power::inject_apm_suspend()
-{
-  l4virtio_input_event_t events[] = {
-      {L4RE_EV_PWR, L4RE_KEY_SUSPEND, 1},
-      {L4RE_EV_SYN, L4RE_SYN_REPORT, 1},
-      {L4RE_EV_PWR, L4RE_KEY_SUSPEND, 0},
-      {L4RE_EV_SYN, L4RE_SYN_REPORT, 1}
-  };
-  inject_events(events, ARRAY_SIZE(events), __func__);
-}
-
-template
-void
-Virtio_input_power::inject_event(l4_uint16_t event, char const * msg)
-{
-  l4virtio_input_event_t events[] = {
-      {L4RE_EV_KEY, event, 1},
-      {L4RE_EV_SYN, L4RE_SYN_REPORT, 1},
-      {L4RE_EV_KEY, event, 0},
-      {L4RE_EV_SYN, L4RE_SYN_REPORT, 1}
-  };
-  inject_events(events, ARRAY_SIZE(events), msg);
-}
-
-template
-bool
-Virtio_input_power::inject_command(unsigned char c)
-{
-  auto event = translate_char(c);
-  l4virtio_input_event_t events[] = {
-      {L4RE_EV_KEY, L4RE_KEY_LEFTALT, 1},
-      {L4RE_EV_KEY, L4RE_KEY_SYSRQ, 1},
-      {L4RE_EV_KEY, event, 1},
-      {L4RE_EV_SYN, L4RE_SYN_REPORT, 1},
-      {L4RE_EV_KEY, event, 0},
-      {L4RE_EV_KEY, L4RE_KEY_SYSRQ, 0},
-      {L4RE_EV_KEY, L4RE_KEY_LEFTALT, 0},
-      {L4RE_EV_SYN, L4RE_SYN_REPORT, 1}
-  };
-
-  auto num = static_cast(ARRAY_SIZE(events));
-  return dev()->inject_events(events, num) == num;
-}
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/device/virtio_input_power_pci.cc b/src/l4/pkg/uvmm/server/src/device/virtio_input_power_pci.cc
deleted file mode 100644
index c2237884..00000000
--- a/src/l4/pkg/uvmm/server/src/device/virtio_input_power_pci.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2022-2024 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *            Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "pci_device.h"
-#include "pci_virtio_device.h"
-#include "pci_host_bridge.h"
-#include "virtio_pci_connector.h"
-#include "event_connector_pci.h"
-#include "virtio_input_power.h"
-
-namespace Vdev {
-
-struct Virtio_input_power_pci
-: public Virtio_input,
-  public Virtio_input_power,
-  public Pci::Virtio_device_pci,
-  public Virtio::Pci_connector
-{
-  explicit Virtio_input_power_pci(Vdev::Dt_node const &node,
-                                  unsigned num_msix_entries, Vmm::Vm_ram *ram,
-                                  L4::Cap con,
-                                  Gic::Msix_dest const &msix_dest,
-                                  Vdev::Pci::Pci_bridge_windows *wnds)
-  : Virtio_input(ram),
-    Virtio_input_power(con),
-    Virtio_device_pci(node, num_msix_entries, wnds),
-    Virtio::Pci_connector(),
-    _evcon(num_msix_entries, msix_dest)
-  {
-    init_virtio_pci_device();
-    if (device_config_len() < sizeof(l4virtio_input_config_t))
-      L4Re::throw_error(-L4_EINVAL, "device config can hold input cfg");
-  }
-
-  Virtio::Event_connector_msix *event_connector() { return &_evcon; }
-
-  int inject_events(l4virtio_input_event_t *events, size_t num)
-  { return Virtio_input::inject_events(events, num); }
-
-  void virtio_device_config_written(unsigned /*reg*/)
-  {
-    l4virtio_input_config_t *dev_cfg = virtio_device_config();
-    virtio_input_cfg_written(dev_cfg);
-  }
-
-protected:
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned idx) override
-  {
-    if (idx == 0)
-      return event_connector()->make_mmio_device();
-
-    return cxx::Ref_ptr(this);
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  {
-    return cxx::Ref_ptr(this);
-  }
-
-private:
-  Virtio::Event_connector_msix _evcon;
-};
-
-} // namespace Vdev
-
-namespace {
-
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-struct Pci_factory : Factory
-{
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "Input-power-pci"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "Input-power-pci"); }
-
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info).printf("Create virtual input power device (Pci factory)\n");
-
-    auto *pci = dynamic_cast(
-      devs->device_from_node(node.parent_node()).get());
-
-    if (!pci)
-      {
-        info().printf("No PCI bus found.\n");
-        return nullptr;
-      }
-
-    auto cap = Vdev::get_cap(node, "l4vmm,vcon_cap");
-    if (!cap)
-      return nullptr;
-
-    auto dev_id = pci->bus()->alloc_dev_id();
-    unsigned num_msix = 5;
-    auto input =
-      make_device(node, num_msix, devs->ram().get(),
-                                          cap, pci->msix_dest(dev_id),
-                                          pci->bridge_windows());
-
-    input->register_obj(devs->vmm()->registry());
-    pci->bus()->register_device(input, dev_id);
-
-    info().printf("Input-power registered\n");
-    return input;
-  }
-};
-
-static Pci_factory pci_factory;
-static Vdev::Device_type pci_dt = { "virtio,pci", "input-power", &pci_factory };
-}
diff --git a/src/l4/pkg/uvmm/server/src/device_factory.cc b/src/l4/pkg/uvmm/server/src/device_factory.cc
deleted file mode 100644
index 2a837592..00000000
--- a/src/l4/pkg/uvmm/server/src/device_factory.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-#include "device_factory.h"
-#include "virt_bus.h"
-#include "l4/re/env"
-
-namespace Vdev {
-
-cxx::H_list_t Device_type::types(true);
-Factory *Factory::pass_thru;
-
-Factory *
-Factory::find_factory(Dt_node const &node)
-{
-  char const *const comp = "compatible";
-  int count = node.stringlist_count(comp);
-  if (count <= 0)
-    return nullptr;
-
-  int l4type_len;
-  char const *l4type = node.get_prop("l4vmm,vdev", &l4type_len);
-
-  for (int i = 0; i < count; ++i)
-    {
-      int cid_len;
-      char const *cid = node.stringlist_get(comp, i, &cid_len);
-      if (!cid)
-        continue;
-
-      auto const *factory = Device_type::find(cid, cid_len,
-                                              l4type, l4type_len);
-      if (factory)
-        return factory->f;
-    }
-  return nullptr;
-}
-
-bool
-Factory::create_irq_parent(Device_lookup *devs, Vdev::Dt_node const &node,
-                           int depth)
-{
-  Vdev::Dt_node parent = node.find_irq_parent();
-
-  // Is there an IRQ parent at all?
-  if (!parent.is_valid())
-    return true;
-
-  // Is the device already present?
-  if (devs->device_from_node(parent))
-    return true;
-
-  // Check for recursion caused by invalid device trees. We should not
-  // visit more than 10 nodes while creating IRQ parents.
-  if (depth > 10)
-    {
-      Err().printf("Recursion detected at node %s while creating interrupt"
-                   " parents.\n", node.get_name());
-      return false;
-    }
-
-  // Create IRQ parent regardless of presence of interrupts; create_dev() will
-  // check for the IRQ parent again, but will return early since the IRQ parent
-  // is already present at that point
-  if (!create_irq_parent(devs, parent, depth + 1))
-    return false;
-
-  Dbg(Dbg::Dev, Dbg::Trace, "factory")
-    .printf("\t%s:%d: Visiting node '%s' - '%s'\n", __func__, depth,
-            node.get_name(), parent.get_name());
-
-  bool res = static_cast(create_dev(devs, parent));
-
-  Dbg(Dbg::Dev, res ? Dbg::Trace : Dbg::Info, "factory")
-    .printf("%s interrupt parent %s for %s\n",
-            res ? "Successfully created" : "Failed to create",
-            parent.get_name(), node.get_name());
-  return res;
-}
-
-cxx::Ref_ptr
-Factory::create_dev(Device_lookup *devs, Dt_node const &node)
-{
-  std::string path;
-  if (cxx::Ref_ptr d = devs->device_from_node(node, &path))
-    return d;
-
-  Factory *f = find_factory(node);
-  if (!f)
-    f = pass_thru;
-
-  if (!f)
-    return nullptr;
-
-  try
-    {
-      cxx::Ref_ptr dev = f->create(devs, node);
-      if (!dev)
-        return nullptr;
-
-      devs->add_device(node, dev, path);
-      return dev;
-    }
-  catch (...)
-    {
-      Err().printf("Device creation for virtual device %s failed.\n",
-                   node.get_name());
-      throw;
-    }
-}
-
-L4::Cap
-_get_cap(Vdev::Dt_node const &node, char const *prop, L4::Cap def_cap)
-{
-  int size;
-  char const *cap_name = node.get_prop(prop, &size);
-  if (!cap_name)
-    {
-      if (def_cap)
-        return def_cap;
-
-      Dbg(Dbg::Dev, Dbg::Warn)
-        .printf("%s: Failed to get property '%s': %s\n", node.get_name(),
-                prop, fdt_strerror(size));
-      return L4::Cap();
-    }
-
-  // According to the device tree spec strings are null terminated. Since the
-  // device tree is provided by the user we are careful and ensure that we are
-  // using the correct length.
-  size = strnlen(cap_name, size);
-
-  auto cap = L4Re::Env::env()->get_cap(cap_name, size);
-  if (!cap)
-    Dbg(Dbg::Dev, Dbg::Warn)
-    .printf("%s.%s: capability %.*s is invalid.\n",
-            node.get_name(), prop, size, cap_name);
-
-  return cap;
-}
-}
diff --git a/src/l4/pkg/uvmm/server/src/device_factory.h b/src/l4/pkg/uvmm/server/src/device_factory.h
deleted file mode 100644
index d9fe3be6..00000000
--- a/src/l4/pkg/uvmm/server/src/device_factory.h
+++ /dev/null
@@ -1,160 +0,0 @@
-#pragma once
-
-#include "device.h"
-#include "device_tree.h"
-
-#include 
-#include 
-
-namespace Vdev {
-
-class Factory;
-
-struct Device_type : public cxx::H_list_item_t
-
-{
-  char const *cid;
-  char const *l4type;
-  Factory *f;
-
-  Device_type(char const *cid, char const *l4type, Factory *f)
-  : cid(cid), l4type(l4type), f(f)
-  {
-    types.push_front(this);
-  }
-
-  static cxx::H_list_t types;
-  static Device_type const *find(char const *cid, l4_size_t cid_len,
-                                 char const *l4type, l4_size_t l4type_len)
-  {
-    if (l4type)
-      l4type_len = strnlen(l4type, l4type_len);
-
-    for (auto const *t: types)
-      {
-        if (strlen(t->cid) != cid_len)
-          continue;
-
-        if (memcmp(cid, t->cid, cid_len) == 0)
-          {
-            if (!t->l4type)
-              return t;
-
-            if (!l4type || (strlen(t->l4type) != l4type_len))
-              continue;
-
-            if (memcmp(l4type, t->l4type, l4type_len) == 0)
-              return t;
-          }
-      }
-
-    return nullptr;
-  }
-};
-
-
-class Factory
-{
-  /**
-   * Lookup factory for device node.
-   *
-   * \param node  The device node a Device a factory is needed for
-   *
-   * \retval  Pointer to factory, if factory present
-   * \retval  nullptr, if no factory found
-   */
-  static Factory *find_factory(Dt_node const &node);
-
-public:
-  /**
-   * Create a Device instance for the interrupt parent of a node
-   *
-   * \param devs   Pointer to device repository
-   * \param node   The node we are creating an interrupt parent for
-   * \param depth  A counter describing the invocation depth, default 0
-   *
-   * \retval true   Interrupt parent is available
-   * \retval false  Interrupt parent is not available
-   *
-   * Creates a Device instance for the interrupt parent if there is one.
-   */
-  static bool create_irq_parent(Device_lookup *devs, Vdev::Dt_node const &node,
-                                int depth = 0);
-
-  /**
-   * Does the node represent a virtual device?
-   *
-   * \retval true   The node describes a virtual device.
-   * \retval false  The node describes a non virtual device
-   *
-   * is_dev() checks whether there is a factory for the device node
-   * present and returns true if that is the case.
-   */
-  static bool is_vdev(Dt_node const &node)
-  { return find_factory(node) != nullptr; }
-
-  /**
-   * Create a Device instance for the device described by node.
-   *
-   * \param devs  Pointer to device repository
-   * \param node  The device node a Device instance shall be created for
-   *
-   * \retval      Pointer to the created Device
-   * \retval      nullpointer, if device creation failed
-   *
-   * Implemented by each derived factory.
-   */
-  virtual cxx::Ref_ptr create(Device_lookup *devs,
-                                      Dt_node const &node) = 0;
-
-  virtual ~Factory() = 0;
-
-  /**
-   * Create a Device instance for a device.
-   *
-   * \param devs   Pointer to device repository
-   * \param node   The device node a Device instance shall be created for
-   *
-   * \retval false  Device creation failed
-   * \retval true   Device was successfully created and added to the device list
-   *
-   * Creates a device instance for a device node by invoking the responsible
-   * factory and adds it to the device repository.
-   */
-  static cxx::Ref_ptr create_dev(Device_lookup *devs,
-                                         Dt_node const &node);
-
-protected:
-  static Factory *pass_thru;
-};
-
-inline Factory::~Factory() {}
-
-L4::Cap
-_get_cap(Vdev::Dt_node const &node, char const *prop, L4::Cap def_cap);
-
-/**
- * Get capability specified by property
- *
- * \param  node    The node containing the property.
- * \param  prop    Pointer to the name of the property containing the name
- *                 of the capability.
- * \param  def_cap Default capability returned if no property is found.
- *
- * \return  On success a valid capability is returned. If the property is
- *          missing the default capability is returned. Otherwise an invalid
- *          capability is returned.
- *
- * This functions tries to lookup a capability name in the device tree and then
- * tries to get the referenced capability. It either returns
- * * a valid capability on success
- * * the default capability if the property is missing
- * * an invalid capability.
- * The function also generates warnings if the property is missing and no valid
- * default capability was passed or the referenced capability is invalid */
-template 
-L4::Cap get_cap(Vdev::Dt_node const &node, char const *prop,
-                   L4::Cap def_cap = L4::Cap())
-{ return L4::cap_cast(_get_cap(node, prop, def_cap)); }
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/device_repo.h b/src/l4/pkg/uvmm/server/src/device_repo.h
deleted file mode 100644
index 2b4ff6cb..00000000
--- a/src/l4/pkg/uvmm/server/src/device_repo.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016-2021, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "device.h"
-#include "device_tree.h"
-
-namespace Vdev {
-
-class Device_repository
-{
-public:
-  struct Dt_device
-  {
-    std::string path;
-    l4_uint32_t phandle;
-    cxx::Ref_ptr dev;
-  };
-
-  cxx::Ref_ptr device_from_node(Dt_node const &node,
-                                        std::string *path = nullptr) const
-  {
-    // Is a device corresponding to that node already part of the repository?
-    // Identify the device using the phandle (if the node contains a phandle)
-    // or using the full node node path (otherwise).
-    l4_uint32_t phandle = node.get_phandle();
-
-    if (phandle != 0 && phandle != -1U)
-      {
-        for (auto const &d : _devices)
-          {
-            if (d.phandle == phandle)
-              return d.dev;
-          }
-      }
-
-    char buf[1024];
-    node.get_path(buf, sizeof(buf));
-
-    for (auto const &d : _devices)
-      {
-        if (d.path == buf)
-          return d.dev;
-      }
-
-    // Return the path to the caller for passing to add(). This saves an
-    // expensive operation.
-    if (path)
-      path->assign(buf);
-
-    return cxx::Ref_ptr();
-  }
-
-  void add(Dt_node const &node, cxx::Ref_ptr dev,
-           std::string const &path)
-  {
-    l4_uint32_t phandle = node.get_phandle();
-
-    if (path.empty())
-      {
-        char buf[1024];
-        node.get_path(buf, sizeof(buf));
-        _devices.push_back({buf, phandle, dev});
-      }
-    else
-      _devices.push_back({path, phandle, dev});
-  }
-
-  std::vector::const_iterator begin() const
-  { return _devices.begin(); }
-
-  std::vector::const_iterator end() const
-  { return _devices.end(); }
-
-private:
-  std::vector _devices;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ds_manager.h b/src/l4/pkg/uvmm/server/src/ds_manager.h
deleted file mode 100644
index 3e6398e6..00000000
--- a/src/l4/pkg/uvmm/server/src/ds_manager.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2014-2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "consts.h"
-
-namespace Vmm {
-
-/**
- * Manager for a unique part of a dataspace, that might be mapped
- * into the VMM.
- *
- * The manager manages and keeps track of a VMM-local mapping of the
- * dataspace if this is needed (requested by using local_addr<>()).
- */
-class Ds_manager : public cxx::Ref_obj
-{
-private:
-  /// Debug name
-  std::string const _dev_name;
-  /// Dataspace capability for the dataspace to be managed
-  L4Re::Util::Ref_cap::Cap _ds;
-  /// Offset within the dataspace of the managed part
-  L4Re::Dataspace::Offset _offset = 0;
-  /// Size of the managed dataspace part
-  L4Re::Dataspace::Size _size = 0;
-  /// Local region if the managed part is locally attached
-  L4Re::Rm::Unique_region _local;
-  /// Region flags to be used when locally attaching the dataspace
-  L4Re::Rm::Region_flags _local_flags;
-  /// Region alignment (log2)
-  unsigned char _align;
-
-  /**
-   * Get the VMM local address of the managed portion of the dataspace.
-   *
-   * \note This function might create a local mapping if it does
-   * not already exist.
-   */
-  void *_local_addr()
-  {
-    if (_local.is_valid())
-      return _local.get();
-
-    auto rm = L4Re::Env::env()->rm();
-
-    L4Re::chksys(rm->attach(&_local, _size,
-                            _local_flags
-                            | L4Re::Rm::F::Search_addr
-                            | L4Re::Rm::F::Eager_map,
-                            L4::Ipc::make_cap_rw(_ds.get()),
-                            _offset, _align),
-                 "Attach dataspace to local address space.");
-    return _local.get();
-  }
-
-public:
-  /**
-   * Create a manager for the given part of the given dataspace.
-   */
-  Ds_manager(std::string const &dev_name,
-             L4Re::Util::Ref_cap::Cap const &ds,
-             L4Re::Dataspace::Offset offset,
-             L4Re::Dataspace::Size size,
-             L4Re::Rm::Region_flags local_flags = L4Re::Rm::F::RW,
-             unsigned char align = L4_SUPERPAGESHIFT)
-  : _dev_name(dev_name),
-    _ds(ds), _offset(offset), _size(size), _local_flags(local_flags),
-    _align(align)
-  {}
-
-  Ds_manager(Ds_manager const &) = delete;
-  Ds_manager(Ds_manager &&) = default;
-  virtual ~Ds_manager() = default;
-
-  /**
-   * Get the capability for the managed dataspace.
-   */
-  L4Re::Util::Ref_cap::Cap dataspace() const
-  { return _ds; }
-
-  /**
-   * Get the size in bytes of the managed part of the dataspace.
-   */
-  L4Re::Dataspace::Size size() const
-  { return _size; }
-
-  /**
-   * Get the offset relative to the start of the dataspace that is
-   * represented by this manager.
-   */
-  L4Re::Dataspace::Offset offset() const
-  { return _offset; }
-
-  /**
-   * Get the VMM local address of the managed portion of the dataspace.
-   *
-   * NOTE: this function might create a local mapping if it does
-   * not already exist.
-   */
-  template
-  T local_addr()
-  { return reinterpret_cast(_local_addr()); }
-
-  /**
-   * Return true if a VMM local mapping of the managed dataspace
-   * part exists.
-   */
-  bool is_mapped() const
-  { return _local.is_valid(); }
-
-  L4Re::Rm::Region_flags local_flags() const
-  { return _local_flags; }
-
-  /**
-   * Returns the dev name.
-   */
-  char const *dev_name() const { return _dev_name.c_str(); }
-};
-
-}
-
diff --git a/src/l4/pkg/uvmm/server/src/ds_mmio_handling.h b/src/l4/pkg/uvmm/server/src/ds_mmio_handling.h
deleted file mode 100644
index 18b636fb..00000000
--- a/src/l4/pkg/uvmm/server/src/ds_mmio_handling.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "mem_access.h"
-
-namespace Vdev {
-
-/**
- * Manager to multiplex access to a specific dataspace.
- *
- * When using this class in cooperation with Ds_mmio_converter you have to
- * ensure that the accessed areas do not overlap and the accesses are within
- * the managed dataspace.
- */
-class Ds_access_mgr : public cxx::Ref_obj
-{
-public:
-  /**
-   * Map and manage `size` bytes of MMIO memory starting at `start`.
-   *
-   * \param ds         Dataspace containing the area to map and manage.
-   * \param start      Start of the area.
-   * \param size       Size of the area.
-   * \param add_flags  Additional flags to use when attaching the dataspace.
-   *                   Search_addr, Eager_map, RW are always applied.
-   */
-  explicit Ds_access_mgr(L4::Cap ds,
-                         l4_addr_t start,
-                         unsigned size,
-                         L4Re::Rm::Flags add_flags = L4Re::Rm::F::Cache_uncached)
-  : _mem(attach_memory(ds, start, size, add_flags))
-  {}
-
-  /**
-   * Read from device memory.
-   *
-   * \param offset  Offset into the managed memory region to read from.
-   * \param size    Width of the read access.
-   *
-   * \return  Read result.
-   *
-   * \pre The read access must be within the managed area.
-   */
-  l4_umword_t read(unsigned offset, char size) const
-  { return Vmm::Mem_access::read_width(_mem.get() + offset, size); }
-
-  /**
-   * Write to device memory.
-   *
-   * \param offset  Offset into the managed memory region to write to.
-   * \param size    Width of the write access.
-   *
-   * \pre The write access must be within the managed area.
-   */
-  void write(unsigned offset, char size, l4_umword_t value) const
-  { Vmm::Mem_access::write_width(_mem.get() + offset, value, size); }
-
-private:
-  /// Attach the device memory to the local address space.
-  static L4Re::Rm::Unique_region
-  attach_memory(L4::Cap ds, l4_addr_t offset,
-                l4_size_t size, L4Re::Rm::Flags add_flags)
-  {
-    L4Re::Rm::Flags rm_flags = L4Re::Rm::F::Search_addr | L4Re::Rm::F::Eager_map
-                               | L4Re::Rm::F::RW | add_flags;
-    auto rm = L4Re::Env::env()->rm();
-    size = l4_round_page(size);
-    offset = l4_trunc_page(offset);
-
-    L4Re::Rm::Unique_region mem;
-    L4Re::chksys(rm->attach(&mem, size, rm_flags, ds, offset),
-                 "Attach memory.");
-
-    info().printf("Attached memory [0x%lx, 0x%lx] to 0x%lx\n", offset,
-                  offset + size - 1, mem.get());
-
-    return cxx::move(mem);
-  }
-
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "DsAccMgr"); }
-
-  /// Device memory region
-  L4Re::Rm::Unique_region _mem;
-}; // class Ds_access_mgr
-
-/**
- * Convert MMIO accesses to the Ds_access_mgr interface and manage the offset
- * into the managed area.
- */
-class Mmio_ds_converter : public Vmm::Mmio_device_t
-{
-public:
-  /**
-   * Connector to the manager of the device memory region.
-   *
-   * \param mgr     Manager of device memory.
-   * \param offset  Memory offset into the memory managed by `mgr`.
-   */
-  Mmio_ds_converter(cxx::Ref_ptr mgr, l4_addr_t offset)
-  : _mem_mgr(mgr), _offset(offset)
-  {}
-
-  /// Apply local offset to `reg` and read from device memory.
-  l4_umword_t read(unsigned reg, char size, unsigned = 0) const
-  { return _mem_mgr->read(_offset + reg, size); }
-
-  /// Apply local offset to `reg` and write to device memory.
-  void write(unsigned reg, char size, l4_umword_t value, unsigned = 0) const
-  { _mem_mgr->write(_offset + reg, size, value); }
-
-  char const *dev_name() const override { return "Mmio_ds_converter"; }
-
-private:
-  /// MMIO memory region manager.
-  cxx::Ref_ptr _mem_mgr;
-  /// Offset inside the Dev_ds_manager memory region.
-  l4_addr_t _offset;
-}; // class Mmio_ds_converter
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/ds_mmio_mapper.h b/src/l4/pkg/uvmm/server/src/ds_mmio_mapper.h
deleted file mode 100644
index 1050696c..00000000
--- a/src/l4/pkg/uvmm/server/src/ds_mmio_mapper.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "mmio_device.h"
-#include "vcpu_ptr.h"
-#include "ds_manager.h"
-
-#ifndef MAP_OTHER
-/**
- * Ds_handler represents a dataspace-backed region in the VMs memory
- * map.
- *
- * This version uses VMM local mappings for the dataspace and forwards
- * pages to the VM using L4::Task::map.
- *
- * The dataspace and the VMM local mapping is managed by the associated
- * Ds_manager. The VMM local mapping is created lazily, either on first
- * access() or map_eager() calls.
- */
-class Ds_handler : public Vmm::Mmio_device
-{
-public:
-  enum Flags
-  {
-    None = 0x0,
-    Map_eager = 0x1
-  };
-
-  explicit Ds_handler(cxx::Ref_ptr ds,
-                      L4_fpage_rights rights = L4_FPAGE_RW,
-                      l4_addr_t offset = 0, Flags flags = Map_eager)
-  : _ds(ds), _rights(rights), _offset(offset), _flags(flags)
-  {
-    l4_addr_t page_offs = offset & ~L4_PAGEMASK;
-    if (page_offs)
-      Dbg(Dbg::Mmio, Dbg::Warn)
-        .printf("Region not page aligned\n");
-  }
-
-private:
-  /// manager for a portion of a dataspace + local mapping
-  cxx::Ref_ptr _ds;
-
-  /// Stores the rights for the mapping into the guest (R/W/X).
-  L4_fpage_rights _rights;
-
-  /// Stores the offset relative to the offset in the Ds_manager
-  l4_addr_t _offset;
-
-  /// Special properties of the dataspace
-  Flags _flags;
-
-  /**
-   * Get the full offset from the start of the dataspace.
-   *
-   * This is mainly useful for implementing _mergable().
-   */
-  l4_addr_t full_offset() const
-  { return _offset + _ds->offset(); }
-
-  /**
-   * Get the VMM local address for this part of the dataspace
-   * represented by this Ds_handler.
-   *
-   * NOTE: this function might create a VMM local mapping of the
-   * dataspace part managed by the Ds_manager (_ds).
-   */
-  l4_addr_t local_start() const
-  {
-    return _ds->local_addr() + _offset;
-  }
-
-  bool _mergable(cxx::Ref_ptr other,
-                 Vmm::Guest_addr start_other, Vmm::Guest_addr start_this) override
-  {
-    // same device type and same underlying dataspace?
-    auto dsh = dynamic_cast(other.get());
-    if (!dsh || (_ds->dataspace() != dsh->_ds->dataspace()))
-      return false;
-
-    // same rights?
-    if (_rights != dsh->_rights)
-      return false;
-
-    // reference the same part of the data space?
-    return (full_offset() + (start_other - start_this)) == dsh->full_offset();
-  }
-
-  /**
-   * Map the entire MMIO region into the guest.
-   *
-   * \param vm_task  VM task capability.
-   * \param start    Guest start address of the region.
-   * \param end      Guest end address of the region.
-   *
-   * \note This might establish a VMM local mapping.
-   */
-  void map_eager(L4::Cap vm_task, Vmm::Guest_addr start,
-                 Vmm::Guest_addr end) override
-  {
-    if (_flags & Map_eager)
-      map_guest_range(vm_task, start, local_start(), end - start + 1, _rights);
-  }
-
-  /**
-   * Map parts of an MMIO region to the guest.
-   *
-   * \note This might establish a VMM local mapping.
-   *
-   * \param pfa      Guest-physical page fault address.
-   * \param offset   Offset of the page fault into the MMIO region.
-   * \param vcpu     Virtual CPU from which the memory was accessed.
-   * \param vm_task  VM task capability.
-   * \param min      Guest-physical address of the MMIO region's first byte.
-   * \param max      Guest-physical address of the MMIO region's last byte.
-   */
-  int access(l4_addr_t pfa, l4_addr_t offset, Vmm::Vcpu_ptr vcpu,
-             L4::Cap vm_task, l4_addr_t min, l4_addr_t max) override
-  {
-    long res;
-    l4_addr_t ls = local_start();
-    // Make sure that the page is currently mapped.
-    res = page_in(ls + offset, vcpu.pf_write());
-
-    if (res >= 0)
-      {
-        // We assume that the region manager provided the largest possible
-        // page size and try to map the largest possible page to the
-        // client.
-        unsigned char ps = Vmm::get_page_shift(pfa, min, max, offset, ls);
-
-        if (vcpu.pf_write() && !(_rights & L4_FPAGE_W))
-          {
-            Err().printf(
-              "not handling VM write access @ %lx ip=%lx on read-only area\n",
-               pfa, vcpu->r.ip);
-            return -L4_EPERM;
-          }
-
-        // Map explicitly cacheable into VM task. This lets the guest choose
-        // the effective memory attributes.
-        res = l4_error(
-                vm_task->map(L4Re::This_task,
-                             l4_fpage(l4_trunc_size(ls + offset, ps),
-                                      ps, _rights),
-                             l4_map_control(l4_trunc_size(pfa, ps),
-                                            L4_FPAGE_CACHEABLE,
-                                            L4_MAP_ITEM_MAP)));
-      }
-
-    if (res < 0)
-      {
-        Err().printf("cannot handle VM memory access @ %lx ip=%lx r=%ld\n",
-                     pfa, vcpu->r.ip, res);
-        return res;
-      }
-
-    return Vmm::Retry;
-  }
-
-  char const *dev_name() const override { return _ds->dev_name(); }
-
-  char const *dev_info(char *buf, size_t size) const override
-  {
-    snprintf(buf, size, "%s: DS local=%lx cap=%lx offset=%lx",
-             dev_name(), _ds->local_addr(),
-             _ds->dataspace().cap(),
-             static_cast(_ds->offset()) + _offset);
-    buf[size - 1] = '\0';
-    return buf;
-  }
-
-};
-
-#else /* MAP_OTHER */
-
-/**
- * Ds_handler represents a dataspace-backed region in the VMs memory
- * map.
- *
- * This version maps the dataspace directly from the dataspace into the VM,
- * without creating VMM local mappings. If such mappings are needed the
- * Ds_manager interface must be used.
- */
-class Ds_handler : public Vmm::Mmio_device
-{
-public:
-  enum Flags
-  {
-    None = 0x0,
-    Map_eager = 0x1
-  };
-
-  explicit Ds_handler(cxx::Ref_ptr const &ds,
-                      L4_fpage_rights rights = L4_FPAGE_RW,
-                      l4_addr_t offset = 0, Flags flags = Map_eager)
-  : _ds(ds->dataspace()), _rights(rights), _offset(ds->offset() + offset)
-  {
-    (void)flags;
-  }
-
-private:
-  /// just keep the dataspace cap (no local region is needed)
-  L4Re::Util::Ref_cap::Cap _ds;
-
-  /// store the rights for the mapping into the guest
-  L4_fpage_rights _rights;
-
-  /// store the offset relative to the start of the dataspace.
-  l4_addr_t _offset;
-
-  bool _mergable(cxx::Ref_ptr other,
-                 Vmm::Guest_addr start_other, Vmm::Guest_addr start_this) override
-  {
-    // same device type and same underlying dataspace?
-    auto dsh = dynamic_cast(other.get());
-    if (!dsh || (_ds != dsh->_ds))
-      return false;
-
-    // same rights?
-    if (_rights != dsh->_rights)
-      return false;
-
-    // reference the same part of the data space?
-    return (_offset + (start_other - start_this)) == dsh->_offset;
-  }
-
-  void map_eager(L4::Cap /*vm_task*/, Vmm::Guest_addr /*start*/,
-                 Vmm::Guest_addr /*end*/) override
-  {
-    // eager mapping not yet supported
-  }
-
-  int access(l4_addr_t pfa, l4_addr_t offset, Vmm::Vcpu_ptr vcpu,
-             L4::Cap vm_task, l4_addr_t min, l4_addr_t max) override
-  {
-    if (vcpu.pf_write() && !(_rights & L4_FPAGE_W))
-      {
-        Err().printf(
-          "not handling VM write access @ %lx ip=%lx on read-only area\n",
-           pfa, vcpu->r.ip);
-        return -L4_EPERM;
-      }
-
-    // XXX This is differs from !MAP_OTHER:
-    //     - There, we copy the cacheability options from the local mappings.
-    //     - Here, we request Dataspace::Flags::Normal = Cacheable mapping!
-    //     Resolve this by changing _rights to Dataspace::Flags.
-#warning Always requests Dataspace::Flags::Cacheable mapping!
-    long res = _ds->map(offset + _offset, L4Re::Dataspace::Flags(_rights),
-                        pfa, min, max, vm_task);
-
-    if (res < 0)
-      {
-        Err().printf("cannot handle VM memory access @ %lx ip=%lx r=%ld\n",
-                     pfa, vcpu->r.ip, res);
-        return res;
-      }
-
-    return Vmm::Retry;
-  }
-
-  char const *dev_name() const override { return _ds->dev_name(); }
-
-  char const *dev_info(char *buf, size_t size) const override
-  {
-    snprintf(buf, size, "%s: DS cap=%lx offset=%lx",
-             dev_name(), _ds.cap(), _offset);
-    buf[size - 1] = '\0';
-    return buf;
-  }
-
-};
-#endif /* MAP_OTHER */
diff --git a/src/l4/pkg/uvmm/server/src/event_connector_pci.h b/src/l4/pkg/uvmm/server/src/event_connector_pci.h
deleted file mode 100644
index 7a39a414..00000000
--- a/src/l4/pkg/uvmm/server/src/event_connector_pci.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "pci_device.h"
-#include "msi_controller.h"
-#include "msix.h"
-#include "virtio_event_connector.h"
-#include "ds_mmio_mapper.h"
-#include "guest.h"
-
-namespace Virtio {
-
-/**
- * This MSIX connector supports sending MSIs configured in the MSI-X table.
- *
- * For further documentation look at Event_connector_irq.
- */
-class Event_connector_msix
-{
-public:
-  Event_connector_msix(unsigned max_msix_entries, Gic::Msix_dest const &msix_dest)
-  : _msix_dest(msix_dest),
-    _msix_mem(make_ram_ds_handler(
-                Vdev::Msix::msix_table_pba_mem_size(max_msix_entries),
-                L4Re::Mem_alloc::Continuous))
-  {}
-
-  void send_events(Virtio::Event_set &&ev)
-  {
-    for (unsigned i = 0; ev.e != 0; ev.e >>= 1, ++i)
-      if (ev.e & 1)
-        send_event(i);
-  }
-
-  void send_event(l4_uint16_t idx) const
-  {
-    auto const *entry = msix_entry(idx);
-    if (!entry->masked())
-      _msix_dest.send_msix(entry->addr, entry->data);
-  }
-
-  void clear_events(unsigned) {}
-
-  l4_size_t mem_size() const
-  { return _msix_mem->size(); }
-
-  /**
-   * Create virtual device to let guest access MSI-X table.
-   */
-  cxx::Ref_ptr make_mmio_device() const
-  {
-    return Vdev::make_device(_msix_mem);
-  }
-
-private:
-  Gic::Msix_dest _msix_dest;
-  cxx::Ref_ptr _msix_mem;
-
-  Vdev::Msix::Table_entry *msix_entry(l4_uint16_t idx) const
-  {
-    return &_msix_mem->local_addr()[idx];
-  }
-
-  // I can use RW MMIO memory, as I am the endpoint for the guest configuration
-  // of the MSIs and evaluate the entries every time, an event should be sent.
-  cxx::Ref_ptr make_ram_ds_handler(l4_size_t size,
-                                                    unsigned long flags)
-  {
-    L4Re::Util::Ref_cap::Cap ds
-      = L4Re::chkcap(L4Re::Util::cap_alloc.alloc(),
-                     "Allocate DS cap for DS-handler memory.");
-
-    L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(size, ds.get(), flags),
-                 "Allocate memory in dataspace.");
-
-    return cxx::make_ref_obj("Event_connector_msix", ds, 0,
-                                              size);
-  }
-
-}; // class Event_connector_msix
-
-} // namespace Virtio
diff --git a/src/l4/pkg/uvmm/server/src/generic_cpu_dev.cc b/src/l4/pkg/uvmm/server/src/generic_cpu_dev.cc
deleted file mode 100644
index 35736bfe..00000000
--- a/src/l4/pkg/uvmm/server/src/generic_cpu_dev.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "generic_cpu_dev.h"
-
-#include 
-
-#include 
-#include 
-
-namespace Vmm {
-
-Vcpu_ptr Generic_cpu_dev::_main_vcpu(nullptr);
-L4Re::Util::Br_manager Generic_cpu_dev::_main_bm;
-Vcpu_obj_registry Generic_cpu_dev::_main_registry(&Generic_cpu_dev::_main_bm);
-bool Generic_cpu_dev::_main_vcpu_used = false;
-unsigned Generic_cpu_dev::_max_vcpu_id;
-
-void
-Generic_cpu_dev::startup()
-{
-  // CPU 0 is the boot CPU and the main thread is already attached
-  if (!_attached)
-    {
-      _attached = true;
-      _vcpu.thread_attach();
-    }
-
-  reset();
-}
-
-void
-Generic_cpu_dev::powerup_cpu()
-{
-  unsigned id = _vcpu.get_vcpu_id();
-
-  if (id == 0)
-    {
-      _thread = pthread_self();
-      reschedule();
-    }
-  else
-    {
-      int err;
-      pthread_attr_t pattr;
-      err = pthread_attr_init(&pattr);
-      if (L4_UNLIKELY(err))
-        L4Re::chksys(-L4_ENOMEM, "Initializing pthread attributes.");
-
-      pattr.create_flags |= PTHREAD_L4_ATTR_NO_START;
-      err = pthread_create(&_thread, &pattr, [](void *cpu) {
-          reinterpret_cast(cpu)->startup();
-          return static_cast(nullptr);
-        }, this);
-
-      if (L4_UNLIKELY(pthread_attr_destroy(&pattr)))
-        L4Re::chksys(-L4_ENOMEM, "Destroying pthread attributes.");
-
-      if (err != 0)
-        L4Re::chksys(-L4_EAGAIN, "Cannot start vcpu thread");
-
-      _registry.set_server(thread_cap());
-      _vcpu.set_ipc_registry(&_registry);
-      _vcpu.set_bm(&_bm);
-    }
-
-  char n[8];
-  snprintf(n, sizeof(n), "vcpu%d", id);
-  l4_debugger_set_object_name(pthread_l4_cap(_thread), n);
-}
-
-void
-Generic_cpu_dev::reschedule()
-{
-  Dbg(Dbg::Cpu, Dbg::Info)
-    .printf("reschedule(): Initiating cpu startup for cap 0x%lx/core %u\n",
-            Pthread::L4::cap(_thread).cap(), _vcpu.get_vcpu_id());
-
-  l4_sched_param_t sp = l4_sched_param(2);
-  sp.affinity = l4_sched_cpu_set(_phys_cpu_id, 0);
-
-  auto sched = L4Re::Env::env()->scheduler();
-  L4Re::chksys(sched->run_thread(Pthread::L4::cap(_thread), sp),
-               "Schedule vCPU on new core.");
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/generic_cpu_dev.h b/src/l4/pkg/uvmm/server/src/generic_cpu_dev.h
deleted file mode 100644
index d2cf805d..00000000
--- a/src/l4/pkg/uvmm/server/src/generic_cpu_dev.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2017-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-namespace Vmm {
-
-class Generic_cpu_dev : public Vdev::Device
-{
-private:
-  static Vcpu_ptr alloc_vcpu(unsigned idx)
-  {
-    l4_addr_t vcpu_addr;
-
-    L4Re::chksys(L4Re::Util::kumem_alloc(&vcpu_addr, 0),
-                 "kumem alloc for vCPU");
-
-    Dbg(Dbg::Cpu, Dbg::Info).printf("Created VCPU %u @ %lx\n", idx, vcpu_addr);
-
-    return Vcpu_ptr(reinterpret_cast(vcpu_addr));
-  }
-
-protected:
-  /**
-   * Stop execution of the vCPU device on IRQ event.
-   */
-  struct Stop_event
-  {
-    Stop_event(Generic_cpu_dev *c) : cpu(c) {}
-    void act()
-    { cpu->stop(); }
-
-    void registration_failure()
-    {
-      Dbg().printf("Failed to register IRQ to stop vCPU; Shutdown "
-                   "synchronization not enforcable.\n");
-    }
-
-    void trigger_failure(long ipc_err)
-    {
-      Dbg().printf("IPI to vCPU %u failed with error %li\n",
-                   cpu->vcpu().get_vcpu_id(), ipc_err);
-    }
-
-    Generic_cpu_dev *cpu;
-  };
-
-protected:
-  /**
-   * Management wrapper for vCPU device specific actions to execute on IRQ event.
-   *
-   * \tparam EVENT  Action to execute when the IRQ is received.
-   */
-  template 
-  class Cpu_irq : public L4::Irqep_t>
-  {
-  public:
-    Cpu_irq(EVENT const &a) : _event(a) {}
-
-    void handle_irq() { _event.act(); }
-
-    void arm(Vcpu_obj_registry *registry)
-    {
-      if (_irq.is_valid())
-        {
-          Dbg().printf("Rearming already armed CPU IRQ. Ignored.\n");
-          return;
-        }
-
-      _irq = registry->register_irq_obj(this);
-      if (!_irq.is_valid())
-        _event.registration_failure();
-    }
-
-    void disarm(Vcpu_obj_registry *registry)
-    {
-      registry->unregister_obj(this);
-      _irq.invalidate();
-    }
-
-    /**
-     * \pre `_irq` capability is registered.
-     */
-    void trigger()
-    {
-      assert(_irq.is_valid());
-
-      l4_msgtag_t tag = _irq->trigger();
-      if (tag.has_error())
-        _event.trigger_failure(l4_ipc_error(tag, l4_utcb()));
-    }
-
-    l4_msgtag_t receive(l4_timeout_t to = L4_IPC_NEVER)
-    {
-      return _irq->receive(to);
-    }
-
-  private:
-    L4::Cap _irq;
-    EVENT _event;
-  };
-
-public:
-  Generic_cpu_dev(unsigned idx, unsigned phys_id)
-  : _vcpu(nullptr), _phys_cpu_id(phys_id), _thread(nullptr),
-    _registry(&_bm), _stop_irq(Stop_event(this))
-  {
-    // The CPU 0 (boot CPU) vCPU is allocated in main
-    if (_main_vcpu_used || (idx != 0))
-      _vcpu = alloc_vcpu(idx);
-    else
-      {
-        _attached = true;
-        _vcpu = _main_vcpu;
-        _main_vcpu_used = true;
-      }
-
-    _vcpu.set_vcpu_id(idx);
-    if (idx > _max_vcpu_id)
-      _max_vcpu_id = idx;
-
-    // entry_sp signals the state the CPU is in. When it starts for the very
-    // first time, entry_sp is zero and needs to be initialised based on the
-    // currently used stack. When the CPU is switched off and on again the
-    // stack is re-used as is.
-    _vcpu->entry_sp = 0;
-  }
-
-  virtual ~Generic_cpu_dev()
-  { _stop_irq.disarm(_vcpu.get_ipc_registry()); }
-
-  Vcpu_ptr vcpu() const
-  { return _vcpu; }
-
-  unsigned get_phys_cpu_id() const noexcept
-  { return _phys_cpu_id; }
-
-  virtual void powerup_cpu();
-  void reschedule();
-
-  void send_stop_event()
-  { _stop_irq.trigger(); }
-
-  virtual void reset() = 0;
-  virtual void stop() = 0;
-
-  /**
-   * Start CPU, run through reset and resume to the VM.
-   */
-  void startup();
-
-  L4::Cap thread_cap() const
-  { return Pthread::L4::cap(_thread); }
-
-  static Vcpu_ptr main_vcpu() { return _main_vcpu; }
-
-  static void alloc_main_vcpu()
-  {
-    if (*_main_vcpu)
-      L4Re::throw_error(-L4_EEXIST, "cannot allocate multiple main CPUs");
-
-    _main_vcpu = alloc_vcpu(0);
-    _main_vcpu.thread_attach();
-    _main_vcpu.set_ipc_registry(&_main_registry);
-    _main_vcpu.set_bm(&_main_bm);
-  }
-
-  static unsigned get_max_vcpu_id()
-  {
-    return _max_vcpu_id;
-  }
-
-protected:
-  Vcpu_ptr _vcpu;
-  /// physical CPU to run on (offset into scheduling mask)
-  unsigned _phys_cpu_id;
-  pthread_t _thread;
-  L4Re::Util::Br_manager _bm;
-  Vcpu_obj_registry _registry;
-  bool _attached = false;
-  Cpu_irq _stop_irq;
-
-private:
-  static Vcpu_ptr _main_vcpu;
-  static L4Re::Util::Br_manager _main_bm;
-  static Vcpu_obj_registry _main_registry;
-  static bool _main_vcpu_used;
-  static unsigned _max_vcpu_id;
-};
-
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/generic_guest.cc b/src/l4/pkg/uvmm/server/src/generic_guest.cc
deleted file mode 100644
index 14df00ee..00000000
--- a/src/l4/pkg/uvmm/server/src/generic_guest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2015-2019, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include "generic_guest.h"
-
-namespace Vmm {
-
-Generic_guest::Generic_guest()
-: _task(L4Re::chkcap(L4Re::Util::cap_alloc.alloc(),
-                     "Allocate guest task capability"))
-{
-  // create the VM task
-  auto *e = L4Re::Env::env();
-  auto ret = e->factory()->create(_task.get(), L4_PROTO_VM);
-
-  if (l4_error(ret) < 0)
-    {
-      Err().printf("Cannot create guest VM. Virtualization support may be missing.\n");
-      L4Re::chksys(ret, "Create VM task.");
-    }
-  l4_debugger_set_object_name(_task.get().cap(), "vm-task");
-}
-
-void
-Generic_guest::register_mmio_device(cxx::Ref_ptr const &dev,
-                                    Region_type type,
-                                    Vdev::Dt_node const &node, size_t index)
-{
-  l4_uint64_t base, size;
-  Dtb::Reg_flags flags;
-  int res = node.get_reg_val(index, &base, &size, &flags);
-  if (res < 0)
-    {
-      Err().printf("Failed to read 'reg' with index %zu from node %s: %s\n",
-                   index, node.get_name(), node.strerror(res));
-      L4Re::throw_error(
-        -L4_EINVAL,
-        "Node has not enough reg property entries for given index.");
-    }
-
-  if (!flags.is_mmio())
-    {
-      Err()
-        .printf("Invalid 'reg' property at index %zu of node %s: not an mmio region\n",
-                index, node.get_name());
-      L4Re::throw_error(-L4_EINVAL, "Reg property contains no MMIO region.");
-    }
-
-  add_mmio_device(Region::ss(Vmm::Guest_addr(base), size, type), dev);
-
-  info().printf("New mmio mapping: @ %llx %llx\n", base, size);
-}
-
-void
-Generic_guest::register_timer_device(cxx::Ref_ptr const &dev,
-                                     unsigned vcpu_no)
-{
-  _clocks[vcpu_no].add_timer(dev);
-  _timer_devices[vcpu_no].push_back(dev);
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/generic_guest.h b/src/l4/pkg/uvmm/server/src/generic_guest.h
deleted file mode 100644
index 5315135d..00000000
--- a/src/l4/pkg/uvmm/server/src/generic_guest.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2015-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "ds_mmio_mapper.h"
-#include "mem_types.h"
-#include "ram_ds.h"
-#include "vm_memmap.h"
-#include "pm.h"
-#include "consts.h"
-#include "monitor/monitor.h"
-#include "io_device.h"
-#include "timer.h"
-#include "generic_cpu_dev.h"
-#include "vcpu_obj_registry.h"
-
-#include 
-#include 
-
-namespace Vmm {
-
-class Generic_guest
-{
-public:
-  enum
-  {
-    Shutdown = 0x0,
-    Reboot = 0x66
-  };
-
-  enum class Fault_mode
-  {
-    Ignore,
-    Halt,
-    Inject,
-  };
-
-  enum { Has_io_space = false };
-
-  Generic_guest();
-  virtual ~Generic_guest() = default;
-
-  /*
-   * By default only Ignore and Halt are supported. If an architecture supports
-   * Inject it must override this method.
-   */
-  static bool fault_mode_supported(Fault_mode mode)
-  {
-    return mode == Fault_mode::Ignore || mode == Fault_mode::Halt;
-  }
-
-  void set_fault_mode(Fault_mode mode) { _fault_mode = mode; }
-
-  void set_dt_addr(l4_addr_t dt_addr) { _dt_addr = dt_addr; }
-  l4_addr_t dt_addr() const { return _dt_addr; }
-
-  void prepare_generic_platform(Vdev::Device_lookup *devs)
-  { _pm = devs->pm(); }
-
-  Vcpu_obj_registry *registry()
-  { return Generic_cpu_dev::main_vcpu().get_ipc_registry(); }
-
-  void register_mmio_device(cxx::Ref_ptr const &dev,
-                            Region_type type,
-                            Vdev::Dt_node const &node, size_t index = 0);
-
-  void register_io_device(cxx::Ref_ptr const &,
-                          Region_type, Vdev::Dt_node const &, size_t = 0) {}
-  void add_io_device(Io_region const &, cxx::Ref_ptr const &) {}
-  void del_io_device(Io_region const &) {}
-
-  bool register_framebuffer(l4_uint64_t /*addr*/, l4_uint64_t /*size*/,
-                            const L4Re::Video::View::Info &)
-  { return true; }
-
-  /**
-   * Register a device for a timer.
-   *
-   * Uniprocessor timer devices such as the legacy PIT are registered ommiting
-   * the CPU number and run off the clock source for vCPU 0.
-   *
-   * Timers registered at run time (e.g. via KVM clock MSR) specify their
-   * core's CPU IDs.
-   *
-   * \note For the timers to actually start operating, it is necessary that the
-   *       \ref Clock_source::start_clock_source_thread() method is executed
-   *       for each item in the \ref _clocks map at the appropriate moment by
-   *       the platform-specific ancestor of the \ref Generic_guest class. This
-   *       is currently only implemented for AMD64.
-   *
-   * \param dev      Timer device to register with a clock source.
-   * \param vcpu_no  Virtual CPU that the timer should be registered for,
-   *                 default 0.
-   */
-  void register_timer_device(cxx::Ref_ptr const &dev,
-                             unsigned vcpu_no = 0);
-
-  /**
-   * Return MMIO map.
-   *
-   * Must only be used before the guest started to run or for debugging. Might
-   * be manipulated concurrently from other vCPUs!
-   */
-  Vm_mem *memmap()
-  { return &_memmap; }
-
-  virtual void L4_NORETURN halt_vm(Vcpu_ptr current_vcpu)
-  {
-    Err().printf("VM entered a fatal state. Halting.\n");
-
-    _pm->free_inhibitors();
-
-    if (!Monitor::cmd_control_enabled())
-      exit(EXIT_FAILURE);
-
-    for (;;)
-      current_vcpu.wait_for_ipc(l4_utcb(), L4_IPC_NEVER);
-  }
-
-  virtual void L4_NORETURN shutdown(int val)
-  {
-    _pm->shutdown(val == Reboot);
-    sync_all_other_cores_off();
-    exit(val);
-  }
-
-  virtual void sync_all_other_cores_off() const {};
-
-  int handle_mmio(l4_addr_t pfa, Vcpu_ptr vcpu)
-  {
-    int ret = -L4_EFAULT;
-
-    {
-      std::unique_lock lock(_memmap_lock);
-      Vm_mem::const_iterator f = _memmap.find(Region(Guest_addr(pfa)));
-
-      if (f != _memmap.end())
-        {
-          Region region = f->first;
-          cxx::Ref_ptr device = f->second;
-          lock.unlock();
-
-          ret = device->access(pfa, pfa - region.start.get(),
-                               vcpu, _task.get(),
-                               region.start.get(), region.end.get());
-          if (ret >= 0)
-            return ret;
-        }
-    }
-
-    auto insn = vcpu.decode_mmio();
-    warn().printf("Invalid %s 0x%lx, ip 0x%lx! %sing...\n",
-                  vcpu.pf_write() ? "write to" : "read from",
-                  pfa, vcpu->r.ip,
-                  _fault_mode == Fault_mode::Ignore
-                    ? "Ignor"
-                    : (_fault_mode == Fault_mode::Inject ? "Inject" : "Halt"));
-
-    switch (_fault_mode)
-      {
-      case Fault_mode::Ignore:
-        if (insn.access == Vmm::Mem_access::Load)
-          {
-            insn.value = 0;
-            vcpu.writeback_mmio(insn);
-          }
-        return Jump_instr;
-      case Fault_mode::Inject:
-        if (inject_abort(pfa, vcpu))
-          return Retry;
-        warn().printf("Abort inject failed! Halting VM...\n");
-        [[fallthrough]];
-      case Fault_mode::Halt:
-        break;
-      }
-
-    return ret;
-  }
-
-  /**
-   * Iterate over memory map and map all regions into the guest if possible.
-   *
-   * This function iterates over all memory areas and invokes their map_eager()
-   * method. Areas are then responsible for the actual mapping if there is one.
-   * There are some areas which trap and emulate mmio accesses and might not
-   * map anything or might only provide mappings for parts of the area they are
-   * responsible for.
-   */
-  void map_eager()
-  {
-    std::lock_guard g(_memmap_lock);
-    for (auto it : _memmap)
-      it.second->map_eager(_task.get(), it.first.start, it.first.end);
-  }
-
-  void add_mmio_device(Region const ®ion,
-                       cxx::Ref_ptr const &dev)
-  {
-    std::lock_guard g(_memmap_lock);
-    _memmap.add_mmio_device(region, dev);
-  }
-
-  void del_mmio_device(Region const ®ion)
-  {
-    std::lock_guard g(_memmap_lock);
-    Vm_mem::const_iterator f = _memmap.find(region);
-    assert(f != _memmap.end());
-    if (f == _memmap.end())
-      return;
-    f->second->unmap_guest_range(_task.get(), region.start,
-                                 region.end.get() - region.start.get() + 1U);
-    _memmap.erase(f);
-  }
-
-  /**
-   * Delete any device covered by the given region.
-   */
-  void del_mmio_devices(Region const ®ion)
-  {
-    std::lock_guard g(_memmap_lock);
-
-    auto range = _memmap.equal_range(region);
-    auto it = range.first;
-    while (it != range.second)
-      {
-        it->second->unmap_guest_range(_task.get(), it->first.start,
-                                      it->first.end - it->first.start + 1U);
-        it = _memmap.erase(it);
-      }
-  }
-
-  L4::Cap vm_task()
-  { return _task.get(); }
-
-protected:
-  using Timer_vector = std::vector>;
-
-  static Dbg warn()
-  { return Dbg(Dbg::Core, Dbg::Warn, "guest"); }
-
-  static Dbg info()
-  { return Dbg(Dbg::Core, Dbg::Info, "guest"); }
-
-  static Dbg trace()
-  { return Dbg(Dbg::Core, Dbg::Trace, "guest"); }
-
-  virtual bool inject_abort(l4_addr_t /*pfa*/, Vcpu_ptr /*vcpu*/)
-  { return false; }
-
-  std::mutex _memmap_lock;
-  Vm_mem _memmap;
-  L4Re::Util::Unique_cap _task;
-  cxx::Ref_ptr _pm;
-  Fault_mode _fault_mode = Fault_mode::Ignore;
-  l4_addr_t _dt_addr = 0;
-
-  std::map _clocks;
-  std::map _timer_devices;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/generic_vcpu_ptr.h b/src/l4/pkg/uvmm/server/src/generic_vcpu_ptr.h
deleted file mode 100644
index 658a9a58..00000000
--- a/src/l4/pkg/uvmm/server/src/generic_vcpu_ptr.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "vcpu_obj_registry.h"
-
-namespace Vmm {
-
-class Pt_walker;
-
-class Generic_vcpu_ptr
-{
-public:
-  l4_vcpu_state_t *operator -> () const noexcept
-  { return _s; }
-
-  l4_vcpu_state_t *operator * () const noexcept
-  { return _s; }
-
-  void control_ext(L4::Cap thread)
-  {
-    if (l4_error(thread->vcpu_control_ext(reinterpret_cast(_s))))
-      {
-        Err().printf("FATAL: Could not create vCPU. "
-                     "Running virtualization-enabled kernel?\n");
-        L4Re::throw_error(-L4_ENODEV, "Enable extended vCPU mode.");
-      }
-
-    if (!l4_vcpu_check_version(_s))
-      {
-        Err().printf("FATAL: Could not create vCPU. "
-                     "vCPU interface mismatch - Kernel %lx != User %x.\n",
-                     _s->version, L4_VCPU_STATE_VERSION);
-        L4Re::throw_error(-L4_ENODEV, "Matching vCPU interface versions.");
-      }
-
-    trace().printf("VCPU mapped @ %p and enabled\n", _s);
-  }
-
-  unsigned get_vcpu_id() const
-  { return _s->user_data[Reg_vcpu_id]; }
-
-  void set_vcpu_id(unsigned id)
-  { _s->user_data[Reg_vcpu_id] = id; }
-
-  Vcpu_obj_registry *get_ipc_registry() const
-  { return reinterpret_cast(_s->user_data[Reg_ipc_registry]); }
-
-  void set_ipc_registry(Vcpu_obj_registry *registry)
-  { _s->user_data[Reg_ipc_registry] = reinterpret_cast(registry); }
-
-  L4Re::Util::Br_manager *get_bm() const
-  { return reinterpret_cast(_s->user_data[Reg_bm]); }
-
-  void set_bm(L4Re::Util::Br_manager *bm)
-  { _s->user_data[Reg_bm] = reinterpret_cast(bm); }
-
-  Pt_walker *get_pt_walker() const
-  { return reinterpret_cast(_s->user_data[Reg_ptw_ptr]); }
-
-  void set_pt_walker(Pt_walker *ptw)
-  { _s->user_data[Reg_ptw_ptr] = reinterpret_cast(ptw); }
-
-  void handle_ipc(l4_msgtag_t tag, l4_umword_t label, l4_utcb_t *utcb)
-  {
-    // IPIs between CPUs have IRQs with zero label and are currently
-    // not handled by the registery. Return immediately on these IPCs.
-    if ((label & ~3UL) == 0)
-      return;
-
-    l4_msgtag_t r = l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
-
-    try
-      {
-        r = get_ipc_registry()->dispatch(tag, label, utcb);
-      }
-    catch (L4::Runtime_error &e)
-      {
-        warn().printf("Runtime exception in ipc path: %s(%ld)",
-                      e.str(), e.err_no());
-        r = l4_msgtag(e.err_no(), 0, 0, 0);
-      }
-    catch (int err)
-      {
-        warn().printf("Runtime exception in ipc path: %d",
-                      err);
-        r = l4_msgtag(err, 0, 0, 0);
-      }
-    catch (long err)
-      {
-        warn().printf("Runtime exception in ipc path: %ld",
-                      err);
-        r = l4_msgtag(err, 0, 0, 0);
-      }
-
-    if (r.label() != -L4_ENOREPLY)
-      l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, utcb, r,
-                  L4_IPC_SEND_TIMEOUT_0);
-  }
-
-  void wait_for_ipc(l4_utcb_t *utcb, l4_timeout_t to)
-  {
-    l4_umword_t src;
-    get_bm()->setup_wait(utcb, L4::Ipc_svr::Reply_separate);
-    l4_msgtag_t tag = l4_ipc_wait(utcb, &src, to);
-    if (!tag.has_error())
-      handle_ipc(tag, src, utcb);
-  }
-
-  void process_pending_ipc(l4_utcb_t *utcb)
-  {
-    while (_s->sticky_flags & L4_VCPU_SF_IRQ_PENDING)
-      wait_for_ipc(utcb, L4_IPC_BOTH_TIMEOUT_0);
-  }
-
-protected:
-  enum User_data_regs
-  {
-    Reg_vcpu_id = 0,
-    Reg_ipc_registry,
-    Reg_bm,
-    Reg_ptw_ptr,
-    Reg_arch_base
-  };
-
-  static Dbg warn()
-  { return Dbg(Dbg::Cpu, Dbg::Warn); }
-
-  static Dbg info()
-  { return Dbg(Dbg::Cpu, Dbg::Info); }
-
-  static Dbg trace()
-  { return Dbg(Dbg::Cpu, Dbg::Trace); }
-
-  static_assert(Reg_arch_base <= 7, "Too many user_data registers used");
-
-  explicit Generic_vcpu_ptr(l4_vcpu_state_t *s) : _s(s) {}
-
-  static l4_umword_t reg_extend_width(l4_umword_t value, char size, bool signext)
-  {
-    if (signext)
-      {
-        switch (size)
-          {
-          case 0: return static_cast(static_cast(value));
-          case 1: return static_cast(static_cast(value));
-          case 2: return static_cast(static_cast(value));
-          default: return value;
-          }
-      }
-
-    switch (size)
-      {
-      case 0: return static_cast(static_cast(value));
-      case 1: return static_cast(static_cast(value));
-      case 2: return static_cast(static_cast(value));
-      default: return value;
-      }
-  }
-
-  l4_vcpu_state_t *_s;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/host_dt.cc b/src/l4/pkg/uvmm/server/src/host_dt.cc
deleted file mode 100644
index 1e565039..00000000
--- a/src/l4/pkg/uvmm/server/src/host_dt.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "debug.h"
-#include "host_dt.h"
-
-static Dbg warn(Dbg::Core, Dbg::Warn, "main");
-
-namespace {
-
-  class Mapped_file
-  {
-  public:
-    explicit Mapped_file(char const *name)
-    {
-      int fd = open(name, O_RDWR);
-      if (fd < 0)
-        {
-          warn.printf("Unable to open file '%s': %s\n", name, strerror(errno));
-          return;
-        }
-
-      struct stat buf;
-      if (fstat(fd, &buf) < 0)
-        {
-          warn.printf("Unable to get size of file '%s': %s\n", name,
-                       strerror(errno));
-          close(fd);
-          return;
-        }
-      _size = buf.st_size;
-
-      _addr = mmap(nullptr, _size, PROT_WRITE | PROT_READ, MAP_PRIVATE, fd, 0);
-      if (_addr == MAP_FAILED)
-        warn.printf("Unable to mmap file '%s': %s\n", name, strerror(errno));
-
-      close(fd);
-    }
-    Mapped_file(Mapped_file &&) = delete;
-    Mapped_file(Mapped_file const &) = delete;
-
-    ~Mapped_file()
-    {
-      if (_addr != MAP_FAILED)
-        {
-          if (munmap(_addr, _size) < 0)
-            warn.printf("Unable to unmap file at addr %p: %s\n",
-                        _addr, strerror(errno));
-        }
-    }
-
-    void *get() const { return _addr; }
-    bool valid() { return _addr != MAP_FAILED; }
-    size_t size() const {return _size; }
-
-  private:
-    size_t _size = 0;
-    void *_addr = MAP_FAILED;
-  };
-
-}
-
-void
-Vdev::Host_dt::add_source(char const *fname)
-{
-  std::string filename(fname);
-
-  // trim leading whitespaces
-  filename.erase(0, filename.find_first_not_of(" "));
-
-  std::size_t pos = filename.find(":limit=");
-  if (pos != std::string::npos)
-    {
-      std::string r = filename.substr(pos + 7, std::string::npos);
-
-      _upper_limit = strtoull(r.c_str(), NULL, 0);
-      if (!_upper_limit)
-        {
-          Err().printf("Failed to parse a valid upper limit for DT placement. "
-                       "Found: '%s'. Configuration error. Exit.\n", r.c_str());
-          L4Re::chksys(-L4_EINVAL, "Unable to parse configuration for upper "
-                                   "limit for DT placement");
-        }
-
-      warn.printf("DT location configured to be below 0x%llx\n",
-                  _upper_limit);
-    }
-
-  Mapped_file mem(filename.substr(0, pos).c_str());
-  if (!mem.valid())
-    L4Re::chksys(-L4_EINVAL, "Unable to access overlay");
-
-  if (valid())
-    {
-      _fdt->resize(_fdt->size() + mem.size());
-      get().apply_overlay(mem.get(), filename.substr(0, pos).c_str());
-      return;
-    }
-
-  Dtb::Fdt fdt(mem.get());
-  Device_tree dt(&fdt);
-
-  dt.check_tree();
-
-  // XXX would be nice to expand dynamically
-  _fdt = cxx::make_unique(fdt, cxx::max(dt.size(), 0x200U));
-}
-
-/**
- * Device tree modification.
- *
- * Add/modify the given property before the device tree is parsed. The
- * syntax of the parameter is dt-path/dt-property=type:val where
- * dt-path are the node components delimited by / and type is either
- * str, bool, u32 or u64. The default type is str and if the "=..."
- * part is missing, it defaults to bool.
- *
- * \param[in] opt  Device tree modification parameter (see above).
- */
-void
-Vdev::Host_dt::modify(std::string const &opt)
-{
-  enum Val_type
-  {
-    String,
-    Bool,
-    UInt32,
-    UInt64
-  };
-
-  if (!valid() || opt.empty())
-    return;
-
-  Val_type vt = String;
-  std::string path = opt;
-  std::string name;
-  std::string val;
-
-  // Find the '=' delimiter between "dt-path/dt-property" and the rest.
-  std::size_t pos = opt.find("=");
-  if (pos != std::string::npos)
-    {
-      path = opt.substr(0, pos);
-      val = opt.substr(pos + 1);
-    }
-
-  // Find the '/' delimiter between "dt-path" and "dt-property".
-  pos = path.rfind("/");
-  if (pos != std::string::npos)
-    {
-      name = path.substr(pos + 1);
-      path = path.substr(0, pos + 1);
-    }
-
-  if (path.empty() || name.empty())
-    L4Re::throw_error_fmt(-L4_EINVAL, "Can't find name or path in option: %s",
-                          opt.c_str());
-
-  auto node = get().path_offset(path.c_str());
-  if (val.empty())
-    vt = Bool;
-  else
-    {
-      // Find the ':' delimiter between "type" and "val".
-      pos = val.find(":");
-      if (pos != std::string::npos)
-        {
-          std::string type = val.substr(0, pos);
-          val = val.substr(pos + 1);
-          if (type == "str")
-            vt = String;
-          else if (type == "bool")
-            vt = Bool;
-          else if (type == "u32")
-            vt = UInt32;
-          else if (type == "u64")
-            vt = UInt64;
-          else
-            L4Re::throw_error_fmt(-L4_EINVAL, "Unsupported type in option: %s",
-                                  opt.c_str());
-        }
-    }
-
-  switch(vt)
-    {
-    case Bool: node.setprop_data(name.c_str(), NULL, 0); break;
-    case String: node.setprop_string(name.c_str(), val.c_str()); break;
-    case UInt32:
-      {
-        errno = 0;
-        auto i = strtoul(val.c_str(), nullptr, 0);
-        if (errno)
-            L4Re::throw_error_fmt(-errno, "Can't convert value in option: %s",
-                                  opt.c_str());
-        node.setprop_u32(name.c_str(), i);
-        break;
-      }
-    case UInt64:
-      {
-        errno = 0;
-        auto i = strtoul(val.c_str(), nullptr, 0);
-        if (errno)
-            L4Re::throw_error_fmt(-errno, "Can't convert value in option: %s",
-                                  opt.c_str());
-        node.setprop_u64(name.c_str(), i);
-        break;
-      }
-    }
-}
-
-void
-Vdev::Host_dt::set_command_line(char const *cmd_line)
-{
-  if (!valid() || !cmd_line)
-    return;
-
-  // assume /choosen is present at this point
-  auto node = get().path_offset("/chosen");
-  node.setprop_string("bootargs", cmd_line);
-
-
-
-  // Do pragmatic sanity check on console= argument of a (Linux) cmdline and
-  // provide hints.
-  printf("Command line: %s\n", cmd_line);
-  if (strstr(cmd_line, "console="))
-    {
-      bool found_virtio_con = false;
-      bool found_pl011 = false;
-      bool found_8250 = false;
-      get().scan([&] (Vdev::Dt_node const &node, unsigned /* depth */)
-        {
-
-          char const *const comp = "compatible";
-          int count = node.stringlist_count(comp);
-          if (count <= 0)
-            return true;
-
-          for (int i = 0; i < count; ++i)
-            {
-              int cid_len;
-              char const *cid = node.stringlist_get(comp, i, &cid_len);
-              if (!cid)
-                continue;
-
-              if (!strncmp(cid, "virtio,mmio", cid_len))
-                {
-                  int prop_size;
-                  const char *p = node.get_prop("l4vmm,vdev", &prop_size);
-                  if (p && !strncmp(p, "console", prop_size))
-                    found_virtio_con = true;
-                }
-              else if (   !strncmp(cid, "arm,pl011", cid_len)
-                       or !strncmp(cid, "arm,sbsa-uart", cid_len))
-                found_pl011 = true;
-              else if (   !strncmp(cid, "uart,8250", cid_len)
-                       or !strncmp(cid, "ns8250", cid_len))
-                found_8250 = true;
-            }
-          return true;
-        },
-        [] (Vdev::Dt_node const &, unsigned) {});
-
-      if (!found_virtio_con && strstr(cmd_line, "console=hvc"))
-        printf("HINT: Found console=hvc on the command line but no "
-               "VirtIO console device in device tree!\n"
-               "HINT: VM-Output likely not to work!\n");
-      if (!found_pl011 && strstr(cmd_line, "console=ttyAMA"))
-        printf("HINT: Found console=ttyAMA on the command line but no "
-               "arm,pl011/sbsa-uart device in device tree!\n"
-               "HINT: VM-Output likely not to work!\n");
-      if (!found_8250 && strstr(cmd_line, "console=ttyS"))
-        printf("HINT: Found console=ttyS on the command line but no "
-               "uart,8250/ns16550a device in device tree!\n"
-               "HINT: VM-Output likely not to work!\n");
-    }
-}
diff --git a/src/l4/pkg/uvmm/server/src/host_dt.h b/src/l4/pkg/uvmm/server/src/host_dt.h
deleted file mode 100644
index da7ea8ce..00000000
--- a/src/l4/pkg/uvmm/server/src/host_dt.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "device.h"
-#include "mem_types.h"
-#include "monitor/dt_cmd_handler.h"
-
-namespace Vdev {
-
-/**
- * uvmm-internal device tree.
- */
-class Host_dt
-: public Monitor::Dt_cmd_handler
-{
-public:
-  Host_dt() = default;
-
-  // Copying isn't allowed
-  Host_dt(Host_dt const &) = delete;
-  Host_dt &operator=(Host_dt const &) = delete;
-
-  // Move is allowed
-  Host_dt(Host_dt &&other) = default;
-  Host_dt &operator=(Host_dt &&other) = default;
-
-  bool valid() const noexcept
-  { return _fdt; }
-
-  /**
-   * \note The returned object is valid only as long as this #Host_dt object
-   *       does not delete the underlying Dtb::Fdt object.
-   */
-  Device_tree get() const
-  { return Device_tree(_fdt.get()); }
-
-  void add_source(char const *fname);
-  void modify(std::string const &opt);
-
-  /**
-   * Set the command line parameter in the device tree.
-   *
-   * \param cmd_line  Command line to pass to the device tree.
-   *
-   * If the device tree is not set up or if the cmd_line is a null pointer,
-   * then the function is a no-op.
-   */
-  void set_command_line(char const *cmd_line);
-
-  /**
-   * Remove unused entries and pack the device tree.
-   *
-   * \note Only packing is implemented at the moment.
-   */
-  void compact()
-  { _fdt->pack(); }
-
-  /**
-   * Move the device tree to the given target address.
-   *
-   * \param target  Target address where to move the device tree.
-   *
-   * After the operation the device tree is invalid and the
-   * corresponding memory freed.
-   */
-  void move(void *target)
-  {
-    if (Monitor::cmd_control_enabled())
-      {
-        // Create a copy for the monitor
-        auto new_fdt = cxx::make_unique(*_fdt);
-        _fdt->move(target);
-        _fdt = cxx::move(new_fdt);
-      }
-    else
-        _fdt->move(target);
-  }
-
-  /**
-   * Return upper limit of guest memory area where the DT can be copied to.
-   *
-   * \returns Upper limit of DT address in guest memory.
-   */
-  l4_uint64_t upper_limit()
-  { return _upper_limit; }
-
-private:
-  cxx::unique_ptr _fdt;
-  l4_uint64_t _upper_limit = ~0ULL;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/io_device.h b/src/l4/pkg/uvmm/server/src/io_device.h
deleted file mode 100644
index 6dc43860..00000000
--- a/src/l4/pkg/uvmm/server/src/io_device.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2017, 2019, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "device.h"
-#include "mem_access.h"
-
-namespace Vmm {
-
-struct Io_device : virtual Vdev::Dev_ref
-{
-  virtual ~Io_device() = 0;
-
-  virtual void io_in(unsigned port, Mem_access::Width width,
-                     l4_uint32_t *value) = 0;
-  virtual void io_out(unsigned port, Mem_access::Width width,
-                      l4_uint32_t value) = 0;
-
-  virtual char const *dev_name() const = 0;
-
-  virtual char const *dev_info(char *buf, size_t size) const
-  {
-    if (size > 0)
-      {
-        strncpy(buf, dev_name(), size);
-        buf[size - 1] = '\0';
-      }
-    return buf;
-  };
-};
-
-inline Io_device::~Io_device() = default;
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/io_port_handler.h b/src/l4/pkg/uvmm/server/src/io_port_handler.h
deleted file mode 100644
index 38c6d898..00000000
--- a/src/l4/pkg/uvmm/server/src/io_port_handler.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018, 2020-2021, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-
-#include "device.h"
-#include "io_device.h"
-
-namespace Vdev {
-
-using namespace Vmm;
-
-class Io_port_handler : public Io_device, public Device
-{
-  unsigned _base;
-
-public:
-  Io_port_handler(unsigned port_base)
-  : _base(port_base)
-  {}
-
-  char const *dev_name() const override
-  { return "Pass-through device"; }
-
-  void io_in(unsigned p, Mem_access::Width width, l4_uint32_t *value) override;
-  void io_out(unsigned p, Mem_access::Width width, l4_uint32_t value) override;
-}; // class Io_port_handler
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/io_port_handler_noop.cc b/src/l4/pkg/uvmm/server/src/io_port_handler_noop.cc
deleted file mode 100644
index 3bf66c23..00000000
--- a/src/l4/pkg/uvmm/server/src/io_port_handler_noop.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2021, 2024 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include "io_port_handler.h"
-
-namespace Vdev {
-
-void Io_port_handler::io_in(unsigned, Mem_access::Width, l4_uint32_t *)
-{
-  assert(false);
-}
-
-void Io_port_handler::io_out(unsigned, Mem_access::Width, l4_uint32_t)
-{
-  assert(false);
-}
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/io_proxy.cc b/src/l4/pkg/uvmm/server/src/io_proxy.cc
deleted file mode 100644
index df29a5bd..00000000
--- a/src/l4/pkg/uvmm/server/src/io_proxy.cc
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (C) 2016-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "device_factory.h"
-#include "device_tree.h"
-#include "guest.h"
-#include "irq_dt.h"
-#include "io_proxy.h"
-#include "virt_bus.h"
-
-static Dbg trace(Dbg::Dev, Dbg::Trace, "ioproxy");
-static Dbg info(Dbg::Dev, Dbg::Info, "ioproxy");
-static Dbg warn(Dbg::Dev, Dbg::Warn, "ioproxy");
-
-namespace {
-
-  unsigned num_reg_entries(Vdev::Dt_node const &node)
-  {
-    if (!node.has_mmio_regs())
-      return 0;
-
-    for (unsigned num = 0;; ++num)
-      {
-        l4_uint64_t dtaddr, dtsize;
-        int ret = node.get_reg_val(num, &dtaddr, &dtsize);
-
-        if (ret == -Vdev::Dt_node::ERR_BAD_INDEX)
-          return num;
-
-        if (ret < 0)
-          L4Re::chksys(-L4_EINVAL, "Check reg descriptor in device tree.");
-      }
-
-    // not reached
-  }
-
-  unsigned num_interrupts(Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-  {
-    if (!node.has_irqs())
-      return 0;
-
-    auto it = Vdev::Irq_dt_iterator(devs, node);
-
-    for (unsigned num = 0;; ++num)
-      {
-        int ret = it.next(devs);
-
-        if (ret == -L4_ERANGE)
-          return num;
-
-        if (ret < 0)
-          L4Re::chksys(ret, "Check interrupt descriptions in device tree");
-      }
-
-    // not reached
-  }
-}
-
-
-namespace Vdev {
-
-// default set to false
-static bool phys_dev_prepared;
-
-void
-Io_proxy::prepare_factory(Device_lookup const *devs)
-{
-  devs->vbus()->collect_resources(devs);
-  phys_dev_prepared = true;
-}
-
-bool
-Io_proxy::check_and_bind_irqs(Device_lookup *devs, Dt_node const &node)
-{
-  if (!node.has_irqs())
-    return true;
-
-  // Check whether all IRQs are available
-  auto vbus = devs->vbus().get();
-
-  Irq_dt_iterator it(devs, node);
-  do
-    {
-      if (it.next(devs) < 0)
-        return false;
-
-      // Check that the IRQ is available on the vbus when a
-      // virtual interrupt handler needs to be connected.
-      if (it.ic_is_virt() && ! vbus->irq_present(it.irq()))
-        {
-          warn.printf("No corresponding IO resource for '%s' IRQ %d.\n",
-                      node.get_name(), it.irq());
-          return false;
-        }
-    }
-  while (it.has_next());
-
-  // Now bind the IRQs.
-  it = Irq_dt_iterator(devs, node);
-  do
-    {
-      it.next(devs);
-
-      if (it.ic_is_virt())
-        {
-          int dt_irq = it.irq();
-          bind_irq(devs->vmm(), vbus, it.ic(), dt_irq, dt_irq, node.get_name());
-          vbus->mark_irq_bound(dt_irq);
-        }
-    }
-  while (it.has_next());
-
-  return true;
-}
-
-void
-Io_proxy::bind_irq(Vmm::Guest *vmm, Vmm::Virt_bus *vbus,
-                   cxx::Ref_ptr const &ic,
-                   unsigned dt_irq, unsigned io_irq, char const *dev_name)
-{
-  info.printf("IO device '%s' - registering IRQ %u -> %u\n",
-      dev_name, io_irq, dt_irq);
-
-  auto *irq_source = ic->get_irq_src_handler(dt_irq);
-  if (!irq_source)
-    {
-      auto irq_svr =
-        cxx::make_ref_obj(vmm->registry(), vbus->icu(),
-                                      io_irq, ic, dt_irq);
-      irq_svr->eoi();
-
-      _irqs.push_back(std::move(irq_svr));
-      return;
-    }
-
-  warn.printf("IO device '%s': IRQ %u -> %u already registered\n",
-      dev_name, io_irq, dt_irq);
-
-  // Ensure we have the correct binding of the currently registered
-  // source
-  auto other_svr = dynamic_cast(irq_source);
-
-  if (!other_svr)
-    {
-      Err().printf("ic:%u is bound to a different IRQ type\n",
-                   dt_irq);
-      L4Re::chksys(-L4_EEXIST, "Bind IRQ for IO proxy object.");
-    }
-
-  if (io_irq != other_svr->get_io_irq())
-    {
-      Err().printf("bind_irq: %u -> ic:%u -- "
-                   "IRQ already bound to different IO IRQ: %u\n",
-                   io_irq, dt_irq, other_svr->get_io_irq());
-      L4Re::chksys(-L4_EEXIST, "Bind IRQ for IO proxy object.");
-    }
-
-  // Take a reference of the existing IRQ handler.
-  _irqs.emplace_back(other_svr);
-}
-
-
-
-namespace {
-
-static bool
-mmio_region_valid(Vmm::Vm_mem const *memmap, l4_uint64_t addr, l4_uint64_t size,
-                  Dt_node const &node, int index)
-{
-  Vmm::Vm_mem::const_iterator f = memmap->find(Vmm::Region(Vmm::Guest_addr(addr)));
-
-  if (f == memmap->end())
-    {
-      warn.printf("No corresponding IO resource for '%s'.reg[%d] (0x%llx-0x%llx).\n",
-                  node.get_name(), index, addr, addr + size - 1);
-      return false;
-    }
-
-  if (f->first.type != Vmm::Region_type::Vbus)
-    {
-      if (f->first.type != Vmm::Region_type::Ram)
-        {
-          warn.printf("Conflicting resource types for '%s'.reg[%d], expected {%d, %d}, got %d\n",
-                      node.get_name(), index,
-                      static_cast(Vmm::Region_type::Vbus),
-                      static_cast(Vmm::Region_type::Ram),
-                      static_cast(f->first.type));
-          return false;
-        }
-      info.printf("'%s'.reg[%d] references physical RAM.\n",
-                  node.get_name(), index);
-    }
-
-  if (Vmm::Guest_addr(addr + size) > f->first.end + 1)
-    {
-      warn.printf("Reg entry '%s'.reg[%d] exceeds corresponding IO resource.\n",
-          node.get_name(), index);
-      return false;
-    }
-
-  return true;
-}
-
-
-struct F : Factory
-{
-  static bool check_regs(Device_lookup const *devs,
-                         Dt_node const &node)
-  {
-    if (!node.has_prop("reg"))
-      return true;
-
-    Vmm::Vm_mem const *memmap = devs->vmm()->memmap();
-    l4_uint64_t addr, size;
-    for (int index = 0; /* no condition */ ; ++index)
-      {
-        int res = node.get_reg_val(index, &addr, &size);
-        switch (res)
-          {
-          case 0:
-            if (!mmio_region_valid(memmap, addr, size, node, index))
-              return false;
-            break;
-          case -Dt_node::ERR_BAD_INDEX:
-            // reached end of reg entries
-            return true;
-          case -Dt_node::ERR_NOT_TRANSLATABLE:
-            // region not managed by us
-            continue;
-          case -Dt_node::ERR_RANGE:
-            info.printf("Reg entry too large '%s'.reg[%d]\n",
-                        node.get_name(), index);
-            return false;
-          default:
-            Err().printf("Invalid reg entry '%s'.reg[%d]: %s\n",
-                         node.get_name(), index, fdt_strerror(res));
-            return false;
-          }
-      }
-  }
-
-  cxx::Ref_ptr create_from_vbus_dev(Device_lookup *devs,
-                                            Dt_node const &node,
-                                            char const *hid)
-  {
-    auto *vdev = devs->vbus()->find_unassigned_device_by_hid(hid);
-
-    if (!vdev)
-      {
-        warn.printf("%s: requested vbus device '%s' not available.\n",
-                    node.get_name(), hid);
-        return nullptr;
-      }
-
-    // Count number of expected resources as a cheap means of validation.
-    // This also checks that the device tree properties are correctly parsable.
-    unsigned todo_regs = num_reg_entries(node);
-    unsigned todo_irqs = num_interrupts(devs, node);
-
-    auto device = make_device(vdev->io_dev());
-
-    // collect resources directly for device
-    auto vbus = devs->vbus().get();
-    for (unsigned i = 0; i < vdev->dev_info().num_resources; ++i)
-      {
-        l4vbus_resource_t res;
-
-        L4Re::chksys(vdev->io_dev().get_resource(i, &res),
-                     "Cannot get resource in collect_resources");
-
-        char const *resname = reinterpret_cast(&res.id);
-
-        if (res.type == L4VBUS_RESOURCE_MEM)
-          {
-            if (strncmp(resname, "reg", 3) || resname[3] < '0' || resname[3] > '9')
-              {
-                warn.printf("%s: Vbus memory resource '%.4s' has no recognisable name.\n",
-                            node.get_name(), resname);
-                continue;
-              }
-
-            unsigned resid = resname[3] - '0';
-            l4_uint64_t dtaddr, dtsize;
-            L4Re::chksys(node.get_reg_val(resid, &dtaddr, &dtsize),
-                         "Match reg entry of device entry with vbus resource.");
-
-            if (res.end - res.start + 1 != dtsize)
-              L4Re::chksys(-L4_ENOMEM,
-                           "Matching resource size of VBUS resource and device tree entry");
-
-            trace.printf("Adding MMIO resource %s.%.4s : [0x%lx - 0x%lx] -> [0x%llx - 0x%llx]\n",
-                      vdev->dev_info().name, resname, res.start, res.end,
-                      dtaddr, dtaddr + (dtsize - 1));
-
-            L4Re::Rm::Region_flags rm_flags = L4Re::Rm::F::RW;
-            if (res.flags & L4VBUS_RESOURCE_F_MEM_CACHEABLE)
-              rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_normal;
-            else if (res.flags & L4VBUS_RESOURCE_F_MEM_PREFETCHABLE)
-              rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_buffered;
-            else
-              rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_uncached;
-            auto ds_mgr = cxx::make_ref_obj(
-              "Io_proxy: vbus", vbus->io_ds(), res.start, dtsize, rm_flags);
-            auto handler = Vdev::make_device(ds_mgr);
-            auto region = Vmm::Region::ss(Vmm::Guest_addr(dtaddr), dtsize,
-                                          Vmm::Region_type::Virtual);
-            devs->vmm()->add_mmio_device(region, handler);
-            --todo_regs;
-          }
-        else if (res.type == L4VBUS_RESOURCE_IRQ)
-          {
-            if (strncmp(resname, "irq", 3) || resname[3] < '0' || resname[3] > '9')
-              {
-                warn.printf("%s: Vbus memory resource '%.4s' has no recognisable name.\n",
-                            node.get_name(), resname);
-                continue;
-              }
-
-            unsigned resid = resname[3] - '0';
-
-            if (resid >= todo_irqs)
-              {
-                Err().printf("%s: VBUS interrupts resource '%.4s' has no matching device tree entry.\n",
-                             node.get_name(), resname);
-                L4Re::chksys(-L4_ENOMEM,
-                             "Matching VBUS interrupt resources against device tree.");
-              }
-
-            auto it = Irq_dt_iterator(devs, node);
-            it.next(devs);
-
-            for (unsigned n = 0; n < resid; ++n)
-              {
-                // Just advance the iterator without error checking. num_interrupts()
-                // above already checked that 'todo_irqs' interrupts are well defined.
-                it.next(devs);
-              }
-
-            if (it.ic_is_virt())
-              {
-                int dt_irq = it.irq();
-                device->bind_irq(devs->vmm(), vbus, it.ic(), dt_irq, res.start,
-                                 node.get_name());
-              }
-
-            trace.printf("Registering IRQ resource %s.%.4s : %lu\n",
-                         vdev->dev_info().name, resname, res.start);
-            --todo_irqs;
-          }
-      }
-
-    if (todo_regs > 0)
-      {
-        Err().printf("%s: not enough memory resources found in VBUS device '%s'.\n",
-                     node.get_name(), hid);
-        L4Re::chksys(-L4_EINVAL, "Match memory resources");
-      }
-    if (todo_irqs > 0)
-      {
-        Err().printf("%s: not enough interrupt resources found in VBUS device '%s'.\n",
-                     node.get_name(), hid);
-        L4Re::chksys(-L4_EINVAL, "Match interrupt resources");
-      }
-
-    vdev->set_handler(device);
-
-    return device;
-  }
-
-  cxx::Ref_ptr create(Device_lookup *devs,
-                              Dt_node const &node) override
-  {
-    char const *prop = node.get_prop("l4vmm,vbus-dev", nullptr);
-
-    if (prop)
-      return create_from_vbus_dev(devs, node, prop);
-
-    if (!phys_dev_prepared)
-      {
-        Err().printf("%s: Io_proxy::create() invoked before prepare_factory()\n"
-                     "\tprobably invalid device tree\n", node.get_name());
-        return nullptr;
-      }
-
-    L4vbus::Device io_dev;
-    auto device = make_device(io_dev);
-
-    // Check mmio resources - mmio areas are already established
-    if (!check_regs(devs, node))
-      return nullptr;
-
-    if (!device->check_and_bind_irqs(devs, node))
-      return nullptr;
-
-    return device;
-  }
-
-  F() { pass_thru = this; }
-};
-
-static F f;
-
-} // namespace
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/io_proxy.h b/src/l4/pkg/uvmm/server/src/io_proxy.h
deleted file mode 100644
index 985e6b17..00000000
--- a/src/l4/pkg/uvmm/server/src/io_proxy.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016-2020, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "irq_svr.h"
-#include "virt_bus.h"
-
-namespace Vdev {
-
-class Io_proxy : public Device
-{
-  class Io_irq_svr : public Irq_svr
-  {
-  public:
-    using Irq_svr::Irq_svr;
-
-    unsigned get_io_irq() const
-    { return _irq_num; }
-  };
-
-public:
-  Io_proxy(L4vbus::Device const &dev)
-  : _dev(dev)
-  {}
-
-  /**
-   * Prepare the factory for creation of physical devices.
-   *
-   * \param devs  Pointer to Device_lookup interface used to prepare the factory
-   *
-   * To create non-virtual devices there might be some additional preparations
-   * needed. This method has to be invoked before trying to create non-physical
-   * devices.
-   */
-  static void prepare_factory(Device_lookup const *devs);
-
-  bool check_and_bind_irqs(Device_lookup *devs, Dt_node const &node);
-
-  void bind_irq(Vmm::Guest *vmm, Vmm::Virt_bus *vbus,
-                cxx::Ref_ptr const &ic,
-                unsigned dt_irq, unsigned io_irq, char const *dev_name);
-
-private:
-  L4vbus::Device _dev;
-  std::vector> _irqs;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/irq.h b/src/l4/pkg/uvmm/server/src/irq.h
deleted file mode 100644
index 0c0d50b4..00000000
--- a/src/l4/pkg/uvmm/server/src/irq.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2015-2018, 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-#include 
-
-#include "device.h"
-#include "device_tree.h"
-#include "generic_vcpu_ptr.h"
-
-namespace Gic {
-
-/**
- * Interface for handlers of interrupt sources.
- *
- * This is the generic interface for notifications from the
- * interrupt controller to an interrupt-emitting device.
- */
-struct Irq_src_handler
-{
-  /**
-   * Guest has issued end-of-interrupt message.
-   */
-  virtual void eoi() {}
-
-  /**
-   * Hint that the target vCPU of an IRQ source has changed.
-   *
-   * Might be used by the IRQ source to change the interrupt affinity
-   * accordingly.
-   */
-  virtual void irq_src_target(Vmm::Generic_vcpu_ptr) {}
-
-  /**
-   * Set IRQ configuration.
-   *
-   * If direct IRQ injection is supported by the platform, update the vCPU
-   * interrupt specification.
-   *
-   * \arg cfg   Architecture specific vIRQ configuration
-   */
-  virtual void configure(l4_umword_t /* cfg */) {}
-
-  /**
-   * Enable interrupt source.
-   *
-   * Called from the virtual interrupt controller if the guest enabled the
-   * interrupt.
-   *
-   * Bind the interrupt source and forward interrupts to the guest. If the
-   * platform supports direct interrupt injection, the function will return
-   * true. The virtual interrupt controller must not forward any events for the
-   * IRQ then. Otherwise, the function returns false and all event delivery is
-   * up to the virtual interrupt controller.
-   *
-   * \retval true   Direct IRQ forwarding supported and enabled.
-   * \retval false  No direct IRQ forwading. Interrupt will be injected via
-   *                Gic::Ic::set().
-   */
-  virtual bool enable() { return false; }
-
-  /**
-   * Disable interrupt source.
-   *
-   * Called from the virtual interrupt controller if the guest disabled the
-   * interrupt.
-   */
-  virtual void disable() {}
-
-protected:
-  virtual ~Irq_src_handler() = default;
-};
-
-/**
- * Generic interrupt controller interface.
- */
-struct Ic : public Vdev::Device
-{
-  virtual void set(unsigned irq) = 0;
-  virtual void clear(unsigned irq) = 0;
-
-  /**
-   * Register an IRQ source for forwarding downstream events.
-   *
-   * Only one device source can be registered, throws a runtime
-   * exception if the IRQ source is already bound
-   *
-   * \param irq Irq number to connect the listener to.
-   * \param src Device source. If the IRQ is already bound it needs to
-   *            be the same device source as the already registered one.
-   *            Set to nullptr to unbind a registered handler.
-   *
-   * \note The caller is responsible to ensure that the IRQ source handler is
-   *       unbound before it is destructed.
-   */
-  virtual void bind_irq_src_handler(unsigned irq, Irq_src_handler *src) = 0;
-
-  /**
-   * Get the IRQ source currently bound to irq
-   *
-   * \param irq Irq number
-   * \return Irq source currently bound to irq
-   */
-  virtual Irq_src_handler *get_irq_src_handler(unsigned irq) const = 0;
-
-  /**
-   * Extract the interrupt id from a device tree property.
-   *
-   * \param prop       Pointer to the property containing the interrupt
-   *                   description. This may also point into the middle
-   *                   of a property list.
-   * \param propsz     Remaining length of the property list.
-   * \param[out] read  If read is not a nullptr, then it contains the number
-   *                   of elements that have been read.
-   *
-   * \retval >=0  Interrupt number to use with the controller.
-   * \retval <0   Error reading property.
-   */
-  virtual int dt_get_interrupt(fdt32_t const *prop, int propsz, int *read) const = 0;
-
-};
-
-} // namespace
-
-namespace Vmm {
-
-/**
- * Generic interrupt line on an interrupt controller.
- *
- * The Irq_sink implements a line-triggered interrupt and
- * remembers it's current state. It will only notify the
- * interrupt controller when it's state changes, thus effectively
- * ignoring multiple inject() or ack().
- */
-class Irq_sink
-{
-public:
-  Irq_sink() : _ic(nullptr) {}
-
-  Irq_sink(cxx::Ref_ptr const &ic, unsigned irq)
-  : _irq(irq), _ic(ic)
-  {}
-
-  Irq_sink(Irq_sink const &) = delete;
-  Irq_sink(Irq_sink &&other) = delete;
-
-  ~Irq_sink()
-  { ack(); }
-
-  void rebind(cxx::Ref_ptr const &ic, unsigned irq)
-  {
-    ack();
-
-    _ic = ic;
-    _irq = irq;
-  }
-
-  void inject()
-  {
-    if (_state || !_ic)
-      return;
-
-    _state = true;
-    _ic->set(_irq);
-  }
-
-  void ack()
-  {
-    if (!_state || !_ic)
-      return;
-
-    _ic->clear(_irq);
-    _state = false;
-  }
-
-  /**
-   * Set the given IRQ source handler at the connected IC.
-   *
-   * \param handler  Handler to set for IRQ source notification.
-   *
-   * The function is only a forwarder to Ic::bind_irq_src_handler(), the
-   * handler must still be managed by the caller. In particular, the caller
-   * must make sure that the handler is unbound before the Irq_sink
-   * object is destructed.
-   *
-   * If no IC has been bound yet, the function does nothing.
-   */
-  void set_irq_src_handler(Gic::Irq_src_handler *handler) const
-  {
-    if (_ic)
-      _ic->bind_irq_src_handler(_irq, handler);
-  }
-
-private:
-  unsigned _irq = 0;
-  cxx::Ref_ptr _ic;
-  bool _state = false;
-};
-
-/**
- * Generic interrupt line on an interrupt controller.
- *
- * The Irq_edge_sink implements an edge-triggered interrupt.
- * It notifies the interrupt controller on each inject.
- */
-class Irq_edge_sink
-{
-public:
-  Irq_edge_sink() = default;
-
-  Irq_edge_sink(cxx::Ref_ptr const &ic, unsigned irq)
-  : _irq(irq), _ic(ic)
-  {}
-
-  void rebind(cxx::Ref_ptr const &ic, unsigned irq)
-  {
-    _ic = ic;
-    _irq = irq;
-  }
-
-  void inject()
-  { _ic->set(_irq); }
-
-  unsigned irq() const { return _irq; }
-  Gic::Ic* ic() const { return _ic.get(); }
-
-private:
-  unsigned _irq;
-  cxx::Ref_ptr _ic;
-};
-
-
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/irq_dt.h b/src/l4/pkg/uvmm/server/src/irq_dt.h
deleted file mode 100644
index 85b521f4..00000000
--- a/src/l4/pkg/uvmm/server/src/irq_dt.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "device_factory.h"
-#include "irq.h"
-
-namespace Vdev {
-
-/**
- * Helper class to allow iterating over the interrupts of a device tree node.
- */
-class Irq_dt_iterator
-{
-public:
-  /**
-   * Create a new iterator.
-   *
-   * \param devs  Device repository of virtual uvmm devices.
-   * \param node  Node to do the interrupt lookup for.
-   *
-   * The iterator is able to parse either class 'interrupt' properties or
-   * the newer 'extended-interrupt' descriptors transparently. It finds and
-   * creates interrupt parents as required while iterating over the interrupts.
-   *
-   * The iterator is set up to point before the first interrupt. You need to
-   * call next() to advance the first interrupt. If there are any errors during
-   * creation, for example when the node has no interrupt description at all,
-   * then the first call to next() will fail.
-   */
-  Irq_dt_iterator(Device_lookup *devs, Dt_node const &node)
-  : _node(node), _irq_num(0), _prop(nullptr)
-  {
-    if (node.has_prop("interrupts-extended"))
-      {
-        _is_extended = true;
-        _prop = node.get_prop("interrupts-extended", &_prop_size);
-      }
-    else if (node.has_prop("interrupts"))
-      {
-        _is_extended = false;
-        _ic_node = node.find_irq_parent();
-
-        if (_ic_node.is_valid())
-          {
-            Device_lookup::Ic_error res = devs->get_or_create_ic(node, &_ic);
-
-            if (res == Device_lookup::Ic_ok || res == Device_lookup::Ic_e_no_virtic)
-              _prop = node.get_prop("interrupts", &_prop_size);
-          }
-      }
-  }
-
-  /**
-   * Advance to the next interrupt entry.
-   *
-   * \param devs  Device repository of virtual uvmm devices.
-   *
-   * \retval L4_EOK      Successfully advanced to next interrupt.
-   * \retval -L4_ERANGE  No further interrupts in the list.
-   * \retval -L4_EINVAL  The device tree entry was badly formatted.
-   * \retval -L4_ENODEV  The interrupt parent for the next interrupt is not
-   *                     available.
-   *
-   * This function has to be called before reading any interrupt information,
-   * including the first interrupt in the list.
-   *
-   * The state of the iterator is undefined after next() has returned
-   * an error.
-   */
-  int next(Device_lookup *devs)
-  {
-    if (!_prop)
-      {
-        if (_node.has_irqs())
-          warn().printf("Interrupt parent not found.\n");
-        else
-          warn().printf("Node has no interrupt information.\n");
-        return -L4_EINVAL;
-      }
-
-    if (_prop_size <= 0)
-      return -L4_ERANGE;
-
-    if (_is_extended)
-      next_extended_ic(devs);
-
-    int cell_size;
-    if (_ic)
-      {
-        _irq_num = _ic->dt_get_interrupt(_prop, _prop_size, &cell_size);
-
-        if (_irq_num < 0)
-          {
-            warn().printf("Cannot translate interrupt.\n");
-            return -L4_EINVAL;
-          }
-      }
-    else
-      {
-        // unmanaged interrupt controller, get cell size for advancing only
-        int sz;
-        auto *cells = _ic_node.get_prop("#interrupt-cells", &sz);
-        if (!cells)
-          {
-            warn().printf("#interrupt-cells property missing in interrupt parent '%s'.\n",
-                _ic_node.get_name());
-            return -L4_ENODEV;
-          }
-        if (sz != 1)
-          {
-            warn().printf("Bad #interrupt-cells property in interrupt parent '%s'.\n",
-                _ic_node.get_name());
-            return -L4_EINVAL;
-          }
-
-        cell_size = fdt32_to_cpu(*cells);
-
-        if (_prop_size < cell_size)
-          {
-            warn().printf("Not enough parameters in interrupt description.\n");
-            return -L4_EINVAL;
-          }
-      }
-
-    _prop += cell_size;
-    _prop_size -= cell_size;
-
-    return L4_EOK;
-  }
-
-  /**
-   * Check if there are more interrupts defined for the node.
-   */
-  bool has_next() const noexcept
-  { return _prop_size > 0; }
-
-  /**
-   * Return the device of the virtual interrupt parent responsible for
-   * handling the interrupt the iterator currently points to.
-   *
-   * \return Reference to the interrupt parent or nullptr if the interrupt
-   *         parent is not managed by uvmm.
-   */
-  cxx::Ref_ptr ic() const noexcept
-  { return _ic; }
-
-  /**
-   * Check if the interrupt is handled by a virtual interrupt handler
-   * that is managed by uvmm.
-   */
-  bool ic_is_virt() const noexcept
-  { return bool(_ic); }
-
-  /**
-   * Return the interrupt number of the interrupt the iterator currently points
-   * to.
-   *
-   * \return Interrupt number to use with the interrupt parent.
-   *
-   * \pre Must only be called when the interrupt parent is managed by uvmm
-   *      (i.e. when ic() is not null).
-   */
-  unsigned irq() const
-  {
-    assert(_irq_num >= 0);
-    return _irq_num;
-  }
-
-private:
-  int next_extended_ic(Device_lookup *devs)
-  {
-    _ic_node = _node.find_phandle(*_prop);
-
-    ++_prop;
-    --_prop_size;
-
-    if (!_ic_node.is_valid())
-      {
-        warn().printf("Interrupt parent node not found.\n");
-        return -L4_EINVAL;
-      }
-
-    if (!_ic_node.is_enabled())
-      {
-        warn().printf("Interrupt parent '%s' disabled.\n", _ic_node.get_name());
-        return -L4_ENODEV;
-      }
-
-    if (Vdev::Factory::is_vdev(_ic_node))
-      {
-        _ic = cxx::dynamic_pointer_cast(
-                Vdev::Factory::create_dev(devs, _ic_node));
-        if (!_ic)
-          {
-            warn().printf("Virtual interrupt parent '%s' cannot be created.\n",
-                          _ic_node.get_name());
-            return -L4_ENODEV; // no device or not an IC
-          }
-      }
-    else
-      _ic = nullptr;
-
-    return L4_EOK;
-  }
-
-
-  Dbg warn() const
-  { return Dbg(Dbg::Core, Dbg::Warn, _node.get_name()); }
-
-  /// Node that is currently being parsed.
-  Dt_node _node;
-  /// Interrupt parent device, if available.
-  cxx::Ref_ptr _ic;
-  /// Node of interrupt parent device.
-  Dt_node _ic_node;
-  /// Interrupt number (only valid when _ic != nullptr).
-  int _irq_num;
-  /// Pointer to current position in interrupt property list.
-  fdt32_t const *_prop;
-  /// Remaining length of property list.
-  int _prop_size;
-  /// True if the property list being parsed is an extended list.
-  bool _is_extended;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/irq_svr.h b/src/l4/pkg/uvmm/server/src/irq_svr.h
deleted file mode 100644
index 7ebfc839..00000000
--- a/src/l4/pkg/uvmm/server/src/irq_svr.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2016-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "vcpu_obj_registry.h"
-#include "irq.h"
-#include "vcpu_ptr.h"
-
-namespace Vdev {
-
-/**
- * Interrupt passthrough.
- *
- * Forwards L4Re interrupts to an Irq_sink.
- */
-class Irq_svr
-: public Gic::Irq_src_handler,
-  public L4::Irqep_t,
-  public cxx::Ref_obj
-{
-  /**
-   * Irq receiver binding state.
-   *
-   * Until the guest enables the interrupt, it stays in the Init state. Upon
-   * the first enable(), it is decided if the kernel supports direct IRQ
-   * injection. If not, move to the final Ipc_bound state where all interrupts
-   * are funnled through uvmm. Otherwise the state will alternate beween
-   * Vcpu_enabled and Vcpu_disabled, depending on the guest state.
-   *
-   * If the platform does not support direct injection at all, we move directly
-   * to the Ipc_bound state. The same is true if the interrupt must be unmasked
-   * at the ICU because the kernel does not support such an Irq.
-   *
-   * Possible state transitions:
-   *
-   *   Init -> Ipc_bound | Vcpu_enabled
-   *   Vcpu_enabled -> Vcpu_disabled
-   *   Vcpu_disabled -> Vcpu_enabled
-   */
-  enum class State : l4_uint8_t
-  {
-    Init,           ///< Initial state. Not bound to vCPU thread yet.
-    Ipc_bound,      ///< Bound as regular IPC receiver at vCPU thread.
-    Vcpu_enabled,   ///< Bound for direct injection at vCPU.
-    Vcpu_disabled,  ///< Use direct injection but temporarily disabled by guest.
-  };
-
-public:
-  Irq_svr(Vcpu_obj_registry *registry, L4::Cap icu,
-          unsigned irq, cxx::Ref_ptr const &ic, unsigned dt_irq)
-  : _ic(ic),
-    _dt_irq(dt_irq),
-    _irq_num(irq),
-    _registry(registry),
-    _cap(L4Re::Util::make_unique_cap())
-  {
-    if (ic->get_irq_src_handler(dt_irq))
-      L4Re::throw_error(-L4_EEXIST, "Bind IRQ for Irq_svr object.");
-
-    L4Re::chkcap(_cap.get(), "Coult not alloc Irq_svr L4::Irq");
-    L4Re::chksys(L4Re::Env::env()->factory()->create(_cap.get()),
-                 "Failed to create Irq_svr L4::Irq");
-
-    int ret = L4Re::chksys(icu->bind(irq, _cap.get()),
-                           "Cannot bind to IRQ");
-    switch (ret)
-      {
-      case 0:
-        Dbg(Dbg::Dev, Dbg::Info, "irq_svr")
-          .printf("Irq 0x%x will be unmasked directly\n", irq);
-        set_eoi(_cap.get());
-        // The _cap is not registered yet. If the platform supports it, we'll
-        // try to setup direct vCPU vIRQ injection on the first enable(). If
-        // that doesn't work, fall back to regular IPC.
-        if (!bind_vcpu_supported())
-          bind_as_ipc();
-        break;
-      case 1:
-        Dbg(Dbg::Dev, Dbg::Info, "irq_svr")
-          .printf("Irq 0x%x will be unmasked at ICU\n", irq);
-        set_eoi(icu);
-        // Fiasco direct injection does not work if the interrupt must be
-        // unmasked at the ICU. Register as IPC receiver...
-        bind_as_ipc();
-        break;
-      default:
-        L4Re::throw_error(-L4_EINVAL, "Invalid return code from bind to IRQ");
-        break;
-      }
-
-    ic->bind_irq_src_handler(dt_irq, this);
-  }
-
-  ~Irq_svr() noexcept
-  {
-    unbind_irq_src_handler();
-
-    switch (_state)
-      {
-      case State::Ipc_bound:
-        unbind_from_ipc();
-        break;
-      case State::Vcpu_enabled:
-        unbind_from_vcpu();
-        break;
-      default:
-        break;
-      }
-  }
-
-  void handle_irq()
-  { _ic->set(_dt_irq); }
-
-  void eoi() override
-  {
-    // Opportunistic check for interrupts that are bound as IPC and are always
-    // funnled through uvmm. We don't need the lock because State::Ipc_bound
-    // is a final state.
-    if (!bind_vcpu_supported() || _state == State::Ipc_bound)
-      {
-        _eoi->unmask(_irq_num);
-        return;
-      }
-
-    std::lock_guard lock(_mutex);
-
-    switch (_state)
-      {
-      case State::Init:
-        // EOI before IRQ was enabled -> ignore.
-        break;
-      case State::Ipc_bound:
-        _eoi->unmask(_irq_num);
-        break;
-      case State::Vcpu_enabled:
-        // This might happen if the guest moved an active IRQ between vCPUs.
-        // The EOI is handled by uvmm and we can now re-bind the interrupt to
-        // the vCPU.
-        L4Re::chksys(_cap->bind_vcpu(_registry->server(), _vcpu_irq_cfg));
-        _eoi->unmask(_irq_num);
-        _active = false;
-        break;
-      case State::Vcpu_disabled:
-        // This might happen if the guest disabled an active IRQ. Otherwise
-        // the EOI is handled by the kernel directly.
-        _active = false;
-        break;
-      }
-  }
-
-  void irq_src_target(Vmm::Generic_vcpu_ptr vcpu) override
-  {
-    std::lock_guard lock(_mutex);
-
-    _registry = vcpu.get_ipc_registry();
-    switch (_state)
-      {
-      case State::Ipc_bound:
-        L4Re::chkcap(_registry->move_obj(this), "move registry");
-        break;
-      case State::Vcpu_enabled:
-        try_bind_as_vcpu();
-        break;
-      case State::Init:
-      case State::Vcpu_disabled:
-        break;
-      }
-  }
-
-  void configure(l4_umword_t cfg) override
-  {
-    if (!bind_vcpu_supported())
-      return;
-
-    std::lock_guard lock(_mutex);
-
-    _vcpu_irq_cfg = cfg;
-    if (_state == State::Vcpu_enabled)
-      try_bind_as_vcpu();
-  }
-
-  bool enable() override
-  {
-    if (!bind_vcpu_supported())
-      return false;
-
-    std::lock_guard lock(_mutex);
-
-    switch (_state)
-      {
-      case State::Init:
-        if (try_bind_as_vcpu())
-          _state = State::Vcpu_enabled;
-        else
-          // Not implemented. Stick to the usual injection through uvmm.
-          bind_as_ipc();
-        _eoi->unmask(_irq_num);
-        break;
-      case State::Vcpu_disabled:
-        try_bind_as_vcpu();
-        _state = State::Vcpu_enabled;
-        _eoi->unmask(_irq_num);
-        break;
-      case State::Ipc_bound:
-      case State::Vcpu_enabled:
-        break;
-      }
-
-    return _state == State::Vcpu_enabled;
-  }
-
-  void disable() override
-  {
-    if (!bind_vcpu_supported())
-      return;
-
-    std::lock_guard lock(_mutex);
-
-    // Only unbind if the IRQ was bound to the vCPU. Otherwise we need to keep
-    // it permanently bound as IPC.
-    if (_state == State::Vcpu_enabled)
-      {
-        unbind_from_vcpu();
-        _state = State::Vcpu_disabled;
-      }
-  }
-
-private:
-  void set_eoi(L4::Cap eoi)
-  { _eoi = eoi; }
-
-  void unbind_irq_src_handler() const
-  { _ic->bind_irq_src_handler(_dt_irq, nullptr); }
-
-  void bind_as_ipc()
-  {
-    L4Re::chkcap(_registry->register_obj(this, _cap.get()),
-                 "Cannot register irq");
-    _state = State::Ipc_bound;
-  }
-
-  void unbind_from_ipc()
-  {
-    _registry->unregister_obj(this);
-  }
-
-#ifdef CONFIG_UVMM_IRQ_DIRECT_INJECT
-  static constexpr bool bind_vcpu_supported()
-  { return true; }
-
-  bool try_bind_as_vcpu()
-  {
-    // The Irq was disabled or moved while being active. We first have to wait
-    // for the EOI of the guest until it can be rebound...
-    if (_active)
-      return true;
-
-    // (Re-)Bind as vCPU IRQ.
-    int err;
-    do
-      {
-        err = l4_error(_cap->bind_vcpu(_registry->server(), _vcpu_irq_cfg));
-        if (err == -L4_EBUSY)
-          {
-            // The guest tried to move an vIRQ to a different vCPU while it was
-            // active. We have to detach and wait for the EOI of the guest to
-            // attach it then to the right vCPU.
-            unbind_from_vcpu();
-            if (_active)
-              break;
-
-            // The vIRQ was not active any more once we detached it. This might
-            // happen if the vIRQ is routed to a different vCPU than the one
-            // that reconfigures it. Try again...
-          }
-        else if (err != -L4_ENOSYS)
-          L4Re::chksys(err, "Irq_svr bind_vcpu failed");
-      }
-    while (err == -L4_EBUSY);
-
-    return err != -L4_ENOSYS;
-  }
-
-  void unbind_from_vcpu()
-  {
-    assert(_state == State::Vcpu_enabled);
-
-    if (_active)
-      return;
-
-    int err = L4Re::chksys(_cap->detach(), "Detach Irq failed");
-    _active = err == 2;
-  }
-#else
-  static constexpr bool bind_vcpu_supported()
-  { return false; }
-
-  bool try_bind_as_vcpu()
-  { return false; }
-
-  void unbind_from_vcpu()
-  {}
-#endif
-
-  cxx::Ref_ptr _ic;  ///< Virtual interrupt controller
-  unsigned _dt_irq = 0;       ///< Line number on virtual interrupt controller
-  State _state = State::Init;
-  bool _active = false;       ///< True if active on a vCPU
-  L4::Cap _eoi;  ///< L4 Interface for EOI
-
-protected:
-  unsigned _irq_num;          ///< Line number on L4 ICU
-
-private:
-  // The following members are not used in the hot paths...
-  Vcpu_obj_registry *_registry; ///< Registry of the vCPU the IRQ currently targets.
-  l4_umword_t _vcpu_irq_cfg = 0;
-  L4Re::Util::Unique_cap _cap;
-  std::mutex _mutex;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/main.cc b/src/l4/pkg/uvmm/server/src/main.cc
deleted file mode 100644
index 54813f55..00000000
--- a/src/l4/pkg/uvmm/server/src/main.cc
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-#include 
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "debug.h"
-#include "guest.h"
-#include "host_dt.h"
-#include "vm_ram.h"
-#include "vm.h"
-#include "monitor/monitor.h"
-
-static Vmm::Vm vm_instance;
-
-static Dbg info(Dbg::Core, Dbg::Info, "main");
-static Dbg warn(Dbg::Core, Dbg::Warn, "main");
-
-static std::terminate_handler old_terminate_handler;
-
-/**
- * Cleanup dependencies into the running system on exit.
- *
- * This function is called whenever uvmm exits unexpectedly. It is here, where
- * we can clean up all the dependencies into the running L4Re system.
- */
-static void uvmm_terminate_handler()
-{
-  // Tingling inhibitors would prevent proper system shutdown/reboot/suspend,
-  // so we must free them here, iff they're initialized already.
-  if (vm_instance.pm())
-    vm_instance.pm()->free_inhibitors();
-  // The upstream terminate handler can show information about the exception
-  // and do the cleanup.
-  old_terminate_handler();
-}
-
-/**
- * Verify the CPU setup from the device tree.
- *
- * The device tree may not have set up any CPU explicitly. Then create a
- * single CPU setup. If CPUs have been setup, then CPU0 must be among them.
- */
-static void
-verify_cpu0_setup()
-{
-  if (vm_instance.cpus()->vcpu_exists(0))
-    return;
-
-  // If there is no CPU0 there should be no other CPU.
-  for (auto cpu: *vm_instance.cpus().get())
-    if (cpu)
-      L4Re::chksys(-L4_EINVAL, "Invalid CPU configuration in device tree,"
-                               " missing CPU0");
-
-  // XXX The CPU device is not added to the device repository here. Is this
-  // necessary? The cpu_dev_array still holds a reference to it so it
-  // doesn't simply vanish here ...
-  vm_instance.cpus()->create_vcpu(nullptr);
-}
-
-/**
- * Set up the ram disk in memory and configure it in the device tree.
- *
- * \param ram_disk       Name of the dataspace containing the ram disk.
- *                       May be nullptr if no ram disk is configured.
- * \param dt             Device tree to add ram disk information to.
- * \param ram_free_list  Free list for memory in `ram`.
- * \param ram            Physical guest ram.
- */
-static void
-setup_ramdisk(char const *ram_disk, Vdev::Host_dt const &dt,
-              Vmm::Ram_free_list *ram_free_list, Vmm::Vm_ram *ram)
-{
-  if (!ram_disk)
-    return;
-
-  info.printf("Loading ram disk...\n");
-  Vmm::Guest_addr rd_start;
-  l4_size_t rd_size;
-  L4Re::chksys(ram_free_list->load_file_to_back(ram, ram_disk, &rd_start,
-                                                &rd_size),
-               "Copy ram disk into RAM.");
-
-  if (dt.valid() && rd_size > 0)
-    {
-      auto node = dt.get().path_offset("/chosen");
-      node.set_prop_address("linux,initrd-start", rd_start.get());
-      node.set_prop_address("linux,initrd-end",
-          rd_start.get() + rd_size);
-    }
-
-  info.printf("Loaded ramdisk image %s to %lx (size: %08zx)\n",
-      ram_disk, rd_start.get(), rd_size);
-}
-
-static void
-setup_kaslr_seed(Vdev::Host_dt const &dt)
-{
-  auto c = L4Re::Env::env()->get_cap("rng");
-  if (!c)
-    return;
-
-  union
-  {
-    l4_uint64_t r;
-    char c[sizeof(l4_uint64_t)];
-  } random;
-
-  L4::Ipc::Array msg(sizeof(random), random.c);
-  int ret = c->get_random(sizeof(random), &msg);
-  if (ret < static_cast(sizeof(random)))
-    L4Re::throw_error(ret < 0 ? ret : -L4_EAGAIN,
-                      "Getting random seed for KASLR initialisation.");
-
-
-  auto node = dt.get().path_offset("/chosen");
-  node.setprop_u64("kaslr-seed", random.r);
-}
-
-static char const *const options = "+k:d:r:c:b:vqD:f:im:";
-static struct option const loptions[] =
-{
-    { "kernel",                  required_argument, NULL, 'k' },
-    { "dtb",                     required_argument, NULL, 'd' },
-    { "ramdisk",                 required_argument, NULL, 'r' },
-    { "cmdline",                 required_argument, NULL, 'c' },
-    { "rambase",                 required_argument, NULL, 'b' },
-    { "debug",                   required_argument, NULL, 'D' },
-    { "verbose",                 no_argument,       NULL, 'v' },
-    { "quiet",                   no_argument,       NULL, 'q' },
-    { "wakeup-on-system-resume", no_argument,       NULL, 'W' },
-    { "fault-mode",              required_argument, NULL, 'f' },
-    { "dt-mod",                  required_argument, NULL, 'm' },
-    { 0, 0, 0, 0}
-};
-
-static bool str_to_fault_mode(char const *s, Vmm::Guest::Fault_mode *mode)
-{
-  static struct {
-    char const *name;
-    Vmm::Guest::Fault_mode mode;
-  } fault_options[] =
-  {
-    { "ignore", Vmm::Guest::Fault_mode::Ignore },
-    { "halt",   Vmm::Guest::Fault_mode::Halt },
-    { "inject", Vmm::Guest::Fault_mode::Inject },
-  };
-
-  for (auto &&i : fault_options)
-    {
-      if (strcmp(i.name, s) == 0)
-        {
-          *mode = i.mode;
-          return Vmm::Guest::fault_mode_supported(*mode);
-        }
-    }
-
-  return false;
-}
-
-int main(int argc, char *argv[])
-{
-  old_terminate_handler = std::set_terminate(&uvmm_terminate_handler);
-
-  unsigned long verbosity = Dbg::Warn;
-
-  Dbg::set_verbosity(verbosity);
-
-  Vdev::Host_dt dt;
-
-  char const *cmd_line     = nullptr;
-  char const *kernel_image = "rom/zImage";
-  char const *ram_disk     = nullptr;
-  l4_addr_t rambase = Vmm::Guest::Default_rambase;
-  bool use_wakeup_inhibitor = false;
-  Vmm::Guest::Fault_mode fault_mode = Vmm::Guest::Fault_mode::Ignore;
-  bool force_ram_identity_mapping = false;
-
-  int opt;
-  while ((opt = getopt_long(argc, argv, options, loptions, NULL)) != -1)
-    {
-      switch (opt)
-        {
-        case 0:
-          break;
-        case 'c': cmd_line     = optarg; break;
-        case 'k': kernel_image = optarg; break;
-        case 'd':
-          dt.add_source(optarg);
-          break;
-        case 'r': ram_disk     = optarg; break;
-        case 'b':
-          rambase = strtoul(optarg, nullptr, 0);
-          break;
-        case 'i':
-          force_ram_identity_mapping = true;
-          break;
-        case 'q':
-          // quiet actually means guest output only
-          verbosity = Dbg::Quiet;
-          Dbg::set_verbosity(verbosity);
-          break;
-        case 'v':
-          verbosity = (verbosity << 1) | 1;
-          Dbg::set_verbosity(verbosity);
-          break;
-        case 'D':
-          if (Dbg::set_verbosity(optarg) != L4_EOK)
-            warn.printf("Failed to set verbosity\n");
-          break;
-        case 'W':
-          use_wakeup_inhibitor = true;
-          break;
-        case 'f':
-          if (!str_to_fault_mode(optarg, &fault_mode))
-            {
-              Err().printf("invalid --fault-mode: %s\n", optarg);
-              return 1;
-            }
-          break;
-        case 'm':
-          dt.modify(optarg);
-          break;
-        default:
-          Err().printf("unknown command-line option\n");
-          return 1;
-        }
-    }
-
-  Vmm::Cpu_dev::alloc_main_vcpu();
-  vm_instance.create_default_devices();
-  vm_instance.ram()->as_mgr()->detect_sys_info(vm_instance.vbus().get(),
-                                               force_ram_identity_mapping);
-
-  auto *vmm = vm_instance.vmm();
-  auto *ram = vm_instance.ram().get();
-
-  vmm->set_fault_mode(fault_mode);
-
-  if (use_wakeup_inhibitor)
-    vm_instance.pm()->use_wakeup_inhibitor(true);
-
-  warn.printf("Hello out there.\n");
-
-  Monitor::enable_cmd_control(&vm_instance);
-
-  Vmm::Ram_free_list ram_free_list
-    = ram->setup_from_device_tree(dt, vmm->memmap(), Vmm::Guest_addr(rambase));
-
-  info.printf("Loading kernel...\n");
-  l4_addr_t entry = vmm->load_binary(ram, kernel_image, &ram_free_list);
-
-  dt.set_command_line(cmd_line);
-
-  setup_ramdisk(ram_disk, dt, &ram_free_list, ram);
-
-  if (dt.valid())
-    {
-      vm_instance.scan_device_tree(dt.get());
-      setup_kaslr_seed(dt);
-    }
-
-  verify_cpu0_setup();
-
-  // finally copy in the device tree
-  l4_addr_t dt_boot_addr = 0;
-  if (dt.valid())
-    {
-      dt_boot_addr = ram->move_in_device_tree(&ram_free_list, cxx::move(dt));
-      vmm->set_dt_addr(dt_boot_addr);
-    }
-
-  vmm->prepare_generic_platform(&vm_instance);
-  vmm->prepare_platform(&vm_instance);
-  vmm->prepare_binary_run(&vm_instance, entry, kernel_image, cmd_line,
-                          dt_boot_addr);
-
-  vmm->memmap()->dump(Dbg::Info);
-
-  info.printf("Populating guest physical address space\n");
-  vmm->map_eager();
-
-  vmm->run(vm_instance.cpus());
-
-  Err().printf("ERROR: we must never reach this....\n");
-  return 0;
-}
diff --git a/src/l4/pkg/uvmm/server/src/mem_access.h b/src/l4/pkg/uvmm/server/src/mem_access.h
deleted file mode 100644
index 622dcebe..00000000
--- a/src/l4/pkg/uvmm/server/src/mem_access.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2017, 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-namespace Vmm {
-
-/**
- * Describes a load/store instruction.
- */
-struct Mem_access
-{
-  enum Kind
-  {
-    Load,  /// load from memory
-    Store, /// store to memory
-    Other  /// unknown instruction
-  };
-
-  enum Width
-  {
-    Wd8 = 0,  // Byte access
-    Wd16 = 1, // Half-word access
-    Wd32 = 2, // Word access
-    Wd64 = 3, // Double word access
-  };
-
-  l4_uint64_t value;
-  Kind access;
-  char width;
-
-  static l4_uint64_t read_width(l4_addr_t addr, char width)
-  {
-    // only naturally aligned accesses are allowed
-    if (L4_UNLIKELY(addr & ((1UL << width) - 1)))
-      return 0;
-
-    switch (width) {
-      case Wd8:  return *reinterpret_cast(addr);
-      case Wd16: return *reinterpret_cast(addr);
-      case Wd32: return *reinterpret_cast(addr);
-      case Wd64: return *reinterpret_cast(addr);
-      default: break;
-    }
-
-    // other widths are unsupported
-    return 0;
-  }
-
-  static int write_width(l4_addr_t addr, l4_uint64_t value, char width)
-  {
-    // only naturally aligned accesses are allowed
-    if (L4_UNLIKELY(addr & ((1UL << width) - 1)))
-      return -L4_EINVAL;
-
-    switch (width)
-      {
-      case Wd8:  *reinterpret_cast(addr) = value;  break;
-      case Wd16: *reinterpret_cast(addr) = value; break;
-      case Wd32: *reinterpret_cast(addr) = value; break;
-      case Wd64: *reinterpret_cast(addr) = value; break;
-      default: return -L4_EINVAL;
-      }
-
-    return L4_EOK;
-  }
-
-  static int cache_clean_data_width(l4_addr_t addr, char width)
-  {
-    switch (width)
-      {
-      case Wd8:  l4_cache_clean_data(addr, addr + 1); break;
-      case Wd16: l4_cache_clean_data(addr, addr + 2); break;
-      case Wd32: l4_cache_clean_data(addr, addr + 4); break;
-      case Wd64: l4_cache_clean_data(addr, addr + 8); break;
-      default: return -L4_EINVAL;
-      }
-
-    return L4_EOK;
-  }
-
-  template
-  static STORAGE read(STORAGE v, unsigned offs, char width)
-  {
-    if ((1u << width) >= sizeof(STORAGE))
-      return v;
-
-    unsigned const szm = sizeof(STORAGE) - 1;
-    unsigned const sh = (offs & (szm << width) & szm) * 8;
-    STORAGE const m = ~((~static_cast(0)) << (8 << width));
-    return (v >> sh) & m;
-  }
-
-  template
-  static void write(STORAGE *s, VAL v, unsigned offs, char width)
-  {
-    if ((1u << width) >= sizeof(STORAGE))
-      {
-        *s = v;
-      }
-    else
-      {
-        unsigned const szm = sizeof(STORAGE) - 1;
-        unsigned const sh = (offs & (szm << width) & szm) * 8;
-        STORAGE const m = ~((~static_cast(0)) << (8 << width)) << sh;
-        *s = (*s & ~m) | (static_cast(v) & m);
-      }
-  }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/mem_types.h b/src/l4/pkg/uvmm/server/src/mem_types.h
deleted file mode 100644
index 6c0ae3bf..00000000
--- a/src/l4/pkg/uvmm/server/src/mem_types.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018-2019, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-namespace Vmm {
-
-/**
- * A guest-physical address.
- */
-class Guest_addr
-{
-public:
-  Guest_addr() : _addr(0) {}
-  explicit Guest_addr(l4_addr_t addr) : _addr(addr) {}
-
-  friend bool operator == (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr == rhs._addr; }
-
-  friend bool operator != (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr != rhs._addr; }
-
-  friend bool operator > (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr > rhs._addr; }
-
-  friend bool operator >= (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr >= rhs._addr; }
-
-  friend bool operator < (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr < rhs._addr; }
-
-  friend bool operator <= (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr <= rhs._addr; }
-
-  friend Guest_addr operator + (Guest_addr lhs, l4_size_t rhs) noexcept
-  { return Guest_addr(lhs._addr + rhs); }
-
-  friend Guest_addr operator + (l4_size_t lhs, Guest_addr rhs) noexcept
-  { return Guest_addr(lhs + rhs._addr); }
-
-  friend Guest_addr operator - (Guest_addr lhs, l4_size_t rhs) noexcept
-  { return Guest_addr(lhs._addr - rhs); }
-
-  friend Guest_addr operator - (l4_size_t lhs, Guest_addr rhs) noexcept
-  { return Guest_addr(lhs - rhs._addr); }
-
-  friend l4_size_t operator - (Guest_addr lhs, Guest_addr rhs) noexcept
-  { return lhs._addr - rhs._addr; }
-
-  l4_addr_t get() const noexcept
-  { return _addr; }
-
-  Guest_addr round_page() const noexcept
-  { return Guest_addr(l4_round_page(_addr)); }
-
-private:
-  l4_addr_t _addr;
-};
-
-/**
- * Type of region in a VM area map
- *
- * This type is used to keep track of regions in an vm area map. It is used to
- * check whether regions are compatible with each other when regions overlap and
- * when someone searches for a region of a specific type..
- */
-enum class Region_type : l4_uint8_t
-{
-  None,         ///< No type specified
-  Ram,          ///< Physical RAM
-  Vbus,         ///< Mmio resource specified on Vbus
-  Kernel,       ///< Mmio resources provided by the kernel
-  Virtual       ///< Mmio resource provided by a virtual device
-};
-
-/**
- * Additional flags for the region
- */
-enum Region_flags : l4_uint8_t
-{
-  None = 0x0,     ///< No flags specified
-  Moveable = 0x1, ///< The region may be moved in address space
-};
-
-template 
-struct Generic_region
-{
-  T start;
-  T end; // inclusive
-  Region_type type;
-  Region_flags flags;
-
-  Generic_region() = delete;
-  explicit Generic_region(T a)
-  : start(a), end(a), type(Region_type::None), flags(Region_flags::None) {}
-  Generic_region(T a, Region_type type, Region_flags flags = Region_flags::None)
-  : start(a), end(a), type(type), flags(flags) {}
-  Generic_region(T s, T e, Region_type type,
-                 Region_flags flags = Region_flags::None)
-  : start(s), end(e), type(type), flags(flags) {}
-
-  static Generic_region ss(T start, l4_size_t size, Region_type type,
-                           Region_flags flags = Region_flags::None)
-  { return Generic_region(start, start + size - 1, type, flags); }
-
-  Generic_region move(T s) const
-  { return Generic_region(s, s + static_cast(end - start),
-                          type, flags); }
-
-  bool operator < (Generic_region const &r) const { return end < r.start; }
-
-  bool contains(Generic_region const &r) const
-  {
-    // [ start [ r.start ... r.end ] end ]
-    return (start <= r.start) && (r.end <= end) &&
-      (type == r.type) && (flags == r.flags);
-  }
-};
-
-using Region = Generic_region;
-using Io_region = Generic_region;
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/mmio_device.cc b/src/l4/pkg/uvmm/server/src/mmio_device.cc
deleted file mode 100644
index 6cf25085..00000000
--- a/src/l4/pkg/uvmm/server/src/mmio_device.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2018, 2021-2024 Kernkonzept GmbH.
- * Author(s): Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "mmio_device.h"
-#include "batch_unmapper.h"
-#include "debug.h"
-#include "consts.h"
-
-void Vmm::Mmio_device::map_guest_range(L4::Cap vm_task,
-                                       Vmm::Guest_addr dest, l4_addr_t src,
-                                       l4_size_t size, unsigned attr)
-{
-  l4_addr_t dest_end = dest.get() + size - 1;
-  l4_addr_t offs = 0;
-
-  Dbg(Dbg::Mmio, Dbg::Info, "mmio")
-    .printf("\tMapping [%lx - %lx] -> [%lx - %lx]\n", src, src + size - 1,
-            dest.get(), dest_end);
-
-  while (offs < size)
-    {
-      auto doffs = dest.get() + offs;
-      char ps = Vmm::get_page_shift(doffs, dest.get(), dest_end, offs, src);
-      // Map explicitly cacheable into VM task. This lets the guest choose the
-      // effective memory attributes.
-      auto res = l4_error(vm_task->map(L4Re::This_task,
-                                       l4_fpage(src + offs, ps, attr),
-                                       l4_map_control(doffs,
-                                                      L4_FPAGE_CACHEABLE,
-                                                      L4_MAP_ITEM_MAP)));
-      if (res < 0)
-        {
-          Err().printf("Could not map (%lx, %d) to (%lx, %d)\n",
-                       src + offs, ps, doffs, ps);
-          L4Re::throw_error(-L4_ENOMEM, "Mapping guest range.");
-        }
-
-      offs += static_cast(1) << ps;
-    }
-}
-
-void Vmm::Mmio_device::unmap_guest_range(L4::Cap vm_task,
-                                         Vmm::Guest_addr dest, l4_size_t size)
-{
-  l4_addr_t dest_end = dest.get() + size - 1;
-  l4_addr_t offs = 0;
-
-  Dbg(Dbg::Mmio, Dbg::Info, "mmio")
-    .printf("\tUnmapping [%lx - %lx]\n", dest.get(), dest_end);
-
-  Vmm::Batch_unmapper b(vm_task, L4_FP_ALL_SPACES);
-  while (offs < size)
-    {
-      auto doffs = dest.get() + offs;
-      char ps = Vmm::get_page_shift(doffs, dest.get(), dest_end, offs);
-      b.unmap(l4_fpage(doffs, ps, L4_FPAGE_RWX));
-      offs += static_cast(1) << ps;
-    }
-}
diff --git a/src/l4/pkg/uvmm/server/src/mmio_device.h b/src/l4/pkg/uvmm/server/src/mmio_device.h
deleted file mode 100644
index e5826e8c..00000000
--- a/src/l4/pkg/uvmm/server/src/mmio_device.h
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "device.h"
-#include "vcpu_ptr.h"
-#include "mem_access.h"
-#include "mem_types.h"
-#include "consts.h"
-#include "ds_manager.h"
-
-namespace Vmm {
-
-/**
- * Interface for any device that processes access to special guest-physical
- * memory regions.
- */
-struct Mmio_device : public virtual Vdev::Dev_ref
-{
-  virtual ~Mmio_device() = 0;
-
-  bool mergable(cxx::Ref_ptr other,
-                Guest_addr start_other, Guest_addr start_this)
-  {
-    auto o = other.get();
-    if (typeid (*this) != typeid (*o))
-      return false;
-    return _mergable(other, start_other, start_this);
-  };
-
-  /**
-   * Map address range into guest.
-   *
-   * \param dest  Guest physical address the address range should be mapped to
-   * \param src   Local address of the range
-   * \param size  Size of range
-   * \param attr  Flexpage access rights used for mapping
-   *
-   * This function iterates over the specified local area and maps everything
-   * into the address space of the guest.
-   */
-  void map_guest_range(L4::Cap vm_task, Vmm::Guest_addr dest,
-                       l4_addr_t src, l4_size_t size, unsigned attr);
-
-  /**
-   * Purge mappings from guest memory.
-   *
-   * \param vm_task Capability to the guest memory.
-   * \param dest    Guest-physical address of the range
-   * \param size    Size of range
-   */
-  void unmap_guest_range(L4::Cap vm_task, Vmm::Guest_addr dest,
-                         l4_size_t size);
-
-  /**
-   * Map address range into the guest.
-   *
-   * \param start  Guest physical address the address range should be mapped to
-   * \param end    Guest physical address of the end of the range [start, end]
-   *
-   * This function iterates over the local area associated with the region and
-   * tries to map everything into the address space of the guest if possible.
-   */
-  virtual void map_eager(L4::Cap vm_task, Vmm::Guest_addr start,
-                         Vmm::Guest_addr end) = 0;
-
-  /**
-   * Page in memory for specified address.
-   *
-   * \param addr         An address to page in memory for
-   * \retval 0           Success
-   * \retval L4_ENOMEM   Address is not valid
-   * \retval L4_EACCESS  Address is not writable or executable
-   *
-   * \retval <0          IPC errors
-   */
-  long page_in(l4_addr_t addr, bool writable)
-  {
-    auto *e = L4Re::Env::env();
-    L4::Ipc::Snd_fpage rfp;
-
-    l4_msgtag_t msgtag = e->rm()
-      ->page_fault(((addr & L4_PAGEMASK) | (writable ? 2 : 0)), -3UL,
-                   L4::Ipc::Rcv_fpage::mem(0, L4_WHOLE_ADDRESS_SPACE, 0),
-                   rfp);
-    return l4_error(msgtag);
-  }
-
-  /**
-   * Callback on memory access.
-   *
-   * \param pfa      Guest-physical address where the access occurred.
-   * \param offset   Accessed address relative to the beginning of the
-   *                 device's memory region.
-   * \param vcpu     Virtual CPU from which the memory was accessed.
-   * \param vm_task  Capability to the guest memory.
-   * \param s        Guest-physical address of start of device memory region.
-   * \param e        Guest-physical address of end of device memory region.
-   *
-   * \retval < 0         if memory access was faulty, the error code.
-   * \retval Retry       if memory was mapped and access can be retried.
-   * \retval Jump_instr  if memory access could be handled.
-   * \
-   */
-  virtual int access(l4_addr_t pfa, l4_addr_t offset, Vcpu_ptr vcpu,
-                     L4::Cap vm_task, l4_addr_t s, l4_addr_t e) = 0;
-
-  virtual char const *dev_name() const = 0;
-
-  virtual char const *dev_info(char *buf, size_t size) const
-  {
-    if (size > 0)
-      {
-        strncpy(buf, dev_name(), size);
-        buf[size - 1] = '\0';
-      }
-    return buf;
-  };
-
-private:
-  virtual bool _mergable(cxx::Ref_ptr /* other */,
-                         Guest_addr /* start_other */,
-                         Guest_addr /* start_this */)
-  { return false; }
-};
-
-/**
- * Mixin for devices that trap read and write access to physical guest memory.
- *
- * The base class DEV needs to provide two functions read() and write() that
- * implement the actual functionality behind the memory access. Those
- * functions must be defined as follows:
- *
- *     l4_umword_t read(unsigned reg, char size, unsigned cpu_id);
- *
- *     void write(unsigned reg, char size, l4_umword_t value, unsigned cpu_id);
- *
- * `reg` is the address offset into the devices memory region. `size`
- * describes the width of the access (see Vmm::Mem_access::Width) and
- * `cpu_id` the accessing CPU (currently unused).
- */
-template
-struct Mmio_device_t : Mmio_device
-{
-  int access(l4_addr_t pfa, l4_addr_t offset, Vcpu_ptr vcpu,
-             L4::Cap, l4_addr_t, l4_addr_t) override
-  {
-    auto insn = vcpu.decode_mmio();
-
-    if (insn.access == Vmm::Mem_access::Other)
-      {
-        Dbg(Dbg::Mmio, Dbg::Warn, "mmio")
-          .printf("MMIO access @ 0x%lx: unknown instruction. Ignored.\n",
-                  pfa);
-        return -L4_ENXIO;
-      }
-
-    Dbg(Dbg::Mmio, Dbg::Trace, "mmio")
-      .printf("MMIO access @ 0x%lx (0x%lx) %s, width: %u\n",
-              pfa, offset,
-              insn.access == Vmm::Mem_access::Load ? "LOAD" : "STORE",
-              static_cast(insn.width));
-
-    if (insn.access == Vmm::Mem_access::Store)
-      dev()->write(offset, insn.width, insn.value, vcpu.get_vcpu_id());
-    else
-      {
-        insn.value = dev()->read(offset, insn.width, vcpu.get_vcpu_id());
-        vcpu.writeback_mmio(insn);
-      }
-
-    return Jump_instr;
-  }
-
-  void map_eager(L4::Cap, Vmm::Guest_addr, Vmm::Guest_addr) override
-  {} // nothing to map
-
-private:
-  DEV *dev()
-  { return static_cast(this); }
-};
-
-/**
- * Mixin for virtual memory-mapped device that allows direct read access to
- * its memory region.
- *
- * \tparam BASE  Type of the device the mixin is used for.
- *
- * The device manages a dataspace of its memory region that is directly
- * mapped into the guest memory for reading. The device needs to take care
- * to keep the region up-to-date. Write access to the region still traps
- * into the VMM and needs to be handled programmatically.
- */
-template
-struct Ro_ds_mapper_t : Mmio_device
-{
-  int access(l4_addr_t pfa, l4_addr_t offset, Vcpu_ptr vcpu,
-             L4::Cap vm_task, l4_addr_t min, l4_addr_t max) override
-  {
-    auto insn = vcpu.decode_mmio();
-
-    if (insn.access == Vmm::Mem_access::Other)
-      {
-        Dbg(Dbg::Mmio, Dbg::Warn, "mmio")
-          .printf("MMIO access @ 0x%lx: unknown instruction. Ignored.\n",
-                  pfa);
-        return -L4_ENXIO;
-      }
-
-    Dbg(Dbg::Mmio, Dbg::Trace, "mmio")
-      .printf("MMIO access @ 0x%lx (0x%lx) %s, width: %u\n",
-              pfa, offset,
-              insn.access == Vmm::Mem_access::Load ? "LOAD" : "STORE",
-              static_cast(insn.width));
-
-    if (insn.access == Vmm::Mem_access::Store)
-      dev()->write(offset, insn.width, insn.value, vcpu.get_vcpu_id());
-    else
-      {
-        if (offset < dev()->mapped_mmio_size())
-          map_mmio(pfa, offset, vm_task, min, max);
-
-        insn.value = dev()->read(offset, insn.width, vcpu.get_vcpu_id());
-        vcpu.writeback_mmio(insn);
-      }
-
-    return Jump_instr;
-  }
-
-  void map_eager(L4::Cap vm_task, Vmm::Guest_addr start,
-                 Vmm::Guest_addr end) override
-  {
-#ifndef CONFIG_MMU
-    // Cannot map if guest address is different. Transparently fall back to
-    // emulation.
-    if (start.get() != dev()->local_addr())
-      return;
-#endif
-
-#ifndef MAP_OTHER
-    l4_size_t size = end - start + 1;
-    if (size > dev()->mapped_mmio_size())
-      size = dev()->mapped_mmio_size();
-    map_guest_range(vm_task, start, dev()->local_addr(), size, L4_FPAGE_RX);
-#else
-    static_cast(vm_task);
-    static_cast(start);
-    static_cast(end);
-#endif
-  }
-
-  /**
-   * Emulate a read access by accessing the dataspace backing the
-   * MMIO region.
-   * \param offset   The offset (in bytes) inside the MMIO region
-   *                 (and inside the dataspace as the dataspace
-   *                 starts at offset 0 in the MMIO region).
-   * \param width   The width (in log2 bytes) of the memory access.
-   * \param cpuid   The CPU that did the access (has to be ignored).
-   *
-   * \pre `offset + (1UL << width) <= mapped_mmio_size()`
-   * \pre `offset <= 2GB`
-   */
-  l4_uint64_t read(unsigned offset, char width, unsigned /* cpuid */)
-  {
-    // cpuid must be ignored by this implementation because
-    // we have no CPU-local mappings of our dataspace.
-    if (0)
-      printf("MMIO/RO/DS read: offset=%x (%u) [0x%lx] = %x\n", offset,
-             static_cast(width), local_addr() + offset,
-             *(reinterpret_cast(local_addr() + offset)));
-
-    // limit MMIO regions to 2GB
-    assert (offset <= 0x80000000);
-    assert (offset + (1UL << width) <= dev()->mapped_mmio_size());
-
-    return Mem_access::read_width(local_addr() + offset, width);
-  }
-
-  void map_mmio(l4_addr_t pfa, l4_addr_t offset, L4::Cap vm_task,
-                l4_addr_t min, l4_addr_t max)
-  {
-#ifdef MAP_OTHER
-    auto res = dev()->mmio_ds()->map(offset, L4Re::Dataspace::F::RX, pfa,
-                                     min, max, vm_task);
-#else
-    auto local_start = local_addr();
-
-#ifndef CONFIG_MMU
-    // Cannot map if guest address is different. Transparently fall back to
-    // emulation.
-    if (local_start + offset != pfa)
-      return;
-#endif
-
-    // Make sure that the page is currently mapped.
-    auto res = page_in(local_start + offset, false);
-
-    if (res >= 0)
-      {
-        // We assume that the region manager provided the largest possible
-        // page size and try to map the largest possible page to the
-        // client.
-        unsigned char ps =
-          Vmm::get_page_shift(pfa, min, max, offset, local_start,
-                              local_start + dev()->mapped_mmio_size() - 1);
-        l4_addr_t base = l4_trunc_size(local_start + offset, ps);
-
-        // Map explicitly cacheable into VM task. This lets the guest choose
-        // the effective memory attributes.
-        res = l4_error(vm_task->map(L4Re::This_task,
-                                    l4_fpage(base, ps, L4_FPAGE_RX),
-                                    l4_map_control(l4_trunc_size(pfa, ps),
-                                                   L4_FPAGE_CACHEABLE,
-                                                   L4_MAP_ITEM_MAP)));
-      }
-#endif
-
-    if (res < 0)
-      Err().printf("Could not map to mmio address %lx. Ignored.\n", pfa);
-  }
-
-private:
-  BASE *dev()
-  { return static_cast(this); }
-
-  BASE const *dev() const
-  { return static_cast(this); }
-
-  l4_addr_t local_addr() const
-  { return reinterpret_cast(dev()->mmio_local_addr()); }
-};
-
-/**
- * Mixin for virtual memory-mapped device that allows direct read access to
- * its memory region.
- *
- * \tparam BASE  Type of the device the mixin is used for.
- * \tparam T     Data type for the device memory region.
- *
- * The device manages a dataspace of its memory region that is directly
- * mapped into the guest memory for reading. The device needs to take care
- * to keep the region up-to-date. Write access to the region still traps
- * into the VMM and needs to be handled programmatically.
- */
-template
-struct Read_mapped_mmio_device_t : Ro_ds_mapper_t
-{
-  /**
-   * Construct a partially mapped MMIO region.
-   *
-   * \param size      Size of the region that is mapped read-only
-   *                  to the guest.
-   * \param rm_flags  Additional properties to set for RM.
-   *                  Default is that the dataspace is mapped uncached
-   *                  into VMM and guest dataspace because operating
-   *                  systems normally expect device memory to be uncached.
-   *
-   * Allocates a new dataspace of the given size and makes it available
-   * for the VMM for reading/writing.
-   *
-   * \note The device may cover an area that is larger than the area covered
-   *       by the dataspace mapped into the guest. Any read access outside
-   *       the area then needs to be emulated as in the standard MMIO device.
-   */
-  explicit Read_mapped_mmio_device_t(char const *dev_name,
-                                     l4_size_t size,
-                                     L4Re::Rm::Flags rm_flags = L4Re::Rm::F::Cache_uncached)
-  {
-    auto *e = L4Re::Env::env();
-
-    L4Re::Util::Ref_cap::Cap ds
-      = L4Re::chkcap(L4Re::Util::make_ref_cap(),
-                     "Allocate dataspace capability for read-mapped MMIO dev.");
-
-    L4Re::chksys(e->mem_alloc()->alloc(size, ds.get()),
-                 "Allocate memory for read-mapped MMIO device.");
-    _mgr = cxx::make_unique(dev_name, ds, 0, size,
-                                        rm_flags.region_flags() |
-                                          L4Re::Rm::F::RW);
-    _mgr->local_addr();
-  }
-
-  l4_size_t mapped_mmio_size() const
-  { return _mgr->size(); }
-
-  L4::Cap mmio_ds() const
-  { return _mgr->dataspace().get(); }
-
-  T *mmio_local_addr() const
-  { return _mgr->local_addr(); }
-
-private:
-  char const *dev_name() const override { return _mgr->dev_name(); }
-
-  cxx::unique_ptr _mgr;
-};
-
-inline Mmio_device::~Mmio_device() = default;
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/mmio_space_handler.h b/src/l4/pkg/uvmm/server/src/mmio_space_handler.h
deleted file mode 100644
index d49ebe10..00000000
--- a/src/l4/pkg/uvmm/server/src/mmio_space_handler.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2017, 2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "mmio_device.h"
-
-namespace Vdev {
-
-class Mmio_space_handler
-: public Vmm::Mmio_device_t
-{
-public:
-  Mmio_space_handler(L4::Cap svr, long /* local_start */,
-                     long /* size */, long offset = 0)
-  : _server(svr), _offset(offset)
-  {}
-
-  l4_uint64_t read(unsigned addr, char width, unsigned)
-  {
-    l4_uint64_t value;
-
-    if (_server->mmio_read(addr + _offset, width, &value) == L4_EOK)
-      return value;
-
-    return 0;
-  }
-
-  void write(unsigned addr, char width, l4_uint64_t value, unsigned)
-  { _server->mmio_write(addr + _offset, width, value); }
-
-  char const *dev_name() const override { return "Mmio_space_handler"; }
-
-private:
-  L4::Cap _server;
-  long _offset;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/cpu_dev_array_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/cpu_dev_array_cmd_handler.h
deleted file mode 100644
index 72256108..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/cpu_dev_array_cmd_handler.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "cpu_dev.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Cpu_dev_array_cmd_handler {};
-
-template
-class Cpu_dev_array_cmd_handler : public Cmd
-{
-public:
-  Cpu_dev_array_cmd_handler()
-  { register_toplevel("cpu"); }
-
-  char const *help() const override
-  { return "CPU state"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'cpu list': list available CPUs\n"
-               "* 'cpu  ': execute  for CPU \n"
-               "* 'cpu all ': execute  for all CPUs\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  {
-    switch (compl_req->count() + compl_req->trailing_space())
-      {
-      case 0:
-      case 1:
-        {
-          compl_req->complete(f, "list");
-
-          for (unsigned cpu = 0; cpu < max_cpus(); ++cpu)
-            {
-              if (!cpu_valid(cpu))
-                continue;
-
-              std::string cpu_s(std::to_string(cpu));
-              compl_req->complete(f, cpu_s.c_str());
-            }
-        }
-        break;
-      default:
-        {
-          auto cpu_arg = compl_req->pop();
-          if (!cpu_arg.check())
-            return;
-
-          unsigned cpu = cpu_arg.get();
-          if (!cpu_valid(cpu))
-            return;
-
-          get_cpu(cpu)->complete(f, compl_req);
-        }
-      }
-  }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "list")
-      list_cpus(f);
-    else if (args->peek() == "all")
-      {
-        args->pop();
-
-        unsigned i = 0;
-        while (cpu_valid(i))
-          {
-            fprintf(f, "vCPU %u\n", i);
-            get_cpu(i)->exec(f, args);
-            fprintf(f, "\n");
-            ++i;
-          }
-      }
-    else
-      exec_subcmd(f, args);
-  }
-
-private:
-  bool cpu_valid(unsigned i) const
-  { return i < max_cpus() && get_cpu(i); }
-
-  void list_cpus(FILE *f) const
-  {
-    fprintf(f, "Available CPUs:\n");
-    for (unsigned i = 0; i < max_cpus(); ++i)
-      {
-        if (cpu_valid(i))
-          fprintf(f, "CPU %u\n", i);
-      }
-  }
-
-  void exec_subcmd(FILE *f, Arglist *args)
-  {
-    unsigned cpu = args->pop("Failed to parse VCPU index");
-
-    if (!cpu_valid(cpu))
-      argument_error("Invalid CPU");
-
-    get_cpu(cpu)->exec(f, args);
-  }
-
-  Vmm::Cpu_dev *get_cpu(unsigned i)
-  { return static_cast(this)->_cpus[i].get(); }
-
-  Vmm::Cpu_dev const *get_cpu(unsigned i) const
-  { return static_cast(this)->_cpus[i].get(); }
-
-  unsigned max_cpus() const
-  { return static_cast(this)->_cpus.size(); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/dbg_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/dbg_cmd_handler.h
deleted file mode 100644
index 2cf1e7cf..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/dbg_cmd_handler.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-#include 
-
-#include "monitor/mem_dump.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Dbg_cmd_handler {};
-
-template
-class Dbg_cmd_handler : public Cmd
-{
-public:
-  Dbg_cmd_handler()
-  { register_toplevel("dbg"); }
-
-  char const *help() const override
-  { return "Guest debugger interface"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'dbg r   [ [(b|w|d|q)]]': dump guest memory\n"
-               "where: *  = VCPU index, this parameter must be specified\n"
-               "         if and only if there are multiple VCPUs\n"
-               "       *  = number of entries to be dumped\n"
-               "       * b = byte, w = word (16 bits), d = double word,\n"
-               "         q = quad word\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, "r"); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    auto subcmd = args->pop();
-
-    unsigned vcpu_idx = 0;
-    if (dbg()->vcpu_smp_active())
-      vcpu_idx = args->pop("Failed to parse VCPU index");
-
-    if (!dbg()->vcpu_valid(vcpu_idx))
-      argument_error("Invalid VCPU index");
-
-    auto vcpu = dbg()->vcpu_ptr(vcpu_idx);
-
-    if (subcmd == "r")
-      {
-        Mem_dumper mem_dump(args);
-
-        try
-          {
-            dbg()->dump_memory(f, &mem_dump, vcpu);
-          }
-        catch (L4::Runtime_error &e)
-          {
-            fprintf(f, "Page table walk failed: %s",
-                    e.extra_str() ? e.extra_str() : "");
-          }
-      }
-    else
-      argument_error("Invalid subcommand");
-  }
-
-  T *dbg()
-  { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/dbg_enable_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/dbg_enable_cmd_handler.h
deleted file mode 100644
index 0d609da0..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/dbg_enable_cmd_handler.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "debugger/guest_debugger.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Vmm {
-  class Vm;
-}
-
-namespace Monitor {
-
-template
-class Dbg_enable_cmd_handler
-{
-public:
-  Dbg_enable_cmd_handler(Vmm::Vm *)
-  {}
-};
-
-template<>
-class Dbg_enable_cmd_handler : public Cmd
-{
-public:
-  Dbg_enable_cmd_handler(Vmm::Vm *vm)
-  : _vm(vm)
-  { register_toplevel("dbg"); }
-
-  char const *help() const override
-  { return "Enable guest debugger"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'dbg on': enable guest debugger interface\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, "on"); }
-
-  void exec(FILE *, Arglist *args) override
-  {
-    if (*args == "on")
-      {
-        unregister_toplevel();
-
-        _dbg.reset(new Guest_debugger(_vm));
-      }
-    else
-      argument_error("Invalid subcommand");
-  }
-
-private:
-  Vmm::Vm *_vm;
-  std::unique_ptr _dbg;
-};
-
-} // namespace Monitor
diff --git a/src/l4/pkg/uvmm/server/src/monitor/dt_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/dt_cmd_handler.h
deleted file mode 100644
index 3005b0c2..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/dt_cmd_handler.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-extern "C" {
-#include 
-}
-
-#include "device_tree.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Dtb {
-
-class Property
-{
-public:
-  enum Value_type
-  {
-    Prop_novalue,
-    Prop_stringlist,
-    Prop_string,
-    Prop_uint8_array,
-    Prop_uint32_array
-  };
-
-  Property(Dtb::Fdt *fdt, int node, struct fdt_property const *prop)
-  : _fdt(fdt),
-    _node(node),
-    _prop(prop)
-  {}
-
-  template
-  static std::vector get_all(T const &node)
-  {
-    std::vector properties;
-
-    int offset;
-    fdt_for_each_property_offset(offset, node._fdt->dt(), node._node)
-      {
-        properties.emplace_back(
-          node._fdt, node._node,
-          fdt_get_property_by_offset(node._fdt->dt(), offset, nullptr));
-      }
-
-    return properties;
-  }
-
-  char const *get_name() const
-  { return fdt_get_string(_fdt->dt(), fdt32_ld(&_prop->nameoff), nullptr); }
-
-  Value_type get_value_type() const
-  {
-    // unfortunately we have to make a guess here as this information is not
-    // encoded in the device tree itself
-
-    l4_uint32_t len = length();
-
-    if (len == 0)
-      return Prop_novalue;
-
-    // the value of the 'compatible' property is always a list of strings
-    if (is_compatible_property())
-      return Prop_stringlist;
-
-    // otherwise, if the property value is zero terminated and otherwise
-    // contains no zero characters, it is most likely a string
-    bool is_string = true;
-
-    if (data()[len - 1] != '\0')
-      is_string = false;
-    else
-      is_string = !memchr(data(), 0, len - 1);
-
-    if (is_string)
-      return Prop_string;
-
-    // any non-string property value is interpreted as a sequence of bytes or
-    // 32bit unsigned integers, depending on whether its length is divisible by
-    // four, there seems to be no more reliable way of deciding this
-    return len % 4 == 0 ? Prop_uint32_array : Prop_uint8_array;
-  }
-
-  std::vector get_stringlist() const
-  {
-    std::vector values;
-
-    char const *name = get_name();
-    for (int i = 0; i < fdt_stringlist_count(_fdt->dt(), _node, name); ++i)
-      {
-        values.push_back(
-          fdt_stringlist_get(_fdt->dt(), _node, name, i, nullptr));
-      }
-
-    return values;
-  }
-
-  char const *get_string() const
-  { return data(); }
-
-  template
-  std::vector get_array() const
-  {
-    std::vector values;
-
-    T const *arr = reinterpret_cast(data());
-
-    for (auto i = 0u; i < length() / sizeof(T); ++i)
-      values.push_back(arr[i]);
-
-    return values;
-  }
-
-private:
-  bool is_compatible_property() const
-  { return strcmp(get_name(), "compatible") == 0; }
-
-  char const *data() const
-  { return _prop->data; }
-
-  l4_uint32_t length() const
-  { return fdt32_ld(&_prop->len); }
-
-  Dtb::Fdt *_fdt;
-  int _node;
-  struct fdt_property const *_prop;
-};
-
-} // namespace Dtb
-
-namespace Monitor {
-
-template
-class Dt_cmd_handler {};
-
-template
-class Dt_cmd_handler : public Cmd
-{
-public:
-  Dt_cmd_handler()
-  { register_toplevel("dt"); }
-
-  char const *help() const override
-  { return "Device tree source"; }
-
-  void exec(FILE *f, Arglist *) override
-  { decompile(f); }
-
-private:
-  void decompile(FILE *f) const
-  {
-    auto *dt = host_dt();
-
-    if (!dt->valid())
-      {
-        fprintf(f, "No device tree loaded\n");
-        return;
-      }
-
-    // print header
-    fprintf(f, "/dts-v1/;\n\n");
-
-    // prepare node stack
-    auto root(dt->get().first_node());
-
-    std::stack nodes;
-    nodes.push(root);
-
-    // indent/dedent helper methods
-    int current_depth = 0;
-    int last_depth = -1;
-
-    auto indent = [&](int depth)
-    {
-      fprintf(f, "%*s", depth * 4, "");
-    };
-
-    auto close = [&](int depth)
-    {
-      current_depth = depth;
-      if (current_depth <= last_depth)
-        {
-          for (int depth = last_depth; depth >= current_depth; --depth)
-            {
-              indent(depth);
-              fprintf(f, "};\n");
-            }
-        }
-
-      if (depth > 0)
-        fputc('\n', f);
-
-      last_depth = current_depth;
-    };
-
-    // print device tree
-    while (!nodes.empty())
-      {
-        auto node(nodes.top());
-        nodes.pop();
-
-        if (!node.is_valid())
-          continue;
-
-        // print closing braces after returning from a more deeply nested level
-        close(node.get_depth());
-
-        // print node name
-        indent(current_depth);
-        fprintf(f, "%s {\n", node.get_name());
-
-        // print node properties
-        auto properties(Dtb::Property::get_all(node));
-        std::sort(properties.begin(),
-                  properties.end(),
-                  sort_named);
-
-        for (auto const &prop : properties)
-          {
-            // property name
-            indent(current_depth + 1);
-            fprintf(f, "%s", prop.get_name());
-
-            // property value(s)
-            switch (prop.get_value_type())
-              {
-              case Dtb::Property::Prop_novalue:
-                fprintf(f, ";\n");
-                break;
-              case Dtb::Property::Prop_stringlist:
-                {
-                  auto values(prop.get_stringlist());
-
-                  fprintf(f, " = \"%s\"", values[0]);
-                  for (auto i = 1u; i < values.size(); ++i)
-                    fprintf(f, ", \"%s\"", values[i]);
-
-                  fprintf(f, ";\n");
-                }
-                break;
-              case Dtb::Property::Prop_string:
-                fprintf(f, " = \"%s\";\n", prop.get_string());
-                break;
-              case Dtb::Property::Prop_uint8_array:
-                {
-                  auto values(prop.template get_array());
-
-                  fprintf(f, " = [");
-
-                  fprintf(f, "0x%0x", values[0]);
-                  for (auto i = 1u; i < values.size(); ++i)
-                    fprintf(f, " 0x%0x", values[i]);
-
-                  fprintf(f, "];\n");
-                }
-                break;
-              case Dtb::Property::Prop_uint32_array:
-                {
-                  auto values(prop.template get_array());
-
-                  fprintf(f, " = <");
-
-                  fprintf(f, "0x%0x", fdt32_to_cpu(values[0]));
-                  for (auto i = 1u; i < values.size(); ++i)
-                    fprintf(f, " 0x%0x", fdt32_to_cpu(values[i]));
-
-                  fprintf(f, ">;\n");
-                }
-                break;
-              }
-          }
-
-        // add nodes children to stack in alphabetical order
-        if (node.has_children())
-          {
-            std::vector children;
-
-            auto child(node.first_child_node());
-            while (child.is_valid())
-              {
-                children.push_back(child);
-                child = child.sibling_node();
-              }
-
-            std::sort(children.begin(),
-                      children.end(),
-                      sort_named);
-
-            for (auto it = children.rbegin(); it != children.rend(); ++it)
-              nodes.push(*it);
-          }
-      }
-
-    close(0);
-  }
-
-  template
-  static int sort_named(U const &a, U const &b)
-  { return strcmp(a.get_name(), b.get_name()) < 0; }
-
-  T const *host_dt() const
-  { return static_cast(this); }
-};
-
-} // namespace Monitor
diff --git a/src/l4/pkg/uvmm/server/src/monitor/mem_dump.h b/src/l4/pkg/uvmm/server/src/monitor/mem_dump.h
deleted file mode 100644
index 3c4c34db..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/mem_dump.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-#include 
-
-#include "monitor_args.h"
-
-namespace Monitor {
-
-/**
- * Memory dumping helper class.
- */
-class Mem_dumper
-{
-  // dumping blocks larger than this constant will result in an error
-  enum : l4_size_t { Max_displayable_entries = 1024 };
-
-public:
-  /**
-   * Initialize memory dumper from parameter string.
-   *
-   * \param args  Must be of the form ` [ []]`
-   *              where: * `` is the starting address of the memory block.
-   *                     * `` is the number of entries to be dumped.
-   *                     * `` is either of b (byte), w (word, 16 bits),
-   *                       d (double word) or q (quad word).
-   *              and `` and `` default to 1 and d respectively.
-   *
-   * \throws L4::Runtime_error  On malformed parameter string.
-   */
-  Mem_dumper(Arglist *args)
-  {
-    _addr = args->pop("Failed to parse address");
-
-    _num_entries = args->pop(1, "Failed to parse number of entries");
-
-    if (!args->empty())
-      {
-        auto byte_width = args->pop("Missing byte width specifier");
-
-        if (byte_width == "b")
-          _bytes_per_entry = 1;
-        else if (byte_width == "w")
-          _bytes_per_entry = 2;
-        else if (byte_width == "d")
-          _bytes_per_entry = 4;
-        else if (byte_width == "q")
-          _bytes_per_entry = 8;
-        else
-          argument_error("Invalid byte width specifier");
-      }
-    else
-      // note that we default to the host word size here and not that of the
-      // guest (which may be different, e.g. on ARM, but determining it is
-      // not trivial)
-      _bytes_per_entry = sizeof(l4_addr_t);
-
-    _addr = align_addr(_addr, _bytes_per_entry);
-
-    // ensure that addr + _num_entries * _bytes_per_entry is not larger than the
-    // largest representable address (by decreasing _num_entries if necessary).
-    l4_size_t max_entries =
-      (std::numeric_limits::max() - _addr) / _bytes_per_entry;
-
-    _num_entries = cxx::min(_num_entries, max_entries);
-
-    // limit the number of displayed entries to a fixed maximum
-    _num_entries = cxx::min(_num_entries,
-                            static_cast(Max_displayable_entries));
-
-    if (_num_entries == 0)
-      argument_error("Nothing to dump");
-  }
-
-  /**
-   * Memory block address specified in parameter string.
-   *
-   * \return  Starting address of memory block to be dumped.
-   */
-  l4_addr_t addr_start() const
-  { return _addr; }
-
-  /**
-   * End of memory block to be dumped.
-   *
-   * \return  Address of first byte after memory block to be dumped.
-   */
-  l4_addr_t addr_end() const
-  { return _addr + _num_entries * _bytes_per_entry; }
-
-  /**
-   * Size of memory block to be dumped.
-   *
-   * \return  Size (in bytes) of memory block to be dumped.
-   */
-  l4_addr_t block_size() const
-  { return _num_entries * _bytes_per_entry; }
-
-  /**
-   * Dump memory block.
-   *
-   * \param f           Stream to which to write output.
-   * \param addr_hvirt  Value return by `addr_start()` converted to a host
-   *                    virtual address (conversion is left to the caller).
-   * \param max_size    Upper limit on the size of the memory block to be
-   *                    dumped (if this is not `0`, the actual size is
-   *                    `max(max_size,  * ||)`).
-   *
-   */
-  void dump(FILE *f, l4_addr_t addr_hvirt, l4_size_t max_size = 0) const
-  {
-    l4_addr_t num_entries;
-    if (max_size == 0 || max_size >= _num_entries * _bytes_per_entry)
-      num_entries = _num_entries;
-    else
-      num_entries = max_size / _bytes_per_entry;
-
-    for (l4_addr_t offs = 0; offs < num_entries; ++offs)
-      {
-        fprintf(f, "0x%016lx: ", _addr + offs * _bytes_per_entry);
-
-        switch (_bytes_per_entry)
-          {
-          case 1:
-            fprintf(f, "0x%02x", get_entry(addr_hvirt, offs));
-            break;
-          case 2:
-            fprintf(f, "0x%04x", get_entry(addr_hvirt, offs));
-            break;
-          case 4:
-            fprintf(f, "0x%08x", get_entry(addr_hvirt, offs));
-            break;
-          case 8:
-            fprintf(f, "0x%016llx", get_entry(addr_hvirt, offs));
-            break;
-          }
-
-        fputc('\n', f);
-      }
-  }
-
-private:
-  static l4_addr_t align_addr(l4_addr_t addr, unsigned bytes_per_entry)
-  { return addr & ~(static_cast(bytes_per_entry) - 1); }
-
-  template
-  static T get_entry(l4_addr_t hvirt, l4_addr_t offs)
-  { return *reinterpret_cast(hvirt + offs * sizeof(T)); }
-
-  l4_addr_t _addr;
-  l4_size_t _num_entries;
-  unsigned _bytes_per_entry;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/monitor.cc b/src/l4/pkg/uvmm/server/src/monitor/monitor.cc
deleted file mode 100644
index 824a7c75..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/monitor.cc
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * Copyright (C) 2019, 2022-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "uvmm_cli.h"
-#include "vm.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-#include "monitor/dbg_enable_cmd_handler.h"
-
-namespace {
-
-class Cmd_control : public L4::Irqep_t
-{
-  enum { Vcon_buf_sz = 100 };
-
-  struct Named_cmd_handler
-  {
-    Named_cmd_handler(Monitor::Cmd *cmd, char const *name)
-    : cmd(cmd),
-      name(name)
-    {}
-
-    Monitor::Cmd *cmd;
-    char const *name;
-  };
-
-public:
-  class Help : public Monitor::Cmd
-  {
-  public:
-    Help()
-    { register_toplevel("help"); }
-
-    char const *help() const override
-    { return "Print help"; }
-
-    void usage(FILE *f) const override
-    {
-      fprintf(f, "%s\n"
-                 "* 'help': list descriptions of all available commands\n"
-                 "* 'help ': show usage message for \n",
-              help());
-    }
-
-    void complete(FILE *f, Monitor::Completion_request *compl_req) const override
-    {
-      for (auto const &handler : Cmd_control::get()->_cmd_handlers)
-        compl_req->complete(f, handler.name);
-    }
-
-    void exec(FILE *f, Monitor::Arglist *args) override
-    {
-      if (args->empty())
-        {
-          for (auto const &handler : Cmd_control::get()->_cmd_handlers)
-            fprintf(f, "%-12s  %s\n", handler.name, handler.cmd->help());
-        }
-      else
-        {
-          auto cmd_arg = args->pop();
-
-          char const *cmd = cmd_arg.get();
-          size_t cmd_len = strlen(cmd);
-
-          auto *handler = Cmd_control::get()->find_cmd_handler(cmd, cmd_len);
-
-          if (!handler)
-            fprintf(f, "Unknown command %.*s\n", static_cast(cmd_len), cmd);
-          else
-            handler->usage(f);
-        }
-    }
-  };
-
-  class Verbose : public Monitor::Cmd
-  {
-  public:
-    Verbose()
-    { register_toplevel("verbose"); }
-
-    char const *help() const override
-    { return "Display/Adjust verbosity"; }
-
-    void usage(FILE *f) const override
-    {
-      fprintf(f, "%s\n"
-                 "* 'verbose show ': display level for some component\n"
-                 "* 'verbose set  ': set level for some component\n"
-                 "where:  = (quiet|warn|info|trace)\n"
-                 "and:    = (all|uest|core|cpu|mmio|irq|dev)\n",
-              help());
-    }
-
-    void complete(FILE *f, Monitor::Completion_request *compl_req) const override
-    {
-      switch (compl_req->count() + compl_req->trailing_space())
-        {
-        case 0:
-        case 1:
-          compl_req->complete(f, {"show", "set"});
-          break;
-        case 2:
-          {
-            auto subcmd = compl_req->pop();
-
-            if (subcmd == "show")
-              complete_components(f, compl_req);
-            else if (subcmd == "set")
-              {
-                complete_components(f, compl_req);
-                compl_req->complete(f, "all");
-              }
-          }
-          break;
-        case 3:
-          {
-            auto subcmd = compl_req->pop();
-            auto component = compl_req->pop();
-
-            if (subcmd == "set"
-                && (component == "all" || component_valid(component.get())))
-              complete_verbosity_levels(f, compl_req);
-          }
-          break;
-        }
-    }
-
-    void exec(FILE *f, Monitor::Arglist *args) override
-    {
-      auto subcmd = args->pop();
-
-      auto component = args->pop("Missing component identifier");
-
-      if (subcmd == "show")
-        {
-          if (strcmp(component.c_str(), "all") == 0)
-            show_all(f);
-          else if (component_valid(component.c_str()))
-            show_component(f, component.c_str());
-          else
-            Monitor::argument_error("Invalid component specifier");
-        }
-      else if (subcmd == "set")
-        {
-          bool all = strcmp(component.c_str(), "all") == 0;
-
-          if (!all && !component_valid(component.c_str()))
-            Monitor::argument_error("Invalid component specifier");
-
-          auto verbosity_level = args->pop(
-            "Missing verbosity level identifier");
-
-          if (!verbosity_level_valid(verbosity_level.c_str()))
-            Monitor::argument_error("Invalid verbosity level specifier");
-
-          bool success;
-
-          if (all)
-            success = Dbg::set_verbosity(verbosity_level.c_str()) == L4_EOK;
-          else
-            {
-              auto verbosity_cmd =
-                component.c_str() + std::string("=") + verbosity_level.c_str();
-
-              success = Dbg::set_verbosity(verbosity_cmd.c_str()) == L4_EOK;
-            }
-
-          if (!success)
-            Monitor::argument_error("Failed to set verbosity");
-        }
-      else
-        Monitor::argument_error("Invalid subcommand");
-    }
-
-  private:
-    static bool component_valid(char const *component)
-    {
-      auto const *c = Dbg::valid_components();
-
-      while (*c)
-        {
-          if (strcmp(component, *c++) == 0)
-            return true;
-        }
-
-      return false;
-    }
-
-    static bool verbosity_level_valid(char const *verbosity_level)
-    {
-      auto const *v = Dbg::valid_verbosity_levels();
-
-      while (*v)
-        {
-          if (strcmp(verbosity_level, *v++) == 0)
-            return true;
-        }
-
-      return false;
-    }
-
-    static void complete_components(FILE *f,
-                                    Monitor::Completion_request *compl_req)
-    {
-      auto const *c = Dbg::valid_components();
-
-      while (*c)
-        compl_req->complete(f, *c++);
-    }
-
-    static void complete_verbosity_levels(FILE *f,
-                                          Monitor::Completion_request *compl_req)
-    {
-      auto const *v = Dbg::valid_verbosity_levels();
-
-      while (*v)
-        compl_req->complete(f, *v++);
-    }
-
-    /**
-     * \pre component string is a valid component within Dbg.
-     */
-    static void show_component(FILE *f, char const *component)
-    {
-      char const *v;
-      if (Dbg::get_verbosity(component, &v) == L4_EOK)
-        fprintf(f, "%s\n", v);
-      else
-        fprintf(f, "-- error getting verbosity for component %s\n", component);
-    }
-
-    static void show_all(FILE *f)
-    {
-      auto const *c = Dbg::valid_components();
-
-      while (*c)
-        {
-          fprintf(f, "%s:\t", *c);
-          show_component(f, *c++);
-        }
-    }
-  };
-
-  static Cmd_control *get()
-  {
-    static Cmd_control mon("mon", "monitor> ");
-    return &mon;
-  }
-
-  ~Cmd_control()
-  {
-    if (_f)
-      fclose(_f);
-  }
-
-  // true if monitoring was enabled during startup
-  bool enabled() const
-  { return _con.is_valid(); }
-
-  void bind(L4::Registry_iface *registry)
-  {
-    if (enabled())
-      _con->bind(0, L4Re::chkcap(registry->register_irq_obj(this),
-                                 "Register monitor console IRQ."));
-  }
-
-  void add_cmd_handler(Monitor::Cmd *cmd, char const *name)
-  {
-    if (!enabled())
-      return;
-
-    auto it = _cmd_handlers.begin();
-
-    while (it != _cmd_handlers.end())
-      {
-        if (strcmp(name, it->name) < 0)
-          break;
-
-        ++it;
-      }
-
-    _cmd_handlers.insert(it, Named_cmd_handler(cmd, name));
-  }
-
-  void remove_cmd_handler(Monitor::Cmd *cmd)
-  {
-    for (auto it = _cmd_handlers.begin(); it != _cmd_handlers.end(); ++it)
-      {
-        if (it->cmd == cmd)
-          {
-            _cmd_handlers.erase(it);
-            return;
-          }
-      }
-  }
-
-  Monitor::Cmd *find_cmd_handler(char const *name, size_t name_len) const
-  {
-    for (auto &handler : _cmd_handlers)
-      {
-        if (strlen(handler.name) == name_len
-            && strncmp(handler.name, name, name_len) == 0)
-          {
-            return handler.cmd;
-          }
-      }
-
-    return nullptr;
-  }
-
-  void handle_irq()
-  {
-    std::string line;
-    if (!get_line(&line))
-      return;
-
-    if (line.back() == (char)Uvmm_cli::PROTO_COMPL_REQ)
-      handle_completion(line.substr(0, line.size() - 1).c_str());
-    else
-      handle_cmd(line.c_str());
-  }
-
-private:
-  Cmd_control(char const *capname, char const *prompt)
-  : _f(nullptr),
-    _prompt(prompt),
-    _con(L4Re::Env::env()->get_cap(capname))
-  {
-    if (!enabled())
-      return; // no monitoring requested
-
-    _f = fopen(capname, "w+");
-    if (!_f)
-      {
-        Err().printf("Could not open command control '%s'\n", capname);
-        L4Re::throw_error(-L4_ENOENT, "Open channel to command control.");
-      }
-
-    l4_vcon_attr_t attr;
-    if (l4_error(_con->get_attr(&attr)) != L4_EOK)
-      {
-        Err().printf("Failed to determine command control attributes, "
-                     "CLI interface may be disabled\n");
-        _show_prompt = false;
-      }
-    else
-      {
-        _show_prompt =
-          !(attr.l_flags & Uvmm_cli::ENABLED);
-      }
-  }
-
-  bool get_line(std::string *line)
-  {
-    // read more data
-    char buf[Vcon_buf_sz];
-
-    for (;;)
-      {
-        int read_sz = _con->read(buf, Vcon_buf_sz);
-
-        if (read_sz < 0)
-          {
-            Err().printf("Failed to read data");
-            return false;
-          }
-
-        if (read_sz > Vcon_buf_sz)
-          {
-            _read_buf.append(buf, Vcon_buf_sz);
-          }
-        else
-          {
-            _read_buf.append(buf, read_sz);
-            break;
-          }
-      }
-
-    // check if a line is buffered
-    char const *newline = reinterpret_cast(
-      memchr(_read_buf.data(), '\n', _read_buf.size()));
-
-    if (!newline)
-      return false;
-
-    *line = std::string(_read_buf.data(), newline - _read_buf.data());
-    _read_buf = std::string(newline + 1);
-
-    return true;
-  }
-
-  void handle_cmd(char const *cmd_line)
-  {
-    char *delim = strchrnul(cmd_line, ' ');
-
-    size_t cmd_len = delim - cmd_line;
-    auto *handler = find_cmd_handler(cmd_line, cmd_len);
-
-    if (handler)
-      {
-        Monitor::Arglist arglist(*delim ? delim + 1 : delim);
-
-        try
-          {
-            handler->exec(_f, &arglist);
-          }
-        catch (L4::Runtime_error const &e)
-          {
-            fprintf(_f, "Command execution failed");
-
-            char const *msg = e.extra_str();
-            if (msg)
-              fprintf(_f, ": %s", msg);
-
-            fprintf(_f, "\n\n%s\n", handler->help());
-          }
-      }
-    else
-      fprintf(_f, "Monitor: Unknown cmd %.*s\n", (int)cmd_len, cmd_line);
-
-    end_transmission();
-  }
-
-  void handle_completion(char const *cmd_line)
-  {
-    // find the position of the first and last character of the last word
-    // on the command line (this is the word for which we want to produce
-    // completions)
-    int end_last = strlen(cmd_line);
-
-    int beg_last = end_last - 1;
-    while (beg_last >= 0 && cmd_line[beg_last] != ' ')
-      --beg_last;
-    ++beg_last;
-
-    if (beg_last == 0)
-      {
-        // if there is only one word, complete it using all registered commands
-        for (auto const &handler : _cmd_handlers)
-          {
-             if (end_last <= (int)(strlen(handler.name))
-                 && strncmp(cmd_line + beg_last, handler.name, end_last) == 0)
-               {
-                 fprintf(_f,
-                         "%s%c",
-                         handler.name,
-                         (char)Uvmm_cli::PROTO_COMPL_SEP);
-               }
-          }
-      }
-    else
-      {
-        // find the position of the last character of the current commands name
-        int end_first = 1;
-        while (cmd_line[end_first] != ' ')
-          ++end_first;
-
-        // look up a handler corresponding to this command name and if such a
-        // handler exists, let it complete the rest of the command line
-        auto *handler = find_cmd_handler(cmd_line, end_first);
-        if (handler)
-          {
-            // find the beginning of additional arguments to the command
-            // and pass them to the handlers completion method
-            int beg_sub = end_first;
-            while (beg_sub < end_last && cmd_line[beg_sub] == ' ')
-              ++beg_sub;
-
-            Monitor::Completion_request compl_req(cmd_line + beg_sub);
-            handler->complete(_f, &compl_req);
-          }
-      }
-
-     end_transmission();
-  }
-
-  void end_transmission()
-  {
-
-    if (_show_prompt)
-      fprintf(_f, "%s", _prompt);
-    else
-      fputc((char)Uvmm_cli::PROTO_EOT, _f);
-
-    fflush(_f);
-  }
-
-  FILE *_f;
-  char const *_prompt;
-  bool _show_prompt;
-  std::string _read_buf;
-
-  L4::Cap _con;
-  std::vector _cmd_handlers;
-};
-
-} // namespace
-
-namespace Monitor {
-
-void
-Cmd::register_toplevel(char const *name)
-{ Cmd_control::get()->add_cmd_handler(this, name); }
-
-void
-Cmd::unregister_toplevel()
-{ Cmd_control::get()->remove_cmd_handler(this); }
-
-Cmd::~Cmd()
-{ unregister_toplevel(); }
-
-void
-enable_cmd_control(Vmm::Vm *vm)
-{
-  static Cmd_control::Help help;
-  static Cmd_control::Verbose verbose;
-
-  static Dbg_enable_cmd_handler
-  dbg_enable_cmd_handler(vm);
-
-  Cmd_control::get()->bind(vm->vmm()->registry());
-}
-
-bool
-cmd_control_enabled()
-{ return Cmd_control::get()->enabled(); }
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/monitor.h b/src/l4/pkg/uvmm/server/src/monitor/monitor.h
deleted file mode 100644
index 5e71134c..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/monitor.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include "monitor/monitor_args.h"
-
-namespace Vmm {
-  class Vm;
-}
-
-namespace Monitor {
-
-/// Monitor console state indicator
-enum : bool {
-  /// `True` if monitor console support has been enabled during compilation
-#ifdef CONFIG_UVMM_MONITOR
-  Enabled = true,
-  /// `True` if guest debugger support has been enabled during compilation
-  #if defined(CONFIG_BUILD_ARCH_amd64) && !defined(CONFIG_RELEASE_MODE)
-    Guest_debugger_support = true
-  #else
-    Guest_debugger_support = false
-  #endif
-#else
-  Enabled = false,
-#endif
-};
-
-/**
- * Abstract monitor console command interface.
- *
- * This class provides a common interface implemented by all monitor console
- * command handlers.
- */
-class Cmd
-{
-public:
-  /**
-   * Return command help message.
-   *
-   * \return The help message as a C-string.
-   *
-   * The value returned by this function is displayed alongside the command
-   * name in the output of the `help` command and should only consist of
-   * a single short line of text describing the action performed by the command.
-   */
-  virtual char const *help() const = 0;
-
-  /**
-   * Display command usage message.
-   *
-   * \return  Stream to which to print usage message.
-   *
-   * \note  The `help ` command uses this function.
-   */
-  virtual void usage(FILE *f) const
-  { fprintf(f, "%s\n", help()); }
-
-  /**
-   * Complete partial arguments.
-   *
-   * \param f          Stream to which completions are to be written.
-   * \param compl_req  Command line to be completed.
-   *
-   * This method should examine whether there exist one or several suitable
-   * completions for the partial arguments to the command implemented by this
-   * monitor passed via `args`. If so, these completions should be written to
-   * `f` in arbitrary order, separated by newlines (with an optional trailing
-   * newline).  Otherwise this method should do nothing. When `args` is an
-   * empty string, all possible subcommands should be output this way.
-   */
-  virtual void complete(FILE * /* f */,
-                        Completion_request * /* compl_req */) const
-  {}
-
-  /**
-   * Invoke command.
-   *
-   * \param f     Stream to which command output (both regular output and
-   *              errors) should be written. The command output should always
-   *              end with a final newline, unless no output is produced to
-   *              begin with.
-   *
-   * \param args  Arguments passed to the command.
-   *
-   * This method is called when the implemented command is sent to uvmm
-   * via the monitor console interface, possibly with additional arguments.
-   */
-  virtual void exec(FILE *f, Arglist *args) = 0;
-
-  /**
-   * Register command.
-   *
-   * \param name  The command name under which this handler will be accessible
-   *              via the monitor console interface.
-   *
-   * This method registers this handler with the monitor console interface and
-   * thus makes it available as an additional top level command.
-   */
-  void register_toplevel(char const *name);
-
-  /**
-   * Unregister command.
-   *
-   * Note that this is automatically called during destruction.
-   */
-  void unregister_toplevel();
-
-  /**
-   * Destructor.
-   *
-   * Upon destruction of this object, the handler will be automatically
-   * unregistered from the monitor console interface.
-   */
-  virtual ~Cmd();
-};
-
-#ifdef CONFIG_UVMM_MONITOR
-/**
- * Enable the monitor console.
- *
- * \param vm  Pointer to virtual machine object.
- *
- * This will make the monitor console interface available to other servers via
- * a capability registered under the name `"mon"`.
- *
- * Note that this function will have no effect if monitor console support has
- * not been enabled during compilation, i.e. if `Enabled` is `false`. This
- * function should be called unconditionally during startup of uvmm such that
- * the availability of the monitor console only depends on the presence of the
- * `"mon"` capability.
- */
-void enable_cmd_control(Vmm::Vm *vm);
-
-/**
- * Check if the monitor console has been enabled.
- *
- * \return  `true` if monitor console support has been enabled during
- *          compilation, a valid `"mon"` capability has been provided and
- *          `enable_cmd_control` has been invoked previously.
- */
-bool cmd_control_enabled();
-#else
-inline void enable_cmd_control(Vmm::Vm *)
-{}
-
-inline bool cmd_control_enabled()
-{ return false; }
-#endif
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/monitor_args.h b/src/l4/pkg/uvmm/server/src/monitor/monitor_args.h
deleted file mode 100644
index 8d80d608..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/monitor_args.h
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-
-namespace Monitor {
-
-namespace Detail {
-  template
-  struct Equality_comparable
-  {
-     friend bool operator == (U const &lhs, T const &rhs) noexcept
-     { return rhs == lhs; }
-     friend bool operator != (T const &lhs, U const &rhs) noexcept
-     { return !(lhs == rhs); }
-     friend bool operator != (U const &lhs, T const &rhs) noexcept
-     { return !(lhs == rhs); }
-  };
-}
-
-class Arglist;
-
-/**
- * Helper class encapsulating a monitor command argument.
- */
-class Arg
-: private Detail::Equality_comparable,
-  private Detail::Equality_comparable
-{
-  friend class Arglist;
-
-public:
-  /**
-   * Compare this argument to a C-string.
-   *
-   * \param rhs  C-string to compare to this argument.
-   *
-   * \return  `true` in case of equality, else `false`.
-   *
-   * \note  It is also possible to evaluate `str == arg`, `arg != str` and
-   *        `str != arg` where `str` is a C-string and `arg` is an object of
-   *        type `Arg`.
-   */
-  bool operator == (char const *rhs) const noexcept
-  { return _arg == rhs; }
-
-  /**
-   * Compare this argument to a String.
-   *
-   * \param rhs  String to compare to this argument.
-   *
-   * \return  `true` in case of equality, else `false`.
-   *
-   * \see `operator == (char const *)`.
-   */
-  bool operator == (std::string const &rhs) const noexcept
-  { return _arg == rhs; }
-
-  /**
-   * Check if this is a valid argument.
-   *
-   * \return  `true` if this is a valid argument, else `false`.
-   *
-   * 'Invalid' arguments are arguments which have been popped from an empty
-   * argument list, calling `get()` without a default argument on an invalid
-   * argument will cause an exception to be thrown.
-   */
-  bool valid() const
-  { return !_arg.empty(); }
-
-  /**
-   * Check if this argument can be converted to a certain type.
-   *
-   * \tparam T  Type to which to convert this argument.
-   *
-   * \return  `true` if a conversion to `T` is possible for this argument,
-   *          else `false`.
-   */
-  template
-  bool check()
-  {
-    if (!valid())
-      return false;
-
-    return do_check();
-  }
-
-  /**
-   * Convert this argument to a certain type.
-   *
-   * \tparam T  Type to which to convert this argument.
-   *
-   * \param msg  Optional conversion failure error message.
-   *
-   * \return  This argument converted to `T`.
-   *
-   * \throws L4::Runtime_error  If this is an invalid argument or if this is a
-   *                            valid argument but the requested conversion is
-   *                            not well defined, i.e. `check() == false`.
-   */
-  template
-  T get(char const *msg = nullptr)
-  {
-    if (!check())
-      conversion_error(msg);
-
-    return do_get();
-  }
-
-  /**
-   * Convert this argument to a certain type.
-   *
-   * \tparam T  Type to which to convert this argument.
-   *
-   * \param def  Default value.
-   * \param msg  Optional conversion failure error message.
-   *
-   * \return  If `valid() == true` this argument converted to `T`, else `def`.
-   *
-   * \throws L4::Runtime_error  If this is a valid argument but the requested
-   *                            conversion is not well defined, i.e.
-   *                            `check() == false`.
-   */
-  template
-  T get(T def, char const *msg = nullptr)
-  {
-    if (!valid())
-      return def;
-
-    if (!check())
-      conversion_error(msg);
-
-    return do_get();
-  }
-
-private:
-  Arg(char const *arg, size_t arglen)
-  : _arg(arg, arglen),
-    _unsigned_cache(0),
-    _unsigned_cached(false)
-  {}
-
-  static bool stoull(char const *str, unsigned long long *ull, int base)
-  {
-    errno = 0;
-
-    char *endptr;
-    *ull = strtoull(str, &endptr, base);
-
-    return errno == 0 && !*endptr;
-  }
-
-  static void conversion_error(char const *msg)
-  { L4Re::chksys(-L4_EINVAL, msg ? msg : "Parameter conversion"); }
-
-  template
-  typename std::enable_if::value, bool>::type
-  do_check()
-  { return true; }
-
-  template
-  typename std::enable_if::value, bool>::type
-  do_check()
-  { return true; }
-
-  template
-  typename std::enable_if::value, bool>::type
-  do_check()
-  {
-    auto max_val = static_cast(std::numeric_limits::max());
-
-    if (_unsigned_cached)
-      return _unsigned_cache <= max_val;
-
-    unsigned long long ull;
-    if (!stoull(_arg.c_str(), &ull, 10) && !stoull(_arg.c_str(), &ull, 16))
-      return false;
-
-    if (ull > max_val)
-      return false;
-
-    _unsigned_cache = ull;
-    _unsigned_cached = true;
-
-    return true;
-  }
-
-  template
-  typename std::enable_if::value, T>::type
-  do_get()
-  { return _arg.c_str(); }
-
-  template
-  typename std::enable_if::value, T>::type
-  do_get()
-  { return _arg; }
-
-  template
-  typename std::enable_if::value, T>::type
-  do_get()
-  { return static_cast(_unsigned_cache); }
-
-  std::string _arg;
-
-  unsigned long long _unsigned_cache;
-  bool _unsigned_cached;
-};
-
-/**
- * Encapsulates a monitor commands argument list.
- */
-class Arglist
-: private Detail::Equality_comparable,
-  private Detail::Equality_comparable
-{
-public:
-  /**
-   * Constructor.
-   *
-   * \param args  A C-string containing a list of arguments in the form of zero
-   *              one or several words separated by single whitespace
-   *              characters. Anything else causes the behaviour of the
-   *              resulting object to be undefined.
-   */
-  explicit Arglist(char const *args)
-  : _args(args),
-    _argc(0)
-  {
-    assert(_args);
-
-    if (empty())
-      return;
-
-    _argc = 1;
-
-    char const *tmp = _args;
-    while ((tmp = strchr(tmp, ' ')))
-      {
-        while (*tmp == ' ')
-          ++tmp;
-
-        if (*tmp != '\0')
-          ++_argc;
-      }
-  }
-
-  /**
-   * Compare the complete argument list to a C-string.
-   *
-   * \param rhs  C-string to compare to the raw argument list.
-   *
-   * \return  `true` in case of equality, else `false`.
-   *
-   * The raw argument list is also a C-string containing all arguments
-   * separated by single space characters.
-   *
-   * \note  It is also possible to evaluate `str == arglist`, `arglist != str`
-   *        and `str != arglist` where `str` is a C-string and `arglist` is an
-   *        object of type `Arglist`.
-   */
-  bool operator == (char const *rhs) const noexcept
-  { return strcmp(_args, rhs) == 0; }
-
-  /**
-   * Compare the complete argument list to a String.
-   *
-   * \param rhs  String to compare to the raw argument list.
-   *
-   * \return  `true` in case of equality, else `false`.
-   *
-   * \see `operator == (char const *)`.
-   */
-  bool operator == (std::string const &rhs) const noexcept
-  { return _args == rhs; }
-
-  /**
-   * Check whether the argument list contains no arguments.
-   *
-   * \return  `true` if the argument list contains no arguments, else `false`.
-   */
-  bool empty() const
-  { return *_args == '\0'; }
-
-  /**
-   * Obtain the number of arguments in the argument list.
-   *
-   * \return  Number of arguments in the argument list.
-   */
-  unsigned count() const
-  { return _argc; }
-
-  /**
-   * Non-destructively retrieve the next argument.
-   *
-   * \return  The next argument, if there are no more arguments (i.e.
-   *          `empty() == true`) this function will still succeed, but calling
-   *          `Arg::check()` on the returned argument will return `false` for
-   *          any `T`.
-   *
-   * This retrieves the first (i.e. leftmost) argument from the list of
-   * arguments.
-   */
-  Arg peek() const
-  {
-    char const *delim = strchrnul(_args, ' ');
-
-    return Arg(_args, delim - _args);
-  }
-
-  /**
-   * Non-destructively retrieve and convert the next argument.
-   *
-   * \tparam T  Type to convert the argument to.
-   *
-   * \param msg  Optional conversion failure error message.
-   *
-   * \return  The next argument converted to `T`.
-   *
-   * This is a convencience method whose result is equal to `peek().get()`.
-   */
-  template
-  T peek(char const *msg = nullptr) const
-  { return peek().get(msg); }
-
-  /**
-   * Retrieve the next argument.
-   *
-   * \return  The next argument, if there are no more arguments (i.e.
-   *          `empty() == true`) this function will still success, but calling
-   *          `Arg::check()` on the returned argument will return `false` for
-   *          any `T`.
-   *
-   * This retrieves and removes the first (i.e. leftmost) argument from the
-   * list of arguments.
-   */
-  Arg pop()
-  {
-    if (empty())
-      return Arg("", 0);
-
-    char const *arg = _args;
-
-    char const *delim = strchrnul(_args, ' ');
-    size_t arglen = delim - _args;
-    _args  = delim;
-    _args += strspn(_args, " ");
-    --_argc;
-
-    return Arg(arg, arglen);
-  }
-
-  /**
-   * Retrieve and convert the next argument.
-   *
-   * \tparam T  Type to convert the argument to.
-   *
-   * \param msg  Optional conversion failure error message.
-   *
-   * \return  The next argument converted to `T`.
-   *
-   * \throws L4::Runtime_error  If there are no more arguments or the conversion
-   *                            fails.
-   *
-   * This is a convencience method whose result is equal to `pop().get()`.
-   */
-  template
-  T pop(char const *msg = nullptr)
-  { return pop().get(msg); }
-
-  /**
-   * Retrieve and convert the next argument.
-   *
-   * \tparam T  Type to which to convert this argument.
-   *
-   * \param def  Default value.
-   * \param msg  Optional conversion failure error message.
-   *
-   * \return  The next argument converted to `T` or `def` if there is no next
-   *          argument.
-   *
-   * \throws L4::Runtime_error  If the conversion fails.
-   *
-   * This is a convencience method whose result is equal to `pop().get(def)`.
-   */
-  template
-  T pop(T def, char const *msg = nullptr)
-  { return pop().get(def, msg); }
-
-protected:
-  char const *_args;
-  unsigned _argc;
-};
-
-// Converting arguments to `char const *` is well defined but directly popping
-// `char const *` must be disallowed since the temporary argument object which
-// owns the memory backing the string is immediately destroyed once
-// `pop()` returns.
-template<>
-inline char const *
-Arglist::pop(char const *) = delete;
-
-template<>
-inline char const *
-Arglist::pop(char const *, char const *) = delete;
-
-/**
- * Encapsulates a monitor command completion request.
- */
-class Completion_request : public Arglist
-{
-public:
-  using Arglist::Arglist;
-
-  /**
-   * Check whether this completion request contains trailing whitespace.
-   *
-   * \return  `true` if this completion request contains trailing whitespace,
-   *          else `false`.
-   *
-   * This returns `true` if and only if the cursor was not positioned in the
-   * middle or directly after the end of a word when this completion request
-   * was created, else `false`.
-   */
-  bool trailing_space() const
-  { return _args[strlen(_args) - 1] == ' '; }
-
-  /**
-   * Complete some word.
-   *
-   * \param f           Stream to which to write output
-   * \param completion  Potential completion.
-   *
-   * If the completion request constitutes a prefix of `completion`, this will
-   * print `completion` followed by a single newline to `f`.
-   */
-  void complete(FILE *f, char const *completion) const
-  {
-    if (strncmp(_args, completion, strlen(_args)) == 0)
-      fprintf(f, "%s\n", completion);
-  }
-
-  /**
-   * Apply `completion(FILE *, char const *)` to several potential completions
-   * at once.
-   *
-   * \param f            Stream to which to write output
-   * \param completions  List of potential completions.
-   *
-   * \see `complete(FILE *, char const *)`.
-   */
-  void complete(FILE *f, std::initializer_list completions) const
-  {
-    for (char const *completion : completions)
-      complete(f, completion);
-  }
-};
-
-/**
- * Produce a command specific argument error.
- *
- * \param msg  Human readable error message.
- *
- * \throws L4::Runtime_error  Unconditionally.
- */
-inline void
-argument_error(char const *msg)
-{ L4Re::chksys(-L4_EINVAL, msg); }
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/virtio_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/virtio_cmd_handler.h
deleted file mode 100644
index fcd6d42a..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/virtio_cmd_handler.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-
-#include "monitor.h"
-#include "monitor_args.h"
-
-namespace Monitor {
-
-template
-class Virtio_cmd_handler {};
-
-template
-class Virtio_cmd_handler : public Cmd
-{
-public:
-  char const *help() const override
-  { return "Virtio device state"; }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, {"config", "queues"}); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    auto subcmd = args->pop();
-
-    auto *config = virtio_dev()->virtio_cfg();
-
-    if (subcmd == "config")
-      {
-        fprintf(f, "# Config Header\n");
-        print_config(f, config);
-      }
-    else if (subcmd == "queues")
-      {
-        for (auto qn = 0u; qn < config->num_queues; ++qn)
-          {
-            auto *queue_config = virtio_dev()->get_queue_config(qn);
-            if (queue_config->ready)
-              {
-                fprintf(f, "\n## Queue %d Config\n", qn);
-                print_queue_config(f, queue_config);
-              }
-            else
-              fprintf(f, "\n## Queue %d Not Ready\n", qn);
-          }
-      }
-  }
-
-  static void print_config(FILE *f, l4virtio_config_hdr_t const *config)
-  {
-    auto device_id = config->device;
-
-    char const *device_name = device_id_to_string(config->device);
-
-    fprintf(f, "VIRTIO Version:         0x%08x\n", config->version);
-    fprintf(f, "Device ID:              0x%08x (%s)\n", device_id, device_name);
-    fprintf(f, "Vendor ID:              0x%08x\n", config->vendor);
-    fprintf(f, "Config Array Offset:    0x%08x\n", config->queues_offset);
-    fprintf(f, "Device Status Register: 0x%08x\n", config->status);
-    fprintf(f, "Cmd:                    0x%08x\n", config->cmd);
-    fprintf(f, "Number of Virtqueues:   %x\n", config->num_queues);
-    fprintf(f, "Event Index (w):        %x\n", config->cfg_driver_notify_index);
-    fprintf(f, "Event Index (r):        %x\n", config->cfg_device_notify_index);
-  }
-
-  static char const *device_id_to_string(l4_uint32_t device_id)
-  {
-    static char const *devices[] = {
-      "Network Card", "Block Device", "Console", "Entropy Source",
-      "Memory Ballooning", "IO Memory", "RPMSG", "SCSI Host", "9P Transport",
-      "MAC802.11 WLAN"
-    };
-
-    if (device_id < 1 || device_id > 10)
-      return "Unknown";
-
-    return devices[device_id - 1];
-  }
-
-  static void print_queue_config(FILE *f, l4virtio_config_queue_t const *config)
-  {
-    fprintf(f, "Configured Descriptors:   %x\n", config->num);
-    fprintf(f, "Maximum Descriptors:      %x\n", config->num_max);
-    fprintf(f, "Descriptor Table Address: 0x%016llx\n", config->desc_addr);
-    fprintf(f, "Available Ring Address:   0x%016llx\n", config->avail_addr);
-    fprintf(f, "Used Ring Address:        0x%016llx\n", config->used_addr);
-    fprintf(f, "Event Index (w):          %x\n", config->driver_notify_index);
-    fprintf(f, "Event Index (r):          %x\n", config->device_notify_index);
-  }
-
-private:
-  T *virtio_dev()
-  { return static_cast(this); }
-};
-
-template
-struct Virtio_dev_cmd_handler : Virtio_cmd_handler
-{
-  l4virtio_config_queue_t *get_queue_config(unsigned qn)
-  { return &static_cast(this)->virtqueue(qn)->config; }
-};
-
-template
-struct Virtio_proxy_cmd_handler : Virtio_cmd_handler
-{
-  l4virtio_config_queue_t *get_queue_config(unsigned qn)
-  { return l4virtio_config_queues(static_cast(this)->virtio_cfg()) + qn; }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/virtio_input_power_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/virtio_input_power_cmd_handler.h
deleted file mode 100644
index 0d02ad6e..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/virtio_input_power_cmd_handler.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Virtio_input_power_cmd_handler {};
-
-template
-class Virtio_input_power_cmd_handler : public Cmd
-{
-public:
-  Virtio_input_power_cmd_handler()
-  { register_toplevel("sysrq"); }
-
-  char const *help() const override
-  { return "Send system request"; }
-
-  void exec(FILE *, Arglist *args) override
-  {
-    auto key = args->pop("Missing key");
-
-    if (key.size() != 1)
-      argument_error("Key expected (try 'h' for help)");
-
-    if (!virtio_input_power()->inject_command(key[0]))
-      argument_error("Failed to inject event");
-  }
-
-private:
-  T * virtio_input_power()
-  { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/vm_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/vm_cmd_handler.h
deleted file mode 100644
index 4764c5c3..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/vm_cmd_handler.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2019, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "device.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_arch.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Vm_cmd_handler {};
-
-template
-class Vm_cmd_handler : public Cmd
-{
-public:
-  Vm_cmd_handler()
-  { register_toplevel("dev"); }
-
-  char const *help() const override
-  { return "Device list"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'dev list': list available devices\n"
-               "* 'dev  ': execute device specific command\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  {
-    compl_req->complete(f, {"list", "memmap", "iomap"});
-
-    for (auto const &d : vm()->_devices)
-      compl_req->complete(f, d.path.c_str());
-  }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    if (*args == "list")
-      {
-        for (auto const &d : vm()->_devices)
-          fprintf(f, " %s\n", d.path.c_str());
-      }
-    else if (*args == "memmap")
-      dump_memmap(f);
-    else if (*args == "iomap")
-      dump_iomap(f);
-    else
-      {
-        auto subcmd = args->pop();
-
-        bool found_device = false;
-        Cmd *monitor = nullptr;
-
-        for (auto const &d : vm()->_devices)
-          {
-            if (d.path == subcmd)
-              {
-                found_device = true;
-                monitor = dynamic_cast(d.dev.get());
-                break;
-              }
-          }
-
-        if (found_device)
-          {
-            if (monitor)
-              monitor->exec(f, args);
-            else
-              argument_error("Not implemented");
-          }
-        else
-          argument_error("Unknown device");
-      }
-  }
-
-private:
-  void dump_memmap(FILE *f)
-  {
-    for (auto const &p : *vm()->vmm()->memmap())
-      {
-        print_region(f, p.first, p.second.get());
-        fputc('\n', f);
-      }
-  }
-
-  template
-  typename std::enable_if::type
-  dump_iomap(FILE *f)
-  {
-    for (auto const &p : *vm()->vmm()->iomap())
-      {
-        print_region(f, p.first, p.second.get());
-        fputc('\n', f);
-      }
-  }
-
-  template
-  typename std::enable_if::type
-  dump_iomap(FILE *f)
-  { fprintf(f, "No iomap\n"); }
-
-  template
-  void print_region(FILE *f, U const ®ion, Vdev::Dev_ref const *dev) const
-  {
-    enum { Region_id_maxlen = 7 };
-
-    char const *region_type = "Untyped";
-
-    switch (region.type)
-      {
-        case Vmm::Region_type::Ram:
-          region_type = "RAM";
-          break;
-        case Vmm::Region_type::Vbus:
-          region_type = "Vbus";
-          break;
-        case Vmm::Region_type::Kernel:
-          region_type = "Kernel";
-          break;
-        case Vmm::Region_type::Virtual:
-          region_type = "Virtual";
-          break;
-        default:
-          break;
-      }
-
-    fprintf(f, "%-*s", Region_id_maxlen + 1, region_type);
-
-    char const *region_fmt =
-      sizeof(l4_addr_t) == 4 ? "[0x%08x...0x%08x]"
-                             : "[0x%016llx...0x%016llx]";
-
-    fprintf(f, region_fmt, region.start, region.end);
-
-    // append device info (currently only works for some regions/devices)
-    for (auto const &d : vm()->_devices)
-      {
-        if (d.dev.get() == dev)
-          {
-            fprintf(f, " (%s)", d.path.c_str());
-            break;
-          }
-      }
-  }
-
-  T const *vm() const
-  { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/vm_io_mem_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/vm_io_mem_cmd_handler.h
deleted file mode 100644
index eae1006c..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/vm_io_mem_cmd_handler.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "mem_types.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Vm_io_mem_cmd_handler {};
-
-template
-class Vm_io_mem_cmd_handler : public Cmd
-{
-  enum { Region_id_maxlen = 7 };
-
-public:
-  Vm_io_mem_cmd_handler()
-  { register_toplevel(IO ? "iomap" : "memmap"); }
-
-  char const *help() const override
-  { return IO ? "IO device mappings" : "MMIO device mappings"; }
-
-  void exec(FILE *f, Arglist *) override
-  {
-    fprintf(f, "Devices mapped at:\n");
-
-    for (auto const &p : *mem())
-      {
-        print_region(f, p.first);
-        fputc('\n', f);
-      }
-  }
-
-private:
-  template
-  static void print_region(FILE *f, U const ®ion)
-  {
-    char const *region_type = "Untyped";
-
-    switch (region.type)
-      {
-        case Vmm::Region_type::Ram:
-          region_type = "RAM";
-          break;
-        case Vmm::Region_type::Vbus:
-          region_type = "Vbus";
-          break;
-        case Vmm::Region_type::Kernel:
-          region_type = "Kernel";
-          break;
-        case Vmm::Region_type::Virtual:
-          region_type = "Virtual";
-          break;
-        default:
-          break;
-      }
-
-    fprintf(f, "%-*s", Region_id_maxlen + 1, region_type);
-
-    char const *region_addr_fmt =
-      sizeof(l4_addr_t) == 4 ? "[0x%08x...0x%08x]"
-                             : "[0x%016llx...0x%016llx]";
-
-    fprintf(f, region_addr_fmt, region.start, region.end);
-  }
-
-  T const *mem() const
-  { return static_cast(this); }
-};
-
-template
-using Vm_mem_cmd_handler = Vm_io_mem_cmd_handler;
-
-template
-using Io_mem_cmd_handler = Vm_io_mem_cmd_handler;
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/monitor/vm_ram_cmd_handler.h b/src/l4/pkg/uvmm/server/src/monitor/vm_ram_cmd_handler.h
deleted file mode 100644
index f3827357..00000000
--- a/src/l4/pkg/uvmm/server/src/monitor/vm_ram_cmd_handler.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "mem_dump.h"
-#include "mem_types.h"
-#include "monitor/monitor.h"
-#include "monitor/monitor_args.h"
-
-namespace Monitor {
-
-template
-class Vm_ram_cmd_handler {};
-
-template
-class Vm_ram_cmd_handler : public Cmd
-{
-public:
-  Vm_ram_cmd_handler()
-  { register_toplevel("ram"); }
-
-  char const *help() const override
-  { return "RAM dataspaces"; }
-
-  void usage(FILE *f) const override
-  {
-    fprintf(f, "%s\n"
-               "* 'ram ds': list RAM dataspaces\n"
-               "* 'ram dump  [ [(b|w|d|q)]]': dump RAM region\n"
-               "where: * b = byte, w = word (16 bits), d = double word, q = quad word\n"
-               "       *  = number of entries to be dumped\n",
-            help());
-  }
-
-  void complete(FILE *f, Completion_request *compl_req) const override
-  { compl_req->complete(f, {"ds", "dump"}); }
-
-  void exec(FILE *f, Arglist *args) override
-  {
-    auto subcmd = args->pop();
-
-    if (subcmd == "ds")
-      show_dataspaces(f);
-    else if (subcmd == "dump")
-      dump_memory(f, args);
-    else
-      argument_error("Invalid subcommand");
-  }
-
-private:
-  void show_dataspaces(FILE *f) const
-  {
-    fprintf(f, "Dataspace  Guest area             Size        Local address  Phys?\n");
-    for (auto const &r : vm_ram()->_regions)
-      fprintf(f, "%9lu  0x%08llx-0x%08llx  0x%08llx  0x%08llx     %s\n",
-              r->dataspace().cap() >> L4_CAP_SHIFT,
-              static_cast(r->vm_start().get()),
-              static_cast(r->vm_start().get() + r->size()),
-              static_cast(r->size()),
-              static_cast(r->local_start()),
-              r->has_phys_addr() ? "Y" : "N");
-  }
-
-  bool dump_memory(FILE *f, Arglist *args) const
-  {
-    Mem_dumper mem_dumper(args);
-
-    Vmm::Guest_addr ga(mem_dumper.addr_start());
-
-    auto const r = vm_ram()->find_region(ga, 0);
-    if (!r)
-      argument_error( "Invalid RAM region");
-
-    l4_addr_t addr_hvirt = reinterpret_cast(r->guest2host(ga));
-    l4_size_t max_size = r->vm_start().get() - ga.get() + r->size();
-
-    mem_dumper.dump(f, addr_hvirt, max_size);
-
-    return true;
-  }
-
-  T const *vm_ram() const
-  { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/msi.h b/src/l4/pkg/uvmm/server/src/msi.h
deleted file mode 100644
index 40e1a8b1..00000000
--- a/src/l4/pkg/uvmm/server/src/msi.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2019-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "vcpu_obj_registry.h"
-#include "msi_controller.h"
-#include "msi_allocator.h"
-#include "msi_irq_src.h"
-#include "pci_device.h"
-
-namespace Vdev { namespace Msi {
-
-/**
- * Source for an MSI to inject into the guest OS.
- */
-class Msi_src : public Msi_irq_src, public virtual Vdev::Dev_ref
-{
-public:
-  /**
-   * \param msi_alloc    Pointer to a MSI manager, e.g. vBus.
-   * \param msix_dest    MSI controller handling the MSI(X).
-   * \param registry     VCPU local object registry.
-   * \param msi_cap      MSI capability of the corresponding PCI device.
-   * \param msi_index    Vector number offset to inject into guest.
-   *
-   * Multiple MSIs are defined as consecutive list of MSI data values.
-   * `msi_index` defines the entry number in this list.
-   */
-  Msi_src(cxx::Ref_ptr msi_alloc,
-          Gic::Msix_dest const &msix_dest,
-          Vcpu_obj_registry *registry,
-          Vdev::Pci::Pci_msi_cap const &msi_cap,
-          unsigned msi_index)
-  : Msi_irq_src(msi_alloc, msix_dest, registry),
-    _msi_cap(msi_cap),
-    _msi_index(msi_index)
-  {}
-
-  l4_uint64_t msi_vec_addr() const
-  { return _msi_cap.addr(); }
-
-  l4_uint64_t msi_vec_data() const
-  { return _msi_cap.data + _msi_index; }
-
-private:
-  Vdev::Pci::Pci_msi_cap const &_msi_cap;
-  unsigned const _msi_index;
-};
-
-class Msi_src_factory : public virtual Vdev::Dev_ref
-{
-public:
-  Msi_src_factory(cxx::Ref_ptr msi_alloc,
-                  Vcpu_obj_registry *registry)
-  : _msi_alloc(msi_alloc), _registry(registry)
-  {}
-
-  cxx::Ref_ptr configure_msi_route(Pci::Pci_msi_cap const &msi_cap,
-                                            Gic::Msix_dest const &msix_dest,
-                                            l4_uint64_t src_id,
-                                            l4_icu_msi_info_t *info)
-  {
-    // allocate IRQ object and bind it to the ICU
-    auto msi_src =
-      Vdev::make_device(_msi_alloc, msix_dest, _registry, msi_cap, 0);
-
-    // get MSI info
-    l4_icu_msi_info_t msiinfo;
-    msi_src->msi_info(src_id, &msiinfo);
-
-    // unmask the MSI-IRQ
-    L4Re::chkipc(msi_src->obj_cap()->unmask(), "Unmask MSI-IRQ.");
-
-    *info = msiinfo;
-    return msi_src;
-  }
-
-private:
-  cxx::Ref_ptr _msi_alloc;
-  Vcpu_obj_registry *_registry;
-}; // class Msi_src_factory
-
-} } // namespace Vdev::Msi
diff --git a/src/l4/pkg/uvmm/server/src/msi_allocator.h b/src/l4/pkg/uvmm/server/src/msi_allocator.h
deleted file mode 100644
index 632e28e0..00000000
--- a/src/l4/pkg/uvmm/server/src/msi_allocator.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "device.h"
-
-namespace Vdev { namespace Msi {
-
-/// Interface for access to the MSI allocator and the ICU providing the MSIs.
-class Allocator : public virtual Vdev::Dev_ref
-{
-public:
-  virtual ~Allocator() = 0;
-
-  /// Access to the ICU providing the MSIs.
-  virtual L4::Cap icu() const = 0;
-
-  /**
-   * Allocate a MSI vector with the app global MSI allocator.
-   *
-   * \retval >= 0        MSI number at the ICU.
-   * \retval -L4_ENOMEM  Currently, no MSI is available.
-   */
-  virtual long alloc_msi() = 0;
-
-  /// Free a previously allocated MSI vector.
-  virtual void free_msi(unsigned num) = 0;
-
-  /// Maximum number of MSIs at the ICU.
-  virtual unsigned max_msis() const = 0;
-};
-
-inline Allocator::~Allocator() = default;
-
-} } // namespace Vdev::Msi
diff --git a/src/l4/pkg/uvmm/server/src/msi_controller.h b/src/l4/pkg/uvmm/server/src/msi_controller.h
deleted file mode 100644
index c86273d7..00000000
--- a/src/l4/pkg/uvmm/server/src/msi_controller.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2018-2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "pci_device.h"
-#include "device.h"
-#include "vcpu_obj_registry.h"
-
-namespace Gic {
-
-enum : l4_uint32_t
-{
-  Invalid_vsrc_id = 0xffffffffu,
-};
-
-struct Msix_controller : virtual Vdev::Dev_ref
-{
-  virtual ~Msix_controller() = default;
-
-  /// Send MSI-X message to controller.
-  virtual Vcpu_obj_registry *send(l4_uint64_t msix_addr, l4_uint64_t msix_data,
-                                  l4_uint32_t vsrc_id = Invalid_vsrc_id) const = 0;
-};
-
-/**
- * Representation of a virtual source ID and the MSI-X controller at whom the
- * ID is valid.
- *
- * The virtual source ID is added as out-of-band data to each MSI-X message sent
- * to the MSI-X controller.
- */
-class Msix_dest
-{
-public:
-  /**
-   * \param distr    MSI-X controller at whom the virtual source ID is valid,
-   *                 might be nullptr, if the MSI-X source is not assigned to
-   *                 an MSI-X controller.
-   * \param vsrc_id  Virtual source ID that the MSI-X source uses to identify
-   *                 itself to the MSI-X controller.
-   */
-  Msix_dest(cxx::Ref_ptr const &distr, l4_uint32_t vsrc_id)
-  : _distr(distr), _vsrc_id(vsrc_id)
-  {}
-
-  /**
-   * Send MSI-X message.
-   *
-   * \pre MSI-X controller is assigned, see `is_present()`
-   */
-  Vcpu_obj_registry *send_msix(l4_uint64_t msix_addr, l4_uint64_t msix_data) const
-  {
-    return _distr->send(msix_addr, msix_data, _vsrc_id);
-  }
-
-  /**
-   * Return whether an MSI-X controller is assigned.
-   */
-  bool is_present() const
-  {
-    return _distr != nullptr;
-  }
-
-private:
-  cxx::Ref_ptr const &_distr;
-  l4_uint32_t _vsrc_id;
-};
-
-} // namespace Gic
diff --git a/src/l4/pkg/uvmm/server/src/msi_irq_src.h b/src/l4/pkg/uvmm/server/src/msi_irq_src.h
deleted file mode 100644
index c52b7d07..00000000
--- a/src/l4/pkg/uvmm/server/src/msi_irq_src.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2019-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "vcpu_obj_registry.h"
-#include "msi_allocator.h"
-#include "msi_controller.h"
-
-namespace Vdev {
-
-/**
- * Source for an MSI(X) from a vBus to inject into the guest OS.
- */
-template
-class Msi_irq_src
-: public L4::Irqep_t>,
-  public virtual Vdev::Dev_ref
-{
-  /// RAII managed MSI number allocation.
-  struct Msi_num
-  {
-    Msi_num(cxx::Ref_ptr msi_alloc) : msi_alloc(msi_alloc)
-    {
-      // Allocate the number with the vBus ICU
-      num = L4Re::chksys(msi_alloc->alloc_msi(),
-                         "MSI-X vector allocation failed. "
-                         "Please increase the 'Property.num_msis' on vbus.");
-    };
-
-    ~Msi_num() { msi_alloc->free_msi(num); }
-
-    cxx::Ref_ptr msi_alloc;
-    l4_uint32_t num = -1U;
-  };
-
-  /// Managed ICU bind and unbind including MSI number allocation.
-  struct Icu_msi
-  {
-    Icu_msi(cxx::Ref_ptr msi_alloc,
-            L4::Cap icap)
-    : msi_num({msi_alloc})
-    {
-      long label =
-        L4Re::chksys(
-          msi_num.msi_alloc->icu()->bind(msi_num.num | L4_ICU_FLAG_MSI, icap),
-          "Bind MSI-IRQ to vBUS ICU.");
-
-      // Currently, this doesn't happen for MSIs as IO's ICU doesn't manage
-      // them. VMM Failure is not an option, as this is called during guest
-      // runtime. What would be the graceful case?
-      if (label > 0)
-        warn().printf("ICU bind returned %li. Unexpected unmask via vBus ICU "
-                      "necessary.\n", label);
-      irq_cap = icap;
-    }
-
-    ~Icu_msi()
-    {
-      msi_num.msi_alloc->icu()->unbind(msi_num.num | L4_ICU_FLAG_MSI, irq_cap);
-    }
-
-    l4_msgtag_t msi_info(l4_uint64_t src_id, l4_icu_msi_info_t *msiinfo)
-    {
-      return msi_num.msi_alloc->icu()->msi_info(msi_num.num | L4_ICU_FLAG_MSI,
-                                                src_id, msiinfo);
-    }
-
-    L4::Cap irq_cap; // Careful, this is non-owning. Check the
-                                      // lifetime with user object!
-    Msi_num msi_num;
-  };
-
-  template 
-  struct Registration
-  {
-    Registration(Vcpu_obj_registry *reg, T *ep) : registry(reg), irqep(ep)
-    { registry->register_irq_obj(irqep); }
-
-    ~Registration()
-    { registry->unregister_obj(irqep); }
-
-    void retarget(Vcpu_obj_registry *reg)
-    {
-      // Store new registry before moving L4Re interrupt to different thread.
-      // The interrupt might immediately fire on the new thread and race with
-      // the code here...
-      registry = reg;
-      L4Re::chkcap(reg->move_obj(irqep), "Move Msi_irq_src to new registry.");
-  }
-
-    Vcpu_obj_registry *registry;
-    T *irqep;
-  };
-
-public:
-  /**
-   * Construct an MSI source.
-   *
-   * \param msi_alloc    Pointer to a MSI manager, e.g. vBus.
-   * \param msix_dest    MSI controller handling the MSI(X).
-   * \param registry     VCPU local object registry.
-   *
-   * Allocates an MSI vector on the vBus and registers the IRQ object.
-   */
-  Msi_irq_src(cxx::Ref_ptr msi_alloc,
-              Gic::Msix_dest const &msix_dest,
-              Vcpu_obj_registry *registry)
-  : _msix_dest(msix_dest),
-    _registry(registry, this),
-    _icu_msi(msi_alloc, this->obj_cap())
-  {}
-
-  // get MSI info
-  void msi_info(l4_uint64_t src_id, l4_icu_msi_info_t *msiinfo)
-  {
-    L4Re::chksys(_icu_msi.msi_info(src_id, msiinfo),
-                 "Acquire MSI vector information.");
-
-    trace().printf("msi address: 0x%llx, data 0x%x\n", msiinfo->msi_addr,
-                   msiinfo->msi_data);
-  }
-
-  // Implements L4::Irqep_t
-  void handle_irq()
-  {
-    Vcpu_obj_registry *reg = _msix_dest.send_msix(msi_vec()->msi_vec_addr(),
-                                                  msi_vec()->msi_vec_data());
-    if (reg && reg != _registry.registry)
-      _registry.retarget(reg);
-  }
-
-protected:
-  static Dbg trace() { return Dbg(Dbg::Irq, Dbg::Trace, "MSI-IRQ-src"); }
-  static Dbg warn()  { return Dbg(Dbg::Irq, Dbg::Warn,  "MSI-IRQ-src"); }
-
-private:
-  DERIVED *msi_vec()
-  { return static_cast(this); }
-
-  Gic::Msix_dest const _msix_dest;
-  Registration> _registry;
-  Icu_msi _icu_msi;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/msi_memory.h b/src/l4/pkg/uvmm/server/src/msi_memory.h
deleted file mode 100644
index e200895a..00000000
--- a/src/l4/pkg/uvmm/server/src/msi_memory.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2019-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-
-#include "debug.h"
-#include "vcpu_obj_registry.h"
-#include "mem_access.h"
-#include "pci_device.h"
-#include "msix.h"
-#include "msi_allocator.h"
-#include "ds_mmio_handling.h"
-#include "msi_controller.h"
-#include "msi_irq_src.h"
-
-namespace Vdev { namespace Msix {
-
-/**
- * Translates the L4Re interrupt to the MSIx Table entry and send it to
- * the Msix_controller.
- */
-class Msix_src
-: public Msi_irq_src,
-  public virtual Vdev::Dev_ref
-{
-public:
-  explicit Msix_src(cxx::Ref_ptr msi_alloc,
-                    Gic::Msix_dest const &msix_dest,
-                    Vcpu_obj_registry *registry,
-                    Table_entry const *entry)
-  : Msi_irq_src(msi_alloc, msix_dest, registry), _entry(entry)
-  {}
-
-  l4_uint64_t msi_vec_addr() const
-  { return _entry->addr; }
-
-  l4_uint64_t msi_vec_data() const
-  { return _entry->data; }
-
-private:
-  Table_entry const *_entry;
-};
-
-/**
- * MSI-X table emulation.
- *
- * The guest accesses this emulation, when reading from or writing to
- * the device's MSI-X table. If the guest unmasks an MSI-X entry, this
- * emulation configures the MSI routing from the device to the VMM and to
- * the guest.
- */
-class Virt_msix_table : public Vmm::Mmio_device_t
-{
-public:
-  /**
-   * Create a MMIO memory handler for MSI-X table memory.
-   *
-   * \param con          Access to physical device memory.
-   * \param msi_alloc    Pointer to a MSI manager, e.g. vBus.
-   * \param registry     Application-global object registry.
-   * \param src_id       IO-specific source ID of the PCI device.
-   * \param num_entries  Maximum number of device-supported MSI-X entries.
-   * \param msix_ctrl    MSI-X controller for MSI-X address decoding.
-   */
-  Virt_msix_table(cxx::Ref_ptr &&con,
-                  cxx::Ref_ptr msi_alloc,
-                  Vcpu_obj_registry *registry,
-                  l4_uint64_t src_id,
-                  unsigned num_entries,
-                  Gic::Msix_dest const &msix_dest)
-  : _con(std::move(con)),
-    _registry(registry),
-    _msi_alloc(msi_alloc),
-    _msi_irqs(num_entries),
-    _src_id(src_id),
-    _msix_dest(msix_dest),
-    _virt_table(cxx::make_unique(num_entries))
-  {}
-
-  /// Read from the emulated MSI-X memory.
-  l4_umword_t read(unsigned reg, char size, unsigned) const
-  {
-    // In case of the vector control, we need to ensure earlier writes reached
-    // the device, hence, we read.
-    if (is_entry_control(reg, size))
-      _con->read(reg, size);
-
-    return Vmm::Mem_access::read_width(
-             reinterpret_cast(_virt_table.get()) + reg, size);
-  }
-  /// Write to the emulated MSI-X memory.
-  void write(unsigned reg, char size, l4_umword_t value, unsigned)
-  {
-    trace().printf("PASS_THROUGH_MEM: write @ 0x%x (0x%x): 0x%lx\n",
-                   reg, size, value);
-
-    Vmm::Mem_access::write_width(
-      reinterpret_cast(_virt_table.get()) + reg, value, size);
-
-    // Handle MSI-X table access
-    if (is_entry_unmask(reg, size, value))
-      conf_msix_entry(reg_to_entry(reg));
-    else if (is_entry_mask(reg, size, value))
-      msi_entry_mask_ctrl(reg_to_entry(reg), true);
-    // else: PCIe brings TPH Requester fields for vector control.
-  }
-
-  char const *dev_name() const override { return "Virt_msix_table"; }
-
-protected:
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "PassThrough"); }
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "PassThrough"); }
-
-private:
-  /// MSI-X table access to the vector control DWORD.
-  static bool is_entry_control(unsigned reg, char size)
-  {
-    enum { Entry_ctrl_offset = 12 };
-
-    return    ((reg % Entry_size) == Entry_ctrl_offset)
-           && (size == Vmm::Mem_access::Wd32);
-  }
-
-  /// Access clears the mask bit in the vector control.
-  static bool is_entry_unmask(unsigned reg, char size, l4_umword_t value)
-  {
-    return    is_entry_control(reg, size)
-           && (value & Vector_ctrl_mask_bit) == 0;
-  }
-
-  /// Access sets the mask bit in the vector control.
-  static bool is_entry_mask(unsigned reg, char size, l4_umword_t value)
-  {
-    return    is_entry_control(reg, size)
-           && (value & Vector_ctrl_mask_bit);
-  }
-
-  /// Convert the register access to the entry number.
-  static unsigned reg_to_entry(unsigned reg)
-  {
-    return reg / Entry_size;
-  }
-
-  /// Mask MSI-X entry on device.
-  void msi_entry_mask_ctrl(unsigned idx, bool mask) const
-  {
-    enum { Vector_offset = 12 };
-
-    trace().printf("%s MSI-X entry %u\n", mask ? "masking" : "unmasking", idx);
-
-    unsigned reg = idx * Entry_size + Vector_offset;
-    l4_umword_t val = _con->read(reg, Vmm::Mem_access::Wd32);
-
-    if (mask)
-      val |= Vector_ctrl_mask_bit;
-    else
-      val &= ~Vector_ctrl_mask_bit;
-
-    _con->write(reg, Vmm::Mem_access::Wd32, val);
-  }
-
-  /// Write device's MSI-X entry.
-  void write_dev_msix_entry(unsigned idx, l4_icu_msi_info_t const &info) const
-  {
-    unsigned entry_off = idx * Entry_size;
-    unsigned width = 1U << Vmm::Mem_access::Wd32;
-
-    _con->write(entry_off, Vmm::Mem_access::Wd32, info.msi_addr & 0xffffffffU);
-
-    entry_off += width;
-    _con->write(entry_off, Vmm::Mem_access::Wd32, info.msi_addr >> 32);
-
-    entry_off += width;
-    _con->write(entry_off, Vmm::Mem_access::Wd32, info.msi_data);
-
-    entry_off += width;
-    _con->write(entry_off, Vmm::Mem_access::Wd32, 0U);
-  }
-
-  /// True; iff the MSI route was already configured, but masked.
-  bool reconfigure(unsigned idx) const
-  {
-    // Check for reconfiguration or entry unmask
-    trace().printf("check for reconfiguration\n");
-
-    if (!_msi_irqs[idx])
-      return false;
-
-    // If the entry is present, we just unmask the entry on the device.
-    trace().printf("reconfiguring\n");
-    msi_entry_mask_ctrl(idx, false);
-
-    return true;
-  }
-
-  /// Parse MSI-X entry and configure the route.
-  void conf_msix_entry(unsigned idx)
-  {
-    // If this is a reconfiguration do not configure the device again.
-    if (!reconfigure(idx))
-      configure_msix_route(idx);
-  }
-
-  /**
-   * Configure the device's MSI-X entry and the interrupt route to inject into
-   * the guest.
-   */
-  void configure_msix_route(unsigned idx)
-  {
-    if (!_msix_dest.is_present())
-      {
-        warn().printf("No MSI-X controller! Entry %u not routed to guest.\n",
-                      idx);
-        return;
-      }
-
-    // guard against multiple threads accessing the Msi_allocator and the
-    // capability allocator
-    std::lock_guard lock(_mutex);
-
-    Table_entry const *entry = &_virt_table[idx];
-
-    trace().printf("Configure MSI-X entry number %u for entry (0x%llx, 0x%x)\n",
-                   idx, entry->addr, entry->data);
-
-    // allocate IRQ object and bind it to the ICU
-    auto msi_src = Vdev::make_device(_msi_alloc, _msix_dest,
-                                               _registry, entry);
-
-    // get MSI info
-    l4_icu_msi_info_t msiinfo;
-    msi_src->msi_info(_src_id, &msiinfo);
-
-    // write to device memory
-    write_dev_msix_entry(idx, msiinfo);
-
-    // unmask the MSI-IRQ
-    L4Re::chkipc(msi_src->obj_cap()->unmask(), "Unmask MSI-IRQ.");
-    _msi_irqs[idx] = msi_src;
-  }
-
-  cxx::Ref_ptr _con;
-  Vcpu_obj_registry *_registry;
-  cxx::Ref_ptr _msi_alloc;
-  std::vector> _msi_irqs;
-  l4_uint64_t const _src_id;
-  Gic::Msix_dest _msix_dest;
-  cxx::unique_ptr _virt_table;
-  std::mutex _mutex;
-}; // class Virt_msix_table
-
-} } // namespace Vdev::Msix
diff --git a/src/l4/pkg/uvmm/server/src/msix.h b/src/l4/pkg/uvmm/server/src/msix.h
deleted file mode 100644
index 64096e04..00000000
--- a/src/l4/pkg/uvmm/server/src/msix.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-/**
- * \file MSI-X structures and constants
- */
-
-namespace Vdev { namespace Msix {
-
-enum Table_entry_const
-{
-  Vector_ctrl_mask_bit = 0x1,
-  Entry_size = 16,      // entry size in bytes: 4 DWORDs.
-};
-
-struct Table_entry
-{
-  /* The structure defined in the PCI spec V.3.0 is as follows:
-   * Each table entry consists of four DWORDs (32 bits), overall 128 bits.
-   * [    127:96     |     95:64    |        63:32      |       31:0      ]
-   * [Vector control | Message Data | Message Addr high | Message Addr low]
-   */
-  l4_uint64_t addr = 0;
-  l4_uint32_t data = 0;
-  l4_uint32_t vector_ctrl;
-
-  Table_entry() : vector_ctrl(Vector_ctrl_mask_bit) {}
-
-  /// True if the entry is masked.
-  bool masked() const { return vector_ctrl & Vector_ctrl_mask_bit; }
-  void mask() { vector_ctrl |= Vector_ctrl_mask_bit; }
-  void unmask() { vector_ctrl &= ~Vector_ctrl_mask_bit; }
-
-  /// Print entry
-  void dump() const
-  {
-    Dbg().printf("Addr 0x%llx, Data 0x%x, ctrl 0x%x\n", addr, data, vector_ctrl);
-  }
-};
-static_assert(sizeof(Table_entry) == 16,
-              "MSI-X table entry size conforms to specification.");
-
-inline size_t msix_table_mem_size(unsigned max_msix_entries)
-{
-  return l4_round_page(sizeof(Table_entry) * max_msix_entries);
-};
-
-inline size_t msix_table_pba_mem_size(unsigned max_msix_entries)
-{
-  return msix_table_mem_size(max_msix_entries) + L4_PAGESIZE;
-};
-
-} } // namespace Vdev::Msix
diff --git a/src/l4/pkg/uvmm/server/src/msr_device.h b/src/l4/pkg/uvmm/server/src/msr_device.h
deleted file mode 100644
index 44a310d0..00000000
--- a/src/l4/pkg/uvmm/server/src/msr_device.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2018-2019, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "device.h"
-
-namespace Vmm {
-
-/**
- * Interface for devices containing MSRs visible to the VM.
- */
-struct Msr_device : virtual Vdev::Dev_ref
-{
-  virtual ~Msr_device() = 0;
-
-  /**
-   * Read from a MSR of the specified vCPU.
-   *
-   * \param msr         Number of the MSR to read.
-   * \param value[out]  Pointer to the memory to read into.
-   * \param vcpu_no     Number of the vCPU to read from.
-   *
-   * The vCPU number passed is of an existing vCPU.
-   */
-  virtual bool read_msr(unsigned msr, l4_uint64_t *value,
-                        unsigned vcpu_no) const = 0;
-  /**
-   * Write to a MSR of the specificed vCPU.
-   *
-   * \param msr      Number of the MSR to write to.
-   * \param value    Value to write to the MSR.
-   * \param vcpu_no  Number of the vCPU to write to.
-   *
-   * The vCPU number passed is of an existing vCPU.
-   */
-  virtual bool write_msr(unsigned msr, l4_uint64_t value, unsigned vcpu_no) = 0;
-};
-
-inline Msr_device::~Msr_device() = default;
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/pci_device.cc b/src/l4/pkg/uvmm/server/src/pci_device.cc
deleted file mode 100644
index be4ea700..00000000
--- a/src/l4/pkg/uvmm/server/src/pci_device.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2021-2024 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "guest.h"
-#include "pci_device.h"
-
-namespace Vdev { namespace Pci {
-
-bool Pci_device::cfg_read_bar(unsigned reg, l4_uint32_t *value,
-                              Vmm::Mem_access::Width width)
-{
-  bool type0 = get_header_type() == Pci_header_type::Type0;
-  if (!is_bar_reg(type0, reg))
-    return false;
-
-  unsigned bar = (reg - Pci_hdr_base_addr0_offset) >> 2;
-  *value = 0;
-
-  // only naturally aligned accesses are allowed
-  if (L4_UNLIKELY(reg & ((1UL << width) - 1U)))
-    return true;
-
-  unsigned expansion_rom = expansion_rom_reg(type0);
-  if (reg >= expansion_rom && reg <= expansion_rom + 3)
-    {
-      l4_uint64_t regval = exp_rom.map_addr | exp_rom.virt_enabled;
-      if (width > Vmm::Mem_access::Wd32)
-        {
-          warn().printf("Unsupported 64-bit read of expansion ROM register! Diminishing width.\n");
-          width = Vmm::Mem_access::Wd32;
-        }
-
-      *value = Vmm::Mem_access::read_width(reinterpret_cast(®val),
-                                           width);
-      return true;
-    }
-
-  // only read one bar per access
-  if (width > Vmm::Mem_access::Wd32)
-    warn().printf("Unsupported 64-bit read of BAR[%u] register!\n", bar);
-
-  l4_uint64_t regval = get_bar_regval(bar);
-  *value = Vmm::Mem_access::read_width(reinterpret_cast(®val),
-                                       width);
-
-  return true;
-}
-
-l4_uint32_t Pci_device::get_bar_regval(unsigned bar) const
-{
-  assert(bar < sizeof(bars) / sizeof(bars[0]));
-
-  switch (bars[bar].type)
-    {
-    case Pci_cfg_bar::Unused_empty:
-      return 0;
-    case Pci_cfg_bar::Reserved_mmio64_upper:
-      assert(bar > 0);
-      return bars[bar-1U].map_addr >> 32;
-    case Pci_cfg_bar::MMIO32:
-      return static_cast(bars[bar].map_addr)
-              | Bar_mem_type_32bit
-              | (bars[bar].prefetchable ? Bar_mem_prefetch_bit
-                                        : Bar_mem_non_prefetch_bit);
-    case Pci_cfg_bar::MMIO64:
-      return static_cast(bars[bar].map_addr)
-              | Bar_mem_type_64bit
-              | (bars[bar].prefetchable ? Bar_mem_prefetch_bit
-                                        : Bar_mem_non_prefetch_bit);
-    case Pci_cfg_bar::IO:
-      return static_cast(bars[bar].map_addr)
-              | Bar_io_space_bit;
-    }
-
-  return 0;
-}
-
-void Pci_device::write_exp_rom_regval(l4_uint32_t value)
-{
-  if (exp_rom.virt_enabled && (enabled_decoders & Memory_space_bit))
-    del_exp_rom_resource();
-
-  exp_rom.virt_enabled = value & Pci_expansion_rom_bar::Enable_bit;
-  exp_rom.map_addr = value & ~(exp_rom.size - 1U);
-
-  if (exp_rom.virt_enabled)
-    {
-      if (enabled_decoders & Memory_space_bit)
-        add_exp_rom_resource();
-
-      if (!exp_rom.hw_enabled)
-        {
-          // unless the HW reported the expansion ROM BAR as enabled, we
-          // enable it to allow the guest to access it. Currenlty, we don't
-          // disable expansion ROM BAR decoding again.
-          unsigned rom_reg =
-            expansion_rom_reg(get_header_type() == Pci_header_type(0));
-          cfg_write_raw(rom_reg,
-                        exp_rom.io_addr | Pci_expansion_rom_bar::Enable_bit,
-                        Vmm::Mem_access::Wd32);
-          exp_rom.hw_enabled = true;
-        }
-    }
-
-  trace()
-    .printf("wrote to expansion rom register: map_addr: 0x%llx, raw: 0x%llx\n",
-            exp_rom.map_addr | exp_rom.virt_enabled ,
-            exp_rom.io_addr | exp_rom.hw_enabled);
-}
-
-bool Pci_device::cfg_write_bar(unsigned reg, l4_uint32_t value,
-                               Vmm::Mem_access::Width width)
-{
-  bool type0 = get_header_type() == Pci_header_type::Type0;
-  if (!is_bar_reg(type0, reg))
-    return false;
-
-  // only naturally aligned accesses are allowed
-  if (L4_UNLIKELY(reg & ((1UL << width) - 1U)))
-    return true;
-
-  unsigned expansion_rom = expansion_rom_reg(type0);
-  if (reg >= expansion_rom && reg <= expansion_rom + 3)
-    {
-      write_exp_rom_regval(value);
-      return true;
-    }
-
-  unsigned bar = (reg - Pci_hdr_base_addr0_offset) >> 2;
-  if (width != Vmm::Mem_access::Wd32)
-    {
-      warn().printf("Ignored non 32-bit write of BAR[%u] register\n", bar);
-      return true;
-    }
-
-  update_bar(bar, value);
-  return true;
-}
-
-void Pci_device::update_bar(unsigned bar, l4_uint32_t value)
-{
-  assert(bar < sizeof(bars) / sizeof(bars[0]));
-
-  switch (bars[bar].type)
-    {
-    case Pci_cfg_bar::Unused_empty:
-      break;
-    case Pci_cfg_bar::Reserved_mmio64_upper:
-    case Pci_cfg_bar::MMIO32:
-    case Pci_cfg_bar::MMIO64:
-      if (enabled_decoders & Memory_space_bit)
-        {
-          info().printf(
-            "Ignore update of BAR[%u] while MMIO decoding is enabled.\n", bar);
-          return;
-        }
-      break;
-    case Pci_cfg_bar::IO:
-      if (enabled_decoders & Io_space_bit)
-        {
-          info().printf(
-            "Ignore update of BAR[%u] while IO decoding is enabled.\n", bar);
-          return;
-        }
-      break;
-    }
-
-  // The BAR size (power of 2!) defines which bits are writable.
-  switch (bars[bar].type)
-    {
-    case Pci_cfg_bar::Unused_empty:
-      break;
-    case Pci_cfg_bar::Reserved_mmio64_upper:
-      {
-        assert(bar > 0);
-        l4_uint64_t mask = ~bars[bar-1U].size + 1U;
-        bars[bar-1U].map_addr &= 0xffffffffULL;
-        bars[bar-1U].map_addr |= (static_cast(value) << 32) & mask;
-        break;
-      }
-    case Pci_cfg_bar::MMIO32:
-      {
-        l4_uint32_t mask = ~bars[bar].size + 1U;
-        bars[bar].map_addr = value & mask;
-        break;
-      }
-    case Pci_cfg_bar::MMIO64:
-      {
-        l4_uint64_t mask = ~bars[bar].size + 1U;
-        bars[bar].map_addr &= ~0xffffffffULL;
-        bars[bar].map_addr |= value & mask;
-        break;
-      }
-    case Pci_cfg_bar::IO:
-      {
-        l4_uint32_t mask = (~bars[bar].size + 1U) & 0xffffU;
-        bars[bar].map_addr = value & mask;
-        break;
-      }
-    }
-}
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/pci_device.h b/src/l4/pkg/uvmm/server/src/pci_device.h
deleted file mode 100644
index ea89db69..00000000
--- a/src/l4/pkg/uvmm/server/src/pci_device.h
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*
- * Copyright (C) 2018-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "mem_access.h"
-#include "device.h"
-#include "msix.h"
-#include "mmio_device.h"
-#include "io_device.h"
-
-#include 
-
-namespace Vmm {
-  class Guest;
-}
-
-namespace Vdev { namespace Pci {
-
-enum Pci_status_register
-{
-  // see PCI Local Bus Specification V.3 (2004) Section 6.2.3 Device Status
-  Interrupt_status_bit = 1U << 3,
-  Capability_list_bit  = 1U << 4,
-};
-
-enum Pci_command_register : l4_uint16_t
-{
-  Io_space_bit = 1U,
-  Memory_space_bit = 1U << 1,
-  Access_mask = Io_space_bit | Memory_space_bit,
-  Bus_master_bit = 1U << 2,
-  Interrupt_disable_bit = 1U << 10,
-};
-
-enum Pci_header_type_register
-{
-  Multi_func_bit = (1U << 7),
-};
-
-enum Pci_header_type
-{
-  Type0 = 0,
-  Type1 = 1,
-  Type2 = 2
-};
-
-enum Pci_config_consts
-{
-  Pci_header_size = 0x100,
-  // see PCI Local Bus Specification V.3 (2004) Section 6
-  Bar_type_mask = 0x1,
-  Bar_io_space_bit = 0x1,
-  Bar_io_attr_mask = 0x3,
-  Bar_mem_type_mask = 0x7,
-  Bar_mem_type_32bit = 0x0,      /// type bits[2:1] 00 = 32bit
-  Bar_mem_type_64bit = 0x1 << 2, /// type bits[2:1] 10 = 64bit
-  Bar_mem_attr_mask = 0xf,
-  Bar_mem_prefetch_bit = 0x8,
-  Bar_mem_non_prefetch_bit = 0x0,
-  Bar_num_max_type0 = 6,
-  Bar_num_max_type1 = 2,
-  Interrupt_line_unknown = 255,
-  Interrupt_pin_unused = 0,
-};
-
-/**
- * PCI BAR configuration.
- *
- * Internal representation of a PCI base address register (BAR) configuration.
- * For 64 bit BARs the lower structure holds the full address and the upper
- * structure is reserved.
- */
-struct Pci_cfg_bar
-{
-  enum Type
-  {
-    Unused_empty, /// Not used
-    Reserved_mmio64_upper,  /// Reserved for upper word of previous MMIO64
-    MMIO32, /// 32bit MMIO
-    MMIO64, /// 64bit MMIO
-    IO      /// IO space
-  };
-
-  l4_uint64_t io_addr = 0;  /// Address used by IO
-  l4_uint64_t map_addr = 0; /// Address to use for the guest mapping
-  l4_uint64_t size = 0;       /// Size of the region
-  Type type = Unused_empty;       /// Type of the BAR
-  bool prefetchable = false;  /// Prefetchable MMIO region?
-
-  char const *to_string() const
-  {
-    switch(type)
-    {
-      case IO: return "io";
-      case MMIO32: return prefetchable ? "mmio32 (prefetchable)"
-                                       : "mmio32 (non-prefetchable)";
-      case MMIO64: return prefetchable ? "mmio64 (prefetchable)"
-                                       : "mmio64 (non-prefetchable)";
-      default: return "unused";
-    }
-  }
-  // for user: get address type dependent
-  // auto addr =
-  //  (type == MMIO64) ? addr : (l4_uint32_t)(addr && 0xffffffff);
-};
-
-/**
- * PCI expansion ROM Bar description.
- */
-struct Pci_expansion_rom_bar
-{
-  l4_uint64_t io_addr = 0;
-  l4_uint64_t size = 0;
-  l4_uint64_t map_addr = 0;
-  bool hw_enabled = false;
-  bool virt_enabled = false;
-
-  enum { Enable_bit = 1 };
-};
-
-enum Cap_ident : l4_uint8_t
-{
-  // see PCI Local Bus Specification V.3 (2004) Appendix H.
-  Power_management = 0x1,
-  Msi = 0x5,
-  Vendor_specific = 0x9,
-  Pcie = 0x10,
-  Msi_x = 0x11,
-};
-
-enum Ext_cap_ident : l4_uint16_t
-{
-  Sr_iov = 0x0010,
-};
-
-enum Pci_cap_mask : l4_uint8_t
-{
-  Next_cap = 0xfc, // Lowest two bits of the pointer to the
-                   // next capability are reserved
-  Cap_id   = 0xff, // Capability ID
-};
-
-enum
-{
-  // see PCI Local Bus Specification V.3 (2004) Section 6.1 and PCI-to-PCI
-  // Bridge Architecture Specification Revision 1.1 Section 3.2
-  Pci_hdr_vendor_id_offset = 0x0,
-  Pci_hdr_device_id_offset = 0x2,
-  Pci_hdr_command_offset = 0x4,
-  Pci_hdr_command_length = 0x10,
-  Pci_hdr_status_offset = 0x6,
-  Pci_hdr_status_length = 0x10,
-  Pci_hdr_revision_id_offset = 0x8,
-  Pci_hdr_classcode_offset = 0x9,
-  Pci_hdr_cacheline_size_offset = 0xc,
-  Pci_hdr_latency_timer_offset = 0xd,
-  Pci_hdr_type_offset = 0xe,
-  Pci_hdr_bist_offset = 0xf,
-  Pci_hdr_base_addr0_offset = 0x10,
-  Pci_hdr_base_addr1_offset = 0x14,
-  Pci_hdr_capability_offset = 0x34,
-  Pci_hdr_interrupt_line_offset = 0x3c,
-  Pci_hdr_interrupt_pin_offset = 0x3d,
-  Pci_hdr_interrupt_pin_min = 0x1,
-  Pci_hdr_interrupt_pin_max = 0x4,
-
-  Pci_hdr_type0_base_addr0_offset = Pci_hdr_base_addr0_offset,
-  Pci_hdr_type0_base_addr1_offset = Pci_hdr_base_addr1_offset,
-  Pci_hdr_type0_base_addr2_offset = 0x18,
-  Pci_hdr_type0_base_addr3_offset = 0x1c,
-  Pci_hdr_type0_base_addr4_offset = 0x20,
-  Pci_hdr_type0_base_addr5_offset = 0x24,
-  Pci_hdr_type0_card_bus_offset = 0x28,
-  Pci_hdr_type0_subsystem_vendor_id_offset = 0x2c,
-  Pci_hdr_type0_subsystem_id_offset = 0x2e,
-  Pci_hdr_type0_expansion_rom_offset = 0x30,
-  Pci_hdr_type0_capability_offset = Pci_hdr_capability_offset,
-  Pci_hdr_type0_interrupt_line_offset = Pci_hdr_interrupt_line_offset,
-  Pci_hdr_type0_interrupt_pin_offset = Pci_hdr_interrupt_pin_offset,
-  Pci_hdr_type0_interrupt_pin_max = Pci_hdr_interrupt_pin_max,
-  Pci_hdr_type0_min_time_offset = 0x3e,
-  Pci_hdr_type0_max_latency_offset = 0x3f,
-
-  Pci_hdr_type1_base_addr0_offset = Pci_hdr_base_addr0_offset,
-  Pci_hdr_type1_base_addr1_offset = Pci_hdr_base_addr1_offset,
-  Pci_hdr_type1_primary_bus_offset = 0x18,
-  Pci_hdr_type1_secondary_bus_offset = 0x19,
-  Pci_hdr_type1_subordinate_bus_offset = 0x1a,
-  Pci_hdr_type1_secondary_latency_offset = 0x1b,
-  Pci_hdr_type1_io_base_offset = 0x1c,
-  Pci_hdr_type1_io_limit_offset = 0x1d,
-  Pci_hdr_type1_secondary_status_offset = 0x1e,
-  Pci_hdr_type1_memory_base_offset = 0x20,
-  Pci_hdr_type1_memory_limit_offset = 0x22,
-  Pci_hdr_type1_prefetchable_memory_base_offset = 0x24,
-  Pci_hdr_type1_prefetchable_memory_limit_offset = 0x26,
-  Pci_hdr_type1_prefetchable_base_upper_offset = 0x28,
-  Pci_hdr_type1_prefetchable_limit_upper_offset = 0x2c,
-  Pci_hdr_type1_io_base_upper_offset = 0x30,
-  Pci_hdr_type1_io_limit_upper_offset = 0x32,
-  Pci_hdr_type1_capabilities_offset = Pci_hdr_capability_offset,
-  Pci_hdr_type1_expansion_rom_offset = 0x38,
-  Pci_hdr_type1_interrupt_line_offset = Pci_hdr_interrupt_line_offset,
-  Pci_hdr_type1_interrupt_pin_offset = Pci_hdr_interrupt_pin_offset,
-  Pci_hdr_type1_interrupt_pin_max = Pci_hdr_interrupt_pin_max,
-  Pci_hdr_type1_bridge_control_offset = 0x3e,
-};
-
-enum : l4_uint8_t
-{
-  Pci_class_code_mass_storage_device = 0x01,
-  Pci_class_code_network_device = 0x02,
-  Pci_class_code_display_device = 0x03,
-  Pci_class_code_multimedia_device = 0x04,
-  Pci_class_code_memory_device = 0x05,
-  Pci_class_code_bridge_device = 0x06,
-  Pci_class_code_communication_device = 0x07,
-  Pci_class_code_system_peripheralls_device = 0x08,
-  Pci_class_code_input_device = 0x09,
-  Pci_class_code_docking_station_device = 0x0a,
-  Pci_class_code_processors_device = 0x0b,
-  Pci_class_code_serial_bus_device = 0x0c,
-  Pci_class_code_wireless_device = 0x0d,
-  Pci_class_code_io_device = 0x0e,
-  Pci_class_code_satellite_device = 0x0f,
-  Pci_class_code_crypt_device = 0x10,
-  Pci_class_code_signal_device = 0x11,
-  Pci_class_code_accelerator_device = 0x12,
-  Pci_class_code_instrument_device = 0x13,
-  Pci_class_code_other_device = 0x80,
-  Pci_class_code_unknown_device = 0xff,
-};
-
-enum : l4_uint8_t
-{
-  Pci_subclass_code_host = 0x00,
-};
-
-enum : l4_uint16_t
-{
-  Pci_invalid_vendor_id = 0xffff,
-};
-
-enum
-{
-  Pci_header_status_capability_bit = (1UL << 4),
-};
-
-/// Base class of a PCI capability.
-struct Pci_cap
-{
-  explicit Pci_cap(l4_uint8_t type) : cap_type(type) {}
-
-  /**
-   * Perform a cast if the input cap `c` is of the expected type `T`.
-   *
-   * \tparam T  The expected PCI capability type.
-   * \param  c  The capability to cast.
-   *
-   * \returns A valid capability pointer if the type is correct; nullptr
-   *          otherwise.
-   */
-  template 
-  static T *
-  cast_type(Pci_cap *c)
-  {
-    return c->cap_type == T::Cap_id ? static_cast(c) : nullptr;
-  }
-
-  // see PCI Local Bus Specification V.3 (2010) 6.8.2.
-  l4_uint8_t const cap_type;
-  l4_uint8_t cap_next = 0;
-};
-
-/// Class for all vendor specific PCI capabilities.
-struct Vendor_specific_cap : Pci_cap
-{
-  enum : l4_uint8_t { Cap_id = Cap_ident::Vendor_specific };
-
-  explicit Vendor_specific_cap(l4_uint8_t len)
-  : Pci_cap(Cap_id), cap_len(len)
-  {}
-
-  l4_uint8_t cap_len;
-};
-static_assert(sizeof(Vendor_specific_cap) == 3,
-              "Vendor_specific_cap size conforms to specification.");
-
-/// MSI-X capability for the PCI config space.
-struct Pci_msix_cap : Pci_cap
-{
-  enum : l4_uint8_t { Cap_id = Cap_ident::Msi_x };
-
-  Pci_msix_cap() : Pci_cap(Cap_id) {}
-
-  struct
-  {
-    l4_uint16_t raw;
-    CXX_BITFIELD_MEMBER(15, 15, enabled, raw);
-    CXX_BITFIELD_MEMBER(14, 14, masked, raw);
-    CXX_BITFIELD_MEMBER(0, 10, max_msis, raw);
-  } ctrl;
-
-  struct Offset_bir
-  {
-    l4_uint32_t raw;
-    CXX_BITFIELD_MEMBER_UNSHIFTED(3, 31, offset, raw);
-    CXX_BITFIELD_MEMBER(0, 2, bir, raw);
-  };
-  Offset_bir tbl;
-  Offset_bir pba;
-};
-static_assert(sizeof(Pci_msix_cap) == 12,
-              "Pci_msix_cap size conforms to specification.");
-
-/// MSI capability for PCI
-struct Pci_msi_cap : Pci_cap
-{
-  enum : l4_uint8_t { Cap_id = Cap_ident::Msi };
-
-  Pci_msi_cap() : Pci_cap(Cap_id) {}
-
-  struct
-  {
-    l4_uint16_t raw;
-    CXX_BITFIELD_MEMBER(8, 8, per_vector_masking, raw);
-    CXX_BITFIELD_MEMBER(7, 7, sixtyfour, raw);
-    CXX_BITFIELD_MEMBER(4, 6, multiple_message_enable, raw);
-    CXX_BITFIELD_MEMBER(1, 3, multiple_message_capable, raw);
-    CXX_BITFIELD_MEMBER(0, 0, msi_enable, raw);
-  } ctrl;
-
-  l4_uint32_t address = 0;
-  l4_uint16_t data = 0;
-  // optional, depends on ctrl.sixtyfour()
-  l4_uint32_t upper_address = 0;
-  unsigned offset = 0; // the offset into the devices config space
-
-  void write_ctrl(l4_uint16_t val)
-  {
-    static l4_uint16_t const ro_mask = 0xff8e;
-    static l4_uint16_t const wr_mask = 0x0071;
-
-    ctrl.raw = (ctrl.raw & ro_mask) | (val & wr_mask);
-  };
-
-  l4_uint64_t addr() const
-  {
-    l4_uint64_t addr = address;
-    if (ctrl.sixtyfour())
-      addr |= static_cast(upper_address) << 32;
-    return addr;
-  }
-
-  unsigned cap_end() const
-  {
-    if (ctrl.sixtyfour() && ctrl.per_vector_masking())
-      return offset + 0x18;
-    if (ctrl.sixtyfour())
-      return offset + 0xe;
-    if (ctrl.per_vector_masking())
-      return offset + 0x14;
-    return offset + 0xa;
-  }
-};
-
-struct Pcie_cap_header
-{
-  enum : l4_uint32_t
-  {
-    Next_cap_mask = 0xffc, // Lowest two bits of the pointer to the
-                           // next capability are reserved
-  };
-
-  l4_uint32_t raw;
-  CXX_BITFIELD_MEMBER(20, 31, next_cap, raw);
-  CXX_BITFIELD_MEMBER(15, 19, version, raw);
-  CXX_BITFIELD_MEMBER(0, 15, id, raw);
-};
-
-/// SR-IOV capability for PCIe
-struct Pcie_sriov_cap
-{
-  unsigned offset = 0; // the offset into the device's config space
-
-  unsigned cap_end() const
-  { return offset + 0x40; }
-};
-
-union alignas(sizeof(l4_uint64_t)) Pci_header
-{
-  l4_uint8_t byte[Pci_header_size];
-  l4_uint16_t word[Pci_header_size / 2];
-  l4_uint32_t dword[Pci_header_size / 4];
-  l4_uint64_t qword[Pci_header_size / 8];
-
-  struct Type0
-  {
-    l4_uint16_t vendor_id;
-    l4_uint16_t device_id;
-    l4_uint16_t command;
-    l4_uint16_t status;
-    l4_uint8_t revision_id;
-    l4_uint8_t classcode[3];
-    l4_uint8_t cachline_size;
-    l4_uint8_t latency_timer;
-    l4_uint8_t header_type;
-    l4_uint8_t bist;
-    l4_uint32_t base_addr_regs[Bar_num_max_type0];
-    l4_uint32_t cardbus_ptr;
-    l4_uint16_t subsystem_vendor;
-    l4_uint16_t subsystem_id;
-    l4_uint32_t expansion_rom_base;
-    l4_uint8_t cap_ptr;
-    l4_uint8_t _reserved0[3];
-    l4_uint32_t _reserved1;
-    l4_uint8_t int_line;
-    l4_uint8_t int_pin;
-    l4_uint8_t min_gnt;
-    l4_uint8_t max_lat;
-    unsigned char cfg_space[192]; // (0x100 - 0x40)
-  };
-
-  struct Type1
-  {
-    l4_uint16_t vendor_id;
-    l4_uint16_t device_id;
-    l4_uint16_t command;
-    l4_uint16_t status;
-    l4_uint8_t revision_id;
-    l4_uint8_t classcode[3];
-    l4_uint8_t cachline_size;
-    l4_uint8_t latency_timer;
-    l4_uint8_t header_type;
-    l4_uint8_t bist;
-    l4_uint32_t base_addr_regs[Bar_num_max_type1];
-    l4_uint8_t primary_bus_num;
-    l4_uint8_t secondary_bus_num;
-    l4_uint8_t subordinate_bus_num;
-    l4_uint8_t secondary_latency_timer;
-    l4_uint8_t io_base;
-    l4_uint8_t io_limit;
-    l4_uint16_t secondary_status;
-    l4_uint16_t mem_base;
-    l4_uint16_t mem_limit;
-    l4_uint16_t prefetch_mem_base;
-    l4_uint16_t prefetch_mem_limit;
-    l4_uint32_t prefetch_mem_base_upper32;
-    l4_uint32_t prefetch_mem_limit_upper32;
-    l4_uint16_t io_base_upper16;
-    l4_uint16_t io_limit_upper16;
-    l4_uint8_t cap_ptr;
-    l4_uint8_t _reserved[3];
-    l4_uint32_t exp_rom_base_addr;
-    l4_uint8_t int_line;
-    l4_uint8_t int_pin;
-    l4_uint16_t bridge_ctrl;
-    unsigned char cfg_space[192]; // (0x100 - 0x40)
-  };
-};
-
-static_assert(   sizeof(Pci_header::Type0) == sizeof(Pci_header)
-              && sizeof(Pci_header::Type1) == sizeof(Pci_header),
-              "Pci_header and Pci_header::Type sizes differ.");
-
-struct Pci_device : public virtual Vdev::Dev_ref
-{
-  virtual ~Pci_device() = default;
-
-  virtual void cfg_write_raw(unsigned reg, l4_uint32_t value,
-                             Vmm::Mem_access::Width width) = 0;
-  virtual void cfg_read_raw(unsigned reg, l4_uint32_t *value,
-                            Vmm::Mem_access::Width width) = 0;
-
-  /**
-   * Go through all resources of the PCI device and register them with the
-   * memmap or iomap.
-   *
-   * \param vmm The guest where the device is mapped
-   * \param access Resources to be added (Io_space_bit | Memory_space_bit)
-   */
-  virtual void add_decoder_resources(Vmm::Guest *vmm, l4_uint32_t access) = 0;
-
-  /**
-   * Go through all resources of the PCI device and remove them from the memmap
-   * or iomap.
-   *
-   * \param vmm The guest where the device is mapped
-   * \param access Resources to be removed (Io_space_bit | Memory_space_bit)
-   */
-  virtual void del_decoder_resources(Vmm::Guest *vmm, l4_uint32_t access) = 0;
-
-  virtual void add_exp_rom_resource() = 0;
-  virtual void del_exp_rom_resource() = 0;
-
-  /*
-   * Get source ID.
-   *
-   * Return a source_id compatible with IO.
-   */
-  virtual l4_uint64_t src_id() const
-  { return 0U; }
-
-  /*
-   * Enable access to the PCI device.
-   *
-   * \param access  The MMIO/IO space configuration bits to enable
-   */
-  void enable_access(l4_uint32_t access)
-  {
-    l4_uint32_t cmd_reg = 0;
-    cfg_read_raw(Pci_hdr_command_offset, &cmd_reg, Vmm::Mem_access::Wd16);
-    // Reenable bar access
-    cfg_write_raw(Pci_hdr_command_offset, cmd_reg | (access & Access_mask),
-                  Vmm::Mem_access::Wd16);
-  }
-
-  /*
-   * Disable access to the PCI device.
-   *
-   * The current configuration will be returned and has to be passed to the
-   * enabled_access function to restore the correct configuration when
-   * enabling the device again.
-   *
-   * \param access  The MMIO/IO space configuration bits to disable
-   *
-   * \return The current MMIO/IO space configuration bits
-   */
-  l4_uint32_t disable_access(l4_uint32_t access)
-  {
-    // Disable any bar access
-    l4_uint32_t cmd_reg = 0;
-    cfg_read_raw(Pci_hdr_command_offset, &cmd_reg, Vmm::Mem_access::Wd16);
-    cfg_write_raw(Pci_hdr_command_offset, cmd_reg & ~(access & Access_mask),
-                  Vmm::Mem_access::Wd16);
-
-    return cmd_reg & Access_mask;
-  }
-
-  /**
-   * Update the guest resource registration.
-   *
-   * \param  Lower byte of the command register of the PCI config space.
-   *
-   * Will add or remove the resources for the enabled/disabled address space.
-   */
-  void update_decoders(Vmm::Guest *vmm, l4_uint8_t value)
-  {
-    l4_uint32_t diff = (enabled_decoders ^ value) & Access_mask;
-
-    if (enabled_decoders & diff)
-      del_decoder_resources(vmm, enabled_decoders & diff);
-    if (value & diff)
-      add_decoder_resources(vmm, value & diff);
-
-    enabled_decoders = value & Access_mask;
-  }
-
-  /**
-   * Queries the size of a bar.
-   */
-  unsigned read_bar_size(unsigned bar_offs, l4_uint32_t bar,
-                         l4_uint32_t *bar_size)
-  {
-    cfg_write_raw(bar_offs, 0xffffffffUL, Vmm::Mem_access::Wd32);
-    cfg_read_raw(bar_offs, bar_size, Vmm::Mem_access::Wd32);
-    cfg_write_raw(bar_offs, bar, Vmm::Mem_access::Wd32);
-    return bar_offs + 4;
-  }
-
-  /**
-   * Parses one bar configuration for a specific device.
-   *
-   * \pre  Because this modifies the base address register the PCI device
-   *       access must be disabled before calling this method.
-   *
-   * \post This may advance the bar offset in case of an 64 bit mmio bar. 64
-   *       bit addresses take up two bars.
-   */
-  unsigned read_bar(unsigned bar_offs, unsigned max_bar_offs,
-                    Pci_cfg_bar *res)
-  {
-    // Read the base address reg
-    l4_uint32_t bar = 0;
-    l4_uint32_t bar_size = 0;
-    cfg_read_raw(bar_offs, &bar, Vmm::Mem_access::Wd32);
-    if ((bar & Bar_type_mask) == Bar_io_space_bit) // IO bar
-      {
-        bar_offs = read_bar_size(bar_offs, bar, &bar_size);
-        if (bar_size == ~0U)
-          return bar_offs;
-
-        bar_size &= ~Bar_io_attr_mask; // clear decoding
-
-        res->type = Pci_cfg_bar::IO;
-        res->io_addr = bar & ~Bar_io_attr_mask;
-        res->size = (~bar_size & 0xffff) + 1;
-      }
-    else if ((bar & Bar_mem_type_mask) == Bar_mem_type_32bit) // 32Bit MMIO bar
-      {
-        bar_offs = read_bar_size(bar_offs, bar, &bar_size);
-        if (bar_size == 0)
-          return bar_offs;
-
-        bar_size &= ~Bar_mem_attr_mask; // clear decoding
-
-        res->type = Pci_cfg_bar::MMIO32;
-        res->io_addr = bar & ~Bar_mem_attr_mask;
-        res->size = ~bar_size + 1;
-        res->prefetchable = (bar & Bar_mem_prefetch_bit) != 0;
-      }
-    else if ((bar & Bar_mem_type_mask) == Bar_mem_type_64bit) // 64Bit MMIO bar
-      {
-        // Process the first 32bit
-        l4_uint64_t addr64 = bar & ~Bar_mem_attr_mask;
-        l4_uint64_t size64 = 0;
-        bar_offs = read_bar_size(bar_offs, bar, &bar_size);
-        if (bar_size == 0)
-          return bar_offs;
-
-        size64 = bar_size;
-
-        // Process the second 32bit
-        if (bar_offs > max_bar_offs) // max_bar_offset is an inclusive end.
-          L4Re::throw_error(-L4_ERANGE,
-                            "PCI device implements 64-bit MMIO in last BAR.");
-
-        res->prefetchable = (bar & Bar_mem_prefetch_bit) != 0;
-
-        cfg_read_raw(bar_offs, &bar, Vmm::Mem_access::Wd32);
-        addr64 |= static_cast(bar) << 32; // shift to upper part
-        bar_offs = read_bar_size(bar_offs, bar, &bar_size);
-
-        size64 |= static_cast(bar_size) << 32; // shift to upper part
-        size64 &= ~static_cast(Bar_mem_attr_mask); // clear decoding
-
-        res->type = Pci_cfg_bar::MMIO64;
-        res->io_addr = addr64;
-        res->size = ~size64 + 1;
-      }
-
-    return bar_offs;
-  }
-
-  static unsigned expansion_rom_reg(bool type0)
-  {
-    return type0 ? Pci_hdr_type0_expansion_rom_offset
-                 : Pci_hdr_type1_expansion_rom_offset;
-  }
-
-  static bool is_bar_reg(bool type0, unsigned reg)
-  {
-    unsigned max_bar_offset = type0 ? Pci_hdr_type0_base_addr5_offset + 3
-                                    : Pci_hdr_type1_base_addr1_offset + 3;
-    unsigned expansion_rom = expansion_rom_reg(type0);
-
-    return (reg >= Pci_hdr_base_addr0_offset && reg <= max_bar_offset) ||
-           (reg >= expansion_rom             && reg <= expansion_rom + 3);
-  }
-
-  /**
-   * Read BAR register value.
-   *
-   * \return True if this was a BAR register, otherwise false.
-   */
-  bool cfg_read_bar(unsigned reg, l4_uint32_t *value,
-                    Vmm::Mem_access::Width width);
-
-  /**
-   * Get BAR register value from shadow copy.
-   */
-  l4_uint32_t get_bar_regval(unsigned bar) const;
-
-  void write_exp_rom_regval(l4_uint32_t value);
-
-  /**
-   * Write BAR register value.
-   *
-   * \return True if this was a BAR register, otherwise false.
-   */
-  bool cfg_write_bar(unsigned reg, l4_uint32_t value,
-                    Vmm::Mem_access::Width width);
-
-  /**
-   * Update BAR values from register value.
-   *
-   * Applies the required masking. BAR updates are only permissible if the
-   * respective address space decoder is disabled. Otherwise we loose track
-   * of where the current mapping in the guest physical address space is.
-   */
-  void update_bar(unsigned bar, l4_uint32_t value);
-
-  /**
-   * Read from config page.
-   *
-   * The BAR register content is kept in a shadow copy in the `bars` array.
-   * Access to these registers are diverted there. Anything else goes to the
-   * underlying HW or virtual device.
-   */
-  void cfg_read(unsigned reg, l4_uint32_t *value, Vmm::Mem_access::Width width)
-  {
-    if (!cfg_read_bar(reg, value, width))
-      cfg_read_raw(reg, value, width);
-  }
-
-  /**
-   * Write to config page.
-   *
-   * If the command register is updated the respective decoder resources will
-   * be added or removed from the guest address space. Updates of the BAR
-   * registers are diverted to the internal `bars` shadow array. Anything else
-   * goes to the underlying HW or virtual device.
-   */
-  void cfg_write(Vmm::Guest *vmm, unsigned reg, l4_uint32_t value,
-                 Vmm::Mem_access::Width width)
-  {
-    if (reg == Pci_hdr_command_offset)
-      update_decoders(vmm, value & 0xffU); // mask value to byte size.
-
-    if (!cfg_write_bar(reg, value, width))
-      cfg_write_raw(reg, value, width);
-  }
-
-  //
-  // *** PCI cap ************************************************************
-  //
-
-  void parse_msix_cap()
-  {
-    unsigned msix_cap_addr = get_capability(Cap_ident::Msi_x);
-    if (!msix_cap_addr)
-      return;
-
-    l4_uint32_t ctrl = 0;
-    cfg_read_raw(msix_cap_addr + 2, &ctrl, Vmm::Mem_access::Wd16);
-    msix_cap.ctrl.raw = static_cast(ctrl);
-    cfg_read_raw(msix_cap_addr + 4, &msix_cap.tbl.raw, Vmm::Mem_access::Wd32);
-    cfg_read_raw(msix_cap_addr + 8, &msix_cap.pba.raw, Vmm::Mem_access::Wd32);
-
-    has_msix = true;
-  }
-
-  void parse_msi_cap()
-  {
-    unsigned msi_cap_addr = get_capability(Cap_ident::Msi);
-    if (!msi_cap_addr)
-      return;
-
-    msi_cap.offset = msi_cap_addr;
-
-    l4_uint32_t ctrl = 0;
-    cfg_read_raw(msi_cap_addr + 2, &ctrl, Vmm::Mem_access::Wd16);
-    msi_cap.ctrl.raw = static_cast(ctrl);
-
-    // Disable multi MSI, as we don't support it, yet.
-    msi_cap.ctrl.multiple_message_capable() = 0;
-
-    has_msi = true;
-  }
-
-  void parse_sriov_cap()
-  {
-    unsigned sriov_cap_addr = get_ext_capability(Ext_cap_ident::Sr_iov);
-    if (!sriov_cap_addr)
-      return;
-
-    sriov_cap.offset = sriov_cap_addr;
-    has_sriov = true;
-  }
-
-  /**
-   * Walk capabilities list and return the first capability of `cap_type` (see
-   * PCI Spec. Version 3, Chapter 6.7). If none is found return 0.
-   *
-   * \param cap_type  Capability type to retrieve
-   *
-   * \returns 0       If no capability was found.
-   *          >0      Pointer to the capability.
-   */
-  unsigned get_capability(l4_uint8_t cap_type)
-  {
-    l4_uint32_t val = 0;
-    cfg_read_raw(Pci_hdr_status_offset, &val, Vmm::Mem_access::Wd16);
-    if (!(val & Pci_header_status_capability_bit))
-      {
-        trace().printf("Pci_header_status_capability_bit is not set.\n");
-        return 0;
-      }
-
-    cfg_read_raw(Pci_hdr_capability_offset, &val, Vmm::Mem_access::Wd8);
-
-    l4_uint8_t next_cap = val & Pci_cap_mask::Next_cap;
-
-    if (next_cap == 0)
-      {
-        trace().printf("get_capability: Capability pointer is zero.\n");
-        return 0;
-      }
-
-    // Capability list is terminated by zero next pointer.
-    while (next_cap)
-      {
-        cfg_read_raw(next_cap, &val, Vmm::Mem_access::Wd16);
-        l4_uint8_t cap_id = val & Pci_cap_mask::Cap_id;
-        trace().printf("get_capability: found cap id 0x%x (cap addr 0x%x)\n",
-                       cap_id, next_cap);
-
-        if (cap_id == cap_type)
-          return next_cap;
-
-        next_cap = (val >> 8) & Pci_cap_mask::Next_cap;
-      }
-
-    trace().printf("get_capability: Did not find capability of type 0x%x\n",
-                   cap_type);
-
-    return 0;
-  }
-
-  /**
-   * Walk PCIe extended capabilities list and return the first capability of
-   * `cap_type` (see PCI Express Spec. Version 5, Chapter 7.6). If none is found
-   * return 0.
-   *
-   * \param cap_type     Capability type to retrieve
-   * \param min_version  Minimum required version of the capability
-   *
-   * \returns 0          If no capability was found.
-   *          >0         Pointer to the capability.
-   */
-  unsigned get_ext_capability(Ext_cap_ident cap_type, l4_uint8_t min_version = 0)
-  {
-    if (!get_capability(Cap_ident::Pcie))
-      // Not a PCIe device.
-      return 0;
-
-    l4_uint16_t next_cap = 0x100;
-    // Extended capability list is terminated by zero next pointer.
-    while (next_cap)
-      {
-        l4_uint32_t val = 0;
-        cfg_read_raw(next_cap, &val, Vmm::Mem_access::Wd32);
-
-        Pcie_cap_header cap{val};
-        if (cap.id() == cap_type && cap.version() >= min_version)
-          // Found matching capability.
-          return next_cap;
-
-        next_cap = cap.next_cap() & Pcie_cap_header::Next_cap_mask;
-      }
-
-    // No matching capability found.
-    return 0;
-  }
-
-  /**
-   * Parses all bars for a specific device.
-   *
-   * Only used for Hw_pci_device devices to sync the BAR shadow copy with the
-   * actual state on the vbus. Guest writes are only working on the shadow copy
-   * afterwards.
-   */
-  void parse_device_bars()
-  {
-    unsigned const max_bar_offset =
-      get_header_type() == Pci_header_type::Type0
-        ? Pci_hdr_type0_base_addr5_offset
-        : Pci_hdr_type1_base_addr1_offset;
-
-    // Disable all access because read_bar() actually modifies the BARs to
-    // detect the size.
-    l4_uint32_t access = disable_access(Access_mask);
-
-    unsigned bar_offs = Pci_hdr_base_addr0_offset;
-    while (bar_offs <= max_bar_offset)
-      {
-        unsigned i = (bar_offs - Pci_hdr_base_addr0_offset) / 4U;
-        Pci_cfg_bar &bar = bars[i];
-
-        // Read one bar configuration
-        bar_offs = read_bar(bar_offs, max_bar_offset, &bar);
-
-        if (bar.type == Pci_cfg_bar::MMIO64)
-          bars[i + 1].type = Pci_cfg_bar::Reserved_mmio64_upper;
-        else if (bar.type == Pci_cfg_bar::Unused_empty)
-          continue;
-
-        info().printf("  bar[%u] addr=0x%llx size=0x%llx type=%s\n", i,
-                      bar.io_addr, bar.size, bar.to_string());
-      }
-
-    // Reenable bar access
-    enable_access(access);
-  }
-
-  /**
-   * Only use for Hw_pci_device.
-   */
-  void parse_device_exp_rom()
-  {
-    Pci_header_type hdr_type = get_header_type();
-    unsigned rom_reg = expansion_rom_reg(hdr_type == Pci_header_type(0));
-
-    trace().printf("Parsing expansion ROM reg 0x%x of type %i header\n",
-                   rom_reg, hdr_type);
-    l4_uint32_t access = disable_access(Access_mask);
-
-    l4_uint32_t val = 0;
-    cfg_read_raw(rom_reg, &val, Vmm::Mem_access::Wd32);
-
-    enum : l4_uint32_t
-    {
-      Expansion_rom_address_shift = 11,
-      Expansion_rom_address_mask = -1U << Expansion_rom_address_shift
-    };
-
-    l4_uint32_t size = 0;
-    cfg_write_raw(rom_reg, Expansion_rom_address_mask, Vmm::Mem_access::Wd32);
-    cfg_read_raw(rom_reg, &size, Vmm::Mem_access::Wd32);
-    cfg_write_raw(rom_reg, val, Vmm::Mem_access::Wd32);
-
-    enable_access(access);
-
-    exp_rom.io_addr = val & size;
-    exp_rom.hw_enabled = val & Pci_expansion_rom_bar::Enable_bit;
-    exp_rom.size = ~size + 1;
-
-    info().printf("Expansion ROM addr reg(0x%x) as read from hardware: 0x%x, "
-                  "size 0x%llx (from hardware: 0x%x)\n",
-                  rom_reg, val, exp_rom.size, size);
-
-  }
-
-  /**
-   * Get the type of the device's PCI header.
-   *
-   * We are not supporting PCI-to-Cardbus bridges (Type2). If such a bridge is
-   * encountered or any other invalid header type, this function throws.
-   *
-   * \retval Pci_header_type::Type0, for normal PCI devices
-   *         Pci_header_type::Type1, for PCI-to-PCI bridge devices.
-   */
-  Pci_header_type get_header_type()
-  {
-    enum { Type_mask = 0x7f };
-    l4_uint8_t type = get_header_field() & Type_mask;
-
-    // Not supporting Cardbus bridges and reserved header type values.
-    if (type >= Pci_header_type::Type2)
-      L4Re::throw_error(-L4_EINVAL, "Device has unsupported PCI header type.");
-
-    return Pci_header_type(type);
-  }
-
-  /// True, iff this device supports multiple functions.
-  bool is_multi_function_device()
-  {
-    return get_header_field() & Multi_func_bit;
-  }
-
-  /// Get the raw value of the header type field in the config space.
-  l4_uint8_t get_header_field()
-  {
-    l4_uint32_t header_type = 0U;
-    cfg_read_raw(Pci_hdr_type_offset, &header_type, Vmm::Mem_access::Wd8);
-    return header_type & 0xff;
-  }
-
-  // These registers keep track of the BARs that are actually mapped.
-  // We expect the guest to reprogram PCI BARs. These writes will modify the
-  // in-memory header BARs, but only when the IO/MMIO decode bits are set in
-  // the control register, we actually commit the configuration (program the
-  // mappings and save the configuration into the shadow registers).
-  Pci_cfg_bar bars[Bar_num_max_type0];
-  Pci_expansion_rom_bar exp_rom;
-  Pci_msix_cap msix_cap;               /// MSI-X capability
-  Pci_msi_cap msi_cap;                 /// MSI capability
-  Pcie_sriov_cap sriov_cap;            /// SR-IOV capability
-  l4_uint8_t enabled_decoders = 0;     /// Currently registered resources
-  bool has_msix = false;               /// indicates MSI-X support
-  bool has_msi = false;                /// indicates MSI support
-  bool has_sriov = false;              /// indicates SR-IOV support
-
-private:
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "PCI dev"); }
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "PCI dev"); }
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "PCI dev"); }
-};
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/pci_virtio_config.h b/src/l4/pkg/uvmm/server/src/pci_virtio_config.h
deleted file mode 100644
index 779b0639..00000000
--- a/src/l4/pkg/uvmm/server/src/pci_virtio_config.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2017, 2019, 2022, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "pci_device.h"
-
-namespace Vdev {
-
-  enum Consts
-  {
-    Num_pci_connector_ports = 0x50,
-  };
-
-  enum Virtio_defaults
-  {
-   // see Virtio 1.0 cs4 (2016) - Section 4.1
-    Virtio_pci_device_vendor_id             = 0x1AF4,
-    Virtio_pci_device_id_base               = 0x1040,
-    Virtio_pci_legacy_device_id_base        = 0x1000,
-    Transitional_device_pci_revision_id     = 0x0,
-    Non_transitional_device_pci_revision_id = 0x1,
-    Virtio_msix_no_vector                   = 0xffff,
-    Virtio_pci_subsystem_id_minimum         = 0x40,
-  };
-
-  enum Virtio_cfg_types
-  {
-    Virtio_pci_cap_common_cfg  = 1,
-    Virtio_pci_cap_notify_cfg  = 2,
-    Virtio_pci_cap_isr_cfg     = 3,
-    Virtio_pci_cap_device_cfg  = 4,
-    Virtio_pci_cap_pci_cfg     = 5,
-  };
-
-  /// Base class of a VirtIO capability.
-  struct Virtio_pci_cap : Pci::Vendor_specific_cap
-  {
-    explicit Virtio_pci_cap(l4_uint8_t vio_cfg_t, l4_uint8_t len)
-    : Vendor_specific_cap(len), cfg_type(vio_cfg_t)
-    {}
-
-    /**
-     * Perform a cast if the input cap type `c` is of the expected
-     * Virtio_pci_cap type.
-     *
-     * \tparam T  The expected Virtio_pci_cap type.
-     * \param  c  The capability to cast.
-     *
-     * \returns A valid capability pointer if the type is correct; nullptr
-     *          otherwise.
-     */
-    template 
-    static T *
-    cast_type(Virtio_pci_cap *c)
-    {
-      if (auto *x = Pci_cap::cast_type(c))
-        return x->cfg_type == T::Virtio_cfg_type ? static_cast(c) : nullptr;
-
-      return nullptr;
-    }
-
-    l4_uint8_t  cfg_type;
-    l4_uint8_t  bar;
-    l4_uint8_t  padding[3];
-    l4_uint32_t offset;
-    l4_uint32_t length;
-  };
-  static_assert(sizeof(Virtio_pci_cap) == 16,
-                "Virtio_pci_cap size conforms to specification.");
-
-  struct Virtio_pci_common_cap : Virtio_pci_cap
-  {
-    enum : l4_uint8_t
-    {
-      Virtio_cfg_type = Virtio_pci_cap_common_cfg
-    };
-
-    Virtio_pci_common_cap()
-    : Virtio_pci_cap(Virtio_cfg_type, sizeof(*this))
-    {}
-  };
-  static_assert(sizeof(Virtio_pci_common_cap) == 16,
-                "Virtio_pci_common_cap size conforms to specification.");
-
-  struct Virtio_pci_isr_cap : Virtio_pci_cap
-  {
-    enum : l4_uint8_t
-    {
-      Virtio_cfg_type = Virtio_pci_cap_isr_cfg
-    };
-
-    Virtio_pci_isr_cap()
-    : Virtio_pci_cap(Virtio_cfg_type, sizeof(*this))
-    {}
-  };
-  static_assert(sizeof(Virtio_pci_isr_cap) == 16,
-                "Virtio_pci_isr_cap size conforms to specification.");
-
-  struct Virtio_pci_notify_cap : Virtio_pci_cap
-  {
-    enum : l4_uint8_t
-    {
-      Virtio_cfg_type = Virtio_pci_cap_notify_cfg
-    };
-
-    Virtio_pci_notify_cap()
-    : Virtio_pci_cap(Virtio_cfg_type, sizeof(*this))
-    {}
-
-    l4_uint32_t     notify_off_multiplier;
-  };
-  static_assert(sizeof(Virtio_pci_notify_cap) == 20,
-                "Virtio_pci_notify_cap size conforms to specification.");
-
-  struct Virtio_pci_device_cap : Virtio_pci_cap
-  {
-    enum : l4_uint8_t
-    {
-      Virtio_cfg_type = Virtio_pci_cap_device_cfg
-    };
-
-    Virtio_pci_device_cap()
-    : Virtio_pci_cap(Virtio_cfg_type, sizeof(*this))
-    {}
-  };
-  static_assert(sizeof(Virtio_pci_device_cap) == 16,
-                "Virtio_pci_device_cap size conforms to specification.");
-
-  struct Virtio_pci_cfg_cap : Virtio_pci_cap
-  {
-    enum : l4_uint8_t
-    {
-      Virtio_cfg_type = Virtio_pci_cap_pci_cfg
-    };
-
-    Virtio_pci_cfg_cap()
-    : Virtio_pci_cap(Virtio_cfg_type, sizeof(*this))
-    {}
-
-    l4_uint8_t      pci_cfg_data[4];
-  };
-  static_assert(sizeof(Virtio_pci_cfg_cap) == 20,
-                "Virtio_pci_cfg_cap size conforms to specification.");
-
-  struct Virtio_pci_common_cfg
-  {
-    l4_uint32_t device_feature_select;  // 0, 1
-    l4_uint32_t device_feature;         // starts at device_features_select * 32
-    l4_uint32_t driver_feature_select;  // 0, 1
-    l4_uint32_t driver_feature;         // starts at driver_features_select * 32
-    l4_uint16_t config_msix_vec;
-    l4_uint16_t num_queues;
-    l4_uint8_t  device_status;
-    l4_uint8_t  config_generation;
-
-    l4_uint16_t queue_select;
-    l4_uint16_t queue_size;
-    l4_uint16_t queue_msix_vector;
-    l4_uint16_t queue_enable;
-    l4_uint16_t queue_notify_off;
-    l4_uint64_t queue_desc;
-    l4_uint64_t queue_avail;
-    l4_uint64_t queue_used;
-  };
-  static_assert(sizeof(Virtio_pci_common_cfg) == 56,
-                "Virtio_pci_common_cfg size conforms to specification.");
-
-}; // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/pci_virtio_device.h b/src/l4/pkg/uvmm/server/src/pci_virtio_device.h
deleted file mode 100644
index 1a429d9d..00000000
--- a/src/l4/pkg/uvmm/server/src/pci_virtio_device.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright (C) 2017-2019, 2021-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-/**
- * Base class definition for devices using the Virtio PCI transport.
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "pci_device.h"
-#include "virt_pci_device.h"
-#include "io_device.h"
-#include "virtio_dev.h"
-#include "pci_virtio_config.h"
-#include "virtio_qword.h"
-#include "device/pci_bridge_windows.h"
-
-namespace Vdev { namespace Pci {
-
-/**
- * Virtio device using the Virtio PCI transport employing MSI-X.
- */
-template
-class Virtio_device_pci
-: public Virt_pci_device
-{
-  unsigned _device_config_len;
-
-public:
-  /**
-   * Create virtual PCI device and configure capabilities.
-   *
-   * The device is constructed in two steps. This constructor initializes the
-   * generic PCI device parts of the virtio related stuff. Once the concrete
-   * device (that has been derived from this class) has finished its setup, it
-   * must call init_virtio_pci_device() to complete the PCI transport related
-   * initialization.
-   *
-   * \param node              Device Tree node of this device.
-   * \param num_msix_entries  Maximum number of MSI-X entries to handle.
-   */
-  Virtio_device_pci(Vdev::Dt_node const &node, unsigned num_msix_entries,
-                    Pci_bridge_windows *wnds)
-  : Virt_pci_device(node, wnds)
-  {
-    // There is a 32-bit BAR configured that fits the MSI-X table.
-    unsigned msix_bar = msix_bar_idx();
-    check_msix_bar_constraints(msix_bar, num_msix_entries);
-    create_msix_cap(num_msix_entries, msix_bar);
-
-    bool mmio_bar = false;
-    // There is either an IO BAR or a second MMIO32 BAR configured.
-    unsigned virtio_bar = virtio_bar_idx(Pci_cfg_bar::IO);
-    if (virtio_bar == -1U)
-      {
-        virtio_bar = virtio_bar_idx(Pci_cfg_bar::MMIO32);
-        if (virtio_bar != -1U)
-          mmio_bar = true;
-      }
-
-    check_config_space_constraints(virtio_bar, mmio_bar);
-    // first VirtIO capability defines the start within the BAR
-    Virtio_pci_cap *cap =
-      create_vio_pci_cap_common_entry(nullptr, virtio_bar);
-    cap = create_vio_pci_cap_notify_entry(cap, virtio_bar);
-    cap = create_vio_pci_cap_isr_entry(cap, virtio_bar);
-    cap = create_vio_pci_cap_pci_entry(cap, virtio_bar);
-
-    // Check actual I/O BAR usage vs configured I/O BAR size
-    l4_uint32_t bar_length = cap->offset + cap->length;
-    if (bar_length > bars[virtio_bar].size)
-      {
-        Err().printf("Actual size greater configured size due to alignment: "
-                     "0x%x > 0x%llx\n",
-                     bar_length, bars[virtio_bar].size);
-        L4Re::chksys(-L4_EINVAL, "Configure greater I/O bar size.");
-      }
-
-    // Must be the last cap created!
-    cap = create_vio_pci_cap_device_entry(cap, virtio_bar);
-    _device_config_len = cap ? cap->length : 0;
-
-    trace().printf("Virtio_device_pci: device configured\n");
-  }
-
-  /**
-   * Complete the initialization of the virtio PCI transport bits.
-   *
-   * This method must be called after the concrete virtio device has been
-   * setup. It will up-call to the derived class to gather required PCI
-   * related information of the device.
-   *
-   * \pre The virtio config page must be valid. Call register_irq() before this.
-   */
-  void init_virtio_pci_device()
-  {
-    auto dev_cfg = dev()->virtio_cfg();
-    assert(dev_cfg);
-    auto * const hdr = get_header();
-    hdr->vendor_id = Virtio_pci_device_vendor_id;
-    // PCI device_id is calculated by Virtio Device ID + 0x1040
-    // (see virtio 1.0 cs4)
-    hdr->device_id = Virtio_pci_device_id_base + dev_cfg->device;
-    hdr->revision_id = Non_transitional_device_pci_revision_id;
-    hdr->subsystem_id = Virtio_pci_subsystem_id_minimum;
-    // hdr->subsystem_id && hdr->subsystem_vendor: virtio spec 1.0 cs4: optional
-    hdr->status = Interrupt_status_bit | Capability_list_bit;
-    hdr->header_type = Multi_func_bit;
-
-    switch (dev_cfg->device)
-      {
-      case L4VIRTIO_ID_NET:
-        hdr->classcode[2] = Pci_class_code_network_device;
-        break;
-      case L4VIRTIO_ID_BLOCK:
-      case L4VIRTIO_ID_SCSI:
-        hdr->classcode[2] = Pci_class_code_mass_storage_device;
-        break;
-      case L4VIRTIO_ID_CONSOLE:
-        // same as used by qemu (communication controller, other)
-        hdr->classcode[2] = Pci_class_code_communication_device;
-        hdr->classcode[1] = Pci_class_code_other_device;
-        break;
-      case L4VIRTIO_ID_INPUT:
-        hdr->classcode[2] = Pci_class_code_input_device; // Input devices
-        hdr->classcode[1] = Pci_class_code_other_device; // Other input controller
-        break;
-      default:
-        hdr->classcode[2] = Pci_class_code_unknown_device;
-        break;
-      }
-  }
-
-  bool msix_enabled()
-  {
-    parse_msix_cap();
-    return has_msix? msix_cap.ctrl.enabled() : false;
-  }
-
-protected:
-  /**
-   * The length of the device specific configuration area.
-   */
-  unsigned device_config_len() const { return _device_config_len; }
-
-private:
-  Virtio_pci_cap *
-  create_vio_pci_cap_common_entry(Virtio_pci_cap *prev, unsigned bar_idx)
-  {
-    auto *entry   = create_pci_cap();
-    entry->bar    = bar_idx;
-    // Start the BAR with the PCI common config
-    entry->offset = prev ? prev->offset + prev->length : 0;
-    entry->length = sizeof(Virtio_pci_common_cfg);
-
-    return entry;
-  }
-
-  Virtio_pci_cap *
-  create_vio_pci_cap_notify_entry(Virtio_pci_cap *prev, unsigned bar_idx)
-  {
-    auto *entry   = create_pci_cap();
-    entry->bar    = bar_idx;
-    // offset must be 2 byte aligned
-    entry->offset = prev ? l4_round_size(prev->offset + prev->length, 1) : 0;
-    entry->length = 2; // smallest possible length
-
-    entry->notify_off_multiplier = 0;
-
-    return entry;
-  }
-
-  Virtio_pci_cap *create_vio_pci_cap_isr_entry(Virtio_pci_cap *prev,
-                                               unsigned bar_idx)
-  {
-    auto *entry   = create_pci_cap();
-    entry->bar    = bar_idx;
-    entry->offset = prev ? prev->offset + prev->length : 0;
-    entry->length = 2;
-
-    return entry;
-  }
-
-  /// The device cap uses the rest of the BAR. Must be the last cap created.
-  Virtio_pci_cap *create_vio_pci_cap_device_entry(Virtio_pci_cap *prev,
-                                                  unsigned bar_idx)
-  {
-    // 4 byte align offset to find device specific config
-    unsigned entry_start =
-      prev ? l4_round_size(prev->offset + prev->length, 2) : 0;
-
-    if (entry_start >= bars[bar_idx].size)
-      return nullptr;
-
-    auto *entry   = create_pci_cap();
-    entry->bar    = bar_idx;
-    entry->offset = entry_start;
-    entry->length = bars[bar_idx].size - entry_start;
-
-    // limit the size of this entry to something sensible. IO BARs are not that
-    // large, but MMIO BARs tend to be 4K, which is way too much for the VirtIO
-    // device config.
-    if (entry->length > 0x200)
-      entry->length = 0x200;
-
-    return entry;
-  }
-
-  Virtio_pci_cap *create_vio_pci_cap_pci_entry(Virtio_pci_cap *prev,
-                                               unsigned bar_idx)
-  {
-    auto *entry   = create_pci_cap();
-    entry->bar    = bar_idx;
-    entry->offset = prev ? prev->offset + prev->length : 0;
-    entry->length = sizeof(Virtio_pci_cfg_cap);
-
-    // TODO This is not fully implemented. But the spec forces me to provide
-    // the cap.
-    return entry;
-  }
-
-  /**
-   * Allocate an entry in the PCI capability list of the PCI configuration
-   * header and fill it with the MSI-X capability.
-   *
-   * \param max_msix_entries  Maximum number of MSI-X entries of this device.
-   * \param BAR index         BAR index[0,5] of the MSI-X memory BAR.
-   *
-   * \pre The BAR starts with the MSI-X table at offset 0 and PBA right behind
-   *      it.
-   */
-  void create_msix_cap(unsigned max_msix_entries, unsigned bar_index)
-  {
-    assert(bar_index < 6);
-
-    Pci_msix_cap *cap    = create_pci_cap();
-    cap->ctrl.enabled()  = 1;
-    cap->ctrl.masked()   = 0;
-    cap->ctrl.max_msis() = max_msix_entries - 1;
-    cap->tbl.bir()       = bar_index;
-    cap->pba.offset()    = Vdev::Msix::msix_table_mem_size(max_msix_entries) >> 3;
-    cap->pba.bir()       = bar_index;
-
-    trace().printf("msi.msg_ctrl 0x%x\n", cap->ctrl.raw);
-    trace().printf("msi.table 0x%x\n", cap->tbl.raw);
-    trace().printf("msi.pba 0x%x\n", cap->pba.raw);
-    trace().printf("Size of MSI-X cap 0x%zx\n", sizeof(*cap));
-  }
-
-  inline void
-  check_msix_bar_constraints(unsigned msix_idx, unsigned max_msix_entries)
-  {
-    if (msix_idx == -1U)
-      L4Re::throw_error(-L4_EINVAL,
-                        "Configure the device with an MMIO BAR for the MSI-X table.");
-
-    if (bars[msix_idx].size <
-        Vdev::Msix::msix_table_pba_mem_size(max_msix_entries))
-      {
-        Err().printf("At least 0x%zx Bytes of MSI-X memory are required "
-                     "in BAR %u.\n",
-                     Vdev::Msix::msix_table_pba_mem_size(max_msix_entries),
-                     msix_idx);
-        L4Re::throw_error(-L4_EINVAL, "More MSI-X memory necessary.");
-      }
-  }
-
-  inline void
-  check_config_space_constraints(unsigned bar_idx, bool mmio_bar)
-  {
-    if (bar_idx == -1U)
-      L4Re::throw_error(
-        -L4_EINVAL,
-        "Configure the device with an IO or MMIO32 BAR for the VirtIO device interface.");
-
-    if (mmio_bar)
-      {
-        if (bars[bar_idx].size < L4_PAGESIZE)
-          {
-            Err().printf("Configure at least a size of 4KB for the MMIO32 BAR %u.\n",
-                         bar_idx);
-            L4Re::throw_error(-L4_EINVAL,
-                              "VirtIO device config space must have a size of 4KB or more.");
-          }
-      }
-    else
-      {
-        if (bars[bar_idx].size < Num_pci_connector_ports)
-          {
-            Err().printf("Configured IO ports in BAR %u are a power of 2 >= 0x%x.\n",
-                         bar_idx, Num_pci_connector_ports);
-            L4Re::throw_error(-L4_EINVAL, "More IO ports necessary.");
-          }
-      }
-  }
-
-  /**
-   * Per convention we return the first MMIO32 BAR.
-   */
-  unsigned msix_bar_idx() const
-  {
-    for (unsigned i = 0; i < Bar_num_max_type0; ++i)
-      if (bars[i].type == Pci_cfg_bar::MMIO32)
-        return i;
-
-    return -1;
-  }
-
-  /**
-   * Per convention we return the first BAR that fits `type`. The first MMIO32
-   * BAR is skipped, as it is solely used for the MSI-X table.
-   */
-  unsigned virtio_bar_idx(Pci_cfg_bar::Type type) const
-  {
-    // The first MMIO32 BAR is for the MSI-X table, thus skip it.
-    bool skip_next_mmio32 = type == Pci_cfg_bar::MMIO32;
-    for (unsigned i = 0; i < Bar_num_max_type0; ++i)
-      if (bars[i].type == type)
-        {
-          if (skip_next_mmio32)
-            skip_next_mmio32 = false;
-          else
-            return i;
-        }
-
-    return -1;
-  }
-
-  DEV *dev() { return static_cast(this); }
-  DEV const *dev() const { return static_cast(this); }
-}; // class Virtio_device_pci
-
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/pm.cc b/src/l4/pkg/uvmm/server/src/pm.cc
deleted file mode 100644
index f3760a49..00000000
--- a/src/l4/pkg/uvmm/server/src/pm.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2017, 2019-2020, 2024 Kernkonzept GmbH.
- * Author: Steffen Liebergeld 
- *         Adam Lackorzynski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "pm.h"
-
-namespace Vmm {
-
-static Dbg warn(Dbg::Pm, Dbg::Warn, "pm");
-
-Pm::Pm()
-: _vbus(L4Re::Env::env()->get_cap("vbus"))
-{
-  // vbus is optional
-  if (_vbus)
-    {
-      // If we have a 'vbus', we assume we also have devices to hand out to
-      // the guest. If acquiring the suspend and shutdown inhibitors fails,
-      // the system can be suspended or shutdown anytime. If we handed out
-      // devices to the guest, this could result in erroneous system
-      // states. Therefore failure to acquire an inhibitor is fatal.
-      int r = 0;
-      if ((r = _vbus->acquire(L4VBUS_INHIBITOR_SUSPEND, "vm running")))
-        {
-          warn.printf("Failed to acquire suspend inhibitor: %d.\n", r);
-          L4Re::chksys(-L4_ENOENT, "acquire suspend inhibitor");
-        }
-
-      if ((r = _vbus->acquire(L4VBUS_INHIBITOR_SHUTDOWN, "vm running")))
-        {
-          warn.printf("Failed to acquire shutdown inhibitor: %d.\n", r);
-          _vbus->release(L4VBUS_INHIBITOR_SUSPEND);
-          L4Re::chksys(-L4_ENOENT, "acquire shutdown inhibitor");
-        }
-    }
-
-  // pfc cap is optional, but when its there, it should be used
-  _pfc = L4Re::Env::env()->get_cap("pfc");
-}
-
-Pm::~Pm()
-{
-  free_inhibitors();
-}
-
-bool
-Pm::acquire_wakeup_inhibitor()
-{
-  if (!_use_wakeup_inhibitor)
-    return true;
-
-  int r = _vbus->acquire(L4VBUS_INHIBITOR_WAKEUP, "wakeup");
-  if (r < 0)
-    warn.printf("Failed to acquire wakeup inhibitor: %d.\n", r);
-
-  return r >= 0;
-}
-
-bool
-Pm::suspend()
-{
-  if (_vbus)
-    {
-      // If we did not get the wakeup inhibitor we will not get wakeup events
-      // therefore we deem suspend unsuccessful and wake up the guest
-      // immediately, so that it can do something useful.
-      if (!acquire_wakeup_inhibitor())
-        return false;
-
-      // If we fail to release the suspend inhibitor, we block the system from
-      // suspending. This is a state that would not be recoverable without a
-      // reboot. Therefore this is a failed suspend, we free the wakeup
-      // inhibitor and resume the guest so that it can do something useful.
-      int r = _vbus->release(L4VBUS_INHIBITOR_SUSPEND);
-      if (r < 0)
-        {
-          warn.printf("Failed to release suspend inhibitor: %d.\n", r);
-          if (_use_wakeup_inhibitor)
-            _vbus->release(L4VBUS_INHIBITOR_WAKEUP);
-          return false;
-        }
-    }
-
-  // If we have a pfc cap and we have the wakeup inhibitor, we assume we are
-  // woken up by a wakeup event. The wakeup event will only come after the
-  // system successfully suspended and was subsequently woken up. Therefore it
-  // is an error if the system_suspend call failed. We have to get the suspend
-  // inhibitor again, possibly free the wakeup inhibitor and return to the
-  // guest immediately, so that it can so do something useful.
-  if (_pfc && (l4_error(_pfc->system_suspend(0)) < 0))
-    {
-      warn.printf("Call to do system suspend failed.\n");
-
-      if (!_vbus)
-        return false;
-
-      _vbus->acquire(L4VBUS_INHIBITOR_SUSPEND, "vm running");
-      if (_use_wakeup_inhibitor)
-        _vbus->release(L4VBUS_INHIBITOR_WAKEUP);
-
-      return false;
-    }
-
-  return true;
-}
-
-void
-Pm::free_inhibitors()
-{
-  if (!_vbus)
-    return;
-
-  if (_vbus->release(L4VBUS_INHIBITOR_SHUTDOWN))
-    warn.printf("Failed to release shutdown inhibitor.\n");
-  if (_vbus->release(L4VBUS_INHIBITOR_SUSPEND))
-    warn.printf("Failed to release suspend inhibitor.\n");
-}
-
-void
-Pm::shutdown(bool reboot)
-{
-  free_inhibitors();
-
-  if (_pfc && l4_error(_pfc->system_shutdown(reboot)))
-    warn.printf("Call to shutdown failed.\n");
-}
-
-void
-Pm::resume()
-{
-  if (_vbus)
-    {
-      // Failure to acquire an inhibitor is a problem (see description
-      // above). However, at this time the guest already has a lot of state
-      // that we would loose if we would crash here. Therefore we warn the
-      // operator that acquiring the inhibitor fails but do not bail out.
-      int r = 0;
-      if ((r = _vbus->acquire(L4VBUS_INHIBITOR_SUSPEND, "vm running")))
-        warn.printf("Failed to release suspend inhibitor: %d.\n", r);
-
-      if (_use_wakeup_inhibitor
-          && (r = _vbus->release(L4VBUS_INHIBITOR_WAKEUP)))
-        warn.printf("Failed to release wakeup inhibitor: %d.\n", r);
-    }
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/pm.h b/src/l4/pkg/uvmm/server/src/pm.h
deleted file mode 100644
index 87af4cb3..00000000
--- a/src/l4/pkg/uvmm/server/src/pm.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017, 2019-2020, 2024 Kernkonzept GmbH.
- * Author: Steffen Liebergeld 
- *         Adam Lackorzynski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "device.h"
-
-#include 
-#include 
-
-namespace Vmm {
-
-/**
- * Guest interface for system power control.
- *
- * Allows the guest to control machine suspend/shutdown. The underlying
- * technique is inhibitors that -if taken- prevent the system from
- * suspending/shutting down/rebooting. This interface acquires suspend and
- * shutdown inhibitors. It allows the guest to release them.
- *
- * If a L4::Platform control cap 'pfc' is available, this interface will
- * announce the guest's intent to this cap as well. This can be used to allow
- * a guest to suspend/shutdown/reboot the machine.
- */
-class Pm
-: public virtual Vdev::Dev_ref
-{
-public:
-  Pm();
-  virtual ~Pm();
-
-  /**
-   * Configure if guest should resume on system resume.
-   *
-   * If true, uvmm will acquire a wakeup inhibitor prior to releasing its
-   * suspend inhibitor. IO sends a wakeup event to all clients holding a
-   * wakeup inhibitor on system resume. This can be used to resume the guest
-   * on system resume.
-   */
-  void use_wakeup_inhibitor(bool val)
-  {
-    _use_wakeup_inhibitor = val;
-  }
-
-  bool suspend();
-  void resume();
-  void shutdown(bool reboot = false);
-  void free_inhibitors();
-
-private:
-  L4::Cap _vbus;
-  L4::Cap _pfc;
-
-  bool _use_wakeup_inhibitor = false;
-
-  /**
-   * \pre _vbus must be valid
-   */
-  bool acquire_wakeup_inhibitor();
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/pm_device_if.cc b/src/l4/pkg/uvmm/server/src/pm_device_if.cc
deleted file mode 100644
index 3becb742..00000000
--- a/src/l4/pkg/uvmm/server/src/pm_device_if.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2022,2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "pm_device_if.h"
-
-namespace Vdev {
-
-cxx::unique_ptr Pm_device_registry::_self;
-
-void
-Pm_device_registry::add(Pm_device *dev)
-{
-  _devices.push_back(dev);
-}
-
-void
-Pm_device_registry::remove(Pm_device *dev)
-{
-  for (auto it = _devices.begin(); it != _devices.end(); ++it)
-    {
-      if (*it == dev)
-        {
-          _devices.erase(it);
-          break;
-        }
-    }
-}
-
-void
-Pm_device_registry::suspend() const
-{
-  for (auto &d : _devices)
-    d->pm_suspend();
-}
-
-void
-Pm_device_registry::resume() const
-{
-  for (auto &d : _devices)
-    d->pm_resume();
-}
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/pm_device_if.h b/src/l4/pkg/uvmm/server/src/pm_device_if.h
deleted file mode 100644
index 1bc25a8c..00000000
--- a/src/l4/pkg/uvmm/server/src/pm_device_if.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2022,2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include "device.h"
-
-namespace Vdev
-{
-
-struct Pm_device;
-
-/**
- * Registry for all devices requesting notification for power management events.
- */
-class Pm_device_registry
-{
-public:
-  /// Register a device for power management event notifications.
-  static void register_device(Pm_device *dev)
-  { Pm_device_registry::get()->add(dev); }
-
-  /// Remove a device from power management event notifications.
-  static void remove_device(Pm_device *dev)
-  { Pm_device_registry::get()->remove(dev); }
-
-  /// Notify all registered devices of a suspend event.
-  static void suspend_devices()
-  { Pm_device_registry::get()->suspend(); }
-
-  /// Notify all registered devices of a resume event.
-  static void resume_devices()
-  { Pm_device_registry::get()->resume(); }
-
-private:
-  Pm_device_registry() = default;
-  Pm_device_registry(Pm_device_registry &) = delete;
-  Pm_device_registry(Pm_device_registry &&) = delete;
-
-  static Pm_device_registry *get()
-  {
-    if (!_self)
-      _self = cxx::make_unique_ptr(new Pm_device_registry());
-
-    return _self.get();
-  }
-
-  void add(Pm_device *dev);
-  void remove(Pm_device *dev);
-
-  void suspend() const;
-  void resume() const;
-
-  static cxx::unique_ptr _self;
-  std::vector _devices;
-}; // class Pm_device_registry
-
-/**
- * Interface for devices which need to act on power management events.
- *
- * This interface provides functions that will be called on power management
- * actions emitting from the guest or events affecting the guest.
- */
-struct Pm_device
-{
-  /// The constructor registers the device for power management events.
-  Pm_device()
-  { Pm_device_registry::register_device(this); }
-
-  /**
-   * The destructor removes the device from power management event
-   * notifications.
-   */
-  ~Pm_device()
-  { Pm_device_registry::remove_device(this); }
-
-  /**
-   * Actions a device needs to perform during the process to suspend the guest.
-   */
-  virtual void pm_suspend() = 0;
-
-  /**
-   * Actions a device needs to perform during the process to resume the guest.
-   */
-  virtual void pm_resume() = 0;
-}; // struct Pm_device
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/ram_ds.cc b/src/l4/pkg/uvmm/server/src/ram_ds.cc
deleted file mode 100644
index ec0850d1..00000000
--- a/src/l4/pkg/uvmm/server/src/ram_ds.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2015-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "ram_ds.h"
-
-static Dbg warn(Dbg::Mmio, Dbg::Warn, "ram");
-static Dbg trace(Dbg::Mmio, Dbg::Trace, "ram");
-
-namespace Vmm {
-
-long
-Ram_ds::setup(Vmm::Guest_addr vm_base, Vmm::Address_space_manager *as_mgr)
-{
-  Dbg info(Dbg::Mmio, Dbg::Info, "ram");
-
-  _vm_start = vm_base;
-
-  if (as_mgr->is_any_identity_mode())
-    {
-      l4_size_t phys_size = size();
-      L4Re::Dma_space::Dma_addr phys_ram = 0;
-      int err = as_mgr->get_phys_mapping(dataspace().get(), ds_offset(),
-                                         &phys_ram, &phys_size);
-
-      if (err < 0 || phys_size < size())
-        {
-          warn.printf(
-            "Identity mapping requested, but dataspace not contiguous.\n");
-          return err < 0 ? err : -L4_ENOMEM;
-        }
-
-      _vm_start = Vmm::Guest_addr(phys_ram);
-
-      if (as_mgr->is_iommu_identity_mode())
-        as_mgr->add_ram_iommu(_vm_start, local_start(), size());
-
-      _phys_ram = phys_ram;
-      _phys_size = phys_size;
-    }
-  else if (as_mgr->is_dma_offset_mode())
-    {
-      /**
-       * While this code looks rather alike to the identity_mode case, the
-       * semantics are quite different. The DMA address the as_mgr returns
-       * can be used by the guest for device access, but it is not the host-
-       * physical address corresponding to the given dataspace.
-       */
-      l4_size_t dma_size = size();
-      L4Re::Dma_space::Dma_addr dma_addr = 0;
-      int err = as_mgr->get_phys_mapping(dataspace().get(), ds_offset(),
-                                         &dma_addr, &dma_size);
-
-      if (err < 0 || dma_size < size())
-        warn.printf("DMA offset mode requested, but dataspace not contiguous. "
-                    "DMA usage not recommended.\n");
-
-      _phys_ram = dma_addr;
-      _phys_size = dma_size;
-    }
-  else if (as_mgr->is_iommu_mode())
-    as_mgr->add_ram_iommu(vm_start(), local_start(), size());
-  else
-    info.printf("RAM not set up for DMA.\n");
-
-  l4_addr_t local_start = this->local_start();
-  info.printf("RAM: @ 0x%lx size=0x%lx\n", _vm_start.get(),
-              static_cast(size()));
-  info.printf("RAM: VMM local mapping @ 0x%lx\n", local_start);
-
-  _offset = local_start - _vm_start.get();
-  info.printf("RAM: VM offset=0x%lx\n", _offset);
-
-  return L4_EOK;
-}
-
-
-void
-Ram_ds::load_file(L4::Cap const &file,
-                  Vmm::Guest_addr addr, l4_size_t sz)
-{
-  Dbg info(Dbg::Mmio, Dbg::Info, "file");
-
-  info.printf("load: @ 0x%lx\n", addr.get());
-  if (!file)
-    L4Re::throw_error(-L4_EINVAL, "File dataspace valid.");
-
-  l4_addr_t offset = addr - _vm_start;
-
-  if (addr < _vm_start || sz > size() || offset > size() - sz)
-    {
-      Err().printf("File does not fit into ram. "
-                   "(Loading [0x%lx - 0x%lx] into area [0x%lx - 0x%llx])\n",
-                   addr.get(), addr.get() + sz - 1,
-                   _vm_start.get(), _vm_start.get() + size() - 1);
-      L4Re::throw_error(-L4_EINVAL, "File fits into guest RAM.");
-    }
-
-  info.printf("copy in: to offset 0x%lx-0x%lx\n", offset, offset + sz - 1);
-
-  int r = dataspace()->copy_in(offset + this->offset(), file, 0, sz);
-  if (r != -L4_EINVAL)
-    L4Re::chksys(r, "Copy file into guest RAM.");
-  else
-    {
-      // Failure was due to different dataspace sources. Therefore the dataspace
-      // manager cannot copy directly and we have to do the copy ourselves.
-      const L4Re::Env *e = L4Re::Env::env();
-      char *src = 0;
-      L4Re::chksys(e->rm()->attach(&src, sz,
-                                   L4Re::Rm::F::Search_addr
-                                   | L4Re::Rm::F::R, file),
-                   "Attach file dataspace for reading.");
-      memcpy(reinterpret_cast(local_start()) + offset, src, sz);
-      L4Re::chksys(e->rm()->detach(src, 0),
-                   "Detach file dataspace.");
-    }
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/ram_ds.h b/src/l4/pkg/uvmm/server/src/ram_ds.h
deleted file mode 100644
index 60567a93..00000000
--- a/src/l4/pkg/uvmm/server/src/ram_ds.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2015-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include "device.h"
-#include "device_tree.h"
-#include "ds_manager.h"
-#include "mem_types.h"
-#include "address_space_manager.h"
-
-namespace Vmm {
-
-/**
- * A contiguous piece of RAM backed by a part of an L4 dataspace.
- */
-class Ram_ds : public Vmm::Ds_manager
-{
-public:
-  /**
-   * Create a new RAM dataspace.
-   *
-   * \param ds       L4Re Dataspace that represents the RAM for the VM.
-   * \param size     Size of the region (default: use dataspace size).
-   * \param offset   Offset into the dataspace.
-   * \param flags    Region manager flags of the mapping
-   */
-  Ram_ds(L4Re::Util::Ref_cap::Cap ds,
-         l4_size_t size, l4_addr_t offset,
-         L4Re::Rm::Region_flags flags = L4Re::Rm::F::RWX)
-  : Ds_manager("Ram", ds, offset, size, flags,
-               sizeof(l4_umword_t) == 8 && size >= Ram_hugepagesize
-               ? Ram_hugepageshift : L4_SUPERPAGESHIFT),
-    _phys_size(0U)
-  {}
-
-  Ram_ds(Vmm::Ram_ds const &) = delete;
-  Ram_ds(Vmm::Ram_ds &&) = default;
-  ~Ram_ds() = default;
-
-  /**
-   * Set up the memory for DMA and host access.
-   *
-   * \param vm_base  Guest physical address where the RAM should be mapped.
-   * \param as_mgr  DMA manager to register the RAM with.
-   *
-   * The actually used `vm_base` address might change, depending on the
-   * necessity of DMA and the presence of an IO-MMU.
-   */
-  long setup(Vmm::Guest_addr vm_base, Vmm::Address_space_manager *as_mgr);
-
-  /**
-   * Load the contents of the given dataspace into guest RAM.
-   *
-   * \param file  Dataspace to load from.
-   * \param addr  Guest physical address to load the data space to.
-   * \param sz    Number of bytes to copy.
-   *
-   * \note This function might create a local mapping if it does
-   *       not already exist.
-   */
-  void load_file(L4::Cap const &file,
-                 Vmm::Guest_addr addr, l4_size_t sz);
-
-  /**
-   * Get a VMM-virtual pointer from a guest-physical address
-   */
-  l4_addr_t guest2host(Vmm::Guest_addr p) const noexcept
-  { return p.get() + _offset; }
-
-  L4::Cap ds() const noexcept
-  { return dataspace().get(); }
-
-  void dt_append_dmaprop(Vdev::Dt_node const &mem_node) const
-  {
-    auto parent = mem_node.parent_node();
-    size_t addr_cells = mem_node.get_address_cells(parent);
-    size_t size_cells = mem_node.get_size_cells(parent);
-    mem_node.appendprop("dma-ranges", _phys_ram, addr_cells);
-    mem_node.appendprop("dma-ranges", _vm_start.get(), addr_cells);
-    mem_node.appendprop("dma-ranges", _phys_size, size_cells);
-  }
-
-  Vmm::Guest_addr vm_start() const noexcept { return _vm_start; }
-
-  l4_addr_t local_start() { return local_addr(); }
-  l4_addr_t ds_offset() const noexcept { return offset(); }
-
-  bool has_phys_addr() const noexcept { return _phys_size > 0; }
-
-  bool writable() const { return local_flags() & L4Re::Rm::F::W; }
-
-private:
-  /// Offset between guest-physical and host-virtual address.
-  l4_mword_t _offset;
-  /// Guest-physical address of the mapped dataspace.
-  Vmm::Guest_addr _vm_start;
-
-  /// Host-physical address of the beginning of the mapped area (if applicable).
-  L4Re::Dma_space::Dma_addr _phys_ram;
-  /// Size of the contiguously mapped area from the beginning of the area.
-  l4_size_t _phys_size;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/timer.h b/src/l4/pkg/uvmm/server/src/timer.h
deleted file mode 100644
index a2c21c86..00000000
--- a/src/l4/pkg/uvmm/server/src/timer.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2017, 2020, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *            Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-/**
- * Timer infrastructure.
- *
- * On x86 there is no direct source of time available to user processes.
- * Instead we rely on IPC timeouts. This infrastructure instantiates a
- * timer-thread on each vCPU. The timer-thread implements an API for timer
- * device models to register callbacks together with a timestamp. The timer
- * thread will run the callbacks once the timestamp was reached. Typically the
- * callback will update device model-internal data structures and inject
- * interrupts accordingly.
- *
- * The timer-thread uses L4::Ipc_svr::Timeout_queue for keeping track of
- * callbacks and running them on time. Device models inherit from
- * L4::Ipc_svr::Timeout_queue::Timeout and implement their callbacks by
- * implementing the expired() method. The expired() method runs on the timer
- * thread, so the device model implementer needs to take care of mutual
- * exclusion to avoid race conditions. Also, only the requeue_timeout()
- * function may be used in the expired() method. enqueue_timeout() and
- * dequeue_timeout() make an IPC to the timer thread, which --if executed on
- * the timer thread-- will lock up Uvmm.
- *
- * Because the IPC framework does not handle interfaces, we encapsulate
- * timeouts in a struct and use that for communication with the timer thread.
- *
- * This infrastructure is used by timer device models such as the APIC timer,
- * the PIT and RTC.
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "device.h"
-#include "debug.h"
-
-namespace Vdev {
-
-// Encapsulate Timeout_queue::Timeout pointers for IPC
-struct Timeout_callback
-{
-  Timeout_callback()
-  : timeout(nullptr)
-  {}
-
-  Timeout_callback(L4::Ipc_svr::Timeout_queue::Timeout *t)
-  : timeout(t)
-  {}
-
-  L4::Ipc_svr::Timeout_queue::Timeout *timeout;
-};
-
-struct Clock_source_if : L4::Kobject_t
-{
-  L4_INLINE_RPC(long, add, (Timeout_callback cb, l4_kernel_clock_t timeout));
-  L4_INLINE_RPC(long, remove, (Timeout_callback cb));
-  typedef L4::Typeid::Rpcs Rpcs;
-};
-
-struct Clock_source_adapter
-{
-  virtual L4::Cap ipc_if() = 0;
-  virtual void requeue_timeout(L4::Ipc_svr::Timeout_queue::Timeout *t,
-                               l4_kernel_clock_t timeout) = 0;
-};
-
-/**
- * Interface for the clock device models.
- */
-class Timer : public virtual Vdev::Dev_ref
-{
-public:
-  virtual ~Timer() = 0;
-  void set_clock_source(Clock_source_adapter *source)
-  { _clock_source = source; }
-  virtual void ready() {};
-
-protected:
-  /**
-   * Enqueue a timeout at the timeout queue. `timeout` must be in microseconds.
-   * This must not be used from the timer thread.
-   *
-   */
-  void enqueue_timeout(L4::Ipc_svr::Timeout_queue::Timeout *t,
-                       l4_kernel_clock_t timeout)
-  {
-    long err;
-    if ((err = _clock_source->ipc_if()->add(Timeout_callback(t), timeout)))
-      Err().printf("Error enqueueing timeout: %ld\n", err);
-  }
-
-  /**
-   * Remove a timeout from the timeout queue.
-   * This must not be used from the timer thread.
-   */
-  void dequeue_timeout(L4::Ipc_svr::Timeout_queue::Timeout *t)
-  {
-    long err;
-    if ((err = _clock_source->ipc_if()->remove(Timeout_callback(t))))
-      Err().printf("Error dequeuing timeout: %ld\n", err);
-  }
-
-  /**
-   * Re-queue a timeout.
-   * This must only be called from the timer thread, e.g. from "expired()".
-   */
-  void requeue_timeout(L4::Ipc_svr::Timeout_queue::Timeout *t,
-                       l4_kernel_clock_t timeout)
-  {
-    _clock_source->requeue_timeout(t, timeout);
-  }
-
-private:
-  Clock_source_adapter *_clock_source;
-};
-
-inline Timer::~Timer() = default;
-
-class Clock_source
-: public L4::Epiface_t,
-  public Clock_source_adapter
-{
-public:
-  // Clock_source_if
-  long op_add(Clock_source_if::Rights, Timeout_callback cb,
-             l4_kernel_clock_t timeout)
-  {
-    assert(cb.timeout != nullptr);
-    _server->remove_timeout(cb.timeout);
-    _server->add_timeout(cb.timeout, timeout);
-    return 0;
-  }
-
-  long op_remove(Clock_source_if::Rights, Timeout_callback cb)
-  {
-    assert(cb.timeout != nullptr);
-    _server->remove_timeout(cb.timeout);
-    return 0;
-  }
-
-  // Register a Timer at this Clock source
-  void add_timer(cxx::Ref_ptr timer)
-  { timer->set_clock_source(this); }
-
-  /**
-   * Migrate a vCPU's clock_source thread to its physical core and run the
-   * clock_source loop.
-   *
-   * The migration is needed so the clock_source value is consistent with the
-   * hardware virtualized RDTSC instruction in the guest.
-   *
-   * \param vcpu_no      Guest vCPU number to run the clock_source for.
-   * \param phys_cpu_id  Scheduler id of the physical core to run on.
-   */
-  void run_clock_source(unsigned vcpu_no, unsigned phys_cpu_id,
-                        L4::Cap sem)
-  {
-    // raise clock_source thread prio above vcpu prio
-    l4_sched_param_t sp = l4_sched_param(3);
-    sp.affinity = l4_sched_cpu_set(phys_cpu_id, 0);
-    auto sched = L4Re::Env::env()->scheduler();
-    L4Re::chksys(sched->run_thread(Pthread::L4::cap(pthread_self()), sp),
-                 "Run clock source thread.");
-
-    // instantiate server loop
-    _server = new L4Re::Util::Registry_server(
-      Pthread::L4::cap(pthread_self()), L4Re::Env::env()->factory());
-    _clock_if =
-      L4::cap_cast(_server->registry()->register_obj(this));
-
-    Dbg().printf("Hello clock source for vCPU %u\n", vcpu_no);
-    char buf[18];
-    snprintf(buf, sizeof(buf), "clock source %1u", vcpu_no);
-    l4_debugger_set_object_name(Pthread::L4::cap(pthread_self()).cap(), buf);
-
-    sem->up(); // signal to the vcpu-thread that the timer is ready
-    _server->loop();
-  }
-
-  /**
-   * Start a new thread to run the clock_source loop.
-   *
-   * \param vcpu_no      Guest vCPU number to run the clock_source for.
-   * \param phys_cpu_id  Scheduler id of the physical core to run on.
-   */
-  void start_clock_source_thread(unsigned vcpu_no, unsigned phys_cpu_id)
-  {
-    auto factory = L4Re::Env::env()->factory();
-    L4Re::Util::Unique_cap sem =
-      L4Re::Util::make_unique_cap();
-    L4Re::chksys(factory->create(sem.get()),
-                 "Create clock source thread startup semaphore");
-    _thread = std::thread(&Clock_source::run_clock_source, this, vcpu_no,
-                          phys_cpu_id, sem.get());
-    sem->down(); // wait until timer thread is alive
-  }
-
-  void stop_clock_source_thread()
-  {
-    // pthread manager termination, cleans up these threads before the uvmm
-    // address space vanishes.
-    _thread.detach();
-  }
-
-  // Clock_source_adapter
-  L4::Cap ipc_if() override
-  { return _clock_if; }
-
-  void requeue_timeout(L4::Ipc_svr::Timeout_queue::Timeout *t,
-                       l4_kernel_clock_t timeout) override
-  {
-    _server->remove_timeout(t);
-    _server->add_timeout(t, timeout);
-  }
-
-private:
-  class Loop_hooks
-  : public L4::Ipc_svr::Timeout_queue_hooks,
-    public L4::Ipc_svr::Ignore_errors
-  {
-  public:
-    /**
-     * This function is required by Timeout_queue_hooks to get current time.
-     */
-    l4_kernel_clock_t now()
-    { return l4_kip_clock(l4re_kip()); }
-  };
-
-  std::thread _thread;
-  L4::Cap _clock_if;
-  L4Re::Util::Registry_server *_server;
-};
-
-} // namespace Vdev
diff --git a/src/l4/pkg/uvmm/server/src/vbus_event.cc b/src/l4/pkg/uvmm/server/src/vbus_event.cc
deleted file mode 100644
index 1ab98395..00000000
--- a/src/l4/pkg/uvmm/server/src/vbus_event.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2024 Kernkonzept GmbH.
- * Author: Steffen Liebergeld 
- *         Adam Lackorzynski 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "debug.h"
-#include "vbus_event.h"
-
-static Dbg warn(Dbg::Pm, Dbg::Warn, "vbus_event");
-std::map Vbus_event::_stream_id_handlers;
-
-Vbus_event::Vbus_event(L4::Cap vbus, L4::Registry_iface *registry)
-{
-  if (!vbus)
-    return;
-
-  if (_vbus_event.init(vbus))
-    {
-      warn.printf("Failed to initialize vbus events.\n");
-      return;
-    }
-
-  L4Re::chkcap(registry->register_obj(this,
-                                      L4::cap_cast(_vbus_event.irq())),
-               "Register event IRQ for vbus events");
-}
-
-void
-Vbus_event::handle_irq()
-{
-  L4Re::Event_buffer::Event *e;
-  while ((e = _vbus_event.buffer().next()))
-    {
-      auto handler = _stream_id_handlers.find(e->payload.stream_id);
-      if (handler != _stream_id_handlers.end())
-        handler->second->handle_event(e);
-      e->free();
-    }
-}
-
diff --git a/src/l4/pkg/uvmm/server/src/vbus_event.h b/src/l4/pkg/uvmm/server/src/vbus_event.h
deleted file mode 100644
index 35ae8d81..00000000
--- a/src/l4/pkg/uvmm/server/src/vbus_event.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2024 Kernkonzept GmbH.
- * Author: Steffen Liebergeld 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-class Vbus_stream_id_handler
-{
-public:
-  virtual void handle_event(L4Re::Event_buffer::Event *e) = 0;
-};
-
-/**
- * Interface for incoming vbus events.
- *
- * This class may handle any incoming vbus events such as inhibitor events or
- * input events.
- *
- * We receive events from the vbus and distribute them to their respective
- * stream handlers. Unhandled events are discarded.
- */
-class Vbus_event: public L4::Irqep_t
-{
-public:
-  Vbus_event(L4::Cap vbus, L4::Registry_iface *registry);
-
-  void handle_irq();
-
-  static void register_stream_id_handler(l4_umword_t stream_id,
-                                         Vbus_stream_id_handler *handler)
-  {
-    if (auto h = _stream_id_handlers.find(stream_id);
-             h != _stream_id_handlers.end())
-      Dbg(Dbg::Core, Dbg::Warn, "vbus_event")
-        .printf("Overwriting handler for stream_id 0x%lx\n",
-                stream_id);
-    _stream_id_handlers[stream_id] = handler;
-  }
-
-private:
-  L4Re::Util::Event _vbus_event;
-  static std::map _stream_id_handlers;
-};
diff --git a/src/l4/pkg/uvmm/server/src/vcon_device.h b/src/l4/pkg/uvmm/server/src/vcon_device.h
deleted file mode 100644
index c2ce8210..00000000
--- a/src/l4/pkg/uvmm/server/src/vcon_device.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Frank Mehnert 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-class Vcon_device
-{
-public:
-  Vcon_device(L4::Cap con)
-  : _con(con)
-  {}
-
-  ~Vcon_device()
-  {
-    if (_con_irq.is_valid())
-      if (long err = l4_error(_con->unbind(0, _con_irq)) < 0)
-          Dbg(Dbg::Irq, Dbg::Warn)
-            .printf("Unbind notification IRQ from Vcon: %s\n.",
-                    l4sys_errtostr(err));
-  }
-
-  void attach_con_irq(char const *devname)
-  {
-    l4_msgtag_t ret;
-    L4Re::chkipc(ret = _con->bind(0, _con_irq),
-                 "Bind notification IRQ to Vcon.");
-    if (l4_error(ret) == -L4_ENOSYS)
-      Err()
-        .printf("Note that binding a %s console to the Moe Vcon interface would not work!\n",
-                devname);
-    L4Re::chksys(ret, "Bind notification IRQ to Vcon.");
-  }
-
-  template 
-  void register_obj(L4::Registry_iface *registry)
-  {
-    _con_irq =
-      L4Re::chkcap(registry->register_irq_obj(static_cast(this)),
-                   "Register Vcon notification IRQ.");
-  }
-
-protected:
-  L4::Cap _con;
-
-private:
-  L4::Cap _con_irq;
-};
diff --git a/src/l4/pkg/uvmm/server/src/vcpu_obj_registry.h b/src/l4/pkg/uvmm/server/src/vcpu_obj_registry.h
deleted file mode 100644
index 8fa09152..00000000
--- a/src/l4/pkg/uvmm/server/src/vcpu_obj_registry.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Jan Klötzke 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#pragma once
-
-#include 
-
-/**
- * IPC object registry with the capability to move objects between threads.
- *
- * The plain L4Re Object_registry does not allow to move ownership of objects
- * between registries.
- */
-class Vcpu_obj_registry : public L4Re::Util::Object_registry
-{
-public:
-  explicit Vcpu_obj_registry(L4::Ipc_svr::Server_iface *sif)
-  : L4Re::Util::Object_registry(sif) {}
-
-  L4::Cap server() const
-  { return _server; }
-
-  void set_server(L4::Cap server)
-  { _server = server; }
-
-  /**
-   * Move registered object `o` to this registry.
-   *
-   * The object must already be registered at another Object_registry.
-   *
-   * \param o Pointer to the Epiface object that shall be moved. The object
-   *          must have been registered previously.
-   *
-   * \retval L4::Cap           Capability `o->obj_cap()` on success.
-   * \retval L4::Cap::Invalid  The object could not be moved.
-   *
-   * After the call succeeded newly arriving IPCs will be dispatched at this
-   * registry. Note that concurrent dispatching at the old registry could lead
-   * to IPC calls being delivered there even *after* this call returned if they
-   * are already in flight! It is the responsibility of the caller to
-   * synchronize with the old thread if this is of concern.
-   */
-  L4::Cap
-  move_obj(L4::Epiface *o)
-  {
-    if (!o->obj_cap().is_valid())
-      return L4::Cap(-L4_EINVAL | L4_INVALID_CAP_BIT);
-
-    int err = _sif->alloc_buffer_demand(o->get_buffer_demand());
-    if (err < 0)
-      return L4::Cap(err | L4_INVALID_CAP_BIT);
-
-    L4::Epiface::Stored_cap c = o->obj_cap();
-    auto ep = L4::cap_cast(c);
-    l4_umword_t id = l4_umword_t(o);
-    err = l4_error(ep->bind_thread(_server, id));
-    if (err < 0)
-      return L4::Cap(err | L4_INVALID_CAP_BIT);
-
-    err = o->set_server(_sif, ep, c.managed());
-    if (err < 0)
-      return L4::Cap(err | L4_INVALID_CAP_BIT);
-
-    return ep;
-  }
-};
diff --git a/src/l4/pkg/uvmm/server/src/virt_bus.cc b/src/l4/pkg/uvmm/server/src/virt_bus.cc
deleted file mode 100644
index 8c53b66e..00000000
--- a/src/l4/pkg/uvmm/server/src/virt_bus.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2016-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "device_tree.h"
-#include "mmio_space_handler.h"
-#include "io_port_handler.h"
-#include "virt_bus.h"
-#include "guest.h"
-#include 
-
-namespace Vmm {
-void
-Virt_bus::Irq_bitmap::dump_irqs()
-{
-  for (int i = 0; i < Num_irqs; ++i)
-    {
-      if (irq_present(i))
-        Dbg().printf("Irq %d: %s\n", i, irq_bound(i) ? "bound" : "present");
-    }
-}
-
-void
-Virt_bus::scan_bus()
-{
-  L4vbus::Device io_dev;
-  l4vbus_device_t dev_info;
-  L4vbus::Device root = _bus->root();
-
-  while (root.next_device(&io_dev, L4VBUS_MAX_DEPTH, &dev_info) == 0)
-    {
-      if (dev_info.type
-          & (1 << L4VBUS_INTERFACE_PCI | 1 << L4VBUS_INTERFACE_PCIDEV))
-        {
-          Dbg(Dbg::Dev, Dbg::Trace, "VirtBus")
-            .printf("scan_bus: skipping PCI device %s\n", dev_info.name);
-          continue;
-        }
-
-      _devices.emplace_back(io_dev, dev_info);
-    }
-}
-
-void
-Virt_bus::collect_dev_resources(Virt_bus::Devinfo const &dev,
-                                Vdev::Device_lookup const *devs)
-{
-  for (unsigned i = 0; i < dev.dev_info().num_resources; ++i)
-    {
-      l4vbus_resource_t res;
-
-      L4Re::chksys(dev.io_dev().get_resource(i, &res),
-                   "Cannot get resource in collect_resources");
-
-      char const *resname = reinterpret_cast(&res.id);
-
-      if (res.type == L4VBUS_RESOURCE_MEM)
-        {
-          l4_size_t size = res.end - res.start + 1;
-          auto region = Region::ss(Vmm::Guest_addr(res.start), size,
-                                   Vmm::Region_type::Vbus);
-          unsigned mmio_space_rw = L4VBUS_RESOURCE_F_MEM_MMIO_READ
-                                 | L4VBUS_RESOURCE_F_MEM_MMIO_WRITE;
-          bool is_mmio_space = res.flags & mmio_space_rw;
-          Dbg(Dbg::Dev, Dbg::Info, "ioproxy")
-            .printf("Adding MMIO %s %s.%.4s : [0x%lx - 0x%lx]\n",
-                    is_mmio_space ? "space handler" : "resource",
-                    dev.dev_info().name, resname, res.start, res.end);
-          if (is_mmio_space)
-            {
-              if ((res.flags & mmio_space_rw) != mmio_space_rw)
-                L4Re::chksys(-EINVAL,
-                             "Only Mmio_space handlers for both reading and writing supported");
-
-              auto mmiocap = L4::cap_reinterpret_cast(_bus);
-              auto handler =
-                Vdev::make_device(mmiocap, 0, size,
-                                                            res.start);
-              devs->vmm()->add_mmio_device(region, handler);
-            }
-          else
-            {
-              l4_uint32_t rights = 0;
-              if (res.flags & L4VBUS_RESOURCE_F_MEM_R)
-                rights |= L4_FPAGE_RO;
-              if (res.flags & L4VBUS_RESOURCE_F_MEM_W)
-                rights |= L4_FPAGE_W;
-              auto rm_flags = static_cast(rights);
-              if (res.flags & L4VBUS_RESOURCE_F_MEM_CACHEABLE)
-                rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_normal;
-              else if (res.flags & L4VBUS_RESOURCE_F_MEM_PREFETCHABLE)
-                rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_buffered;
-              else
-                rm_flags = rm_flags | L4Re::Rm::Region_flags::Cache_uncached;
-              auto ds_mgr = cxx::make_ref_obj(
-                std::string("Virt_bus: ") + dev.dev_info().name,
-                io_ds(), res.start, size, rm_flags);
-              auto handler = Vdev::make_device(
-                ds_mgr, static_cast(rights));
-              devs->vmm()->add_mmio_device(region, handler);
-            }
-
-        }
-      else if (res.type == L4VBUS_RESOURCE_IRQ)
-        {
-          Dbg(Dbg::Dev, Dbg::Info, "ioproxy")
-            .printf("Registering IRQ resource %s.%.4s : %lu\n",
-                    dev.dev_info().name, resname, res.start);
-          _irqs.mark_irq_present(res.start);
-        }
-      else if (res.type == L4VBUS_RESOURCE_PORT)
-        {
-          Dbg(Dbg::Dev, Dbg::Info, "ioproxy")
-            .printf("Registering IO Port resource %s.%.4s : 0x%lx - 0x%lx\n",
-                    dev.dev_info().name, resname, res.start, res.end);
-          auto region = Io_region::ss(res.start, res.end - res.start + 1,
-                                      Vmm::Region_type::Vbus);
-          L4Re::chksys(_bus->request_ioport(&res),
-                       "Request IO port resource from vBus.");
-          auto handler = Vdev::make_device(res.start);
-          devs->vmm()->add_io_device(region, handler);
-        }
-    }
-}
-
-void
-Virt_bus::collect_resources(Vdev::Device_lookup const *devs)
-{
-  for (auto &iodev : _devices)
-    {
-      if (iodev.allocated())
-        continue;
-
-      collect_dev_resources(iodev, devs);
-    }
-}
-
-Virt_bus::Devinfo *
-Virt_bus::find_unassigned_device_by_hid(char const *hid)
-{
-  L4vbus::Device vdev;
-  while (_bus->root().device_by_hid(&vdev, hid) >= 0)
-    {
-      for (auto &iodev : _devices)
-        if (   iodev.io_dev().dev_handle() == vdev.dev_handle()
-            && !iodev.allocated())
-          return &iodev;
-    }
-
-  return nullptr;
-}
-
-void Virt_bus::print_resource(l4vbus_resource_t const &res, char const *prefix)
-{
-  union
-  {
-    l4_uint32_t id32;
-    char v[4];
-  } id;
-  id.id32 = res.id;
-
-  const char *types[] = { "Invalid", "IRQ", "Mem", "Port",
-                          "Bus", "GPIO", "DMA-Domain" };
-  const char *rtype = "Unknown";
-  if (res.type < cxx::array_size(types))
-    rtype = types[res.type];
-
-
-  Dbg(Dbg::Dev, Dbg::Info, "vbus").
-    printf("%s%c%c%c%c: 0x%012lx-0x%012lx %s flags=%x\n",
-           prefix,
-           isprint(id.v[0]) ? id.v[0] : '_',
-           isprint(id.v[1]) ? id.v[1] : '_',
-           isprint(id.v[2]) ? id.v[2] : '_',
-           isprint(id.v[3]) ? id.v[3] : '_',
-           res.start, res.end, rtype, res.flags);
-}
-
-void Virt_bus::show_bus()
-{
-  Dbg d(Dbg::Dev, Dbg::Info, "vbus");
-  if (d.is_active())
-    {
-      L4vbus::Device b(_bus, 0);
-      L4vbus::Device dev;
-      l4vbus_device_t dev_info;
-
-      d.printf("Showing vbus contents:\n");
-      while (b.next_device(&dev, L4VBUS_MAX_DEPTH, &dev_info) == 0)
-        {
-          d.printf("%s with %d resources\n",
-                   dev_info.name, dev_info.num_resources);
-
-          for (unsigned i = 0; i < dev_info.num_resources; ++i)
-            {
-              l4vbus_resource_t res;
-              if (dev.get_resource(i, &res))
-                continue;
-
-              print_resource(res, " ");
-            }
-        }
-    }
-}
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/virt_bus.h b/src/l4/pkg/uvmm/server/src/virt_bus.h
deleted file mode 100644
index 45d07ad4..00000000
--- a/src/l4/pkg/uvmm/server/src/virt_bus.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "device.h"
-#include "vbus_event.h"
-#include "msi_allocator.h"
-
-namespace Vmm {
-
-class Virt_bus : public virtual Vdev::Dev_ref, public Vdev::Msi::Allocator
-{
-public:
-  class Devinfo
-  {
-  public:
-    L4vbus::Device io_dev() const
-    { return _io_dev; }
-
-    l4vbus_device_t dev_info() const
-    { return _dev_info; }
-
-    /*
-     * Return the handler managing this device.
-     */
-    cxx::Ref_ptr handler() const
-    { return _handler; }
-
-    /*
-     * Set the handler managing this device.
-     *
-     * \param handler  The handler managing this device.
-     *
-     * A common pattern is to request the unassigned device from vbus and
-     * assign it to the device implementation responsible for it:
-     *
-     *   auto *vdev = devs->vbus()->find_unassigned_device_by_hid(hid);
-     *   ...
-     *   auto c = Vdev::make_device(...);
-     *   vdev->set_handler(c);
-     *
-     * Note: If the device does not have a handler it will be assign to the
-     * io_proxy (if configured).
-     */
-    void set_handler(cxx::Ref_ptr const &handler)
-    { _handler = handler; }
-
-    /*
-     * Check whether a device is already managed by a handler.
-     *
-     * \retval true   The device is already managed by a handler.
-     * \retval false  The device is still free.
-     */
-    bool allocated() const
-    { return _handler != nullptr; }
-
-    Devinfo(L4vbus::Device io_dev, l4vbus_device_t dev_info)
-    : _io_dev(io_dev), _dev_info(dev_info)
-    {}
-
-  private:
-    L4vbus::Device _io_dev;
-    l4vbus_device_t _dev_info;
-    cxx::Ref_ptr _handler;
-  };
-
-private:
-  void collect_dev_resources(Virt_bus::Devinfo const &dev,
-                             Vdev::Device_lookup const *devs);
-
-  /**
-   * Local MSI vector allocator with the vBUS ICU.
-   */
-  class Msi_bitmap
-  {
-    enum { Num_msis = 2048 };
-
-  public:
-    Msi_bitmap() : _max_available(0) { _m.clear_all(); }
-
-    /**
-     * Set the maximum number of available MSIs.
-     *
-     * \param max_avail  Number of MSIs supperted by the vBus ICU.
-     */
-    void set_msi_limit(unsigned max_avail)
-    {
-      // Only allow to set the limit once. It is only necessary once.
-      assert(_max_available == 0);
-
-      _max_available = max_avail;
-
-      if (_max_available > Num_msis)
-        Dbg().printf("Msi_bitmap: ICU supported number of MSIs is greater than "
-                     "the number the allocator supports.\n");
-    }
-
-    long alloc()
-    {
-      std::lock_guard lock(_mut);
-
-      long num = _m.scan_zero();
-
-      if (num < 0 || static_cast(num) >= _max_available)
-        return -L4_ENOMEM;
-
-      _m[num] = 1;
-      return num;
-    }
-
-    void free(unsigned num)
-    {
-      std::lock_guard lock(_mut);
-      _m[num] = 0;
-    }
-
-    unsigned limit() const { return _max_available; }
-
-  private:
-    cxx::Bitmap _m;
-    unsigned _max_available;
-    std::mutex _mut;
-  };
-
-  class Irq_bitmap
-  {
-    enum { Num_irqs = 2048 };
-    cxx::Bitmap _i;
-
-  public:
-    bool irq_present(unsigned irq)
-    { return _i[irq * 2]; }
-
-    bool irq_bound(unsigned irq)
-    { return _i[irq * 2 + 1]; }
-
-    void mark_irq_present(unsigned irq)
-    { _i[irq * 2] = 1; }
-
-    void mark_irq_bound(unsigned irq)
-    {
-      assert(irq_present(irq));
-      _i[irq * 2 + 1] = 1;
-    }
-
-    void dump_irqs();
-  };
-
-public:
-  explicit Virt_bus(L4::Cap bus, L4::Registry_iface *registry)
-  : _bus(bus), _vbus_event(bus, registry)
-  {
-    if (!bus.is_valid())
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "vmbus")
-          .printf("'vbus' capability not found. "
-                  "Hardware access not possible for VM.\n");
-        return;
-      }
-
-    L4vbus::Icu dev;
-    L4Re::chksys(_bus->root().device_by_hid(&dev, "L40009"),
-                 "requesting ICU");
-    _icu = L4Re::chkcap(L4Re::Util::cap_alloc.alloc(),
-                        "allocate ICU cap");
-    L4Re::chksys(dev.vicu(_icu), "requesting ICU cap");
-
-    l4_icu_info_t info;
-    L4Re::chksys(_icu->info(&info), "Request ICU info.");
-
-    unsigned max_msi = 0;
-    if (info.features & L4::Icu::F_msi)
-      max_msi = info.nr_msis;
-
-    _msis.set_msi_limit(max_msi);
-
-    scan_bus();
-
-    show_bus();
-  }
-
-  virtual ~Virt_bus() = default;
-
-  bool available() const
-  { return _bus.is_valid(); }
-
-  bool irq_present(unsigned irq)
-  { return _irqs.irq_present(irq); }
-
-  bool irq_bound(unsigned irq)
-  { return _irqs.irq_bound(irq); }
-
-  void mark_irq_bound(unsigned irq)
-  { return _irqs.mark_irq_bound(irq); }
-
-  void dump_irqs()
-  { _irqs.dump_irqs(); }
-
-  Devinfo const *find_device(Vdev::Device const *handler) const
-  {
-    for (auto const &i: _devices)
-      {
-        if (i.handler() == handler)
-          return &i;
-      }
-    return nullptr;
-  }
-
-  /// Allocate a MSI vector with the app global MSI allocator.
-  long alloc_msi() override { return _msis.alloc(); }
-  /// Free a previously allocated MSI vector.
-  void free_msi(unsigned num) override { _msis.free(num); }
-  /// Maximum number of MSIs at the ICU.
-  unsigned max_msis() const override { return _msis.limit(); }
-
-  /*
-   * Lookup unassigned device by hid
-   *
-   * \param hid  The hid we are looking for.
-   *
-   * \return  Pointer to unallocated device, nullptr if device not present or
-   *          already claimed by someone else. To claim the device, invoke
-   *          Devinfo::set_handler().
-   *
-   * The method iterates over the vbus and tries to find a device matching hid.
-   * If a device is found and not allocated it is returned. Otherwise we
-   * continue the iteration.
-   */
-  Devinfo *find_unassigned_device_by_hid(char const *hid);
-
-  /**
-   * Collect all resources available on the vbus
-   *
-   * \param devs  Reference to device lookup instance
-   *
-   * \retval true   Successfully collected all resources
-   * \retval false  Failed to collect resources
-   *
-   * Iterate over all unallocated devices on the vbus and collect available
-   * resources. The function looks at memory and irq resources. Memory is
-   * mapped and added to the memory map. Irqs are tracked in a bitmap and may
-   * be bind later on (see irq_present(), irq_bound(), mark_irq_bound()).
-   */
-  void collect_resources(Vdev::Device_lookup const *devs);
-
-  L4::Cap io_ds() const
-  { return L4::cap_reinterpret_cast(_bus); }
-
-  L4::Cap bus() const
-  { return _bus; }
-
-  L4::Cap icu() const override
-  { return _icu; }
-
-  static void print_resource(l4vbus_resource_t const &res,
-                             const char *prefix = "");
-
-  void show_bus();
-
-private:
-  void scan_bus();
-
-  L4::Cap _bus;
-  Vbus_event _vbus_event;
-  L4::Cap _icu;
-  std::vector _devices;
-  Irq_bitmap _irqs;
-  Msi_bitmap _msis;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virt_pci_device.cc b/src/l4/pkg/uvmm/server/src/virt_pci_device.cc
deleted file mode 100644
index 4afee8f9..00000000
--- a/src/l4/pkg/uvmm/server/src/virt_pci_device.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "guest.h"
-#include "virt_pci_device.h"
-#include "device/pci_host_bridge.h"
-
-namespace Vdev { namespace Pci {
-
-Virt_pci_device::Virt_pci_device(Vdev::Dt_node const &node,
-                                 Pci_bridge_windows *wnds)
-: Virt_pci_device()
-{
-  l4_uint64_t size;
-  Dtb::Reg_flags flags;
-
-  // First reg entry shall be the config space. Note that we ignore the
-  // assigned bus/device/function numbers. This might change in the future!
-  if (node.get_reg_size_flags(0, nullptr, &flags) < 0)
-    L4Re::throw_error(-L4_EINVAL, "extract PCI dev reg[0] property");
-  if (!flags.is_cfgspace())
-    L4Re::throw_error(-L4_EINVAL,
-                      "PCI dev reg[0] property shall be the config space");
-
-  for (int i = 1; node.get_reg_size_flags(i, &size, &flags) >= 0; i++)
-    {
-      unsigned bar = (flags.pci_reg() - Pci_hdr_base_addr0_offset) / 4U;
-      if (bar >= Bar_num_max_type0)
-        L4Re::throw_error(-L4_EINVAL,
-                          "PCI dev reg property must reference valid BAR");
-      if (bars[bar].type != Pci_cfg_bar::Type::Unused_empty)
-        L4Re::throw_error(-L4_EINVAL, "BAR must be defined only once");
-      check_power_of_2(size, "BAR size must be power of 2");
-
-      if (flags.is_mmio64())
-        {
-          l4_addr_t addr =
-            wnds->alloc_bar_resource(size, Pci_cfg_bar::Type::MMIO64);
-          set_mem64_space(bar, addr, size);
-        }
-      else if (flags.is_mmio32())
-        {
-          l4_addr_t addr =
-            wnds->alloc_bar_resource(size, Pci_cfg_bar::Type::MMIO32);
-          set_mem_space(bar, addr, size);
-        }
-      else if (flags.is_ioport())
-        {
-          l4_addr_t addr =
-            wnds->alloc_bar_resource(size, Pci_cfg_bar::Type::IO);
-          set_io_space(bar, addr, size);
-        }
-      else
-        L4Re::throw_error(-L4_EINVAL,
-                          "PCI dev reg property has invalid type");
-
-      info().printf("  bar[%u] addr=0x%llx size=0x%llx type=%s\n", bar,
-                    bars[bar].io_addr, bars[bar].size, bars[bar].to_string());
-    }
-}
-void Virt_pci_device::add_decoder_resources(Vmm::Guest *vmm, l4_uint32_t access)
-{
-  unsigned i = 0;
-  for (auto &bar : bars)
-    {
-      switch (bar.type)
-        {
-        case Pci_cfg_bar::Unused_empty:
-        case Pci_cfg_bar::Reserved_mmio64_upper:
-          break;
-        case Pci_cfg_bar::MMIO32:
-        case Pci_cfg_bar::MMIO64:
-          if (!(access & Memory_space_bit))
-            break;
-
-          vmm->add_mmio_device(Vmm::Region::ss(Vmm::Guest_addr(bar.map_addr),
-                                               bar.size,
-                                               Vmm::Region_type::Virtual,
-                                               Vmm::Region_flags::Moveable),
-                               get_mmio_bar_handler(i));
-          break;
-        case Pci_cfg_bar::IO:
-          if (!Vmm::Guest::Has_io_space || !(access & Io_space_bit))
-            break;
-
-          vmm->add_io_device(Vmm::Io_region::ss(bar.map_addr, bar.size,
-                                                Vmm::Region_type::Virtual,
-                                                Vmm::Region_flags::Moveable),
-                             get_io_bar_handler(i));
-          break;
-        }
-      i++;
-    }
-}
-
-void Virt_pci_device::del_decoder_resources(Vmm::Guest *vmm, l4_uint32_t access)
-{
-  for (auto &bar : bars)
-    {
-      switch (bar.type)
-        {
-        case Pci_cfg_bar::Unused_empty:
-        case Pci_cfg_bar::Reserved_mmio64_upper:
-          break;
-        case Pci_cfg_bar::MMIO32:
-        case Pci_cfg_bar::MMIO64:
-          if (access & Memory_space_bit)
-            vmm->del_mmio_device(Vmm::Region::ss(Vmm::Guest_addr(bar.map_addr),
-                                                 bar.size,
-                                                 Vmm::Region_type::Virtual,
-                                                 Vmm::Region_flags::Moveable));
-          break;
-        case Pci_cfg_bar::IO:
-          if (Vmm::Guest::Has_io_space && access & Io_space_bit)
-            vmm->del_io_device(Vmm::Io_region::ss(bar.map_addr, bar.size,
-                                                  Vmm::Region_type::Virtual,
-                                                  Vmm::Region_flags::Moveable));
-          break;
-        }
-    }
-}
-
-}} // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/virt_pci_device.h b/src/l4/pkg/uvmm/server/src/virt_pci_device.h
deleted file mode 100644
index de967810..00000000
--- a/src/l4/pkg/uvmm/server/src/virt_pci_device.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2023-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include "device_tree.h"
-#include "mem_access.h"
-#include "pci_device.h"
-#include "mmio_device.h"
-#include "io_device.h"
-#include "device/pci_bridge_windows.h"
-
-namespace Vdev { namespace Pci {
-
-class Virt_pci_device:
-  public Pci_device
-{
-public:
-  Virt_pci_device()
-  {
-    memset(&_hdr, 0, sizeof(_hdr));
-    _last_caps_next_ptr = &get_header()->cap_ptr;
-    _next_free_idx = 0x40; // first byte after the PCI header;
-  }
-
-  /**
-   * Construct virtual PCI device from device tree node.
-   *
-   * This implies a type0 device.
-   */
-  Virt_pci_device(Vdev::Dt_node const &node, Pci_bridge_windows *wnds);
-
-  /**
-   * Read from the PCI header config.
-   *
-   * \param      reg    The config space register to read from.
-   * \param[out] value  The value returned by the read. -1 if failed.
-   * \param      width  The width of the register access.
-   */
-  void cfg_read_raw(unsigned reg, l4_uint32_t *value,
-                    Vmm::Mem_access::Width width) override
-  {
-    using Vmm::Mem_access;
-
-    *value = -1;
-
-    if (!check_cfg_range(reg, width))
-      return;
-
-    reg >>= width;
-    switch (width)
-      {
-      case Mem_access::Wd8: *value  = _hdr.byte[reg]; break;
-      case Mem_access::Wd16: *value = _hdr.word[reg]; break;
-      case Mem_access::Wd32: *value = _hdr.dword[reg]; break;
-      case Mem_access::Wd64: *value = _hdr.qword[reg]; break;
-      }
-
-    trace().printf("read config 0x%x(%d) = 0x%x\n", reg, width,
-                   static_cast(*value));
-  }
-
-  /**
-   * Write to the PCI header config.
-   *
-   * \param reg    Register number to write to.
-   * \param value  Value to write to `reg`.
-   * \param width  Width of the memory access.
-   */
-  void cfg_write_raw(unsigned reg, l4_uint32_t value,
-                     Vmm::Mem_access::Width width) override
-  {
-    using Vmm::Mem_access;
-
-    if (!check_cfg_range(reg, width))
-      return;
-
-    if (   reg == Pci_hdr_status_offset
-        && ((8U << width)) == Pci_hdr_status_length)
-      return;
-
-    reg >>= width;
-    switch (width)
-      {
-      case Mem_access::Wd8:  _hdr.byte[reg] = value; break;
-      case Mem_access::Wd16: _hdr.word[reg] = value; break;
-      case Mem_access::Wd32: _hdr.dword[reg] = value; break;
-      case Mem_access::Wd64: _hdr.qword[reg] = value; break;
-      }
-
-    trace().printf("write config 0x%x(%d) = 0x%x\n", reg, width, value);
-  }
-
-  /**
-   * Create a PCI capability of type `T` in the device's capability table.
-   *
-   * \tparam T  Type of the capability to create. The type must have a Cap_id
-   *            member defining the PCI capability ID.
-   *
-   * Allocate a new PCI capability in the PCI header config space and enqueue
-   * it in the cap list.
-   *
-   * \return  Pointer to the new typed capability.
-   */
-  template 
-  T *create_pci_cap()
-  {
-    // _next_free_idx: next location for a capability
-    assert(_next_free_idx < sizeof(_hdr));
-    assert(_last_caps_next_ptr < (l4_uint8_t *)(&_hdr + 1));
-
-    l4_uint8_t cap_offset = align_min_dword(_next_free_idx);
-
-    // guard against wrap around of uint8
-    assert(cap_offset >= 0x40);
-    assert((unsigned)cap_offset + sizeof(T) < 0x100);
-
-    T *ret = new (&_hdr.byte[cap_offset]) T();
-    trace().printf("cap offset 0x%x, cap size 0x%zx\n", cap_offset,
-                   sizeof(*ret));
-
-    *_last_caps_next_ptr = cap_offset;
-    _last_caps_next_ptr = &ret->cap_next;
-
-    _next_free_idx = cap_offset + sizeof(*ret);
-
-    trace().printf("indexes: cap's next ptr %p, next free byte 0x%x\n",
-                   &_last_caps_next_ptr, _next_free_idx);
-
-    ret->cap_next = 0;
-    assert(ret->cap_type == T::Cap_id);
-    return ret;
-  }
-
-  void add_decoder_resources(Vmm::Guest *vmm, l4_uint32_t access) override;
-  void del_decoder_resources(Vmm::Guest *vmm, l4_uint32_t access) override;
-
-  void add_exp_rom_resource() override {};
-  void del_exp_rom_resource() override {};
-
-private:
-  template 
-  static void assert_header_type()
-  {
-    static_assert(    (std::is_same::value)
-                   || (std::is_same::value),
-                  "Invalid PCI header type requested.");
-  }
-
-  template 
-  static void assert_bar_type_size(unsigned bar)
-  {
-    static_cast(bar);
-    if (std::is_same::value)
-      assert(bar < Bar_num_max_type0);
-    else if (std::is_same::value)
-      assert(bar < Bar_num_max_type1);
-  }
-
-  /**
-   * Test if the requested access references a location inside the PCI
-   * configuration.
-   *
-   * \param reg    Location inside the PCI header to be accessed.
-   * \param width  Access width.
-   *
-   * \retval True  If the access falls inside the PCI configuration area.
-   * \retval False Otherwise.
-   */
-  bool check_cfg_range(unsigned reg, Vmm::Mem_access::Width width) const
-  {
-    if (width == Vmm::Mem_access::Wd64)
-      return false;
-
-    unsigned w = 1U << width;
-    bool ret = (reg + w) <= Pci_header_size;
-    if (!ret)
-      trace().printf("config access 0x%x(%d): out of range\n", reg, width);
-
-    return ret;
-  }
-
-  inline void
-  check_power_of_2(l4_uint64_t size, char const *err)
-  {
-    if (size & (size - 1))
-      L4Re::chksys(-L4_EINVAL, err);
-  }
-
-protected:
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "Virt PCI dev"); }
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "Virt PCI dev"); }
-  static Dbg dbg() { return Dbg(Dbg::Dev, Dbg::Warn, "Virt PCI dev"); }
-
-  virtual cxx::Ref_ptr get_mmio_bar_handler(unsigned bar) = 0;
-  virtual cxx::Ref_ptr get_io_bar_handler(unsigned bar) = 0;
-
-  /**
-   * Get a pointer to the header memory of type `TYPE`.
-   *
-   * \tparam TYPE  PCI header type 0 or 1.
-   */
-  template 
-  TYPE *get_header()
-  {
-    assert_header_type();
-
-    return reinterpret_cast(&_hdr);
-  }
-
-  template 
-  TYPE const *get_header() const
-  {
-    assert_header_type();
-
-    return reinterpret_cast(&_hdr);
-  }
-
-  void dump_header() const
-  {
-    for (unsigned i = 0; i < Pci_header_size; i += 4)
-      info().printf("0x%x:: 0x%x 0x%x \t 0x%x 0x%x\n", i, _hdr.byte[i],
-                     _hdr.byte[i + 1], _hdr.byte[i + 2], _hdr.byte[i + 3]);
-  }
-
-  /// Align cap address at least to DWORD or to `CAP` requirement.
-  template 
-  l4_uint8_t align_min_dword(l4_uint8_t addr)
-  {
-    l4_uint8_t align = alignof(CAP) < 4 ? 4 : alignof(CAP);
-    return (addr + align - 1) & ~(align - 1);
-  }
-
-  /**
-   * Configure a BAR address as IO BAR address.
-   *
-   * \param bar   BAR number
-   * \param addr  Address to write to BAR.
-   * \param size  Size of the memory referenced by `addr`.
-   */
-  template 
-  void set_io_space(unsigned bar, l4_uint32_t addr, l4_size_t size)
-  {
-    assert_bar_type_size(bar);
-
-    bars[bar].map_addr = addr & ~Bar_io_attr_mask;
-    bars[bar].type = Pci_cfg_bar::Type::IO;
-    set_bar_size(bar, size);
-  }
-
-  /**
-   * Configure a BAR address as 32-bit memory BAR address.
-   *
-   * \param bar   BAR number
-   * \param addr  Address to write to BAR.
-   * \param size  Size of the memory referenced by `addr`.
-   */
-  template 
-  void set_mem_space(unsigned bar, l4_uint32_t addr, l4_uint32_t size)
-  {
-    assert_bar_type_size(bar);
-
-    bars[bar].map_addr = addr & ~Bar_mem_attr_mask;
-    bars[bar].type = Pci_cfg_bar::Type::MMIO32;
-    set_bar_size(bar, size);
-  }
-
-  /**
-   * Configure a BAR address as 64-bit memory BAR address.
-   *
-   * Attention: this will occupy *two* BAR registers!
-   *
-   * \param bar   BAR number
-   * \param addr  Address to write to BAR.
-   * \param size  Size of the memory referenced by `addr`.
-   */
-  template 
-  void set_mem64_space(unsigned bar, l4_uint64_t addr, l4_uint64_t size)
-  {
-    assert_bar_type_size(bar);
-
-    bars[bar + 0].map_addr = addr & ~Bar_mem_attr_mask;
-    bars[bar + 0].type = Pci_cfg_bar::Type::MMIO64;
-    bars[bar + 1].type = Pci_cfg_bar::Type::Reserved_mmio64_upper;
-    set_bar_size(bar, size);
-  }
-
-  /**
-   * Set the size of a BAR. According to the PCI spec, this value is rounded up
-   * to the nearest power of two >= 16.
-   *
-   * \param bar   BAR number.
-   * \param size  BAR size.
-   */
-  void set_bar_size(unsigned bar, l4_uint64_t size)
-  {
-    // Keep in mind that __builtin_clzl(0) is undefined.
-    if (size < 16)
-      size = 16;
-    else
-      size = 1ULL << (8 * sizeof(unsigned long long) - __builtin_clzll(size - 1U));
-    bars[bar].size = size;
-  }
-
-  Pci_header _hdr;
-  /// Index into _hdr.byte array
-  l4_uint8_t _next_free_idx;
-  /// Index into _hdr.byte array
-  l4_uint8_t *_last_caps_next_ptr;
-};
-
-} } // namespace Vdev::Pci
diff --git a/src/l4/pkg/uvmm/server/src/virtio_console.cc b/src/l4/pkg/uvmm/server/src/virtio_console.cc
deleted file mode 100644
index 5817e1ab..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_console.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-#include 
-
-#include "virtio_console.h"
-#include "device_factory.h"
-#include "guest.h"
-
-#include 
-
-namespace {
-
-using namespace Vdev;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    Dbg(Dbg::Dev, Dbg::Info).printf("Create virtual console\n");
-
-    /* Deprecation warning, added 2021-08 */
-    if (node.has_prop("l4vmm,virtiocap"))
-      Dbg(Dbg::Dev, Dbg::Warn).printf("Device tree node for Virtio console"
-                                      " contains old property 'l4vmm,virtiocap',"
-                                      " which has been renamed to 'l4vmm,vcon_cap'\n");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,vcon_cap",
-                                       L4Re::Env::env()->log());
-    if (!cap)
-      return nullptr;
-
-    auto c = make_device(devs->ram().get(), cap);
-    if (c->init_irqs(devs, node) < 0)
-      return nullptr;
-
-    c->register_obj(devs->vmm()->registry());
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-    return c;
-  }
-};
-
-static F f;
-static Device_type t = { "virtio,mmio", "console", &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virtio_console.h b/src/l4/pkg/uvmm/server/src/virtio_console.h
deleted file mode 100644
index 9a4238eb..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_console.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "mmio_device.h"
-#include "debug.h"
-#include "irq.h"
-#include "vcon_device.h"
-#include "virtio_dev.h"
-#include "virtio_event_connector.h"
-
-#include 
-#include 
-
-#include 
-
-#include 
-
-namespace Vdev {
-
-/**
- * Virtio device that lets guests communicate with an L4::Vcon object.
- *
- * Example device tree entry to make it available to guests:
- *
- * \code{.dtb}
- *   virtio_uart@20000 {
- *       compatible = "virtio,mmio";
- *       reg = <0x20000 0x100>;
- *       interrupt-parent = <0x1>;
- *       interrupts = <0x0 0x7a 0x4>;
- *       l4vmm,vdev = "console";
- *       l4vmm,vcon_cap = "guest_log";
- *   };
- * \endcode
- *
- * "l4vmm,vcon_cap" is a capability to a L4::Vcon passed to uvmm. If it is not
- * given in the device tree or no such capability exists in uvmm's initial
- * namespace, the log of L4Re::Env is used.
- */
-template 
-class Virtio_console
-: public Virtio::Dev,
-  public Vcon_device,
-  public L4::Irqep_t >
-{
-  typedef L4virtio::Svr::Virtqueue::Desc Desc;
-  typedef L4virtio::Svr::Request_processor Request_processor;
-
-  struct Payload
-  {
-    char *data;
-    unsigned len;
-    bool writable;
-  };
-
-  enum
-  {
-    Console_queue_num = 2,
-    Console_queue_length = 0x100,
-  };
-
-  Virtio::Virtqueue _vqs[Console_queue_num];
-
-public:
-  struct Features : Virtio::Dev::Features
-  {
-    CXX_BITFIELD_MEMBER(0, 0, console_size, raw);
-    CXX_BITFIELD_MEMBER(1, 1, console_multiport, raw);
-
-    explicit Features(l4_uint32_t v)
-    : Virtio::Dev::Features(v)
-    {}
-  };
-
-  Virtio_console(Vmm::Vm_ram *ram, L4::Cap con)
-  : Virtio::Dev(ram, 0x44, L4VIRTIO_ID_CONSOLE),
-    Vcon_device(con)
-  {
-    Features feat(0);
-    feat.ring_indirect_desc() = true;
-    _cfg_header->dev_features_map[0] = feat.raw;
-    _cfg_header->num_queues = Console_queue_num;
-
-    for (auto &q : _vqs)
-      q.config.num_max = Console_queue_length;
-
-    l4_vcon_attr_t attr;
-    if (l4_error(con->get_attr(&attr)) != L4_EOK)
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "cons")
-          .printf("WARNING: Cannot set console attributes. "
-                  "Output may not work as expected.\n");
-        return;
-      }
-
-    attr.set_raw();
-    L4Re::chksys(con->set_attr(&attr), "console set_attr");
-  }
-
-  void virtio_queue_ready(unsigned ready)
-  {
-    auto *q = current_virtqueue();
-    if (!q)
-      return;
-
-    auto *qc = &q->config;
-
-    if (ready == 0 && q->ready())
-      {
-        q->disable();
-        qc->ready = 0;
-      }
-    else if (ready == 1 && !q->ready())
-      {
-        qc->ready = 0;
-        l4_uint16_t num = qc->num;
-        // num must be: a power of two in range [1,num_max].
-        if (!num || (num & (num - 1)) || num > qc->num_max)
-          return;
-
-        q->init_queue(dev()->template devaddr_to_virt(qc->desc_addr),
-                      dev()->template devaddr_to_virt(qc->avail_addr),
-                      dev()->template devaddr_to_virt(qc->used_addr));
-        qc->ready = 1;
-
-        attach_con_irq("VirtIO console");
-      }
-  }
-
-  int init_irqs(Vdev::Device_lookup *devs, Vdev::Dt_node const &self)
-  { return dev()->event_connector()->init_irqs(devs, self); }
-
-  void reset() override
-  {
-    for (auto &q : _vqs)
-      {
-        q.disable();
-        q.config.ready = 0;
-      }
-  }
-
-  void virtio_queue_notify(unsigned)
-  {
-    Virtio::Event_set ev;
-
-    handle_input(&ev);
-    int const q_idx = 1;
-    auto *q = &_vqs[q_idx];
-
-    while (q->ready())
-      {
-        auto r = q->next_avail();
-
-        if (!r)
-          break;
-
-        Request_processor rp;
-        Payload p;
-        rp.start(this, r, &p);
-        while (p.len)
-          {
-            long rsz = _con->write(p.data, p.len);
-            if (rsz < 0)
-              break;
-            p.data += rsz;
-            p.len  -= rsz;
-          }
-
-        q->consumed(r);
-        if (!q->no_notify_guest())
-          {
-            _irq_status_shadow |= 1;
-            ev.set(q->config.driver_notify_index);
-          }
-      }
-
-    if (_cfg_header->irq_status != _irq_status_shadow)
-      dev()->set_irq_status(_irq_status_shadow);
-
-    dev()->event_connector()->send_events(cxx::move(ev));
-  }
-
-  void load_desc(Desc const &desc, Request_processor const *, Payload *p)
-  {
-    p->data = devaddr_to_virt(desc.addr.get(), desc.len);
-    p->len = desc.len;
-    p->writable = desc.flags.write();
-  }
-
-  void load_desc(Desc const &desc, Request_processor const *,
-                 Desc const **table)
-  {
-    *table = devaddr_to_virt(desc.addr.get(), sizeof(Desc));
-  }
-
-
-  void handle_input(Virtio::Event_set *ev)
-  {
-    int const q_idx = 0;
-    auto *q = &_vqs[q_idx];
-
-    while (1)
-      {
-        int r = _con->read(NULL, 0);
-
-        if (r <= 0)
-          break; // empty
-
-        if (!q->ready())
-          {
-            // drop input
-            do
-              {
-                r = _con->read(NULL, L4_VCON_READ_SIZE);
-              }
-            while (r > L4_VCON_READ_SIZE);
-            break;
-          }
-
-        auto req = q->next_avail();
-
-        if (!req)
-          break;
-
-        Request_processor rp;
-        Payload p;
-        rp.start(this, req, &p);
-
-        if (!p.writable)
-          {
-            Err().printf("Virtio_console: error read-only buffer in input queue\n");
-            break;
-          }
-
-        r = _con->read(p.data, p.len);
-        if (r < 0)
-          {
-            Err().printf("Virtio_console: read error: %d\n", r);
-            break;
-          }
-
-        unsigned size = static_cast(r) <= p.len
-                        ? static_cast(r) : p.len;
-        q->consumed(req, size);
-
-        if (!q->no_notify_guest())
-          {
-            dev()->_irq_status_shadow |= 1;
-            ev->set(q->config.driver_notify_index);
-          }
-
-        if (static_cast(r) <= p.len)
-          break;
-      }
-  }
-
-  void handle_irq()
-  {
-    Virtio::Event_set ev;
-    handle_input(&ev);
-
-    if (_cfg_header->irq_status != _irq_status_shadow)
-      dev()->set_irq_status(_irq_status_shadow);
-
-    dev()->event_connector()->send_events(cxx::move(ev));
-  }
-
-  void virtio_irq_ack(unsigned val)
-  {
-    _irq_status_shadow &= ~val;
-    if (_cfg_header->irq_status != _irq_status_shadow)
-      dev()->set_irq_status(_irq_status_shadow);
-
-    dev()->event_connector()->clear_events(val);
-  }
-
-  Virtio::Virtqueue *virtqueue(unsigned qn) override
-  {
-    if (qn >= Console_queue_num)
-      return nullptr;
-
-    return &_vqs[qn];
-  }
-private:
-  DEV *dev() { return static_cast(this); }
-};
-
-class Virtio_console_mmio
-: public Virtio_console,
-  public Vmm::Ro_ds_mapper_t,
-  public Virtio::Mmio_connector
-{
-public:
-  Virtio_console_mmio(Vmm::Vm_ram *ram, L4::Cap con)
-  : Virtio_console(ram, con)
-  {}
-
-  Virtio::Event_connector_irq *event_connector() { return &_evcon; }
-
-  char const *dev_name() const override { return "Virtio_console_mmio"; }
-
-private:
-  Virtio::Event_connector_irq _evcon;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virtio_console_pci.cc b/src/l4/pkg/uvmm/server/src/virtio_console_pci.cc
deleted file mode 100644
index c88986c7..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_console_pci.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-
-#include "debug.h"
-#include "device_factory.h"
-#include "guest.h"
-#include "ds_mmio_mapper.h"
-#include "pci_virtio_device.h"
-#include "virtio_pci_connector.h"
-#include "virtio_console.h"
-#include "event_connector_pci.h"
-#include "device/pci_host_bridge.h"
-
-class Virtio_console_pci
-: public Vdev::Virtio_console,
-  public Vdev::Pci::Virtio_device_pci,
-  public Virtio::Pci_connector
-{
-public:
-  Virtio_console_pci(Vdev::Dt_node const &node, unsigned num_msix_entries,
-                     Vmm::Vm_ram *ram, L4::Cap con,
-                     Gic::Msix_dest const &msix_dest,
-                     Vdev::Pci::Pci_bridge_windows *wnds)
-  : Virtio_console(ram, con),
-    Virtio_device_pci(node, num_msix_entries, wnds),
-    Virtio::Pci_connector(),
-    _evcon(num_msix_entries, msix_dest)
-  {
-    init_virtio_pci_device();
-  }
-
-  Virtio::Event_connector_msix *event_connector() { return &_evcon; }
-
-protected:
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned idx) override
-  {
-    if (idx == 0)
-      return event_connector()->make_mmio_device();
-
-    return cxx::Ref_ptr(this);
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  {
-    return cxx::Ref_ptr(this);
-  }
-
-private:
-  Virtio::Event_connector_msix _evcon;
-};
-
-namespace {
-
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-struct F : Factory
-{
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "VIO Cons"); }
-
-  cxx::Ref_ptr create(Vdev::Device_lookup *devs,
-                                    Vdev::Dt_node const &node) override
-  {
-    info().printf("Create virtual PCI console\n");
-
-    auto *pci = dynamic_cast(
-      devs->device_from_node(node.parent_node()).get());
-
-    if (!pci)
-      {
-        info().printf("No PCI bus found.\n");
-        return nullptr;
-      }
-
-    /* Deprecation warning */
-    if (node.has_prop("l4vmm,virtiocap"))
-      Dbg(Dbg::Dev, Dbg::Warn).printf("Device tree node for Virtio console pci"
-                                      " contains old property 'l4vmm,virtiocap',"
-                                      " which has been renamed to 'l4vmm,vcon_cap'\n");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,vcon_cap",
-                                       L4Re::Env::env()->log());
-    if (!cap)
-      return nullptr;
-
-    auto dev_id = pci->bus()->alloc_dev_id();
-    unsigned num_msix = 5;
-    auto console =
-      make_device(node, num_msix, devs->ram().get(), cap,
-                                      pci->msix_dest(dev_id),
-                                      pci->bridge_windows());
-
-    console->register_obj(devs->vmm()->registry());
-    pci->bus()->register_device(console, dev_id);
-
-    info().printf("Console: %p\n", console.get());
-
-    return console;
-  }
-}; // struct F
-
-static F f;
-static Device_type t = {"virtio,pci", "console", &f};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/virtio_dev.h b/src/l4/pkg/uvmm/server/src/virtio_dev.h
deleted file mode 100644
index 4b58b2a8..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_dev.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "device.h"
-#include "mem_access.h"
-#include "vm_ram.h"
-#include "virtio_qword.h"
-#include "monitor/virtio_cmd_handler.h"
-
-namespace Virtio {
-
-class Virtqueue : public L4virtio::Svr::Virtqueue
-{
-public:
-  typedef l4virtio_config_queue_t Queue_config;
-
-  Queue_config config;
-
-  Virtqueue()
-  { memset(&config, 0, sizeof(config)); }
-
-  void init_queue(void *desc, void *avail, void *used)
-  { setup(config.num, desc, avail, used); }
-
-};
-
-struct Event_set
-{
-  l4_uint64_t e = 0;
-  void reset() { e = 0; };
-  void set(l4_uint16_t index)
-  {
-    if (index < sizeof(e) * 8)
-      e |= 1ULL << index;
-  }
-};
-
-/**
- * Abstract interface for virtio event handling.
- *
- * \note This interface is currently just for the sake of documentation.
- */
-class Event_if
-{
-public:
-  /**
-   * Inject the given set of events into the VM.
-   *
-   * \param ev  Set of pending events to be injected into the guest.
-   */
-  virtual void send_events(Event_set &&ev) = 0;
-
-  /**
-   * Acknowledge via the virtio irq_ack register.
-   *
-   * \param mask  The value written to the virtio irq_ack register.
-   */
-  virtual void clear_events(unsigned mask) = 0;
-};
-
-class Dev
-: public Vdev::Device,
-  public Monitor::Virtio_dev_cmd_handler
-{
-public:
-  typedef L4virtio::Svr::Dev_status Status;
-  typedef L4virtio::Svr::Dev_features Features;
-  typedef l4virtio_config_queue_t Queue_config;
-
-protected:
-  enum { Config_ds_size = L4_PAGESIZE };
-  l4_uint32_t _irq_status_shadow = 0;
-  l4_uint16_t _config_event_index = 0;
-
-  L4Re::Rm::Unique_region _cfg_header;
-  L4Re::Util::Unique_del_cap _cfg_ds;
-
-  void update_virtio_config()
-  {
-    l4_cache_clean_data(reinterpret_cast(_cfg_header.get()),
-                        reinterpret_cast(_cfg_header.get())
-                        + Config_ds_size);
-  }
-
-public:
-  Dev(Vmm::Vm_ram *ram, l4_uint32_t vendor, l4_uint32_t device)
-  : _ram(ram)
-  {
-    auto *e = L4Re::Env::env();
-    auto ds = L4Re::chkcap(L4Re::Util::make_unique_del_cap(),
-                           "Alocate Virtio::Dev dataspace capability.");
-
-    L4Re::chksys(e->mem_alloc()->alloc(Config_ds_size, ds.get()),
-                 "Allocate Virtio::Dev configuration memory.");
-
-    L4Re::Rm::Unique_region cfg;
-    L4Re::chksys(e->rm()->attach(&cfg, Config_ds_size,
-                                 L4Re::Rm::F::Search_addr | L4Re::Rm::F::Eager_map
-                                 | L4Re::Rm::F::RW
-                                 , //| L4Re::Rm::Cache_uncached,
-                                 L4::Ipc::make_cap_rw(ds.get())),
-                 "Attach Virtio::Dev configuration memory in address space.");
-
-    _cfg_ds = cxx::move(ds);
-    _cfg_header = cxx::move(cfg);
-
-    _cfg_header->magic = 0x74726976; // virt
-    _cfg_header->version = 2;
-    _cfg_header->device = device;
-    _cfg_header->vendor = vendor;
-    _cfg_header->dev_features_map[1] = 1; // set VERSION 1 flag
-
-    update_virtio_config();
-  }
-
-  virtual Virtqueue *virtqueue(unsigned qn) = 0;
-
-  Virtqueue *current_virtqueue()
-  {
-    return virtqueue(_cfg_header->queue_sel);
-  }
-
-  Queue_config *virtqueue_config(unsigned qn)
-  {
-    auto *q = virtqueue(qn);
-    return q ? &q->config : nullptr;
-  }
-
-  Queue_config *current_virtqueue_config()
-  {
-    auto *q = current_virtqueue();
-    return q ? &q->config : nullptr;
-  }
-
-  l4virtio_config_hdr_t *mmio_local_addr() const
-  { return _cfg_header.get(); }
-
-  l4_size_t mapped_mmio_size() const
-  { return Config_ds_size; }
-
-  L4::Cap mmio_ds() const
-  { return _cfg_ds.get(); }
-
-  l4virtio_config_hdr_t *virtio_cfg()
-  { return _cfg_header.get(); }
-
-  void virtio_device_config_written(unsigned /*reg*/) {}
-  virtual void reset() {}
-
-  void virtio_set_status(l4_uint32_t status)
-  {
-    _cfg_header->status = status;
-    if (status == 0)
-      reset();
-  }
-
-  template
-  T *devaddr_to_virt(l4_addr_t devaddr, l4_size_t len = 0) const
-  { return _ram->guest2host(Vmm::Region::ss(Vmm::Guest_addr(devaddr), len, Vmm::Region_type::Ram)); }
-
-private:
-  Vmm::Vm_ram *_ram;
-};
-
-
-template
-class Mmio_connector
-{
-  enum { Device_config_start = 0x100 };
-
-public:
-  template
-  void writeback_cache(T const *p)
-  {
-    l4_cache_clean_data(reinterpret_cast(p),
-                        reinterpret_cast(p) + sizeof(T));
-  }
-
-protected:
-  template
-  T *virtio_device_config()
-  {
-    return reinterpret_cast(  reinterpret_cast(dev()->virtio_cfg())
-                                 + Device_config_start);
-  }
-
-public:
-  void set_irq_status(l4_uint32_t irq_status)
-  {
-    auto *vcfg = dev()->virtio_cfg();
-    vcfg->irq_status = irq_status;
-    writeback_cache(&vcfg->irq_status);
-  }
-
-  void write(unsigned reg, char size, l4_uint64_t value, unsigned)
-  {
-    auto *vcfg = dev()->virtio_cfg();
-    if (L4_UNLIKELY(reg >= dev()->mapped_mmio_size()))
-      return;
-
-    if (L4_UNLIKELY((reg + (1U << size)) > dev()->mapped_mmio_size()))
-      return;
-
-    if (L4_UNLIKELY(reg & ((1U << size) - 1)))
-      return;
-    if (reg >= Device_config_start)
-      {
-        l4_addr_t a = reinterpret_cast(vcfg) + reg;
-        if (Vmm::Mem_access::write_width(a, value, size) == L4_EOK)
-          {
-            Vmm::Mem_access::cache_clean_data_width(a, size);
-            dev()->virtio_device_config_written(reg - Device_config_start);
-          }
-        return;
-      }
-
-    if (size < 2)
-      return;
-
-    switch (reg)
-      {
-      case 0x14:
-        vcfg->dev_features_sel = value;
-        if (value < (sizeof(vcfg->dev_features_map) / 4))
-          vcfg->dev_features = vcfg->dev_features_map[value];
-        else
-          vcfg->dev_features = 0;
-        writeback_cache(&vcfg->dev_features);
-        break;
-
-      case 0x20:
-          {
-            unsigned sel = cxx::access_once(&vcfg->driver_features_sel);
-            vcfg->driver_features = value;
-            if (sel < (sizeof(vcfg->driver_features_map) / 4))
-              vcfg->driver_features_map[sel] = value;
-          }
-        break;
-
-      case 0x24:
-        vcfg->driver_features_sel = value;
-        break;
-
-      case 0x30:
-        {
-          vcfg->queue_sel = value;
-          auto *qc = dev()->current_virtqueue_config();
-          if (!qc)
-            {
-              vcfg->queue_num_max = 0;
-              vcfg->queue_ready = 0;
-              break;
-            }
-
-          vcfg->queue_num_max = qc->num_max;
-          vcfg->queue_ready = qc->ready;
-          vcfg->queue_desc = qc->desc_addr;
-          vcfg->queue_avail = qc->avail_addr;
-          vcfg->queue_used = qc->used_addr;
-          // Only queue_num_max/queue_ready are read by the guest. So no cache
-          // write back for the *_addr fields is necessary.
-          writeback_cache(&vcfg->queue_num_max);
-          writeback_cache(&vcfg->queue_ready);
-          break;
-        }
-
-      case 0x38:
-        {
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            qc->num = value;
-
-          vcfg->queue_num = value;
-          break;
-        }
-
-      case 0x44:
-        {
-          dev()->virtio_queue_ready(value);
-
-          auto *cfg = dev()->current_virtqueue_config();
-          vcfg->queue_ready = cfg ? cfg->ready : 0;
-
-          writeback_cache(&vcfg->queue_ready);
-          writeback_cache(&vcfg->queue_num_max);
-          break;
-        }
-
-      case 0x50:
-        vcfg->queue_notify = value;
-        writeback_cache(&vcfg->queue_notify);
-        dev()->virtio_queue_notify(value);
-        break;
-
-      case 0x64:
-        dev()->virtio_irq_ack(value);
-        writeback_cache(&vcfg->irq_status);
-        break;
-
-      case 0x70:
-        dev()->virtio_set_status(value);
-        writeback_cache(&vcfg->status);
-        writeback_cache(&vcfg->irq_status);
-        break;
-
-      case 0x80:
-      case 0x84:
-        {
-          int i = reg == 0x80 ? 0 : 1;
-          (reinterpret_cast(&vcfg->queue_desc))->w[i] = value;
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            (reinterpret_cast(&qc->desc_addr))->w[i] = value;
-          break;
-        }
-
-      case 0x90:
-      case 0x94:
-        {
-          int i = reg == 0x90 ? 0 : 1;
-          (reinterpret_cast(&vcfg->queue_avail))->w[i] = value;
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            (reinterpret_cast(&qc->avail_addr))->w[i] = value;
-          break;
-        }
-
-      case 0xa0:
-      case 0xa4:
-        {
-          int i = reg == 0xa0 ? 0 : 1;
-          (reinterpret_cast(&vcfg->queue_used))->w[i] = value;
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            (reinterpret_cast(&qc->used_addr))->w[i] = value;
-          break;
-        }
-      }
-  }
-
-private:
-  DEV *dev()
-  { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virtio_event_connector.h b/src/l4/pkg/uvmm/server/src/virtio_event_connector.h
deleted file mode 100644
index 9205fdff..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_event_connector.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2017-2018, 2020, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "irq.h"
-#include "irq_dt.h"
-#include "virtio_dev.h"
-
-namespace Virtio {
-
-/**
- * This IRQ event connector supports a single IRQ for all events.
- *
- * In general, the event connector connects the events issued by a
- * virtio device with the interrupt configured in the transport layer.
- * The connector makes the virtio device independent from the transport
- * specific event notification facility, e.g. Interrupt or MSI.
- */
-class Event_connector_irq
-{
-public:
-  /**
-   * Commit / send events marked in `ev` to the guest.
-   *
-   * \param ev  Set of pending events to be injected into the guest.
-   */
-  void send_events(Virtio::Event_set &&ev)
-  {
-    if (ev.e)
-      _sink.inject();
-
-    ev.reset();
-  }
-
-  /// Send a single event with index `idx` to the guest.
-  void send_event(l4_uint16_t /* idx */)
-  {
-    _sink.inject();
-  }
-
-  /**
-   * Acknowledge the bits set in the bit mask.
-   *
-   * \param irq_ack_mask  Describes the config/queue events to acknowledge.
-   */
-  void clear_events(unsigned /* irq_ack_mask */)
-  {
-    _sink.ack();
-  }
-
-  /**
-   * Line-based IRQ setup routine for device-tree setup.
-   */
-  int init_irqs(Vdev::Device_lookup *devs, Vdev::Dt_node const &node)
-  {
-    Vdev::Irq_dt_iterator it(devs, node);
-
-    if (it.next(devs) < 0 || !it.ic_is_virt())
-      return -1;
-
-    _sink.rebind(it.ic(), it.irq());
-    return 0;
-  }
-
-private:
-  Vmm::Irq_sink _sink;
-};
-
-} // namespace Virtio
diff --git a/src/l4/pkg/uvmm/server/src/virtio_input.h b/src/l4/pkg/uvmm/server/src/virtio_input.h
deleted file mode 100644
index 38ff1ec1..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_input.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "virtio_dev.h"
-#include "virtio_event_connector.h"
-
-namespace Vdev {
-
-template 
-class Virtio_input
-: public Virtio::Dev
-{
-  typedef L4virtio::Svr::Virtqueue::Desc Desc;
-  typedef L4virtio::Svr::Request_processor Request_processor;
-
-  struct Payload
-  {
-    char *data;
-    unsigned len;
-    bool writable;
-  };
-
-  enum
-  {
-    Input_event_queue = 0,
-    Input_status_queue = 1,
-    Input_queue_num = 2,
-    Input_queue_length = 0x100,
-  };
-
-protected:
-  Virtio::Virtqueue _vqs[Input_queue_num];
-
-public:
-  Virtio_input(Vmm::Vm_ram *ram)
-  : Virtio::Dev(ram, 0x44, L4VIRTIO_ID_INPUT)
-  {
-    Features feat(0);
-    feat.ring_indirect_desc() = true;
-    _cfg_header->dev_features_map[0] = feat.raw;
-    _cfg_header->num_queues = Input_queue_num;
-
-    for (auto &q : _vqs)
-      q.config.num_max = Input_queue_length;
-  }
-
-  void virtio_queue_ready(unsigned ready)
-  {
-    auto *q = current_virtqueue();
-    if (!q)
-      return;
-
-    auto *qc = &q->config;
-
-    if (ready == 0 && q->ready())
-      {
-        q->disable();
-        qc->ready = 0;
-      }
-    else if (ready == 1 && !q->ready())
-      {
-        qc->ready = 0;
-        l4_uint16_t num = qc->num;
-        // num must be: a power of two in range [1,num_max].
-        if (!num || (num & (num - 1)) || num > qc->num_max)
-          return;
-
-        q->init_queue(dev()->template devaddr_to_virt(qc->desc_addr),
-                      dev()->template devaddr_to_virt(qc->avail_addr),
-                      dev()->template devaddr_to_virt(qc->used_addr));
-        qc->ready = 1;
-      }
-  }
-
-  void reset() override
-  {
-    for (auto &q : _vqs)
-      {
-        q.disable();
-        q.config.ready = 0;
-        q.config.num_max = Input_queue_length;
-      }
-  }
-
-  void load_desc(Desc const &desc, Request_processor const *, Payload *p)
-  {
-    p->data = devaddr_to_virt(desc.addr.get(), desc.len);
-    p->len = desc.len;
-    p->writable = desc.flags.write();
-  }
-
-  void load_desc(Desc const &desc, Request_processor const *,
-                 Desc const **table)
-  {
-    *table = devaddr_to_virt(desc.addr.get(), sizeof(Desc));
-  }
-
-  void virtio_irq_ack(unsigned val)
-  {
-    _irq_status_shadow &= ~val;
-    if (_cfg_header->irq_status != _irq_status_shadow)
-      dev()->set_irq_status(_irq_status_shadow);
-
-    dev()->event_connector()->clear_events(val);
-  }
-
-  Virtio::Virtqueue *virtqueue(unsigned qn) override
-  { return qn < Input_queue_num ? &_vqs[qn] : nullptr; }
-
-  bool inject_event(l4virtio_input_event_t &event)
-  {
-    auto *q = &_vqs[0];
-    if (!q->ready())
-      {
-        Err().printf("Virtio_input: not ready yet\n");
-        return false;
-      }
-
-    auto req = q->next_avail();
-
-    if (!req)
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "virtio")
-          .printf("Virtio_input: No request available\n");
-        return false;
-      }
-
-    Request_processor rp;
-    Payload p;
-
-    rp.start(this, req, &p);
-
-    // Check consistency of buffer
-    if (!p.writable || p.len < sizeof(event))
-      {
-        Dbg(Dbg::Dev, Dbg::Warn, "virtio")
-          .printf("Virtio_input: buffer %s\n",
-                  p.writable ? "read only" : "too small");
-        // return it to the queue with 0 content
-        q->consumed(req, 0);
-        return false;
-      }
-
-    memcpy(p.data, &event, sizeof(event));
-    q->consumed(req, sizeof(event));
-    return true;
-  }
-
-  int inject_events(l4virtio_input_event_t *events, size_t num)
-  {
-    if (!num)
-      return 0;
-
-    unsigned injected;
-
-    auto *q = &_vqs[0];
-    if (!q->ready())
-      {
-        Err().printf("Virtio_input: not ready yet\n");
-        return 0;
-      }
-
-    for (injected = 0; injected < num; ++injected)
-      {
-        if (!inject_event(events[injected]))
-          break;
-      }
-
-    notify_events();
-    return injected;
-  }
-
-  void notify_events()
-  {
-    auto *q = &_vqs[0];
-
-    // If we end up here we either successfully injected events or got an error
-    // while doing so (e.g. no buffer available anymore). We notify the guest if
-    // it did not disable notifications.
-    // We could consider sending notifications in error cases even with disabled
-    // notificatins (by adding  || (injected != num))but are currently not doing
-    // so.
-    if (!q->no_notify_guest())
-      {
-        dev()->_irq_status_shadow |= 1;
-        if (_cfg_header->irq_status != _irq_status_shadow)
-          dev()->set_irq_status(_irq_status_shadow);
-
-        Virtio::Event_set ev;
-        ev.set(q->config.driver_notify_index);
-        dev()->event_connector()->send_events(cxx::move(ev));
-      }
-  }
-
-private:
-  DEV *dev() { return static_cast(this); }
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virtio_pci_connector.h b/src/l4/pkg/uvmm/server/src/virtio_pci_connector.h
deleted file mode 100644
index 6945961d..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_pci_connector.h
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright (C) 2018-2019, 2022-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "pci_virtio_device.h"
-#include "mem_access.h"
-#include "mmio_device.h"
-#include "io_device.h"
-#include "virtio_dev.h"
-#include "virtio_qword.h"
-#include "pci_virtio_config.h"
-
-namespace Virtio {
-
-/**
- * Connecting instance between the Virtio world and the PCI transport world.
- *
- * \tparam DEV  The derived class.
- */
-template
-class Pci_layout
-{
-  void init_queue_sizes()
-  {
-    auto vcfg = dev()->virtio_cfg();
-    for (unsigned i = 0; i < vcfg->num_queues; i++)
-      {
-        auto *qc = dev()->virtqueue_config(i);
-        assert(qc && !qc->ready);
-        qc->num = qc->num_max;
-      }
-  }
-
-public:
-  void in(unsigned port, Vmm::Mem_access::Width wd, l4_uint32_t *value)
-  {
-    auto vcfg = dev()->virtio_cfg();
-    l4_uint32_t result = 0;
-
-    if (port >= Vdev::Num_pci_connector_ports)
-      {
-        read_device_memory(port - Vdev::Num_pci_connector_ports, wd, value);
-        trace().printf("DevMem: In port(width) %i(%i) : 0x%x\n", port, wd,
-                       *value);
-        return;
-      }
-
-    switch(port)
-      {
-      case 0: // device feature select
-        result = vcfg->dev_features_sel;
-        break;
-
-      case 4: // device feature
-        {
-          auto sel = vcfg->dev_features_sel;
-          if (sel < (sizeof(vcfg->dev_features_map)
-                     / sizeof(vcfg->dev_features_map[0])))
-            result = vcfg->dev_features_map[sel];
-          break;
-        }
-
-      case 8: // driver feature select
-        result = vcfg->driver_features_sel;
-        break;
-
-      case 12: // driver feature
-        {
-          auto sel = vcfg->driver_features_sel;
-          if (sel < (sizeof(vcfg->driver_features_map)
-                     / sizeof(vcfg->driver_features_map[0])))
-            result = vcfg->driver_features_map[sel];
-          break;
-        }
-
-      case 16: // config msix vec
-        result = vcfg->cfg_driver_notify_index;
-        break;
-
-      case 18: // RO num queues (max)
-        // set the number of VQs for the virtio_console to 2
-        result  = vcfg->num_queues;
-        break;
-
-      case 20: // device status
-        result = vcfg->status;
-        break;
-
-      case 21: // RO config_generation
-        result = vcfg->generation;
-        break;
-
-      case 22: // queue select
-        result = vcfg->queue_sel;
-        break;
-
-      case 24: // queue size (max)
-        {
-          auto *qc = dev()->current_virtqueue_config();
-          result = qc ? qc->num : 0;
-          trace().printf("read queue size %i\n", result);
-          break;
-        }
-
-      case 26: // queue_msix_vector
-        {
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            result = qc->driver_notify_index;
-
-          break;
-        }
-
-      case 28: // queue_enable
-        {
-          auto *qc = dev()->current_virtqueue_config();
-          result = qc ? qc->ready : 0;
-          break;
-        }
-
-      case 30: // RO queue_notify_off
-        // Read as 0.
-        break;
-
-      case 32: // queue_desc[31:0]
-      case 36: // queue_desc[63:32]
-        {
-          if (wd == Vmm::Mem_access::Wd32)
-            {
-              auto *qc = dev()->current_virtqueue_config();
-              int i = port == 32 ? 0 : 1;
-              result = qc ? ((Virtio::Qword *)(&qc->desc_addr))->w[i] : -1;
-            }
-          else
-            dbg().printf("Invalid width access to port %i with width %i\n",
-                         port, wd);
-          break;
-        }
-
-      case 40: // queue_avail[31:0]
-      case 44: // queue_avail[63:32]
-        {
-          if (wd == Vmm::Mem_access::Wd32)
-            {
-              auto *qc = dev()->current_virtqueue_config();
-              int i = port == 40 ? 0 : 1;
-              result = qc ? ((Virtio::Qword *)(&qc->avail_addr))->w[i] : -1;
-            }
-          else
-            dbg().printf("Invalid width access to port %i with width %i\n",
-                         port, wd);
-          break;
-        }
-
-      case 48: // queue_used[31:0]
-      case 52: // queue_used[63:32]
-        {
-          if (wd == Vmm::Mem_access::Wd32)
-            {
-              auto *qc = dev()->current_virtqueue_config();
-              int i = port == 48 ? 0 : 1;
-              result = qc ? ((Virtio::Qword *)(&qc->used_addr))->w[i] : -1;
-            }
-          else
-            dbg().printf("Invalid width access to port %i with width %i\n",
-                         port, wd);
-          break;
-        }
-
-      default:
-        dbg().printf("unknown port number read: %i\n", port);
-      }
-
-    *value = Vmm::Mem_access::read(result, 0, wd);
-
-    trace().printf("In port(width) %i(%i) : 0x%x\n", port, wd, *value);
-  }
-
-  void out(unsigned port, Vmm::Mem_access::Width wd, l4_uint32_t value)
-  {
-    auto vcfg = dev()->virtio_cfg();
-
-    if (port >= Vdev::Num_pci_connector_ports)
-      {
-        trace().printf("DevMem OUT port(width) %i(%i) = 0x%x\n", port, wd,
-                       value);
-        write_device_memory(port - Vdev::Num_pci_connector_ports, wd, value);
-        return;
-      }
-
-    if (port != 56)
-      trace().printf("OUT port(width) %i(%i) = 0x%x\n", port, wd, value);
-
-    switch(port)
-      {
-      case 0: // device feature select
-        vcfg->dev_features_sel = value;
-        break;
-
-      case 8: // driver feature select
-        vcfg->driver_features_sel = value;
-        break;
-
-      case 12: // driver feature
-        {
-          auto sel = vcfg->driver_features_sel;
-          if (sel < (sizeof(vcfg->driver_features_map)
-                     / sizeof(vcfg->driver_features_map[0])))
-            vcfg->driver_features_map[sel] = value;
-          break;
-        }
-
-      case 16: // config msix vec
-        {
-          vcfg->cfg_driver_notify_index = value;
-          dbg().printf("config_msix_vec set %i\n", value);
-          break;
-        }
-
-      case 20: // device status
-        dev()->virtio_set_status(value);
-        if (!value)
-          init_queue_sizes();
-        break;
-
-      case 22: // queue select
-        vcfg->queue_sel = value;
-        break;
-
-      case 24: // queue size (max)
-        {
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            qc->num = value;
-          break;
-        }
-
-      case 26: // queue_msix_vector
-        {
-          dbg().printf("\t[q.%u] queue_msix_vector set %i\n", vcfg->queue_sel,
-                       value);
-
-          auto *qc = dev()->current_virtqueue_config();
-          if (qc)
-            qc->driver_notify_index = value;
-          break;
-        }
-
-      case 28: // queue_enable
-        dev()->virtio_queue_ready(value);
-        break;
-
-      case 32: // queue_desc[31:0]
-      case 36: // queue_desc[63:32]
-        {
-          if (wd == Vmm::Mem_access::Wd32)
-            {
-              auto *qc = dev()->current_virtqueue_config();
-              int i = port == 32 ? 0 : 1;
-              if (qc)
-                ((Virtio::Qword *)(&qc->desc_addr))->w[i] = value;
-            }
-          else
-            dbg().printf("Invalid width access to port %i with width %i\n",
-                         port, wd);
-          break;
-        }
-
-      case 40: // queue_avail[31:0]
-      case 44: // queue_avail[63:32]
-        {
-          if (wd == Vmm::Mem_access::Wd32)
-            {
-              auto *qc = dev()->current_virtqueue_config();
-              int i = port == 40 ? 0 : 1;
-              if (qc)
-                ((Virtio::Qword *)(&qc->avail_addr))->w[i] = value;
-            }
-          else
-            dbg().printf("Invalid width access to port %i with width %i\n",
-                         port, wd);
-          break;
-        }
-
-      case 48: // queue_used[31:0]
-      case 52: // queue_used[63:32]
-        {
-          if (wd == Vmm::Mem_access::Wd32)
-            {
-              auto *qc = dev()->current_virtqueue_config();
-              int i = port == 48 ? 0 : 1;
-              if (qc)
-                ((Virtio::Qword *)(&qc->used_addr))->w[i] = value;
-            }
-          else
-            dbg().printf("Invalid width access to port %i with width %i\n",
-                         port, wd);
-          break;
-        }
-
-      case 56: // queue notify: length depends on cap values set
-        dev()->virtio_queue_notify(value);
-        break;
-
-      case 58: // ISR status
-        if (!dev()->msix_enabled())
-          dbg().printf("ISR status access for legacy IRQ -- NOT implemented\n");
-        break;
-
-      default: dbg().printf("unknown port number written: %i\n", port);
-      }
-  }
-
-  void set_irq_status(int val)
-  {
-    // Only necessary in case of legacy IRQ, but a check if legacy IRQs are
-    // used would be more expensive than just setting it either way.
-    dev()->virtio_cfg()->irq_status = val;
-  }
-
-  enum
-  {
-    Device_config_start = 0x100,
-  };
-
-  template
-  void writeback_cache(T const *p)
-  {
-    l4_cache_clean_data((l4_addr_t)p, (l4_addr_t)p + sizeof(T));
-  }
-
-  template
-  T *virtio_device_config()
-  {
-    return reinterpret_cast(  (l4_addr_t)dev()->virtio_cfg()
-                                 + Device_config_start);
-  }
-
-private:
-  DEV *dev() { return static_cast(this); }
-  DEV const *dev() const { return static_cast(this); }
-
-  static Dbg trace() { return Dbg(Dbg::Dev, Dbg::Trace, "PCI con"); }
-  static Dbg dbg() { return Dbg(Dbg::Dev, Dbg::Warn, "PCI con"); }
-
-  void read_device_memory(unsigned port, Vmm::Mem_access::Width wd,
-                          l4_uint32_t *val)
-  {
-    l4_addr_t dev_cfg =
-      reinterpret_cast(l4virtio_device_config(dev()->virtio_cfg()))
-      + port;
-
-    *val = Vmm::Mem_access::read_width(dev_cfg, wd);
-  }
-
-  void write_device_memory(unsigned port, Vmm::Mem_access::Width wd,
-                           l4_uint32_t val)
-  {
-    l4_addr_t dev_cfg =
-      reinterpret_cast(l4virtio_device_config(dev()->virtio_cfg()))
-      + port;
-
-    if (Vmm::Mem_access::write_width(dev_cfg, val, wd) == L4_EOK)
-      {
-        Vmm::Mem_access::cache_clean_data_width(dev_cfg, wd);
-        dev()->virtio_device_config_written(port);
-      }
-  }
-}; // Pci_layout
-
-template 
-class Pci_connector
-: public Pci_layout,
-  public virtual Vmm::Mmio_device,
-  public virtual Vmm::Io_device
-{
-public:
-  Pci_connector() {}
-
-  char const *dev_name() const override
-  { return "Virtio PCI Device"; }
-
-  int access(l4_addr_t pfa, l4_addr_t offset, Vmm::Vcpu_ptr vcpu,
-             L4::Cap, l4_addr_t, l4_addr_t) override
-  {
-    auto insn = vcpu.decode_mmio();
-
-    if (insn.access == Vmm::Mem_access::Other)
-      {
-        Dbg(Dbg::Mmio, Dbg::Warn, "mmio")
-          .printf("MMIO access @ 0x%lx: unknown instruction. Ignored.\n",
-                  pfa);
-        return -L4_ENXIO;
-      }
-
-    Dbg(Dbg::Mmio, Dbg::Trace, "mmio")
-      .printf("MMIO access @ 0x%lx (0x%lx) %s, width: %u\n",
-              pfa, offset,
-              insn.access == Vmm::Mem_access::Load ? "LOAD" : "STORE",
-              (unsigned) insn.width);
-
-    if (insn.access == Vmm::Mem_access::Store)
-      write(offset, insn.width, insn.value, vcpu.get_vcpu_id());
-    else
-      {
-        insn.value = read(offset, insn.width, vcpu.get_vcpu_id());
-        vcpu.writeback_mmio(insn);
-      }
-
-    return Vmm::Jump_instr;
-  }
-
-  void map_eager(L4::Cap, Vmm::Guest_addr, Vmm::Guest_addr) override
-  {} // nothing to map
-
-  // MMIO interface
-  l4_umword_t read(unsigned reg, char wd, unsigned /*cpu_id*/)
-  {
-    l4_uint32_t ret;
-    Pci_layout::in(reg, (Vmm::Mem_access::Width)wd, &ret);
-    return ret;
-  }
-
-  void write(unsigned reg, char wd, l4_umword_t value, unsigned /*cpu_id*/)
-  {
-    Pci_layout::out(reg, (Vmm::Mem_access::Width)wd, value);
-  }
-
-  // IO interface
-  void io_in(unsigned port, Vmm::Mem_access::Width wd, l4_uint32_t *value) override
-  {
-    Pci_layout::in(port, wd, value);
-  }
-
-  void io_out(unsigned port, Vmm::Mem_access::Width wd, l4_uint32_t value) override
-  {
-    Pci_layout::out(port, wd, value);
-  }
-}; // Pci_connector
-} // namespace Virtio
diff --git a/src/l4/pkg/uvmm/server/src/virtio_proxy.cc b/src/l4/pkg/uvmm/server/src/virtio_proxy.cc
deleted file mode 100644
index 1948d8a8..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_proxy.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016-2019, 2024 Kernkonzept GmbH.
- * Author(s): Alexander Warg 
- *            Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include "virtio_proxy.h"
-#include "device_factory.h"
-
-namespace {
-
-using namespace Vdev;
-
-struct F : Factory
-{
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    auto cap = Vdev::get_cap(node, "l4vmm,virtiocap");
-    if (!cap)
-      return nullptr;
-
-    l4_uint64_t base, cfgsz;
-    int res = node.get_reg_val(0, &base, &cfgsz);
-    if (res < 0)
-      {
-#ifdef CONFIG_MMU
-        Err().printf("Failed to read 'reg' from node %s: %s\n",
-                     node.get_name(), node.strerror(res));
-        throw L4::Runtime_error(-L4_EINVAL);
-#else
-        // This is not fatal. In case of no-MMU systems, all addresses are
-        // globally unique. We preferrbly use the address of the config DS.
-        base = ~0UL;
-        cfgsz = L4_PAGESIZE;
-#endif
-      }
-
-    auto c = make_device(cap, static_cast(cfgsz),
-                                            devs->ram().get());
-    if (c->init_irqs(devs, node) < 0)
-      return nullptr;
-
-    c->register_irq(devs->vmm()->registry());
-#ifndef CONFIG_MMU
-    // No remapping possible: preferrably map to the physical address.
-    l4_addr_t cfg_ds_start;
-    l4_addr_t cfg_ds_end;
-    L4Re::chksys(c->mmio_ds()->map_info(&cfg_ds_start, &cfg_ds_end),
-                 "get config ds addr");
-
-    if (res < 0)
-        node.set_reg_val(cfg_ds_start, cfg_ds_end - cfg_ds_start + 1U);
-    else if (base != cfg_ds_start)
-      {
-        auto warn = Dbg(Dbg::Dev, Dbg::Warn, "Virtio_proxy_mmio");
-        warn.printf("Cannot map to requrested MMIO region"
-                    " (requested: 0x%llx, actual: 0x%lx)."
-                    " Guest performance will be impaired!\n",
-                    base, cfg_ds_start);
-      }
-#endif
-
-    devs->vmm()->register_mmio_device(c, Vmm::Region_type::Virtual, node);
-    return c;
-  }
-};
-
-static F f;
-static Device_type t = { "virtio,mmio", "proxy", &f };
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virtio_proxy.h b/src/l4/pkg/uvmm/server/src/virtio_proxy.h
deleted file mode 100644
index 10a9506f..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_proxy.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "irq.h"
-#include "guest.h"
-#include "mmio_device.h"
-#include "virtio_event_connector.h"
-#include "vm_ram.h"
-#include "monitor/virtio_cmd_handler.h"
-
-namespace L4virtio { namespace Driver {
-
-/**
- * \brief Client-side implementation for a general virtio device.
- */
-class Device
-{
-public:
-  Device(L4::Cap device, l4_size_t config_size)
-  : _device(device), _config_page_size(config_size)
-  {}
-
-  /**
-   * Contacts the device and sets up the config page.
-   *
-   * \param guest_irq Irq capability to send to device.
-   *
-   * \throws L4::Runtime_error if the initialisation fails
-   *
-   * This function contacts the server, sets up the notification
-   * channels and the configuration dataspace. After this is done,
-   * the caller can set up any dataspaces it needs.
-   */
-  void driver_connect(L4::Cap guest_irq)
-  {
-    auto vicu = L4::cap_dynamic_cast(_device);
-
-    if (!vicu.is_valid())
-      L4Re::chksys(-L4_ENOSYS,
-                   "ICU protocol not supported by virtio device. Legacy interface?");
-
-    l4_icu_info_t icu_info;
-    L4Re::chksys(vicu->info(&icu_info), "Get info about ICU.");
-
-    _config_cap = L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                               "Allocating cap for config dataspace");
-
-    l4_addr_t ds_offset;
-    L4Re::chksys(_device->device_config(_config_cap.get(), &ds_offset),
-                 "Request device config page");
-
-    L4Re::Dataspace::Stats stats;
-    auto ret = _config_cap->info(&stats);
-    if ((ret != -L4_ENOSYS)
-         && (ret != L4_EOK || stats.size < _config_page_size + ds_offset))
-      L4Re::chksys(-L4_ENODEV, "Virtio config space too small");
-
-    auto *e = L4Re::Env::env();
-    L4Re::chksys(e->rm()->attach(&_config, _config_page_size,
-                                 L4Re::Rm::F::Search_addr | L4Re::Rm::F::Eager_map
-                                 | L4Re::Rm::F::RW,
-                                 L4::Ipc::make_cap_rw(_config_cap.get()),
-                                 ds_offset),
-                 "Attaching config dataspace");
-
-    if (memcmp(&_config->magic, "virt", 4) != 0)
-      L4Re::chksys(-L4_ENODEV, "Device config has wrong magic value");
-
-    if (_config->version != 2)
-      L4Re::chksys(-L4_ENODEV, "Require virtio version of 2");
-
-    _guest_irq = guest_irq;
-
-    _host_irq = L4Re::chkcap(L4Re::Util::make_unique_cap(),
-                             "Allocating cap for host irq");
-
-    _config->cfg_driver_notify_index = 0;
-
-    if (icu_info.nr_irqs > 0)
-      L4Re::chksys(vicu->bind(0, guest_irq),
-                   "Send notification IRQ to device");
-
-    ret = _device->device_notification_irq(_config->cfg_device_notify_index,
-                                           _host_irq.get());
-
-    if (ret != L4_EOK && ret != -L4_ENOSYS)
-      L4Re::chksys(ret, "Receive notification IRQ from device");
-
-    _queue_irqs.resize(_config->num_queues);
-
-    // Flush initial config page content
-    l4_cache_clean_data(reinterpret_cast(_config.get()),
-                        reinterpret_cast(_config.get())
-                        + _config_page_size);
-  }
-
-
-  /**
-   * Share a dataspace with the device.
-   *
-   * \param ds      Dataspace to share with the device.
-   * \param offset  Offset in dataspace where the shared part starts.
-   * \param size    Total size in bytes of the shared space.
-   * \param devaddr Start of shared space in the device address space.
-   *
-   * Although this function allows to share only a part of the given dataspace
-   * for convenience, the granularity of sharing is always the dataspace level.
-   * Thus, the remainder of the dataspace is not protected from the device.
-   */
-  int register_ds(L4::Cap ds, l4_umword_t offset,
-                  l4_umword_t size, l4_uint64_t devaddr)
-  {
-    return _device->register_ds(L4::Ipc::make_cap_rw(ds), devaddr, offset, size);
-  }
-
-  int config_queue(unsigned num)
-  {
-    if (l4virtio_get_feature(_config->dev_features_map,
-                             L4VIRTIO_FEATURE_CMD_CONFIG))
-      // Do busy waiting, because the irq could arrive on any CPU
-      return _config->config_queue(num, _host_irq.get(), L4::Cap());
-
-    _config->queues()[num].driver_notify_index = 0;
-
-    if (_queue_irqs.size() <= num)
-      _queue_irqs.resize(num + 1);
-    else
-      _queue_irqs[num].reset();
-
-    int ret = _device->config_queue(num);
-
-    if (ret >= 0 && _config->queues()[num].ready)
-      {
-        l4_uint16_t irq = _config->queues()[num].device_notify_index;
-        auto cap = L4Re::Util::make_unique_cap();
-        if (_device->device_notification_irq(irq, cap.get()) >= 0)
-          _queue_irqs[num] = std::move(cap);
-      }
-
-    return ret;
-  }
-
-  L4virtio::Device::Config_hdr *device_config() const
-  { return _config.get(); }
-
-  L4::Cap config_ds() const
-  { return _config_cap.get(); }
-
-  l4_uint32_t config_size() const
-  { return _config_page_size; }
-
-  L4virtio::Device::Config_queue *queue_config(int num) const
-  { return &_config->queues()[num]; }
-
-  void virtio_queue_notify(unsigned num)
-  {
-    if (l4virtio_get_feature(_config->dev_features_map,
-                             L4VIRTIO_FEATURE_CMD_CONFIG))
-      // Do busy waiting, because the irq could arrive on any CPU
-      _config->notify_queue(num, _host_irq.get(), L4::Cap());
-    else if (num < _queue_irqs.size())
-      _queue_irqs[num]->trigger();
-  }
-
-  void set_status(l4_uint32_t status)
-  {
-    bool use_irq = l4virtio_get_feature(_config->dev_features_map,
-                                        L4VIRTIO_FEATURE_CMD_CONFIG);
-
-    if (use_irq
-        && status == (L4VIRTIO_STATUS_ACKNOWLEDGE | L4VIRTIO_STATUS_DRIVER
-                      | L4VIRTIO_STATUS_FEATURES_OK))
-      l4virtio_set_feature(_config->driver_features_map,
-                           L4VIRTIO_FEATURE_CMD_CONFIG);
-
-    if (use_irq)
-      // Do busy waiting, because the irq could arrive on any CPU
-      _config->set_status(status, _host_irq.get(), L4::Cap());
-    else
-      _device->set_status(status);
-  }
-
-  void cfg_changed(unsigned reg)
-  {
-    bool use_irq = l4virtio_get_feature(_config->dev_features_map,
-                                        L4VIRTIO_FEATURE_CMD_CONFIG);
-
-    if (use_irq)
-      // Do busy waiting, because the irq could arrive on any CPU
-      _config->cfg_changed(reg, _host_irq.get(), L4::Cap());
-    else
-      L4Re::throw_error(-L4_EINVAL, "Direct config change not supported in L4Virtio protocol.");
-  }
-
-  ~Device()
-  {
-    if (!_config.get())
-      return;
-
-    set_status(0); // reset
-  }
-
-protected:
-  L4::Cap _device;
-  L4Re::Rm::Unique_region _config;
-  L4::Cap _guest_irq;
-
-private:
-  std::vector > _queue_irqs;
-  L4Re::Util::Unique_cap _host_irq;
-  L4Re::Util::Unique_cap _config_cap;
-
-  unsigned _config_page_size = 0;
-};
-
-} } // namespace
-
-namespace Vdev {
-
-template 
-class Virtio_proxy
-: public L4::Irqep_t>,
-  public Device,
-  public Monitor::Virtio_proxy_cmd_handler>
-{
-public:
-  Virtio_proxy(L4::Cap device, l4_size_t config_size,
-               Vmm::Vm_ram *ram)
-  : _dev(device, config_size)
-  {
-    ram->foreach_region([this](Vmm::Ram_ds const &r)
-      {
-        L4Re::chksys(_dev.register_ds(r.ds(), r.ds_offset(), r.size(),
-                                      r.vm_start().get()),
-                     "Registering RAM for virtio proxy");
-      });
-  }
-
-  int init_irqs(Vdev::Device_lookup *devs, Vdev::Dt_node const &self)
-  { return dev()->event_connector()->init_irqs(devs, self); }
-
-  void register_irq(L4::Registry_iface *registry)
-  {
-    L4::Cap guest_irq = L4Re::chkcap(registry->register_irq_obj(this),
-                                              "Registering guest IRQ in proxy");
-
-    _dev.driver_connect(guest_irq);
-
-    // Unmask it, this might be a hardware interrupt.
-    guest_irq->unmask();
-  }
-
-  void handle_irq()
-  {
-    Virtio::Event_set ev;
-    // FIXME: our L4 transport supports just a single IRQ, so trigger event 1
-    //        for all queues until we implemented per-queue events.
-    //        And use event index 0 for config events.
-    auto s = _dev.device_config()->irq_status;
-    if (s & L4VIRTIO_IRQ_STATUS_CONFIG)
-        ev.set(0);
-    if (s & L4VIRTIO_IRQ_STATUS_VRING)
-        ev.set(1); // set event index 1 for all queue events
-
-    // Write back the irq status, so that required cache management can happen
-    dev()->set_irq_status(s);
-    dev()->event_connector()->send_events(cxx::move(ev));
-  }
-
-  void virtio_irq_ack(unsigned val)
-  {
-    dev()->set_irq_status(_dev.device_config()->irq_status & ~val);
-    dev()->event_connector()->clear_events(val);
-  }
-
-  l4virtio_config_hdr_t *mmio_local_addr() const
-  { return _dev.device_config(); }
-
-  l4_size_t mapped_mmio_size() const
-  { return l4_round_page(_dev.config_size()); }
-
-  L4::Cap mmio_ds() const
-  { return _dev.config_ds(); }
-
-  l4virtio_config_hdr_t *virtio_cfg()
-  { return _dev.device_config(); }
-
-  void virtio_device_config_written(unsigned reg)
-  { _dev.cfg_changed(reg); }
-
-  L4virtio::Device::Config_queue *virtqueue_config(unsigned qn)
-  {
-    if (qn >= _dev.device_config()->num_queues)
-      return nullptr;
-
-    return _dev.queue_config(qn);
-  }
-
-  L4virtio::Device::Config_queue *current_virtqueue_config()
-  {
-    return virtqueue_config(_dev.device_config()->queue_sel);
-  }
-
-  void virtio_queue_ready(unsigned ready)
-  {
-    auto *cfg = _dev.device_config();
-    unsigned qn = cfg->queue_sel;
-
-    if (qn >= cfg->num_queues)
-      return;
-
-    if (ready != 1 && ready != 0)
-      return;
-
-    auto *q = _dev.queue_config(qn);
-    if (ready == q->ready)
-      return;
-
-    q->ready = ready;
-
-    _dev.config_queue(qn);
-  }
-
-  void virtio_queue_notify(unsigned q)
-  { _dev.virtio_queue_notify(q); }
-
-  void virtio_set_status(l4_uint32_t status)
-  { _dev.set_status(status); }
-
-private:
-  DEV *dev() { return static_cast(this); }
-
-  L4virtio::Driver::Device _dev;
-};
-
-class Virtio_proxy_mmio
-: public Virtio_proxy,
-  public Vmm::Ro_ds_mapper_t,
-  public Virtio::Mmio_connector
-{
-public:
-  Virtio_proxy_mmio(L4::Cap device, l4_size_t config_size,
-                    Vmm::Vm_ram *ram)
-  : Virtio_proxy(device, config_size, ram)
-  {}
-
-  Virtio::Event_connector_irq *event_connector() { return &_evcon; }
-
-  char const *dev_name() const override { return "Virtio_proxy_mmio"; }
-
-private:
-  Virtio::Event_connector_irq _evcon;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/virtio_proxy_pci.cc b/src/l4/pkg/uvmm/server/src/virtio_proxy_pci.cc
deleted file mode 100644
index 539aec29..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_proxy_pci.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2017-2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-
-#include "virtio_pci_connector.h"
-#include "event_connector_pci.h"
-#include "pci_virtio_device.h"
-#include "virtio_proxy.h"
-#include "device/pci_host_bridge.h"
-
-
-class Virtio_proxy_pci
-: public Vdev::Pci::Virtio_device_pci,
-  public Vdev::Virtio_proxy,
-  public Virtio::Pci_connector
-{
-public:
-  Virtio_proxy_pci(Vdev::Dt_node const &node, unsigned num_msix_entries,
-                   L4::Cap device, Vmm::Vm_ram *ram,
-                   Gic::Msix_dest const &msix_dest,
-                   Vdev::Pci::Pci_bridge_windows *wnds)
-  : Virtio_device_pci(node, num_msix_entries, wnds),
-    // 0x100: size of the virtio config header
-    Virtio_proxy(device, 0x100 + device_config_len(), ram),
-    Virtio::Pci_connector(),
-    _evcon(num_msix_entries, msix_dest)
-  {}
-
-  Virtio::Event_connector_msix *event_connector() { return &_evcon; }
-
-protected:
-  cxx::Ref_ptr get_mmio_bar_handler(unsigned idx) override
-  {
-    if (idx == 0)
-      return event_connector()->make_mmio_device();
-
-    return cxx::Ref_ptr(this);
-  }
-
-  cxx::Ref_ptr get_io_bar_handler(unsigned) override
-  {
-    return cxx::Ref_ptr(this);
-  }
-
-private:
-  Virtio::Event_connector_msix _evcon;
-};
-
-#include "device_factory.h"
-#include "pci_device.h"
-#include "guest.h"
-#include "ds_mmio_mapper.h"
-
-#include 
-#include 
-
-namespace {
-
-using namespace Vdev;
-using namespace Vdev::Pci;
-
-struct F : Factory
-{
-  static Dbg warn() { return Dbg(Dbg::Dev, Dbg::Warn, "VIO proxy"); }
-  static Dbg info() { return Dbg(Dbg::Dev, Dbg::Info, "VIO proxy"); }
-
-  cxx::Ref_ptr create(Device_lookup *devs, Dt_node const &node) override
-  {
-    info().printf("Creating proxy\n");
-
-    auto cap = Vdev::get_cap(node, "l4vmm,virtiocap");
-    if (!cap)
-      return nullptr;
-
-    auto *pci = dynamic_cast(
-      devs->device_from_node(node.parent_node()).get());
-
-    if (!pci)
-      {
-        info().printf("VirtIO proxy: No PCI bus found.\n");
-        return nullptr;
-      }
-
-    auto vmm = devs->vmm();
-
-    // Only two MSIs (config & VQ). l4virtio supports only shared IRQs for all
-    // VQs.
-    auto dev_id = pci->bus()->alloc_dev_id();
-    int const num_msix = 2;
-    auto proxy =
-      make_device(node, num_msix, cap,
-                                    devs->ram().get(), pci->msix_dest(dev_id),
-                                    pci->bridge_windows());
-
-    proxy->register_irq(vmm->registry());
-    proxy->init_virtio_pci_device();
-    pci->bus()->register_device(proxy, dev_id);
-
-    return proxy;
-  }
-};
-
-static F f;
-static Device_type t = { "virtio,pci", "proxy", &f };
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/virtio_qword.h b/src/l4/pkg/uvmm/server/src/virtio_qword.h
deleted file mode 100644
index 6072197a..00000000
--- a/src/l4/pkg/uvmm/server/src/virtio_qword.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2016-2017, 2024 Kernkonzept GmbH.
- * Author(s): Philipp Eppelt 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-namespace Virtio {
-
-union Qword
-{
-  l4_uint32_t w[2];
-  l4_uint64_t q;
-};
-
-} // namespace Virtio
diff --git a/src/l4/pkg/uvmm/server/src/vm.cc b/src/l4/pkg/uvmm/server/src/vm.cc
deleted file mode 100644
index 2e4d9466..00000000
--- a/src/l4/pkg/uvmm/server/src/vm.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2017-2021, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Jean Wolter 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "vm.h"
-#include "device.h"
-#include "device_factory.h"
-#include "debug.h"
-#include "io_proxy.h"
-#include "msi_controller.h"
-
-static Dbg warn(Dbg::Core, Dbg::Warn, "vm");
-
-namespace Vmm {
-
-Vdev::Device_lookup::Ic_error
-Vm::get_or_create_ic(Vdev::Dt_node const &node, cxx::Ref_ptr *ic_ptr)
-{
-  Vdev::Dt_node ic_node = node.find_irq_parent();
-  if (!ic_node.is_valid())
-    return Ic_e_no_iparent;
-
-  if (!ic_node.is_enabled())
-    return Ic_e_disabled;
-
-  if (!Vdev::Factory::is_vdev(ic_node))
-    return Ic_e_no_virtic;
-
-  cxx::Ref_ptr dev = device_from_node(ic_node);
-  if (!dev)
-    {
-      if (!Vdev::Factory::create_irq_parent(this, node))
-        return Ic_e_failed;
-
-      dev = device_from_node(ic_node);
-      assert(dev);
-    }
-
-  cxx::Ref_ptr ic = cxx::dynamic_pointer_cast(dev);
-  if (!ic)
-    return Ic_e_no_virtic;
-
-  *ic_ptr = ic;
-  return Ic_ok;
-}
-
-Vdev::Device_lookup::Mc_error
-Vm::get_or_create_mc(Vdev::Dt_node const &node,
-                     cxx::Ref_ptr *mc_ptr)
-{
-  Vdev::Dt_node msi_parent = find_msi_parent(node);
-
-  if (!msi_parent.is_valid())
-    return Mc_e_no_msiparent;
-
-  if (!msi_parent.is_enabled())
-    return Mc_e_disabled;
-
-  if (!Vdev::Factory::is_vdev(msi_parent))
-    return Mc_e_no_msictrl;
-
-  auto dev = Vdev::Factory::create_dev(this, msi_parent);
-  if (!dev)
-    return Mc_e_failed;
-
-  auto mc = cxx::dynamic_pointer_cast(dev);
-  if (!mc)
-    return Mc_e_no_msictrl;
-
-  *mc_ptr = mc;
-  return Mc_ok;
-}
-
-cxx::Ref_ptr
-Vm::get_or_create_mc_dev(Vdev::Dt_node const &node)
-{
-  cxx::Ref_ptr mc;
-  Mc_error res = get_or_create_mc(node, &mc);
-  if (res == Mc_ok)
-    return mc;
-
-  Err().printf("%s: Failed to get MSI controller: %s\n",
-               node.get_name(), mc_err_str(res));
-
-  L4Re::throw_error(-L4_ENODEV, "Unable to locate MSI controller.");
-
-  return nullptr;
-}
-
-void
-Vm::scan_device_tree(Vdev::Device_tree dt)
-{
-  vmm()->setup_device_tree(dt);
-
-  // Instantiate all virtual devices
-  dt.scan([this] (Vdev::Dt_node const &node, unsigned /* depth */)
-          { return add_virt_device(node); },
-          [] (Vdev::Dt_node const &, unsigned) {});
-
-  // Instantiate physical devices that request a specific vbus device
-  dt.scan([this] (Vdev::Dt_node const &node, unsigned /* depth */)
-          { return add_phys_device_by_vbus_id(node); },
-          [] (Vdev::Dt_node const &, unsigned) {});
-
-  // Prepare creation of physical devices
-  Vdev::Io_proxy::prepare_factory(this);
-
-  // Instantiate all devices which have the necessary resources
-  dt.scan([this] (Vdev::Dt_node const &node, unsigned /* depth */)
-          { return add_phys_device(node); },
-          [] (Vdev::Dt_node const &, unsigned) {});
-}
-
-bool
-Vm::add_virt_device(Vdev::Dt_node const &node)
-{
-  // Ignore non virtual devices
-  if (!Vdev::Factory::is_vdev(node))
-    return true;
-
-  if (Vdev::Factory::create_dev(this, node))
-    return true;
-
-  warn.printf("Device creation for virtual device %s failed. Disabling device.\n",
-              node.get_name());
-
-  node.disable();
-  return false;
-}
-
-bool
-Vm::add_phys_device(Vdev::Dt_node const &node)
-{
-  // device_type is a deprecated option and should be set for "cpu"
-  // and "memory" devices only. Currently there are some more uses
-  // like "pci", "network", "phy", "soc2, "mdio", but we ignore these
-  // here, since they do not need special treatment.
-  char const *devtype = node.get_prop("device_type", nullptr);
-
-  // Ignore memory nodes
-  if (devtype && strcmp("memory", devtype) == 0)
-    {
-      // there should be no subnode to memory devices so it should be
-      // safe to return false to stop traversal of subnodes
-      return false;
-    }
-
-  cxx::Ref_ptr dev;
-  bool is_cpu_dev = devtype && strcmp("cpu", devtype) == 0;
-
-  // Cpu devices need to be treated specially because they use a
-  // different factory (there are too many compatible attributes to
-  // use the normal factory mechanism).
-  if (is_cpu_dev)
-    {
-      dev = cpus()->create_vcpu(&node);
-      if (!dev)
-        return false;
-
-      // XXX Other create methods directly add the created device to the device
-      // repository; We might want to do the same in create_vcpu.
-      add_device(node, dev);
-      return true;
-    }
-  else
-    {
-      if (!node.has_irqs() && !node.has_mmio_regs())
-        return true;
-
-      if (Vdev::Factory::create_dev(this, node))
-        return true;
-    }
-
-  // Device creation failed
-  if (node.has_prop("l4vmm,force-enable"))
-    {
-      warn.printf("Device creation for %s failed, 'l4vmm,force-enable' set\n",
-                  node.get_name());
-      return true;
-    }
-
-  warn.printf("Device creation for %s failed. Disabling device.\n",
-              node.get_name());
-
-  node.disable();
-  return false;
-}
-
-bool
-Vm::add_phys_device_by_vbus_id(Vdev::Dt_node const &node)
-{
-  if (!node.has_irqs() && !node.has_mmio_regs())
-    return true;
-
-  if (!node.has_prop("l4vmm,vbus-dev"))
-    return true;
-
-  if (Vdev::Factory::create_dev(this, node))
-    return true;
-
-  warn.printf("Device creation for %s failed. Disabling device.\n",
-              node.get_name());
-
-  node.disable();
-  return false;
-}
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/vm.h b/src/l4/pkg/uvmm/server/src/vm.h
deleted file mode 100644
index 5b4faf7e..00000000
--- a/src/l4/pkg/uvmm/server/src/vm.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2017-2021, 2023-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "cpu_dev_array.h"
-#include "device.h"
-#include "device_repo.h"
-#include "guest.h"
-#include "vm_ram.h"
-#include "virt_bus.h"
-#include "monitor/vm_cmd_handler.h"
-#include "pm.h"
-
-namespace Vmm {
-
-/**
- * The main instance of a hardware-virtualized guest.
- */
-class Vm
-: public Vdev::Device_lookup,
-  public Monitor::Vm_cmd_handler
-{
-  friend Vm_cmd_handler;
-
-public:
-  cxx::Ref_ptr
-  device_from_node(Vdev::Dt_node const &node,
-                   std::string *path = nullptr) const override
-  { return _devices.device_from_node(node, path); }
-
-  Vmm::Guest *vmm() const override
-  { return _vmm; }
-
-  cxx::Ref_ptr ram() const override
-  { return _ram; }
-
-  cxx::Ref_ptr vbus() const override
-  { return _vbus; }
-
-  cxx::Ref_ptr cpus() const override
-  { return _cpus; }
-
-  cxx::Ref_ptr pm() const override
-  { return _pm; }
-
-  /**
-   * \see Device_lookup::get_or_create_ic(Vdev::Dt_node const &node,
-   *                                      cxx::Ref_ptr *ic_ptr)
-   */
-  Ic_error get_or_create_ic(Vdev::Dt_node const &node,
-                            cxx::Ref_ptr *ic_ptr) override;
-
-  /**
-   * \see Device_lookup::get_or_create_mc(
-   *        Vdev::Dt_node const &node,
-   *        cxx::Ref_ptr *mc_ptr)
-   */
-  Mc_error
-  get_or_create_mc(Vdev::Dt_node const &node,
-                   cxx::Ref_ptr *mc_ptr) override;
-
-  /**
-   * \see Device_lookup::get_or_create_mc_dev()
-   */
-  cxx::Ref_ptr
-  get_or_create_mc_dev(Vdev::Dt_node const &node) override;
-
-  void create_default_devices()
-  {
-    _vmm = Vmm::Guest::create_instance();
-    _ram = Vdev::make_device(Vmm::Guest::Boot_offset);
-
-    auto vbus_cap = L4Re::Env::env()->get_cap("vbus");
-    _vbus = Vdev::make_device(vbus_cap, _vmm->registry());
-
-    _cpus = Vdev::make_device();
-
-    _pm = Vdev::make_device();
-
-  }
-
-  void add_device(Vdev::Dt_node const &node,
-                  cxx::Ref_ptr dev,
-                  std::string const &path = std::string()) override
-  { _devices.add(node, dev, path); }
-
-  /**
-   * Find MSI parent of node.
-   *
-   * \param node  Node to find the MSI parent of.
-   *
-   * \return  The node of the MSI parent or an invalid node, if neither the
-   *          'msi-parent' nor the 'msi-map' property are specified or
-   *          reference an invalid node.
-   *
-   * \note  Currently, this function only returns the simple case of one
-   *        referenced MSI parent node in the device tree.
-   */
-  Vdev::Dt_node find_msi_parent(Vdev::Dt_node const &node) const
-  {
-    int size = 0;
-    auto *prop = node.get_prop("msi-parent", &size);
-    if (prop)
-      {
-        if (size != 1)
-          L4Re::throw_error(
-            -L4_EINVAL, "The msi-parent property must be a single reference.");
-
-        return node.find_phandle(*prop);
-      }
-
-    prop = node.get_prop("msi-map", &size);
-    if (prop)
-      {
-        if (size != 4)
-          L4Re::throw_error(
-            -L4_EINVAL, "The msi-map property must contain exactly one entry.");
-
-        return node.find_phandle(prop[1]);
-      }
-
-    return Vdev::Dt_node();
-  }
-
-  /**
-   * Collect and instantiate all devices described in the device tree.
-   *
-   * \param dt  Device tree to scan.
-   *
-   * This function first instantiates all device for which a virtual
-   * implementation exists and then goes through the remaining devices
-   * and tries to assign any missing resources from the vbus (if existing).
-   */
-  void scan_device_tree(Vdev::Device_tree dt);
-
-private:
-  bool add_virt_device(Vdev::Dt_node const &node);
-  bool add_phys_device(Vdev::Dt_node const &node);
-  bool add_phys_device_by_vbus_id(Vdev::Dt_node const &node);
-
-  Vdev::Device_repository _devices;
-  Vmm::Guest *_vmm;
-  cxx::Ref_ptr _ram;
-  cxx::Ref_ptr _vbus;
-  cxx::Ref_ptr _cpus;
-  cxx::Ref_ptr _pm;
-};
-}
diff --git a/src/l4/pkg/uvmm/server/src/vm_memmap.cc b/src/l4/pkg/uvmm/server/src/vm_memmap.cc
deleted file mode 100644
index 3e4af4ea..00000000
--- a/src/l4/pkg/uvmm/server/src/vm_memmap.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015-2019, 2021-2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *            Alexander Warg 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include "vm_memmap.h"
-
-
-void Vmm::Vm_mem::dump(Dbg::Verbosity l) const
-{
-  Dbg d(Dbg::Dev, l, "vmmap");
-  if (d.is_active())
-    {
-      d.printf("VM map:\n");
-      for (auto const &r: *this)
-        d.printf(" [%8lx:%8lx]: %s\n",
-                 r.first.start.get(), r.first.end.get(),
-                 r.second->dev_name());
-    }
-}
-
-void
-Vmm::Vm_mem::throw_error(char const *msg,
-            cxx::Ref_ptr const &dev, Vmm::Region const ®ion,
-            cxx::Ref_ptr const &new_dev, Vmm::Region const &new_region)
-{
-  char buf[80], buf_new[80];
-  dump(Dbg::Warn);
-  Err().printf("%s:\n"
-               " VM addresses: [%08lx:%08lx] <-> [%08lx:%08lx]\n"
-               " Device info:  %s <-> %s\n", msg,
-               region.start.get(), region.end.get(),
-               new_region.start.get(), new_region.end.get(),
-               dev->dev_info(buf, sizeof(buf)),
-               new_dev->dev_info(buf_new, sizeof(buf_new)));
-  L4Re::throw_error(-L4_EINVAL, msg);
-}
-
-void
-Vmm::Vm_mem::add_mmio_device(Vmm::Region const ®ion,
-                             cxx::Ref_ptr const &dev)
-{
-  if (count(region) == 0)
-    {
-      insert(std::make_pair(region, dev));
-      return;
-    }
-
-  auto lower = lower_bound(region);
-  auto const ¤t_region = lower->first;
-
-  // We can't merge if the region is marked moveable
-  if (region.flags & Region_flags::Moveable)
-    throw_error("Unmergable mmio regions in VM address space: region is moveable",
-                lower->second, current_region, dev, region);
-
-  if (current_region.contains(region))
-    {
-      // Region is a subset of an already existing one, there can be
-      // at most one such region
-      if (!lower->second->mergable(dev, region.start, current_region.start))
-        throw_error("Unmergable mmio regions in VM address space: region is subset",
-                    lower->second, current_region, dev, region);
-      return;
-    }
-
-  auto upper = upper_bound(region);
-  for(auto it = lower; it != upper; ++it)
-    {
-      auto const &tmp_region = it->first;
-      // We already handled smaller regions above, so the region is
-      // either a superset or not a candidate for a merge operation
-      if (region.contains(tmp_region))
-        {
-          if (!it->second->mergable(dev, region.start, tmp_region.start))
-            throw_error("Unmergable mmio regions in VM address space: region is superset",
-                        lower->second, tmp_region, dev, region);
-        }
-      else
-        throw_error("Unmergable mmio regions in VM address space",
-                    lower->second, tmp_region, dev, region);
-    }
-
-  // [lower, upper) is a subset of region - erase it
-  erase(lower, upper);
-  insert(std::make_pair(region, dev));
-}
diff --git a/src/l4/pkg/uvmm/server/src/vm_memmap.h b/src/l4/pkg/uvmm/server/src/vm_memmap.h
deleted file mode 100644
index 07c363d5..00000000
--- a/src/l4/pkg/uvmm/server/src/vm_memmap.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "mmio_device.h"
-#include "mem_types.h"
-
-namespace Vmm {
-
-class Vm_mem : public std::map>
-{
-public:
-  void add_mmio_device(Region const ®ion,
-                       cxx::Ref_ptr const &dev);
-
-  void dump(Dbg::Verbosity l) const;
-
-private:
-  void throw_error(char const *msg,
-            cxx::Ref_ptr const &dev, Vmm::Region const ®ion,
-            cxx::Ref_ptr const &new_dev, Vmm::Region const &new_region);
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/server/src/vm_ram.cc b/src/l4/pkg/uvmm/server/src/vm_ram.cc
deleted file mode 100644
index 55b42d16..00000000
--- a/src/l4/pkg/uvmm/server/src/vm_ram.cc
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2018-2022, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "debug.h"
-#include "vm_memmap.h"
-#include "vm_ram.h"
-#include "device_factory.h"
-
-namespace {
-
-class Auto_fd
-{
-public:
-  explicit Auto_fd(int fd) : _fd(fd) {}
-  Auto_fd(Auto_fd &&) = delete;
-  Auto_fd(Auto_fd const &) = delete;
-
-  ~Auto_fd()
-  {
-    if (_fd >= 0)
-      close(_fd);
-  }
-
-  int get() const { return _fd; }
-
-private:
-  int _fd;
-};
-
-}
-
-static Dbg warn(Dbg::Core, Dbg::Warn, "ram");
-static Dbg info(Dbg::Core, Dbg::Info, "ram");
-static Dbg trace(Dbg::Core, Dbg::Trace, "ram");
-
-bool
-Vmm::Ram_free_list::reserve_fixed(Vmm::Guest_addr start, l4_size_t size)
-{
-  for (auto it = _freelist.begin(); it != _freelist.end(); ++it)
-    {
-      if (!it->contains(Region::ss(start, size, Region_type::Ram)))
-        continue;
-
-      if (start == it->start)
-        *it = Region(start + size, it->end, Region_type::Ram);
-      else
-        {
-          auto oldend = it->end;
-          *it = Region(it->start, start - 1, Region_type::Ram);
-
-          if (oldend >= start + size)
-            _freelist.insert(it + 1, Region(start + size, oldend,
-                                            Region_type::Ram));
-        }
-
-      return true;
-    }
-
-  return false;
-}
-
-bool
-Vmm::Ram_free_list::reserve_back(l4_size_t size, Vmm::Guest_addr *start,
-                                 unsigned char page_shift,
-                                 Vmm::Guest_addr upper_limit)
-{
-  for (auto rit = _freelist.rbegin(); rit != _freelist.rend(); ++rit)
-    {
-      l4_uint64_t end = rit->end.get();
-      if (rit->end - rit->start + 1 < size)
-        continue;
-
-      // region resides above upper_limit completely
-      if (rit->start >= upper_limit)
-        continue;
-
-      // region is at or spans upper limit
-      if (rit->end >= upper_limit)
-        {
-          // and the area below upper_limit is too small
-          if ((rit->start + size) >= upper_limit)
-            continue;
-
-          // use the area below upper limit
-          end = upper_limit.get();
-        }
-
-      auto s = l4_trunc_size(end - size + 1, page_shift);
-
-      if (s < rit->start.get())
-        continue;
-
-      assert(*start + size < upper_limit);
-      *start = Vmm::Guest_addr(s);
-
-      return reserve_fixed(*start, size);
-    }
-
-  return false;
-}
-
-long
-Vmm::Ram_free_list::load_file_to_back(Vm_ram *ram, char const *name,
-                                      Vmm::Guest_addr *start, l4_size_t *size)
-{
-  Auto_fd fd(open(name, O_RDONLY));
-  if (fd.get() < 0)
-    {
-      Err().printf("could not open file: %s\n", name);
-      L4Re::throw_error(-L4_EINVAL, "Open file to load into guest RAM.");
-    }
-
-  cxx::Ref_ptr file = L4Re::Vfs::vfs_ops->get_file(fd.get());
-  if (!file)
-    {
-      Err().printf("bad file descriptor: %s\n", name);
-      L4Re::throw_error(-L4_EINVAL,
-                        "Get VFS file descriptor to load into guest RAM.");
-    }
-
-  L4::Cap f = file->data_space();
-  if (!f)
-    {
-      Err().printf("could not get data space for %s\n", name);
-      L4Re::throw_error(-L4_EINVAL, "Get dataspace to load into guest RAM.");
-    }
-
-  Vmm::Guest_addr addr;
-  l4_size_t sz = f->size();
-
-  if (!reserve_back(sz, &addr, L4_SUPERPAGESHIFT))
-    return -L4_ENOMEM;
-
-  info.printf("load: %s -> 0x%lx\n", name, addr.get());
-
-  if (start)
-    *start = addr;
-  if (size)
-    *size = sz;
-
-  ram->load_file(f, addr, sz);
-
-  return L4_EOK;
-}
-
-l4_size_t
-Vmm::Vm_ram::add_memory_region(L4::Cap ds, Vmm::Guest_addr baseaddr,
-                               l4_addr_t ds_offset, l4_size_t size, Vm_mem *memmap,
-                               L4Re::Rm::Region_flags flags)
-{
-  cxx::Ref_ptr r = cxx::make_ref_obj(ds, size, ds_offset, flags);
-
-  if (!r || r->setup(baseaddr, as_mgr()) < 0)
-    return -1;
-
-  auto dsdev = Vdev::make_device(r, L4_FPAGE_RWX);
-  memmap->add_mmio_device(Region::ss(r->vm_start(), r->size(), Region_type::Ram),
-                          std::move(dsdev));
-
-  _regions.push_back(std::move(r));
-
-  return _regions.size() - 1;
-}
-
-
-Vmm::Ram_free_list
-Vmm::Vm_ram::setup_from_device_tree(Vdev::Host_dt const &dt, Vm_mem *memmap,
-                                    Vmm::Guest_addr default_address)
-{
-  bool has_memory_nodes = false;
-
-  if (dt.valid())
-    {
-      dt.get().scan(
-        [this, &memmap, &has_memory_nodes](Vdev::Dt_node const &node, int)
-          {
-            char const *devtype = node.get_prop("device_type", nullptr);
-
-            if (!devtype || strcmp("memory", devtype) != 0)
-              return true;
-
-            if (add_from_dt_node(memmap, &has_memory_nodes, node) < 0)
-              node.disable();
-
-            // memory nodes should not have children, so no point in further
-            // scanning
-            return false;
-          },
-          [] (Vdev::Dt_node const &, unsigned) {});
-
-      int err = dt.get().remove_nodes_by_property("device_type", "memory", true);
-      if (err < 0)
-        {
-          Err().printf("Unable to remove disabled memory nodes: %s\n",
-                       fdt_strerror(err));
-          throw L4::Runtime_error(-L4_EINVAL);
-        }
-    }
-
-  // In case of an invalid DT or without memory node, do mode selection;
-  // otherwise, doing it again returns directly.
-  as_mgr()->mode_selection();
-
-  if (!has_memory_nodes)
-    {
-      warn.printf("No memory nodes found, setting up default region\n");
-      setup_default_region(dt, memmap, default_address);
-    }
-  else if (_regions.empty())
-    L4Re::chksys(-L4_ENOMEM,
-                 "Memory configuration in device tree provides no valid RAM");
-
-  Ram_free_list list;
-  L4::Cap main_ds = _regions[0]->ds();
-
-  for (auto const &r : _regions)
-    {
-      if (r->ds() != main_ds)
-        break;
-
-      list.add_free_region(r->vm_start(), r->size());
-    }
-
-  return list;
-}
-
-l4_addr_t
-Vmm::Vm_ram::move_in_device_tree(Ram_free_list *free_list, Vdev::Host_dt &&dt)
-{
-  dt.compact();
-
-  l4_size_t new_size = dt.get().size();
-  Guest_addr addr;
-
-  if (!free_list->reserve_back(new_size, &addr, L4_PAGESHIFT,
-                               Guest_addr(dt.upper_limit())))
-    L4Re::chksys(-L4_ENOMEM, "Copy device tree into guest memory. "
-                             "Failed to find a memory area.");
-
-  void *target = guest2host(addr);
-
-  dt.move(target);
-
-  l4_addr_t ds_start = reinterpret_cast(target);
-  l4_cache_clean_data(ds_start, ds_start + new_size);
-
-  warn.printf("Cleaning caches for device tree [%lx-%lx] ([%lx])\n",
-              ds_start, ds_start + new_size - 1, addr.get());
-
-  return guest_phys2boot(addr);
-}
-
-
-long
-Vmm::Vm_ram::add_from_dt_node(Vm_mem *memmap, bool *found,
-                              Vdev::Dt_node const &node)
-{
-  if (!node.is_enabled())
-    return -L4_ENOSYS;
-
-  if (!node.has_prop("l4vmm,dscap"))
-    return -L4_ENOSYS;
-
-  *found = true;
-  auto ds = Vdev::get_cap(node, "l4vmm,dscap");
-  if (!ds)
-    return -L4_EINVAL;
-
-  L4Re::Dataspace::Stats ds_stats;
-  L4Re::chksys(ds->info(&ds_stats), "Get Dataspace statistics.");
-
-  l4_addr_t offset = 0;
-  l4_uint64_t remain = ds_stats.size;
-
-  int reg_idx = 0;
-
-  // so we can iterate later over new regions
-  l4_size_t first_region = _regions.size();
-  // dma-ranges can only be set for all regions or none
-  bool add_dma_ranges = node.has_prop("dma-ranges");
-  if (add_dma_ranges)
-    as_mgr()->info_add_dma_ranges();
-
-  // all info acquired, do mode selection.
-  as_mgr()->mode_selection();
-
-  if (node.has_prop("l4vmm,physmap"))
-    {
-      Err().printf("Physmap property in device tree memory nodes is deprecated.\n"
-                   "Remove the property from the memory node and check that "
-                   "DMA capable devices in \nIo's System_bus configuration "
-                   "feature the 'Io.Hw_device_DF_dma_supported' flag. \n"
-                   "If you still need a physmap alike mode, use the '-i' flag "
-                   "on the command line.\n");
-      L4Re::throw_error(-L4_EINVAL, "DT property 'l4vmm,physmap' deprecated.");
-    }
-
-  if (as_mgr()->is_any_identity_mode())
-    {
-      l4_size_t ridx =
-        add_memory_region(ds, Vmm::Guest_addr(0UL), 0, remain, memmap);
-
-      if (ridx != -1U)
-        remain = 0; // we are done
-      else
-        {
-          warn.printf("Memory region '%s' cannot be identity mapped.\n",
-                      node.get_name());
-          if (!node.has_prop("reg"))
-            L4Re::chksys(-L4_ENOMEM, "Setup of RAM memory region");
-        }
-    }
-
-  while (remain > 0)
-    {
-      l4_uint64_t reg_addr, reg_size;
-      int ret = node.get_reg_val(reg_idx++, ®_addr, ®_size);
-
-      if (ret == -Vdev::Dt_node::ERR_BAD_INDEX)
-        break;
-
-      if (ret < 0)
-        {
-          if (ret == -FDT_ERR_NOTFOUND)
-            Err().printf("Memory node %s must contain a reg property in %s "
-                         "mode.\n",
-                         node.get_name(), as_mgr()->mode());
-          else
-            Err().printf("Error when parsing memory node %s: %s (%i)\n",
-                         node.get_name(), node.strerror(ret), ret);
-
-          L4Re::throw_error(-L4_EINVAL,
-                            "Reading reg values from DT memory nodes.");
-        }
-
-      trace.printf("Adding region @0x%llx (size = 0x%llx remaining = 0x%llx)\n",
-                   reg_addr, reg_size, remain);
-
-      // If the size 0 was specified it means the user wants to use the
-      // remaining available space.
-      if (reg_size == 0)
-        reg_size = remain;
-
-      l4_uint64_t map_size = cxx::min(reg_size, remain);
-
-      if (map_size & ~L4_PAGEMASK)
-        L4Re::chksys(-L4_EINVAL,
-                     "Size must be rounded to page size for DT memory nodes");
-
-      if (reg_addr & ~L4_PAGEMASK)
-        L4Re::chksys(-L4_EINVAL,
-                     "Start address must be rounded to page size for DT memory nodes");
-
-      l4_size_t ridx = add_memory_region(ds, Vmm::Guest_addr(reg_addr), offset,
-                                         map_size, memmap);
-      if (ridx == -1U)
-        L4Re::chksys(-L4_ENOMEM, "Setting up RAM region via DT memory nodes.");
-
-      remain -= map_size;
-      offset += map_size;
-
-      if (!_regions[ridx]->has_phys_addr())
-        add_dma_ranges = false;
-    }
-
-  if (first_region == _regions.size())
-    return -L4_ENOMEM; // no regions found, disable
-
-  // update the regs property
-  bool append = false;
-  for (l4_size_t i = first_region; i < _regions.size(); ++i)
-    {
-      node.set_reg_val(_regions[i]->vm_start().get(), _regions[i]->size(), append);
-      append = true;
-
-      if (add_dma_ranges)
-        _regions[i]->dt_append_dmaprop(node);
-    }
-
-  if (!add_dma_ranges)
-    node.delprop("dma-ranges");
-
-  return L4_EOK;
-}
-
-void
-Vmm::Vm_ram::setup_default_region(Vdev::Host_dt const &dt, Vm_mem *memmap,
-                                  Vmm::Guest_addr baseaddr)
-{
-  auto ds = L4Re::chkcap(L4Re::Env::env()->get_cap("ram"),
-                         "Grabbing default \"ram\" capability", -L4_ENOENT);
-  l4_size_t ridx = add_memory_region(ds, baseaddr, 0, ds->size(), memmap);
-
-  if (ridx == -1U)
-    L4Re::chksys(-L4_ENOMEM, "Setting up default RAM region.");
-
-  if (dt.valid())
-    {
-      auto const &r = _regions[ridx];
-      // "memory@" + 64bit hex address + '\0'
-      char buf[7 + 16 + 1];
-      std::snprintf(buf, sizeof(buf), "memory@%lx", r->vm_start().get());
-
-      auto node = dt.get().first_node().add_subnode(buf);
-      node.setprop_string("device_type", "memory");
-      node.set_reg_val(r->vm_start().get(), r->size());
-
-      if (r->has_phys_addr())
-        r->dt_append_dmaprop(node);
-    }
-}
diff --git a/src/l4/pkg/uvmm/server/src/vm_ram.h b/src/l4/pkg/uvmm/server/src/vm_ram.h
deleted file mode 100644
index 99c4b3f6..00000000
--- a/src/l4/pkg/uvmm/server/src/vm_ram.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * (c) 2013-2014 Alexander Warg 
- *     economic rights: Technische Universität Dresden (Germany)
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-#include "device.h"
-#include "ds_mmio_mapper.h"
-#include "host_dt.h"
-#include "mem_types.h"
-#include "ram_ds.h"
-#include "vm_memmap.h"
-#include "monitor/vm_ram_cmd_handler.h"
-#include "address_space_manager.h"
-
-class Vm_mem;
-
-namespace Vmm {
-
-class Ram_free_list
-{
-  friend class Vm_ram;
-
-public:
-  /**
-   * Return the first available address in the free list.
-   *
-   * This is the first address found in the order that regions were originally
-   * added to the list and that is still available.
-   */
-  Vmm::Guest_addr first_free_address() const
-  { return _freelist[0].start; }
-
-  bool reserve_fixed(Vmm::Guest_addr start, l4_size_t size);
-  bool reserve_back(l4_size_t size, Vmm::Guest_addr *start,
-                    unsigned char page_shift = L4_PAGESHIFT,
-                    Vmm::Guest_addr upper_limit = Vmm::Guest_addr(~0UL));
-
-  long load_file_to_back(Vm_ram *ram, char const *name,
-                         Vmm::Guest_addr *start, l4_size_t *size);
-
-private:
-  void add_free_region(Vmm::Guest_addr start, l4_size_t size)
-  { _freelist.push_back(Region::ss(start, size, Region_type::Ram)); }
-
-  std::vector _freelist;
-};
-
-/**
- * The memory device which manages the RAM available to the guest.
- */
-class Vm_ram
-: public Vdev::Device,
-  public Monitor::Vm_ram_cmd_handler
-{
-  friend Vm_ram_cmd_handler;
-
-public:
-  Vm_ram(l4_addr_t boot_offset)
-  : _boot_offset(boot_offset),
-    _as_mgr(Vdev::make_device())
-  {}
-
-  /**
-   * Load the contents of the given dataspace into guest RAM.
-   *
-   * \param file  Dataspace to load from. The entire dataspace is loaded.
-   * \param addr  Guest physical address to load the data space to.
-   * \param sz    Number of bytes to copy.
-   */
-  void load_file(L4::Cap const &file,
-                 Vmm::Guest_addr addr, l4_size_t sz) const
-  {
-    auto r = find_region(addr, 0);
-    if (!r)
-      L4Re::chksys(-L4_ENOENT, "Guest region found");
-
-    r->load_file(file, addr, sz);
-  }
-
-  /**
-   * Get a VMM-virtual pointer from a guest-physical address.
-   */
-  template 
-  T guest2host(Vmm::Guest_addr p) const
-  {
-    auto r = find_region(p, 0);
-    if (!r)
-      L4Re::chksys(-L4_ENOENT, "Guest address outside RAM");
-
-    return reinterpret_cast(r->guest2host(p));
-  }
-
-  /**
-   * Get a VMM-virtual pointer for the start of the given region.
-   *
-   * An exception is thrown if the region is not completely contained in
-   * one of the RAM areas.
-   */
-  template 
-  T guest2host(Region region) const
-  {
-    auto r = find_region(region.start, region.end - region.start + 1);
-    if (!r)
-      L4Re::chksys(-L4_ERANGE, "Guest address outside RAM region");
-
-    return reinterpret_cast(r->guest2host(region.start));
-  }
-
-  /**
-   * Set up the RAM according to the configuration in the given device tree.
-   *
-   * \param dt               Device tree to scan. May be invalid, in which case
-   *                         only a single region from the 'ram' dataspace is
-   *                         set up.
-   * \param memap            Guest memory map where to register the new region.
-   * \param default_address  Address to map RAM to when no config is found
-   *                         in the device tree.
-   *
-   * \return Free list of RAM that may be prefilled with custom content.
-   *         At the moment the list contains all regions that are related to
-   *         the first memory entry in the device tree.
-   */
-  Ram_free_list setup_from_device_tree(Vdev::Host_dt const &dt, Vm_mem *memmap,
-                                       Vmm::Guest_addr default_address);
-
-  /**
-   * Move the device tree into guest RAM.
-   *
-   * \param free_list  List of usable RAM regions. The device tree will be
-   *                   copied to the first available area at the end of this
-   *                   list.
-   * \param dt         Host device tree, to be discarded after having been
-   *                   moved to RAM.
-   *
-   * \return Boot address of the begining of the device tree.
-   */
-  l4_addr_t move_in_device_tree(Ram_free_list *free_list, Vdev::Host_dt &&dt);
-
-  /**
-   * Compute the boot address of a guest physical pointer.
-   */
-  l4_addr_t guest_phys2boot(Vmm::Guest_addr p) const noexcept
-  { return p.get() + _boot_offset; }
-
-  Vmm::Guest_addr boot2guest_phys(l4_addr_t p) const
-  {
-    if (p < _boot_offset)
-      L4Re::chksys(-L4_ERANGE, "Not a boot address");
-
-    return Vmm::Guest_addr(p - _boot_offset);
-  }
-
-  void copy_from_ds(L4::Cap ds, l4_addr_t offset,
-                    Vmm::Guest_addr gp_addr, l4_size_t size) const
-  {
-    auto r = find_region(gp_addr, size);
-
-    // XXX cannot handle copying into consecutive DS at the moment
-    if (!r)
-      L4Re::chksys(-L4_EINVAL, "Target address outside RAM while copying data to guest.");
-
-    L4Re::chksys(r->ds()->copy_in(gp_addr.get() - r->vm_start().get(),
-                                  ds, offset, size),
-                 "Copying from dataspace into guest RAM.");
-  }
-
-  template
-  void foreach_region(FUNC &&func) const
-  {
-    for (auto const &r : _regions)
-      func(*r.get());
-  }
-
-  Vmm::Address_space_manager *as_mgr() const { return _as_mgr.get(); }
-
-  /**
-   * Add a new RAM region.
-   *
-   * \param ds        Dataspace containing the RAM.
-   * \param baseaddr  Guest physical start address of the dataspce.
-   * \param ds_offset Offset into the dataspace where to start mapping.
-   * \param size      Size of the area to map.
-   * \param memap     Guest memory map where to register the new region.
-   * \param flags     Access rights for the memory region.
-   *
-   * \return Index into _regions of the newly added region.
-   */
-  l4_size_t add_memory_region(L4::Cap ds,
-                              Vmm::Guest_addr baseaddr, l4_addr_t ds_offset,
-                              l4_size_t size, Vm_mem *memmap,
-                              L4Re::Rm::Region_flags flags = L4Re::Rm::F::RWX);
-
-private:
-  cxx::Ref_ptr find_region(Vmm::Guest_addr addr, l4_size_t size) const
-  {
-    // Check that search range is valid, i.e. does not wrap around.
-    if (size > std::numeric_limits::max() - addr.get())
-      return nullptr;
-
-    for (auto const &r : _regions)
-      {
-        if (addr >= r->vm_start() && addr - r->vm_start() + size <= r->size())
-          return r;
-      }
-
-    return nullptr;
-  }
-
-  long add_from_dt_node(Vm_mem *memmap, bool *found, Vdev::Dt_node const &node);
-  void setup_default_region(Vdev::Host_dt const &dt, Vm_mem *memmap,
-                            Vmm::Guest_addr baseaddr);
-
-  std::vector> _regions;
-  l4_addr_t _boot_offset;
-  cxx::Ref_ptr _as_mgr;
-};
-
-}
diff --git a/src/l4/pkg/uvmm/server/src/vmprint.h b/src/l4/pkg/uvmm/server/src/vmprint.h
deleted file mode 100644
index db2d4d3e..00000000
--- a/src/l4/pkg/uvmm/server/src/vmprint.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2015-2016, 2019, 2024 Kernkonzept GmbH.
- * Author(s): Sarah Hoffmann 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "debug.h"
-
-namespace Vmm {
-
-/**
- * A simple console output buffer to be used with early print
- * implementations via hypcall.
- */
-class Guest_print_buffer
-{
-public:
-
-  Guest_print_buffer()
-  : _early_print_pos(0)
-  {
-    _early_print_buf[255] = '\0';
-  }
-
-  void print_char(char c)
-  {
-    if (!(c == '\n' || c == '\0'))
-      _early_print_buf[_early_print_pos++] = c;
-
-    if (_early_print_pos >= 255 || c == '\n' || c == '\0')
-      {
-        _early_print_buf[_early_print_pos] = '\0';
-        printf("GUEST: %s\n", _early_print_buf);
-        _early_print_pos = 0;
-      }
-  }
-
-private:
-  char _early_print_buf[256];
-  unsigned _early_print_pos;
-};
-
-} // namespace
diff --git a/src/l4/pkg/uvmm/tools/Makefile b/src/l4/pkg/uvmm/tools/Makefile
deleted file mode 100644
index 3d07ad0d..00000000
--- a/src/l4/pkg/uvmm/tools/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-PKGDIR ?= ..
-L4DIR  ?= $(PKGDIR)/../..
-
-TARGET = uvmm_cli uvmm_dtg
-
-include $(L4DIR)/mk/subdir.mk
diff --git a/src/l4/pkg/uvmm/tools/uvmm_cli/Makefile b/src/l4/pkg/uvmm/tools/uvmm_cli/Makefile
deleted file mode 100644
index 35b5b413..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_cli/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-PKGDIR ?= ../..
-L4DIR  ?= $(PKGDIR)/../..
-
-TARGET = uvmm_cli
-SRC_CC = uvmm_cli.cc
-
-REQUIRES_LIBS = libstdc++ readline
-DEPENDS_PKGS = readline
-
-include $(L4DIR)/mk/prog.mk
diff --git a/src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.cc b/src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.cc
deleted file mode 100644
index 03b64d97..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (C) 2019-2020, 2023-2024 Kernkonzept GmbH.
- * Author(s): Adam Lackorzynski 
- *            Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include "uvmm_cli.h"
-
-/**
- * Uvmm CLI server.
- *
- * See `uvmm_cli.h` for an explanation of the protocol used to exchange
- * commands and completions with uvmm.
- */
-
-/*
- * Two threads will run inside a server running this program, the main thread
- * and the "readline-thread". The main thread runs the server loop after
- * registering an object that implements the vcon protocol over which uvmm
- * exchanges data with the server. The readline thread implements the main
- * readline loop. In principle, this second thread could have been avoided by
- * utilizing readlines asynchronous interface but it turns out that this does
- * not work well together with e.g. history search.
- *
- * Cooperation and synchronisation between these two threads works as follows:
- * Once the user has entered a line via the readline interface, the readline
- * thread will preprocess this line, append it to the command history and then
- * copy it into a buffer (`Uvmm_cli_vcon::_send_buf`) that is shared between
- * both threads. It will then trigger an irq that signals uvmm to start
- * receiving command data from the server and subsequently block on a semaphore
- * (`Uvmm_cli_vcon::_sem`). The thread will continue to block on this
- * semaphore until uvmm has read the issued command and sent back the complete
- * command output.
- *
- * Inside an irq handler uvmm will issue vcon read requests which will lead to
- * the execution of `Uvmm_cli_vcon::vcon_read` inside the main thread. We make
- * no assumptions about whether uvmm will read the whole command at once or in
- * blocks (i.e. `Uvmm_cli_vcon::vcon_read` may run arbitrarily often). Once
- * uvmm has read the whole command, a flag which indicates that uvmm command
- * output is expected (`Uvmm_cli_vcon::_ready_to_receive`) is set. This is
- * done such as to prevent any possibility of spurious vcon writes coming from
- * uvmm at other points in time interfering with the command output receive
- * buffer (`Uvmm_cli_vcon::_receive_buf`). Receiving the command output, again
- * possibly in blocks, happens inside `Uvmm_cli_vcon::vcon_write` running in
- * the main thread. When a special terminating character sequence is read (see
- * `uvmm_cli.h`), `Uvmm_cli_vcon::_ready_to_receive` is set to `false` and
- * `Uvmm_cli_vcon::_sem` is incremented such that the readline thread can wake
- * up, read the command output from `Uvmm_cli_vcon::_receive_buf`, write it to
- * stdout and start the whole process anew.
- *
- * This procedure ensure that readline prompt will only become active again
- * after the complete output of a command has been produced and sent back to
- * the server.
- */
-
-namespace {
-
-class Uvmm_cli_vcon
-: public L4Re::Util::Vcon_svr,
-  public L4Re::Util::Icu_cap_array_svr,
-  public L4::Epiface_t
-{
-public:
-  static Uvmm_cli_vcon *get()
-  {
-    static Uvmm_cli_vcon cons;
-    return &cons;
-  }
-
-  unsigned vcon_read(char *buf, unsigned size)
-  {
-    std::lock_guard lock(_send_mutex);
-
-    if (_send_buf.empty())
-      return L4_VCON_READ_STAT_DONE;
-
-    if (size == 0)
-      return 0;
-
-    if (size < _send_buf.size())
-      {
-        memcpy(buf, _send_buf.data(), size);
-
-        _send_buf = _send_buf.substr(size);
-      }
-    else
-      {
-        memcpy(buf, _send_buf.data(), _send_buf.size());
-        size = _send_buf.size() | L4_VCON_READ_STAT_DONE;
-
-        _send_buf.clear();
-        _ready_to_receive = true;
-      }
-
-    return size;
-  }
-
-  void vcon_write(const char *buf, unsigned size)
-  {
-    if (!_ready_to_receive || size == 0)
-      return;
-
-    std::lock_guard lock(_receive_mutex);
-
-    char const *eot = reinterpret_cast(
-      memchr(buf, (char)Uvmm_cli::PROTO_EOT, size));
-
-    if (eot)
-      {
-        _receive_buf << std::string(buf, eot);
-        _ready_to_receive = false;
-        _sem->up();
-      }
-    else
-      {
-        _receive_buf << std::string(buf, buf + size);
-      }
-  }
-
-  int vcon_get_attr(l4_vcon_attr_t *attr)
-  {
-    attr->l_flags = Uvmm_cli::ENABLED;
-    attr->o_flags = attr->i_flags = 0;
-    return L4_EOK;
-  }
-
-  void send(std::string const &buf)
-  { _send(buf); }
-
-  void complete(std::string const &buf)
-  { _send(buf, true); }
-
-  std::string receive()
-  {
-    std::lock_guard lock(_receive_mutex);
-
-    assert(!_ready_to_receive);
-
-    std::string ret(_receive_buf.str());
-    _receive_buf.str("");
-
-    return ret;
-  }
-
-private:
-  Uvmm_cli_vcon() : Icu_cap_array_svr(1, &_irq),
-                   _sem(L4Re::Util::make_unique_cap()),
-                   _ready_to_receive(false)
-  {
-    L4Re::chkcap(_sem, "semaphore capability slot valid");
-
-    L4Re::chksys(L4Re::Env::env()->factory()->create(_sem.get()),
-                 "create semaphore kernel object");
-  }
-
-  void _send(std::string const &buf, bool complete = false)
-  {
-    {
-      std::lock_guard lock(_send_mutex);
-
-      assert(_send_buf.empty());
-
-      _send_buf = buf;
-      if (complete)
-        _send_buf += (char)Uvmm_cli::PROTO_COMPL_REQ;
-      _send_buf += '\n';
-    }
-
-    _irq.trigger();
-
-    _sem->down();
-  }
-
-  std::string _send_buf;
-  std::stringstream _receive_buf;
-  L4Re::Util::Icu_cap_array_svr::Irq _irq;
-
-  L4Re::Util::Unique_cap _sem;
-  std::mutex _send_mutex; /// synchronises access to _send_buf
-  std::mutex _receive_mutex; /// synchronises access to _receive_buf
-  bool _ready_to_receive;
-};
-
-class Readline_loop
-{
-public:
-  static Readline_loop *get()
-  {
-    static Readline_loop rl;
-    return &rl;
-  }
-
-  void run(char const *prompt)
-  {
-    // readline loop
-    for (;;)
-      {
-        // read line
-        char *line = readline(const_cast(prompt));
-
-        // ignore EOF or empty line
-        if (!line)
-          {
-            std::cout << '\n';
-            continue;
-          }
-
-        std::string line_preprocessed(preprocess_command(line));
-
-        if (line_preprocessed.empty())
-          continue;
-
-        // add to history, mimicking the 'ignoreboth' HISTOCONTROL setting
-        if (strlen(line) > 0 && line[0] != ' ')
-          {
-            HIST_ENTRY **hist_list = history_list();
-            if (hist_list)
-              {
-                HIST_ENTRY *hist = hist_list[history_length - 1];
-                if (!hist || strcmp(line, hist->line) != 0)
-                  add_history(line);
-              }
-            else
-              {
-                add_history(line);
-              }
-          }
-
-        free(line);
-
-        // send to uvmm
-        Uvmm_cli_vcon::get()->send(line_preprocessed);
-
-        // receive from uvmm
-        std::cout << Uvmm_cli_vcon::get()->receive();
-      }
-  }
-
-private:
-  Readline_loop()
-  {
-    rl_attempted_completion_function = attempt_completion;
-    rl_completer_word_break_characters = const_cast(" \t\n");
-  }
-
-  static char *generate_completion(const char *, int state)
-  {
-    static decltype(_completions_buf.size()) i;
-
-    if (!state)
-      i = 0;
-
-    while (i < _completions_buf.size())
-      return strdup(_completions_buf[i++].c_str());
-
-    return nullptr;
-  }
-
-  static char **attempt_completion(char const *, int, int)
-  {
-    rl_attempted_completion_over = 1;
-
-    // send completion request to uvmm
-    std::string to_complete(preprocess_completion(
-      std::string(rl_line_buffer, rl_line_buffer + rl_point)));
-
-    Uvmm_cli_vcon::get()->complete(to_complete);
-
-    // parse completions
-    std::string completed(Uvmm_cli_vcon::get()->receive());
-    std::stringstream ss(completed.substr(0, completed.size() - 1));
-
-    _completions_buf.clear();
-
-    std::string completion;
-    while (std::getline(ss, completion, (char)Uvmm_cli::PROTO_COMPL_SEP))
-      {
-        if (!completion.empty())
-          _completions_buf.emplace_back(completion);
-      }
-
-    return rl_completion_matches(nullptr, generate_completion);
-  }
-
-  static std::string trim_left(std::string const &line)
-  {
-    auto beg = std::find_if(
-      line.begin(), line.end(), [](int c){ return c != ' '; });
-
-    return std::string(beg, line.end());
-  }
-
-  static std::string trim_right(std::string const &line)
-  {
-    auto end = std::find_if(
-      line.rbegin(), line.rend(), [](int c){ return c != ' '; }).base();
-
-    return std::string(line.begin(), end);
-  }
-
-  static std::string trim(std::string const &line)
-  {
-    auto it = std::find_if(
-      line.begin(), line.end(), [](int c){ return c != ' '; });
-
-    if (it == line.end())
-      return "";
-
-    return trim_right(trim_left(line));
-  }
-
-  static std::string compress(std::string const &line)
-  {
-    if (line.empty())
-      return line;
-
-    std::stringstream ss(line), ret;
-
-    std::string::size_type beg = 0;
-    while (beg < line.size())
-      {
-        auto end = beg + 1;
-
-        while (end < line.size() && line[end] != ' ')
-          ++end;
-
-        ret << (beg == 0 ? "" : " ") << line.substr(beg, end - beg);
-
-        beg = end + 1;
-        while (beg < line.size() && line[beg] == ' ')
-          ++beg;
-      }
-
-    if (line.back() == ' ')
-      ret << ' ';
-
-    return ret.str();
-  }
-
-  static std::string preprocess_command(std::string const &line)
-  { return compress(trim(line)); }
-
-  static std::string preprocess_completion(std::string const &line)
-  { return compress(trim_left(line)); }
-
-  static std::vector _completions_buf;
-};
-
-std::vector Readline_loop::_completions_buf;
-
-void run_readline(std::string prompt)
-{ Readline_loop::get()->run(prompt.c_str()); }
-
-} // namespace
-
-int main(int argc, char **argv)
-{
-  if (argc > 2)
-    {
-      std::cerr << "Usage: " << argv[0] << " [PROMPT]\n";
-      return EXIT_FAILURE;
-    }
-
-  try
-    {
-      // start readline thread
-      std::thread readline_thread(run_readline,
-                                  argc == 2 ? argv[1] : "monitor> ");
-
-      // create registry
-      L4Re::Util::Registry_server registry_server;
-
-      registry_server.registry()->register_obj(Uvmm_cli_vcon::get(), "mon");
-
-      // start server loop
-      registry_server.loop();
-    }
-  catch (std::exception const &e)
-    {
-      std::cerr << e.what() << '\n';
-      return EXIT_FAILURE;
-    }
-  catch (...)
-    {
-      std::cerr
-        << "An unknown exception occurred while running the readline loop\n";
-      return EXIT_FAILURE;
-    }
-
-  return EXIT_SUCCESS;
-}
diff --git a/src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.h b/src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.h
deleted file mode 100644
index f0787f28..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_cli/uvmm_cli.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2019, 2024 Kernkonzept GmbH.
- * Author(s): Timo Nicolai 
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-/**
- * \file
- * Uvmm CLI server protocol constants.
- *
- * The CLI server implements a readline interface and is able to send commands
- * and completion requests to uvmm and in return receive and display command
- * output and completions. This way no readline code has to be included inside
- * uvmm itself.
- *
- * The protocol by which the CLI server and uvmm exchange data is currently
- * implemented as follows:
- *
- * Once a (non-empty) line is entered on the CLI server, the CLI server
- * triggers an IRQ that causes a handler inside uvmm to read the complete line
- * via the Vcon protocol which is implemented by an object that the CLI server
- * exports under the name 'mon'. Lines read by uvmm are already automatically
- * stripped of leading and trailing whitespace with all remaining spaces
- * 'compressed' such that any adjacent spaces are combined into a single one.
- * Uvmm then tries to interpret these lines as commands by using the first word
- * in each line to look up an object implementing the `Monitor::Cmd` interface
- * and passing the rest of the line as arguments to that objects `exec` method.
- *
- * Output resulting from successful or failed command execution is sent back to
- * the CLI server which is blocked for further readline input until the output
- * has arrived completely. Because command output can be comprised of more than
- * one line of text, uvmm has to send a token signifying the end of a commands
- * output on every transmission. Currently this is the EOT (0x04) ASCII
- * character followed by a single newline ('\n'). If this token is not sent,
- * the CLI server will block indefinitely.
- *
- * Command completion works similarly to command transmission. A command
- * completion request is made by providing a line ending in "\t\n" to uvmm.
- * This happens when the user of the CLI server enters the TAB key, the line
- * transmitted is then the currently displayed line until the current cursor
- * position (plus "\t\n"). Uvmm will then try to find possible completions for
- * this partial command, delegating the completion to components implementing
- * the Monitor::Cmd interface if the word to be completed occurs after the
- * first one in the line. The completions are sent back to the CLI server the
- * same way command output is, all possible completions are transmitted in one
- * line, separated by '\n' characters, as before this line ends with EOT +
- * '\n'. The list of completions should be be comprised of completions for the
- * last word in the partial command line, not the whole line itself.
- */
-
-namespace Uvmm_cli {
-
-enum : char {
-  /**
-   * Delimiting token that must be included at the end of every commands
-   * output.
-   */
-  PROTO_EOT = 0x04,
-  /**
-   * Token used to indicate a completion request.
-   */
-  PROTO_COMPL_REQ = '\t',
-  /**
-   * Token used to separate possible completions sent back to the CLI server
-   * by uvmm.
-   */
-  PROTO_COMPL_SEP = '\n'
-};
-
-enum : l4_umword_t {
-  /**
-   * The CLI server server sets this local vcon attribute so that uvmm can
-   * detect that a readline interface is available and turn off its own console
-   * prompt.
-   */
-  ENABLED = 000020
-};
-
-}
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/Makefile b/src/l4/pkg/uvmm/tools/uvmm_dtg/Makefile
deleted file mode 100644
index c4634ff2..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-PKGDIR  ?= ../..
-L4DIR   ?= $(PKGDIR)/../..
-
-TARGET = build build-host
-
-include $(L4DIR)/mk/subdir.mk
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build-host/Makefile b/src/l4/pkg/uvmm/tools/uvmm_dtg/build-host/Makefile
deleted file mode 100644
index 80005846..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build-host/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-PKGDIR ?= ../../..
-L4DIR  ?= $(PKGDIR)/../..
-
-TARGET = uvmm_dtg
-MODE   = host
-
-REQUIRES_LIBS = libfdt
-
-PRIVATE_INCDIR = $(PKGDIR)/tools/uvmm_dtg/build $(PKGDIR)/tools/uvmm_dtg/build/host
-VPATH = $(PKGDIR)/tools/uvmm_dtg/build
-
-include $(PKGDIR)/tools/uvmm_dtg/build/Makefile
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-amd64/config.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-amd64/config.h
deleted file mode 100644
index 8ca5fc5a..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-amd64/config.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-constexpr Arch Default_arch = X86_64();
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm/config.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm/config.h
deleted file mode 100644
index f9ed3aab..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm/config.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-constexpr Arch Default_arch = Arm32();
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm64/config.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm64/config.h
deleted file mode 100644
index c6edec97..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-arm64/config.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-constexpr Arch Default_arch = Arm64();
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-mips/config.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-mips/config.h
deleted file mode 100644
index fd67a82e..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-mips/config.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-constexpr Arch Default_arch = Mips64();
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-x86/config.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-x86/config.h
deleted file mode 100644
index 4c30d376..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/ARCH-x86/config.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-constexpr Arch Default_arch = X86_32();
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/Makefile b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/Makefile
deleted file mode 100644
index af828f77..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-PKGDIR ?= ../../..
-L4DIR  ?= $(PKGDIR)/../..
-
-SYSTEMS = arm-l4f mips-l4f arm64-l4f amd64-l4f
-TARGET = uvmm_dtg
-
-SRC_CC = uvmm_dtg.cc device.cc tree.cc ic.cc \
-	devices/memory.cc \
-	devices/cpu.cc \
-	devices/sysclock.cc \
-	devices/gic.cc \
-	devices/pic.cc \
-	devices/ioapic.cc \
-	devices/msi_control.cc \
-	devices/pit.cc \
-	devices/arm_psci.cc \
-	devices/arm_timer.cc \
-	devices/pl011.cc \
-	devices/ns8250.cc \
-	devices/acpi_platform.cc \
-	devices/acpi_timer.cc \
-	devices/pl031.cc \
-	devices/rtc.cc \
-	devices/stats.cc \
-	devices/kvm_clock.cc \
-	devices/virtio_console.cc \
-	devices/virtio_input_power.cc \
-	devices/virtio_input_power_pci.cc \
-	devices/virtio_proxy.cc \
-	devices/virtio_device_proxy.cc \
-	devices/pci_host_ecam.cc \
-	devices/pci_bridge.cc \
-	devices/virtio_console_pci.cc \
-	devices/virtio_proxy_pci.cc \
-	devices/mmio_proxy.cc \
-	devices/virq_rcv.cc \
-	devices/virq_snd.cc \
-	devices/syscon.cc \
-	devices/cfi.cc \
-	devices/optee.cc \
-	devices/eisa.cc \
-	devices/qemu_fw_if.cc \
-	devices/isa-debugport.cc \
-	devices/rom.cc \
-	devices/l4rtc.cc \
-	devices/virtio_input_event_pci.cc \
-	devices/framebuffer.cc
-
-PRIVATE_INCDIR ?= $(SRC_DIR) $(SRC_DIR)/target $(SRC_DIR)/ARCH-$(ARCH)
-
-REQUIRES_LIBS ?= libfdt libstdc++
-
-include $(L4DIR)/mk/prog.mk
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/algh.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/algh.h
deleted file mode 100644
index bd359cf2..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/algh.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-
-inline uint64_t round_size(uint64_t addr, unsigned char bits)
-{ return (addr + (1UL << bits) - 1) & (~0UL << bits); };
-
-template 
-inline std::string to_string(const T &t, std::ios_base & (*f)(std::ios_base&))
-{
-  std::ostringstream oss;
-  oss << f << t;
-  return oss.str();
-}
-
-inline std::string string_list(const std::vector &vec)
-{
-  std::ostringstream oss;
-  oss << "\"";
-  for (auto i = vec.begin(); i != vec.end(); i++)
-    oss << (i != vec.begin() ? "\", \"" : "") << *i;
-  oss << "\"";
-  return oss.str();
-}
-
-inline std::string int_list(const std::vector &vec)
-{
-  std::ostringstream oss;
-  oss << "<";
-  for (auto i = vec.begin(); i != vec.end(); i++)
-    oss << (i != vec.begin() ? " " : "") << "0x" << std::hex << *i;
-  oss << ">";
-  return oss.str();
-}
-
-inline std::string int_list(const std::vector &vec)
-{
-  std::ostringstream oss;
-  oss << "<";
-  for (auto i = vec.begin(); i != vec.end(); i++)
-    oss << (i != vec.begin() ? " " : "") << *i;
-  oss << ">";
-  return oss.str();
-}
-
-inline std::vector split(const std::string &s,
-                                      const std::string &c = " ")
-{
-  std::vector res;
-  std::size_t prev = 0, pos;
-  while ((pos = s.find_first_of(c, prev)) != std::string::npos)
-    {
-      if (pos > prev)
-        res.push_back(s.substr(prev, pos - prev));
-      prev = pos + 1;
-    }
-  if (prev < s.length())
-    res.push_back(s.substr(prev, std::string::npos));
-  return res;
-}
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/const.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/const.h
deleted file mode 100644
index c3299ac8..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/const.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include 
-#include 
-
-struct Arch
-{
-  enum
-  {
-    X86_32 = 1UL << 0,
-    X86_64 = 1UL << 1,
-    Arm32  = 1UL << 2,
-    Arm64  = 1UL << 3,
-    Mips32 = 1UL << 4,
-    Mips64 = 1UL << 5,
-
-    X86 = X86_32 | X86_64,
-    Arm = Arm32 | Arm64,
-    Mips = Mips32 | Mips64,
-    All = X86 | Arm | Mips,
-  };
-
-  Arch() = default;
-  constexpr Arch(const Arch&) = default;
-  constexpr Arch(Arch&&) = default;
-  constexpr Arch(int a, bool i64, uint32_t ac, uint32_t sc, const char *ictl)
-  : arch(a),
-    is64bit(i64),
-    acells(ac),
-    scells(sc),
-    ic(ictl)
-  {}
-
-  Arch& operator=(const Arch&) = default;
-  Arch& operator=(Arch&&) = default;
-
-  bool is(int a) const
-  { return arch & a; }
-
-  int arch;
-  bool is64bit;
-  uint32_t acells;
-  uint32_t scells;
-  const char *ic;
-};
-
-inline std::ostream &operator<<(std::ostream &os, const Arch &arch)
-{
-  switch (arch.arch)
-    {
-    case Arch::X86_32: os << "x86"; break;
-    case Arch::X86_64: os << "x86_64"; break;
-    case Arch::Arm32: os << "arm32"; break;
-    case Arch::Arm64: os << "arm64"; break;
-    case Arch::Mips32: os << "mips32"; break;
-    case Arch::Mips64: os << "mips64"; break;
-    default: os << "unknown"; break;
-    }
-
-  return os;
-}
-
-struct X86_32: Arch
-{ constexpr X86_32() : Arch(Arch::X86_32, false, 1, 1, "ioapic") {} };
-
-struct X86_64: Arch
-{ constexpr X86_64() : Arch(Arch::X86_64, true, 2, 2, "ioapic") {} };
-
-struct Arm32: Arch
-{ constexpr Arm32() : Arch(Arch::Arm32, false, 1, 1, "gic") {} };
-
-struct Arm64: Arch
-{ constexpr Arm64() : Arch(Arch::Arm64, true, 2, 2, "gic") {} };
-
-struct Mips32: Arch
-{ constexpr Mips32() : Arch(Arch::Mips32, false, 1, 1, "gic") {} };
-
-struct Mips64: Arch
-{ constexpr Mips64() : Arch(Arch::Mips64, true, 2, 2, "gic") {} };
-
-enum OutFormat
-{
-  Txt,
-  Bin
-};
-
-inline std::ostream &operator<<(std::ostream &os, const OutFormat &fmt)
-{
-  switch (fmt)
-    {
-    case Txt: os << "txt"; break;
-    case Bin: os << "bin"; break;
-    default: os << "unknown"; break;
-    }
-
-  return os;
-}
-
-struct Exception
-{
-  Exception(const std::string &e)
-  : error(e)
-  {}
-
-  Exception(std::string &&e)
-  : error(std::move(e))
-  {}
-
-  std::string error;
-};
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.cc b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.cc
deleted file mode 100644
index 23606118..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.cc
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#include "device.h"
-
-std::vector Factory::facs;
-std::vector> Factory::_devices;
diff --git a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.h b/src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.h
deleted file mode 100644
index 18309aba..00000000
--- a/src/l4/pkg/uvmm/tools/uvmm_dtg/build/device.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2022 Kernkonzept GmbH.
- * Author(s): Christian Pötzsch christian.poetzsch@kernkonzept.com
- *
- * License: see LICENSE.spdx (in this directory or the directories above)
- */
-#pragma once
-
-#include "tree.h"
-#include "opts.h"
-#include "support.h"
-#include "config.h"
-
-/*
- * Simple parser which splits the --device argument on colon and pass it to the
- * next parser.
- */
-struct Device_list_parser: Parser_with_args
-{
-  Device_list_parser()
-  : _opts("--device", "configures devices (help for list)",
-          {Option("help", "show usage", make_parser(&_opts))})
-  {}
-
-  virtual ~Device_list_parser()
-  {}
-
-  void add_options(Option &&opts)
-  { _opts.add_option(std::move(opts)); };
-
-  Result parse(const std::string & /*opt*/, arg_vec *vec, arg_vec_it s) override
-  {
-    Result r;
-    auto w = split(*s, ":");
-    auto key = w[0];
-    Results e = _opts.parse(&w, w.begin(), true);
-    if (e.is_error())
-      r.set_error(e);
-    else
-      // Nothing else to do here
-      vec->erase(s);
-    return r;
-  }
-
-  Options _opts;
-};
-
-/*
- * Base class of all devices.
- */
-struct Device
-{
-  Device(const Arch &arch, size_t count, const Results &res)
-  : _trg_arch(arch),
-    _count(count),
-    _res(res)
-  {}
-
-  virtual void add(Tree *tree) = 0;
-
-  std::string name(const std::string &s)
-  { return s + std::to_string(_count); }
-
-protected:
-  Arch _trg_arch;
-  size_t _count;
-  Results _res;
-};
-
-/*
- * Device factory
- *
- * All devices automatically register here. Based on the arch provided on the
- * commandline they will be considered in later processing.
- */
-struct Factory
-{
-  Factory(int arch, const std::string &provides)
-  : _avl_archs(arch),
-    _provides(provides)
-  { facs.push_back(this); }
-
-  bool has_arch(const Arch &arch) const { return _avl_archs & arch.arch; }
-  bool has_flag(int flag) const { return flags() & flag; }
-  size_t count() const { return _count; }
-
-  void set_arch(const Arch &arch)
-  { _trg_arch = arch; }
-
-  void add_results(const Results &res)
-  { _results.push_back(res); }
-
-  virtual Option option() = 0;
-
-  static void prepare(const Arch &arch, std::shared_ptr dlp)
-  {
-    // Filter everything by the target arch and relevant options to the device
-    // parser
-    for (auto a = facs.begin(); a != facs.end();)
-      {
-        if ((*a)->has_arch(arch))
-          {
-            (*a)->set_arch(arch);
-            dlp->add_options((*a)->option());
-            ++a;
-          }
-        else
-          // Remove devices not targeted for the specified arch
-          a = facs.erase(a);
-      }
-  }
-
-  static void create_all_devices()
-  {
-    for (auto f: facs)
-      f->create_devices();
-  }
-
-  static void build_tree(Tree *t)
-  {
-    for(auto d: _devices)
-      d->add(t);
-  }
-
-protected:
-
-  virtual int flags() const { return Option::None; };
-  virtual std::vector a_requires() const { return {}; };
-  virtual std::shared_ptr create(const Results &res) = 0;
-
-  Factory* find(const std::string &name)
-  {
-    for (auto a: facs)
-      if (a->_provides == name)
-        return a;
-    throw Exception(std::string("can't find '") + name + "' dependency");
-  }
-
-  void create_devices(bool force = false)
-  {
-    // This adds an result in case of:
-    // - it is a default device
-    // - it was forced by the caller (it is a requirement for another device)
-    // - we haven't already an Results from the command line parsing
-    // - it wasn't already created
-    if ((has_flag(Option::Default) || force) &&  _results.size() == 0 && !created)
-      option().auto_fill(Results());
-
-    // If we are going to create devices, make sure the requirements are fulfilled
-    if (_results.size() > 0)
-      {
-        // We have to make sure that any dependent devices are created before
-        // this device
-        for (auto a: a_requires())
-          find(a)->create_devices(true);
-
-        // Now create a device for every Result we got from the command line or
-        // internally
-        for (auto r = _results.begin(); r != _results.end();)
-          {
-            _devices.push_back(create(*r));
-            r = _results.erase(r);
-            created = true;
-          }
-      }
-  }
-
-  Arch _trg_arch;
-  int _avl_archs;
-  std::string _provides;
-  size_t _count = 0;
-  bool created = false;
-
-  std::vector _results;
-  static std::vector facs;
-  static std::vector> _devices;
-};
-
-template 
-struct Device_factory : Factory
-{
-  using Factory::Factory;
-
-  std::shared_ptr create(const Results &res) override
-  { return std::make_shared(_trg_arch, _count++, res); }
-};
-
-/*
- * Parses the options of one specific device and adds the results back to the
- * appropriate factory for later creation.
- */
-struct Device_parser: Parser
-{
-  Device_parser(const std::string &name, const std::string &desc, Factory *f)
-  : _opts(name, desc, {Option("help", "show usage",
-                              make_parser(&_opts))}),
-    _f(f)
-  {}
-
-  Device_parser(const std::string &name, const std::string &desc, Factory *f,
-                std::initializer_list