Emulate I2C on QEMU Aarch64 - embedded-linux

I have read this post How to emulate an i2c device on QEMU x86? about a solution for configuring an I2C device for QEMU emulating x86_64.
I am trying to do the same thing for ARM. Currently I have a simple I2C user space program that is timing out because although QEMU lists an I2C device in /dev it has no actual method of simulating the device and returning ACK. I was curious if someone could provide more detail on how I might implement the solution from that post because I am not very experienced in that area and the answer is pretty sparse in detail.
I am wondering how peripheral devices, other than USB, like ones using CAN and SPI are emulated when using QEMU.

Devices are supported on a device-by-device basis. QEMU emulation of Zynq 7000 can emulate certain EEPROM and flash devices and read and write to them over the I2C bus. Device support is listed here. Xilinx QEMU peripheral device support: http://www.wiki.xilinx.com/QEMU+-+Zynq-7000
I assume that support for other machine types is also on a by device basis, and hopefully it is as well documented as Xilinx's QEMU machines' peripheral support.
The wiki provided has other pages which provide examples of adding peripheral devices to the device tree. When you specify the device tree at QEMU invocation, QEMU will read the device tree and will begin emulating devices for which it has support.

Related

PCIe DMA problems in ARM Machines

I'm trying to write a PCIe driver for an ARM machine (Cavium ThunderX2). I'm working with Xilinx Alveo FPGAs. Our work involves migrating pages between heterogeneous nodes (x86 and ARM) and the driver takes care of the DMA between the host and the FPGA, and handles the device interrupts.
The DMA doesn't work (From Device/To Device) and I get "ARM SMMU v3.x 0x10 event occurred" errors. I tried disabling the SMMU (recommended by some threads in the NVIDIA community - https://forums.developer.nvidia.com/t/how-dma-works-in-arm-the-dma-stopped-working-with-our-pci-driver/53699), but that leads to a protection issue ("RAS Controller stopped"), and the system hangs.
I use dma_map_single APIs from dma-mapping.h to convert the virtual address to a DMA-capable bus address. Would dma_alloc_coherent make a difference? (Of course, I'll try this out)
I'm unable to figure out the problem. Is this is a PCIe driver issue or an issue with the device or is there a fix/patch available for ARM PCIe DMA ops? Any help would be appreciated!!
Thanks,
Narayan
Error snippet

How to implement a custom peripheral driver for an embedded Linux project using STM32MP1?

I would like to undertake a low level approach to transferring data from an FPGA to the STM32MP1 processor, I'm currently using an FTDI USB device which is an extra IC consuming power on my battery power device.
I would initialise and read data from the QUADSPI peripheral on the STM32 in dual bank mode.
I have been reading into kernel modules to gain register level access however they all seem to stop at Hello World or best toggling GPIO pins. I can't find any solid documentation for what I'm trying to do.
What is the best way to initialise a peripheral that has no Linux driver written for it?

Porting a Linux kernel driver to libusb

So I was wondering: Since libusb provides userspace access to USB, is it possible to port already existing kernel drivers to libusb?
I do understand it might need rewriting of the driver, but do you think it is possible to write a "virtual kernel" that relies on libusb for access to devices and link already existing drivers to that? Essentially writing a layer between libusb and kernel modules that translates kernel USB commands to libusb commands.
Why bother? If you want to run a kernel driver on Android for example, you need to make sure it was compiled for a particular kernel version/device model. So an app will not be able to run on all devices. On the other hand libusb is fully compatible with most of the latest Android devcices.
AFAIK, libusb is a library that communicates with the higher level of the USB layer of the kernel. The lowest parts of the USB subsystem have to be written in kernel space, because they need to have access to the physical address space of the USB host controller and uses interrupts, and other low-level functions that are not possible to implement in user space.
So I don't think that it is possible to port low-level parts of the USB subsystem in user-space.

where is device driver code executed? Kernel space or User space?

Part1:
To the linux/unix experts out there, Could you please help me understanding about device drivers. As i understood, a driver is a piece of code that directly interacts with hardware and exposes some apis to access the device. My question is where does this piece of code runs, User space or Kernel space?
I know that code that is executed in kernel space has some extra privileges like accessing any memory location(pls correct if i'm wrong). If we install a third party driver and if it runs in kernel space, wouldn't this be harmful for the whole system? How any OS handles this?
Part2:
Lets take an example of USB device(camera, keyboard..), How the system recognizes these devices? how does the system know which driver to install? How does the driver know the address of the device to read and write the data?
(if this is too big to answer here, pls provide links of some good documentation or tutorials.., I've tried and couldn't find answers for these. pls help)
Part 1
On linux, drivers run in kernel space. And yes, as you state there a significant security implications to this. Most exceptions in drivers will take down the kernel, potentially corrupt kernel memory (with all manner of consequences). Buggy drivers also have an impact on system security, and malicious drivers can do absolutely anything they want.
A trend seen on MacOSX and Window NT kernels is user-space drivers. Microsoft has for some time been pushing the Windows Userspace Driver Framework, and MacOSX has long provided user-space APIs for Firewire and USB drivers, and class-compliant drivers for many USB peripherals. it is quite unusual to install 3rd party kernel-mode device drivers on MacOSX.
Arguably, the bad reputation Windows used to have for kernel panics can be attributed to the (often poor quality) kernel mode drivers that came with just about every mobile phone, camera and printer.
Linux graphics drivers are pretty much all implemented in user-space with a minimal kernel-resident portion, and Fuse allows the implementation of filing systems in user-space.
Part 2
USB, Firewire, MCI (and also PCI-e) all have enumeration mechanisms through which a bus driver can match the device to a driver. In practice this means that all devices expose metadata describing what they are.
Contained within the metadata is a DeviceID, VendorID and a description of functions the device provides and associated ClassIDs. ClassIDs facilitate generic Class Drivers.
Conceptually, the operating system will attempt to find a driver that specifically supports the VendorID and DeviceID, and then fall back to one that supports the ClassID(s).
Matching devices to drivers is a core concept at the heart of the Linux Device Model, and exact matching criteria used for matching is match() function in the specific bus driver.
Once device drivers are bound to a device, it uses the bus-driver (or addressing information given by it) to perform read and writes. In the case of PCI and Firewire, this is a memory mapped IO address. For USB it bus addressing information.
The Linux Documentation tree provides some insight into the design of the Linux Device Model, but isn't really entry-level reading.
I'd also recommend reading Linux Device Driver (3rd Edition)

Keeping device functionality inside device controller rather than OS kernel. What are consequences?

A friend of mine asked me this question in the class and I could not answer it. He asked:
Since we know kernel controls the physical hardware via device drivers. What if all this functionality is kept inside the device controller itself rather than kernel managing them. What would be the consequences of such scenario? Good or Bad?
I searched online for this question but could not get information about this scenario. May be I'm not googling in the right keyword.
You insight into this will help me getting clearing my concepts.
Please answer.
Thanks.
Your question seems to propose the elimination of the "device driver" by "keeping" "control (of) the physical hardware ... inside the device controller". The premise for this seems to be:
kernel controls the physical hardware via device drivers.
That description of a device driver is something similar to what I've seem for end-user comprehension rather than from a developer's perspective. The end-user is aware of the device, and it is the device driver that takes that abstraction and can control that device down to the specific control bits of each device port.
But a device driver is responsible for mundane housekeeping tasks such as:
maintaining device status and availability;
configuring the device for operation;
managing data flow, setting-up/tearing-down data transfers, copying data between user space and kernel space;
handling interrupts and exceptions.
These tasks are integral to a device driver. These tasks cannot be transferred out of the purview of the kernel driver to a peripheral device.
Sometimes the device driver can only try to manage the device, rather than fully control it, for example, a NIC driver during a packet flood.
There is simply no possibility that you can eliminate a device driver no matter how much of "all this functionality is kept inside the device controller itself". And there would still be control directives/commands issued from the device driver to the peripheral.
The hardware device in question should be a computer peripheral device, not an autonomous robot device. The device should be designed to operate with a computer. Whatever interface there is between processor and device should be suitable for the task. If the peripheral is made more "intelligent", then perhaps the CPU can be unburdened and a high-level command interface can replace low-level sub-operation directives. But only "some" functionality can be transferred to the peripheral, not "all".

Resources