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
This commit is contained in:
Stefan Kalkowski 2023-03-13 11:37:16 +01:00 committed by Christian Helmuth
parent 441186468c
commit cb3b6c4b88
7 changed files with 34 additions and 15 deletions

View File

@ -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);
}
};

View File

@ -45,7 +45,7 @@ class Vmm::Virtio_console : public Virtio_device<Virtio_split_queue, 2>
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<Virtio_split_queue, 2>
};
if (_queue[TX]->notify(write))
_assert_irq();
_buffer_notification();
}
enum Device_id { CONSOLE = 0x3 };

View File

@ -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_ */

View File

@ -37,7 +37,7 @@ void Vmm::Virtio_gpu_queue::notify(Virtio_gpu_device & dev)
_used.write<Used_queue::Idx>((uint16_t)_cur_idx.idx());
memory_barrier();
if (_avail.inject_irq()) dev.assert_irq();
if (_avail.inject_irq()) dev.buffer_notification();
}

View File

@ -469,7 +469,10 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
_mode_change();
}
void assert_irq() { _assert_irq(); }
void buffer_notification()
{
_buffer_notification();
}
};
#endif /* _VIRTIO_GPU_H_ */

View File

@ -272,7 +272,7 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
return size;
});
if (irq) _assert_irq();
if (irq) _buffer_notification();
}
void _notify(unsigned idx) override

View File

@ -74,7 +74,7 @@ class Vmm::Virtio_net : public Virtio_device<Virtio_split_queue, 2>
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<Virtio_split_queue, 2>
if (!_queue[TX].constructed()) return;
if (_queue[TX]->notify(send)) _assert_irq();
if (_queue[TX]->notify(send)) _buffer_notification();
_free_packets();
}