QEMU's -cpu arm1136 emulation stopped working in the 2.6.35 and later kernels, now QEMU dies early in the kernel boot with:
qemu: fatal: Unimplemented cp15 register write (c13, c0, {0, 3}) This is due to this change to the Linux kernel: commit f159f4ed55bb0fa5470800641e03a13a7e0eae6e Author: Tony Lindgren <t...@atomide.com> Date: Mon Jul 5 14:53:10 2010 +0100 ARM: 6207/1: Replace CONFIG_HAS_TLS_REG with HWCAP_TLS and check for it on V6 The TLS register is only available on ARM1136 r1p0 and later. Set HWCAP_TLS flags if hardware TLS is available and test for it if CONFIG_CPU_32v6K is not set for V6. Which does is remove the CONFIG_HAS_TLS_REG kernel config symbol, and replaces it with a probe. I.E. this code: +++ b/arch/arm/kernel/entry-armv.S -#if defined(CONFIG_HAS_TLS_REG) - mcr p15, 0, r3, c13, c0, 3 @ set TLS register -#elif !defined(CONFIG_TLS_REG_EMUL) - mov r4, #0xffff0fff - str r3, [r4, #-15] @ TLS val at 0xffff0ff0 -#endif Becomes this code: +++ b/arch/arm/include/asm/hwcap.h +#define HWCAP_TLS 32768 + .macro set_tls_v6, tp, tmp1, tmp2 + ldr \tmp1, =elf_hwcap + ldr \tmp1, [\tmp1, #0] + mov \tmp2, #0xffff0fff + tst \tmp1, #HWCAP_TLS @ hardware TLS available? + mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register + streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0 + .endm The elf_hwcap variable with the HWCAP_TLS bit is initialized (in mm/proc-v6.S) with HWCAP_TLS always set, and then this switches it off: +static void __init feat_v6_fixup(void) +{ + int id = read_cpuid_id(); + + if ((id & 0xff0f0000) != 0x41070000) + return; + + /* + * HWCAP_TLS is available only on 1136 r1p0 and later, + * see also kuser_get_tls_init. + */ + if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0)) + elf_hwcap &= ~HWCAP_TLS; +} + The CPUID for arm1136 QEMU emulates a process that should have hardware TLS (target-arm/cpu.h): #define ARM_CPUID_ARM1136 0x4117b363 Meaning the above "switch it off" test doesn't trigger, the kernel tries to access a hardware feature QEMU doesn't emulate, and QEMU aborts. Note: I can work around this with -cpu arm1136-r2 (0x4107b363), but it seems like the correct fix would be to add "hardware" TLS support to arm kernels. Is this currently on anybody's todo list? (Is there a data sheet somewhere...?) Rob