示例#1
0
static void handle_trap(int pid, union uml_pt_regs *regs)
{
	int err, syscall_nr, status;

	syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
	UPT_SYSCALL_NR(regs) = syscall_nr;
	if(syscall_nr < 1){
		relay_signal(SIGTRAP, regs);
		return;
	}

	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
	if(err < 0)
	        panic("handle_trap - nullifying syscall failed errno = %d\n", 
		      errno);

	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
	if(err < 0)
	        panic("handle_trap - continuing to end of syscall failed, "
		      "errno = %d\n", errno);

	CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
	if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
		panic("handle_trap - failed to wait at end of syscall, "
		      "errno = %d, status = %d\n", errno, status);

	handle_syscall(regs);
}
示例#2
0
/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
{
	int err, status;

	/* Mark this as a syscall */
	UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);

	if (!local_using_sysemu)
	{
		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
		if(err < 0)
			panic("handle_trap - nullifying syscall failed errno = %d\n",
			      errno);

		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
		if(err < 0)
			panic("handle_trap - continuing to end of syscall failed, "
			      "errno = %d\n", errno);

		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
		if((err < 0) || !WIFSTOPPED(status) ||
		   (WSTOPSIG(status) != SIGTRAP + 0x80))
			panic("handle_trap - failed to wait at end of syscall, "
			      "errno = %d, status = %d\n", errno, status);
	}

	handle_syscall(regs);
}
示例#3
0
// Poll for incoming messages and send responses. 
void run_server() 
{
	// Struct for reading the syscall over the channel
	syscall_req_t syscall_req;
	syscall_rsp_t syscall_rsp;
	
	int fd_read, fd_write;
	int ret = init_syscall_server(&fd_read, &fd_write);
	if(ret < 0)
		error(ret, "Could not open file desciptors for communication\n");

	printf("Server started....");
	// Continuously read in data from the channel socket
	while(1) {
		syscall_req.payload_len = 0;
		syscall_req.payload = NULL;
		syscall_rsp.payload_len = 0;
		syscall_rsp.payload = NULL;
	
		debug("\nWaiting for syscall...\n");
		read_syscall_req(fd_read, &syscall_req);	

		debug("Processing syscall: %d\n", syscall_req.header.id);
		handle_syscall(&syscall_req, &syscall_rsp);

		debug("Writing response: %d\n", syscall_req.header.id);
		write_syscall_rsp(fd_write, &syscall_rsp);

		if(syscall_req.payload != NULL) 
			free(syscall_req.payload);
		if(syscall_rsp.payload != NULL)
			free(syscall_rsp.payload);
	}
}
示例#4
0
pid_t handle_events_until_dump_trap(pid_t wait_for) {
  while (true) {
    event_t e = wait_event(wait_for);
    if (e.signo == SIGTRAP) {
      if (is_dump_sigtrap(e.tid)) {
        clear_trap(e.tid);
        return e.tid;
      } else if (is_hook_sigtrap(e.tid)) {
        assert(tracer_state == TRACER_LOCKED || tracer_state == TRACER_FIRSTTOUCH);
        clear_trap(e.tid);
        tracer_lock_range(e.tid);
        continue;
      } else { // If we arrive here, it is a syscall
        handle_syscall(e.tid);
        ptrace_syscall(e.tid);
        continue;
      }
    } else if (e.signo == SIGSEGV) {
      void *addr = round_to_page(e.sigaddr);
      switch (tracer_state) {
      case TRACER_UNLOCKED:
        /* We should never get a sigsegv in unlocked state ! */
        errx(EXIT_FAILURE,
             "SIGSEGV at %p before locking memory during capture\n",
             e.sigaddr);
      case TRACER_FIRSTTOUCH:
        firsttouch_handler(e.tid, addr);
        break;
      case TRACER_LOCKED:
        mru_handler(e.tid, addr);
        break;
      case TRACER_DUMPING:
        dump_handler(e.tid, addr);
        break;
      default:
        assert(false); /* we should never be here */
      }
      ptrace_syscall(e.tid);
    }
    else if (e.signo == SIGSTOP) {
      /* A new thread is starting, ignore this event, next wait_event call will
         unblock the thread once its parents registers it in tids array */
    }
    else if (e.signo == SIGWINCH) {
      /* Ignore signal SIGWINCH, tty resize */
      ptrace_syscall(e.tid);
      continue;
    }
    else {
      errx(EXIT_FAILURE, "Unexpected signal in wait_sigtrap: %d\n", e.signo);
    }
  }
  debug_print("%s", "\n");
}
示例#5
0
void handle_trap(struct interrupt_frame *frame)
{
    unsigned int address;
    int trap_cause = __builtin_nyuzi_read_control_reg(CR_TRAP_CAUSE);

    switch (trap_cause & 0xf)
    {
        case TT_PAGE_FAULT:
        case TT_ILLEGAL_STORE:
            address = __builtin_nyuzi_read_control_reg(CR_TRAP_ADDR);
            enable_interrupts();
            if (!handle_page_fault(address, (trap_cause & 0x10) != 0))
            {
                // Jump to user_copy fault handler if set
                if (fault_handler[current_hw_thread()] != 0)
                    frame->pc = fault_handler[current_hw_thread()];
                else
                    bad_fault(frame);
            }

            disable_interrupts();
            break;

        case TT_SYSCALL:
            // Enable interrupts
            address = __builtin_nyuzi_read_control_reg(CR_TRAP_ADDR);
            enable_interrupts();

            frame->gpr[0] = handle_syscall(frame->gpr[0], frame->gpr[1],
                                           frame->gpr[2], frame->gpr[3],
                                           frame->gpr[4], frame->gpr[5]);

            frame->pc += 4;    // Next instruction
            disable_interrupts();
            break;

        case TT_INTERRUPT:
            handle_interrupt(frame);
            break;

        default:
            bad_fault(frame);
    }
}
示例#6
0
void
catbox_syscall_handle(struct trace_context *ctx, struct traced_child *kid)
{
	int syscall;
	struct user_regs_struct regs;
	pid_t pid;

	pid = kid->pid;
	ptrace(PTRACE_GETREGS, pid, 0, &regs);
	syscall = regs.REG_CALL;

	if (kid->in_syscall) { // returning from syscall
		if (syscall == 0xbadca11) {
			// restore real call number, and return our error code
			regs.REG_ERROR = kid->error_code;
			regs.REG_CALL = kid->orig_call;
			ptrace(PTRACE_SETREGS, pid, 0, &regs);
		}
		kid->in_syscall = 0;
	} else { // entering syscall
		kid->in_syscall = 1;

		// skip extra sigtrap from execve call
		if (syscall == __NR_execve) {
			kid->in_execve = 1;
			goto out;
		}

		int ret = handle_syscall(ctx, pid, syscall);
		if (ret != 0) {
			kid->error_code = ret;
			kid->orig_call = regs.REG_CALL;
			if (!ctx->collect_only) {
				// prevent the call by giving an invalid call number
				regs.REG_CALL = 0xbadca11;
				ptrace(PTRACE_SETREGS, pid, 0, &regs);
			}
		}
	}
out:
	// continue tracing
	ptrace(PTRACE_SYSCALL, pid, 0, 0);
}
示例#7
0
文件: syscall.c 项目: Tayyib/uludag
void
catbox_syscall_handle(struct trace_context *ctx, struct traced_child *kid)
{
	int syscall;
	struct user_regs_struct regs;
	pid_t pid;

	pid = kid->pid;
	ptrace(PTRACE_GETREGS, pid, 0, &regs);
	syscall = regs.orig_eax;

	if (kid->in_syscall) {
		// returning from syscall
		if (syscall == 0xbadca11) {
			// restore real call number, and return our error code
			ptrace(PTRACE_POKEUSER, pid, 44, kid->orig_eax);
			ptrace(PTRACE_POKEUSER, pid, 24, kid->error_code);
		}
		kid->in_syscall = 0;
	} else {
		// entering syscall

		// skip extra sigtrap from execve call
		if (syscall == __NR_execve) {
			kid->in_execve = 1;
			goto out;
		}

		int ret = handle_syscall(ctx, pid, syscall);
		if (ret != 0) {
			kid->error_code = ret;
			kid->orig_eax = regs.orig_eax;
			// prevent the call by giving an invalid call number
			ptrace(PTRACE_POKEUSER, pid, 44, 0xbadca11);
		}
		kid->in_syscall = 1;
	}
out:
	// continue tracing
	ptrace(PTRACE_SYSCALL, pid, 0, 0);
}
示例#8
0
文件: main.c 项目: gapry/AOS
void syscall_loop(seL4_CPtr ep) {

    while (1) {
        //dprintf(3, "looping\n");
        seL4_Word badge;
        seL4_Word label;
        seL4_MessageInfo_t message;

        message = seL4_Wait(ep, &badge);
        //dprintf(3, "badge=0x%x\n", badge);
        label = seL4_MessageInfo_get_label(message);
        if(badge & IRQ_EP_BADGE){
            /* Interrupt */
            if (badge & IRQ_BADGE_NETWORK) {
                network_irq();
            }
            if (badge & IRQ_BADGE_TIMER) {
                int ret = timer_interrupt();
                if (ret != CLOCK_R_OK) {
                    //What now?
                }
            }
        }else if(label == seL4_VMFault){
            /* Page fault */
            dprintf(3, "user with pid = %d, 0x%08x is having a vmfault\n", badge & ~USER_EP_BADGE, badge);
            set_cur_proc(badge & ~USER_EP_BADGE);
            handle_pagefault();

        }else if(label == seL4_NoFault) {
            /* System call */
            dprintf(3, "user with pid = %d, 0x%08x is making a syscall\n", badge & ~USER_EP_BADGE, badge);
            set_cur_proc(badge & ~USER_EP_BADGE);
            handle_syscall(badge, seL4_MessageInfo_get_length(message) - 1);

        }else{
            dprintf(3, "Rootserver got an unknown message\n");
        }
    }
}
示例#9
0
void soft_interrupt_entry(regs *r)
{
   const int int_num = regs_intnum(r);
   ASSERT(!are_interrupts_enabled());

   if (int_num == SYSCALL_SOFT_INTERRUPT)
      DEBUG_check_preemption_enabled_for_usermode();

   push_nested_interrupt(int_num);
   disable_preemption();

   if (int_num == SYSCALL_SOFT_INTERRUPT) {

      enable_interrupts_forced();
      {
         handle_syscall(r);
      }
      disable_interrupts_forced(); /* restore IF = 0 */

   } else {

      /*
       * General rule: fault handlers get control with interrupts disabled but
       * they are supposed to call enable_interrupts_forced() ASAP.
       */
      handle_fault(r);

      /* Faults are expected to return with interrupts disabled. */
      ASSERT(!are_interrupts_enabled());
   }

   enable_preemption();
   pop_nested_interrupt();

   if (int_num == SYSCALL_SOFT_INTERRUPT)
      DEBUG_check_preemption_enabled_for_usermode();
}
示例#10
0
文件: sandbox.c 项目: alphaKAI/poe
static int
sigchld_handler(sd_event_source *es, const struct signalfd_siginfo *si, void *vmpid)
{
    (void)es;
    pid_t mpid = *(pid_t *)vmpid;
    if (si->ssi_signo != SIGCHLD) ERROR("parent: unexpected signal");

    while (true) {
        int status;
        pid_t spid = waitpid(-mpid, &status, WNOHANG | __WALL);
        NONNEGATIVE(spid);
        if (!spid) break;

        if (WIFEXITED(status) && spid == mpid) {
            FINISH(POE_SUCCESS, WEXITSTATUS(status), NULL);
        } else if (WIFSIGNALED(status) && spid == mpid) {
            FINISH(POE_SIGNALED, -1, "Program terminated with signal %d (%s)", WTERMSIG(status), strsignal(WTERMSIG(status)));
        } else if (WIFSTOPPED(status)) {
            int e = status >> 16 & 0xff;
            switch (e) {
            case PTRACE_EVENT_SECCOMP:
                handle_syscall(spid);
                break;
            case PTRACE_EVENT_CLONE:
            case PTRACE_EVENT_FORK:
            case PTRACE_EVENT_VFORK:
                ptrace(PTRACE_CONT, spid, 0, 0);
                break;
            default:
                ptrace(PTRACE_CONT, spid, 0, WSTOPSIG(status));
                break;
            }
        }
    }
    return 0;
}
int
main(int argc, char **argv)
{
	int sig, status, exit_code;
	pink_event_t event;
	struct child son;

	/* Parse arguments */
	if (argc < 2) {
		fprintf(stderr, "Usage: %s program [argument...]\n", argv[0]);
		return EXIT_FAILURE;
	}

	/* Fork */
	if ((son.pid = fork()) < 0) {
		perror("fork");
		return EXIT_FAILURE;
	}
	else if (!son.pid) { /* child */
		/* Set up for tracing */
		if (!pink_trace_me()) {
			perror("pink_trace_me");
			_exit(EXIT_FAILURE);
		}
		/* Stop and let the parent continue the execution. */
		kill(getpid(), SIGSTOP);

		++argv;
		execvp(argv[0], argv);
		perror("execvp");
		_exit(-1);
	}
	else {
		waitpid(son.pid, &status, 0);
		event = pink_event_decide(status);
		assert(event == PINK_EVENT_STOP);

		/* Set up the tracing options. */
		if (!pink_trace_setup(son.pid, PINK_TRACE_OPTION_SYSGOOD | PINK_TRACE_OPTION_EXEC)) {
			perror("pink_trace_setup");
			pink_trace_kill(son.pid);
			return EXIT_FAILURE;
		}

		/* Figure out the bitness of the traced child. */
		son.bitness = pink_bitness_get(son.pid);
		if (son.bitness == PINK_BITNESS_UNKNOWN)
			err(1, "pink_bitness_get");
		printf("Child %i runs in %s mode\n", son.pid, pink_bitness_name(son.bitness));

		son.dead = son.insyscall = false;
		sig = exit_code = 0;
		for (;;) {
			/* At this point the traced child is stopped and needs
			 * to be resumed.
			 */
			if (!pink_trace_syscall(son.pid, sig)) {
				perror("pink_trace_syscall");
				return (errno == ESRCH) ? 0 : 1;
			}
			sig = 0;

			/* Wait for the child */
			if ((son.pid = waitpid(son.pid, &status, 0)) < 0) {
				perror("waitpid");
				return (errno == ECHILD) ? 0 : 1;
			}

			/* Check the event. */
			event = pink_event_decide(status);
			switch (event) {
			case PINK_EVENT_SYSCALL:
				handle_syscall(&son);
				break;
				break;
			case PINK_EVENT_EXEC:
				/* Update bitness */
				son.bitness = pink_bitness_get(son.pid);
				if (son.bitness == PINK_BITNESS_UNKNOWN)
					err(1, "pink_bitness_get");
				else
					printf(" (Updating the bitness of child %i to %s mode)\n",
						son.pid, pink_bitness_name(son.bitness));
				break;
			case PINK_EVENT_GENUINE:
			case PINK_EVENT_UNKNOWN:
				/* Send the signal to the traced child as it
				 * was a genuine signal.
				 */
				sig = WSTOPSIG(status);
				break;
			case PINK_EVENT_EXIT_GENUINE:
				exit_code = WEXITSTATUS(status);
				printf("Child %i exited normally with return code %d\n",
						son.pid, exit_code);
				son.dead = true;
				break;
			case PINK_EVENT_EXIT_SIGNAL:
				exit_code = 128 + WTERMSIG(status);
				printf("Child %i exited with signal %d\n",
						son.pid, WTERMSIG(status));
				son.dead = true;
				break;
			default:
				/* Nothing */
				;
			}
			if (son.dead)
				break;
		}

		return exit_code;
	}
}
示例#12
0
void
handle_event(Event *event) {
	if (exiting == 1) {
		exiting = 2;
		debug(1, "ltrace about to exit");
		ltrace_exiting();
	}
	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
	      event->proc ? event->proc->pid : -1, event->type);

	/* If the thread group or an individual task define an
	   overriding event handler, give them a chance to kick in.
	   We will end up calling both handlers, if the first one
	   doesn't sink the event.  */
	if (event->proc != NULL) {
		event = call_handler(event->proc, event);
		if (event == NULL)
			/* It was handled.  */
			return;

		/* Note: the previous handler has a chance to alter
		 * the event.  */
		if (event->proc != NULL
		    && event->proc->leader != NULL
		    && event->proc != event->proc->leader) {
			event = call_handler(event->proc->leader, event);
			if (event == NULL)
				return;
		}
	}

	switch (event->type) {
	case EVENT_NONE:
		debug(1, "event: none");
		return;
	case EVENT_SIGNAL:
		debug(1, "event: signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_signal(event);
		return;
	case EVENT_EXIT:
		debug(1, "event: exit (%d)", event->e_un.ret_val);
		handle_exit(event);
		return;
	case EVENT_EXIT_SIGNAL:
		debug(1, "event: exit signal (%s [%d])",
		      shortsignal(event->proc, event->e_un.signum),
		      event->e_un.signum);
		handle_exit_signal(event);
		return;
	case EVENT_SYSCALL:
		debug(1, "event: syscall (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_syscall(event);
		return;
	case EVENT_SYSRET:
		debug(1, "event: sysret (%s [%d])",
		      sysname(event->proc, event->e_un.sysnum),
		      event->e_un.sysnum);
		handle_sysret(event);
		return;
	case EVENT_ARCH_SYSCALL:
		debug(1, "event: arch_syscall (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_syscall(event);
		return;
	case EVENT_ARCH_SYSRET:
		debug(1, "event: arch_sysret (%s [%d])",
				arch_sysname(event->proc, event->e_un.sysnum),
				event->e_un.sysnum);
		handle_arch_sysret(event);
		return;
	case EVENT_CLONE:
	case EVENT_VFORK:
		debug(1, "event: clone (%u)", event->e_un.newpid);
		handle_clone(event);
		return;
	case EVENT_EXEC:
		debug(1, "event: exec()");
		handle_exec(event);
		return;
	case EVENT_BREAKPOINT:
		debug(1, "event: breakpoint");
		handle_breakpoint(event);
		return;
	case EVENT_NEW:
		debug(1, "event: new process");
		handle_new(event);
		return;
	default:
		fprintf(stderr, "Error! unknown event?\n");
		exit(1);
	}
}
示例#13
0
文件: main.c 项目: jmgc/noah
void
main_loop(int return_on_sigret)
{
  /* main_loop returns only if return_on_sigret == 1 && rt_sigreturn is invoked.
     see also: rt_sigsuspend */

  while (task_run() == 0) {

    /* dump_instr(); */
    /* print_regs(); */

    uint64_t exit_reason;
    vmm_read_vmcs(VMCS_RO_EXIT_REASON, &exit_reason);

    switch (exit_reason) {
    case VMX_REASON_VMCALL:
      printk("reason: vmcall\n");
      assert(false);
      break;

    case VMX_REASON_EXC_NMI: {
      /* References:
       * - Intel SDM 27.2.2, Table 24-15: Information for VM Exits Due to Vectored Events
       */
      uint64_t exc_info;
      vmm_read_vmcs(VMCS_RO_VMEXIT_IRQ_INFO, &exc_info);

      int int_type = (exc_info & 0x700) >> 8;
      switch (int_type) {
      default:
        assert(false);
      case VMCS_EXCTYPE_EXTERNAL_INTERRUPT:
      case VMCS_EXCTYPE_NONMASKTABLE_INTERRUPT:
        /* nothing we can do, host os handles it */
        continue;
      case VMCS_EXCTYPE_HARDWARE_EXCEPTION: /* including invalid opcode */
      case VMCS_EXCTYPE_SOFTWARE_EXCEPTION: /* including break points, overflows */
        break;
      }

      int exc_vec = exc_info & 0xff;
      switch (exc_vec) {
      case X86_VEC_PF: {
        /* FIXME */
        uint64_t gladdr;
        vmm_read_vmcs(VMCS_RO_EXIT_QUALIFIC, &gladdr);
        printk("page fault: caused by guest linear address 0x%llx\n", gladdr);
        send_signal(getpid(), LINUX_SIGSEGV);
      }
      case X86_VEC_UD: {
        uint64_t instlen, rip;
        vmm_read_vmcs(VMCS_RO_VMEXIT_INSTR_LEN, &instlen);
        vmm_read_register(HV_X86_RIP, &rip);
        if (is_syscall(instlen, rip)) {
          int r = handle_syscall();
          vmm_read_register(HV_X86_RIP, &rip); /* reload rip for execve */
          vmm_write_register(HV_X86_RIP, rip + 2);
          if (return_on_sigret && r < 0) {
            return;
          }
          continue;
        } else if (is_avx(instlen, rip)) {
	  uint64_t xcr0;
	  vmm_read_register(HV_X86_XCR0, &xcr0);
	  if ((xcr0 & XCR0_AVX_STATE) == 0) {
	    unsigned int eax, ebx, ecx, edx;
	    get_cpuid_count(0x0d, 0x0, &eax, &ebx, &ecx, &edx);
	    if (eax & XCR0_AVX_STATE) {
	      vmm_write_register(HV_X86_XCR0, xcr0 | XCR0_AVX_STATE);
	      continue;
	    }
	  }
	}
        /* FIXME */
        warnk("invalid opcode! (rip = %p): ", (void *) rip);
        unsigned char inst[instlen];
        if (copy_from_user(inst, rip, instlen))
          assert(false);
        for (uint64_t i = 0; i < instlen; ++i)
          fprintf(stderr, "%02x ", inst[i] & 0xff);
        fprintf(stderr, "\n");
        send_signal(getpid(), LINUX_SIGILL);
      }
      case X86_VEC_DE:
      case X86_VEC_DB:
      case X86_VEC_BP:
      case X86_VEC_OF:
      case X86_VEC_BR:
      case X86_VEC_NM:
      case X86_VEC_DF:
      case X86_VEC_TS:
      case X86_VEC_NP:
      case X86_VEC_SS:
      case X86_VEC_GP:
      case X86_VEC_MF:
      case X86_VEC_AC:
      case X86_VEC_MC:
      case X86_VEC_XM:
      case X86_VEC_VE:
      case X86_VEC_SX:
      default:
        /* FIXME */
        warnk("exception thrown: %d\n", exc_vec);
        uint64_t instlen, rip;
        vmm_read_vmcs(VMCS_RO_VMEXIT_INSTR_LEN, &instlen);
        vmm_read_register(HV_X86_RIP, &rip);
        fprintf(stderr, "inst: \n");
        unsigned char inst[instlen];
        if (copy_from_user(inst, rip, instlen))
          assert(false);
        for (uint64_t i = 0; i < instlen; ++i)
          fprintf(stderr, "%02x ", inst[i] & 0xff);
        fprintf(stderr, "\n");
        exit(1);                /* TODO */
      }
      break;
    }

    case VMX_REASON_EPT_VIOLATION:
      printk("reason: ept_violation\n");

      uint64_t gpaddr;
      vmm_read_vmcs(VMCS_GUEST_PHYSICAL_ADDRESS, &gpaddr);
      printk("guest-physical address = 0x%llx\n", gpaddr);

      uint64_t qual;

      vmm_read_vmcs(VMCS_RO_EXIT_QUALIFIC, &qual);
      printk("exit qualification = 0x%llx\n", qual);

      if (qual & (1 << 7)) {
        uint64_t gladdr;
        vmm_read_vmcs(VMCS_RO_GUEST_LIN_ADDR, &gladdr);
        printk("guest linear address = 0x%llx\n", gladdr);

        int verify = 0;
        if (qual & (1 << 0)) {
          verify = VERIFY_READ;
        } else if (qual & (1 << 1)) {
          verify = VERIFY_WRITE;
        } else if (qual & (1 << 2)) {
          verify = VERIFY_EXEC;
        }

        if (!addr_ok(gladdr, verify)) {
          printk("page fault: caused by guest linear address 0x%llx\n", gladdr);
          send_signal(getpid(), LINUX_SIGSEGV);
        }
      } else {
        printk("guest linear address = (unavailable)\n");
      }
      break;

    case VMX_REASON_CPUID: {
      uint64_t rax;
      vmm_read_register(HV_X86_RAX, &rax);
      unsigned eax, ebx, ecx, edx;
      __get_cpuid(rax, &eax, &ebx, &ecx, &edx);

      vmm_write_register(HV_X86_RAX, eax);
      vmm_write_register(HV_X86_RBX, ebx);
      vmm_write_register(HV_X86_RCX, ecx);
      vmm_write_register(HV_X86_RDX, edx);

      uint64_t rip;
      vmm_read_register(HV_X86_RIP, &rip);
      vmm_write_register(HV_X86_RIP, rip + 2);

      break;
    }

    case VMX_REASON_IRQ: {
      break;
    }

    case VMX_REASON_HLT: {
      break;
    }

    default:
    // See: Intel® 64 and IA-32 Architectures Software Developer’s Manual
    // Volume 3B: System Programming Guide, Part 2
    // Order Number: 253669-033US
    // December 2009
    // Section 21.9 VM-EXIT INFORMATION FIELDS
    // 21.9.1 Basic VM-Exit information
    // Exit reason
      if (exit_reason & (1<<31)) {
        exit_reason ^= (1<<31);
        printk("VM-entry failure exit reason: %llx\n", exit_reason);
      } else
        printk("other exit reason: %llx\n", exit_reason);
      if (exit_reason & VMX_REASON_VMENTRY_GUEST)
        check_vm_entry();
      vmm_read_vmcs(VMCS_RO_EXIT_QUALIFIC, &qual);
      printk("exit qualification: %llx\n", qual);
    }
  }

  __builtin_unreachable();
}
示例#14
0
文件: 6502v.c 项目: dhkris/6502v
word xqt( m6502* m, byte* j, word X ) {
   word Y = 0;
   /* INSTRUCTIONS */
   if( CI == op_LDA_imm ) {
      Y++;
      byte new_a_value = j[X+Y];
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  LDA:immediate <-- #%0.2x (was #%0.2x)\n", 
              CADD, new_a_value, m->acc);
      #endif
      m->acc = new_a_value;
      Y++;
   }
   else if( CI == op_LDA_abs ) {
      Y++;
      word addr = ADDRGEN(j[Y],j[++Y]);
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  LDA:absolute <-- (byteAt: %0.4x (=%0.2x))\n", 
              CADD, addr, m->memory[addr]);
      #endif      
      m->acc = m->memory[addr];
      Y++;
   }
   else if( CI == op_LDA_abx ) {
      Y++;
      word addr = (ADDRGEN(j[Y],j[++Y])) + m->ix;
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  LDA:absolute+x <-- (byteAt: %0.4x (=%0.2x))\n", 
              CADD, addr, m->memory[addr]);
      #endif      
      m->acc = m->memory[addr];
      Y++;
   }   
   else if( CI == op_LDA_idx ) {
      Y++;
      word addr = m->memory[(word)(ADDRGEN(j[Y],j[++Y]))+m->ix];
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  LDA:indirect+x <-- (byteAt: %0.4x (=%0.2x))\n", 
              CADD, addr, m->memory[addr]);
      #endif      
      m->acc = m->memory[addr];
      Y++;
   }      
   else if( CI == op_STA_abs ) {
      Y++;
      word addr = ADDRGEN( j[CO], j[X+(++Y)]);
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  STA:absolute --> $%4x\n", CADD, addr);      
      #endif
      if(addr == OUTCHAR_ADDR) m->OUTFLAG=ON;
      MEM(addr) = m->acc;
      ++Y;
   }
   else if( CI == op_STX_abs ) {
      Y++;
      word addr = ADDRGEN( j[CO], j[X+(++Y)]);
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  STX:absolute --> $%4x\n", CADD, addr);      
      #endif
      if(addr == OUTCHAR_ADDR) m->OUTFLAG=ON;
      MEM(addr) = m->ix;
      ++Y;
   }   
   else if( CI == op_CMP_imm ) {
      Y++;
      byte cmp_byte = j[CO];
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  CMP:immediate #%0.2x = #%0.2x?...\n",
              CADD, cmp_byte, m->acc );
      #endif
      if( cmp_byte == m->acc ) {
         m->ZEROFLAG = ON;
         m->NOTZEROFLAG = OFF;
      } else if( cmp_byte > m->acc ) {
         m->NOTZEROFLAG = ON;
         m->NOTZEROFLAG = OFF;
      }
      ++Y;
   }
   else if( CI == op_CMP_abs ) {
      Y++;
      word cmp_addr = ADDRGEN( j[Y], j[++Y]);
      byte cmp_byte = MEM(cmp_addr);
      if( cmp_byte == m->acc ) {
         m->ZEROFLAG = ON;
         m->NOTZEROFLAG = OFF;
      } else if( cmp_byte > m->acc ) {
         m->NOTZEROFLAG = ON;
         m->NOTZEROFLAG = OFF;
      }      
   }
   else if( CI == op_BNE_rel ) {
      Y++;
      #ifdef DEBUG
      fprintf(stderr,"$%0.4x |  BNE:relative <if_branch_addr:=+$%x> ", CADD, j[CO]);
      #endif
      if( m->ZEROFLAG == OFF ) {
         #ifdef DEBUG
         fprintf(stderr,"-:true; branching to addr: %0.2x...\n", X+Y+j[X+1]+1);
         #endif
         Y = X+Y+j[X+1]+1;
         X = 0;
         m->DID_CMP = OFF;
                  return Y;
      } else {
         #ifdef DEBUG
         fprintf(stderr,"-:false; no_branch_taken");
         #endif
         Y++;
      }
      #ifdef DEBUG
      fprintf(stderr,"\n");
      #endif
   }
   else if( CI == op_BEQ_rel ) {
       Y++;
       #ifdef DEBUG
       fprintf(stderr,"$%0.4x | BEQ:relative <if_branch_addr:=$%0.2x> ", CADD, j[CO]);
       #endif
       if( m->ZEROFLAG == ON ) {
           #ifdef DEBUG
           fprintf(stderr, "-: branching>\n");
#endif
           Y=X+Y+j[X+1]+1;
           X=0;
           m->DID_CMP = OFF;
           return Y;
       } else {
           #ifdef DEBUG
           fprintf(stderr,"-/no_branch\n");
           #endif
       }
   }
   else if( CI == op_DEC_abs ) {
      word addr = ADDRGEN( j[X+(++Y)], j[X+(++Y)] );
      #ifdef DEBUG
         fprintf(stderr,"$%0.4x |  INC:absolute_addr:$%0.4x! %0.2x => %0.2x\n", 
                 CADD, addr, MEM(addr), MEM(addr)-1);
      #endif
      if(addr == OUTCHAR_ADDR) m->OUTFLAG=ON;
      MEM(addr) -= 1;
   } 
   else if( CI == op_INC_abs ) {
      word addr = ADDRGEN( j[X+(++Y)], j[X+(++Y)] );
      #ifdef DEBUG
         fprintf(stderr,"$%0.4x |  INC:absolute_addr:$%0.4x! #%0.2x => #%0.2x\n", 
                 CADD, addr, MEM(addr), MEM(addr)+1);
      #endif
      MEM(addr) += 1;      
   }
   else if( CI == op_INX ) {
      #ifdef DEBUG
         fprintf(stderr,"$%0.4x |  INX; x := #%0.2x -> #%0.2x\n", 
                 CADD, m->ix, m->ix+1 );
      #endif
      m->ix += 1;
   }
   else if( CI == op_JMP_abs )  /* absolute (immediate) */ {
      word addr = ADDRGEN( j[X+(++Y)], j[X+(++Y)] );
      #ifdef DEBUG
         fprintf(stderr,"$%0.4x |  JMP:absolute_addr ------> jump_to:$%0.4x\n", 
                 CADD, addr);
      #endif
      X = addr;
      Y = 0;
      return addr;
   }
   else if( CI == op_JMP_ind ) /*indirect*/ {
      word addr_addr = ADDRGEN( j[X+(++Y)], j[X+(++Y)] );
      word addr = MEM(addr_addr);
      #ifdef DEBUG
         fprintf(stderr,"$%0.4x |  JMP:indirection! jump_to_value_of:$%0.4x (-*=>$%0.4x)\n", 
                 CADD, addr_addr, addr);
      #endif      
      X = addr;
      Y = 0;
      return addr;
   }
   else if( CI == op_DIE ) {
      #ifdef DEBUG
         fprintf(stderr,"$%0.4x |  EXIT\n", CADD);
      #endif
      return 0xFFFF;
   }
   
   /* IRQ handling!*/
   else if( CI == op_BRK ) {
       m->stack_ptr++;
       m->stack[m->stack_ptr] = j[X+Y];
       handle_syscall(m);
   }
  
   /* HANDLE OUTCHAR */
   if( m->OUTFLAG == ON ) {
      #ifdef DEBUG
      fprintf(stderr, "$%0.4x |  POLL_OUTCHAR_FOUND: '%c'\n", 
              CO, m->memory[OUTCHAR_ADDR]);
      #else
      fputc(MEM(OUTCHAR_ADDR), stdout);
      #endif
      m->OUTFLAG=OFF;
   }

   /* HANDLE SYNC */
   if( DOES_WAIT == 1 ) usleep(1000000/CPS);
   m->pc = X+Y;
   if(Y==0) Y=1;
   return Y+X;
}
示例#15
0
void execute_one_inst(processor_t* p, int prompt, int print_regs)
{
	inst_t inst;
	
	/* fetch an instruction */
	inst.bits = load_mem(p->pc, SIZE_WORD);
	
	/* interactive-mode prompt */
	if(prompt)
	{
		if (prompt == 1) {
			printf("simulator paused, enter to continue...");
			while(getchar() != '\n')
				;
		}
		printf("%08x: ",p->pc);
		disassemble(inst);
	}
	
	switch (inst.rtype.opcode) /* could also use e.g. inst.itype.opcode */
	{
		case 0x0: // opcode == 0x0 (SPECIAL)
			
			switch (inst.rtype.funct)
		{
			case 0x0: //opcode = 0x0 (SLL)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rt] << inst.rtype.shamt;
				p->pc += 4;
				break;
				
			case 0x2: //opcode = 0x2 (SRL)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rt] >> inst.rtype.shamt;
				p->pc += 4;
				break;
				
			case 0x3: //opcode = 0x3 (SRA)
				p->R[inst.rtype.rd] = (signed int)(p->R[inst.rtype.rt]) >> inst.rtype.shamt;
				p->pc += 4;
				break;
				
			case 0x8: //opcode = 0x8 (JR)
				p->pc = p->R[inst.rtype.rs];
				break;
				
			case 0x9: //opcode = 0x9 (JALR)
			{
				int tmp = p->pc + 4;
				p->pc = p->R[inst.rtype.rs];
				p->R[inst.rtype.rd] = tmp;
			}
				break;
				
			case 0xc: // funct == 0xc (SYSCALL)
				handle_syscall(p);
				p->pc += 4;
				break;
				
			case 0x21: //opcode = 0x21 (ADDU)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] + p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x23: //opcode = 0x23 (SUBU)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] - p->R[inst.rtype.rt]; 
				p->pc += 4;
				break;
				
			case 0x24: //opcode = 0x24 (AND)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] & p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x25: // funct == 0x25 (OR)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] | p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x26: // funct == 0x26 (XOR)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x27: // funct == 0x27 (NOR)
				p->R[inst.rtype.rd] = ~(p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt]);
				p->pc += 4;
				break;
				
			case 0x2a: // funct == 0x2a (SLT)
				p->R[inst.rtype.rd] = (signed int)(p->R[inst.rtype.rs]) < (signed int)(p->R[inst.rtype.rt]);
				p->pc += 4;
				break;
				
			case 0x2b: // funct == 0x2b (SLTU)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] < p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			default: // undefined funct
				fprintf(stderr, "%s: pc=%08x, illegal instruction=%08x\n", __FUNCTION__, p->pc, inst.bits);
				exit(-1);
				break;
		}
			break;
			
		case 0x2: // opcode == 0x2 (J)
			p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
			break;
			
		case 0x3: // opcode == 0x3 (JAL)
			p->R[31] = p->pc + 4;
			p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
			break;
			
		case 0x4: // opcode == 0x4 (BEQ)
			if (p->R[inst.itype.rs] == p->R[inst.itype.rt]) {
				p->pc += (4 + (((int16_t)inst.itype.imm) << 2));
			}
			else {
				p->pc += 4;
			}
			break;
			
		case 0x5: // opcode == 0x5 (BNE)
			if (p->R[inst.itype.rs] != p->R[inst.itype.rt]) {
				p->pc += (4 + (((int16_t)inst.itype.imm) << 2));
			}
			else {
				p->pc += 4;
			}
			break;
			
		case 0x9: // opcode == 0x9 (ADDIU)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] + (int16_t)(inst.itype.imm);
			p->pc += 4;
			break;
			
		case 0xa: // opcode == 0xa (SLTI)
			p->R[inst.itype.rt] = (signed int)p->R[inst.itype.rs] < (int16_t)(inst.itype.imm);
			p->pc += 4;
			break;
			
		case 0xb: // opcode == 0xb (SLTIU)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] < (int16_t)(inst.itype.imm);
			p->pc += 4;
			break;
			
		case 0xc: // opcode == 0xc (ANDI)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] & inst.itype.imm;
			p->pc += 4;
			break;
			
		case 0xd: // opcode == 0xd (ORI)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] | inst.itype.imm;
			p->pc += 4;
			break;
			
		case 0xe: // opcode == 0xe (XORI)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] ^ inst.itype.imm;
			p->pc += 4;
			break;
			
		case 0xf: // opcode == 0xf (LUI)
			p->R[inst.itype.rt] = inst.itype.imm << 16;
			p->pc += 4;
			break;
			
		case 0x20: // opcode == 0x20 (LB)
			p->R[inst.itype.rt] = (int8_t)(load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE));  
			p->pc += 4;
			break;
			
		case 0x21: // opcode == 0x21 (LH)
			p->R[inst.itype.rt] = (int16_t)(load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD));  
			p->pc += 4;
			break;
			
		case 0x23: // opcode == 0x23 (LW)
			p->R[inst.itype.rt] = (int32_t)load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_WORD);  
			p->pc += 4;
			break;
			
		case 0x24: // opcode == 0x24 (LBU)
			p->R[inst.itype.rt] = load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE);  
			p->pc += 4;
			break;
			
		case 0x25: // opcode == 0x25 (LHU)
			p->R[inst.itype.rt] = load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD);  
			p->pc += 4;
			break;
			
		case 0x28: // opcode == 0x28 (SB)
			store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE, p->R[inst.itype.rt]);
			p->pc += 4;
			break;
			
		case 0x29: // opcode == 0x29 (SH)
			store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD, p->R[inst.itype.rt]);
			p->pc += 4;
			break;
			
		case 0x2b: // opcode == 0x2b (SW)
			store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_WORD, p->R[inst.itype.rt]);
			p->pc += 4;
			break;
			
		default: // undefined opcode
			fprintf(stderr, "%s: pc=%08x, illegal instruction: %08x\n", __FUNCTION__, p->pc, inst.bits);
			exit(-1);
			break;
	}
	
	// enforce $0 being hard-wired to 0
	p->R[0] = 0;
	
	if(print_regs)
		print_registers(p);
}
示例#16
0
int
vm_event(vm_t* vm, seL4_MessageInfo_t tag)
{
    seL4_Word label;
    seL4_Word length;

    label = seL4_MessageInfo_get_label(tag);
    length = seL4_MessageInfo_get_length(tag);

    switch (label) {
    case SEL4_PFIPC_LABEL: {
        int err;
        fault_t* fault;
        fault = vm->fault;
        err = new_fault(fault);
        assert(!err);
        do {
            err = handle_page_fault(vm, fault);
            if (err) {
                return -1;
            }
        } while (!fault_handled(fault));
    }
    break;

    case SEL4_EXCEPT_IPC_LABEL: {
        int err;
        assert(length == SEL4_EXCEPT_IPC_LENGTH);
        err = handle_syscall(vm, length);
        assert(!err);
        if (!err) {
            seL4_MessageInfo_t reply;
            reply = seL4_MessageInfo_new(0, 0, 0, 0);
            seL4_Reply(reply);
        }
    }
    break;

    case SEL4_USER_EXCEPTION_LABEL: {
        seL4_Word ip;
        int err;
        assert(length == SEL4_USER_EXCEPTION_LENGTH);
        ip = seL4_GetMR(0);
        err = handle_exception(vm, ip);
        assert(!err);
        if (!err) {
            seL4_MessageInfo_t reply;

            reply = seL4_MessageInfo_new(0, 0, 0, 0);
            seL4_Reply(reply);
        }
    }
    break;
    case SEL4_VGIC_MAINTENANCE_LABEL: {
        int idx;
        int err;
        assert(length == SEL4_VGIC_MAINTENANCE_LENGTH);
        idx = seL4_GetMR(EXCEPT_IPC_SYS_MR_R0);
        /* Currently not handling spurious IRQs */
        assert(idx >= 0);

        err = handle_vgic_maintenance(vm, idx);
        assert(!err);
        if (!err) {
            seL4_MessageInfo_t reply;

            reply = seL4_MessageInfo_new(0, 0, 0, 0);
            seL4_Reply(reply);
        }
    }
    break;
    case SEL4_VCPU_FAULT_LABEL: {
        seL4_MessageInfo_t reply;
        seL4_UserContext regs;
        seL4_CPtr tcb;
        uint32_t hsr;
        int err;
        assert(length == SEL4_VCPU_FAULT_LENGTH);
        hsr = seL4_GetMR(EXCEPT_IPC_SYS_MR_R0);
        /* Increment the PC and ignore the fault */
        tcb = vm_get_tcb(vm);
        err = seL4_TCB_ReadRegisters(tcb, false, 0,
                                     sizeof(regs) / sizeof(regs.pc), &regs);
        assert(!err);
        switch (hsr) {
        case HSR_WFI:
        case HSR_WFE:
            regs.pc += (regs.cpsr & BIT(5)) ? 2 : 4;
            err = seL4_TCB_WriteRegisters(tcb, false, 0,
                                          sizeof(regs) / sizeof(regs.pc), &regs);
            assert(!err);
            reply = seL4_MessageInfo_new(0, 0, 0, 0);
            seL4_Reply(reply);
            return 0;
        default:
            printf("Unhandled VCPU fault from [%s]: HSR 0x%08x\n", vm->name, hsr);
            print_ctx_regs(&regs);
            return -1;
        }
    }
    break;
    default:
        /* What? Why are we here? What just happened? */
        printf("Unknown fault from [%s]: label=0x%x length=0x%x\n",
               vm->name, label, length);
        return -1;
    }
    return 0;
}
示例#17
0
void execute_one_inst(processor_t* p, int prompt, int print_regs)
{
  inst_t inst;

  /* fetch an instruction */
  inst.bits = load_mem(p->pc, SIZE_WORD);

  /* interactive-mode prompt */
  if(prompt)
  {
    if (prompt == 1) {
      printf("simulator paused, enter to continue...");
      while(getchar() != '\n')
        ;
    }
    printf("%08x: ",p->pc);
    disassemble(inst);
  }
	uint32_t temp;
  switch (inst.rtype.opcode) /* could also use e.g. inst.itype.opcode */
  {
  case 0x0: // opcode == 0x0 (SPECIAL)
  
    switch (inst.rtype.funct) {
    	case 0x0: // funct == 0x0 (sll)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rt] << inst.rtype.shamt;
     	 	p->pc += 4;
      	break;    		
    
    	case 0x2: // funct == 0x0 (srl)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rt] >> inst.rtype.shamt;
     	 	p->pc += 4;
      	break;   
      
      case 0x3: // funct == 0x0 (sra)
      	p->R[inst.rtype.rd] = (signed)p->R[inst.rtype.rt] >> inst.rtype.shamt;
    		p->pc += 4;
      	break;
      
      case 0x8: // funct == 0x8 (jr)
      	p->pc = p->R[inst.rtype.rs];
    		break;
    	
    	case 0x9: // funct == 0x9 (jalr)
    		temp = p->pc + 4;
    		p->pc = p->R[inst.rtype.rs];
    		p->R[inst.rtype.rd] = temp;
    		break;
				
    	case 0x10: // funct == 0x10 (mfhi)
    		p->R[inst.rtype.rd] = p->RHI;
    		p->pc += 4;
    		break;
    
    	case 0x12: // funct == 0x12 (mflo)
    		p->R[inst.rtype.rd] = p->RLO;
    		p->pc += 4;
    		break;
    	
    	case 0x18: // funct == 0x18 (mult)
    		perform_mult(p->R[inst.rtype.rs], p->R[inst.rtype.rt], &(p->RHI), &(p->RLO));
    		p->pc += 4;
    		break;
    	
    	case 0x21: // funct == 0x21 (addu)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] + p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x23: // funct == 0x23 (subu)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] - p->R[inst.rtype.rd];
    		p->pc += 4;
    		break;
    	
    	case 0x24: // funct == 0x24 (and)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] & p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x26: // funct == 0x26 (xor)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x27: // funct == 0x27 (nor)
    		p->R[inst.rtype.rd] = ~(p->R[inst.rtype.rs] | p->R[inst.rtype.rt]);
    		p->pc += 4;
    		break;
    	
    	case 0x2a: // funct == 0x2a (slt)
    		p->R[inst.rtype.rd] = (signed)p->R[inst.rtype.rs] < (signed)p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x2b: // funct == 0x2a (sltu)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] < p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    		
    	case 0xc: // funct == 0xc (SYSCALL)
      	handle_syscall(p);
     	 	p->pc += 4;
      	break;

    	case 0x25: // funct == 0x25 (OR)
      	p->R[inst.rtype.rd] = p->R[inst.rtype.rs] | p->R[inst.rtype.rt];
      	p->pc += 4;
      	break;

    	default: // undefined funct
      	fprintf(stderr, "%s: pc=%08x, illegal instruction=%08x\n", __FUNCTION__, p->pc, inst.bits);
      	exit(-1);
      	break;
    	}
    break;
	
	case 0x3: // opcode == 0x3 (jal)
		p->R[31] = p->pc += 4;
		p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
		break;
	
	case 0x4: // opcode == 0x4 (beq)
		if (p->R[inst.itype.rs] == p->R[inst.itype.rt]) {
			p->pc += 4 + signext(inst.itype.imm)*4;
		}
		else {
			p->pc += 4;
		}
		break;
	
	case 0x5: // opcode == 0x4 (bne)
		if (p->R[inst.itype.rs] != p->R[inst.itype.rt]) {
			p->pc += 4 + signext(inst.itype.imm)*4;
		}
		else {
			p->pc += 4;
		}
		break;
	
	case 0x9: // opcode == 0x9 (addiu)
		p->R[inst.rtype.rt] = p->R[inst.itype.rs] + signext(inst.itype.imm);
    p->pc += 4;
    break;
  
  case 0xa: // opcode == 0xa (slti)
  	p->R[inst.itype.rt] = (signed)p->R[inst.itype.rs] < signext(inst.itype.imm);
    p->pc += 4;
    break;
		
	case 0xb: // opcode == 0xb (sltiu)
		p->R[inst.rtype.rt] = (signed)p->R[inst.itype.rs] < signext(inst.itype.imm);
    p->pc += 4;
    break;
  
  case 0xc: // opcode == 0xc (andi)
  	p->R[inst.rtype.rt] = p->R[inst.itype.rs] & zeroext(inst.itype.imm);
  	p->pc += 4;
  	break;
  
  case 0xe: // opcode == 0xe (xori)
  	p->R[inst.rtype.rt] = p->R[inst.itype.rs] ^ zeroext(inst.itype.imm);
  	p->pc += 4;
  	break;
  
  case 0xf: // opcode == 0xf (lui)
  	p->R[inst.rtype.rt] = inst.itype.imm << 16;
  	p->pc += 4;
  	break;
  
  case 0x20: // opcode == 0x20 (lb)
  	p->R[inst.rtype.rt] = signext(load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_BYTE));
  	p->pc += 4;
  	break;
  
  case 0x23: // opcode == 0x23 (lw)
  	p->R[inst.rtype.rt] = load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD);
  	p->pc += 4;
  	break;
  
  case 0x24: // opcode == 0x24 (lbu)
  	p->R[inst.itype.rt] = zeroext(load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD));
  	p->pc += 4;
  	break;
  
  case 0x28: // opcode == 0x28 (sb)
  	store_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_BYTE, p->R[inst.itype.rt]);
  	p->pc += 4;
  	break;
  
  case 0x2b: // opcode == 0x20 (sw)
  	store_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD, p->R[inst.itype.rt]);
  	p->pc += 4;
  	break;
	
  case 0xd: // opcode == 0xd (ORI)
    p->R[inst.itype.rt] = (p->R[inst.itype.rs] | inst.itype.imm);
    p->pc += 4;
    break;

  case 0x2: // opcode == 0x2 (J)
    p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
    break;

  default: // undefined opcode
    fprintf(stderr, "%s: pc=%08x, illegal instruction: %08x\n", __FUNCTION__, p->pc, inst.bits);
    exit(-1);
    break;
  }

  // enforce $0 being hard-wired to 0
  p->R[0] = 0;

  if(print_regs) {
    print_registers(p);
	}
}