I am currently going through Linux Device Drivers book and found the functions for reading from I/O memory:
To read from I/O memory, use one of the following:
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);
If you must read or write a series of values to a given I/O memory address, you can use the repeating versions of the functions:
void ioread8_rep(void *addr, void *buf, unsigned long count);
void ioread16_rep(void *addr, void *buf, unsigned long count);
void ioread32_rep(void *addr, void *buf, unsigned long count);
These functions read or writecount
values from the givenbuf
to the givenaddr
. Note thatcount
is expressed in the size of the data being written;ioread32_rep
readscount
32-bit values starting atbuf
.
I used ioread64()
and iowrite64()
in a driver code for reading and writing to a memory-mapped IO register (8 bytes). iowrite64()
works but iowrite64()
function never returns and my virtual machine (QEMU) froze – all I could do was to restart. I used GDB to debug remotely but no error messages shown. By checking dmesg on host machine, no error message shown either. For more detailed information, please refer to this question.
Since I cannot find a way to figure out why ioread64()
failed, I thought I may use ioread32_rep()
instead.
By searching through the kernel driver code, I noticed that most of the use cases of ioread32_rep()
are some buffers within the device (e.g. those network devices which handle streaming data). If I could use ioread32_rep()
to replace ioread64()
for merely reading an 8-byte memory mapped register, would that be appropriate?
Any ideas would be appreciated.
Advertisement
Answer
ioread32_rep(addr, buf, 2) to replace ioread64()?
On an old 8088 CPU, ioread16(n)
does more or less the same as ioread8(n)
followed by ioread8(n+1)
.
For this reason, I suspect that ioread64(n)
does more or less the same as ioread32(n)
followed by ioread32(n+4)
on a 64-bit computer when the hardware is connected using a 32-bit bus.
However, ioread32_rep(n,buffer,2)
will perform ioread32(n)
(and not (n+4)
) twice.
If a real hardware is connected using a 64-bit bus, the electrical signals sent by ioread64
cannot be emulated using ioread32
at all. It depends on that hardware if it accepts two ioread32
instructions instead of one ioread64
instruction.
Some devices may even distinguish between calling ioread32
multiple times and calling ioread32_rep
.
QEMU
I don’t know about QEMU, but I know that VMware (another virtual machine software) sometimes does distinguish between ioread32
and ioread32_rep
.
and my virtual machine (QEMU) froze
Real hardware may also freeze if you access some I/O registers in a way that is not allowed – I already saw that when accessing PCI registers.
Are you sure that the corresponding address(es) can be accessed using iowrite64
at all?