lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <EADF0A36011179459010BDF5142A457501C9BF2AE4@pdsmsx502.ccr.corp.intel.com>
Date:	Sun, 31 May 2009 14:43:55 +0800
From:	"Xu, Dongxiao" <dongxiao.xu@...el.com>
To:	"greg@...ah.com" <greg@...ah.com>
CC:	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	"Nashif, Anas" <anas.nashif@...el.com>,
	"Obara, Marcin" <marcin.obara@...el.com>
Subject: [Patch 06/08] Staging: heci - fix setting h_is bit in h_csr register

>From 88efd711b8209047054126e1d89254b0a6cfb5d4 Mon Sep 17 00:00:00 2001
From: Dongxiao Xu <dongxiao.xu@...el.com>
Date: Sun, 31 May 2009 22:46:34 +0800
Subject: [PATCH] heci: fix setting h_is bit in h_csr register.

Host software could issue interrupts to ME firmware, using H_IG bit. While
Setting H_IG bit, host software should preserve all the other bits in H_CSR
unchanged. In the original function which sets H_CSR register, they first read
the register, then set some bits, and write the whole 32bits back to the
register. And that the special behavior of H_IS (write-one-to-zero) causes problem.
This patch fixes the issue in the following ways:

 - Modify heci_set_csr_register() function so that it doesn't change H_IS bit.
 - Add interface heci_csr_clear_his() to clear H_IS bit. This function is called
   after H_IS checking (dev->host_hw_state & H_IS == H_IS).
 - In original heci_csr_disable_interrupts() function, it not only clears H_IE
   bit, sometimes it also clears H_IS bit. This patch separates the two parts.
 - Avoid calling write_heci_register() function to set H_CSR register directly,
   and instead using heci_set_csr_register() function

Signed-off-by: Dongxiao Xu <dongxiao.xu@...el.com>
---
 drivers/staging/heci/heci_init.c      |    4 ++--
 drivers/staging/heci/heci_interface.c |   17 +++++++++++++++--
 drivers/staging/heci/heci_interface.h |    1 +
 drivers/staging/heci/interrupt.c      |    6 ++++++
 4 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/heci/heci_init.c b/drivers/staging/heci/heci_init.c
index 06ea196..427f55d 100644
--- a/drivers/staging/heci/heci_init.c
+++ b/drivers/staging/heci/heci_init.c
@@ -249,7 +249,7 @@ int heci_hw_init(struct iamt_heci_device *dev)
 
 	if ((dev->host_hw_state & H_IS) == H_IS) {
 		/* acknowledge interrupt and stop interupts */
-		heci_set_csr_register(dev);
+		heci_csr_clear_his(dev);
 	}
 	dev->recvd_msg = 0;
 	DBG("reset in start the heci device.\n");
@@ -354,7 +354,7 @@ void heci_reset(struct iamt_heci_device *dev, int interrupts)
 	dev->host_hw_state &= ~H_RST;
 	dev->host_hw_state |= H_IG;
 
-	write_heci_register(dev, H_CSR, dev->host_hw_state);
+	heci_set_csr_register(dev);
 
 	DBG("currently saved host_hw_state = 0x%08x.\n",
 	    dev->host_hw_state);
diff --git a/drivers/staging/heci/heci_interface.c b/drivers/staging/heci/heci_interface.c
index c5f51a7..03e1df1 100644
--- a/drivers/staging/heci/heci_interface.c
+++ b/drivers/staging/heci/heci_interface.c
@@ -44,12 +44,15 @@
 
 
 /**
- * heci_set_csr_register - write H_CSR register to the heci device
+ * heci_set_csr_register - write H_CSR register to the heci device,
+ * and ignore the H_IS bit for it is write-one-to-zero.
  *
  * @dev: device object for our driver
  */
 void heci_set_csr_register(struct iamt_heci_device *dev)
 {
+	if ((dev->host_hw_state & H_IS) == H_IS)
+		dev->host_hw_state &= ~H_IS;
 	write_heci_register(dev, H_CSR, dev->host_hw_state);
 	dev->host_hw_state = read_heci_register(dev, H_CSR);
 }
@@ -76,6 +79,16 @@ void heci_csr_disable_interrupts(struct iamt_heci_device *dev)
 	heci_set_csr_register(dev);
 }
 
+/**
+ * heci_csr_clear_his - clear H_IS bit in H_CSR
+ *
+ * @dev: device object for our driver
+ */
+void heci_csr_clear_his(struct iamt_heci_device *dev)
+{
+	write_heci_register(dev, H_CSR, dev->host_hw_state);
+	dev->host_hw_state = read_heci_register(dev, H_CSR);
+}
 
 /**
  * _host_get_filled_slots - get number of device filled buffer slots
@@ -185,7 +198,7 @@ int heci_write_message(struct iamt_heci_device *dev,
 	}
 
 	dev->host_hw_state |= H_IG;
-	write_heci_register(dev, H_CSR, dev->host_hw_state);
+	heci_set_csr_register(dev);
 	dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
 	if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
 		return 0;
diff --git a/drivers/staging/heci/heci_interface.h b/drivers/staging/heci/heci_interface.h
index 37336eb..aff7f80 100644
--- a/drivers/staging/heci/heci_interface.h
+++ b/drivers/staging/heci/heci_interface.h
@@ -134,6 +134,7 @@ enum client_disconnect_status_types{
 void heci_set_csr_register(struct iamt_heci_device *dev);
 void heci_csr_enable_interrupts(struct iamt_heci_device *dev);
 void heci_csr_disable_interrupts(struct iamt_heci_device *dev);
+void heci_csr_clear_his(struct iamt_heci_device *dev);
 
 void heci_read_slots(struct iamt_heci_device *dev,
 		     unsigned char *buffer, unsigned long buffer_length);
diff --git a/drivers/staging/heci/interrupt.c b/drivers/staging/heci/interrupt.c
index b7ce73b..3a510ed 100644
--- a/drivers/staging/heci/interrupt.c
+++ b/drivers/staging/heci/interrupt.c
@@ -92,6 +92,9 @@ irqreturn_t heci_isr_interrupt(int irq, void *dev_id)
 	/* disable interrupts */
 	heci_csr_disable_interrupts(dev);
 
+	/* clear H_IS bit in H_CSR */
+	heci_csr_clear_his(dev);
+
 	/*
 	 * Our device interrupted, schedule work the heci_bh_handler
 	 * to handle the interrupt processing. This needs to be a
@@ -251,6 +254,9 @@ end:
 		/* acknowledge interrupt and disable interrupts */
 		heci_csr_disable_interrupts(dev);
 
+		/* clear H_IS bit in H_CSR */
+		heci_csr_clear_his(dev);
+
 		PREPARE_WORK(&dev->work, heci_bh_handler);
 		DBG("schedule work the heci_bh_handler.\n");
 		rets = schedule_work(&dev->work);
-- 
1.6.0.rc1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ