This example will exercise vMMIO using the RaspberryPi model by demonstrating an external (over the network) MMIO handler and a local (RaspberryPi userspace) driver.
Read more in the AVH vMMIO Introduction article.
Creating the VM
Create a Raspberry Pi 4 Virtual Machine. In "DEVICES" in the menu click on "CREATE DEVICE"
Click on the RPi VM device the click "NEXT"
Select the
lite
firmware option if not already selected. Then click "SELECT"Select the
Set advanced boot options ...
checkbox and click "CREATE DEVICE"Select "Custom vMMIO" and enter 0xfef00000 for
start
, 0x1000 forsize
, 0 forIRQ
(not used in this example), and 4300 forport
(arbitrary). Then click "CREATE DEVICE" one final timeNote that 0xfef00000 was selected because the Raspberry Pi hardware does not have anything mapped at this address and as such it is safe to use for our purposes
The device will take a few moments to build. When complete click on "CONSOLE"
Writing to MMIO Without a vMMIO Handler Registered
Log in using the default credentials of
pi/raspberry
Download project sources to your Raspberry Pi, extract, and build it
pi@raspberrypi:~ $ wget https://avh.arm.com/downloads/coreio.tar.gz
...
2022-04-12 14:28:55 (18.0 MB/s) - ‘coreio.tar.gz’ saved [23940/23940]
pi@raspberrypi:~ $ tar -xf coreio.tar.gz
pi@raspberrypi:~ $ cd coreio/examples/rpi-test/
pi@raspberrypi:~/coreio/examples/rpi-test $ make
gcc -g -Wall -I../../ -shared -fPIC -o libcoreio.so ../../corehdl-base.c ../../coreio.c
gcc -g -Wall -I../../ -c -o corehdl-base.o ../../corehdl-base.c
gcc -g -Wall -I../../ -c -o coreio.o ../../coreio.c
ar cr libcoreio.a corehdl-base.o coreio.o
gcc -g -Wall -I../../ -ovmmio-test-inside vmmio-test-inside.c
gcc -g -Wall -I../../ -ovmmio-test-outside vmmio-test-outside.c libcoreio.aRun the
vmmio-test-inside
build productThis example source will open
/dev/mem
at offset 0xfef00000 (recall this is the address of the registered vMMIO) and attempt to read and write to it.However, without any registered vMMIO handlers running, AVH's default behavior, as mentioned earlier, is to return 0xaa in the registers receiving the read contents.
$ sudo ./vmmio-test-inside
0: 0xaa
1: 0xaa
2: 0xaa
3: 0xaa
...
0: 0xaaaa
1: 0xaaaa
2: 0xaaaa
3: 0xaaaa
...
0: 0xaaaaaaaa
1: 0xaaaaaaaa
2: 0xaaaaaaaa
3: 0xaaaaaaaa
...
0: 0xaaaaaaaaaaaaaaaa
1: 0xaaaaaaaaaaaaaaaa
2: 0xaaaaaaaaaaaaaaaa
3: 0xaaaaaaaaaaaaaaaaIn order to implement something more meaningful we need to handle those read and write requests by registering a handler
Writing to MMIO With a vMMIO Handler Registered
Download project sources to your local machine, extract, and build it
$ wget https://avh.arm.com/downloads/coreio.tar.gz
...
2022-04-12 14:28:55 (18.0 MB/s) - ‘coreio.tar.gz’ saved [23940/23940]
$ tar -xf coreio.tar.gz
$ cd coreio/examples/rpi-test/
$ make
gcc -g -Wall -I../../ -shared -fPIC -o libcoreio.so ../../corehdl-base.c ../../coreio.c
gcc -g -Wall -I../../ -c -o corehdl-base.o ../../corehdl-base.c
gcc -g -Wall -I../../ -c -o coreio.o ../../coreio.c
ar cr libcoreio.a corehdl-base.o coreio.o
gcc -g -Wall -I../../ -ovmmio-test-inside vmmio-test-inside.c
gcc -g -Wall -I../../ -ovmmio-test-outside vmmio-test-outside.c libcoreio.aRun the
vmmio-test-outside
build product, targeting the Services IP of the VM and vMMIO port (4300) as argumentsNote that this step registers the vMMIO handler, overriding the default behavior just observed
$ ./vmmio-test-outside 10.11.1.1:4300
tick
tick
tick
...Re-run
vmmio-test-inside
within the RaspberryPi VM. Observe that thevmmio-test-outside
binary will now emit state information for each read and write event happening inside the VM byvmmio-test-inside
.$ ./vmmio-test-outside 10.11.1.1:4300
tick
tick
tick
write fef00000 1 0000000000000000 0
write fef00001 1 0000000000000001 0
write fef00002 1 0000000000000002 0
write fef00003 1 0000000000000003 0
write fef00004 1 0000000000000004 0
write fef00005 1 0000000000000005 0
write fef00006 1 0000000000000006 0
tick
write fef00007 1 0000000000000007 0
write fef00008 1 0000000000000008 0
...Meanwhile
vmmio-test-inside
will emit the contents it reads from the MMIO address after attempting to modify its contents with a write.$ sudo ./vmmio-test-inside
0: 0x00
1: 0x01
2: 0x02
3: 0x03
...
0: 0x0100
1: 0x0201
2: 0x0302
3: 0x0403
...
0: 0x03020100
1: 0x04030201
2: 0x05040302
3: 0x06050403
...
0: 0x0706050403020100
1: 0x0807060504030201
2: 0x0908070605040302
3: 0x0a09080706050403
Flow Diagram
The flow followed in this example is illustrated below. The first example follows the "vMMIO Handler Registered" No path while the second has a remote handler registered and follows the Yes path.
Summary
In summary, vmmio-test-outside
is registering as an vMMIO read and write handler for a specified address range within the VM. When the physical address range specified is read from or written to, this handler receives a callback allowing it to handle the request. In this example, the vmmio-test-inside
binary opened /dev/mem
and simulates the OS or some other entity reading or writing to physical memory in order to exercise the callbacks in the registered vMMIO handler.