linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Omar Sandoval <osandov@osandov.com>
To: James Bottomley <James.Bottomley@hansenpartnership.com>
Cc: Peter Huewe <peterhuewe@gmx.de>,
	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>,
	Jason Gunthorpe <jgg@ziepe.ca>,
	linux-integrity@vger.kernel.org
Subject: Re: [PATCH] tpm_tis: work around status register bug in STMicroelectronics TPM
Date: Wed, 15 Apr 2020 17:24:42 -0700	[thread overview]
Message-ID: <20200416002442.GB673482@vader> (raw)
In-Reply-To: <20200416001605.GA673482@vader>

[-- Attachment #1: Type: text/plain, Size: 1154 bytes --]

On Wed, Apr 15, 2020 at 05:16:05PM -0700, Omar Sandoval wrote:
> On Wed, Apr 15, 2020 at 04:51:39PM -0700, James Bottomley wrote:
> > On Wed, 2020-04-15 at 15:45 -0700, Omar Sandoval wrote:
> > > From: Omar Sandoval <osandov@fb.com>
> > > 
> > > We've encountered a particular model of STMicroelectronics TPM that
> > > transiently returns a bad value in the status register. This causes
> > > the kernel to believe that the TPM is ready to receive a command when
> > > it actually isn't, which in turn causes the send to time out in
> > > get_burstcount(). In testing, reading the status register one extra
> > > time convinces the TPM to return a valid value.
> > 
> > Interesting, I've got a very early upgradeable nuvoton that seems to be
> > behaving like this.
> 
> I'll attach the userspace reproducer I used to figure this out. I'd be
> interested to see if it times out on your TPM, too. Note that it bangs
> on /dev/mem and assumes that the MMIO address is 0xfed40000. That seems
> to be the hard-coded address for x86 in the kernel, but just to be safe
> you might want to check `grep MSFT0101 /proc/iomem`.

Forgot to attach it, of course...

[-- Attachment #2: test_tpm_tis.c --]
[-- Type: text/plain, Size: 2123 bytes --]

#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

enum tis_access {
	TPM_ACCESS_VALID = 0x80,
	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
	TPM_ACCESS_REQUEST_PENDING = 0x04,
	TPM_ACCESS_REQUEST_USE = 0x02,
};

enum tis_status {
	TPM_STS_VALID = 0x80,
	TPM_STS_COMMAND_READY = 0x40,
	TPM_STS_GO = 0x20,
	TPM_STS_DATA_AVAIL = 0x10,
	TPM_STS_DATA_EXPECT = 0x08,
};

#define TPM_ACCESS(l)                   (0x0000 | ((l) << 12))
#define TPM_STS(l)                      (0x0018 | ((l) << 12))

int main(void)
{
	int fd;
	void *map;
	volatile uint8_t *access;
	volatile uint8_t *sts;
	unsigned long long i;

	fd = open("/dev/mem", O_RDWR | O_DSYNC);
	if (fd == -1) {
		perror("open");
		return EXIT_FAILURE;
	}
	map = mmap(NULL, 0x5000, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
		   0xfed40000);
	if (map == MAP_FAILED) {
		perror("mmap");
		return EXIT_FAILURE;
	}
	access = (uint8_t *)map + TPM_ACCESS(0);
	sts = (uint8_t *)map + TPM_STS(0);

	i = 0;
	for (;;) {
		struct timespec stop, now;
		uint32_t burstcnt;
		uint8_t sts_read;

		*access = TPM_ACCESS_REQUEST_USE;
		while ((*access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) !=
		       (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
			;

		sts_read = *sts;
#if 0
		if (sts_read == 0xff)
			sts_read = *sts;
#endif
		if (!(sts_read & TPM_STS_COMMAND_READY)) {
			*sts = TPM_STS_COMMAND_READY;
			while (!(*sts & TPM_STS_COMMAND_READY))
				;
		}

		clock_gettime(CLOCK_MONOTONIC, &stop);
		stop.tv_sec += 1;
		for (;;) {
			burstcnt = ((*(volatile uint32_t *)sts) >> 8) & 0xffff;
			if (burstcnt)
				break;
			clock_gettime(CLOCK_MONOTONIC, &now);
			if (now.tv_sec > stop.tv_sec ||
			    (now.tv_sec == stop.tv_sec &&
			     now.tv_nsec >= stop.tv_nsec)) {
				fprintf(stderr, "Timed out after %llu iterations\n", i);
				i = 0;
				break;
			}
		}

		*access = TPM_ACCESS_ACTIVE_LOCALITY;
		while ((*access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) !=
		       TPM_ACCESS_VALID)
			;
		i++;
	}

	return EXIT_SUCCESS;
}

  reply	other threads:[~2020-04-16  0:24 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-15 22:45 [PATCH] tpm_tis: work around status register bug in STMicroelectronics TPM Omar Sandoval
2020-04-15 23:51 ` James Bottomley
2020-04-16  0:16   ` Omar Sandoval
2020-04-16  0:24     ` Omar Sandoval [this message]
2020-04-16 18:02       ` James Bottomley
2020-04-17 23:55         ` Jarkko Sakkinen
2020-04-18  0:12           ` James Bottomley
2020-04-20 20:46             ` Jarkko Sakkinen
2020-04-20 22:28               ` James Bottomley
2020-04-21 14:36                 ` Mimi Zohar
2020-04-21 20:25                   ` Jarkko Sakkinen
2020-04-21 20:31                     ` Mimi Zohar
2020-04-21 20:23                 ` Jarkko Sakkinen
2020-04-21 22:08                   ` James Bottomley
2020-04-16 17:09   ` Jarkko Sakkinen
2020-04-16 17:56     ` James Bottomley
2020-08-27 15:24   ` Jason Andryuk
2020-08-28 23:18     ` Jarkko Sakkinen
2020-08-29  0:12       ` Jason Andryuk
2020-08-31 13:55         ` Jarkko Sakkinen
2020-09-04 12:03         ` Jarkko Sakkinen
2020-04-16 17:08 ` Jarkko Sakkinen
2020-04-16 18:54   ` Omar Sandoval
2020-04-17 23:54     ` Jarkko Sakkinen

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=20200416002442.GB673482@vader \
    --to=osandov@osandov.com \
    --cc=James.Bottomley@hansenpartnership.com \
    --cc=jarkko.sakkinen@linux.intel.com \
    --cc=jgg@ziepe.ca \
    --cc=linux-integrity@vger.kernel.org \
    --cc=peterhuewe@gmx.de \
    /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;
as well as URLs for NNTP newsgroup(s).