Beispiel #1
0
static void update_dtlb(unsigned long address, pte_t pte)
{
	u32 tlbehi;
	u32 mmucr;

	tlbehi = sysreg_read(TLBEHI);
	tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
	tlbehi |= address & MMU_VPN_MASK;
	tlbehi |= SYSREG_BIT(TLBEHI_V);
	sysreg_write(TLBEHI, tlbehi);

	
	__builtin_tlbs();
	mmucr = sysreg_read(MMUCR);

	if (mmucr & SYSREG_BIT(MMUCR_N)) {
		
		unsigned int rp;
		u32 tlbar = sysreg_read(TLBARLO);

		rp = 32 - fls(tlbar);
		if (rp == 32) {
			rp = 0;
			sysreg_write(TLBARLO, -1L);
		}

		mmucr = SYSREG_BFINS(DRP, rp, mmucr);
		sysreg_write(MMUCR, mmucr);
	}

	sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK);

	
	__builtin_tlbw();
}
Beispiel #2
0
static void __flush_tlb_page(unsigned long asid, unsigned long page)
{
	u32 mmucr, tlbehi;

	/*
	 * Caller is responsible for masking out non-PFN bits in page
	 * and changing the current ASID if necessary. This means that
	 * we don't need to flush the pipeline after writing TLBEHI.
	 */
	tlbehi = page | asid;
	sysreg_write(TLBEHI, tlbehi);

	__builtin_tlbs();
	mmucr = sysreg_read(MMUCR);

	if (!(mmucr & SYSREG_BIT(MMUCR_N))) {
		unsigned int entry;
		u32 tlbarlo;

		/* Clear the "valid" bit */
		sysreg_write(TLBEHI, tlbehi);

		/* mark the entry as "not accessed" */
		entry = SYSREG_BFEXT(DRP, mmucr);
		tlbarlo = sysreg_read(TLBARLO);
		tlbarlo |= (0x80000000UL >> entry);
		sysreg_write(TLBARLO, tlbarlo);

		/* update the entry with valid bit clear */
		__builtin_tlbw();
	}
Beispiel #3
0
static void __flush_tlb_page(unsigned long asid, unsigned long page)
{
	u32 mmucr, tlbehi;

	tlbehi = page | asid;
	sysreg_write(TLBEHI, tlbehi);

	__builtin_tlbs();
	mmucr = sysreg_read(MMUCR);

	if (!(mmucr & SYSREG_BIT(MMUCR_N))) {
		unsigned int entry;
		u32 tlbarlo;

		
		sysreg_write(TLBEHI, tlbehi);

		
		entry = SYSREG_BFEXT(DRP, mmucr);
		tlbarlo = sysreg_read(TLBARLO);
		tlbarlo |= (0x80000000UL >> entry);
		sysreg_write(TLBARLO, tlbarlo);

		
		__builtin_tlbw();
	}
Beispiel #4
0
static void update_dtlb(unsigned long address, pte_t pte)
{
	u32 tlbehi;
	u32 mmucr;

	/*
	 * We're not changing the ASID here, so no need to flush the
	 * pipeline.
	 */
	tlbehi = sysreg_read(TLBEHI);
	tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
	tlbehi |= address & MMU_VPN_MASK;
	tlbehi |= SYSREG_BIT(TLBEHI_V);
	sysreg_write(TLBEHI, tlbehi);

	/* Does this mapping already exist? */
	__builtin_tlbs();
	mmucr = sysreg_read(MMUCR);

	if (mmucr & SYSREG_BIT(MMUCR_N)) {
		/* Not found -- pick a not-recently-accessed entry */
		unsigned int rp;
		u32 tlbar = sysreg_read(TLBARLO);

		rp = 32 - fls(tlbar);
		if (rp == 32) {
			rp = 0;
			sysreg_write(TLBARLO, -1L);
		}

		mmucr = SYSREG_BFINS(DRP, rp, mmucr);
		sysreg_write(MMUCR, mmucr);
	}

	sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK);

	/* Let's go */
	__builtin_tlbw();
}
Beispiel #5
0
static void show_dtlb_entry(unsigned int index)
{
	u32 tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
	unsigned long flags;

	local_irq_save(flags);
	mmucr_save = sysreg_read(MMUCR);
	tlbehi_save = sysreg_read(TLBEHI);
	mmucr = SYSREG_BFINS(DRP, index, mmucr_save);
	sysreg_write(MMUCR, mmucr);

	__builtin_tlbr();
	cpu_sync_pipeline();

	tlbehi = sysreg_read(TLBEHI);
	tlbelo = sysreg_read(TLBELO);

	printk("%2u: %c %c %02x   %05x %05x %o  %o  %c %c %c %c\n",
	       index,
	       SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0',
	       SYSREG_BFEXT(G, tlbelo) ? '1' : '0',
	       SYSREG_BFEXT(ASID, tlbehi),
	       SYSREG_BFEXT(VPN, tlbehi) >> 2,
	       SYSREG_BFEXT(PFN, tlbelo) >> 2,
	       SYSREG_BFEXT(AP, tlbelo),
	       SYSREG_BFEXT(SZ, tlbelo),
	       SYSREG_BFEXT(TLBELO_C, tlbelo) ? 'C' : ' ',
	       SYSREG_BFEXT(B, tlbelo) ? 'B' : ' ',
	       SYSREG_BFEXT(W, tlbelo) ? 'W' : ' ',
	       SYSREG_BFEXT(TLBELO_D, tlbelo) ? 'D' : ' ');

	sysreg_write(MMUCR, mmucr_save);
	sysreg_write(TLBEHI, tlbehi_save);
	cpu_sync_pipeline();
	local_irq_restore(flags);
}