Fixed ACRs for running BaS in flash (hang on MMU enable)

This commit is contained in:
Markus Fröschle
2014-09-29 19:08:38 +00:00
parent acca9ca2be
commit 285866181f
2 changed files with 611 additions and 606 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -63,12 +63,12 @@
#error "unknown machine!" #error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
// #define DEBUG_MMU //#define DBG_MMU
#ifdef DEBUG_MMU #ifdef DBG_MMU
#define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0) #define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0)
#else #else
#define dbg(format, arg...) do {;} while (0) #define dbg(format, arg...) do {;} while (0)
#endif /* DEBUG_MMU */ #endif /* DBG_MMU */
#define err(format, arg...) do { xprintf("ERROR (%s()): " format, __FUNCTION__, ##arg); xprintf("system halted\r\n"); } while(0); while(1) #define err(format, arg...) do { xprintf("ERROR (%s()): " format, __FUNCTION__, ##arg); xprintf("system halted\r\n"); } while(0); while(1)
/* /*
@@ -77,19 +77,19 @@
*/ */
inline uint32_t set_asid(uint32_t value) inline uint32_t set_asid(uint32_t value)
{ {
extern long rt_asid; extern long rt_asid;
uint32_t ret = rt_asid; uint32_t ret = rt_asid;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ASID\n\t" "movec %[value],ASID\n\t"
: /* no output */ : /* no output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_asid = value; rt_asid = value;
return ret; return ret;
} }
@@ -99,18 +99,18 @@ inline uint32_t set_asid(uint32_t value)
*/ */
inline uint32_t set_acr0(uint32_t value) inline uint32_t set_acr0(uint32_t value)
{ {
extern uint32_t rt_acr0; extern uint32_t rt_acr0;
uint32_t ret = rt_acr0; uint32_t ret = rt_acr0;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR0\n\t" "movec %[value],ACR0\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr0 = value; rt_acr0 = value;
return ret; return ret;
} }
/* /*
@@ -119,18 +119,18 @@ inline uint32_t set_acr0(uint32_t value)
*/ */
inline uint32_t set_acr1(uint32_t value) inline uint32_t set_acr1(uint32_t value)
{ {
extern uint32_t rt_acr1; extern uint32_t rt_acr1;
uint32_t ret = rt_acr1; uint32_t ret = rt_acr1;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR1\n\t" "movec %[value],ACR1\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr1 = value; rt_acr1 = value;
return ret; return ret;
} }
@@ -140,18 +140,18 @@ inline uint32_t set_acr1(uint32_t value)
*/ */
inline uint32_t set_acr2(uint32_t value) inline uint32_t set_acr2(uint32_t value)
{ {
extern uint32_t rt_acr2; extern uint32_t rt_acr2;
uint32_t ret = rt_acr2; uint32_t ret = rt_acr2;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR2\n\t" "movec %[value],ACR2\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr2 = value; rt_acr2 = value;
return ret; return ret;
} }
/* /*
@@ -160,35 +160,35 @@ inline uint32_t set_acr2(uint32_t value)
*/ */
inline uint32_t set_acr3(uint32_t value) inline uint32_t set_acr3(uint32_t value)
{ {
extern uint32_t rt_acr3; extern uint32_t rt_acr3;
uint32_t ret = rt_acr3; uint32_t ret = rt_acr3;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR3\n\t" "movec %[value],ACR3\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr3 = value; rt_acr3 = value;
return ret; return ret;
} }
inline uint32_t set_mmubar(uint32_t value) inline uint32_t set_mmubar(uint32_t value)
{ {
extern uint32_t rt_mmubar; extern uint32_t rt_mmubar;
uint32_t ret = rt_mmubar; uint32_t ret = rt_mmubar;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],MMUBAR\n\t" "movec %[value],MMUBAR\n\t"
: /* no output */ : /* no output */
: [value] "r" (value) : [value] "r" (value)
: /* no clobber */ : /* no clobber */
); );
rt_mmubar = value; rt_mmubar = value;
NOP(); NOP();
return ret; return ret;
} }
@@ -359,64 +359,64 @@ int mmu_map_data_page(uint32_t virt, uint8_t asid)
*/ */
int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags) int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags)
{ {
int size_mask; int size_mask;
int ipl; int ipl;
switch (sz) switch (sz)
{ {
case MMU_PAGE_SIZE_1M: case MMU_PAGE_SIZE_1M:
size_mask = ~ (SIZE_1M - 1); size_mask = ~ (SIZE_1M - 1);
break; break;
case MMU_PAGE_SIZE_8K: case MMU_PAGE_SIZE_8K:
size_mask = ~ (SIZE_8K - 1); size_mask = ~ (SIZE_8K - 1);
break; break;
case MMU_PAGE_SIZE_4K: case MMU_PAGE_SIZE_4K:
size_mask = ~ (SIZE_4K - 1); size_mask = ~ (SIZE_4K - 1);
break; break;
case MMU_PAGE_SIZE_1K: case MMU_PAGE_SIZE_1K:
size_mask = ~ (SIZE_1K - 1); size_mask = ~ (SIZE_1K - 1);
break; break;
default: default:
dbg("illegal map size %d\r\n", sz); dbg("illegal map size %d\r\n", sz);
return 0; return 0;
} }
/* /*
* add page to TLB * add page to TLB
*/ */
ipl = set_ipl(7); /* do not disturb */ ipl = set_ipl(7); /* do not disturb */
MCF_MMU_MMUTR = ((int) virt & size_mask) | /* virtual address */ MCF_MMU_MMUTR = ((int) virt & size_mask) | /* virtual address */
MCF_MMU_MMUTR_ID(page_id) | /* address space id (ASID) */ MCF_MMU_MMUTR_ID(page_id) | /* address space id (ASID) */
(flags->global ? MCF_MMU_MMUTR_SG : 0) | /* shared global */ (flags->global ? MCF_MMU_MMUTR_SG : 0) | /* shared global */
MCF_MMU_MMUTR_V; /* valid */ MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = ((int) phys & size_mask) | /* physical address */ MCF_MMU_MMUDR = ((int) phys & size_mask) | /* physical address */
MCF_MMU_MMUDR_SZ(sz) | /* page size */ MCF_MMU_MMUDR_SZ(sz) | /* page size */
MCF_MMU_MMUDR_CM(flags->cache_mode) | MCF_MMU_MMUDR_CM(flags->cache_mode) |
(flags->read ? MCF_MMU_MMUDR_R : 0) | /* read access enable */ (flags->read ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
(flags->write ? MCF_MMU_MMUDR_W : 0) | /* write access enable */ (flags->write ? MCF_MMU_MMUDR_W : 0) | /* write access enable */
(flags->execute ? MCF_MMU_MMUDR_X : 0) | /* execute access enable */ (flags->execute ? MCF_MMU_MMUDR_X : 0) | /* execute access enable */
(flags->locked ? MCF_MMU_MMUDR_LK : 0); (flags->locked ? MCF_MMU_MMUDR_LK : 0);
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */ MCF_MMU_MMUOR_UAA; /* update allocation address field */
NOP(); NOP();
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */ MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */ MCF_MMU_MMUOR_UAA; /* update allocation address field */
set_ipl(ipl); set_ipl(ipl);
dbg("mapped virt=0x%08x to phys=0x%08x\r\n", virt, phys); dbg("mapped virt=0x%08x to phys=0x%08x\r\n", virt, phys);
return 1; return 1;
} }
void mmu_init(void) void mmu_init(void)
@@ -482,86 +482,91 @@ void mmu_init(void)
pages[0].supervisor_protect = 0; /* protect system vectors */ pages[0].supervisor_protect = 0; /* protect system vectors */
} }
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */ set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
/* set data access attributes in ACR0 and ACR1 */ /* set data access attributes in ACR0 and ACR1 */
set_acr0(ACR_W(0) | /* read and write accesses permitted */ set_acr0(ACR_W(0) | /* read and write accesses permitted */
ACR_SP(0) | /* supervisor and user mode access permitted */ ACR_SP(0) | /* supervisor and user mode access permitted */
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */ ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */
ACR_AMM(0) | /* control region > 16 MB */ ACR_AMM(0) | /* control region > 16 MB */
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */ ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */
ACR_E(1) | /* enable ACR */ ACR_E(1) | /* enable ACR */
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
ACR_ADMSK(0x7f) | /* cover 2GB area from 0x80000000 to 0xffffffff */ ACR_ADMSK(0x7f) | /* cover 2GB area from 0x80000000 to 0xffffffff */
ACR_BA(0x80000000)); /* (equals area from 3 to 4 GB */ ACR_BA(0x80000000)); /* (equals area from 3 to 4 GB */
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */ ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */
ACR_BA(0x80000000)); ACR_BA(0x80000000));
#elif defined(MACHINE_M54455) #elif defined(MACHINE_M54455)
ACR_ADMSK(0x7f) | ACR_ADMSK(0x7f) |
ACR_BA(0x80000000)); /* FIXME: not determined yet */ ACR_BA(0x80000000)); /* FIXME: not determined yet */
#else #else
#error unknown machine! #error unknown machine!
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
// set_acr1(0x601fc000); // set_acr1(0x601fc000);
set_acr1(ACR_W(0) |
ACR_SP(0) | /* data access attributes for BaS in flash */
ACR_CM(0) |
set_acr1(ACR_W(0) |
ACR_SP(0) |
ACR_CM(0) |
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
ACR_CM(ACR_CM_CACHEABLE_WT) | /* video RAM on the Firebee */ ACR_CM(ACR_CM_CACHEABLE_WT) | /* flash on the Firebee */
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */ ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */
#elif defined(MACHINE_M54455) #elif defined(MACHINE_M54455)
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* FIXME: not determined yet */ ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* FIXME: not determined yet */
#else #else
#error unknown machine! #error unknown machine!
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
ACR_AMM(0) | ACR_AMM(0) |
ACR_S(ACR_S_ALL) | ACR_S(ACR_S_ALL) |
ACR_E(1) | ACR_E(1) |
ACR_ADMSK(0x1f) | ACR_ADMSK(0x1f) |
ACR_BA(0x60000000)); ACR_BA(0xe0000000));
/* set instruction access attributes in ACR2 and ACR3 */ /* set instruction access attributes in ACR2 and ACR3 */
//set_acr2(0xe007c400); //set_acr2(0xe007c400);
set_acr2(ACR_W(0) |
ACR_SP(0) | /* instruction access attribute for BaS in flash */
ACR_CM(0) |
ACR_CM(ACR_CM_CACHEABLE_WT) | set_acr2(ACR_W(0) |
ACR_AMM(1) | ACR_SP(0) |
ACR_S(ACR_S_ALL) | ACR_CM(0) |
ACR_E(1) | ACR_CM(ACR_CM_CACHEABLE_WT) |
ACR_ADMSK(0x7) | ACR_AMM(1) |
ACR_BA(0xe0000000)); ACR_S(ACR_S_ALL) |
ACR_E(1) |
ACR_ADMSK(0x7) |
ACR_BA(0xe0000000));
/* disable ACR1 - 3, essentially disabling all of the above */ /* disable ACR1 - 3, essentially disabling all of the above */
set_acr1(0x0);
set_acr2(0x0);
set_acr3(0x0);
set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */ set_acr3(0x0);
/* create locked TLB entries */ set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */
flags.cache_mode = CACHE_COPYBACK; /* create locked TLB entries */
flags.cache_mode = CACHE_COPYBACK;
flags.supervisor_protect = 0; flags.supervisor_protect = 0;
flags.read = 1; flags.read = 1;
flags.write = 1; flags.write = 1;
flags.execute = 1; flags.execute = 1;
flags.locked = true; flags.locked = true;
/* 0x00000000 - 0x00100000 (first MB of physical memory) locked virt = phys */ /* 0x00000000 - 0x00100000 (first MB of physical memory) locked virt = phys */
mmu_map_page(0x0, 0x0, MMU_PAGE_SIZE_1M, 0, &flags); mmu_map_page(0x0, 0x0, MMU_PAGE_SIZE_1M, 0, &flags);
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
/* /*
* 0x00d00000 - 0x00e00000 (last megabyte of ST RAM = Falcon video memory) locked ID = 6 * 0x00d00000 - 0x00e00000 (last megabyte of ST RAM = Falcon video memory) locked ID = 6
* mapped to physical address 0x60d0'0000 (FPGA video memory) * mapped to physical address 0x60d0'0000 (FPGA video memory)
* video RAM: read write execute normal write true * video RAM: read write execute normal write true
*/ */
flags.cache_mode = CACHE_WRITETHROUGH; flags.cache_mode = CACHE_WRITETHROUGH;
flags.supervisor_protect = 0; flags.supervisor_protect = 0;
flags.read = 1; flags.read = 1;
flags.write = 1; flags.write = 1;
@@ -569,15 +574,15 @@ void mmu_init(void)
flags.locked = true; flags.locked = true;
mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags); mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags);
video_tlb = 0x2000; /* set page as video page */ video_tlb = 0x2000; /* set page as video page */
video_sbt = 0x0; /* clear time */ video_sbt = 0x0; /* clear time */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
/* /*
* Make the TOS (in SDRAM) read-only * Make the TOS (in SDRAM) read-only
* This maps virtual 0x00e0'0000 - 0x00ef'ffff to the same virtual address * This maps virtual 0x00e0'0000 - 0x00ef'ffff to the same virtual address
*/ */
flags.cache_mode = CACHE_COPYBACK; flags.cache_mode = CACHE_COPYBACK;
flags.supervisor_protect = 0; flags.supervisor_protect = 0;
flags.read = 1; flags.read = 1;
flags.write = 0; flags.write = 0;
@@ -586,11 +591,11 @@ void mmu_init(void)
mmu_map_page(0xe00000, 0xe00000, MMU_PAGE_SIZE_1M, 0, &flags); mmu_map_page(0xe00000, 0xe00000, MMU_PAGE_SIZE_1M, 0, &flags);
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
/* /*
* Map FireBee I/O area (0xfff0'0000 - 0xffff'ffff physical) to the Falcon-compatible I/O * Map FireBee I/O area (0xfff0'0000 - 0xffff'ffff physical) to the Falcon-compatible I/O
* area (0x00f0'0000 - 0x00ff'ffff virtual) for the FireBee * area (0x00f0'0000 - 0x00ff'ffff virtual) for the FireBee
*/ */
flags.cache_mode = CACHE_NOCACHE_PRECISE; flags.cache_mode = CACHE_NOCACHE_PRECISE;
flags.supervisor_protect = 1; flags.supervisor_protect = 1;
flags.read = 1; flags.read = 1;
flags.write = 1; flags.write = 1;
@@ -599,11 +604,11 @@ void mmu_init(void)
mmu_map_page(0x00f00000, 0xfff00000, MMU_PAGE_SIZE_1M, 0, &flags); mmu_map_page(0x00f00000, 0xfff00000, MMU_PAGE_SIZE_1M, 0, &flags);
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
/* /*
* Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same * Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same
* virtual address. This is also used (completely) when BaS is in RAM * virtual address. This is also used (completely) when BaS is in RAM
*/ */
flags.cache_mode = CACHE_COPYBACK; flags.cache_mode = CACHE_COPYBACK;
flags.supervisor_protect = 1; flags.supervisor_protect = 1;
flags.read = 1; flags.read = 1;
flags.write = 1; flags.write = 1;
@@ -611,11 +616,11 @@ void mmu_init(void)
flags.locked = 1; flags.locked = 1;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0x00200000, SDRAM_START + SDRAM_SIZE - 0x00200000, MMU_PAGE_SIZE_1M, 0, &flags); mmu_map_page(SDRAM_START + SDRAM_SIZE - 0x00200000, SDRAM_START + SDRAM_SIZE - 0x00200000, MMU_PAGE_SIZE_1M, 0, &flags);
/* /*
* Map (locked) the very last MB of physical SDRAM (this is where the driver buffers reside) to the same * Map (locked) the very last MB of physical SDRAM (this is where the driver buffers reside) to the same
* virtual address. Used uncached for drivers. * virtual address. Used uncached for drivers.
*/ */
flags.cache_mode = CACHE_NOCACHE_PRECISE; flags.cache_mode = CACHE_NOCACHE_PRECISE;
flags.supervisor_protect = 1; flags.supervisor_protect = 1;
flags.read = 1; flags.read = 1;
flags.write = 1; flags.write = 1;
@@ -630,11 +635,11 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
{ {
uint32_t fault = format_status & 0xc030000; uint32_t fault = format_status & 0xc030000;
dbg("MMU TLB MISS accessing 0x%08x\r\nFS = 0x%08x\r\nPC = 0x%08x\r\n", address, format_status, pc); dbg("MMU TLB MISS accessing 0x%08x\r\nFS = 0x%08x\r\nPC = 0x%08x\r\n", fault_address, format_status, pc);
// flush_and_invalidate_caches(); // flush_and_invalidate_caches();
switch (fault) switch (fault)
{ {
/* if we have a real TLB miss, map the offending page */ /* if we have a real TLB miss, map the offending page */
case 0x04010000: /* TLB miss on opword of instruction fetch */ case 0x04010000: /* TLB miss on opword of instruction fetch */