fixed wrong stack address offset for "magic number"

This commit is contained in:
Markus Fröschle
2014-09-30 19:29:46 +00:00
parent 66dff57624
commit b857519ea5
4 changed files with 311 additions and 500 deletions

View File

@@ -223,8 +223,10 @@ void __attribute__((interrupt)) get_bas_drivers(void)
* The trap itself is 2 bytes, the four bytes before that must * The trap itself is 2 bytes, the four bytes before that must
* read '_BAS' or we are not meant by this call * read '_BAS' or we are not meant by this call
*/ */
" move.l d0,-(sp) \n\t" // save register " move.l a0,-(sp) \n\t" // save registers
" move.l 10(sp),d0 \n\t" // get "magic word" " move.l d0,-(sp) \n\t"
" move.l 12(sp),a0 \n\t" // get return address
" move.l -6(a0),d0 \n\t" //
" cmp.l #0x5f424153,d0 \n\t" // is it '_BAS'? " cmp.l #0x5f424153,d0 \n\t" // is it '_BAS'?
" beq fetch_drivers \n\t" // yes " beq fetch_drivers \n\t" // yes
/* /*
@@ -232,13 +234,15 @@ void __attribute__((interrupt)) get_bas_drivers(void)
* If trap #0 isn't set to something sensible, we'll probably crash here, but this must be * If trap #0 isn't set to something sensible, we'll probably crash here, but this must be
* prevented on the caller side. * prevented on the caller side.
*/ */
" move.l (sp)+,d0 \n\t" // restore register " move.l (sp)+,d0 \n\t" // restore registers
" move.l (sp)+,a0 \n\t"
" move.l 0x80,-(sp) \n\t" // fetch vector " move.l 0x80,-(sp) \n\t" // fetch vector
" rts \n\t" // and jump through it " rts \n\t" // and jump through it
"fetch_drivers: \n\t" "fetch_drivers: \n\t"
" move.l #%[drivers],d0 \n\t" // return driver struct in d0 " move.l #%[drivers],d0 \n\t" // return driver struct in d0
" addq.l #4,sp \n\t" // adjust stack " addq.l #4,sp \n\t" // adjust stack
" move.l (sp)+,a0 \n\t" // restore register
: /* no output */ : /* no output */
: [drivers] "o" (bas_drivers) /* input */ : [drivers] "o" (bas_drivers) /* input */
: /* clobber */ : /* clobber */

View File

@@ -236,98 +236,10 @@ int pic_interrupt_handler(void *arg1, void *arg2)
return 1; return 1;
} }
extern int32_t video_sbt;
extern int32_t video_tlb;
void video_addr_timeout(void) void video_addr_timeout(void)
{ {
uint32_t addr = 0x0L;
uint32_t *src;
uint32_t *dst;
uint32_t asid;
dbg("video address timeout\r\n"); dbg("video address timeout\r\n");
flush_and_invalidate_caches();
do
{
uint32_t tlb;
uint32_t page_attr;
/*
* search tlb entry id for addr (if not available, the MMU
* will provide a new one based on its LRU algorithm)
*/
MCF_MMU_MMUAR = addr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/*
* retrieve tlb entry with the found TLB entry id
*/
MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */
{
addr += 0x100000;
continue; /* next page */
}
/* modify found TLB entry */
if (addr == 0x0)
{
page_attr =
MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X;
}
else
{
page_attr =
MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V;
}
MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_ACC |
MCF_MMU_MMUOR_UAA;
NOP();
dst = (uint32_t *) 0x60000000 + addr;
src = (uint32_t *) addr;
while (dst < (uint32_t *) 0x60000000 + addr + 0x10000)
{
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
addr += 0x100000;
} while (addr < 0xd00000);
video_tlb = 0x2000;
video_sbt = 0;
} }
@@ -378,26 +290,6 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */ MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT)
{
video_addr_timeout();
handled = true;
}
/*
* check if ACSI DMA interrupt
*/
if (FALCON_MFP_IERA & (1 << 7))
{
/* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7))
{
irq6_acsi_dma_interrupt();
handled = true;
}
}
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB) if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{ {
blink_led(); blink_led();
@@ -430,110 +322,8 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
*/ */
void gpt0_interrupt_handler(void) void gpt0_interrupt_handler(void)
{ {
uint32_t video_address;
uint32_t video_end_address;
int page_number;
bool already_set;
extern uint32_t _STRAM_END;
dbg("screen base = 0x%x\r\n", vbasehi); dbg("screen base = 0x%x\r\n", vbasehi);
if (vbasehi < 2) /* screen base lower than 0x20000? */
{
goto rearm_trigger; /* do nothing */
}
else if (vbasehi >= 0xd0) /* higher than 0xd00000 (normal Falcon address)? */
{
video_sbt = MCF_SLT0_SCNT; /* FIXME: no idea why we need to save the time here */
}
video_address = (vbasehi << 16) | (vbasemid << 8) | vbaselow;
page_number = video_address >> 20; /* calculate a page number */
already_set = (video_tlb & (1 << page_number)); /* already in bitset? */
video_tlb |= page_number; /* set it */
if (! already_set) /* newly set page, need to copy contents */
{
flush_and_invalidate_caches();
dma_memcpy((uint8_t *) video_address + 0x60000000, (uint8_t *) video_address, 0x100000);
/*
* create an MMU TLB entry for the new video page
*/
/*
* first search for an existing entry with our address. If none is found,
* the MMU will propose a new one
*/
MCF_MMU_MMUAR = video_address;
MCF_MMU_MMUOR = 0x106;
NOP();
/*
* take this MMU TLB entry and set it to our video address and page mapping
*/
MCF_MMU_MMUAR = (MCF_MMU_MMUOR >> 16) & 0xffff; /* set TLB id */
MCF_MMU_MMUTR = video_address |
MCF_MMU_MMUTR_ID(sca_page_ID) | /* set video page ID */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (video_address + 0x60000000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0) | /* writethrough */
MCF_MMU_MMUDR_R | /* readable */
MCF_MMU_MMUDR_W | /* writeable */
MCF_MMU_MMUDR_X; /* executable */
MCF_MMU_MMUOR = 0x10b; /* update TLB entry */
}
/*
* Calculate the effective screen memory size to see if we need to map another page
* in case the new screen spans more than one single page
*/
video_end_address = video_address + (vde - vdb) * vwrap;
if (video_end_address < _STRAM_END)
{
page_number = video_end_address >> 20; /* calculate a page number */
already_set = (video_tlb & (1 << page_number)); /* already in bitset? */
video_tlb |= page_number; /* set it */
if (! already_set) /* newly set page, need to copy contents */
{
flush_and_invalidate_caches();
dma_memcpy((uint8_t *) video_end_address + 0x60000000, (uint8_t *) video_end_address, 0x100000);
/*
* create an MMU TLB entry for the new video page
*/
/*
* first search for an existing entry with our address. If none is found,
* the MMU will propose a new one
*/
MCF_MMU_MMUAR = video_end_address;
MCF_MMU_MMUOR = 0x106;
NOP();
/*
* take this MMU TLB entry and set it to our video address and page mapping
*/
MCF_MMU_MMUAR = (MCF_MMU_MMUOR >> 16) & 0xffff; /* set TLB id */
MCF_MMU_MMUTR = video_end_address |
MCF_MMU_MMUTR_ID(sca_page_ID) | /* set video page ID */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (video_end_address + 0x60000000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0) | /* writethrough */
MCF_MMU_MMUDR_R | /* readable */
MCF_MMU_MMUDR_W | /* writeable */
MCF_MMU_MMUDR_X; /* executable */
MCF_MMU_MMUOR = 0x10b; /* update TLB entry */
}
}
rearm_trigger:
MCF_GPT0_GMS &= ~1; /* rearm trigger */ MCF_GPT0_GMS &= ~1; /* rearm trigger */
NOP(); NOP();
MCF_GPT0_GMS |= 1; MCF_GPT0_GMS |= 1;

View File

@@ -70,16 +70,16 @@
#elif defined(MACHINE_M54455) #elif defined(MACHINE_M54455)
#include "m54455.h" #include "m54455.h"
#else #else
#error "unknown machine!" #error "unknown machine!"x
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
//#define DBG_MMU #define DBG_MMU
#ifdef DBG_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 /* DBG_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); } while(0);
/* /*
* set ASID register * set ASID register
@@ -582,8 +582,6 @@ 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_sbt = 0x0; /* clear time */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
/* /*
@@ -658,7 +656,12 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
"PC = 0x%08x\r\n", "PC = 0x%08x\r\n",
fault_address, format_status, mmu_sr, pc); fault_address, format_status, mmu_sr, pc);
dbg("fault = 0x%08x\r\n", fault); dbg("fault = 0x%08x\r\n", fault);
mmu_map_instruction_page(pc, 0);
if (!mmu_map_instruction_page(pc, 0))
{
dbg("bus error\r\n");
return 1; /* bus error */
}
/* due to prefetch, it makes sense to map the next adjacent page also for ITLBs */ /* due to prefetch, it makes sense to map the next adjacent page also for ITLBs */
if (pc + DEFAULT_PAGE_SIZE < TARGET_ADDRESS) if (pc + DEFAULT_PAGE_SIZE < TARGET_ADDRESS)
@@ -666,7 +669,11 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
/* /*
* only do this if the next page is still valid RAM * only do this if the next page is still valid RAM
*/ */
mmu_map_instruction_page(pc + DEFAULT_PAGE_SIZE, 0); if (!mmu_map_instruction_page(pc + DEFAULT_PAGE_SIZE, 0))
{
dbg("bus error\r\n");
return 1; /* bus error */
}
} }
break; break;
@@ -678,7 +685,12 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
"PC = 0x%08x\r\n", "PC = 0x%08x\r\n",
fault_address, format_status, mmu_sr, pc); fault_address, format_status, mmu_sr, pc);
dbg("fault = 0x%08x\r\n", fault); dbg("fault = 0x%08x\r\n", fault);
mmu_map_data_page(fault_address, 0);
if (!mmu_map_data_page(fault_address, 0))
{
dbg("bus error\r\n");
return 1; /* bus error */
}
break; break;
/* else issue an bus error */ /* else issue an bus error */

View File

@@ -68,7 +68,9 @@ void setcookie(uint32_t cookie, uint32_t value)
* work from TSRs) * work from TSRs)
*/ */
if (cookiejar[-1]) if (cookiejar[-1])
{
max_slots = cookiejar[-1]; max_slots = cookiejar[-1];
}
if (max_slots > num_slots) if (max_slots > num_slots)
{ {
@@ -83,7 +85,7 @@ void setcookie(uint32_t cookie, uint32_t value)
printf("cannot set cookie, cookie jar is full!\r\n"); printf("cannot set cookie, cookie jar is full!\r\n");
} }
# define COOKIE_DMAC 0x444D4143L /* FireTOS DMA API */ #define COOKIE_DMAC 0x444d4143L /* FireTOS DMA API */
static char *dt_to_str(enum driver_type dt) static char *dt_to_str(enum driver_type dt)
{ {
@@ -118,7 +120,7 @@ int main(int argc, char *argv[])
if (sig == 0x45544f53) if (sig == 0x45544f53)
{ {
old_vector = Setexc(0x20, my_own_trap0_handler); /* set our own temporarily */ old_vector = Setexc(0x20, my_own_trap0_handler); /* set our own temporarily */
dt = get_bas_drivers(); /* trap #1 */ dt = get_bas_drivers(); /* trap #0 */
(void) Setexc(0x20, old_vector); /* restore original vector */ (void) Setexc(0x20, old_vector); /* restore original vector */
if (dt) if (dt)
@@ -143,17 +145,20 @@ int main(int argc, char *argv[])
ifc++; ifc++;
} }
} }
else
{
printf("driver table not found.\r\n");
}
} }
else else
{ {
printf("not running on EmuTOS,\r\n(signature 0x%04x instead of 0x%04x),\r\n\r\nexiting\r\n", printf("not running on EmuTOS,\r\n(signature 0x%04x instead of 0x%04x\r\n",
(uint32_t) sig, 0x45544f53); (uint32_t) sig, 0x45544f53);
} }
Super(ssp); Super(ssp);
while (Cconis()) Cconin(); /* eat keys */ while (Cconis()) Cconin(); /* eat keys */
// printf("press any key to continue\n\r");
// while (! Cconis());
return 0; return 0;
} }