Prev: [PATCH -next] mtd/nand/r852: fix build for CONFIG_PM=n
Next: [PATCH 3/3] time: Kill off CONFIG_GENERIC_TIME
From: Matteo Croce on 1 Mar 2010 17:10 Hi, I have refreshed my AMD Geode i686 patch with NOPL and I have added a new nice feature. When a NOPL is found the parser looks for any NOPL after the current one, so they are emulated in bulk. Tested ok on a Pcengines Alix. Signed-off-by: Matteo Croce <technoboy85(a)gmail.com> --- a/arch/x86/kernel/Makefile 2010-03-01 01:18:51.697166322 +0100 +++ b/arch/x86/kernel/Makefile 2010-03-01 01:19:45.727095700 +0100 @@ -89,6 +89,8 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_K8_NB) += k8.o +obj-$(CONFIG_MGEODEGX1) += nopl_emu.o +obj-$(CONFIG_MGEODE_LX) += nopl_emu.o obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o --- a/arch/x86/kernel/cpu/amd.c 2010-03-01 01:18:51.737097341 +0100 +++ b/arch/x86/kernel/cpu/amd.c 2010-03-01 01:19:27.867865836 +0100 @@ -138,8 +138,10 @@ } if (c->x86_model == 10) { - /Index: linux-2.6.33/arch/x86/kernel/Makefile =================================================================== * AMD Geode LX is model 10 */ - /* placeholder for any needed mods */ + /* Geode only lacks the NOPL instruction to be i686, + but we can emulate it in the exception handler + and promote it to a class 6 cpu */ + boot_cpu_data.x86 = 6; return; } } --- a/arch/x86/kernel/entry_32.S 2010-03-01 01:18:51.717096708 +0100 +++ b/arch/x86/kernel/entry_32.S 2010-03-01 01:19:27.867865836 +0100 @@ -960,7 +960,11 @@ RING0_INT_FRAME pushl $0 CFI_ADJUST_CFA_OFFSET 4 +#ifdef CONFIG_MGEODE_LX + pushl $do_nopl_emu +#else pushl $do_invalid_op +#endif CFI_ADJUST_CFA_OFFSET 4 jmp error_code CFI_ENDPROC --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ b/arch/x86/kernel/nopl_emu.c 2010-03-01 02:40:44.324595733 +0100 @@ -0,0 +1,107 @@ +/* + * linux/arch/x86/kernel/nopl_emu.c + * + * Copyright (C) 2002 Willy Tarreau + * Copyright (C) 2010 Matteo Croce + */ + +#include <asm/processor.h> +#include <asm/traps.h> + +/* This code can be used to allow the AMD Geode to hopefully correctly execute + * some code which was originally compiled for an i686, by emulating NOPL, + * the only missing i686 instruction in the CPU + * + * Willy Tarreau <willy(a)meta-x.org> + * Matteo Croce <technoboy85(a)gmail.com> + */ + +static inline int do_1f(u8 *ip) +{ + int length = 3; + switch (*ip) { + case 0x84: + if (!ip[5]) + length++; + else + return 0; + case 0x80: + if (!ip[4] && !ip[3]) + length += 2; + else + return 0; + case 0x44: + if (!ip[2]) + length++; + else + return 0; + case 0x40: + if (!ip[1]) + length++; + else + return 0; + case 0x00: + return length; + } + return 0; +} + +static inline int do_0f(u8 *ip) +{ + if (*ip == 0x1f) + return do_1f(ip + 1); + return 0; +} + +static inline int do_66(u8 *ip) +{ + if (*ip == 0x90) + return 2; + if (*ip == 0x0f) { + int res = do_0f(ip + 1); + if (res) + return res + 1; + else + return 0; + } + return 0; +} + +static inline int do_start(u8 *ip) +{ + if (*ip == 0x0f) + return do_0f(ip + 1); + if (*ip == 0x66) + return do_66(ip + 1); + return 0; +} + +/* [do_nopl_emu] is called by exception 6 after an invalid opcode has been + * encountered. It will try to emulate it by doing nothing, + * and will send a SIGILL or SIGSEGV to the process if not possible. + * the NOPL can have variable length opcodes: + +bytes number opcode + 2 66 90 + 3 0f 1f 00 + 4 0f 1f 40 00 + 5 0f 1f 44 00 00 + 6 66 0f 1f 44 00 00 + 7 0f 1f 80 00 00 00 00 + 8 0f 1f 84 00 00 00 00 00 + 9 66 0f 1f 84 00 00 00 00 00 +*/ +void do_nopl_emu(struct pt_regs *regs, long error_code) +{ + u8 *ip = (u8 *)instruction_pointer(regs); + int res = do_start(ip); + + if (res) { + do { + ip += res; + res = do_start(ip); + } while (res); + regs->ip = (typeof(regs->ip))ip; + } else + do_invalid_op(regs, error_code); +} -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
From: Brian Gerst on 1 Mar 2010 18:50 On Mon, Mar 1, 2010 at 5:03 PM, Matteo Croce <technoboy85(a)gmail.com> wrote: > Hi, > I have refreshed my AMD Geode i686 patch with NOPL and I have added a > new nice feature. > When a NOPL is found the parser looks for any NOPL after the current > one, so they are emulated in bulk. > Tested ok on a Pcengines Alix. > > Signed-off-by: Matteo Croce <technoboy85(a)gmail.com> 1. Since this can possibly touch userspace, you must use get_user() to read the instruction bytes. 2. This parser is too simple to cover all the possible encodings, not just the recommended ones from the Intel manual. You really should be decoding: - all prefixes (like segment overrides), which can be repeated. - the 0f 1f opcode. - the Mod R/M byte. - the SIB byte (if present). - the displacement. This should probably be part of a more general instruction emulator. -- Brian Gerst -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
From: H. Peter Anvin on 1 Mar 2010 19:00
On 03/01/2010 03:43 PM, Brian Gerst wrote: > > This should probably be part of a more general instruction emulator. > .... as is being developed; see other thread. -hpa -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |