From 3082950e744aca57f8e28381148e1792485ecbf9 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 2 Nov 2022 11:17:51 +0100 Subject: [PATCH] usb_session: align USB packet allocation correctly To prevent caching side-effects of USB DMA memory taken from the packet stream all allocations of USB packets need to be on separated cachelines at least. Fix genodelabs/genode#4655 --- repos/dde_linux/src/drivers/usb_modem/driver.h | 2 +- repos/dde_linux/src/drivers/usb_net/driver.h | 2 +- repos/dde_linux/src/include/legacy/lx_kit/usb.h | 2 +- repos/libports/src/lib/libusb/genode_usb_raw.cc | 10 +++++----- repos/libports/src/lib/qemu-usb/host.cc | 2 +- repos/os/include/usb/packet_handler.h | 2 +- repos/os/include/usb_session/client.h | 14 ++++++++++++++ 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/repos/dde_linux/src/drivers/usb_modem/driver.h b/repos/dde_linux/src/drivers/usb_modem/driver.h index 97e5f3797b..68f47c73b1 100644 --- a/repos/dde_linux/src/drivers/usb_modem/driver.h +++ b/repos/dde_linux/src/drivers/usb_modem/driver.h @@ -105,7 +105,7 @@ struct Driver private: Usb::Session_client & _usb; - Usb::Packet_descriptor _packet { _usb.source()->alloc_packet(0) }; + Usb::Packet_descriptor _packet { _usb.alloc_packet(0) }; completion _comp; public: diff --git a/repos/dde_linux/src/drivers/usb_net/driver.h b/repos/dde_linux/src/drivers/usb_net/driver.h index e1e265c8e6..3afb931fb7 100644 --- a/repos/dde_linux/src/drivers/usb_net/driver.h +++ b/repos/dde_linux/src/drivers/usb_net/driver.h @@ -103,7 +103,7 @@ struct Driver private: Usb::Session_client & _usb; - Usb::Packet_descriptor _packet { _usb.source()->alloc_packet(0) }; + Usb::Packet_descriptor _packet { _usb.alloc_packet(0) }; completion _comp; public: diff --git a/repos/dde_linux/src/include/legacy/lx_kit/usb.h b/repos/dde_linux/src/include/legacy/lx_kit/usb.h index 6d503b0efe..00d80aec68 100644 --- a/repos/dde_linux/src/include/legacy/lx_kit/usb.h +++ b/repos/dde_linux/src/include/legacy/lx_kit/usb.h @@ -26,7 +26,7 @@ class Urb : public Usb::Completion Usb::Session_client & _usb; urb & _urb; Usb::Packet_descriptor _packet { - _usb.source()->alloc_packet(_urb.transfer_buffer_length) }; + _usb.alloc_packet(_urb.transfer_buffer_length) }; bool _completed { false }; public: diff --git a/repos/libports/src/lib/libusb/genode_usb_raw.cc b/repos/libports/src/lib/libusb/genode_usb_raw.cc index a861e82e7b..a46a37897b 100644 --- a/repos/libports/src/lib/libusb/genode_usb_raw.cc +++ b/repos/libports/src/lib/libusb/genode_usb_raw.cc @@ -80,7 +80,7 @@ struct Usb_device raw_config_descriptor = (char*)malloc(config_descriptor.total_length); Usb::Packet_descriptor p = - usb_connection->source()->alloc_packet(config_descriptor.total_length); + usb_connection->alloc_packet(config_descriptor.total_length); p.type = Usb::Packet_descriptor::CTRL; p.control.request = LIBUSB_REQUEST_GET_DESCRIPTOR; @@ -121,7 +121,7 @@ struct Usb_device return false; Usb::Packet_descriptor p = - usb_connection->source()->alloc_packet(0); + usb_connection->alloc_packet(0); p.type = Usb::Packet_descriptor::ALT_SETTING; p.interface.number = number; @@ -521,7 +521,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer) Usb::Packet_descriptor p; try { - p = usb_device->usb_connection->source()->alloc_packet(setup->wLength); + p = usb_device->usb_connection->alloc_packet(setup->wLength); } catch (Usb::Session::Tx::Source::Packet_alloc_failed) { return LIBUSB_ERROR_BUSY; } @@ -565,7 +565,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer) Usb::Packet_descriptor p; try { - p = usb_device->usb_connection->source()->alloc_packet(transfer->length); + p = usb_device->usb_connection->alloc_packet(transfer->length); } catch (Usb::Session::Tx::Source::Packet_alloc_failed) { return LIBUSB_ERROR_BUSY; } @@ -601,7 +601,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer) Usb::Packet_descriptor p; try { - p = usb_device->usb_connection->source()->alloc_packet(total_length); + p = usb_device->usb_connection->alloc_packet(total_length); } catch (Usb::Session::Tx::Source::Packet_alloc_failed) { return LIBUSB_ERROR_BUSY; } diff --git a/repos/libports/src/lib/qemu-usb/host.cc b/repos/libports/src/lib/qemu-usb/host.cc index cd2bbbbbe8..e042f31214 100644 --- a/repos/libports/src/lib/qemu-usb/host.cc +++ b/repos/libports/src/lib/qemu-usb/host.cc @@ -534,7 +534,7 @@ struct Usb_host_device : List::Element throw Packet_alloc_failed(); } - Usb::Packet_descriptor packet = usb_raw.source()->alloc_packet(length); + Usb::Packet_descriptor packet = usb_raw.alloc_packet(length); if (!completion) { packet.completion = nullptr; diff --git a/repos/os/include/usb/packet_handler.h b/repos/os/include/usb/packet_handler.h index 98ff826843..3ab175d41e 100644 --- a/repos/os/include/usb/packet_handler.h +++ b/repos/os/include/usb/packet_handler.h @@ -94,7 +94,7 @@ class Usb::Packet_handler while (true) { try { - Packet_descriptor p = _connection.source()->alloc_packet(size); + Packet_descriptor p = _connection.alloc_packet(size); return p; } catch (Usb::Session::Tx::Source::Packet_alloc_failed) { /* block until some packets are freed */ diff --git a/repos/os/include/usb_session/client.h b/repos/os/include/usb_session/client.h index 4b4554fac3..8f60861ee3 100644 --- a/repos/os/include/usb_session/client.h +++ b/repos/os/include/usb_session/client.h @@ -52,6 +52,20 @@ class Usb::Session_client : public Genode::Rpc_client sigh_state_change(state_change); } + /* + * Helper utility to always allocate correctly aligned USB packets + */ + Packet_descriptor alloc_packet(Genode::size_t size) + { + /* + * At least on ARM the minimal alignment for distinct + * DMA-capable USB URBs shall meet a maximum cache-line + * size of 128 bytes + */ + enum { URB_PAYLOAD_MIN_ALIGN_LOG2 = 7 }; + return source()->alloc_packet(size, URB_PAYLOAD_MIN_ALIGN_LOG2); + } + /*************************** ** USB session interface ** ***************************/