All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rui Wang <rui.y.wang@intel.com>
To: bhelgaas@google.com, tony.luck@intel.com, rafael.j.wysocki@intel.com
Cc: ruiv.wang@gmail.com, chaohong.guo@intel.com,
	dave.hansen@intel.com, linux-pci@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	Rui Wang <rui.y.wang@intel.com>
Subject: [PATCH v3 2/5] I/O Hook: Help functions to manage the hook
Date: Tue, 15 Apr 2014 21:48:08 +0800	[thread overview]
Message-ID: <1397569691-24691-3-git-send-email-rui.y.wang@intel.com> (raw)
In-Reply-To: <1397569691-24691-1-git-send-email-rui.y.wang@intel.com>

Add the following kernel helper functions used to add/delete/query Register
Overrides, and to start/stop the I/O Hook:
        iohook_add_ovrd
        iohook_query_ovrd
        iohook_cleanup_ovrd
        iohook_start_ovrd
        iohook_stop_ovrd
        iohook_get_status

Signed-off-by: Rui Wang <rui.y.wang@intel.com>
---
 drivers/misc/iohook/iohook.c |  151 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 151 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/iohook/iohook.c b/drivers/misc/iohook/iohook.c
index e6a626f..d8c41d0 100644
--- a/drivers/misc/iohook/iohook.c
+++ b/drivers/misc/iohook/iohook.c
@@ -6,6 +6,7 @@
 #include "iohook.h"
 
 static DEFINE_RAW_SPINLOCK(io_hook_lock);
+static DEFINE_RAW_SPINLOCK(engine_lock);
 
 LIST_HEAD(ovrd_io_reg_map);
 LIST_HEAD(ovrd_mem_reg_map);
@@ -14,6 +15,150 @@ LIST_HEAD(ovrd_pci_conf_reg_map);
 struct static_key ovrdhw_enabled = STATIC_KEY_INIT_FALSE;
 EXPORT_SYMBOL(ovrdhw_enabled);
 
+int	g_ovrd_on;
+/* query a Register Override given spaceid and index */
+struct reg_ovrd *iohook_query_ovrd(int spaceid, int idx)
+{
+	struct list_head *reg_ovrd;
+	struct reg_ovrd *ovrdreg, *regentry;
+	unsigned long lock_flags = 0;
+	int n = 0;
+
+	if (spaceid == OVRD_SPACE_MEM)
+		reg_ovrd = &ovrd_mem_reg_map;
+	else if (spaceid == OVRD_SPACE_IO)
+		reg_ovrd = &ovrd_io_reg_map;
+	else
+		reg_ovrd = &ovrd_pci_conf_reg_map;
+
+	regentry = NULL;
+	raw_spin_lock_irqsave(&io_hook_lock, lock_flags);
+	list_for_each_entry(ovrdreg, reg_ovrd, node) {
+		if (n++ >= idx) {
+			regentry = ovrdreg;
+			break;
+		}
+	}
+	raw_spin_unlock_irqrestore(&io_hook_lock, lock_flags);
+
+	pr_info("iohook_query_ovrd() returns %p, idx=%d\n",
+		regentry, idx);
+	return regentry;
+
+}
+
+/* delete all Register Overrides from one space (IO/mem/pciconf) */
+void iohook_cleanup_ovrd(int spaceid)
+{
+	struct list_head *tmp, *next, *ovrd_list;
+
+	if (spaceid == OVRD_SPACE_MEM)
+		ovrd_list = &ovrd_mem_reg_map;
+	else if (spaceid == OVRD_SPACE_IO)
+		ovrd_list = &ovrd_io_reg_map;
+	else
+		ovrd_list = &ovrd_pci_conf_reg_map;
+
+	list_for_each_safe(tmp, next, ovrd_list) {
+		struct reg_ovrd *ovrdreg =
+		    list_entry(tmp, struct reg_ovrd, node);
+		list_del(tmp);
+		kfree(ovrdreg);
+	}
+}
+
+/* for pci config space, address is encoded per PCI_ENCODE_ADDR() */
+void iohook_add_ovrd(int spaceid, u64 address, u64 value, u64 mask,
+		u32 length, u8 attrib)
+{
+	struct list_head *reg_ovrd;
+	struct reg_ovrd *ovrdreg;
+	unsigned long lock_flags = 0;
+
+	if (spaceid == OVRD_SPACE_MEM)
+		reg_ovrd = &ovrd_mem_reg_map;
+	else if (spaceid == OVRD_SPACE_IO)
+		reg_ovrd = &ovrd_io_reg_map;
+	else
+		reg_ovrd = &ovrd_pci_conf_reg_map;
+
+	raw_spin_lock_irqsave(&io_hook_lock, lock_flags);
+	list_for_each_entry(ovrdreg, reg_ovrd, node) {
+		if (ovrdreg->address == address &&
+			ovrdreg->attrib == attrib &&
+			ovrdreg->length == length) {
+			/* if already added the address, just change the bits */
+			ovrdreg->bit_mask |= mask;
+			ovrdreg->val |= value;
+			pr_info("iohook_add_ovrd(): 0x%llx already added, changed to 0x%llx, mask:0x%llx, attrib:0x%x\n",
+				address, ovrdreg->val, ovrdreg->bit_mask,
+				attrib);
+			goto out;
+		} else if (address >= ovrdreg->address &&
+			address < ovrdreg->address + ovrdreg->length) {
+			pr_info("iohook_add_ovrd(): conflicting reg at 0x%llx, length:%llx, mask:0x%llx, attrib:0x%x\n",
+				address, ovrdreg->val, ovrdreg->bit_mask,
+				attrib);
+			goto out;
+		}
+	}
+
+	raw_spin_unlock_irqrestore(&io_hook_lock, lock_flags);
+
+	ovrdreg = kmalloc(sizeof(struct reg_ovrd), GFP_ATOMIC);
+	if (!ovrdreg) {
+		pr_info("failed to alloc Reg Override!\n");
+		return;
+	}
+
+	ovrdreg->address = address;
+	ovrdreg->val = value;
+	ovrdreg->length = length;
+	ovrdreg->bit_mask = mask;
+	ovrdreg->attrib = attrib;
+	raw_spin_lock_irqsave(&io_hook_lock, lock_flags);
+	list_add_tail(&ovrdreg->node, reg_ovrd);
+out:
+	raw_spin_unlock_irqrestore(&io_hook_lock, lock_flags);
+
+}
+
+/* to start the hook */
+void iohook_start_ovrd(void)
+{
+	unsigned long lock_flags = 0;
+
+	raw_spin_lock_irqsave(&engine_lock, lock_flags);
+	if (g_ovrd_on)
+		goto done;
+
+	static_key_slow_inc(&ovrdhw_enabled);
+	g_ovrd_on = 1;
+done:
+	raw_spin_unlock_irqrestore(&engine_lock, lock_flags);
+
+}
+
+/* to stop the hook */
+void iohook_stop_ovrd(void)
+{
+	unsigned long lock_flags = 0;
+
+	raw_spin_lock_irqsave(&engine_lock, lock_flags);
+	if (!g_ovrd_on)
+		goto done;
+	g_ovrd_on = 0;
+	static_key_slow_dec(&ovrdhw_enabled);
+done:
+	raw_spin_unlock_irqrestore(&engine_lock, lock_flags);
+
+}
+
+int iohook_get_status(void)
+{
+	return g_ovrd_on;
+}
+
 /* len should only be 1, 2, 4, 8 */
 static int mem_read(u64 address, int len, void *data)
 {
@@ -170,6 +315,9 @@ int read_ovrd_common(int spaceid, u64 address, int len, void *value, void *bus)
 
 	ret = -EINVAL;
 
+	if (!g_ovrd_on)
+		return ret;
+
 	if (spaceid == OVRD_SPACE_MEM) {
 		/* in the case of memory, 'address' is virtual */
 		vaddr = address;
@@ -300,6 +448,9 @@ int write_ovrd_common(int spaceid, u64 address, int len, void *data, void *bus)
 
 	ret = -EINVAL;
 
+	if (!g_ovrd_on)
+		return ret;
+
 	if (spaceid == OVRD_SPACE_MEM) {
 		/* in the case of memory, 'address' is virtual */
 		vaddr = address;
-- 
1.7.5.4

  parent reply	other threads:[~2014-04-15 13:48 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-15 13:48 [PATCH v3 0/5] I/O Hook: Trace h/w access and emulate h/w events Rui Wang
2014-04-15 13:48 ` [PATCH v3 1/5] I/O Hook: core functions and Register Override Rui Wang
2014-04-15 13:48 ` Rui Wang [this message]
2014-04-15 13:48 ` [PATCH v3 3/5] I/O Hook: sysfs interface to emulate h/w events Rui Wang
2014-04-15 13:48 ` [PATCH v3 4/5] I/O Hook: Override MSRs while triggering MCEs Rui Wang
2014-04-15 13:48 ` [PATCH v3 5/5] IO Hook: Tracing hw access Rui Wang

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=1397569691-24691-3-git-send-email-rui.y.wang@intel.com \
    --to=rui.y.wang@intel.com \
    --cc=bhelgaas@google.com \
    --cc=chaohong.guo@intel.com \
    --cc=dave.hansen@intel.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rafael.j.wysocki@intel.com \
    --cc=ruiv.wang@gmail.com \
    --cc=tony.luck@intel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.