Building a small Go program for MIPS with no hardware floating point (softfloat required) - go

I have small program written in go that I'm trying to cross compile to get working on a MIPS architecture machine. I've been trying to cross compile using the XGO cross compilation library but have had limited success getting my program to run (https://github.com/karalabe/xgo).
Here is the cpuinfo of the device, which is currently running a version of openwrt.
system type : Qualcomm Atheros QCA9533 ver 2 rev 0
machine : GL.iNet GL-AR750
processor : 0
cpu model : MIPS 24Kc V7.4
BogoMIPS : 432.53
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa : mips1 mips2 mips32r1 mips32r2
ASEs implemented : mips16
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
Running the program I get a SIGILL Illegal instruction from the following:
Program terminated with signal SIGILL, Illegal instruction.
#0 0x008274a8 in __sigsetjmp_aux ()
I can see that __sigsetjmp_aux() is defined here
/usr/lib/gcc-cross/mips-linux-gnu/5/../../../../mips-linux-gnu/lib/../lib/libc.a(setjmp_aux.o): definition of __sigsetjmp_aux
How can I ensure all my dependencies are compiled using SOFTFLOAT ?
I've been passing xgo the following environment variables but it seems GLIBC is not being compiled as soft-float
CC=mips-linux-gnu-gcc-5 CXX=mips-linux-gnu-g++-5 GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=1 CFLAGS=msoft-float
Any help would be appreciated thanks!
EDIT
Here is the asm layout
0x8274a4 <__sigsetjmp_aux+4> addiu gp,gp,-19312 │
>│0x8274a8 <__sigsetjmp_aux+8> sdc1 $f20,56(a0) │
│0x8274ac <__sigsetjmp_aux+12> sdc1 $f22,64(a0)

I had to run Go on MIPS one time, and solved the problem by building the kernel with floating point emulation. It's slow but it works.

In addition to CFLAGS=-msoft-float add CGO_CFLAGS=-msoft-float and CGO_LDFLAGS=-msoft-float. Note that this will only work if you have a soft-float version of libc.a installed; look for /usr/lib/gcc-cross/mips-linux-gnu/5/../../../../mips-linux-gnu/lib/../lib/soft-float/libc.a (I added a soft-float directory at the end).

Related

Compilation failure in cpu_features_get.cc

I'm trying to compile Cobalt and getting errors building cpu_features_get.cc. The specific version I'm building is here: https://github.com/Metrological/cobalt/blob/master/src/starboard/shared/linux/cpu_features_get.cc and it appears to be based on Cobalt 22. I'm building using stbgcc-6.3.18, only Ubuntu 20.04. Sysroot is set to the cross compiler. And I'm building the starboard port at https://github.com/Metrological/cobalt/tree/master/src/third_party/starboard/wpe/brcm/arm, for ARM64.
An example of the error:
cpu_features_get.cc:381:12: error: 'HWCAP_SET_FOR_ARMV8' was not declared in this scope
There follow others, all related to HWCAP #defines.
As far as I can tell, the file defines these values if:
53: #if SB_IS(32_BIT) || defined(ANDROID)
Neither of these is true - I am compiling for ARM64 on Linux.
The code using HWCAP_SET_FOR_ARMV8 and the other missing defines is conditionally compiled as well:
340: #if SB_IS(ARCH_ARM) || SB_IS(ARCH_ARM64)
...
// Construct hwcap bitmask by the feature flags in /proc/cpuinfo
uint32_t ConstructHwcapFromCPUInfo(ProcCpuInfo* cpu_info,
int16_t architecture_generation,
uint32_t hwcap_type) {
if (hwcap_type == AT_HWCAP && architecture_generation >= 8) {
// This is a 32-bit ARM binary running on a 64-bit ARM64 kernel.
// The 'Features' line only lists the optional features that the
// device's CPU supports, compared to its reference architecture
// which are of no use for this process.
SB_LOG(INFO) << "Faking 32-bit ARM HWCaps on ARMv"
<< architecture_generation;
return HWCAP_SET_FOR_ARMV8;
}
...
...
So ARCH_ARM64 is true, and this code is compiled. But the defines are missing because it's not 32-bit. This seems contradictory and to my eyes could never have worked. How is it possible to compile Cobalt for ARM64?

ModelSim: Intel On-Chip Flash IP: Error: (vsim-3033) Instantiation of 'altera_onchip_flash_block' failed

I am getting this vsim error when I'm trying to use an Intel On-Chip Flash IP generated by Quartus. There's an altera_onchip_flash_block.v file in the submodules/rtl folder but it's only hex numbers in it so it's not compilable by ModelSim.
# Time: 0 ps Iteration: 0 Instance: /ufm_testbench/ufm_inst/flash/onchip_flash_0 File: ../../FFB900_UFM/verilog/altera_onchip_flash.v Line: 309
# Searched libraries:
(all my libraries)
The altera_onchip_flash_block gets instantiated in the altera_onchip_flash.v as seen above.
When I'm only compiling the IP it's working but when I'm using it from my Top-Level testbench I always get this error. I am using VHDL in all my files, except the verilog files generated by quartus.
Any help is appreciated.
As you already realized, this is a precompiled IP-Core. Normally these precompiled IP-Cores come with files for simulation.
This pdf includes a step-by-step tutorial to instantiate the IP-Core and generate simulation files with Quartus (on page 12 of 36 or section 4-2).

How to read PMC(Performance Monitoring Counter) of x86 intel processor

My desktop is Intel x86_64 processor with Ubuntu operating system.
I know there is perf tool to get a list of statistics of a program.
But what I am trying to do is read performance counter directly without using the perf tool.
First Question
First Questions is I downloaded this code from Github: Github Code Reference.
It compiled successfully with linux-headers-5.3.0-40-generic kernel without any errors. Once I use "insmod" the .ko file, the system hangs. The .ko file is not inserted when I checked the dmesg, so I have to cease it after I do "insmod" the .ko file. Does it happen because I attempted unauthorized access? If there are suggestions that I can try, I am glad to hear that.
The corresponding code is below.
static void set_pce(void *arg)
{
int to_val = (arg != 0);
u_int64_t cr4_val;
cr4_val = __read_cr4();
if (to_val) {
cr4_val |= X86_CR4_PCE;
} else {
cr4_val &= ~X86_CR4_PCE;
}
__write_cr4(cr4_val);
}
static int __init user_rdpmc_init(void){
int cpu;
num_cpus = num_online_cpus();
printk(KERN_INFO "Enabling RDPMC from ring 3 for %d CPUs\n", num_cpus);
for (cpu = 0; cpu < num_cpus; cpu++) {
smp_call_function_single(cpu, set_pce, (void *) 1, 1);
}
return 0;
}
Second Question
Second question is I am using linux-headers-5.3.0-40-generic kernel version in my Ubuntu desktop. I downloaded kernel code version 5.5.3 from kernel.org. I followed the perf code given in the 5.5.3 kernel code thoroughly and discovered that core.c file under linux-5.5.3/arch/x86/events/intel directory actually does setting and reading the performance counters. I used the core.c file contents to make it as a module to read the performance counter. When I compile it, it creates a bunch of errors because I use linux-headers-5.3.0-40-generic to build the module but my ubuntu kernel doesn't have all header files linked to the core.c file from kernel code from kernel.org.
How can I make my Ubuntu kernel use all the files linked to core.c from kernel.org and build the .ko file?
Or Is there any module source code that has x86 performance counter reading that I can use as a reference?
Thank you for your help in advance.
I know there is perf tool to get a list of statistics of a program. But what I am trying to do is read performance counter directly without using the perf tool.
If you do not want to use perf tool, you can try to use oprofile tool or intel vtune or https://github.com/RRZE-HPC/likwid or https://github.com/opcm/pcm. Or you can use perf_event_open syscall which is how perf tool works (you can study or modify perf tool sources from https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf/ - and perf tool version may not be equal to kernel version).
If you want to access msr registers as root, use modprobe msr (this is standard kernel module, already compiled for your kernel in ubuntu) and wrmsr and rdmsr tools (msr-tools deb/ubuntu package, by intel), like in slide 27 of Performance Monitoring Chris Dahnken Intel SSG EMEA HPCTC presentation.
I don't understand why do you want to work with performance counters without perf tool. If you want to get counter readings from inside of your program, for example before and after some loops, you can use perf_event_open syscall (with specific ioctls) directly. (Or try to use perf stat + same ioctls PERF_EVENT_IOC_* or try to learn perf + JIT integration)
Or you can use existing kernel module which will export msr register access to root user - the msr.ko. And msr tools - https://01.org/msr-tools. Or with this msr+pmc example https://technicalandstuff.wordpress.com/2015/05/15/using-intels-pcm-in-linux-and-inside-c/ + https://software.intel.com/en-us/articles/intel-performance-counter-monitor (https://github.com/opcm/pcm)
There are also some examples of perf counters usage in https://github.com/RRZE-HPC/likwid.
You can also use PAPI library to access counters from your code, it will handle most of perf_event_open stuff for you. http://icl.cs.utk.edu/projects/papi/wiki/PAPITopics:Getting_Started
First Questions is I downloaded this code https://github.com/softdevteam/user_rdpmc ... "insmod" the .ko file, the system hangs.
There are too low "Stars" rating and the code is too old (2016) to really doing any investigations on the hang. Direct access of PMC may interfere with NMI watchdog (do echo 0 > /proc/sys/kernel/nmi_watchdog as root) or other perf session. It is safer to use perf_event_open syscall.
Second question ... discovered that core.c file under linux-5.5.3/arch/x86/events/intel directory actually does setting and reading the performance counters
This file is part of perf_event_open syscall implementation (perf_events subsystem of the kernel, https://github.com/torvalds/linux/tree/master/kernel/events + https://github.com/torvalds/linux/tree/master/arch/x86/events).
To use this code you can use the perf tool or perf_event_open syscall.
You should not compile the perf_events subsystem of the kernel as separate module because it is already compiled into your kernel (intel/amd specific part can be partially ko) and the Subsystem itself does not support compilation as module:
https://github.com/torvalds/linux/tree/master/kernel/events
Makefile: obj-y := core.o ring_buffer.o callchain.o
How can I make my Ubuntu kernel use all the files linked to core.c from kernel.org and build the .ko file?
Your ubuntu kernel already have all perf_events subsystem files compiled, some are linked into the kernel image and other are .ko files already installed like intel-rapl-perf.ko
$ grep _PERF_ /boot/config-`uname -r`
$ ls -l /lib/modules/`uname -r`/kernel/arch/x86/events/intel

Linux debugging with Jtag - [ARM9][AT91SAM9G25] - Amontec, openocd, gdb, eclipse

I'm trying to start kernel debugging with this sytem:
Amontec JTAGkey2, openocd, gdb, eclipse.
At the end I would like to debug kernel and application that is running within.
I have few problems, and it seems that I need to solve them sequently.
Now I have CPU suspend/resume, read/write RAM
What is missing: Step into, Step over, C/C++ Level debugging.
I do following:
- Connect JTAG, Power up board, start uImage with Debug messages via Uboot
- start openocd:
# openocd -f /usr/share/openocd/scripts/interface/jtagkey2.cfg -f /usr/share/openocd/scripts/board/at91sam9g20-ek.cfg
Output:
jtag_nsrst_delay: 200
jtag_ntrst_delay: 200
RCLK - adaptive
TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr
---|--------------------|---------|------------|------------|------|------|------|---------
0 | at91sam9g20.cpu | Y | 0x00000000 | 0x0792603f | 0x04 | 0x01 | 0x0f | 0x0f
Info : max TCK change to: 30000 kHz
Info : RCLK (adaptive clock speed)
Info : JTAG tap: at91sam9g20.cpu tap/device found: 0x0792603f (mfg: 0x01f, part: 0x7926, ver: 0x0)
Info : Embedded ICE version 6
And problems starts here:
openocd:
Warn : acknowledgment received, but no packet pending
undefined debug reason 6 - target needs reset
Warn : target not halted
eclipse:
symbol-file /opt/Tixi_Repos/KiwiG6v2/buildroot-2011.05/package_tixi/linux-2.6.39/arch/arm/boot/compressed/vmlinux
target remote localhost:3333
start () at arch/arm/boot/compressed/head.S:108
108 kphex r5, 8 /* end of kernel */
It seems also that JTAG is trying to load the code into 0x0, what is incorrect I suppose:
Update 1:
After analyzing some online tutorials for ARM:
Eclipse Reset and Halt commands doesn't work perfect. It is better to uncheck them and write into command window. Also load address can be add:
monitor halt
load arch/arm/boot/compressed/vmlinux 0x22000000
I don't use
monitor reset
I let Uboot start and initialize RAM and other peripherals. Then I stop Uboot by getting into shell. Then I let eclipse write linux into RAM, and start it. It takes very long, but works bit better. Kernel starts and stopps on RPC initialization without giving console back.
would it be possible to load kernel into RAM within Uboot console, and start JTAG session afterwards ?
What is the difference between [load ...] and [monitor load...] commands
Why do I need to load /compressed/vmlinux instead of uImage ?
in eclipse window I have two load fields: load image i load symbol. I disable both options but write only load arch/arm/boot/compressed/vmlinux 0x22000000. Is it maybe the reason for next problems ?
Update 2:
Ok. Thank you for hints.
I've made some progress. Could you give me some advices, maybe I'm still doing something wrong.
Now my kernel runs under JTAG control, but I still can't debug on source code level.
I do as follows:
Power up the board, go into uboot shell.
start openOCD session
Set Uboot breakpoint in bootm.c on theKernel call:
cleanup_before_linux ();
theKernel (0, machid, bd->bi_boot_params);
start eclipse debug session :
monitor halt
load uboot-a without offset
load u-boot-2010.06/u-boot
Loading section .text, size 0x349ec lma 0x26f00000
start uboot and let it run
uboot stopps on "theKernel" call
I know that kernel is located on address 0x20008000.
restart openOCD session
start ecipse debugger once more with kernel configuration:
monitor halt
load kernel on address 0x20008000
load arch/arm/boot/compressed/vmlinux 0x20008000
Loading section .text, size 0x8bdc7c lma 0x20008000
start debugg session
Everything works fine now, and kernel starts, but I still can't debug on source code level.
"symbol is not available"
DEBUG and DEBUG_INFO are on for kernel.
vmlinux screenshot
What seems starnge for me that there are around 50 function symbols in this file.

Debug Linux kernel pre-decompression stage

I am trying to use GDB to debug a Linux kernel zImage before it is decompressed. The kernel is running on an ARM target and I have a JTAG debugger connected to it with a GDB server stub. The target has to load a boot loader. The boot loader reads the kernel image from flash and puts it in RAM at 0x20008000, then branches to that location.
I have started GDB and connected to the remote target, then I use GDB's add-symbol-file command like so:
add-symbol-file arch/arm/boot/compressed/vmlinux 0x20008000 -readnow
When I set a breakpoint for that address, it does trap at the correct place - right when it branches to the kernel. However, GDB shows the wrong line from the source of arch/arm/boot/compressed/head.S. It's 4 lines behind. How can I fix this?
I also have tried adding the -s section addr option to add-symbol-file with -s .start 0x20008000; this results in exactly the same problem.
There are assembler macros that print out stuff when compiling with low level debug. You have to make sure the macros are appropriate for your board.
linux-latest/arch/arm$ find . -name debug-macro.S | wc
56 56 2306
Find the file for your board and ensure the correct serial port registers are hit. You can instrument the code with out using JTAG. These macros are used in the decompress code. Of course configure with *CONFIG_DEBUG_LL*.
Most likely the ATAGs are not correct or one of the other requirements. Checkout Documentation/arm/Booting to make sure you have registers set properly. Note there is a new requirement with recent kernels to send a dt list.

Resources