x86: Make support for 16-bit segments a config option Embedded systems and the like are likely never going to experience 16-bit software, so make it an option to reject them entirely and not carry any of the overhead. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 25d2c6f..f1da8b1 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig
@@ -914,6 +914,14 @@ XFree86 to initialize some video cards via BIOS. Disabling this option saves about 6k. +config X86_16BIT + bool "Enable 16-bit segments" if EXPERT + default y + ---help--- + This option enables the execution of 16-bit protected mode + software. This is primarily used to run Win16 software + under Wine and 16-bit extended DOS programs under DOSEMU. + config TOSHIBA tristate "Toshiba Laptop support" depends on X86_32
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 2780b8f..30dd6e5 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S
@@ -527,6 +527,7 @@ restore_all: TRACE_IRQS_IRET restore_all_notrace: +#ifdef CONFIG_X86_16BIT movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS # Warning: PT_OLDSS(%esp) contains the wrong/random values if we # are returning to the kernel. @@ -537,6 +538,7 @@ cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax CFI_REMEMBER_STATE je ldt_ss # returning to user-space with LDT SS +#endif restore_nocheck: RESTORE_REGS 4 # skip orig_eax/error_code irq_return: @@ -549,6 +551,7 @@ .previous _ASM_EXTABLE(irq_return,iret_exc) +#ifdef CONFIG_X86_16BIT CFI_RESTORE_STATE ldt_ss: #ifdef CONFIG_PARAVIRT @@ -592,6 +595,7 @@ lss (%esp), %esp /* switch to espfix segment */ CFI_ADJUST_CFA_OFFSET -8 jmp restore_nocheck +#endif /* CONFIG_X86_16BIT */ CFI_ENDPROC ENDPROC(system_call) @@ -692,6 +696,7 @@ .popsection .macro FIXUP_ESPFIX_STACK +#ifdef CONFIG_X86_16BIT /* * Switch back for ESPFIX stack to the normal zerobased stack * @@ -708,8 +713,10 @@ pushl_cfi %eax lss (%esp), %esp /* switch to the normal stack segment */ CFI_ADJUST_CFA_OFFSET -8 +#endif .endm .macro UNWIND_ESPFIX_STACK +#ifdef CONFIG_X86_16BIT movl %ss, %eax /* see if on espfix stack */ cmpw $__ESPFIX_SS, %ax @@ -720,6 +727,7 @@ /* switch to normal stack */ FIXUP_ESPFIX_STACK 27: +#endif .endm /* @@ -1350,11 +1358,13 @@ ENTRY(nmi) RING0_INT_FRAME ASM_CLAC +#ifdef CONFIG_X86_16BIT pushl_cfi %eax movl %ss, %eax cmpw $__ESPFIX_SS, %ax popl_cfi %eax je nmi_espfix_stack +#endif cmpl $ia32_sysenter_target,(%esp) je nmi_stack_fixup pushl_cfi %eax @@ -1394,6 +1404,7 @@ FIX_STACK 24, nmi_stack_correct, 1 jmp nmi_stack_correct +#ifdef CONFIG_X86_16BIT nmi_espfix_stack: /* We have a RING0_INT_FRAME here. * @@ -1415,6 +1426,8 @@ lss 12+4(%esp), %esp # back to espfix stack CFI_ADJUST_CFA_OFFSET -24 jmp irq_return +#endif /* CONFIG_X86_16BIT */ + CFI_ENDPROC END(nmi)
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index af1d14a..cc34ae8 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c
@@ -229,11 +229,7 @@ } } - /* - * On x86-64 we do not support 16-bit segments due to - * IRET leaking the high bits of the kernel stack address. - */ -#ifdef CONFIG_X86_64 +#ifndef CONFIG_X86_16BIT if (!ldt_info.seg_32bit) { error = -EINVAL; goto out_unlock;