How to load vfio driver before ahci driver with mkinitcpio? - vfio

Good morning all,
I'd want to attach to vfio driver at boot my secondary sata controller in a manjaro os (kernel 5.16.7).
Usually, I add the devices in /etc/modprobe.d/vfio.conf, for example:
options vfio-pci ids=10de:100c,10de:0e1a,1b4b:9230,15b3:6274,1106:3403
In this example, there is gpu audio and video (10de), the sata controller (1b4b), an infiniband card (15b3) and firewire (1106).
Then, I add the modules in /etc/mkinitcpio.conf:
MODULES=(vfio_pci vfio vfio_iommu_type1 vfio_virqfd)
making sure that modconf is in the HOOKS:
HOOKS=(modconf base udev autodetect block filesystems keyboard)
Finally I generate initramfs:
mkinitcpio -P
All quite good, devices are attached to vfio, except for the sata controller, which is attached to the ahci driver (if not in use by some vm).
If I start the kvm vm with the sata controller set to be passed through, vfio driver attaches to it, but that's not what I'd want: the goal is to attach that sata controller to vfio at boot (not attaching it to vfio "on the fly").
I found some instructions for other oses, for example here:
https://gist.github.com/kiler129/4f765e8fdc41e1709f1f34f7f8f41706
The op explains that ahci driver loads before vfio, but manjaro uses mkinitcpio and my issue is that I don't understand how to adapt/translate those instructions for my os.

Related

Azure NetX Duo only provides the driver for LAN8742 compatible Ethernet PHYs. How can I manage other Ethernet PHYs?

I'm developing an application for STM32F4 with Azure RTOS Netx Duo. In particular I'm trying to adapt the example Nx_TCP_Echo_Server application for my board where is present the Ethernet Phy ADIN1200 produced by Analog Devices.
Note about example Nx_TCP_Echo_Server
The Nx_TCP_Echo_Server example application has been made for a STM32F429ZI-NUCLEO demo board (code of Nx_TCP_Echo_Server on github).
In the demo board STM32F429ZI-NUCLEO the Ethernet Phy is compatible with the lan8742 driver (see the lan8742 driver code on GitHub). Unfortunately the Ethernet PHY ADIN1200 present on my board is not compatible with that driver.
I have noted that the sixth parameter of the function nx_ip_create() is the pointer function nx_stm32_eth_driver.
This pointer function points to lan8742 driver.
Below I show the invocation of the function nx_ip_create() present in the file app_netxduo.c (code of app_netxduo.c) of the Nx_TCP_Echo_Server example application:
/* Create the main NX_IP instance */
ret = nx_ip_create(&IpInstance, "Main Ip instance", NULL_ADDRESS, NULL_ADDRESS, &AppPool, nx_stm32_eth_driver,
pointer, 2 * DEFAULT_MEMORY_SIZE, DEFAULT_PRIORITY);
The documentation of NetX Duo reports the following info:
The NX_IP structure contains everything to manage a single IP instance. This includes general TCP/IP protocol information as well as the application-specific physical network driver's entry routine. The driver's entry routine is defined during the nx_ip_create service. Additional devices may be added to the IP instance via the nx_ip_interface_attach service.
My development environment
My development environment is composed by:
STM32CubeMX version 6.7.0
In the STM32CubeMX I have installed the Package STM32F4 version 1.27.1
To use ThreadX I have added to CubeMX the software pack X-CUBE-AZRTOS-F4 version 1.1.0
By the previous environment I can find only the driver for LAN8742.
My question
How can I find other Ethernet PHY drivers for NetX Duo other than the one for lan8742?
EDIT
I have found this driver for ADIN1200 but it is very far from the driver lan8742.c provided by my development tool (see the code of lan8742).
In fact the API of the 2 drivers are very different; for example NetX Duo (and before it: LwIP) needs a function like LAN8742_RegisterBusIO() (present in the LAN8742 driver) to init a structure with pointer functions useful to write and read registers of the Ethernet PHY, but in this driver this function and its data structures are not present.
You can find different phy drivers from https://github.com/azure-rtos/samples.
mimxrt1060:KSZ8081RNB
same54:KSZ8091RNA 
stm32f746:LAN8742A-CZ-TR
rx65n rsk:DP83620SQE
For others, you will need to develop the driver by yourself, based on existing ones.

How to find out who loads specific Linux kernel module?

I built a certain driver as module (m) for Linux, the spi-imx by NXP. Nontheless, Linux probes this driver when booting. I'm struggling to find out what process/other module/driver requests this spi-imx driver. A depmod does not show any dependencies between the spi-imx an other modules (except for the spidev as submodule).
After some research, I found out that Linux automatically (?) calls modprobe when it detects a new device. So does Linux actually call modprobe because the ecSPI'S status in the device tree as "okay"? If so, how can I prevent this? I would like to dynamically load the spi-imx from a user space application via modprobe. The story behind it: a coprocessor uses this SPI line in parallel to the Linux boot process. This interferes of course and interrupts the coprocessor's use of the SPI line. When the coprocessor has finished its transfer via SPI (a boot mechanism as well), it should hand over the SPI line to Linux.
I'm very thankful for any kind of tips, links, hints and comments on this.
Thanks a lot for the answers. As you guys mentioned, I also found out that Linux itself probes the device if present ("okay").
One possible solution is to complete cut off the modprobe call via an entry like "install spi-imx /bin/false" in the *.conf file. But that makes it impossible to load the driver via modprobe, for Linux and for user space.
"blacklist spi-imx" inside a *.conf located at /etc/modprobe.d/ is the way to prevent Linux from probing the driver when booting. After that, a modprobe from user space can successfully load the driver afterwards.
Thanks again & best regards

How to use GDB to debug a kernel with custom GDT? (Breakpoints Failed)

I'm using QEMU to emulate a mini OS.
The kernel was linked with the virtual address entry point located at 0xC0100000. (All symbols' addresses in file kernel are higher than 0xC0100000)
After bootloader loaded kernel on the physical address 0x00100000, it setted a global descriptor table which makes so that virtual address space beyond 0xC0100000 is mapped to physical address 0x00100000, then long jumped to the kernel entry point.
When I'm using GDB to debug the kernel, it ignores all breakpoints setted in kernel.
The GDB still assumes my kernel code is located at 0xC0100000, however, kernel code is located at 0x00100000. When I set breakpoints using physical addresses it could hit but raises issues in later execution.
How to make GDB does not ignore the existence of custom GDT?

Bare metal Raspberry Pi 2: Generating an SD card image for QEMU emulation

I've recently been getting into bare metal development for the Raspberry Pi 2, and having some success. Admittedly I've hesitated to buy an actual physical device until I feel I can do something useful with it, for the time being I've been emulating the device using qemu 2.11.0.
So far I've developed multicore capabilities for my kernel, as well as simple Serial I/O, but I feel I'd like to get much further before working with a physical device.
My issue right now is that I'm trying to learn how to place my kernel onto an SD card image and boot qemu-system-arm from that SD card image, so I can properly emulate a kernel loaded from the raspberry pi 2 bootloader.
I've gotten as far as grabbing the SD card contents from https://github.com/raspberrypi/firmware ... aster/boot, and using the following script to create the image and load my kernel into it. I've seen that people have figured out how to load Raspbian from an emulated SD card, so I figure I can do the same.
#!/bin/bash
OUTPUT_IMG=os.img
OUTPUT_IMG_SIZE=40
TEMP_MOUNT_DIR="$(mktemp -d)"
# the SD card boot partition contents are in this folder...
OUTPUT_IMG_CONTENTS_DIR="./sd"
OS_DIR="${HOME}/os"
OS_BINARY="${OS_DIR}/kernel.bin"
dd if=/dev/null of=${OUTPUT_IMG} bs=1M seek=${OUTPUT_IMG_SIZE}
mkfs.fat -F 32 ${OUTPUT_IMG}
sudo mount -t vfat -o loop ${OUTPUT_IMG} ${TEMP_MOUNT_DIR}
make -C ${OS_DIR} clean
make -C ${OS_DIR}
sudo cp -r ${OUTPUT_IMG_CONTENTS_DIR} ${TEMP_MOUNT_DIR}
sudo cp ${OS_BINARY} "${TEMP_MOUNT_DIR}/kernel.img"
The only issue is that qemu doesn't seem to boot from this image using the following command:
qemu-system-arm -machine raspi2 -serial file:serial.log -sd ./dev/os.img
I've tried a few different combinations, but to no avail.
I can see from hooking GDB that the kernel is simply not booting from this card image. Loading the kernel directly into qemu with the -kernel argument works otherwise perfectly.
I was wondering if anyone here had any insight on how to accomplish this!
Any help here would be greatly appreciated!
Your command won't work because you haven't passed QEMU either a guest BIOS or a guest kernel to run. The QEMU arm boards aren't like the x86 PC machine, which always automatically runs a guest BIOS image. If you want to run a BIOS (probably UEFI?) you need to find a suitable BIOS blob and pass it to QEMU with the -bios argument. Then QEMU will run the BIOS code, which will hopefully include SD card drivers to load the kernel and so on off the SD card.
Just using -kernel is much simpler...
After doing a bit of reading and searching online, as well as a bit of help from other contributors such as Peter Maydell with his answer above, I think I've answered my own question. Unless I'm mistaken qemu-system-arm does not fully emulate the Raspberry Pi boot process, and instead just loads the kernel specified with the -kernel argument by loading the binary into the guest system's memory and jumping to the entry point. It doesn't look like any additional hardware bootloading is emualted for -M raspi2 unfortunately.
Can ARM qemu system emulator boot from card image without kernel param?
This question is similar and contains some more useful details on this issue, relating to qemu-system-arm as a whole..

iMX6: MSI-X not working in Linux PCIe device driver

I'm trying to get MSI-X working on an iMX6 (Freescale/NXP/Qualcomm) CPU in Linux v4.1 for a PCIe character device driver. Whenever I call either pci_enable_msix() or pci_enable_msix_range() or pci_enable_msix_exact() I get an EINVAL value returned. I do have the CONFIG_PCI_MSI option selected in the kernel configuration and I am also able to get single MSI working with pci_enable_msi(), but I cannot get multiple MSI working either.
I have tested my driver code on an Intel i7 running kernel v3 with the same PCIe hardware attached and I was able to get MSI-X working without any problems so I know my code is correctly written and the hardware is correctly functioning.
When running on the iMX6 I can use lspci -v to view that the hardware has MSI-X capabilities and see the number of IRQs it allows. I can even get the same correct number in my driver when calling pci_msix_vec_count().Questions
Are there any other kernel configuration flags I need to set?
Is there anything specific to the iMX6 CPU I need to consider?
Does anyone have any experience with the iMX6 and either MSI-X or
multiple MSI?