Commit 3b1c8be4f4f1b5d4114320aaf41ec4872ab4598c
1 parent
c281868e
Fix PageMask handling, second part.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2345 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
36 additions
and
16 deletions
target-mips/cpu.h
@@ -44,8 +44,7 @@ union fpr_t { | @@ -44,8 +44,7 @@ union fpr_t { | ||
44 | typedef struct tlb_t tlb_t; | 44 | typedef struct tlb_t tlb_t; |
45 | struct tlb_t { | 45 | struct tlb_t { |
46 | target_ulong VPN; | 46 | target_ulong VPN; |
47 | - target_ulong end; | ||
48 | - target_ulong end2; | 47 | + uint_fast32_t PageMask; |
49 | uint_fast8_t ASID; | 48 | uint_fast8_t ASID; |
50 | uint_fast16_t G:1; | 49 | uint_fast16_t G:1; |
51 | uint_fast16_t C0:3; | 50 | uint_fast16_t C0:3; |
target-mips/helper.c
@@ -41,23 +41,26 @@ enum { | @@ -41,23 +41,26 @@ enum { | ||
41 | static int map_address (CPUState *env, target_ulong *physical, int *prot, | 41 | static int map_address (CPUState *env, target_ulong *physical, int *prot, |
42 | target_ulong address, int rw, int access_type) | 42 | target_ulong address, int rw, int access_type) |
43 | { | 43 | { |
44 | - target_ulong tag = address & (TARGET_PAGE_MASK << 1); | ||
45 | - uint8_t ASID = env->CP0_EntryHi & 0xFF; | ||
46 | - tlb_t *tlb; | ||
47 | - int i, n; | 44 | + int i; |
48 | 45 | ||
49 | for (i = 0; i < env->tlb_in_use; i++) { | 46 | for (i = 0; i < env->tlb_in_use; i++) { |
50 | - tlb = &env->tlb[i]; | 47 | + tlb_t *tlb = &env->tlb[i]; |
48 | + /* 1k pages are not supported. */ | ||
49 | + uint8_t ASID = env->CP0_EntryHi & 0xFF; | ||
50 | + target_ulong mask = tlb->PageMask | 0x1FFF; | ||
51 | + target_ulong tag = address & ~mask; | ||
52 | + int n; | ||
53 | + | ||
51 | /* Check ASID, virtual page number & size */ | 54 | /* Check ASID, virtual page number & size */ |
52 | if ((tlb->G == 1 || tlb->ASID == ASID) && | 55 | if ((tlb->G == 1 || tlb->ASID == ASID) && |
53 | tlb->VPN == tag) { | 56 | tlb->VPN == tag) { |
54 | /* TLB match */ | 57 | /* TLB match */ |
55 | - n = (address >> TARGET_PAGE_BITS) & 1; | 58 | + n = !!(address & mask & ~(mask >> 1)); |
56 | /* Check access rights */ | 59 | /* Check access rights */ |
57 | if (!(n ? tlb->V1 : tlb->V0)) | 60 | if (!(n ? tlb->V1 : tlb->V0)) |
58 | return TLBRET_INVALID; | 61 | return TLBRET_INVALID; |
59 | if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { | 62 | if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { |
60 | - *physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK); | 63 | + *physical = tlb->PFN[n] | (address & (mask >> 1)); |
61 | *prot = PAGE_READ; | 64 | *prot = PAGE_READ; |
62 | if (n ? tlb->D1 : tlb->D0) | 65 | if (n ? tlb->D1 : tlb->D0) |
63 | *prot |= PAGE_WRITE; | 66 | *prot |= PAGE_WRITE; |
@@ -420,9 +423,10 @@ void do_interrupt (CPUState *env) | @@ -420,9 +423,10 @@ void do_interrupt (CPUState *env) | ||
420 | void invalidate_tlb (CPUState *env, int idx, int use_extra) | 423 | void invalidate_tlb (CPUState *env, int idx, int use_extra) |
421 | { | 424 | { |
422 | tlb_t *tlb; | 425 | tlb_t *tlb; |
423 | - uint8_t ASID; | ||
424 | - | ||
425 | - ASID = env->CP0_EntryHi & 0xFF; | 426 | + target_ulong addr; |
427 | + target_ulong end; | ||
428 | + uint8_t ASID = env->CP0_EntryHi & 0xFF; | ||
429 | + target_ulong mask; | ||
426 | 430 | ||
427 | tlb = &env->tlb[idx]; | 431 | tlb = &env->tlb[idx]; |
428 | /* The qemu TLB is flushed then the ASID changes, so no need to | 432 | /* The qemu TLB is flushed then the ASID changes, so no need to |
@@ -440,8 +444,23 @@ void invalidate_tlb (CPUState *env, int idx, int use_extra) | @@ -440,8 +444,23 @@ void invalidate_tlb (CPUState *env, int idx, int use_extra) | ||
440 | return; | 444 | return; |
441 | } | 445 | } |
442 | 446 | ||
443 | - if (tlb->V0) | ||
444 | - tlb_flush_page (env, tlb->VPN); | ||
445 | - if (tlb->V1) | ||
446 | - tlb_flush_page (env, tlb->VPN + TARGET_PAGE_SIZE); | 447 | + /* 1k pages are not supported. */ |
448 | + mask = tlb->PageMask | 0x1FFF; | ||
449 | + if (tlb->V0) { | ||
450 | + addr = tlb->VPN; | ||
451 | + end = addr | (mask >> 1); | ||
452 | + while (addr < end) { | ||
453 | + tlb_flush_page (env, addr); | ||
454 | + addr += TARGET_PAGE_SIZE; | ||
455 | + } | ||
456 | + } | ||
457 | + if (tlb->V1) { | ||
458 | + addr = tlb->VPN | ((mask >> 1) + 1); | ||
459 | + addr = tlb->VPN + TARGET_PAGE_SIZE; | ||
460 | + end = addr | mask; | ||
461 | + while (addr < end) { | ||
462 | + tlb_flush_page (env, addr); | ||
463 | + addr += TARGET_PAGE_SIZE; | ||
464 | + } | ||
465 | + } | ||
447 | } | 466 | } |
target-mips/op_helper.c
@@ -392,6 +392,7 @@ static void fill_tlb (int idx) | @@ -392,6 +392,7 @@ static void fill_tlb (int idx) | ||
392 | tlb = &env->tlb[idx]; | 392 | tlb = &env->tlb[idx]; |
393 | tlb->VPN = env->CP0_EntryHi & (int32_t)0xFFFFE000; | 393 | tlb->VPN = env->CP0_EntryHi & (int32_t)0xFFFFE000; |
394 | tlb->ASID = env->CP0_EntryHi & 0xFF; | 394 | tlb->ASID = env->CP0_EntryHi & 0xFF; |
395 | + tlb->PageMask = env->CP0_PageMask; | ||
395 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; | 396 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
396 | tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; | 397 | tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; |
397 | tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; | 398 | tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; |
@@ -473,6 +474,7 @@ void do_tlbr (void) | @@ -473,6 +474,7 @@ void do_tlbr (void) | ||
473 | mips_tlb_flush_extra(env, MIPS_TLB_NB); | 474 | mips_tlb_flush_extra(env, MIPS_TLB_NB); |
474 | 475 | ||
475 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; | 476 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
477 | + env->CP0_PageMask = tlb->PageMask; | ||
476 | env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | | 478 | env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | |
477 | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); | 479 | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); |
478 | env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | | 480 | env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | |