* Re: [RFC PATCH 0/9] vhost-nvme: new qemu nvme backend using nvme target
From: Christoph Hellwig @ 2015-11-20 5:16 UTC (permalink / raw)
To: Ming Lin; +Cc: Christoph Hellwig, qemu-devel, linux-nvme, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
Thanks Ming,
from a first quick view this looks great. I'll look over it in a bit
more detail once I get a bit more time.
^ permalink raw reply
* Re: [RFC PATCH 4/9] nvmet: add a controller "start" hook
From: Christoph Hellwig @ 2015-11-20 5:13 UTC (permalink / raw)
To: Ming Lin
Cc: Ming Lin, qemu-devel, virtualization, linux-nvme,
Christoph Hellwig
In-Reply-To: <1447978868-17138-5-git-send-email-mlin@kernel.org>
On Thu, Nov 19, 2015 at 04:21:03PM -0800, Ming Lin wrote:
> #define NVMET_SUBSYS_NAME_LEN 256
> char subsys_name[NVMET_SUBSYS_NAME_LEN];
> +
> + void *opaque;
> + void (*start)(void *);
> };
Why can't vhost use container_of to get at the containing structure
similar to what the loop driver does?
In addition I think we'll eventually need an ops structure here,
but I can take care of that later.
^ permalink raw reply
* Re: [PATCH v3 0/3] virtio DMA API core stuff
From: Benjamin Herrenschmidt @ 2015-11-20 2:56 UTC (permalink / raw)
To: David Woodhouse, Andy Lutomirski, Michael S. Tsirkin
Cc: linux-s390, KVM, Sebastian Ott, linux-kernel@vger.kernel.org,
Linux Virtualization, Christian Borntraeger, Joerg Roedel,
Martin Schwidefsky, Paolo Bonzini, Christoph Hellwig
In-Reply-To: <1447976286.145626.122.camel@infradead.org>
On Thu, 2015-11-19 at 23:38 +0000, David Woodhouse wrote:
>
> I understand that POWER and other platforms don't currently have a
> clean way to indicate that certain device don't have translation. And I
> understand that we may end up with a *quirk* which ensures that the DMA
> API does the right thing (i.e. nothing) in certain cases.
>
> But we should *NOT* be involving the virtio device drivers in that
> quirk, in any way. And putting a feature bit in the virtio device
> itself doesn't seem at all sane either.
>
> Bear in mind that qemu-system-x86_64 currently has the *same* problem
> with assigned physical devices. It's claiming they're translated, and
> they're not.
It's not that clear but yeah ... as I mentioned, I can't find a
way to do that quirk that won't break when we want to actually use
the iommu...
Ben.
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* [RFC PATCH 9/9] nvme-vhost: add nvme queue handlers
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme
Cc: Ming Lin, qemu-devel, virtualization, Keith Busch,
Christoph Hellwig
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
This adds nvme submission/completion queue handlers,
which are ported from qemu-nvme.
And hooks into nvme-target to do the real job.
Cc: Keith Busch <keith.busch@intel.com>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/vhost.c | 420 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 416 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
index 6847c86..3ce1348 100644
--- a/drivers/nvme/target/vhost.c
+++ b/drivers/nvme/target/vhost.c
@@ -6,10 +6,12 @@
#include <linux/mutex.h>
#include <linux/file.h>
#include <linux/highmem.h>
+#include <linux/kthread.h>
#include "../../vhost/vhost.h"
#include "nvmet.h"
#define NVMET_VHOST_AQ_DEPTH 256
+#define NVMET_VHOST_MAX_SEGMENTS 32
enum NvmeCcShift {
CC_MPS_SHIFT = 7,
@@ -52,6 +54,15 @@ struct nvmet_vhost_ctrl_eventfd {
int __user *vector;
};
+struct nvmet_vhost_iod {
+ struct nvmet_vhost_sq *sq;
+ struct scatterlist sg[NVMET_VHOST_MAX_SEGMENTS];
+ struct nvme_command cmd;
+ struct nvme_completion rsp;
+ struct nvmet_req req;
+ struct list_head entry;
+};
+
struct nvmet_vhost_cq {
struct nvmet_cq cq;
struct nvmet_vhost_ctrl *ctrl;
@@ -61,6 +72,12 @@ struct nvmet_vhost_cq {
u8 phase;
u64 dma_addr;
struct eventfd_ctx *eventfd;
+
+ struct list_head sq_list;
+ struct list_head req_list;
+ spinlock_t lock;
+ struct task_struct *thread;
+ int scheduled;
};
struct nvmet_vhost_sq {
@@ -71,6 +88,13 @@ struct nvmet_vhost_sq {
u32 tail;
u64 dma_addr;
u16 cqid;
+
+ struct nvmet_vhost_iod *io_req;
+ struct list_head req_list;
+ struct list_head entry;
+ struct mutex lock;
+ struct task_struct *thread;
+ int scheduled;
};
struct nvmet_vhost_ctrl {
@@ -191,13 +215,13 @@ static int nvmet_vhost_rw(struct vhost_dev *dev, u64 guest_pa,
return 0;
}
-int nvmet_vhost_read(struct vhost_dev *dev, u64 guest_pa,
+static int nvmet_vhost_read(struct vhost_dev *dev, u64 guest_pa,
void *buf, uint32_t size)
{
return nvmet_vhost_rw(dev, guest_pa, buf, size, 0);
}
-int nvmet_vhost_write(struct vhost_dev *dev, u64 guest_pa,
+static int nvmet_vhost_write(struct vhost_dev *dev, u64 guest_pa,
void *buf, uint32_t size)
{
return nvmet_vhost_rw(dev, guest_pa, buf, size, 1);
@@ -216,6 +240,289 @@ static int nvmet_vhost_check_cqid(struct nvmet_ctrl *n, u16 cqid)
return cqid <= n->subsys->max_qid && n->cqs[cqid] != NULL ? 0 : -1;
}
+static void nvmet_vhost_inc_cq_tail(struct nvmet_vhost_cq *cq)
+{
+ cq->tail++;
+ if (cq->tail >= cq->cq.size) {
+ cq->tail = 0;
+ cq->phase = !cq->phase;
+ }
+}
+
+static void nvmet_vhost_inc_sq_head(struct nvmet_vhost_sq *sq)
+{
+ sq->head = (sq->head + 1) % sq->sq.size;
+}
+
+static uint8_t nvmet_vhost_cq_full(struct nvmet_vhost_cq *cq)
+{
+ return (cq->tail + 1) % cq->cq.size == cq->head;
+}
+
+static uint8_t nvmet_vhost_sq_empty(struct nvmet_vhost_sq *sq)
+{
+ return sq->head == sq->tail;
+}
+
+static void nvmet_vhost_post_cqes(struct nvmet_vhost_cq *cq)
+{
+ struct nvmet_vhost_ctrl *n = cq->ctrl;
+ struct nvmet_vhost_iod *req;
+ struct list_head *p, *tmp;
+ int signal = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cq->lock, flags);
+ list_for_each_safe(p, tmp, &cq->req_list) {
+ struct nvmet_vhost_sq *sq;
+ u64 addr;
+
+ if (nvmet_vhost_cq_full(cq))
+ goto unlock;
+
+ req = list_entry(p, struct nvmet_vhost_iod, entry);
+ list_del(p);
+
+ sq = req->sq;
+ req->rsp.status |= cq->phase;
+ req->rsp.sq_id = cpu_to_le16(sq->sq.qid);
+ req->rsp.sq_head = cpu_to_le16(sq->head);
+ addr = cq->dma_addr + cq->tail * n->cqe_size;
+ nvmet_vhost_inc_cq_tail(cq);
+ spin_unlock_irqrestore(&cq->lock, flags);
+
+ nvmet_vhost_write(&n->dev, addr, (void *)&req->rsp,
+ sizeof(req->rsp));
+
+ mutex_lock(&sq->lock);
+ list_add_tail(p, &sq->req_list);
+ mutex_unlock(&sq->lock);
+
+ signal = 1;
+
+ spin_lock_irqsave(&cq->lock, flags);
+ }
+
+ if (signal)
+ eventfd_signal(cq->eventfd, 1);
+
+unlock:
+ cq->scheduled = 0;
+ spin_unlock_irqrestore(&cq->lock, flags);
+}
+
+static int nvmet_vhost_cq_thread(void *arg)
+{
+ struct nvmet_vhost_cq *sq = arg;
+
+ while (1) {
+ if (kthread_should_stop())
+ break;
+
+ nvmet_vhost_post_cqes(sq);
+
+ schedule();
+ }
+
+ return 0;
+}
+
+static void nvmet_vhost_enqueue_req_completion(
+ struct nvmet_vhost_cq *cq, struct nvmet_vhost_iod *iod)
+{
+ unsigned long flags;
+
+ BUG_ON(cq->cq.qid != iod->sq->sq.qid);
+ spin_lock_irqsave(&cq->lock, flags);
+ list_add_tail(&iod->entry, &cq->req_list);
+ if (!cq->scheduled) {
+ wake_up_process(cq->thread);
+ cq->scheduled = 1;
+ }
+ spin_unlock_irqrestore(&cq->lock, flags);
+}
+
+static void nvmet_vhost_queue_response(struct nvmet_req *req)
+{
+ struct nvmet_vhost_iod *iod =
+ container_of(req, struct nvmet_vhost_iod, req);
+ struct nvmet_vhost_sq *sq = iod->sq;
+ struct nvmet_vhost_ctrl *n = sq->ctrl;
+ struct nvmet_vhost_cq *cq = n->cqs[sq->sq.qid];
+
+ nvmet_vhost_enqueue_req_completion(cq, iod);
+}
+
+static int nvmet_vhost_sglist_add(struct nvmet_vhost_ctrl *n, struct scatterlist *sg,
+ u64 guest_addr, int len, int is_write)
+{
+ void __user *host_addr;
+ struct page *page;
+ unsigned int offset, nbytes;
+ int ret;
+
+ host_addr = map_guest_to_host(&n->dev, guest_addr, len);
+ if (unlikely(!host_addr)) {
+ pr_warn("cannot map guest addr %p, error %ld\n",
+ (void *)guest_addr, PTR_ERR(host_addr));
+ return PTR_ERR(host_addr);
+ }
+
+ ret = get_user_pages(current, n->dev.mm, (unsigned long)host_addr, 1,
+ is_write, 0, &page, NULL);
+ BUG_ON(ret == 0); /* we should either get our page or fail */
+ if (ret < 0) {
+ pr_warn("get_user_pages faild: host_addr %p, %d\n",
+ host_addr, ret);
+ return ret;
+ }
+
+ offset = (uintptr_t)host_addr & ~PAGE_MASK;
+ nbytes = min_t(unsigned int, PAGE_SIZE - offset, len);
+ sg_set_page(sg, page, nbytes, offset);
+
+ return 0;
+}
+
+static int nvmet_vhost_map_prp(struct nvmet_vhost_ctrl *n, struct scatterlist *sgl,
+ u64 prp1, u64 prp2, unsigned int len)
+{
+ unsigned int trans_len = n->page_size - (prp1 % n->page_size);
+ int num_prps = (len >> n->page_bits) + 1;
+ //FIXME
+ int is_write = 1;
+
+ trans_len = min(len, trans_len);
+ if (!prp1)
+ return -1;
+
+ sg_init_table(sgl, num_prps);
+
+ nvmet_vhost_sglist_add(n, sgl, prp1, trans_len, is_write);
+
+ len -= trans_len;
+ if (len) {
+ if (!prp2)
+ goto error;
+ if (len > n->page_size) {
+ u64 prp_list[n->max_prp_ents];
+ u16 nents, prp_trans;
+ int i = 0;
+
+ nents = (len + n->page_size - 1) >> n->page_bits;
+ prp_trans = min(n->max_prp_ents, nents) * sizeof(u64);
+ nvmet_vhost_read(&n->dev, prp2, (void *)prp_list, prp_trans);
+
+ while (len != 0) {
+ u64 prp_ent = le64_to_cpu(prp_list[i]);
+
+ if (i == n->max_prp_ents - 1 && len > n->page_size) {
+ if (!prp_ent || prp_ent & (n->page_size - 1))
+ goto error;
+ i = 0;
+ nents = (len + n->page_size - 1) >> n->page_bits;
+ prp_trans = min(n->max_prp_ents, nents) * sizeof(u64);
+ nvmet_vhost_read(&n->dev, prp_ent, (void *)prp_list, prp_trans);
+ prp_ent = le64_to_cpu(prp_list[i]);
+ }
+
+ if (!prp_ent || prp_ent & (n->page_size - 1))
+ goto error;
+
+ trans_len = min(len, n->page_size);
+ nvmet_vhost_sglist_add(n, sgl, prp_ent, trans_len, is_write);
+ sgl++;
+ len -= trans_len;
+ i++;
+ }
+ } else {
+ if (prp2 & (n->page_size - 1))
+ goto error;
+ nvmet_vhost_sglist_add(n, sgl, prp2, trans_len, is_write);
+ }
+ }
+
+ return num_prps;
+
+error:
+ return -1;
+}
+
+static void nvmet_vhost_process_sq(struct nvmet_vhost_sq *sq)
+{
+ struct nvmet_vhost_ctrl *n = sq->ctrl;
+ struct nvmet_vhost_cq *cq = n->cqs[sq->sq.qid];
+ struct nvmet_vhost_iod *iod;
+ struct nvme_command *cmd;
+ int ret;
+
+ mutex_lock(&sq->lock);
+
+ while (!(nvmet_vhost_sq_empty(sq) || list_empty(&sq->req_list))) {
+ u64 addr = sq->dma_addr + sq->head * n->sqe_size;;
+
+ nvmet_vhost_inc_sq_head(sq);
+ iod = list_first_entry(&sq->req_list,
+ struct nvmet_vhost_iod, entry);
+ list_del(&iod->entry);
+ mutex_unlock(&sq->lock);
+
+ cmd = &iod->cmd;
+ ret = nvmet_vhost_read(&n->dev, addr,
+ (void *)cmd, sizeof(*cmd));
+ if (ret) {
+ pr_warn("nvmet_vhost_read fail\n");
+ goto out;
+ }
+
+ ret = nvmet_req_init(&iod->req, &cq->cq, &sq->sq,
+ nvmet_vhost_queue_response);
+ if (ret) {
+ pr_warn("nvmet_req_init error: ret 0x%x, qid %d\n", ret, sq->sq.qid);
+ goto out;
+ }
+ if (iod->req.data_len) {
+ ret = nvmet_vhost_map_prp(n, iod->sg, cmd->common.prp1,
+ cmd->common.prp2, iod->req.data_len);
+ if (ret > 0) {
+ iod->req.sg = iod->sg;
+ iod->req.sg_cnt = ret;
+ } else {
+ pr_warn("map prp error\n");
+ goto out;
+ }
+ }
+ iod->req.execute(&iod->req);
+ mutex_lock(&sq->lock);
+ }
+
+unlock:
+ sq->scheduled = 0;
+ mutex_unlock(&sq->lock);
+ return;
+
+out:
+ mutex_lock(&sq->lock);
+ list_add_tail(&iod->entry, &sq->req_list);
+ goto unlock;
+}
+
+static int nvmet_vhost_sq_thread(void *opaque)
+{
+ struct nvmet_vhost_sq *sq = opaque;
+
+ while (1) {
+ if (kthread_should_stop())
+ break;
+
+ nvmet_vhost_process_sq(sq);
+
+ schedule();
+ }
+
+ return 0;
+}
+
static int nvmet_vhost_init_cq(struct nvmet_vhost_cq *cq,
struct nvmet_vhost_ctrl *n, u64 dma_addr,
u16 cqid, u16 size, struct eventfd_ctx *eventfd,
@@ -228,6 +535,12 @@ static int nvmet_vhost_init_cq(struct nvmet_vhost_cq *cq,
cq->eventfd = eventfd;
n->cqs[cqid] = cq;
+ spin_lock_init(&cq->lock);
+ INIT_LIST_HEAD(&cq->req_list);
+ INIT_LIST_HEAD(&cq->sq_list);
+ cq->scheduled = 0;
+ cq->thread = kthread_create(nvmet_vhost_cq_thread, cq, "nvmet_vhost_cq");
+
nvmet_cq_init(n->ctrl, &cq->cq, cqid, size);
return 0;
@@ -237,12 +550,36 @@ static int nvmet_vhost_init_sq(struct nvmet_vhost_sq *sq,
struct nvmet_vhost_ctrl *n, u64 dma_addr,
u16 sqid, u16 cqid, u16 size)
{
+ struct nvmet_vhost_cq *cq;
+ struct nvmet_vhost_iod *iod;
+ int i;
+
sq->ctrl = n;
sq->dma_addr = dma_addr;
sq->cqid = cqid;
sq->head = sq->tail = 0;
n->sqs[sqid] = sq;
+ mutex_init(&sq->lock);
+ INIT_LIST_HEAD(&sq->req_list);
+ sq->io_req = kmalloc(sizeof(struct nvmet_vhost_iod) * size, GFP_KERNEL);
+ if (!sq->io_req)
+ return -ENOMEM;
+ for (i = 0; i < size; i++) {
+ iod = &sq->io_req[i];
+
+ iod->req.cmd = &iod->cmd;
+ iod->req.rsp = &iod->rsp;
+ iod->sq = sq;
+ list_add_tail(&iod->entry, &sq->req_list);
+ }
+ sq->scheduled = 0;
+ sq->thread = kthread_create(nvmet_vhost_sq_thread, sq, "nvmet_vhost_sq");
+
+ cq = n->cqs[cqid];
+ list_add_tail(&sq->entry, &cq->sq_list);
+ n->sqs[sqid] = sq;
+
nvmet_sq_init(n->ctrl, &sq->sq, sqid, size);
return 0;
@@ -564,12 +901,84 @@ static int nvmet_bar_write(struct nvmet_vhost_ctrl *n, int offset, u64 val)
return status;
}
+static int nvmet_vhost_process_db(struct nvmet_ctrl *ctrl, int offset, u64 val)
+{
+ u16 qid;
+
+ if (offset & ((1 << 2) - 1))
+ return -EINVAL;
+
+ if (((offset - 0x1000) >> 2) & 1) {
+ u16 new_head = val & 0xffff;
+ int start_sqs;
+ struct nvmet_vhost_cq *vcq;
+ struct nvmet_cq *cq;
+ unsigned long flags;
+
+ qid = (offset - (0x1000 + (1 << 2))) >> 3;
+ if (nvmet_vhost_check_cqid(ctrl, qid))
+ return -EINVAL;
+
+ cq = ctrl->cqs[qid];
+ if (new_head >= cq->size)
+ return -EINVAL;
+
+ vcq = cq_to_vcq(cq);
+ spin_lock_irqsave(&vcq->lock, flags);
+ start_sqs = nvmet_vhost_cq_full(vcq) ? 1 : 0;
+ vcq->head = new_head;
+ spin_unlock_irqrestore(&vcq->lock, flags);
+ if (start_sqs) {
+ struct nvmet_vhost_sq *sq;
+ struct list_head *p;
+
+ list_for_each(p, &vcq->sq_list) {
+ sq = list_entry(p, struct nvmet_vhost_sq, entry);
+ if (!sq->scheduled) {
+ sq->scheduled = 1;
+ wake_up_process(sq->thread);
+ }
+ }
+ if (!vcq->scheduled) {
+ vcq->scheduled = 1;
+ wake_up_process(vcq->thread);
+ }
+ }
+
+ if (vcq->tail != vcq->head)
+ eventfd_signal(vcq->eventfd, 1);
+ } else {
+ struct nvmet_vhost_sq *vsq;
+ struct nvmet_sq *sq;
+ u16 new_tail = val & 0xffff;
+
+ qid = (offset - 0x1000) >> 3;
+ if (nvmet_vhost_check_sqid(ctrl, qid))
+ return -EINVAL;
+
+ sq = ctrl->sqs[qid];
+ if (new_tail >= sq->size)
+ return -ENOSPC;
+
+ vsq = sq_to_vsq(sq);
+ mutex_lock(&vsq->lock);
+ vsq->tail = new_tail;
+ if (!vsq->scheduled) {
+ vsq->scheduled = 1;
+ wake_up_process(vsq->thread);
+ }
+ mutex_unlock(&vsq->lock);
+ }
+
+ return 0;
+}
+
static int nvmet_vhost_bar_write(struct nvmet_vhost_ctrl *n, int offset, u64 val)
{
if (offset < 0x1000)
return nvmet_bar_write(n, offset, val);
-
- return -1;
+ else
+ return nvmet_vhost_process_db(n->ctrl, offset, val);
}
static int nvmet_vhost_ioc_bar(struct nvmet_vhost_ctrl *n, void __user *argp)
@@ -612,6 +1021,8 @@ static void nvme_free_sq(struct nvmet_vhost_sq *sq,
struct nvmet_vhost_ctrl *n)
{
n->sqs[sq->sq.qid] = NULL;
+ kthread_stop(sq->thread);
+ kfree(sq->io_req);
if (sq->sq.qid)
kfree(sq);
}
@@ -620,6 +1031,7 @@ static void nvme_free_cq(struct nvmet_vhost_cq *cq,
struct nvmet_vhost_ctrl *n)
{
n->cqs[cq->cq.qid] = NULL;
+ kthread_stop(cq->thread);
if (cq->cq.qid)
kfree(cq);
}
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 8/9] nvme-vhost: add vhost memory helpers
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, qemu-devel, virtualization, Christoph Hellwig
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
This borrows code from Hannes Reinecke's rts-megasas.
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/vhost.c | 108 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
index 04ed0bc..6847c86 100644
--- a/drivers/nvme/target/vhost.c
+++ b/drivers/nvme/target/vhost.c
@@ -5,6 +5,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/file.h>
+#include <linux/highmem.h>
#include "../../vhost/vhost.h"
#include "nvmet.h"
@@ -95,6 +96,113 @@ struct nvmet_vhost_ctrl {
u32 page_size;
};
+const struct vhost_memory_region *
+find_region(struct vhost_dev *hba, __u64 addr, __u32 len)
+{
+ struct vhost_memory *mem;
+ struct vhost_memory_region *reg;
+ int i;
+
+ if (!hba->memory)
+ return NULL;
+
+ mem = hba->memory;
+ /* linear search is not brilliant, but we really have on the order of 6
+ * regions in practice */
+ for (i = 0; i < mem->nregions; ++i) {
+ reg = mem->regions + i;
+ if (reg->guest_phys_addr <= addr &&
+ reg->guest_phys_addr + reg->memory_size - 1 >= addr)
+ return reg;
+ }
+ return NULL;
+}
+
+static bool check_region_boundary(const struct vhost_memory_region *reg,
+ uint64_t addr, size_t len)
+{
+ unsigned long max_size;
+
+ max_size = reg->memory_size - addr + reg->guest_phys_addr;
+ return (max_size < len);
+}
+
+static void __user *map_to_region(const struct vhost_memory_region *reg,
+ uint64_t addr)
+{
+ return (void __user *)(unsigned long)
+ (reg->userspace_addr + addr - reg->guest_phys_addr);
+}
+
+static void __user *map_guest_to_host(struct vhost_dev *dev,
+ uint64_t addr, int size)
+{
+ const struct vhost_memory_region *reg = NULL;
+
+ reg = find_region(dev, addr, size);
+ if (unlikely(!reg))
+ return ERR_PTR(-EPERM);
+
+ if (unlikely(check_region_boundary(reg, addr, size)))
+ return ERR_PTR(-EFAULT);
+
+ return map_to_region(reg, addr);
+}
+
+static int nvmet_vhost_rw(struct vhost_dev *dev, u64 guest_pa,
+ void *buf, uint32_t size, int write)
+{
+ void __user *host_user_va;
+ void *host_kernel_va;
+ struct page *page;
+ uintptr_t offset;
+ int ret;
+
+ host_user_va = map_guest_to_host(dev, guest_pa, size);
+ if (unlikely(!host_user_va)) {
+ pr_warn("cannot map guest addr %p, error %ld\n",
+ (void *)guest_pa, PTR_ERR(host_user_va));
+ return -EINVAL;
+ }
+
+ ret = get_user_pages(current, dev->mm,
+ (unsigned long)host_user_va, 1,
+ false, 0, &page, NULL);
+ if (unlikely(ret != 1)) {
+ pr_warn("get_user_pages fail!!!\n");
+ return -EINVAL;
+ }
+
+ host_kernel_va = kmap(page);
+ if (unlikely(!host_kernel_va)) {
+ pr_warn("kmap fail!!!\n");
+ put_page(page);
+ return -EINVAL;
+ }
+
+ offset = (uintptr_t)host_user_va & ~PAGE_MASK;
+ if (write)
+ memcpy(host_kernel_va + offset, buf, size);
+ else
+ memcpy(buf, host_kernel_va + offset, size);
+ kunmap(host_kernel_va);
+ put_page(page);
+
+ return 0;
+}
+
+int nvmet_vhost_read(struct vhost_dev *dev, u64 guest_pa,
+ void *buf, uint32_t size)
+{
+ return nvmet_vhost_rw(dev, guest_pa, buf, size, 0);
+}
+
+int nvmet_vhost_write(struct vhost_dev *dev, u64 guest_pa,
+ void *buf, uint32_t size)
+{
+ return nvmet_vhost_rw(dev, guest_pa, buf, size, 1);
+}
+
#define sq_to_vsq(sq) container_of(sq, struct nvmet_vhost_sq, sq)
#define cq_to_vcq(cq) container_of(cq, struct nvmet_vhost_cq, cq)
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 7/9] nvme-vhost: add "parse_extra_admin_cmd" callback
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/vhost.c | 153 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 153 insertions(+)
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
index 4a147d6..04ed0bc 100644
--- a/drivers/nvme/target/vhost.c
+++ b/drivers/nvme/target/vhost.c
@@ -39,6 +39,11 @@ enum NvmeAqaMask {
#define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK)
#define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK)
+#define NVME_CQ_FLAGS_PC(cq_flags) (cq_flags & 0x1)
+#define NVME_CQ_FLAGS_IEN(cq_flags) ((cq_flags >> 1) & 0x1)
+
+#define NVME_SQ_FLAGS_PC(sq_flags) (sq_flags & 0x1)
+
struct nvmet_vhost_ctrl_eventfd {
struct file *call;
struct eventfd_ctx *call_ctx;
@@ -90,6 +95,19 @@ struct nvmet_vhost_ctrl {
u32 page_size;
};
+#define sq_to_vsq(sq) container_of(sq, struct nvmet_vhost_sq, sq)
+#define cq_to_vcq(cq) container_of(cq, struct nvmet_vhost_cq, cq)
+
+static int nvmet_vhost_check_sqid(struct nvmet_ctrl *n, u16 sqid)
+{
+ return sqid <= n->subsys->max_qid && n->sqs[sqid] != NULL ? 0 : -1;
+}
+
+static int nvmet_vhost_check_cqid(struct nvmet_ctrl *n, u16 cqid)
+{
+ return cqid <= n->subsys->max_qid && n->cqs[cqid] != NULL ? 0 : -1;
+}
+
static int nvmet_vhost_init_cq(struct nvmet_vhost_cq *cq,
struct nvmet_vhost_ctrl *n, u64 dma_addr,
u16 cqid, u16 size, struct eventfd_ctx *eventfd,
@@ -147,6 +165,140 @@ static void nvmet_vhost_start_ctrl(void *opaque)
}
}
+static void nvmet_vhost_create_cq(struct nvmet_req *req)
+{
+ struct nvmet_cq *cq;
+ struct nvmet_vhost_cq *vcq;
+ struct nvmet_vhost_ctrl *n;
+ struct nvme_create_cq *c;
+ u16 cqid;
+ u16 vector;
+ u16 qsize;
+ u16 qflags;
+ u64 prp1;
+ int status;
+ int ret;
+
+ cq = req->cq;
+ vcq = cq_to_vcq(cq);
+ n = vcq->ctrl;
+ c = &req->cmd->create_cq;
+ cqid = le16_to_cpu(c->cqid);
+ vector = le16_to_cpu(c->irq_vector);
+ qsize = le16_to_cpu(c->qsize);
+ qflags = le16_to_cpu(c->cq_flags);
+ prp1 = le64_to_cpu(c->prp1);
+ status = NVME_SC_SUCCESS;
+
+ if (!cqid || (cqid && !nvmet_vhost_check_cqid(n->ctrl, cqid))) {
+ status = NVME_SC_QID_INVALID | NVME_SC_DNR;
+ goto out;
+ }
+ if (!qsize || qsize > NVME_CAP_MQES(n->ctrl->cap)) {
+ status = NVME_SC_QUEUE_SIZE | NVME_SC_DNR;
+ goto out;
+ }
+ if (!prp1) {
+ status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ goto out;
+ }
+ if (vector > n->num_queues) {
+ status = NVME_SC_INVALID_VECTOR | NVME_SC_DNR;
+ goto out;
+ }
+ if (!(NVME_CQ_FLAGS_PC(qflags))) {
+ status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ goto out;
+ }
+
+ vcq = kmalloc(sizeof(*vcq), GFP_KERNEL);
+ if (!vcq) {
+ status = NVME_SC_INTERNAL | NVME_SC_DNR;
+ goto out;
+ }
+
+ ret = nvmet_vhost_init_cq(vcq, n, prp1, cqid, qsize+1,
+ n->eventfd[cqid].call_ctx, vector,
+ NVME_CQ_FLAGS_IEN(qflags));
+ if (ret)
+ status = NVME_SC_INTERNAL | NVME_SC_DNR;
+
+out:
+ nvmet_req_complete(req, status);
+}
+
+static void nvmet_vhost_create_sq(struct nvmet_req *req)
+{
+ struct nvme_create_sq *c = &req->cmd->create_sq;
+ u16 cqid = le16_to_cpu(c->cqid);
+ u16 sqid = le16_to_cpu(c->sqid);
+ u16 qsize = le16_to_cpu(c->qsize);
+ u16 qflags = le16_to_cpu(c->sq_flags);
+ u64 prp1 = le64_to_cpu(c->prp1);
+
+ struct nvmet_sq *sq = req->sq;
+ struct nvmet_vhost_sq *vsq;
+ struct nvmet_vhost_ctrl *n;
+ int status;
+ int ret;
+
+ status = NVME_SC_SUCCESS;
+ vsq = sq_to_vsq(sq);
+ n = vsq->ctrl;
+
+ if (!cqid || nvmet_vhost_check_cqid(n->ctrl, cqid)) {
+ status = NVME_SC_CQ_INVALID | NVME_SC_DNR;
+ goto out;
+ }
+ if (!sqid || (sqid && !nvmet_vhost_check_sqid(n->ctrl, sqid))) {
+ status = NVME_SC_QID_INVALID | NVME_SC_DNR;
+ goto out;
+ }
+ if (!qsize || qsize > NVME_CAP_MQES(n->ctrl->cap)) {
+ status = NVME_SC_QUEUE_SIZE | NVME_SC_DNR;
+ goto out;
+ }
+ if (!prp1 || prp1 & (n->page_size - 1)) {
+ status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ goto out;
+ }
+ if (!(NVME_SQ_FLAGS_PC(qflags))) {
+ status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ goto out;
+ }
+
+ vsq = kmalloc(sizeof(*vsq), GFP_KERNEL);
+ if (!sq) {
+ status = NVME_SC_INTERNAL | NVME_SC_DNR;
+ goto out;
+ }
+
+ ret = nvmet_vhost_init_sq(vsq, n, prp1, sqid, cqid, qsize + 1);
+ if (ret)
+ status = NVME_SC_INTERNAL | NVME_SC_DNR;
+
+out:
+ nvmet_req_complete(req, status);
+}
+
+static int nvmet_vhost_parse_admin_cmd(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ switch (cmd->common.opcode) {
+ case nvme_admin_create_cq:
+ req->execute = nvmet_vhost_create_cq;
+ req->data_len = 0;
+ return 0;
+ case nvme_admin_create_sq:
+ req->execute = nvmet_vhost_create_sq;
+ req->data_len = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
static int
nvmet_vhost_set_endpoint(struct nvmet_vhost_ctrl *n,
struct vhost_nvme_target *c)
@@ -173,6 +325,7 @@ nvmet_vhost_set_endpoint(struct nvmet_vhost_ctrl *n,
n->num_queues = subsys->max_qid + 1;
ctrl->opaque = n;
ctrl->start = nvmet_vhost_start_ctrl;
+ ctrl->parse_extra_admin_cmd = nvmet_vhost_parse_admin_cmd;
num_queues = ctrl->subsys->max_qid + 1;
n->cqs = kzalloc(sizeof(*n->cqs) * num_queues, GFP_KERNEL);
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 6/9] nvmet: add a "parse_extra_admin_cmd" hook
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
This is used to execute controller specific cmd parse code
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/admin-cmd.c | 7 +++++++
drivers/nvme/target/nvmet.h | 3 +++
2 files changed, 10 insertions(+)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index d9db0d4..f009c77 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -346,6 +346,13 @@ int nvmet_parse_admin_cmd(struct nvmet_req *req)
req->data = 0;
return 0;
#endif
+ default:
+ if (req->sq->ctrl->parse_extra_admin_cmd) {
+ int ret = req->sq->ctrl->parse_extra_admin_cmd(req);
+
+ if (!ret)
+ return 0;
+ }
}
pr_err("nvmet: unhandled cmd %d\n", cmd->common.opcode);
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index eac008b..ef79813 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -44,6 +44,8 @@ struct nvmet_sq {
u16 size;
};
+struct nvmet_req;
+
struct nvmet_ctrl {
struct nvmet_subsys *subsys;
struct nvmet_cq **cqs;
@@ -62,6 +64,7 @@ struct nvmet_ctrl {
void *opaque;
void (*start)(void *);
+ int (*parse_extra_admin_cmd)(struct nvmet_req *);
};
struct nvmet_subsys {
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 5/9] nvme-vhost: add controller "start" callback
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/vhost.c | 106 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
index 01c44b8..4a147d6 100644
--- a/drivers/nvme/target/vhost.c
+++ b/drivers/nvme/target/vhost.c
@@ -10,6 +10,35 @@
#define NVMET_VHOST_AQ_DEPTH 256
+enum NvmeCcShift {
+ CC_MPS_SHIFT = 7,
+ CC_IOSQES_SHIFT = 16,
+ CC_IOCQES_SHIFT = 20,
+};
+
+enum NvmeCcMask {
+ CC_MPS_MASK = 0xf,
+ CC_IOSQES_MASK = 0xf,
+ CC_IOCQES_MASK = 0xf,
+};
+
+#define NVME_CC_MPS(cc) ((cc >> CC_MPS_SHIFT) & CC_MPS_MASK)
+#define NVME_CC_IOSQES(cc) ((cc >> CC_IOSQES_SHIFT) & CC_IOSQES_MASK)
+#define NVME_CC_IOCQES(cc) ((cc >> CC_IOCQES_SHIFT) & CC_IOCQES_MASK)
+
+enum NvmeAqaShift {
+ AQA_ASQS_SHIFT = 0,
+ AQA_ACQS_SHIFT = 16,
+};
+
+enum NvmeAqaMask {
+ AQA_ASQS_MASK = 0xfff,
+ AQA_ACQS_MASK = 0xfff,
+};
+
+#define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK)
+#define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK)
+
struct nvmet_vhost_ctrl_eventfd {
struct file *call;
struct eventfd_ctx *call_ctx;
@@ -19,12 +48,23 @@ struct nvmet_vhost_ctrl_eventfd {
struct nvmet_vhost_cq {
struct nvmet_cq cq;
+ struct nvmet_vhost_ctrl *ctrl;
+ u32 head;
+ u32 tail;
+ u8 phase;
+ u64 dma_addr;
struct eventfd_ctx *eventfd;
};
struct nvmet_vhost_sq {
struct nvmet_sq sq;
+ struct nvmet_vhost_ctrl *ctrl;
+
+ u32 head;
+ u32 tail;
+ u64 dma_addr;
+ u16 cqid;
};
struct nvmet_vhost_ctrl {
@@ -37,12 +77,76 @@ struct nvmet_vhost_ctrl {
struct nvmet_vhost_cq **cqs;
struct nvmet_vhost_sq **sqs;
+ struct nvmet_vhost_cq admin_cq;
+ struct nvmet_vhost_sq admin_sq;
u32 aqa;
u64 asq;
u64 acq;
+ u16 cqe_size;
+ u16 sqe_size;
+ u16 max_prp_ents;
+ u16 page_bits;
+ u32 page_size;
};
+static int nvmet_vhost_init_cq(struct nvmet_vhost_cq *cq,
+ struct nvmet_vhost_ctrl *n, u64 dma_addr,
+ u16 cqid, u16 size, struct eventfd_ctx *eventfd,
+ u16 vector, u16 irq_enabled)
+{
+ cq->ctrl = n;
+ cq->dma_addr = dma_addr;
+ cq->phase = 1;
+ cq->head = cq->tail = 0;
+ cq->eventfd = eventfd;
+ n->cqs[cqid] = cq;
+
+ nvmet_cq_init(n->ctrl, &cq->cq, cqid, size);
+
+ return 0;
+}
+
+static int nvmet_vhost_init_sq(struct nvmet_vhost_sq *sq,
+ struct nvmet_vhost_ctrl *n, u64 dma_addr,
+ u16 sqid, u16 cqid, u16 size)
+{
+ sq->ctrl = n;
+ sq->dma_addr = dma_addr;
+ sq->cqid = cqid;
+ sq->head = sq->tail = 0;
+ n->sqs[sqid] = sq;
+
+ nvmet_sq_init(n->ctrl, &sq->sq, sqid, size);
+
+ return 0;
+}
+
+static void nvmet_vhost_start_ctrl(void *opaque)
+{
+ struct nvmet_vhost_ctrl *n = opaque;
+ u32 page_bits = NVME_CC_MPS(n->ctrl->cc) + 12;
+ u32 page_size = 1 << page_bits;
+ int ret;
+
+ n->page_bits = page_bits;
+ n->page_size = page_size;
+ n->max_prp_ents = n->page_size / sizeof(uint64_t);
+ n->cqe_size = 1 << NVME_CC_IOCQES(n->ctrl->cc);
+ n->sqe_size = 1 << NVME_CC_IOSQES(n->ctrl->cc);
+
+ nvmet_vhost_init_cq(&n->admin_cq, n, n->acq, 0,
+ NVME_AQA_ACQS(n->aqa) + 1, n->eventfd[0].call_ctx,
+ 0, 1);
+
+ ret = nvmet_vhost_init_sq(&n->admin_sq, n, n->asq, 0, 0,
+ NVME_AQA_ASQS(n->aqa) + 1);
+ if (ret) {
+ pr_warn("nvmet_vhost_init_sq failed!!!\n");
+ BUG_ON(1);
+ }
+}
+
static int
nvmet_vhost_set_endpoint(struct nvmet_vhost_ctrl *n,
struct vhost_nvme_target *c)
@@ -67,6 +171,8 @@ nvmet_vhost_set_endpoint(struct nvmet_vhost_ctrl *n,
n->cntlid = ctrl->cntlid;
n->ctrl = ctrl;
n->num_queues = subsys->max_qid + 1;
+ ctrl->opaque = n;
+ ctrl->start = nvmet_vhost_start_ctrl;
num_queues = ctrl->subsys->max_qid + 1;
n->cqs = kzalloc(sizeof(*n->cqs) * num_queues, GFP_KERNEL);
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 4/9] nvmet: add a controller "start" hook
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
This is used to execute controller specific start code
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/core.c | 3 +++
drivers/nvme/target/nvmet.h | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 1bfef66..0a0fc48 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -251,6 +251,9 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl)
}
ctrl->csts = NVME_CSTS_RDY;
+
+ if (ctrl->start)
+ ctrl->start(ctrl->opaque);
}
static void nvmet_clear_ctrl(struct nvmet_ctrl *ctrl)
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 9335584..eac008b 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -59,6 +59,9 @@ struct nvmet_ctrl {
struct kref ref;
#define NVMET_SUBSYS_NAME_LEN 256
char subsys_name[NVMET_SUBSYS_NAME_LEN];
+
+ void *opaque;
+ void (*start)(void *);
};
struct nvmet_subsys {
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 3/9] nvme-vhost: add basic nvme bar read/write
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/vhost.c | 102 ++++++++++++++++++++++++++++++++++++++++++++
include/uapi/linux/vhost.h | 17 ++++++--
2 files changed, 116 insertions(+), 3 deletions(-)
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
index fa2e668..01c44b8 100644
--- a/drivers/nvme/target/vhost.c
+++ b/drivers/nvme/target/vhost.c
@@ -8,6 +8,8 @@
#include "../../vhost/vhost.h"
#include "nvmet.h"
+#define NVMET_VHOST_AQ_DEPTH 256
+
struct nvmet_vhost_ctrl_eventfd {
struct file *call;
struct eventfd_ctx *call_ctx;
@@ -35,6 +37,10 @@ struct nvmet_vhost_ctrl {
struct nvmet_vhost_cq **cqs;
struct nvmet_vhost_sq **sqs;
+
+ u32 aqa;
+ u64 asq;
+ u64 acq;
};
static int
@@ -127,6 +133,100 @@ static int nvmet_vhost_set_eventfd(struct nvmet_vhost_ctrl *n, void __user *argp
return 0;
}
+static int nvmet_vhost_bar_read(struct nvmet_ctrl *ctrl, int offset, u64 *val)
+{
+ int status = NVME_SC_SUCCESS;
+
+ switch(offset) {
+ case NVME_REG_CAP:
+ *val = ctrl->cap;
+ break;
+ case NVME_REG_CAP+4:
+ *val = ctrl->cap >> 32;
+ case NVME_REG_VS:
+ *val = ctrl->subsys->ver;
+ break;
+ case NVME_REG_CC:
+ *val = ctrl->cc;
+ break;
+ case NVME_REG_CSTS:
+ *val = ctrl->csts;
+ break;
+ case NVME_REG_AQA:
+ *val = (NVMET_VHOST_AQ_DEPTH - 1) |
+ (((NVMET_VHOST_AQ_DEPTH - 1) << 16));
+ break;
+ default:
+ printk("Unknown offset: 0x%x\n", offset);
+ status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ break;
+ }
+
+ return status;
+}
+
+static int nvmet_bar_write(struct nvmet_vhost_ctrl *n, int offset, u64 val)
+{
+ struct nvmet_ctrl *ctrl = n->ctrl;
+ int status = NVME_SC_SUCCESS;
+
+ switch(offset) {
+ case NVME_REG_CC:
+ nvmet_update_cc(ctrl, val);
+ break;
+ case NVME_REG_AQA:
+ n->aqa = val & 0xffffffff;
+ break;
+ case NVME_REG_ASQ:
+ n->asq = val;
+ break;
+ case NVME_REG_ASQ + 4:
+ n->asq |= val << 32;
+ break;
+ case NVME_REG_ACQ:
+ n->acq = val;
+ break;
+ case NVME_REG_ACQ + 4:
+ n->acq |= val << 32;
+ break;
+ default:
+ status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ break;
+ }
+
+ return status;
+}
+
+static int nvmet_vhost_bar_write(struct nvmet_vhost_ctrl *n, int offset, u64 val)
+{
+ if (offset < 0x1000)
+ return nvmet_bar_write(n, offset, val);
+
+ return -1;
+}
+
+static int nvmet_vhost_ioc_bar(struct nvmet_vhost_ctrl *n, void __user *argp)
+{
+ struct nvmet_vhost_bar bar;
+ struct nvmet_vhost_bar __user *user_bar = argp;
+ int ret = -EINVAL;
+
+ ret = copy_from_user(&bar, argp, sizeof(bar));
+ if (unlikely(ret))
+ return ret;
+
+ if (bar.type == VHOST_NVME_BAR_READ) {
+ u64 val;
+ ret = nvmet_vhost_bar_read(n->ctrl, bar.offset, &val);
+ if (ret != NVME_SC_SUCCESS)
+ return ret;
+ ret = copy_to_user(&user_bar->val, &val, sizeof(u64));
+ } else if (bar.type == VHOST_NVME_BAR_WRITE)
+ ret = nvmet_vhost_bar_write(n, bar.offset, bar.val);
+
+ return ret;
+}
+
static int nvmet_vhost_open(struct inode *inode, struct file *f)
{
struct nvmet_vhost_ctrl *n = kzalloc(sizeof(*n), GFP_KERNEL);
@@ -223,6 +323,8 @@ static long nvmet_vhost_ioctl(struct file *f, unsigned int ioctl,
case VHOST_NVME_SET_EVENTFD:
r = nvmet_vhost_set_eventfd(n, argp);
return r;
+ case VHOST_NVME_BAR:
+ return nvmet_vhost_ioc_bar(n, argp);
case VHOST_GET_FEATURES:
features = VHOST_FEATURES;
if (copy_to_user(featurep, &features, sizeof(features)))
diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index ae4b619..a0cefcc 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -180,8 +180,19 @@ struct nvmet_vhost_eventfd {
int *vector;
};
-#define VHOST_NVME_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x47, struct vhost_nvme_target)
-#define VHOST_NVME_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x48, struct vhost_nvme_target)
-#define VHOST_NVME_SET_EVENTFD _IOW(VHOST_VIRTIO, 0x45, struct nvmet_vhost_eventfd)
+#define VHOST_NVME_BAR_READ 0
+#define VHOST_NVME_BAR_WRITE 1
+
+struct nvmet_vhost_bar {
+ int type; /* read/write */
+ u64 offset;
+ unsigned size;
+ u64 val;
+};
+
+#define VHOST_NVME_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x45, struct vhost_nvme_target)
+#define VHOST_NVME_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x46, struct vhost_nvme_target)
+#define VHOST_NVME_SET_EVENTFD _IOW(VHOST_VIRTIO, 0x47, struct nvmet_vhost_eventfd)
+#define VHOST_NVME_BAR _IOW(VHOST_VIRTIO, 0x48, struct nvmet_vhost_bar)
#endif
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 2/9] nvme-vhost: add basic ioctl handlers
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/core.c | 1 +
drivers/nvme/target/vhost.c | 264 +++++++++++++++++++++++++++++++++++++++++++-
include/uapi/linux/vhost.h | 15 +++
3 files changed, 279 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 5c770bf..1bfef66 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -378,6 +378,7 @@ void nvmet_ctrl_put(struct nvmet_ctrl *ctrl)
{
kref_put(&ctrl->ref, nvmet_ctrl_free);
}
+EXPORT_SYMBOL_GPL(nvmet_ctrl_put);
struct nvmet_subsys *nvmet_find_subsys(char *subsys_name)
{
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
index 623af00..fa2e668 100644
--- a/drivers/nvme/target/vhost.c
+++ b/drivers/nvme/target/vhost.c
@@ -1,13 +1,275 @@
#include <linux/module.h>
+#include <linux/compat.h>
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/file.h>
+#include "../../vhost/vhost.h"
+#include "nvmet.h"
-static int __init nvmet_vhost_init(void)
+struct nvmet_vhost_ctrl_eventfd {
+ struct file *call;
+ struct eventfd_ctx *call_ctx;
+ int __user *irq_enabled;
+ int __user *vector;
+};
+
+struct nvmet_vhost_cq {
+ struct nvmet_cq cq;
+
+ struct eventfd_ctx *eventfd;
+};
+
+struct nvmet_vhost_sq {
+ struct nvmet_sq sq;
+};
+
+struct nvmet_vhost_ctrl {
+ struct vhost_dev dev;
+ struct nvmet_vhost_ctrl_eventfd *eventfd;
+
+ u16 cntlid;
+ struct nvmet_ctrl *ctrl;
+ u32 num_queues;
+
+ struct nvmet_vhost_cq **cqs;
+ struct nvmet_vhost_sq **sqs;
+};
+
+static int
+nvmet_vhost_set_endpoint(struct nvmet_vhost_ctrl *n,
+ struct vhost_nvme_target *c)
{
+ struct nvmet_subsys *subsys;
+ struct nvmet_ctrl *ctrl;
+ int num_queues;
+ int ret = 0;
+
+ subsys = nvmet_find_subsys(c->vhost_wwpn);
+ if (!subsys) {
+ pr_warn("connect request for invalid subsystem!\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&subsys->lock);
+ ctrl = nvmet_alloc_ctrl(subsys, c->vhost_wwpn);
+ if (IS_ERR(ctrl)) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+ n->cntlid = ctrl->cntlid;
+ n->ctrl = ctrl;
+ n->num_queues = subsys->max_qid + 1;
+
+ num_queues = ctrl->subsys->max_qid + 1;
+ n->cqs = kzalloc(sizeof(*n->cqs) * num_queues, GFP_KERNEL);
+ if (!n->cqs) {
+ ret = -ENOMEM;
+ goto out_ctrl_put;
+ }
+ n->sqs = kzalloc(sizeof(*n->sqs) * num_queues, GFP_KERNEL);
+ if (!n->sqs) {
+ ret = -ENOMEM;
+ goto free_cqs;
+ }
+
+ n->eventfd = kmalloc(sizeof(struct nvmet_vhost_ctrl_eventfd)
+ * num_queues, GFP_KERNEL);
+ if (!n->eventfd) {
+ ret = -ENOMEM;
+ goto free_sqs;
+ }
+
+ mutex_unlock(&subsys->lock);
return 0;
+
+free_sqs:
+ kfree(n->sqs);
+
+free_cqs:
+ kfree(n->cqs);
+
+out_ctrl_put:
+ nvmet_ctrl_put(ctrl);
+
+out_unlock:
+ mutex_unlock(&subsys->lock);
+ return ret;
+}
+
+static int nvmet_vhost_set_eventfd(struct nvmet_vhost_ctrl *n, void __user *argp)
+{
+ struct nvmet_vhost_eventfd eventfd;
+ int num;
+ int ret;
+
+ ret = copy_from_user(&eventfd, argp, sizeof(struct nvmet_vhost_eventfd));
+ if (unlikely(ret))
+ return ret;
+
+ num = eventfd.num;
+ if (num > n->ctrl->subsys->max_qid)
+ return -EINVAL;
+
+ n->eventfd[num].call = eventfd_fget(eventfd.fd);
+ if (IS_ERR(n->eventfd[num].call))
+ return -EBADF;
+ n->eventfd[num].call_ctx = eventfd_ctx_fileget(n->eventfd[num].call);
+ if (IS_ERR(n->eventfd[num].call_ctx)) {
+ fput(n->eventfd[num].call);
+ return -EBADF;
+ }
+
+ n->eventfd[num].irq_enabled = eventfd.irq_enabled;
+ n->eventfd[num].vector = eventfd.vector;
+
+ return 0;
+}
+
+static int nvmet_vhost_open(struct inode *inode, struct file *f)
+{
+ struct nvmet_vhost_ctrl *n = kzalloc(sizeof(*n), GFP_KERNEL);
+
+ if (!n)
+ return -ENOMEM;
+
+ /* We don't use virtqueue */
+ vhost_dev_init(&n->dev, NULL, 0);
+ f->private_data = n;
+
+ return 0;
+}
+
+static void nvme_free_sq(struct nvmet_vhost_sq *sq,
+ struct nvmet_vhost_ctrl *n)
+{
+ n->sqs[sq->sq.qid] = NULL;
+ if (sq->sq.qid)
+ kfree(sq);
+}
+
+static void nvme_free_cq(struct nvmet_vhost_cq *cq,
+ struct nvmet_vhost_ctrl *n)
+{
+ n->cqs[cq->cq.qid] = NULL;
+ if (cq->cq.qid)
+ kfree(cq);
+}
+
+static void nvmet_vhost_clear_ctrl(struct nvmet_vhost_ctrl *n)
+{
+ int i;
+
+ for (i = 0; i < n->num_queues; i++) {
+ if (n->sqs[i] != NULL)
+ nvme_free_sq(n->sqs[i], n);
+ }
+ for (i = 0; i < n->num_queues; i++) {
+ if (n->cqs[i] != NULL)
+ nvme_free_cq(n->cqs[i], n);
+ }
+
+ kfree(n->eventfd);
+ kfree(n->cqs);
+ kfree(n->sqs);
+ nvmet_ctrl_put(n->ctrl);
+}
+
+static void nvmet_vhost_clear_eventfd(struct nvmet_vhost_ctrl *n)
+{
+ int i;
+
+ for (i = 0; i < n->num_queues; i++) {
+ if (n->eventfd[i].call_ctx) {
+ eventfd_ctx_put(n->eventfd[i].call_ctx);
+ fput(n->eventfd[i].call);
+ }
+ }
+}
+
+static int nvmet_vhost_release(struct inode *inode, struct file *f)
+{
+ struct nvmet_vhost_ctrl *n = f->private_data;
+
+ nvmet_vhost_clear_eventfd(n);
+ nvmet_vhost_clear_ctrl(n);
+
+ vhost_dev_stop(&n->dev);
+ vhost_dev_cleanup(&n->dev, false);
+
+ kfree(n);
+ return 0;
+}
+
+static long nvmet_vhost_ioctl(struct file *f, unsigned int ioctl,
+ unsigned long arg)
+{
+ struct nvmet_vhost_ctrl *n = f->private_data;
+ void __user *argp = (void __user *)arg;
+ u64 __user *featurep = argp;
+ u64 features;
+ int r;
+
+ switch (ioctl) {
+ case VHOST_NVME_SET_ENDPOINT:
+ {
+ struct vhost_nvme_target conf;
+ if (copy_from_user(&conf, argp, sizeof(conf)))
+ return -EFAULT;
+
+ return nvmet_vhost_set_endpoint(n, &conf);
+ }
+ case VHOST_NVME_SET_EVENTFD:
+ r = nvmet_vhost_set_eventfd(n, argp);
+ return r;
+ case VHOST_GET_FEATURES:
+ features = VHOST_FEATURES;
+ if (copy_to_user(featurep, &features, sizeof(features)))
+ return -EFAULT;
+ return 0;
+ default:
+ mutex_lock(&n->dev.mutex);
+ r = vhost_dev_ioctl(&n->dev, ioctl, argp);
+ mutex_unlock(&n->dev.mutex);
+ return r;
+ }
+}
+
+#ifdef CONFIG_COMPAT
+static long nvmet_vhost_compat_ioctl(struct file *f, unsigned int ioctl,
+ unsigned long arg)
+{
+ return nvmet_vhost_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations nvmet_vhost_fops = {
+ .owner = THIS_MODULE,
+ .release = nvmet_vhost_release,
+ .unlocked_ioctl = nvmet_vhost_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = nvmet_vhost_compat_ioctl,
+#endif
+ .open = nvmet_vhost_open,
+ .llseek = noop_llseek,
+};
+
+static struct miscdevice nvmet_vhost_misc = {
+ MISC_DYNAMIC_MINOR,
+ "vhost-nvme",
+ &nvmet_vhost_fops,
+};
+
+static int __init nvmet_vhost_init(void)
+{
+ return misc_register(&nvmet_vhost_misc);
}
module_init(nvmet_vhost_init);
static void nvmet_vhost_exit(void)
{
+ misc_deregister(&nvmet_vhost_misc);
}
module_exit(nvmet_vhost_exit);
diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index ab373191..ae4b619 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -169,4 +169,19 @@ struct vhost_scsi_target {
#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
+struct vhost_nvme_target {
+ char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
+};
+
+struct nvmet_vhost_eventfd {
+ int num;
+ int fd;
+ int *irq_enabled;
+ int *vector;
+};
+
+#define VHOST_NVME_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x47, struct vhost_nvme_target)
+#define VHOST_NVME_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x48, struct vhost_nvme_target)
+#define VHOST_NVME_SET_EVENTFD _IOW(VHOST_VIRTIO, 0x45, struct nvmet_vhost_eventfd)
+
#endif
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 1/9] nvme-vhost: add initial commit
From: Ming Lin @ 2015-11-20 0:21 UTC (permalink / raw)
To: linux-nvme; +Cc: Ming Lin, Christoph Hellwig, qemu-devel, virtualization
In-Reply-To: <1447978868-17138-1-git-send-email-mlin@kernel.org>
From: Ming Lin <ming.l@ssi.samsung.com>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
---
drivers/nvme/target/Kconfig | 11 +++++++++++
drivers/nvme/target/Makefile | 2 ++
drivers/nvme/target/vhost.c | 16 ++++++++++++++++
3 files changed, 29 insertions(+)
create mode 100644 drivers/nvme/target/vhost.c
diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig
index 1bf92db..22760f5 100644
--- a/drivers/nvme/target/Kconfig
+++ b/drivers/nvme/target/Kconfig
@@ -12,3 +12,14 @@ config NVME_TARGET_LOOP
to test NVMe host and target side features.
If unsure, say N.
+
+config NVME_TARGET_VHOST
+ tristate "NVMe vhost support"
+ depends on BLK_DEV_NVME
+ select NVME_TARGET
+ select VHOST
+ select VHOST_RING
+ help
+ This enabled the NVMe vhost support.
+
+ If unsure, say N.
diff --git a/drivers/nvme/target/Makefile b/drivers/nvme/target/Makefile
index 21e9134..1d8d523 100644
--- a/drivers/nvme/target/Makefile
+++ b/drivers/nvme/target/Makefile
@@ -1,6 +1,8 @@
obj-$(CONFIG_NVME_TARGET) += nvmet.o
obj-$(CONFIG_NVME_TARGET_LOOP) += nvme-loop.o
+obj-$(CONFIG_NVME_TARGET_VHOST) += nvme-vhost.o
nvmet-y += core.o configfs.o admin-cmd.o io-cmd.o
nvme-loop-y += loop.o
+nvme-vhost-y += vhost.o
diff --git a/drivers/nvme/target/vhost.c b/drivers/nvme/target/vhost.c
new file mode 100644
index 0000000..623af00
--- /dev/null
+++ b/drivers/nvme/target/vhost.c
@@ -0,0 +1,16 @@
+#include <linux/module.h>
+
+static int __init nvmet_vhost_init(void)
+{
+ return 0;
+}
+module_init(nvmet_vhost_init);
+
+static void nvmet_vhost_exit(void)
+{
+}
+module_exit(nvmet_vhost_exit);
+
+MODULE_AUTHOR("Ming Lin <ming.l@ssi.samsung.com>");
+MODULE_LICENSE("GPL v2");
+
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 0/9] vhost-nvme: new qemu nvme backend using nvme target
From: Ming Lin @ 2015-11-20 0:20 UTC (permalink / raw)
To: linux-nvme; +Cc: Christoph Hellwig, qemu-devel, virtualization
Hi,
This is the first attempt to add a new qemu nvme backend using
in-kernel nvme target.
Most code are ported from qemu-nvme and also borrow code from
Hannes Reinecke's rts-megasas.
It's similar as vhost-scsi, but doesn't use virtio.
The advantage is guest can run unmodified NVMe driver.
So guest can be any OS that has a NVMe driver.
The goal is to get as good performance as vhost-scsi.
But for now, peformance is poor.
MMIO is the bottleneck.
One improvment could be to use google's NVMe vendor extension that
I send in another thread, aslo here:
https://git.kernel.org/cgit/linux/kernel/git/mlin/linux.git/log/?h=nvme-google-ext
Qemu side:
http://www.minggr.net/cgit/cgit.cgi/qemu/log/?h=vhost-nvme.0
Kernel side also here:
https://git.kernel.org/cgit/linux/kernel/git/mlin/linux.git/log/?h=vhost-nvme.0
Thanks for any comment,
Ming
^ permalink raw reply
* Re: [PATCH v3 0/3] virtio DMA API core stuff
From: David Woodhouse @ 2015-11-19 23:38 UTC (permalink / raw)
To: Andy Lutomirski, Michael S. Tsirkin
Cc: linux-s390, KVM, Benjamin Herrenschmidt, Sebastian Ott,
linux-kernel@vger.kernel.org, Linux Virtualization,
Christian Borntraeger, Joerg Roedel, Martin Schwidefsky,
Paolo Bonzini, Christoph Hellwig
In-Reply-To: <CALCETrXXsThXpbRMQ_CWTsq7_HiRFaK+dTeDYaz5cSm0QtoW_w@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 1498 bytes --]
On Thu, 2015-11-19 at 13:59 -0800, Andy Lutomirski wrote:
>
> >
> > So thinking hard about it, I don't see any real drawbacks to making this
> > conditional on a new feature bit, that Xen can then set..
>
> Can you elaborate? If I run QEMU, hosting Xen, hosting Linux, and the
> virtio device is provided by QEMU, then how does Xen set the bit?
> Similarly, how would Xen set the bit for a real physical device?
Right. This is *not* a fundamental characteristic of the device. This
is all about how your *particular* hypervisor (in the set of turtles-
all-the-way-down) happened to expose the thing to you.
This is why it lives in the DMAR table, in the Intel world, which
*tells* you which devices are behind which IOMMU (and which are not).
And why I keep repeating myself that it has nothing to do with the
actual device or the virtio drivers.
I understand that POWER and other platforms don't currently have a
clean way to indicate that certain device don't have translation. And I
understand that we may end up with a *quirk* which ensures that the DMA
API does the right thing (i.e. nothing) in certain cases.
But we should *NOT* be involving the virtio device drivers in that
quirk, in any way. And putting a feature bit in the virtio device
itself doesn't seem at all sane either.
Bear in mind that qemu-system-x86_64 currently has the *same* problem
with assigned physical devices. It's claiming they're translated, and
they're not.
--
dwmw2
[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 5691 bytes --]
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Extended deadline: November 22 --- WorldCIST'2016: 4th World Conference on Information Systems and Technologies
From: Maria Lemos @ 2015-11-19 23:27 UTC (permalink / raw)
To: virtualization
[-- Attachment #1: Type: text/plain, Size: 7126 bytes --]
---------
WorldCIST'16 - 4th World Conference on Information Systems and Technologies
Recife, PE, Brazil
22th-24th of March 2016
http://www.aisti.eu/worldcist16/
-------------------------------------------
SCOPE
The WorldCist'16 - 4th World Conference on Information Systems and Technologies ( http://www.aisti.eu/worldcist16/ ), to be held at Recife, PE, Brazil, 22 - 24 March 2016, is a global forum for researchers and practitioners to present and discuss the most recent innovations, trends, results, experiences and concerns in the several perspectives of Information Systems and Technologies.
We are pleased to invite you to submit your papers to WorldCist'16. All submissions will be reviewed on the basis of relevance, originality, importance and clarity.
THEMES
Submitted papers should be related with one or more of the main themes proposed for the Conference:
A) Information and Knowledge Management (IKM);
B) Organizational Models and Information Systems (OMIS);
C) Software and Systems Modeling (SSM);
D) Software Systems, Architectures, Applications and Tools (SSAAT);
E) Multimedia Systems and Applications (MSA);
F) Computer Networks, Mobility and Pervasive Systems (CNMPS);
G) Intelligent and Decision Support Systems (IDSS);
H) Big Data Analytics and Applications (BDAA);
I) Human-Computer Interaction (HCI);
J) Health Informatics (HIS);
K) Information Technologies in Education (ITE);
L) Information Technologies in Radiocommunications (ITR).
TYPES OF SUBMISSIONS AND DECISIONS
Four types of papers can be submitted:
- Full paper: Finished or consolidated R&D works, to be included in one of the Conference themes. These papers are assigned a 10-page limit.
- Short paper: Ongoing works with relevant preliminary results, open to discussion. These papers are assigned a 7-page limit.
-Poster paper: Initial work with relevant ideas, open to discussion. These papers are assigned to a 4-page limit.
- Company paper: Companies' papers that show practical experience, R & D, tools, etc., focused on some topics of the conference. These papers are assigned to a 4-page limit.
Submitted papers must comply with the format of Advances in Intelligent Systems and Computing Series (see Instructions for Authors at Springer Website or download a DOC example) be written in English, must not have been published before, not be under review for any other conference or publication and not include any information leading to the authors identification. Therefore, the authors names, affiliations and bibliographic references should not be included in the version for evaluation by the Program Committee. This information should only be included in the camera-ready version, saved in Word or Latex format and also in PDF format. These files must be accompanied by the Consent to Publication form filled out, in a ZIP file, and uploaded at the conference management system.
All papers will be subjected to a double-blind review by at least two members of the Program Committee.
Based on Program Committee evaluation, a paper can be rejected or accepted by the Conference Chairs. In the later case, it can be accepted as the type originally submitted or as another type. Thus, full papers can be accepted as short papers or poster papers only. Similarly, short papers can be accepted as poster papers only. In these cases, the authors will be allowed to maintain the original number of pages in the camera-ready version.
The authors of accepted poster papers must also build and print a poster to be exhibited during the Conference. This poster must follow an A1 or A2 vertical format. The Conference can includes Work Sessions where these posters are presented and orally discussed, with a 5 minute limit per poster.
The authors of accepted full papers will have 15 minutes to present their work in a Conference Work Session; approximately 5 minutes of discussion will follow each presentation. The authors of accepted short papers and company papers will have 11 minutes to present their work in a Conference Work Session; approximately 4 minutes of discussion will follow each presentation.
PUBLICATION AND INDEXING
To ensure that a full paper, short paper, poster paper or company paper is published in the Proceedings, at least one of the authors must be fully registered by the 27th of December 2015, and the paper must comply with the suggested layout and page-limit. Additionally, all recommended changes must be addressed by the authors before they submit the camera-ready version.
No more than one paper per registration will be published in the Conference Proceedings. An extra fee must be paid for publication of additional papers, with a maximum of one additional paper per registration.
Full and short papers will be published in Proceedings by Springer, in a book of Advances in Intelligent Systems and Computing series. Poster and company papers will be published by AISTI.
Published full and short papers will be submitted for indexation by ISI, EI-Compendex, SCOPUS and DBLP, among others, and will be available in the SpringerLink Digital Library.
The authors of the best selected papers will be invited to extend them for publication in international journals indexed by ISI/SCI, SCOPUS and DBLP, among others, such as:
- International Journal of Neural Systems (IF: 6.507)
- Integrated Computer-Aided Engineering (IF: 4.698)
- Computers in Human Behavior (IF: 2.694)
- Journal of Medical Systems (IF: 2.213)
- International Journal of Computer-Supported Collaborative Learning (IF: 1.841)
- Journal of Intelligent & Fuzzy Systems (IF: 1.812)
- Telemedicine and e-Health (IF: 1.668)
- International Journal of Information Management (IF: 1.550)
- Engineering Computations (IF: 1.495)
- Electronic Commerce Research and Applications (IF: 1.482)
- Telematics and Informatics (IF: 1.120)
- Journal of Evaluation in Clinical Practice (IF: 1.084)
- Ethics and Information Technology (IF: 1.021)
- Int. Journal of Computers Communications & Control (IF: 0.746)
- IET Software (IF: 0.595)
- Knowledge Management Research & Practice (IF: 0.554)
- AI Communications (IF: 0.547)
- Computing and Informatics (IF: 0.504)
- Universal Access in the Information Society (IF: 0.475)
- Journal of Global Information Management (IF: 0.424)
- Journal of Internet Services and Applications (SJR: 0.88)
- Journal of Hospitality and Tourism Technology (SJR: 0.41)
- VINE - The Journal of Information and Knowledge Management Systems (SJR: 0.24)
- International Journal of Online Engineering (SJR: 0.21)
- Int. Journal of Emerging Technologies in Learning (SJR: 0.12)
- Computer Methods in Biomechanics and Biomedical Engineering: Imaging & Visualization
IMPORTANT DATES
Paper Submission: November 27, 2015
Notification of Acceptance: December 13, 2015
Payment of Registration, to ensure the inclusion of an accepted paper in the conference proceedings: December 27, 2015.
Camera-ready Submission: December 31, 2015
-
WorldCIST'16
http://www.aisti.eu/worldcist16/
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH v2 0/3] Fix and cleanup for 32-bit PV sysexit
From: Borislav Petkov @ 2015-11-19 23:02 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: konrad.wilk, linux-kernel, virtualization, mingo, david.vrabel,
luto, hpa, xen-devel, tglx
In-Reply-To: <1447970147-1733-1-git-send-email-boris.ostrovsky@oracle.com>
On Thu, Nov 19, 2015 at 04:55:44PM -0500, Boris Ostrovsky wrote:
> The first patch fixes Xen PV regression introduced by 32-bit rewrite. Unlike the
> earlier version it uses ALTERNATIVE instruction and avoids using xen_sysexit
> (and sysret32 in compat mode) pv ops, as suggested by Andy.
>
> As result of this patch irq_enable_sysexit and usergs_sysret32 pv ops are not
> used anymore by anyone and so can be removed.
>
>
> v2:
> * patch both TEST and JZ intructions with a single JMP
> * Add magic prefix to X86_FEATURE_XENPV comment to avoid having it printed in
> /proc/cpuinfo
> * Clarify in commit messages why irq_enable_sysexit and usergs_sysret32 are
> removed
>
>
> Boris Ostrovsky (3):
> x86/xen: Avoid fast syscall path for Xen PV guests
> x86: irq_enable_sysexit pv op is no longer needed
> x86: usergs_sysret32 pv op is no longer needed
>
> arch/x86/entry/entry_32.S | 13 +++++--------
> arch/x86/entry/entry_64_compat.S | 20 ++++++++------------
> arch/x86/include/asm/cpufeature.h | 1 +
> arch/x86/include/asm/paravirt.h | 12 ------------
> arch/x86/include/asm/paravirt_types.h | 17 -----------------
> arch/x86/kernel/asm-offsets.c | 3 ---
> arch/x86/kernel/asm-offsets_64.c | 1 -
> arch/x86/kernel/paravirt.c | 12 ------------
> arch/x86/kernel/paravirt_patch_32.c | 2 --
> arch/x86/kernel/paravirt_patch_64.c | 3 ---
> arch/x86/xen/enlighten.c | 7 +++----
> arch/x86/xen/xen-asm_32.S | 14 --------------
> arch/x86/xen/xen-asm_64.S | 19 -------------------
> arch/x86/xen/xen-ops.h | 3 ---
> 14 files changed, 17 insertions(+), 110 deletions(-)
All three look good to me.
Reviewed-by: Borislav Petkov <bp@suse.de>
--
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH v2 0/3] Fix and cleanup for 32-bit PV sysexit
From: Andy Lutomirski @ 2015-11-19 22:07 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: Konrad Rzeszutek Wilk, linux-kernel@vger.kernel.org,
Linux Virtualization, Ingo Molnar, David Vrabel,
Andrew Lutomirski, H. Peter Anvin, xen-devel@lists.xenproject.org,
Thomas Gleixner, Borislav Petkov
In-Reply-To: <1447970147-1733-1-git-send-email-boris.ostrovsky@oracle.com>
On Thu, Nov 19, 2015 at 1:55 PM, Boris Ostrovsky
<boris.ostrovsky@oracle.com> wrote:
> The first patch fixes Xen PV regression introduced by 32-bit rewrite. Unlike the
> earlier version it uses ALTERNATIVE instruction and avoids using xen_sysexit
> (and sysret32 in compat mode) pv ops, as suggested by Andy.
>
> As result of this patch irq_enable_sysexit and usergs_sysret32 pv ops are not
> used anymore by anyone and so can be removed.
This whole series is:
Acked-by: Andy Lutomirski <luto@kernel.org>
Now I just have to sucker someone into getting rid of
PARAVIRT_ADJUST_EXCEPTION_FRAME (by using stub entries) and the
overcomplicated syscall entry stuff. :) And whoever gets rid of
PARAVIRT_ADJUST_EXCEPTION_FRAME gets to wonder why it doesn't crash
and burn for NMIs on Xen, since I'm reasonably confident that it can't
possibly be correct.
--Andy
^ permalink raw reply
* Re: [PATCH v3 0/3] virtio DMA API core stuff
From: Andy Lutomirski @ 2015-11-19 21:59 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: linux-s390, KVM, Benjamin Herrenschmidt, Sebastian Ott,
linux-kernel@vger.kernel.org, Linux Virtualization,
Christian Borntraeger, Joerg Roedel, Martin Schwidefsky,
Paolo Bonzini, David Woodhouse, Christoph Hellwig
In-Reply-To: <20151119153821-mutt-send-email-mst@redhat.com>
On Nov 19, 2015 5:45 AM, "Michael S. Tsirkin" <mst@redhat.com> wrote:
>
> On Tue, Oct 27, 2015 at 11:38:57PM -0700, Andy Lutomirski wrote:
> > This switches virtio to use the DMA API unconditionally. I'm sure
> > it breaks things, but it seems to work on x86 using virtio-pci, with
> > and without Xen, and using both the modern 1.0 variant and the
> > legacy variant.
>
> So thinking hard about it, I don't see any real drawbacks to making this
> conditional on a new feature bit, that Xen can then set..
Can you elaborate? If I run QEMU, hosting Xen, hosting Linux, and the
virtio device is provided by QEMU, then how does Xen set the bit?
Similarly, how would Xen set the bit for a real physical device?
--Andy
^ permalink raw reply
* [PATCH v2 3/3] x86: usergs_sysret32 pv op is no longer needed
From: Boris Ostrovsky @ 2015-11-19 21:55 UTC (permalink / raw)
To: tglx, mingo, hpa, david.vrabel, konrad.wilk
Cc: linux-kernel, virtualization, luto, xen-devel, Boris Ostrovsky,
bp
In-Reply-To: <1447970147-1733-1-git-send-email-boris.ostrovsky@oracle.com>
As result of commit "x86/xen: Avoid fast syscall path for Xen PV guests"
usergs_sysret32 pv op is not called by Xen PV guests anymore and
since they were the only ones who used it we can safely remove it.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
arch/x86/entry/entry_64_compat.S | 10 ++--------
arch/x86/include/asm/paravirt.h | 5 -----
arch/x86/include/asm/paravirt_types.h | 8 --------
arch/x86/kernel/asm-offsets_64.c | 1 -
arch/x86/kernel/paravirt.c | 5 -----
arch/x86/kernel/paravirt_patch_64.c | 2 --
arch/x86/xen/xen-asm_64.S | 19 -------------------
7 files changed, 2 insertions(+), 48 deletions(-)
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 402e34a..bbcb285 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -18,13 +18,6 @@
.section .entry.text, "ax"
-#ifdef CONFIG_PARAVIRT
-ENTRY(native_usergs_sysret32)
- swapgs
- sysretl
-ENDPROC(native_usergs_sysret32)
-#endif
-
/*
* 32-bit SYSENTER instruction entry.
*
@@ -238,7 +231,8 @@ sysret32_from_system_call:
xorq %r9, %r9
xorq %r10, %r10
movq RSP-ORIG_RAX(%rsp), %rsp
- USERGS_SYSRET32
+ swapgs
+ sysretl
END(entry_SYSCALL_compat)
/*
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index c28518e..1b71c3a 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -922,11 +922,6 @@ extern void default_banner(void);
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \
PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
-#define USERGS_SYSRET32 \
- PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \
- CLBR_NONE, \
- jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret32))
-
#ifdef CONFIG_X86_32
#define GET_CR0_INTO_EAX \
push %ecx; push %edx; \
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 608bbf3..702c8bd 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -165,14 +165,6 @@ struct pv_cpu_ops {
*/
void (*usergs_sysret64)(void);
- /*
- * Switch to usermode gs and return to 32-bit usermode using
- * sysret. Used to return to 32-on-64 compat processes.
- * Other usermode register state, including %esp, must already
- * be restored.
- */
- void (*usergs_sysret32)(void);
-
/* Normal iret. Jump to this with the standard iret stack
frame set up. */
void (*iret)(void);
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index d8f42f9..f2edafb 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -23,7 +23,6 @@ int main(void)
{
#ifdef CONFIG_PARAVIRT
OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame);
- OFFSET(PV_CPU_usergs_sysret32, pv_cpu_ops, usergs_sysret32);
OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64);
OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
BLANK();
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index c55f437..8c19b4d 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -162,7 +162,6 @@ unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
ret = paravirt_patch_ident_64(insnbuf, len);
else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
- type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
/* If operation requires a jmp, then jmp */
ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
@@ -217,7 +216,6 @@ static u64 native_steal_clock(int cpu)
/* These are in entry.S */
extern void native_iret(void);
-extern void native_usergs_sysret32(void);
extern void native_usergs_sysret64(void);
static struct resource reserve_ioports = {
@@ -376,9 +374,6 @@ __visible struct pv_cpu_ops pv_cpu_ops = {
.load_sp0 = native_load_sp0,
#ifdef CONFIG_X86_64
-#ifdef CONFIG_IA32_EMULATION
- .usergs_sysret32 = native_usergs_sysret32,
-#endif
.usergs_sysret64 = native_usergs_sysret64,
#endif
.iret = native_iret,
diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c
index 17c00f8..e70087a 100644
--- a/arch/x86/kernel/paravirt_patch_64.c
+++ b/arch/x86/kernel/paravirt_patch_64.c
@@ -14,7 +14,6 @@ DEF_NATIVE(pv_cpu_ops, clts, "clts");
DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
-DEF_NATIVE(pv_cpu_ops, usergs_sysret32, "swapgs; sysretl");
DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs");
DEF_NATIVE(, mov32, "mov %edi, %eax");
@@ -54,7 +53,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
PATCH_SITE(pv_irq_ops, save_fl);
PATCH_SITE(pv_irq_ops, irq_enable);
PATCH_SITE(pv_irq_ops, irq_disable);
- PATCH_SITE(pv_cpu_ops, usergs_sysret32);
PATCH_SITE(pv_cpu_ops, usergs_sysret64);
PATCH_SITE(pv_cpu_ops, swapgs);
PATCH_SITE(pv_mmu_ops, read_cr2);
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
index f22667a..cc8acc4 100644
--- a/arch/x86/xen/xen-asm_64.S
+++ b/arch/x86/xen/xen-asm_64.S
@@ -68,25 +68,6 @@ ENTRY(xen_sysret64)
ENDPATCH(xen_sysret64)
RELOC(xen_sysret64, 1b+1)
-ENTRY(xen_sysret32)
- /*
- * We're already on the usermode stack at this point, but
- * still with the kernel gs, so we can easily switch back
- */
- movq %rsp, PER_CPU_VAR(rsp_scratch)
- movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
-
- pushq $__USER32_DS
- pushq PER_CPU_VAR(rsp_scratch)
- pushq %r11
- pushq $__USER32_CS
- pushq %rcx
-
- pushq $0
-1: jmp hypercall_iret
-ENDPATCH(xen_sysret32)
-RELOC(xen_sysret32, 1b+1)
-
/*
* Xen handles syscall callbacks much like ordinary exceptions, which
* means we have:
--
1.8.1.4
^ permalink raw reply related
* [PATCH v2 2/3] x86: irq_enable_sysexit pv op is no longer needed
From: Boris Ostrovsky @ 2015-11-19 21:55 UTC (permalink / raw)
To: tglx, mingo, hpa, david.vrabel, konrad.wilk
Cc: linux-kernel, virtualization, luto, xen-devel, Boris Ostrovsky,
bp
In-Reply-To: <1447970147-1733-1-git-send-email-boris.ostrovsky@oracle.com>
As result of commit "x86/xen: Avoid fast syscall path for Xen PV guests"
irq_enable_sysexit pv op is not called by Xen PV guests anymore and since
they were the only ones who used it we can safely remove it.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
arch/x86/entry/entry_32.S | 8 ++------
arch/x86/include/asm/paravirt.h | 7 -------
arch/x86/include/asm/paravirt_types.h | 9 ---------
arch/x86/kernel/asm-offsets.c | 3 ---
arch/x86/kernel/paravirt.c | 7 -------
arch/x86/kernel/paravirt_patch_32.c | 2 --
arch/x86/kernel/paravirt_patch_64.c | 1 -
arch/x86/xen/enlighten.c | 3 ---
arch/x86/xen/xen-asm_32.S | 14 --------------
arch/x86/xen/xen-ops.h | 3 ---
10 files changed, 2 insertions(+), 55 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 0870825..9870c97 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -329,7 +329,8 @@ sysenter_past_esp:
* Return back to the vDSO, which will pop ecx and edx.
* Don't bother with DS and ES (they already contain __USER_DS).
*/
- ENABLE_INTERRUPTS_SYSEXIT
+ sti
+ sysexit
.pushsection .fixup, "ax"
2: movl $0, PT_FS(%esp)
@@ -552,11 +553,6 @@ ENTRY(native_iret)
iret
_ASM_EXTABLE(native_iret, iret_exc)
END(native_iret)
-
-ENTRY(native_irq_enable_sysexit)
- sti
- sysexit
-END(native_irq_enable_sysexit)
#endif
ENTRY(overflow)
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 10d0596..c28518e 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -932,13 +932,6 @@ extern void default_banner(void);
push %ecx; push %edx; \
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
pop %edx; pop %ecx
-
-#define ENABLE_INTERRUPTS_SYSEXIT \
- PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
- CLBR_NONE, \
- jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
-
-
#else /* !CONFIG_X86_32 */
/*
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 31247b5..608bbf3 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -157,15 +157,6 @@ struct pv_cpu_ops {
u64 (*read_pmc)(int counter);
-#ifdef CONFIG_X86_32
- /*
- * Atomically enable interrupts and return to userspace. This
- * is only used in 32-bit kernels. 64-bit kernels use
- * usergs_sysret32 instead.
- */
- void (*irq_enable_sysexit)(void);
-#endif
-
/*
* Switch to usermode gs and return to 64-bit usermode using
* sysret. Only used in 64-bit kernels to return to 64-bit
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 439df97..84a7524 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -65,9 +65,6 @@ void common(void) {
OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
-#ifdef CONFIG_X86_32
- OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
-#endif
OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
#endif
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index c2130ae..c55f437 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -162,9 +162,6 @@ unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
ret = paravirt_patch_ident_64(insnbuf, len);
else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
-#ifdef CONFIG_X86_32
- type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
-#endif
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
/* If operation requires a jmp, then jmp */
@@ -220,7 +217,6 @@ static u64 native_steal_clock(int cpu)
/* These are in entry.S */
extern void native_iret(void);
-extern void native_irq_enable_sysexit(void);
extern void native_usergs_sysret32(void);
extern void native_usergs_sysret64(void);
@@ -379,9 +375,6 @@ __visible struct pv_cpu_ops pv_cpu_ops = {
.load_sp0 = native_load_sp0,
-#if defined(CONFIG_X86_32)
- .irq_enable_sysexit = native_irq_enable_sysexit,
-#endif
#ifdef CONFIG_X86_64
#ifdef CONFIG_IA32_EMULATION
.usergs_sysret32 = native_usergs_sysret32,
diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c
index c89f50a..158dc06 100644
--- a/arch/x86/kernel/paravirt_patch_32.c
+++ b/arch/x86/kernel/paravirt_patch_32.c
@@ -5,7 +5,6 @@ DEF_NATIVE(pv_irq_ops, irq_enable, "sti");
DEF_NATIVE(pv_irq_ops, restore_fl, "push %eax; popf");
DEF_NATIVE(pv_irq_ops, save_fl, "pushf; pop %eax");
DEF_NATIVE(pv_cpu_ops, iret, "iret");
-DEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "sti; sysexit");
DEF_NATIVE(pv_mmu_ops, read_cr2, "mov %cr2, %eax");
DEF_NATIVE(pv_mmu_ops, write_cr3, "mov %eax, %cr3");
DEF_NATIVE(pv_mmu_ops, read_cr3, "mov %cr3, %eax");
@@ -46,7 +45,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
PATCH_SITE(pv_irq_ops, restore_fl);
PATCH_SITE(pv_irq_ops, save_fl);
PATCH_SITE(pv_cpu_ops, iret);
- PATCH_SITE(pv_cpu_ops, irq_enable_sysexit);
PATCH_SITE(pv_mmu_ops, read_cr2);
PATCH_SITE(pv_mmu_ops, read_cr3);
PATCH_SITE(pv_mmu_ops, write_cr3);
diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c
index 8aa0558..17c00f8 100644
--- a/arch/x86/kernel/paravirt_patch_64.c
+++ b/arch/x86/kernel/paravirt_patch_64.c
@@ -13,7 +13,6 @@ DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
DEF_NATIVE(pv_cpu_ops, clts, "clts");
DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
-DEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "swapgs; sti; sysexit");
DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
DEF_NATIVE(pv_cpu_ops, usergs_sysret32, "swapgs; sysretl");
DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs");
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index d315151..a068e36 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1229,10 +1229,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
.iret = xen_iret,
#ifdef CONFIG_X86_64
- .usergs_sysret32 = xen_sysret32,
.usergs_sysret64 = xen_sysret64,
-#else
- .irq_enable_sysexit = xen_sysexit,
#endif
.load_tr_desc = paravirt_nop,
diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S
index fd92a64..feb6d40 100644
--- a/arch/x86/xen/xen-asm_32.S
+++ b/arch/x86/xen/xen-asm_32.S
@@ -35,20 +35,6 @@ check_events:
ret
/*
- * We can't use sysexit directly, because we're not running in ring0.
- * But we can easily fake it up using iret. Assuming xen_sysexit is
- * jumped to with a standard stack frame, we can just strip it back to
- * a standard iret frame and use iret.
- */
-ENTRY(xen_sysexit)
- movl PT_EAX(%esp), %eax /* Shouldn't be necessary? */
- orl $X86_EFLAGS_IF, PT_EFLAGS(%esp)
- lea PT_EIP(%esp), %esp
-
- jmp xen_iret
-ENDPROC(xen_sysexit)
-
-/*
* This is run where a normal iret would be run, with the same stack setup:
* 8: eflags
* 4: cs
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 1399423..4140b07 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -139,9 +139,6 @@ DECL_ASM(void, xen_restore_fl_direct, unsigned long);
/* These are not functions, and cannot be called normally */
__visible void xen_iret(void);
-#ifdef CONFIG_X86_32
-__visible void xen_sysexit(void);
-#endif
__visible void xen_sysret32(void);
__visible void xen_sysret64(void);
__visible void xen_adjust_exception_frame(void);
--
1.8.1.4
^ permalink raw reply related
* [PATCH v2 1/3] x86/xen: Avoid fast syscall path for Xen PV guests
From: Boris Ostrovsky @ 2015-11-19 21:55 UTC (permalink / raw)
To: tglx, mingo, hpa, david.vrabel, konrad.wilk
Cc: linux-kernel, virtualization, luto, xen-devel, Boris Ostrovsky,
bp
In-Reply-To: <1447970147-1733-1-git-send-email-boris.ostrovsky@oracle.com>
After 32-bit syscall rewrite, and specifically after commit 5f310f739b4c
("x86/entry/32: Re-implement SYSENTER using the new C path"), the stack
frame that is passed to xen_sysexit is no longer a "standard" one (i.e.
it's not pt_regs).
Since we end up calling xen_iret from xen_sysexit we don't need to fix
up the stack and instead follow entry_SYSENTER_32's IRET path directly
to xen_iret.
We can do the same thing for compat mode even though stack does not need
to be fixed. This will allow us to drop usergs_sysret32 paravirt op (in
the subsequent patch)
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Suggested-by: Andy Lutomirski <luto@amacapital.net>
---
arch/x86/entry/entry_32.S | 5 +++--
arch/x86/entry/entry_64_compat.S | 10 ++++++----
arch/x86/include/asm/cpufeature.h | 1 +
arch/x86/xen/enlighten.c | 4 +++-
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 3eb572e..0870825 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -308,8 +308,9 @@ sysenter_past_esp:
movl %esp, %eax
call do_fast_syscall_32
- testl %eax, %eax
- jz .Lsyscall_32_done
+ /* XEN PV guests always use IRET path */
+ ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
+ "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
/* Opportunistic SYSEXIT */
TRACE_IRQS_ON /* User mode traces as IRQs on. */
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index c320183..402e34a 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -121,8 +121,9 @@ sysenter_flags_fixed:
movq %rsp, %rdi
call do_fast_syscall_32
- testl %eax, %eax
- jz .Lsyscall_32_done
+ /* XEN PV guests always use IRET path */
+ ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
+ "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
jmp sysret32_from_system_call
sysenter_fix_flags:
@@ -200,8 +201,9 @@ ENTRY(entry_SYSCALL_compat)
movq %rsp, %rdi
call do_fast_syscall_32
- testl %eax, %eax
- jz .Lsyscall_32_done
+ /* XEN PV guests always use IRET path */
+ ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
+ "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
/* Opportunistic SYSRET */
sysret32_from_system_call:
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index e4f8010..f7ba9fb 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -216,6 +216,7 @@
#define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */
#define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */
#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */
+#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 5774800..d315151 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1886,8 +1886,10 @@ EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
static void xen_set_cpu_features(struct cpuinfo_x86 *c)
{
- if (xen_pv_domain())
+ if (xen_pv_domain()) {
clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+ set_cpu_cap(c, X86_FEATURE_XENPV);
+ }
}
const struct hypervisor_x86 x86_hyper_xen = {
--
1.8.1.4
^ permalink raw reply related
* [PATCH v2 0/3] Fix and cleanup for 32-bit PV sysexit
From: Boris Ostrovsky @ 2015-11-19 21:55 UTC (permalink / raw)
To: tglx, mingo, hpa, david.vrabel, konrad.wilk
Cc: linux-kernel, virtualization, luto, xen-devel, Boris Ostrovsky,
bp
The first patch fixes Xen PV regression introduced by 32-bit rewrite. Unlike the
earlier version it uses ALTERNATIVE instruction and avoids using xen_sysexit
(and sysret32 in compat mode) pv ops, as suggested by Andy.
As result of this patch irq_enable_sysexit and usergs_sysret32 pv ops are not
used anymore by anyone and so can be removed.
v2:
* patch both TEST and JZ intructions with a single JMP
* Add magic prefix to X86_FEATURE_XENPV comment to avoid having it printed in
/proc/cpuinfo
* Clarify in commit messages why irq_enable_sysexit and usergs_sysret32 are
removed
Boris Ostrovsky (3):
x86/xen: Avoid fast syscall path for Xen PV guests
x86: irq_enable_sysexit pv op is no longer needed
x86: usergs_sysret32 pv op is no longer needed
arch/x86/entry/entry_32.S | 13 +++++--------
arch/x86/entry/entry_64_compat.S | 20 ++++++++------------
arch/x86/include/asm/cpufeature.h | 1 +
arch/x86/include/asm/paravirt.h | 12 ------------
arch/x86/include/asm/paravirt_types.h | 17 -----------------
arch/x86/kernel/asm-offsets.c | 3 ---
arch/x86/kernel/asm-offsets_64.c | 1 -
arch/x86/kernel/paravirt.c | 12 ------------
arch/x86/kernel/paravirt_patch_32.c | 2 --
arch/x86/kernel/paravirt_patch_64.c | 3 ---
arch/x86/xen/enlighten.c | 7 +++----
arch/x86/xen/xen-asm_32.S | 14 --------------
arch/x86/xen/xen-asm_64.S | 19 -------------------
arch/x86/xen/xen-ops.h | 3 ---
14 files changed, 17 insertions(+), 110 deletions(-)
--
1.8.1.4
^ permalink raw reply
* Re: [PATCH] virtio_ring: Shadow available ring flags & index
From: Xie, Huawei @ 2015-11-19 16:15 UTC (permalink / raw)
To: Venkatesh Srinivas
Cc: KVM list, Michael S. Tsirkin,
virtualization@lists.linux-foundation.org, Venkatesh Srinivas,
luto@kernel.org, David Matlack, Paolo Bonzini
In-Reply-To: <20151118042839.GA24662@google.com>
On 11/18/2015 12:28 PM, Venkatesh Srinivas wrote:
> On Tue, Nov 17, 2015 at 08:08:18PM -0800, Venkatesh Srinivas wrote:
>> On Mon, Nov 16, 2015 at 7:46 PM, Xie, Huawei <huawei.xie@intel.com> wrote:
>>
>>> On 11/14/2015 7:41 AM, Venkatesh Srinivas wrote:
>>>> On Wed, Nov 11, 2015 at 02:34:33PM +0200, Michael S. Tsirkin wrote:
>>>>> On Tue, Nov 10, 2015 at 04:21:07PM -0800, Venkatesh Srinivas wrote:
>>>>>> Improves cacheline transfer flow of available ring header.
>>>>>>
>>>>>> Virtqueues are implemented as a pair of rings, one producer->consumer
>>>>>> avail ring and one consumer->producer used ring; preceding the
>>>>>> avail ring in memory are two contiguous u16 fields -- avail->flags
>>>>>> and avail->idx. A producer posts work by writing to avail->idx and
>>>>>> a consumer reads avail->idx.
>>>>>>
>>>>>> The flags and idx fields only need to be written by a producer CPU
>>>>>> and only read by a consumer CPU; when the producer and consumer are
>>>>>> running on different CPUs and the virtio_ring code is structured to
>>>>>> only have source writes/sink reads, we can continuously transfer the
>>>>>> avail header cacheline between 'M' states between cores. This flow
>>>>>> optimizes core -> core bandwidth on certain CPUs.
>>>>>>
>>>>>> (see: "Software Optimization Guide for AMD Family 15h Processors",
>>>>>> Section 11.6; similar language appears in the 10h guide and should
>>>>>> apply to CPUs w/ exclusive caches, using LLC as a transfer cache)
>>>>>>
>>>>>> Unfortunately the existing virtio_ring code issued reads to the
>>>>>> avail->idx and read-modify-writes to avail->flags on the producer.
>>>>>>
>>>>>> This change shadows the flags and index fields in producer memory;
>>>>>> the vring code now reads from the shadows and only ever writes to
>>>>>> avail->flags and avail->idx, allowing the cacheline to transfer
>>>>>> core -> core optimally.
>>>>> Sounds logical, I'll apply this after a bit of testing
>>>>> of my own, thanks!
>>>> Thanks!
>>> Venkatesh:
>>> Is it that your patch only applies to CPUs w/ exclusive caches?
>> No --- it applies when the inter-cache coherence flow is optimized by
>> 'M' -> 'M' transfers and when producer reads might interfere w/
>> consumer prefetchw/reads. The AMD Optimization guides have specific
>> language on this subject, but other platforms may benefit.
>> (see Intel #'s below)
For core2core case(not HT paire), after consumer reads that M cache line
for avail_idx, is that line still in the producer core's L1 data cache
with state changing from M->O state?
>>
>>> Do you have perf data on Intel CPUs?
>> Good idea -- I ran some tests on a couple of Intel platforms:
>>
>> (these are perf data from sample runs; for each I ran many runs, the
>> numbers were pretty stable except for Haswell-EP cross-socket)
>>
>> One-socket Intel Xeon W3690 ("Westmere"), 3.46 GHz; core turbo disabled
>> =======================================================================
>> (note -- w/ core turbo disabled, performance is _very_ stable; variance of
>> < 0.5% run-to-run; figure of merit is "seconds elapsed" here)
>>
>> * Producer / consumer bound to Hyperthread pairs:
>>
>> Performance counter stats for './vring_bench_noshadow 1000000000':
>>
>> 343,425,166,916 L1-dcache-loads
>> 21,393,148 L1-dcache-load-misses # 0.01% of all L1-dcache hits
>> 61,709,640,363 L1-dcache-stores
>> 5,745,690 L1-dcache-store-misses
>> 10,186,932,553 L1-dcache-prefetches
>> 1,491 L1-dcache-prefetch-misses
>> 121.335699344 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 1000000000':
>>
>> 334,766,413,861 L1-dcache-loads
>> 15,787,778 L1-dcache-load-misses # 0.00% of all L1-dcache hits
>> 62,735,792,799 L1-dcache-stores
>> 3,252,113 L1-dcache-store-misses
>> 9,018,273,596 L1-dcache-prefetches
>> 819 L1-dcache-prefetch-misses
>> 121.206339656 seconds time elapsed
>>
>> Effectively Performance-neutral.
>>
>> * Producer / consumer bound to separate cores, same socket:
>>
>> Performance counter stats for './vring_bench_noshadow 1000000000':
>>
>> 399,943,384,509 L1-dcache-loads
>> 8,868,334,693 L1-dcache-load-misses # 2.22% of all L1-dcache hits
>> 62,721,376,685 L1-dcache-stores
>> 2,786,806,982 L1-dcache-store-misses
>> 10,915,046,967 L1-dcache-prefetches
>> 328,508 L1-dcache-prefetch-misses
>> 146.585969976 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 1000000000':
>>
>> 425,123,067,750 L1-dcache-loads
>> 6,689,318,709 L1-dcache-load-misses # 1.57% of all L1-dcache hits
>> 62,747,525,005 L1-dcache-stores
>> 2,496,274,505 L1-dcache-store-misses
>> 8,627,873,397 L1-dcache-prefetches
>> 146,729 L1-dcache-prefetch-misses
>> 142.657327765 seconds time elapsed
>>
>> 2.6% reduction in runtime; note that L1-dcache-load-misses reduced
>> dramatically, 2 Billion(!) L1d misses saved.
>>
>> Two-socket Intel Sandy Bridge(-EP) Xeon, 2.6 GHz; core turbo disabled
>> =====================================================================
>>
>> * Producer / consumer bound to Hyperthread pairs:
>>
>> Performance counter stats for './vring_bench_noshadow 100000000':
>>
>> 37,129,070,402 L1-dcache-loads
>> 6,416,246 L1-dcache-load-misses # 0.02% of all L1-dcache hits
>> 6,207,794,675 L1-dcache-stores
>> 2,800,094 L1-dcache-store-misses
>> 17.029790809 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 100000000':
>>
>> 36,799,559,391 L1-dcache-loads
>> 10,241,080 L1-dcache-load-misses # 0.03% of all L1-dcache hits
>> 6,312,252,458 L1-dcache-stores
>> 2,742,239 L1-dcache-store-misses
>> 16.941001709 seconds time elapsed
>>
>> Effectively Performance-neutral.
>>
>> * Producer / consumer bound to separate cores, same socket:
>>
>> Performance counter stats for './vring_bench_noshadow 100000000':
>>
>> 27,684,883,046 L1-dcache-loads
>> 809,933,091 L1-dcache-load-misses # 2.93% of all L1-dcache hits
>> 6,219,598,352 L1-dcache-stores
>> 1,758,503 L1-dcache-store-misses
>> 15.020511218 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 100000000':
>>
>> 28,092,111,012 L1-dcache-loads
>> 716,687,011 L1-dcache-load-misses # 2.55% of all L1-dcache hits
>> 6,290,821,211 L1-dcache-stores
>> 1,565,583 L1-dcache-store-misses
>> 15.208420297 seconds time elapsed
>>
>> Effectively Performance-neutral.
>>
>> * Producer / consumer bound to separate cores, cross socket:
>> (Sandy Bridge-EP appears to have less cross-socket variance than Haswell-EP)
>>
>> Performance counter stats for './vring_bench_noshadow 100000000':
>>
>> 35,857,245,449 L1-dcache-loads
>> 821,746,755 L1-dcache-load-misses # 2.29% of all L1-dcache hits
>> 6,252,551,550 L1-dcache-stores
>> 4,665,405 L1-dcache-store-misses
>> 46.340035651 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 100000000':
>>
>> 39,044,022,857 L1-dcache-loads
>> 711,731,527 L1-dcache-load-misses # 1.82% of all L1-dcache hits
>> 6,349,051,557 L1-dcache-stores
>> 4,292,362 L1-dcache-store-misses
>> 42.593259436 seconds time elapsed
>>
>> Runtimes for the cross-socket test have somewhat higher variance, but the
>> pattern in counts of L1-dcache-loads and L1-dcache-load-misses for nonshadow
>> vs. shadow code is very stable.
>>
>> noshadow (w/o this patch) reliably clocks in at ~46 seconds, shadow ranges
>> from ~48 to ~42 (-2.8% to +8.0%).
>>
>> Two-socket Intel Haswell(-EP) Xeon, 2.3 GHz; core turbo disabled
>> ================================================================
>>
>> * Producer / consumer bound to Hyperthread pairs:
>>
>> Performance counter stats for './vring_bench_noshadow 10000000000':
>>
>> 474,856,463,271 L1-dcache-loads
>> 74,223,784 L1-dcache-load-misses # 0.02% of all L1-dcache hits
>> 87,274,898,671 L1-dcache-stores
>> 31,869,448 L1-dcache-store-misses
>> 243.290969318 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 10000000000':
>>
>> 466,891,993,302 L1-dcache-loads
>> 80,859,208 L1-dcache-load-misses # 0.02% of all L1-dcache hits
>> 88,760,627,355 L1-dcache-stores
>> 35,727,720 L1-dcache-store-misses
>> 242.146970822 seconds time elapsed
>>
>> Effectively Performance-neutral.
>>
>> * Producer / consumer bound to separate cores, same socket:
>>
>> Performance counter stats for './vring_bench_noshadow 10000000000':
>>
>> 357,657,891,797 L1-dcache-loads
>> 8,760,549,978 L1-dcache-load-misses # 2.45% of all L1-dcache hits
>> 87,357,651,103 L1-dcache-stores
>> 10,166,431 L1-dcache-store-misses
>> 229.733047436 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow 10000000000':
>>
>> 382,508,881,516 L1-dcache-loads
>> 8,348,013,630 L1-dcache-load-misses # 2.18% of all L1-dcache hits
>> 88,756,639,931 L1-dcache-stores
>> 9,842,999 L1-dcache-store-misses
>> 230.850697668 seconds time elapsed
>>
>> Effectively Performance-neutral.
>>
>> * Producer / consumer bound to separate cores, different sockets:
>>
>> Unfortunately I don't have useful numbers for this case -- even with
>> core turbo disabled, runtime variance is very high (10 - 30% run-to-run).
>>
>>> For the perf metric you provide, why not L1-dcache-load-misses which is
>>> more meaning full?
>> L1-dcache-load-misses is a better metric, you're right; for the original
>> AMD Piledriver run I posted:
>>
>> Performance counter stats for './vring_bench_noshadow':
>> 5,451,082,016 L1-dcache-loads
>> 31,690,398 L1-dcache-load-misses
>> 60,288,052 L1-dcache-stores
>> 60,517,840 LLC-loads
>> 9,726 LLC-load-misses
>> 2.221477739 seconds time elapsed
>>
>> Performance counter stats for './vring_bench_shadow':
>> 5,405,701,361 L1-dcache-loads
>> 31,157,235 L1-dcache-load-misses
>> 59,172,380 L1-dcache-stores
>> 59,398,269 LLC-loads
>> 10,944 LLC-load-misses
>> 2.168405376 seconds time elapsed
>>
>> There is a 1.6% reduction in L1-dcache-load-misses, which lines up with
>> about a 2% reduction in runtime.
>>
>> Summary:
>> * No workload on Westmere 1S, Sandy Bridge 2S, and Haswell 2S got worse;
>> * Westmere 1S cross-core improved by ~2.5% reliably;
>> * Sandy Bridge 2S cross-core cross-socket may have improved. (cross-socket
>> run variance makes it hard to tell)
>> * AMD Piledriver tests improved by ~2%;
>> * Other virtio implementations (over PCIe for example) should benefit;
>>
>> HTH,
>> -- vs;
> I'm sorry -- I appear to have added an unintentional HTML draft part to my
> reply. This would prevent the message from appearing on the kvm@ mailing list
> at the minimum.
>
> Re-posting with the HTML part scrubbed.
>
> Sorry,
> -- vs;
>
^ permalink raw reply
* Re: [RFC] kvmtool: add support for modern virtio-pci
From: Gerd Hoffmann @ 2015-11-19 14:55 UTC (permalink / raw)
To: Sasha Levin
Cc: kvm, mst, andre.przywara, will.deacon, josh, virtualization,
penberg
In-Reply-To: <564DD178.9010904@oracle.com>
Hi,
> That was indeed the ISR field. Fixing that makes seabios reach the same point as
> legacy virtio before failing.
>
> I don't see the original correspondence about seabios failures you've reported, if
> you want to forward them over we can look at it further.
It was a few months back, when I posted the seabios patches for kvmtool
to both seabios and kvm lists.
Issue #1 is that kvmtool adds a bunch of kernel command line options,
not only for stuff like rootfs configuration, but also to force specific
things the kernel fails to autodetect (or to speedup boot by
shortcutting hardware probing). Among them is "pci=conf1", without that
the kernel doesn't find a pci bus and therefore also doesn't find the
virtio-{blk,net} devices.
So, when booting with seabios and let grub or another boot loader load
the kernel from the guest disk image those kernel arguments are not
there. Of course you can boot the image with qemu, add "pci=conf1" to
grub.cfg (maybe others are required too, don't remember exactly), then
try again with kvmtool. That gets the boot one step further and leads
to ...
Issue #2: virtio kernel drivers fail initialize the virtio devices.
I suspect virtio device reset is not implemented properly and because of
that the state of the device as left by seabios confuses the kernel
driver. Didn't check that in detail though.
cheers,
Gerd
^ permalink raw reply
* Re: [PATCH v3 0/3] virtio DMA API core stuff
From: Michael S. Tsirkin @ 2015-11-19 13:45 UTC (permalink / raw)
To: Andy Lutomirski
Cc: linux-s390, Joerg Roedel, KVM, benh, Sebastian Ott, linux-kernel,
virtualization, Christian Borntraeger, Paolo Bonzini, dwmw2,
Christoph Hellwig, Martin Schwidefsky
In-Reply-To: <cover.1446014204.git.luto@kernel.org>
On Tue, Oct 27, 2015 at 11:38:57PM -0700, Andy Lutomirski wrote:
> This switches virtio to use the DMA API unconditionally. I'm sure
> it breaks things, but it seems to work on x86 using virtio-pci, with
> and without Xen, and using both the modern 1.0 variant and the
> legacy variant.
So thinking hard about it, I don't see any real drawbacks to making this
conditional on a new feature bit, that Xen can then set.
As a bonus, host can distinguish between old and new guests using the
feature bit, even though making driver *control* whether IOMMU is
bypassed makes userspace drivers unsafe, so might not be a good idea.
A tiny bit more code but not by much, and we clearly won't
be breaking anything that's not already broken,
and we will be able to drop the extra code later
if we think it's a good idea.
I'll run this by the virtio TC on OASIS next week so we
can reserve a feature bit.
> Changes from v2:
> - Fix really embarrassing bug. This version actually works.
>
> Changes from v1:
> - Fix an endian conversion error causing a BUG to hit.
> - Fix a DMA ordering issue (swiotlb=force works now).
> - Minor cleanups.
>
> Andy Lutomirski (3):
> virtio_net: Stop doing DMA from the stack
> virtio_ring: Support DMA APIs
> virtio_pci: Use the DMA API
>
> drivers/net/virtio_net.c | 53 +++++++----
> drivers/virtio/Kconfig | 2 +-
> drivers/virtio/virtio_pci_common.h | 3 +-
> drivers/virtio/virtio_pci_legacy.c | 19 +++-
> drivers/virtio/virtio_pci_modern.c | 34 +++++--
> drivers/virtio/virtio_ring.c | 187 ++++++++++++++++++++++++++++++-------
> tools/virtio/linux/dma-mapping.h | 17 ++++
> 7 files changed, 246 insertions(+), 69 deletions(-)
> create mode 100644 tools/virtio/linux/dma-mapping.h
>
> --
> 2.4.3
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox