summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c115
1 files changed, 93 insertions, 22 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 9eb1179..9a4aedd 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -9728,8 +9728,16 @@ static void gsp_phys_rmcall_pdb_build(void)
u64 guest_pte;
int gpa_ret;
- gpa_ret = gsp_phys_gpa_to_hpa(boot_stage.rmcall_guest_gpa,
- &guest_hpa);
+ /*
+ * The pinned GPA is a single-guest test aid (the pin write is
+ * refused while more than one mdev is open; see
+ * gsp_phys_guest_gpa_write): resolve through the first open
+ * mdev exactly as before the per-mdev records, via the NULL
+ * selector (a per-mdev pin is not modelled).
+ */
+ gpa_ret = gsp_phys_gpa_to_hpa_vgpu(NULL,
+ boot_stage.rmcall_guest_gpa,
+ &guest_hpa);
if (!gpa_ret) {
guest_pte = gsp_phys_rmcall_pte(guest_hpa);
put_unaligned_le64(guest_pte,
@@ -19110,7 +19118,11 @@ static int gsp_phys_rmcall_guest_g2h(void __iomem *bar0)
return -EIO;
}
- ret = gsp_phys_gpa_to_hpa(gpa, &hpa);
+ /*
+ * Single-guest pin (see gsp_phys_guest_gpa_write): NULL selects the
+ * first open mdev, exactly as before the per-mdev records.
+ */
+ ret = gsp_phys_gpa_to_hpa_vgpu(NULL, gpa, &hpa);
if (ret) {
pr_err("vgsp-boot: rm-call: GUEST G2H COPY FAILED: hpa=0x%llx pte=0x%016llx: GPA 0x%llx -> HPA translation failed (%d: no active mdev/VFIO domain, GPA unmapped, or not a RAM PFN)\n",
hpa, pte, gpa, ret);
@@ -19193,7 +19205,11 @@ static int gsp_phys_rmcall_guest_w2g(void __iomem *bar0)
return -EIO;
}
- ret = gsp_phys_gpa_to_hpa(gpa, &hpa);
+ /*
+ * Single-guest pin (see gsp_phys_guest_gpa_write): NULL selects the
+ * first open mdev, exactly as before the per-mdev records.
+ */
+ ret = gsp_phys_gpa_to_hpa_vgpu(NULL, gpa, &hpa);
if (ret) {
pr_err("vgsp-boot: rm-call: GUEST W2G COPY FAILED: hpa=0x%llx pte=0x%016llx: GPA 0x%llx -> HPA translation failed (%d: no active mdev/VFIO domain, GPA unmapped, or not a RAM PFN)\n",
hpa, pte, gpa, ret);
@@ -20404,6 +20420,18 @@ static ssize_t gsp_phys_guest_gpa_write(struct file *file,
gpa);
return -EINVAL;
}
+ /*
+ * Dual-guest guard (goal 1.0): the pin is a single-guest test aid. The
+ * triggers translate it through the first open mdev (see
+ * gsp_phys_gpa_to_hpa / boot_stage.rmcall_guest_gpa), so with more than
+ * one open mdev the pin cannot name its owner and is refused instead of
+ * silently resolving through whichever guest opened first.
+ */
+ if (gsp_phys_open_mdev_count() > 1) {
+ pr_err("vgsp-boot: gsp-phys-guest-gpa: refused: %d mdevs are open; the guest-GPA pin is a single-guest test aid (translates through the first open mdev). Close all but one mdev, or use the per-mdev guest/GPA paths\n",
+ gsp_phys_open_mdev_count());
+ return -EBUSY;
+ }
if (boot_stage.rmcall_guest_gpa_valid &&
boot_stage.rmcall_guest_gpa != gpa) {
pr_err("vgsp-boot: gsp-phys-guest-gpa: refused: this boot already pinned GPA 0x%llx; one GPA per boot (stale GMMU TLB safety). Reuse that GPA, or release/reboot before changing it\n",
@@ -20426,18 +20454,26 @@ static const struct file_operations gsp_phys_guest_gpa_fops = {
};
/*
- * gsp-phys-guest-ram (write-only, mode 0200): configure the shared guest RAM
- * backing file that gsp_phys_gpa_to_hpa() translates through (QEMU
+ * gsp-phys-guest-ram (write-only, mode 0200): configure a guest RAM backing
+ * file that gsp_phys_gpa_to_hpa_vgpu() translates through (QEMU
* memory-backend-file,...,share=yes). One write is
*
* "<path> <gpa_base_hex> <file_offset_hex> <size_hex>"
*
* (path without spaces; all three numbers hex with 0x, e.g.
- * "/dev/shm/vgpu-ram 0x100000000 0x0 0x40000000"). The first write opens the
- * file and fixes the path for this module cycle; later writes may add ranges
- * (up to four) or replace a range with the same gpa_base. The ranges are
- * only consulted by gsp_phys_gpa_to_hpa(), and only while a live mdev
- * session exists. A single "-" clears the configuration and closes the file.
+ * "/dev/shm/vgpu-ram 0x100000000 0x0 0x40000000"). This historical form
+ * configures the legacy record and serves the FIRST/ONLY open mdev exactly
+ * as before the per-mdev records existed. With two live guests each writes
+ * its own record by naming its mdev UUID first:
+ *
+ * "<mdev-uuid> <path> <gpa_base_hex> <file_offset_hex> <size_hex>"
+ *
+ * Paths and UUIDs contain no spaces, so the token count (4 vs 5) decides.
+ * The first write for a record opens the file and fixes the path for that
+ * record; later writes may add ranges (up to four) or replace a range with
+ * the same gpa_base. The ranges are only consulted by the translators, and
+ * only while a live mdev session exists. A single "-" clears ALL records
+ * (legacy and per-mdev) and closes the files.
*/
static char *gsp_phys_guest_ram_token(char **cursor)
{
@@ -20452,9 +20488,11 @@ static ssize_t gsp_phys_guest_ram_write(struct file *file,
const char __user *ubuf, size_t len,
loff_t *ppos)
{
- char buf[384];
- char *p, *tok, *path;
+ char buf[448];
+ char *t[5];
+ char *path;
u64 gpa_base, file_offset, size;
+ int nt = 0, off;
int ret;
if (len == 0 || len >= sizeof(buf))
@@ -20463,30 +20501,63 @@ static ssize_t gsp_phys_guest_ram_write(struct file *file,
return -EFAULT;
buf[len] = '\0';
- p = strim(buf);
- if (!strcmp(p, "-")) {
+ if (!strcmp(strim(buf), "-")) {
gsp_phys_guest_ram_clear();
pr_info("vgsp-boot: gsp-phys-guest-ram: cleared the guest RAM file configuration\n");
return len;
}
- path = gsp_phys_guest_ram_token(&p);
- tok = gsp_phys_guest_ram_token(&p);
- if (!path || !tok || kstrtoull(tok, 0, &gpa_base)) {
+ {
+ char *p = buf;
+
+ while (nt < 5 && (t[nt] = gsp_phys_guest_ram_token(&p)))
+ nt++;
+ }
+ if (nt != 4 && nt != 5) {
+ pr_info("vgsp-boot: gsp-phys-guest-ram: write ignored: expected \"<path> <gpa_base_hex> <file_offset_hex> <size_hex>\", \"<mdev-uuid> <path> <gpa_base_hex> <file_offset_hex> <size_hex>\" or \"-\"\n");
+ return -EINVAL;
+ }
+ off = nt - 4; /* 0 = legacy form, 1 = per-mdev form */
+ path = t[off];
+ if (!path || kstrtoull(t[off + 1], 0, &gpa_base)) {
pr_info("vgsp-boot: gsp-phys-guest-ram: write ignored: expected \"<path> <gpa_base_hex> <file_offset_hex> <size_hex>\" or \"-\"\n");
return -EINVAL;
}
- tok = gsp_phys_guest_ram_token(&p);
- if (!tok || kstrtoull(tok, 0, &file_offset)) {
+ if (kstrtoull(t[off + 2], 0, &file_offset)) {
pr_info("vgsp-boot: gsp-phys-guest-ram: write ignored: expected a hex file offset after the GPA\n");
return -EINVAL;
}
- tok = gsp_phys_guest_ram_token(&p);
- if (!tok || kstrtoull(tok, 0, &size)) {
+ if (kstrtoull(t[off + 3], 0, &size)) {
pr_info("vgsp-boot: gsp-phys-guest-ram: write ignored: expected a hex size after the file offset\n");
return -EINVAL;
}
+ if (off) {
+ /*
+ * Per-mdev form: the selector must name an OPEN mdev (the mdev
+ * UUID is its device name). Refusing an unknown selector keeps
+ * a typo from silently configuring the legacy record.
+ */
+ struct nv_vgpu_device *mdev =
+ gsp_phys_open_mdev_by_name(t[0]);
+
+ if (!mdev) {
+ pr_err("vgsp-boot: gsp-phys-guest-ram: no open mdev named %s; write refused\n",
+ t[0]);
+ return -ENODEV;
+ }
+ ret = gsp_phys_guest_ram_configure_vgpu(mdev, path, gpa_base,
+ file_offset, size);
+ if (ret) {
+ pr_err("vgsp-boot: gsp-phys-guest-ram: configure failed: mdev=%s path=%s gpa=0x%llx off=0x%llx size=0x%llx ret=%d\n",
+ t[0], path, gpa_base, file_offset, size, ret);
+ return ret;
+ }
+ pr_info("vgsp-boot: gsp-phys-guest-ram: configured mdev=%s path=%s gpa=0x%llx off=0x%llx size=0x%llx\n",
+ t[0], path, gpa_base, file_offset, size);
+ return len;
+ }
+
ret = gsp_phys_guest_ram_configure(path, gpa_base, file_offset, size);
if (ret) {
pr_err("vgsp-boot: gsp-phys-guest-ram: configure failed: path=%s gpa=0x%llx off=0x%llx size=0x%llx ret=%d\n",