CPU write value passed from application to qemu is weird

I tried to run an RTEMS application (real-time application) on a sparc virtual machine using QEMU. I am almost there, and I saw this working time ago. But after deleting some fingerprints, it does not work, and later I did not find it because of deleted fingerprints. Data is not transferred correctly between the RTEMS image and the QEMU emulation model (I work with the QEMU model 1.5.50 and lan9118.c, borrowed from QEMU version 2.0.0. I modified lan9118 a bit.)
In the QEMU model, memory region operators are defined as

struct MemoryRegionOps { /* Read from the memory region. @addr is relative to @mr; @size is * in bytes. */ uint64_t (*read)(void *opaque, hwaddr addr, unsigned size); /* Write to the memory region. @addr is relative to @mr; @size is * in bytes. */ void (*write)(void *opaque, hwaddr addr, uint64_t data, unsigned size); ... } 

and in the RTEMS application I write to the device, for example

  *TX_FIFO_PORT = cmdA; *TX_FIFO_PORT = cmdB; 

where TX_FIFO_PORT is defined below.

 #define TX_FIFO_PORT (volatile ulong *)(SMSC9118_BASE + 0x20) 

But when I write, for example,

 cmdA : 0x2a300200 and cmdB : 0x2a002a00, 

Expected Values

 cmdA : 0x0002302a and cmdB : 0x002a002a. (Just endian converted values) 

But the values ​​that I see when writing a function (input to QEMU) are

 cmdA : 0x02000200 and cmdB : 0x2a002a00 respectively. 

The observed values ​​were not converted to the end, and even the first value is different (the lower 16 bit is repeated). What could be the problem?
Any hint would be greatly appreciated.

+5
source share
1 answer

Strange I fixed this by commenting on the endian conversion for cmdA and cmdB to RTEMS before recording to the device. (This was normal with endian conversion. I don't know). So it works almost. In any case, here is an example on how to process and write CPU data to the QEMU processor and start it up.
In QEMU, each device model provides a write and read function, and also indicates how this word should be transmitted to / from the device regarding the approval. It is listed as shown below.

 static const MemoryRegionOps lan9118_mem_ops = { .read = lan9118_readl, .write = lan9118_writel, .endianness = DEVICE_NATIVE_ENDIAN, }; 

Here is a copy from the email that I received from Peter Maidell from the mail list qemu-discuss@nongnu.org.

------------------------

It depends on how the MemoryRegionOps structure for the memory area sets its .endianness field. DEVICE_NATIVE_ENDIAN means that the device sees the values ​​in the same way as the original endianness of the guest processor [*], therefore, if a guest makes 32-bit recording 0x12345678, then it appears in the argument of the recording function as 0x12345678. DEVICE_BIG_ENDIAN means that if the CPU is little oriented, then the word will be byte. DEVICE_LITTLE_ENDIAN means that if the CPU is large, then the word will be a byte. The latter are useful for devices or buses that have a certain specification, which is not the same as that of the CPU (for example, PCI is always little endian).

0
source

Source: https://habr.com/ru/post/1203592/


All Articles