The kernel provides a viewport into the port address space via the /proc/ioports pseudo-file. Let's check it out on our x86_64 guest VM (again, we're only showing part of the output):
$ sudo cat /proc/ioports
[sudo] password for llkd:
0000-0cf7 : PCI Bus 0000:00
0000-001f : dma1
0020-0021 : pic1
0040-0043 : timer0
0050-0053 : timer1
0060-0060 : keyboard
0064-0064 : keyboard
0070-0071 : rtc_cmos
0070-0071 : rtc0
[...]
d270-d27f : 0000:00:0d.0
d270-d27f : ahci
$
We've highlighted the keyboard ports in bold. Notice how the port numbers match what the i8042 driver code we saw previously specifies. Interestingly, running the same command on the Raspberry Pi yields nothing; this is because no driver or subsystem is using any I/O ports. Analogous with MMIO, an entry in /proc/ioports is generated when the request_region() API runs, and, conversely, is removed when the corresponding release_region...