qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: What is TYPE_TPM_TIS_ISA? (Not an ISA Device)


From: Markus Armbruster
Subject: Re: What is TYPE_TPM_TIS_ISA? (Not an ISA Device)
Date: Thu, 23 Jul 2020 11:10:29 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux)

Stefan Berger <stefanb@linux.ibm.com> writes:

> On 7/22/20 1:55 AM, Markus Armbruster wrote:
>> pm socket --tpmstate dir=tpm --ctrl type=unixio,path=tpm/swtpm-soc
>> running in another terminal.
>>
>>>> 3/ no machine plug it using isa_register_ioport()
>>>>     (it is not registered to the ISA memory space)
>>> There's no requirement for an ISA device to have IO ports...
>>>
>>> thanks
>>> -- PMM
>> Thread hijack!  Since I didn't have swtpm installed, I tried to take a
>> shortcut:
>>
>>      $ qemu-system-x86_64 -nodefaults -S -display none -monitor stdio 
>> -chardev null,id=tpm0 -tpmdev emulator,id=tpm0,chardev=chrtpm -device 
>> tpm-tis,tpmdev=tpm0
>>      qemu-system-x86_64: -tpmdev emulator,id=tpm0,chardev=chrtpm: 
>> tpm-emulator: tpm chardev 'chrtpm' not found.
>>      qemu-system-x86_64: -tpmdev emulator,id=tpm0,chardev=chrtpm: 
>> tpm-emulator: Could not cleanly shutdown the TPM: No such file or directory
>>      QEMU 5.0.90 monitor - type 'help' for more information
>>      (qemu) qemu-system-x86_64: -device tpm-tis,tpmdev=tpm0: Property 
>> 'tpm-tis.tpmdev' can't find value 'tpm0'
>>      $ echo $?
>>      1
>>
>> That a null chardev doesn't work is fine.  But the error handling looks
>> broken: QEMU diagnoses and reports the problem, then continues.  The
>> final error message indicates that it continued without creating the
>> backend "tpm0".  That's wrong.
>
>
> This issue can be solve via the following change that then displays
> this error:
>
> $ x86_64-softmmu/qemu-system-x86_64 -nodefaults -S -display none
> -monitor stdio -chardev null,id=tpm0 -tpmdev
> emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0
> qemu-system-x86_64: -tpmdev emulator,id=tpm0,chardev=chrtpm:
> tpm-emulator: tpm chardev 'chrtpm' not found.
> qemu-system-x86_64: -tpmdev emulator,id=tpm0,chardev=chrtpm:
> tpm-emulator: Could not cleanly shutdown the TPM: No such file or
> directory
>
>
> diff --git a/tpm.c b/tpm.c
> index 358566cb10..857a861e69 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -170,8 +170,10 @@ void tpm_cleanup(void)
>   */
>  void tpm_init(void)
>  {
> -    qemu_opts_foreach(qemu_find_opts("tpmdev"),
> -                      tpm_init_tpmdev, NULL, &error_fatal);
> +    if (qemu_opts_foreach(qemu_find_opts("tpmdev"),
> +                          tpm_init_tpmdev, NULL, &error_fatal)) {
> +        exit(1);
> +    }
>  }
>
>  /*

Interesting.

> We had something like this before this patch here was applied:
> https://github.com/qemu/qemu/commit/d10e05f15d5c3dd5e5cc59c5dfff460d89d48580#diff-0ec5df49c6751cb2dc9fa18ed5cf9f0e
>
>
> Do we now want to partially revert this patch or call the exit(1) as
> shown here?

Let's have a closer look.

qemu_opts_foreach()'s contract:

 * For each member of @list, call @func(@opaque, member, @errp).
 * Call it with the current location temporarily set to the member's.
 * @func() may store an Error through @errp, but must return non-zero then.
 * When @func() returns non-zero, break the loop and return that value.
 * Return zero when the loop completes.

When qemu_opts_foreach(list, func, opaque, &error_fatal) returns, then
func() did not set an error (If it did, we'd have died due to
&error_fatal).

Therefore, func() must have returned non-zero without setting an error.
That's wrong.  Let's look for this in tpm_init_tpmdev():

    static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp)
    {
        [...]
        drv = be->create(opts);
        if (!drv) {
            return 1;

Bingo!

When I did commit d10e05f15d5, I missed this error path.

        }

        drv->id = g_strdup(id);
        QLIST_INSERT_HEAD(&tpm_backends, drv, list);

        return 0;
    }

Two possible fixes:

1. Revert d10e05f15d5, live with the "error_report() in a function that
takes an Error ** argument" code smell.  Bearable, because it's confined
to tpm.c.  I'd recommend a comment explaining the non-use of @errp in
tpm_init_tpmdev().

2. Convert the ->create() to Error: tpm_passthrough_create(),
tpm_emulator_create(), and their helpers.  I think this would leave us
in a better state, but I'm not sure the improvement is worth the effort
right now.

Spotted while writing this: ->tpm_startup() methods can fail.  They
appear to run in DeviceClass method reset(), which can't fail.
Awkward.  Could some failures be moved to realize() somehow?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]