Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 5/6] arm64: dts: qcom: qcs6490-rb3gen2: Enable USB Type-C display
From: Dmitry Baryshkov @ 2024-03-28  2:04 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: cros-qcom-dts-watchers, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, linux-arm-msm, devicetree, linux-kernel,
	linux-arm-kernel, Neil Armstrong, Krishna Kurapati PSSNV
In-Reply-To: <20240326-rb3gen2-dp-connector-v2-5-a9f1bc32ecaf@quicinc.com>

On Wed, 27 Mar 2024 at 04:04, Bjorn Andersson <quic_bjorande@quicinc.com> wrote:
>
> With the ADSP remoteproc loaded pmic_glink can be introduced and
> together with the redriver wired up to provide role and orientation
> switching signals as well as USB Type-C display on the RB3gen2.
>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> Tested-By: Krishna Kurapati PSSNV <quic_kriskura@quicinc.com>
> Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
> ---
>  arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 107 ++++++++++++++++++++++++++-
>  1 file changed, 106 insertions(+), 1 deletion(-)

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

-- 
With best wishes
Dmitry

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v6 2/4] ARM: dts: aspeed: Add the AST2600 WDT with SCU register
From: Peter Yin @ 2024-03-28  2:22 UTC (permalink / raw)
  To: patrick, Wim Van Sebroeck, Guenter Roeck, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240328022231.3649741-1-peteryin.openbmc@gmail.com>

The AST2600 Watchdog Timer (WDT) references
the System Control Unit (SCU) register for its operation.

Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index ead835fca657..b47850f0dca0 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -557,23 +557,27 @@ uart5: serial@1e784000 {
 			wdt1: watchdog@1e785000 {
 				compatible = "aspeed,ast2600-wdt";
 				reg = <0x1e785000 0x40>;
+				aspeed,scu = <&syscon>;
 			};
 
 			wdt2: watchdog@1e785040 {
 				compatible = "aspeed,ast2600-wdt";
 				reg = <0x1e785040 0x40>;
+				aspeed,scu = <&syscon>;
 				status = "disabled";
 			};
 
 			wdt3: watchdog@1e785080 {
 				compatible = "aspeed,ast2600-wdt";
 				reg = <0x1e785080 0x40>;
+				aspeed,scu = <&syscon>;
 				status = "disabled";
 			};
 
 			wdt4: watchdog@1e7850c0 {
 				compatible = "aspeed,ast2600-wdt";
 				reg = <0x1e7850C0 0x40>;
+				aspeed,scu = <&syscon>;
 				status = "disabled";
 			};
 
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v6 4/4] drivers: watchdog: ast2500 and ast2600 support bootstatus
From: Peter Yin @ 2024-03-28  2:22 UTC (permalink / raw)
  To: patrick, Wim Van Sebroeck, Guenter Roeck, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240328022231.3649741-1-peteryin.openbmc@gmail.com>

Add WDIOF_EXTERN1 and WDIOF_CARDRESET bootstatus in ast2600

Regarding the AST2600 specification, the WDTn Timeout Status Register
(WDT10) has bit 1 reserved. Bit 1 of the status register indicates
on ast2500 if the boot was from the second boot source.
It does not indicate that the most recent reset was triggered by
the watchdog. The code should just be changed to set WDIOF_CARDRESET
if bit 0 of the status register is set.

Include SCU register to veriy WDIOF_EXTERN1 in ast2600 SCU74 or
ast2500 SCU3C when bit1 is set.

Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
---
 drivers/watchdog/aspeed_wdt.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
index b4773a6aaf8c..0e7ef860cbdc 100644
--- a/drivers/watchdog/aspeed_wdt.c
+++ b/drivers/watchdog/aspeed_wdt.c
@@ -11,10 +11,12 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kstrtox.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/watchdog.h>
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -77,11 +79,19 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
 #define WDT_TIMEOUT_STATUS	0x10
 #define   WDT_TIMEOUT_STATUS_IRQ		BIT(2)
 #define   WDT_TIMEOUT_STATUS_BOOT_SECONDARY	BIT(1)
+#define   WDT_TIMEOUT_STATUS_EVENT		BIT(0)
 #define WDT_CLEAR_TIMEOUT_STATUS	0x14
 #define   WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION	BIT(0)
 #define WDT_RESET_MASK1		0x1c
 #define WDT_RESET_MASK2		0x20
 
+/*
+ * Ast2600 SCU74 bit1 is External reset flag
+ * Ast2500 SCU3C bit1 is External reset flag
+ */
+#define AST2500_SYSTEM_RESET_EVENT	0x3C
+#define AST2600_SYSTEM_RESET_EVENT	0x74
+#define   EXTERN_RESET_FLAG		BIT(1)
 /*
  * WDT_RESET_WIDTH controls the characteristics of the external pulse (if
  * enabled), specifically:
@@ -330,6 +340,11 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
 	if (IS_ERR(wdt->base))
 		return PTR_ERR(wdt->base);
 
+	struct regmap *scu_base = syscon_regmap_lookup_by_phandle(dev->of_node,
+							     "aspeed,scu");
+	if (IS_ERR(scu_base))
+		return PTR_ERR(scu_base);
+
 	wdt->wdd.info = &aspeed_wdt_info;
 
 	if (wdt->cfg->irq_mask) {
@@ -459,14 +474,26 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
 	}
 
 	status = readl(wdt->base + WDT_TIMEOUT_STATUS);
-	if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) {
+	if (status & WDT_TIMEOUT_STATUS_EVENT)
 		wdt->wdd.bootstatus = WDIOF_CARDRESET;
 
-		if (of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
-		    of_device_is_compatible(np, "aspeed,ast2500-wdt"))
-			wdt->wdd.groups = bswitch_groups;
+	if (of_device_is_compatible(np, "aspeed,ast2600-wdt")) {
+		ret = regmap_read(scu_base,
+				  AST2600_SYSTEM_RESET_EVENT,
+				  &status);
+	} else {
+		ret = regmap_read(scu_base,
+				  AST2500_SYSTEM_RESET_EVENT,
+				  &status);
+		wdt->wdd.groups = bswitch_groups;
 	}
 
+	/*
+	 * Reset cause by Extern Reset
+	 */
+	if (status & EXTERN_RESET_FLAG && !ret)
+		wdt->wdd.bootstatus |= WDIOF_EXTERN1;
+
 	dev_set_drvdata(dev, wdt);
 
 	return devm_watchdog_register_device(dev, &wdt->wdd);
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v6 3/4] dt-bindings: watchdog: aspeed-wdt: Add aspeed,scu
From: Peter Yin @ 2024-03-28  2:22 UTC (permalink / raw)
  To: patrick, Wim Van Sebroeck, Guenter Roeck, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240328022231.3649741-1-peteryin.openbmc@gmail.com>

To use the SCU register to obtain reset flags for supporting
bootstatus.

Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
---
 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
index 3208adb3e52e..80a1f58b5a2e 100644
--- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
@@ -8,6 +8,8 @@ Required properties:
 
  - reg: physical base address of the controller and length of memory mapped
    region
+ - aspeed,scu: a reference to the System Control Unit node of the Aspeed
+   SOC.
 
 Optional properties:
 
@@ -62,6 +64,7 @@ Examples:
 		reg = <0x1e785000 0x1c>;
 		aspeed,reset-type = "system";
 		aspeed,external-signal;
+		aspeed,scu = <&syscon>;
 	};
 
 	#include <dt-bindings/watchdog/aspeed-wdt.h>
@@ -70,4 +73,5 @@ Examples:
 		reg = <0x1e785040 0x40>;
 		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
 				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
+		aspeed,scu = <&syscon>;
 	};
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* Re: [PATCH v3] NUMA: Early use of cpu_to_node() returns 0 instead of the correct node id
From: Shijie Huang @ 2024-03-28  2:09 UTC (permalink / raw)
  To: Andrew Morton, Huang Shijie
  Cc: gregkh, patches, rafael, paul.walmsley, palmer, aou, yury.norov,
	kuba, vschneid, mingo, vbabka, rppt, tglx, jpoimboe, ndesaulniers,
	mikelley, mhiramat, arnd, linux-kernel, linux-riscv,
	linux-arm-kernel, catalin.marinas, will, mark.rutland, mpe,
	linuxppc-dev, chenhuacai, jiaxun.yang, linux-mips, cl
In-Reply-To: <20240327111740.f8d3802b0eae15bcb8727e04@linux-foundation.org>


在 2024/3/28 2:17, Andrew Morton 写道:
> On Fri, 26 Jan 2024 14:44:51 +0800 Huang Shijie <shijie@os.amperecomputing.com> wrote:
>
>> During the kernel booting, the generic cpu_to_node() is called too early in
>> arm64, powerpc and riscv when CONFIG_NUMA is enabled.
>>
>> There are at least four places in the common code where
>> the generic cpu_to_node() is called before it is initialized:
>> 	   1.) early_trace_init()         in kernel/trace/trace.c
>> 	   2.) sched_init()               in kernel/sched/core.c
>> 	   3.) init_sched_fair_class()    in kernel/sched/fair.c
>> 	   4.) workqueue_init_early()     in kernel/workqueue.c
>>
>> In order to fix the bug, the patch introduces early_numa_node_init()
>> which is called after smp_prepare_boot_cpu() in start_kernel.
>> early_numa_node_init will initialize the "numa_node" as soon as
>> the early_cpu_to_node() is ready, before the cpu_to_node() is called
>> at the first time.
> What are the userspace-visible runtime effects of this bug?
>
For this bug, I do not see too much performance impact in the userspace 
applications.

It just pollutes the CPU caches in NUMA.


Thanks

Huang Shijie



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] ASoC: sunxi: sun4i-i2s: Enable 32-bit audio formats
From: John Watts @ 2024-03-28  2:21 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Chen-Yu Tsai, Samuel Holland, linux-sound, linux-arm-kernel,
	linux-sunxi, linux-kernel
In-Reply-To: <23447395.6Emhk5qWAg@jernej-laptop>

On Wed, Mar 27, 2024 at 08:53:32PM +0100, Jernej Škrabec wrote:
> I wish it would be that simple. SUN4I_FORMATS is cross section of all I2S
> variants that are supported by this driver. If you check A10, you'll see that
> it doesn't support S32.
> 
> If you want to add support for S32, you'll have to add new quirk for each
> variant.

Yes, A10 doesn't support it. But it should error out in hw_params due to
get_sr not supporting 32-bit, no?

> 
> Best regards,
> Jernej

John.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 13/18] KVM: selftests: Drop superfluous switch() on vm->mode in vcpu_init_sregs()
From: Ackerley Tng @ 2024-03-28  2:28 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-14-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Replace the switch statement on vm->mode in x86's vcpu_init_sregs()'s with
> a simple assert that the VM has a 48-bit virtual address space.  A switch
> statement is both overkill and misleading, as the existing code incorrectly
> implies that VMs with LA57 would need different to configuration for the
> LDT, TSS, and flat segments.  In all likelihood, the only difference that
> would be needed for selftests is CR4.LA57 itself.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../selftests/kvm/lib/x86_64/processor.c      | 25 ++++++++-----------
>  1 file changed, 10 insertions(+), 15 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index 8547833ffa26..561c0aa93608 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -555,6 +555,8 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  {
>  	struct kvm_sregs sregs;
>  
> +	TEST_ASSERT_EQ(vm->mode, VM_MODE_PXXV48_4K);
> +
>  	/* Set mode specific system register values. */
>  	vcpu_sregs_get(vcpu, &sregs);
>  
> @@ -562,22 +564,15 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  
>  	kvm_setup_gdt(vm, &sregs.gdt);
>  
> -	switch (vm->mode) {
> -	case VM_MODE_PXXV48_4K:
> -		sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
> -		sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
> -		sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
> +	sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
> +	sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
> +	sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
>  
> -		kvm_seg_set_unusable(&sregs.ldt);
> -		kvm_seg_set_kernel_code_64bit(vm, DEFAULT_CODE_SELECTOR, &sregs.cs);
> -		kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.ds);
> -		kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.es);
> -		kvm_setup_tss_64bit(vm, &sregs.tr, 0x18);
> -		break;
> -
> -	default:
> -		TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
> -	}
> +	kvm_seg_set_unusable(&sregs.ldt);
> +	kvm_seg_set_kernel_code_64bit(vm, DEFAULT_CODE_SELECTOR, &sregs.cs);
> +	kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.ds);
> +	kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.es);
> +	kvm_setup_tss_64bit(vm, &sregs.tr, 0x18);
>  
>  	sregs.cr3 = vm->pgd;
>  	vcpu_sregs_set(vcpu, &sregs);
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [RESEND PATCH v4 2/3] perf/marvell: perf/marvell: Odyssey DDR Performance
From: kernel test robot @ 2024-03-28  1:31 UTC (permalink / raw)
  To: Gowthami Thiagarajan, will, mark.rutland, linux-arm-kernel,
	linux-kernel
  Cc: oe-kbuild-all, sgoutham, bbhushan2, gcherian,
	Gowthami Thiagarajan
In-Reply-To: <20240327071832.1556576-3-gthiagarajan@marvell.com>

Hi Gowthami,

kernel test robot noticed the following build warnings:

[auto build test WARNING on soc/for-next]
[also build test WARNING on linus/master v6.9-rc1 next-20240327]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Gowthami-Thiagarajan/perf-marvell-Refactor-to-extract-platform-data/20240327-152242
base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
patch link:    https://lore.kernel.org/r/20240327071832.1556576-3-gthiagarajan%40marvell.com
patch subject: [RESEND PATCH v4 2/3] perf/marvell: perf/marvell: Odyssey DDR Performance
config: sparc-allmodconfig (https://download.01.org/0day-ci/archive/20240328/202403280921.NALZ6Tp8-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240328/202403280921.NALZ6Tp8-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202403280921.NALZ6Tp8-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/perf/marvell_cn10k_ddr_pmu.c:982:34: warning: 'ddr_pmu_v2_data' defined but not used [-Wunused-const-variable=]
     982 | static const struct ddr_pmu_data ddr_pmu_v2_data = {
         |                                  ^~~~~~~~~~~~~~~


vim +/ddr_pmu_v2_data +982 drivers/perf/marvell_cn10k_ddr_pmu.c

   981	
 > 982	static const struct ddr_pmu_data ddr_pmu_v2_data = {
   983		.id   = DDR_PMU_V2,
   984	};
   985	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v5 1/4] ARM: dts: aspeed: Add the AST2500 WDT with SCU register
From: Peter Yin @ 2024-03-28  1:32 UTC (permalink / raw)
  To: patrick, Wim Van Sebroeck, Guenter Roeck, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240328013303.3609385-1-peteryin.openbmc@gmail.com>

The AST2500 WDT references the System Control Unit
register for its operation.

Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g5.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi
index 04f98d1dbb97..5fd12c057c31 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi
@@ -410,12 +410,14 @@ wdt1: watchdog@1e785000 {
 				compatible = "aspeed,ast2500-wdt";
 				reg = <0x1e785000 0x20>;
 				clocks = <&syscon ASPEED_CLK_APB>;
+				aspeed,scu = <&syscon>;
 			};
 
 			wdt2: watchdog@1e785020 {
 				compatible = "aspeed,ast2500-wdt";
 				reg = <0x1e785020 0x20>;
 				clocks = <&syscon ASPEED_CLK_APB>;
+				aspeed,scu = <&syscon>;
 			};
 
 			wdt3: watchdog@1e785040 {
@@ -423,6 +425,7 @@ wdt3: watchdog@1e785040 {
 				reg = <0x1e785040 0x20>;
 				clocks = <&syscon ASPEED_CLK_APB>;
 				status = "disabled";
+				aspeed,scu = <&syscon>;
 			};
 
 			pwm_tacho: pwm-tacho-controller@1e786000 {
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* Re: [PATCH 12/18] KVM: selftests: Allocate x86's GDT during VM creation
From: Ackerley Tng @ 2024-03-28  2:33 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-13-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Allocate the GDT during creation of non-barebones VMs instead of waiting
> until the first vCPU is created, as the whole point of non-barebones VMs
> is to be able to run vCPUs, i.e. the GDT is going to get allocated no
> matter what.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  tools/testing/selftests/kvm/lib/x86_64/processor.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index f4046029f168..8547833ffa26 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -518,9 +518,6 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
>  
>  static void kvm_setup_gdt(struct kvm_vm *vm, struct kvm_dtable *dt)
>  {
> -	if (!vm->arch.gdt)
> -		vm->arch.gdt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
> -
>  	dt->base = vm->arch.gdt;
>  	dt->limit = getpagesize() - 1;
>  }
> @@ -644,6 +641,7 @@ static void vm_init_descriptor_tables(struct kvm_vm *vm)
>  	extern void *idt_handlers;
>  	int i;
>  
> +	vm->arch.gdt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
>  	vm->arch.idt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
>  	vm->handlers = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
>  	/* Handlers have the same address in both address spaces.*/
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 11/18] KVM: selftests: Map x86's exception_handlers at VM creation, not vCPU setup
From: Ackerley Tng @ 2024-03-28  2:35 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-12-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Map x86's exception handlers at VM creation, not vCPU setup, as the
> mapping is per-VM, i.e. doesn't need to be (re)done for every vCPU.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  tools/testing/selftests/kvm/lib/x86_64/processor.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index 5813d93b2e7c..f4046029f168 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -552,7 +552,6 @@ static void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
>  	sregs.gdt.limit = getpagesize() - 1;
>  	kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
>  	vcpu_sregs_set(vcpu, &sregs);
> -	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
>  }
>  
>  static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> @@ -651,6 +650,8 @@ static void vm_init_descriptor_tables(struct kvm_vm *vm)
>  	for (i = 0; i < NUM_INTERRUPTS; i++)
>  		set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0,
>  			DEFAULT_CODE_SELECTOR);
> +
> +	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
>  }
>  
>  void vm_install_exception_handler(struct kvm_vm *vm, int vector,
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 10/18] KVM: selftests: Init IDT and exception handlers for all VMs/vCPUs on x86
From: Ackerley Tng @ 2024-03-28  2:46 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-11-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Initialize the IDT and exception handlers for all non-barebones VMs and
> vCPUs on x86.  Forcing tests to manually configure the IDT just to save
> 8KiB of memory is a terrible tradeoff, and also leads to weird tests
> (multiple tests have deliberately relied on shutdown to indicate success),
> and hard-to-debug failures, e.g. instead of a precise unexpected exception
> failure, tests see only shutdown.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  tools/testing/selftests/kvm/include/x86_64/processor.h    | 2 --
>  tools/testing/selftests/kvm/lib/x86_64/processor.c        | 8 ++++++--
>  tools/testing/selftests/kvm/x86_64/amx_test.c             | 2 --
>  tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c   | 2 --
>  tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c         | 2 --
>  tools/testing/selftests/kvm/x86_64/hyperv_features.c      | 6 ------
>  tools/testing/selftests/kvm/x86_64/hyperv_ipi.c           | 3 ---
>  tools/testing/selftests/kvm/x86_64/kvm_pv_test.c          | 3 ---
>  tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c   | 3 ---
>  tools/testing/selftests/kvm/x86_64/platform_info_test.c   | 3 ---
>  tools/testing/selftests/kvm/x86_64/pmu_counters_test.c    | 3 ---
>  .../testing/selftests/kvm/x86_64/pmu_event_filter_test.c  | 6 ------
>  .../kvm/x86_64/smaller_maxphyaddr_emulation_test.c        | 3 ---
>  tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c     | 3 ---
>  .../selftests/kvm/x86_64/svm_nested_shutdown_test.c       | 3 ---
>  .../selftests/kvm/x86_64/svm_nested_soft_inject_test.c    | 3 ---
>  tools/testing/selftests/kvm/x86_64/ucna_injection_test.c  | 4 ----
>  .../selftests/kvm/x86_64/userspace_msr_exit_test.c        | 3 ---
>  .../kvm/x86_64/vmx_exception_with_invalid_guest_state.c   | 3 ---
>  tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c    | 3 ---
>  tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c       | 2 --
>  tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c      | 3 ---
>  tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c      | 2 --
>  23 files changed, 6 insertions(+), 69 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
> index d6ffe03c9d0b..4804abe00158 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/processor.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
> @@ -1129,8 +1129,6 @@ struct idt_entry {
>  	uint32_t offset2; uint32_t reserved;
>  };
>  
> -void vm_init_descriptor_tables(struct kvm_vm *vm);
> -void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu);
>  void vm_install_exception_handler(struct kvm_vm *vm, int vector,
>  			void (*handler)(struct ex_regs *));
>  
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index d6bfe96a6a77..5813d93b2e7c 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -540,7 +540,7 @@ static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
>  	kvm_seg_fill_gdt_64bit(vm, segp);
>  }
>  
> -void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
> +static void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
>  {
>  	struct kvm_vm *vm = vcpu->vm;
>  	struct kvm_sregs sregs;
> @@ -585,6 +585,8 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  
>  	sregs.cr3 = vm->pgd;
>  	vcpu_sregs_set(vcpu, &sregs);
> +
> +	vcpu_init_descriptor_tables(vcpu);
>  }
>  
>  static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
> @@ -638,7 +640,7 @@ void route_exception(struct ex_regs *regs)
>  		     regs->vector, regs->rip);
>  }
>  
> -void vm_init_descriptor_tables(struct kvm_vm *vm)
> +static void vm_init_descriptor_tables(struct kvm_vm *vm)
>  {
>  	extern void *idt_handlers;
>  	int i;
> @@ -670,6 +672,8 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
>  void kvm_arch_vm_post_create(struct kvm_vm *vm)
>  {
>  	vm_create_irqchip(vm);
> +	vm_init_descriptor_tables(vm);
> +
>  	sync_global_to_guest(vm, host_cpu_is_intel);
>  	sync_global_to_guest(vm, host_cpu_is_amd);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/amx_test.c b/tools/testing/selftests/kvm/x86_64/amx_test.c
> index eae521f050e0..ab6c31aee447 100644
> --- a/tools/testing/selftests/kvm/x86_64/amx_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/amx_test.c
> @@ -246,8 +246,6 @@ int main(int argc, char *argv[])
>  	vcpu_regs_get(vcpu, &regs1);
>  
>  	/* Register #NM handler */
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
>  	vm_install_exception_handler(vm, NM_VECTOR, guest_nm_handler);
>  
>  	/* amx cfg for guest_code */
> diff --git a/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c b/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
> index f3c2239228b1..762628f7d4ba 100644
> --- a/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
> @@ -110,8 +110,6 @@ static void test_fix_hypercall(struct kvm_vcpu *vcpu, bool disable_quirk)
>  {
>  	struct kvm_vm *vm = vcpu->vm;
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
>  	vm_install_exception_handler(vcpu->vm, UD_VECTOR, guest_ud_handler);
>  
>  	if (disable_quirk)
> diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c b/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c
> index 4c7257ecd2a6..4238691a755c 100644
> --- a/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c
> +++ b/tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c
> @@ -258,8 +258,6 @@ int main(int argc, char *argv[])
>  	vcpu_args_set(vcpu, 3, vmx_pages_gva, hv_pages_gva, addr_gva2gpa(vm, hcall_page));
>  	vcpu_set_msr(vcpu, HV_X64_MSR_VP_INDEX, vcpu->id);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
>  	vm_install_exception_handler(vm, UD_VECTOR, guest_ud_handler);
>  	vm_install_exception_handler(vm, NMI_VECTOR, guest_nmi_handler);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_features.c b/tools/testing/selftests/kvm/x86_64/hyperv_features.c
> index b923a285e96f..068e9c69710d 100644
> --- a/tools/testing/selftests/kvm/x86_64/hyperv_features.c
> +++ b/tools/testing/selftests/kvm/x86_64/hyperv_features.c
> @@ -156,9 +156,6 @@ static void guest_test_msrs_access(void)
>  			vcpu_init_cpuid(vcpu, prev_cpuid);
>  		}
>  
> -		vm_init_descriptor_tables(vm);
> -		vcpu_init_descriptor_tables(vcpu);
> -
>  		/* TODO: Make this entire test easier to maintain. */
>  		if (stage >= 21)
>  			vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_SYNIC2, 0);
> @@ -532,9 +529,6 @@ static void guest_test_hcalls_access(void)
>  	while (true) {
>  		vm = vm_create_with_one_vcpu(&vcpu, guest_hcall);
>  
> -		vm_init_descriptor_tables(vm);
> -		vcpu_init_descriptor_tables(vcpu);
> -
>  		/* Hypercall input/output */
>  		hcall_page = vm_vaddr_alloc_pages(vm, 2);
>  		memset(addr_gva2hva(vm, hcall_page), 0x0, 2 * getpagesize());
> diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c b/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c
> index f1617762c22f..c6a03141cdaa 100644
> --- a/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c
> +++ b/tools/testing/selftests/kvm/x86_64/hyperv_ipi.c
> @@ -256,16 +256,13 @@ int main(int argc, char *argv[])
>  	hcall_page = vm_vaddr_alloc_pages(vm, 2);
>  	memset(addr_gva2hva(vm, hcall_page), 0x0, 2 * getpagesize());
>  
> -	vm_init_descriptor_tables(vm);
>  
>  	vcpu[1] = vm_vcpu_add(vm, RECEIVER_VCPU_ID_1, receiver_code);
> -	vcpu_init_descriptor_tables(vcpu[1]);
>  	vcpu_args_set(vcpu[1], 2, hcall_page, addr_gva2gpa(vm, hcall_page));
>  	vcpu_set_msr(vcpu[1], HV_X64_MSR_VP_INDEX, RECEIVER_VCPU_ID_1);
>  	vcpu_set_hv_cpuid(vcpu[1]);
>  
>  	vcpu[2] = vm_vcpu_add(vm, RECEIVER_VCPU_ID_2, receiver_code);
> -	vcpu_init_descriptor_tables(vcpu[2]);
>  	vcpu_args_set(vcpu[2], 2, hcall_page, addr_gva2gpa(vm, hcall_page));
>  	vcpu_set_msr(vcpu[2], HV_X64_MSR_VP_INDEX, RECEIVER_VCPU_ID_2);
>  	vcpu_set_hv_cpuid(vcpu[2]);
> diff --git a/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c b/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c
> index 9e2879af7c20..cef0bd80038b 100644
> --- a/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/kvm_pv_test.c
> @@ -146,9 +146,6 @@ int main(void)
>  
>  	vcpu_clear_cpuid_entry(vcpu, KVM_CPUID_FEATURES);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	enter_guest(vcpu);
>  	kvm_vm_free(vm);
>  }
> diff --git a/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c b/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c
> index 853802641e1e..9c8445379d76 100644
> --- a/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c
> @@ -80,9 +80,6 @@ int main(int argc, char *argv[])
>  	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
>  	vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_MWAIT);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	while (1) {
>  		vcpu_run(vcpu);
>  		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
> diff --git a/tools/testing/selftests/kvm/x86_64/platform_info_test.c b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
> index 6300bb70f028..9cf2b9fbf459 100644
> --- a/tools/testing/selftests/kvm/x86_64/platform_info_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
> @@ -51,9 +51,6 @@ int main(int argc, char *argv[])
>  
>  	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	msr_platform_info = vcpu_get_msr(vcpu, MSR_PLATFORM_INFO);
>  	vcpu_set_msr(vcpu, MSR_PLATFORM_INFO,
>  		     msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
> diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
> index 29609b52f8fa..ff6d21d148de 100644
> --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
> @@ -31,9 +31,6 @@ static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
>  	struct kvm_vm *vm;
>  
>  	vm = vm_create_with_one_vcpu(vcpu, guest_code);
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(*vcpu);
> -
>  	sync_global_to_guest(vm, kvm_pmu_version);
>  	sync_global_to_guest(vm, is_forced_emulation_enabled);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
> index 3c85d1ae9893..5cbe9d331acb 100644
> --- a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
> @@ -337,9 +337,6 @@ static void test_pmu_config_disable(void (*guest_code)(void))
>  	vm_enable_cap(vm, KVM_CAP_PMU_CAPABILITY, KVM_PMU_CAP_DISABLE);
>  
>  	vcpu = vm_vcpu_add(vm, 0, guest_code);
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	TEST_ASSERT(!sanity_check_pmu(vcpu),
>  		    "Guest should not be able to use disabled PMU.");
>  
> @@ -876,9 +873,6 @@ int main(int argc, char *argv[])
>  
>  	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	TEST_REQUIRE(sanity_check_pmu(vcpu));
>  
>  	if (use_amd_pmu())
> diff --git a/tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c b/tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c
> index 416207c38a17..0d682d6b76f1 100644
> --- a/tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c
> @@ -60,9 +60,6 @@ int main(int argc, char *argv[])
>  	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
>  	vcpu_args_set(vcpu, 1, kvm_is_tdp_enabled());
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_MAX_PHY_ADDR, MAXPHYADDR);
>  
>  	rc = kvm_check_cap(KVM_CAP_EXIT_ON_EMULATION_FAILURE);
> diff --git a/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c b/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c
> index 32bef39bec21..916e04248fbb 100644
> --- a/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c
> @@ -93,9 +93,6 @@ int main(int argc, char *argv[])
>  
>  	vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vm_install_exception_handler(vm, VINTR_IRQ_NUMBER, vintr_irq_handler);
>  	vm_install_exception_handler(vm, INTR_IRQ_NUMBER, intr_irq_handler);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c
> index f4a1137e04ab..00135cbba35e 100644
> --- a/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c
> @@ -48,9 +48,6 @@ int main(int argc, char *argv[])
>  	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM));
>  
>  	vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vcpu_alloc_svm(vm, &svm_gva);
>  
>  	vcpu_args_set(vcpu, 2, svm_gva, vm->arch.idt);
> diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c
> index 2478a9e50743..7b6481d6c0d3 100644
> --- a/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c
> @@ -152,9 +152,6 @@ static void run_test(bool is_nmi)
>  
>  	vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vm_install_exception_handler(vm, NMI_VECTOR, guest_nmi_handler);
>  	vm_install_exception_handler(vm, BP_VECTOR, guest_bp_handler);
>  	vm_install_exception_handler(vm, INT_NR, guest_int_handler);
> diff --git a/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c b/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
> index bc9be20f9600..6eeb5dd1e65c 100644
> --- a/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
> @@ -284,10 +284,6 @@ int main(int argc, char *argv[])
>  	cmcidis_vcpu = create_vcpu_with_mce_cap(vm, 1, false, cmci_disabled_guest_code);
>  	cmci_vcpu = create_vcpu_with_mce_cap(vm, 2, true, cmci_enabled_guest_code);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(ucna_vcpu);
> -	vcpu_init_descriptor_tables(cmcidis_vcpu);
> -	vcpu_init_descriptor_tables(cmci_vcpu);
>  	vm_install_exception_handler(vm, CMCI_VECTOR, guest_cmci_handler);
>  	vm_install_exception_handler(vm, GP_VECTOR, guest_gp_handler);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c b/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c
> index f4f61a2d2464..fffda40e286f 100644
> --- a/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c
> @@ -531,9 +531,6 @@ KVM_ONE_VCPU_TEST(user_msr, msr_filter_allow, guest_code_filter_allow)
>  
>  	vm_ioctl(vm, KVM_X86_SET_MSR_FILTER, &filter_allow);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vm_install_exception_handler(vm, GP_VECTOR, guest_gp_handler);
>  
>  	/* Process guest code userspace exits. */
> diff --git a/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c b/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c
> index fad3634fd9eb..3fd6eceab46f 100644
> --- a/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c
> +++ b/tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c
> @@ -115,9 +115,6 @@ int main(int argc, char *argv[])
>  	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
>  	get_set_sigalrm_vcpu(vcpu);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vm_install_exception_handler(vm, UD_VECTOR, guest_ud_handler);
>  
>  	/*
> diff --git a/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c b/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c
> index ea0cb3cae0f7..1b6e20e3a56d 100644
> --- a/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c
> @@ -86,9 +86,6 @@ KVM_ONE_VCPU_TEST(vmx_pmu_caps, guest_wrmsr_perf_capabilities, guest_code)
>  	struct ucall uc;
>  	int r, i;
>  
> -	vm_init_descriptor_tables(vcpu->vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
>  
>  	vcpu_args_set(vcpu, 1, host_cap.capabilities);
> diff --git a/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c
> index 725c206ba0b9..f51084061134 100644
> --- a/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c
> @@ -410,8 +410,6 @@ int main(int argc, char *argv[])
>  
>  	vm = vm_create_with_one_vcpu(&params[0].vcpu, halter_guest_code);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(params[0].vcpu);
>  	vm_install_exception_handler(vm, IPI_VECTOR, guest_ipi_handler);
>  
>  	virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
> diff --git a/tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c b/tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c
> index 25a0b0db5c3c..95ce192d0753 100644
> --- a/tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c
> @@ -109,9 +109,6 @@ int main(int argc, char *argv[])
>  	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
>  	run = vcpu->run;
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
> -
>  	while (1) {
>  		vcpu_run(vcpu);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
> index d2ea0435f4f7..a7236f17dfd0 100644
> --- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
> @@ -553,8 +553,6 @@ int main(int argc, char *argv[])
>  	};
>  	vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &vec);
>  
> -	vm_init_descriptor_tables(vm);
> -	vcpu_init_descriptor_tables(vcpu);
>  	vm_install_exception_handler(vm, EVTCHN_VECTOR, evtchn_handler);
>  
>  	if (do_runstate_tests) {
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 09/18] KVM: selftests: Rename x86's vcpu_setup() to vcpu_init_sregs()
From: Ackerley Tng @ 2024-03-28  2:47 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-10-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Rename vcpu_setup() to be more descriptive and precise, there is a whole
> lot of "setup" that is done for a vCPU that isn't in said helper.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  tools/testing/selftests/kvm/lib/x86_64/processor.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index 3640d3290f0a..d6bfe96a6a77 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -555,7 +555,7 @@ void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
>  	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
>  }
>  
> -static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> +static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  {
>  	struct kvm_sregs sregs;
>  
> @@ -716,7 +716,7 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
>  
>  	vcpu = __vm_vcpu_add(vm, vcpu_id);
>  	vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid());
> -	vcpu_setup(vm, vcpu);
> +	vcpu_init_sregs(vm, vcpu);
>  
>  	/* Setup guest general purpose registers */
>  	vcpu_regs_get(vcpu, &regs);
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 08/18] KVM: selftests: Move x86's descriptor table helpers "up" in processor.c
From: Ackerley Tng @ 2024-03-28  2:47 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-9-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Move x86's various descriptor table helpers in processor.c up above
> kvm_arch_vm_post_create() and vcpu_setup() so that the helpers can be
> made static and invoked from the aforementioned functions.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../selftests/kvm/lib/x86_64/processor.c      | 191 +++++++++---------
>  1 file changed, 95 insertions(+), 96 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index eaeba907bb53..3640d3290f0a 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -540,6 +540,21 @@ static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
>  	kvm_seg_fill_gdt_64bit(vm, segp);
>  }
>  
> +void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
> +{
> +	struct kvm_vm *vm = vcpu->vm;
> +	struct kvm_sregs sregs;
> +
> +	vcpu_sregs_get(vcpu, &sregs);
> +	sregs.idt.base = vm->arch.idt;
> +	sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1;
> +	sregs.gdt.base = vm->arch.gdt;
> +	sregs.gdt.limit = getpagesize() - 1;
> +	kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
> +	vcpu_sregs_set(vcpu, &sregs);
> +	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
> +}
> +
>  static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  {
>  	struct kvm_sregs sregs;
> @@ -572,6 +587,86 @@ static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  	vcpu_sregs_set(vcpu, &sregs);
>  }
>  
> +static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
> +			  int dpl, unsigned short selector)
> +{
> +	struct idt_entry *base =
> +		(struct idt_entry *)addr_gva2hva(vm, vm->arch.idt);
> +	struct idt_entry *e = &base[vector];
> +
> +	memset(e, 0, sizeof(*e));
> +	e->offset0 = addr;
> +	e->selector = selector;
> +	e->ist = 0;
> +	e->type = 14;
> +	e->dpl = dpl;
> +	e->p = 1;
> +	e->offset1 = addr >> 16;
> +	e->offset2 = addr >> 32;
> +}
> +
> +static bool kvm_fixup_exception(struct ex_regs *regs)
> +{
> +	if (regs->r9 != KVM_EXCEPTION_MAGIC || regs->rip != regs->r10)
> +		return false;
> +
> +	if (regs->vector == DE_VECTOR)
> +		return false;
> +
> +	regs->rip = regs->r11;
> +	regs->r9 = regs->vector;
> +	regs->r10 = regs->error_code;
> +	return true;
> +}
> +
> +void route_exception(struct ex_regs *regs)
> +{
> +	typedef void(*handler)(struct ex_regs *);
> +	handler *handlers = (handler *)exception_handlers;
> +
> +	if (handlers && handlers[regs->vector]) {
> +		handlers[regs->vector](regs);
> +		return;
> +	}
> +
> +	if (kvm_fixup_exception(regs))
> +		return;
> +
> +	ucall_assert(UCALL_UNHANDLED,
> +		     "Unhandled exception in guest", __FILE__, __LINE__,
> +		     "Unhandled exception '0x%lx' at guest RIP '0x%lx'",
> +		     regs->vector, regs->rip);
> +}
> +
> +void vm_init_descriptor_tables(struct kvm_vm *vm)
> +{
> +	extern void *idt_handlers;
> +	int i;
> +
> +	vm->arch.idt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
> +	vm->handlers = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
> +	/* Handlers have the same address in both address spaces.*/
> +	for (i = 0; i < NUM_INTERRUPTS; i++)
> +		set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0,
> +			DEFAULT_CODE_SELECTOR);
> +}
> +
> +void vm_install_exception_handler(struct kvm_vm *vm, int vector,
> +			       void (*handler)(struct ex_regs *))
> +{
> +	vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers);
> +
> +	handlers[vector] = (vm_vaddr_t)handler;
> +}
> +
> +void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
> +{
> +	struct ucall uc;
> +
> +	if (get_ucall(vcpu, &uc) == UCALL_UNHANDLED)
> +		REPORT_GUEST_ASSERT(uc);
> +}
> +
>  void kvm_arch_vm_post_create(struct kvm_vm *vm)
>  {
>  	vm_create_irqchip(vm);
> @@ -1087,102 +1182,6 @@ void kvm_init_vm_address_properties(struct kvm_vm *vm)
>  	}
>  }
>  
> -static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
> -			  int dpl, unsigned short selector)
> -{
> -	struct idt_entry *base =
> -		(struct idt_entry *)addr_gva2hva(vm, vm->arch.idt);
> -	struct idt_entry *e = &base[vector];
> -
> -	memset(e, 0, sizeof(*e));
> -	e->offset0 = addr;
> -	e->selector = selector;
> -	e->ist = 0;
> -	e->type = 14;
> -	e->dpl = dpl;
> -	e->p = 1;
> -	e->offset1 = addr >> 16;
> -	e->offset2 = addr >> 32;
> -}
> -
> -
> -static bool kvm_fixup_exception(struct ex_regs *regs)
> -{
> -	if (regs->r9 != KVM_EXCEPTION_MAGIC || regs->rip != regs->r10)
> -		return false;
> -
> -	if (regs->vector == DE_VECTOR)
> -		return false;
> -
> -	regs->rip = regs->r11;
> -	regs->r9 = regs->vector;
> -	regs->r10 = regs->error_code;
> -	return true;
> -}
> -
> -void route_exception(struct ex_regs *regs)
> -{
> -	typedef void(*handler)(struct ex_regs *);
> -	handler *handlers = (handler *)exception_handlers;
> -
> -	if (handlers && handlers[regs->vector]) {
> -		handlers[regs->vector](regs);
> -		return;
> -	}
> -
> -	if (kvm_fixup_exception(regs))
> -		return;
> -
> -	ucall_assert(UCALL_UNHANDLED,
> -		     "Unhandled exception in guest", __FILE__, __LINE__,
> -		     "Unhandled exception '0x%lx' at guest RIP '0x%lx'",
> -		     regs->vector, regs->rip);
> -}
> -
> -void vm_init_descriptor_tables(struct kvm_vm *vm)
> -{
> -	extern void *idt_handlers;
> -	int i;
> -
> -	vm->arch.idt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
> -	vm->handlers = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
> -	/* Handlers have the same address in both address spaces.*/
> -	for (i = 0; i < NUM_INTERRUPTS; i++)
> -		set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0,
> -			DEFAULT_CODE_SELECTOR);
> -}
> -
> -void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
> -{
> -	struct kvm_vm *vm = vcpu->vm;
> -	struct kvm_sregs sregs;
> -
> -	vcpu_sregs_get(vcpu, &sregs);
> -	sregs.idt.base = vm->arch.idt;
> -	sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1;
> -	sregs.gdt.base = vm->arch.gdt;
> -	sregs.gdt.limit = getpagesize() - 1;
> -	kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
> -	vcpu_sregs_set(vcpu, &sregs);
> -	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
> -}
> -
> -void vm_install_exception_handler(struct kvm_vm *vm, int vector,
> -			       void (*handler)(struct ex_regs *))
> -{
> -	vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers);
> -
> -	handlers[vector] = (vm_vaddr_t)handler;
> -}
> -
> -void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
> -{
> -	struct ucall uc;
> -
> -	if (get_ucall(vcpu, &uc) == UCALL_UNHANDLED)
> -		REPORT_GUEST_ASSERT(uc);
> -}
> -
>  const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
>  					       uint32_t function, uint32_t index)
>  {
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 02/18] KVM: sefltests: Add kvm_util_types.h to hold common types, e.g. vm_vaddr_t
From: Ackerley Tng @ 2024-03-28  2:48 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-3-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Move the base types unique to KVM selftests out of kvm_util.h and into a
> new header, kvm_util_types.h.  This will allow kvm_util_arch.h, i.e. core
> arch headers, to reference common types, e.g. vm_vaddr_t and vm_paddr_t.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../testing/selftests/kvm/include/kvm_util.h  | 16 +--------------
>  .../selftests/kvm/include/kvm_util_types.h    | 20 +++++++++++++++++++
>  2 files changed, 21 insertions(+), 15 deletions(-)
>  create mode 100644 tools/testing/selftests/kvm/include/kvm_util_types.h
>
> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
> index 95baee5142a7..acdcddf78e3f 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util.h
> @@ -21,28 +21,14 @@
>  #include <sys/ioctl.h>
>  
>  #include "kvm_util_arch.h"
> +#include "kvm_util_types.h"
>  #include "sparsebit.h"
>  
> -/*
> - * Provide a version of static_assert() that is guaranteed to have an optional
> - * message param.  If _ISOC11_SOURCE is defined, glibc (/usr/include/assert.h)
> - * #undefs and #defines static_assert() as a direct alias to _Static_assert(),
> - * i.e. effectively makes the message mandatory.  Many KVM selftests #define
> - * _GNU_SOURCE for various reasons, and _GNU_SOURCE implies _ISOC11_SOURCE.  As
> - * a result, static_assert() behavior is non-deterministic and may or may not
> - * require a message depending on #include order.
> - */
> -#define __kvm_static_assert(expr, msg, ...) _Static_assert(expr, msg)
> -#define kvm_static_assert(expr, ...) __kvm_static_assert(expr, ##__VA_ARGS__, #expr)
> -
>  #define KVM_DEV_PATH "/dev/kvm"
>  #define KVM_MAX_VCPUS 512
>  
>  #define NSEC_PER_SEC 1000000000L
>  
> -typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
> -typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
> -
>  struct userspace_mem_region {
>  	struct kvm_userspace_memory_region2 region;
>  	struct sparsebit *unused_phy_pages;
> diff --git a/tools/testing/selftests/kvm/include/kvm_util_types.h b/tools/testing/selftests/kvm/include/kvm_util_types.h
> new file mode 100644
> index 000000000000..764491366eb9
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/include/kvm_util_types.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef SELFTEST_KVM_UTIL_TYPES_H
> +#define SELFTEST_KVM_UTIL_TYPES_H
> +
> +/*
> + * Provide a version of static_assert() that is guaranteed to have an optional
> + * message param.  If _ISOC11_SOURCE is defined, glibc (/usr/include/assert.h)
> + * #undefs and #defines static_assert() as a direct alias to _Static_assert(),
> + * i.e. effectively makes the message mandatory.  Many KVM selftests #define
> + * _GNU_SOURCE for various reasons, and _GNU_SOURCE implies _ISOC11_SOURCE.  As
> + * a result, static_assert() behavior is non-deterministic and may or may not
> + * require a message depending on #include order.
> + */
> +#define __kvm_static_assert(expr, msg, ...) _Static_assert(expr, msg)
> +#define kvm_static_assert(expr, ...) __kvm_static_assert(expr, ##__VA_ARGS__, #expr)
> +
> +typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
> +typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
> +
> +#endif /* SELFTEST_KVM_UTIL_TYPES_H */
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 01/18] Revert "kvm: selftests: move base kvm_util.h declarations to kvm_util_base.h"
From: Ackerley Tng @ 2024-03-28  2:49 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-2-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Effectively revert the movement of code from kvm_util.h => kvm_util_base.h,
> as the TL;DR of the justification for the move was to avoid #idefs and/or
> circular dependencies between what ended up being ucall_common.h and what
> was (and now again, is), kvm_util.h.
>
> But avoiding #ifdef and circular includes is trivial: don't do that.  The
> cost of removing kvm_util_base.h is a few extra includes of ucall_common.h,
> but that cost is practically nothing.  On the other hand, having a "base"
> version of a header that is really just the header itself is confusing,
> and makes it weird/hard to choose names for headers that actually are
> "base" headers, e.g. to hold core KVM selftests typedefs.
>
> For all intents and purposes, this reverts commit
> 7d9a662ed9f0403e7b94940dceb81552b8edb931.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../selftests/kvm/aarch64/arch_timer.c        |    1 +
>  tools/testing/selftests/kvm/arch_timer.c      |    1 +
>  .../selftests/kvm/demand_paging_test.c        |    1 +
>  .../selftests/kvm/dirty_log_perf_test.c       |    1 +
>  tools/testing/selftests/kvm/dirty_log_test.c  |    1 +
>  .../testing/selftests/kvm/guest_memfd_test.c  |    2 +-
>  .../testing/selftests/kvm/guest_print_test.c  |    1 +
>  .../selftests/kvm/include/aarch64/processor.h |    2 +
>  .../selftests/kvm/include/aarch64/ucall.h     |    2 +-
>  .../testing/selftests/kvm/include/kvm_util.h  | 1128 +++++++++++++++-
>  .../selftests/kvm/include/kvm_util_base.h     | 1135 -----------------
>  .../selftests/kvm/include/s390x/ucall.h       |    2 +-
>  .../selftests/kvm/include/x86_64/processor.h  |    3 +-
>  .../selftests/kvm/include/x86_64/ucall.h      |    2 +-
>  .../selftests/kvm/kvm_page_table_test.c       |    1 +
>  .../selftests/kvm/lib/aarch64/processor.c     |    2 +
>  tools/testing/selftests/kvm/lib/kvm_util.c    |    1 +
>  tools/testing/selftests/kvm/lib/memstress.c   |    1 +
>  .../selftests/kvm/lib/riscv/processor.c       |    1 +
>  .../testing/selftests/kvm/lib/ucall_common.c  |    5 +-
>  .../testing/selftests/kvm/riscv/arch_timer.c  |    1 +
>  tools/testing/selftests/kvm/rseq_test.c       |    1 +
>  tools/testing/selftests/kvm/s390x/cmma_test.c |    1 +
>  tools/testing/selftests/kvm/s390x/memop.c     |    1 +
>  tools/testing/selftests/kvm/s390x/tprot.c     |    1 +
>  tools/testing/selftests/kvm/steal_time.c      |    1 +
>  .../x86_64/dirty_log_page_splitting_test.c    |    1 +
>  .../x86_64/exit_on_emulation_failure_test.c   |    2 +-
>  .../kvm/x86_64/ucna_injection_test.c          |    1 -
>  29 files changed, 1156 insertions(+), 1147 deletions(-)
>  delete mode 100644 tools/testing/selftests/kvm/include/kvm_util_base.h
>
> diff --git a/tools/testing/selftests/kvm/aarch64/arch_timer.c b/tools/testing/selftests/kvm/aarch64/arch_timer.c
> index ddba2c2fb5de..ee83b2413da8 100644
> --- a/tools/testing/selftests/kvm/aarch64/arch_timer.c
> +++ b/tools/testing/selftests/kvm/aarch64/arch_timer.c
> @@ -12,6 +12,7 @@
>  #include "gic.h"
>  #include "processor.h"
>  #include "timer_test.h"
> +#include "ucall_common.h"
>  #include "vgic.h"
>  
>  #define GICD_BASE_GPA			0x8000000ULL
> diff --git a/tools/testing/selftests/kvm/arch_timer.c b/tools/testing/selftests/kvm/arch_timer.c
> index ae1f1a6d8312..40cb6c1bec0a 100644
> --- a/tools/testing/selftests/kvm/arch_timer.c
> +++ b/tools/testing/selftests/kvm/arch_timer.c
> @@ -29,6 +29,7 @@
>  #include <sys/sysinfo.h>
>  
>  #include "timer_test.h"
> +#include "ucall_common.h"
>  
>  struct test_args test_args = {
>  	.nr_vcpus = NR_VCPUS_DEF,
> diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c
> index bf3609f71854..a36227731564 100644
> --- a/tools/testing/selftests/kvm/demand_paging_test.c
> +++ b/tools/testing/selftests/kvm/demand_paging_test.c
> @@ -22,6 +22,7 @@
>  #include "test_util.h"
>  #include "memstress.h"
>  #include "guest_modes.h"
> +#include "ucall_common.h"
>  #include "userfaultfd_util.h"
>  
>  #ifdef __NR_userfaultfd
> diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/testing/selftests/kvm/dirty_log_perf_test.c
> index 504f6fe980e8..f0d3ccdb023c 100644
> --- a/tools/testing/selftests/kvm/dirty_log_perf_test.c
> +++ b/tools/testing/selftests/kvm/dirty_log_perf_test.c
> @@ -18,6 +18,7 @@
>  #include "test_util.h"
>  #include "memstress.h"
>  #include "guest_modes.h"
> +#include "ucall_common.h"
>  
>  #ifdef __aarch64__
>  #include "aarch64/vgic.h"
> diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
> index eaad5b20854c..d95120f9dc40 100644
> --- a/tools/testing/selftests/kvm/dirty_log_test.c
> +++ b/tools/testing/selftests/kvm/dirty_log_test.c
> @@ -23,6 +23,7 @@
>  #include "test_util.h"
>  #include "guest_modes.h"
>  #include "processor.h"
> +#include "ucall_common.h"
>  
>  #define DIRTY_MEM_BITS 30 /* 1G */
>  #define PAGE_SHIFT_4K  12
> diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
> index 92eae206baa6..38320de686f6 100644
> --- a/tools/testing/selftests/kvm/guest_memfd_test.c
> +++ b/tools/testing/selftests/kvm/guest_memfd_test.c
> @@ -19,8 +19,8 @@
>  #include <sys/types.h>
>  #include <sys/stat.h>
>  
> +#include "kvm_util.h"
>  #include "test_util.h"
> -#include "kvm_util_base.h"
>  
>  static void test_file_read_write(int fd)
>  {
> diff --git a/tools/testing/selftests/kvm/guest_print_test.c b/tools/testing/selftests/kvm/guest_print_test.c
> index 3502caa3590c..8092c2d0f5d6 100644
> --- a/tools/testing/selftests/kvm/guest_print_test.c
> +++ b/tools/testing/selftests/kvm/guest_print_test.c
> @@ -13,6 +13,7 @@
>  #include "test_util.h"
>  #include "kvm_util.h"
>  #include "processor.h"
> +#include "ucall_common.h"
>  
>  struct guest_vals {
>  	uint64_t a;
> diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h
> index 9e518b562827..1814af7d8567 100644
> --- a/tools/testing/selftests/kvm/include/aarch64/processor.h
> +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h
> @@ -8,6 +8,8 @@
>  #define SELFTEST_KVM_PROCESSOR_H
>  
>  #include "kvm_util.h"
> +#include "ucall_common.h"
> +
>  #include <linux/stringify.h>
>  #include <linux/types.h>
>  #include <asm/sysreg.h>
> diff --git a/tools/testing/selftests/kvm/include/aarch64/ucall.h b/tools/testing/selftests/kvm/include/aarch64/ucall.h
> index 4b68f37efd36..4ec801f37f00 100644
> --- a/tools/testing/selftests/kvm/include/aarch64/ucall.h
> +++ b/tools/testing/selftests/kvm/include/aarch64/ucall.h
> @@ -2,7 +2,7 @@
>  #ifndef SELFTEST_KVM_UCALL_H
>  #define SELFTEST_KVM_UCALL_H
>  
> -#include "kvm_util_base.h"
> +#include "kvm_util.h"
>  
>  #define UCALL_EXIT_REASON       KVM_EXIT_MMIO
>  
> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
> index c9286811a4cb..95baee5142a7 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util.h
> @@ -1,13 +1,1133 @@
>  /* SPDX-License-Identifier: GPL-2.0-only */
>  /*
> - * tools/testing/selftests/kvm/include/kvm_util.h
> - *
>   * Copyright (C) 2018, Google LLC.
>   */
>  #ifndef SELFTEST_KVM_UTIL_H
>  #define SELFTEST_KVM_UTIL_H
>  
> -#include "kvm_util_base.h"
> -#include "ucall_common.h"
> +#include "test_util.h"
> +
> +#include <linux/compiler.h>
> +#include "linux/hashtable.h"
> +#include "linux/list.h"
> +#include <linux/kernel.h>
> +#include <linux/kvm.h>
> +#include "linux/rbtree.h"
> +#include <linux/types.h>
> +
> +#include <asm/atomic.h>
> +#include <asm/kvm.h>
> +
> +#include <sys/ioctl.h>
> +
> +#include "kvm_util_arch.h"
> +#include "sparsebit.h"
> +
> +/*
> + * Provide a version of static_assert() that is guaranteed to have an optional
> + * message param.  If _ISOC11_SOURCE is defined, glibc (/usr/include/assert.h)
> + * #undefs and #defines static_assert() as a direct alias to _Static_assert(),
> + * i.e. effectively makes the message mandatory.  Many KVM selftests #define
> + * _GNU_SOURCE for various reasons, and _GNU_SOURCE implies _ISOC11_SOURCE.  As
> + * a result, static_assert() behavior is non-deterministic and may or may not
> + * require a message depending on #include order.
> + */
> +#define __kvm_static_assert(expr, msg, ...) _Static_assert(expr, msg)
> +#define kvm_static_assert(expr, ...) __kvm_static_assert(expr, ##__VA_ARGS__, #expr)
> +
> +#define KVM_DEV_PATH "/dev/kvm"
> +#define KVM_MAX_VCPUS 512
> +
> +#define NSEC_PER_SEC 1000000000L
> +
> +typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
> +typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
> +
> +struct userspace_mem_region {
> +	struct kvm_userspace_memory_region2 region;
> +	struct sparsebit *unused_phy_pages;
> +	struct sparsebit *protected_phy_pages;
> +	int fd;
> +	off_t offset;
> +	enum vm_mem_backing_src_type backing_src_type;
> +	void *host_mem;
> +	void *host_alias;
> +	void *mmap_start;
> +	void *mmap_alias;
> +	size_t mmap_size;
> +	struct rb_node gpa_node;
> +	struct rb_node hva_node;
> +	struct hlist_node slot_node;
> +};
> +
> +struct kvm_vcpu {
> +	struct list_head list;
> +	uint32_t id;
> +	int fd;
> +	struct kvm_vm *vm;
> +	struct kvm_run *run;
> +#ifdef __x86_64__
> +	struct kvm_cpuid2 *cpuid;
> +#endif
> +	struct kvm_dirty_gfn *dirty_gfns;
> +	uint32_t fetch_index;
> +	uint32_t dirty_gfns_count;
> +};
> +
> +struct userspace_mem_regions {
> +	struct rb_root gpa_tree;
> +	struct rb_root hva_tree;
> +	DECLARE_HASHTABLE(slot_hash, 9);
> +};
> +
> +enum kvm_mem_region_type {
> +	MEM_REGION_CODE,
> +	MEM_REGION_DATA,
> +	MEM_REGION_PT,
> +	MEM_REGION_TEST_DATA,
> +	NR_MEM_REGIONS,
> +};
> +
> +struct kvm_vm {
> +	int mode;
> +	unsigned long type;
> +	uint8_t subtype;
> +	int kvm_fd;
> +	int fd;
> +	unsigned int pgtable_levels;
> +	unsigned int page_size;
> +	unsigned int page_shift;
> +	unsigned int pa_bits;
> +	unsigned int va_bits;
> +	uint64_t max_gfn;
> +	struct list_head vcpus;
> +	struct userspace_mem_regions regions;
> +	struct sparsebit *vpages_valid;
> +	struct sparsebit *vpages_mapped;
> +	bool has_irqchip;
> +	bool pgd_created;
> +	vm_paddr_t ucall_mmio_addr;
> +	vm_paddr_t pgd;
> +	vm_vaddr_t gdt;
> +	vm_vaddr_t tss;
> +	vm_vaddr_t idt;
> +	vm_vaddr_t handlers;
> +	uint32_t dirty_ring_size;
> +	uint64_t gpa_tag_mask;
> +
> +	struct kvm_vm_arch arch;
> +
> +	/* Cache of information for binary stats interface */
> +	int stats_fd;
> +	struct kvm_stats_header stats_header;
> +	struct kvm_stats_desc *stats_desc;
> +
> +	/*
> +	 * KVM region slots. These are the default memslots used by page
> +	 * allocators, e.g., lib/elf uses the memslots[MEM_REGION_CODE]
> +	 * memslot.
> +	 */
> +	uint32_t memslots[NR_MEM_REGIONS];
> +};
> +
> +struct vcpu_reg_sublist {
> +	const char *name;
> +	long capability;
> +	int feature;
> +	int feature_type;
> +	bool finalize;
> +	__u64 *regs;
> +	__u64 regs_n;
> +	__u64 *rejects_set;
> +	__u64 rejects_set_n;
> +	__u64 *skips_set;
> +	__u64 skips_set_n;
> +};
> +
> +struct vcpu_reg_list {
> +	char *name;
> +	struct vcpu_reg_sublist sublists[];
> +};
> +
> +#define for_each_sublist(c, s)		\
> +	for ((s) = &(c)->sublists[0]; (s)->regs; ++(s))
> +
> +#define kvm_for_each_vcpu(vm, i, vcpu)			\
> +	for ((i) = 0; (i) <= (vm)->last_vcpu_id; (i)++)	\
> +		if (!((vcpu) = vm->vcpus[i]))		\
> +			continue;			\
> +		else
> +
> +struct userspace_mem_region *
> +memslot2region(struct kvm_vm *vm, uint32_t memslot);
> +
> +static inline struct userspace_mem_region *vm_get_mem_region(struct kvm_vm *vm,
> +							     enum kvm_mem_region_type type)
> +{
> +	assert(type < NR_MEM_REGIONS);
> +	return memslot2region(vm, vm->memslots[type]);
> +}
> +
> +/* Minimum allocated guest virtual and physical addresses */
> +#define KVM_UTIL_MIN_VADDR		0x2000
> +#define KVM_GUEST_PAGE_TABLE_MIN_PADDR	0x180000
> +
> +#define DEFAULT_GUEST_STACK_VADDR_MIN	0xab6000
> +#define DEFAULT_STACK_PGS		5
> +
> +enum vm_guest_mode {
> +	VM_MODE_P52V48_4K,
> +	VM_MODE_P52V48_16K,
> +	VM_MODE_P52V48_64K,
> +	VM_MODE_P48V48_4K,
> +	VM_MODE_P48V48_16K,
> +	VM_MODE_P48V48_64K,
> +	VM_MODE_P40V48_4K,
> +	VM_MODE_P40V48_16K,
> +	VM_MODE_P40V48_64K,
> +	VM_MODE_PXXV48_4K,	/* For 48bits VA but ANY bits PA */
> +	VM_MODE_P47V64_4K,
> +	VM_MODE_P44V64_4K,
> +	VM_MODE_P36V48_4K,
> +	VM_MODE_P36V48_16K,
> +	VM_MODE_P36V48_64K,
> +	VM_MODE_P36V47_16K,
> +	NUM_VM_MODES,
> +};
> +
> +struct vm_shape {
> +	uint32_t type;
> +	uint8_t  mode;
> +	uint8_t  subtype;
> +	uint16_t padding;
> +};
> +
> +kvm_static_assert(sizeof(struct vm_shape) == sizeof(uint64_t));
> +
> +#define VM_TYPE_DEFAULT			0
> +
> +#define VM_SHAPE(__mode)			\
> +({						\
> +	struct vm_shape shape = {		\
> +		.mode = (__mode),		\
> +		.type = VM_TYPE_DEFAULT		\
> +	};					\
> +						\
> +	shape;					\
> +})
> +
> +#if defined(__aarch64__)
> +
> +extern enum vm_guest_mode vm_mode_default;
> +
> +#define VM_MODE_DEFAULT			vm_mode_default
> +#define MIN_PAGE_SHIFT			12U
> +#define ptes_per_page(page_size)	((page_size) / 8)
> +
> +#elif defined(__x86_64__)
> +
> +#define VM_MODE_DEFAULT			VM_MODE_PXXV48_4K
> +#define MIN_PAGE_SHIFT			12U
> +#define ptes_per_page(page_size)	((page_size) / 8)
> +
> +#elif defined(__s390x__)
> +
> +#define VM_MODE_DEFAULT			VM_MODE_P44V64_4K
> +#define MIN_PAGE_SHIFT			12U
> +#define ptes_per_page(page_size)	((page_size) / 16)
> +
> +#elif defined(__riscv)
> +
> +#if __riscv_xlen == 32
> +#error "RISC-V 32-bit kvm selftests not supported"
> +#endif
> +
> +#define VM_MODE_DEFAULT			VM_MODE_P40V48_4K
> +#define MIN_PAGE_SHIFT			12U
> +#define ptes_per_page(page_size)	((page_size) / 8)
> +
> +#endif
> +
> +#define VM_SHAPE_DEFAULT	VM_SHAPE(VM_MODE_DEFAULT)
> +
> +#define MIN_PAGE_SIZE		(1U << MIN_PAGE_SHIFT)
> +#define PTES_PER_MIN_PAGE	ptes_per_page(MIN_PAGE_SIZE)
> +
> +struct vm_guest_mode_params {
> +	unsigned int pa_bits;
> +	unsigned int va_bits;
> +	unsigned int page_size;
> +	unsigned int page_shift;
> +};
> +extern const struct vm_guest_mode_params vm_guest_mode_params[];
> +
> +int open_path_or_exit(const char *path, int flags);
> +int open_kvm_dev_path_or_exit(void);
> +
> +bool get_kvm_param_bool(const char *param);
> +bool get_kvm_intel_param_bool(const char *param);
> +bool get_kvm_amd_param_bool(const char *param);
> +
> +int get_kvm_param_integer(const char *param);
> +int get_kvm_intel_param_integer(const char *param);
> +int get_kvm_amd_param_integer(const char *param);
> +
> +unsigned int kvm_check_cap(long cap);
> +
> +static inline bool kvm_has_cap(long cap)
> +{
> +	return kvm_check_cap(cap);
> +}
> +
> +#define __KVM_SYSCALL_ERROR(_name, _ret) \
> +	"%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno)
> +
> +/*
> + * Use the "inner", double-underscore macro when reporting errors from within
> + * other macros so that the name of ioctl() and not its literal numeric value
> + * is printed on error.  The "outer" macro is strongly preferred when reporting
> + * errors "directly", i.e. without an additional layer of macros, as it reduces
> + * the probability of passing in the wrong string.
> + */
> +#define __KVM_IOCTL_ERROR(_name, _ret)	__KVM_SYSCALL_ERROR(_name, _ret)
> +#define KVM_IOCTL_ERROR(_ioctl, _ret) __KVM_IOCTL_ERROR(#_ioctl, _ret)
> +
> +#define kvm_do_ioctl(fd, cmd, arg)						\
> +({										\
> +	kvm_static_assert(!_IOC_SIZE(cmd) || sizeof(*arg) == _IOC_SIZE(cmd));	\
> +	ioctl(fd, cmd, arg);							\
> +})
> +
> +#define __kvm_ioctl(kvm_fd, cmd, arg)				\
> +	kvm_do_ioctl(kvm_fd, cmd, arg)
> +
> +#define kvm_ioctl(kvm_fd, cmd, arg)				\
> +({								\
> +	int ret = __kvm_ioctl(kvm_fd, cmd, arg);		\
> +								\
> +	TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(#cmd, ret));	\
> +})
> +
> +static __always_inline void static_assert_is_vm(struct kvm_vm *vm) { }
> +
> +#define __vm_ioctl(vm, cmd, arg)				\
> +({								\
> +	static_assert_is_vm(vm);				\
> +	kvm_do_ioctl((vm)->fd, cmd, arg);			\
> +})
> +
> +/*
> + * Assert that a VM or vCPU ioctl() succeeded, with extra magic to detect if
> + * the ioctl() failed because KVM killed/bugged the VM.  To detect a dead VM,
> + * probe KVM_CAP_USER_MEMORY, which (a) has been supported by KVM since before
> + * selftests existed and (b) should never outright fail, i.e. is supposed to
> + * return 0 or 1.  If KVM kills a VM, KVM returns -EIO for all ioctl()s for the
> + * VM and its vCPUs, including KVM_CHECK_EXTENSION.
> + */
> +#define __TEST_ASSERT_VM_VCPU_IOCTL(cond, name, ret, vm)				\
> +do {											\
> +	int __errno = errno;								\
> +											\
> +	static_assert_is_vm(vm);							\
> +											\
> +	if (cond)									\
> +		break;									\
> +											\
> +	if (errno == EIO &&								\
> +	    __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)KVM_CAP_USER_MEMORY) < 0) {	\
> +		TEST_ASSERT(errno == EIO, "KVM killed the VM, should return -EIO");	\
> +		TEST_FAIL("KVM killed/bugged the VM, check the kernel log for clues");	\
> +	}										\
> +	errno = __errno;								\
> +	TEST_ASSERT(cond, __KVM_IOCTL_ERROR(name, ret));				\
> +} while (0)
> +
> +#define TEST_ASSERT_VM_VCPU_IOCTL(cond, cmd, ret, vm)		\
> +	__TEST_ASSERT_VM_VCPU_IOCTL(cond, #cmd, ret, vm)
> +
> +#define vm_ioctl(vm, cmd, arg)					\
> +({								\
> +	int ret = __vm_ioctl(vm, cmd, arg);			\
> +								\
> +	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm);		\
> +})
> +
> +static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
> +
> +#define __vcpu_ioctl(vcpu, cmd, arg)				\
> +({								\
> +	static_assert_is_vcpu(vcpu);				\
> +	kvm_do_ioctl((vcpu)->fd, cmd, arg);			\
> +})
> +
> +#define vcpu_ioctl(vcpu, cmd, arg)				\
> +({								\
> +	int ret = __vcpu_ioctl(vcpu, cmd, arg);			\
> +								\
> +	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm);	\
> +})
> +
> +/*
> + * Looks up and returns the value corresponding to the capability
> + * (KVM_CAP_*) given by cap.
> + */
> +static inline int vm_check_cap(struct kvm_vm *vm, long cap)
> +{
> +	int ret =  __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)cap);
> +
> +	TEST_ASSERT_VM_VCPU_IOCTL(ret >= 0, KVM_CHECK_EXTENSION, ret, vm);
> +	return ret;
> +}
> +
> +static inline int __vm_enable_cap(struct kvm_vm *vm, uint32_t cap, uint64_t arg0)
> +{
> +	struct kvm_enable_cap enable_cap = { .cap = cap, .args = { arg0 } };
> +
> +	return __vm_ioctl(vm, KVM_ENABLE_CAP, &enable_cap);
> +}
> +static inline void vm_enable_cap(struct kvm_vm *vm, uint32_t cap, uint64_t arg0)
> +{
> +	struct kvm_enable_cap enable_cap = { .cap = cap, .args = { arg0 } };
> +
> +	vm_ioctl(vm, KVM_ENABLE_CAP, &enable_cap);
> +}
> +
> +static inline void vm_set_memory_attributes(struct kvm_vm *vm, uint64_t gpa,
> +					    uint64_t size, uint64_t attributes)
> +{
> +	struct kvm_memory_attributes attr = {
> +		.attributes = attributes,
> +		.address = gpa,
> +		.size = size,
> +		.flags = 0,
> +	};
> +
> +	/*
> +	 * KVM_SET_MEMORY_ATTRIBUTES overwrites _all_ attributes.  These flows
> +	 * need significant enhancements to support multiple attributes.
> +	 */
> +	TEST_ASSERT(!attributes || attributes == KVM_MEMORY_ATTRIBUTE_PRIVATE,
> +		    "Update me to support multiple attributes!");
> +
> +	vm_ioctl(vm, KVM_SET_MEMORY_ATTRIBUTES, &attr);
> +}
> +
> +
> +static inline void vm_mem_set_private(struct kvm_vm *vm, uint64_t gpa,
> +				      uint64_t size)
> +{
> +	vm_set_memory_attributes(vm, gpa, size, KVM_MEMORY_ATTRIBUTE_PRIVATE);
> +}
> +
> +static inline void vm_mem_set_shared(struct kvm_vm *vm, uint64_t gpa,
> +				     uint64_t size)
> +{
> +	vm_set_memory_attributes(vm, gpa, size, 0);
> +}
> +
> +void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t gpa, uint64_t size,
> +			    bool punch_hole);
> +
> +static inline void vm_guest_mem_punch_hole(struct kvm_vm *vm, uint64_t gpa,
> +					   uint64_t size)
> +{
> +	vm_guest_mem_fallocate(vm, gpa, size, true);
> +}
> +
> +static inline void vm_guest_mem_allocate(struct kvm_vm *vm, uint64_t gpa,
> +					 uint64_t size)
> +{
> +	vm_guest_mem_fallocate(vm, gpa, size, false);
> +}
> +
> +void vm_enable_dirty_ring(struct kvm_vm *vm, uint32_t ring_size);
> +const char *vm_guest_mode_string(uint32_t i);
> +
> +void kvm_vm_free(struct kvm_vm *vmp);
> +void kvm_vm_restart(struct kvm_vm *vmp);
> +void kvm_vm_release(struct kvm_vm *vmp);
> +int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, const vm_vaddr_t gva,
> +		       size_t len);
> +void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename);
> +int kvm_memfd_alloc(size_t size, bool hugepages);
> +
> +void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
> +
> +static inline void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
> +{
> +	struct kvm_dirty_log args = { .dirty_bitmap = log, .slot = slot };
> +
> +	vm_ioctl(vm, KVM_GET_DIRTY_LOG, &args);
> +}
> +
> +static inline void kvm_vm_clear_dirty_log(struct kvm_vm *vm, int slot, void *log,
> +					  uint64_t first_page, uint32_t num_pages)
> +{
> +	struct kvm_clear_dirty_log args = {
> +		.dirty_bitmap = log,
> +		.slot = slot,
> +		.first_page = first_page,
> +		.num_pages = num_pages
> +	};
> +
> +	vm_ioctl(vm, KVM_CLEAR_DIRTY_LOG, &args);
> +}
> +
> +static inline uint32_t kvm_vm_reset_dirty_ring(struct kvm_vm *vm)
> +{
> +	return __vm_ioctl(vm, KVM_RESET_DIRTY_RINGS, NULL);
> +}
> +
> +static inline int vm_get_stats_fd(struct kvm_vm *vm)
> +{
> +	int fd = __vm_ioctl(vm, KVM_GET_STATS_FD, NULL);
> +
> +	TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_GET_STATS_FD, fd, vm);
> +	return fd;
> +}
> +
> +static inline void read_stats_header(int stats_fd, struct kvm_stats_header *header)
> +{
> +	ssize_t ret;
> +
> +	ret = pread(stats_fd, header, sizeof(*header), 0);
> +	TEST_ASSERT(ret == sizeof(*header),
> +		    "Failed to read '%lu' header bytes, ret = '%ld'",
> +		    sizeof(*header), ret);
> +}
> +
> +struct kvm_stats_desc *read_stats_descriptors(int stats_fd,
> +					      struct kvm_stats_header *header);
> +
> +static inline ssize_t get_stats_descriptor_size(struct kvm_stats_header *header)
> +{
> +	 /*
> +	  * The base size of the descriptor is defined by KVM's ABI, but the
> +	  * size of the name field is variable, as far as KVM's ABI is
> +	  * concerned. For a given instance of KVM, the name field is the same
> +	  * size for all stats and is provided in the overall stats header.
> +	  */
> +	return sizeof(struct kvm_stats_desc) + header->name_size;
> +}
> +
> +static inline struct kvm_stats_desc *get_stats_descriptor(struct kvm_stats_desc *stats,
> +							  int index,
> +							  struct kvm_stats_header *header)
> +{
> +	/*
> +	 * Note, size_desc includes the size of the name field, which is
> +	 * variable. i.e. this is NOT equivalent to &stats_desc[i].
> +	 */
> +	return (void *)stats + index * get_stats_descriptor_size(header);
> +}
> +
> +void read_stat_data(int stats_fd, struct kvm_stats_header *header,
> +		    struct kvm_stats_desc *desc, uint64_t *data,
> +		    size_t max_elements);
> +
> +void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *data,
> +		   size_t max_elements);
> +
> +static inline uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name)
> +{
> +	uint64_t data;
> +
> +	__vm_get_stat(vm, stat_name, &data, 1);
> +	return data;
> +}
> +
> +void vm_create_irqchip(struct kvm_vm *vm);
> +
> +static inline int __vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size,
> +					uint64_t flags)
> +{
> +	struct kvm_create_guest_memfd guest_memfd = {
> +		.size = size,
> +		.flags = flags,
> +	};
> +
> +	return __vm_ioctl(vm, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
> +}
> +
> +static inline int vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size,
> +					uint64_t flags)
> +{
> +	int fd = __vm_create_guest_memfd(vm, size, flags);
> +
> +	TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_GUEST_MEMFD, fd));
> +	return fd;
> +}
> +
> +void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> +			       uint64_t gpa, uint64_t size, void *hva);
> +int __vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> +				uint64_t gpa, uint64_t size, void *hva);
> +void vm_set_user_memory_region2(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> +				uint64_t gpa, uint64_t size, void *hva,
> +				uint32_t guest_memfd, uint64_t guest_memfd_offset);
> +int __vm_set_user_memory_region2(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> +				 uint64_t gpa, uint64_t size, void *hva,
> +				 uint32_t guest_memfd, uint64_t guest_memfd_offset);
> +
> +void vm_userspace_mem_region_add(struct kvm_vm *vm,
> +	enum vm_mem_backing_src_type src_type,
> +	uint64_t guest_paddr, uint32_t slot, uint64_t npages,
> +	uint32_t flags);
> +void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
> +		uint64_t guest_paddr, uint32_t slot, uint64_t npages,
> +		uint32_t flags, int guest_memfd_fd, uint64_t guest_memfd_offset);
> +
> +#ifndef vm_arch_has_protected_memory
> +static inline bool vm_arch_has_protected_memory(struct kvm_vm *vm)
> +{
> +	return false;
> +}
> +#endif
> +
> +void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
> +void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa);
> +void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot);
> +struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id);
> +void vm_populate_vaddr_bitmap(struct kvm_vm *vm);
> +vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
> +vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
> +vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
> +			    enum kvm_mem_region_type type);
> +vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz,
> +				 vm_vaddr_t vaddr_min,
> +				 enum kvm_mem_region_type type);
> +vm_vaddr_t vm_vaddr_alloc_pages(struct kvm_vm *vm, int nr_pages);
> +vm_vaddr_t __vm_vaddr_alloc_page(struct kvm_vm *vm,
> +				 enum kvm_mem_region_type type);
> +vm_vaddr_t vm_vaddr_alloc_page(struct kvm_vm *vm);
> +
> +void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
> +	      unsigned int npages);
> +void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa);
> +void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva);
> +vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva);
> +void *addr_gpa2alias(struct kvm_vm *vm, vm_paddr_t gpa);
> +
> +
> +static inline vm_paddr_t vm_untag_gpa(struct kvm_vm *vm, vm_paddr_t gpa)
> +{
> +	return gpa & ~vm->gpa_tag_mask;
> +}
> +
> +void vcpu_run(struct kvm_vcpu *vcpu);
> +int _vcpu_run(struct kvm_vcpu *vcpu);
> +
> +static inline int __vcpu_run(struct kvm_vcpu *vcpu)
> +{
> +	return __vcpu_ioctl(vcpu, KVM_RUN, NULL);
> +}
> +
> +void vcpu_run_complete_io(struct kvm_vcpu *vcpu);
> +struct kvm_reg_list *vcpu_get_reg_list(struct kvm_vcpu *vcpu);
> +
> +static inline void vcpu_enable_cap(struct kvm_vcpu *vcpu, uint32_t cap,
> +				   uint64_t arg0)
> +{
> +	struct kvm_enable_cap enable_cap = { .cap = cap, .args = { arg0 } };
> +
> +	vcpu_ioctl(vcpu, KVM_ENABLE_CAP, &enable_cap);
> +}
> +
> +static inline void vcpu_guest_debug_set(struct kvm_vcpu *vcpu,
> +					struct kvm_guest_debug *debug)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_GUEST_DEBUG, debug);
> +}
> +
> +static inline void vcpu_mp_state_get(struct kvm_vcpu *vcpu,
> +				     struct kvm_mp_state *mp_state)
> +{
> +	vcpu_ioctl(vcpu, KVM_GET_MP_STATE, mp_state);
> +}
> +static inline void vcpu_mp_state_set(struct kvm_vcpu *vcpu,
> +				     struct kvm_mp_state *mp_state)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_MP_STATE, mp_state);
> +}
> +
> +static inline void vcpu_regs_get(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
> +{
> +	vcpu_ioctl(vcpu, KVM_GET_REGS, regs);
> +}
> +
> +static inline void vcpu_regs_set(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_REGS, regs);
> +}
> +static inline void vcpu_sregs_get(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
> +{
> +	vcpu_ioctl(vcpu, KVM_GET_SREGS, sregs);
> +
> +}
> +static inline void vcpu_sregs_set(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_SREGS, sregs);
> +}
> +static inline int _vcpu_sregs_set(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
> +{
> +	return __vcpu_ioctl(vcpu, KVM_SET_SREGS, sregs);
> +}
> +static inline void vcpu_fpu_get(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
> +{
> +	vcpu_ioctl(vcpu, KVM_GET_FPU, fpu);
> +}
> +static inline void vcpu_fpu_set(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_FPU, fpu);
> +}
> +
> +static inline int __vcpu_get_reg(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
> +{
> +	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)addr };
> +
> +	return __vcpu_ioctl(vcpu, KVM_GET_ONE_REG, &reg);
> +}
> +static inline int __vcpu_set_reg(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
> +{
> +	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)&val };
> +
> +	return __vcpu_ioctl(vcpu, KVM_SET_ONE_REG, &reg);
> +}
> +static inline void vcpu_get_reg(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
> +{
> +	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)addr };
> +
> +	vcpu_ioctl(vcpu, KVM_GET_ONE_REG, &reg);
> +}
> +static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
> +{
> +	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)&val };
> +
> +	vcpu_ioctl(vcpu, KVM_SET_ONE_REG, &reg);
> +}
> +
> +#ifdef __KVM_HAVE_VCPU_EVENTS
> +static inline void vcpu_events_get(struct kvm_vcpu *vcpu,
> +				   struct kvm_vcpu_events *events)
> +{
> +	vcpu_ioctl(vcpu, KVM_GET_VCPU_EVENTS, events);
> +}
> +static inline void vcpu_events_set(struct kvm_vcpu *vcpu,
> +				   struct kvm_vcpu_events *events)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_VCPU_EVENTS, events);
> +}
> +#endif
> +#ifdef __x86_64__
> +static inline void vcpu_nested_state_get(struct kvm_vcpu *vcpu,
> +					 struct kvm_nested_state *state)
> +{
> +	vcpu_ioctl(vcpu, KVM_GET_NESTED_STATE, state);
> +}
> +static inline int __vcpu_nested_state_set(struct kvm_vcpu *vcpu,
> +					  struct kvm_nested_state *state)
> +{
> +	return __vcpu_ioctl(vcpu, KVM_SET_NESTED_STATE, state);
> +}
> +
> +static inline void vcpu_nested_state_set(struct kvm_vcpu *vcpu,
> +					 struct kvm_nested_state *state)
> +{
> +	vcpu_ioctl(vcpu, KVM_SET_NESTED_STATE, state);
> +}
> +#endif
> +static inline int vcpu_get_stats_fd(struct kvm_vcpu *vcpu)
> +{
> +	int fd = __vcpu_ioctl(vcpu, KVM_GET_STATS_FD, NULL);
> +
> +	TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_CHECK_EXTENSION, fd, vcpu->vm);
> +	return fd;
> +}
> +
> +int __kvm_has_device_attr(int dev_fd, uint32_t group, uint64_t attr);
> +
> +static inline void kvm_has_device_attr(int dev_fd, uint32_t group, uint64_t attr)
> +{
> +	int ret = __kvm_has_device_attr(dev_fd, group, attr);
> +
> +	TEST_ASSERT(!ret, "KVM_HAS_DEVICE_ATTR failed, rc: %i errno: %i", ret, errno);
> +}
> +
> +int __kvm_device_attr_get(int dev_fd, uint32_t group, uint64_t attr, void *val);
> +
> +static inline void kvm_device_attr_get(int dev_fd, uint32_t group,
> +				       uint64_t attr, void *val)
> +{
> +	int ret = __kvm_device_attr_get(dev_fd, group, attr, val);
> +
> +	TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_GET_DEVICE_ATTR, ret));
> +}
> +
> +int __kvm_device_attr_set(int dev_fd, uint32_t group, uint64_t attr, void *val);
> +
> +static inline void kvm_device_attr_set(int dev_fd, uint32_t group,
> +				       uint64_t attr, void *val)
> +{
> +	int ret = __kvm_device_attr_set(dev_fd, group, attr, val);
> +
> +	TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_SET_DEVICE_ATTR, ret));
> +}
> +
> +static inline int __vcpu_has_device_attr(struct kvm_vcpu *vcpu, uint32_t group,
> +					 uint64_t attr)
> +{
> +	return __kvm_has_device_attr(vcpu->fd, group, attr);
> +}
> +
> +static inline void vcpu_has_device_attr(struct kvm_vcpu *vcpu, uint32_t group,
> +					uint64_t attr)
> +{
> +	kvm_has_device_attr(vcpu->fd, group, attr);
> +}
> +
> +static inline int __vcpu_device_attr_get(struct kvm_vcpu *vcpu, uint32_t group,
> +					 uint64_t attr, void *val)
> +{
> +	return __kvm_device_attr_get(vcpu->fd, group, attr, val);
> +}
> +
> +static inline void vcpu_device_attr_get(struct kvm_vcpu *vcpu, uint32_t group,
> +					uint64_t attr, void *val)
> +{
> +	kvm_device_attr_get(vcpu->fd, group, attr, val);
> +}
> +
> +static inline int __vcpu_device_attr_set(struct kvm_vcpu *vcpu, uint32_t group,
> +					 uint64_t attr, void *val)
> +{
> +	return __kvm_device_attr_set(vcpu->fd, group, attr, val);
> +}
> +
> +static inline void vcpu_device_attr_set(struct kvm_vcpu *vcpu, uint32_t group,
> +					uint64_t attr, void *val)
> +{
> +	kvm_device_attr_set(vcpu->fd, group, attr, val);
> +}
> +
> +int __kvm_test_create_device(struct kvm_vm *vm, uint64_t type);
> +int __kvm_create_device(struct kvm_vm *vm, uint64_t type);
> +
> +static inline int kvm_create_device(struct kvm_vm *vm, uint64_t type)
> +{
> +	int fd = __kvm_create_device(vm, type);
> +
> +	TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_DEVICE, fd));
> +	return fd;
> +}
> +
> +void *vcpu_map_dirty_ring(struct kvm_vcpu *vcpu);
> +
> +/*
> + * VM VCPU Args Set
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   num - number of arguments
> + *   ... - arguments, each of type uint64_t
> + *
> + * Output Args: None
> + *
> + * Return: None
> + *
> + * Sets the first @num input parameters for the function at @vcpu's entry point,
> + * per the C calling convention of the architecture, to the values given as
> + * variable args. Each of the variable args is expected to be of type uint64_t.
> + * The maximum @num can be is specific to the architecture.
> + */
> +void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...);
> +
> +void kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level);
> +int _kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level);
> +
> +#define KVM_MAX_IRQ_ROUTES		4096
> +
> +struct kvm_irq_routing *kvm_gsi_routing_create(void);
> +void kvm_gsi_routing_irqchip_add(struct kvm_irq_routing *routing,
> +		uint32_t gsi, uint32_t pin);
> +int _kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
> +void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
> +
> +const char *exit_reason_str(unsigned int exit_reason);
> +
> +vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
> +			     uint32_t memslot);
> +vm_paddr_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
> +				vm_paddr_t paddr_min, uint32_t memslot,
> +				bool protected);
> +vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm);
> +
> +static inline vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
> +					    vm_paddr_t paddr_min, uint32_t memslot)
> +{
> +	/*
> +	 * By default, allocate memory as protected for VMs that support
> +	 * protected memory, as the majority of memory for such VMs is
> +	 * protected, i.e. using shared memory is effectively opt-in.
> +	 */
> +	return __vm_phy_pages_alloc(vm, num, paddr_min, memslot,
> +				    vm_arch_has_protected_memory(vm));
> +}
> +
> +/*
> + * ____vm_create() does KVM_CREATE_VM and little else.  __vm_create() also
> + * loads the test binary into guest memory and creates an IRQ chip (x86 only).
> + * __vm_create() does NOT create vCPUs, @nr_runnable_vcpus is used purely to
> + * calculate the amount of memory needed for per-vCPU data, e.g. stacks.
> + */
> +struct kvm_vm *____vm_create(struct vm_shape shape);
> +struct kvm_vm *__vm_create(struct vm_shape shape, uint32_t nr_runnable_vcpus,
> +			   uint64_t nr_extra_pages);
> +
> +static inline struct kvm_vm *vm_create_barebones(void)
> +{
> +	return ____vm_create(VM_SHAPE_DEFAULT);
> +}
> +
> +#ifdef __x86_64__
> +static inline struct kvm_vm *vm_create_barebones_protected_vm(void)
> +{
> +	const struct vm_shape shape = {
> +		.mode = VM_MODE_DEFAULT,
> +		.type = KVM_X86_SW_PROTECTED_VM,
> +	};
> +
> +	return ____vm_create(shape);
> +}
> +#endif
> +
> +static inline struct kvm_vm *vm_create(uint32_t nr_runnable_vcpus)
> +{
> +	return __vm_create(VM_SHAPE_DEFAULT, nr_runnable_vcpus, 0);
> +}
> +
> +struct kvm_vm *__vm_create_with_vcpus(struct vm_shape shape, uint32_t nr_vcpus,
> +				      uint64_t extra_mem_pages,
> +				      void *guest_code, struct kvm_vcpu *vcpus[]);
> +
> +static inline struct kvm_vm *vm_create_with_vcpus(uint32_t nr_vcpus,
> +						  void *guest_code,
> +						  struct kvm_vcpu *vcpus[])
> +{
> +	return __vm_create_with_vcpus(VM_SHAPE_DEFAULT, nr_vcpus, 0,
> +				      guest_code, vcpus);
> +}
> +
> +
> +struct kvm_vm *__vm_create_shape_with_one_vcpu(struct vm_shape shape,
> +					       struct kvm_vcpu **vcpu,
> +					       uint64_t extra_mem_pages,
> +					       void *guest_code);
> +
> +/*
> + * Create a VM with a single vCPU with reasonable defaults and @extra_mem_pages
> + * additional pages of guest memory.  Returns the VM and vCPU (via out param).
> + */
> +static inline struct kvm_vm *__vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
> +						       uint64_t extra_mem_pages,
> +						       void *guest_code)
> +{
> +	return __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, vcpu,
> +					       extra_mem_pages, guest_code);
> +}
> +
> +static inline struct kvm_vm *vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
> +						     void *guest_code)
> +{
> +	return __vm_create_with_one_vcpu(vcpu, 0, guest_code);
> +}
> +
> +static inline struct kvm_vm *vm_create_shape_with_one_vcpu(struct vm_shape shape,
> +							   struct kvm_vcpu **vcpu,
> +							   void *guest_code)
> +{
> +	return __vm_create_shape_with_one_vcpu(shape, vcpu, 0, guest_code);
> +}
> +
> +struct kvm_vcpu *vm_recreate_with_one_vcpu(struct kvm_vm *vm);
> +
> +void kvm_pin_this_task_to_pcpu(uint32_t pcpu);
> +void kvm_print_vcpu_pinning_help(void);
> +void kvm_parse_vcpu_pinning(const char *pcpus_string, uint32_t vcpu_to_pcpu[],
> +			    int nr_vcpus);
> +
> +unsigned long vm_compute_max_gfn(struct kvm_vm *vm);
> +unsigned int vm_calc_num_guest_pages(enum vm_guest_mode mode, size_t size);
> +unsigned int vm_num_host_pages(enum vm_guest_mode mode, unsigned int num_guest_pages);
> +unsigned int vm_num_guest_pages(enum vm_guest_mode mode, unsigned int num_host_pages);
> +static inline unsigned int
> +vm_adjust_num_guest_pages(enum vm_guest_mode mode, unsigned int num_guest_pages)
> +{
> +	unsigned int n;
> +	n = vm_num_guest_pages(mode, vm_num_host_pages(mode, num_guest_pages));
> +#ifdef __s390x__
> +	/* s390 requires 1M aligned guest sizes */
> +	n = (n + 255) & ~255;
> +#endif
> +	return n;
> +}
> +
> +#define sync_global_to_guest(vm, g) ({				\
> +	typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g));	\
> +	memcpy(_p, &(g), sizeof(g));				\
> +})
> +
> +#define sync_global_from_guest(vm, g) ({			\
> +	typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g));	\
> +	memcpy(&(g), _p, sizeof(g));				\
> +})
> +
> +/*
> + * Write a global value, but only in the VM's (guest's) domain.  Primarily used
> + * for "globals" that hold per-VM values (VMs always duplicate code and global
> + * data into their own region of physical memory), but can be used anytime it's
> + * undesirable to change the host's copy of the global.
> + */
> +#define write_guest_global(vm, g, val) ({			\
> +	typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g));	\
> +	typeof(g) _val = val;					\
> +								\
> +	memcpy(_p, &(_val), sizeof(g));				\
> +})
> +
> +void assert_on_unhandled_exception(struct kvm_vcpu *vcpu);
> +
> +void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu,
> +		    uint8_t indent);
> +
> +static inline void vcpu_dump(FILE *stream, struct kvm_vcpu *vcpu,
> +			     uint8_t indent)
> +{
> +	vcpu_arch_dump(stream, vcpu, indent);
> +}
> +
> +/*
> + * Adds a vCPU with reasonable defaults (e.g. a stack)
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   vcpu_id - The id of the VCPU to add to the VM.
> + */
> +struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id);
> +void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code);
> +
> +static inline struct kvm_vcpu *vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
> +					   void *guest_code)
> +{
> +	struct kvm_vcpu *vcpu = vm_arch_vcpu_add(vm, vcpu_id);
> +
> +	vcpu_arch_set_entry_point(vcpu, guest_code);
> +
> +	return vcpu;
> +}
> +
> +/* Re-create a vCPU after restarting a VM, e.g. for state save/restore tests. */
> +struct kvm_vcpu *vm_arch_vcpu_recreate(struct kvm_vm *vm, uint32_t vcpu_id);
> +
> +static inline struct kvm_vcpu *vm_vcpu_recreate(struct kvm_vm *vm,
> +						uint32_t vcpu_id)
> +{
> +	return vm_arch_vcpu_recreate(vm, vcpu_id);
> +}
> +
> +void vcpu_arch_free(struct kvm_vcpu *vcpu);
> +
> +void virt_arch_pgd_alloc(struct kvm_vm *vm);
> +
> +static inline void virt_pgd_alloc(struct kvm_vm *vm)
> +{
> +	virt_arch_pgd_alloc(vm);
> +}
> +
> +/*
> + * VM Virtual Page Map
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   vaddr - VM Virtual Address
> + *   paddr - VM Physical Address
> + *   memslot - Memory region slot for new virtual translation tables
> + *
> + * Output Args: None
> + *
> + * Return: None
> + *
> + * Within @vm, creates a virtual translation for the page starting
> + * at @vaddr to the page starting at @paddr.
> + */
> +void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr);
> +
> +static inline void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
> +{
> +	virt_arch_pg_map(vm, vaddr, paddr);
> +}
> +
> +
> +/*
> + * Address Guest Virtual to Guest Physical
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   gva - VM virtual address
> + *
> + * Output Args: None
> + *
> + * Return:
> + *   Equivalent VM physical address
> + *
> + * Returns the VM physical address of the translated VM virtual
> + * address given by @gva.
> + */
> +vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva);
> +
> +static inline vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
> +{
> +	return addr_arch_gva2gpa(vm, gva);
> +}
> +
> +/*
> + * Virtual Translation Tables Dump
> + *
> + * Input Args:
> + *   stream - Output FILE stream
> + *   vm     - Virtual Machine
> + *   indent - Left margin indent amount
> + *
> + * Output Args: None
> + *
> + * Return: None
> + *
> + * Dumps to the FILE stream given by @stream, the contents of all the
> + * virtual translation tables for the VM given by @vm.
> + */
> +void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
> +
> +static inline void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
> +{
> +	virt_arch_dump(stream, vm, indent);
> +}
> +
> +
> +static inline int __vm_disable_nx_huge_pages(struct kvm_vm *vm)
> +{
> +	return __vm_enable_cap(vm, KVM_CAP_VM_DISABLE_NX_HUGE_PAGES, 0);
> +}
> +
> +/*
> + * Arch hook that is invoked via a constructor, i.e. before exeucting main(),
> + * to allow for arch-specific setup that is common to all tests, e.g. computing
> + * the default guest "mode".
> + */
> +void kvm_selftest_arch_init(void);
> +
> +void kvm_arch_vm_post_create(struct kvm_vm *vm);
> +
> +bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr);
> +
> +uint32_t guest_get_vcpuid(void);
>  
>  #endif /* SELFTEST_KVM_UTIL_H */
> diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
> deleted file mode 100644
> index 3e0db283a46a..000000000000
> --- a/tools/testing/selftests/kvm/include/kvm_util_base.h
> +++ /dev/null
> @@ -1,1135 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * tools/testing/selftests/kvm/include/kvm_util_base.h
> - *
> - * Copyright (C) 2018, Google LLC.
> - */
> -#ifndef SELFTEST_KVM_UTIL_BASE_H
> -#define SELFTEST_KVM_UTIL_BASE_H
> -
> -#include "test_util.h"
> -
> -#include <linux/compiler.h>
> -#include "linux/hashtable.h"
> -#include "linux/list.h"
> -#include <linux/kernel.h>
> -#include <linux/kvm.h>
> -#include "linux/rbtree.h"
> -#include <linux/types.h>
> -
> -#include <asm/atomic.h>
> -#include <asm/kvm.h>
> -
> -#include <sys/ioctl.h>
> -
> -#include "kvm_util_arch.h"
> -#include "sparsebit.h"
> -
> -/*
> - * Provide a version of static_assert() that is guaranteed to have an optional
> - * message param.  If _ISOC11_SOURCE is defined, glibc (/usr/include/assert.h)
> - * #undefs and #defines static_assert() as a direct alias to _Static_assert(),
> - * i.e. effectively makes the message mandatory.  Many KVM selftests #define
> - * _GNU_SOURCE for various reasons, and _GNU_SOURCE implies _ISOC11_SOURCE.  As
> - * a result, static_assert() behavior is non-deterministic and may or may not
> - * require a message depending on #include order.
> - */
> -#define __kvm_static_assert(expr, msg, ...) _Static_assert(expr, msg)
> -#define kvm_static_assert(expr, ...) __kvm_static_assert(expr, ##__VA_ARGS__, #expr)
> -
> -#define KVM_DEV_PATH "/dev/kvm"
> -#define KVM_MAX_VCPUS 512
> -
> -#define NSEC_PER_SEC 1000000000L
> -
> -typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
> -typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
> -
> -struct userspace_mem_region {
> -	struct kvm_userspace_memory_region2 region;
> -	struct sparsebit *unused_phy_pages;
> -	struct sparsebit *protected_phy_pages;
> -	int fd;
> -	off_t offset;
> -	enum vm_mem_backing_src_type backing_src_type;
> -	void *host_mem;
> -	void *host_alias;
> -	void *mmap_start;
> -	void *mmap_alias;
> -	size_t mmap_size;
> -	struct rb_node gpa_node;
> -	struct rb_node hva_node;
> -	struct hlist_node slot_node;
> -};
> -
> -struct kvm_vcpu {
> -	struct list_head list;
> -	uint32_t id;
> -	int fd;
> -	struct kvm_vm *vm;
> -	struct kvm_run *run;
> -#ifdef __x86_64__
> -	struct kvm_cpuid2 *cpuid;
> -#endif
> -	struct kvm_dirty_gfn *dirty_gfns;
> -	uint32_t fetch_index;
> -	uint32_t dirty_gfns_count;
> -};
> -
> -struct userspace_mem_regions {
> -	struct rb_root gpa_tree;
> -	struct rb_root hva_tree;
> -	DECLARE_HASHTABLE(slot_hash, 9);
> -};
> -
> -enum kvm_mem_region_type {
> -	MEM_REGION_CODE,
> -	MEM_REGION_DATA,
> -	MEM_REGION_PT,
> -	MEM_REGION_TEST_DATA,
> -	NR_MEM_REGIONS,
> -};
> -
> -struct kvm_vm {
> -	int mode;
> -	unsigned long type;
> -	uint8_t subtype;
> -	int kvm_fd;
> -	int fd;
> -	unsigned int pgtable_levels;
> -	unsigned int page_size;
> -	unsigned int page_shift;
> -	unsigned int pa_bits;
> -	unsigned int va_bits;
> -	uint64_t max_gfn;
> -	struct list_head vcpus;
> -	struct userspace_mem_regions regions;
> -	struct sparsebit *vpages_valid;
> -	struct sparsebit *vpages_mapped;
> -	bool has_irqchip;
> -	bool pgd_created;
> -	vm_paddr_t ucall_mmio_addr;
> -	vm_paddr_t pgd;
> -	vm_vaddr_t gdt;
> -	vm_vaddr_t tss;
> -	vm_vaddr_t idt;
> -	vm_vaddr_t handlers;
> -	uint32_t dirty_ring_size;
> -	uint64_t gpa_tag_mask;
> -
> -	struct kvm_vm_arch arch;
> -
> -	/* Cache of information for binary stats interface */
> -	int stats_fd;
> -	struct kvm_stats_header stats_header;
> -	struct kvm_stats_desc *stats_desc;
> -
> -	/*
> -	 * KVM region slots. These are the default memslots used by page
> -	 * allocators, e.g., lib/elf uses the memslots[MEM_REGION_CODE]
> -	 * memslot.
> -	 */
> -	uint32_t memslots[NR_MEM_REGIONS];
> -};
> -
> -struct vcpu_reg_sublist {
> -	const char *name;
> -	long capability;
> -	int feature;
> -	int feature_type;
> -	bool finalize;
> -	__u64 *regs;
> -	__u64 regs_n;
> -	__u64 *rejects_set;
> -	__u64 rejects_set_n;
> -	__u64 *skips_set;
> -	__u64 skips_set_n;
> -};
> -
> -struct vcpu_reg_list {
> -	char *name;
> -	struct vcpu_reg_sublist sublists[];
> -};
> -
> -#define for_each_sublist(c, s)		\
> -	for ((s) = &(c)->sublists[0]; (s)->regs; ++(s))
> -
> -#define kvm_for_each_vcpu(vm, i, vcpu)			\
> -	for ((i) = 0; (i) <= (vm)->last_vcpu_id; (i)++)	\
> -		if (!((vcpu) = vm->vcpus[i]))		\
> -			continue;			\
> -		else
> -
> -struct userspace_mem_region *
> -memslot2region(struct kvm_vm *vm, uint32_t memslot);
> -
> -static inline struct userspace_mem_region *vm_get_mem_region(struct kvm_vm *vm,
> -							     enum kvm_mem_region_type type)
> -{
> -	assert(type < NR_MEM_REGIONS);
> -	return memslot2region(vm, vm->memslots[type]);
> -}
> -
> -/* Minimum allocated guest virtual and physical addresses */
> -#define KVM_UTIL_MIN_VADDR		0x2000
> -#define KVM_GUEST_PAGE_TABLE_MIN_PADDR	0x180000
> -
> -#define DEFAULT_GUEST_STACK_VADDR_MIN	0xab6000
> -#define DEFAULT_STACK_PGS		5
> -
> -enum vm_guest_mode {
> -	VM_MODE_P52V48_4K,
> -	VM_MODE_P52V48_16K,
> -	VM_MODE_P52V48_64K,
> -	VM_MODE_P48V48_4K,
> -	VM_MODE_P48V48_16K,
> -	VM_MODE_P48V48_64K,
> -	VM_MODE_P40V48_4K,
> -	VM_MODE_P40V48_16K,
> -	VM_MODE_P40V48_64K,
> -	VM_MODE_PXXV48_4K,	/* For 48bits VA but ANY bits PA */
> -	VM_MODE_P47V64_4K,
> -	VM_MODE_P44V64_4K,
> -	VM_MODE_P36V48_4K,
> -	VM_MODE_P36V48_16K,
> -	VM_MODE_P36V48_64K,
> -	VM_MODE_P36V47_16K,
> -	NUM_VM_MODES,
> -};
> -
> -struct vm_shape {
> -	uint32_t type;
> -	uint8_t  mode;
> -	uint8_t  subtype;
> -	uint16_t padding;
> -};
> -
> -kvm_static_assert(sizeof(struct vm_shape) == sizeof(uint64_t));
> -
> -#define VM_TYPE_DEFAULT			0
> -
> -#define VM_SHAPE(__mode)			\
> -({						\
> -	struct vm_shape shape = {		\
> -		.mode = (__mode),		\
> -		.type = VM_TYPE_DEFAULT		\
> -	};					\
> -						\
> -	shape;					\
> -})
> -
> -#if defined(__aarch64__)
> -
> -extern enum vm_guest_mode vm_mode_default;
> -
> -#define VM_MODE_DEFAULT			vm_mode_default
> -#define MIN_PAGE_SHIFT			12U
> -#define ptes_per_page(page_size)	((page_size) / 8)
> -
> -#elif defined(__x86_64__)
> -
> -#define VM_MODE_DEFAULT			VM_MODE_PXXV48_4K
> -#define MIN_PAGE_SHIFT			12U
> -#define ptes_per_page(page_size)	((page_size) / 8)
> -
> -#elif defined(__s390x__)
> -
> -#define VM_MODE_DEFAULT			VM_MODE_P44V64_4K
> -#define MIN_PAGE_SHIFT			12U
> -#define ptes_per_page(page_size)	((page_size) / 16)
> -
> -#elif defined(__riscv)
> -
> -#if __riscv_xlen == 32
> -#error "RISC-V 32-bit kvm selftests not supported"
> -#endif
> -
> -#define VM_MODE_DEFAULT			VM_MODE_P40V48_4K
> -#define MIN_PAGE_SHIFT			12U
> -#define ptes_per_page(page_size)	((page_size) / 8)
> -
> -#endif
> -
> -#define VM_SHAPE_DEFAULT	VM_SHAPE(VM_MODE_DEFAULT)
> -
> -#define MIN_PAGE_SIZE		(1U << MIN_PAGE_SHIFT)
> -#define PTES_PER_MIN_PAGE	ptes_per_page(MIN_PAGE_SIZE)
> -
> -struct vm_guest_mode_params {
> -	unsigned int pa_bits;
> -	unsigned int va_bits;
> -	unsigned int page_size;
> -	unsigned int page_shift;
> -};
> -extern const struct vm_guest_mode_params vm_guest_mode_params[];
> -
> -int open_path_or_exit(const char *path, int flags);
> -int open_kvm_dev_path_or_exit(void);
> -
> -bool get_kvm_param_bool(const char *param);
> -bool get_kvm_intel_param_bool(const char *param);
> -bool get_kvm_amd_param_bool(const char *param);
> -
> -int get_kvm_param_integer(const char *param);
> -int get_kvm_intel_param_integer(const char *param);
> -int get_kvm_amd_param_integer(const char *param);
> -
> -unsigned int kvm_check_cap(long cap);
> -
> -static inline bool kvm_has_cap(long cap)
> -{
> -	return kvm_check_cap(cap);
> -}
> -
> -#define __KVM_SYSCALL_ERROR(_name, _ret) \
> -	"%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno)
> -
> -/*
> - * Use the "inner", double-underscore macro when reporting errors from within
> - * other macros so that the name of ioctl() and not its literal numeric value
> - * is printed on error.  The "outer" macro is strongly preferred when reporting
> - * errors "directly", i.e. without an additional layer of macros, as it reduces
> - * the probability of passing in the wrong string.
> - */
> -#define __KVM_IOCTL_ERROR(_name, _ret)	__KVM_SYSCALL_ERROR(_name, _ret)
> -#define KVM_IOCTL_ERROR(_ioctl, _ret) __KVM_IOCTL_ERROR(#_ioctl, _ret)
> -
> -#define kvm_do_ioctl(fd, cmd, arg)						\
> -({										\
> -	kvm_static_assert(!_IOC_SIZE(cmd) || sizeof(*arg) == _IOC_SIZE(cmd));	\
> -	ioctl(fd, cmd, arg);							\
> -})
> -
> -#define __kvm_ioctl(kvm_fd, cmd, arg)				\
> -	kvm_do_ioctl(kvm_fd, cmd, arg)
> -
> -#define kvm_ioctl(kvm_fd, cmd, arg)				\
> -({								\
> -	int ret = __kvm_ioctl(kvm_fd, cmd, arg);		\
> -								\
> -	TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(#cmd, ret));	\
> -})
> -
> -static __always_inline void static_assert_is_vm(struct kvm_vm *vm) { }
> -
> -#define __vm_ioctl(vm, cmd, arg)				\
> -({								\
> -	static_assert_is_vm(vm);				\
> -	kvm_do_ioctl((vm)->fd, cmd, arg);			\
> -})
> -
> -/*
> - * Assert that a VM or vCPU ioctl() succeeded, with extra magic to detect if
> - * the ioctl() failed because KVM killed/bugged the VM.  To detect a dead VM,
> - * probe KVM_CAP_USER_MEMORY, which (a) has been supported by KVM since before
> - * selftests existed and (b) should never outright fail, i.e. is supposed to
> - * return 0 or 1.  If KVM kills a VM, KVM returns -EIO for all ioctl()s for the
> - * VM and its vCPUs, including KVM_CHECK_EXTENSION.
> - */
> -#define __TEST_ASSERT_VM_VCPU_IOCTL(cond, name, ret, vm)				\
> -do {											\
> -	int __errno = errno;								\
> -											\
> -	static_assert_is_vm(vm);							\
> -											\
> -	if (cond)									\
> -		break;									\
> -											\
> -	if (errno == EIO &&								\
> -	    __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)KVM_CAP_USER_MEMORY) < 0) {	\
> -		TEST_ASSERT(errno == EIO, "KVM killed the VM, should return -EIO");	\
> -		TEST_FAIL("KVM killed/bugged the VM, check the kernel log for clues");	\
> -	}										\
> -	errno = __errno;								\
> -	TEST_ASSERT(cond, __KVM_IOCTL_ERROR(name, ret));				\
> -} while (0)
> -
> -#define TEST_ASSERT_VM_VCPU_IOCTL(cond, cmd, ret, vm)		\
> -	__TEST_ASSERT_VM_VCPU_IOCTL(cond, #cmd, ret, vm)
> -
> -#define vm_ioctl(vm, cmd, arg)					\
> -({								\
> -	int ret = __vm_ioctl(vm, cmd, arg);			\
> -								\
> -	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm);		\
> -})
> -
> -static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
> -
> -#define __vcpu_ioctl(vcpu, cmd, arg)				\
> -({								\
> -	static_assert_is_vcpu(vcpu);				\
> -	kvm_do_ioctl((vcpu)->fd, cmd, arg);			\
> -})
> -
> -#define vcpu_ioctl(vcpu, cmd, arg)				\
> -({								\
> -	int ret = __vcpu_ioctl(vcpu, cmd, arg);			\
> -								\
> -	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm);	\
> -})
> -
> -/*
> - * Looks up and returns the value corresponding to the capability
> - * (KVM_CAP_*) given by cap.
> - */
> -static inline int vm_check_cap(struct kvm_vm *vm, long cap)
> -{
> -	int ret =  __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)cap);
> -
> -	TEST_ASSERT_VM_VCPU_IOCTL(ret >= 0, KVM_CHECK_EXTENSION, ret, vm);
> -	return ret;
> -}
> -
> -static inline int __vm_enable_cap(struct kvm_vm *vm, uint32_t cap, uint64_t arg0)
> -{
> -	struct kvm_enable_cap enable_cap = { .cap = cap, .args = { arg0 } };
> -
> -	return __vm_ioctl(vm, KVM_ENABLE_CAP, &enable_cap);
> -}
> -static inline void vm_enable_cap(struct kvm_vm *vm, uint32_t cap, uint64_t arg0)
> -{
> -	struct kvm_enable_cap enable_cap = { .cap = cap, .args = { arg0 } };
> -
> -	vm_ioctl(vm, KVM_ENABLE_CAP, &enable_cap);
> -}
> -
> -static inline void vm_set_memory_attributes(struct kvm_vm *vm, uint64_t gpa,
> -					    uint64_t size, uint64_t attributes)
> -{
> -	struct kvm_memory_attributes attr = {
> -		.attributes = attributes,
> -		.address = gpa,
> -		.size = size,
> -		.flags = 0,
> -	};
> -
> -	/*
> -	 * KVM_SET_MEMORY_ATTRIBUTES overwrites _all_ attributes.  These flows
> -	 * need significant enhancements to support multiple attributes.
> -	 */
> -	TEST_ASSERT(!attributes || attributes == KVM_MEMORY_ATTRIBUTE_PRIVATE,
> -		    "Update me to support multiple attributes!");
> -
> -	vm_ioctl(vm, KVM_SET_MEMORY_ATTRIBUTES, &attr);
> -}
> -
> -
> -static inline void vm_mem_set_private(struct kvm_vm *vm, uint64_t gpa,
> -				      uint64_t size)
> -{
> -	vm_set_memory_attributes(vm, gpa, size, KVM_MEMORY_ATTRIBUTE_PRIVATE);
> -}
> -
> -static inline void vm_mem_set_shared(struct kvm_vm *vm, uint64_t gpa,
> -				     uint64_t size)
> -{
> -	vm_set_memory_attributes(vm, gpa, size, 0);
> -}
> -
> -void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t gpa, uint64_t size,
> -			    bool punch_hole);
> -
> -static inline void vm_guest_mem_punch_hole(struct kvm_vm *vm, uint64_t gpa,
> -					   uint64_t size)
> -{
> -	vm_guest_mem_fallocate(vm, gpa, size, true);
> -}
> -
> -static inline void vm_guest_mem_allocate(struct kvm_vm *vm, uint64_t gpa,
> -					 uint64_t size)
> -{
> -	vm_guest_mem_fallocate(vm, gpa, size, false);
> -}
> -
> -void vm_enable_dirty_ring(struct kvm_vm *vm, uint32_t ring_size);
> -const char *vm_guest_mode_string(uint32_t i);
> -
> -void kvm_vm_free(struct kvm_vm *vmp);
> -void kvm_vm_restart(struct kvm_vm *vmp);
> -void kvm_vm_release(struct kvm_vm *vmp);
> -int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, const vm_vaddr_t gva,
> -		       size_t len);
> -void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename);
> -int kvm_memfd_alloc(size_t size, bool hugepages);
> -
> -void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
> -
> -static inline void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
> -{
> -	struct kvm_dirty_log args = { .dirty_bitmap = log, .slot = slot };
> -
> -	vm_ioctl(vm, KVM_GET_DIRTY_LOG, &args);
> -}
> -
> -static inline void kvm_vm_clear_dirty_log(struct kvm_vm *vm, int slot, void *log,
> -					  uint64_t first_page, uint32_t num_pages)
> -{
> -	struct kvm_clear_dirty_log args = {
> -		.dirty_bitmap = log,
> -		.slot = slot,
> -		.first_page = first_page,
> -		.num_pages = num_pages
> -	};
> -
> -	vm_ioctl(vm, KVM_CLEAR_DIRTY_LOG, &args);
> -}
> -
> -static inline uint32_t kvm_vm_reset_dirty_ring(struct kvm_vm *vm)
> -{
> -	return __vm_ioctl(vm, KVM_RESET_DIRTY_RINGS, NULL);
> -}
> -
> -static inline int vm_get_stats_fd(struct kvm_vm *vm)
> -{
> -	int fd = __vm_ioctl(vm, KVM_GET_STATS_FD, NULL);
> -
> -	TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_GET_STATS_FD, fd, vm);
> -	return fd;
> -}
> -
> -static inline void read_stats_header(int stats_fd, struct kvm_stats_header *header)
> -{
> -	ssize_t ret;
> -
> -	ret = pread(stats_fd, header, sizeof(*header), 0);
> -	TEST_ASSERT(ret == sizeof(*header),
> -		    "Failed to read '%lu' header bytes, ret = '%ld'",
> -		    sizeof(*header), ret);
> -}
> -
> -struct kvm_stats_desc *read_stats_descriptors(int stats_fd,
> -					      struct kvm_stats_header *header);
> -
> -static inline ssize_t get_stats_descriptor_size(struct kvm_stats_header *header)
> -{
> -	 /*
> -	  * The base size of the descriptor is defined by KVM's ABI, but the
> -	  * size of the name field is variable, as far as KVM's ABI is
> -	  * concerned. For a given instance of KVM, the name field is the same
> -	  * size for all stats and is provided in the overall stats header.
> -	  */
> -	return sizeof(struct kvm_stats_desc) + header->name_size;
> -}
> -
> -static inline struct kvm_stats_desc *get_stats_descriptor(struct kvm_stats_desc *stats,
> -							  int index,
> -							  struct kvm_stats_header *header)
> -{
> -	/*
> -	 * Note, size_desc includes the size of the name field, which is
> -	 * variable. i.e. this is NOT equivalent to &stats_desc[i].
> -	 */
> -	return (void *)stats + index * get_stats_descriptor_size(header);
> -}
> -
> -void read_stat_data(int stats_fd, struct kvm_stats_header *header,
> -		    struct kvm_stats_desc *desc, uint64_t *data,
> -		    size_t max_elements);
> -
> -void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *data,
> -		   size_t max_elements);
> -
> -static inline uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name)
> -{
> -	uint64_t data;
> -
> -	__vm_get_stat(vm, stat_name, &data, 1);
> -	return data;
> -}
> -
> -void vm_create_irqchip(struct kvm_vm *vm);
> -
> -static inline int __vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size,
> -					uint64_t flags)
> -{
> -	struct kvm_create_guest_memfd guest_memfd = {
> -		.size = size,
> -		.flags = flags,
> -	};
> -
> -	return __vm_ioctl(vm, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
> -}
> -
> -static inline int vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size,
> -					uint64_t flags)
> -{
> -	int fd = __vm_create_guest_memfd(vm, size, flags);
> -
> -	TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_GUEST_MEMFD, fd));
> -	return fd;
> -}
> -
> -void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> -			       uint64_t gpa, uint64_t size, void *hva);
> -int __vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> -				uint64_t gpa, uint64_t size, void *hva);
> -void vm_set_user_memory_region2(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> -				uint64_t gpa, uint64_t size, void *hva,
> -				uint32_t guest_memfd, uint64_t guest_memfd_offset);
> -int __vm_set_user_memory_region2(struct kvm_vm *vm, uint32_t slot, uint32_t flags,
> -				 uint64_t gpa, uint64_t size, void *hva,
> -				 uint32_t guest_memfd, uint64_t guest_memfd_offset);
> -
> -void vm_userspace_mem_region_add(struct kvm_vm *vm,
> -	enum vm_mem_backing_src_type src_type,
> -	uint64_t guest_paddr, uint32_t slot, uint64_t npages,
> -	uint32_t flags);
> -void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
> -		uint64_t guest_paddr, uint32_t slot, uint64_t npages,
> -		uint32_t flags, int guest_memfd_fd, uint64_t guest_memfd_offset);
> -
> -#ifndef vm_arch_has_protected_memory
> -static inline bool vm_arch_has_protected_memory(struct kvm_vm *vm)
> -{
> -	return false;
> -}
> -#endif
> -
> -void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
> -void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa);
> -void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot);
> -struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id);
> -void vm_populate_vaddr_bitmap(struct kvm_vm *vm);
> -vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
> -vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
> -vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
> -			    enum kvm_mem_region_type type);
> -vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz,
> -				 vm_vaddr_t vaddr_min,
> -				 enum kvm_mem_region_type type);
> -vm_vaddr_t vm_vaddr_alloc_pages(struct kvm_vm *vm, int nr_pages);
> -vm_vaddr_t __vm_vaddr_alloc_page(struct kvm_vm *vm,
> -				 enum kvm_mem_region_type type);
> -vm_vaddr_t vm_vaddr_alloc_page(struct kvm_vm *vm);
> -
> -void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
> -	      unsigned int npages);
> -void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa);
> -void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva);
> -vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva);
> -void *addr_gpa2alias(struct kvm_vm *vm, vm_paddr_t gpa);
> -
> -
> -static inline vm_paddr_t vm_untag_gpa(struct kvm_vm *vm, vm_paddr_t gpa)
> -{
> -	return gpa & ~vm->gpa_tag_mask;
> -}
> -
> -void vcpu_run(struct kvm_vcpu *vcpu);
> -int _vcpu_run(struct kvm_vcpu *vcpu);
> -
> -static inline int __vcpu_run(struct kvm_vcpu *vcpu)
> -{
> -	return __vcpu_ioctl(vcpu, KVM_RUN, NULL);
> -}
> -
> -void vcpu_run_complete_io(struct kvm_vcpu *vcpu);
> -struct kvm_reg_list *vcpu_get_reg_list(struct kvm_vcpu *vcpu);
> -
> -static inline void vcpu_enable_cap(struct kvm_vcpu *vcpu, uint32_t cap,
> -				   uint64_t arg0)
> -{
> -	struct kvm_enable_cap enable_cap = { .cap = cap, .args = { arg0 } };
> -
> -	vcpu_ioctl(vcpu, KVM_ENABLE_CAP, &enable_cap);
> -}
> -
> -static inline void vcpu_guest_debug_set(struct kvm_vcpu *vcpu,
> -					struct kvm_guest_debug *debug)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_GUEST_DEBUG, debug);
> -}
> -
> -static inline void vcpu_mp_state_get(struct kvm_vcpu *vcpu,
> -				     struct kvm_mp_state *mp_state)
> -{
> -	vcpu_ioctl(vcpu, KVM_GET_MP_STATE, mp_state);
> -}
> -static inline void vcpu_mp_state_set(struct kvm_vcpu *vcpu,
> -				     struct kvm_mp_state *mp_state)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_MP_STATE, mp_state);
> -}
> -
> -static inline void vcpu_regs_get(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
> -{
> -	vcpu_ioctl(vcpu, KVM_GET_REGS, regs);
> -}
> -
> -static inline void vcpu_regs_set(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_REGS, regs);
> -}
> -static inline void vcpu_sregs_get(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
> -{
> -	vcpu_ioctl(vcpu, KVM_GET_SREGS, sregs);
> -
> -}
> -static inline void vcpu_sregs_set(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_SREGS, sregs);
> -}
> -static inline int _vcpu_sregs_set(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
> -{
> -	return __vcpu_ioctl(vcpu, KVM_SET_SREGS, sregs);
> -}
> -static inline void vcpu_fpu_get(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
> -{
> -	vcpu_ioctl(vcpu, KVM_GET_FPU, fpu);
> -}
> -static inline void vcpu_fpu_set(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_FPU, fpu);
> -}
> -
> -static inline int __vcpu_get_reg(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
> -{
> -	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)addr };
> -
> -	return __vcpu_ioctl(vcpu, KVM_GET_ONE_REG, &reg);
> -}
> -static inline int __vcpu_set_reg(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
> -{
> -	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)&val };
> -
> -	return __vcpu_ioctl(vcpu, KVM_SET_ONE_REG, &reg);
> -}
> -static inline void vcpu_get_reg(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
> -{
> -	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)addr };
> -
> -	vcpu_ioctl(vcpu, KVM_GET_ONE_REG, &reg);
> -}
> -static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
> -{
> -	struct kvm_one_reg reg = { .id = id, .addr = (uint64_t)&val };
> -
> -	vcpu_ioctl(vcpu, KVM_SET_ONE_REG, &reg);
> -}
> -
> -#ifdef __KVM_HAVE_VCPU_EVENTS
> -static inline void vcpu_events_get(struct kvm_vcpu *vcpu,
> -				   struct kvm_vcpu_events *events)
> -{
> -	vcpu_ioctl(vcpu, KVM_GET_VCPU_EVENTS, events);
> -}
> -static inline void vcpu_events_set(struct kvm_vcpu *vcpu,
> -				   struct kvm_vcpu_events *events)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_VCPU_EVENTS, events);
> -}
> -#endif
> -#ifdef __x86_64__
> -static inline void vcpu_nested_state_get(struct kvm_vcpu *vcpu,
> -					 struct kvm_nested_state *state)
> -{
> -	vcpu_ioctl(vcpu, KVM_GET_NESTED_STATE, state);
> -}
> -static inline int __vcpu_nested_state_set(struct kvm_vcpu *vcpu,
> -					  struct kvm_nested_state *state)
> -{
> -	return __vcpu_ioctl(vcpu, KVM_SET_NESTED_STATE, state);
> -}
> -
> -static inline void vcpu_nested_state_set(struct kvm_vcpu *vcpu,
> -					 struct kvm_nested_state *state)
> -{
> -	vcpu_ioctl(vcpu, KVM_SET_NESTED_STATE, state);
> -}
> -#endif
> -static inline int vcpu_get_stats_fd(struct kvm_vcpu *vcpu)
> -{
> -	int fd = __vcpu_ioctl(vcpu, KVM_GET_STATS_FD, NULL);
> -
> -	TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_CHECK_EXTENSION, fd, vcpu->vm);
> -	return fd;
> -}
> -
> -int __kvm_has_device_attr(int dev_fd, uint32_t group, uint64_t attr);
> -
> -static inline void kvm_has_device_attr(int dev_fd, uint32_t group, uint64_t attr)
> -{
> -	int ret = __kvm_has_device_attr(dev_fd, group, attr);
> -
> -	TEST_ASSERT(!ret, "KVM_HAS_DEVICE_ATTR failed, rc: %i errno: %i", ret, errno);
> -}
> -
> -int __kvm_device_attr_get(int dev_fd, uint32_t group, uint64_t attr, void *val);
> -
> -static inline void kvm_device_attr_get(int dev_fd, uint32_t group,
> -				       uint64_t attr, void *val)
> -{
> -	int ret = __kvm_device_attr_get(dev_fd, group, attr, val);
> -
> -	TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_GET_DEVICE_ATTR, ret));
> -}
> -
> -int __kvm_device_attr_set(int dev_fd, uint32_t group, uint64_t attr, void *val);
> -
> -static inline void kvm_device_attr_set(int dev_fd, uint32_t group,
> -				       uint64_t attr, void *val)
> -{
> -	int ret = __kvm_device_attr_set(dev_fd, group, attr, val);
> -
> -	TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_SET_DEVICE_ATTR, ret));
> -}
> -
> -static inline int __vcpu_has_device_attr(struct kvm_vcpu *vcpu, uint32_t group,
> -					 uint64_t attr)
> -{
> -	return __kvm_has_device_attr(vcpu->fd, group, attr);
> -}
> -
> -static inline void vcpu_has_device_attr(struct kvm_vcpu *vcpu, uint32_t group,
> -					uint64_t attr)
> -{
> -	kvm_has_device_attr(vcpu->fd, group, attr);
> -}
> -
> -static inline int __vcpu_device_attr_get(struct kvm_vcpu *vcpu, uint32_t group,
> -					 uint64_t attr, void *val)
> -{
> -	return __kvm_device_attr_get(vcpu->fd, group, attr, val);
> -}
> -
> -static inline void vcpu_device_attr_get(struct kvm_vcpu *vcpu, uint32_t group,
> -					uint64_t attr, void *val)
> -{
> -	kvm_device_attr_get(vcpu->fd, group, attr, val);
> -}
> -
> -static inline int __vcpu_device_attr_set(struct kvm_vcpu *vcpu, uint32_t group,
> -					 uint64_t attr, void *val)
> -{
> -	return __kvm_device_attr_set(vcpu->fd, group, attr, val);
> -}
> -
> -static inline void vcpu_device_attr_set(struct kvm_vcpu *vcpu, uint32_t group,
> -					uint64_t attr, void *val)
> -{
> -	kvm_device_attr_set(vcpu->fd, group, attr, val);
> -}
> -
> -int __kvm_test_create_device(struct kvm_vm *vm, uint64_t type);
> -int __kvm_create_device(struct kvm_vm *vm, uint64_t type);
> -
> -static inline int kvm_create_device(struct kvm_vm *vm, uint64_t type)
> -{
> -	int fd = __kvm_create_device(vm, type);
> -
> -	TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_DEVICE, fd));
> -	return fd;
> -}
> -
> -void *vcpu_map_dirty_ring(struct kvm_vcpu *vcpu);
> -
> -/*
> - * VM VCPU Args Set
> - *
> - * Input Args:
> - *   vm - Virtual Machine
> - *   num - number of arguments
> - *   ... - arguments, each of type uint64_t
> - *
> - * Output Args: None
> - *
> - * Return: None
> - *
> - * Sets the first @num input parameters for the function at @vcpu's entry point,
> - * per the C calling convention of the architecture, to the values given as
> - * variable args. Each of the variable args is expected to be of type uint64_t.
> - * The maximum @num can be is specific to the architecture.
> - */
> -void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...);
> -
> -void kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level);
> -int _kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level);
> -
> -#define KVM_MAX_IRQ_ROUTES		4096
> -
> -struct kvm_irq_routing *kvm_gsi_routing_create(void);
> -void kvm_gsi_routing_irqchip_add(struct kvm_irq_routing *routing,
> -		uint32_t gsi, uint32_t pin);
> -int _kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
> -void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
> -
> -const char *exit_reason_str(unsigned int exit_reason);
> -
> -vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
> -			     uint32_t memslot);
> -vm_paddr_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
> -				vm_paddr_t paddr_min, uint32_t memslot,
> -				bool protected);
> -vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm);
> -
> -static inline vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
> -					    vm_paddr_t paddr_min, uint32_t memslot)
> -{
> -	/*
> -	 * By default, allocate memory as protected for VMs that support
> -	 * protected memory, as the majority of memory for such VMs is
> -	 * protected, i.e. using shared memory is effectively opt-in.
> -	 */
> -	return __vm_phy_pages_alloc(vm, num, paddr_min, memslot,
> -				    vm_arch_has_protected_memory(vm));
> -}
> -
> -/*
> - * ____vm_create() does KVM_CREATE_VM and little else.  __vm_create() also
> - * loads the test binary into guest memory and creates an IRQ chip (x86 only).
> - * __vm_create() does NOT create vCPUs, @nr_runnable_vcpus is used purely to
> - * calculate the amount of memory needed for per-vCPU data, e.g. stacks.
> - */
> -struct kvm_vm *____vm_create(struct vm_shape shape);
> -struct kvm_vm *__vm_create(struct vm_shape shape, uint32_t nr_runnable_vcpus,
> -			   uint64_t nr_extra_pages);
> -
> -static inline struct kvm_vm *vm_create_barebones(void)
> -{
> -	return ____vm_create(VM_SHAPE_DEFAULT);
> -}
> -
> -#ifdef __x86_64__
> -static inline struct kvm_vm *vm_create_barebones_protected_vm(void)
> -{
> -	const struct vm_shape shape = {
> -		.mode = VM_MODE_DEFAULT,
> -		.type = KVM_X86_SW_PROTECTED_VM,
> -	};
> -
> -	return ____vm_create(shape);
> -}
> -#endif
> -
> -static inline struct kvm_vm *vm_create(uint32_t nr_runnable_vcpus)
> -{
> -	return __vm_create(VM_SHAPE_DEFAULT, nr_runnable_vcpus, 0);
> -}
> -
> -struct kvm_vm *__vm_create_with_vcpus(struct vm_shape shape, uint32_t nr_vcpus,
> -				      uint64_t extra_mem_pages,
> -				      void *guest_code, struct kvm_vcpu *vcpus[]);
> -
> -static inline struct kvm_vm *vm_create_with_vcpus(uint32_t nr_vcpus,
> -						  void *guest_code,
> -						  struct kvm_vcpu *vcpus[])
> -{
> -	return __vm_create_with_vcpus(VM_SHAPE_DEFAULT, nr_vcpus, 0,
> -				      guest_code, vcpus);
> -}
> -
> -
> -struct kvm_vm *__vm_create_shape_with_one_vcpu(struct vm_shape shape,
> -					       struct kvm_vcpu **vcpu,
> -					       uint64_t extra_mem_pages,
> -					       void *guest_code);
> -
> -/*
> - * Create a VM with a single vCPU with reasonable defaults and @extra_mem_pages
> - * additional pages of guest memory.  Returns the VM and vCPU (via out param).
> - */
> -static inline struct kvm_vm *__vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
> -						       uint64_t extra_mem_pages,
> -						       void *guest_code)
> -{
> -	return __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, vcpu,
> -					       extra_mem_pages, guest_code);
> -}
> -
> -static inline struct kvm_vm *vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
> -						     void *guest_code)
> -{
> -	return __vm_create_with_one_vcpu(vcpu, 0, guest_code);
> -}
> -
> -static inline struct kvm_vm *vm_create_shape_with_one_vcpu(struct vm_shape shape,
> -							   struct kvm_vcpu **vcpu,
> -							   void *guest_code)
> -{
> -	return __vm_create_shape_with_one_vcpu(shape, vcpu, 0, guest_code);
> -}
> -
> -struct kvm_vcpu *vm_recreate_with_one_vcpu(struct kvm_vm *vm);
> -
> -void kvm_pin_this_task_to_pcpu(uint32_t pcpu);
> -void kvm_print_vcpu_pinning_help(void);
> -void kvm_parse_vcpu_pinning(const char *pcpus_string, uint32_t vcpu_to_pcpu[],
> -			    int nr_vcpus);
> -
> -unsigned long vm_compute_max_gfn(struct kvm_vm *vm);
> -unsigned int vm_calc_num_guest_pages(enum vm_guest_mode mode, size_t size);
> -unsigned int vm_num_host_pages(enum vm_guest_mode mode, unsigned int num_guest_pages);
> -unsigned int vm_num_guest_pages(enum vm_guest_mode mode, unsigned int num_host_pages);
> -static inline unsigned int
> -vm_adjust_num_guest_pages(enum vm_guest_mode mode, unsigned int num_guest_pages)
> -{
> -	unsigned int n;
> -	n = vm_num_guest_pages(mode, vm_num_host_pages(mode, num_guest_pages));
> -#ifdef __s390x__
> -	/* s390 requires 1M aligned guest sizes */
> -	n = (n + 255) & ~255;
> -#endif
> -	return n;
> -}
> -
> -#define sync_global_to_guest(vm, g) ({				\
> -	typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g));	\
> -	memcpy(_p, &(g), sizeof(g));				\
> -})
> -
> -#define sync_global_from_guest(vm, g) ({			\
> -	typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g));	\
> -	memcpy(&(g), _p, sizeof(g));				\
> -})
> -
> -/*
> - * Write a global value, but only in the VM's (guest's) domain.  Primarily used
> - * for "globals" that hold per-VM values (VMs always duplicate code and global
> - * data into their own region of physical memory), but can be used anytime it's
> - * undesirable to change the host's copy of the global.
> - */
> -#define write_guest_global(vm, g, val) ({			\
> -	typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g));	\
> -	typeof(g) _val = val;					\
> -								\
> -	memcpy(_p, &(_val), sizeof(g));				\
> -})
> -
> -void assert_on_unhandled_exception(struct kvm_vcpu *vcpu);
> -
> -void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu,
> -		    uint8_t indent);
> -
> -static inline void vcpu_dump(FILE *stream, struct kvm_vcpu *vcpu,
> -			     uint8_t indent)
> -{
> -	vcpu_arch_dump(stream, vcpu, indent);
> -}
> -
> -/*
> - * Adds a vCPU with reasonable defaults (e.g. a stack)
> - *
> - * Input Args:
> - *   vm - Virtual Machine
> - *   vcpu_id - The id of the VCPU to add to the VM.
> - */
> -struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id);
> -void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code);
> -
> -static inline struct kvm_vcpu *vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
> -					   void *guest_code)
> -{
> -	struct kvm_vcpu *vcpu = vm_arch_vcpu_add(vm, vcpu_id);
> -
> -	vcpu_arch_set_entry_point(vcpu, guest_code);
> -
> -	return vcpu;
> -}
> -
> -/* Re-create a vCPU after restarting a VM, e.g. for state save/restore tests. */
> -struct kvm_vcpu *vm_arch_vcpu_recreate(struct kvm_vm *vm, uint32_t vcpu_id);
> -
> -static inline struct kvm_vcpu *vm_vcpu_recreate(struct kvm_vm *vm,
> -						uint32_t vcpu_id)
> -{
> -	return vm_arch_vcpu_recreate(vm, vcpu_id);
> -}
> -
> -void vcpu_arch_free(struct kvm_vcpu *vcpu);
> -
> -void virt_arch_pgd_alloc(struct kvm_vm *vm);
> -
> -static inline void virt_pgd_alloc(struct kvm_vm *vm)
> -{
> -	virt_arch_pgd_alloc(vm);
> -}
> -
> -/*
> - * VM Virtual Page Map
> - *
> - * Input Args:
> - *   vm - Virtual Machine
> - *   vaddr - VM Virtual Address
> - *   paddr - VM Physical Address
> - *   memslot - Memory region slot for new virtual translation tables
> - *
> - * Output Args: None
> - *
> - * Return: None
> - *
> - * Within @vm, creates a virtual translation for the page starting
> - * at @vaddr to the page starting at @paddr.
> - */
> -void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr);
> -
> -static inline void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
> -{
> -	virt_arch_pg_map(vm, vaddr, paddr);
> -}
> -
> -
> -/*
> - * Address Guest Virtual to Guest Physical
> - *
> - * Input Args:
> - *   vm - Virtual Machine
> - *   gva - VM virtual address
> - *
> - * Output Args: None
> - *
> - * Return:
> - *   Equivalent VM physical address
> - *
> - * Returns the VM physical address of the translated VM virtual
> - * address given by @gva.
> - */
> -vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva);
> -
> -static inline vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
> -{
> -	return addr_arch_gva2gpa(vm, gva);
> -}
> -
> -/*
> - * Virtual Translation Tables Dump
> - *
> - * Input Args:
> - *   stream - Output FILE stream
> - *   vm     - Virtual Machine
> - *   indent - Left margin indent amount
> - *
> - * Output Args: None
> - *
> - * Return: None
> - *
> - * Dumps to the FILE stream given by @stream, the contents of all the
> - * virtual translation tables for the VM given by @vm.
> - */
> -void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
> -
> -static inline void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
> -{
> -	virt_arch_dump(stream, vm, indent);
> -}
> -
> -
> -static inline int __vm_disable_nx_huge_pages(struct kvm_vm *vm)
> -{
> -	return __vm_enable_cap(vm, KVM_CAP_VM_DISABLE_NX_HUGE_PAGES, 0);
> -}
> -
> -/*
> - * Arch hook that is invoked via a constructor, i.e. before exeucting main(),
> - * to allow for arch-specific setup that is common to all tests, e.g. computing
> - * the default guest "mode".
> - */
> -void kvm_selftest_arch_init(void);
> -
> -void kvm_arch_vm_post_create(struct kvm_vm *vm);
> -
> -bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr);
> -
> -uint32_t guest_get_vcpuid(void);
> -
> -#endif /* SELFTEST_KVM_UTIL_BASE_H */
> diff --git a/tools/testing/selftests/kvm/include/s390x/ucall.h b/tools/testing/selftests/kvm/include/s390x/ucall.h
> index b231bf2e49d6..8035a872a351 100644
> --- a/tools/testing/selftests/kvm/include/s390x/ucall.h
> +++ b/tools/testing/selftests/kvm/include/s390x/ucall.h
> @@ -2,7 +2,7 @@
>  #ifndef SELFTEST_KVM_UCALL_H
>  #define SELFTEST_KVM_UCALL_H
>  
> -#include "kvm_util_base.h"
> +#include "kvm_util.h"
>  
>  #define UCALL_EXIT_REASON       KVM_EXIT_S390_SIEIC
>  
> diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
> index 3bd03b088dda..d6ffe03c9d0b 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/processor.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
> @@ -18,7 +18,8 @@
>  #include <linux/kvm_para.h>
>  #include <linux/stringify.h>
>  
> -#include "../kvm_util.h"
> +#include "kvm_util.h"
> +#include "ucall_common.h"
>  
>  extern bool host_cpu_is_intel;
>  extern bool host_cpu_is_amd;
> diff --git a/tools/testing/selftests/kvm/include/x86_64/ucall.h b/tools/testing/selftests/kvm/include/x86_64/ucall.h
> index 06b244bd06ee..d3825dcc3cd9 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/ucall.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/ucall.h
> @@ -2,7 +2,7 @@
>  #ifndef SELFTEST_KVM_UCALL_H
>  #define SELFTEST_KVM_UCALL_H
>  
> -#include "kvm_util_base.h"
> +#include "kvm_util.h"
>  
>  #define UCALL_EXIT_REASON       KVM_EXIT_IO
>  
> diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/testing/selftests/kvm/kvm_page_table_test.c
> index e0ba97ac1c56..e16ef18bcfc0 100644
> --- a/tools/testing/selftests/kvm/kvm_page_table_test.c
> +++ b/tools/testing/selftests/kvm/kvm_page_table_test.c
> @@ -21,6 +21,7 @@
>  #include "kvm_util.h"
>  #include "processor.h"
>  #include "guest_modes.h"
> +#include "ucall_common.h"
>  
>  #define TEST_MEM_SLOT_INDEX             1
>  
> diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
> index a9eb17295be4..0ac7cc89f38c 100644
> --- a/tools/testing/selftests/kvm/lib/aarch64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
> @@ -11,6 +11,8 @@
>  #include "guest_modes.h"
>  #include "kvm_util.h"
>  #include "processor.h"
> +#include "ucall_common.h"
> +
>  #include <linux/bitfield.h>
>  #include <linux/sizes.h>
>  
> diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
> index b2262b5fad9e..cec39b52b90d 100644
> --- a/tools/testing/selftests/kvm/lib/kvm_util.c
> +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
> @@ -9,6 +9,7 @@
>  #include "test_util.h"
>  #include "kvm_util.h"
>  #include "processor.h"
> +#include "ucall_common.h"
>  
>  #include <assert.h>
>  #include <sched.h>
> diff --git a/tools/testing/selftests/kvm/lib/memstress.c b/tools/testing/selftests/kvm/lib/memstress.c
> index cf2c73971308..96432ad9efa6 100644
> --- a/tools/testing/selftests/kvm/lib/memstress.c
> +++ b/tools/testing/selftests/kvm/lib/memstress.c
> @@ -10,6 +10,7 @@
>  #include "kvm_util.h"
>  #include "memstress.h"
>  #include "processor.h"
> +#include "ucall_common.h"
>  
>  struct memstress_args memstress_args;
>  
> diff --git a/tools/testing/selftests/kvm/lib/riscv/processor.c b/tools/testing/selftests/kvm/lib/riscv/processor.c
> index e8211f5d6863..79b67e2627cb 100644
> --- a/tools/testing/selftests/kvm/lib/riscv/processor.c
> +++ b/tools/testing/selftests/kvm/lib/riscv/processor.c
> @@ -10,6 +10,7 @@
>  
>  #include "kvm_util.h"
>  #include "processor.h"
> +#include "ucall_common.h"
>  
>  #define DEFAULT_RISCV_GUEST_STACK_VADDR_MIN	0xac0000
>  
> diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c
> index f5af65a41c29..42151e571953 100644
> --- a/tools/testing/selftests/kvm/lib/ucall_common.c
> +++ b/tools/testing/selftests/kvm/lib/ucall_common.c
> @@ -1,9 +1,12 @@
>  // SPDX-License-Identifier: GPL-2.0-only
> -#include "kvm_util.h"
>  #include "linux/types.h"
>  #include "linux/bitmap.h"
>  #include "linux/atomic.h"
>  
> +#include "kvm_util.h"
> +#include "ucall_common.h"
> +
> +
>  #define GUEST_UCALL_FAILED -1
>  
>  struct ucall_header {
> diff --git a/tools/testing/selftests/kvm/riscv/arch_timer.c b/tools/testing/selftests/kvm/riscv/arch_timer.c
> index e22848f747c0..d6375af0b23e 100644
> --- a/tools/testing/selftests/kvm/riscv/arch_timer.c
> +++ b/tools/testing/selftests/kvm/riscv/arch_timer.c
> @@ -14,6 +14,7 @@
>  #include "kvm_util.h"
>  #include "processor.h"
>  #include "timer_test.h"
> +#include "ucall_common.h"
>  
>  static int timer_irq = IRQ_S_TIMER;
>  
> diff --git a/tools/testing/selftests/kvm/rseq_test.c b/tools/testing/selftests/kvm/rseq_test.c
> index 28f97fb52044..d81f9b9c5809 100644
> --- a/tools/testing/selftests/kvm/rseq_test.c
> +++ b/tools/testing/selftests/kvm/rseq_test.c
> @@ -19,6 +19,7 @@
>  #include "kvm_util.h"
>  #include "processor.h"
>  #include "test_util.h"
> +#include "ucall_common.h"
>  
>  #include "../rseq/rseq.c"
>  
> diff --git a/tools/testing/selftests/kvm/s390x/cmma_test.c b/tools/testing/selftests/kvm/s390x/cmma_test.c
> index 626a2b8a2037..9e0033906638 100644
> --- a/tools/testing/selftests/kvm/s390x/cmma_test.c
> +++ b/tools/testing/selftests/kvm/s390x/cmma_test.c
> @@ -18,6 +18,7 @@
>  #include "test_util.h"
>  #include "kvm_util.h"
>  #include "kselftest.h"
> +#include "ucall_common.h"
>  
>  #define MAIN_PAGE_COUNT 512
>  
> diff --git a/tools/testing/selftests/kvm/s390x/memop.c b/tools/testing/selftests/kvm/s390x/memop.c
> index bb3ca9a5d731..9b31693be1cb 100644
> --- a/tools/testing/selftests/kvm/s390x/memop.c
> +++ b/tools/testing/selftests/kvm/s390x/memop.c
> @@ -15,6 +15,7 @@
>  #include "test_util.h"
>  #include "kvm_util.h"
>  #include "kselftest.h"
> +#include "ucall_common.h"
>  
>  enum mop_target {
>  	LOGICAL,
> diff --git a/tools/testing/selftests/kvm/s390x/tprot.c b/tools/testing/selftests/kvm/s390x/tprot.c
> index c73f948c9b63..7a742a673b7c 100644
> --- a/tools/testing/selftests/kvm/s390x/tprot.c
> +++ b/tools/testing/selftests/kvm/s390x/tprot.c
> @@ -8,6 +8,7 @@
>  #include "test_util.h"
>  #include "kvm_util.h"
>  #include "kselftest.h"
> +#include "ucall_common.h"
>  
>  #define PAGE_SHIFT 12
>  #define PAGE_SIZE (1 << PAGE_SHIFT)
> diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
> index bae0c5026f82..4c669d0cb8c0 100644
> --- a/tools/testing/selftests/kvm/steal_time.c
> +++ b/tools/testing/selftests/kvm/steal_time.c
> @@ -18,6 +18,7 @@
>  #include "test_util.h"
>  #include "kvm_util.h"
>  #include "processor.h"
> +#include "ucall_common.h"
>  
>  #define NR_VCPUS		4
>  #define ST_GPA_BASE		(1 << 30)
> diff --git a/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c b/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c
> index ee3b384b991c..2929c067c207 100644
> --- a/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/dirty_log_page_splitting_test.c
> @@ -17,6 +17,7 @@
>  #include "test_util.h"
>  #include "memstress.h"
>  #include "guest_modes.h"
> +#include "ucall_common.h"
>  
>  #define VCPUS		2
>  #define SLOTS		2
> diff --git a/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c b/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c
> index 6c2e5e0ceb1f..fbac69d49b39 100644
> --- a/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/exit_on_emulation_failure_test.c
> @@ -8,8 +8,8 @@
>  #define _GNU_SOURCE /* for program_invocation_short_name */
>  
>  #include "flds_emulation.h"
> -
>  #include "test_util.h"
> +#include "ucall_common.h"
>  
>  #define MMIO_GPA	0x700000000
>  #define MMIO_GVA	MMIO_GPA
> diff --git a/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c b/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
> index dcbb3c29fb8e..bc9be20f9600 100644
> --- a/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
> @@ -24,7 +24,6 @@
>  #include <string.h>
>  #include <time.h>
>  
> -#include "kvm_util_base.h"
>  #include "kvm_util.h"
>  #include "mce.h"
>  #include "processor.h"
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Happy that this got simplified!

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 14/18] KVM: selftests: Fold x86's descriptor tables helpers into vcpu_init_sregs()
From: Ackerley Tng @ 2024-03-28  2:50 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-15-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Now that the per-VM, on-demand allocation logic in kvm_setup_gdt() and
> vcpu_init_descriptor_tables() is gone, fold them into vcpu_init_sregs().
>
> Note, both kvm_setup_gdt() and vcpu_init_descriptor_tables() configured the
> GDT, which is why it looks like kvm_setup_gdt() disappears.
>
> Opportunistically delete the pointless zeroing of the IDT limit (it was
> being unconditionally overwritten by vcpu_init_descriptor_tables()).
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../selftests/kvm/lib/x86_64/processor.c      | 32 ++++---------------
>  1 file changed, 6 insertions(+), 26 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index 561c0aa93608..5cf845975f66 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -516,12 +516,6 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
>  	return vm_untag_gpa(vm, PTE_GET_PA(*pte)) | (gva & ~HUGEPAGE_MASK(level));
>  }
>  
> -static void kvm_setup_gdt(struct kvm_vm *vm, struct kvm_dtable *dt)
> -{
> -	dt->base = vm->arch.gdt;
> -	dt->limit = getpagesize() - 1;
> -}
> -
>  static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
>  				int selector)
>  {
> @@ -537,32 +531,19 @@ static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
>  	kvm_seg_fill_gdt_64bit(vm, segp);
>  }
>  
> -static void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
> +static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  {
> -	struct kvm_vm *vm = vcpu->vm;
>  	struct kvm_sregs sregs;
>  
> +	TEST_ASSERT_EQ(vm->mode, VM_MODE_PXXV48_4K);
> +
> +	/* Set mode specific system register values. */
>  	vcpu_sregs_get(vcpu, &sregs);
> +
>  	sregs.idt.base = vm->arch.idt;
>  	sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1;
>  	sregs.gdt.base = vm->arch.gdt;
>  	sregs.gdt.limit = getpagesize() - 1;
> -	kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
> -	vcpu_sregs_set(vcpu, &sregs);
> -}
> -
> -static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> -{
> -	struct kvm_sregs sregs;
> -
> -	TEST_ASSERT_EQ(vm->mode, VM_MODE_PXXV48_4K);
> -
> -	/* Set mode specific system register values. */
> -	vcpu_sregs_get(vcpu, &sregs);
> -
> -	sregs.idt.limit = 0;
> -
> -	kvm_setup_gdt(vm, &sregs.gdt);
>  
>  	sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
>  	sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
> @@ -572,12 +553,11 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  	kvm_seg_set_kernel_code_64bit(vm, DEFAULT_CODE_SELECTOR, &sregs.cs);
>  	kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.ds);
>  	kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.es);
> +	kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
>  	kvm_setup_tss_64bit(vm, &sregs.tr, 0x18);
>  
>  	sregs.cr3 = vm->pgd;
>  	vcpu_sregs_set(vcpu, &sregs);
> -
> -	vcpu_init_descriptor_tables(vcpu);
>  }
>  
>  static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v6 04/14] drm/mediatek: Add DRM_MODE_ROTATE_0 to rotation property
From: Shawn Sung (宋孝謙) @ 2024-03-28  2:50 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org
In-Reply-To: <fd3beacfc59f466ab5e51276a3479c0501350a39.camel@mediatek.com>

Hi CK,

On Mon, 2024-03-25 at 01:52 +0000, CK Hu (胡俊光) wrote:
> 
> > > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > index 0ebeaf9830d83..2a767a823c83a 100644
> > > --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > > @@ -288,6 +288,10 @@ unsigned int mtk_ovl_layer_nr(struct device
> > > *dev)
> > >  
> > >  unsigned int mtk_ovl_supported_rotations(struct device *dev)
> > >  {
> > > +	/*
> > > +	 * although currently OVL can only do reflection,
> > > +	 * reflect x + reflect y = rotate 180
> > > +	 */
> 
> Sorry, this comment is not related to DRM_MODE_ROTATE_0, so after
> removing this comment,
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 

Got it. No problem. Will remove it from this series.

Thanks,
Shawn
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 17/18] KVM: selftests: Init x86's segments during VM creation
From: Ackerley Tng @ 2024-03-28  2:51 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-18-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Initialize x86's various segments in the GDT during creation of relevant
> VMs instead of waiting until vCPUs come along.  Re-installing the segments
> for every vCPU is both wasteful and confusing, as is installing KERNEL_DS
> multiple times; NOT installing KERNEL_DS for GS is icing on the cake.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../selftests/kvm/lib/x86_64/processor.c      | 68 ++++++-------------
>  1 file changed, 20 insertions(+), 48 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index 67235013f6f9..dab719ee7734 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -438,24 +438,7 @@ static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
>  		desc->base3 = segp->base >> 32;
>  }
>  
> -
> -/*
> - * Set Long Mode Flat Kernel Code Segment
> - *
> - * Input Args:
> - *   vm - VM whose GDT is being filled, or NULL to only write segp
> - *   selector - selector value
> - *
> - * Output Args:
> - *   segp - Pointer to KVM segment
> - *
> - * Return: None
> - *
> - * Sets up the KVM segment pointed to by @segp, to be a code segment
> - * with the selector value given by @selector.
> - */
> -static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
> -	struct kvm_segment *segp)
> +static void kvm_seg_set_kernel_code_64bit(uint16_t selector, struct kvm_segment *segp)
>  {
>  	memset(segp, 0, sizeof(*segp));
>  	segp->selector = selector;
> @@ -467,27 +450,9 @@ static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
>  	segp->g = true;
>  	segp->l = true;
>  	segp->present = 1;
> -	if (vm)
> -		kvm_seg_fill_gdt_64bit(vm, segp);
>  }
>  
> -/*
> - * Set Long Mode Flat Kernel Data Segment
> - *
> - * Input Args:
> - *   vm - VM whose GDT is being filled, or NULL to only write segp
> - *   selector - selector value
> - *
> - * Output Args:
> - *   segp - Pointer to KVM segment
> - *
> - * Return: None
> - *
> - * Sets up the KVM segment pointed to by @segp, to be a data segment
> - * with the selector value given by @selector.
> - */
> -static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
> -	struct kvm_segment *segp)
> +static void kvm_seg_set_kernel_data_64bit(uint16_t selector, struct kvm_segment *segp)
>  {
>  	memset(segp, 0, sizeof(*segp));
>  	segp->selector = selector;
> @@ -498,8 +463,6 @@ static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
>  					  */
>  	segp->g = true;
>  	segp->present = true;
> -	if (vm)
> -		kvm_seg_fill_gdt_64bit(vm, segp);
>  }
>  
>  vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
> @@ -517,16 +480,15 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
>  	return vm_untag_gpa(vm, PTE_GET_PA(*pte)) | (gva & ~HUGEPAGE_MASK(level));
>  }
>  
> -static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
> -				int selector)
> +static void kvm_seg_set_tss_64bit(vm_vaddr_t base, struct kvm_segment *segp,
> +				  int selector)
>  {
>  	memset(segp, 0, sizeof(*segp));
> -	segp->base = vm->arch.tss;
> +	segp->base = base;
>  	segp->limit = 0x67;
>  	segp->selector = selector;
>  	segp->type = 0xb;
>  	segp->present = 1;
> -	kvm_seg_fill_gdt_64bit(vm, segp);
>  }
>  
>  static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> @@ -548,11 +510,11 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  	sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
>  
>  	kvm_seg_set_unusable(&sregs.ldt);
> -	kvm_seg_set_kernel_code_64bit(vm, KERNEL_CS, &sregs.cs);
> -	kvm_seg_set_kernel_data_64bit(vm, KERNEL_DS, &sregs.ds);
> -	kvm_seg_set_kernel_data_64bit(vm, KERNEL_DS, &sregs.es);
> -	kvm_seg_set_kernel_data_64bit(NULL, KERNEL_DS, &sregs.gs);
> -	kvm_setup_tss_64bit(vm, &sregs.tr, KERNEL_TSS);
> +	kvm_seg_set_kernel_code_64bit(KERNEL_CS, &sregs.cs);
> +	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.ds);
> +	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.es);
> +	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.gs);
> +	kvm_seg_set_tss_64bit(vm->arch.tss, &sregs.tr, KERNEL_TSS);
>  
>  	sregs.cr3 = vm->pgd;
>  	vcpu_sregs_set(vcpu, &sregs);
> @@ -612,6 +574,7 @@ void route_exception(struct ex_regs *regs)
>  static void vm_init_descriptor_tables(struct kvm_vm *vm)
>  {
>  	extern void *idt_handlers;
> +	struct kvm_segment seg;
>  	int i;
>  
>  	vm->arch.gdt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
> @@ -624,6 +587,15 @@ static void vm_init_descriptor_tables(struct kvm_vm *vm)
>  		set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0, KERNEL_CS);
>  
>  	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
> +
> +	kvm_seg_set_kernel_code_64bit(KERNEL_CS, &seg);
> +	kvm_seg_fill_gdt_64bit(vm, &seg);
> +
> +	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &seg);
> +	kvm_seg_fill_gdt_64bit(vm, &seg);
> +
> +	kvm_seg_set_tss_64bit(vm->arch.tss, &seg, KERNEL_TSS);
> +	kvm_seg_fill_gdt_64bit(vm, &seg);
>  }
>  
>  void vm_install_exception_handler(struct kvm_vm *vm, int vector,
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 18/18] KVM: selftests: Drop @selector from segment helpers
From: Ackerley Tng @ 2024-03-28  2:51 UTC (permalink / raw)
  To: Sean Christopherson, Marc Zyngier, Oliver Upton, Paolo Bonzini,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Anup Patel, Paul Walmsley, Palmer Dabbelt, Albert Ou
  Cc: linux-arm-kernel, kvmarm, kvm, kvm-riscv, linux-riscv,
	linux-kernel
In-Reply-To: <20240314232637.2538648-19-seanjc@google.com>

Sean Christopherson <seanjc@google.com> writes:

> Drop the @selector from the kernel code, data, and TSS builders and
> instead hardcode the respective selector in the helper.  Accepting a
> selector but not a base makes the selector useless, e.g. the data helper
> can't create per-vCPU for FS or GS, and so loading GS with KERNEL_DS is
> the only logical choice.
>
> And for code and TSS, there is no known reason to ever want multiple
> segments, e.g. there are zero plans to support 32-bit kernel code (and
> again, that would require more than just the selector).
>
> If KVM selftests ever do add support for per-vCPU segments, it'd arguably
> be more readable to add a dedicated helper for building/setting the
> per-vCPU segment, and move the common data segment code to an inner
> helper.
>
> Lastly, hardcoding the selector reduces the probability of setting the
> wrong selector in the vCPU versus what was created by the VM in the GDT.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  .../selftests/kvm/lib/x86_64/processor.c      | 29 +++++++++----------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> index dab719ee7734..6abd50d6e59d 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
> @@ -438,10 +438,10 @@ static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
>  		desc->base3 = segp->base >> 32;
>  }
>  
> -static void kvm_seg_set_kernel_code_64bit(uint16_t selector, struct kvm_segment *segp)
> +static void kvm_seg_set_kernel_code_64bit(struct kvm_segment *segp)
>  {
>  	memset(segp, 0, sizeof(*segp));
> -	segp->selector = selector;
> +	segp->selector = KERNEL_CS;
>  	segp->limit = 0xFFFFFFFFu;
>  	segp->s = 0x1; /* kTypeCodeData */
>  	segp->type = 0x08 | 0x01 | 0x02; /* kFlagCode | kFlagCodeAccessed
> @@ -452,10 +452,10 @@ static void kvm_seg_set_kernel_code_64bit(uint16_t selector, struct kvm_segment
>  	segp->present = 1;
>  }
>  
> -static void kvm_seg_set_kernel_data_64bit(uint16_t selector, struct kvm_segment *segp)
> +static void kvm_seg_set_kernel_data_64bit(struct kvm_segment *segp)
>  {
>  	memset(segp, 0, sizeof(*segp));
> -	segp->selector = selector;
> +	segp->selector = KERNEL_DS;
>  	segp->limit = 0xFFFFFFFFu;
>  	segp->s = 0x1; /* kTypeCodeData */
>  	segp->type = 0x00 | 0x01 | 0x02; /* kFlagData | kFlagDataAccessed
> @@ -480,13 +480,12 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
>  	return vm_untag_gpa(vm, PTE_GET_PA(*pte)) | (gva & ~HUGEPAGE_MASK(level));
>  }
>  
> -static void kvm_seg_set_tss_64bit(vm_vaddr_t base, struct kvm_segment *segp,
> -				  int selector)
> +static void kvm_seg_set_tss_64bit(vm_vaddr_t base, struct kvm_segment *segp)
>  {
>  	memset(segp, 0, sizeof(*segp));
>  	segp->base = base;
>  	segp->limit = 0x67;
> -	segp->selector = selector;
> +	segp->selector = KERNEL_TSS;
>  	segp->type = 0xb;
>  	segp->present = 1;
>  }
> @@ -510,11 +509,11 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
>  	sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
>  
>  	kvm_seg_set_unusable(&sregs.ldt);
> -	kvm_seg_set_kernel_code_64bit(KERNEL_CS, &sregs.cs);
> -	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.ds);
> -	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.es);
> -	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.gs);
> -	kvm_seg_set_tss_64bit(vm->arch.tss, &sregs.tr, KERNEL_TSS);
> +	kvm_seg_set_kernel_code_64bit(&sregs.cs);
> +	kvm_seg_set_kernel_data_64bit(&sregs.ds);
> +	kvm_seg_set_kernel_data_64bit(&sregs.es);
> +	kvm_seg_set_kernel_data_64bit(&sregs.gs);
> +	kvm_seg_set_tss_64bit(vm->arch.tss, &sregs.tr);
>  
>  	sregs.cr3 = vm->pgd;
>  	vcpu_sregs_set(vcpu, &sregs);
> @@ -588,13 +587,13 @@ static void vm_init_descriptor_tables(struct kvm_vm *vm)
>  
>  	*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
>  
> -	kvm_seg_set_kernel_code_64bit(KERNEL_CS, &seg);
> +	kvm_seg_set_kernel_code_64bit(&seg);
>  	kvm_seg_fill_gdt_64bit(vm, &seg);
>  
> -	kvm_seg_set_kernel_data_64bit(KERNEL_DS, &seg);
> +	kvm_seg_set_kernel_data_64bit(&seg);
>  	kvm_seg_fill_gdt_64bit(vm, &seg);
>  
> -	kvm_seg_set_tss_64bit(vm->arch.tss, &seg, KERNEL_TSS);
> +	kvm_seg_set_tss_64bit(vm->arch.tss, &seg);
>  	kvm_seg_fill_gdt_64bit(vm, &seg);
>  }
>  
> -- 
> 2.44.0.291.gc1ea87d7ee-goog

Reviewed-by: Ackerley Tng <ackerleytng@google.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v6 07/14] drm/mediatek: Support alpha blending in display driver
From: Shawn Sung (宋孝謙) @ 2024-03-28  2:52 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org
In-Reply-To: <d170ccc1b2e6275cfc6df32f90d2c1b11295f019.camel@mediatek.com>

Hi CK,

On Fri, 2024-03-22 at 09:37 +0000, CK Hu (胡俊光) wrote:
> > diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c
> > b/drivers/gpu/drm/mediatek/mtk_plane.c
> > index 1723d4333f371..5bf757a3ef202 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_plane.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_plane.c
> > @@ -346,6 +346,17 @@ int mtk_plane_init(struct drm_device *dev,
> > struct drm_plane *plane,
> >  			DRM_INFO("Create rotation property failed\n");
> >  	}
> >  
> > +	err = drm_plane_create_alpha_property(plane);
> > +	if (err)
> > +		DRM_ERROR("failed to create property: alpha\n");
> > +
> > +	err = drm_plane_create_blend_mode_property(plane,
> > +						   BIT(DRM_MODE_BLEND_P
> > REMULTI) |
> > +						   BIT(DRM_MODE_BLEND_C
> > OVERAGE) |
> > +						   BIT(DRM_MODE_BLEND_P
> > IXEL_NONE));
> 
> After all sub driver support these function, then create blend
> property. So move this patch after all sub driver support these blend
> mode.
> 

Got it. Will rearrange the patches in the next version

Thanks,
Shawn
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v6 11/14] drm/mediatek: Support "None" alpha blending in Mixer
From: Shawn Sung (宋孝謙) @ 2024-03-28  2:56 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <3a427289f49b196d99934b9b4aaebeeebb13c628.camel@mediatek.com>

Hi CK,

On Mon, 2024-03-25 at 02:03 +0000, CK Hu (胡俊光) wrote:
> Hi, Shawn:
> 
> On Fri, 2024-03-22 at 13:28 +0800, Shawn Sung wrote:
> > From: Hsiao Chien Sung <shawn.sung@mediatek.com>
> > 
> > Support "None" blend mode on MediaTek's chips.
> > 
> > Please refer to the description of the commit
> > "drm/mediatek: Support alpha blending in display driver"
> > for more information.
> 
> But I would like you to describe the information in this patch
> instead
> of referring to another patch. This patch could describe more detail,
> and the integration patch could describe more brief.
> 

Got it. Will try to add more information to all the related patches.

Thanks,
Shawn
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v2 2/6] arm64: dts: qcom: qcs6490-rb3gen2: Add DP output
From: Bjorn Andersson @ 2024-03-28  3:07 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Bjorn Andersson, cros-qcom-dts-watchers, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, linux-arm-msm, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <CAA8EJpoe7A94608V1GdQ-oU9UXagHPm0mVBUe4Yxi=HF2pMd7w@mail.gmail.com>

On Thu, Mar 28, 2024 at 03:51:54AM +0200, Dmitry Baryshkov wrote:
> On Wed, 27 Mar 2024 at 04:04, Bjorn Andersson <quic_bjorande@quicinc.com> wrote:
> >
> > The RB3Gen2 board comes with a mini DP connector, describe this, enable
> > MDSS, DP controller and the PHY that drives this.
> >
> > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
> > ---
> >  arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 40 ++++++++++++++++++++++++++++
> >  1 file changed, 40 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> > index 63ebe0774f1d..f90bf3518e98 100644
> > --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> > +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> > @@ -39,6 +39,20 @@ chosen {
> >                 stdout-path = "serial0:115200n8";
> >         };
> >
> > +       dp-connector {
> > +               compatible = "dp-connector";
> > +               label = "DP";
> > +               type = "mini";
> > +
> > +               hpd-gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>;
> 
> Is it the standard hpd gpio? If so, is there any reason for using it
> through dp-connector rather than as a native HPD signal?
> 

I added it because you asked for it. That said, I do like having it
clearly defined in the devicetree.

Regards,
Bjorn

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v5 4/4] drivers: watchdog: ast2500 and ast2600 support bootstatus
From: PeterYin @ 2024-03-28  3:17 UTC (permalink / raw)
  To: patrick, Wim Van Sebroeck, Guenter Roeck, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240328013303.3609385-5-peteryin.openbmc@gmail.com>

Peter Yin 於 3/28/24 09:33 寫道:
> Add WDIOF_EXTERN1 and WDIOF_CARDRESET bootstatus in ast2600
> 
> Regarding the AST2600 specification, the WDTn Timeout Status Register
> (WDT10) has bit 1 reserved. Bit 1 of the status register indicates
> on ast2500 if the boot was from the second boot source.
> It does not indicate that the most recent reset was triggered by
> the watchdog. The code should just be changed to set WDIOF_CARDRESET
> if bit 0 of the status register is set.
> 
> Include SCU register to veriy WDIOF_EXTERN1 in ast2600 SCU74 or
> ast2500 SCU3C when bit1 is set.
> 
> Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
> ---
>   drivers/watchdog/aspeed_wdt.c | 34 ++++++++++++++++++++++++++++++----
>   1 file changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> index b4773a6aaf8c..c3c8098c035d 100644
> --- a/drivers/watchdog/aspeed_wdt.c
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -11,10 +11,12 @@
>   #include <linux/io.h>
>   #include <linux/kernel.h>
>   #include <linux/kstrtox.h>
> +#include <linux/mfd/syscon.h>
>   #include <linux/module.h>
>   #include <linux/of.h>
>   #include <linux/of_irq.h>
>   #include <linux/platform_device.h>
> +#include <linux/regmap.h>
>   #include <linux/watchdog.h>
>   
>   static bool nowayout = WATCHDOG_NOWAYOUT;
> @@ -82,6 +84,13 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
>   #define WDT_RESET_MASK1		0x1c
>   #define WDT_RESET_MASK2		0x20
>   
> +/*
> + * Ast2600 SCU74 bit1 is External reset flag
> + * Ast2500 SCU3C bit1 is External reset flag
> + */
> +#define AST2500_SYSTEM_RESET_EVENT	0x3C
> +#define AST2600_SYSTEM_RESET_EVENT	0x74
> +#define   EXTERN_RESET_FLAG		BIT(1)
>   /*
>    * WDT_RESET_WIDTH controls the characteristics of the external pulse (if
>    * enabled), specifically:
> @@ -330,6 +339,11 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
>   	if (IS_ERR(wdt->base))
>   		return PTR_ERR(wdt->base);
>   
> +	struct regmap *scu_base = syscon_regmap_lookup_by_phandle(dev->of_node,
> +							     "aspeed,scu");
> +	if (IS_ERR(scu_base))
> +		return PTR_ERR(scu_base);
> +
>   	wdt->wdd.info = &aspeed_wdt_info;
>   
>   	if (wdt->cfg->irq_mask) {
> @@ -459,14 +473,26 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
>   	}
>   
>   	status = readl(wdt->base + WDT_TIMEOUT_STATUS);
> -	if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) {
> +	if (status & WDT_TIMEOUT_STATUS_EVENT)
>   		wdt->wdd.bootstatus = WDIOF_CARDRESET;
>   
> -		if (of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
> -		    of_device_is_compatible(np, "aspeed,ast2500-wdt"))
> -			wdt->wdd.groups = bswitch_groups;
> +	if (of_device_is_compatible(np, "aspeed,ast2600-wdt")) {
> +		ret = regmap_read(scu_base,
> +				  AST2600_SYSTEM_RESET_EVENT,
> +				  &status);
> +	} else {
> +		ret = regmap_read(scu_base,
> +				  AST2500_SYSTEM_RESET_EVENT,
> +				  &status);
> +		wdt->wdd.groups = bswitch_groups;
>   	}
>   
> +	/*
> +	 * Reset cause by Extern Reset
> +	 */
> +	if (status & EXTERN_RESET_FLAG && !ret)
> +		wdt->wdd.bootstatus |= WDIOF_EXTERN1;
> +
>   	dev_set_drvdata(dev, wdt);
>   
>   	return devm_watchdog_register_device(dev, &wdt->wdd);
Please ignore this version, as I lost the definition for 
WDT_TIMEOUT_STATUS_EVENT.


Thanks.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v6 13/14] drm/mediatek: Support CRC in OVL
From: Shawn Sung (宋孝謙) @ 2024-03-28  3:22 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu@kernel.org,
	angelogioacchino.delregno@collabora.com
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	Bibby Hsieh (謝濟遠),
	jason-ch.chen@mediatek.corp-partner.google.com,
	Nancy Lin (林欣螢), daniel@ffwll.ch,
	p.zabel@pengutronix.de, dri-devel@lists.freedesktop.org,
	airlied@gmail.com, sean@poorly.run, matthias.bgg@gmail.com,
	fshao@chromium.org, linux-arm-kernel@lists.infradead.org
In-Reply-To: <10afc2842aea3700263c4accf0593b75e7209431.camel@mediatek.com>

Hi CK,

On Tue, 2024-03-26 at 06:11 +0000, CK Hu (胡俊光) wrote:
> > @@ -488,6 +567,83 @@ void mtk_ovl_layer_config(struct device *dev,
> > unsigned int idx,
> >  	    (state->base.fb && !state->base.fb->format->has_alpha))
> >  		ignore_pixel_alpha = OVL_CONST_BLEND;
> >  
> > +	/*
> > +	 * OVL only supports 8 bits data in CRC calculation, transform
> > 10-bit
> > +	 * RGB to 8-bit RGB by leveraging the ability of the Y2R (YUV-
> > to-RGB)
> > +	 * hardware to multiply coefficients, although there is nothing
> > to do
> > +	 * with the YUV format.
> > +	 */
> > +	if (ovl->data->supports_clrfmt_ext) {
> > +		u32 y2r_coef = 0, y2r_offset = 0, r2r_coef = 0, csc_en
> > = 0;
> > +
> > +		if (is_10bit_rgb(fmt)) {
> > +			con |= OVL_CON_MTX_AUTO_DIS | OVL_CON_MTX_EN |
> > OVL_CON_MTX_PROGRAMMABLE;
> > +
> > +			/*
> > +			 * Y2R coefficient setting
> > +			 * bit 13 is 2^1, bit 12 is 2^0, bit 11 is 2^-
> > 1,
> > +			 * bit 10 is 2^-2 = 0.25
> > +			 */
> > +			y2r_coef = BIT(10);
> > +
> > +			/* -1 in 10bit */
> > +			y2r_offset = GENMASK(10, 0) - 1;
> 
> I don't know why do this? If an input value is 0x100, then
> 
> 0x100 right shit 2 bit become 0x40.
> 0x40 - 1 = 0x3f.
> 0x3f left shift 2 bit become 0xfc.
> 
> So input 0x100 and output 0xfc. Why?
> 

There is no input here, all the settings are direct bit assignment, and
all the values are calculated by the designer. The main purpose of it
is to configure the Y2R module to be able to transform 10bit RGB format
into 8bit RGB, while this is not Y2R module is originally designed for.

> > +
> > +			/*
> > +			 * R2R coefficient setting
> > +			 * bit 19 is 2^1, bit 18 is 2^0, bit 17 is 2^-
> > 1,
> > +			 * bit 20 is 2^2 = 4
> > +			 */
> > +			r2r_coef = BIT(20);
> > +
> > +			/* CSC_EN is for R2R */
> > +			csc_en = OVL_CLRFMT_EXT1_CSC_EN(idx);
> > +
> > +			/*
> > +			 * 1. YUV input data - 1 and shift right for 2
> > bits to remove it
> > +			 * [R']   [0.25    0    0]   [Y in - 1]
> > +			 * [G'] = [   0 0.25    0] * [U in - 1]
> > +			 * [B']   [   0    0 0.25]   [V in - 1]
> > +			 *
> > +			 * 2. shift left for 2 bit letting the last 2
> > bits become 0
> 
> You truncate the last two bit, so some quality lost. I think the
> quality is main function and CRC is just for debug. So it's better
> that
> in normal case we keep quality and only for debug to lost the
> quality.

Got it. Will modify in the next version to enter this section only if
we need to calculate the CRC.

> I have another question. You just truncate the last two bit but it is
> still 10 bit value, so CRC could calculate this 10 bit value? I don't
> know why you say CRC just for 8 bit?
> 

Yes, for RGB format, OVL can only handle 8bit per channel for CRC
calculation, so I assume there may be similar issue handling 10bit YUV
formats (P010) in the future.

Thanks,
Shawn

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox