cacheun.c 2.89 KB
#include "cpusim.h"

#define CMEM_WORD	(*(vu32*)K0BASE)
#define UMEM_WORD	(*(vu32*)K1BASE)

#define CMEM64_WORD	(*(vu32*)PHYS_TO_K0(DDRRAM64_START))
#define UMEM64_WORD	(*(vu32*)PHYS_TO_K1(DDRRAM64_START))

#define CNONMEM_WORD	(*(vu32*)PHYS_TO_K0(PI_BUFFER_BASE_REG))
#define UNONMEM_WORD	(*(vu32*)PHYS_TO_K1(PI_BUFFER_BASE_REG))

void
failed(const char* code) {
    message("cached/uncached test failed (");
    message(code);
    message(")\n");
    DBG_JTAG_FAIL(code);
    test_postamble();
}

#define saved_cause     (*(volatile int*)PHYS_TO_K1(INTERNAL_RAM_START))

/* run from the exception handler.  don't use regular regs, or stack */
/*
 * stash C0_CAUSE in saved_case and clear C0_CAUSE
 * increment C0_EPC by 4 to skip instruction causing bus error, but
 * temporarily set C0_SR to 0 to clear the EXL bit when writing C0_EPC
 */
void exception(void) {
    //saved_cause = getcp0reg(C0_CAUSE);
    //setcp0reg(C0_CAUSE, 0);
    __asm__ __volatile__ ("lui\t$26,0xbfc4\n\t"
			  "mfc0\t$27,$13\n\t"
			  "sw\t$27,0($26)\n\t"
			  "mtc0\t$0,$13\n\t"
			  "mfc0\t$27,$14\n\t"
			  "mfc0\t$26,$12\n\t"
			  "mtc0\t$0,$12\n\t"
			  "addiu $27,$27,4\n\t"
			  "mtc0\t$27,$14\n\t"
			  "mtc0\t$26,$12\n\t"
			  "nop\t\n"
			  "eret");
}

int
main() {
    extern void *__exception;

    test_preamble();
    init_ddr();

#if 0
    invalICache((void*)K0BASE, ICACHE_SIZE);
    invalDCache((void*)K0BASE, DCACHE_SIZE);
#endif
    initICache();
    initDCache();

    setcp0reg(C0_SR, SR_CU0|SR_CU1|SR_BEV);
    setcp0reg(C0_CONFIG, CONFIG_BE|CONFIG_NONCOHRNT);

    CMEM_WORD = 0xbabecafe;
    *(&CMEM_WORD+1) = 0xfeedfade;
    writebackDCache((void*)&CMEM_WORD, 8);
    if (UMEM_WORD != 0xbabecafe || *(&UMEM_WORD+1) != 0xfeedfade)
	failed("0");

    if (UMEM64_WORD != 0xbabecafe || *(&UMEM64_WORD+2) != 0xfeedfade)
	failed("1");
    invalDCache((void*)&CMEM64_WORD, 4);
    CMEM64_WORD = 0xb0bafad;
    writebackDCache((void*)&CMEM64_WORD, 4);
    if (UMEM64_WORD != 0xb0bafad)
	failed("2");

    CNONMEM_WORD = 0xdeadbeef;
    writebackDCache((void*)&CNONMEM_WORD, 4);

    IO_WRITE(MI_CTRL_REG, MI_CTRL_BUS_ERROR_BNM|MI_CTRL_WR_INTR_BNM);

    /* generate write error interrupt on block write */
    setcp0reg(C0_CAUSE, 0);
    CNONMEM_WORD = 0xbad2dad;
    writebackDCache((void*)&CNONMEM_WORD, 4);
    if ((getcp0reg(C0_CAUSE) & CAUSE_IP6) != CAUSE_IP6)
	failed("3");
    if (IO_READ(MI_ERROR_ADDR_REG) != K0_TO_PHYS(&CNONMEM_WORD) ||
        IO_READ(MI_ERROR_INFO_REG) != (MI_ERROR_INFO_ENABLE | MI_ERROR_INFO_TYPE_BLOCK | 1))
	failed("4");

    __exception = exception;
    saved_cause = 0;
    setcp0reg(C0_CAUSE, 0);
    /* generate bus error on read */
    (void)*(vu32*)(&CNONMEM_WORD+4);
    IO_WRITE(PI_IDE0_BASE_REG, saved_cause);
    if ((saved_cause & CAUSE_EXCMASK) != EXC_DBE)
        failed("5");
    
    message("cached/uncached test passed\n");
    DBG_JTAG_PASS("cached/uncached test passed\n");
    test_postamble();
    return 0;
}