Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144954812
D52328.id171895.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D52328.id171895.diff
View Options
diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h
--- a/sys/dev/tpm/tpm20.h
+++ b/sys/dev/tpm/tpm20.h
@@ -105,6 +105,12 @@
MALLOC_DECLARE(M_TPM20);
+struct tpm_priv {
+ uint8_t buf[TPM_BUFSIZE];
+ size_t offset;
+ size_t len;
+};
+
struct tpm_sc {
device_t dev;
@@ -116,18 +122,13 @@
struct cdev *sc_cdev;
struct sx dev_lock;
- struct cv buf_cv;
void *intr_cookie;
int intr_type; /* Current event type */
bool interrupts;
- uint8_t *buf;
- size_t pending_data_length;
- size_t total_length;
- lwpid_t owner_tid;
+ struct tpm_priv *internal_priv;
- struct callout discard_buffer_callout;
#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
struct timeout_task harvest_task;
#endif
diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c
--- a/sys/dev/tpm/tpm20.c
+++ b/sys/dev/tpm/tpm20.c
@@ -67,25 +67,21 @@
tpm20_read(struct cdev *dev, struct uio *uio, int flags)
{
struct tpm_sc *sc;
+ struct tpm_priv *priv;
size_t bytes_to_transfer;
size_t offset;
int result = 0;
sc = (struct tpm_sc *)dev->si_drv1;
+ devfs_get_cdevpriv((void **)&priv);
- callout_stop(&sc->discard_buffer_callout);
sx_xlock(&sc->dev_lock);
- if (sc->owner_tid != uio->uio_td->td_tid) {
- sx_xunlock(&sc->dev_lock);
- return (EPERM);
- }
-
- bytes_to_transfer = MIN(sc->pending_data_length, uio->uio_resid);
- offset = sc->total_length - sc->pending_data_length;
+ offset = priv->offset;
+ bytes_to_transfer = MIN(priv->len, uio->uio_resid);
if (bytes_to_transfer > 0) {
- result = uiomove((caddr_t) sc->buf + offset, bytes_to_transfer, uio);
- sc->pending_data_length -= bytes_to_transfer;
- cv_signal(&sc->buf_cv);
+ result = uiomove((caddr_t) priv->buf + offset, bytes_to_transfer, uio);
+ priv->offset += bytes_to_transfer;
+ priv->len -= bytes_to_transfer;
} else {
result = ETIMEDOUT;
}
@@ -99,10 +95,12 @@
tpm20_write(struct cdev *dev, struct uio *uio, int flags)
{
struct tpm_sc *sc;
+ struct tpm_priv *priv;
size_t byte_count;
int result = 0;
sc = (struct tpm_sc *)dev->si_drv1;
+ devfs_get_cdevpriv((void **)&priv);
byte_count = uio->uio_resid;
if (byte_count < TPM_HEADER_SIZE) {
@@ -119,52 +117,42 @@
sx_xlock(&sc->dev_lock);
- while (sc->pending_data_length != 0)
- cv_wait(&sc->buf_cv, &sc->dev_lock);
-
- result = uiomove(sc->buf, byte_count, uio);
+ result = uiomove(priv->buf, byte_count, uio);
if (result != 0) {
sx_xunlock(&sc->dev_lock);
return (result);
}
- result = TPM_TRANSMIT(sc->dev, byte_count);
-
- if (result == 0) {
- callout_reset(&sc->discard_buffer_callout,
- TPM_READ_TIMEOUT / tick, tpm20_discard_buffer, sc);
- sc->owner_tid = uio->uio_td->td_tid;
- }
+ result = TPM_TRANSMIT(sc->dev, priv, byte_count);
sx_xunlock(&sc->dev_lock);
return (result);
}
-static void
-tpm20_discard_buffer(void *arg)
+static struct tpm_priv *
+tpm20_priv_alloc(void)
{
- struct tpm_sc *sc;
-
- sc = (struct tpm_sc *)arg;
- if (callout_pending(&sc->discard_buffer_callout))
- return;
+ struct tpm_priv *priv;
- sx_xlock(&sc->dev_lock);
-
- memset(sc->buf, 0, TPM_BUFSIZE);
- sc->pending_data_length = 0;
- sc->total_length = 0;
+ priv = malloc(sizeof (*priv), M_TPM20, M_WAITOK | M_ZERO);
+ return (priv);
+}
- cv_signal(&sc->buf_cv);
- sx_xunlock(&sc->dev_lock);
+static void
+tpm20_priv_dtor(void *data)
+{
+ struct tpm_priv *priv = data;
- device_printf(sc->dev,
- "User failed to read buffer in time\n");
+ free(priv->buf, M_TPM20);
}
int
tpm20_open(struct cdev *dev, int flag, int mode, struct thread *td)
{
+ struct tpm_priv *priv;
+
+ priv = tpm20_priv_alloc();
+ devfs_set_cdevpriv(priv, tpm20_priv_dtor);
return (0);
}
@@ -197,10 +185,7 @@
struct make_dev_args args;
int result;
- cv_init(&sc->buf_cv, "TPM buffer cv");
- callout_init(&sc->discard_buffer_callout, 1);
- sc->pending_data_length = 0;
- sc->total_length = 0;
+ sc->internal_priv = tpm20_priv_alloc();
make_dev_args_init(&args);
args.mda_devsw = &tpm20_cdevsw;
@@ -233,11 +218,8 @@
random_source_deregister(&random_tpm);
#endif
- if (sc->buf != NULL)
- free(sc->buf, M_TPM20);
-
+ tpm20_priv_dtor(sc->internal_priv);
sx_destroy(&sc->dev_lock);
- cv_destroy(&sc->buf_cv);
if (sc->sc_cdev != NULL)
destroy_dev(sc->sc_cdev);
}
@@ -263,6 +245,7 @@
tpm20_harvest(void *arg, int unused)
{
struct tpm_sc *sc;
+ struct tpm_priv *priv;
unsigned char entropy[TPM_HARVEST_SIZE];
uint16_t entropy_size;
int result;
@@ -275,26 +258,22 @@
sc = arg;
sx_xlock(&sc->dev_lock);
- while (sc->pending_data_length != 0)
- cv_wait(&sc->buf_cv, &sc->dev_lock);
- memcpy(sc->buf, cmd, sizeof(cmd));
- result = TPM_TRANSMIT(sc->dev, sizeof(cmd));
+ priv = sc->internal_priv;
+ memcpy(priv->buf, cmd, sizeof(cmd));
+
+ result = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd));
if (result != 0) {
sx_xunlock(&sc->dev_lock);
return;
}
- /* Ignore response size */
- sc->pending_data_length = 0;
- sc->total_length = 0;
-
/* The number of random bytes we got is placed right after the header */
- entropy_size = (uint16_t) sc->buf[TPM_HEADER_SIZE + 1];
+ entropy_size = (uint16_t) priv->buf[TPM_HEADER_SIZE + 1];
if (entropy_size > 0) {
entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE);
memcpy(entropy,
- sc->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
+ priv->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
entropy_size);
}
@@ -311,6 +290,7 @@
tpm20_save_state(device_t dev, bool suspend)
{
struct tpm_sc *sc;
+ struct tpm_priv *priv;
uint8_t save_cmd[] = {
0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/
0x00, 0x00, 0x00, 0x0C, /* cmd length */
@@ -326,13 +306,14 @@
if (suspend)
save_cmd[11] = 1; /* TPM_SU_STATE */
- if (sc == NULL || sc->buf == NULL)
+ if (sc == NULL)
return (0);
sx_xlock(&sc->dev_lock);
- memcpy(sc->buf, save_cmd, sizeof(save_cmd));
- TPM_TRANSMIT(sc->dev, sizeof(save_cmd));
+ priv = sc->internal_priv;
+ memcpy(priv->buf, save_cmd, sizeof(save_cmd));
+ TPM_TRANSMIT(sc->dev, priv, sizeof(save_cmd));
sx_xunlock(&sc->dev_lock);
diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c
--- a/sys/dev/tpm/tpm_crb.c
+++ b/sys/dev/tpm/tpm_crb.c
@@ -127,7 +127,7 @@
size_t rsp_buf_size;
};
-int tpmcrb_transmit(device_t dev, size_t size);
+int tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t size);
static int tpmcrb_acpi_probe(device_t dev);
static int tpmcrb_attach(device_t dev);
@@ -257,7 +257,6 @@
sc->dev = dev;
sx_init(&sc->dev_lock, "TPM driver lock");
- sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK);
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
@@ -480,7 +479,7 @@
}
int
-tpmcrb_transmit(device_t dev, size_t length)
+tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length)
{
struct tpmcrb_sc *crb_sc;
struct tpm_sc *sc;
@@ -531,12 +530,12 @@
* Calculate timeout for current command.
* Command code is passed in bytes 6-10.
*/
- curr_cmd = be32toh(*(uint32_t *) (&sc->buf[6]));
+ curr_cmd = be32toh(*(uint32_t *) (&priv->buf[6]));
timeout = tpm20_get_timeout(curr_cmd);
/* Send command and tell device to process it. */
bus_write_region_stream_1(sc->mem_res, crb_sc->cmd_off,
- sc->buf, length);
+ priv->buf, length);
TPM_WRITE_BARRIER(dev, crb_sc->cmd_off, length);
TPM_WRITE_4(dev, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD);
@@ -559,8 +558,8 @@
/* Read response header. Length is passed in bytes 2 - 6. */
bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off,
- sc->buf, TPM_HEADER_SIZE);
- bytes_available = be32toh(*(uint32_t *) (&sc->buf[2]));
+ priv->buf, TPM_HEADER_SIZE);
+ bytes_available = be32toh(*(uint32_t *) (&priv->buf[2]));
if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) {
device_printf(dev,
@@ -570,7 +569,7 @@
}
bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
- &sc->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
+ &priv->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
/*
* No need to wait for the transition to idle on the way out, we can
@@ -583,8 +582,8 @@
}
tpmcrb_relinquish_locality(sc);
- sc->pending_data_length = bytes_available;
- sc->total_length = bytes_available;
+ priv->offset = 0;
+ priv->len = bytes_available;
return (0);
}
diff --git a/sys/dev/tpm/tpm_if.m b/sys/dev/tpm/tpm_if.m
--- a/sys/dev/tpm/tpm_if.m
+++ b/sys/dev/tpm/tpm_if.m
@@ -28,6 +28,10 @@
#include <sys/bus.h>
#include <dev/tpm/tpm20.h>
+HEADER {
+ struct tpm_priv;
+};
+
INTERFACE tpm;
#
@@ -35,6 +39,7 @@
#
METHOD int transmit {
device_t dev;
+ struct tpm_priv *priv;
size_t length;
};
diff --git a/sys/dev/tpm/tpm_tis_core.c b/sys/dev/tpm/tpm_tis_core.c
--- a/sys/dev/tpm/tpm_tis_core.c
+++ b/sys/dev/tpm/tpm_tis_core.c
@@ -73,7 +73,7 @@
#define TPM_STS_BURST_MASK 0xFFFF00
#define TPM_STS_BURST_OFFSET 0x8
-static int tpmtis_transmit(device_t dev, size_t length);
+static int tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length);
static int tpmtis_detach(device_t dev);
@@ -104,7 +104,6 @@
sc->intr_type = -1;
sx_init(&sc->dev_lock, "TPM driver lock");
- sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK);
resource_int_value("tpm", device_get_unit(dev), "use_polling", &poll);
if (poll != 0) {
@@ -164,6 +163,7 @@
static void
tpmtis_test_intr(struct tpm_sc *sc)
{
+ struct tpm_priv *priv;
uint8_t cmd[] = {
0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/
0x00, 0x00, 0x00, 0x0c, /* cmd length */
@@ -172,9 +172,9 @@
};
sx_xlock(&sc->dev_lock);
- memcpy(sc->buf, cmd, sizeof(cmd));
- tpmtis_transmit(sc->dev, sizeof(cmd));
- sc->pending_data_length = 0;
+ priv = sc->internal_priv;
+ memcpy(priv->buf, cmd, sizeof(cmd));
+ tpmtis_transmit(sc->dev, priv, sizeof(cmd));
sx_xunlock(&sc->dev_lock);
}
@@ -384,7 +384,7 @@
}
static int
-tpmtis_transmit(device_t dev, size_t length)
+tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length)
{
struct tpm_sc *sc;
size_t bytes_available;
@@ -404,7 +404,7 @@
"Failed to switch to ready state\n");
return (EIO);
}
- if (!tpmtis_write_bytes(sc, length, sc->buf)) {
+ if (!tpmtis_write_bytes(sc, length, priv->buf)) {
device_printf(dev,
"Failed to write cmd to device\n");
return (EIO);
@@ -428,7 +428,7 @@
* Calculate timeout for current command.
* Command code is passed in bytes 6-10.
*/
- curr_cmd = be32toh(*(uint32_t *) (&sc->buf[6]));
+ curr_cmd = be32toh(*(uint32_t *) (&priv->buf[6]));
timeout = tpm20_get_timeout(curr_cmd);
TPM_WRITE_4(dev, TPM_STS, TPM_STS_CMD_START);
@@ -455,12 +455,12 @@
return (EIO);
}
/* Read response header. Length is passed in bytes 2 - 6. */
- if(!tpmtis_read_bytes(sc, TPM_HEADER_SIZE, sc->buf)) {
+ if (!tpmtis_read_bytes(sc, TPM_HEADER_SIZE, priv->buf)) {
device_printf(dev,
"Failed to read response header\n");
return (EIO);
}
- bytes_available = be32toh(*(uint32_t *) (&sc->buf[2]));
+ bytes_available = be32toh(*(uint32_t *) (&priv->buf[2]));
if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) {
device_printf(dev,
@@ -468,15 +468,15 @@
bytes_available);
return (EIO);
}
- if(!tpmtis_read_bytes(sc, bytes_available - TPM_HEADER_SIZE,
- &sc->buf[TPM_HEADER_SIZE])) {
+ if (!tpmtis_read_bytes(sc, bytes_available - TPM_HEADER_SIZE,
+ &priv->buf[TPM_HEADER_SIZE])) {
device_printf(dev,
"Failed to read response\n");
return (EIO);
}
tpmtis_relinquish_locality(sc);
- sc->pending_data_length = bytes_available;
- sc->total_length = bytes_available;
+ priv->offset = 0;
+ priv->len = bytes_available;
return (0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 11:24 AM (3 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28739051
Default Alt Text
D52328.id171895.diff (11 KB)
Attached To
Mode
D52328: tpm: fix multi-threaded access with per-open state
Attached
Detach File
Event Timeline
Log In to Comment