Compat SYSCALL in Lego¶
Lego does not support compatible syscalls, where one is able to run 32-bit image on 64-bit OS. However, the ugly FPU code and signal part in Linux is heavily hacked with the assumption that compat syscall is supported. We are no expert in this FPU thing, just to make sure we don’t break this FPU evil, Lego adds the fake compat syscall support. Fake means whenever a 32-bit syscall is issued, Lego will just panic.
Kconfig¶
If one compiles a x86_64 Linux kernel, compat syscalls are supported by default. Everything related to compat syscalls are controlled by the following two Kconfig options. Lego may want to support compat syscalls in the future, thus we add these two Kconfigs to avoid future mess:
CONFIG_COMPAT
CONFIG_IA32_EMULATION
Internal¶
Entry Points¶
The assembly entry points are defined in entry/entry_64_compat.S
:
```asm
ENTRY(entry_SYSENTER_compat)
…
call do_fast_syscall_32
GLOBAL(__end_entry_SYSENTER_compat)
ENDPROC(entry_SYSENTER_compat)
ENTRY(entry_SYSCALL_compat) … call do_fast_syscall_32 END(entry_SYSCALL_compat)
ENTRY(entry_INT80_compat) … call do_int80_syscall_32 END(entry_INT80_compat) ```
Entry Points Setup¶
The assembly entry points are filled to system registers and IDT table. So users can actually
issue those calls, Lego is able to catch them:
```c
static void syscall_init(void)
{
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
ifdef CONFIG_IA32_EMULATION¶
1 2 3 4 5 6 7 8 9 10 |
|
else¶
1 2 3 4 |
|
endif¶
1 2 3 4 |
|
} arch/x86/kernel/cpu/common.c
void __init trap_init(void) { …
ifdef CONFIG_IA32_EMULATION¶
1 2 |
|
endif¶
1 |
|
} arch/x86/kernel/traps.c ```
C code¶
The actual C code is in entry/common.c
:
```c
if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)¶
static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) {
ifdef CONFIG_IA32_EMULATION¶
1 |
|
endif¶
1 |
|
}
/* Handles int $0x80 */ __visible void do_int80_syscall_32(struct pt_regs *regs) { BUG(); }
/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */ __visible long do_fast_syscall_32(struct pt_regs *regs) { BUG(); }
endif¶
```
–
Yizhou Shan
Created: Feb 22, 2018
Last Updated: Feb 22, 2018