The tpm_crb driver should follow the policy of reserving and
relinquishing the locality it uses when multiple localities are used,
like when TXT is another locality.
Jarkko Sakkinen (3):
tpm_crb: map locality registers
tpm_crb: encapsulate crb_wait_for_reg_32
tpm_crb: request and relinquish locality 0
drivers/char/tpm/tpm_crb.c | 159 ++++++++++++++++++++++++++++++---------------
1 file changed, 106 insertions(+), 53 deletions(-)
--
v2: added sanity check for start address of the control area
2.9.3
Request and relinquish locality for the driver use in order to be
a better citizen in a multi locality environment like TXT. The
locality is requested and relinquished as part of going into and
waking up from idle.
Signed-off-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/tpm_crb.c | 36 ++++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index f986d02..f6e0beb 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -34,6 +34,15 @@ enum crb_defaults {
CRB_ACPI_START_INDEX = 1,
};
+enum crb_loc_ctrl {
+ CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+ CRB_LOC_CTRL_RELINQUISH = BIT(1),
+};
+
+enum crb_loc_state {
+ CRB_LOC_STATE_LOC_ASSIGNED = BIT(1),
+};
+
enum crb_ctrl_req {
CRB_CTRL_REQ_CMD_READY = BIT(0),
CRB_CTRL_REQ_GO_IDLE = BIT(1),
@@ -101,12 +110,8 @@ struct crb_priv {
* @dev: crb device
* @priv: crb private data
*
- * Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
- * The device should respond within TIMEOUT_C by clearing the bit.
- * Anyhow, we do not wait here as a consequent CMD_READY request
- * will be handled correctly even if idle was not completed.
- *
- * The function does nothing for devices with ACPI-start method.
+ * Put device to the idle state and relinquish locality. The function does
+ * nothing for devices with the ACPI-start method.
*
* Return: 0 always
*/
@@ -115,6 +120,7 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
if (priv->flags & CRB_FL_ACPI_START)
return 0;
+ iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
/* we don't really care when this settles */
@@ -146,11 +152,8 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
* @dev: crb device
* @priv: crb private data
*
- * Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
- * and poll till the device acknowledge it by clearing the bit.
- * The device should respond within TIMEOUT_C.
- *
- * The function does nothing for devices with ACPI-start method
+ * Try to wake up the device and request locality. The function does nothing
+ * for devices with the ACPI-start method.
*
* Return: 0 on success -ETIME on timeout;
*/
@@ -165,7 +168,16 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
CRB_CTRL_REQ_CMD_READY /* mask */,
0, /* value */
TPM2_TIMEOUT_C)) {
- dev_warn(dev, "cmdReady timed out\n");
+ dev_warn(dev, "TPM_CRB_CTRL_REQ_x.cmdReady timed out\n");
+ return -ETIME;
+ }
+
+ iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
+ if (!crb_wait_for_reg_32(&priv->regs_h->loc_state,
+ CRB_LOC_STATE_LOC_ASSIGNED, /* mask */
+ CRB_LOC_STATE_LOC_ASSIGNED, /* value */
+ TPM2_TIMEOUT_C)) {
+ dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
return -ETIME;
}
--
2.9.3
In order to provide access to locality registers, this commits adds
mapping of the head of the CRB registers, which are located right
before the control area.
Signed-off-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/tpm_crb.c | 96 ++++++++++++++++++++++++++++++----------------
1 file changed, 64 insertions(+), 32 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 717b6b4..8d81b66 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -52,18 +52,28 @@ enum crb_cancel {
CRB_CANCEL_INVOKE = BIT(0),
};
-struct crb_control_area {
- u32 req;
- u32 sts;
- u32 cancel;
- u32 start;
- u32 int_enable;
- u32 int_sts;
- u32 cmd_size;
- u32 cmd_pa_low;
- u32 cmd_pa_high;
- u32 rsp_size;
- u64 rsp_pa;
+struct crb_regs_head {
+ u32 loc_state;
+ u32 reserved1;
+ u32 loc_ctrl;
+ u32 loc_sts;
+ u8 reserved2[32];
+ u64 intf_id;
+ u64 ctrl_ext;
+} __packed;
+
+struct crb_regs_tail {
+ u32 ctrl_req;
+ u32 ctrl_sts;
+ u32 ctrl_cancel;
+ u32 ctrl_start;
+ u32 ctrl_int_enable;
+ u32 ctrl_int_sts;
+ u32 ctrl_cmd_size;
+ u32 ctrl_cmd_pa_low;
+ u32 ctrl_cmd_pa_high;
+ u32 ctrl_rsp_size;
+ u64 ctrl_rsp_pa;
} __packed;
enum crb_status {
@@ -78,7 +88,8 @@ enum crb_flags {
struct crb_priv {
unsigned int flags;
void __iomem *iobase;
- struct crb_control_area __iomem *cca;
+ struct crb_regs_head __iomem *regs_h;
+ struct crb_regs_tail __iomem *regs_t;
u8 __iomem *cmd;
u8 __iomem *rsp;
u32 cmd_size;
@@ -104,7 +115,7 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
if (priv->flags & CRB_FL_ACPI_START)
return 0;
- iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
+ iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
/* we don't really care when this settles */
return 0;
@@ -128,21 +139,23 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
struct crb_priv *priv)
{
ktime_t stop, start;
+ u32 req;
if (priv->flags & CRB_FL_ACPI_START)
return 0;
- iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
+ iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
start = ktime_get();
stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
do {
- if (!(ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY))
+ req = ioread32(&priv->regs_t->ctrl_req);
+ if (!(req & CRB_CTRL_REQ_CMD_READY))
return 0;
usleep_range(50, 100);
} while (ktime_before(ktime_get(), stop));
- if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
+ if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY) {
dev_warn(dev, "cmdReady timed out\n");
return -ETIME;
}
@@ -155,7 +168,7 @@ static u8 crb_status(struct tpm_chip *chip)
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
u8 sts = 0;
- if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
+ if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) !=
CRB_START_INVOKE)
sts |= CRB_DRV_STS_COMPLETE;
@@ -171,7 +184,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
if (count < 6)
return -EIO;
- if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
+ if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR)
return -EIO;
memcpy_fromio(buf, priv->rsp, 6);
@@ -210,7 +223,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
/* Zero the cancel register so that the next command will not get
* canceled.
*/
- iowrite32(0, &priv->cca->cancel);
+ iowrite32(0, &priv->regs_t->ctrl_cancel);
if (len > priv->cmd_size) {
dev_err(&chip->dev, "invalid command count value %zd %d\n",
@@ -224,7 +237,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
wmb();
if (priv->flags & CRB_FL_CRB_START)
- iowrite32(CRB_START_INVOKE, &priv->cca->start);
+ iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
if (priv->flags & CRB_FL_ACPI_START)
rc = crb_do_acpi_start(chip);
@@ -236,7 +249,7 @@ static void crb_cancel(struct tpm_chip *chip)
{
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
- iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel);
+ iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
dev_err(&chip->dev, "ACPI Start failed\n");
@@ -245,7 +258,7 @@ static void crb_cancel(struct tpm_chip *chip)
static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
{
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
- u32 cancel = ioread32(&priv->cca->cancel);
+ u32 cancel = ioread32(&priv->regs_t->ctrl_cancel);
return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
}
@@ -287,6 +300,8 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
if (start != new_res.start)
return (void __iomem *) ERR_PTR(-EINVAL);
+ dev_dbg(dev, "%pr %pr", io_res, &new_res);
+
if (!resource_contains(io_res, &new_res))
return devm_ioremap_resource(dev, &new_res);
@@ -322,10 +337,27 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
if (IS_ERR(priv->iobase))
return PTR_ERR(priv->iobase);
- priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
- sizeof(struct crb_control_area));
- if (IS_ERR(priv->cca))
- return PTR_ERR(priv->cca);
+ /* The ACPI IO region starts at the head area and continues to include
+ * the control area, as one nice sane region except for some older
+ * stuff that puts the control area outside the ACPI IO region.
+ */
+ if (!(priv->flags & CRB_FL_ACPI_START)) {
+ if (buf->control_address == io_res.start +
+ sizeof(struct crb_regs_head)) {
+ priv->regs_h = crb_map_res(
+ dev, priv, &io_res, io_res.start,
+ sizeof(struct crb_regs_head));
+ if (IS_ERR(priv->regs_h))
+ return PTR_ERR(priv->regs_h);
+ } else {
+ dev_warn(dev, FW_BUG "Bad ACPI memory layout");
+ }
+ }
+
+ priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
+ sizeof(struct crb_regs_tail));
+ if (IS_ERR(priv->regs_t))
+ return PTR_ERR(priv->regs_t);
/*
* PTT HW bug w/a: wake up the device to access
@@ -335,10 +367,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
if (ret)
return ret;
- pa_high = ioread32(&priv->cca->cmd_pa_high);
- pa_low = ioread32(&priv->cca->cmd_pa_low);
+ pa_high = ioread32(&priv->regs_t->ctrl_cmd_pa_high);
+ pa_low = ioread32(&priv->regs_t->ctrl_cmd_pa_low);
cmd_pa = ((u64)pa_high << 32) | pa_low;
- cmd_size = ioread32(&priv->cca->cmd_size);
+ cmd_size = ioread32(&priv->regs_t->ctrl_cmd_size);
dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
pa_high, pa_low, cmd_size);
@@ -349,9 +381,9 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
goto out;
}
- memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
+ memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8);
rsp_pa = le64_to_cpu(rsp_pa);
- rsp_size = ioread32(&priv->cca->rsp_size);
+ rsp_size = ioread32(&priv->regs_t->ctrl_rsp_size);
if (cmd_pa != rsp_pa) {
priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
--
2.9.3
Encapsulated crb_wait_for_reg32() so that state changes in other CRB
registers than TPM_CRB_CTRL_REQ_x can be waited.
Signed-off-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/tpm_crb.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 8d81b66..f986d02 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -121,6 +121,25 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
return 0;
}
+static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
+ unsigned long timeout)
+{
+ ktime_t start;
+ ktime_t stop;
+
+ start = ktime_get();
+ stop = ktime_add(start, ms_to_ktime(timeout));
+
+ do {
+ if ((ioread32(reg) & mask) == value)
+ return true;
+
+ usleep_range(50, 100);
+ } while (ktime_before(ktime_get(), stop));
+
+ return false;
+}
+
/**
* crb_cmd_ready - request tpm crb device to enter ready state
*
@@ -138,24 +157,14 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
static int __maybe_unused crb_cmd_ready(struct device *dev,
struct crb_priv *priv)
{
- ktime_t stop, start;
- u32 req;
-
if (priv->flags & CRB_FL_ACPI_START)
return 0;
iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
-
- start = ktime_get();
- stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
- do {
- req = ioread32(&priv->regs_t->ctrl_req);
- if (!(req & CRB_CTRL_REQ_CMD_READY))
- return 0;
- usleep_range(50, 100);
- } while (ktime_before(ktime_get(), stop));
-
- if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY) {
+ if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
+ CRB_CTRL_REQ_CMD_READY /* mask */,
+ 0, /* value */
+ TPM2_TIMEOUT_C)) {
dev_warn(dev, "cmdReady timed out\n");
return -ETIME;
}
--
2.9.3
CC linux-security-module
On Sat, Dec 03, 2016 at 07:52:10PM +0200, Jarkko Sakkinen wrote:
> The tpm_crb driver should follow the policy of reserving and
> relinquishing the locality it uses when multiple localities are used,
> like when TXT is another locality.
>
> Jarkko Sakkinen (3):
> tpm_crb: map locality registers
> tpm_crb: encapsulate crb_wait_for_reg_32
> tpm_crb: request and relinquish locality 0
>
> drivers/char/tpm/tpm_crb.c | 159 ++++++++++++++++++++++++++++++---------------
> 1 file changed, 106 insertions(+), 53 deletions(-)
>
> --
> v2: added sanity check for start address of the control area
> 2.9.3
>
CC linux-security-module
On Sat, Dec 03, 2016 at 07:52:11PM +0200, Jarkko Sakkinen wrote:
> In order to provide access to locality registers, this commits adds
> mapping of the head of the CRB registers, which are located right
> before the control area.
>
> Signed-off-by: Jarkko Sakkinen <[email protected]>
> ---
> drivers/char/tpm/tpm_crb.c | 96 ++++++++++++++++++++++++++++++----------------
> 1 file changed, 64 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> index 717b6b4..8d81b66 100644
> --- a/drivers/char/tpm/tpm_crb.c
> +++ b/drivers/char/tpm/tpm_crb.c
> @@ -52,18 +52,28 @@ enum crb_cancel {
> CRB_CANCEL_INVOKE = BIT(0),
> };
>
> -struct crb_control_area {
> - u32 req;
> - u32 sts;
> - u32 cancel;
> - u32 start;
> - u32 int_enable;
> - u32 int_sts;
> - u32 cmd_size;
> - u32 cmd_pa_low;
> - u32 cmd_pa_high;
> - u32 rsp_size;
> - u64 rsp_pa;
> +struct crb_regs_head {
> + u32 loc_state;
> + u32 reserved1;
> + u32 loc_ctrl;
> + u32 loc_sts;
> + u8 reserved2[32];
> + u64 intf_id;
> + u64 ctrl_ext;
> +} __packed;
> +
> +struct crb_regs_tail {
> + u32 ctrl_req;
> + u32 ctrl_sts;
> + u32 ctrl_cancel;
> + u32 ctrl_start;
> + u32 ctrl_int_enable;
> + u32 ctrl_int_sts;
> + u32 ctrl_cmd_size;
> + u32 ctrl_cmd_pa_low;
> + u32 ctrl_cmd_pa_high;
> + u32 ctrl_rsp_size;
> + u64 ctrl_rsp_pa;
> } __packed;
>
> enum crb_status {
> @@ -78,7 +88,8 @@ enum crb_flags {
> struct crb_priv {
> unsigned int flags;
> void __iomem *iobase;
> - struct crb_control_area __iomem *cca;
> + struct crb_regs_head __iomem *regs_h;
> + struct crb_regs_tail __iomem *regs_t;
> u8 __iomem *cmd;
> u8 __iomem *rsp;
> u32 cmd_size;
> @@ -104,7 +115,7 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
> if (priv->flags & CRB_FL_ACPI_START)
> return 0;
>
> - iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
> + iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> /* we don't really care when this settles */
>
> return 0;
> @@ -128,21 +139,23 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
> struct crb_priv *priv)
> {
> ktime_t stop, start;
> + u32 req;
>
> if (priv->flags & CRB_FL_ACPI_START)
> return 0;
>
> - iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
> + iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
>
> start = ktime_get();
> stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> do {
> - if (!(ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY))
> + req = ioread32(&priv->regs_t->ctrl_req);
> + if (!(req & CRB_CTRL_REQ_CMD_READY))
> return 0;
> usleep_range(50, 100);
> } while (ktime_before(ktime_get(), stop));
>
> - if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
> + if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY) {
> dev_warn(dev, "cmdReady timed out\n");
> return -ETIME;
> }
> @@ -155,7 +168,7 @@ static u8 crb_status(struct tpm_chip *chip)
> struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> u8 sts = 0;
>
> - if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
> + if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) !=
> CRB_START_INVOKE)
> sts |= CRB_DRV_STS_COMPLETE;
>
> @@ -171,7 +184,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> if (count < 6)
> return -EIO;
>
> - if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
> + if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR)
> return -EIO;
>
> memcpy_fromio(buf, priv->rsp, 6);
> @@ -210,7 +223,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
> /* Zero the cancel register so that the next command will not get
> * canceled.
> */
> - iowrite32(0, &priv->cca->cancel);
> + iowrite32(0, &priv->regs_t->ctrl_cancel);
>
> if (len > priv->cmd_size) {
> dev_err(&chip->dev, "invalid command count value %zd %d\n",
> @@ -224,7 +237,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
> wmb();
>
> if (priv->flags & CRB_FL_CRB_START)
> - iowrite32(CRB_START_INVOKE, &priv->cca->start);
> + iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
>
> if (priv->flags & CRB_FL_ACPI_START)
> rc = crb_do_acpi_start(chip);
> @@ -236,7 +249,7 @@ static void crb_cancel(struct tpm_chip *chip)
> {
> struct crb_priv *priv = dev_get_drvdata(&chip->dev);
>
> - iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel);
> + iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
>
> if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
> dev_err(&chip->dev, "ACPI Start failed\n");
> @@ -245,7 +258,7 @@ static void crb_cancel(struct tpm_chip *chip)
> static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
> {
> struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> - u32 cancel = ioread32(&priv->cca->cancel);
> + u32 cancel = ioread32(&priv->regs_t->ctrl_cancel);
>
> return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
> }
> @@ -287,6 +300,8 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
> if (start != new_res.start)
> return (void __iomem *) ERR_PTR(-EINVAL);
>
> + dev_dbg(dev, "%pr %pr", io_res, &new_res);
> +
> if (!resource_contains(io_res, &new_res))
> return devm_ioremap_resource(dev, &new_res);
>
> @@ -322,10 +337,27 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
> if (IS_ERR(priv->iobase))
> return PTR_ERR(priv->iobase);
>
> - priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
> - sizeof(struct crb_control_area));
> - if (IS_ERR(priv->cca))
> - return PTR_ERR(priv->cca);
> + /* The ACPI IO region starts at the head area and continues to include
> + * the control area, as one nice sane region except for some older
> + * stuff that puts the control area outside the ACPI IO region.
> + */
> + if (!(priv->flags & CRB_FL_ACPI_START)) {
> + if (buf->control_address == io_res.start +
> + sizeof(struct crb_regs_head)) {
> + priv->regs_h = crb_map_res(
> + dev, priv, &io_res, io_res.start,
> + sizeof(struct crb_regs_head));
> + if (IS_ERR(priv->regs_h))
> + return PTR_ERR(priv->regs_h);
> + } else {
> + dev_warn(dev, FW_BUG "Bad ACPI memory layout");
> + }
> + }
> +
> + priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
> + sizeof(struct crb_regs_tail));
> + if (IS_ERR(priv->regs_t))
> + return PTR_ERR(priv->regs_t);
>
> /*
> * PTT HW bug w/a: wake up the device to access
> @@ -335,10 +367,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
> if (ret)
> return ret;
>
> - pa_high = ioread32(&priv->cca->cmd_pa_high);
> - pa_low = ioread32(&priv->cca->cmd_pa_low);
> + pa_high = ioread32(&priv->regs_t->ctrl_cmd_pa_high);
> + pa_low = ioread32(&priv->regs_t->ctrl_cmd_pa_low);
> cmd_pa = ((u64)pa_high << 32) | pa_low;
> - cmd_size = ioread32(&priv->cca->cmd_size);
> + cmd_size = ioread32(&priv->regs_t->ctrl_cmd_size);
>
> dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
> pa_high, pa_low, cmd_size);
> @@ -349,9 +381,9 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
> goto out;
> }
>
> - memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
> + memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8);
> rsp_pa = le64_to_cpu(rsp_pa);
> - rsp_size = ioread32(&priv->cca->rsp_size);
> + rsp_size = ioread32(&priv->regs_t->ctrl_rsp_size);
>
> if (cmd_pa != rsp_pa) {
> priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
> --
> 2.9.3
>
CC linux-security-module
On Sat, Dec 03, 2016 at 07:52:12PM +0200, Jarkko Sakkinen wrote:
> Encapsulated crb_wait_for_reg32() so that state changes in other CRB
> registers than TPM_CRB_CTRL_REQ_x can be waited.
>
> Signed-off-by: Jarkko Sakkinen <[email protected]>
> ---
> drivers/char/tpm/tpm_crb.c | 37 +++++++++++++++++++++++--------------
> 1 file changed, 23 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> index 8d81b66..f986d02 100644
> --- a/drivers/char/tpm/tpm_crb.c
> +++ b/drivers/char/tpm/tpm_crb.c
> @@ -121,6 +121,25 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
> return 0;
> }
>
> +static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
> + unsigned long timeout)
> +{
> + ktime_t start;
> + ktime_t stop;
> +
> + start = ktime_get();
> + stop = ktime_add(start, ms_to_ktime(timeout));
> +
> + do {
> + if ((ioread32(reg) & mask) == value)
> + return true;
> +
> + usleep_range(50, 100);
> + } while (ktime_before(ktime_get(), stop));
> +
> + return false;
> +}
> +
> /**
> * crb_cmd_ready - request tpm crb device to enter ready state
> *
> @@ -138,24 +157,14 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
> static int __maybe_unused crb_cmd_ready(struct device *dev,
> struct crb_priv *priv)
> {
> - ktime_t stop, start;
> - u32 req;
> -
> if (priv->flags & CRB_FL_ACPI_START)
> return 0;
>
> iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> -
> - start = ktime_get();
> - stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> - do {
> - req = ioread32(&priv->regs_t->ctrl_req);
> - if (!(req & CRB_CTRL_REQ_CMD_READY))
> - return 0;
> - usleep_range(50, 100);
> - } while (ktime_before(ktime_get(), stop));
> -
> - if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY) {
> + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
> + CRB_CTRL_REQ_CMD_READY /* mask */,
> + 0, /* value */
> + TPM2_TIMEOUT_C)) {
> dev_warn(dev, "cmdReady timed out\n");
> return -ETIME;
> }
> --
> 2.9.3
>
CC linux-security-module
On Sat, Dec 03, 2016 at 07:52:13PM +0200, Jarkko Sakkinen wrote:
> Request and relinquish locality for the driver use in order to be
> a better citizen in a multi locality environment like TXT. The
> locality is requested and relinquished as part of going into and
> waking up from idle.
>
> Signed-off-by: Jarkko Sakkinen <[email protected]>
> ---
> drivers/char/tpm/tpm_crb.c | 36 ++++++++++++++++++++++++------------
> 1 file changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> index f986d02..f6e0beb 100644
> --- a/drivers/char/tpm/tpm_crb.c
> +++ b/drivers/char/tpm/tpm_crb.c
> @@ -34,6 +34,15 @@ enum crb_defaults {
> CRB_ACPI_START_INDEX = 1,
> };
>
> +enum crb_loc_ctrl {
> + CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
> + CRB_LOC_CTRL_RELINQUISH = BIT(1),
> +};
> +
> +enum crb_loc_state {
> + CRB_LOC_STATE_LOC_ASSIGNED = BIT(1),
> +};
> +
> enum crb_ctrl_req {
> CRB_CTRL_REQ_CMD_READY = BIT(0),
> CRB_CTRL_REQ_GO_IDLE = BIT(1),
> @@ -101,12 +110,8 @@ struct crb_priv {
> * @dev: crb device
> * @priv: crb private data
> *
> - * Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
> - * The device should respond within TIMEOUT_C by clearing the bit.
> - * Anyhow, we do not wait here as a consequent CMD_READY request
> - * will be handled correctly even if idle was not completed.
> - *
> - * The function does nothing for devices with ACPI-start method.
> + * Put device to the idle state and relinquish locality. The function does
> + * nothing for devices with the ACPI-start method.
> *
> * Return: 0 always
> */
> @@ -115,6 +120,7 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
> if (priv->flags & CRB_FL_ACPI_START)
> return 0;
>
> + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
> iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> /* we don't really care when this settles */
>
> @@ -146,11 +152,8 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
> * @dev: crb device
> * @priv: crb private data
> *
> - * Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
> - * and poll till the device acknowledge it by clearing the bit.
> - * The device should respond within TIMEOUT_C.
> - *
> - * The function does nothing for devices with ACPI-start method
> + * Try to wake up the device and request locality. The function does nothing
> + * for devices with the ACPI-start method.
> *
> * Return: 0 on success -ETIME on timeout;
> */
> @@ -165,7 +168,16 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
> CRB_CTRL_REQ_CMD_READY /* mask */,
> 0, /* value */
> TPM2_TIMEOUT_C)) {
> - dev_warn(dev, "cmdReady timed out\n");
> + dev_warn(dev, "TPM_CRB_CTRL_REQ_x.cmdReady timed out\n");
> + return -ETIME;
> + }
> +
> + iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
> + if (!crb_wait_for_reg_32(&priv->regs_h->loc_state,
> + CRB_LOC_STATE_LOC_ASSIGNED, /* mask */
> + CRB_LOC_STATE_LOC_ASSIGNED, /* value */
> + TPM2_TIMEOUT_C)) {
> + dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
> return -ETIME;
> }
>
> --
> 2.9.3
>
> > ---
> > drivers/char/tpm/tpm_crb.c | 96
> > ++++++++++++++++++++++++++++++----------------
> > 1 file changed, 64 insertions(+), 32 deletions(-)
> >
> > diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> > index 717b6b4..8d81b66 100644
> > --- a/drivers/char/tpm/tpm_crb.c
> > +++ b/drivers/char/tpm/tpm_crb.c
> > @@ -52,18 +52,28 @@ enum crb_cancel {
> > CRB_CANCEL_INVOKE = BIT(0),
> > };
> >
> > -struct crb_control_area {
> > - u32 req;
> > - u32 sts;
> > - u32 cancel;
> > - u32 start;
> > - u32 int_enable;
> > - u32 int_sts;
> > - u32 cmd_size;
> > - u32 cmd_pa_low;
> > - u32 cmd_pa_high;
> > - u32 rsp_size;
> > - u64 rsp_pa;
> > +struct crb_regs_head {
> > + u32 loc_state;
> > + u32 reserved1;
> > + u32 loc_ctrl;
> > + u32 loc_sts;
> > + u8 reserved2[32];
> > + u64 intf_id;
> > + u64 ctrl_ext;
> > +} __packed;
> > +
> > +struct crb_regs_tail {
> > + u32 ctrl_req;
> > + u32 ctrl_sts;
> > + u32 ctrl_cancel;
> > + u32 ctrl_start;
> > + u32 ctrl_int_enable;
> > + u32 ctrl_int_sts;
> > + u32 ctrl_cmd_size;
> > + u32 ctrl_cmd_pa_low;
> > + u32 ctrl_cmd_pa_high;
> > + u32 ctrl_rsp_size;
> > + u64 ctrl_rsp_pa;
> > } __packed;
Now I wonder if using traditional offsets wouldn't be cleaner solution.
> > enum crb_status {
> > @@ -78,7 +88,8 @@ enum crb_flags {
> > struct crb_priv {
> > unsigned int flags;
> > void __iomem *iobase;
> > - struct crb_control_area __iomem *cca;
> > + struct crb_regs_head __iomem *regs_h;
> > + struct crb_regs_tail __iomem *regs_t;
Why just not leaving it cca, it's descriptive enough.
> > u8 __iomem *cmd;
> > u8 __iomem *rsp;
> > u32 cmd_size;
> > @@ -104,7 +115,7 @@ static int __maybe_unused crb_go_idle(struct device
> *dev, struct crb_priv *priv)
> > if (priv->flags & CRB_FL_ACPI_START)
> > return 0;
> >
> > - iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
> > + iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> > /* we don't really care when this settles */
> >
> > return 0;
> > @@ -128,21 +139,23 @@ static int __maybe_unused crb_cmd_ready(struct
> device *dev,
> > struct crb_priv *priv)
> > {
> > ktime_t stop, start;
> > + u32 req;
> >
> > if (priv->flags & CRB_FL_ACPI_START)
> > return 0;
> >
> > - iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
> > + iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> >
> > start = ktime_get();
> > stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> > do {
> > - if (!(ioread32(&priv->cca->req) &
> CRB_CTRL_REQ_CMD_READY))
> > + req = ioread32(&priv->regs_t->ctrl_req);
> > + if (!(req & CRB_CTRL_REQ_CMD_READY))
> > return 0;
> > usleep_range(50, 100);
> > } while (ktime_before(ktime_get(), stop));
> >
> > - if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
> > + if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY)
> {
> > dev_warn(dev, "cmdReady timed out\n");
> > return -ETIME;
> > }
> > @@ -155,7 +168,7 @@ static u8 crb_status(struct tpm_chip *chip)
> > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > u8 sts = 0;
> >
> > - if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
> > + if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) !=
> > CRB_START_INVOKE)
> > sts |= CRB_DRV_STS_COMPLETE;
> >
> > @@ -171,7 +184,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf,
> size_t count)
> > if (count < 6)
> > return -EIO;
> >
> > - if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
> > + if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR)
> > return -EIO;
> >
> > memcpy_fromio(buf, priv->rsp, 6);
> > @@ -210,7 +223,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf,
> size_t len)
> > /* Zero the cancel register so that the next command will not get
> > * canceled.
> > */
> > - iowrite32(0, &priv->cca->cancel);
> > + iowrite32(0, &priv->regs_t->ctrl_cancel);
> >
> > if (len > priv->cmd_size) {
> > dev_err(&chip->dev, "invalid command count value %zd %d\n",
> @@
> > -224,7 +237,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t
> len)
> > wmb();
> >
> > if (priv->flags & CRB_FL_CRB_START)
> > - iowrite32(CRB_START_INVOKE, &priv->cca->start);
> > + iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
> >
> > if (priv->flags & CRB_FL_ACPI_START)
> > rc = crb_do_acpi_start(chip);
> > @@ -236,7 +249,7 @@ static void crb_cancel(struct tpm_chip *chip) {
> > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> >
> > - iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel);
> > + iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
> >
> > if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
> > dev_err(&chip->dev, "ACPI Start failed\n"); @@ -245,7 +258,7
> @@
> > static void crb_cancel(struct tpm_chip *chip) static bool
> > crb_req_canceled(struct tpm_chip *chip, u8 status) {
> > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > - u32 cancel = ioread32(&priv->cca->cancel);
> > + u32 cancel = ioread32(&priv->regs_t->ctrl_cancel);
> >
> > return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; }
> @@
> > -287,6 +300,8 @@ static void __iomem *crb_map_res(struct device *dev,
> struct crb_priv *priv,
> > if (start != new_res.start)
> > return (void __iomem *) ERR_PTR(-EINVAL);
> >
> > + dev_dbg(dev, "%pr %pr", io_res, &new_res);
> > +
> > if (!resource_contains(io_res, &new_res))
> > return devm_ioremap_resource(dev, &new_res);
> >
> > @@ -322,10 +337,27 @@ static int crb_map_io(struct acpi_device *device,
> struct crb_priv *priv,
> > if (IS_ERR(priv->iobase))
> > return PTR_ERR(priv->iobase);
> >
> > - priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
> > - sizeof(struct crb_control_area));
> > - if (IS_ERR(priv->cca))
> > - return PTR_ERR(priv->cca);
> > + /* The ACPI IO region starts at the head area and continues to include
> > + * the control area, as one nice sane region except for some older
> > + * stuff that puts the control area outside the ACPI IO region.
> > + */
This is not by the spec, can you be more specific, what platforms has that behavior?
> > + if (!(priv->flags & CRB_FL_ACPI_START)) {
> > + if (buf->control_address == io_res.start +
> > + sizeof(struct crb_regs_head)) {
> > + priv->regs_h = crb_map_res(
Why do you need to map this again it just same as iobase ?
> > + dev, priv, &io_res, io_res.start,
> > + sizeof(struct crb_regs_head));
> > + if (IS_ERR(priv->regs_h))
> > + return PTR_ERR(priv->regs_h);
> > + } else {
> > + dev_warn(dev, FW_BUG "Bad ACPI memory layout");
> > + }
> > + }
> > +
> > + priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
> > + sizeof(struct crb_regs_tail));
> > + if (IS_ERR(priv->regs_t))
> > + return PTR_ERR(priv->regs_t);
> >
> > /*
> > * PTT HW bug w/a: wake up the device to access @@ -335,10 +367,10
> > @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
> > if (ret)
> > return ret;
> >
> > - pa_high = ioread32(&priv->cca->cmd_pa_high);
> > - pa_low = ioread32(&priv->cca->cmd_pa_low);
> > + pa_high = ioread32(&priv->regs_t->ctrl_cmd_pa_high);
> > + pa_low = ioread32(&priv->regs_t->ctrl_cmd_pa_low);
> > cmd_pa = ((u64)pa_high << 32) | pa_low;
> > - cmd_size = ioread32(&priv->cca->cmd_size);
> > + cmd_size = ioread32(&priv->regs_t->ctrl_cmd_size);
> >
> > dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
> > pa_high, pa_low, cmd_size);
> > @@ -349,9 +381,9 @@ static int crb_map_io(struct acpi_device *device,
> struct crb_priv *priv,
> > goto out;
> > }
> >
> > - memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
> > + memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8);
> > rsp_pa = le64_to_cpu(rsp_pa);
> > - rsp_size = ioread32(&priv->cca->rsp_size);
> > + rsp_size = ioread32(&priv->regs_t->ctrl_rsp_size);
> >
> > if (cmd_pa != rsp_pa) {
> > priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
> > --
> > 2.9.3
> >
>
On Mon, Dec 05, 2016 at 12:07:51PM +0000, Winkler, Tomas wrote:
> > > ---
> > > drivers/char/tpm/tpm_crb.c | 96
> > > ++++++++++++++++++++++++++++++----------------
> > > 1 file changed, 64 insertions(+), 32 deletions(-)
> > >
> > > diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> > > index 717b6b4..8d81b66 100644
> > > --- a/drivers/char/tpm/tpm_crb.c
> > > +++ b/drivers/char/tpm/tpm_crb.c
> > > @@ -52,18 +52,28 @@ enum crb_cancel {
> > > CRB_CANCEL_INVOKE = BIT(0),
> > > };
> > >
> > > -struct crb_control_area {
> > > - u32 req;
> > > - u32 sts;
> > > - u32 cancel;
> > > - u32 start;
> > > - u32 int_enable;
> > > - u32 int_sts;
> > > - u32 cmd_size;
> > > - u32 cmd_pa_low;
> > > - u32 cmd_pa_high;
> > > - u32 rsp_size;
> > > - u64 rsp_pa;
> > > +struct crb_regs_head {
> > > + u32 loc_state;
> > > + u32 reserved1;
> > > + u32 loc_ctrl;
> > > + u32 loc_sts;
> > > + u8 reserved2[32];
> > > + u64 intf_id;
> > > + u64 ctrl_ext;
> > > +} __packed;
> > > +
> > > +struct crb_regs_tail {
> > > + u32 ctrl_req;
> > > + u32 ctrl_sts;
> > > + u32 ctrl_cancel;
> > > + u32 ctrl_start;
> > > + u32 ctrl_int_enable;
> > > + u32 ctrl_int_sts;
> > > + u32 ctrl_cmd_size;
> > > + u32 ctrl_cmd_pa_low;
> > > + u32 ctrl_cmd_pa_high;
> > > + u32 ctrl_rsp_size;
> > > + u64 ctrl_rsp_pa;
> > > } __packed;
>
>
> Now I wonder if using traditional offsets wouldn't be cleaner solution.
I'm not sure what you are trying to say.
> > > enum crb_status {
> > > @@ -78,7 +88,8 @@ enum crb_flags {
> > > struct crb_priv {
> > > unsigned int flags;
> > > void __iomem *iobase;
> > > - struct crb_control_area __iomem *cca;
> > > + struct crb_regs_head __iomem *regs_h;
> > > + struct crb_regs_tail __iomem *regs_t;
> Why just not leaving it cca, it's descriptive enough.
> > > u8 __iomem *cmd;
> > > u8 __iomem *rsp;
> > > u32 cmd_size;
> > > @@ -104,7 +115,7 @@ static int __maybe_unused crb_go_idle(struct device
> > *dev, struct crb_priv *priv)
> > > if (priv->flags & CRB_FL_ACPI_START)
> > > return 0;
> > >
> > > - iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
> > > + iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> > > /* we don't really care when this settles */
> > >
> > > return 0;
> > > @@ -128,21 +139,23 @@ static int __maybe_unused crb_cmd_ready(struct
> > device *dev,
> > > struct crb_priv *priv)
> > > {
> > > ktime_t stop, start;
> > > + u32 req;
> > >
> > > if (priv->flags & CRB_FL_ACPI_START)
> > > return 0;
> > >
> > > - iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
> > > + iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> > >
> > > start = ktime_get();
> > > stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> > > do {
> > > - if (!(ioread32(&priv->cca->req) &
> > CRB_CTRL_REQ_CMD_READY))
> > > + req = ioread32(&priv->regs_t->ctrl_req);
> > > + if (!(req & CRB_CTRL_REQ_CMD_READY))
> > > return 0;
> > > usleep_range(50, 100);
> > > } while (ktime_before(ktime_get(), stop));
> > >
> > > - if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
> > > + if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY)
> > {
> > > dev_warn(dev, "cmdReady timed out\n");
> > > return -ETIME;
> > > }
> > > @@ -155,7 +168,7 @@ static u8 crb_status(struct tpm_chip *chip)
> > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > u8 sts = 0;
> > >
> > > - if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
> > > + if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) !=
> > > CRB_START_INVOKE)
> > > sts |= CRB_DRV_STS_COMPLETE;
> > >
> > > @@ -171,7 +184,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf,
> > size_t count)
> > > if (count < 6)
> > > return -EIO;
> > >
> > > - if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
> > > + if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR)
> > > return -EIO;
> > >
> > > memcpy_fromio(buf, priv->rsp, 6);
> > > @@ -210,7 +223,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf,
> > size_t len)
> > > /* Zero the cancel register so that the next command will not get
> > > * canceled.
> > > */
> > > - iowrite32(0, &priv->cca->cancel);
> > > + iowrite32(0, &priv->regs_t->ctrl_cancel);
> > >
> > > if (len > priv->cmd_size) {
> > > dev_err(&chip->dev, "invalid command count value %zd %d\n",
> > @@
> > > -224,7 +237,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t
> > len)
> > > wmb();
> > >
> > > if (priv->flags & CRB_FL_CRB_START)
> > > - iowrite32(CRB_START_INVOKE, &priv->cca->start);
> > > + iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
> > >
> > > if (priv->flags & CRB_FL_ACPI_START)
> > > rc = crb_do_acpi_start(chip);
> > > @@ -236,7 +249,7 @@ static void crb_cancel(struct tpm_chip *chip) {
> > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > >
> > > - iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel);
> > > + iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
> > >
> > > if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
> > > dev_err(&chip->dev, "ACPI Start failed\n"); @@ -245,7 +258,7
> > @@
> > > static void crb_cancel(struct tpm_chip *chip) static bool
> > > crb_req_canceled(struct tpm_chip *chip, u8 status) {
> > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > - u32 cancel = ioread32(&priv->cca->cancel);
> > > + u32 cancel = ioread32(&priv->regs_t->ctrl_cancel);
> > >
> > > return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; }
> > @@
> > > -287,6 +300,8 @@ static void __iomem *crb_map_res(struct device *dev,
> > struct crb_priv *priv,
> > > if (start != new_res.start)
> > > return (void __iomem *) ERR_PTR(-EINVAL);
> > >
> > > + dev_dbg(dev, "%pr %pr", io_res, &new_res);
> > > +
> > > if (!resource_contains(io_res, &new_res))
> > > return devm_ioremap_resource(dev, &new_res);
> > >
> > > @@ -322,10 +337,27 @@ static int crb_map_io(struct acpi_device *device,
> > struct crb_priv *priv,
> > > if (IS_ERR(priv->iobase))
> > > return PTR_ERR(priv->iobase);
> > >
> > > - priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
> > > - sizeof(struct crb_control_area));
> > > - if (IS_ERR(priv->cca))
> > > - return PTR_ERR(priv->cca);
> > > + /* The ACPI IO region starts at the head area and continues to include
> > > + * the control area, as one nice sane region except for some older
> > > + * stuff that puts the control area outside the ACPI IO region.
> > > + */
>
> This is not by the spec, can you be more specific, what platforms has that behavior?
Pre-Skylake (Haswell, Broadwell) does not follow the spec.
> > > + if (!(priv->flags & CRB_FL_ACPI_START)) {
> > > + if (buf->control_address == io_res.start +
> > > + sizeof(struct crb_regs_head)) {
> > > + priv->regs_h = crb_map_res(
> Why do you need to map this again it just same as iobase ?
crb_map_res() works in a way that it does ioremap only when the range
is not included to iomem.
/Jarkko
On Sat, Dec 03, 2016 at 07:52:13PM +0200, Jarkko Sakkinen wrote:
> + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
Since regs_h can be null shouldn't there be some guards ?
Jason
>
> On Mon, Dec 05, 2016 at 12:07:51PM +0000, Winkler, Tomas wrote:
> > > > ---
> > > > drivers/char/tpm/tpm_crb.c | 96
> > > > ++++++++++++++++++++++++++++++----------------
> > > > 1 file changed, 64 insertions(+), 32 deletions(-)
> > > >
> > > > diff --git a/drivers/char/tpm/tpm_crb.c
> > > > b/drivers/char/tpm/tpm_crb.c index 717b6b4..8d81b66 100644
> > > > --- a/drivers/char/tpm/tpm_crb.c
> > > > +++ b/drivers/char/tpm/tpm_crb.c
> > > > @@ -52,18 +52,28 @@ enum crb_cancel {
> > > > CRB_CANCEL_INVOKE = BIT(0),
> > > > };
> > > >
> > > > -struct crb_control_area {
> > > > - u32 req;
> > > > - u32 sts;
> > > > - u32 cancel;
> > > > - u32 start;
> > > > - u32 int_enable;
> > > > - u32 int_sts;
> > > > - u32 cmd_size;
> > > > - u32 cmd_pa_low;
> > > > - u32 cmd_pa_high;
> > > > - u32 rsp_size;
> > > > - u64 rsp_pa;
> > > > +struct crb_regs_head {
> > > > + u32 loc_state;
> > > > + u32 reserved1;
> > > > + u32 loc_ctrl;
> > > > + u32 loc_sts;
> > > > + u8 reserved2[32];
> > > > + u64 intf_id;
> > > > + u64 ctrl_ext;
> > > > +} __packed;
> > > > +
> > > > +struct crb_regs_tail {
> > > > + u32 ctrl_req;
> > > > + u32 ctrl_sts;
> > > > + u32 ctrl_cancel;
> > > > + u32 ctrl_start;
> > > > + u32 ctrl_int_enable;
> > > > + u32 ctrl_int_sts;
> > > > + u32 ctrl_cmd_size;
> > > > + u32 ctrl_cmd_pa_low;
> > > > + u32 ctrl_cmd_pa_high;
> > > > + u32 ctrl_rsp_size;
> > > > + u64 ctrl_rsp_pa;
> > > > } __packed;
> >
> >
> > Now I wonder if using traditional offsets wouldn't be cleaner solution.
>
> I'm not sure what you are trying to say.
Such as iowrite32(val, base + offset)
>
> > > > enum crb_status {
> > > > @@ -78,7 +88,8 @@ enum crb_flags { struct crb_priv {
> > > > unsigned int flags;
> > > > void __iomem *iobase;
> > > > - struct crb_control_area __iomem *cca;
> > > > + struct crb_regs_head __iomem *regs_h;
> > > > + struct crb_regs_tail __iomem *regs_t;
> > Why just not leaving it cca, it's descriptive enough.
> > > > u8 __iomem *cmd;
> > > > u8 __iomem *rsp;
> > > > u32 cmd_size;
> > > > @@ -104,7 +115,7 @@ static int __maybe_unused crb_go_idle(struct
> > > > device
> > > *dev, struct crb_priv *priv)
> > > > if (priv->flags & CRB_FL_ACPI_START)
> > > > return 0;
> > > >
> > > > - iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
> > > > + iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> > > > /* we don't really care when this settles */
> > > >
> > > > return 0;
> > > > @@ -128,21 +139,23 @@ static int __maybe_unused
> > > > crb_cmd_ready(struct
> > > device *dev,
> > > > struct crb_priv *priv)
> > > > {
> > > > ktime_t stop, start;
> > > > + u32 req;
> > > >
> > > > if (priv->flags & CRB_FL_ACPI_START)
> > > > return 0;
> > > >
> > > > - iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
> > > > + iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> > > >
> > > > start = ktime_get();
> > > > stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> > > > do {
> > > > - if (!(ioread32(&priv->cca->req) &
> > > CRB_CTRL_REQ_CMD_READY))
> > > > + req = ioread32(&priv->regs_t->ctrl_req);
> > > > + if (!(req & CRB_CTRL_REQ_CMD_READY))
> > > > return 0;
> > > > usleep_range(50, 100);
> > > > } while (ktime_before(ktime_get(), stop));
> > > >
> > > > - if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
> > > > + if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY)
> > > {
> > > > dev_warn(dev, "cmdReady timed out\n");
> > > > return -ETIME;
> > > > }
> > > > @@ -155,7 +168,7 @@ static u8 crb_status(struct tpm_chip *chip)
> > > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > > u8 sts = 0;
> > > >
> > > > - if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
> > > > + if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) !=
> > > > CRB_START_INVOKE)
> > > > sts |= CRB_DRV_STS_COMPLETE;
> > > >
> > > > @@ -171,7 +184,7 @@ static int crb_recv(struct tpm_chip *chip, u8
> > > > *buf,
> > > size_t count)
> > > > if (count < 6)
> > > > return -EIO;
> > > >
> > > > - if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
> > > > + if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR)
> > > > return -EIO;
> > > >
> > > > memcpy_fromio(buf, priv->rsp, 6); @@ -210,7 +223,7 @@ static int
> > > > crb_send(struct tpm_chip *chip, u8 *buf,
> > > size_t len)
> > > > /* Zero the cancel register so that the next command will not get
> > > > * canceled.
> > > > */
> > > > - iowrite32(0, &priv->cca->cancel);
> > > > + iowrite32(0, &priv->regs_t->ctrl_cancel);
> > > >
> > > > if (len > priv->cmd_size) {
> > > > dev_err(&chip->dev, "invalid command count value %zd %d\n",
> > > @@
> > > > -224,7 +237,7 @@ static int crb_send(struct tpm_chip *chip, u8
> > > > *buf, size_t
> > > len)
> > > > wmb();
> > > >
> > > > if (priv->flags & CRB_FL_CRB_START)
> > > > - iowrite32(CRB_START_INVOKE, &priv->cca->start);
> > > > + iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
> > > >
> > > > if (priv->flags & CRB_FL_ACPI_START)
> > > > rc = crb_do_acpi_start(chip);
> > > > @@ -236,7 +249,7 @@ static void crb_cancel(struct tpm_chip *chip) {
> > > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > >
> > > > - iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel);
> > > > + iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
> > > >
> > > > if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
> > > > dev_err(&chip->dev, "ACPI Start failed\n"); @@ -245,7 +258,7
> > > @@
> > > > static void crb_cancel(struct tpm_chip *chip) static bool
> > > > crb_req_canceled(struct tpm_chip *chip, u8 status) {
> > > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > > - u32 cancel = ioread32(&priv->cca->cancel);
> > > > + u32 cancel = ioread32(&priv->regs_t->ctrl_cancel);
> > > >
> > > > return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; }
> > > @@
> > > > -287,6 +300,8 @@ static void __iomem *crb_map_res(struct device
> > > > *dev,
> > > struct crb_priv *priv,
> > > > if (start != new_res.start)
> > > > return (void __iomem *) ERR_PTR(-EINVAL);
> > > >
> > > > + dev_dbg(dev, "%pr %pr", io_res, &new_res);
> > > > +
> > > > if (!resource_contains(io_res, &new_res))
> > > > return devm_ioremap_resource(dev, &new_res);
> > > >
> > > > @@ -322,10 +337,27 @@ static int crb_map_io(struct acpi_device
> > > > *device,
> > > struct crb_priv *priv,
> > > > if (IS_ERR(priv->iobase))
> > > > return PTR_ERR(priv->iobase);
> > > >
> > > > - priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
> > > > - sizeof(struct crb_control_area));
> > > > - if (IS_ERR(priv->cca))
> > > > - return PTR_ERR(priv->cca);
> > > > + /* The ACPI IO region starts at the head area and continues to include
> > > > + * the control area, as one nice sane region except for some older
> > > > + * stuff that puts the control area outside the ACPI IO region.
> > > > + */
> >
> > This is not by the spec, can you be more specific, what platforms has that
> behavior?
>
> Pre-Skylake (Haswell, Broadwell) does not follow the spec.
Okay, will check what is the issue heere
> > > > + if (!(priv->flags & CRB_FL_ACPI_START)) {
> > > > + if (buf->control_address == io_res.start +
> > > > + sizeof(struct crb_regs_head)) {
> > > > + priv->regs_h = crb_map_res(
> > Why do you need to map this again it just same as iobase ?
>
> crb_map_res() works in a way that it does ioremap only when the range is not
> included to iomem.
Right it does nothing, so why to do so, or I'm missing something?
Tomas
> CC linux-security-module
>
> On Sat, Dec 03, 2016 at 07:52:12PM +0200, Jarkko Sakkinen wrote:
> > Encapsulated crb_wait_for_reg32() so that state changes in other CRB
> > registers than TPM_CRB_CTRL_REQ_x can be waited.
> >
> > Signed-off-by: Jarkko Sakkinen <[email protected]>
> > ---
> > drivers/char/tpm/tpm_crb.c | 37 +++++++++++++++++++++++--------------
> > 1 file changed, 23 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> > index 8d81b66..f986d02 100644
> > --- a/drivers/char/tpm/tpm_crb.c
> > +++ b/drivers/char/tpm/tpm_crb.c
> > @@ -121,6 +121,25 @@ static int __maybe_unused crb_go_idle(struct
> device *dev, struct crb_priv *priv)
> > return 0;
> > }
> >
> > +static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
> > + unsigned long timeout)
> > +{
> > + ktime_t start;
> > + ktime_t stop;
> > +
> > + start = ktime_get();
> > + stop = ktime_add(start, ms_to_ktime(timeout));
> > +
> > + do {
> > + if ((ioread32(reg) & mask) == value)
> > + return true;
> > +
> > + usleep_range(50, 100);
This was tuned for power management, have you tuned it for locality?
> > + } while (ktime_before(ktime_get(), stop));
> > +
> > + return false;
> > +}
> > +
> > /**
> > * crb_cmd_ready - request tpm crb device to enter ready state
> > *
> > @@ -138,24 +157,14 @@ static int __maybe_unused crb_go_idle(struct
> > device *dev, struct crb_priv *priv) static int __maybe_unused
> crb_cmd_ready(struct device *dev,
> > struct crb_priv *priv)
> > {
> > - ktime_t stop, start;
> > - u32 req;
> > -
> > if (priv->flags & CRB_FL_ACPI_START)
> > return 0;
> >
> > iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> > -
> > - start = ktime_get();
> > - stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> > - do {
> > - req = ioread32(&priv->regs_t->ctrl_req);
> > - if (!(req & CRB_CTRL_REQ_CMD_READY))
> > - return 0;
> > - usleep_range(50, 100);
> > - } while (ktime_before(ktime_get(), stop));
> > -
> > - if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY)
> {
> > + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
> > + CRB_CTRL_REQ_CMD_READY /* mask */,
> > + 0, /* value */
> > + TPM2_TIMEOUT_C)) {
> > dev_warn(dev, "cmdReady timed out\n");
> > return -ETIME;
> > }
> > --
> > 2.9.3
> >
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, SlashDot.org! http://sdm.link/slashdot
> _______________________________________________
> tpmdd-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
>
> CC linux-security-module
>
> On Sat, Dec 03, 2016 at 07:52:13PM +0200, Jarkko Sakkinen wrote:
> > Request and relinquish locality for the driver use in order to be a
> > better citizen in a multi locality environment like TXT. The locality
> > is requested and relinquished as part of going into and waking up from
> > idle.
>
This has nothing to do with power management, please note, that this is run via runtime_pm handlers,
which can be disabled via sysfs and actually on server platforms runtime pm is not relevant,
while you cannot disable locality acquire/relinquish flow.
NACK
> > Signed-off-by: Jarkko Sakkinen <[email protected]>
> > ---
> > drivers/char/tpm/tpm_crb.c | 36 ++++++++++++++++++++++++------------
> > 1 file changed, 24 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> > index f986d02..f6e0beb 100644
> > --- a/drivers/char/tpm/tpm_crb.c
> > +++ b/drivers/char/tpm/tpm_crb.c
> > @@ -34,6 +34,15 @@ enum crb_defaults {
> > CRB_ACPI_START_INDEX = 1,
> > };
> >
> > +enum crb_loc_ctrl {
> > + CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
> > + CRB_LOC_CTRL_RELINQUISH = BIT(1),
> > +};
> > +
> > +enum crb_loc_state {
> > + CRB_LOC_STATE_LOC_ASSIGNED = BIT(1),
> > +};
> > +
> > enum crb_ctrl_req {
> > CRB_CTRL_REQ_CMD_READY = BIT(0),
> > CRB_CTRL_REQ_GO_IDLE = BIT(1),
> > @@ -101,12 +110,8 @@ struct crb_priv {
> > * @dev: crb device
> > * @priv: crb private data
> > *
> > - * Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
> > - * The device should respond within TIMEOUT_C by clearing the bit.
> > - * Anyhow, we do not wait here as a consequent CMD_READY request
> > - * will be handled correctly even if idle was not completed.
> > - *
> > - * The function does nothing for devices with ACPI-start method.
> > + * Put device to the idle state and relinquish locality. The function
> > + does
> > + * nothing for devices with the ACPI-start method.
> > *
> > * Return: 0 always
> > */
> > @@ -115,6 +120,7 @@ static int __maybe_unused crb_go_idle(struct device
> *dev, struct crb_priv *priv)
> > if (priv->flags & CRB_FL_ACPI_START)
> > return 0;
> >
> > + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
This is misleading this has nothing to do with go idle, what is the
> > iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> > /* we don't really care when this settles */
> >
> > @@ -146,11 +152,8 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg,
> u32 mask, u32 value,
> > * @dev: crb device
> > * @priv: crb private data
> > *
> > - * Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
> > - * and poll till the device acknowledge it by clearing the bit.
> > - * The device should respond within TIMEOUT_C.
> > - *
> > - * The function does nothing for devices with ACPI-start method
> > + * Try to wake up the device and request locality. The function does
> > + nothing
> > + * for devices with the ACPI-start method.
> > *
> > * Return: 0 on success -ETIME on timeout;
> > */
> > @@ -165,7 +168,16 @@ static int __maybe_unused crb_cmd_ready(struct
> device *dev,
> > CRB_CTRL_REQ_CMD_READY /* mask */,
> > 0, /* value */
> > TPM2_TIMEOUT_C)) {
> > - dev_warn(dev, "cmdReady timed out\n");
> > + dev_warn(dev, "TPM_CRB_CTRL_REQ_x.cmdReady timed
> out\n");
We are always in locality 0 here, right?
> > + return -ETIME;
> > + }
> > +
> > + iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h-
> >loc_ctrl);
> > + if (!crb_wait_for_reg_32(&priv->regs_h->loc_state,
> > + CRB_LOC_STATE_LOC_ASSIGNED, /* mask */
> > + CRB_LOC_STATE_LOC_ASSIGNED, /* value */
> > + TPM2_TIMEOUT_C)) {
> > + dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed
> out\n");
> > return -ETIME;
> > }
On Mon, Dec 05, 2016 at 09:31:57PM +0000, Winkler, Tomas wrote:
> >
> > On Mon, Dec 05, 2016 at 12:07:51PM +0000, Winkler, Tomas wrote:
> > > > > ---
> > > > > drivers/char/tpm/tpm_crb.c | 96
> > > > > ++++++++++++++++++++++++++++++----------------
> > > > > 1 file changed, 64 insertions(+), 32 deletions(-)
> > > > >
> > > > > diff --git a/drivers/char/tpm/tpm_crb.c
> > > > > b/drivers/char/tpm/tpm_crb.c index 717b6b4..8d81b66 100644
> > > > > --- a/drivers/char/tpm/tpm_crb.c
> > > > > +++ b/drivers/char/tpm/tpm_crb.c
> > > > > @@ -52,18 +52,28 @@ enum crb_cancel {
> > > > > CRB_CANCEL_INVOKE = BIT(0),
> > > > > };
> > > > >
> > > > > -struct crb_control_area {
> > > > > - u32 req;
> > > > > - u32 sts;
> > > > > - u32 cancel;
> > > > > - u32 start;
> > > > > - u32 int_enable;
> > > > > - u32 int_sts;
> > > > > - u32 cmd_size;
> > > > > - u32 cmd_pa_low;
> > > > > - u32 cmd_pa_high;
> > > > > - u32 rsp_size;
> > > > > - u64 rsp_pa;
> > > > > +struct crb_regs_head {
> > > > > + u32 loc_state;
> > > > > + u32 reserved1;
> > > > > + u32 loc_ctrl;
> > > > > + u32 loc_sts;
> > > > > + u8 reserved2[32];
> > > > > + u64 intf_id;
> > > > > + u64 ctrl_ext;
> > > > > +} __packed;
> > > > > +
> > > > > +struct crb_regs_tail {
> > > > > + u32 ctrl_req;
> > > > > + u32 ctrl_sts;
> > > > > + u32 ctrl_cancel;
> > > > > + u32 ctrl_start;
> > > > > + u32 ctrl_int_enable;
> > > > > + u32 ctrl_int_sts;
> > > > > + u32 ctrl_cmd_size;
> > > > > + u32 ctrl_cmd_pa_low;
> > > > > + u32 ctrl_cmd_pa_high;
> > > > > + u32 ctrl_rsp_size;
> > > > > + u64 ctrl_rsp_pa;
> > > > > } __packed;
> > >
> > >
> > > Now I wonder if using traditional offsets wouldn't be cleaner solution.
> >
> > I'm not sure what you are trying to say.
>
> Such as iowrite32(val, base + offset)
I rather stick using structures. I do not see the point to turn things
around.
>
> >
> > > > > enum crb_status {
> > > > > @@ -78,7 +88,8 @@ enum crb_flags { struct crb_priv {
> > > > > unsigned int flags;
> > > > > void __iomem *iobase;
> > > > > - struct crb_control_area __iomem *cca;
> > > > > + struct crb_regs_head __iomem *regs_h;
> > > > > + struct crb_regs_tail __iomem *regs_t;
> > > Why just not leaving it cca, it's descriptive enough.
> > > > > u8 __iomem *cmd;
> > > > > u8 __iomem *rsp;
> > > > > u32 cmd_size;
> > > > > @@ -104,7 +115,7 @@ static int __maybe_unused crb_go_idle(struct
> > > > > device
> > > > *dev, struct crb_priv *priv)
> > > > > if (priv->flags & CRB_FL_ACPI_START)
> > > > > return 0;
> > > > >
> > > > > - iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
> > > > > + iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> > > > > /* we don't really care when this settles */
> > > > >
> > > > > return 0;
> > > > > @@ -128,21 +139,23 @@ static int __maybe_unused
> > > > > crb_cmd_ready(struct
> > > > device *dev,
> > > > > struct crb_priv *priv)
> > > > > {
> > > > > ktime_t stop, start;
> > > > > + u32 req;
> > > > >
> > > > > if (priv->flags & CRB_FL_ACPI_START)
> > > > > return 0;
> > > > >
> > > > > - iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
> > > > > + iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> > > > >
> > > > > start = ktime_get();
> > > > > stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> > > > > do {
> > > > > - if (!(ioread32(&priv->cca->req) &
> > > > CRB_CTRL_REQ_CMD_READY))
> > > > > + req = ioread32(&priv->regs_t->ctrl_req);
> > > > > + if (!(req & CRB_CTRL_REQ_CMD_READY))
> > > > > return 0;
> > > > > usleep_range(50, 100);
> > > > > } while (ktime_before(ktime_get(), stop));
> > > > >
> > > > > - if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
> > > > > + if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY)
> > > > {
> > > > > dev_warn(dev, "cmdReady timed out\n");
> > > > > return -ETIME;
> > > > > }
> > > > > @@ -155,7 +168,7 @@ static u8 crb_status(struct tpm_chip *chip)
> > > > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > > > u8 sts = 0;
> > > > >
> > > > > - if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
> > > > > + if ((ioread32(&priv->regs_t->ctrl_start) & CRB_START_INVOKE) !=
> > > > > CRB_START_INVOKE)
> > > > > sts |= CRB_DRV_STS_COMPLETE;
> > > > >
> > > > > @@ -171,7 +184,7 @@ static int crb_recv(struct tpm_chip *chip, u8
> > > > > *buf,
> > > > size_t count)
> > > > > if (count < 6)
> > > > > return -EIO;
> > > > >
> > > > > - if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR)
> > > > > + if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR)
> > > > > return -EIO;
> > > > >
> > > > > memcpy_fromio(buf, priv->rsp, 6); @@ -210,7 +223,7 @@ static int
> > > > > crb_send(struct tpm_chip *chip, u8 *buf,
> > > > size_t len)
> > > > > /* Zero the cancel register so that the next command will not get
> > > > > * canceled.
> > > > > */
> > > > > - iowrite32(0, &priv->cca->cancel);
> > > > > + iowrite32(0, &priv->regs_t->ctrl_cancel);
> > > > >
> > > > > if (len > priv->cmd_size) {
> > > > > dev_err(&chip->dev, "invalid command count value %zd %d\n",
> > > > @@
> > > > > -224,7 +237,7 @@ static int crb_send(struct tpm_chip *chip, u8
> > > > > *buf, size_t
> > > > len)
> > > > > wmb();
> > > > >
> > > > > if (priv->flags & CRB_FL_CRB_START)
> > > > > - iowrite32(CRB_START_INVOKE, &priv->cca->start);
> > > > > + iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
> > > > >
> > > > > if (priv->flags & CRB_FL_ACPI_START)
> > > > > rc = crb_do_acpi_start(chip);
> > > > > @@ -236,7 +249,7 @@ static void crb_cancel(struct tpm_chip *chip) {
> > > > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > > >
> > > > > - iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel);
> > > > > + iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
> > > > >
> > > > > if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
> > > > > dev_err(&chip->dev, "ACPI Start failed\n"); @@ -245,7 +258,7
> > > > @@
> > > > > static void crb_cancel(struct tpm_chip *chip) static bool
> > > > > crb_req_canceled(struct tpm_chip *chip, u8 status) {
> > > > > struct crb_priv *priv = dev_get_drvdata(&chip->dev);
> > > > > - u32 cancel = ioread32(&priv->cca->cancel);
> > > > > + u32 cancel = ioread32(&priv->regs_t->ctrl_cancel);
> > > > >
> > > > > return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; }
> > > > @@
> > > > > -287,6 +300,8 @@ static void __iomem *crb_map_res(struct device
> > > > > *dev,
> > > > struct crb_priv *priv,
> > > > > if (start != new_res.start)
> > > > > return (void __iomem *) ERR_PTR(-EINVAL);
> > > > >
> > > > > + dev_dbg(dev, "%pr %pr", io_res, &new_res);
> > > > > +
> > > > > if (!resource_contains(io_res, &new_res))
> > > > > return devm_ioremap_resource(dev, &new_res);
> > > > >
> > > > > @@ -322,10 +337,27 @@ static int crb_map_io(struct acpi_device
> > > > > *device,
> > > > struct crb_priv *priv,
> > > > > if (IS_ERR(priv->iobase))
> > > > > return PTR_ERR(priv->iobase);
> > > > >
> > > > > - priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
> > > > > - sizeof(struct crb_control_area));
> > > > > - if (IS_ERR(priv->cca))
> > > > > - return PTR_ERR(priv->cca);
> > > > > + /* The ACPI IO region starts at the head area and continues to include
> > > > > + * the control area, as one nice sane region except for some older
> > > > > + * stuff that puts the control area outside the ACPI IO region.
> > > > > + */
> > >
> > > This is not by the spec, can you be more specific, what platforms has that
> > behavior?
> >
> > Pre-Skylake (Haswell, Broadwell) does not follow the spec.
>
> Okay, will check what is the issue heere
> > > > > + if (!(priv->flags & CRB_FL_ACPI_START)) {
> > > > > + if (buf->control_address == io_res.start +
> > > > > + sizeof(struct crb_regs_head)) {
> > > > > + priv->regs_h = crb_map_res(
> > > Why do you need to map this again it just same as iobase ?
> >
> > crb_map_res() works in a way that it does ioremap only when the range is not
> > included to iomem.
>
> Right it does nothing, so why to do so, or I'm missing something?
> Tomas
Yes, in this case using the wrapper is not necessity. I can change that
to assignment.
/Jarkko
On Mon, Dec 05, 2016 at 09:34:50PM +0000, Winkler, Tomas wrote:
> > CC linux-security-module
> >
> > On Sat, Dec 03, 2016 at 07:52:12PM +0200, Jarkko Sakkinen wrote:
> > > Encapsulated crb_wait_for_reg32() so that state changes in other CRB
> > > registers than TPM_CRB_CTRL_REQ_x can be waited.
> > >
> > > Signed-off-by: Jarkko Sakkinen <[email protected]>
> > > ---
> > > drivers/char/tpm/tpm_crb.c | 37 +++++++++++++++++++++++--------------
> > > 1 file changed, 23 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> > > index 8d81b66..f986d02 100644
> > > --- a/drivers/char/tpm/tpm_crb.c
> > > +++ b/drivers/char/tpm/tpm_crb.c
> > > @@ -121,6 +121,25 @@ static int __maybe_unused crb_go_idle(struct
> > device *dev, struct crb_priv *priv)
> > > return 0;
> > > }
> > >
> > > +static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
> > > + unsigned long timeout)
> > > +{
> > > + ktime_t start;
> > > + ktime_t stop;
> > > +
> > > + start = ktime_get();
> > > + stop = ktime_add(start, ms_to_ktime(timeout));
> > > +
> > > + do {
> > > + if ((ioread32(reg) & mask) == value)
> > > + return true;
> > > +
> > > + usleep_range(50, 100);
> This was tuned for power management, have you tuned it for locality?
We don't want million different wait functions and the current values
work without issues for locale.
/Jarkko
> > > + } while (ktime_before(ktime_get(), stop));
> > > +
> > > + return false;
> > > +}
> > > +
> > > /**
> > > * crb_cmd_ready - request tpm crb device to enter ready state
> > > *
> > > @@ -138,24 +157,14 @@ static int __maybe_unused crb_go_idle(struct
> > > device *dev, struct crb_priv *priv) static int __maybe_unused
> > crb_cmd_ready(struct device *dev,
> > > struct crb_priv *priv)
> > > {
> > > - ktime_t stop, start;
> > > - u32 req;
> > > -
> > > if (priv->flags & CRB_FL_ACPI_START)
> > > return 0;
> > >
> > > iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
> > > -
> > > - start = ktime_get();
> > > - stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
> > > - do {
> > > - req = ioread32(&priv->regs_t->ctrl_req);
> > > - if (!(req & CRB_CTRL_REQ_CMD_READY))
> > > - return 0;
> > > - usleep_range(50, 100);
> > > - } while (ktime_before(ktime_get(), stop));
> > > -
> > > - if (ioread32(&priv->regs_t->ctrl_req) & CRB_CTRL_REQ_CMD_READY)
> > {
> > > + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
> > > + CRB_CTRL_REQ_CMD_READY /* mask */,
> > > + 0, /* value */
> > > + TPM2_TIMEOUT_C)) {
> > > dev_warn(dev, "cmdReady timed out\n");
> > > return -ETIME;
> > > }
> > > --
> > > 2.9.3
> > >
> >
> > ------------------------------------------------------------------------------
> > Check out the vibrant tech community on one of the world's most
> > engaging tech sites, SlashDot.org! http://sdm.link/slashdot
> > _______________________________________________
> > tpmdd-devel mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
On Mon, Dec 05, 2016 at 09:51:42PM +0000, Winkler, Tomas wrote:
> >
> > CC linux-security-module
> >
> > On Sat, Dec 03, 2016 at 07:52:13PM +0200, Jarkko Sakkinen wrote:
> > > Request and relinquish locality for the driver use in order to be a
> > > better citizen in a multi locality environment like TXT. The locality
> > > is requested and relinquished as part of going into and waking up from
> > > idle.
> >
> This has nothing to do with power management, please note, that this is run via runtime_pm handlers,
> which can be disabled via sysfs and actually on server platforms runtime pm is not relevant,
> while you cannot disable locality acquire/relinquish flow.
>
> NACK
Good point. I'll move it as part of tpm_transmit()
/Jarkko
> > > Signed-off-by: Jarkko Sakkinen <[email protected]>
> > > ---
> > > drivers/char/tpm/tpm_crb.c | 36 ++++++++++++++++++++++++------------
> > > 1 file changed, 24 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> > > index f986d02..f6e0beb 100644
> > > --- a/drivers/char/tpm/tpm_crb.c
> > > +++ b/drivers/char/tpm/tpm_crb.c
> > > @@ -34,6 +34,15 @@ enum crb_defaults {
> > > CRB_ACPI_START_INDEX = 1,
> > > };
> > >
> > > +enum crb_loc_ctrl {
> > > + CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
> > > + CRB_LOC_CTRL_RELINQUISH = BIT(1),
> > > +};
> > > +
> > > +enum crb_loc_state {
> > > + CRB_LOC_STATE_LOC_ASSIGNED = BIT(1),
> > > +};
> > > +
> > > enum crb_ctrl_req {
> > > CRB_CTRL_REQ_CMD_READY = BIT(0),
> > > CRB_CTRL_REQ_GO_IDLE = BIT(1),
> > > @@ -101,12 +110,8 @@ struct crb_priv {
> > > * @dev: crb device
> > > * @priv: crb private data
> > > *
> > > - * Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
> > > - * The device should respond within TIMEOUT_C by clearing the bit.
> > > - * Anyhow, we do not wait here as a consequent CMD_READY request
> > > - * will be handled correctly even if idle was not completed.
> > > - *
> > > - * The function does nothing for devices with ACPI-start method.
> > > + * Put device to the idle state and relinquish locality. The function
> > > + does
> > > + * nothing for devices with the ACPI-start method.
> > > *
> > > * Return: 0 always
> > > */
> > > @@ -115,6 +120,7 @@ static int __maybe_unused crb_go_idle(struct device
> > *dev, struct crb_priv *priv)
> > > if (priv->flags & CRB_FL_ACPI_START)
> > > return 0;
> > >
> > > + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
> This is misleading this has nothing to do with go idle, what is the
> > > iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
> > > /* we don't really care when this settles */
> > >
> > > @@ -146,11 +152,8 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg,
> > u32 mask, u32 value,
> > > * @dev: crb device
> > > * @priv: crb private data
> > > *
> > > - * Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
> > > - * and poll till the device acknowledge it by clearing the bit.
> > > - * The device should respond within TIMEOUT_C.
> > > - *
> > > - * The function does nothing for devices with ACPI-start method
> > > + * Try to wake up the device and request locality. The function does
> > > + nothing
> > > + * for devices with the ACPI-start method.
> > > *
> > > * Return: 0 on success -ETIME on timeout;
> > > */
> > > @@ -165,7 +168,16 @@ static int __maybe_unused crb_cmd_ready(struct
> > device *dev,
> > > CRB_CTRL_REQ_CMD_READY /* mask */,
> > > 0, /* value */
> > > TPM2_TIMEOUT_C)) {
> > > - dev_warn(dev, "cmdReady timed out\n");
> > > + dev_warn(dev, "TPM_CRB_CTRL_REQ_x.cmdReady timed
> > out\n");
> We are always in locality 0 here, right?
>
> > > + return -ETIME;
> > > + }
> > > +
> > > + iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h-
> > >loc_ctrl);
> > > + if (!crb_wait_for_reg_32(&priv->regs_h->loc_state,
> > > + CRB_LOC_STATE_LOC_ASSIGNED, /* mask */
> > > + CRB_LOC_STATE_LOC_ASSIGNED, /* value */
> > > + TPM2_TIMEOUT_C)) {
> > > + dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed
> > out\n");
>
>
> > > return -ETIME;
> > > }
>
>
On Mon, Dec 05, 2016 at 09:32:35AM -0700, Jason Gunthorpe wrote:
> On Sat, Dec 03, 2016 at 07:52:13PM +0200, Jarkko Sakkinen wrote:
> > + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
>
> Since regs_h can be null shouldn't there be some guards ?
Yes, there should. Thanks for pointing this out!
/Jarkko