+ if (nds32->virtual_hosting) {
+ /** enable virtual hosting */
+ uint32_t value_ir3;
+ uint32_t entry_size;
+ uint32_t syscall_address;
+
+ /* get syscall entry address */
+ nds32_get_mapped_reg(nds32, IR3, &value_ir3);
+ entry_size = 0x4 << (((value_ir3 >> 14) & 0x3) << 1);
+ syscall_address = (value_ir3 & 0xFFFF0000) + entry_size * 8; /* The index of SYSCALL is 8 */
+
+ if (nds32->hit_syscall) {
+ /* single step to skip syscall entry */
+ /* use IRET to skip syscall */
+ struct aice_port_s *aice = target_to_aice(target);
+ uint32_t value_ir9;
+ uint32_t value_ir6;
+ uint32_t syscall_id;
+
+ nds32_get_mapped_reg(nds32, IR6, &value_ir6);
+ syscall_id = (value_ir6 >> 16) & 0x7FFF;
+
+ if (syscall_id == NDS32_SYSCALL_EXIT) {
+ /* If target hits exit syscall, do not use IRET to skip handler. */
+ aice_step(aice);
+ } else {
+ /* use api->read/write_reg to skip nds32 register cache */
+ uint32_t value_dimbr;
+ aice_read_debug_reg(aice, NDS_EDM_SR_DIMBR, &value_dimbr);
+ aice_write_register(aice, IR11, value_dimbr + 0xC);
+
+ aice_read_register(aice, IR9, &value_ir9);
+ value_ir9 += 4; /* syscall is always 4 bytes */
+ aice_write_register(aice, IR9, value_ir9);
+
+ /* backup hardware breakpoint 0 */
+ uint32_t backup_bpa, backup_bpam, backup_bpc;
+ aice_read_debug_reg(aice, NDS_EDM_SR_BPA0, &backup_bpa);
+ aice_read_debug_reg(aice, NDS_EDM_SR_BPAM0, &backup_bpam);
+ aice_read_debug_reg(aice, NDS_EDM_SR_BPC0, &backup_bpc);
+
+ /* use hardware breakpoint 0 to stop cpu after skipping syscall */
+ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, value_ir9);
+ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, 0);
+ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, 0xA);
+
+ /* Execute two IRET.
+ * First IRET is used to quit debug mode.
+ * Second IRET is used to quit current syscall. */
+ uint32_t dim_inst[4] = {NOP, NOP, IRET, IRET};
+ aice_execute(aice, dim_inst, 4);
+
+ /* restore origin hardware breakpoint 0 */
+ aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, backup_bpa);
+ aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, backup_bpam);
+ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, backup_bpc);
+ }
+
+ nds32->hit_syscall = false;
+ }
+
+ /* insert breakpoint at syscall entry */
+ struct breakpoint *syscall_break = &(nds32->syscall_break);
+
+ syscall_break->address = syscall_address;
+ syscall_break->type = BKPT_SOFT;
+ syscall_break->set = 1;
+ target_add_breakpoint(target, syscall_break);
+ }