Enable faults for unassigned memory accesses and unimplemented ASIs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2824 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
4edebb0e8e
commit
6c36d3fa86
@ -593,7 +593,11 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
|
|||||||
}
|
}
|
||||||
pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
|
pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
|
||||||
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
|
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
|
||||||
|
#ifdef TARGET_SPARC
|
||||||
|
do_unassigned_access(addr, 0, 1, 0);
|
||||||
|
#else
|
||||||
cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
|
cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
|
return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
|
||||||
}
|
}
|
||||||
|
10
exec.c
10
exec.c
@ -1957,11 +1957,10 @@ void qemu_ram_free(ram_addr_t addr)
|
|||||||
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
|
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_UNASSIGNED
|
#ifdef DEBUG_UNASSIGNED
|
||||||
printf("Unassigned mem read 0x%08x\n", (int)addr);
|
printf("Unassigned mem read " TARGET_FMT_lx "\n", addr);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_SPARC
|
#ifdef TARGET_SPARC
|
||||||
// Not enabled yet because of bugs in gdbstub etc.
|
do_unassigned_access(addr, 0, 0, 0);
|
||||||
//raise_exception(TT_DATA_ACCESS);
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1969,11 +1968,10 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
|
|||||||
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_UNASSIGNED
|
#ifdef DEBUG_UNASSIGNED
|
||||||
printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
|
printf("Unassigned mem write " TARGET_FMT_lx " = 0x%x\n", addr, val);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_SPARC
|
#ifdef TARGET_SPARC
|
||||||
// Not enabled yet because of bugs in gdbstub etc.
|
do_unassigned_access(addr, 1, 0, 0);
|
||||||
//raise_exception(TT_DATA_ACCESS);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +290,8 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
|
|||||||
|
|
||||||
int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
|
int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||||
void raise_exception(int tt);
|
void raise_exception(int tt);
|
||||||
|
void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
|
||||||
|
int is_asi);
|
||||||
|
|
||||||
#include "cpu-all.h"
|
#include "cpu-all.h"
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
//#define DEBUG_PCALL
|
//#define DEBUG_PCALL
|
||||||
//#define DEBUG_MMU
|
//#define DEBUG_MMU
|
||||||
//#define DEBUG_UNALIGNED
|
//#define DEBUG_UNALIGNED
|
||||||
|
//#define DEBUG_UNASSIGNED
|
||||||
|
|
||||||
void raise_exception(int tt)
|
void raise_exception(int tt)
|
||||||
{
|
{
|
||||||
@ -151,6 +152,8 @@ void helper_ld_asi(int asi, int size, int sign)
|
|||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
switch (asi) {
|
switch (asi) {
|
||||||
|
case 2: /* SuperSparc MXCC registers */
|
||||||
|
break;
|
||||||
case 3: /* MMU probe */
|
case 3: /* MMU probe */
|
||||||
{
|
{
|
||||||
int mmulev;
|
int mmulev;
|
||||||
@ -179,7 +182,30 @@ void helper_ld_asi(int asi, int size, int sign)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x20 ... 0x2f: /* MMU passthrough */
|
case 9: /* Supervisor code access */
|
||||||
|
switch(size) {
|
||||||
|
case 1:
|
||||||
|
ret = ldub_code(T0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ret = lduw_code(T0 & ~1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 4:
|
||||||
|
ret = ldl_code(T0 & ~3);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ret = ldl_code(T0 & ~3);
|
||||||
|
T0 = ldl_code((T0 + 4) & ~3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xc: /* I-cache tag */
|
||||||
|
case 0xd: /* I-cache data */
|
||||||
|
case 0xe: /* D-cache tag */
|
||||||
|
case 0xf: /* D-cache data */
|
||||||
|
break;
|
||||||
|
case 0x20: /* MMU passthrough */
|
||||||
switch(size) {
|
switch(size) {
|
||||||
case 1:
|
case 1:
|
||||||
ret = ldub_phys(T0);
|
ret = ldub_phys(T0);
|
||||||
@ -197,7 +223,9 @@ void helper_ld_asi(int asi, int size, int sign)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
|
||||||
default:
|
default:
|
||||||
|
do_unassigned_access(T0, 0, 0, 1);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -207,6 +235,8 @@ void helper_ld_asi(int asi, int size, int sign)
|
|||||||
void helper_st_asi(int asi, int size, int sign)
|
void helper_st_asi(int asi, int size, int sign)
|
||||||
{
|
{
|
||||||
switch(asi) {
|
switch(asi) {
|
||||||
|
case 2: /* SuperSparc MXCC registers */
|
||||||
|
break;
|
||||||
case 3: /* MMU flush */
|
case 3: /* MMU flush */
|
||||||
{
|
{
|
||||||
int mmulev;
|
int mmulev;
|
||||||
@ -271,18 +301,28 @@ void helper_st_asi(int asi, int size, int sign)
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 0xc: /* I-cache tag */
|
||||||
|
case 0xd: /* I-cache data */
|
||||||
|
case 0xe: /* D-cache tag */
|
||||||
|
case 0xf: /* D-cache data */
|
||||||
|
case 0x10: /* I/D-cache flush page */
|
||||||
|
case 0x11: /* I/D-cache flush segment */
|
||||||
|
case 0x12: /* I/D-cache flush region */
|
||||||
|
case 0x13: /* I/D-cache flush context */
|
||||||
|
case 0x14: /* I/D-cache flush user */
|
||||||
|
break;
|
||||||
case 0x17: /* Block copy, sta access */
|
case 0x17: /* Block copy, sta access */
|
||||||
{
|
{
|
||||||
// value (T1) = src
|
// value (T1) = src
|
||||||
// address (T0) = dst
|
// address (T0) = dst
|
||||||
// copy 32 bytes
|
// copy 32 bytes
|
||||||
uint32_t src = T1, dst = T0;
|
unsigned int i;
|
||||||
uint8_t temp[32];
|
uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
|
||||||
|
|
||||||
tswap32s(&src);
|
for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
|
||||||
|
temp = ldl_kernel(src);
|
||||||
cpu_physical_memory_read(src, (void *) &temp, 32);
|
stl_kernel(dst, temp);
|
||||||
cpu_physical_memory_write(dst, (void *) &temp, 32);
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0x1f: /* Block fill, stda access */
|
case 0x1f: /* Block fill, stda access */
|
||||||
@ -290,19 +330,17 @@ void helper_st_asi(int asi, int size, int sign)
|
|||||||
// value (T1, T2)
|
// value (T1, T2)
|
||||||
// address (T0) = dst
|
// address (T0) = dst
|
||||||
// fill 32 bytes
|
// fill 32 bytes
|
||||||
int i;
|
unsigned int i;
|
||||||
uint32_t dst = T0;
|
uint32_t dst = T0 & 7;
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
|
|
||||||
val = (((uint64_t)T1) << 32) | T2;
|
val = (((uint64_t)T1) << 32) | T2;
|
||||||
tswap64s(&val);
|
|
||||||
|
|
||||||
for (i = 0; i < 32; i += 8, dst += 8) {
|
for (i = 0; i < 32; i += 8, dst += 8)
|
||||||
cpu_physical_memory_write(dst, (void *) &val, 8);
|
stq_kernel(dst, val);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0x20 ... 0x2f: /* MMU passthrough */
|
case 0x20: /* MMU passthrough */
|
||||||
{
|
{
|
||||||
switch(size) {
|
switch(size) {
|
||||||
case 1:
|
case 1:
|
||||||
@ -322,7 +360,14 @@ void helper_st_asi(int asi, int size, int sign)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
case 0x31: /* Ross RT620 I-cache flush */
|
||||||
|
case 0x36: /* I-cache flash clear */
|
||||||
|
case 0x37: /* D-cache flash clear */
|
||||||
|
break;
|
||||||
|
case 9: /* Supervisor code access, XXX */
|
||||||
|
case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
|
||||||
default:
|
default:
|
||||||
|
do_unassigned_access(T0, 1, 0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,6 +486,7 @@ void helper_ld_asi(int asi, int size, int sign)
|
|||||||
case 0x5f: // D-MMU demap, WO
|
case 0x5f: // D-MMU demap, WO
|
||||||
case 0x77: // Interrupt vector, WO
|
case 0x77: // Interrupt vector, WO
|
||||||
default:
|
default:
|
||||||
|
do_unassigned_access(T0, 0, 0, 1);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -656,6 +702,7 @@ void helper_st_asi(int asi, int size, int sign)
|
|||||||
case 0x8a: // Primary no-fault LE, RO
|
case 0x8a: // Primary no-fault LE, RO
|
||||||
case 0x8b: // Secondary no-fault LE, RO
|
case 0x8b: // Secondary no-fault LE, RO
|
||||||
default:
|
default:
|
||||||
|
do_unassigned_access(T0, 1, 0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -986,3 +1033,53 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TARGET_SPARC64
|
||||||
|
void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
|
||||||
|
int is_asi)
|
||||||
|
{
|
||||||
|
CPUState *saved_env;
|
||||||
|
|
||||||
|
/* XXX: hack to restore env in all cases, even if not called from
|
||||||
|
generated code */
|
||||||
|
saved_env = env;
|
||||||
|
env = cpu_single_env;
|
||||||
|
if (env->mmuregs[3]) /* Fault status register */
|
||||||
|
env->mmuregs[3] = 1; /* overflow (not read before another fault) */
|
||||||
|
if (is_asi)
|
||||||
|
env->mmuregs[3] |= 1 << 16;
|
||||||
|
if (env->psrs)
|
||||||
|
env->mmuregs[3] |= 1 << 5;
|
||||||
|
if (is_exec)
|
||||||
|
env->mmuregs[3] |= 1 << 6;
|
||||||
|
if (is_write)
|
||||||
|
env->mmuregs[3] |= 1 << 7;
|
||||||
|
env->mmuregs[3] |= (5 << 2) | 2;
|
||||||
|
env->mmuregs[4] = addr; /* Fault address register */
|
||||||
|
if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
|
||||||
|
#ifdef DEBUG_UNASSIGNED
|
||||||
|
printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx
|
||||||
|
"\n", addr, env->pc);
|
||||||
|
#endif
|
||||||
|
raise_exception(TT_DATA_ACCESS);
|
||||||
|
}
|
||||||
|
env = saved_env;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
|
||||||
|
int is_asi)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_UNASSIGNED
|
||||||
|
CPUState *saved_env;
|
||||||
|
|
||||||
|
/* XXX: hack to restore env in all cases, even if not called from
|
||||||
|
generated code */
|
||||||
|
saved_env = env;
|
||||||
|
env = cpu_single_env;
|
||||||
|
printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx "\n",
|
||||||
|
addr, env->pc);
|
||||||
|
env = saved_env;
|
||||||
|
#endif
|
||||||
|
raise_exception(TT_DATA_ACCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -3494,6 +3494,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
|||||||
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
|
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
|
||||||
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
|
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
|
||||||
|
return -1;
|
||||||
return phys_addr;
|
return phys_addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user