Thread (9 messages) 9 messages, 3 authors, 2011-09-08

Doubt regarding asmlinkage

From: Pei Lin <hidden>
Date: 2011-09-08 11:58:53

2011/9/8 rohan puri [off-list ref]:

On Thu, Sep 8, 2011 at 12:47 PM, Pei Lin [off-list ref] wrote:
quoted
2011/9/8 rohan puri [off-list ref]:
quoted

On Thu, Sep 8, 2011 at 9:50 AM, Mulyadi Santosa
[off-list ref]
wrote:
quoted
Hi :)

On Thu, Sep 8, 2011 at 10:40, rohan puri [off-list ref]
wrote:
quoted
Hi Mulyadi,

Thanks for the response. I do agree with the issue concerning the
no.of
registers available are less for 32 bit to that of 64 bit.

But even in this case if parameters are more than the no of register
for
32
bit, then also before executing int 80h interrupt it stores the
parameters
in the register and after that system call dispatcher puts them on
the
kernel stack of that process. So, how the case where more than no of
registers are the parameters to the system call is handled.

Please don't top post :)

Regarding passing the parameters when it is more than number of
registers used in x86 32 bit, AFAIK it's using EDX to contain the
address of user space memory that contains the data, later it will be
copied to kernel stack IIRC.

--
regards,

Mulyadi Santosa
Freelance Linux trainer and consultant

blog: the-hydra.blogspot.com
training: mulyaditraining.blogspot.com
Sorry for top posting. :)

Got it now. Thanks.

Regards,
Rohan.

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies at kernelnewbies.org
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Kernel newbies website crashed? can not login, only get the snapshot as
below.
http://kernelnewbies.org/FAQ/asmlinkage

FAQ/asmlinkage
What is asmlinkage?
The asmlinkage tag is one other thing that we should observe about
this simple function. This is a #define for some gcc magic that tells
the compiler that the function should not expect to find any of its
arguments in registers (a common optimization), but only on the CPU's
stack. Recall our earlier assertion that system_call consumes its
first argument, the system call number, and allows up to four more
arguments that are passed along to the real system call. system_call
achieves this feat simply by leaving its other arguments (which were
passed to it in registers) on the stack. All system calls are marked
with the asmlinkage tag, so they all look to the stack for arguments.
Of course, in sys_ni_syscall's case, this doesn't make any difference,
because sys_ni_syscall doesn't take any arguments, but it's an issue
for most other system calls. And, because you'll be seeing asmlinkage
in front of many other functions, I thought you should know what it
was about.

It is also used to allow calling a function from assembly files.

There also have explicit explanation in the kernel maillist archive.
Date: ? Sat, 18 Jun 2005 16:29:01 +0200
To: Roy Lee <redacted>


On Sat, 18 Jun 2005 22:00:39 +0800
Roy Lee [off-list ref] wrote:

quoted
It says that "To tell a compiler not to use the argument in the
registers". but the syscall's argument does pass the arguments though
registers, doesn't it?

yes, user space programs put arguments in registers (ebx, ecx, edx...) but
see what happens later...


1) user space programs do something like this:


mov $SYSCALLNUMER, %eax
mov $ARG1, %ebx
mov $ARG2, %ecx
...
int $0x80 ------ go to kernel syscall handler --->



---> arch(i386/kernel/entry.S:


....
? ? ? ?# system call handler stub
ENTRY(system_call)
? ? ? ?pushl %eax # save orig_eax
? ? ? ?SAVE_ALL
? ? ? ?GET_THREAD_INFO(%ebp)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# system call tracing in operation
? ? ? ?/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw
and not testb
?*/ testw
$(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp) jnz
syscall_trace_entry cmpl $(nr_syscalls), %eax
? ? ? ?jae syscall_badsys
syscall_call:
? ? ? ?call *sys_call_table(,%eax,4)
? ? ? ?movl %eax,EAX(%esp) # store the return value
...



notice just these 2 things:


1) SAVE_ALL ---> it's a MACRO that do this:


#define SAVE_ALL \
? ? ? ?cld; \
? ? ? ?pushl %es; \
? ? ? ?pushl %ds; \
? ? ? ?pushl %eax; \
? ? ? ?pushl %ebp; \
? ? ? ?pushl %edi; \
? ? ? ?pushl %esi; \ ....
? ? ? ?pushl %edx; \ > ARG3 <
? ? ? ?pushl %ecx; \ > ARG2 <
? ? ? ?pushl %ebx; \ > ARG1 <
? ? ? ?movl $(__USER_DS), %edx; \
? ? ? ?movl %edx, %ds; \
? ? ? ?movl %edx, %es;


2) call *sys_call_table(,%eax,4)


this calls the "C" system call function



So, since the arguments are passed on the stack (see SAVE_ALL) the "C"
function MUST take them from the stack.


--
Best Regards
Lin
Hi Lin,

Thanks for the information. :)

One thing regarding that asmlinkage FAQ, does the author means process
kernel stack when he indicates the usage of CPU stack?

Also in file,
arch/x86/include/asm/linkage.h : -

/*
?* Make sure the compiler doesn't do anything stupid with the
?* arguments on the stack - they are owned by the *caller*, not
?* the callee. This just fools gcc into not spilling into them,
?* and keeps it from doing tailcall recursion and/or using the
?* stack slots for temporaries, since they are live and "used"
?* all the way to the end of the function.
?*
?* NOTE! On x86-64, all the arguments are in registers, so this
?* only matters on a 32-bit kernel.
?*/

This comment states that it only happens for 32-bit arch and for 64 - bit
arch parameters are kept in registers itself.

Thats why for system_call assembly function, for 32-bit this SAVE_ALL method
is used and for 64-bit this SAVE_ALL method is not used.
Yes, x86-64 expand the general-purpose registers from 8 to 16
The main features include:
 Pointers and long integers are 64 bits long. Integer arithmetic
operations support 8, 16, 32, and 64-bit
data types.
 The set of general-purpose registers is expanded from 8 to 16.
 Much of the program state is held in registers rather than on the
stack. Integer and pointer procedure
arguments (up to 6) are passed via registers. Some procedures do not
need to access the stack at all.
 Conditional operations are implemented using conditional move
instructions when possible, yielding
better performance than traditional branching code.
 Floating-point operations are implemented using a register-oriented
instruction set, rather than the
stack-based approach supported by IA32.

more information as below link:
http://www.cs.cmu.edu/~fp/courses/15213-s07/misc/asm64-handout.pdf

Regards,
Rohan.





-- 
Best Regards
Lin
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help