From cb3b6c4b8859ea27df751f66074bb9e5b41da673 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 13 Mar 2023 11:37:16 +0100 Subject: [PATCH] vmm: distinguish virtio interrupts VirtIO device models can assert interrupts to notify about buffer and configuration changes. By now, we could only assert buffer notification interrupts, but no configuration changes. The latter is needed, e.g. to notify about GPU mode changes. Ref genodelabs/genode#4783 --- repos/os/src/server/vmm/virtio_block.h | 2 +- repos/os/src/server/vmm/virtio_console.h | 4 ++-- repos/os/src/server/vmm/virtio_device.h | 30 ++++++++++++++++++------ repos/os/src/server/vmm/virtio_gpu.cc | 2 +- repos/os/src/server/vmm/virtio_gpu.h | 5 +++- repos/os/src/server/vmm/virtio_input.h | 2 +- repos/os/src/server/vmm/virtio_net.h | 4 ++-- 7 files changed, 34 insertions(+), 15 deletions(-) diff --git a/repos/os/src/server/vmm/virtio_block.h b/repos/os/src/server/vmm/virtio_block.h index 5fc67dff3d..44aae3040d 100644 --- a/repos/os/src/server/vmm/virtio_block.h +++ b/repos/os/src/server/vmm/virtio_block.h @@ -279,7 +279,7 @@ class Vmm::Virtio_block_device void completed(Job &job, bool) { job.done(*_queue[REQUEST]); - _assert_irq(); + _buffer_notification(); destroy(_heap, &job); } }; diff --git a/repos/os/src/server/vmm/virtio_console.h b/repos/os/src/server/vmm/virtio_console.h index 6a034c6de7..ca95cbf6c1 100644 --- a/repos/os/src/server/vmm/virtio_console.h +++ b/repos/os/src/server/vmm/virtio_console.h @@ -45,7 +45,7 @@ class Vmm::Virtio_console : public Virtio_device if (!_terminal.avail() || !_queue[RX].constructed()) return; _queue[RX]->notify(read); - _assert_irq(); + _buffer_notification(); } void _notify(unsigned idx) override @@ -59,7 +59,7 @@ class Vmm::Virtio_console : public Virtio_device }; if (_queue[TX]->notify(write)) - _assert_irq(); + _buffer_notification(); } enum Device_id { CONSOLE = 0x3 }; diff --git a/repos/os/src/server/vmm/virtio_device.h b/repos/os/src/server/vmm/virtio_device.h index b1688aa849..29482e16ab 100644 --- a/repos/os/src/server/vmm/virtio_device.h +++ b/repos/os/src/server/vmm/virtio_device.h @@ -341,18 +341,35 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, private Virtio_device_base return ((uint64_t)_device_high.value()<<32) | _device_low.value(); } - void _assert_irq() + enum Irq : uint64_t { + NONE = 0UL, + BUFFER = 1UL << 0, + CONFIG = 1UL << 1, + }; + + void _assert_irq(uint64_t irq) { - _irq_status.set(0x1); + _irq_status.set(_irq_status.value() | irq); _irq.assert(); } - void _deassert_irq() + void _deassert_irq(uint64_t irq) { - _irq_status.set(0); + _irq_status.set(_irq_status.value() & ~irq); _irq.deassert(); } + void _buffer_notification() + { + _assert_irq(BUFFER); + } + + void _config_notification() + { + _config_gen.set(_config_gen.value() + 1); + _assert_irq(CONFIG); + } + void _construct_queue() { Genode::Mutex::Guard guard(mutex()); @@ -403,10 +420,10 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, private Virtio_device_base struct Interrupt_ack : Reg { - void write(Address_range&, Cpu&, Register) override + void write(Address_range&, Cpu&, Register v) override { Genode::Mutex::Guard guard(Reg::device().mutex()); - Reg::device()._deassert_irq(); + Reg::device()._deassert_irq(v); } Interrupt_ack(Virtio_device &device) @@ -442,7 +459,6 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, private Virtio_device_base } Genode::Mutex & mutex() { return _mutex; } - void config_has_changed() { _config_gen.set(_config_gen.get() + 1); } }; #endif /* _VIRTIO_DEVICE_H_ */ diff --git a/repos/os/src/server/vmm/virtio_gpu.cc b/repos/os/src/server/vmm/virtio_gpu.cc index a81c4cca0c..4f937f6d94 100644 --- a/repos/os/src/server/vmm/virtio_gpu.cc +++ b/repos/os/src/server/vmm/virtio_gpu.cc @@ -37,7 +37,7 @@ void Vmm::Virtio_gpu_queue::notify(Virtio_gpu_device & dev) _used.write((uint16_t)_cur_idx.idx()); memory_barrier(); - if (_avail.inject_irq()) dev.assert_irq(); + if (_avail.inject_irq()) dev.buffer_notification(); } diff --git a/repos/os/src/server/vmm/virtio_gpu.h b/repos/os/src/server/vmm/virtio_gpu.h index d7d5cdb930..e9effa52ea 100644 --- a/repos/os/src/server/vmm/virtio_gpu.h +++ b/repos/os/src/server/vmm/virtio_gpu.h @@ -469,7 +469,10 @@ class Vmm::Virtio_gpu_device : public Virtio_device _mode_change(); } - void assert_irq() { _assert_irq(); } + void buffer_notification() + { + _buffer_notification(); + } }; #endif /* _VIRTIO_GPU_H_ */ diff --git a/repos/os/src/server/vmm/virtio_input.h b/repos/os/src/server/vmm/virtio_input.h index 20d0e058aa..36afc210ed 100644 --- a/repos/os/src/server/vmm/virtio_input.h +++ b/repos/os/src/server/vmm/virtio_input.h @@ -272,7 +272,7 @@ class Vmm::Virtio_input_device : public Virtio_device return size; }); - if (irq) _assert_irq(); + if (irq) _buffer_notification(); } void _notify(unsigned idx) override diff --git a/repos/os/src/server/vmm/virtio_net.h b/repos/os/src/server/vmm/virtio_net.h index 3b8405b63f..8a67f66c37 100644 --- a/repos/os/src/server/vmm/virtio_net.h +++ b/repos/os/src/server/vmm/virtio_net.h @@ -74,7 +74,7 @@ class Vmm::Virtio_net : public Virtio_device bool irq = _queue[RX]->notify(recv); - if (irq) _assert_irq(); + if (irq) _buffer_notification(); } void _tx() @@ -99,7 +99,7 @@ class Vmm::Virtio_net : public Virtio_device if (!_queue[TX].constructed()) return; - if (_queue[TX]->notify(send)) _assert_irq(); + if (_queue[TX]->notify(send)) _buffer_notification(); _free_packets(); }