I have committed these two patches to fix bug #5679.
When executing instruction from EMUPC register in emulation mode, PC
will be advanced. So when PC falls out the valid memory boundary,
hardware error happens. These patches reset the PC to keep it in L1
instruction sram to prevent the hardware error.
I tested the test case in the bug report. It now works OK. And running
gcc execute.exp on bare metal bf537-stamp and bf561-ezkit seems OK.
Running and debugging dual core bf561 blink example seems OK.
Jie
* include/bfin.h (struct bfin_part_data): Add emupc_orig.
(BFIN_PART_EMUPC_ORIG): Define.
(chain_emupc_get): Add a new argument.
(part_emupc_get): Likewise.
(chain_emupc_reset): Declare.
(gen_jump_reg): Declare.
* src/bfin/bfin.c (chain_scan_select_array): New.
(chain_emupc_get): Add a new argument to save EMUPC.
(part_emupc_get): Likewise.
(chain_emuir_set): New.
(chain_emupc_reset): New.
* src/bfin/insn-gen.c (gen_jump_reg): New.
Index: include/bfin.h
===================================================================
--- include/bfin.h (revision 3763)
+++ include/bfin.h (working copy)
@@ -139,6 +139,7 @@ struct bfin_part_data
uint64_t emudat_out;
uint64_t emudat_in;
uint32_t emupc;
+ uint32_t emupc_orig;
};
#define BFIN_PART_BYPASS(part) (((struct bfin_part_data *)((part)->params->data))->bypass)
@@ -153,6 +154,7 @@ struct bfin_part_data
#define BFIN_PART_EMUDAT_OUT(part) (((struct bfin_part_data *)((part)->params->data))->emudat_out)
#define BFIN_PART_EMUDAT_IN(part) (((struct bfin_part_data *)((part)->params->data))->emudat_in)
#define BFIN_PART_EMUPC(part) (((struct bfin_part_data *)((part)->params->data))->emupc)
+#define BFIN_PART_EMUPC_ORIG(part) (((struct bfin_part_data *)((part)->params->data))->emupc_orig)
extern struct emu_oab bfin_emu_oab;
@@ -287,8 +289,8 @@ DECLARE_PART_DBGSTAT_BIT_IS (emudof)
uint16_t part_dbgstat_emucause (chain_t *, int);
void chain_dbgstat_get (chain_t *);
void part_dbgstat_get (chain_t *, int);
-void chain_emupc_get (chain_t *);
-uint32_t part_emupc_get (chain_t *, int);
+void chain_emupc_get (chain_t *, int);
+uint32_t part_emupc_get (chain_t *, int, int);
void chain_dbgstat_clear_ovfs (chain_t *);
void part_dbgstat_clear_ovfs (chain_t *, int);
void chain_wait_emuready (chain_t *);
@@ -329,6 +331,7 @@ void part_execute_instructions (chain_t
void chain_system_reset (chain_t *);
void bfin_core_reset (chain_t *);
void software_reset (chain_t *);
+void chain_emupc_reset (chain_t *, uint32_t *);
uint32_t part_mmr_read_clobber_r0 (chain_t *, int, int32_t, int);
void part_mmr_write_clobber_r0 (chain_t *, int, int32_t, uint32_t, int);
uint32_t part_mmr_read (chain_t *, int, uint32_t, int);
@@ -363,5 +366,6 @@ uint32_t gen_flushinv (enum core_regnum
uint32_t gen_flushinv_pm (enum core_regnum addr);
uint32_t gen_prefetch (enum core_regnum addr);
uint32_t gen_prefetch_pm (enum core_regnum addr);
+uint32_t gen_jump_reg (enum core_regnum addr);
#endif /* BFIN_H */
Index: src/bfin/bfin.c
===================================================================
--- src/bfin/bfin.c (revision 3763)
+++ src/bfin/bfin.c (working copy)
@@ -149,6 +149,30 @@ bfin_set_scan (part_t *part, int scan)
static void emuir_init_value (tap_register *r, uint64_t insn);
int
+chain_scan_select_array (chain_t *chain, int *scan)
+{
+ int i;
+ int changed;
+
+ changed = 0;
+
+ for (i = 0; i < chain->parts->len; i++)
+ {
+ part_t *part = chain->parts->parts[i];
+
+ if (part_is_bypassed (chain, i))
+ changed += bfin_set_scan (part, BYPASS);
+ else
+ changed += bfin_set_scan (part, scan[i]);
+ }
+
+ if (changed)
+ chain_shift_instructions_mode (chain, 0, 1, EXITMODE_UPDATE);
+
+ return 0;
+}
+
+int
chain_scan_select (chain_t *chain, int scan)
{
int i;
@@ -431,7 +455,7 @@ part_dbgstat_get (chain_t *chain, int n)
}
void
-chain_emupc_get (chain_t *chain)
+chain_emupc_get (chain_t *chain, int save)
{
part_t *part;
tap_register *r;
@@ -449,11 +473,13 @@ chain_emupc_get (chain_t *chain)
r = part->active_instruction->data_register->out;
BFIN_PART_EMUPC (part) = register_value (r);
+ if (save)
+ BFIN_PART_EMUPC_ORIG (part) = BFIN_PART_EMUPC (part);
}
}
uint32_t
-part_emupc_get (chain_t *chain, int n)
+part_emupc_get (chain_t *chain, int n, int save)
{
part_t *part;
tap_register *r;
@@ -467,6 +493,8 @@ part_emupc_get (chain_t *chain, int n)
part = chain->parts->parts[n];
r = part->active_instruction->data_register->out;
BFIN_PART_EMUPC (part) = register_value (r);
+ if (save)
+ BFIN_PART_EMUPC_ORIG (part) = BFIN_PART_EMUPC (part);
return BFIN_PART_EMUPC (part);
}
@@ -741,6 +769,39 @@ emuir_init_value (tap_register *r, uint6
}
}
+/* FIXME: Assume all instructions length less than or equal to 32-bit. */
+void
+chain_emuir_set (chain_t *chain, uint64_t *insn, int exit)
+{
+ int emuir_scan;
+ part_t *part;
+ tap_register *r;
+ int i;
+
+ assert (exit == EXITMODE_UPDATE || exit == EXITMODE_IDLE);
+
+ emuir_scan = EMUIR_SCAN;
+ chain_scan_select (chain, DBGCTL_SCAN);
+ chain_dbgctl_bit_set_emuirsz_32 (chain);
+ chain_shift_data_registers_mode (chain, 0, 1, EXITMODE_UPDATE);
+ chain_scan_select (chain, emuir_scan);
+
+ for (i = 0; i < chain->parts->len; i++)
+ {
+ assert ((insn[i] & 0xffffffff00000000ULL) == 0);
+
+ part = chain->parts->parts[i];
+ r = part->active_instruction->data_register->in;
+ emuir_init_value (r, insn[i]);
+ BFIN_PART_EMUIR_A (part) = insn[i];
+ }
+
+ chain_shift_data_registers_mode (chain, 0, 1, exit);
+
+ if (exit == EXITMODE_IDLE && bfin_wait_emuready)
+ chain_wait_emuready (chain);
+}
+
void
chain_emuir_set_same (chain_t *chain, uint64_t insn, int exit)
{
@@ -1585,6 +1646,30 @@ software_reset (chain_t *chain)
bfin_core_reset (chain);
}
+void
+chain_emupc_reset (chain_t *chain, uint32_t *new_pc)
+{
+ uint32_t p0[chain->parts->len];
+ int i;
+
+ chain_register_get (chain, REG_P0, p0);
+
+ for (i = 0; i < chain->parts->len; i++)
+ {
+ part_t *part = chain->parts->parts[i];
+
+ if (part_is_bypassed (chain, i))
+ continue;
+
+ BFIN_PART_EMUPC (part) = new_pc[i];
+ }
+
+ chain_register_set (chain, REG_P0, new_pc);
+ chain_emuir_set_same (chain, gen_jump_reg (REG_P0), EXITMODE_IDLE);
+
+ chain_register_set (chain, REG_P0, p0);
+}
+
uint32_t
part_mmr_read_clobber_r0 (chain_t *chain, int n, int32_t offset, int size)
{
Index: src/bfin/insn-gen.c
===================================================================
--- src/bfin/insn-gen.c (revision 3763)
+++ src/bfin/insn-gen.c (working copy)
@@ -258,3 +258,14 @@ gen_prefetch_pm (enum core_regnum addr)
{
return gen_flush_insn (addr, 0, 1);
}
+
+uint32_t
+gen_jump_reg (enum core_regnum addr)
+{
+ uint32_t insn;
+
+ insn = 0x0050;
+ insn |= addr & 0x7;
+
+ return insn;
+}
\ No newline at end of file
* target_bfin_new.c (rti_limit): Define.
(emupc_get): Add a new argument.
(core_emupc_get): Add a new argument.
(emupc_show): New.
(core_emupc_show): New.
(emupc_reset): New.
(memory_read): Rename to ...
(memory_read_1): ... this.
(memory_read): New.
(dma_copy): Call emupc_reset.
(memory_write): Rename to ...
(memory_write_1): ... this.
(memory_write): New.
(itest_sram_read): Rename to ...
(itest_sram_read_1): ... this.
(itest_sram_read): New.
(itest_sram_write): Rename to ...
(itest_sram_write_1): ... this.
(itest_sram_write): New.
(bfin_open): Calculate rti_limit.
(bfin_connect): Call emupc_reset.
(bfin_read_single_register): Likewise.
(bfin_write_single_register): Likewise.
(bfin_read_mem): Likewise.
(bfin_write_mem): Likewise.
(bfin_resume_from_current): Likewise.
(bfin_resume_from_addr): Likewise.
(bfin_wait_partial): Likewise.
(bfin_add_break): Likewise.
(bfin_remove_break): Likewise.
Index: target_bfin_new.c
===================================================================
--- target_bfin_new.c (revision 3763)
+++ target_bfin_new.c (working copy)
@@ -471,6 +471,7 @@ static uint32_t bfin_frequency = 0;
static int bfin_processor = -1;
static struct timespec bfin_loop_wait_first_ts = {0, 50000000};
static struct timespec bfin_loop_wait_ts = {0, 10000000};
+static int rti_limit = INT_MAX;
typedef struct _bfin_swbp
{
@@ -1101,15 +1102,56 @@ core_dbgstat_get (int core)
}
static void
-emupc_get (void)
+emupc_get (int save)
{
- chain_emupc_get (cpu->chain);
+ chain_emupc_get (cpu->chain, save);
}
static uint32_t
-core_emupc_get (int core)
+core_emupc_get (int core, int save)
{
- return part_emupc_get (cpu->chain, cpu->first_core + core);
+ return part_emupc_get (cpu->chain, cpu->first_core + core, save);
+}
+
+static void
+emupc_show (const char *id)
+{
+ part_t *part;
+ int i;
+
+ chain_emupc_get (cpu->chain, 0);
+ for (i = 0; i < cpu->core_num; i++)
+ {
+ part = cpu->chain->parts->parts[cpu->first_core + i];
+ bfin_log (RP_VAL_LOGLEVEL_DEBUG, "[%d] EMUPC [0x%08x] <%s>",
+ cpu->first_core + i, BFIN_PART_EMUPC (part), id);
+ }
+}
+
+static void
+core_emupc_show (int core, const char *id)
+{
+ part_t *part;
+ part_emupc_get (cpu->chain, cpu->first_core + core, 0);
+ part = cpu->chain->parts->parts[cpu->first_core + core];
+ bfin_log (RP_VAL_LOGLEVEL_DEBUG, "[%d] EMUPC [0x%08x] <%s>",
+ cpu->first_core + core, BFIN_PART_EMUPC (part), id);
+}
+
+static void
+emupc_reset (void)
+{
+ uint32_t new_pc[cpu->chain->parts->len];
+ int i;
+
+ bfin_log (RP_VAL_LOGLEVEL_DEBUG, "Reset EMUPC");
+
+ for (i = 0; i < cpu->core_num; i++)
+ new_pc[i + cpu->first_core] = cpu->cores[i].l1_map.l1_code;
+
+ emupc_show ("before");
+ chain_emupc_reset (cpu->chain, new_pc);
+ emupc_show ("after");
}
static void
@@ -2430,7 +2472,7 @@ icache_flush (int core, uint32_t addr, i
}
static int
-memory_read (int core, uint32_t addr, uint8_t *buf, int size)
+memory_read_1 (int core, uint32_t addr, uint8_t *buf, int size)
{
uint32_t p0, r0;
int count1 = 0, count2 = 0, count3 = 0;
@@ -2523,6 +2565,36 @@ finish_read:
return 0;
}
+static int
+memory_read (int core, uint32_t addr, uint8_t *buf, int size)
+{
+ int s;
+
+ if ((addr & 0x3) != 0)
+ {
+ s = 4 - (addr & 0x3);
+ s = size < s ? size : s;
+ memory_read_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ while (size > 0)
+ {
+ emupc_reset ();
+
+ /* The overhead should be no larger than 0x20. */
+ s = (rti_limit - 0x20) * 4;
+ s = size < s ? size : s;
+ memory_read_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ return 0;
+}
static void
dma_context_save_clobber_p0r0 (int core, uint32_t base, bfin_dma *dma)
@@ -2574,6 +2646,8 @@ dma_copy (int core, uint32_t dest, uint3
int ret;
struct timespec dma_wait = {0, 50000000};
+ emupc_reset ();
+
p0 = core_register_get (core, REG_P0);
r0 = core_register_get (core, REG_R0);
@@ -2751,7 +2825,7 @@ finish_dma_copy:
static int
-memory_write (int core, uint32_t addr, uint8_t *buf, int size)
+memory_write_1 (int core, uint32_t addr, uint8_t *buf, int size)
{
uint32_t p0, r0;
int dcplb_enabled;
@@ -2820,6 +2894,36 @@ finish_write:
return 0;
}
+static int
+memory_write (int core, uint32_t addr, uint8_t *buf, int size)
+{
+ int s;
+
+ if ((addr & 0x3) != 0)
+ {
+ s = 4 - (addr & 0x3);
+ s = size < s ? size : s;
+ memory_write_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ while (size > 0)
+ {
+ emupc_reset ();
+
+ /* The overhead should be no larger than 0x20. */
+ s = (rti_limit - 0x20) * 4;
+ s = size < s ? size : s;
+ memory_write_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ return 0;
+}
static int
@@ -3001,7 +3105,7 @@ test_context_restore_clobber_r0 (int cor
}
static int
-itest_sram_read (int core, uint32_t addr, uint8_t *buf, int size)
+itest_sram_read_1 (int core, uint32_t addr, uint8_t *buf, int size)
{
bfin_test_data test_data_save;
uint32_t p0, r0;
@@ -3056,7 +3160,38 @@ itest_sram_read (int core, uint32_t addr
}
static int
-itest_sram_write (int core, uint32_t addr, uint8_t *buf, int size)
+itest_sram_read (int core, uint32_t addr, uint8_t *buf, int size)
+{
+ int s;
+
+ if ((addr & 0x7) != 0)
+ {
+ s = 8 - (addr & 0x7);
+ s = size < s ? size : s;
+ itest_sram_read_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ while (size > 0)
+ {
+ emupc_reset ();
+
+ /* The overhead should be no larger than 0x20. */
+ s = (rti_limit - 0x20) / 25 * 32;
+ s = size < s ? size : s;
+ itest_sram_read_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ return 0;
+}
+
+static int
+itest_sram_write_1 (int core, uint32_t addr, uint8_t *buf, int size)
{
bfin_test_data test_data_save;
uint32_t p0, r0;
@@ -3116,6 +3251,37 @@ itest_sram_write (int core, uint32_t add
return 0;
}
+static int
+itest_sram_write (int core, uint32_t addr, uint8_t *buf, int size)
+{
+ int s;
+
+ if ((addr & 0x7) != 0)
+ {
+ s = 8 - (addr & 0x7);
+ s = size < s ? size : s;
+ itest_sram_write_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ while (size > 0)
+ {
+ emupc_reset ();
+
+ /* The overhead should be no larger than 0x20. */
+ s = (rti_limit - 0x20) / 25 * 32;
+ s = size < s ? size : s;
+ itest_sram_write_1 (core, addr, buf, s);
+ size -= s;
+ addr += s;
+ buf += s;
+ }
+
+ return 0;
+}
+
/* Wrappers for sram_read and sram_write. If DMA_P is not zero, DMA
should be used. Otherwise, ITEST may be used. */
@@ -4276,6 +4442,15 @@ bfin_open (int argc,
abort ();
}
+ /* Assume only 32-bit instruction are used in gdbproxy. */
+ for (i = 0; i < cpu->core_num; i++)
+ {
+ int tmp;
+ tmp = (cpu->cores[i].l1_map.l1_code_end - cpu->cores[i].l1_map.l1_code) / 8;
+ if (rti_limit > tmp)
+ rti_limit = tmp;
+ }
+
/* Let --sdram-size and --flash-size override the board settting. */
if (sdram_size != -1)
cpu->mem_map.sdram_end = sdram_size;
@@ -4376,6 +4551,8 @@ bfin_connect (char *status_string, int s
emulation_enable ();
emulation_trigger ();
+ emupc_reset ();
+
dbgstat_get ();
need_reset = 0;
@@ -4750,6 +4927,7 @@ bfin_read_single_register (unsigned int
}
else
{
+ emupc_reset ();
cpu->cores[core].registers[reg_no]
= core_register_get (core, map_gdb_core[reg_no]);
data_buf[0] = cpu->cores[core].registers[reg_no] & 0xff;
@@ -4878,6 +5056,7 @@ bfin_write_single_register (unsigned int
cpu->cores[core].registers[reg_no] = value;
+ emupc_reset ();
core_register_set (core, map_gdb_core[reg_no],
cpu->cores[core].registers[reg_no]);
@@ -4949,6 +5128,8 @@ bfin_read_mem (uint64_t addr,
}
}
+ emupc_reset ();
+
if (addr < cpu->mem_map.l1 || addr >= cpu->mem_map.l1_end)
goto skip_l1;
@@ -5269,6 +5450,8 @@ bfin_write_mem (uint64_t addr, uint8_t *
}
}
+ emupc_reset ();
+
if (addr < cpu->mem_map.l1 || addr >= cpu->mem_map.l1_end)
goto skip_l1;
@@ -5519,6 +5702,8 @@ bfin_resume_from_current (int step, int
assert (cpu);
+ emupc_reset ();
+
for (i = 0; i < cpu->core_num; i++)
{
if (cpu->cores[i].is_locked)
@@ -5607,6 +5792,8 @@ bfin_resume_from_addr (int step, int sig
assert (cpu);
+ emupc_reset ();
+
core_register_set (cpu->continue_core, REG_RETE, addr);
return bfin_resume_from_current (step, sig);
@@ -5663,13 +5850,11 @@ bfin_wait_partial (int first,
if (!cpu->cores[i].is_locked
&& !cpu->cores[i].leave_stopped && cpu->cores[i].status_pending_p)
{
- part_t *part = cpu->chain->parts->parts[cpu->first_core + i];
-
sprintf (status_string, "T%02d", cpu->cores[i].pending_signal);
cp = &status_string[3];
if (cpu->cores[i].is_corefault)
{
- pc = BFIN_PART_EMUPC (part);
+ pc = cpu->cores[i].pending_stop_pc;
cp = bfin_out_treg_value (cp, BFIN_PC_REGNUM, pc);
}
else
@@ -5794,8 +5979,9 @@ bfin_wait_partial (int first,
/* All cores are stopped. Check their status. */
+ emupc_get (1);
+ emupc_reset ();
dbgstat_get ();
- emupc_get ();
for (i = 0; i < cpu->core_num; i++)
{
@@ -5813,14 +5999,14 @@ bfin_wait_partial (int first,
{
bfin_log (RP_VAL_LOGLEVEL_INFO,
"%s: [%d] a double fault has occured EMUPC [0x%08X]",
- bfin_target.name, cpu->first_core + i, core_emupc_get (i));
+ bfin_target.name, cpu->first_core + i, BFIN_PART_EMUPC_ORIG (part));
sig = RP_SIGNAL_TRAP;
cpu->cores[i].is_corefault = 1;
cpu->cores[i].status_pending_p = 1;
cpu->cores[i].pending_is_breakpoint = 0;
cpu->cores[i].pending_signal = sig;
- cpu->cores[i].pending_stop_pc = BFIN_PART_EMUPC (part);
+ cpu->cores[i].pending_stop_pc = BFIN_PART_EMUPC_ORIG (part);
}
else if (core_dbgstat_is_emuready (i))
{
@@ -5889,7 +6075,7 @@ bfin_wait_partial (int first,
bfin_log (RP_VAL_LOGLEVEL_DEBUG,
"%s: [%d] unhandled debug status [0x%08X] EMUPC [0x%08X]",
bfin_target.name,
- cpu->first_core + i, BFIN_PART_DBGSTAT (part), BFIN_PART_EMUPC (part));
+ cpu->first_core + i, BFIN_PART_DBGSTAT (part), BFIN_PART_EMUPC_ORIG (part));
}
}
@@ -6121,6 +6307,8 @@ bfin_add_break (int type, uint64_t addr,
"%s: bfin_add_break (%d, 0x%08llx, %d)",
bfin_target.name, type, addr, len);
+ emupc_reset ();
+
switch (type)
{
case 0:
@@ -6311,6 +6499,8 @@ bfin_remove_break (int type, uint64_t ad
"%s: bfin_remove_break(%d, 0x%08llx, %d)",
bfin_target.name, type, addr, len);
+ emupc_reset ();
+
switch (type)
{
case 0:
_______________________________________________
Toolchain-devel mailing list
Toolchain-devel@blackfin.uclinux.org
https://blackfin.uclinux.org/mailman/listinfo/toolchain-devel