Commit fcb4a419f52e538b68510a68f30d8834dd211155
1 parent
04f20795
Choose number of TLBs at runtime, by Herve Poussineau.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2693 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
26 additions
and
27 deletions
hw/mips_timer.c
| @@ -10,7 +10,7 @@ uint32_t cpu_mips_get_random (CPUState *env) | @@ -10,7 +10,7 @@ uint32_t cpu_mips_get_random (CPUState *env) | ||
| 10 | static uint32_t seed = 0; | 10 | static uint32_t seed = 0; |
| 11 | uint32_t idx; | 11 | uint32_t idx; |
| 12 | seed = seed * 314159 + 1; | 12 | seed = seed * 314159 + 1; |
| 13 | - idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired; | 13 | + idx = (seed >> 16) % (env->nb_tlb - env->CP0_Wired) + env->CP0_Wired; |
| 14 | return idx; | 14 | return idx; |
| 15 | } | 15 | } |
| 16 | 16 |
target-mips/cpu.h
| @@ -99,6 +99,7 @@ struct CPUMIPSState { | @@ -99,6 +99,7 @@ struct CPUMIPSState { | ||
| 99 | #if defined(MIPS_USES_R4K_TLB) | 99 | #if defined(MIPS_USES_R4K_TLB) |
| 100 | tlb_t tlb[MIPS_TLB_MAX]; | 100 | tlb_t tlb[MIPS_TLB_MAX]; |
| 101 | uint32_t tlb_in_use; | 101 | uint32_t tlb_in_use; |
| 102 | + uint32_t nb_tlb; | ||
| 102 | #endif | 103 | #endif |
| 103 | int32_t CP0_Index; | 104 | int32_t CP0_Index; |
| 104 | int32_t CP0_Random; | 105 | int32_t CP0_Random; |
target-mips/mips-defs.h
| @@ -10,7 +10,6 @@ | @@ -10,7 +10,6 @@ | ||
| 10 | #define TARGET_PAGE_BITS 12 | 10 | #define TARGET_PAGE_BITS 12 |
| 11 | /* Uses MIPS R4Kc TLB model */ | 11 | /* Uses MIPS R4Kc TLB model */ |
| 12 | #define MIPS_USES_R4K_TLB | 12 | #define MIPS_USES_R4K_TLB |
| 13 | -#define MIPS_TLB_NB 16 | ||
| 14 | #define MIPS_TLB_MAX 128 | 13 | #define MIPS_TLB_MAX 128 |
| 15 | 14 | ||
| 16 | #ifdef TARGET_MIPS64 | 15 | #ifdef TARGET_MIPS64 |
target-mips/op.c
| @@ -1270,7 +1270,7 @@ void op_mfc0_desave (void) | @@ -1270,7 +1270,7 @@ void op_mfc0_desave (void) | ||
| 1270 | 1270 | ||
| 1271 | void op_mtc0_index (void) | 1271 | void op_mtc0_index (void) |
| 1272 | { | 1272 | { |
| 1273 | - env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1)); | 1273 | + env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb); |
| 1274 | RETURN(); | 1274 | RETURN(); |
| 1275 | } | 1275 | } |
| 1276 | 1276 | ||
| @@ -1314,7 +1314,7 @@ void op_mtc0_pagegrain (void) | @@ -1314,7 +1314,7 @@ void op_mtc0_pagegrain (void) | ||
| 1314 | 1314 | ||
| 1315 | void op_mtc0_wired (void) | 1315 | void op_mtc0_wired (void) |
| 1316 | { | 1316 | { |
| 1317 | - env->CP0_Wired = T0 & (MIPS_TLB_NB - 1); | 1317 | + env->CP0_Wired = T0 % env->nb_tlb; |
| 1318 | RETURN(); | 1318 | RETURN(); |
| 1319 | } | 1319 | } |
| 1320 | 1320 |
target-mips/op_helper.c
| @@ -394,7 +394,7 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global) | @@ -394,7 +394,7 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global) | ||
| 394 | { | 394 | { |
| 395 | /* Flush qemu's TLB and discard all shadowed entries. */ | 395 | /* Flush qemu's TLB and discard all shadowed entries. */ |
| 396 | tlb_flush (env, flush_global); | 396 | tlb_flush (env, flush_global); |
| 397 | - env->tlb_in_use = MIPS_TLB_NB; | 397 | + env->tlb_in_use = env->nb_tlb; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | static void mips_tlb_flush_extra (CPUState *env, int first) | 400 | static void mips_tlb_flush_extra (CPUState *env, int first) |
| @@ -430,12 +430,10 @@ void do_tlbwi (void) | @@ -430,12 +430,10 @@ void do_tlbwi (void) | ||
| 430 | /* Discard cached TLB entries. We could avoid doing this if the | 430 | /* Discard cached TLB entries. We could avoid doing this if the |
| 431 | tlbwi is just upgrading access permissions on the current entry; | 431 | tlbwi is just upgrading access permissions on the current entry; |
| 432 | that might be a further win. */ | 432 | that might be a further win. */ |
| 433 | - mips_tlb_flush_extra (env, MIPS_TLB_NB); | 433 | + mips_tlb_flush_extra (env, env->nb_tlb); |
| 434 | 434 | ||
| 435 | - /* Wildly undefined effects for CP0_Index containing a too high value and | ||
| 436 | - MIPS_TLB_NB not being a power of two. But so does real silicon. */ | ||
| 437 | - invalidate_tlb(env, env->CP0_Index & (MIPS_TLB_NB - 1), 0); | ||
| 438 | - fill_tlb(env->CP0_Index & (MIPS_TLB_NB - 1)); | 435 | + invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0); |
| 436 | + fill_tlb(env->CP0_Index % env->nb_tlb); | ||
| 439 | } | 437 | } |
| 440 | 438 | ||
| 441 | void do_tlbwr (void) | 439 | void do_tlbwr (void) |
| @@ -455,7 +453,7 @@ void do_tlbp (void) | @@ -455,7 +453,7 @@ void do_tlbp (void) | ||
| 455 | 453 | ||
| 456 | tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; | 454 | tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; |
| 457 | ASID = env->CP0_EntryHi & 0xFF; | 455 | ASID = env->CP0_EntryHi & 0xFF; |
| 458 | - for (i = 0; i < MIPS_TLB_NB; i++) { | 456 | + for (i = 0; i < env->nb_tlb; i++) { |
| 459 | tlb = &env->tlb[i]; | 457 | tlb = &env->tlb[i]; |
| 460 | /* Check ASID, virtual page number & size */ | 458 | /* Check ASID, virtual page number & size */ |
| 461 | if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { | 459 | if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { |
| @@ -464,9 +462,9 @@ void do_tlbp (void) | @@ -464,9 +462,9 @@ void do_tlbp (void) | ||
| 464 | break; | 462 | break; |
| 465 | } | 463 | } |
| 466 | } | 464 | } |
| 467 | - if (i == MIPS_TLB_NB) { | 465 | + if (i == env->nb_tlb) { |
| 468 | /* No match. Discard any shadow entries, if any of them match. */ | 466 | /* No match. Discard any shadow entries, if any of them match. */ |
| 469 | - for (i = MIPS_TLB_NB; i < env->tlb_in_use; i++) { | 467 | + for (i = env->nb_tlb; i < env->tlb_in_use; i++) { |
| 470 | tlb = &env->tlb[i]; | 468 | tlb = &env->tlb[i]; |
| 471 | 469 | ||
| 472 | /* Check ASID, virtual page number & size */ | 470 | /* Check ASID, virtual page number & size */ |
| @@ -486,13 +484,13 @@ void do_tlbr (void) | @@ -486,13 +484,13 @@ void do_tlbr (void) | ||
| 486 | uint8_t ASID; | 484 | uint8_t ASID; |
| 487 | 485 | ||
| 488 | ASID = env->CP0_EntryHi & 0xFF; | 486 | ASID = env->CP0_EntryHi & 0xFF; |
| 489 | - tlb = &env->tlb[env->CP0_Index & (MIPS_TLB_NB - 1)]; | 487 | + tlb = &env->tlb[env->CP0_Index % env->nb_tlb]; |
| 490 | 488 | ||
| 491 | /* If this will change the current ASID, flush qemu's TLB. */ | 489 | /* If this will change the current ASID, flush qemu's TLB. */ |
| 492 | if (ASID != tlb->ASID) | 490 | if (ASID != tlb->ASID) |
| 493 | cpu_mips_tlb_flush (env, 1); | 491 | cpu_mips_tlb_flush (env, 1); |
| 494 | 492 | ||
| 495 | - mips_tlb_flush_extra(env, MIPS_TLB_NB); | 493 | + mips_tlb_flush_extra(env, env->nb_tlb); |
| 496 | 494 | ||
| 497 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; | 495 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
| 498 | env->CP0_PageMask = tlb->PageMask; | 496 | env->CP0_PageMask = tlb->PageMask; |
target-mips/translate.c
| @@ -5430,10 +5430,6 @@ void cpu_reset (CPUMIPSState *env) | @@ -5430,10 +5430,6 @@ void cpu_reset (CPUMIPSState *env) | ||
| 5430 | } | 5430 | } |
| 5431 | env->hflags = 0; | 5431 | env->hflags = 0; |
| 5432 | env->PC = (int32_t)0xBFC00000; | 5432 | env->PC = (int32_t)0xBFC00000; |
| 5433 | -#if defined (MIPS_USES_R4K_TLB) | ||
| 5434 | - env->CP0_Random = MIPS_TLB_NB - 1; | ||
| 5435 | - env->tlb_in_use = MIPS_TLB_NB; | ||
| 5436 | -#endif | ||
| 5437 | env->CP0_Wired = 0; | 5433 | env->CP0_Wired = 0; |
| 5438 | /* SMP not implemented */ | 5434 | /* SMP not implemented */ |
| 5439 | env->CP0_EBase = 0x80000000; | 5435 | env->CP0_EBase = 0x80000000; |
target-mips/translate_init.c
| @@ -28,13 +28,13 @@ | @@ -28,13 +28,13 @@ | ||
| 28 | (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \ | 28 | (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \ |
| 29 | (0x2 << CP0C0_K0)) | 29 | (0x2 << CP0C0_K0)) |
| 30 | 30 | ||
| 31 | -/* Have config2, 16 TLB entries, 64 sets Icache, 16 bytes Icache line, | 31 | +/* Have config2, 64 sets Icache, 16 bytes Icache line, |
| 32 | 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, | 32 | 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, |
| 33 | no coprocessor2 attached, no MDMX support attached, | 33 | no coprocessor2 attached, no MDMX support attached, |
| 34 | no performance counters, watch registers present, | 34 | no performance counters, watch registers present, |
| 35 | no code compression, EJTAG present, no FPU */ | 35 | no code compression, EJTAG present, no FPU */ |
| 36 | #define MIPS_CONFIG1 \ | 36 | #define MIPS_CONFIG1 \ |
| 37 | -((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) | \ | 37 | +((1 << CP0C1_M) | \ |
| 38 | (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \ | 38 | (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \ |
| 39 | (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \ | 39 | (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \ |
| 40 | (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ | 40 | (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ |
| @@ -81,7 +81,7 @@ static mips_def_t mips_defs[] = | @@ -81,7 +81,7 @@ static mips_def_t mips_defs[] = | ||
| 81 | .name = "4Kc", | 81 | .name = "4Kc", |
| 82 | .CP0_PRid = 0x00018000, | 82 | .CP0_PRid = 0x00018000, |
| 83 | .CP0_Config0 = MIPS_CONFIG0, | 83 | .CP0_Config0 = MIPS_CONFIG0, |
| 84 | - .CP0_Config1 = MIPS_CONFIG1, | 84 | + .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU), |
| 85 | .CP0_Config2 = MIPS_CONFIG2, | 85 | .CP0_Config2 = MIPS_CONFIG2, |
| 86 | .CP0_Config3 = MIPS_CONFIG3, | 86 | .CP0_Config3 = MIPS_CONFIG3, |
| 87 | .SYNCI_Step = 32, | 87 | .SYNCI_Step = 32, |
| @@ -92,7 +92,7 @@ static mips_def_t mips_defs[] = | @@ -92,7 +92,7 @@ static mips_def_t mips_defs[] = | ||
| 92 | .name = "4KEcR1", | 92 | .name = "4KEcR1", |
| 93 | .CP0_PRid = 0x00018400, | 93 | .CP0_PRid = 0x00018400, |
| 94 | .CP0_Config0 = MIPS_CONFIG0, | 94 | .CP0_Config0 = MIPS_CONFIG0, |
| 95 | - .CP0_Config1 = MIPS_CONFIG1, | 95 | + .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU), |
| 96 | .CP0_Config2 = MIPS_CONFIG2, | 96 | .CP0_Config2 = MIPS_CONFIG2, |
| 97 | .CP0_Config3 = MIPS_CONFIG3, | 97 | .CP0_Config3 = MIPS_CONFIG3, |
| 98 | .SYNCI_Step = 32, | 98 | .SYNCI_Step = 32, |
| @@ -103,7 +103,7 @@ static mips_def_t mips_defs[] = | @@ -103,7 +103,7 @@ static mips_def_t mips_defs[] = | ||
| 103 | .name = "4KEc", | 103 | .name = "4KEc", |
| 104 | .CP0_PRid = 0x00019000, | 104 | .CP0_PRid = 0x00019000, |
| 105 | .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), | 105 | .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), |
| 106 | - .CP0_Config1 = MIPS_CONFIG1, | 106 | + .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU), |
| 107 | .CP0_Config2 = MIPS_CONFIG2, | 107 | .CP0_Config2 = MIPS_CONFIG2, |
| 108 | .CP0_Config3 = MIPS_CONFIG3, | 108 | .CP0_Config3 = MIPS_CONFIG3, |
| 109 | .SYNCI_Step = 32, | 109 | .SYNCI_Step = 32, |
| @@ -114,7 +114,7 @@ static mips_def_t mips_defs[] = | @@ -114,7 +114,7 @@ static mips_def_t mips_defs[] = | ||
| 114 | .name = "24Kc", | 114 | .name = "24Kc", |
| 115 | .CP0_PRid = 0x00019300, | 115 | .CP0_PRid = 0x00019300, |
| 116 | .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), | 116 | .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), |
| 117 | - .CP0_Config1 = MIPS_CONFIG1, | 117 | + .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU), |
| 118 | .CP0_Config2 = MIPS_CONFIG2, | 118 | .CP0_Config2 = MIPS_CONFIG2, |
| 119 | .CP0_Config3 = MIPS_CONFIG3, | 119 | .CP0_Config3 = MIPS_CONFIG3, |
| 120 | .SYNCI_Step = 32, | 120 | .SYNCI_Step = 32, |
| @@ -125,7 +125,7 @@ static mips_def_t mips_defs[] = | @@ -125,7 +125,7 @@ static mips_def_t mips_defs[] = | ||
| 125 | .name = "24Kf", | 125 | .name = "24Kf", |
| 126 | .CP0_PRid = 0x00019300, | 126 | .CP0_PRid = 0x00019300, |
| 127 | .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), | 127 | .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), |
| 128 | - .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP), | 128 | + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU), |
| 129 | .CP0_Config2 = MIPS_CONFIG2, | 129 | .CP0_Config2 = MIPS_CONFIG2, |
| 130 | .CP0_Config3 = MIPS_CONFIG3, | 130 | .CP0_Config3 = MIPS_CONFIG3, |
| 131 | .SYNCI_Step = 32, | 131 | .SYNCI_Step = 32, |
| @@ -137,7 +137,7 @@ static mips_def_t mips_defs[] = | @@ -137,7 +137,7 @@ static mips_def_t mips_defs[] = | ||
| 137 | .name = "R4000", | 137 | .name = "R4000", |
| 138 | .CP0_PRid = 0x00000400, | 138 | .CP0_PRid = 0x00000400, |
| 139 | .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT), | 139 | .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT), |
| 140 | - .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP), | 140 | + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU), |
| 141 | .CP0_Config2 = MIPS_CONFIG2, | 141 | .CP0_Config2 = MIPS_CONFIG2, |
| 142 | .CP0_Config3 = MIPS_CONFIG3, | 142 | .CP0_Config3 = MIPS_CONFIG3, |
| 143 | .SYNCI_Step = 16, | 143 | .SYNCI_Step = 16, |
| @@ -192,5 +192,10 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) | @@ -192,5 +192,10 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) | ||
| 192 | env->SYNCI_Step = def->SYNCI_Step; | 192 | env->SYNCI_Step = def->SYNCI_Step; |
| 193 | env->CCRes = def->CCRes; | 193 | env->CCRes = def->CCRes; |
| 194 | env->fcr0 = def->CP1_fcr0; | 194 | env->fcr0 = def->CP1_fcr0; |
| 195 | +#if defined (MIPS_USES_R4K_TLB) | ||
| 196 | + env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); | ||
| 197 | + env->CP0_Random = env->nb_tlb - 1; | ||
| 198 | + env->tlb_in_use = env->nb_tlb; | ||
| 199 | +#endif | ||
| 195 | return 0; | 200 | return 0; |
| 196 | } | 201 | } |