public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <levinsasha928@gmail.com>
To: penberg@kernel.org
Cc: mingo@elte.hu, asias.hejun@gmail.com, prasadjoshi124@gmail.com,
	gorcunov@gmail.com, kvm@vger.kernel.org, john@jfloren.net,
	Sasha Levin <levinsasha928@gmail.com>
Subject: [PATCH 2/2 V2] kvm tools: Add MMIO address mapper
Date: Tue, 17 May 2011 13:28:43 +0300	[thread overview]
Message-ID: <1305628123-18440-2-git-send-email-levinsasha928@gmail.com> (raw)
In-Reply-To: <1305628123-18440-1-git-send-email-levinsasha928@gmail.com>

When we have a MMIO exit, we need to find which device
has registered to use the accessed MMIO space.

The mapper maps ranges of guest physical addresses to
callback functions.

Implementation is based on an interval red-black tree.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/include/kvm/kvm.h |    2 +
 tools/kvm/mmio.c            |   79 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index b310d50..d9943bf 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -44,6 +44,8 @@ void kvm__stop_timer(struct kvm *kvm);
 void kvm__irq_line(struct kvm *kvm, int irq, int level);
 bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+bool kvm__register_mmio(u64 phys_addr, u64 phys_addr_len, void (*kvm_mmio_callback_fn)(u64 addr, u8 *data, u32 len, u8 is_write));
+bool kvm__deregister_mmio(u64 phys_addr);
 
 /*
  * Debugging
diff --git a/tools/kvm/mmio.c b/tools/kvm/mmio.c
index 848267d..ef986bf 100644
--- a/tools/kvm/mmio.c
+++ b/tools/kvm/mmio.c
@@ -1,7 +1,48 @@
 #include "kvm/kvm.h"
+#include "kvm/rbtree-interval.h"
 
 #include <stdio.h>
+#include <stdlib.h>
+
 #include <linux/types.h>
+#include <linux/rbtree.h>
+
+#define mmio_node(n) rb_entry(n, struct mmio_mapping, node)
+
+struct mmio_mapping {
+	struct rb_int_node	node;
+	void			(*kvm_mmio_callback_fn)(u64 addr, u8 *data, u32 len, u8 is_write);
+};
+
+static struct rb_root mmio_tree = RB_ROOT;
+
+static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
+{
+	struct rb_int_node *node;
+
+	node = rb_int_search_range(root, addr, addr + len);
+	if (node == NULL)
+		return NULL;
+
+	return mmio_node(node);
+}
+
+/* Find lowest match, Check for overlap */
+static struct mmio_mapping *mmio_search_single(struct rb_root *root, u64 addr)
+{
+	struct rb_int_node *node;
+
+	node = rb_int_search_single(root, addr);
+	if (node == NULL)
+		return NULL;
+
+	return mmio_node(node);
+}
+
+static int mmio_insert(struct rb_root *root, struct mmio_mapping *data)
+{
+	return rb_int_insert(root, &data->node);
+}
 
 static const char *to_direction(u8 is_write)
 {
@@ -11,10 +52,44 @@ static const char *to_direction(u8 is_write)
 	return "read";
 }
 
+bool kvm__register_mmio(u64 phys_addr, u64 phys_addr_len, void (*kvm_mmio_callback_fn)(u64 addr, u8 *data, u32 len, u8 is_write))
+{
+	struct mmio_mapping *mmio;
+
+	mmio = malloc(sizeof(*mmio));
+	if (mmio == NULL)
+		return false;
+
+	*mmio = (struct mmio_mapping) {
+		.node = RB_INT_INIT(phys_addr, phys_addr + phys_addr_len),
+		.kvm_mmio_callback_fn = kvm_mmio_callback_fn,
+	};
+
+	return mmio_insert(&mmio_tree, mmio);
+}
+
+bool kvm__deregister_mmio(u64 phys_addr)
+{
+	struct mmio_mapping *mmio;
+
+	mmio = mmio_search_single(&mmio_tree, phys_addr);
+	if (mmio == NULL)
+		return false;
+
+	rb_int_erase(&mmio_tree, &mmio->node);
+	free(mmio);
+	return true;
+}
+
 bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
 {
-	fprintf(stderr, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
-		to_direction(is_write), phys_addr, len);
+	struct mmio_mapping *mmio = mmio_search(&mmio_tree, phys_addr, len);
+
+	if (mmio)
+		mmio->kvm_mmio_callback_fn(phys_addr, data, len, is_write);
+	else
+		fprintf(stderr, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
+			to_direction(is_write), phys_addr, len);
 
 	return true;
 }
-- 
1.7.5.rc3


  reply	other threads:[~2011-05-17 10:29 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-17 10:28 [PATCH 1/2 V2] kvm tools: Add interval red-black tree helper Sasha Levin
2011-05-17 10:28 ` Sasha Levin [this message]
2011-05-17 10:51   ` [PATCH 2/2 V2] kvm tools: Add MMIO address mapper Ingo Molnar
2011-05-17 10:50 ` [PATCH 1/2 V2] kvm tools: Add interval red-black tree helper Ingo Molnar
2011-05-17 11:38   ` Sasha Levin
2011-05-17 11:57     ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1305628123-18440-2-git-send-email-levinsasha928@gmail.com \
    --to=levinsasha928@gmail.com \
    --cc=asias.hejun@gmail.com \
    --cc=gorcunov@gmail.com \
    --cc=john@jfloren.net \
    --cc=kvm@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=penberg@kernel.org \
    --cc=prasadjoshi124@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox