Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- /home/rossierd/soo/git/micofe/build/tmp/work/linux-6.12-r0/linux-6.12/soo/drivers/vdevback.c 1970-01-01 01:00:00.000000000 +0100
+++ ./soo/drivers/vdevback.c 2025-08-29 08:46:41.395627342 +0200
@@ -0,0 +1,309 @@
@@ -0,0 +1,350 @@
+
+/*
+ * Copyright (C) 2020 Daniel Rossier <daniel.rossier@heig-vd.ch>
Expand Down Expand Up @@ -81,6 +81,46 @@
+}
+
+/*
+ * Non-blocking counterpart of vdevback_processing_begin(): it never waits for
+ * the frontend to (re)connect and reports false instead.
+ *
+ * Any caller running in a context which must not sleep -- the console input
+ * path, driven by the serial interrupt -- has to use this one. A capsule being
+ * suspended, snapshotted or shut down leaves its frontend out of the connected
+ * state, and waiting for it there would hang the interrupt.
+ */
+bool vdevback_processing_try_begin(struct vbus_device *vdev)
+{
+ void *priv = dev_get_drvdata(&vdev->dev);
+ vdevback_t *vdevback = (vdevback_t *) priv;
+
+ if (vdev->fe_state != VbusStateConnected)
+ return false;
+
+ if (atomic_read(&vdevback->processing_count) == 0) {
+ atomic_inc(&vdevback->processing_count);
+
+ if (!mutex_trylock(&vdevback->processing_lock)) {
+ atomic_dec(&vdevback->processing_count);
+
+ return false;
+ }
+
+ /* Make sure we are still connected after taking the lock. */
+
+ if (vdev->fe_state != VbusStateConnected) {
+ mutex_unlock(&vdevback->processing_lock);
+ atomic_dec(&vdevback->processing_count);
+
+ return false;
+ }
+ } else
+ atomic_inc(&vdevback->processing_count);
+
+ return true;
+}
+
+/*
+ * Finish a processing section against suspend/close prevention
+ */
+void vdevback_processing_end(struct vbus_device *vdev) {
Expand All @@ -98,12 +138,13 @@
+ * Check if the frontend state and tell whether it is connected.
+ */
+bool vdevfront_is_connected(struct vbus_device *vdev) {
+ void *priv = dev_get_drvdata(&vdev->dev);
+ vdevback_t *vdevback = (vdevback_t *) priv;
+ vdevback_t *vdevback;
+
+ if (!vdev)
+ return false;
+
+ vdevback = (vdevback_t *) dev_get_drvdata(&vdev->dev);
+
+ return vdevback->vdevfront_connected;
+}
+
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- /home/rossierd/soo/git/micofe/build/tmp/work/linux-6.12-r0/linux-6.12/soo/drivers/vuartback/vuart.c 1970-01-01 01:00:00.000000000 +0100
+++ ./soo/drivers/vuartback/vuart.c 2025-08-29 08:46:41.395804736 +0200
@@ -0,0 +1,327 @@
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2016-2018 Daniel Rossier <daniel.rossier@heig-vd.ch>
+ * Copyright (C) 2016 Baptiste Delporte <bonel@bonel.net>
Expand Down Expand Up @@ -191,10 +191,19 @@
+
+ console = get_console(domid);
+
+ if (!vdevfront_is_connected(console))
+ /* The capsule may have gone while the console focus was still pointing at
+ * its slot -- a paused capsule is suspended, then shut down.
+ */
+
+ if (!console || !vdevfront_is_connected(console))
+ return;
+
+ vdevback_processing_begin(console);
+ /* This runs from the serial interrupt: the blocking flavour would wait for
+ * a frontend which is suspended or already gone, and hang the console.
+ */
+
+ if (!vdevback_processing_try_begin(console))
+ return;
+
+ vuart_priv = dev_get_drvdata(&console->dev);
+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
+int inject_capsule(void *buffer, size_t size, int slotID, unsigned capsuleId);
+void start_capsule(int slotID);
+
+void read_snapshot(uint32_t slotID, void *buffer, uint32_t *size);
+void read_snapshot(uint32_t slotID, void *buffer, uint32_t *size, bool resume);
+int write_snapshot(void *buffer);
+
+int get_S3C_state(unsigned int S3C_slotID);
Expand All @@ -40,5 +40,4 @@
+void capsule_init(void);
+void capsule_exit(void);
+
+#endif /* CAPSULE_H */
\ No newline at end of file
+#endif /* CAPSULE_H */
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- /home/rossierd/soo/git/micofe/build/tmp/work/linux-6.12-r0/linux-6.12/soo/include/soo/uapi/soo.h 1970-01-01 01:00:00.000000000 +0100
+++ ./soo/include/soo/uapi/soo.h 2025-08-29 08:46:41.395924678 +0200
@@ -0,0 +1,482 @@
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2014-2025 Daniel Rossier <daniel.rossier@heig-vd.ch>
+ *
Expand Down Expand Up @@ -74,6 +74,13 @@
+
+void do_gnttab(gnttab_op_t *args);
+
+#define MAX_FBDEV_PFN 8
+typedef struct fbdev_pfns {
+ size_t pfn_count;
+ addr_t pfn[MAX_FBDEV_PFN];
+ size_t page_count[MAX_FBDEV_PFN];
+} fbdev_pfns_t;
+
+#define AVZ_SCHEDULER_FLIP 0
+
+/*
Expand Down Expand Up @@ -167,6 +174,11 @@
+#define AGENCY_IOCTL_GET_S3C_ID _IOWR('S', 6, agency_ioctl_args_t)
+#define AGENCY_IOCTL_GET_S3C_ID_ARRAY _IOR('S', 7, agency_ioctl_args_t)
+
+/* Same as AGENCY_IOCTL_READ_SNAPSHOT, but the capsule is left suspended instead
+ * of being resumed: for a caller which shuts it down right after.
+ */
+#define AGENCY_IOCTL_READ_SNAPSHOT_HOLD _IOWR('S', 8, agency_ioctl_args_t)
+
+#define SOO_NAME_SIZE 16
+
+/*
Expand Down Expand Up @@ -302,6 +314,9 @@
+#define AVZ_SET_S3C_STATE 11
+#define AVZ_GET_DOM_DESC 12
+#define AVZ_GRANT_TABLE_OP 13
+#define AVZ_FBDEV_SET_PFNS 14
+#define AVZ_FBDEV_CHANGE_FOCUS 15
+#define AVZ_FBDEV_GET_S3C_ADDR 16
+
+/* Staged hypercalls.
+ *
Expand All @@ -320,6 +335,22 @@
+#define AVZ_STAGE_CHUNK 1
+#define AVZ_STAGE_FINALIZE 2
+
+/* Snapshot only: complete without resuming the capsule, which is left
+ * suspended. Taking a snapshot normally leaves the capsule living -- that is
+ * the point of snapshotting a running capsule -- but a caller which is about to
+ * shut it down would otherwise let it run, and diverge from the snapshot it has
+ * just taken, for nothing.
+ */
+#define AVZ_STAGE_FINALIZE_HOLD 3
+
+/* Maximum amount of capsule memory moved in a single AVZ_STAGE_CHUNK call.
+ *
+ * A snapshot is streamed through a bounce buffer of that size instead of being
+ * mapped as a whole: the agency has no reason to find several hundreds of
+ * contiguous MB in its CMA zone just to save or restore a capsule.
+ */
+#define AVZ_STAGE_CHUNK_SIZE (4 * 1024 * 1024)
+
+/* AVZ_INJECT_CAPSULE */
+typedef struct {
+ void *itb_paddr;
Expand Down Expand Up @@ -367,10 +398,17 @@
+
+/* AVZ_READ_SNAPSHOT */
+/* AVZ_WRITE_SNAPSHOT */
+/*
+ * `snapshot_paddr` points to the agency bounce buffer and is read again at each
+ * stage. At the INIT and FINALIZE stages the buffer holds the snapshot header
+ * (payload size + domain context), which AVZ reads to restore the capsule; at
+ * the CHUNK stage it holds one chunk of capsule memory, at its very beginning,
+ * and `size` tells AVZ how much of it may be used.
+ */
+typedef struct {
+ void *snapshot_paddr;
+ int32_t slotID;
+ int size;
+ int size; /* INIT: IN/OUT snapshot size / CHUNK: IN bounce buffer size */
+ uint32_t stage; /* IN: AVZ_STAGE_* */
+ uint32_t offset; /* CHUNK: IN/OUT byte cursor / INIT: OUT bytes to copy */
+} avz_snapshot_t;
Expand All @@ -385,6 +423,21 @@
+ gnttab_op_t gnttab_op;
+} avz_gnttab_t;
+
+/* AVZ_FBDEV_SET_PFNS */
+typedef struct {
+ fbdev_pfns_t fbdev;
+} avz_fbdev_pfns_t;
+
+/* AVZ_FBDEV_CHANGE_FOCUS */
+typedef struct {
+ int new_slotID;
+} avz_fbdev_focus_t;
+
+/* AVZ_FBDEV_GET_S3C_ADDR */
+typedef struct {
+ addr_t paddr;
+} avz_fbdev_addr_t;
+
+/*
+ * AVZ hypercall argument
+ */
Expand All @@ -404,6 +457,9 @@
+ avz_console_io_t avz_console_io_args;
+ avz_domctl_t avz_domctl_args;
+ avz_gnttab_t avz_gnttab_args;
+ avz_fbdev_pfns_t avz_fbdev_pfns_args;
+ avz_fbdev_focus_t avz_fbdev_focus_args;
+ avz_fbdev_addr_t avz_fbdev_addr_args;
+ } u;
+} avz_hyp_t;
+
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- /home/rossierd/soo/git/micofe/build/tmp/work/linux-6.12-r0/linux-6.12/soo/include/soo/vbus.h 1970-01-01 01:00:00.000000000 +0100
+++ ./soo/include/soo/vbus.h 2025-08-29 08:46:41.396103436 +0200
@@ -0,0 +1,336 @@
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2014-2019 Daniel Rossier <daniel.rossier@heig-vd.ch>
+ * Copyright (C) 2016, 2018 Baptiste Delporte <bonel@bonel.net>
Expand Down Expand Up @@ -265,10 +265,13 @@
+
+extern void vbus_read_otherend_details(struct vbus_device *vdev, char *id_node, char *path_node);
+extern int vbus_suspend_dev(struct bus_type *bus, unsigned int domID);
+int vbus_remove_dev(struct bus_type *bus, unsigned int domID);
+extern int vbus_resume_dev(struct bus_type *bus, unsigned int domID);
+
+/* Prepare for domain suspend: then resume or cancel the suspend. */
+int vbus_suspend_devices(unsigned int domID);
+int vbus_remove_devices(unsigned int domID);
+void vbstore_capsule_remove(unsigned int domID);
+int vbus_resume_devices(unsigned int domID);
+
+int vdev_probe(char *node);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- /home/rossierd/soo/git/micofe/build/tmp/work/linux-6.12-r0/linux-6.12/soo/include/soo/vdevback.h 1970-01-01 01:00:00.000000000 +0100
+++ ./soo/include/soo/vdevback.h 2025-08-29 08:46:41.396178895 +0200
@@ -0,0 +1,90 @@
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 Daniel Rossier <daniel.rossier@heig-vd.ch>
+ *
Expand Down Expand Up @@ -72,6 +72,7 @@
+
+void vdevback_init(char *name, vdrvback_t *vdrvback);
+bool vdevback_processing_begin(struct vbus_device *vdev);
+bool vdevback_processing_try_begin(struct vbus_device *vdev);
+void vdevback_processing_end(struct vbus_device *vdev);
+
+bool vdevfront_is_connected(struct vbus_device *vdev);
Expand Down
Loading
Loading