diff mbox series

[RFC,v2,12/12] i386/sev: update query-sev QAPI format to handle SEV-SNP

Message ID 20210826222627.3556-13-michael.roth@amd.com (mailing list archive)
State New, archived
Headers show
Series Add AMD Secure Nested Paging (SEV-SNP) support | expand

Commit Message

Michael Roth Aug. 26, 2021, 10:26 p.m. UTC
Most of the current 'query-sev' command is relevant to both legacy
SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:

  - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
    the meaning of the bit positions has changed
  - 'handle' is not relevant to SEV-SNP

To address this, this patch adds a new 'sev-type' field that can be
used as a discriminator to select between SEV and SEV-SNP-specific
fields/formats without breaking compatibility for existing management
tools (so long as management tools that add support for launching
SEV-SNP guest update their handling of query-sev appropriately).

The corresponding HMP command has also been fixed up similarly.

Signed-off-by: Michael Roth <michael.roth@amd.com>
---
 qapi/misc-target.json  | 71 +++++++++++++++++++++++++++++++++---------
 target/i386/monitor.c  | 29 +++++++++++++----
 target/i386/sev.c      | 22 +++++++------
 target/i386/sev_i386.h |  3 ++
 4 files changed, 95 insertions(+), 30 deletions(-)

Comments

Michael Roth Sept. 3, 2021, 3:13 p.m. UTC | #1
On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> Michael Roth <michael.roth@amd.com> writes:
> 
> > Most of the current 'query-sev' command is relevant to both legacy
> > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> >
> >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> >     the meaning of the bit positions has changed
> >   - 'handle' is not relevant to SEV-SNP
> >
> > To address this, this patch adds a new 'sev-type' field that can be
> > used as a discriminator to select between SEV and SEV-SNP-specific
> > fields/formats without breaking compatibility for existing management
> > tools (so long as management tools that add support for launching
> > SEV-SNP guest update their handling of query-sev appropriately).
> 
> Technically a compatibility break: query-sev can now return an object
> that whose member @policy has different meaning, and also lacks @handle.
> 
> Matrix:
> 
>                             Old mgmt app    New mgmt app
>     Old QEMU, SEV/SEV-ES       good            good(1)
>     New QEMU, SEV/SEV-ES       good(2)         good
>     New QEMU, SEV-SNP           bad(3)         good
> 
> Notes:
> 
> (1) As long as the management application can cope with absent member
> @sev-type.
> 
> (2) As long as the management application ignores unknown member
> @sev-type.
> 
> (3) Management application may choke on missing member @handle, or
> worse, misinterpret member @policy.  Can only happen when something
> other than the management application created the SEV-SNP guest (or the
> user somehow made the management application create one even though it
> doesn't know how, say with CLI option passthrough, but that's always
> fragile, and I wouldn't worry about it here).
> 
> I think (1) and (2) are reasonable.  (3) is an issue for management
> applications that support attaching to existing guests.  Thoughts?

Hmm... yah I hadn't considering 'old mgmt' trying to interact with a SNP
guest started through some other means.

Don't really see an alternative other than introducing a new
'query-sev-snp', but that would still leave 'old mgmt' broken, since
it might still call do weird stuff like try to interpret the SNP policy
as an SEV/SEV-ES and end up with some very unexpected results. So if I
did go this route, I would need to have QMP begin returning an error if
query-sev is run against an SNP guest. But currently for non-SEV guests
it already does:

  error_setg(errp, "SEV feature is not available")

so 'old mgmt' should be able to handle the error just fine.

Would that approach be reasonable?
Daniel P. Berrangé Sept. 3, 2021, 3:27 p.m. UTC | #2
On Thu, Aug 26, 2021 at 05:26:27PM -0500, Michael Roth wrote:
> Most of the current 'query-sev' command is relevant to both legacy
> SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> 
>   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
>     the meaning of the bit positions has changed
>   - 'handle' is not relevant to SEV-SNP

If the host supports SEV-SNP guests, is it still possible for mgmt
app to create guests using the  "legacy" SEV/SEV-ES approach ? ie
is the hardware backwards compatible, or is it strictly required
to always create SEV-SNP guests when the hardware is capable ?

The code here seems to imply a non-backwards compatible approach,
mandating use of SEV-SNP guests on such capable kernel/hardware.

> To address this, this patch adds a new 'sev-type' field that can be
> used as a discriminator to select between SEV and SEV-SNP-specific
> fields/formats without breaking compatibility for existing management
> tools (so long as management tools that add support for launching
> SEV-SNP guest update their handling of query-sev appropriately).
> 
> The corresponding HMP command has also been fixed up similarly.
> 
> Signed-off-by: Michael Roth <michael.roth@amd.com>
> ---
>  qapi/misc-target.json  | 71 +++++++++++++++++++++++++++++++++---------
>  target/i386/monitor.c  | 29 +++++++++++++----
>  target/i386/sev.c      | 22 +++++++------
>  target/i386/sev_i386.h |  3 ++
>  4 files changed, 95 insertions(+), 30 deletions(-)
> 
> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> index 3b05ad3dbf..80f994ff9b 100644
> --- a/qapi/misc-target.json
> +++ b/qapi/misc-target.json
> @@ -81,6 +81,49 @@
>             'send-update', 'receive-update' ],
>    'if': 'TARGET_I386' }
>  
> +##
> +# @SevGuestType:
> +#
> +# An enumeration indicating the type of SEV guest being run.
> +#
> +# @sev:     The guest is a legacy SEV or SEV-ES guest.
> +# @sev-snp: The guest is an SEV-SNP guest.
> +#
> +# Since: 6.2
> +##
> +{ 'enum': 'SevGuestType',
> +  'data': [ 'sev', 'sev-snp' ],
> +  'if': 'TARGET_I386' }
> +
> +##
> +# @SevGuestInfo:
> +#
> +# Information specific to legacy SEV/SEV-ES guests.
> +#
> +# @policy: SEV policy value
> +#
> +# @handle: SEV firmware handle
> +#
> +# Since: 2.12
> +##
> +{ 'struct': 'SevGuestInfo',
> +  'data': { 'policy': 'uint32',
> +            'handle': 'uint32' },
> +  'if': 'TARGET_I386' }
> +
> +##
> +# @SevSnpGuestInfo:
> +#
> +# Information specific to SEV-SNP guests.
> +#
> +# @policy: SEV-SNP policy value
> +#
> +# Since: 6.2
> +##
> +{ 'struct': 'SevSnpGuestInfo',
> +  'data': { 'policy': 'uint64' },
> +  'if': 'TARGET_I386' }
> +
>  ##
>  # @SevInfo:
>  #
> @@ -94,25 +137,25 @@
>  #
>  # @build-id: SEV FW build id
>  #
> -# @policy: SEV policy value
> -#
>  # @state: SEV guest state
>  #
> -# @handle: SEV firmware handle
> +# @sev-type: Type of SEV guest being run
>  #
>  # Since: 2.12
>  ##
> -{ 'struct': 'SevInfo',
> -    'data': { 'enabled': 'bool',
> -              'api-major': 'uint8',
> -              'api-minor' : 'uint8',
> -              'build-id' : 'uint8',
> -              'policy' : 'uint32',
> -              'state' : 'SevState',
> -              'handle' : 'uint32'
> -            },
> -  'if': 'TARGET_I386'
> -}
> +{ 'union': 'SevInfo',
> +  'base': { 'enabled': 'bool',
> +            'api-major': 'uint8',
> +            'api-minor' : 'uint8',
> +            'build-id' : 'uint8',
> +            'state' : 'SevState',
> +            'sev-type' : 'SevGuestType' },
> +  'discriminator': 'sev-type',
> +  'data': {
> +      'sev': 'SevGuestInfo',
> +      'sev-snp': 'SevSnpGuestInfo' },
> +  'if': 'TARGET_I386' }
> +
>  
>  ##
>  # @query-sev:
> diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> index 119211f0b0..85a8bc2bef 100644
> --- a/target/i386/monitor.c
> +++ b/target/i386/monitor.c
> @@ -692,20 +692,37 @@ void hmp_info_sev(Monitor *mon, const QDict *qdict)
>  {
>      SevInfo *info = sev_get_info();
>  
> -    if (info && info->enabled) {
> -        monitor_printf(mon, "handle: %d\n", info->handle);
> +    if (!info || !info->enabled) {
> +        monitor_printf(mon, "SEV is not enabled\n");
> +        goto out;
> +    }
> +
> +    if (sev_snp_enabled()) {
>          monitor_printf(mon, "state: %s\n", SevState_str(info->state));
>          monitor_printf(mon, "build: %d\n", info->build_id);
>          monitor_printf(mon, "api version: %d.%d\n",
>                         info->api_major, info->api_minor);
>          monitor_printf(mon, "debug: %s\n",
> -                       info->policy & SEV_POLICY_NODBG ? "off" : "on");
> -        monitor_printf(mon, "key-sharing: %s\n",
> -                       info->policy & SEV_POLICY_NOKS ? "off" : "on");
> +                       info->u.sev_snp.policy & SEV_SNP_POLICY_DBG ? "on"
> +                                                                   : "off");
> +        monitor_printf(mon, "SMT allowed: %s\n",
> +                       info->u.sev_snp.policy & SEV_SNP_POLICY_SMT ? "on"
> +                                                                   : "off");
> +        monitor_printf(mon, "SEV type: %s\n", SevGuestType_str(info->sev_type));
>      } else {
> -        monitor_printf(mon, "SEV is not enabled\n");
> +        monitor_printf(mon, "handle: %d\n", info->u.sev.handle);
> +        monitor_printf(mon, "state: %s\n", SevState_str(info->state));
> +        monitor_printf(mon, "build: %d\n", info->build_id);
> +        monitor_printf(mon, "api version: %d.%d\n",
> +                       info->api_major, info->api_minor);
> +        monitor_printf(mon, "debug: %s\n",
> +                       info->u.sev.policy & SEV_POLICY_NODBG ? "off" : "on");
> +        monitor_printf(mon, "key-sharing: %s\n",
> +                       info->u.sev.policy & SEV_POLICY_NOKS ? "off" : "on");
> +        monitor_printf(mon, "SEV type: %s\n", SevGuestType_str(info->sev_type));
>      }
>  
> +out:
>      qapi_free_SevInfo(info);
>  }
>  
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index 72a6146295..fac2755e68 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -704,25 +704,27 @@ sev_get_info(void)
>  {
>      SevInfo *info;
>      SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
> -    SevGuestState *sev_guest =
> -        (SevGuestState *)object_dynamic_cast(OBJECT(sev_common),
> -                                             TYPE_SEV_GUEST);
>  
>      info = g_new0(SevInfo, 1);
>      info->enabled = sev_enabled();
>  
>      if (info->enabled) {
> -        if (sev_guest) {
> -            info->handle = sev_guest->handle;
> -        }
>          info->api_major = sev_common->api_major;
>          info->api_minor = sev_common->api_minor;
>          info->build_id = sev_common->build_id;
>          info->state = sev_common->state;
> -        /* we only report the lower 32-bits of policy for SNP, ok for now... */
> -        info->policy =
> -            (uint32_t)object_property_get_uint(OBJECT(sev_common),
> -                                               "policy", NULL);
> +
> +        if (sev_snp_enabled()) {
> +            info->sev_type = SEV_GUEST_TYPE_SEV_SNP;
> +            info->u.sev_snp.policy =
> +                object_property_get_uint(OBJECT(sev_common), "policy", NULL);
> +        } else {
> +            info->sev_type = SEV_GUEST_TYPE_SEV;
> +            info->u.sev.handle = SEV_GUEST(sev_common)->handle;
> +            info->u.sev.policy =
> +                (uint32_t)object_property_get_uint(OBJECT(sev_common),
> +                                                   "policy", NULL);
> +        }
>      }
>  
>      return info;
> diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h
> index e0e1a599be..948d8f1079 100644
> --- a/target/i386/sev_i386.h
> +++ b/target/i386/sev_i386.h
> @@ -28,6 +28,9 @@
>  #define SEV_POLICY_DOMAIN       0x10
>  #define SEV_POLICY_SEV          0x20
>  
> +#define SEV_SNP_POLICY_SMT      0x10000
> +#define SEV_SNP_POLICY_DBG      0x80000
> +
>  extern bool sev_es_enabled(void);
>  extern bool sev_snp_enabled(void);
>  extern uint64_t sev_get_me_mask(void);
> -- 
> 2.25.1
> 

Regards,
Daniel
Daniel P. Berrangé Sept. 3, 2021, 3:30 p.m. UTC | #3
On Fri, Sep 03, 2021 at 10:13:16AM -0500, Michael Roth wrote:
> On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> > Michael Roth <michael.roth@amd.com> writes:
> > 
> > > Most of the current 'query-sev' command is relevant to both legacy
> > > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> > >
> > >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> > >     the meaning of the bit positions has changed
> > >   - 'handle' is not relevant to SEV-SNP
> > >
> > > To address this, this patch adds a new 'sev-type' field that can be
> > > used as a discriminator to select between SEV and SEV-SNP-specific
> > > fields/formats without breaking compatibility for existing management
> > > tools (so long as management tools that add support for launching
> > > SEV-SNP guest update their handling of query-sev appropriately).
> > 
> > Technically a compatibility break: query-sev can now return an object
> > that whose member @policy has different meaning, and also lacks @handle.
> > 
> > Matrix:
> > 
> >                             Old mgmt app    New mgmt app
> >     Old QEMU, SEV/SEV-ES       good            good(1)
> >     New QEMU, SEV/SEV-ES       good(2)         good
> >     New QEMU, SEV-SNP           bad(3)         good
> > 
> > Notes:
> > 
> > (1) As long as the management application can cope with absent member
> > @sev-type.
> > 
> > (2) As long as the management application ignores unknown member
> > @sev-type.
> > 
> > (3) Management application may choke on missing member @handle, or
> > worse, misinterpret member @policy.  Can only happen when something
> > other than the management application created the SEV-SNP guest (or the
> > user somehow made the management application create one even though it
> > doesn't know how, say with CLI option passthrough, but that's always
> > fragile, and I wouldn't worry about it here).
> > 
> > I think (1) and (2) are reasonable.  (3) is an issue for management
> > applications that support attaching to existing guests.  Thoughts?
> 
> Hmm... yah I hadn't considering 'old mgmt' trying to interact with a SNP
> guest started through some other means.
> 
> Don't really see an alternative other than introducing a new
> 'query-sev-snp', but that would still leave 'old mgmt' broken, since
> it might still call do weird stuff like try to interpret the SNP policy
> as an SEV/SEV-ES and end up with some very unexpected results. So if I
> did go this route, I would need to have QMP begin returning an error if
> query-sev is run against an SNP guest. But currently for non-SEV guests
> it already does:
> 
>   error_setg(errp, "SEV feature is not available")
> 
> so 'old mgmt' should be able to handle the error just fine.
> 
> Would that approach be reasonable?

This ties into the question I've just sent in my other mail.

If the hardware strictly requires that guest are created in SEV-SNP
mode only, and will not support SEV/SEV-ES mode, then we need to
ensure "query-sev" reports the feature as not-available, so that
existing mgmt apps don't try to use SEV/SEV-ES.

If the SEV-SNP hardware is functionally back-compatible with a gues
configured in SEV/SEV-ES mode, then we souldn't need a new command,
just augment th eexisting command with additional field(s), to
indicate existance of SEV-SNP features.

Regards,
Daniel
Michael Roth Sept. 3, 2021, 3:43 p.m. UTC | #4
On Fri, Sep 03, 2021 at 04:30:48PM +0100, Daniel P. Berrangé wrote:
> On Fri, Sep 03, 2021 at 10:13:16AM -0500, Michael Roth wrote:
> > On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> > > Michael Roth <michael.roth@amd.com> writes:
> > > 
> > > > Most of the current 'query-sev' command is relevant to both legacy
> > > > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> > > >
> > > >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> > > >     the meaning of the bit positions has changed
> > > >   - 'handle' is not relevant to SEV-SNP
> > > >
> > > > To address this, this patch adds a new 'sev-type' field that can be
> > > > used as a discriminator to select between SEV and SEV-SNP-specific
> > > > fields/formats without breaking compatibility for existing management
> > > > tools (so long as management tools that add support for launching
> > > > SEV-SNP guest update their handling of query-sev appropriately).
> > > 
> > > Technically a compatibility break: query-sev can now return an object
> > > that whose member @policy has different meaning, and also lacks @handle.
> > > 
> > > Matrix:
> > > 
> > >                             Old mgmt app    New mgmt app
> > >     Old QEMU, SEV/SEV-ES       good            good(1)
> > >     New QEMU, SEV/SEV-ES       good(2)         good
> > >     New QEMU, SEV-SNP           bad(3)         good
> > > 
> > > Notes:
> > > 
> > > (1) As long as the management application can cope with absent member
> > > @sev-type.
> > > 
> > > (2) As long as the management application ignores unknown member
> > > @sev-type.
> > > 
> > > (3) Management application may choke on missing member @handle, or
> > > worse, misinterpret member @policy.  Can only happen when something
> > > other than the management application created the SEV-SNP guest (or the
> > > user somehow made the management application create one even though it
> > > doesn't know how, say with CLI option passthrough, but that's always
> > > fragile, and I wouldn't worry about it here).
> > > 
> > > I think (1) and (2) are reasonable.  (3) is an issue for management
> > > applications that support attaching to existing guests.  Thoughts?
> > 
> > Hmm... yah I hadn't considering 'old mgmt' trying to interact with a SNP
> > guest started through some other means.
> > 
> > Don't really see an alternative other than introducing a new
> > 'query-sev-snp', but that would still leave 'old mgmt' broken, since
> > it might still call do weird stuff like try to interpret the SNP policy
> > as an SEV/SEV-ES and end up with some very unexpected results. So if I
> > did go this route, I would need to have QMP begin returning an error if
> > query-sev is run against an SNP guest. But currently for non-SEV guests
> > it already does:
> > 
> >   error_setg(errp, "SEV feature is not available")
> > 
> > so 'old mgmt' should be able to handle the error just fine.
> > 
> > Would that approach be reasonable?
> 
> This ties into the question I've just sent in my other mail.
> 
> If the hardware strictly requires that guest are created in SEV-SNP
> mode only, and will not support SEV/SEV-ES mode, then we need to
> ensure "query-sev" reports the feature as not-available, so that
> existing mgmt apps don't try to use SEV/SEV-ES.

An SEV-SNP-capable host can run both 'legacy' SEV/SEV-ES, as well as
SEV-SNP guests, at the same time. But as far as QEMU goes, we need
to specify one or the other explicitly at launch time, via existing
'sev-guest', or the new 'sev-snp-guest' ConfidentialGuestSupport type.

> 
> If the SEV-SNP hardware is functionally back-compatible with a gues
> configured in SEV/SEV-ES mode, then we souldn't need a new command,
> just augment th eexisting command with additional field(s), to
> indicate existance of SEV-SNP features.

query-sev-info provides information specific to the guest instance,
like the configured policy. Are you thinking of query-sev-capabilities,
which reports some host-wide information and should indeed remain
available for either case. (and maybe should also be updated to report
on SEV-SNP availability for the host?)

> 
> Regards,
> Daniel
> -- 
> |: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fberrange.com%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7C86e4ceb7f55f4cf839e708d96eefd768%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637662798671249591%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=Fo%2FCcCEG7OrpVNj2ij2CzYJCMFXs30YUnRaClz17Okc%3D&amp;reserved=0      -o-    https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.flickr.com%2Fphotos%2Fdberrange&amp;data=04%7C01%7Cmichael.roth%40amd.com%7C86e4ceb7f55f4cf839e708d96eefd768%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637662798671249591%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=ypMyoiFFTmgWnDD3UwJrKIcHGzDaKQ8nXnFASw7gyRE%3D&amp;reserved=0 :|
> |: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flibvirt.org%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7C86e4ceb7f55f4cf839e708d96eefd768%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637662798671249591%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=viWBuUPauLi41pEKT143wh0Ds%2FwJqIG%2BDfraIO5uxNE%3D&amp;reserved=0         -o-            https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Ffstop138.berrange.com%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7C86e4ceb7f55f4cf839e708d96eefd768%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637662798671249591%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=H%2BTFPox5kDO4osMWicvwUrb8PvNfMBPLwCWEiEfcIOw%3D&amp;reserved=0 :|
> |: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fentangle-photo.org%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7C86e4ceb7f55f4cf839e708d96eefd768%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637662798671259556%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=9mp0c7dJ07EIdYYNZ73DQ6ax%2Bw0ORKTpScI6p5gNpVo%3D&amp;reserved=0    -o-    https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.instagram.com%2Fdberrange&amp;data=04%7C01%7Cmichael.roth%40amd.com%7C86e4ceb7f55f4cf839e708d96eefd768%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637662798671259556%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=%2FL1f9LxzAqXxVNbUhWa4w2Sibb6f0vLcRzaM2%2F9NY90%3D&amp;reserved=0 :|
>
Daniel P. Berrangé Sept. 3, 2021, 3:58 p.m. UTC | #5
On Fri, Sep 03, 2021 at 10:43:19AM -0500, Michael Roth wrote:
> On Fri, Sep 03, 2021 at 04:30:48PM +0100, Daniel P. Berrangé wrote:
> > On Fri, Sep 03, 2021 at 10:13:16AM -0500, Michael Roth wrote:
> > > On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> > > > Michael Roth <michael.roth@amd.com> writes:
> > > > 
> > > > > Most of the current 'query-sev' command is relevant to both legacy
> > > > > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> > > > >
> > > > >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> > > > >     the meaning of the bit positions has changed
> > > > >   - 'handle' is not relevant to SEV-SNP
> > > > >
> > > > > To address this, this patch adds a new 'sev-type' field that can be
> > > > > used as a discriminator to select between SEV and SEV-SNP-specific
> > > > > fields/formats without breaking compatibility for existing management
> > > > > tools (so long as management tools that add support for launching
> > > > > SEV-SNP guest update their handling of query-sev appropriately).
> > > > 
> > > > Technically a compatibility break: query-sev can now return an object
> > > > that whose member @policy has different meaning, and also lacks @handle.
> > > > 
> > > > Matrix:
> > > > 
> > > >                             Old mgmt app    New mgmt app
> > > >     Old QEMU, SEV/SEV-ES       good            good(1)
> > > >     New QEMU, SEV/SEV-ES       good(2)         good
> > > >     New QEMU, SEV-SNP           bad(3)         good
> > > > 
> > > > Notes:
> > > > 
> > > > (1) As long as the management application can cope with absent member
> > > > @sev-type.
> > > > 
> > > > (2) As long as the management application ignores unknown member
> > > > @sev-type.
> > > > 
> > > > (3) Management application may choke on missing member @handle, or
> > > > worse, misinterpret member @policy.  Can only happen when something
> > > > other than the management application created the SEV-SNP guest (or the
> > > > user somehow made the management application create one even though it
> > > > doesn't know how, say with CLI option passthrough, but that's always
> > > > fragile, and I wouldn't worry about it here).
> > > > 
> > > > I think (1) and (2) are reasonable.  (3) is an issue for management
> > > > applications that support attaching to existing guests.  Thoughts?
> > > 
> > > Hmm... yah I hadn't considering 'old mgmt' trying to interact with a SNP
> > > guest started through some other means.
> > > 
> > > Don't really see an alternative other than introducing a new
> > > 'query-sev-snp', but that would still leave 'old mgmt' broken, since
> > > it might still call do weird stuff like try to interpret the SNP policy
> > > as an SEV/SEV-ES and end up with some very unexpected results. So if I
> > > did go this route, I would need to have QMP begin returning an error if
> > > query-sev is run against an SNP guest. But currently for non-SEV guests
> > > it already does:
> > > 
> > >   error_setg(errp, "SEV feature is not available")
> > > 
> > > so 'old mgmt' should be able to handle the error just fine.
> > > 
> > > Would that approach be reasonable?
> > 
> > This ties into the question I've just sent in my other mail.
> > 
> > If the hardware strictly requires that guest are created in SEV-SNP
> > mode only, and will not support SEV/SEV-ES mode, then we need to
> > ensure "query-sev" reports the feature as not-available, so that
> > existing mgmt apps don't try to use SEV/SEV-ES.
> 
> An SEV-SNP-capable host can run both 'legacy' SEV/SEV-ES, as well as
> SEV-SNP guests, at the same time. But as far as QEMU goes, we need
> to specify one or the other explicitly at launch time, via existing
> 'sev-guest', or the new 'sev-snp-guest' ConfidentialGuestSupport type.
> 
> > 
> > If the SEV-SNP hardware is functionally back-compatible with a gues
> > configured in SEV/SEV-ES mode, then we souldn't need a new command,
> > just augment th eexisting command with additional field(s), to
> > indicate existance of SEV-SNP features.
> 
> query-sev-info provides information specific to the guest instance,
> like the configured policy. Are you thinking of query-sev-capabilities,
> which reports some host-wide information and should indeed remain
> available for either case. (and maybe should also be updated to report
> on SEV-SNP availability for the host?)

Oh right, yes, I am getting confused with query-sev-capabilities.

I think this means everything is OK with your query-sev-info
changes proposed here, I'll reply direct to Markus' point though.

Regards,
Daniel
Daniel P. Berrangé Sept. 3, 2021, 4:01 p.m. UTC | #6
On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> Michael Roth <michael.roth@amd.com> writes:
> 
> > Most of the current 'query-sev' command is relevant to both legacy
> > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> >
> >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> >     the meaning of the bit positions has changed
> >   - 'handle' is not relevant to SEV-SNP
> >
> > To address this, this patch adds a new 'sev-type' field that can be
> > used as a discriminator to select between SEV and SEV-SNP-specific
> > fields/formats without breaking compatibility for existing management
> > tools (so long as management tools that add support for launching
> > SEV-SNP guest update their handling of query-sev appropriately).
> 
> Technically a compatibility break: query-sev can now return an object
> that whose member @policy has different meaning, and also lacks @handle.
> 
> Matrix:
> 
>                             Old mgmt app    New mgmt app
>     Old QEMU, SEV/SEV-ES       good            good(1)
>     New QEMU, SEV/SEV-ES       good(2)         good
>     New QEMU, SEV-SNP           bad(3)         good
> 
> Notes:
> 
> (1) As long as the management application can cope with absent member
> @sev-type.
> 
> (2) As long as the management application ignores unknown member
> @sev-type.
> 
> (3) Management application may choke on missing member @handle, or
> worse, misinterpret member @policy.  Can only happen when something
> other than the management application created the SEV-SNP guest (or the
> user somehow made the management application create one even though it
> doesn't know how, say with CLI option passthrough, but that's always
> fragile, and I wouldn't worry about it here).
> 
> I think (1) and (2) are reasonable.  (3) is an issue for management
> applications that support attaching to existing guests.  Thoughts?

IIUC you can only reach scenario (3) if you have created a guest
using '-object sev-snp-guest', which is a new feature introduced
in patch 2.

IOW, scenario (3)  old mgmt app + new QEMU + sev-snp guest does
not exist as a combination. Thus the (bad) field is actually (n/a)

So I believe this proposed change is acceptable in all scenarios
with existing deployed usage, as well as all newly introduced
scenarios.

Regards,
Daniel
Dr. David Alan Gilbert Sept. 7, 2021, 11:52 a.m. UTC | #7
* Daniel P. Berrangé (berrange@redhat.com) wrote:
> On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> > Michael Roth <michael.roth@amd.com> writes:
> > 
> > > Most of the current 'query-sev' command is relevant to both legacy
> > > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> > >
> > >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> > >     the meaning of the bit positions has changed
> > >   - 'handle' is not relevant to SEV-SNP
> > >
> > > To address this, this patch adds a new 'sev-type' field that can be
> > > used as a discriminator to select between SEV and SEV-SNP-specific
> > > fields/formats without breaking compatibility for existing management
> > > tools (so long as management tools that add support for launching
> > > SEV-SNP guest update their handling of query-sev appropriately).
> > 
> > Technically a compatibility break: query-sev can now return an object
> > that whose member @policy has different meaning, and also lacks @handle.
> > 
> > Matrix:
> > 
> >                             Old mgmt app    New mgmt app
> >     Old QEMU, SEV/SEV-ES       good            good(1)
> >     New QEMU, SEV/SEV-ES       good(2)         good
> >     New QEMU, SEV-SNP           bad(3)         good
> > 
> > Notes:
> > 
> > (1) As long as the management application can cope with absent member
> > @sev-type.
> > 
> > (2) As long as the management application ignores unknown member
> > @sev-type.
> > 
> > (3) Management application may choke on missing member @handle, or
> > worse, misinterpret member @policy.  Can only happen when something
> > other than the management application created the SEV-SNP guest (or the
> > user somehow made the management application create one even though it
> > doesn't know how, say with CLI option passthrough, but that's always
> > fragile, and I wouldn't worry about it here).
> > 
> > I think (1) and (2) are reasonable.  (3) is an issue for management
> > applications that support attaching to existing guests.  Thoughts?
> 
> IIUC you can only reach scenario (3) if you have created a guest
> using '-object sev-snp-guest', which is a new feature introduced
> in patch 2.
> 
> IOW, scenario (3)  old mgmt app + new QEMU + sev-snp guest does
> not exist as a combination. Thus the (bad) field is actually (n/a)
> 
> So I believe this proposed change is acceptable in all scenarios
> with existing deployed usage, as well as all newly introduced
> scenarios.

I wonder if it's worth going firther and renaming 'policy' in the 
SNP world to 'snppolicy' just to reduce the risk of accidentally
specifying the wrong one.

Dave

> Regards,
> Daniel
> -- 
> |: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org         -o-            https://fstop138.berrange.com :|
> |: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
>
Michael Roth Sept. 7, 2021, 2:33 p.m. UTC | #8
On Tue, Sep 07, 2021 at 12:52:54PM +0100, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berrange@redhat.com) wrote:
> > On Wed, Sep 01, 2021 at 04:14:10PM +0200, Markus Armbruster wrote:
> > > Michael Roth <michael.roth@amd.com> writes:
> > > 
> > > > Most of the current 'query-sev' command is relevant to both legacy
> > > > SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
> > > >
> > > >   - 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
> > > >     the meaning of the bit positions has changed
> > > >   - 'handle' is not relevant to SEV-SNP
> > > >
> > > > To address this, this patch adds a new 'sev-type' field that can be
> > > > used as a discriminator to select between SEV and SEV-SNP-specific
> > > > fields/formats without breaking compatibility for existing management
> > > > tools (so long as management tools that add support for launching
> > > > SEV-SNP guest update their handling of query-sev appropriately).
> > > 
> > > Technically a compatibility break: query-sev can now return an object
> > > that whose member @policy has different meaning, and also lacks @handle.
> > > 
> > > Matrix:
> > > 
> > >                             Old mgmt app    New mgmt app
> > >     Old QEMU, SEV/SEV-ES       good            good(1)
> > >     New QEMU, SEV/SEV-ES       good(2)         good
> > >     New QEMU, SEV-SNP           bad(3)         good
> > > 
> > > Notes:
> > > 
> > > (1) As long as the management application can cope with absent member
> > > @sev-type.
> > > 
> > > (2) As long as the management application ignores unknown member
> > > @sev-type.
> > > 
> > > (3) Management application may choke on missing member @handle, or
> > > worse, misinterpret member @policy.  Can only happen when something
> > > other than the management application created the SEV-SNP guest (or the
> > > user somehow made the management application create one even though it
> > > doesn't know how, say with CLI option passthrough, but that's always
> > > fragile, and I wouldn't worry about it here).
> > > 
> > > I think (1) and (2) are reasonable.  (3) is an issue for management
> > > applications that support attaching to existing guests.  Thoughts?
> > 
> > IIUC you can only reach scenario (3) if you have created a guest
> > using '-object sev-snp-guest', which is a new feature introduced
> > in patch 2.
> > 
> > IOW, scenario (3)  old mgmt app + new QEMU + sev-snp guest does
> > not exist as a combination. Thus the (bad) field is actually (n/a)
> > 
> > So I believe this proposed change is acceptable in all scenarios
> > with existing deployed usage, as well as all newly introduced
> > scenarios.
> 
> I wonder if it's worth going firther and renaming 'policy' in the 
> SNP world to 'snppolicy' just to reduce the risk of accidentally
> specifying the wrong one.

Seems reasonable. I'll plan on renaming to 'snp-policy' if there are no
objections.

> 
> Dave
> 
> > Regards,
> > Daniel
> > -- 
> > |: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fberrange.com%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7Cb9a484cd5d4f484b542908d971f61073%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637666123947391605%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=D56oHIuVk%2FmAJaKYtpJ3ZEZpKZpDPWZXydV3tpYjcM4%3D&amp;reserved=0      -o-    https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.flickr.com%2Fphotos%2Fdberrange&amp;data=04%7C01%7Cmichael.roth%40amd.com%7Cb9a484cd5d4f484b542908d971f61073%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637666123947401567%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=A9YA65nj6En3f3E2wm%2BVZE%2F6DpdbDKyHSWN9VXHAk8U%3D&amp;reserved=0 :|
> > |: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flibvirt.org%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7Cb9a484cd5d4f484b542908d971f61073%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637666123947401567%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=yf%2FV3f3%2FNxEDwmYESp7D0ZOn74aM6cXskVJrvHLvXRE%3D&amp;reserved=0         -o-            https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Ffstop138.berrange.com%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7Cb9a484cd5d4f484b542908d971f61073%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637666123947401567%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=pUYNVu6WWgPtwjwrjvz3YCCY7S1Qli%2FfvQKmkaRu3gc%3D&amp;reserved=0 :|
> > |: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fentangle-photo.org%2F&amp;data=04%7C01%7Cmichael.roth%40amd.com%7Cb9a484cd5d4f484b542908d971f61073%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637666123947401567%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=opdXI%2BlyzxWhUbNNgka6sMKMiLmMHfk8WuZY6cMy7yE%3D&amp;reserved=0    -o-    https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.instagram.com%2Fdberrange&amp;data=04%7C01%7Cmichael.roth%40amd.com%7Cb9a484cd5d4f484b542908d971f61073%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637666123947401567%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=8cV6tsleO5nDBVKR3WX74a%2BKch5RdRdmPciv%2F6T9nOg%3D&amp;reserved=0 :|
> > 
> -- 
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>
diff mbox series

Patch

diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 3b05ad3dbf..80f994ff9b 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -81,6 +81,49 @@ 
            'send-update', 'receive-update' ],
   'if': 'TARGET_I386' }
 
+##
+# @SevGuestType:
+#
+# An enumeration indicating the type of SEV guest being run.
+#
+# @sev:     The guest is a legacy SEV or SEV-ES guest.
+# @sev-snp: The guest is an SEV-SNP guest.
+#
+# Since: 6.2
+##
+{ 'enum': 'SevGuestType',
+  'data': [ 'sev', 'sev-snp' ],
+  'if': 'TARGET_I386' }
+
+##
+# @SevGuestInfo:
+#
+# Information specific to legacy SEV/SEV-ES guests.
+#
+# @policy: SEV policy value
+#
+# @handle: SEV firmware handle
+#
+# Since: 2.12
+##
+{ 'struct': 'SevGuestInfo',
+  'data': { 'policy': 'uint32',
+            'handle': 'uint32' },
+  'if': 'TARGET_I386' }
+
+##
+# @SevSnpGuestInfo:
+#
+# Information specific to SEV-SNP guests.
+#
+# @policy: SEV-SNP policy value
+#
+# Since: 6.2
+##
+{ 'struct': 'SevSnpGuestInfo',
+  'data': { 'policy': 'uint64' },
+  'if': 'TARGET_I386' }
+
 ##
 # @SevInfo:
 #
@@ -94,25 +137,25 @@ 
 #
 # @build-id: SEV FW build id
 #
-# @policy: SEV policy value
-#
 # @state: SEV guest state
 #
-# @handle: SEV firmware handle
+# @sev-type: Type of SEV guest being run
 #
 # Since: 2.12
 ##
-{ 'struct': 'SevInfo',
-    'data': { 'enabled': 'bool',
-              'api-major': 'uint8',
-              'api-minor' : 'uint8',
-              'build-id' : 'uint8',
-              'policy' : 'uint32',
-              'state' : 'SevState',
-              'handle' : 'uint32'
-            },
-  'if': 'TARGET_I386'
-}
+{ 'union': 'SevInfo',
+  'base': { 'enabled': 'bool',
+            'api-major': 'uint8',
+            'api-minor' : 'uint8',
+            'build-id' : 'uint8',
+            'state' : 'SevState',
+            'sev-type' : 'SevGuestType' },
+  'discriminator': 'sev-type',
+  'data': {
+      'sev': 'SevGuestInfo',
+      'sev-snp': 'SevSnpGuestInfo' },
+  'if': 'TARGET_I386' }
+
 
 ##
 # @query-sev:
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 119211f0b0..85a8bc2bef 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -692,20 +692,37 @@  void hmp_info_sev(Monitor *mon, const QDict *qdict)
 {
     SevInfo *info = sev_get_info();
 
-    if (info && info->enabled) {
-        monitor_printf(mon, "handle: %d\n", info->handle);
+    if (!info || !info->enabled) {
+        monitor_printf(mon, "SEV is not enabled\n");
+        goto out;
+    }
+
+    if (sev_snp_enabled()) {
         monitor_printf(mon, "state: %s\n", SevState_str(info->state));
         monitor_printf(mon, "build: %d\n", info->build_id);
         monitor_printf(mon, "api version: %d.%d\n",
                        info->api_major, info->api_minor);
         monitor_printf(mon, "debug: %s\n",
-                       info->policy & SEV_POLICY_NODBG ? "off" : "on");
-        monitor_printf(mon, "key-sharing: %s\n",
-                       info->policy & SEV_POLICY_NOKS ? "off" : "on");
+                       info->u.sev_snp.policy & SEV_SNP_POLICY_DBG ? "on"
+                                                                   : "off");
+        monitor_printf(mon, "SMT allowed: %s\n",
+                       info->u.sev_snp.policy & SEV_SNP_POLICY_SMT ? "on"
+                                                                   : "off");
+        monitor_printf(mon, "SEV type: %s\n", SevGuestType_str(info->sev_type));
     } else {
-        monitor_printf(mon, "SEV is not enabled\n");
+        monitor_printf(mon, "handle: %d\n", info->u.sev.handle);
+        monitor_printf(mon, "state: %s\n", SevState_str(info->state));
+        monitor_printf(mon, "build: %d\n", info->build_id);
+        monitor_printf(mon, "api version: %d.%d\n",
+                       info->api_major, info->api_minor);
+        monitor_printf(mon, "debug: %s\n",
+                       info->u.sev.policy & SEV_POLICY_NODBG ? "off" : "on");
+        monitor_printf(mon, "key-sharing: %s\n",
+                       info->u.sev.policy & SEV_POLICY_NOKS ? "off" : "on");
+        monitor_printf(mon, "SEV type: %s\n", SevGuestType_str(info->sev_type));
     }
 
+out:
     qapi_free_SevInfo(info);
 }
 
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 72a6146295..fac2755e68 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -704,25 +704,27 @@  sev_get_info(void)
 {
     SevInfo *info;
     SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
-    SevGuestState *sev_guest =
-        (SevGuestState *)object_dynamic_cast(OBJECT(sev_common),
-                                             TYPE_SEV_GUEST);
 
     info = g_new0(SevInfo, 1);
     info->enabled = sev_enabled();
 
     if (info->enabled) {
-        if (sev_guest) {
-            info->handle = sev_guest->handle;
-        }
         info->api_major = sev_common->api_major;
         info->api_minor = sev_common->api_minor;
         info->build_id = sev_common->build_id;
         info->state = sev_common->state;
-        /* we only report the lower 32-bits of policy for SNP, ok for now... */
-        info->policy =
-            (uint32_t)object_property_get_uint(OBJECT(sev_common),
-                                               "policy", NULL);
+
+        if (sev_snp_enabled()) {
+            info->sev_type = SEV_GUEST_TYPE_SEV_SNP;
+            info->u.sev_snp.policy =
+                object_property_get_uint(OBJECT(sev_common), "policy", NULL);
+        } else {
+            info->sev_type = SEV_GUEST_TYPE_SEV;
+            info->u.sev.handle = SEV_GUEST(sev_common)->handle;
+            info->u.sev.policy =
+                (uint32_t)object_property_get_uint(OBJECT(sev_common),
+                                                   "policy", NULL);
+        }
     }
 
     return info;
diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h
index e0e1a599be..948d8f1079 100644
--- a/target/i386/sev_i386.h
+++ b/target/i386/sev_i386.h
@@ -28,6 +28,9 @@ 
 #define SEV_POLICY_DOMAIN       0x10
 #define SEV_POLICY_SEV          0x20
 
+#define SEV_SNP_POLICY_SMT      0x10000
+#define SEV_SNP_POLICY_DBG      0x80000
+
 extern bool sev_es_enabled(void);
 extern bool sev_snp_enabled(void);
 extern uint64_t sev_get_me_mask(void);