Hi all, The patch below change the get_physical_address() function to support 64-bit addresses in the MMU. Other parts of the MMU implementation probably have to be fixed to get a full 64-bit support. For example the refill vector should be XTLB instead of TLB for a 64-bit address.
With this patch I have been able to get a 64-bit kernel to print a few things (see below), this is already a good start. Also note that the patch fixes the mapping of the useg segment when ERL = 1. It should be unmapped only from kernel (kuseg) mode, not from supervisor (suseg) or user mode (useg). Cheers, Aurelien (qemu) Linux version 2.6.21.1 ([EMAIL PROTECTED]) (gcc version 4.1.1 ()) #1 Sun May 6 21:43:32 CEST 2007 LINUX started... CPU revision is: 00000400 FPU revision is: 00730400 registering PCI controller with io_map_base unset Determined physical RAM map: memory: 0000000000001000 @ 0000000000000000 (reserved) memory: 00000000000ef000 @ 0000000000001000 (ROM data) memory: 0000000000464000 @ 00000000000f0000 (reserved) memory: 0000000007aab000 @ 0000000000554000 (usable) Wasting 76384 bytes for tracking 1364 unused pages Index: target-mips/helper.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/helper.c,v retrieving revision 1.36 diff -u -d -p -r1.36 helper.c --- target-mips/helper.c 7 May 2007 13:55:33 -0000 1.36 +++ target-mips/helper.c 8 May 2007 21:50:52 -0000 @@ -77,8 +77,13 @@ static int get_physical_address (CPUStat int *prot, target_ulong address, int rw, int access_type) { - /* User mode can only access useg */ + /* User mode can only access useg/xuseg */ int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; +#ifdef TARGET_MIPS64 + int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; + int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; + int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; +#endif int ret = TLBRET_MATCH; #if 0 @@ -87,10 +92,18 @@ static int get_physical_address (CPUStat user_mode, env->hflags); } #endif + +#ifdef TARGET_MIPS64 + if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL) + return TLBRET_BADADDR; +#else if (user_mode && address > 0x7FFFFFFFUL) return TLBRET_BADADDR; - if (address < (int32_t)0x80000000UL) { - if (!(env->CP0_Status & (1 << CP0St_ERL))) { +#endif + + if (address <= (int32_t)0x7FFFFFFFUL) { + /* useg */ + if (!(env->CP0_Status & (1 << CP0St_ERL) && user_mode)) { #ifdef MIPS_USES_R4K_TLB ret = map_address(env, physical, prot, address, rw, access_type); #else @@ -101,6 +114,45 @@ static int get_physical_address (CPUStat *physical = address; *prot = PAGE_READ | PAGE_WRITE; } +#ifdef TARGET_MIPS64 +/* + XXX: Assuming : + - PABITS = 36 (correct for MIPS64R1) + - SEGBITS = 40 +*/ + } else if (address < 0x3FFFFFFFFFFFFFFFULL) { + /* xuseg */ + if (UX && address < 0x000000FFFFFFFFFFULL) { + ret = map_address(env, physical, prot, address, rw, access_type); + } else { + ret = TLBRET_BADADDR; + } + } else if (address < 0x7FFFFFFFFFFFFFFFULL) { + /* xsseg */ + if (SX && address < 0x400000FFFFFFFFFFULL) { + ret = map_address(env, physical, prot, address, rw, access_type); + } else { + ret = TLBRET_BADADDR; + } + } else if (address < 0xBFFFFFFFFFFFFFFFULL) { + /* xkphys */ + /* XXX: check supervisor mode */ + if (KX && (address & 0x03FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) + { + *physical = address & 0X000000FFFFFFFFFFULL; + *prot = PAGE_READ | PAGE_WRITE; + } else { + ret = TLBRET_BADADDR; + } + } else if (address < 0xFFFFFFFF7FFFFFFFULL) { + /* xkseg */ + /* XXX: check supervisor mode */ + if (KX && address < 0xC00000FF7FFFFFFFULL) { + ret = map_address(env, physical, prot, address, rw, access_type); + } else { + ret = TLBRET_BADADDR; + } +#endif } else if (address < (int32_t)0xA0000000UL) { /* kseg0 */ /* XXX: check supervisor mode */ @@ -116,7 +168,7 @@ static int get_physical_address (CPUStat #ifdef MIPS_USES_R4K_TLB ret = map_address(env, physical, prot, address, rw, access_type); #else - *physical = address; + *physical = address & 0xFFFFFFFF; *prot = PAGE_READ | PAGE_WRITE; #endif } else { @@ -126,7 +178,7 @@ static int get_physical_address (CPUStat #ifdef MIPS_USES_R4K_TLB ret = map_address(env, physical, prot, address, rw, access_type); #else - *physical = address; + *physical = address & 0xFFFFFFFF; *prot = PAGE_READ | PAGE_WRITE; #endif } -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [EMAIL PROTECTED] | [EMAIL PROTECTED] `- people.debian.org/~aurel32 | www.aurel32.net