ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Your example was written in C. Among many other things done by the compiler as it generates the machine-code translation of your source code, the compiler sets up the user stack for your program. This stack is used to handle the return address from each called subroutine, the parameters, and the local automatic variables used within the subroutine. That is, you do not need to set up the stack, the compiler and linker and loader set up a stack for you. This involves initializing the stack segment register and the stack pointer register, along with allocating some address space for the stack. The allocated space should be initialized to all zeros somewhere along the way, probably by writing a zero dword to some address and block copying the zero dword through the entire block allocated to the stack. Setting up the preamble code and exit code is a large part of the reason that a simple hello, world program is as large as it is. The actual part of the program that prints hello, world is twenty bytes or so from your source code and perhaps a hundred bytes or so from the required routine in the stdio library.
If you wish to look at the assembly language code generated by a simple program, you can tell cc to keep the assembly language output in file and look at it with a text editor. For this you may wish to use an even simpler program than hello, world, something like
Code:
void main(void)
{
return;
};
Your system may require a more complicated declaration for main(), in which case you may need to make the program slightly more complicated. I hope you get the idea.
The references in the previous responses involve setting up a stack of program data items. This typically involves defining a struct which contains a pointer to its own type to link it into the stack, and data and/or pointers to data that you want the stack to contain.
I hope this is not too confusing. I am just trying to make a distinction between the hardware machine-level stack implemented with the stack pointer register and the user-level implementation of data stacks.
Your example was written in C. Among many other things done by the compiler as it generates the machine-code translation of your source code, the compiler sets up the user stack for your program.
Sorry, we are talking about LKM (Loadable Kernel Module) here.
But maybe you can say how to define the stack so it get maybe 1 kilo byte big no more or less so I get a working stack in my LKM (GDT or LDT task).
The stack have to be setup by ld (mem) and maybe a kernel function.
Oh, wait maybe a syscall can do it? ... - No.
Yes, it could be a multicore (4-core) issue that the kernel's stack is in an other core than the module is loaded to. That it could explain, why the stack did work some time.
Does anybody know something about this issue? - and maybe a solution or how to setup a working stack? (hint: ENTER does not work, because it needs a working stack)
Can the kernel be configured to only load modules into its core?
I recommend Linux Device Drivers by Corbett, Rubini, and Kroah-Hartman (ISBN 978-0-596-00590-0). They address the problem of limited kernel stack. They point out that the stack for the entire kernel may be as small as 4096 bytes, so one must be careful to use it sparingly. If you need large data structures in your module, then you should attempt to allocate the memory you need with kmalloc when the module is loaded and handle it yourself.
I sometimes make stacks by defining a list node structure which includes a pointer to its own type and contains fields for data. An empty stack is simply a structure including a NULL pointer to a list node and fields for book keeping. Then I allocate an array of such structs. I usually define an unused-node stack and push all the nodes in the array on that unused-nodes stack. As I need nodes for data, I pop them from the unused-nodes stack, fill the data fields, and insert them in the in-use stack or, more often, an in-use queue. When the data consumer has used the data, it can be popped from the in-use stack or dequeued from the in-use queue and pushed back onto the unused-nodes stack.
The book keeping fields in the stacks and queues may include synchronization objects to prevent corruption by interleaved accesses of data producers and consumers if these can be in independent threads.
On the other hand, there should be enough stack to handle any reasonable number of calls in a kernel module. You do have use of the kernel stack. Deeply nested recursion in kernel modules could possibly crash the system and cause loss of information.
They point out that the stack for the entire kernel may be as small as 4096 bytes...
I sometimes make stacks...
On the other hand, there should be enough stack to handle any reasonable number of calls in a kernel module. You do have use of the kernel stack.
Yes, I know that a kernel stack is very small but it should take 10 bytes for a call in any case, else an interrupt would crash the core on return.
If you make stacks yourself how do you set the stack (GDT, LDT) that SS gets the right entrance? And it should be done before my init function is called from the kernel.
Problem characteristics:
- module loads
- init function is called by the kernel
- init function does call other functions(values)
- values never reach the called functions
- even with hard coded stack handel (push pop) it does not work
- it doesn't make difference in which way the module is loaded
at least dozens of levels of stack should be available
Yes, you should expect that you have at least dozens or hundreds of levels of stack available to your kernel module. You should not run out of stack space even with a long parameter list.
How are you tracing the parameters? My first line of attack is sprinkling printk() calls through the routines. If the calling routine reports the parameters before the call, and the called routine immediately reports the parameters on entry, the values should match.
Another issue is that any allocation by kmalloc() can fail, just as any call to malloc() can fail out in user code. I presume you are testing the allocation for failure.
My discussion of stack implementation relates only to stacks of local data. You should not need to manipulate the system stack. I believe it is possible to allocate larger system stack when you configure a system. If you do allocate more kernel memory to the stack, you remove it from availability for any other use.
How are you tracing the parameters?
printk()
Another issue is that any allocation by kmalloc() can fail
You should not need to manipulate the system stack.
My parameters are func(int, int32, char) it should have enough space for these on the stack.
ESP has also a good value!
Yes, I use printk() for debugging.
I don't allocate memory anywhere it is all linked memory and only a view bytes.
That with the stack is only a thing of debugging to get more hints and to work out the problem.
I searched through the stack 100 bytes up and down - nowhere my parameters!
ESP, EBP, EBX don't point to or have possible C values. The only values on the stack are right set return values. Even if I exchange the parameter by assembler the stack looks the same - zeroed.
I can imagine that linux kernel has to do something with it. Maybe the kernel doesn't want to alow function calls while module initialization - security manner. In this case I have to code directly in the kernel's code.
My task is to programm a new feature into the kernel and I first wanted to test it as module. It is also faster like to reboot all the time.
separate stack pointer and data size conflicts in kernel mode
The kernel has its own separate stack pointer which overlays the user stack pointer while the processor is in kernel mode. Thus, it may be futile to look at the stack frame for your data. It is on a different stack. You might try writing a dummy routine in the kernel module which prints the parameters with printk() and then calls the kernel routine you really wanted to call.
There is a considerable hazard that the data types in the kernel may be a different size than the data types in user space. In kernel mode, you can always be certain of the size and types of the following data types defined in <asm/types.h> included by <linux/types.h>:
Code:
u8, s8 unsigned and signed 8 bits
u16, s16 unsigned and signed 16 bits
u32, s32 unsigned and signed 32 bits
u64, s64 unsigned and signed 64 bits
Casting your data to one of these types for all kernel-mode routines should ensure that you avoid size mismatch. A size mismatch would cause a stack imbalance, which would cause the symptoms you described. C may treat char as int, so you may wish to avoid the 8-bit types outside of I/O routines involving 8-bit data devices.
These types are Linux specific. This hinders porting modules to other Unix systems.
Floating point is not generally supported in kernel routines.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.