As far as my understanding goes, User space programs run in the unprivileged mode, and thus do not have direct access to memory or I/O.
Then how exactly can we directly access memory or I/O locations when we mmap /dev/mem in user space programs?
For example:
int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);
This is a hack very commonly used in embedded devices.
Now the variable leds can be used on the fly to access any device that could be present at 0x80840000.
We won't be using any system call to access that address anymore.
Even something like
leds[0x20] = val;
would work.
But privileged operations, such as reading/writing directly to/from an I/O address should be possible only by putting the processor to privileged mode through a system call.