diff mbox series

[kvm-unit-tests,v2,3/3] s390x: Ultravisor guest API test

Message ID 20200727095415.494318-4-frankja@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series PV tests part 1 | expand

Commit Message

Janosch Frank July 27, 2020, 9:54 a.m. UTC
Test the error conditions of guest 2 Ultravisor calls, namely:
     * Query Ultravisor information
     * Set shared access
     * Remove shared access

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
 lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
 s390x/Makefile      |   1 +
 s390x/unittests.cfg |   3 +
 s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 231 insertions(+)
 create mode 100644 lib/s390x/asm/uv.h
 create mode 100644 s390x/uv-guest.c

Comments

Cornelia Huck July 30, 2020, 11:16 a.m. UTC | #1
On Mon, 27 Jul 2020 05:54:15 -0400
Janosch Frank <frankja@linux.ibm.com> wrote:

> Test the error conditions of guest 2 Ultravisor calls, namely:
>      * Query Ultravisor information
>      * Set shared access
>      * Remove shared access
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> ---
>  lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
>  s390x/Makefile      |   1 +
>  s390x/unittests.cfg |   3 +
>  s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 231 insertions(+)
>  create mode 100644 lib/s390x/asm/uv.h
>  create mode 100644 s390x/uv-guest.c
> 

(...)

> +static inline int uv_call(unsigned long r1, unsigned long r2)
> +{
> +	int cc;
> +
> +	asm volatile(
> +		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
> +		"		brc	3,0b\n"
> +		"		ipm	%[cc]\n"
> +		"		srl	%[cc],28\n"
> +		: [cc] "=d" (cc)
> +		: [r1] "a" (r1), [r2] "a" (r2)
> +		: "memory", "cc");
> +	return cc;
> +}

This returns the condition code, but no caller seems to check it
(instead, they look at header.rc, which is presumably only set if the
instruction executed successfully in some way?)

Looking at the kernel, it retries for cc > 1 (presumably busy
conditions), and cc != 0 seems to be considered a failure. Do we want
to look at the cc here as well?

(...)
Thomas Huth July 30, 2020, 3:58 p.m. UTC | #2
On 30/07/2020 13.16, Cornelia Huck wrote:
> On Mon, 27 Jul 2020 05:54:15 -0400
> Janosch Frank <frankja@linux.ibm.com> wrote:
> 
>> Test the error conditions of guest 2 Ultravisor calls, namely:
>>      * Query Ultravisor information
>>      * Set shared access
>>      * Remove shared access
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
>> ---
>>  lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
>>  s390x/Makefile      |   1 +
>>  s390x/unittests.cfg |   3 +
>>  s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 231 insertions(+)
>>  create mode 100644 lib/s390x/asm/uv.h
>>  create mode 100644 s390x/uv-guest.c
>>
> 
> (...)
> 
>> +static inline int uv_call(unsigned long r1, unsigned long r2)
>> +{
>> +	int cc;
>> +
>> +	asm volatile(
>> +		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
>> +		"		brc	3,0b\n"
>> +		"		ipm	%[cc]\n"
>> +		"		srl	%[cc],28\n"
>> +		: [cc] "=d" (cc)
>> +		: [r1] "a" (r1), [r2] "a" (r2)
>> +		: "memory", "cc");
>> +	return cc;
>> +}
> 
> This returns the condition code, but no caller seems to check it
> (instead, they look at header.rc, which is presumably only set if the
> instruction executed successfully in some way?)
> 
> Looking at the kernel, it retries for cc > 1 (presumably busy
> conditions), and cc != 0 seems to be considered a failure. Do we want
> to look at the cc here as well?

It's there - but here it's in the assembly code, the "brc 3,0b".

Patch looks ok to me (but I didn't do a full review):

Acked-by: Thomas Huth <thuth@redhat.com>
Janosch Frank July 31, 2020, 7:34 a.m. UTC | #3
On 7/30/20 5:58 PM, Thomas Huth wrote:
> On 30/07/2020 13.16, Cornelia Huck wrote:
>> On Mon, 27 Jul 2020 05:54:15 -0400
>> Janosch Frank <frankja@linux.ibm.com> wrote:
>>
>>> Test the error conditions of guest 2 Ultravisor calls, namely:
>>>      * Query Ultravisor information
>>>      * Set shared access
>>>      * Remove shared access
>>>
>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>>> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
>>> ---
>>>  lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
>>>  s390x/Makefile      |   1 +
>>>  s390x/unittests.cfg |   3 +
>>>  s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 231 insertions(+)
>>>  create mode 100644 lib/s390x/asm/uv.h
>>>  create mode 100644 s390x/uv-guest.c
>>>
>>
>> (...)
>>
>>> +static inline int uv_call(unsigned long r1, unsigned long r2)
>>> +{
>>> +	int cc;
>>> +
>>> +	asm volatile(
>>> +		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
>>> +		"		brc	3,0b\n"
>>> +		"		ipm	%[cc]\n"
>>> +		"		srl	%[cc],28\n"
>>> +		: [cc] "=d" (cc)
>>> +		: [r1] "a" (r1), [r2] "a" (r2)
>>> +		: "memory", "cc");
>>> +	return cc;
>>> +}
>>
>> This returns the condition code, but no caller seems to check it
>> (instead, they look at header.rc, which is presumably only set if the
>> instruction executed successfully in some way?)
>>
>> Looking at the kernel, it retries for cc > 1 (presumably busy
>> conditions), and cc != 0 seems to be considered a failure. Do we want
>> to look at the cc here as well?
> 
> It's there - but here it's in the assembly code, the "brc 3,0b".

Yes, we needed to factor that out in KVM because we sometimes need to
schedule and then it looks nicer handling that in C code. The branch on
condition will jump back for cc 2 and 3. cc 0 and 1 are success and
error respectively and only then the rc and rrc in the UV header are set.

> 
> Patch looks ok to me (but I didn't do a full review):
> 
> Acked-by: Thomas Huth <thuth@redhat.com>
>
Cornelia Huck July 31, 2020, 8:42 a.m. UTC | #4
On Fri, 31 Jul 2020 09:34:41 +0200
Janosch Frank <frankja@linux.ibm.com> wrote:

> On 7/30/20 5:58 PM, Thomas Huth wrote:
> > On 30/07/2020 13.16, Cornelia Huck wrote:  
> >> On Mon, 27 Jul 2020 05:54:15 -0400
> >> Janosch Frank <frankja@linux.ibm.com> wrote:
> >>  
> >>> Test the error conditions of guest 2 Ultravisor calls, namely:
> >>>      * Query Ultravisor information
> >>>      * Set shared access
> >>>      * Remove shared access
> >>>
> >>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> >>> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> >>> ---
> >>>  lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
> >>>  s390x/Makefile      |   1 +
> >>>  s390x/unittests.cfg |   3 +
> >>>  s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
> >>>  4 files changed, 231 insertions(+)
> >>>  create mode 100644 lib/s390x/asm/uv.h
> >>>  create mode 100644 s390x/uv-guest.c
> >>>  
> >>
> >> (...)
> >>  
> >>> +static inline int uv_call(unsigned long r1, unsigned long r2)
> >>> +{
> >>> +	int cc;
> >>> +
> >>> +	asm volatile(
> >>> +		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
> >>> +		"		brc	3,0b\n"
> >>> +		"		ipm	%[cc]\n"
> >>> +		"		srl	%[cc],28\n"
> >>> +		: [cc] "=d" (cc)
> >>> +		: [r1] "a" (r1), [r2] "a" (r2)
> >>> +		: "memory", "cc");
> >>> +	return cc;
> >>> +}  
> >>
> >> This returns the condition code, but no caller seems to check it
> >> (instead, they look at header.rc, which is presumably only set if the
> >> instruction executed successfully in some way?)
> >>
> >> Looking at the kernel, it retries for cc > 1 (presumably busy
> >> conditions), and cc != 0 seems to be considered a failure. Do we want
> >> to look at the cc here as well?  
> > 
> > It's there - but here it's in the assembly code, the "brc 3,0b".  

Ah yes, I missed that.

> 
> Yes, we needed to factor that out in KVM because we sometimes need to
> schedule and then it looks nicer handling that in C code. The branch on
> condition will jump back for cc 2 and 3. cc 0 and 1 are success and
> error respectively and only then the rc and rrc in the UV header are set.

Yeah, it's a bit surprising that rc/rrc are also set with cc 1.

(Can you add a comment? Just so that it is clear that callers never
need to check the cc, as rc/rrc already contain more information than
that.)

> 
> > 
> > Patch looks ok to me (but I didn't do a full review):
> > 
> > Acked-by: Thomas Huth <thuth@redhat.com>
> >   
> 
>
Janosch Frank July 31, 2020, 9:06 a.m. UTC | #5
On 7/31/20 10:42 AM, Cornelia Huck wrote:
> On Fri, 31 Jul 2020 09:34:41 +0200
> Janosch Frank <frankja@linux.ibm.com> wrote:
> 
>> On 7/30/20 5:58 PM, Thomas Huth wrote:
>>> On 30/07/2020 13.16, Cornelia Huck wrote:  
>>>> On Mon, 27 Jul 2020 05:54:15 -0400
>>>> Janosch Frank <frankja@linux.ibm.com> wrote:
>>>>  
>>>>> Test the error conditions of guest 2 Ultravisor calls, namely:
>>>>>      * Query Ultravisor information
>>>>>      * Set shared access
>>>>>      * Remove shared access
>>>>>
>>>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>>>>> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
>>>>> ---
>>>>>  lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
>>>>>  s390x/Makefile      |   1 +
>>>>>  s390x/unittests.cfg |   3 +
>>>>>  s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
>>>>>  4 files changed, 231 insertions(+)
>>>>>  create mode 100644 lib/s390x/asm/uv.h
>>>>>  create mode 100644 s390x/uv-guest.c
>>>>>  
>>>>
>>>> (...)
>>>>  
>>>>> +static inline int uv_call(unsigned long r1, unsigned long r2)
>>>>> +{
>>>>> +	int cc;
>>>>> +
>>>>> +	asm volatile(
>>>>> +		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
>>>>> +		"		brc	3,0b\n"
>>>>> +		"		ipm	%[cc]\n"
>>>>> +		"		srl	%[cc],28\n"
>>>>> +		: [cc] "=d" (cc)
>>>>> +		: [r1] "a" (r1), [r2] "a" (r2)
>>>>> +		: "memory", "cc");
>>>>> +	return cc;
>>>>> +}  
>>>>
>>>> This returns the condition code, but no caller seems to check it
>>>> (instead, they look at header.rc, which is presumably only set if the
>>>> instruction executed successfully in some way?)
>>>>
>>>> Looking at the kernel, it retries for cc > 1 (presumably busy
>>>> conditions), and cc != 0 seems to be considered a failure. Do we want
>>>> to look at the cc here as well?  
>>>
>>> It's there - but here it's in the assembly code, the "brc 3,0b".  
> 
> Ah yes, I missed that.
> 
>>
>> Yes, we needed to factor that out in KVM because we sometimes need to
>> schedule and then it looks nicer handling that in C code. The branch on
>> condition will jump back for cc 2 and 3. cc 0 and 1 are success and
>> error respectively and only then the rc and rrc in the UV header are set.
> 
> Yeah, it's a bit surprising that rc/rrc are also set with cc 1.

Is it?
The (r)rc *only* contain meaningful information on CC 1.
On CC 0 they will simply say everything is fine which CC 0 states
already anyway.

> 
> (Can you add a comment? Just so that it is clear that callers never
> need to check the cc, as rc/rrc already contain more information than
> that.)

I'd rather fix my test code and also check the CC.
I did check it for my other UV tests so I've no idea why I didn't do it
here...


How about adding a comment for the cc 2/3 case?
"The brc instruction will take care of the cc 2/3 case where we need to
continue the execution because we were interrupted.
The inline assembly will only return on success/error i.e. cc 0/1."

> 
>>
>>>
>>> Patch looks ok to me (but I didn't do a full review):
>>>
>>> Acked-by: Thomas Huth <thuth@redhat.com>
>>>   
>>
>>
>
Cornelia Huck July 31, 2020, 9:21 a.m. UTC | #6
On Fri, 31 Jul 2020 11:06:25 +0200
Janosch Frank <frankja@linux.ibm.com> wrote:

> On 7/31/20 10:42 AM, Cornelia Huck wrote:
> > On Fri, 31 Jul 2020 09:34:41 +0200
> > Janosch Frank <frankja@linux.ibm.com> wrote:
> >   
> >> On 7/30/20 5:58 PM, Thomas Huth wrote:  
> >>> On 30/07/2020 13.16, Cornelia Huck wrote:    
> >>>> On Mon, 27 Jul 2020 05:54:15 -0400
> >>>> Janosch Frank <frankja@linux.ibm.com> wrote:
> >>>>    
> >>>>> Test the error conditions of guest 2 Ultravisor calls, namely:
> >>>>>      * Query Ultravisor information
> >>>>>      * Set shared access
> >>>>>      * Remove shared access
> >>>>>
> >>>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> >>>>> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> >>>>> ---
> >>>>>  lib/s390x/asm/uv.h  |  68 +++++++++++++++++++
> >>>>>  s390x/Makefile      |   1 +
> >>>>>  s390x/unittests.cfg |   3 +
> >>>>>  s390x/uv-guest.c    | 159 ++++++++++++++++++++++++++++++++++++++++++++
> >>>>>  4 files changed, 231 insertions(+)
> >>>>>  create mode 100644 lib/s390x/asm/uv.h
> >>>>>  create mode 100644 s390x/uv-guest.c
> >>>>>    
> >>>>
> >>>> (...)
> >>>>    
> >>>>> +static inline int uv_call(unsigned long r1, unsigned long r2)
> >>>>> +{
> >>>>> +	int cc;
> >>>>> +
> >>>>> +	asm volatile(
> >>>>> +		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
> >>>>> +		"		brc	3,0b\n"
> >>>>> +		"		ipm	%[cc]\n"
> >>>>> +		"		srl	%[cc],28\n"
> >>>>> +		: [cc] "=d" (cc)
> >>>>> +		: [r1] "a" (r1), [r2] "a" (r2)
> >>>>> +		: "memory", "cc");
> >>>>> +	return cc;
> >>>>> +}    
> >>>>
> >>>> This returns the condition code, but no caller seems to check it
> >>>> (instead, they look at header.rc, which is presumably only set if the
> >>>> instruction executed successfully in some way?)
> >>>>
> >>>> Looking at the kernel, it retries for cc > 1 (presumably busy
> >>>> conditions), and cc != 0 seems to be considered a failure. Do we want
> >>>> to look at the cc here as well?    
> >>>
> >>> It's there - but here it's in the assembly code, the "brc 3,0b".    
> > 
> > Ah yes, I missed that.
> >   
> >>
> >> Yes, we needed to factor that out in KVM because we sometimes need to
> >> schedule and then it looks nicer handling that in C code. The branch on
> >> condition will jump back for cc 2 and 3. cc 0 and 1 are success and
> >> error respectively and only then the rc and rrc in the UV header are set.  
> > 
> > Yeah, it's a bit surprising that rc/rrc are also set with cc 1.  
> 
> Is it?
> The (r)rc *only* contain meaningful information on CC 1.
> On CC 0 they will simply say everything is fine which CC 0 states
> already anyway.

I would consider "things worked" to actually be meaningful :)

(I've seen other instructions indicating different kinds of success.)

> 
> > 
> > (Can you add a comment? Just so that it is clear that callers never
> > need to check the cc, as rc/rrc already contain more information than
> > that.)  
> 
> I'd rather fix my test code and also check the CC.
> I did check it for my other UV tests so I've no idea why I didn't do it
> here...
> 
> 
> How about adding a comment for the cc 2/3 case?
> "The brc instruction will take care of the cc 2/3 case where we need to
> continue the execution because we were interrupted.
> The inline assembly will only return on success/error i.e. cc 0/1."

Sounds good.
diff mbox series

Patch

diff --git a/lib/s390x/asm/uv.h b/lib/s390x/asm/uv.h
new file mode 100644
index 0000000..14ab5cc
--- /dev/null
+++ b/lib/s390x/asm/uv.h
@@ -0,0 +1,68 @@ 
+/*
+ * s390x Ultravisor related definitions
+ *
+ * Copyright (c) 2020 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ */
+#ifndef UV_H
+#define UV_H
+
+#define UVC_RC_EXECUTED		0x0001
+#define UVC_RC_INV_CMD		0x0002
+#define UVC_RC_INV_STATE	0x0003
+#define UVC_RC_INV_LEN		0x0005
+#define UVC_RC_NO_RESUME	0x0007
+
+#define UVC_CMD_QUI			0x0001
+#define UVC_CMD_SET_SHARED_ACCESS	0x1000
+#define UVC_CMD_REMOVE_SHARED_ACCESS	0x1001
+
+/* Bits in installed uv calls */
+enum uv_cmds_inst {
+	BIT_UVC_CMD_QUI = 0,
+	BIT_UVC_CMD_SET_SHARED_ACCESS = 8,
+	BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9,
+};
+
+struct uv_cb_header {
+	u16 len;
+	u16 cmd;	/* Command Code */
+	u16 rc;		/* Response Code */
+	u16 rrc;	/* Return Reason Code */
+} __attribute__((packed))  __attribute__((aligned(8)));
+
+struct uv_cb_qui {
+	struct uv_cb_header header;
+	u64 reserved08;
+	u64 inst_calls_list[4];
+	u64 reserved30[15];
+} __attribute__((packed))  __attribute__((aligned(8)));
+
+struct uv_cb_share {
+	struct uv_cb_header header;
+	u64 reserved08[3];
+	u64 paddr;
+	u64 reserved28;
+} __attribute__((packed))  __attribute__((aligned(8)));
+
+static inline int uv_call(unsigned long r1, unsigned long r2)
+{
+	int cc;
+
+	asm volatile(
+		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
+		"		brc	3,0b\n"
+		"		ipm	%[cc]\n"
+		"		srl	%[cc],28\n"
+		: [cc] "=d" (cc)
+		: [r1] "a" (r1), [r2] "a" (r2)
+		: "memory", "cc");
+	return cc;
+}
+
+#endif
diff --git a/s390x/Makefile b/s390x/Makefile
index 0f54bf4..c2213ad 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -18,6 +18,7 @@  tests += $(TEST_DIR)/skrf.elf
 tests += $(TEST_DIR)/smp.elf
 tests += $(TEST_DIR)/sclp.elf
 tests += $(TEST_DIR)/css.elf
+tests += $(TEST_DIR)/uv-guest.elf
 tests_binary = $(patsubst %.elf,%.bin,$(tests))
 
 all: directories test_cases test_cases_binary
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index b35269b..6d50c63 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -92,3 +92,6 @@  extra_params = -device virtio-net-ccw
 [skrf]
 file = skrf.elf
 smp = 2
+
+[uv-guest]
+file = uv-guest.elf
diff --git a/s390x/uv-guest.c b/s390x/uv-guest.c
new file mode 100644
index 0000000..15720a9
--- /dev/null
+++ b/s390x/uv-guest.c
@@ -0,0 +1,159 @@ 
+/*
+ * Guest Ultravisor Call tests
+ *
+ * Copyright (c) 2020 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include <libcflat.h>
+#include <alloc_page.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+#include <asm/interrupt.h>
+#include <asm/facility.h>
+#include <asm/uv.h>
+
+static unsigned long page;
+
+static inline int share(unsigned long addr, u16 cmd)
+{
+	struct uv_cb_share uvcb = {
+		.header.cmd = cmd,
+		.header.len = sizeof(uvcb),
+		.paddr = addr
+	};
+
+	uv_call(0, (u64)&uvcb);
+	return uvcb.header.rc;
+}
+
+static inline int uv_set_shared(unsigned long addr)
+{
+	return share(addr, UVC_CMD_SET_SHARED_ACCESS);
+}
+
+static inline int uv_remove_shared(unsigned long addr)
+{
+	return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
+}
+
+static void test_priv(void)
+{
+	struct uv_cb_header uvcb = {};
+
+	report_prefix_push("privileged");
+
+	report_prefix_push("query");
+	expect_pgm_int();
+	uvcb.cmd = UVC_CMD_QUI;
+	uvcb.len = sizeof(struct uv_cb_qui);
+	enter_pstate();
+	uv_call(0, (u64)&uvcb);
+	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
+	report_prefix_pop();
+
+	report_prefix_push("share");
+	expect_pgm_int();
+	enter_pstate();
+	uv_set_shared((unsigned long)page);
+	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
+	report_prefix_pop();
+
+	report_prefix_push("unshare");
+	expect_pgm_int();
+	enter_pstate();
+	uv_remove_shared((unsigned long)page);
+	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
+	report_prefix_pop();
+
+	report_prefix_pop();
+}
+
+static void test_query(void)
+{
+	struct uv_cb_qui uvcb = {
+		.header.cmd = UVC_CMD_QUI,
+		.header.len = sizeof(uvcb) - 8,
+	};
+
+	report_prefix_push("query");
+	uv_call(0, (u64)&uvcb);
+	report(uvcb.header.rc == UVC_RC_INV_LEN, "length");
+
+	uvcb.header.len = sizeof(uvcb);
+	uv_call(0, (u64)&uvcb);
+	report(uvcb.header.rc == UVC_RC_EXECUTED, "successful query");
+
+	/*
+	 * These bits have been introduced with the very first
+	 * Ultravisor version and are expected to always be available
+	 * because they are basic building blocks.
+	 */
+	report(uvcb.inst_calls_list[0] & (1UL << (63 - BIT_UVC_CMD_QUI)),
+	       "query indicated");
+	report(uvcb.inst_calls_list[0] & (1UL << (63 - BIT_UVC_CMD_SET_SHARED_ACCESS)),
+	       "share indicated");
+	report(uvcb.inst_calls_list[0] & (1UL << (63 - BIT_UVC_CMD_REMOVE_SHARED_ACCESS)),
+	       "unshare indicated");
+	report_prefix_pop();
+}
+
+static void test_sharing(void)
+{
+	struct uv_cb_share uvcb = {
+		.header.cmd = UVC_CMD_SET_SHARED_ACCESS,
+		.header.len = sizeof(uvcb) - 8,
+	};
+
+	report_prefix_push("share");
+	uv_call(0, (u64)&uvcb);
+	report(uvcb.header.rc == UVC_RC_INV_LEN, "length");
+	report(uv_set_shared(page) == UVC_RC_EXECUTED, "share");
+	report_prefix_pop();
+
+	report_prefix_push("unshare");
+	uvcb.header.cmd = UVC_CMD_REMOVE_SHARED_ACCESS;
+	uv_call(0, (u64)&uvcb);
+	report(uvcb.header.rc == UVC_RC_INV_LEN, "length");
+	report(uv_remove_shared(page) == UVC_RC_EXECUTED, "unshare");
+	report_prefix_pop();
+
+	report_prefix_pop();
+}
+
+static void test_invalid(void)
+{
+	struct uv_cb_header uvcb = {
+		.len = 16,
+		.cmd = 0x4242,
+	};
+
+	uv_call(0, (u64)&uvcb);
+	report(uvcb.rc == UVC_RC_INV_CMD, "invalid command");
+}
+
+int main(void)
+{
+	bool has_uvc = test_facility(158);
+
+	report_prefix_push("uvc");
+	if (!has_uvc) {
+		report_skip("Ultravisor call facility is not available");
+		goto done;
+	}
+
+	page = (unsigned long)alloc_page();
+	test_priv();
+	test_invalid();
+	test_query();
+	test_sharing();
+	free_page((void *)page);
+done:
+	report_prefix_pop();
+	return report_summary();
+}