Exemplo n.º 1
0
void lguest_arch_handle_trap(struct lg_cpu *cpu)
{
	switch (cpu->regs->trapnum) {
	case 13: 
		if (cpu->regs->errcode == 0) {
			if (emulate_insn(cpu))
				return;
		}
		break;
	case 14: 
		if (demand_page(cpu, cpu->arch.last_pagefault,
				cpu->regs->errcode))
			return;

		if (cpu->lg->lguest_data &&
		    put_user(cpu->arch.last_pagefault,
			     &cpu->lg->lguest_data->cr2))
			kill_guest(cpu, "Writing cr2");
		break;
	case 7: 
		if (!cpu->ts)
			return;
		break;
	case 32 ... 255:
		cond_resched();
		return;
	case LGUEST_TRAP_ENTRY:
		cpu->hcall = (struct hcall_args *)cpu->regs;
		return;
	}

	
	if (!deliver_trap(cpu, cpu->regs->trapnum))
		kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)",
			   cpu->regs->trapnum, cpu->regs->eip,
			   cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault
			   : cpu->regs->errcode);
}
Exemplo n.º 2
0
/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
void lguest_arch_handle_trap(struct lg_cpu *cpu)
{
	unsigned long iomem_addr;

	switch (cpu->regs->trapnum) {
	case 13: /* We've intercepted a General Protection Fault. */
		/* Hand to Launcher to emulate those pesky IN and OUT insns */
		if (cpu->regs->errcode == 0) {
			setup_emulate_insn(cpu);
			return;
		}
		break;
	case 14: /* We've intercepted a Page Fault. */
		/*
		 * The Guest accessed a virtual address that wasn't mapped.
		 * This happens a lot: we don't actually set up most of the page
		 * tables for the Guest at all when we start: as it runs it asks
		 * for more and more, and we set them up as required. In this
		 * case, we don't even tell the Guest that the fault happened.
		 *
		 * The errcode tells whether this was a read or a write, and
		 * whether kernel or userspace code.
		 */
		if (demand_page(cpu, cpu->arch.last_pagefault,
				cpu->regs->errcode, &iomem_addr))
			return;

		/* Was this an access to memory mapped IO? */
		if (iomem_addr) {
			/* Tell Launcher, let it handle it. */
			setup_iomem_insn(cpu, iomem_addr);
			return;
		}

		/*
		 * OK, it's really not there (or not OK): the Guest needs to
		 * know.  We write out the cr2 value so it knows where the
		 * fault occurred.
		 *
		 * Note that if the Guest were really messed up, this could
		 * happen before it's done the LHCALL_LGUEST_INIT hypercall, so
		 * lg->lguest_data could be NULL
		 */
		if (cpu->lg->lguest_data &&
		    put_user(cpu->arch.last_pagefault,
			     &cpu->lg->lguest_data->cr2))
			kill_guest(cpu, "Writing cr2");
		break;
	case 7: /* We've intercepted a Device Not Available fault. */
		/* No special handling is needed here. */
		break;
	case 32 ... 255:
		/* This might be a syscall. */
		if (could_be_syscall(cpu->regs->trapnum))
			break;

		/*
		 * Other values mean a real interrupt occurred, in which case
		 * the Host handler has already been run. We just do a
		 * friendly check if another process should now be run, then
		 * return to run the Guest again.
		 */
		cond_resched();
		return;
	case LGUEST_TRAP_ENTRY:
		/*
		 * Our 'struct hcall_args' maps directly over our regs: we set
		 * up the pointer now to indicate a hypercall is pending.
		 */
		cpu->hcall = (struct hcall_args *)cpu->regs;
		return;
	}

	/* We didn't handle the trap, so it needs to go to the Guest. */
	if (!deliver_trap(cpu, cpu->regs->trapnum))
		/*
		 * If the Guest doesn't have a handler (either it hasn't
		 * registered any yet, or it's one of the faults we don't let
		 * it handle), it dies with this cryptic error message.
		 */
		kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)",
			   cpu->regs->trapnum, cpu->regs->eip,
			   cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault
			   : cpu->regs->errcode);
}
Exemplo n.º 3
0
/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
void lguest_arch_handle_trap(struct lg_cpu *cpu)
{
	switch (cpu->regs->trapnum) {
	case 13: /* We've intercepted a General Protection Fault. */
		/* Check if this was one of those annoying IN or OUT
		 * instructions which we need to emulate.  If so, we just go
		 * back into the Guest after we've done it. */
		if (cpu->regs->errcode == 0) {
			if (emulate_insn(cpu))
				return;
		}
		break;
	case 14: /* We've intercepted a Page Fault. */
		/* The Guest accessed a virtual address that wasn't mapped.
		 * This happens a lot: we don't actually set up most of the page
		 * tables for the Guest at all when we start: as it runs it asks
		 * for more and more, and we set them up as required. In this
		 * case, we don't even tell the Guest that the fault happened.
		 *
		 * The errcode tells whether this was a read or a write, and
		 * whether kernel or userspace code. */
		if (demand_page(cpu, cpu->arch.last_pagefault,
				cpu->regs->errcode))
			return;

		/* OK, it's really not there (or not OK): the Guest needs to
		 * know.  We write out the cr2 value so it knows where the
		 * fault occurred.
		 *
		 * Note that if the Guest were really messed up, this could
		 * happen before it's done the LHCALL_LGUEST_INIT hypercall, so
		 * lg->lguest_data could be NULL */
		if (cpu->lg->lguest_data &&
		    put_user(cpu->arch.last_pagefault,
			     &cpu->lg->lguest_data->cr2))
			kill_guest(cpu, "Writing cr2");
		break;
	case 7: /* We've intercepted a Device Not Available fault. */
		/* If the Guest doesn't want to know, we already restored the
		 * Floating Point Unit, so we just continue without telling
		 * it. */
		if (!cpu->ts)
			return;
		break;
	case 32 ... 255:
		/* These values mean a real interrupt occurred, in which case
		 * the Host handler has already been run.  We just do a
		 * friendly check if another process should now be run, then
		 * return to run the Guest again */
		cond_resched();
		return;
	case LGUEST_TRAP_ENTRY:
		/* Our 'struct hcall_args' maps directly over our regs: we set
		 * up the pointer now to indicate a hypercall is pending. */
		cpu->hcall = (struct hcall_args *)cpu->regs;
		return;
	}

	/* We didn't handle the trap, so it needs to go to the Guest. */
	if (!deliver_trap(cpu, cpu->regs->trapnum))
		/* If the Guest doesn't have a handler (either it hasn't
		 * registered any yet, or it's one of the faults we don't let
		 * it handle), it dies with this cryptic error message. */
		kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)",
			   cpu->regs->trapnum, cpu->regs->eip,
			   cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault
			   : cpu->regs->errcode);
}