diff mbox series

[RFC,06/37] s390: UV: Add import and export to UV library

Message ID 20191024114059.102802-7-frankja@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series KVM: s390: Add support for protected VMs | expand

Commit Message

Janosch Frank Oct. 24, 2019, 11:40 a.m. UTC
The convert to/from secure (or also "import/export") ultravisor calls
are need for page management, i.e. paging, of secure execution VM.

Export encrypts a secure guest's page and makes it accessible to the
guest for paging.

Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the
Ultravisor before it is given to the guest.

All following imports will decrypt a exported page and verify
integrity before giving the page to the guest.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

Comments

David Hildenbrand Oct. 25, 2019, 8:31 a.m. UTC | #1
On 24.10.19 13:40, Janosch Frank wrote:
> The convert to/from secure (or also "import/export") ultravisor calls
> are need for page management, i.e. paging, of secure execution VM.
> 
> Export encrypts a secure guest's page and makes it accessible to the
> guest for paging.

How does paging play along with pinning the pages (from 
uv_convert_to_secure() -> kvm_s390_pv_pin_page()) in a follow up patch? 
Can you paint me the bigger picture?

Just so I understand:

When a page is "secure", it is actually unencrypted but only the guest 
can access it. If the host accesses it, there is an exception.

When a page is "not secure", it is encrypted but only the host can read 
it. If the guest accesses it, there is an exception.

Based on these exceptions, you are able to request to convert back and 
forth.


> 
> Import makes a page accessible to a secure guest.
> On the first import of that page, the page will be cleared by the
> Ultravisor before it is given to the guest.
> 
> All following imports will decrypt a exported page and verify
> integrity before giving the page to the guest.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
>   arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>   1 file changed, 51 insertions(+)
> 
> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
> index 0bfbafcca136..99cdd2034503 100644
> --- a/arch/s390/include/asm/uv.h
> +++ b/arch/s390/include/asm/uv.h
> @@ -15,6 +15,7 @@
>   #include <linux/errno.h>
>   #include <linux/bug.h>
>   #include <asm/page.h>
> +#include <asm/gmap.h>
>   
>   #define UVC_RC_EXECUTED		0x0001
>   #define UVC_RC_INV_CMD		0x0002
> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>   	return rc ? -EINVAL : 0;
>   }
>   
> +/*
> + * Requests the Ultravisor to encrypt a guest page and make it
> + * accessible to the host for paging (export).
> + *
> + * @paddr: Absolute host address of page to be exported
> + */
> +static inline int uv_convert_from_secure(unsigned long paddr)
> +{
> +	struct uv_cb_cfs uvcb = {
> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.paddr = paddr
> +	};
> +	if (!uv_call(0, (u64)&uvcb))
> +		return 0;
> +	return -EINVAL;
> +}
> +
> +/*
> + * Requests the Ultravisor to make a page accessible to a guest
> + * (import). If it's brought in the first time, it will be cleared. If
> + * it has been exported before, it will be decrypted and integrity
> + * checked.
> + *
> + * @handle: Ultravisor guest handle
> + * @gaddr: Guest 2 absolute address to be imported
> + */
> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
> +{
> +	int cc;
> +	struct uv_cb_cts uvcb = {
> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.guest_handle = gmap->se_handle,
> +		.gaddr = gaddr
> +	};
> +
> +	cc = uv_call(0, (u64)&uvcb);
> +
> +	if (!cc)
> +		return 0;
> +	if (uvcb.header.rc == 0x104)
> +		return -EEXIST;
> +	if (uvcb.header.rc == 0x10a)
> +		return -EFAULT;
> +	return -EINVAL;
> +}
> +
>   void setup_uv(void);
>   void adjust_to_uv_max(unsigned long *vmax);
>   #else
> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>   static inline void setup_uv(void) {}
>   static inline void adjust_to_uv_max(unsigned long *vmax) {}
>   static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>   #endif
>   
>   #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
>
Janosch Frank Oct. 25, 2019, 8:39 a.m. UTC | #2
On 10/25/19 10:31 AM, David Hildenbrand wrote:
> On 24.10.19 13:40, Janosch Frank wrote:
>> The convert to/from secure (or also "import/export") ultravisor calls
>> are need for page management, i.e. paging, of secure execution VM.
>>
>> Export encrypts a secure guest's page and makes it accessible to the
>> guest for paging.
> 
> How does paging play along with pinning the pages (from 
> uv_convert_to_secure() -> kvm_s390_pv_pin_page()) in a follow up patch? 
> Can you paint me the bigger picture?

That's a stale comment I should have removed before sending...
The current patches do not support paging.

> 
> Just so I understand:
> 
> When a page is "secure", it is actually unencrypted but only the guest 
> can access it. If the host accesses it, there is an exception.
> 
> When a page is "not secure", it is encrypted but only the host can read 
> it. If the guest accesses it, there is an exception.
> 
> Based on these exceptions, you are able to request to convert back and 
> forth.

Yes
Shared pages are the exception, because they are accessible to both parties.

> 
> 
>>
>> Import makes a page accessible to a secure guest.
>> On the first import of that page, the page will be cleared by the
>> Ultravisor before it is given to the guest.
>>
>> All following imports will decrypt a exported page and verify
>> integrity before giving the page to the guest.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> ---
>>   arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 51 insertions(+)
>>
>> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
>> index 0bfbafcca136..99cdd2034503 100644
>> --- a/arch/s390/include/asm/uv.h
>> +++ b/arch/s390/include/asm/uv.h
>> @@ -15,6 +15,7 @@
>>   #include <linux/errno.h>
>>   #include <linux/bug.h>
>>   #include <asm/page.h>
>> +#include <asm/gmap.h>
>>   
>>   #define UVC_RC_EXECUTED		0x0001
>>   #define UVC_RC_INV_CMD		0x0002
>> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>>   	return rc ? -EINVAL : 0;
>>   }
>>   
>> +/*
>> + * Requests the Ultravisor to encrypt a guest page and make it
>> + * accessible to the host for paging (export).
>> + *
>> + * @paddr: Absolute host address of page to be exported
>> + */
>> +static inline int uv_convert_from_secure(unsigned long paddr)
>> +{
>> +	struct uv_cb_cfs uvcb = {
>> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
>> +		.header.len = sizeof(uvcb),
>> +		.paddr = paddr
>> +	};
>> +	if (!uv_call(0, (u64)&uvcb))
>> +		return 0;
>> +	return -EINVAL;
>> +}
>> +
>> +/*
>> + * Requests the Ultravisor to make a page accessible to a guest
>> + * (import). If it's brought in the first time, it will be cleared. If
>> + * it has been exported before, it will be decrypted and integrity
>> + * checked.
>> + *
>> + * @handle: Ultravisor guest handle
>> + * @gaddr: Guest 2 absolute address to be imported
>> + */
>> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
>> +{
>> +	int cc;
>> +	struct uv_cb_cts uvcb = {
>> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
>> +		.header.len = sizeof(uvcb),
>> +		.guest_handle = gmap->se_handle,
>> +		.gaddr = gaddr
>> +	};
>> +
>> +	cc = uv_call(0, (u64)&uvcb);
>> +
>> +	if (!cc)
>> +		return 0;
>> +	if (uvcb.header.rc == 0x104)
>> +		return -EEXIST;
>> +	if (uvcb.header.rc == 0x10a)
>> +		return -EFAULT;
>> +	return -EINVAL;
>> +}
>> +
>>   void setup_uv(void);
>>   void adjust_to_uv_max(unsigned long *vmax);
>>   #else
>> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>>   static inline void setup_uv(void) {}
>>   static inline void adjust_to_uv_max(unsigned long *vmax) {}
>>   static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
>> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
>> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>>   #endif
>>   
>>   #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
>>
> 
>
David Hildenbrand Oct. 25, 2019, 8:40 a.m. UTC | #3
On 25.10.19 10:39, Janosch Frank wrote:
> On 10/25/19 10:31 AM, David Hildenbrand wrote:
>> On 24.10.19 13:40, Janosch Frank wrote:
>>> The convert to/from secure (or also "import/export") ultravisor calls
>>> are need for page management, i.e. paging, of secure execution VM.
>>>
>>> Export encrypts a secure guest's page and makes it accessible to the
>>> guest for paging.
>>
>> How does paging play along with pinning the pages (from
>> uv_convert_to_secure() -> kvm_s390_pv_pin_page()) in a follow up patch?
>> Can you paint me the bigger picture?
> 
> That's a stale comment I should have removed before sending...
> The current patches do not support paging.

Note that once you pin you really have to disable the balloon in the 
QEMU (inhibit it).
Janosch Frank Oct. 25, 2019, 8:42 a.m. UTC | #4
On 10/25/19 10:40 AM, David Hildenbrand wrote:
> On 25.10.19 10:39, Janosch Frank wrote:
>> On 10/25/19 10:31 AM, David Hildenbrand wrote:
>>> On 24.10.19 13:40, Janosch Frank wrote:
>>>> The convert to/from secure (or also "import/export") ultravisor calls
>>>> are need for page management, i.e. paging, of secure execution VM.
>>>>
>>>> Export encrypts a secure guest's page and makes it accessible to the
>>>> guest for paging.
>>>
>>> How does paging play along with pinning the pages (from
>>> uv_convert_to_secure() -> kvm_s390_pv_pin_page()) in a follow up patch?
>>> Can you paint me the bigger picture?
>>
>> That's a stale comment I should have removed before sending...
>> The current patches do not support paging.
> 
> Note that once you pin you really have to disable the balloon in the 
> QEMU (inhibit it).
> 

Yes, and you need the iommu for virtio.
We didn't yet fully discuss how to handle that.
Christian Borntraeger Nov. 1, 2019, 11:26 a.m. UTC | #5
On 24.10.19 13:40, Janosch Frank wrote:
> The convert to/from secure (or also "import/export") ultravisor calls
> are need for page management, i.e. paging, of secure execution VM.
> 
> Export encrypts a secure guest's page and makes it accessible to the
> guest for paging.
> 
> Import makes a page accessible to a secure guest.
> On the first import of that page, the page will be cleared by the
> Ultravisor before it is given to the guest.
> 
> All following imports will decrypt a exported page and verify
> integrity before giving the page to the guest.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
>  arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
> index 0bfbafcca136..99cdd2034503 100644
> --- a/arch/s390/include/asm/uv.h
> +++ b/arch/s390/include/asm/uv.h
> @@ -15,6 +15,7 @@
>  #include <linux/errno.h>
>  #include <linux/bug.h>
>  #include <asm/page.h>
> +#include <asm/gmap.h>
>  
>  #define UVC_RC_EXECUTED		0x0001
>  #define UVC_RC_INV_CMD		0x0002
> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>  	return rc ? -EINVAL : 0;
>  }
>  
> +/*
> + * Requests the Ultravisor to encrypt a guest page and make it
> + * accessible to the host for paging (export).
> + *
> + * @paddr: Absolute host address of page to be exported
> + */
> +static inline int uv_convert_from_secure(unsigned long paddr)
> +{
> +	struct uv_cb_cfs uvcb = {
> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.paddr = paddr
> +	};
> +	if (!uv_call(0, (u64)&uvcb))
> +		return 0;

As discussed on the KVM forum. We should also check for
uvcb.header.rc != UVC_RC_EXECUTED
I know, we cant really do much if this fails, but we certainly want to know.






> +	return -EINVAL;
> +}
> +
> +/*
> + * Requests the Ultravisor to make a page accessible to a guest
> + * (import). If it's brought in the first time, it will be cleared. If
> + * it has been exported before, it will be decrypted and integrity
> + * checked.
> + *
> + * @handle: Ultravisor guest handle
> + * @gaddr: Guest 2 absolute address to be imported
> + */
> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
> +{
> +	int cc;
> +	struct uv_cb_cts uvcb = {
> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.guest_handle = gmap->se_handle,
> +		.gaddr = gaddr
> +	};
> +
> +	cc = uv_call(0, (u64)&uvcb);
> +
> +	if (!cc)
> +		return 0;
> +	if (uvcb.header.rc == 0x104)
> +		return -EEXIST;
> +	if (uvcb.header.rc == 0x10a)
> +		return -EFAULT;

again, we should probably check for rc != UVC_RC_EXECUTED to detect any other problem.

> +	return -EINVAL;
> +}
> +
>  void setup_uv(void);
>  void adjust_to_uv_max(unsigned long *vmax);
>  #else
> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>  static inline void setup_uv(void) {}
>  static inline void adjust_to_uv_max(unsigned long *vmax) {}
>  static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>  #endif
>  
>  #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
>
Janosch Frank Nov. 1, 2019, 12:25 p.m. UTC | #6
On 11/1/19 12:26 PM, Christian Borntraeger wrote:
> 
> 
> On 24.10.19 13:40, Janosch Frank wrote:
>> The convert to/from secure (or also "import/export") ultravisor calls
>> are need for page management, i.e. paging, of secure execution VM.
>>
>> Export encrypts a secure guest's page and makes it accessible to the
>> guest for paging.
>>
>> Import makes a page accessible to a secure guest.
>> On the first import of that page, the page will be cleared by the
>> Ultravisor before it is given to the guest.
>>
>> All following imports will decrypt a exported page and verify
>> integrity before giving the page to the guest.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> ---
>>  arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 51 insertions(+)
>>
>> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
>> index 0bfbafcca136..99cdd2034503 100644
>> --- a/arch/s390/include/asm/uv.h
>> +++ b/arch/s390/include/asm/uv.h
>> @@ -15,6 +15,7 @@
>>  #include <linux/errno.h>
>>  #include <linux/bug.h>
>>  #include <asm/page.h>
>> +#include <asm/gmap.h>
>>  
>>  #define UVC_RC_EXECUTED		0x0001
>>  #define UVC_RC_INV_CMD		0x0002
>> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>>  	return rc ? -EINVAL : 0;
>>  }
>>  
>> +/*
>> + * Requests the Ultravisor to encrypt a guest page and make it
>> + * accessible to the host for paging (export).
>> + *
>> + * @paddr: Absolute host address of page to be exported
>> + */
>> +static inline int uv_convert_from_secure(unsigned long paddr)
>> +{
>> +	struct uv_cb_cfs uvcb = {
>> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
>> +		.header.len = sizeof(uvcb),
>> +		.paddr = paddr
>> +	};
>> +	if (!uv_call(0, (u64)&uvcb))
>> +		return 0;
> 
> As discussed on the KVM forum. We should also check for
> uvcb.header.rc != UVC_RC_EXECUTED
> I know, we cant really do much if this fails, but we certainly want to know.
> 
> 
> 
> 
> 
> 
>> +	return -EINVAL;
>> +}
>> +
>> +/*
>> + * Requests the Ultravisor to make a page accessible to a guest
>> + * (import). If it's brought in the first time, it will be cleared. If
>> + * it has been exported before, it will be decrypted and integrity
>> + * checked.
>> + *
>> + * @handle: Ultravisor guest handle
>> + * @gaddr: Guest 2 absolute address to be imported
>> + */
>> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
>> +{
>> +	int cc;
>> +	struct uv_cb_cts uvcb = {
>> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
>> +		.header.len = sizeof(uvcb),
>> +		.guest_handle = gmap->se_handle,
>> +		.gaddr = gaddr
>> +	};
>> +
>> +	cc = uv_call(0, (u64)&uvcb);
>> +
>> +	if (!cc)
>> +		return 0;
>> +	if (uvcb.header.rc == 0x104)
>> +		return -EEXIST;
>> +	if (uvcb.header.rc == 0x10a)
>> +		return -EFAULT;
> 
> again, we should probably check for rc != UVC_RC_EXECUTED to detect any other problem.

That's handled by the CC and the return below.
CC == 1 means error
cc == 0 is success, that's why we return erly on cc == 0

> 
>> +	return -EINVAL;
>> +}
>> +
>>  void setup_uv(void);
>>  void adjust_to_uv_max(unsigned long *vmax);
>>  #else
>> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>>  static inline void setup_uv(void) {}
>>  static inline void adjust_to_uv_max(unsigned long *vmax) {}
>>  static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
>> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
>> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>>  #endif
>>  
>>  #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
>>
Christian Borntraeger Nov. 1, 2019, 12:39 p.m. UTC | #7
On 01.11.19 13:25, Janosch Frank wrote:
> On 11/1/19 12:26 PM, Christian Borntraeger wrote:
>>
>>
>> On 24.10.19 13:40, Janosch Frank wrote:
>>> The convert to/from secure (or also "import/export") ultravisor calls
>>> are need for page management, i.e. paging, of secure execution VM.
>>>
>>> Export encrypts a secure guest's page and makes it accessible to the
>>> guest for paging.
>>>
>>> Import makes a page accessible to a secure guest.
>>> On the first import of that page, the page will be cleared by the
>>> Ultravisor before it is given to the guest.
>>>
>>> All following imports will decrypt a exported page and verify
>>> integrity before giving the page to the guest.
>>>
>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>>> ---
>>>  arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 51 insertions(+)
>>>
>>> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
>>> index 0bfbafcca136..99cdd2034503 100644
>>> --- a/arch/s390/include/asm/uv.h
>>> +++ b/arch/s390/include/asm/uv.h
>>> @@ -15,6 +15,7 @@
>>>  #include <linux/errno.h>
>>>  #include <linux/bug.h>
>>>  #include <asm/page.h>
>>> +#include <asm/gmap.h>
>>>  
>>>  #define UVC_RC_EXECUTED		0x0001
>>>  #define UVC_RC_INV_CMD		0x0002
>>> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>>>  	return rc ? -EINVAL : 0;
>>>  }
>>>  
>>> +/*
>>> + * Requests the Ultravisor to encrypt a guest page and make it
>>> + * accessible to the host for paging (export).
>>> + *
>>> + * @paddr: Absolute host address of page to be exported
>>> + */
>>> +static inline int uv_convert_from_secure(unsigned long paddr)
>>> +{
>>> +	struct uv_cb_cfs uvcb = {
>>> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
>>> +		.header.len = sizeof(uvcb),
>>> +		.paddr = paddr
>>> +	};
>>> +	if (!uv_call(0, (u64)&uvcb))
>>> +		return 0;
>>
>> As discussed on the KVM forum. We should also check for
>> uvcb.header.rc != UVC_RC_EXECUTED
>> I know, we cant really do much if this fails, but we certainly want to know.
>>
>>
>>
>>
>>
>>
>>> +	return -EINVAL;
>>> +}
>>> +
>>> +/*
>>> + * Requests the Ultravisor to make a page accessible to a guest
>>> + * (import). If it's brought in the first time, it will be cleared. If
>>> + * it has been exported before, it will be decrypted and integrity
>>> + * checked.
>>> + *
>>> + * @handle: Ultravisor guest handle
>>> + * @gaddr: Guest 2 absolute address to be imported
>>> + */
>>> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
>>> +{
>>> +	int cc;
>>> +	struct uv_cb_cts uvcb = {
>>> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
>>> +		.header.len = sizeof(uvcb),
>>> +		.guest_handle = gmap->se_handle,
>>> +		.gaddr = gaddr
>>> +	};
>>> +
>>> +	cc = uv_call(0, (u64)&uvcb);
>>> +
>>> +	if (!cc)
>>> +		return 0;
>>> +	if (uvcb.header.rc == 0x104)
>>> +		return -EEXIST;
>>> +	if (uvcb.header.rc == 0x10a)
>>> +		return -EFAULT;
>>
>> again, we should probably check for rc != UVC_RC_EXECUTED to detect any other problem.
> 
> That's handled by the CC and the return below.
> CC == 1 means error
> cc == 0 is success, that's why we return erly on cc == 0

Right, uv_call return depends on CC. Nevermind.
Christian Borntraeger Nov. 1, 2019, 12:42 p.m. UTC | #8
On 24.10.19 13:40, Janosch Frank wrote:
> The convert to/from secure (or also "import/export") ultravisor calls
> are need for page management, i.e. paging, of secure execution VM.
> 
> Export encrypts a secure guest's page and makes it accessible to the
> guest for paging.
> 
> Import makes a page accessible to a secure guest.
> On the first import of that page, the page will be cleared by the
> Ultravisor before it is given to the guest.
> 
> All following imports will decrypt a exported page and verify
> integrity before giving the page to the guest.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

After re-reading.
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
>  arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
> index 0bfbafcca136..99cdd2034503 100644
> --- a/arch/s390/include/asm/uv.h
> +++ b/arch/s390/include/asm/uv.h
> @@ -15,6 +15,7 @@
>  #include <linux/errno.h>
>  #include <linux/bug.h>
>  #include <asm/page.h>
> +#include <asm/gmap.h>
>  
>  #define UVC_RC_EXECUTED		0x0001
>  #define UVC_RC_INV_CMD		0x0002
> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>  	return rc ? -EINVAL : 0;
>  }
>  
> +/*
> + * Requests the Ultravisor to encrypt a guest page and make it
> + * accessible to the host for paging (export).
> + *
> + * @paddr: Absolute host address of page to be exported
> + */
> +static inline int uv_convert_from_secure(unsigned long paddr)
> +{
> +	struct uv_cb_cfs uvcb = {
> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.paddr = paddr
> +	};
> +	if (!uv_call(0, (u64)&uvcb))
> +		return 0;
> +	return -EINVAL;
> +}
> +
> +/*
> + * Requests the Ultravisor to make a page accessible to a guest
> + * (import). If it's brought in the first time, it will be cleared. If
> + * it has been exported before, it will be decrypted and integrity
> + * checked.
> + *
> + * @handle: Ultravisor guest handle
> + * @gaddr: Guest 2 absolute address to be imported
> + */
> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
> +{
> +	int cc;
> +	struct uv_cb_cts uvcb = {
> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.guest_handle = gmap->se_handle,
> +		.gaddr = gaddr
> +	};
> +
> +	cc = uv_call(0, (u64)&uvcb);
> +
> +	if (!cc)
> +		return 0;
> +	if (uvcb.header.rc == 0x104)
> +		return -EEXIST;
> +	if (uvcb.header.rc == 0x10a)
> +		return -EFAULT;
> +	return -EINVAL;
> +}
> +
>  void setup_uv(void);
>  void adjust_to_uv_max(unsigned long *vmax);
>  #else
> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>  static inline void setup_uv(void) {}
>  static inline void adjust_to_uv_max(unsigned long *vmax) {}
>  static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>  #endif
>  
>  #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
>
Cornelia Huck Nov. 11, 2019, 4:40 p.m. UTC | #9
On Thu, 24 Oct 2019 07:40:28 -0400
Janosch Frank <frankja@linux.ibm.com> wrote:

> The convert to/from secure (or also "import/export") ultravisor calls
> are need for page management, i.e. paging, of secure execution VM.
> 
> Export encrypts a secure guest's page and makes it accessible to the
> guest for paging.
> 
> Import makes a page accessible to a secure guest.
> On the first import of that page, the page will be cleared by the
> Ultravisor before it is given to the guest.
> 
> All following imports will decrypt a exported page and verify
> integrity before giving the page to the guest.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
>  arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
> index 0bfbafcca136..99cdd2034503 100644
> --- a/arch/s390/include/asm/uv.h
> +++ b/arch/s390/include/asm/uv.h
> @@ -15,6 +15,7 @@
>  #include <linux/errno.h>
>  #include <linux/bug.h>
>  #include <asm/page.h>
> +#include <asm/gmap.h>
>  
>  #define UVC_RC_EXECUTED		0x0001
>  #define UVC_RC_INV_CMD		0x0002
> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>  	return rc ? -EINVAL : 0;
>  }
>  
> +/*
> + * Requests the Ultravisor to encrypt a guest page and make it
> + * accessible to the host for paging (export).
> + *
> + * @paddr: Absolute host address of page to be exported
> + */
> +static inline int uv_convert_from_secure(unsigned long paddr)
> +{
> +	struct uv_cb_cfs uvcb = {
> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.paddr = paddr
> +	};
> +	if (!uv_call(0, (u64)&uvcb))
> +		return 0;
> +	return -EINVAL;

No possibility for other return codes here (e.g. -EFAULT)? (Asking
because you look at a rc in the control block in the reverse function.)

> +}
> +
> +/*
> + * Requests the Ultravisor to make a page accessible to a guest
> + * (import). If it's brought in the first time, it will be cleared. If
> + * it has been exported before, it will be decrypted and integrity
> + * checked.
> + *
> + * @handle: Ultravisor guest handle
> + * @gaddr: Guest 2 absolute address to be imported
> + */
> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
> +{
> +	int cc;
> +	struct uv_cb_cts uvcb = {
> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
> +		.header.len = sizeof(uvcb),
> +		.guest_handle = gmap->se_handle,
> +		.gaddr = gaddr
> +	};
> +
> +	cc = uv_call(0, (u64)&uvcb);
> +
> +	if (!cc)
> +		return 0;
> +	if (uvcb.header.rc == 0x104)
> +		return -EEXIST;
> +	if (uvcb.header.rc == 0x10a)
> +		return -EFAULT;
> +	return -EINVAL;
> +}
> +
>  void setup_uv(void);
>  void adjust_to_uv_max(unsigned long *vmax);
>  #else
> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>  static inline void setup_uv(void) {}
>  static inline void adjust_to_uv_max(unsigned long *vmax) {}
>  static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>  #endif
>  
>  #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
Janosch Frank Nov. 11, 2019, 4:56 p.m. UTC | #10
On 11/11/19 5:40 PM, Cornelia Huck wrote:
> On Thu, 24 Oct 2019 07:40:28 -0400
> Janosch Frank <frankja@linux.ibm.com> wrote:
> 
>> The convert to/from secure (or also "import/export") ultravisor calls
>> are need for page management, i.e. paging, of secure execution VM.
>>
>> Export encrypts a secure guest's page and makes it accessible to the
>> guest for paging.
>>
>> Import makes a page accessible to a secure guest.
>> On the first import of that page, the page will be cleared by the
>> Ultravisor before it is given to the guest.
>>
>> All following imports will decrypt a exported page and verify
>> integrity before giving the page to the guest.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> ---
>>  arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 51 insertions(+)
>>
>> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
>> index 0bfbafcca136..99cdd2034503 100644
>> --- a/arch/s390/include/asm/uv.h
>> +++ b/arch/s390/include/asm/uv.h
>> @@ -15,6 +15,7 @@
>>  #include <linux/errno.h>
>>  #include <linux/bug.h>
>>  #include <asm/page.h>
>> +#include <asm/gmap.h>
>>  
>>  #define UVC_RC_EXECUTED		0x0001
>>  #define UVC_RC_INV_CMD		0x0002
>> @@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
>>  	return rc ? -EINVAL : 0;
>>  }
>>  
>> +/*
>> + * Requests the Ultravisor to encrypt a guest page and make it
>> + * accessible to the host for paging (export).
>> + *
>> + * @paddr: Absolute host address of page to be exported
>> + */
>> +static inline int uv_convert_from_secure(unsigned long paddr)
>> +{
>> +	struct uv_cb_cfs uvcb = {
>> +		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
>> +		.header.len = sizeof(uvcb),
>> +		.paddr = paddr
>> +	};
>> +	if (!uv_call(0, (u64)&uvcb))
>> +		return 0;
>> +	return -EINVAL;
> 
> No possibility for other return codes here (e.g. -EFAULT)? (Asking
> because you look at a rc in the control block in the reverse function.)

Notice the "paddr" variable?
We work on physical memory for this UV call, all error codes that are
defined are either input errors (not possible via the exception
handlers), a KVM management error or an attack on the VM.

> 
>> +}
>> +
>> +/*
>> + * Requests the Ultravisor to make a page accessible to a guest
>> + * (import). If it's brought in the first time, it will be cleared. If
>> + * it has been exported before, it will be decrypted and integrity
>> + * checked.
>> + *
>> + * @handle: Ultravisor guest handle
>> + * @gaddr: Guest 2 absolute address to be imported
>> + */
>> +static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
>> +{
>> +	int cc;
>> +	struct uv_cb_cts uvcb = {
>> +		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
>> +		.header.len = sizeof(uvcb),
>> +		.guest_handle = gmap->se_handle,
>> +		.gaddr = gaddr
>> +	};
>> +
>> +	cc = uv_call(0, (u64)&uvcb);
>> +
>> +	if (!cc)
>> +		return 0;
>> +	if (uvcb.header.rc == 0x104)
>> +		return -EEXIST;
>> +	if (uvcb.header.rc == 0x10a)
>> +		return -EFAULT;
>> +	return -EINVAL;
>> +}
>> +
>>  void setup_uv(void);
>>  void adjust_to_uv_max(unsigned long *vmax);
>>  #else
>> @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);
>>  static inline void setup_uv(void) {}
>>  static inline void adjust_to_uv_max(unsigned long *vmax) {}
>>  static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
>> +static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
>> +static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
>>  #endif
>>  
>>  #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \
>
diff mbox series

Patch

diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
index 0bfbafcca136..99cdd2034503 100644
--- a/arch/s390/include/asm/uv.h
+++ b/arch/s390/include/asm/uv.h
@@ -15,6 +15,7 @@ 
 #include <linux/errno.h>
 #include <linux/bug.h>
 #include <asm/page.h>
+#include <asm/gmap.h>
 
 #define UVC_RC_EXECUTED		0x0001
 #define UVC_RC_INV_CMD		0x0002
@@ -279,6 +280,54 @@  static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)
 	return rc ? -EINVAL : 0;
 }
 
+/*
+ * Requests the Ultravisor to encrypt a guest page and make it
+ * accessible to the host for paging (export).
+ *
+ * @paddr: Absolute host address of page to be exported
+ */
+static inline int uv_convert_from_secure(unsigned long paddr)
+{
+	struct uv_cb_cfs uvcb = {
+		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
+		.header.len = sizeof(uvcb),
+		.paddr = paddr
+	};
+	if (!uv_call(0, (u64)&uvcb))
+		return 0;
+	return -EINVAL;
+}
+
+/*
+ * Requests the Ultravisor to make a page accessible to a guest
+ * (import). If it's brought in the first time, it will be cleared. If
+ * it has been exported before, it will be decrypted and integrity
+ * checked.
+ *
+ * @handle: Ultravisor guest handle
+ * @gaddr: Guest 2 absolute address to be imported
+ */
+static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
+{
+	int cc;
+	struct uv_cb_cts uvcb = {
+		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
+		.header.len = sizeof(uvcb),
+		.guest_handle = gmap->se_handle,
+		.gaddr = gaddr
+	};
+
+	cc = uv_call(0, (u64)&uvcb);
+
+	if (!cc)
+		return 0;
+	if (uvcb.header.rc == 0x104)
+		return -EEXIST;
+	if (uvcb.header.rc == 0x10a)
+		return -EFAULT;
+	return -EINVAL;
+}
+
 void setup_uv(void);
 void adjust_to_uv_max(unsigned long *vmax);
 #else
@@ -286,6 +335,8 @@  void adjust_to_uv_max(unsigned long *vmax);
 static inline void setup_uv(void) {}
 static inline void adjust_to_uv_max(unsigned long *vmax) {}
 static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) { return 0; }
+static inline int uv_convert_from_secure(unsigned long paddr) { return 0; }
+static inline int uv_convert_to_secure(unsigned long handle, unsigned long gaddr) { return 0; }
 #endif
 
 #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) ||                          \