1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 14:47:44 +00:00

Kernel/VirtIO: Remove the m_class_name member

This class member was used only to determine the device type when
printing messages to the debug log. Instead, remove this class member,
and add a quick way to find the device type according to how the VirtIO
specification says to do that.

This simplifies construction of VirtIODevices a bit, because now the
constructor doesn't need to ask for a String identified with the device
type.
This commit is contained in:
Liav A 2021-08-27 11:41:27 +03:00 committed by Andreas Kling
parent 5a0aa66b73
commit 9a03c00f45
8 changed files with 56 additions and 35 deletions

View file

@ -43,13 +43,29 @@ UNMAP_AFTER_INIT void VirtIO::detect()
}); });
} }
UNMAP_AFTER_INIT VirtIODevice::VirtIODevice(PCI::Address address, String class_name) StringView VirtIO::determine_device_class(const PCI::Address& address)
{
auto subsystem_device_id = PCI::get_subsystem_id(address);
switch (subsystem_device_id) {
case 1:
return "VirtIONetAdapter";
case 2:
return "VirtIOBlockDevice";
case 3:
return "VirtIOConsole";
case 4:
return "VirtIORNG";
}
dbgln("VirtIO: Unknown subsystem_device_id {}", subsystem_device_id);
VERIFY_NOT_REACHED();
}
UNMAP_AFTER_INIT VirtIODevice::VirtIODevice(PCI::Address address)
: PCI::Device(address) : PCI::Device(address)
, IRQHandler(PCI::get_interrupt_line(address)) , IRQHandler(PCI::get_interrupt_line(address))
, m_class_name(move(class_name))
, m_io_base(IOAddress(PCI::get_BAR0(pci_address()) & ~1)) , m_io_base(IOAddress(PCI::get_BAR0(pci_address()) & ~1))
{ {
dbgln("{}: Found @ {}", m_class_name, pci_address()); dbgln("{}: Found @ {}", VirtIO::determine_device_class(address), pci_address());
enable_bus_mastering(pci_address()); enable_bus_mastering(pci_address());
PCI::enable_interrupt_line(pci_address()); PCI::enable_interrupt_line(pci_address());
@ -62,23 +78,23 @@ UNMAP_AFTER_INIT VirtIODevice::VirtIODevice(PCI::Address address, String class_n
auto cfg = make<Configuration>(); auto cfg = make<Configuration>();
auto raw_config_type = capability.read8(0x3); auto raw_config_type = capability.read8(0x3);
if (raw_config_type < static_cast<u8>(ConfigurationType::Common) || raw_config_type > static_cast<u8>(ConfigurationType::PCI)) { if (raw_config_type < static_cast<u8>(ConfigurationType::Common) || raw_config_type > static_cast<u8>(ConfigurationType::PCI)) {
dbgln("{}: Unknown capability configuration type: {}", m_class_name, raw_config_type); dbgln("{}: Unknown capability configuration type: {}", VirtIO::determine_device_class(address), raw_config_type);
return; return;
} }
cfg->cfg_type = static_cast<ConfigurationType>(raw_config_type); cfg->cfg_type = static_cast<ConfigurationType>(raw_config_type);
auto cap_length = capability.read8(0x2); auto cap_length = capability.read8(0x2);
if (cap_length < 0x10) { if (cap_length < 0x10) {
dbgln("{}: Unexpected capability size: {}", m_class_name, cap_length); dbgln("{}: Unexpected capability size: {}", VirtIO::determine_device_class(address), cap_length);
break; break;
} }
cfg->bar = capability.read8(0x4); cfg->bar = capability.read8(0x4);
if (cfg->bar > 0x5) { if (cfg->bar > 0x5) {
dbgln("{}: Unexpected capability bar value: {}", m_class_name, cfg->bar); dbgln("{}: Unexpected capability bar value: {}", VirtIO::determine_device_class(address), cfg->bar);
break; break;
} }
cfg->offset = capability.read32(0x8); cfg->offset = capability.read32(0x8);
cfg->length = capability.read32(0xc); cfg->length = capability.read32(0xc);
dbgln_if(VIRTIO_DEBUG, "{}: Found configuration {}, bar: {}, offset: {}, length: {}", m_class_name, (u32)cfg->cfg_type, cfg->bar, cfg->offset, cfg->length); dbgln_if(VIRTIO_DEBUG, "{}: Found configuration {}, bar: {}, offset: {}, length: {}", VirtIO::determine_device_class(address), (u32)cfg->cfg_type, cfg->bar, cfg->offset, cfg->length);
if (cfg->cfg_type == ConfigurationType::Common) if (cfg->cfg_type == ConfigurationType::Common)
m_use_mmio = true; m_use_mmio = true;
else if (cfg->cfg_type == ConfigurationType::Notify) else if (cfg->cfg_type == ConfigurationType::Notify)
@ -112,14 +128,14 @@ auto VirtIODevice::mapping_for_bar(u8 bar) -> MappedMMIO&
mapping.size = PCI::get_BAR_space_size(pci_address(), bar); mapping.size = PCI::get_BAR_space_size(pci_address(), bar);
mapping.base = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR(pci_address(), bar))), Memory::page_round_up(mapping.size), "VirtIO MMIO", Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No); mapping.base = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR(pci_address(), bar))), Memory::page_round_up(mapping.size), "VirtIO MMIO", Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No);
if (!mapping.base) if (!mapping.base)
dbgln("{}: Failed to map bar {}", m_class_name, bar); dbgln("{}: Failed to map bar {}", VirtIO::determine_device_class(pci_address()), bar);
} }
return mapping; return mapping;
} }
void VirtIODevice::notify_queue(u16 queue_index) void VirtIODevice::notify_queue(u16 queue_index)
{ {
dbgln_if(VIRTIO_DEBUG, "{}: notifying about queue change at idx: {}", m_class_name, queue_index); dbgln_if(VIRTIO_DEBUG, "{}: notifying about queue change at idx: {}", VirtIO::determine_device_class(pci_address()), queue_index);
if (!m_notify_cfg) if (!m_notify_cfg)
out<u16>(REG_QUEUE_NOTIFY, queue_index); out<u16>(REG_QUEUE_NOTIFY, queue_index);
else else
@ -207,7 +223,7 @@ bool VirtIODevice::accept_device_features(u64 device_features, u64 accepted_feat
} }
if (is_feature_set(device_features, VIRTIO_F_RING_PACKED)) { if (is_feature_set(device_features, VIRTIO_F_RING_PACKED)) {
dbgln_if(VIRTIO_DEBUG, "{}: packed queues not yet supported", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: packed queues not yet supported", VirtIO::determine_device_class(pci_address()));
accepted_features &= ~(VIRTIO_F_RING_PACKED); accepted_features &= ~(VIRTIO_F_RING_PACKED);
} }
@ -220,8 +236,8 @@ bool VirtIODevice::accept_device_features(u64 device_features, u64 accepted_feat
accepted_features |= VIRTIO_F_IN_ORDER; accepted_features |= VIRTIO_F_IN_ORDER;
} }
dbgln_if(VIRTIO_DEBUG, "{}: Device features: {}", m_class_name, device_features); dbgln_if(VIRTIO_DEBUG, "{}: Device features: {}", VirtIO::determine_device_class(pci_address()), device_features);
dbgln_if(VIRTIO_DEBUG, "{}: Accepted features: {}", m_class_name, accepted_features); dbgln_if(VIRTIO_DEBUG, "{}: Accepted features: {}", VirtIO::determine_device_class(pci_address()), accepted_features);
if (!m_common_cfg) { if (!m_common_cfg) {
out<u32>(REG_GUEST_FEATURES, accepted_features); out<u32>(REG_GUEST_FEATURES, accepted_features);
@ -235,18 +251,18 @@ bool VirtIODevice::accept_device_features(u64 device_features, u64 accepted_feat
m_status = read_status_bits(); m_status = read_status_bits();
if (!(m_status & DEVICE_STATUS_FEATURES_OK)) { if (!(m_status & DEVICE_STATUS_FEATURES_OK)) {
set_status_bit(DEVICE_STATUS_FAILED); set_status_bit(DEVICE_STATUS_FAILED);
dbgln("{}: Features not accepted by host!", m_class_name); dbgln("{}: Features not accepted by host!", VirtIO::determine_device_class(pci_address()));
return false; return false;
} }
m_accepted_features = accepted_features; m_accepted_features = accepted_features;
dbgln_if(VIRTIO_DEBUG, "{}: Features accepted by host", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: Features accepted by host", VirtIO::determine_device_class(pci_address()));
return true; return true;
} }
void VirtIODevice::reset_device() void VirtIODevice::reset_device()
{ {
dbgln_if(VIRTIO_DEBUG, "{}: Reset device", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: Reset device", VirtIO::determine_device_class(pci_address()));
if (!m_common_cfg) { if (!m_common_cfg) {
mask_status_bits(0); mask_status_bits(0);
while (read_status_bits() != 0) { while (read_status_bits() != 0) {
@ -268,7 +284,7 @@ bool VirtIODevice::setup_queue(u16 queue_index)
config_write16(*m_common_cfg, COMMON_CFG_QUEUE_SELECT, queue_index); config_write16(*m_common_cfg, COMMON_CFG_QUEUE_SELECT, queue_index);
u16 queue_size = config_read16(*m_common_cfg, COMMON_CFG_QUEUE_SIZE); u16 queue_size = config_read16(*m_common_cfg, COMMON_CFG_QUEUE_SIZE);
if (queue_size == 0) { if (queue_size == 0) {
dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] is unavailable!", m_class_name, queue_index); dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] is unavailable!", VirtIO::determine_device_class(pci_address()), queue_index);
return true; return true;
} }
@ -282,7 +298,7 @@ bool VirtIODevice::setup_queue(u16 queue_index)
config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DRIVER, queue->driver_area().get()); config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DRIVER, queue->driver_area().get());
config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DEVICE, queue->device_area().get()); config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DEVICE, queue->device_area().get());
dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] configured with size: {}", m_class_name, queue_index, queue_size); dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] configured with size: {}", VirtIO::determine_device_class(pci_address()), queue_index, queue_size);
m_queues.append(move(queue)); m_queues.append(move(queue));
return true; return true;
@ -296,7 +312,7 @@ bool VirtIODevice::activate_queue(u16 queue_index)
config_write16(*m_common_cfg, COMMON_CFG_QUEUE_SELECT, queue_index); config_write16(*m_common_cfg, COMMON_CFG_QUEUE_SELECT, queue_index);
config_write16(*m_common_cfg, COMMON_CFG_QUEUE_ENABLE, true); config_write16(*m_common_cfg, COMMON_CFG_QUEUE_ENABLE, true);
dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] activated", m_class_name, queue_index); dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] activated", VirtIO::determine_device_class(pci_address()), queue_index);
return true; return true;
} }
@ -310,17 +326,17 @@ bool VirtIODevice::setup_queues(u16 requested_queue_count)
if (requested_queue_count == 0) { if (requested_queue_count == 0) {
m_queue_count = maximum_queue_count; m_queue_count = maximum_queue_count;
} else if (requested_queue_count > maximum_queue_count) { } else if (requested_queue_count > maximum_queue_count) {
dbgln("{}: {} queues requested but only {} available!", m_class_name, m_queue_count, maximum_queue_count); dbgln("{}: {} queues requested but only {} available!", VirtIO::determine_device_class(pci_address()), m_queue_count, maximum_queue_count);
return false; return false;
} else { } else {
m_queue_count = requested_queue_count; m_queue_count = requested_queue_count;
} }
} else { } else {
m_queue_count = requested_queue_count; m_queue_count = requested_queue_count;
dbgln("{}: device's available queue count could not be determined!", m_class_name); dbgln("{}: device's available queue count could not be determined!", VirtIO::determine_device_class(pci_address()));
} }
dbgln_if(VIRTIO_DEBUG, "{}: Setting up {} queues", m_class_name, m_queue_count); dbgln_if(VIRTIO_DEBUG, "{}: Setting up {} queues", VirtIO::determine_device_class(pci_address()), m_queue_count);
for (u16 i = 0; i < m_queue_count; i++) { for (u16 i = 0; i < m_queue_count; i++) {
if (!setup_queue(i)) if (!setup_queue(i))
return false; return false;
@ -339,7 +355,7 @@ void VirtIODevice::finish_init()
VERIFY(!(m_status & DEVICE_STATUS_DRIVER_OK)); // ensure we didn't already finish the initialization VERIFY(!(m_status & DEVICE_STATUS_DRIVER_OK)); // ensure we didn't already finish the initialization
set_status_bit(DEVICE_STATUS_DRIVER_OK); set_status_bit(DEVICE_STATUS_DRIVER_OK);
dbgln_if(VIRTIO_DEBUG, "{}: Finished initialization", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: Finished initialization", VirtIO::determine_device_class(pci_address()));
} }
u8 VirtIODevice::isr_status() u8 VirtIODevice::isr_status()
@ -353,25 +369,25 @@ bool VirtIODevice::handle_irq(const RegisterState&)
{ {
u8 isr_type = isr_status(); u8 isr_type = isr_status();
if ((isr_type & (QUEUE_INTERRUPT | DEVICE_CONFIG_INTERRUPT)) == 0) { if ((isr_type & (QUEUE_INTERRUPT | DEVICE_CONFIG_INTERRUPT)) == 0) {
dbgln_if(VIRTIO_DEBUG, "{}: Handling interrupt with unknown type: {}", m_class_name, isr_type); dbgln_if(VIRTIO_DEBUG, "{}: Handling interrupt with unknown type: {}", VirtIO::determine_device_class(pci_address()), isr_type);
return false; return false;
} }
if (isr_type & DEVICE_CONFIG_INTERRUPT) { if (isr_type & DEVICE_CONFIG_INTERRUPT) {
dbgln_if(VIRTIO_DEBUG, "{}: VirtIO Device config interrupt!", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: VirtIO Device config interrupt!", VirtIO::determine_device_class(pci_address()));
if (!handle_device_config_change()) { if (!handle_device_config_change()) {
set_status_bit(DEVICE_STATUS_FAILED); set_status_bit(DEVICE_STATUS_FAILED);
dbgln("{}: Failed to handle device config change!", m_class_name); dbgln("{}: Failed to handle device config change!", VirtIO::determine_device_class(pci_address()));
} }
} }
if (isr_type & QUEUE_INTERRUPT) { if (isr_type & QUEUE_INTERRUPT) {
dbgln_if(VIRTIO_DEBUG, "{}: VirtIO Queue interrupt!", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: VirtIO Queue interrupt!", VirtIO::determine_device_class(pci_address()));
for (size_t i = 0; i < m_queues.size(); i++) { for (size_t i = 0; i < m_queues.size(); i++) {
if (get_queue(i).new_data_available()) { if (get_queue(i).new_data_available()) {
handle_queue_update(i); handle_queue_update(i);
return true; return true;
} }
} }
dbgln_if(VIRTIO_DEBUG, "{}: Got queue interrupt but all queues are up to date!", m_class_name); dbgln_if(VIRTIO_DEBUG, "{}: Got queue interrupt but all queues are up to date!", VirtIO::determine_device_class(pci_address()));
} }
return true; return true;
} }

View file

@ -82,6 +82,7 @@ struct Configuration {
class VirtIO { class VirtIO {
public: public:
static void detect(); static void detect();
static StringView determine_device_class(const PCI::Address& address);
}; };
class VirtIODevice class VirtIODevice
@ -91,9 +92,9 @@ public:
virtual ~VirtIODevice() override; virtual ~VirtIODevice() override;
protected: protected:
VirtIODevice(PCI::Address, String); explicit VirtIODevice(PCI::Address);
const String m_class_name;
virtual StringView class_name() const = 0;
struct MappedMMIO { struct MappedMMIO {
OwnPtr<Memory::Region> base; OwnPtr<Memory::Region> base;
size_t size { 0 }; size_t size { 0 };

View file

@ -13,7 +13,7 @@ namespace Kernel {
unsigned VirtIOConsole::next_device_id = 0; unsigned VirtIOConsole::next_device_id = 0;
UNMAP_AFTER_INIT VirtIOConsole::VirtIOConsole(PCI::Address address) UNMAP_AFTER_INIT VirtIOConsole::VirtIOConsole(PCI::Address address)
: VirtIODevice(address, "VirtIOConsole") : VirtIODevice(address)
, m_device_id(next_device_id++) , m_device_id(next_device_id++)
{ {
if (auto cfg = get_config(ConfigurationType::Device)) { if (auto cfg = get_config(ConfigurationType::Device)) {

View file

@ -21,7 +21,7 @@ public:
VirtIOConsole(PCI::Address); VirtIOConsole(PCI::Address);
virtual ~VirtIOConsole() override = default; virtual ~VirtIOConsole() override = default;
virtual StringView purpose() const override { return "VirtIOConsole"; } virtual StringView purpose() const override { return class_name(); }
unsigned device_id() const unsigned device_id() const
{ {
@ -29,6 +29,7 @@ public:
} }
private: private:
virtual StringView class_name() const override { return "VirtIOConsole"; }
enum class ControlEvent : u16 { enum class ControlEvent : u16 {
DeviceReady = 0, DeviceReady = 0,
DeviceAdd = 1, DeviceAdd = 1,

View file

@ -10,7 +10,7 @@
namespace Kernel { namespace Kernel {
UNMAP_AFTER_INIT VirtIORNG::VirtIORNG(PCI::Address address) UNMAP_AFTER_INIT VirtIORNG::VirtIORNG(PCI::Address address)
: VirtIODevice(address, "VirtIORNG") : VirtIODevice(address)
{ {
bool success = negotiate_features([&](auto) { bool success = negotiate_features([&](auto) {
return 0; return 0;

View file

@ -19,12 +19,13 @@ class VirtIORNG final
: public RefCounted<VirtIORNG> : public RefCounted<VirtIORNG>
, public VirtIODevice { , public VirtIODevice {
public: public:
virtual StringView purpose() const override { return m_class_name; } virtual StringView purpose() const override { return class_name(); }
VirtIORNG(PCI::Address); VirtIORNG(PCI::Address);
virtual ~VirtIORNG() override; virtual ~VirtIORNG() override;
private: private:
virtual StringView class_name() const override { return "VirtIOConsole"; }
virtual bool handle_device_config_change() override; virtual bool handle_device_config_change() override;
virtual void handle_queue_update(u16 queue_index) override; virtual void handle_queue_update(u16 queue_index) override;
void request_entropy_from_host(); void request_entropy_from_host();

View file

@ -16,7 +16,7 @@
namespace Kernel::Graphics::VirtIOGPU { namespace Kernel::Graphics::VirtIOGPU {
GPU::GPU(PCI::Address address) GPU::GPU(PCI::Address address)
: VirtIODevice(address, "GPU") : VirtIODevice(address)
, m_scratch_space(MM.allocate_contiguous_kernel_region(32 * PAGE_SIZE, "VirtGPU Scratch Space", Memory::Region::Access::ReadWrite)) , m_scratch_space(MM.allocate_contiguous_kernel_region(32 * PAGE_SIZE, "VirtGPU Scratch Space", Memory::Region::Access::ReadWrite))
{ {
VERIFY(!!m_scratch_space); VERIFY(!!m_scratch_space);
@ -65,7 +65,7 @@ bool GPU::handle_device_config_change()
auto events = get_pending_events(); auto events = get_pending_events();
if (events & VIRTIO_GPU_EVENT_DISPLAY) { if (events & VIRTIO_GPU_EVENT_DISPLAY) {
// The host window was resized, in SerenityOS we completely ignore this event // The host window was resized, in SerenityOS we completely ignore this event
dbgln_if(VIRTIO_DEBUG, "{}: Ignoring virtio gpu display resize event", m_class_name); dbgln_if(VIRTIO_DEBUG, "VirtIOGPU: Ignoring virtio gpu display resize event");
clear_pending_events(VIRTIO_GPU_EVENT_DISPLAY); clear_pending_events(VIRTIO_GPU_EVENT_DISPLAY);
} }
if (events & ~VIRTIO_GPU_EVENT_DISPLAY) { if (events & ~VIRTIO_GPU_EVENT_DISPLAY) {

View file

@ -77,6 +77,8 @@ public:
void flush_dirty_rectangle(ScanoutID, Protocol::Rect const& dirty_rect, ResourceID); void flush_dirty_rectangle(ScanoutID, Protocol::Rect const& dirty_rect, ResourceID);
private: private:
virtual StringView class_name() const override { return "VirtIOGPU"; }
struct Scanout { struct Scanout {
RefPtr<FrameBufferDevice> framebuffer; RefPtr<FrameBufferDevice> framebuffer;
RefPtr<Console> console; RefPtr<Console> console;