From 015b91f08dfd13e8e38f920ff453f1a546e7d33a Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Thu, 1 Oct 2026 00:34:40 +0800 Subject: [PATCH] [Test] (extmem_probe): T4-host-image closes the round trip, and its first verdict was wrong for one constant The leg now reports OK on the device: offered=3 imported=3 drawn=3 hostReadback=3 agreed=3 -- three self-allocated AHardwareBuffers from the display host imported as EGLImages by this side, drawn into, and read back by the host at both the first pixel and the far corner. Getting there took one measurement and one correction. The handle message is 256 bytes on this path and recvHandleFromUnixSocket drains it exactly (pending 256 -> 100, then 0 -> 100, then 0 -> 0), so the description that follows it was never the problem; the comparison was. This leg was checking the display host's messages against kT4Magic -- the dma-buf protocol's magic, which belongs to the container peer -- while the host stamps AHB_BRIDGE_MAGIC on all three of its messages. A perfect round trip was reported as 'the offer's sideband did not follow its handle', which named the wrong cause and cost the time. kT4HostMagic is that value, and the leg now also prints the handle's footprint and the bytes it actually read, so the next failure of this shape cannot be mistaken for the other one. --- tools/spikes/extmem_probe/extmem_probe.cpp | 37 +++++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/tools/spikes/extmem_probe/extmem_probe.cpp b/tools/spikes/extmem_probe/extmem_probe.cpp index 8613ca84..0dcf3814 100644 --- a/tools/spikes/extmem_probe/extmem_probe.cpp +++ b/tools/spikes/extmem_probe/extmem_probe.cpp @@ -89,6 +89,7 @@ static const char* kT4HostRow = "T4-host-image"; #include #include #include +#include #include #include #include @@ -5634,6 +5635,19 @@ struct T4HostSeen { char note[64]; } __attribute__((packed)); +static int t4Pending(int fd) +{ + int n = -1; + return ioctl(fd, FIONREAD, &n) == 0 ? n : -1; +} + + +// The magic the display host's ahb_bridge.h stamps on all three of its messages. It is NOT +// kT4Magic: that one belongs to the dma-buf protocol between this probe and the container +// peer, and using it here failed a good round trip while reporting the wrong reason -- the +// handle had arrived, the description had arrived, and only the comparison was wrong. +static const uint32_t kT4HostMagic = 0x4D474C41u; // "ALGM" in memory order + static void runT4Host(GlCtx& g, bool glOk, const char* path) { if (!glOk) { record(kT4HostRow, "SKIP", "no headless GLES context: nothing on this side could take the host's image"); @@ -5684,12 +5698,25 @@ static void runT4Host(GlCtx& g, bool glOk, const char* path) { std::string trace, fail; for (int i = 0; i < 16; ++i) { + const int pendBefore = t4Pending(fd); AHardwareBuffer* ahb = nullptr; - if (AHardwareBuffer_recvHandleFromUnixSocket(fd, &ahb) != 0 || !ahb) + const int hrc = AHardwareBuffer_recvHandleFromUnixSocket(fd, &ahb); + const int pendAfter = t4Pending(fd); + /* The handle message footprint, measured rather than assumed: a receiver that leaves + * bytes behind hands the description reader whatever was left. */ + pr("T4-host: recvHandle rc=%d pending %d -> %d", hrc, pendBefore, pendAfter); + if (hrc != 0 || !ahb) break; T4HostOffer of{}; - if (!readAll(fd, &of, sizeof(of)) || of.magic != kT4Magic) { - fail = "the offer's sideband did not follow its handle"; + const bool ofRead = readAll(fd, &of, sizeof(of)); + if (!ofRead || of.magic != kT4HostMagic) { + pr("T4-host: sideband read=%d magic=0x%08x first=%02x %02x %02x %02x", (int)ofRead, of.magic, + ((const unsigned char *)&of)[0], ((const unsigned char *)&of)[1], + ((const unsigned char *)&of)[2], ((const unsigned char *)&of)[3]); + char why[160]; + snprintf(why, sizeof(why), "handle rc=%d (pending %d -> %d) then sideband read=%d magic=0x%08x", + hrc, pendBefore, pendAfter, (int)ofRead, of.magic); + fail = why; AHardwareBuffer_release(ahb); break; } @@ -5698,7 +5725,7 @@ static void runT4Host(GlCtx& g, bool glOk, const char* path) { AHardwareBuffer_describe(ahb, &d); T4HostAck ack{}; - ack.magic = kT4Magic; + ack.magic = kT4HostMagic; ack.version = 1; ack.index = of.index; @@ -5750,7 +5777,7 @@ static void runT4Host(GlCtx& g, bool glOk, const char* path) { (void)writeAll(fd, &ack, sizeof(ack)); T4HostSeen back{}; - if (readAll(fd, &back, sizeof(back)) && back.magic == kT4Magic) { + if (readAll(fd, &back, sizeof(back)) && back.magic == kT4HostMagic) { ++seen; const bool first = !memcmp(back.observed, kT4AhbSeed, 4); const bool corner = !memcmp(back.observed_corner, kT4AhbSeed, 4);