Skip to content

Commit f65dc7a

Browse files
committed
tpm, tpm_tis: Avoid cache incoherency in test for interrupts
JIRA: https://issues.redhat.com/browse/RHEL-72765 Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Conflicts: Context difference due to missing 7bfda9c. commit 858e8b7 Author: Lino Sanfilippo <l.sanfilippo@kunbus.com> Date: Thu Nov 24 14:55:25 2022 +0100 tpm, tpm_tis: Avoid cache incoherency in test for interrupts The interrupt handler that sets the boolean variable irq_tested may run on another CPU as the thread that checks irq_tested as part of the irq test in tpm_tis_send(). Since nothing guarantees cache coherency between CPUs for unsynchronized accesses to boolean variables the testing thread might not perceive the value change done in the interrupt handler. Avoid this issue by setting the bit TPM_TIS_IRQ_TESTED in the flags field of the tpm_tis_data struct and by accessing this field with the bit manipulating functions that provide cache coherency. Also convert all other existing sites to use the proper macros when accessing this bitfield. Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com> Tested-by: Michael Niewöhner <linux@mniewoehner.de> Tested-by: Jarkko Sakkinen <jarkko@kernel.org> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Štěpán Horáček <shoracek@redhat.com>
1 parent 79919c3 commit f65dc7a

File tree

3 files changed

+13
-12
lines changed

3 files changed

+13
-12
lines changed

drivers/char/tpm/tpm_tis.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
266266
irq = tpm_info->irq;
267267

268268
if (itpm || is_itpm(ACPI_COMPANION(dev)))
269-
phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND;
269+
set_bit(TPM_TIS_ITPM_WORKAROUND, &phy->priv.flags);
270270

271271
return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
272272
ACPI_HANDLE(dev));

drivers/char/tpm/tpm_tis_core.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
343343
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
344344
int rc, status, burstcnt;
345345
size_t count = 0;
346-
bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND;
346+
bool itpm = test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
347347

348348
status = tpm_tis_status(chip);
349349
if ((status & TPM_STS_COMMAND_READY) == 0) {
@@ -470,7 +470,8 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
470470
int rc, irq;
471471
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
472472

473-
if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested)
473+
if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
474+
test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
474475
return tpm_tis_send_main(chip, buf, len);
475476

476477
/* Verify receipt of the expected IRQ */
@@ -480,11 +481,11 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
480481
rc = tpm_tis_send_main(chip, buf, len);
481482
priv->irq = irq;
482483
chip->flags |= TPM_CHIP_FLAG_IRQ;
483-
if (!priv->irq_tested)
484+
if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
484485
tpm_msleep(1);
485-
if (!priv->irq_tested)
486+
if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
486487
disable_interrupts(chip);
487-
priv->irq_tested = true;
488+
set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
488489
return rc;
489490
}
490491

@@ -627,7 +628,7 @@ static int probe_itpm(struct tpm_chip *chip)
627628
size_t len = sizeof(cmd_getticks);
628629
u16 vendor;
629630

630-
if (priv->flags & TPM_TIS_ITPM_WORKAROUND)
631+
if (test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags))
631632
return 0;
632633

633634
rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor);
@@ -647,13 +648,13 @@ static int probe_itpm(struct tpm_chip *chip)
647648

648649
tpm_tis_ready(chip);
649650

650-
priv->flags |= TPM_TIS_ITPM_WORKAROUND;
651+
set_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
651652

652653
rc = tpm_tis_send_data(chip, cmd_getticks, len);
653654
if (rc == 0)
654655
dev_info(&chip->dev, "Detected an iTPM.\n");
655656
else {
656-
priv->flags &= ~TPM_TIS_ITPM_WORKAROUND;
657+
clear_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
657658
rc = -EFAULT;
658659
}
659660

@@ -693,7 +694,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
693694
if (interrupt == 0)
694695
return IRQ_NONE;
695696

696-
priv->irq_tested = true;
697+
set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
697698
if (interrupt & TPM_INTF_DATA_AVAIL_INT)
698699
wake_up_interruptible(&priv->read_queue);
699700
if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
@@ -779,7 +780,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
779780
if (rc < 0)
780781
return rc;
781782

782-
priv->irq_tested = false;
783+
clear_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
783784

784785
/* Generate an interrupt by having the core call through to
785786
* tpm_tis_send

drivers/char/tpm/tpm_tis_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ enum tis_defaults {
8686
enum tpm_tis_flags {
8787
TPM_TIS_ITPM_WORKAROUND = BIT(0),
8888
TPM_TIS_INVALID_STATUS = BIT(1),
89+
TPM_TIS_IRQ_TESTED = BIT(3),
8990
};
9091

9192
struct tpm_tis_data {
9293
u16 manufacturer_id;
9394
int locality;
9495
int irq;
95-
bool irq_tested;
9696
unsigned long flags;
9797
void __iomem *ilb_base_addr;
9898
u16 clkrun_enabled;

0 commit comments

Comments
 (0)