XDP offloaded mode flags set is not working with bcc - bpf

I'm trying to run this tutorial XDP code that is provided in the bcc.
The code I use is this script: bcc/examples/networking/xdp/xdp_drop_count.py.
and to my understanding, XDP flag works as follows (from that question):
#define XDP_FLAGS_SKB_MODE (1U << 1)
#define XDP_FLAGS_DRV_MODE (1U << 2)
#define XDP_FLAGS_HW_MODE (1U << 3)
So, doesn't this mean that if I change the flags bit to
flags |= 1 << 3
I should be able to run this code in hardware accelerated mode (offloaded)?
I have a NIC card that supports XDP HW accelerated mode and it works fine when I just attach a simple program with only one line of code:
return XDP_PASS;
and attach it in offloaded mode by using ip link set dev interface xdpoffload etc.
So I have confirmed my NIC is capable of loading an offloaded XDP program but when I try the above, it gives me an error:
bpf: Attaching prog to enp4s0np1: Invalid argumentTraceback (most recent call last) :
File "xdp_drop_count.py", line 132, in <module>
b. attach_xdp(device, fn, flags)
File "usr/lib/python2.7/dist-packages/bcc/__init__.py", line 723, in attach_xdp % (dev, errstr))
Exception : Failed to attach BPF to device enp4s0np1: No such file or directory
Also, when I set the flags to :
flags |= 1 << 2
I am not sure if this is actually running the XDP program in driver mode.
Am I missing something?
Thank you in advance.

If you build bcc from sources
Since commit d147588, bcc has hardware offload support. To offload programs using bcc, you will need three things:
The XDP_FLAGS_HW_MODE bit (1U << 3) should be set in the flags passed to attach_xdp().
The name of the interface to which you want to offload the program should be given to BPF() with the device= parameter. It will allow bcc to offload the maps to the appropriate device. It is unnecessary if you don't have maps.
The interface's name should also be given to load_func, again with parameter device=, such that bcc tells the kernel where to offload the program.
Note that, with the latest bcc sources, the xdp_drop_count.py script has been updated to do all this for you when you pass the -H option:
sudo ./xdp_drop_count.py -H $ETHNAME
For older versions of bcc
Older versions of bcc do not support hardware offload. You can use bpftool or ip (>v4.16) instead, e.g.:
sudo ip link set dev $ETHNAME xdpoffload obj prog.o sec .text
sudo bpftool prog load prog.o /sys/fs/bpf/prog type xdp dev $ETHNAME

For a BPF program to be attached as a XDP program, it needs to be offloaded to the NIC first, when being loaded on the system.
In your case, the b.load_func() provided by bcc does not support any option for offloading programs when passing them to the kernel. So when you later call b.attach_xdp() with the XDP_FLAGS_HW_MODE, the function fails, because it cannot find any program offloaded on the NIC.
Right now there is no workaround for offloading program with bcc. As pchaigno mentioned, the function simply does not offer an option to indicate the program should be offloaded.
It should not be too difficult to add support for offloading programs to bcc though, so it should probably be available in the future (especially if pchaigno feels like adding it :p). You would still need to replace the per-CPU array by a regular array in your program, as the former is not supported for offload at this time.
Regarding the mode in which your programs run, this is something you can check with bpftool net for example.

Related

How to get U-Boot to Load and Run a Bare-Metal Binary on the Raspberry Pi 3 Model B+? [closed]

Closed. This question is not about programming or software development. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 days ago.
Improve this question
I have a Raspberry Pi Model 3B+. Currently, I can successfully load this exact kernel8.img file (which is just a raw binary) from this tutorial bare metal following the instructions outlined in the tutorial's README as shown below:
... you can download a raspbian image, dd it to the SD card, mount it and delete the unnecessary .img files. Whichever you prefer. What's important, you'll create kernel8.img with these tutorials which must be copied to the root directory on the SD card, and no other .img files should exists there.
The serial output after the above kernel8.img is running successfully looks something like this:
EMMC: GPIO set up
EMMC: reset OK
sd_clk divisor 00000068, shift 00000006
EMMC: Sending command 00000000 arg 00000000
EMMC: Sending command 08020000 arg 000001AA
EMMC: Sending command 37000000 arg 00000000
EMMC: Sending command 29020000 arg 51FF8000
EMMC: CMD_SEND_OP_COND returned VOLTAGE CCS 0000000040F98000
...
However, I would like to load that kernel8.img file via U-Boot and TFTP so that I don't have to keep plugging/unplugging microSD cards.
I have a functioning TFTP server and I have loaded U-Boot onto the Raspberry Pi successfully.
The physical address the kernel image gets loaded to bare metal is 0x80000 as explained by the tutorial:
Important note, for AArch64 the load address is 0x80000, and not 0x8000 as with AArch32.
The kernel8.img's file-type is also just a raw binary:
$ file kernel8.img
kernel8.img: data
As such, I've run the following two U-Boot commands:
tftp 0x80000 rpi3bp/kernel8.img
go 0x80000
However, as shown below, I'm getting some garbled mess once the binary is running: ��ogK�S��rK.
...
U-Boot> tftp 0x80000 rpi3bp/kernel8.img
lan78xx_eth Waiting for PHY auto negotiation to complete........ done
Using lan78xx_eth device
TFTP from server 192.168.0.198; our IP address is 192.168.0.111
Filename 'rpi3bp/kernel8.img'.
Load address: 0x80000
Loading: ################################################## 6.6 KiB
603.5 KiB/s
done
Bytes transferred = 6808 (1a98 hex)
U-Boot> go 0x80000
## Starting application at 0x00080000 ��ogK�S��rK
According to this SO post (as shown below), the go command is all that is required to get a bare-metal binary running on U-boot.
If you have issues executing your binary when using the go command,
then the problem lies with your program, e.g. taking control of the
processor and initializing its C environment.
However, I know for a fact that the kernel image runs fine bare-metal using the Raspberry Pi's default bootloader. So what could be the issue here and why can't I seem to get that kernel image running via U-Boot?
Edit 1:
Here's some context on how I set up U-Boot on the Raspberry Pi. Currently, the Raspberry Pi's bootloader is booting U-Boot in 64-bit mode. The Raspberry Pi's bootloader is configured via the config.txt file and below is my config.txt file:
enable_uart=1
arm_64bit=1
kernel=u-boot.bin
Documentation on the arm_64bit option is here:
arm_64bit
If set to non-zero, forces the kernel loading system to assume a
64-bit kernel, starts the processors up in 64-bit mode, and sets
kernel8.img to be the kernel image loaded, unless there is an explicit
kernel option defined in which case that is used instead. Defaults to
0 on all platforms.
The issue is related to the fact that U-Boot uses UART1 on the Raspberry Pi and the binary I'm trying to run uses UART0 as explained by #sawdust below:
Per U-Boot's DT, it appears that U-Boot uses UART1 on gpios 14&15. The
standalone uses UART0 on the same gpios. So that explains both (a)
getting output from two programs on same pin, and (b) why removing
uart_init() failed. Since U-Boot sets up UART0 for Bluetooth, perhaps
the standalone does not expect that; hence a goofy baudrate. An
oscilloscope could easily verify that.
I know this to be true because I modified the code in uart.c to use UART1 instead and I can now see sensible serial output now.
However, it is still unclear to me why despite the seemingly valid initialisation of UART0 in this part of the code, UART0 does not seem to output legible characters at the right baud rate.

SIM7020E NB-Iot module does not respond to AT commands

I am using a RPi Pico, a NB-IoT SIM7020E Module from Waveshare and a Twilio Super SIM card. I fitted the Raspberry Pi Pico into the SIM7020E module using header pins: a picture of the setup is given through this link (Picture 1: Hardware setup).
To send different AT commands to configure the modem and set up the APN, I used Micro Python and copy pasted the Python code into Putty (after doing ctrl C, ctrl E and ctrl D to run the code). The main functions I utilised to send AT commands are “uart.write”, “uart.any” and “uart.read”. I have copy-pasted a portion of the code here:
#Send an AT command - just return the response
def send_at_get_resp(cmd, timeout=1000):
# Send the AT command
uart.write((cmd + "\r\n").encode())
# Read and return the response (until timeout)
return read_buffer(timeout)
#Read in the buffer by sampling the UART until timeout
def read_buffer(timeout):
buffer = bytes()
now = ticks_ms()
while (ticks_ms() - now) < timeout and len(buffer) < 1025:
if uart.any(): # check if there is anything to be read
buffer += uart.read(1) # read 1 characters, returns a bytes object
return buffer.decode()
#Send an AT command - return True if we got an expected otherwise False
def send_at(cmd, back="OK", timeout=1000):
# Send the command and get the response (until timeout)
buffer = send_at_get_resp(cmd, timeout)
if len(buffer) > 0:
return True
else:
return False
send_at("AT")
send_at("ATE1")
The issues I have with the code are that:
After sending an AT command (“AT” and “ATE1”), uart.read reads ‘b\x00’ and not the AT command. It looks like the SIM7020E module does not receive the AT command and does not respond to it (I should receive the response “OK”).
The “Read_buffer” function (see code below in picture 2) that reads the command in the buffer by sampling the UART returns an empty string.
Before sending the AT commands, I powered the module on and off to boot the modem using the Pin(14) of the SIM7020E module. When powered on, the module’s LED switches on so I know that my python code can communicate correctly and that the problem occurs for AT commands only.
Alternative 1:
I have tried typing AT commands ("AT" and "ATE1") directly on Putty (I did not hit Ctrl-C to break to the Python REPL), but I received an error message saying that Putty does not recognise the AT command (Picture 2: error with Putty)
Alternative 2:
I also tried using an AT command tester for Simcom modules from the website https://m2msupport.net/m2msupport/download-at-command-tester-for-simcom-modules/, but the software was unable to connect to the USB port (Picture 3: error from the AT command tester). It recognised the port but could not connect to it. The software asked me to try other baud rates and to enable flow control, so I tried all the possible different baud rates, and it did not work. For the flow control, I did not know how to configure it.
I do not understand why the module does not recognise the AT commands despite the other alternatives I tried and if it comes from a hardware or a software related problem. Do you know how I can make my module respond to AT commands?
It doesn't look like you are using the right serial interface in Putty. When you send your AT commands directly in Putty what is the COM5 port? It should be the COM port that shows up under the modem in the device manager.

AArch64 - GNU ld - multiple linker scripts (for kernel and userland)

I have started a bare-metal application for AArch64. The bare-metal application should implement a simple kernel (for memory/device management and exception handling) and an userland which can made syscalls to output something over the UART via printf() as example. Currently I'm working on the kernel at EL1. The indent is to put kernel and userland in a single ELF binary, because I don't have implemented an filesystem driver and ELF support yet.
The kernel should reside at address 0xC0000000 and the main application (userland) at 0x40000000 as example. But I will change this addresses later. Is it possible to pass two linker scripts to GNU ld? I realize that I must use different sections for kernel and userland.
Or in another question:
Is my indent even possible? Okay it's maybe a generic question, but currently didn't find a similar question here.
From the LD manual: https://man7.org/linux/man-pages/man1/ld.1.html, it's said:
Multiple -T options accumulate.
Just use it like this: -T script1.ld -T script2.ld

Determining the library which causes "Illegal instruction" on a Pi Zero W (armv6), and fixing the build

I understand that a lot of compilation issues on the Pi Zeros are due to the fact that they use armv6, whereas the newer Raspberry Pi's like the 3 A+ and B+ use armv7. However, I do not understand how to find the offending library in an application that is causing the issue, and if there is perhaps a simple fix for the problem.
Background:
I am trying to port an application from a Linux Desktop environment to the Pi Zero (running armv6). I successfully ported it to the Pi 3 B and B+. That is, I compiled the code, and checked that it is producing the correct output.
However, the Pi Zero implementation compiles, but just spits out a single message when run:
Illegal instruction
This is most likely due to some command that is not compatible with armv6, but I cannot figure out which command that is. I would like to start by determining which library is the problem child. Please tell me how I would diagnose that.
Extra Info:
I have checked that the compiler is not the issue. How? I made a simple hello world program, and compiled it for the Pi Zero:
#include<iostream>
int main(int argc, char *argv[]){
std::cout << "Hello World!" << std::endl;
return 0;
}
So the compiler itself doesn't seem to be the issue.
More details:
If I run readelf -A myapp, my understanding is that the output is reporting that the app is indeed compiled for armv6:
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "6"
Tag_CPU_arch: v6
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_FP_arch: VFPv2
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_rounding: Needed
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_VFP_args: VFP registers
Tag_CPU_unaligned_access: v6
Here is the readelf -A for one of the shared libraries:
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "6"
Tag_CPU_arch: v6
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_FP_arch: VFPv4
Tag_Advanced_SIMD_arch: NEONv1 with Fused-MAC
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_HardFP_use: Deprecated
Tag_ABI_VFP_args: VFP registers
Tag_CPU_unaligned_access: v6
To identify a fault such as Illegal instruction you can run the program under a debugger capable of interacting with the operating system's fault handler.
On a Linux system such as the pi, that would be gdb. You may need to install this, on a debian-derived distribution that would be sudo apt-get install gdb
Then run your program
gdb myprog
or if your program needs command line arguments
gdb myprog --args some_argument another_argument
Once gdb starts up type run, and the program will execute near normally until it reaches the illegal instruction, at which point you will be dumped back at the gdb prompt with a hopefully informative error message.
There you can explore with commands such as backtrace or if the programmer has associated source, list. If the fault is at an address gdb can see as being mapped as from a file it should show you that - you can also get at the mapping information via the gdb command info files or by looking in /proc/[PID]/maps
If for some reason you can't run the program live under gdb, you can research how to enable core dumps for your system, and then load the program and the core dump into gdb for post-mortem analysis.
Depending on system configuration, if running the program on its own without a debugger, you may also see information about the fault in the output of dmesg or another system log.
i have simple answer just press up button and try
rpi0 can run all programs if you have armel
see here its a rpi0 os build script build a minimal os on based on armel architecture
https://gitlab.com/kalilinux/build-scripts/kali-arm
how i solved i tried to run java on raspbian os it did not worked i used kali for raspberry pi zero java was running
so use armel arch

STM32 GDB/OpenOCD Commands and Initialization for Flash and Ram Debugging

I am looking for assistance with the proper GDB / OpenOCD initializion and running commands (external tools) to use within Eclipse for flash and RAM debugging, as well as the proper modifications or additions that need to be incorporated in a makefile for flash vs RAM building for this MCU, if this matters of course.
MCU: STM32F103VET6
I am using Eclipse Helios with Zylin Embedded CDT, Yagarto Tools and Bins, OpenOCD 0.4, and have an Olimex ARM-USB-OCD JTAG adapter.
I have already configured the ARM-USB-OCD and added it as an external tool in Eclipse. For initializing OpenOCD I used the following command in Eclipse. The board config file references the stm32 MCU:
openocd -f interface/olimex-arm-usb-ocd-h.cfg -f board/stm32f10x_128k_eval.cfg
When I run this within Eclipse everything appears to be working (GDB Interface, OpenOCD finds the MCU, etc). I can also telnet into OpenOCD and run commands.
So, I am stuck on the next part; initialization and commands for flash and RAM debugging, as well as erasing flash.
I read through several tutorials, and scoured the net, but have not been able to find anything particular to this processor. I am new to this, so I might not be recognizing an equivalent product for an example.
I'm working with the same tool chain to program and debug a STM32F107 board. Following are my observations to get an STM32Fxxx chip programmed and debugged under this toolchain.
Initial Starting Point
So at this point you've got a working OpenOCD to ARM-USB-OCD connection and so you should be all set on that end. Now the work is on getting Eclipse/Zylin/Yagarto GDB combination to properly talk to the STM32Fxxx through the OpenOCD/Olimex connection. One thing to keep in mind is that all the OpenOCD commands to issue are the run mode commands. The configuration scripts and command-line options to invoke the OpenOCD server are configuration mode commands. Once you issue the init command then the server enters run mode which opens up the set of commands you'll need next. You've probably done it somewhere else but I tack on a '-c "init"' option when I call the OpenOCD server like so:
openocd -f /path to scripts/olimex-arm-usb-ocd-h.cfg -f /path to targets/stm32f107.cfg -c "init"
The following commands I issue next are done by the Eclipse Debug Configurations dialogue. Under the Zylin Embedded debug (Native) section, I create a new configuration, give it a name, Project (optional), and absolute path to the binary that I want to program. Under the Debugger tab I set the debugger to Embedded GDB, point to the Yagarto GDB binary path, don't set a GDB command file, set GDB command set to Standard, and the protocol to mi.
The Commands Tab - Connect GDB to OpenOCD
So the next tab is the Commands tab and that's where the meat of the issue lies. You have two spaces Initialize and Run. Not sure exactly what the difference is except to guess that they occur pre- and post-invocation of GDB. Either way I haven't noticed a difference in how my commands are run.
But anyway, following the examples I found on the net, I filled the Initialize box with the following commands:
set remote hardware-breakpoint limit 6
set remote hardware-watchoint-limit 4
target remote localhost:3333
monitor halt
monitor poll
First two lines tell GDB how many breakpoints and watchpoints you have. Open OCD Manual Section 20.3 says GDB can't query for that information so I tell it myself. Next line commands GDB to connect to the remote target at the localhost over port 3333. The last line is a monitor command which tells GDB to pass the command on to the target without taking any action itself. In this case the target is OpenOCD and I'm giving it the command halt. After that I tell OpenOCD to switch to asynchronous mode of operation. As some of the following operations take a while, it's useful not to have OpenOCD block and wait for every operation.
Sidenote #1: If you're ever in doubt about the state of GDB or OpenOCD then you can use the Eclipse debug console to send commands to GDB or OpenOCD (via GDB monitor commands) after invoking this debug configuration.
The Commands Tab - Setting up the User Flash
Next are commands I give in the Run commands section:
monitor flash probe 0
monitor flash protect 0 0 127 off
monitor reset halt
monitor stm32x mass_erase 0
monitor flash write_image STM3210CTest/test_rom.elf
monitor flash protect 0 0 127 on
disconnect
target remote localhost:3333
monitor soft_reset_halt
to be explained in the following sections...
Setting up Access to User Flash Memory
First I issue an OpenOCD query to see if it can find the flash module and report the proper address. If it responds that it found the flash at address 0x08000000 then we're good. The 0 at the end specifies to get information about flash bank 0.
Sidenote #2: The STM32Fxxx part-specific data sheets have a memory map in section 4. Very useful to keep on hand as you work with the chip. Also as everything is accessed as a memory address, you'll come to know this layout like the back of your hand after a little programming time!
So after confirming that the flash has been properly configured we invoke the command to turn off write protection to the flash bank. PM0075 describes everything you need to know about programming the flash memory. What you need to know for this command is the flash bank, starting sector, ending sector, and whether to enable or disable write protection. The flash bank is defined in the configuration files you passed to OpenOCD and was confirmed by the previous command. Since I want to disable protection for the entire flash space I specify sectors 0 to 127. PM0075 explains how I got that number as it refers to how the flash memory is organized into 2KB pages for my (and your) device. My device has 256KB of flash so that means I have 128 pages. Your device has 512KB of flash so you'll have 256 pages. To confirm that your device's write-protection has been disabled properly, you can check the FLASH_WRPR register at address 0x40022020 using the OpenOCD command:
monitor mdw 0x40022020
The resulting word that it prints will be 0xffffffff which means all pages have their write protection disabled. 0x00000000 means all pages have write protection enabled.
Sidenote #3: On the subject of the memory commands, I bricked my chip twice as I was messing with the option bytes at the block starting at address 0x1ffff800. First time I set the read protection on the flash (kind of hard to figure out what your doing if you do that), second time I set the hardware watchdog which prevented me from doing anything afterwards since the watchdog kept firing off! Fixed it by using the OpenOCD memory access commands. Moral of the story is: With great power comes great responsibility.... Or another take is that if I shoot myself in the foot I can still fix things via JTAG.
Sidenote #4: One thing that'll happen if you try to write to protected flash memory is the FLASH_SR:WRPRTERR bit will be set. OpenOCD will report a more user-friendly error message.
Erasing the Flash
So after disabling the write protection, we need to erase the memory that you want to program. I do a mass erase which erases everything, you also have the option to erase by sector or address (I think). Either way you need to erase first before programming as the hardware checks for erasure first before allowing a write to occur. If the FLASH_SR:PGERR bit (0x4002200c) ever gets set during programming then you know you haven't erased that chunk of memory yet.
Sidenote #5: Erasing a bit in flash memory means setting it to 1.
Programming Your Binary
The next two lines after erasure writes the binary image to the flash and reenables the write protection. There isn't much more to say that isn't covered by PM0075. Basically any error that occurs when you issue flash write_image is probably related to the flash protection not being disabled. It's probably NOT OpenOCD though if you're curious you can take enable the debug output and follow what it does.
GDB Debugging
So finally after programming I disconnect GDB from the remote connection and then reconnect it to the target, do a soft-reset, and my GDB is now ready to debug. This last part I just figured out last night as I was trying to figure out why, after programming, GDB wouldn't properly stop at main() after reset. It kept going off into the weeds and blowing up.
My current thinking and from what I read in the OpenOCD and GDB manuals is that the remote connection is, first and foremost, meant to be used between GDB and a target that has already been configured and running. Well I'm using GDB to configure before I run so I think the symbol table or some other important info gets messed up during the programming. The OpenOCD manual says that the server automatically reports the memory and symbols when GDB connects but all that info probably becomes invalid when the chip gets programmed. Disconnecting and reconnecting I think refreshes the info GDB needs to debug properly. So that has led me to create another Debug Configuration, this one just connects and resets the target since I don't necessarily need to program the chip every time I want to use GDB.
Whew! Done! Kind of long but this took me 3 weekends to figure out so isn't too terribly bad I think...
Final sidenote: During my time debugging I found that OpenOCD debug output to be invaluable to me understanding what OpenOCD was doing under the covers. To program a STM32x chip you need to unlock the flash registers, flip the right bits, and can only write a half-word at a time. For a while I was questioning whether OpenOCD was doing this properly but after looking through the OpenOCD debug output and comparing it against what the PM0075 instructions were, I was able to confirm that it did indeed follow the proper steps to do each operation. I also found I was duplicating steps that OpenOCD was already doing so I was able to cut out instructions that weren't helping! So moral of the story: Debug output is your friend!
I struggled getting JLink to work with a STM3240XX and found a statement in the JLink GDB server documentation saying that after loading flash you must issue a "target reset":
"When debugging in flash the stack pointer and the PC are set automatically when the target is reset after the flash download. Without reset after download, the stack pointer and the PC need to be initialized correctly, typically in the .gdbinit file."
When I added a "target reset" in the Run box of the debugger Setup of Eclipse, suddenly everything worked. I did not have this problem with a Kinetis K60.
The document also explains how to manually set the stack pointer and pc directly if you don't want to issue a reset. It may not be the disconnect/connect that solves the problem but the reset.
What i use after the last sentence in the Comannd Tab - 'Run' Commands, is:
symbol-file STM3210CTest/test_rom.elf
thbreak main
continue
The thbreak main sentence is what makes gdb stop at main.