Пример #1
0
void arch_set_dtlb(void *vaddr,void *paddr) {
    unsigned int flags = DTLB_PR_NOLIMIT;
    unsigned int mr = ((unsigned int)vaddr & SPR_DTLBMR_VPN) | SPR_ITLBMR_V;
    unsigned int tr = ((unsigned int)paddr & SPR_DTLBTR_PPN) | (flags & DTLB_PR_MASK) | SPR_DTLBTR_A | SPR_DTLBTR_D;
    unsigned int set = ((((unsigned int)vaddr) >> PAGE_BITS) & 63);
    or1k_mtspr (SPR_DTLBMR_BASE(0)+set, mr);
    or1k_mtspr (SPR_DTLBTR_BASE(0)+set, tr);
}
Пример #2
0
void flush_tlb_all(void)
{
	int i;
	unsigned long num_tlb_sets;

	/* Determine number of sets for IMMU. */
	/* FIXME: Assumption is I & D nsets equal. */
	num_tlb_sets = NUM_ITLB_SETS;

	for (i = 0; i < num_tlb_sets; i++) {
		mtspr_off(SPR_DTLBMR_BASE(0), i, 0);
		mtspr_off(SPR_ITLBMR_BASE(0), i, 0);
	}
}
Пример #3
0
void
tlb_invalidate_all () 
{
	bool intr_flag;
	
	local_intr_save (intr_flag);
	int i;
	for (i = 0; i < NR_SETS; i++) {
		mtspr (SPR_DTLBMR_BASE(0) + i, 0);
		mtspr (SPR_ITLBMR_BASE(0) + i, 0);
		asm ("l.nop;l.nop;");
	}
	local_intr_restore (intr_flag);
}
Пример #4
0
/* DTLB miss exception handler */
void dtlb_miss_handler (void)
{
  unsigned long ea;
  int set, way = 0;
  int i;

  /* Get EA that cause the exception */
  ea = mfspr (SPR_EEAR_BASE);

  /* Find TLB set and LRU way */
  set = (ea / PAGE_SIZE) % DTLB_SETS;
  for (i = 0; i < DTLB_WAYS; i++) {
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_LRU) == 0) {
      way = i;
      break;
    }
  }

  mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
  mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | dtlb_val);

  except_mask |= 1 << V_DTLB_MISS;
  except_count++;
}
Пример #5
0
/* Data page fault exception handler */
void dpage_fault_handler (void)
{
  unsigned long ea;
  int set, way = 0;
  int i;

  /* Get EA that cause the exception */
  ea = mfspr (SPR_EEAR_BASE);

  /* Find TLB set and way */
  set = (ea / PAGE_SIZE) % DTLB_SETS;
  for (i = 0; i < DTLB_WAYS; i++) {
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_VPN) == (ea & SPR_DTLBMR_VPN)) {
      way = i;
      break;
    }
  }

  /* Give permission */
  mtspr (SPR_DTLBTR_BASE(way) + set, (mfspr (SPR_DTLBTR_BASE(way) + set) & ~DTLB_PR_NOLIMIT) | dtlb_val);

  except_mask |= 1 << V_DPF;
  except_count++;
}
Пример #6
0
#ifndef NOCHECK
	//check_boot_pgdir ();
#endif
	
    print_pgdir (kprintf);

	slab_init ();
}


// invalidate a TLB entry, but only if the page tables being
// edited are the ones currently in use by the processor.
void
tlb_update (pde_t *pgdir, uintptr_t la) {
	uint32_t set = (la >> PGSHIFT) & (NR_SETS - 1);
	mtspr (SPR_DTLBMR_BASE(0) + set, 0);
	mtspr (SPR_ITLBMR_BASE(0) + set, 0);
	asm ("l.nop;l.nop;");
}

void
tlb_invalidate(pde_t *pgdir, uintptr_t la) {
	uint32_t set = (la >> PGSHIFT) & (NR_SETS - 1);
	mtspr (SPR_DTLBMR_BASE(0) + set, 0);
	mtspr (SPR_ITLBMR_BASE(0) + set, 0);
	asm ("l.nop;l.nop;");
}

void
check_boot_pgdir(void) {
    pte_t *ptep;
Пример #7
0
/* Exception priority test */
void except_priority_test (void)
{
  int i, j;
  unsigned long ea, ta, ret;

  /* Invalidate all entries in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
    for (j = 0; j < ITLB_SETS; j++) {
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
    }
  }
  
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
  } 

  /* Set dtlb no permisions */
  itlb_val = SPR_ITLBTR_CI;

  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
  }

  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  } 

  /* Init tick timer */
  tick_init (1, 1);

  /* Set dtlb no permisions */
  dtlb_val = SPR_DTLBTR_CI;

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Enable IMMU */
  immu_enable ();

  /* The following is currently disabled due to differing behavior between
     or1ksim and the OR1200 RTL. Or1ksim appears to receive only 1 exception
     during the call_with_int() call. The OR1200 correctly, in my opionion,
     reports 2 exceptions - ITLB miss and tick timer. -- Julius
     
     TODO: Investigate why or1ksim isn't reporting ITLB miss.

  */

#if 0
  /* Check if there was INT exception */
  call_with_int (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
  printf("ec:%d 0x%lx\n",except_count,except_mask);  ASSERT(except_count == 2);
  ASSERT(except_mask == ((1 << V_TICK) | (1 << V_ITLB_MISS)));
  printf("epc %8lx\n",except_pc);
  ASSERT(except_pc == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;
#endif

  /* Check if there was ITLB exception */
  call (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_ITLB_MISS));
  ASSERT(except_pc == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));
  ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));

  /* Set dtlb permisions */
  itlb_val |= SPR_ITLBTR_SXE;

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Check if there was IPF exception */
  call (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE), 0);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_IPF));
  ASSERT(except_pc == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));
  ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_TEXT_SET_NB*PAGE_SIZE)));

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;
  
  /* Disable MMU */
  immu_disable ();

  /* Set illegal instruction. JPB. Use a really illegal instruction, not
     l.cust8 0x3ffffff. */
  REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 0) = 0x00000000;
  REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4) = 0xe8000000;
  REG32(RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 8) = 0x00000000;

  /* Check if there was illegal insn exception */
  call (RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4, 0);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_ILLINSN));
  ASSERT(except_pc == (RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4));
  ASSERT(except_ea == (RAM_START + (RAM_SIZE/2) + (TLB_TEXT_SET_NB*PAGE_SIZE) + 4 ));

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Enable DMMU */
  dmmu_enable ();

  /* Check if there was alignment exception on read insn */
  ret = call ((unsigned long)&load_acc_32, RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE) + 1);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_ALIGN));
  ASSERT(ret == 0x12345678);
  ASSERT(except_pc == ((unsigned long)(load_acc_32) + 8));
  ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE + 1)));

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Check if there was DTLB exception */
  ret = call ((unsigned long)&load_acc_32, RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE));
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_DTLB_MISS));
  ASSERT(ret == 0x12345678);
  ASSERT(except_pc == ((unsigned long)(load_acc_32) + 8));
  ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE)));

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Set dtlb permisions */
  dtlb_val |= SPR_DTLBTR_SRE;

  /* Check if there was DPF exception */
  ret = call ((unsigned long)&load_acc_32, RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE));
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_DPF));
  ASSERT(ret == 0x12345678);
  ASSERT(except_pc == ((unsigned long)(load_acc_32) + 8));
  ASSERT(except_ea == (RAM_START + (RAM_SIZE) + (TLB_DATA_SET_NB*PAGE_SIZE)));
 
  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Check if there was trap exception */
  call ((unsigned long)&trap, 0);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_TRAP));
  ASSERT(except_pc == (unsigned long)(trap));

}
Пример #8
0
/* Bus error test */
int buserr_test (void)
{
  int i, j, ret;
  unsigned long ea, ta;

  /* Invalidate all entries in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
    for (j = 0; j < ITLB_SETS; j++) {
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
    }
  }

  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
  } 

  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
  }

  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  } 

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Set IMMU translation */
  ea = RAM_START + (RAM_SIZE) + ((TLB_TEXT_SET_NB)*PAGE_SIZE);
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
  mtspr (SPR_ITLBMR_BASE(0) + TLB_TEXT_SET_NB, (ea & SPR_ITLBMR_VPN) | 
	 SPR_ITLBMR_V);
  // Set translate to invalid address: 0xee000000
  mtspr (SPR_ITLBTR_BASE(0) + TLB_TEXT_SET_NB, (0xee000000 & SPR_ITLBTR_PPN) | 
	 itlb_val);

  /* Enable IMMU */
  immu_enable ();

  /* Check if there was bus error exception */
  ret = call (ea, 0);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_BERR));
  ASSERT(except_pc == ea);
  ASSERT(except_ea == ea);

  /* Disable IMMU */
  immu_disable ();

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Set EA as an invalid memory location */
  ea  = 0xee000000;

  /* Check if there was bus error exception */
  ret = call (ea, 0);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_BERR));
  ASSERT(except_pc == ea); 
  ASSERT(except_ea == ea);

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Set DMMU translation */
  ea = RAM_START + (RAM_SIZE) + ((TLB_DATA_SET_NB)*PAGE_SIZE);
  dtlb_val = SPR_DTLBTR_CI | SPR_DTLBTR_SRE;
  mtspr (SPR_DTLBMR_BASE(0) + TLB_DATA_SET_NB, (ea & SPR_DTLBMR_VPN) | 
	 SPR_DTLBMR_V);
  // Set translate to invalid address: 0xee000000
  mtspr (SPR_DTLBTR_BASE(0) + TLB_DATA_SET_NB, (0xee000000 & SPR_DTLBTR_PPN) | 
	 dtlb_val);

  /* Enable DMMU */
  dmmu_enable ();

  /* Check if there was bus error exception */
  ret = call ((unsigned long)&load_acc_32, ea );
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_BERR));
  ASSERT(except_pc == (unsigned long)load_acc_32 + 8);
  ASSERT(except_ea == ea);
  ASSERT(ret == 0x12345678);

  /* Disable DMMU */
  dmmu_disable ();

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  // Set ea to invalid address
  ea = 0xee000000;
  
  /* Check if there was bus error exception */
  ret = call ((unsigned long)&load_acc_32, ea );
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_BERR));
  ASSERT(except_pc == (unsigned long)load_acc_32 + 8);
  ASSERT(except_ea == ea);
  ASSERT(ret == 0x12345678);

  return 0;
}
Пример #9
0
/* DTLB miss test */
int dtlb_test (void)
{
  int i, j, ret;
  unsigned long ea, ta;

  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
  }

  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  } 

  /* Set dtlb no permisions */
  dtlb_val = SPR_DTLBTR_CI;

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Set pattern */
  ea = RAM_START + (RAM_SIZE/2) + ((TLB_DATA_SET_NB)*PAGE_SIZE);
  REG32(ea) = 0x87654321;

  /* Enable DMMU */
  dmmu_enable ();

  /* Check if there was DTLB miss exception */
  ret = call ((unsigned long)&load_b_acc_32, ea);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_DTLB_MISS));
  ASSERT(except_pc == (unsigned long)load_b_acc_32 + 8);
  ASSERT(except_ea == ea);
  ASSERT(ret == 0x12345678);

  /* Set dtlb no permisions */
  dtlb_val = SPR_DTLBTR_CI | SPR_DTLBTR_SRE; 

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  /* Check if there was DPF miss exception */
  ret = call ((unsigned long)&load_b_acc_32, ea);
  ASSERT(except_count == 1);
  ASSERT(except_mask == (1 << V_DPF));
  ASSERT(except_pc == (unsigned long)load_b_acc_32 + 8);
  ASSERT(except_ea == ea);
  ASSERT(ret == 0x12345678);

  /* Reset except counter */
  except_count = 0;
  except_mask = 0;
  except_pc = 0;
  except_ea = 0;

  ret = call ((unsigned long)&load_b_acc_32, ea);
  ASSERT(except_count == 0);
  ASSERT(ret == 0x87654321);

  /* Disable DMMU */
  dmmu_disable ();

  return 0;
}