summaryrefslogtreecommitdiffstats
path: root/drivers/lguest/lguest_user.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2015-02-11 15:15:09 +1030
committerRusty Russell <rusty@rustcorp.com.au>2015-02-11 16:47:29 +1030
commit18c137371b2ea86d263b75665a4904a0b8872990 (patch)
tree59f8e6bf9b43195b8d9d77fb3235468baeb8d946 /drivers/lguest/lguest_user.c
parenta454bb36cabdac163fcd80ddb37662893ea603f1 (diff)
downloadop-kernel-dev-18c137371b2ea86d263b75665a4904a0b8872990.zip
op-kernel-dev-18c137371b2ea86d263b75665a4904a0b8872990.tar.gz
lguest: add operations to get/set a register from the Launcher.
We use the ptrace API struct, and we currently don't let them set anything but the normal registers (we'd have to filter the others). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest/lguest_user.c')
-rw-r--r--drivers/lguest/lguest_user.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 4263f4c..7f14c15 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -173,6 +173,51 @@ static int attach_eventfd(struct lguest *lg, const unsigned long __user *input)
return err;
}
+/* The Launcher can get the registers, and also set some of them. */
+static int getreg_setup(struct lg_cpu *cpu, const unsigned long __user *input)
+{
+ unsigned long which;
+
+ /* We re-use the ptrace structure to specify which register to read. */
+ if (get_user(which, input) != 0)
+ return -EFAULT;
+
+ /*
+ * We set up the cpu register pointer, and their next read will
+ * actually get the value (instead of running the guest).
+ *
+ * The last argument 'true' says we can access any register.
+ */
+ cpu->reg_read = lguest_arch_regptr(cpu, which, true);
+ if (!cpu->reg_read)
+ return -ENOENT;
+
+ /* And because this is a write() call, we return the length used. */
+ return sizeof(unsigned long) * 2;
+}
+
+static int setreg(struct lg_cpu *cpu, const unsigned long __user *input)
+{
+ unsigned long which, value, *reg;
+
+ /* We re-use the ptrace structure to specify which register to read. */
+ if (get_user(which, input) != 0)
+ return -EFAULT;
+ input++;
+ if (get_user(value, input) != 0)
+ return -EFAULT;
+
+ /* The last argument 'false' means we can't access all registers. */
+ reg = lguest_arch_regptr(cpu, which, false);
+ if (!reg)
+ return -ENOENT;
+
+ *reg = value;
+
+ /* And because this is a write() call, we return the length used. */
+ return sizeof(unsigned long) * 3;
+}
+
/*L:050
* Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
* number to /dev/lguest.
@@ -434,6 +479,10 @@ static ssize_t write(struct file *file, const char __user *in,
return user_send_irq(cpu, input);
case LHREQ_EVENTFD:
return attach_eventfd(lg, input);
+ case LHREQ_GETREG:
+ return getreg_setup(cpu, input);
+ case LHREQ_SETREG:
+ return setreg(cpu, input);
default:
return -EINVAL;
}
OpenPOWER on IntegriCloud