Skip to contentSkip to conversation

x86-32: A better system call mechanism

PATCH In review H. Peter Anvin 2 participants 3 messages Apr 1, 2012 x86

lore
Share & tools
lore

H. Peter Anvin

author reviewer
#0 lore raw

PATCH 1/1 x86-32: A better system call mechanism

On x86-32, we currently use int $0x80 as the primary system call mechanism. Although there are some recent variants available on certain hardware (sysenter, syscall) via the vdso, the primary system call vector is still way up the interrupt vector table, which is inefficient.

This patch adds a very small amount of code which permits the very first vector to be used for system call. That vector is #DE, divide error, generally known as division by zero.

An example of how to use this new system call mechanism:

.text
.globl _start
_start:

	movl $__NR_write, %eax
	movl $1, %ebx
	movl $str_1, %ecx
	movl $str_1_len, %edx
	aam $0

	movl $__NR_write, %eax
	movl $1, %ebx
	movl $str_2, %ecx
	movl $str_2_len, %edx
	divl %edx

	movl $__NR_exit, %eax
	xorl %ebx, %ebx
	divl %edx

	.type	_start, @function
	.size	_start, . - _start

	.section ".rodata", "a"
	.balign	128

str_1:
.ascii "This works!\n"
str_1_len = . - str_1

str_2:
.ascii "This works too!\n"
str_2_len = . - str_2

We use the shortest forms of the relevant instructions only, for simplicity. Why these mechanisms work is left as a trivial exercise to the reader.

---
 arch/x86/kernel/entry_32.S |    5 ++++-
 arch/x86/kernel/traps.c    |    3 ++-
 2 files changed, 6 insertions(+), 2 deletions(-)
arch/x86/kernel/entry_32.S +4 -1
index 7b784f4..0dfe246 100644
@@ -497,7 +497,10 @@ ENDPROC(ia32_sysenter_target)
  */
 	.pushsection .kprobes.text, "ax"
 	# system call handler stub
-ENTRY(system_call)
+ENTRY(system_call_divide_error)
+	addl $2,(%esp)			# Skip past the faulting instruction
+	.globl system_call		# Don't use ENTRY because of padding
+system_call:
 	RING0_INT_FRAME			# can't unwind into user space anyway
 	pushl_cfi %eax			# save orig_eax
 	SAVE_ALL
arch/x86/kernel/traps.c +2 -1
index ff9281f1..d5bd411 100644
@@ -67,6 +67,7 @@
 #include <asm/setup.h>
 
 asmlinkage int system_call(void);
+asmlinkage int system_call_divide_error(void);
 
 /* Do we ignore FPU interrupts ? */
 char ignore_fpu_irq;
@@ -679,7 +680,7 @@ void __init trap_init(void)
 	early_iounmap(p, 4);
 #endif
 
-	set_intr_gate(X86_TRAP_DE, &divide_error);
+	set_system_trap_gate(X86_TRAP_DE, &system_call_divide_error);
 	set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
 	/* int4 can be called from all */
 	set_system_intr_gate(X86_TRAP_OF, &overflow);
Signature · 1 line
1.7.6.5
#1 lore raw

Hi Peter,

Quoted 9 lines · H. Peter Anvin

On x86-32, we currently use int $0x80 as the primary system call mechanism. Although there are some recent variants available on certain hardware (sysenter, syscall) via the vdso, the primary system call vector is still way up the interrupt vector table, which is inefficient.

This patch adds a very small amount of code which permits the very first vector to be used for system call. That vector is #DE, divide error, generally known as division by zero.

Looks like a clever trick, but beyond the beauty, what does it really save ? Code size is the same as aam 0 / div edx are both 2-byte long, just like int 0x80. Is the call less expensive ? And if so, how does it compare to vdso ?

Thanks,
Willy

#2 lore raw
Quoted 9 lines · Willy Tarreau

Hi Peter,

Quoted 6 lines · H. Peter Anvin

On x86-32, we currently use int $0x80 as the primary system call mechanism. Although there are some recent variants available on certain hardware (sysenter, syscall) via the vdso, the primary system call vector is still way up the interrupt vector table, which is inefficient.

Quoted 8 lines
Quoted 3 lines

This patch adds a very small amount of code which permits the very first vector to be used for system call. That vector is #DE, divide error, generally known as division by zero.

Looks like a clever trick, but beyond the beauty, what does it really save ? Code size is the same as aam 0 / div edx are both 2-byte long, just like int 0x80. Is the call less expensive ? And if so, how does it compare to vdso ?

Hmmm I think I just found the response in the Date header, time to get some coffee :-)

Willy