Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69a09dc1 authored by Rusty Russell's avatar Rusty Russell
Browse files

lguest: write more information to userspace about pending traps.



This is preparation for userspace handling MMIO and ioport accesses.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 18c13737
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -229,16 +229,17 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
		 * It's possible the Guest did a NOTIFY hypercall to the
		 * Launcher.
		 */
		if (cpu->pending_notify) {
		if (cpu->pending.trap) {
			/*
			 * Does it just needs to write to a registered
			 * eventfd (ie. the appropriate virtqueue thread)?
			 */
			if (!send_notify_to_eventfd(cpu)) {
				/* OK, we tell the main Launcher. */
				if (put_user(cpu->pending_notify, user))
				if (copy_to_user(user, &cpu->pending,
						 sizeof(cpu->pending)))
					return -EFAULT;
				return sizeof(cpu->pending_notify);
				return sizeof(cpu->pending);
			}
		}

+4 −3
Original line number Diff line number Diff line
@@ -118,7 +118,8 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
		cpu->halted = 1;
		break;
	case LHCALL_NOTIFY:
		cpu->pending_notify = args->arg1;
		cpu->pending.trap = LGUEST_TRAP_ENTRY;
		cpu->pending.addr = args->arg1;
		break;
	default:
		/* It should be an architecture-specific hypercall. */
@@ -189,7 +190,7 @@ static void do_async_hcalls(struct lg_cpu *cpu)
		 * Stop doing hypercalls if they want to notify the Launcher:
		 * it needs to service this first.
		 */
		if (cpu->pending_notify)
		if (cpu->pending.trap)
			break;
	}
}
@@ -280,7 +281,7 @@ void do_hypercalls(struct lg_cpu *cpu)
	 * NOTIFY to the Launcher, we want to return now.  Otherwise we do
	 * the hypercall.
	 */
	if (!cpu->pending_notify) {
	if (!cpu->pending.trap) {
		do_hcall(cpu, cpu->hcall);
		/*
		 * Tricky point: we reset the hcall pointer to mark the
+2 −1
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ struct lg_cpu {
	/* Bitmap of what has changed: see CHANGED_* above. */
	int changed;

	unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */
	/* Pending operation. */
	struct lguest_pending pending;

	unsigned long *reg_read; /* register from LHREQ_GETREG */

+9 −5
Original line number Diff line number Diff line
@@ -29,6 +29,10 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu)
	unsigned int i;
	struct lg_eventfd_map *map;

	/* We only connect LHCALL_NOTIFY to event fds, not other traps. */
	if (cpu->pending.trap != LGUEST_TRAP_ENTRY)
		return false;

	/*
	 * This "rcu_read_lock()" helps track when someone is still looking at
	 * the (RCU-using) eventfds array.  It's not actually a lock at all;
@@ -52,9 +56,9 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu)
	 * we'll continue to use the old array and just won't see the new one.
	 */
	for (i = 0; i < map->num; i++) {
		if (map->map[i].addr == cpu->pending_notify) {
		if (map->map[i].addr == cpu->pending.addr) {
			eventfd_signal(map->map[i].event, 1);
			cpu->pending_notify = 0;
			cpu->pending.trap = 0;
			break;
		}
	}
@@ -62,7 +66,7 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu)
	rcu_read_unlock();

	/* If we cleared the notification, it's because we found a match. */
	return cpu->pending_notify == 0;
	return cpu->pending.trap == 0;
}

/*L:055
@@ -282,8 +286,8 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
	 * If we returned from read() last time because the Guest sent I/O,
	 * clear the flag.
	 */
	if (cpu->pending_notify)
		cpu->pending_notify = 0;
	if (cpu->pending.trap)
		cpu->pending.trap = 0;

	/* Run the Guest until something interesting happens. */
	return run_guest(cpu, (unsigned long __user *)user);
+13 −0
Original line number Diff line number Diff line
@@ -67,6 +67,19 @@ enum lguest_req
	LHREQ_SETREG, /* + offset within struct pt_regs, value. */
};

/*
 * This is what read() of the lguest fd populates.  trap ==
 * LGUEST_TRAP_ENTRY for an LHCALL_NOTIFY (addr is the
 * argument), 14 for a page fault in the MMIO region (addr is
 * the trap address, insn is the instruction), or 13 for a GPF
 * (insn is the instruction).
 */
struct lguest_pending {
	__u8 trap;
	__u8 insn[7];
	__u32 addr;
};

/*
 * The alignment to use between consumer and producer parts of vring.
 * x86 pagesize for historical reasons.
Loading