reading and writing a register linux device driver - device-driver

I am writing a watchdog timer device driver for Pandaboard(Omap4) for educational purposes(I know the driver already exist). I want to know how I can access watchdog timer registers (e.g. WDT_WLDR(timer load register) has address offset 0x0000002C and Physical L4 interconnect address 0x4A31402C) in kernel space. Please guide in the write direction so that I can write my own watchdog device driver.
Regards
==================================================================================
Now I wrote this module however it is not working how it is supposed to be
ioread32(reg_WLDR) returns 0
==================================================================================
dmesg returns
[ 72.798461] Now in kernel space
[ 72.798583] Starting to read
[ 72.798583]
[ 72.798645] 0
[ 72.798645] ------------[ cut here ]------------
[ 72.798645] WARNING: at arch/arm/mach-omap2/omap_l3_noc.c:113 l3_interrupt_handler+0x)
[ 72.798706] L3 custom error: MASTER:MPU TARGET:L4CFG
[ 72.798706] Modules linked in: test_device(O+)
[ 72.798706] 2nd Read
[ 72.798736]
[ 72.798736] (null)
[ 72.798736]
[ 72.798797] [<c001a0f4>] (unwind_backtrace+0x0/0xec) from [<c003a298>] (warn_slowpath)
[ 72.798797] [<c003a298>] (warn_slowpath_common+0x4c/0x64) from [<c003a344>] (warn_slo)
[ 72.798797] [<c003a344>] (warn_slowpath_fmt+0x30/0x40) from [<c002efe8>] (l3_interrup)
[ 72.798858] [<c002efe8>] (l3_interrupt_handler+0x120/0x16c) from [<c0092af4>] (handle)
[ 72.798889] [<c0092af4>] (handle_irq_event_percpu+0x74/0x1f8) from [<c0092cb4>] (hand)
[ 72.798889] [<c0092cb4>] (handle_irq_event+0x3c/0x5c) from [<c0095958>] (handle_faste)
[ 72.798950] [<c0095958>] (handle_fasteoi_irq+0xd4/0x110) from [<c00925b4>] (generic_h)
[ 72.798950] [<c00925b4>] (generic_handle_irq+0x30/0x48) from [<c0014208>] (handle_IRQ)
[ 72.798950] [<c0014208>] (handle_IRQ+0x78/0xb8) from [<c00084b8>] (gic_handle_irq+0x8)
[ 72.799072] [<c00084b8>] (gic_handle_irq+0x80/0xac) from [<c04b74c4>] (__irq_svc+0x44)
[ 72.799072] Exception stack(0xece47ec0 to 0xece47f08)
[ 72.799102] 7ec0: ecdbc0e0 00000004 c0748c64 00000000 000080d0 c0743a88 ecdbc0e0 ee270
[ 72.799102] 7ee0: c0013328 00000000 c0c99720 00020348 ece46000 ece47f08 c0081c38 c03ac
[ 72.799102] 7f00: 60000013 ffffffff
[ 72.799102] [<c04b74c4>] (__irq_svc+0x44/0x60) from [<c03a610c>] (sk_prot_alloc+0x50/)
[ 72.799102] [<c03a610c>] (sk_prot_alloc+0x50/0x14c) from [<c03a6268>] (sk_alloc+0x1c/)
[ 72.799102] [<c03a6268>] (sk_alloc+0x1c/0xd8) from [<c042789c>] (unix_create1+0x50/0x)
[ 72.799255] [<c042789c>] (unix_create1+0x50/0x178) from [<c0427a34>] (unix_create+0x7)
[ 72.799255] [<c0427a34>] (unix_create+0x70/0x90) from [<c03a3878>] (__sock_create+0x1)
[ 72.799255] [<c03a3878>] (__sock_create+0x19c/0x2b8) from [<c03a3a10>] (sock_create+0)
[ 72.799316] [<c03a3a10>] (sock_create+0x40/0x48) from [<c03a3b8c>] (sys_socket+0x2c/0)
[ 72.799346] [<c03a3b8c>] (sys_socket+0x2c/0x68) from [<c0013160>] (ret_fast_syscall+0)
[ 72.799346] ---[ end trace 4316415ef3b8cf4c ]---
==================================================================================
Code
#include </home/salman/kernel_panda_compile/linux/include/linux/version.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/module.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/miscdevice.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/highmem.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/fs.h>
#include </home/salman/kernel_panda_compile/linux/arch/arm/include/asm/unistd.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/unistd.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/kernel.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/moduleparam.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/io.h>
#include </home/salman/kernel_panda_compile/linux/arch/arm/include/asm/io.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/ioport.h>
static void *reg_WLDR;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Muhammad Salman Khalid");
MODULE_VERSION("0.100");
static int start_module(void)
{
int retval;
printk(KERN_INFO "Now in kernel space\n");
// retval = misc_register(&our_device);
reg_WLDR = ioremap(0x4A31402C,0x001);//0x4A31402C is the physical address (L4 Interconnect) of WDT_WLDR register of watchdog timer(pandaboard omap4) it is readable & writeable
iowrite32(252,reg_WLDR);
printk(KERN_ALERT "Starting to read\n");
printk(KERN_ALERT "\n%d\n",ioread32(reg_WLDR));
printk(KERN_ALERT "2nd Read\n");
printk(KERN_ALERT "\n%p\n",ioread32(reg_WLDR));
iounmap(reg_WLDR);
return retval;
}
static void finish_module(void)
{
printk(KERN_INFO "Leaving kernel space\n");
// misc_deregister(&our_device);
return;
}
module_init(start_module);
module_exit(finish_module);

If you plan to use Linux Kernel then you can use following api's for reading and writing to peripheral registers:
1. ioremap() (Map the physical address into kernel virtual memory)
2. ioread32() (Read from 32 bit register)
3. iowrite32() (Write to 32 bit register)
and finally iounmap() (Unmapping memory which you allocated with ioremap())
Now please refer to below two things:
1. OMAP4 datasheet/manual to get the physical address of registers.
2. Link for explaining above mentioned api's: http://www.makelinux.net/ldd3/chp-9-sect-4

Try replacing this line: ioremap(0x4A31402C,0x001) in your code with this: ioremap(0x4A31402C,0x04) and then check.

Related

OPA REGO: How to find all not matching items in another dictionary?

Given input as follow:
{
"source": "serverA",
"destination": "serverB",
"rules": {
"tcp": {
"ssh": [
22
],
"https": [
8443
]
},
"udp": [
53
]
}
}
and data source:
{
"allowedProtocolTypeToPortMapping": {
"tcp": {
"ssh": [22],
"https": [443]
},
"udp": {
"dns": [53]
},
"icmp": {
"type": [0]
}
}
}
I want to create a policy that checks all rules and shows the ones that are not compliant to data source. In this example that would be port 8443 with protocol type https that is not compliant (allowed only 443). What is the best way to achieve it using rego language?
Here's one way of doing it.
package play
violations[msg] {
# Traverse input object stopping only at array values
walk(input.rules, [path, value])
is_array(value)
# Get corresponding list of allowed ports from matching path
allowedPorts := select(data.allowedProtocolTypeToPortMapping, path)
# At this point, we have one array of ports from the input (value)
# and one array of allowed ports. Converting both to sets would allow
# us to compare the two using simple set intersection - i.e. checking
# that all ports in the input are also in the allowed ports.
ip := {port | port := value[_]}
ap := {port | port := allowedPorts[_]}
# Unless all ports in the input array are in both the input and the
# allowed ports, it's a violation
count(ip) != count(ip & ap)
msg := concat(".", path)
}
select(o, path) = value {
walk(o, [path, value])
}
Rego Playground example available here.

Bazel: defines in a header-only library

If I have a header-only library (Eigen in my case) like this:
cc_library(
name = "eigen",
hdrs = glob(
["Eigen/**"],
exclude = [
"Eigen/src/OrderingMethods/Amd.h",
"Eigen/src/SparseCholesky/**",
"Eigen/Eigen",
"Eigen/IterativeLinearSolvers",
"Eigen/MetisSupport",
"Eigen/Sparse",
"Eigen/SparseCholesky",
"Eigen/SparseLU",
],
),
defines = [
"EIGEN_MPL_ONLY",
"EIGEN_NO_DEBUG",
"EIGEN_DONT_PARALLELIZE",
"EIGEN_UNALIGNED_VECTORIZE=0",
"EIGEN_MAX_ALIGN_BYTES=32",
"EIGEN_MAX_STATIC_ALIGN_BYTES=32",
"EIGEN_NO_AUTOMATIC_RESIZING"
],
)
Are the defines observed at all, or do I have to manually add these defines to each dependend library?
additionally, say I have two libraries in my project that depend on Eigen, and I want to compile one with AVX512 and the other without. How can I hide the respective compiled eigen symbols from each other, so that it does not reuse the ones compiled with different defines?
A target that depedens on eigen will also inherit the defines (e.g. EIGEN_MPL_ONLY).
See for details here:
Each string, ..., is
prepended with -D and added to the compile command line to this
target, as well as to every rule that depends on it
A can also setup a small testbed to check how defines work:
WORKSPACE.bazel
# Empty
main/BUILD.bazel
cc_binary(
name = "main",
srcs = ["main.cpp"],
deps = ["//my_header_only_lib:my_header_only_lib"]
)
main/main.cpp
#include "header.h"
#include <iostream>
int main() {
Vector3<float> vec;
vec.print();
#ifdef FOO_BAR
std::cout << "FOO_BAR is also known in main" << std::endl;
#endif
}
my_header_only_lib/BUILD.bazel
package(
default_visibility = ["//visibility:public"],
)
cc_library(
name = "my_header_only_lib",
hdrs = ["header.h"],
includes=["."],
defines = ["FOO_BAR"],
)
my_header_only_lib/my_header_only_lib.h
#pragma once
#include <iostream>
template<typename ScalarType>
class Vector3 {
public:
ScalarType x, y, z;
void print() {
#ifdef FOO_BAR
std::cout << "FOO_BAR defined" << std::endl;
#endif
}
};
Output
FOO_BAR defined
FOO_BAR is also known in main

Device Tree Bad Data (for PocketBeagle)

I am trying to create a device tree overlay for the PocketBeagle to interface to the MCP3204 ADC. I am trying to use the driver that exists already in the Linux kernel. My device tree source is the following:
/dts-v1/;
/plugin/;
/ {
compatible = "ti,am335x-pocketbeagle";
part-number = "mm-cape";
version = "00A0";
fragment#0 {
target = <&am33xx_pinmux>;
__overlay__ {
mm_chipselect: MM_CHIP_SELECT_PIN {
pinctrl-single,pin = <0xe8 0xf>;
};
};
};
fragment#1 {
target = <&ocp>;
__overlay__ {
mm_chipselect_helper: helper {
compatible = "bone-pinmux-helper";
pinctrl-names = "default";
pinctrl-0 = <&mm_chipselect>;
status = "okay";
};
};
};
fragment#2 {
target = <&spi0>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&gpio2 24 0>, <0>, <0>, <0>;
mcp320x: mcp320x#0 {
compatible = "microchip,mcp3208";
reg = <0>;
spi-max-frequency = <1000000>;
};
};
};
};
When I load my device tree overlay I get the following output from dmesg:
[ 2.157460] pinctrl-single 44e10800.pinmux: bad data for mux MM_CHIP_SELECT_PIN
[ 2.164916] pinctrl-single 44e10800.pinmux: no pins entries for MM_CHIP_SELECT_PIN
[ 2.172687] pinctrl-single 44e10800.pinmux: bad data for mux MM_CHIP_SELECT_PIN
[ 2.180072] pinctrl-single 44e10800.pinmux: no pins entries for MM_CHIP_SELECT_PIN
[ 2.187700] bone-pinmux-helper ocp:helper: Failed to get pinctrl
[ 2.193762] ------------[ cut here ]------------
[ 2.193783] WARNING: CPU: 0 PID: 1 at drivers/base/devres.c:888 devm_kfree+0x4c/0x50()
[ 2.193791] Modules linked in:
[ 2.193810] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.91-ti-r133 #1
[ 2.193818] Hardware name: Generic AM33XX (Flattened Device Tree)
[ 2.193862] [<c001bed0>] (unwind_backtrace) from [<c0015978>] (show_stack+0x20/0x24)
[ 2.193885] [<c0015978>] (show_stack) from [<c05c1674>] (dump_stack+0x8c/0xa0)
[ 2.193905] [<c05c1674>] (dump_stack) from [<c004435c>] (warn_slowpath_common+0x94/0xc4)
[ 2.193919] [<c004435c>] (warn_slowpath_common) from [<c0044490>] (warn_slowpath_null+0x2c/0x34)
[ 2.193932] [<c0044490>] (warn_slowpath_null) from [<c0718418>] (devm_kfree+0x4c/0x50)
[ 2.193951] [<c0718418>] (devm_kfree) from [<c073bea8>] (bone_pinmux_helper_probe+0x1c4/0x260)
[ 2.193966] [<c073bea8>] (bone_pinmux_helper_probe) from [<c0716368>] (platform_drv_probe+0x60/0xc0)
[ 2.193990] [<c0716368>] (platform_drv_probe) from [<c0713fcc>] (driver_probe_device+0x234/0x470)
[ 2.194005] [<c0713fcc>] (driver_probe_device) from [<c07142a4>] (__driver_attach+0x9c/0xa0)
[ 2.194020] [<c07142a4>] (__driver_attach) from [<c0711a80>] (bus_for_each_dev+0x8c/0xd0)
[ 2.194035] [<c0711a80>] (bus_for_each_dev) from [<c0713728>] (driver_attach+0x2c/0x30)
[ 2.194049] [<c0713728>] (driver_attach) from [<c0713200>] (bus_add_driver+0x1b8/0x278)
[ 2.194062] [<c0713200>] (bus_add_driver) from [<c0714d94>] (driver_register+0x88/0x104)
[ 2.194075] [<c0714d94>] (driver_register) from [<c0716274>] (__platform_driver_register+0x50/0x58)
[ 2.194094] [<c0716274>] (__platform_driver_register) from [<c0f96218>] (bone_pinmux_helper_driver_init+0x1c/0x20)
[ 2.194113] [<c0f96218>] (bone_pinmux_helper_driver_init) from [<c00098e4>] (do_one_initcall+0xd8/0x228)
[ 2.194133] [<c00098e4>] (do_one_initcall) from [<c0f4c000>] (kernel_init_freeable+0x1ec/0x288)
[ 2.194152] [<c0f4c000>] (kernel_init_freeable) from [<c0aa4314>] (kernel_init+0x1c/0xf8)
[ 2.194172] [<c0aa4314>] (kernel_init) from [<c0010e00>] (ret_from_fork+0x14/0x34)
[ 2.194217] ---[ end trace 20e7a3ce9aa45d9c ]---
[ 2.194310] bone-pinmux-helper: probe of ocp:helper failed with error -22
[ 2.222490] spi spi1.0: failed to request gpio
[ 2.227072] omap2_mcspi 48030000.spi: can't setup spi1.0, status -16
[ 2.233483] spi_master spi1: spi_device register error /ocp/spi#48030000/mcp320x#0
[ 2.241309] spi_master spi1: Failed to create SPI device for /ocp/spi#48030000/mcp320x#0
I can't seem to find what the source of the error could be. I have confirmed using multiple other examples that the structure of the file should be correct, and that the pin offset and mux value are correct. What could be causing this error?

can we use virt_to_phys for user space memory in kernel module?

I will allocate memory in user application using malloc and send the malloc returned address to a kernel module through character driver interface.
I will pin the pages for this memory using get_user_pages_fast in kernel module.
Can I use virt_to_phys to get the address returned by malloc.
Is it valid? If not then how can I get proper physical address?
My aim is to get physical address of user space allocated memory.
I m limiting my transfer size to pagesize (4KB).
No you can't, virt_to_phys converts kernel virtual addresses into physical addresses. There exist 3 (or 4) types of addresses in linux:
kernel virtual address: which is physical address +/- an offset (PAGE_OFFSET).
kernel physical address: actual physical address (obtained by __pa or virt_to_phys functions).
user virtual address: the translation to physical address is inside the page table of the process.
Note that page table 'layout' depends on the architecture of the processor, so you need to implement a software page table walk that corresponds to the architecture you work on.
And last word, the 4th kind of addresses that exists is :
bus address: which is an address as seen by a device.
malloc returns the user virtual address. So I think you can not use the address returned by malloc from inside the driver.
virt_to_phys: The returned physical address is the physical (CPU) mapping for the memory address given. It is only valid to use this function on addresses directly mapped or allocated via kmalloc. It means It is used by the kernel to translate kernel virtual address (not user virtual address) to physical address
This program will help you to access the physical memory directly. Idea is to mmap with /dev/mem(RAM)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
return 0;
}
off_t offset = strtoul(argv[1], NULL, 0);
size_t len = strtoul(argv[2], NULL, 0);
// Truncate offset to a multiple of the page size, or mmap will fail.
size_t pagesize = sysconf(_SC_PAGE_SIZE);
off_t page_base = (offset / pagesize) * pagesize;
off_t page_offset = offset - page_base;
int fd = open("/dev/mem", O_SYNC);
unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
if (mem == MAP_FAILED) {
perror("Can't map memory");
return -1;
}
size_t i;
for (i = 0; i < len; ++i)
printf("%02x ", (int)mem[page_offset + i]);
return 0;
}
Credit goes to Accessing physical address from user space

Docker API: cpu_stats vs percpu_stats

What is the difference between
cpu_stats and percpu_stats when using Docker remote API:
The request is :
GET /containers/(id or name)/stats
(A part of) The response is:
"cpu_stats" : {
"cpu_usage" : {
"percpu_usage" : [
8646879,
24472255,
36438778,
30657443
],
"usage_in_usermode" : 50000000,
"total_usage" : 100215355,
"usage_in_kernelmode" : 30000000
},
"system_cpu_usage" : 739306590000000,
"throttling_data" : {"periods":0,"throttled_periods":0,"throttled_time":0}
},
"precpu_stats" : {
"cpu_usage" : {
"percpu_usage" : [
8646879,
24350896,
36438778,
30657443
],
"usage_in_usermode" : 50000000,
"total_usage" : 100093996,
"usage_in_kernelmode" : 30000000
},
"system_cpu_usage" : 9492140000000,
"throttling_data" : {"periods":0,"throttled_periods":0,"throttled_time":0}
}
Example taken from Docker docs:
https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#get-container-stats-based-on-resource-usage
When testing with a sample container, values are almost the same.
Example of an output:
#Cpu stas
{u'cpu_usage': {u'usage_in_usermode': 0, u'total_usage': 36569630, u'percpu_usage': [8618616, 3086454, 16466404, 8398156], u'usage_in_kernelmode': 20000000}, u'system_cpu_usage': 339324470000000, u'throttling_data': {u'throttled_time': 0, u'periods': 0, u'throttled_periods': 0}}
#Per cup stats
{u'cpu_usage': {u'usage_in_usermode': 0, u'total_usage': 36569630, u'percpu_usage': [8618616, 3086454, 16466404, 8398156], u'usage_in_kernelmode': 20000000}, u'system_cpu_usage': 339320550000000, u'throttling_data': {u'throttled_time': 0, u'periods': 0, u'throttled_periods': 0}}
I tried also to compare specific metrics in the two case for 4 containers:
#First container
359727340000000 #CPU Stats
359723390000000 #Per CPU Stats
#2
359735220000000
359731290000000
#3
359743100000000
359739170000000
#4
359750940000000
359747000000000
The values above are almost same (some differences but not huge - may be because there are some ms between each request.)
In the official documentation:
The precpu_stats is the cpu statistic of last read, which is used for
calculating the cpu usage percent. It is not the exact copy of the
“cpu_stats” field.
Not very clear for me.
Anyone could explain better ?

Resources