Skip to content

Commit 877c57d

Browse files
author
Jarkko Sakkinen
committed
tpm_crb: request and relinquish locality 0
This commit adds support for requesting and relinquishing locality 0 in tpm_crb for the course of command transmission. In order to achieve this, two new callbacks are added to struct tpm_class_ops: - request_locality - relinquish_locality With CRB interface you first set either requestAccess or relinquish bit from TPM_LOC_CTRL_x register and then wait for locAssigned and tpmRegValidSts bits to be set in the TPM_LOC_STATE_x register. The reason why were are doing this is to make sure that the driver will work properly with Intel TXT that uses locality 2. There's no explicit guarantee that it would relinquish this locality. In more general sense this commit enables tpm_crb to be a well behaving citizen in a multi locality environment. Signed-off-by: Jarkko Sakkinen <[email protected]> Reviewed-by: Jerry Snitselaar <[email protected]> Tested-by: Jerry Snitselaar <[email protected]>
1 parent 84d2594 commit 877c57d

File tree

5 files changed

+63
-1
lines changed

5 files changed

+63
-1
lines changed

drivers/char/tpm/tpm-chip.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
231231
goto out;
232232
}
233233

234+
chip->locality = -1;
234235
return chip;
235236

236237
out:

drivers/char/tpm/tpm-interface.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
389389
ssize_t len = 0;
390390
u32 count, ordinal;
391391
unsigned long stop;
392+
bool need_locality;
392393

393394
if (!tpm_validate_command(chip, space, buf, bufsiz))
394395
return -EINVAL;
@@ -412,6 +413,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
412413
if (chip->dev.parent)
413414
pm_runtime_get_sync(chip->dev.parent);
414415

416+
/* Store the decision as chip->locality will be changed. */
417+
need_locality = chip->locality == -1;
418+
419+
if (need_locality && chip->ops->request_locality) {
420+
rc = chip->ops->request_locality(chip, 0);
421+
if (rc < 0)
422+
goto out_no_locality;
423+
chip->locality = rc;
424+
}
425+
415426
rc = tpm2_prepare_space(chip, space, ordinal, buf);
416427
if (rc)
417428
goto out;
@@ -471,6 +482,11 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
471482
rc = tpm2_commit_space(chip, space, ordinal, buf, &len);
472483

473484
out:
485+
if (need_locality && chip->ops->relinquish_locality) {
486+
chip->ops->relinquish_locality(chip, chip->locality);
487+
chip->locality = -1;
488+
}
489+
out_no_locality:
474490
if (chip->dev.parent)
475491
pm_runtime_put_sync(chip->dev.parent);
476492

drivers/char/tpm/tpm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ struct tpm_chip {
228228
struct tpm_space work_space;
229229
u32 nr_commands;
230230
u32 *cc_attrs_tbl;
231+
232+
/* active locality */
233+
int locality;
231234
};
232235

233236
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)

drivers/char/tpm/tpm_crb.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ enum crb_defaults {
3434
CRB_ACPI_START_INDEX = 1,
3535
};
3636

37+
enum crb_loc_ctrl {
38+
CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
39+
CRB_LOC_CTRL_RELINQUISH = BIT(1),
40+
};
41+
42+
enum crb_loc_state {
43+
CRB_LOC_STATE_LOC_ASSIGNED = BIT(1),
44+
CRB_LOC_STATE_TPM_REG_VALID_STS = BIT(7),
45+
};
46+
3747
enum crb_ctrl_req {
3848
CRB_CTRL_REQ_CMD_READY = BIT(0),
3949
CRB_CTRL_REQ_GO_IDLE = BIT(1),
@@ -172,6 +182,35 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
172182
return 0;
173183
}
174184

185+
static int crb_request_locality(struct tpm_chip *chip, int loc)
186+
{
187+
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
188+
u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
189+
CRB_LOC_STATE_TPM_REG_VALID_STS;
190+
191+
if (!priv->regs_h)
192+
return 0;
193+
194+
iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
195+
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value,
196+
TPM2_TIMEOUT_C)) {
197+
dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
198+
return -ETIME;
199+
}
200+
201+
return 0;
202+
}
203+
204+
static void crb_relinquish_locality(struct tpm_chip *chip, int loc)
205+
{
206+
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
207+
208+
if (!priv->regs_h)
209+
return;
210+
211+
iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
212+
}
213+
175214
static u8 crb_status(struct tpm_chip *chip)
176215
{
177216
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
@@ -278,6 +317,8 @@ static const struct tpm_class_ops tpm_crb = {
278317
.send = crb_send,
279318
.cancel = crb_cancel,
280319
.req_canceled = crb_req_canceled,
320+
.request_locality = crb_request_locality,
321+
.relinquish_locality = crb_relinquish_locality,
281322
.req_complete_mask = CRB_DRV_STS_COMPLETE,
282323
.req_complete_val = CRB_DRV_STS_COMPLETE,
283324
};

include/linux/tpm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ struct tpm_class_ops {
4848
u8 (*status) (struct tpm_chip *chip);
4949
bool (*update_timeouts)(struct tpm_chip *chip,
5050
unsigned long *timeout_cap);
51-
51+
int (*request_locality)(struct tpm_chip *chip, int loc);
52+
void (*relinquish_locality)(struct tpm_chip *chip, int loc);
5253
};
5354

5455
#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)

0 commit comments

Comments
 (0)