Processor affinity settings for Linux kernel modules? - linux-kernel

In Windows, I can set the processor affinity of driver code using KeSetSystemAffinityThread, and check which processor my code is running on using KeGetCurrentProcessorNumber.
I'm trying to do something similar in a Linux kernel module, but the only affinity calls I can see are for userland processes. Is there any way to do this, so that I can run assembly code on a specific processor? (i.e. sgdt)
Edit:
I think I've figured out how to get the current processor. smp_processor_id() seems like it should work.

I think you'll probably have to modify the kernel, but the change isn't too rough. Just export sched_setaffinity in sched.c to modules:
long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
{
...
}
+ EXPORT_SYMBOL_GPL(sched_setaffinity); // Exported, now callable from your code.

smp_processor_id() should tell you what logical processor you're running on.
Some architectures also support the smp_call_function_single kernel function that will use an inter-processor-interrupt to run a function on another processor.

Related

how to trigger c program when kernel variable changes

I am new to linux kernel programming.
Currently, I use debugfs to output the value of a kernel variable (say myKernelVariable) to a file, say, debugfs/myFile
What I want to do is this: I want to use a user-level program (prefer C, but python also works for me) that when the value of myKernelVariable in debugfs/myFile is changed, my user-level program will be notified.
A very inefficient way is that I can set up a timer in my user-level program and repeatedly check if the value in debugfs/myFile is changed.
Are there any trigger/notify - based lightweight methods to do this?
Thanks very much.

Call an instruction on a specific core in kernel

I know that I can call a function on a selected set of cores in Linux kernel by using smp_call_function_single() [1].
What if I only want to execute an instruction, say rdmsr, on a specific core?
I know that I can wrap it as a function, but I think it is too expensive since I only execute one instruction.
Does anyone know if it is possible to call an instruction on a specific core in Linux kernel or Xen kernel?
Thank you very much for your help!
[1] http://lxr.free-electrons.com/source/kernel/smp.c#L271.

Linux kernel detecting the pre-boot environment for watchdog

So I'm developing for an embedded Linux system and we had some trouble with an external watchdog chip which needed to be fed very early in the boot process.
More specifically, from what we could work out it would this external watchdog would cause a reset while the kernel was decompressing its image in the pre-boot environment. Not enough down time before it starts needing to be fed, which should probably have been sorted in hardware as it is external, but an internal software solution is wanted.
The solution from one of our developers was to put in some extra code into...
int zlib_inflate(z_streamp strm, int flush) in the lib/zlib_inflate/inflate.c kernel code
This new code periodically toggles the watchdog pin during the decompression.
Now besides the fact that I feel like this is a little bit of a dirty hack. It does work, and it has raised an interesting point in my mind. Because this lib is used after boot as well. So is there a nice way for a bit of code detecting whether you're in the pre-boot environment? So it could only preform this toggling pre-boot and not when the lib is used later.
As an aside, I'm also interested in any ideas to avoid the hack in the first place.
So is there a nice way for a bit of code detecting whether you're in the pre-boot environment?
You're asking an XY question.
The solution to the X problem can be cleanly solved if you are using U-Boot.
(BTW instead of "pre-boot", i.e. before boot, you probably mean "boot", i.e. before the kernel is started.)
If you're using U-Boot in the boot sequence, then you do not have to hack any boot or kernel code. Apparently you are booting a self-extracting compressed kernel in a zImage (or a zImage within a uImage) file. The hack-free solution is described by U-Boot's author/maintainer, Wolfgang Denk:
It is much better to use normal (uncompressed) kernel image, compress it
using just gzip, and use this as poayload for mkimage. This way
U-Boot does the uncompresiong instead of including yet another
uncompressor with each kernel image.
So instead of make uImage, do a simple make.
Compress the Image file, and then encapsulate it with the U-Boot wrapper using mkimage (and specify the compression algorithm that was applied so that U-Boot can use its built-in decompressor) to produce your uImage file.
When U-Boot loads this uImage file, the wrapper will indicate that it's a compressed file.
U-Boot will execute its internal decompressor library, which (in recent versions) is already watchdog aware.
Quick and dirty solution off the top of my head:
Make a global static variable in the file that's initialized to 1, and as long as it's 1, consider that "pre-boot".
Add a *_initcall (choose whichever fits your needs. I'm not sure when the kernel is decompressed) to set it to 0.
See include/linux/init.h in the kernel tree for initcall levels.
See #sawdust answer for an answer on how to achieve the watchdog feeding without having to hack the kernel code.
However this does not fully address the original question of how to detect that code is being compiled in the "pre-boot environment", as it is called within kernel source.
Files within the kernel such as ...
include/linux/decompress/mm.h
lib/decompress_inflate.c
And to a lesser extent (it isn't commented as clearly)...
lib/decompress_unlzo.c
Seem to check the STATIC definition to set "pre-boot environment" differences. Such as in this excerpt from include/linux/decompress/mm.h ...
#ifdef STATIC
/* Code active when included from pre-boot environment: */
...
#else /* STATIC */
/* Code active when compiled standalone for use when loading ramdisk: */
...
#endif /* STATIC */
Another idea can be disabling watchdog from bootloader and enabling it from user space once system has booted completely.

Set linux power state from kernel module?

I have a little driver that is handling a gpio that when enabled should tell the system to sleep/wake when a button is pressed. If its held down it should power off.
On WinCE there is a very easy to use mechanism (SetSystemPowerState) but there doesn't appear to be something similar on linux.
We also don't have dbus...
update:
I may have found the answer
Shutdown (embedded) linux from kernel-space
Though it doesn't really say how to sleep but i think I'll be able to figure the rest out. This doesn't seem like the proper way to handle a linux kernel driver since the module is built into the kernel. It doesn't appear that I have all the power states available to switch to without adding packages outside of the kernel.
If you want to suspend your system entirely, you can use /sys/power/state interface like belows.
echo "mem" > /sys/power/state
It calls state_store() function in kernel/power/main.c to suspend your system into memory. Instead of "mem", you can use "standby" or "disk" only if your system supports them.
The most general way would be to initiate the process from kernelspace as a userspace helper:
static const char * const set_power_argv[] =
{ "/bin/echo", "mem", "/sys/power/state", NULL };
call_usermodehelper(shutdown_argv[0], shutdown_argv, NULL, UMH_NO_WAIT);
However, location of echo command and power driver can differ in your system.

How can I shrink the OS region in RAM through U-boot?

From my understanding, after a PC/embedded system booted up, the OS will occupy the entire RAM region, the RAM will look like this:
Which means, while I'm running a program I write, all the variables, dynamic memory allocated in the stacks, heaps and etc, will remain inside the region. If I run firefox, paint, gedit, etc, they will also be running in this region. (Is this understanding correct?)
However, I would like to shrink the OS region. Below is an illustration of how I want to divide the RAM:
The reason that I want to do this is because, I want to store some data receive externally through the driver into the Custom Region at fixed physical location, then I will be able to access it directly from the user space without using copy_to_user().
I think it is possible to do that by configuring u-boot, but I have no experience in u-boot, can anyone give me some directions where to begin with, such as: do I need to modify the source of u-boot, or changing the environment variables of u-boot will be sufficient?
Or is there any alternative method of doing this?
Any help is much appreciated. Thanks!
p/s: I'm using TI ARM processor, and booting up from an SD card, I'm not sure if it matters.
The platform is ARM. min_addr and max_addr will not work on these platform since these are for Intel-only implementations.
For the ARM platform try to look at "mem=size#start" kernel parameter. Read up on Documentation/kernel-parameters.txt and arch/arm/kernel/setup.c. This option is available on most new Linux code base (ie. 2.6.XX).
You need to set the following parameters:
max_addr=some_max_physical
min_addr=some_min_physical
to be passed to the kernel through uboot in the 'bootargs' u-boot environment variable.
I found myself trying to do the opposite recently - in other words get Linux to use the additional memory in my system - although I'm using Barebox rather than u-boot on a OMAP4 platform.
I found (a bit to my surprise) that once the Barebox MLO first stage boot-loader was aware of the extra RAM, the kernel then detected and used it as well without any bootargs. Since the memory size is not passed anywhere on the boot-line, I can only assume the kernel inspects the memory mappings set up by the boot-loader to determine RAM size. This suggests that modifying your u-boot to not map all of the RAM is the way to go.
On the subject of boot-args, there was a time when you it was recommended that you mapped out a chunk of RAM (used by the frame buffer?) on OMAP4 systems, using the boot-line. It's still unclear whether this is still necessary.

Resources