diff --git a/drivers/vhost/dsp.c b/drivers/vhost/dsp.c
index 205ae8c..33e849a 100644
--- a/drivers/vhost/dsp.c
+++ b/drivers/vhost/dsp.c
@@ -114,6 +114,9 @@ static void vhost_dsp_deactivate(struct vhost_dsp *dsp)
 
 		dsp->active = false;
 
+		/* If a VM reboots dsp_sof_client_release() isn't called */
+		dsp_sof_topology_purge(dsp->snd);
+
 		spin_lock_irqsave(&dsp->posn_lock, flags);
 		list_for_each_entry_safe(buf, next, &dsp->posn_buf_list, list) {
 			list_del(&buf->list);
diff --git a/include/sound/sof/virtio.h b/include/sound/sof/virtio.h
index fc98664..80e174e 100644
--- a/include/sound/sof/virtio.h
+++ b/include/sound/sof/virtio.h
@@ -147,6 +147,9 @@ struct dsp_sof_client {
 	struct list_head pipe_conn;
 	/* List of vhost instances on a DSP */
 	struct list_head list;
+	/* List of widgets to free for tear-down */
+	struct list_head comp_list;
+	struct list_head pipe_list;
 
 	/* Component ID range index in the bitmap */
 	unsigned int id;
@@ -177,6 +180,7 @@ int dsp_sof_stream_data(struct dsp_sof_client *client,
 int dsp_sof_ipc_fwd(struct dsp_sof_client *client, int vq_idx,
 		    void *ipc_buf, void *reply_buf,
 		    size_t count, size_t reply_sz);
+void dsp_sof_topology_purge(struct dsp_sof_client *client);
 
 /* The below functions are always referenced, they need dummy counterparts */
 int dsp_sof_update_guest_posn(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sof/vhost-be.c b/sound/soc/sof/vhost-be.c
index e1dede9..c25512b 100644
--- a/sound/soc/sof/vhost-be.c
+++ b/sound/soc/sof/vhost-be.c
@@ -43,6 +43,18 @@ struct dsp_pipeline_connect {
 	struct list_head list;
 };
 
+struct dsp_sof_comp_list {
+	struct list_head list;
+	uint32_t comp_id;
+	enum sof_comp_type comp_type;
+};
+
+struct dsp_sof_pipe_list {
+	struct list_head list;
+	uint32_t comp_id;
+	uint32_t pipe_id;
+};
+
 static const char dsp_pcm_name[] = "VHost PCM";
 
 /*
@@ -446,6 +458,75 @@ static int dsp_sof_ipc_comp(struct dsp_sof_client *client,
 		cdata->comp_id >= client->comp_id_end ? -EINVAL : 0;
 }
 
+void dsp_sof_topology_purge(struct dsp_sof_client *client)
+{
+	struct snd_sof_dev *sdev = client->sdev;
+	struct sof_ipc_free fcomp = {
+		.hdr = {
+			.size = sizeof(fcomp),
+		},
+	};
+	struct sof_ipc_reply reply;
+	struct dsp_sof_comp_list *citem, *ctmp;
+	struct dsp_sof_pipe_list *pitem, *ptmp;
+	int ret;
+
+	pm_runtime_get_sync(sdev->dev);
+
+	/* First free all pipelines */
+	list_for_each_entry_safe(pitem, ptmp, &client->pipe_list, list) {
+		fcomp.id = pitem->comp_id;
+		fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG |
+			SOF_IPC_TPLG_PIPE_FREE;
+
+		dev_dbg(sdev->dev, "tplg: unload component ID: %d pipe %u\n",
+			fcomp.id, pitem->pipe_id);
+
+		/* send IPC to the DSP */
+		ret = sof_ipc_tx_message(sdev->ipc,
+					 fcomp.hdr.cmd, &fcomp, sizeof(fcomp),
+					 &reply, sizeof(reply));
+		if (ret < 0)
+			dev_err(sdev->dev, "error: %d unloading component %d\n",
+				ret, fcomp.id);
+
+		list_del(&pitem->list);
+		kfree(pitem);
+	}
+
+	/* Then free all individual components */
+	list_for_each_entry_safe(citem, ctmp, &client->comp_list, list) {
+		fcomp.id = citem->comp_id;
+		switch (citem->comp_type) {
+		case SOF_COMP_BUFFER:
+			fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG |
+				SOF_IPC_TPLG_BUFFER_FREE;
+			break;
+		default:
+			fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG |
+				SOF_IPC_TPLG_COMP_FREE;
+		}
+
+		dev_dbg(sdev->dev, "tplg: unload component ID: %d type %u\n",
+			fcomp.id, citem->comp_type);
+
+		/* send IPC to the DSP */
+		ret = sof_ipc_tx_message(sdev->ipc,
+					 fcomp.hdr.cmd, &fcomp, sizeof(fcomp),
+					 &reply, sizeof(reply));
+		if (ret < 0)
+			dev_err(sdev->dev, "error: %d unloading component %d\n",
+				ret, fcomp.id);
+
+		list_del(&citem->list);
+		kfree(citem);
+	}
+
+	pm_runtime_mark_last_busy(sdev->dev);
+	pm_runtime_put_autosuspend(sdev->dev);
+}
+EXPORT_SYMBOL_GPL(dsp_sof_topology_purge);
+
 /* process PM IPC */
 static int dsp_sof_ipc_pm(struct dsp_sof_client *client, struct sof_ipc_cmd_hdr *hdr,
 			  struct sof_vfe_ipc_power_resp *resp)
@@ -526,6 +607,47 @@ int dsp_sof_add_conn(struct snd_sof_dev *sdev,
 	return 0;
 }
 
+static int dsp_sof_tplg_comp_add(struct dsp_sof_client *client,
+				 struct sof_ipc_comp *comp)
+{
+	struct dsp_sof_comp_list *citem = kmalloc(sizeof(*citem), GFP_KERNEL);
+	if (!citem)
+		return -ENOMEM;
+
+	citem->comp_id = comp->id;
+	citem->comp_type = comp->type;
+
+	dev_dbg(client->sdev->dev, "%s(): adding %p ID %d type %x\n",
+		__func__, citem, comp->id, comp->type);
+	list_add_tail(&citem->list, &client->comp_list);
+
+	return 0;
+}
+
+static int dsp_sof_tplg_pipe_add(struct dsp_sof_client *client,
+				 struct sof_ipc_pipe_new *pipe)
+{
+	struct dsp_sof_pipe_list *pitem = kmalloc(sizeof(*pitem), GFP_KERNEL);
+	if (!pitem)
+		return -ENOMEM;
+
+	pitem->comp_id = pipe->comp_id;
+	pitem->pipe_id = pipe->pipeline_id;
+
+	dev_dbg(client->sdev->dev, "%s(): adding %p ID %d pipe %x\n",
+		__func__, pitem, pipe->comp_id, pipe->pipeline_id);
+	list_add_tail(&pitem->list, &client->pipe_list);
+
+	return 0;
+}
+
+static int dsp_sof_ipc_tplg_buf_new(struct dsp_sof_client *client,
+			struct sof_ipc_cmd_hdr *hdr, struct sof_ipc_reply *rhdr)
+{
+	struct sof_ipc_comp *comp = container_of(hdr, struct sof_ipc_comp, hdr);
+	return dsp_sof_tplg_comp_add(client, comp);
+}
+
 /* Handle some special cases of the "new component" IPC */
 static int dsp_sof_ipc_tplg_comp_new(struct dsp_sof_client *client, int vq_idx,
 			struct sof_ipc_cmd_hdr *hdr, struct sof_ipc_reply *rhdr)
@@ -535,6 +657,7 @@ static int dsp_sof_ipc_tplg_comp_new(struct dsp_sof_client *client, int vq_idx,
 	struct snd_sof_pcm *spcm, *last;
 	struct sof_ipc_comp_host *host;
 	struct dsp_pipeline_connect *conn;
+	int ret;
 
 	if (comp->id < client->comp_id_begin ||
 	    comp->id >= client->comp_id_end)
@@ -595,6 +718,10 @@ static int dsp_sof_ipc_tplg_comp_new(struct dsp_sof_client *client, int vq_idx,
 		break;
 	}
 
+	ret = dsp_sof_tplg_comp_add(client, comp);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -606,6 +733,9 @@ static int dsp_sof_ipc_tplg_pipe_new(struct dsp_sof_client *client, int vq_idx,
 						struct sof_ipc_pipe_new, hdr);
 	struct snd_sof_dev *sdev = client->sdev;
 	struct dsp_pipeline_connect *conn;
+	int ret = dsp_sof_tplg_pipe_add(client, pipeline);
+	if (ret < 0)
+		return ret;
 
 	list_for_each_entry(conn, &sdev->connector_list, list)
 		if (pipeline->pipeline_id == conn->guest_pipeline_id) {
@@ -723,6 +853,8 @@ static int dsp_sof_ipc_tplg(struct dsp_sof_client *client, int vq_idx,
 	case SOF_IPC_TPLG_COMP_NEW:
 		return dsp_sof_ipc_tplg_comp_new(client, vq_idx, hdr,
 						 reply_buf);
+	case SOF_IPC_TPLG_BUFFER_NEW:
+		return dsp_sof_ipc_tplg_buf_new(client, hdr, reply_buf);
 	case SOF_IPC_TPLG_PIPE_NEW:
 		return dsp_sof_ipc_tplg_pipe_new(client, vq_idx, hdr);
 	case SOF_IPC_TPLG_COMP_CONNECT:
@@ -987,6 +1119,23 @@ int dsp_sof_set_tplg(struct dsp_sof_client *client,
 void dsp_sof_suspend(struct snd_sof_dev *sdev)
 {
 	struct snd_sof_pcm *spcm, *next;
+	struct dsp_sof_client *client;
+
+	/* Upon resume we'll rebuild lists */
+	list_for_each_entry(client, &sdev->vbe_list, list) {
+		struct dsp_sof_comp_list *citem, *ctmp;
+		struct dsp_sof_pipe_list *pitem, *ptmp;
+
+		list_for_each_entry_safe(pitem, ptmp, &client->pipe_list, list) {
+			list_del(&pitem->list);
+			kfree(pitem);
+		}
+
+		list_for_each_entry_safe(citem, ctmp, &client->comp_list, list) {
+			list_del(&citem->list);
+			kfree(citem);
+		}
+	}
 
 	list_for_each_entry_safe(spcm, next, &sdev->pcm_list, list)
 		if (!strcmp(dsp_pcm_name, spcm->pcm.pcm_name)) {
@@ -1000,6 +1149,9 @@ void dsp_sof_suspend(struct snd_sof_dev *sdev)
 /* A VM instance has closed the miscdevice */
 void dsp_sof_client_release(struct dsp_sof_client *client)
 {
+	/* If a VM crashes we don't get ioctl(VHOST_SET_RUNNING, 0) from QEMU */
+	dsp_sof_topology_purge(client);
+
 	bitmap_release_region(client->sdev->vfe_mask, client->id, 0);
 
 	list_del(&client->list);
@@ -1024,6 +1176,9 @@ struct dsp_sof_client *dsp_sof_client_add(struct snd_sof_dev *sdev,
 		return NULL;
 	}
 
+	INIT_LIST_HEAD(&client->pipe_list);
+	INIT_LIST_HEAD(&client->comp_list);
+
 	client->sdev = sdev;
 	client->id = id;
 	client->vhost = dsp;
