Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion hw/dma/apple_sio.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ static void apple_sio_dma_del_buffers(AppleSIODMAEndpoint* ep)
QTAILQ_FOREACH_SAFE (buf, &ep->buffers, next, buf_next) { apple_sio_dma_destroy_buffer(ep, buf); }
}

static void apple_sio_dma_writeback(AppleSIO* s, AppleSIODMAEndpoint* ep, SIODMABuffer* buf);

// -- internal references --
// Firestorm$Inferno/18A5351d/sio.bndb@000030e4{sio_endpoint::handle_message}+0x64
// -- end internal references --
Expand All @@ -224,7 +226,17 @@ static void apple_sio_dma_stop(AppleSIO* s, AppleSIODMAEndpoint* ep)
SIOMessage m = {0};
AppleRTKit* rtk = &s->parent_obj;

QTAILQ_FOREACH_SAFE (buf, &ep->buffers, next, buf_next) { apple_sio_dma_destroy_buffer(ep, buf); }
/*
* Every transfer still out comes back completed, however little of it was done. The kernel's stop
* waits, uninterruptibly, for the channel to go idle, and a channel goes idle only once every command
* it handed out has come back. Dropped quietly, they left the audio server's IO thread asleep in
* AppleSmartIODMA::_stopDMA for good — the first time right after the actuator's first vibration —
* and every sound in the system went with it.
*/
QTAILQ_FOREACH_SAFE (buf, &ep->buffers, next, buf_next) {
if (!buf->mapped) { buf->start_timestamp = apple_sio_get_cur_ts(s); }
apple_sio_dma_writeback(s, ep, buf);
}

m.op = OP_COMPLETE;
m.ep = ep->id;
Expand Down
6 changes: 5 additions & 1 deletion hw/misc/aop.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,12 @@ static void apple_aop_ep_handle_message(void* opaque, uint8_t ep, uint64_t msg)
g_free(actual_out_payload);
}
else {
// Past the result word there are out_len bytes; actual_out_len counts the word as well.
// Given that size, a handler that fills its buffer writes four bytes past the end of the
// allocation, into the next block on the heap, and malloc later spins in the damaged
// freelist with the guest stopped around it.
res = s->descr->handle_command(s->opaque, seq, actual_in_payload, actual_in_len,
actual_out_payload, actual_out_len);
actual_out_payload, out_len);
}

stl_le_p(out_payload, res);
Expand Down
Loading