LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer
User Name
Password
Linux - Embedded & Single-board computer This forum is for the discussion of Linux on both embedded devices and single-board computers (such as the Raspberry Pi, BeagleBoard and PandaBoard). Discussions involving Arduino, plug computers and other micro-controller like devices are also welcome.

Notices


Reply
  Search this Thread
Old 06-28-2018, 11:14 AM   #1
ArmNewbie
LQ Newbie
 
Registered: Jun 2018
Posts: 8

Rep: Reputation: Disabled
Help with kernel modules when cross-compiling for arm


Hi,

I'm not sure if this is the right place to post this particular question, but here it goes.

Context:
I'm trying to enable PMU's (Performance Monitor Units) on arm versatile juno r2 development board.

Manuals I've consulted so far to check how to access the registers and enable userspace
  1. ARM ® Cortex ® -A72 MPCore Processor
  2. ARM® Cortex ® -A53 MPCore Processor
  3. Juno r2 ARM® Development Platform SoC
  4. ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile

Online sources to guide me in this process:
  1. http://zhiyisun.github.io/2016/03/02...-in-Linux.html
  2. http://valtrix.in/programming/progra...mance-counters
  3. http://syndication2605.rssing.com/ch...test.php#item4
  4. https://github.com/thoughtpolice/ena...able_arm_pmu.c
  5. http://ilinuxkernel.com/?p=1755

Code that I'm trying to compile:
Code:
/*                                                                             
 * Enable user-mode ARM performance counter access.                            
 */                                                                           
#include <linux/kernel.h>                                                      
#include <linux/module.h>                                                      
#include <linux/smp.h>                                                         
                                                                                
 
#define PERF_DEF_OPTS       (1 | 16)                                                                       
#define PERF_OPT_RESET_CYCLES   (2 | 4)                                                                  
#define PERF_OPT_DIV64      (8)                                                                          
#define ARMV8_PMCR_MASK         0x3f                                                                    
#define ARMV8_PMCR_E            (1 << 0) /* Enable all counters */                                      
#define ARMV8_PMCR_P            (1 << 1) /* Reset all counters */                                       
#define ARMV8_PMCR_C            (1 << 2) /* Cycle counter reset */                                      
#define ARMV8_PMCR_D            (1 << 3) /* CCNT counts every 64th cpu cycle */                         
#define ARMV8_PMCR_X            (1 << 4) /* Export to ETM */                                            
#define ARMV8_PMCR_DP           (1 << 5) /* Disable CCNT if non-invasive debug*/                        
#define ARMV8_PMCR_LC           (1 << 6) /* Cycle Counter 64bit overflow*/
#define ARMV8_PMCR_N_SHIFT      11       /* Number of counters supported */                             
#define ARMV8_PMCR_N_MASK       0x1f                                                                    
                                                                                                         
#define ARMV8_PMUSERENR_EN_EL0  (1 << 0) /* EL0 access enable */                                        
#define ARMV8_PMUSERENR_CR      (1 << 2) /* Cycle counter read enable */                                
#define ARMV8_PMUSERENR_ER      (1 << 3) /* Event counter read enable */                                
                                                                                                         
static inline u32 armv8pmu_pmcr_read(void)                                                              
{                                                                                                       
        u64 val=0;                                                                                      
        asm volatile("mrs %0, pmcr_el0" : "=r" (val));                                                  
        return (u32)val;                                                                                
}                                                                                                       
static inline void armv8pmu_pmcr_write(u32 val)                                                         
{                                                                                                       
        val &= ARMV8_PMCR_MASK;                                                                         
        isb();                                                                                          
        asm volatile("msr pmcr_el0, %0" : : "r" ((u64)val));                                            
}       
 
static inline  long long armv8_read_CNTPCT_EL0(void)
{
   long long val;
   asm volatile("mrs %0, CNTVCT_EL0" : "=r" (val));
 
   return val;
}
 
                                                                                                         
static void                                                                                            
enable_cpu_counters(void* data)                                                                         
{                                                                                                       
    u32 val=0;                                                         
    asm volatile("msr pmuserenr_el0, %0" : : "r"(0xf));
    armv8pmu_pmcr_write(ARMV8_PMCR_LC|ARMV8_PMCR_E);                                                      
        asm volatile("msr PMCNTENSET_EL0, %0" :: "r" ((u32)(1<<31)));
    armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E|ARMV8_PMCR_LC);   
        printk("\nCPU:%d ", smp_processor_id());
}                                                                                                       
                                                                                                         
static void                                                                                            
disable_cpu_counters(void* data)                                                                        
{                                                                                                       
    u32 val=0;                                                                                             
    printk(KERN_INFO "\ndisabling user-mode PMU access on CPU #%d",                       
    smp_processor_id());                                                                                   
                                                                                                         
    /* Program PMU and disable all counters */                                                            
        armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E);                                              
    asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)0));                                                 
                                                                                                         
}                                                                                                       
                                                                                                         
static int __init                                                                                       
init(void)                                                                                              
{                                                                       
    u64 cval;
        u32 val;
 
        isb();
        asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(cval));
        printk("\nCPU Cycle count:%llu \n", cval);
        asm volatile("mrs %0, PMCNTENSET_EL0" : "=r"(val));
        printk("PMCNTENSET_EL0:%lX ", val);
        asm volatile("mrs %0, PMCR_EL0" : "=r"(val));
        printk("\nPMCR_EL0 Register:%lX ", val);
 
        on_each_cpu(enable_cpu_counters, NULL, 1);                                                             
        printk(KERN_INFO "Enable Access PMU Initialized");                                                       
    return 0;                                                                                              
}                                                                                                       
                                                                                                         
static void __exit                                                                                      
fini(void)                                                                                              
{                                                                                                       
    on_each_cpu(disable_cpu_counters, NULL, 1);                                                            
    printk(KERN_INFO "Access PMU Disabled");                                                          
}                                                                                                       
                                                                                                         
module_init(init);                                                                                      
module_exit(fini);
This is the Makefile that I'm using to compile it:
Code:
PWD := $(shell pwd)

obj-m += enable_arm_pmu.o

all:
	make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KERNEL) SUBDIRS=$(PWD) modules
clean:
	make -C $(KERNEL) SUBDIRS=$(PWD) clean
I'm executing this command on the terminal:
Code:
make KERNEL=/lib/modules/4.13.0-45-generic/build CROSS=aarch64-linux-gnu-
The output I'm receiving from executing that instruction is:
Code:
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- -C /lib/modules/4.13.0-45-generic/build SUBDIRS=/home/lfpm1993/Desktop modules
make[1]: Entering directory '/usr/src/linux-headers-4.13.0-45-generic'
  CC [M]  /home/lfpm1993/Desktop/enable_arm_pmu.o
aarch64-linux-gnu-gcc: error: unrecognized argument in option ‘-mabi=apcs-gnu’
aarch64-linux-gnu-gcc: note: valid arguments to ‘-mabi=’ are: ilp32 lp64
aarch64-linux-gnu-gcc: error: unrecognized command line option ‘-mapcs’
aarch64-linux-gnu-gcc: error: unrecognized command line option ‘-mno-sched-prolog’
aarch64-linux-gnu-gcc: error: unrecognized command line option ‘-msoft-float’
scripts/Makefile.build:323: recipe for target '/home/lfpm1993/Desktop/enable_arm_pmu.o' failed
make[2]: *** [/home/lfpm1993/Desktop/enable_arm_pmu.o] Error 1
Makefile:1550: recipe for target '_module_/home/lfpm1993/Desktop' failed
make[1]: *** [_module_/home/lfpm1993/Desktop] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.13.0-45-generic'
Makefile:6: recipe for target 'all' failed
make: *** [all] Error 2
I'm not sure on how to solve it.

Maybe it is the wrong toolchain?
Maybe I linked the wrong path to the kernel?
Maybe it is the kernel, should I put the native kernel there instead of linking to the host kernel?

Any assistance would be welcome.

Thanks,
Luís
 
Old 06-29-2018, 01:27 AM   #2
AwesomeMachine
LQ Guru
 
Registered: Jan 2005
Location: USA and Italy
Distribution: Debian testing/sid; OpenSuSE; Fedora; Mint
Posts: 5,524

Rep: Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015
You could look here: scripts/Makefile.build:323, 323 is a line number. It looks like the wrong includes being used.
 
1 members found this post helpful.
Old 06-29-2018, 10:35 AM   #3
ArmNewbie
LQ Newbie
 
Registered: Jun 2018
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thanks for the reply @AwesomeMachine,

I looked at the file you pointed out (located in, /usr/src/linux-source-4.4.0/Makefile.build), lines #322 and #323 have the following content:
Code:
# To build objects in subdirs, we need to descend into the directories
$(sort $(subdir-obj-y)): $(subdir-ym) ;
Unfortunately, I keep on not being able to find the problem in this particular line of code, so I searched for 'include' in this file, since you said "It looks like the wrong includes being used.".

From the results, the most important ones seem to be:
Code:
include scripts/Kbuild.include
include scripts/Makefile.lib
If needed I can append or post the files here.

Thanks again for the help.
 
Old 06-29-2018, 06:06 PM   #4
X-LFS-2010
Member
 
Registered: Apr 2016
Posts: 510

Rep: Reputation: 58
it's not a newbie question
 
Old 07-02-2018, 06:28 PM   #5
ArmNewbie
LQ Newbie
 
Registered: Jun 2018
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thanks for the reply @X-LFS-2010

Who should I talk to, to move this topic to another section of the forum?

Either way, some progress:

1) Downloaded the kernel from:
https://git.linaro.org/landing-teams...el-release.git

2) Changed Makefile to export the variables:
Code:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

PWD := $(shell pwd)

obj-m += enable_arm_pmu.o

all:
	make ARCH=$(ARCH) CPU=$(CPU) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL) SUBDIRS=$(PWD) modules
clean:
	make -C $(KERNEL) SUBDIRS=$(PWD) clean
3) I'm compiling with:
Code:
make KERNEL=/home/lfpm1993/Desktop/kernel-release/
Logs from the terminal:
Code:
make ARCH=arm64 CPU= CROSS_COMPILE=aarch64-linux-gnu- -C /home/lfpm1993/Desktop/kernel-release/ SUBDIRS=/home/lfpm1993/Desktop/build modules
make[1]: Entering directory '/home/lfpm1993/Desktop/kernel-release'

  WARNING: Symbol version dump ./Module.symvers
           is missing; modules will have no dependencies and modversions.

  Building modules, stage 2.
  MODPOST 1 modules
make[1]: Leaving directory '/home/lfpm1993/Desktop/kernel-release'
Next steps:

1)Connected to the board through adb:
sudo adb connect 146.193.56.204

2)Pushed the files:
adb push /home/lfpm1993/Desktop/build/enable_arm_pmu.ko /data/data/modules/

3)Started a serial communication with Putty to arm versatile juno development board.

4)Changed directories to:
cd /data/data/modules/

5)Executed this command:
insmod enable_arm_pmu.k

Logs from the juno development board:
insmod: failed to load enable_arm_pmu.ko: Exec format error

Much better since the starting point! I'm just having some problems regarding this new error message. I'll append an image.
I just need a new perspective on how to tackle this problem.

Thanks,
Luís
Attached Thumbnails
Click image for larger version

Name:	conflict.PNG
Views:	42
Size:	9.5 KB
ID:	28040  
 
Old 07-02-2018, 08:18 PM   #6
AwesomeMachine
LQ Guru
 
Registered: Jan 2005
Location: USA and Italy
Distribution: Debian testing/sid; OpenSuSE; Fedora; Mint
Posts: 5,524

Rep: Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015
It could be that enable_arm_pmu.ko isn't signed. When you configure the kernel, disable the 'module signature verification' option.

But you actually need to understand how to use the build tools. These same questions but with different details will come up again and again. Trial and error is no way to learn. Although I compliment you on what you've done thus far.
 
Old 07-24-2018, 10:18 AM   #7
ArmNewbie
LQ Newbie
 
Registered: Jun 2018
Posts: 8

Original Poster
Rep: Reputation: Disabled
Hi,

Forgot to post the anwer...

I want to thanks @AwesomeMachine for all the help.

I pulled the configuration files from the development board:
adb pull /proc/config.gz /home/lfpm1993/Desktop

Code:
#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_SLAB_FREELIST_RANDOM is not set
# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
# CONFIG_KPROBES is not set
This is part of the configuration file. As you can see lines 199 and 208 the profilling tools are enabled.

Changed the Makefile to:
Code:
obj-m := enable_arm_pmu.o

sema-objs := enable_arm_pmu.o
KDIR := /home/lfpm1993/Desktop/KERNEL/kernel-release/
PWD := $(shell pwd)

ARCH=arm64

CROSS_COMPILE=aarch64-linux-gnu-

CC=$(CROSS_COMPILE)gcc

LD=$(CROSS_COMPILE)ld
all:
	make -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
And it runs fine!

Follow up questions:

1) How does exactly insmod work?
I thought it loaded a module in the running kernel. I'm asking this because I can run 'insmod enable_arm_pmu.ko' and check if its loaded using lsmod. But, for some reason it seems to work only 'locally'. This is, if I load the module (enable_arm_pmu.ko) it calls the function 'enable_cpu_counters' for all cpus, then I can execute some instructions to read the registers and it works. If I divide the module in two; one module enables pmus, the other module read registers, I stop being able to read those registers despite of them being enabled in the previous module. I don't get why, and I need to run outside of kernelspace to benchmark my code in userspace.


2) What are the advantages of using modprobe instead of insmod?
I tried to run modprobe, I have a bunch of inexistent directories (stopping the execution)...and I'm pretty sure, that I don't have any modules dependencies.

3) After the module is loaded, do I have to call it in my application?
I'm asking this because I made a program in userspace now, to access some performance counters and I'm getting 'illegal instructions' and I bet it is because, the module doesn't work 'globally'.

Code:
juno:/data/data/papi/workplace # ./monitoring 2 2 2 3
[1359092.706711] monitoring[11095]: undefined instruction: pc=000000000040065c
[1359092.713652] Code: 00000000 00000000 00000000 d10043ff (d53b9c00)
Illegal instruction
Notes: This is a guide to enable PMUs:
https://developer.arm.com/products/s...e-monitor-unit

TLDR: Modules not working, application gives 'Illegal instruction'.

Thanks,
Luís
Attached Thumbnails
Click image for larger version

Name:	1.PNG
Views:	54
Size:	17.3 KB
ID:	28213   Click image for larger version

Name:	2.PNG
Views:	47
Size:	20.8 KB
ID:	28214   Click image for larger version

Name:	3.PNG
Views:	35
Size:	10.5 KB
ID:	28215   Click image for larger version

Name:	6.PNG
Views:	37
Size:	9.9 KB
ID:	28218  

Last edited by ArmNewbie; 07-24-2018 at 10:24 AM.
 
Old 07-24-2018, 06:45 PM   #8
AwesomeMachine
LQ Guru
 
Registered: Jan 2005
Location: USA and Italy
Distribution: Debian testing/sid; OpenSuSE; Fedora; Mint
Posts: 5,524

Rep: Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015
insmod will try to load any module. modprobe is more sophisticated and will only load modules that are part of the running kernel. You might want to load the module from /etc/modprobe.d if it exists on the system.

Last edited by AwesomeMachine; 07-24-2018 at 06:47 PM.
 
1 members found this post helpful.
Old 07-26-2018, 08:32 AM   #9
ArmNewbie
LQ Newbie
 
Registered: Jun 2018
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thanks @AwesomeMachine

Unfortunaly I don't have those files and I can't create new ones:
Code:
/system/bin/sh: can't create modprobe.conf: Read-only file system

Logs and Outputs:

enable_arm_pmu.ko

juno:/data/data/modules # insmod enable_arm_pmu.ko
[67468.860505] enable_arm_pmu: loading out-of-tree module taints kernel.
[67468.860706] type=1400 audit(1532563200.038:89): avc: denied { write } for pid=306 comm="Binder:306_8" name="timerslack_ns" dev="proc" ino=15297 scontext=u:r:system_server:s0 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=file permissive=1
[67468.860729] type=1400 audit(1532606771.326:90): avc: denied { module_load } for pid=1528 comm="insmod" path="/data/data/modules/enable_arm_pmu.ko" dev="sda4" ino=7646 scontext=u:r:su:s0 tcontext=ubject_r:system_data_file:s0 tclass=system permissive=1
[67468.910305] enable_arm_pmu: module license 'unspecified' taints kernel.
[67468.916862] Disabling lock debugging due to kernel taint
[67468.922373]
[67468.922373] PMCR_EL0 register before : 41023040
[67468.928346]
[67468.928346] PMUSERENR register before : 0
[67468.933814]
[67468.933814] CPU:3
[67468.933908]
[67468.933908] CPU:1
[67468.933921]
[67468.933921] CPU:4
[67468.933957]
[67468.933957] CPU:0
[67468.933973]
[67468.933973] CPU:5
[67468.951084]
[67468.951084] CPU:2
[67468.954543]
[67468.954543] Enable Access PMU Initialized
[67468.959973]
[67468.959973] PMCR_EL0 register after : 41023001
[67468.965839]
[67468.965839] PMUSERENR register after : f

_____________________

read_arm_pmu.ko

juno:/data/data/modules # insmod read_arm_pmu.ko
[67596.492763]
[67596.492763] PMCR_EL0 register : 41023040
[67596.498140]
[67596.498140] PMUSERENR register : 0



The output should be the same.

Reading http://tldp.org/HOWTO/Module-HOWTO/x197.html:
"So you've successfully loaded an LKM, and verified that via /proc/modules. But how do you know it's working? That's up to the LKM, and varies according to what kind of LKM it is, but here are some of the more common actions of an LKM upon being loaded.

The first thing a device driver LKM does after loading (which is what the module would do at boot time if it were bound into the base kernel) is usually to search the system for a device it knows how to drive. Just how it does this search varies from one driver to the next, and can usually be controlled by module parameters. But in any case, if the driver doesn't find any device it is capable of driving, it causes the load to fail. Otherwise, the driver registers itself as the driver for a particular major number and you can start using the device it found via a device special file that specifies that major number. It may also register itself as the handler for the interrupt level that the device uses. It may also send setup commands to the device, so you may see lights blink or something like that.

You can see that a device driver has registered itself in the file /proc/devices. You can see that the device driver is handling the device's interrupts in /proc/interrupts."

Running:
juno:/ # cat /proc/modules
read_arm_pmu 16384 0 - Live 0x0000000000000000 (PO)
enable_arm_pmu 16384 0 - Live 0x0000000000000000 (PO)


juno:/ # cat /proc/devices
Character devices:
1 mem
5 /dev/tty
5 /dev/console
5 /dev/ptmx
10 misc
13 input
14 sound
29 fb
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
204 ttyAMA
226 drm
249 roccat
250 hidraw
251 bsg
252 tee
253 rtc
254 gpiochip

Block devices:
1 ramdisk
259 blkext
7 loop
8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
253 device-mapper
254 virtblk

___________________________

cat /proc/sys/kernel/tainted
4097
___________________________

juno:/ # cat /proc/interrupts CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
2: 1844410 1197983 1353732 16779 3199 5419 GIC v2 92 Level arch_mem_timer
3: 0 0 0 0 0 0 GIC v2 29 Level arch_timer
4: 894927 272142 288023 18616 39333 15390 GIC v2 30 Level arch_timer
7: 0 0 0 0 0 0 GIC v2 198 Level timer
14: 419017 0 0 0 0 0 GIC v2 68 Level mhu_link
15: 0 0 0 0 0 0 GIC v2 67 Level mhu_link
16: 0 0 0 0 0 0 GIC v2 120 Level 7ff00000.dma
17: 0 0 0 0 0 0 GIC v2 121 Level 7ff00000.dma
18: 0 0 0 0 0 0 GIC v2 122 Level 7ff00000.dma
19: 0 0 0 0 0 0 GIC v2 123 Level 7ff00000.dma
20: 0 0 0 0 0 0 GIC v2 124 Level 7ff00000.dma
21: 0 0 0 0 0 0 GIC v2 140 Level 7ff00000.dma
22: 0 0 0 0 0 0 GIC v2 141 Level 7ff00000.dma
23: 0 0 0 0 0 0 GIC v2 142 Level 7ff00000.dma
24: 0 0 0 0 0 0 GIC v2 143 Level 7ff00000.dma
25: 0 0 0 0 0 0 GIC v2 125 Level hdlcd
26: 0 0 0 0 0 0 GIC v2 117 Level hdlcd
27: 6336 0 0 0 0 0 GIC v2 115 Level uart-pl011
28: 53666 0 0 0 0 0 GIC v2 136 Level 7ffa0000.i2c
30: 47345 0 0 0 0 0 GIC v2 149 Level ehci_hcd:usb1
33: 14370 0 0 0 0 0 GIC v2 65 Level 2d000000.gpu
34: 0 0 0 0 0 0 GIC v2 66 Level 2d000000.gpu
35: 39222 0 0 0 0 0 GIC v2 64 Level 2d000000.gpu
37: 52 0 0 0 0 0 GIC v2 194 Level mmci-pl18x (cmd)
40: 0 0 0 0 0 0 GIC v2 100 Level rtc-pl031
43: 0 0 0 0 0 0 GIC v2 169 Level sata_sil24[0000:03:00.0]
45: 0 0 0 0 0 0 M SI 0 Edge PCIe PME, aerdrv
52: 1049234 0 0 0 0 0 M SI 4194304 Edge eth0
IPI0: 62569 1835646 1888285 43688 29194 29798 R escheduling interrupts
IPI1: 315 1276 725 386 307 207 F unction call interrupts
IPI2: 0 0 0 0 0 0 C PU stop interrupts
IPI3: 829962 24938 62500 1274 498 1029 T imer broadcast interrupts
IPI4: 800250 925302 1266671 10821 9264 7192 I RQ work interrupts
IPI5: 0 0 0 0 0 0 C PU wake-up interrupts
Err: 0

I'm thinking if I need to find a usable major and give it to my module?
Attached Thumbnails
Click image for larger version

Name:	comandos1.PNG
Views:	18
Size:	22.5 KB
ID:	28223   Click image for larger version

Name:	comandos2.PNG
Views:	21
Size:	25.0 KB
ID:	28224   Click image for larger version

Name:	comandos3.PNG
Views:	19
Size:	12.9 KB
ID:	28225  
 
Old 07-26-2018, 08:35 PM   #10
AwesomeMachine
LQ Guru
 
Registered: Jan 2005
Location: USA and Italy
Distribution: Debian testing/sid; OpenSuSE; Fedora; Mint
Posts: 5,524

Rep: Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015
The insmod output is not necessarily the same for different modules.
 
Old 07-30-2018, 10:24 AM   #11
ArmNewbie
LQ Newbie
 
Registered: Jun 2018
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thanks for the reply @AwesomeMachine,

That's my fault, I forgot to post the code that was generating those logs...

If I understand LKM correctly, when I load the module with 'insmod name_of_the_module', module_init (init); is called and all the functions inside init are executed, same thing when I type 'rmmod name_of_the_module', the difference being that fini is called.

So, the main functions that are executed in the first module to turn 'on' the userspace access are these ones:
Code:
static void enable_cpu_counters(void* data)                                                                         
{                                                                                                       
	asm volatile("msr pmuserenr_el0, %0" :: "r"(0xf));
	armv8pmu_pmcr_write (ARMV8_PMCR_LC|ARMV8_PMCR_E);                                                      
	asm volatile("msr PMCNTENSET_EL0, %0" :: "r" ((u32)(1<<31)));
	armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E|ARMV8_PMCR_LC);   
	printk("\nCPU:%d \n", smp_processor_id());
}                                                                                                       
                                                                                                         
static void disable_cpu_counters (void* data)                                                                        
{                                                                                                                                                                                                   
	printk(KERN_INFO "\ndisabling user-mode PMU access on CPU #%d \n",                       
	smp_processor_id());
	/* Program PMU and disable all counters */                                                            
	armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E);                                              
	asm volatile("msr pmuserenr_el0, %0" ::"r"((u64)0));                                                 
}                                                                                                       
   
static int __init init(void)                                                                                              
{
        unsigned int reguser=0;     
                                                                                                                        
        isb();
        
        asm volatile("mrs %0, pmcr_el0" : "=r" (reguser));
        printk(KERN_INFO "\nPMCR_EL0 register before : %x\n", reguser);
        asm volatile("mrs %0, pmuserenr_el0" : "=r" (reguser));
        printk(KERN_INFO "\nPMUSERENR register before : %x\n", reguser);

        /* Enable counters */
	on_each_cpu (enable_cpu_counters, NULL, 1);                                                             
        printk(KERN_INFO "\nEnable Access PMU Initialized\n");

        asm volatile("mrs %0, pmcr_el0" : "=r" (reguser));
        printk(KERN_INFO "\nPMCR_EL0 register after : %x\n", reguser);
        asm volatile("mrs %0, pmuserenr_el0" : "=r" (reguser));
        printk(KERN_INFO "\nPMUSERENR register after : %x\n", reguser);

	return 0;                                                                                              
}                                                                                                       
                                                                                                         
static void __exit fini(void)                                                                                              
{                                                                                                       
	on_each_cpu(disable_cpu_counters, NULL, 1);                                                            
	printk(KERN_INFO "\nAccess PMU Disabled\n");                                                          
}                                                                                                       
                                                                                                         
module_init (init);                                                                                      
module_exit (fini);

The main functions of the other module that runs after the first one and only reads the registers (supposedly having userspace acess) are:
Code:
static int __init init(void)                                                                                              
{        
        unsigned int reguser=0;                                                               
        isb();

	/* Enable counters */
        asm volatile("mrs %0, pmcr_el0" : "=r" (reguser));
        printk(KERN_INFO "\nPMCR_EL0 register : %x\n", reguser);
        asm volatile("mrs %0, pmuserenr_el0" : "=r" (reguser));
        printk(KERN_INFO "\nPMUSERENR register : %x\n", reguser);

	return 0;                                                                                              
}                                                                                                       
                                                                                                         
static void __exit fini(void)                                                                                              
{                                                                                                                                                         
	printk(KERN_INFO "\nDisabling read_arm_pmu.ko\n");                                                          
}                                                                                                       
                                                                                                         
module_init (init);                                                                                      
module_exit (fini);
Since the reading code is the same (In the first and second module) and the second module doesn't write anything I was expecting to keep the values from the first module, but something changes back those values like a reset. Unless this modules have some kind of scope I'm not aware of. Or is it the code? I'm really confused...

Thanks again,
Luís
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] building dependencies for kernel modules in cross compiling environment ayyasprings Linux - Embedded & Single-board computer 4 08-08-2014 03:57 AM
Need help with cross-compiling self-written kernel modules TeaYoung Linux - Kernel 6 04-23-2013 06:09 PM
Need help with cross-compiling self-written kernel modules TeaYoung Linux - Newbie 0 04-22-2013 10:17 AM
cross-compiling modules for a preemptive kernel(2.6.23) Trixy_Tree Linux - Embedded & Single-board computer 1 04-07-2009 11:47 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer

All times are GMT -5. The time now is 12:25 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration