diff --git a/repos/libports/ports/qemu-usb.hash b/repos/libports/ports/qemu-usb.hash index d77b1f7c5..4f25d1ffe 100644 --- a/repos/libports/ports/qemu-usb.hash +++ b/repos/libports/ports/qemu-usb.hash @@ -1 +1 @@ -a7b787edadc09700d4619f783404b70ef63681d2 +2ff18fbfd11a955148cfbdcaa81d4a1162750fcd diff --git a/repos/libports/src/lib/qemu-usb/host.cc b/repos/libports/src/lib/qemu-usb/host.cc index af783aa3b..5448a092e 100644 --- a/repos/libports/src/lib/qemu-usb/host.cc +++ b/repos/libports/src/lib/qemu-usb/host.cc @@ -16,24 +16,83 @@ #include #include #include +#include using namespace Genode; -static bool const verbose_devices = false; -static bool const verbose_host = false; +static bool const verbose_devices = false; +static bool const verbose_host = false; +static bool const verbose_warnings = false; Lock _lock; - static void update_ep(USBDevice *); static bool claim_interfaces(USBDevice *dev); +using Packet_alloc_failed = Usb::Session::Tx::Source::Packet_alloc_failed; +using Packet_type = Usb::Packet_descriptor::Type; +using Packet_error = Usb::Packet_descriptor::Error; + + +static unsigned endpoint_number(USBEndpoint const *usb_ep) +{ + bool in = usb_ep->pid == USB_TOKEN_IN; + return usb_ep->nr | (in ? USB_DIR_IN : 0); + +} + +class Isoc_packet : Fifo::Element +{ + friend class Fifo; + friend class Usb_host_device; + + private: + + Usb::Packet_descriptor _packet; + int _offset { 0 }; + char *_content; + int _size; + + public: + + Isoc_packet(Usb::Packet_descriptor packet, char *content) + : _packet(packet), _content(content), + _size (_packet.read_transfer() ? _packet.transfer.actual_size : _packet.size()) + { } + + bool copy(USBPacket *usb_packet) + { + if (!valid()) return false; + + int remaining = _size - _offset; + int copy_size = min(usb_packet->iov.size, remaining); + + usb_packet_copy(usb_packet, _content + _offset, copy_size); + + _offset += copy_size; + + if (!_packet.read_transfer()) { + _packet.transfer.packet_size[_packet.transfer.number_of_packets] = copy_size; + _packet.transfer.number_of_packets++; + } + + return remaining <= usb_packet->iov.size; + } + + bool valid() const { return _content != nullptr; } + unsigned packet_count() const { return _packet.transfer.number_of_packets; } + + Usb::Packet_descriptor& packet() { return _packet; } +}; + struct Completion : Usb::Completion { - USBPacket *p = nullptr; - USBDevice *dev = nullptr; - uint8_t *data = nullptr; + USBPacket *p = nullptr; + USBDevice *dev = nullptr; + uint8_t *data = nullptr; + unsigned endpoint = 0; + enum State { VALID, FREE, CANCELED }; State state = FREE; @@ -41,17 +100,18 @@ struct Completion : Usb::Completion void complete(Usb::Packet_descriptor &packet, char *content) { - if (state != VALID) + if (state != VALID) { return; + } int actual_size = 0; switch (packet.type) { - case Usb::Packet_descriptor::CTRL: + case Packet_type::CTRL: actual_size = packet.control.actual_size; break; - case Usb::Packet_descriptor::BULK: - case Usb::Packet_descriptor::IRQ: + case Packet_type::BULK: + case Packet_type::IRQ: actual_size = packet.transfer.actual_size; default: break; @@ -60,7 +120,7 @@ struct Completion : Usb::Completion if (actual_size < 0) actual_size = 0; if (verbose_host) - log(__func__, ": packet.type: ", (int)packet.type, " " + log(__func__, ": packet: ", p, " packet.type: ", (int)packet.type, " " "actual_size: ", Hex(actual_size)); p->actual_length = 0; @@ -75,29 +135,34 @@ struct Completion : Usb::Completion if (packet.succeded) p->status = USB_RET_SUCCESS; else { - if (packet.error == Usb::Packet_descriptor::STALL_ERROR) + if (packet.error == Packet_error::STALL_ERROR) p->status = USB_RET_STALL; else p->status = USB_RET_IOERROR; } switch (packet.type) { - case Usb::Packet_descriptor::CONFIG: + case Packet_type::CONFIG: if (!claim_interfaces(dev)) p->status = USB_RET_IOERROR; - case Usb::Packet_descriptor::ALT_SETTING: + case Packet_type::ALT_SETTING: update_ep(dev); - case Usb::Packet_descriptor::CTRL: + case Packet_type::CTRL: usb_generic_async_ctrl_complete(dev, p); break; - case Usb::Packet_descriptor::BULK: - case Usb::Packet_descriptor::IRQ: + case Packet_type::BULK: + case Packet_type::IRQ: usb_packet_complete(dev, p); break; default: break; } } + + bool valid() const { return state == VALID; } + void cancel() { state = CANCELED; } + void free() { state = FREE; } + unsigned ep() const { return p ? endpoint_number(p->ep) : endpoint; } }; @@ -114,12 +179,12 @@ struct Dev_info vendor(vendor), product(product), bus(bus), dev(dev) { } - void print(Genode::Output &out) const + void print(Output &out) const { Genode::print(out, Hex(bus, Hex::OMIT_PREFIX, Hex::PAD), ":", - Hex(dev, Hex::OMIT_PREFIX, Hex::PAD), " (", - "vendor=", Hex(vendor, Hex::OMIT_PREFIX), ", ", - "product=", Hex(product, Hex::OMIT_PREFIX), ")"); + Hex(dev, Hex::OMIT_PREFIX, Hex::PAD), " (", + "vendor=", Hex(vendor, Hex::OMIT_PREFIX), ", ", + "product=", Hex(product, Hex::OMIT_PREFIX), ")"); } bool operator != (Dev_info const &other) const @@ -137,21 +202,27 @@ struct Dev_info struct Usb_host_device : List::Element { - struct Could_not_create_device : Genode::Exception { }; + struct Could_not_create_device : Exception { }; bool deleted = false; char const *label = nullptr; Dev_info const info; - USBHostDevice *qemu_dev; - Completion completion[Usb::Session::TX_QUEUE_SIZE]; + + /* submit queue + ack queue + 1 -> max nr of packets in flight */ + enum { NUM_COMPLETIONS = Usb::Session::TX_QUEUE_SIZE * 2 + 1 }; + Completion completion[NUM_COMPLETIONS]; + + Fifo isoc_read_queue; + Reconstructible isoc_write_packet { Usb::Packet_descriptor(), nullptr }; Signal_receiver &sig_rec; Signal_dispatcher state_dispatcher { sig_rec, *this, &Usb_host_device::state_change }; - Allocator_avl _alloc; - Usb::Connection usb_raw; // { &alloc, label, 1024*1024, state_dispatcher }; + Allocator &_alloc; + Allocator_avl _usb_alloc { &_alloc }; + Usb::Connection usb_raw; //{ &_usb_alloc, label, 1024*1024, state_dispatcher }; Signal_dispatcher ack_avail_dispatcher { sig_rec, *this, &Usb_host_device::ack_avail }; @@ -160,10 +231,12 @@ struct Usb_host_device : List::Element Usb::Config_descriptor cdescr; Usb::Device_descriptor ddescr; - usb_raw.config_descriptor(&ddescr, &cdescr); + try { usb_raw.config_descriptor(&ddescr, &cdescr); } + catch (Usb::Session::Device_not_found) { return; } for (unsigned i = 0; i < cdescr.num_interfaces; i++) { - usb_raw.release_interface(i); + try { usb_raw.release_interface(i); } + catch (Usb::Session::Device_not_found) { return; } } } @@ -172,7 +245,8 @@ struct Usb_host_device : List::Element Usb::Config_descriptor cdescr; Usb::Device_descriptor ddescr; - usb_raw.config_descriptor(&ddescr, &cdescr); + try { usb_raw.config_descriptor(&ddescr, &cdescr); } + catch (Usb::Session::Device_not_found) { return false; } bool result = true; for (unsigned i = 0; i < cdescr.num_interfaces; i++) { @@ -189,11 +263,11 @@ struct Usb_host_device : List::Element } Usb_host_device(Signal_receiver &sig_rec, Allocator &alloc, - Genode::Env &env, char const *label, + Env &env, char const *label, Dev_info info) : - label(label), _alloc(&alloc), - usb_raw(env, &_alloc, label, 6*1024*1024, state_dispatcher), + label(label), _alloc(alloc), + usb_raw(env, &_usb_alloc, label, 6*1024*1024, state_dispatcher), info(info), sig_rec(sig_rec) { usb_raw.tx_channel()->sigh_ack_avail(ack_avail_dispatcher); @@ -207,6 +281,11 @@ struct Usb_host_device : List::Element throw Could_not_create_device(); } + ~Usb_host_device() + { + isoc_in_flush(0, true); + } + static int to_qemu_speed(unsigned speed) { switch (speed) { @@ -227,13 +306,149 @@ struct Usb_host_device : List::Element while (usb_raw.source()->ack_avail()) { Usb::Packet_descriptor packet = usb_raw.source()->get_acked_packet(); + Completion *c = dynamic_cast(packet.completion); - char *packet_content = usb_raw.source()->packet_content(packet); - dynamic_cast(packet.completion)->complete(packet, packet_content); - free_packet(packet); + if ((packet.type == Packet_type::ISOC && !packet.read_transfer()) || + (c && c->state == Completion::CANCELED)) { + free_packet(packet); + continue; + } + + char *content = usb_raw.source()->packet_content(packet); + + if (packet.type != Packet_type::ISOC) { + c->complete(packet, content); + free_packet(packet); + } else { + /* isochronous in */ + free_completion(packet); + _isoc_in_pending--; + isoc_read_queue.enqueue(new (_alloc) Isoc_packet(packet, content)); + } } } + + /********************************** + ** Isochronous packet handling ** + **********************************/ + + bool isoc_read(USBPacket *packet) + { + if (isoc_read_queue.empty()) { + return false; + } + + if (isoc_read_queue.head()->copy(packet)) { + free_packet(isoc_read_queue.dequeue()); + } + + return true; + } + + unsigned _isoc_in_pending = 0; + + bool isoc_new_packet() + { + unsigned count = 0; + for (Isoc_packet *packet = isoc_read_queue.head(); packet; + packet = packet->next(), count++); + + return (count + _isoc_in_pending) < 3 ? true : false; + } + + void isoc_in_packet(USBPacket *usb_packet) + { + enum { NUMBER_OF_PACKETS = 2 }; + isoc_read(usb_packet); + + if (!isoc_new_packet()) + return; + + size_t size = usb_packet->ep->max_packet_size * NUMBER_OF_PACKETS; + try { + Usb::Packet_descriptor packet = alloc_packet(size); + packet.type = Packet_type::ISOC; + packet.transfer.ep = usb_packet->ep->nr | USB_DIR_IN; + packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL; + packet.transfer.number_of_packets = NUMBER_OF_PACKETS; + for (unsigned i = 0; i < NUMBER_OF_PACKETS; i++) { + packet.transfer.packet_size[i] = usb_packet->ep->max_packet_size; + } + + Completion *c = dynamic_cast(packet.completion); + c->p = nullptr; + c->dev = usb_packet->ep->dev; + c->data = nullptr; + c->endpoint = endpoint_number(usb_packet->ep); + + _isoc_in_pending++; + + submit(packet); + } catch (Packet_alloc_failed) { + if (verbose_warnings) + warning("xHCI: packet allocation failed (size ", Hex(size), "in ", __func__, ")"); + } + } + + void isoc_in_flush(unsigned ep, bool all = false) + { + /* flush finished and stored data */ + for (Isoc_packet *packet = isoc_read_queue.head(); packet; ) + { + if (!all && (!packet->valid() || packet->packet().transfer.ep != ep)) { + packet = packet->next(); + continue; + } + + Isoc_packet *next = packet->next(); + isoc_read_queue.remove(packet); + free_packet(packet); + packet = next; + } + + /* flush in flight packets */ + flush_completion(ep); + } + + void isoc_out_packet(USBPacket *usb_packet) + { + enum { NUMBER_OF_PACKETS = 32 }; + + bool valid = isoc_write_packet->valid(); + if (valid) { + isoc_write_packet->copy(usb_packet); + + if (isoc_write_packet->packet_count() < NUMBER_OF_PACKETS) + return; + + submit(isoc_write_packet->packet()); + } + + size_t size = usb_packet->ep->max_packet_size * NUMBER_OF_PACKETS; + try { + Usb::Packet_descriptor packet = alloc_packet(size, false); + packet.type = Packet_type::ISOC; + packet.transfer.ep = usb_packet->ep->nr; + packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL; + packet.transfer.number_of_packets = 0; + + isoc_write_packet.construct(packet, usb_raw.source()->packet_content(packet)); + if (!valid) isoc_write_packet->copy(usb_packet); + + } catch (Packet_alloc_failed) { + if (verbose_warnings) + warning("xHCI: packet allocation failed (size ", Hex(size), "in ", __func__, ")"); + isoc_write_packet.construct(Usb::Packet_descriptor(), nullptr); + return; + } + } + + + /*********************** + ** Device disconnect ** + ***********************/ + void _destroy() { /* mark delete before removing */ @@ -262,45 +477,89 @@ struct Usb_host_device : List::Element _destroy(); } - Usb::Packet_descriptor alloc_packet(int length) - { - if (!usb_raw.source()->ready_to_submit()) - throw -1; + /******************* + ** Packet stream ** + *******************/ + + Usb::Packet_descriptor alloc_packet(int length, bool completion = true) + { + if (!usb_raw.source()->ready_to_submit()) { + throw Packet_alloc_failed(); + } Usb::Packet_descriptor packet = usb_raw.source()->alloc_packet(length); + + if (!completion) { + packet.completion = nullptr; + return packet; + } + packet.completion = alloc_completion(); + if (!packet.completion) { + usb_raw.source()->release_packet(packet); + throw Packet_alloc_failed(); + } + return packet; } void free_packet(Usb::Packet_descriptor &packet) { - dynamic_cast(packet.completion)->state = Completion::FREE; + free_completion(packet); usb_raw.source()->release_packet(packet); } + void free_packet(Isoc_packet *packet) + { + free_packet(packet->packet()); + Genode::destroy(_alloc, packet); + } + Completion *alloc_completion() { - for (unsigned i = 0; i < Usb::Session::TX_QUEUE_SIZE; i++) + for (unsigned i = 0; i < NUM_COMPLETIONS; i++) if (completion[i].state == Completion::FREE) { - completion[i]. state = Completion::VALID; + completion[i].state = Completion::VALID; return &completion[i]; } return nullptr; } - Completion *find_completion(USBPacket *p) + void free_completion(Usb::Packet_descriptor &packet) { - for (unsigned i = 0; i < Usb::Session::TX_QUEUE_SIZE; i++) - if (completion[i].p == p) + if (packet.completion) { + dynamic_cast(packet.completion)->free(); + } + } + + Completion *find_valid_completion(USBPacket *p) + { + for (unsigned i = 0; i < NUM_COMPLETIONS; i++) + if (completion[i].p == p && completion[i].valid()) return &completion[i]; return nullptr; } - void submit(Usb::Packet_descriptor p) { - usb_raw.source()->submit_packet(p); } + void flush_completion(unsigned ep) + { + for (unsigned i = 0; i < NUM_COMPLETIONS; i++) + { + if (!completion[i].valid()) + continue; + + if (completion[i].ep() == ep) { + completion[i].cancel(); + } + } + } + + void submit(Usb::Packet_descriptor p) + { + usb_raw.source()->submit_packet(p); + } bool claim_interfaces() { return _claim_interfaces(); } @@ -308,29 +567,42 @@ struct Usb_host_device : List::Element { _release_interfaces(); - Usb::Packet_descriptor packet = alloc_packet(0); - packet.type = Usb::Packet_descriptor::CONFIG; - packet.number = value; + try { + Usb::Packet_descriptor packet = alloc_packet(0); + packet.type = Usb::Packet_descriptor::CONFIG; + packet.number = value; + + Completion *c = dynamic_cast(packet.completion); + c->p = p; + c->dev = cast_USBDevice(qemu_dev); + submit(packet); + p->status = USB_RET_ASYNC; + } catch (...) { + if (verbose_warnings) + warning(__func__, " packet allocation failed"); + p->status = USB_RET_NAK; + } - Completion *c = dynamic_cast(packet.completion); - c->p = p; - c->dev = cast_USBDevice(qemu_dev); - submit(packet); - p->status = USB_RET_ASYNC; } void set_interface(int index, uint8_t value, USBPacket *p) { - Usb::Packet_descriptor packet = alloc_packet(0); - packet.type = Usb::Packet_descriptor::ALT_SETTING; - packet.interface.number = index; - packet.interface.alt_setting = value; + try { + Usb::Packet_descriptor packet = alloc_packet(0); + packet.type = Usb::Packet_descriptor::ALT_SETTING; + packet.interface.number = index; + packet.interface.alt_setting = value; - Completion *c = dynamic_cast(packet.completion); - c->p = p; - c->dev = cast_USBDevice(qemu_dev); - submit(packet); - p->status = USB_RET_ASYNC; + Completion *c = dynamic_cast(packet.completion); + c->p = p; + c->dev = cast_USBDevice(qemu_dev); + submit(packet); + p->status = USB_RET_ASYNC; + } catch (...) { + if (verbose_warnings) + warning(__func__, " packet allocation failed"); + p->status = USB_RET_NAK; + } } void update_ep(USBDevice *udev) @@ -341,7 +613,8 @@ struct Usb_host_device : List::Element Usb::Config_descriptor cdescr; Usb::Device_descriptor ddescr; - usb_raw.config_descriptor(&ddescr, &cdescr); + try { usb_raw.config_descriptor(&ddescr, &cdescr); } + catch (Usb::Session::Device_not_found) { return; } for (unsigned i = 0; i < cdescr.num_interfaces; i++) { udev->altsetting[i] = usb_raw.alt_settings(i); @@ -407,7 +680,8 @@ static void usb_host_realize(USBDevice *udev, Error **errp) Usb::Config_descriptor cdescr; Usb::Device_descriptor ddescr; - dev->usb_raw.config_descriptor(&ddescr, &cdescr); + try { dev->usb_raw.config_descriptor(&ddescr, &cdescr); } + catch (Usb::Session::Device_not_found) { return; } if (verbose_host) log("set udev->speed to %d", Usb_host_device::to_qemu_speed(ddescr.speed)); @@ -425,40 +699,48 @@ static void usb_host_cancel_packet(USBDevice *udev, USBPacket *p) { USBHostDevice *d = USB_HOST_DEVICE(udev); Usb_host_device *dev = (Usb_host_device *)d->data; - Completion *c = dev->find_completion(p); - c->state = Completion::CANCELED; + Completion *c = dev->find_valid_completion(p); + + if (c) + c->cancel(); } static void usb_host_handle_data(USBDevice *udev, USBPacket *p) { - USBHostDevice *d = USB_HOST_DEVICE(udev); - Usb_host_device *dev = (Usb_host_device *)d->data; - - Genode::size_t size = 0; + USBHostDevice *d = USB_HOST_DEVICE(udev); + Usb_host_device *dev = (Usb_host_device *)d->data; + Genode::size_t size = 0; Usb::Packet_descriptor::Type type = Usb::Packet_descriptor::BULK; + bool const in = p->pid == USB_TOKEN_IN; switch (usb_ep_get_type(udev, p->pid, p->ep->nr)) { case USB_ENDPOINT_XFER_BULK: - type = Usb::Packet_descriptor::BULK; - size = usb_packet_size(p); + type = Usb::Packet_descriptor::BULK; + size = usb_packet_size(p); + p->status = USB_RET_ASYNC; break; case USB_ENDPOINT_XFER_INT: - type = Usb::Packet_descriptor::IRQ; - size = p->iov.size; + type = Usb::Packet_descriptor::IRQ; + size = p->iov.size; + p->status = USB_RET_ASYNC; break; + case USB_ENDPOINT_XFER_ISOC: + if (in) + dev->isoc_in_packet(p); + else + dev->isoc_out_packet(p); + return; default: error("not supported data request"); break; } - bool const in = p->pid == USB_TOKEN_IN; - try { - Usb::Packet_descriptor packet = dev->alloc_packet(size); - packet.type = type; - packet.transfer.ep = p->ep->nr | (in ? USB_DIR_IN : 0); - packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL; + Usb::Packet_descriptor packet = dev->alloc_packet(size); + packet.type = type; + packet.transfer.ep = p->ep->nr | (in ? USB_DIR_IN : 0); + packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL; if (!in) { char * const content = dev->usb_raw.source()->packet_content(packet); @@ -471,10 +753,9 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p) c->data = nullptr; dev->submit(packet); - p->status = USB_RET_ASYNC; - } catch (...) { - /* submit queue full or packet larger than packet stream */ - Genode::warning("xHCI: packet allocation failed (size ", Genode::Hex(size), ")"); + } catch (Packet_alloc_failed) { + if (verbose_warnings) + warning("xHCI: packet allocation failed (size ", Hex(size), "in ", __func__, ")"); p->status = USB_RET_NAK; } } @@ -512,7 +793,11 @@ static void usb_host_handle_control(USBDevice *udev, USBPacket *p, Usb::Packet_descriptor packet; try { packet = dev->alloc_packet(length); - } catch (...) { error("Packet allocation failed"); return; } + } catch (...) { + if (verbose_warnings) + warning("Packet allocation failed"); + return; + } packet.type = Usb::Packet_descriptor::CTRL; packet.control.request_type = request >> 8; @@ -535,6 +820,24 @@ static void usb_host_handle_control(USBDevice *udev, USBPacket *p, } +static void usb_host_ep_stopped(USBDevice *udev, USBEndpoint *usb_ep) +{ + USBHostDevice *d = USB_HOST_DEVICE(udev); + Usb_host_device *dev = (Usb_host_device *)d->data; + + bool in = usb_ep->pid == USB_TOKEN_IN; + unsigned ep = endpoint_number(usb_ep); + + switch (usb_ep->type) { + case USB_ENDPOINT_XFER_ISOC: + if (in) + dev->isoc_in_flush(ep); + default: + return; + } +} + + static Property usb_host_dev_properties[] = { DEFINE_PROP_END_OF_LIST(), }; @@ -550,6 +853,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data) uc->cancel_packet = usb_host_cancel_packet; uc->handle_data = usb_host_handle_data; uc->handle_control = usb_host_handle_control; + uc->ep_stopped = usb_host_ep_stopped; dc->props = usb_host_dev_properties; } @@ -624,10 +928,10 @@ struct Usb_devices : List Dev_info const dev_info(bus, dev, vendor, product); - Genode::String<128> label; + String<128> label; try { node.attribute("label").value(&label); - } catch (Genode::Xml_attribute::Nonexistent_attribute) { + } catch (Xml_attribute::Nonexistent_attribute) { error("no label found for device ", dev_info); return; } @@ -653,7 +957,6 @@ struct Usb_devices : List insert(new_device); log("Attach USB device ", dev_info); - } catch (...) { error("could not attach USB device ", dev_info); } @@ -669,7 +972,7 @@ struct Usb_devices : List _garbage_collect(); } - Usb_devices(Signal_receiver *sig_rec, Allocator &alloc, Genode::Env &env) + Usb_devices(Signal_receiver *sig_rec, Allocator &alloc, Env &env) : _sig_rec(*sig_rec), _env(env), _alloc(alloc) { _devices_rom.sigh(_device_dispatcher); @@ -707,9 +1010,9 @@ extern "C" void usb_host_update_devices() /* * Do not use type_init macro because of name mangling */ -extern "C" void _type_init_usb_host_register_types(Genode::Signal_receiver *sig_rec, - Genode::Allocator *alloc, - Genode::Env *env) +extern "C" void _type_init_usb_host_register_types(Signal_receiver *sig_rec, + Allocator *alloc, + Env *env) { usb_host_register_types(); diff --git a/repos/libports/src/lib/qemu-usb/include/qemu_emul.h b/repos/libports/src/lib/qemu-usb/include/qemu_emul.h index e240bc8f8..7b6e5e38d 100644 --- a/repos/libports/src/lib/qemu-usb/include/qemu_emul.h +++ b/repos/libports/src/lib/qemu-usb/include/qemu_emul.h @@ -56,10 +56,8 @@ enum { EINVAL = 22, }; -void *malloc(size_t size); void *memset(void *s, int c, size_t n); void *memcpy(void *dest, const void *src, size_t n); -void free(void *p); void abort(); @@ -247,17 +245,17 @@ const char *object_get_typename(Object *obj); ** glib emulation ** ********************/ +void *g_malloc(size_t size); +void g_free(void *ptr); + #define g_new0(type, count)({ \ - typeof(type) *t = (typeof(type)*)malloc(sizeof(type) * count); \ + typeof(type) *t = (typeof(type)*)g_malloc(sizeof(type) * count); \ memset(t, 0, sizeof(type) * count); \ t; \ }) -#define g_free(p) free(p) -#define g_malloc malloc - #define g_malloc0(size) ({ \ - void *t = malloc((size)); \ + void *t = g_malloc((size)); \ memset(t, 0, (size)); \ t; \ }) diff --git a/repos/libports/src/lib/qemu-usb/patches/xhci_state.patch b/repos/libports/src/lib/qemu-usb/patches/xhci_state.patch index b9c57f61d..0b054895b 100644 --- a/repos/libports/src/lib/qemu-usb/patches/xhci_state.patch +++ b/repos/libports/src/lib/qemu-usb/patches/xhci_state.patch @@ -1,5 +1,5 @@ diff --git a/src/lib/qemu/hw/usb/hcd-xhci.c b/src/lib/qemu/hw/usb/hcd-xhci.c -index c673bed..b2a8939 100644 +index c673bed..cd930da 100644 --- a/src/lib/qemu/hw/usb/hcd-xhci.c +++ b/src/lib/qemu/hw/usb/hcd-xhci.c @@ -486,6 +486,8 @@ struct XHCIState { @@ -11,7 +11,22 @@ index c673bed..b2a8939 100644 #define XHCI(obj) \ OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI) -@@ -2361,6 +2363,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, +@@ -1349,6 +1351,14 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, + static void xhci_ep_kick_timer(void *opaque) + { + XHCIEPContext *epctx = opaque; ++ ++ /* ++ * We might have blocked in the entry lock, while the endpoint was stopped ++ * by another thread ++ */ ++ if (epctx->state == CC_STOPPED) ++ return; ++ + xhci_kick_ep(epctx->xhci, epctx->slotid, epctx->epid, 0); + } + +@@ -2361,6 +2371,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, if (bsr) { slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT; @@ -19,7 +34,7 @@ index c673bed..b2a8939 100644 } else { USBPacket p; uint8_t buf[1]; -@@ -3914,3 +3917,5 @@ static void xhci_register_types(void) +@@ -3914,3 +3925,5 @@ static void xhci_register_types(void) } type_init(xhci_register_types) diff --git a/repos/libports/src/lib/qemu-usb/qemu_emul.cc b/repos/libports/src/lib/qemu-usb/qemu_emul.cc index 7f39870f2..f4d5118c0 100644 --- a/repos/libports/src/lib/qemu-usb/qemu_emul.cc +++ b/repos/libports/src/lib/qemu-usb/qemu_emul.cc @@ -92,20 +92,20 @@ void Qemu::usb_timer_callback(void (*cb)(void*), void *data) ** libc ** **********/ -void *malloc(size_t size) { +void *g_malloc(size_t size) { return _heap->alloc(size); } +void g_free(void *p) { + if (!p) return; + _heap->free(p, 0); +} + + void *memset(void *s, int c, size_t n) { return Genode::memset(s, c, n); } -void free(void *p) { - if (!p) return; - _heap->free(p, 0); -} - - void q_printf(char const *fmt, ...) { va_list va; @@ -400,7 +400,7 @@ Type type_register_static(TypeInfo const *t) { if (!Genode::strcmp(t->name, TYPE_XHCI)) { Wrapper *w = &Object_pool::p()->obj[Object_pool::XHCI]; - w->_xhci_state = (XHCIState*) malloc(sizeof(XHCIState)); + w->_xhci_state = (XHCIState*) g_malloc(sizeof(XHCIState)); Genode::memset(w->_xhci_state, 0, sizeof(XHCIState)); t->class_init(&w->_object_class, 0); @@ -439,7 +439,7 @@ void qbus_create_inplace(void* bus, size_t size , const char* type, Wrapper *w = &Object_pool::p()->obj[Object_pool::USB_BUS]; BusState *b = &w->_bus_state; char const *n = "xhci.0"; - b->name = (char *)malloc(Genode::strlen(n) + 1); + b->name = (char *)g_malloc(Genode::strlen(n) + 1); Genode::strncpy(b->name, n, Genode::strlen(n) + 1); } @@ -453,7 +453,7 @@ void timer_del(QEMUTimer *t) void timer_free(QEMUTimer *t) { _timer_queue->delete_timer(t); - free(t); + g_free(t); } @@ -465,7 +465,7 @@ void timer_mod(QEMUTimer *t, int64_t expire) QEMUTimer* timer_new_ns(QEMUClockType, void (*cb)(void*), void *opaque) { - QEMUTimer *t = (QEMUTimer*)malloc(sizeof(QEMUTimer)); + QEMUTimer *t = (QEMUTimer*)g_malloc(sizeof(QEMUTimer)); if (t == nullptr) { Genode::error("could not create QEMUTimer"); return nullptr; @@ -710,7 +710,7 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) " <= niov: ", niov); qiov->alloc_hint += 64; - iovec *new_iov = (iovec*) malloc(sizeof(iovec) * qiov->alloc_hint); + iovec *new_iov = (iovec*) g_malloc(sizeof(iovec) * qiov->alloc_hint); if (new_iov == nullptr) { Genode::error("could not reallocate iov"); throw -1; @@ -721,7 +721,7 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) new_iov[i].iov_len = qiov->iov[i].iov_len; } - free(qiov->iov); + g_free(qiov->iov); qiov->iov = new_iov; } @@ -740,7 +740,7 @@ void qemu_iovec_destroy(QEMUIOVector *qiov) { qemu_iovec_reset(qiov); - free(qiov->iov); + g_free(qiov->iov); qiov->iov = nullptr; } @@ -770,7 +770,7 @@ void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint) qiov->alloc_hint = alloc_hint; - qiov->iov = (iovec*) malloc(sizeof(iovec) * alloc_hint); + qiov->iov = (iovec*) g_malloc(sizeof(iovec) * alloc_hint); if (qiov->iov == nullptr) { Genode::error("could not allocate iov"); throw -1; @@ -890,7 +890,7 @@ void error_setg(Error **errp, const char *fmt, ...) { assert(*errp == nullptr); - *errp = (Error*) malloc(sizeof(Error)); + *errp = (Error*) g_malloc(sizeof(Error)); if (*errp == nullptr) { Genode::error("could not allocate Error"); return; @@ -911,4 +911,4 @@ void error_propagate(Error **dst_errp, Error *local_err) { *dst_errp = local_err; } -void error_free(Error *err) { free(err); } +void error_free(Error *err) { g_free(err); }