Page MenuHomeFreeBSD

bhyve/tpm: add emulation for crb register
ClosedPublic

Authored by corvink on Jun 7 2023, 12:05 PM.
Tags
None
Referenced Files
F83910563: D40459.id125689.diff
Thu, May 16, 7:26 PM
Unknown Object (File)
Fri, May 3, 9:32 AM
Unknown Object (File)
Thu, May 2, 10:46 PM
Unknown Object (File)
Thu, May 2, 10:46 PM
Unknown Object (File)
Thu, May 2, 10:46 PM
Unknown Object (File)
Thu, May 2, 10:46 PM
Unknown Object (File)
Thu, May 2, 10:45 PM
Unknown Object (File)
Thu, May 2, 9:10 PM
Subscribers

Details

Summary

This commit only adds the emulation. It doesn't enable the trap to those
registers. Enabling the trap yet, isn't possible. A tpm passthru device
maps the mmio region of the physical tpm device into the guest memory.
This mapping conflicts with the trap. A future commit will add the trap.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

usr.sbin/bhyve/tpm_intf_crb.c
299

Is it not important to validate the size of the write?

317

mr.name doesn't get copied. It'll become a pointer to stack garbage once this function returns.

329

"rw mutex" sounds like this should be a reader/writer lock, but presumably the mutex is really meant to serialize MMIO operations? Maybe mmio_mutex would be a better name?

354

The comment doesn't explain why.

corvink marked 4 inline comments as done.
corvink added inline comments.
usr.sbin/bhyve/tpm_intf_crb.c
329

I've rechecked the usage of the mutex. It was useless as mem.c:access_memory already locks on mmio accesses.

usr.sbin/bhyve/tpm_intf_crb.c
273

This can be replaced with

if (!(size == 1 || size == 2 || size == 4 || size == 8))
    return (EINVAL);
memcpy(dst, src, size);
291

Why bother trying to handle unaligned accesses at all? The code below becomes more complicated as a result (you need this is_offsetof macro), and its behaviour is hard to reason about.

348

warn/warnx don't need trailing newlines.

369

Suppose that the thread is currently processing a command. When it's done, it'll re-acquire the lock, then set crb->regs.ctrl_start.start = false, then go to sleep, so the signal is not acknowledged. Presumably that's not what we want here?

381
415

This can be defined on the stack. register_mem() just makes a copy of it, so there's no need for this to be a global variable.

corvink added inline comments.
usr.sbin/bhyve/tpm_intf_crb.c
369

When the thread is processing a command, the write is ignored by

			if (!start.start || crb->regs.ctrl_start.start)
				break;

That's the required behaviour by the TPM specification https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf

1. On a write of 0001h to the Start field:
   a. If the TPM is in the Command Reception state, the TPM SHALL transition to Command Execution and begin processing the command in the buffer.
   b. If the TPM is in any other State, the TPM SHALL ignore the write.
2. The TPM SHALL ignore writes of 0 to this field.
3. When the TPM completes command processing, the TPM SHALL clear this field to 0000h and transition to Command Completion.
corvink marked an inline comment as done.
  • address feedback from markj
usr.sbin/bhyve/tpm_intf_crb.c
369

Ok. Shouldn't we acquire the mutex before calling tpm_crb_mmiocpy() and checking !start.start || crb->regs.ctrl_start.start though?

usr.sbin/bhyve/tpm_intf_crb.c
369

I don't have a strong preference on that. The crb thread is only accessing cmd_size, cmd_addr, rsp_size, rsp_addr and data_buffer. My patch already acquires the mutex for accesses to those register.

usr.sbin/bhyve/tpm_intf_crb.c
369

I think it would be better to avoid the data race nonetheless.

  • acquire crb->mutex before writing and reading ctrl_start
usr.sbin/bhyve/tpm_intf_crb.c
366
369
397

Should this return error?

corvink marked an inline comment as done.
  • apply correct diff
This revision is now accepted and ready to land.Aug 9 2023, 8:48 PM