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 44 typedef struct tlb_t tlb_t;
45 45 struct tlb_t {
46 46 target_ulong VPN;
47   - target_ulong end;
48   - target_ulong end2;
  47 + uint_fast32_t PageMask;
49 48 uint_fast8_t ASID;
50 49 uint_fast16_t G:1;
51 50 uint_fast16_t C0:3;
... ...
target-mips/helper.c
... ... @@ -41,23 +41,26 @@ enum {
41 41 static int map_address (CPUState *env, target_ulong *physical, int *prot,
42 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 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 54 /* Check ASID, virtual page number & size */
52 55 if ((tlb->G == 1 || tlb->ASID == ASID) &&
53 56 tlb->VPN == tag) {
54 57 /* TLB match */
55   - n = (address >> TARGET_PAGE_BITS) & 1;
  58 + n = !!(address & mask & ~(mask >> 1));
56 59 /* Check access rights */
57 60 if (!(n ? tlb->V1 : tlb->V0))
58 61 return TLBRET_INVALID;
59 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 64 *prot = PAGE_READ;
62 65 if (n ? tlb->D1 : tlb->D0)
63 66 *prot |= PAGE_WRITE;
... ... @@ -420,9 +423,10 @@ void do_interrupt (CPUState *env)
420 423 void invalidate_tlb (CPUState *env, int idx, int use_extra)
421 424 {
422 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 431 tlb = &env->tlb[idx];
428 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 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 392 tlb = &env->tlb[idx];
393 393 tlb->VPN = env->CP0_EntryHi & (int32_t)0xFFFFE000;
394 394 tlb->ASID = env->CP0_EntryHi & 0xFF;
  395 + tlb->PageMask = env->CP0_PageMask;
395 396 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
396 397 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
397 398 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
... ... @@ -473,6 +474,7 @@ void do_tlbr (void)
473 474 mips_tlb_flush_extra(env, MIPS_TLB_NB);
474 475  
475 476 env->CP0_EntryHi = tlb->VPN | tlb->ASID;
  477 + env->CP0_PageMask = tlb->PageMask;
476 478 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
477 479 (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
478 480 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
... ...