How to build kernel module for Cortex A8? - arm

I want to compile this code which enables cycles counters on ARM Cortex A8 through Debian OS on target. I wrote this code in /home and want to compile it.
How can i compile it and where should i put the output file?
i am just a beginner in embedded systems,
i tried to follow some links but all failed
i don't actually know the steps to do that because i am not familiar with Linux
Code:
#include <linux/module.h>
#include <linux/kernel.h>
static int OldState;
int __init init_module(void)
{
/* enable user-mode access */
asm ("MCR p15, 0, %0, C9, C14, 0\n\t" :: "r"(1));
/* disable counter overflow interrupts (just in case)*/
asm ("MCR p15, 0, %0, C9, C14, 2\n\t" :: "r"(0x8000000f));
printk(KERN_INFO "user-mode access to performance registers enabled\n");
return 0;
}
void cleanup_module(void)
{
}

You need ARM toolchain (cross-compiler) for this. It will compile sources for ARM architecture on your x86 machine. See this and this.
Once you installed ARM toolchain, provide CROSS_COMPILE environment variable to make (or just do something like export CROSS_COMPILE=arm-none-eabi- in your shell before running make). Kernel build system will use this variable as prefix for tools like gcc, as, ld etc. This way your module will be built for ARM architecture. Use file tool on your module file (.ko) to be sure it was built for ARM.

Related

is there any use of __attribute__ ((interrupt)) for riscv compilers?

we can read here that the interrupt attribute keyword is use for ARM, AVR, CR16, Epiphany, M32C, M32R/D, m68k, MeP, MIPS, RL78, RX and Xstormy16.
does it have any impact on riscv compilation using riscv32-***-elf-gcc compilers?
There is a separate page for RISC-V which claims it works. You can find it here. Also you could probably verify it by compiling code with and without the attribute set.
I don't have riscv32 toolchain installed, but i managed to verify it using the riscv64 toolchain. You should reproduce the same steps using the riscv32 toolchain to make sure it works.
Using a simple test.c file:
__attribute__((interrupt))
void test() {}
Compiling it with riscv64-linux-gnu-gcc -c -o test.o test.c and disassembling with riscv64-linux-gnu-objdump -D -j.text test.o we can see it generates mret instruction at the end of the function:
0: 1141 addi sp,sp,-16
2: e422 sd s0,8(sp)
4: 0800 addi s0,sp,16
6: 0001 nop
8: 6422 ld s0,8(sp)
a: 0141 addi sp,sp,16
c: 30200073 mret
After removing the interrupt attribute the instruction changes to regular ret. According to this SO answer this seems like correct behaviour.
Normally, an interrupt handler requires a different entry/exit sequence than a normal function. The differences focus in the saving of all registers in the interrupt (normally, only some registers are preserved in a normal function call) and the return instruction is normally different (e.g. in the ARM it has to change processor mode of operation, probably this is also true in the RISCV processor)
The interrupt attribute informs the compiler of the routine properties, so it can generate the correct code for it.

ARM ASM: Bad Instruction end

In my current project we are using Segger embOS as an RTOS.
The target system is an ARM Cortex-M MCU
The RTOS has some code written in assembler.
However the ASM code produces an error:
RTOS.s:69: Error: bad instruction `end'
According to the ARM assembler reference guide
http://infocenter.arm.com/help/topic/com.arm.doc.dui0489f/DUI0489F_arm_assembler_reference.pdf
(Chapter 6.8.5) the instruction "END" exists (I'm not sure if assembler is case sensitive)
although this instruction exists, the assembly won't compile.
Each of the includes files terminate with an
.end (note the "." and the lower case letters)
File RTOS.s
#define OS_RTOS_S_INCLUDED
/*******************************************************************
*
* Code section includes selected code
*
********************************************************************
*/
#if (defined __ARM_ARCH_6M__) || (defined __ARM_ARCH_8M_BASE__)
//
// Cortex-M0
//
#include "RTOS_CM0.S"
#elif (defined (__VFP_FP__) && defined (__SOFTFP__))
//
// Cortex-M3 or Cortex-M4 without VFP
//
#include "RTOS_CM3.S"
#elif (defined (__VFP_FP__) && !defined (__SOFTFP__))
//
// Cortex-M4 with VFP
//
#include "RTOS_CM4F.S"
#else
#error "No RTOS.S for selected CPU available, check configuration"
#endif
/********************************************************************/
END//Line 69
/***** End of file ************************************************/
Switch the END to .end seams to resolve the compile error. However the function defined in the assembler script are not found by the linker (this could be different problem though)
So my question is: Why is the instruction END a bad instruction?
The END directive is an armasm directive, not an ARM assembly instruction. That is to say it is an instruction to the assembler during the build of the code, not an instruction to the processor. .end is the GNU as (GNU assembler) equivalent.
Different toolchains use different assembler directives and syntax. You are trying to build the armasm source code using gas (GNU assembler) which is not compatible. You will certainly encounter other issues than this that will prevent you building ARM toolchain specific source code/object with the GNU toolchain - not least, apart from the technical issues, there are legal issues given that embOS licences are toolchain specific.
Each Segger embOS license is provided for a specific toolchain. If you wish to use a different toolchain you will need a new license and different toolchain specific code/library - even if you have a source code licence; it is not just a legal issue but a technical one - Segger do not provide the code for all toolchains with a license for a single toolchain. If you only have an object code licence, it may not link if using a different toolchain (or in some cases even different toolchain version) than the object code was built with.
You need to check, but it is likely that you have a licence for the Keil ARM MDK toolchain (which includes armcc/armasm etc.). It is not a free tool one way or another you need to either purchase an embOS licence for GNU, or licence to the toolchain you have the embOS licence for.
You might do well in any case to update your Segger support and maintenance licence in any case, so you can get technical support from them.

Translation of CUDA inline asm from GAS to Intel

I have some C-CUDA code that contains inline PTX assembly, which compiles OK on Linux with g++ backend.
I need to build it under Windows, and clearly MSVC backend does not recognize inline asm properly - gives errors like "not an asm string". I assume it has to do with syntax this PTX assembly is written, for example:
asm volatile ("subc.cc.u32 %0, %0, "q2_s";": "+r"(c[2]));
asm volatile ("subc.cc.u32 %0, %0, "q3_s";": "+r"(c[3]));
I don't know much about assembly, and am wondering - is there some translator from GAS(at&t) style to Intel syntax?
Or is there some workaround to build CUDA kernels to PTX on Linux, and then build PTX & link to remaining code on Windows?
I've tried that, but PTX compiler on linux gives kernel functions some unrecognizable _Z-starting names and linker does not know how to link the stuff.
Turns out, problem was not with inline asm, but with preprocessing, e.g. for example, asm string
asm volatile ("subc.cc.u32 %0, %0, "q2_s";": "+r"(c[2]));
relied on this define
#define q2_s "0xAF48A03B"
On Linux it compiled without errors, but on Windows gave "expected an asm string" error.
So, workaround for Windows was just to hardcode hex values in asm strings, and it has nothing to do with assembly syntax, sorry for misguiding.

Read the value of a cpu control register from admin privilege app (Windows)

I am trying to read data from a cpu control register using inline assembly. Im initially targeting x86-64. I'm not that familiar with c or assembly but ive managed to put together a very simple attempt as follows:
#include <stdio.h>
#include <stdint.h>
int main() {
uint64_t result;
asm ("movq %%cr4, %0;"
: "=r" (result) ::
);
printf("result: %d \n", result);
return 0;
}
This compiles but throws a runtime error in gdb:
Thread 1 received signal SIGILL, Illegal instruction.
main () at main.c:6
6 asm ("movq %%cr4, %0;"
I think the c/assembly is correct as I'm able to pull values from other registers. I presume the error is due to the fact that I'm not running in kernel mode (based on what I've read) but I don't fully understand what that entails and with my limited understanding of c/assembly I'm not sure i should be playing with kernel mode just yet.
Is there any other way of doing this outside of kernel mode? For example is this info available via an exposed dll call somewhere.
I would welcome any comments on the implications of running an app in kernel mode.
Update: This answer is not appropriate for CR registers, per this comment.
What you're looking for is the so-called 'WinRing0.sys' driver, which exposes an API allowing you to read from user-mode all the various interesting MSRs that are only available to kernel (ring 0) code.
This is an open-source component, but most importantly someone has already paid to sign to the driver so it can be loaded in Windows (as an individual, it is practically impossible to sign a current Windows driver even if you are willing to pay). You can find the 32-bit and 64-bit (WinRing0x64.sys) binaries here.
More details are available in this answer - the question there is about programming performance counters, but the access needed is the same and WinRing0.sys will work for both use-cases.

What is the role of .s files in a C project?

I am working with an ARM Cortex M3 chip (STM32F2) and ST provides a "standard peripheral library". It has some useful .c and .h files. It also has .s files.
What is the purpose of these .s files in the context of a C project? How do I get my compiler/linker/? to take them into account?
The .s extension is the convention used by GNU and many other tool-chains for assembler files.
Last I looked the STM32 Standard Peripheral Library itself contains no assembler files, however the CMSIS library contains start-up code for various STM32 parts, for example startup_stm32f2xx.s is start-up code for all STM32F2xx series devices. There are different implementations for different tool-chains; you need to build and link the file associated with your specific part and tool-chain. If you are using an example project that builds and runs or an IDE that creates part-specific projects for you, this will probably already have been done - if you have code that runs it certainly has.
How you build and link the code will depend on what tool-chain you are using. Most IDE based tools will automatically recognise the extension and invoke the assembler to generate an object file that will be linked like any other. The exact content differs slightly between tool-chain versions, but primarily creates the C runtime environment (stack and heap), initialises the processor, defines an initial interrupt/exception vector table, initialises static data and jumps to main().
The core of the file for the Keil/ARM RealView version for example looks like this:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
Reset_Handler is the address Program Counter (PC) register will be set to after a processor reset.
SystemInit is an external C code function that does the bulk of the initialisation - this may need customisation for your hardware. Cortex-M is unusual in that it can start running C code immediately after reset because the vector table includes both the reset address and the initial stack pointer address, which is automatically loaded to the SP register on reset. As a result you do not need much assembler knowledge to get one running.
__main() is the compiler supplied entry point for your C code. It is not the main() function you write, but performs initialisation for the standard library, static data, the heap before calling your `main()' function.
The GCC version is somewhat more involved since it does much of the work done by __main() in the Keil/ARM RealView version, but essentially it performs the same function.
Note that in the CMSIS SystemInit() is defined in system_stm32f2xx.c, and may need customisation for your board (correct crystal frequency, PLL setup, external SRAM configuration etc.). Because this is C code, and well commented, you will probably be more comfortable with it.
They usually contain assembly code. The assembler turns them into object files which are later linked by the linker with the main stuff. But I imagine it does depend on the compiler, toolchain etc.
The .s files usually contain the Vector tables. It defines what should the system do when an interrupt occurs. This table (code) is placed in a memory address defined by you in linker file. For example, every time a reset occurs what or rather where should your processor begin from , what code should it run. similarly, there are other handlers ( interrupt vectors). In STM32 , usually the controller loops on particular handlers.
As given in the below example:See this link for detailed explanation
.section INTERRUPT_VECTOR, "x"
.global _Reset
_Reset:
B Reset_Handler /* Reset */
B . /* Undefined */
B . /* SWI */
B . /* Prefetch Abort */
B . /* Data Abort */
B . /* reserved */
B . /* IRQ */
B . /* FIQ */
Reset_Handler:
LDR sp, =stack_top
BL c_entry
B .
This assembly code later is converted to object files and linked with your .c files and .ld to create a .elf or .bin files.
You've probably got a Keil-based development environment for your ST kit. Depending on the version of your compiler, the project file should have different sections for C, C++, and assembler code. In your IDE, open your project and look for "Project Properties" or something like it.
You can import and export symbols to and from the assembler code so that it and the C/C++ code will link. With Keil it all integrates reasonably well.
The EXPORT directive tells the assembler to make the specified symbol public so that your C/C++ code can link to it.
The IMPORT directive tells the assembler that the specified symbol is defined elsewhere and will be resolved at link time.

Resources