QEMU MIPS32 - 16550 Uart Implementation on a Custom Board
Asked Answered
H

1

8

I’m trying to use QEMU to emulate a piece of firmware, but I’m having trouble getting the UART device to properly update the Line Status Register and display the input character.

Details:

Target device: Qualcomm QCA9533 (Documentation here if you're curious)

Target firmware: VxWorks 6.6 with U-Boot bootload

CPU: MIPS 24Kc

Board: mipssim (modified)

Memory: 512MB

Command used: qemu-system-mips -S -s -cpu 24Kc -M mipssim –nographic -device loader,addr=0xBF000000,cpu-num=0 -serial /dev/ttyS0 -bios target_image.bin

I have to apologize here, but I am unable to share my source. However, as I am attempting to retool the mipssim board, I have only made minor changes to the code, which are as follows:

  • Rebased bios memory region to 0x1F000000

  • Changed load_image_targphys() target address to 0x1F000000

  • Changed $pc initial value to 0xBF000000 (TLB remap of 0x1F000000)

  • Replaced the mipssim serial_init() ¬call with serial_mm_init(isa, 0x20000, env->irq[0], 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN).

While it seems like serial_init() is probably the currently accepted standard, I wasn’t having any luck with remapping it. I noticed the malta board had no issues outputting on a MIPS test kernel I gave it, so I tried to mimic what was done there. However, I still cannot understand how QEMU works and I am unable to find many good resources that explain it. My slog through the source and included docs is ongoing, but in the meantime I was hoping someone might have some insight into what I’m doing wrong.

The binary loads and executes correctly from address 0xBF000000, but hangs when it hits the first UART polling loop. A look at mtree in the QEMU monitor shows that the I/O device is mapped correctly to address range 0x18020000-0x1802003F, and when the firmware writes to the Tx buffer, gdb shows the character successfully is written to memory. There’s just no further action from the serial device to pull that character and display it, so the firmware endlessly polls on the LSR waiting for an update.

Is there something I’m missing when it comes to serial/hardware interaction in QEMU? I would have assumed that remapping all of the existing functional components of the mipssim board would be enough to at least get serial communication working, especially since the target uses the same 16550 UART that mipssim does. Please let me know if you have any insights. It would be helpful if I could find a way to debug QEMU itself with symbols, but at the same time I’m not totally sure what I’d be looking for. Even advice on how to scope down the issue would be useful.

Thank you!

Haigh answered 22/10, 2019 at 18:46 Comment(1)
Further update: I looked at the docs more closely, and it appears that I may need to implement an APB as the QCA9533 does not have a UART directly connect to the GPIO pins. I found an implementation of an APB UART in the SPARC code, but I'm still working on getting it ported to work with MIPS. Not sure if that's the right answer, but it's the only lead I've got so far.Haigh
H
6

Well after a lot of hard work I got the UART working. The answer to the question lies within the serial_ioport_read() and serial_ioport_write() functions. These two methods are assigned as the callbacks QEMU invokes when data is read or written to the MemoryRegion for the serial device (which is initialized in serial_init() or serial_mm_init()). These functions do a bit of masking on the address (passed into the functions as addr) to determine which register is being referenced, then return the value from the SerialState struct corresponding to that register. It's surprisingly simple, but I guess everything seems simple once you've figured it out. The big turning point was the realization that QEMU effectively implements the serial device as a MemoryRegion with special functionality that is triggered on a memory operation.

Anyway, hope this helps someone in the future avoid the nightmare I went through. Cheers!

Haigh answered 25/10, 2019 at 20:8 Comment(1)
Good job! Keep it up :)Unparliamentary

© 2022 - 2024 — McMap. All rights reserved.