On Sat Feb 17, 2024 at 12:02 AM AEST, Thomas Huth wrote: > getchar() can currently only be called once on arm since the implementation > is a little bit too naïve: After the first character has arrived, the > data register never gets set to zero again. To properly check whether a > byte is available, we need to check the "RX fifo empty" on the pl011 UART > or the "RX data ready" bit on the ns16550a UART instead. > > With this proper check in place, we can finally also get rid of the > ugly assert(count < 16) statement here. > Thanks, this seems to work well. But arm64 still behaves strangely with QEMU migration. It seems some odd corruption around __getchar, but this turns out not to have anything to do with the MMIO read, but it's just because the test case generally is spinning there when a migration happens. I modified __getchar() to the following, which removes the MMIO entirely and just waits a number of times called before returning a getchar, chosen to be enough time for QEMU migration to complete on my system... int __getchar(void) { static int i; static volatile int locked; int ret = -1; assert(!locked); locked = 1; assert(locked); cpu_relax(); assert(locked); i++; if (i >= 3000000) { i = 0; ret = 1; } assert(locked); locked = 0; assert(!locked); return ret; } I get asserts on the line right after cpu_relax() on arm64 after a few migrations on migration selftest. Without the cpu_relax() it takes longer to hit an assert and it's usually the first one. I expect this is related to TCG translation blocks and where it exits back to be migrated. Something is very strange, I suspect it's QEMU migration bug. Thanks, Nick