How to emulate memory mapped I / O

I have hardware that I want to emulate; I wonder if I can do it at such a low level. The hardware has many registers, which I place in the structure:

#include <stdint.h> struct MyControlStruct { uint32_t data_reg_1; uint32_t data_reg_2; uint32_t dummy[2]; // to make the following registers have certain addresses uint32_t control_reg_1; uint32_t control_reg_2; }; volatile struct MyControlStruct* MyDevice = (struct MyControlStruct*)0xDeadF00; 

So, I want to support the following syntax for accessing hardware on Windows and Linux:

 MyDevice->data_reg_1 = 42; MyDevice->data_reg_2 = 100; MyDevice->control_reg_1 = 1; 

When the last line of code is executed, I want the hardware emulator to wake up and do some things. Can I implement this on Windows and / or Linux? I thought about somehow catching the "segmentation fault" signal, but I'm not sure if this can be done on Windows or in general.

I looked at the mmap manual page; it might seem to help, but I couldnโ€™t figure out how I could use it.

Of course, I could abstract hardware access by defining functions like WriteToMyDevice , and everything will be easy (maybe), but I want to understand if I can provide access to my equipment in this way.

+6
source share
3 answers

Basically, you can encode a (not portable) handler for SIGSEGV , which will block and process access to unwanted pages and can check access to the specified address.

To do this on Linux, you need to use the sigaction system call with SA_SIGINFO and use the third argument ucontext_t* your signal handler.

This is extremely unmanageable: you will have to write differently for different Unix (maybe even the size of your Linux kernel version may matter) and when changing processors.

And I heard that Linux kernels do not work so fast with such processing.

Other top cores (Hurd, Plan9) offer user-level pagination, which should help.

+2
source

In fact, your emulator (rather rudely) is possible on linux with clean user space code.

To create an emulator, simply add a second thread or process (using shared memory, or perhaps the mmap'd and inotify file), observing a memory that mimics the displayed memory.

For a real hardware driver, you need a tiny bit of kernel code, but it may just be what maps the actual hardware addresses in user space to the corresponding permissions. In fact, this regresses the modern multi-user operating environment to the point that it acts like an old dos panel or a simple microcontroller - not a good practice, but it is functional, at least where security is not a concern.

Another thing you might consider is running the code in a virtual machine.

If the code you are going to execute is your own, it is best to write it in a portable way, in order to abstract from accessing the hardware to functions that you can rewrite for each platform (for example, OS, hardware version, or physical / emulated). These methods are more useful if this is someone else's existing code that you need to create the environment. Another thing that you can consider (if the original is not too tightly integrated) uses library-level interception at the level of dynamic libraries of certain functions, for example, LD_PRELOAD on linux or dll wrappers in windows. Or, for that matter, fixing the binary.

+1
source

At first I misunderstand your question. You have a piece of memory mapped to hardware and you want your emulation to be binary compatible. On Windows, you can allocate memory for a structure using VirtualAlloc and make it a protective page and catch any access to it using SEH.

+1
source

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


All Articles