Commit 3b1c8be4f4f1b5d4114320aaf41ec4872ab4598c

Authored by ths
1 parent c281868e

Fix PageMask handling, second part.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2345 c046a42c-6fe2-441c-8c8c-71466251a162
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) |