diff mbox

[RFC,v1,05/22] i386: add new option to enable SEV guest

Message ID 147377805350.11859.16913701772043413471.stgit@brijesh-build-machine
State New
Headers show

Commit Message

Brijesh Singh Sept. 13, 2016, 2:47 p.m. UTC
The patch adds '-sev' option to enable the Secure Encrypted
Virtualization (SEV) guest. If this option is specified, Qemu
assumes that user wants to launch this guest into SEV mode.

Here are example on how to launch a guest into SEV mode.

1) late launch: in this mode the images received from guest
owner are unencrypted and must be encrypted using SEV LAUNCH command
before starting the guest.

$ qemu -sev type=unencrypted config=guest_01.conf

2) pre-encrypted: in this mode the images received from guest
owners are encrypted using transport keys. It must be re-encrypted
using SEV RECEIVE commands before starting the guest.

$ qemu -sev type=encrypted config=guest_02.conf

The config file will contains various parameters (e.g key , policy)
required during guest launch process.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 qemu-options.hx |    6 ++++++
 vl.c            |   29 +++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

Comments

Paolo Bonzini Sept. 13, 2016, 10:41 p.m. UTC | #1
On 13/09/2016 16:47, Brijesh Singh wrote:
> The patch adds '-sev' option to enable the Secure Encrypted
> Virtualization (SEV) guest. If this option is specified, Qemu
> assumes that user wants to launch this guest into SEV mode.
> 
> Here are example on how to launch a guest into SEV mode.
> 
> 1) late launch: in this mode the images received from guest
> owner are unencrypted and must be encrypted using SEV LAUNCH command
> before starting the guest.
> 
> $ qemu -sev type=unencrypted config=guest_01.conf
> 
> 2) pre-encrypted: in this mode the images received from guest
> owners are encrypted using transport keys. It must be re-encrypted
> using SEV RECEIVE commands before starting the guest.
> 
> $ qemu -sev type=encrypted config=guest_02.conf
> 
> The config file will contains various parameters (e.g key , policy)
> required during guest launch process.

Any reason not to pass the sev options themselves through -sev?  You can
then use "-readconfig sev-guest.cfg" where sev-guest.cfg contains

	[sev]
	type="encrypted"
	flags = "00000000"
	policy	= "000000"
	dh_pub_qx = "0123456789abcdef0123456789abcdef"
	dh_pub_qy = "0123456789abcdef0123456789abcdef"
	nonce = "0123456789abcdef"
	vcpu_count = "1"
	vcpu_length = "30"
	vcpu_mask = "00ab"

Paolo

> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  qemu-options.hx |    6 ++++++
>  vl.c            |   29 +++++++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
> 
> diff --git a/qemu-options.hx b/qemu-options.hx
> index a71aaf8..1b6aa82 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -118,6 +118,12 @@ given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
>  specifies the maximum number of hotpluggable CPUs.
>  ETEXI
>  
> +DEF("sev", HAS_ARG, QEMU_OPTION_sev,
> +    "-sev type=[encrypted,unencrypted] config=<file>\n"
> +    "                image type (encrypted or unencrypted)\n"
> +    "                set the config file for SEV guest\n",
> +        QEMU_ARCH_I386)
> +
>  DEF("numa", HAS_ARG, QEMU_OPTION_numa,
>      "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n"
>      "-numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
> diff --git a/vl.c b/vl.c
> index b3c80d5..22b8eba 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -178,6 +178,7 @@ bool boot_strict;
>  uint8_t *boot_splash_filedata;
>  size_t boot_splash_filedata_size;
>  uint8_t qemu_extra_params_fw[2];
> +static bool sev_allowed;
>  
>  int icount_align_option;
>  
> @@ -506,6 +507,25 @@ static QemuOptsList qemu_fw_cfg_opts = {
>      },
>  };
>  
> +static QemuOptsList qemu_sev_opts = {
> +    .name = "sev",
> +    .implied_opt_name = "name",
> +    .head = QTAILQ_HEAD_INITIALIZER(qemu_sev_opts.head),
> +    .desc = {
> +        {
> +            .name = "config",
> +            .type = QEMU_OPT_STRING,
> +            .help = "Set the SEV config file\n",
> +        },
> +        {
> +            .name = "type",
> +            .type = QEMU_OPT_STRING,
> +            .help = "Set the image type (encrypted or unencrypted)\n",
> +        },
> +        { /* end of list */ }
> +    },
> +};
> +
>  /**
>   * Get machine options
>   *
> @@ -3002,6 +3022,7 @@ int main(int argc, char **argv, char **envp)
>      qemu_add_opts(&qemu_icount_opts);
>      qemu_add_opts(&qemu_semihosting_config_opts);
>      qemu_add_opts(&qemu_fw_cfg_opts);
> +    qemu_add_opts(&qemu_sev_opts);
>      module_call_init(MODULE_INIT_OPTS);
>  
>      runstate_init();
> @@ -3970,6 +3991,14 @@ int main(int argc, char **argv, char **envp)
>                      exit(1);
>                  }
>                  break;
> +            case QEMU_OPTION_sev:
> +                olist = qemu_find_opts("sev");
> +                opts = qemu_opts_parse_noisily(olist, optarg, true);
> +                if (!opts) {
> +                    exit(1);
> +                }
> +                sev_allowed = true;
> +                break;
>              default:
>                  os_parse_cmd_args(popt->index, optarg);
>              }
> 
> 
>
Daniel P. Berrangé Sept. 14, 2016, 8:41 a.m. UTC | #2
On Wed, Sep 14, 2016 at 12:41:59AM +0200, Paolo Bonzini wrote:
> 
> 
> On 13/09/2016 16:47, Brijesh Singh wrote:
> > The patch adds '-sev' option to enable the Secure Encrypted
> > Virtualization (SEV) guest. If this option is specified, Qemu
> > assumes that user wants to launch this guest into SEV mode.
> > 
> > Here are example on how to launch a guest into SEV mode.
> > 
> > 1) late launch: in this mode the images received from guest
> > owner are unencrypted and must be encrypted using SEV LAUNCH command
> > before starting the guest.
> > 
> > $ qemu -sev type=unencrypted config=guest_01.conf
> > 
> > 2) pre-encrypted: in this mode the images received from guest
> > owners are encrypted using transport keys. It must be re-encrypted
> > using SEV RECEIVE commands before starting the guest.
> > 
> > $ qemu -sev type=encrypted config=guest_02.conf
> > 
> > The config file will contains various parameters (e.g key , policy)
> > required during guest launch process.
> 
> Any reason not to pass the sev options themselves through -sev?  You can
> then use "-readconfig sev-guest.cfg" where sev-guest.cfg contains
> 
> 	[sev]
> 	type="encrypted"
> 	flags = "00000000"
> 	policy	= "000000"
> 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
> 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
> 	nonce = "0123456789abcdef"
> 	vcpu_count = "1"
> 	vcpu_length = "30"
> 	vcpu_mask = "00ab"

Agreed, it is really preferrable to define all the options via
one command line arg (using -object) and not re-invent external
config files when QEMU already has generic config file support


Regards,
Daniel
Paolo Bonzini Sept. 14, 2016, 9:11 a.m. UTC | #3
On 14/09/2016 10:41, Daniel P. Berrange wrote:
>> > Any reason not to pass the sev options themselves through -sev?  You can
>> > then use "-readconfig sev-guest.cfg" where sev-guest.cfg contains
>> > 
>> > 	[sev]
>> > 	type="encrypted"
>> > 	flags = "00000000"
>> > 	policy	= "000000"
>> > 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
>> > 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
>> > 	nonce = "0123456789abcdef"
>> > 	vcpu_count = "1"
>> > 	vcpu_length = "30"
>> > 	vcpu_mask = "00ab"
> Agreed, it is really preferrable to define all the options via
> one command line arg (using -object) and not re-invent external
> config files when QEMU already has generic config file support

To be fair, they _were_ reusing QEMU's config file support.  I was
ambivalent regarding using -object vs. creating a new command line,
since this is a singleton object, but indeed it's nicer if the policy is
split to its own object.

The object would be defined like this:

     [object "mypolicy"]
     qom-type = "sev-policy-encrypted"
     dh_pub_qx = "..."
     dh_pub_qy = "..."
     nonce = "..."
     ...

and then you also need to add a property to the MachineState.  The
property is accessed with -machine, and it creates a link to the policy
object---which also enables sev.  In the end you'd have this on the
command line:

    -readconfig mypolicy.cfg -machine sev-policy=mypolicy

Thanks,

Paolo
diff mbox

Patch

diff --git a/qemu-options.hx b/qemu-options.hx
index a71aaf8..1b6aa82 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -118,6 +118,12 @@  given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
 specifies the maximum number of hotpluggable CPUs.
 ETEXI
 
+DEF("sev", HAS_ARG, QEMU_OPTION_sev,
+    "-sev type=[encrypted,unencrypted] config=<file>\n"
+    "                image type (encrypted or unencrypted)\n"
+    "                set the config file for SEV guest\n",
+        QEMU_ARCH_I386)
+
 DEF("numa", HAS_ARG, QEMU_OPTION_numa,
     "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n"
     "-numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index b3c80d5..22b8eba 100644
--- a/vl.c
+++ b/vl.c
@@ -178,6 +178,7 @@  bool boot_strict;
 uint8_t *boot_splash_filedata;
 size_t boot_splash_filedata_size;
 uint8_t qemu_extra_params_fw[2];
+static bool sev_allowed;
 
 int icount_align_option;
 
@@ -506,6 +507,25 @@  static QemuOptsList qemu_fw_cfg_opts = {
     },
 };
 
+static QemuOptsList qemu_sev_opts = {
+    .name = "sev",
+    .implied_opt_name = "name",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_sev_opts.head),
+    .desc = {
+        {
+            .name = "config",
+            .type = QEMU_OPT_STRING,
+            .help = "Set the SEV config file\n",
+        },
+        {
+            .name = "type",
+            .type = QEMU_OPT_STRING,
+            .help = "Set the image type (encrypted or unencrypted)\n",
+        },
+        { /* end of list */ }
+    },
+};
+
 /**
  * Get machine options
  *
@@ -3002,6 +3022,7 @@  int main(int argc, char **argv, char **envp)
     qemu_add_opts(&qemu_icount_opts);
     qemu_add_opts(&qemu_semihosting_config_opts);
     qemu_add_opts(&qemu_fw_cfg_opts);
+    qemu_add_opts(&qemu_sev_opts);
     module_call_init(MODULE_INIT_OPTS);
 
     runstate_init();
@@ -3970,6 +3991,14 @@  int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_sev:
+                olist = qemu_find_opts("sev");
+                opts = qemu_opts_parse_noisily(olist, optarg, true);
+                if (!opts) {
+                    exit(1);
+                }
+                sev_allowed = true;
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }