Re: [XEN PATCH v5 1/3] arm/bitops: encapsulate violation of MISRA C:2012 Rule 10.1

2023-11-24 Thread Jan Beulich
On 23.11.2023 08:37, Nicola Vetrini wrote:
> The definitions of ffs{l}? violate Rule 10.1, by using the well-known
> pattern (x & -x); its usage is wrapped by the ISOLATE_LSB macro.
> 
> No functional change.
> 
> Signed-off-by: Nicola Vetrini 
> Reviewed-by: Stefano Stabellini 

This patch failed my pre-push build test; apparently xen/macros.h needs
including explicitly.

Jan



[XEN PATCH v4] xen: replace some occurrences of SAF-1-safe with asmlinkage attribute

2023-11-24 Thread Nicola Vetrini
The comment-based justifications for MISRA C:2012 Rule 8.4 are replaced
by the asmlinkage pseudo-attribute, for the sake of uniformity.

asmlinkage may in the future have the effect of altering the calling
convention, therefore three special where the calling convention is
altered by another macro retain the textual deviation.

No functional change.

Signed-off-by: Nicola Vetrini 
Acked-by: Julien Grall 
---
This patch does not depend on any other patch.

Changes in v2:
- Edit safe.json.
- Remove mention of SAF-1-safe in deviations.rst.
Changes in v3:
- Sorted #include-s and rebased against
7ad0c774e474 ("x86/boot: tidy #include-s")
Changes in v4:
- Drop functions that shouldn't have the attribute added
- Drop the change in safe.json, as now SAF-1-safe is still used
- Edited the commit message accordingly
---
 xen/arch/arm/cpuerrata.c |  7 +++
 xen/arch/arm/setup.c |  5 ++---
 xen/arch/arm/smpboot.c   |  3 +--
 xen/arch/arm/traps.c | 21 +++--
 xen/arch/x86/extable.c   |  3 +--
 xen/arch/x86/setup.c |  3 +--
 xen/arch/x86/traps.c | 27 +--
 7 files changed, 24 insertions(+), 45 deletions(-)

diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c
index 9137958fb682..a28fa6ac78cc 100644
--- a/xen/arch/arm/cpuerrata.c
+++ b/xen/arch/arm/cpuerrata.c
@@ -370,10 +370,9 @@ custom_param("spec-ctrl", parse_spec_ctrl);
 
 /* Arm64 only for now as for Arm32 the workaround is currently handled in C. */
 #ifdef CONFIG_ARM_64
-/* SAF-1-safe */
-void __init arm_enable_wa2_handling(const struct alt_instr *alt,
-const uint32_t *origptr,
-uint32_t *updptr, int nr_inst)
+void asmlinkage __init arm_enable_wa2_handling(const struct alt_instr *alt,
+   const uint32_t *origptr,
+   uint32_t *updptr, int nr_inst)
 {
 BUG_ON(nr_inst != 1);
 
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 9b9018574919..188ddd490437 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -759,9 +759,8 @@ static bool __init is_dom0less_mode(void)
 size_t __read_mostly dcache_line_bytes;
 
 /* C entry point for boot CPU */
-/* SAF-1-safe */
-void __init start_xen(unsigned long boot_phys_offset,
-  unsigned long fdt_paddr)
+void asmlinkage __init start_xen(unsigned long boot_phys_offset,
+ unsigned long fdt_paddr)
 {
 size_t fdt_size;
 const char *cmdline;
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index 36db6b8880d3..7110bc11fc05 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -303,8 +303,7 @@ smp_prepare_cpus(void)
 }
 
 /* Boot the current CPU */
-/* SAF-1-safe */
-void start_secondary(void)
+void asmlinkage start_secondary(void)
 {
 unsigned int cpuid = init_data.cpuid;
 
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 8492e2b7bbb8..3784e8276ef6 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -161,8 +161,7 @@ void init_traps(void)
 isb();
 }
 
-/* SAF-1-safe */
-void __div0(void)
+void asmlinkage __div0(void)
 {
 printk("Division by zero in hypervisor.\n");
 BUG();
@@ -1955,8 +1954,7 @@ static inline bool needs_ssbd_flip(struct vcpu *v)
  * Actions that needs to be done after entering the hypervisor from the
  * guest and before the interrupts are unmasked.
  */
-/* SAF-1-safe */
-void enter_hypervisor_from_guest_preirq(void)
+void asmlinkage enter_hypervisor_from_guest_preirq(void)
 {
 struct vcpu *v = current;
 
@@ -1970,8 +1968,7 @@ void enter_hypervisor_from_guest_preirq(void)
  * guest and before we handle any request. Depending on the exception trap,
  * this may be called with interrupts unmasked.
  */
-/* SAF-1-safe */
-void enter_hypervisor_from_guest(void)
+void asmlinkage enter_hypervisor_from_guest(void)
 {
 struct vcpu *v = current;
 
@@ -1999,8 +1996,7 @@ void enter_hypervisor_from_guest(void)
 vgic_sync_from_lrs(v);
 }
 
-/* SAF-1-safe */
-void do_trap_guest_sync(struct cpu_user_regs *regs)
+void asmlinkage do_trap_guest_sync(struct cpu_user_regs *regs)
 {
 const union hsr hsr = { .bits = regs->hsr };
 
@@ -2195,14 +2191,12 @@ void do_trap_guest_serror(struct cpu_user_regs *regs)
 __do_trap_serror(regs, true);
 }
 
-/* SAF-1-safe */
-void do_trap_irq(struct cpu_user_regs *regs)
+void asmlinkage do_trap_irq(struct cpu_user_regs *regs)
 {
 gic_interrupt(regs, 0);
 }
 
-/* SAF-1-safe */
-void do_trap_fiq(struct cpu_user_regs *regs)
+void asmlinkage do_trap_fiq(struct cpu_user_regs *regs)
 {
 gic_interrupt(regs, 1);
 }
@@ -2275,8 +2269,7 @@ static bool check_for_vcpu_work(void)
  *
  * The function will return with IRQ masked.
  */
-/* SAF-1-safe */
-void leave_hypervisor_to_guest(void)
+void asmlinkage leave_hypervisor_to_guest(void)
 {
 local_irq_disable();
 
diff --git a/xen/arch/x86/extable.c b/xen/arch/x86/e

Re: [XEN PATCH v5 1/3] arm/bitops: encapsulate violation of MISRA C:2012 Rule 10.1

2023-11-24 Thread Nicola Vetrini

On 2023-11-24 09:06, Jan Beulich wrote:

On 23.11.2023 08:37, Nicola Vetrini wrote:

The definitions of ffs{l}? violate Rule 10.1, by using the well-known
pattern (x & -x); its usage is wrapped by the ISOLATE_LSB macro.

No functional change.

Signed-off-by: Nicola Vetrini 
Reviewed-by: Stefano Stabellini 


This patch failed my pre-push build test; apparently xen/macros.h needs
including explicitly.

Jan


Yes, indeed. I must have dropped that change when experimenting with 
single evaluation and then never reinstated it.

--
Nicola Vetrini, BSc
Software Engineer, BUGSENG srl (https://bugseng.com)



[PATCH v2 00/15] x86/HVM: misc tidying

2023-11-24 Thread Jan Beulich
01: VMX: drop vmx_virt_exception and make vmx_vmfunc static
02: x86/HVM: hide SVM/VMX when their enabling is prohibited by firmware
03: VMX: don't run with CR4.VMXE set when VMX could not be enabled
04: x86/HVM: drop tsc_scaling.setup() hook
05: x86: amend cpu_has_xen_{ibt,shstk}
06: x86/HVM: improve CET-IBT pruning of ENDBR
07: VMX: drop vmcs_revision_id
08: VMX: convert vmx_basic_msr
09: VMX: convert vmx_pin_based_exec_control
10: VMX: convert vmx_cpu_based_exec_control
11: VMX: convert vmx_secondary_exec_control
12: VMX: convert vmx_vmexit_control
13: VMX: convert vmx_vmentry_control
14: VMX: convert vmx_ept_vpid_cap
15: VMX: convert vmx_vmfunc

Jan



[PATCH v2 02/15] x86/HVM: hide SVM/VMX when their enabling is prohibited by firmware

2023-11-24 Thread Jan Beulich
... or we fail to enable the functionality on the BSP for other reasons.
The only place where hardware announcing the feature is recorded is the
raw CPU policy/featureset.

Inspired by 
https://lore.kernel.org/all/20230921114940.957141-1-pbonz...@redhat.com/.

Signed-off-by: Jan Beulich 
Acked-by: Roger Pau Monné 

--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2543,6 +2543,7 @@ const struct hvm_function_table * __init
 
 if ( _svm_cpu_up(true) )
 {
+setup_clear_cpu_cap(X86_FEATURE_SVM);
 printk("SVM: failed to initialise.\n");
 return NULL;
 }
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -2162,6 +2162,23 @@ int __init vmx_vmcs_init(void)
 
 if ( !ret )
 register_keyhandler('v', vmcs_dump, "dump VT-x VMCSs", 1);
+else
+{
+setup_clear_cpu_cap(X86_FEATURE_VMX);
+
+/*
+ * _vmx_vcpu_up() may have made it past feature identification.
+ * Make sure all dependent features are off as well.
+ */
+vmx_basic_msr  = 0;
+vmx_pin_based_exec_control = 0;
+vmx_cpu_based_exec_control = 0;
+vmx_secondary_exec_control = 0;
+vmx_vmexit_control = 0;
+vmx_vmentry_control= 0;
+vmx_ept_vpid_cap   = 0;
+vmx_vmfunc = 0;
+}
 
 return ret;
 }




[PATCH v2 01/15] VMX: drop vmx_virt_exception and make vmx_vmfunc static

2023-11-24 Thread Jan Beulich
The variable was introduced by 69b830e5ffb4 ("VMX: VMFUNC and #VE
definitions and detection") without any use and - violating Misra C:2012
rule 8.4 - without a declaration. Since no use has appeared, drop it.

For vmx_vmfunc the situation is similar, but not identical: It at least
has one use. Convert it to be static (and make style adjustments while
there).

Signed-off-by: Jan Beulich 
Acked-by: Roger Pau Monné 
---
In how far the sole vmx_vmfunc use is actually meaningful (on its own)
I'm not really sure.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -167,8 +167,7 @@ u32 vmx_secondary_exec_control __read_mo
 u32 vmx_vmexit_control __read_mostly;
 u32 vmx_vmentry_control __read_mostly;
 u64 vmx_ept_vpid_cap __read_mostly;
-u64 vmx_vmfunc __read_mostly;
-bool vmx_virt_exception __read_mostly;
+static uint64_t __read_mostly vmx_vmfunc;
 
 static DEFINE_PER_CPU_READ_MOSTLY(paddr_t, vmxon_region);
 static DEFINE_PER_CPU(paddr_t, current_vmcs);
@@ -475,8 +474,7 @@ static int vmx_init_vmcs_config(bool bsp
 vmx_basic_msr  = ((u64)vmx_basic_msr_high << 32) |
  vmx_basic_msr_low;
 vmx_vmfunc = _vmx_vmfunc;
-vmx_virt_exception = !!(_vmx_secondary_exec_control &
-   SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS);
+
 vmx_display_features();
 
 /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */




[PATCH v2 04/15] x86/HVM: drop tsc_scaling.setup() hook

2023-11-24 Thread Jan Beulich
This was used by VMX only, and the intended VMCS write can as well
happen from vmx_set_tsc_offset(), invoked (directly or indirectly)
almost immediately after the present call sites of the hook.
vmx_set_tsc_offset() isn't invoked frequently elsewhere, so the extra
VMCS write shouldn't raise performance concerns.

Signed-off-by: Jan Beulich 
Acked-by: Roger Pau Monné 

--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1086,9 +1086,6 @@ static int cf_check hvm_load_cpu_ctxt(st
 v->arch.hvm.guest_cr[2] = ctxt.cr2;
 hvm_update_guest_cr(v, 2);
 
-if ( hvm_funcs.tsc_scaling.setup )
-alternative_vcall(hvm_funcs.tsc_scaling.setup, v);
-
 v->arch.msrs->tsc_aux = ctxt.msr_tsc_aux;
 
 hvm_set_guest_tsc_fixed(v, ctxt.tsc, d->arch.hvm.sync_tsc);
@@ -4033,9 +4030,6 @@ void hvm_vcpu_reset_state(struct vcpu *v
 hvm_set_segment_register(v, x86_seg_gdtr, ®);
 hvm_set_segment_register(v, x86_seg_idtr, ®);
 
-if ( hvm_funcs.tsc_scaling.setup )
-alternative_vcall(hvm_funcs.tsc_scaling.setup, v);
-
 /* Sync AP's TSC with BSP's. */
 v->arch.hvm.cache_tsc_offset =
 v->domain->vcpu[0]->arch.hvm.cache_tsc_offset;
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -1454,20 +1454,13 @@ static void cf_check vmx_handle_cd(struc
 }
 }
 
-static void cf_check vmx_setup_tsc_scaling(struct vcpu *v)
-{
-if ( v->domain->arch.vtsc )
-return;
-
-vmx_vmcs_enter(v);
-__vmwrite(TSC_MULTIPLIER, hvm_tsc_scaling_ratio(v->domain));
-vmx_vmcs_exit(v);
-}
-
 static void cf_check vmx_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
 {
 vmx_vmcs_enter(v);
 
+if ( !v->domain->arch.vtsc && cpu_has_vmx_tsc_scaling )
+__vmwrite(TSC_MULTIPLIER, hvm_tsc_scaling_ratio(v->domain));
+
 if ( nestedhvm_vcpu_in_guestmode(v) )
 offset += nvmx_get_tsc_offset(v);
 
@@ -3031,10 +3024,7 @@ const struct hvm_function_table * __init
 }
 
 if ( cpu_has_vmx_tsc_scaling )
-{
 vmx_function_table.tsc_scaling.ratio_frac_bits = 48;
-vmx_function_table.tsc_scaling.setup = vmx_setup_tsc_scaling;
-}
 
 model_specific_lbr = get_model_specific_lbr();
 lbr_tsx_fixup_check();
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -240,9 +240,6 @@ struct hvm_function_table {
 uint8_t  ratio_frac_bits;
 /* maximum-allowed TSC scaling ratio */
 uint64_t max_ratio;
-
-/* Architecture function to setup TSC scaling ratio */
-void (*setup)(struct vcpu *v);
 } tsc_scaling;
 };
 




[PATCH v2 03/15] VMX: don't run with CR4.VMXE set when VMX could not be enabled

2023-11-24 Thread Jan Beulich
While generally benign, doing so is still at best misleading.

Signed-off-by: Jan Beulich 
---
Using set_in_cr4() seems favorable over updating mmu_cr4_features
despite the resulting redundant CR4 update. But I certainly could be
talked into going the alternative route.
---
v2: Actually clear CR4.VMXE for the BSP on the error path.

--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2959,14 +2959,18 @@ static bool __init has_if_pschange_mc(vo
 
 const struct hvm_function_table * __init start_vmx(void)
 {
-set_in_cr4(X86_CR4_VMXE);
+write_cr4(read_cr4() | X86_CR4_VMXE);
 
 if ( vmx_vmcs_init() )
 {
+write_cr4(read_cr4() & ~X86_CR4_VMXE);
 printk("VMX: failed to initialise.\n");
 return NULL;
 }
 
+/* Arrange for APs to have CR4.VMXE set early on. */
+set_in_cr4(X86_CR4_VMXE);
+
 vmx_function_table.singlestep_supported = cpu_has_monitor_trap_flag;
 
 if ( cpu_has_vmx_dt_exiting )




[PATCH v2 05/15] x86: amend cpu_has_xen_[ibt,shstk}

2023-11-24 Thread Jan Beulich
... to evaluate to false at compile-time when the respective Kconfig
control is off, thus allowing the compiler to eliminate then-dead code.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/include/asm/cpufeature.h
+++ b/xen/arch/x86/include/asm/cpufeature.h
@@ -215,8 +215,10 @@ static inline bool boot_cpu_has(unsigned
 #define cpu_has_lfence_dispatch boot_cpu_has(X86_FEATURE_LFENCE_DISPATCH)
 #define cpu_has_nscbboot_cpu_has(X86_FEATURE_NSCB)
 #define cpu_has_xen_lbr boot_cpu_has(X86_FEATURE_XEN_LBR)
-#define cpu_has_xen_shstk   boot_cpu_has(X86_FEATURE_XEN_SHSTK)
-#define cpu_has_xen_ibt boot_cpu_has(X86_FEATURE_XEN_IBT)
+#define cpu_has_xen_shstk   (IS_ENABLED(CONFIG_XEN_SHSTK) && \
+ boot_cpu_has(X86_FEATURE_XEN_SHSTK))
+#define cpu_has_xen_ibt (IS_ENABLED(CONFIG_XEN_IBT) && \
+ boot_cpu_has(X86_FEATURE_XEN_IBT))
 
 #define cpu_has_msr_tsc_aux (cpu_has_rdtscp || cpu_has_rdpid)
 




[PATCH v2 06/15] x86/HVM: improve CET-IBT pruning of ENDBR

2023-11-24 Thread Jan Beulich
__init{const,data}_cf_clobber can have an effect only for pointers
actually populated in the respective tables. While not the case for SVM
right now, VMX installs a number of pointers only under certain
conditions. Hence the respective functions would have their ENDBR purged
only when those conditions are met. Invoke "pruning" functions after
having copied the respective tables, for them to install any "missing"
pointers.

Signed-off-by: Jan Beulich 
---
This is largely cosmetic for present hardware, which when supporting
CET-IBT likely also supports all of the advanced VMX features for which
hook pointers are installed conditionally. The only case this would make
a difference there is when use of respective features was suppressed via
command line option (where available). For future hooks it may end up
relevant even by default, and it also would be if AMD started supporting
CET-IBT; right now it matters only for .pi_update_irte, as iommu_intpost
continues to default to off.

Originally I had meant to put the SVM and VMX functions in presmp-
initcalls, but hvm/{svm,vmx}/built_in.o are linked into hvm/built_in.o
before hvm/hvm.o. And I don't think I want to fiddle with link order
here.
---
v2: Use cpu_has_xen_ibt in prune_{svm,vmx}().

--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -161,10 +161,15 @@ static int __init cf_check hvm_enable(vo
 else if ( cpu_has_svm )
 fns = start_svm();
 
+if ( fns )
+hvm_funcs = *fns;
+
+prune_vmx();
+prune_svm();
+
 if ( fns == NULL )
 return 0;
 
-hvm_funcs = *fns;
 hvm_enabled = 1;
 
 printk("HVM: %s enabled\n", fns->name);
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2587,6 +2587,19 @@ const struct hvm_function_table * __init
 return &svm_function_table;
 }
 
+void __init prune_svm(void)
+{
+/*
+ * Now that svm_function_table was copied, populate all function pointers
+ * which may have been left at NULL, for __initdata_cf_clobber to have as
+ * much of an effect as possible.
+ */
+if ( !cpu_has_xen_ibt )
+return;
+
+/* Nothing at present. */
+}
+
 void asmlinkage svm_vmexit_handler(void)
 {
 struct cpu_user_regs *regs = guest_cpu_user_regs();
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -3033,6 +3033,30 @@ const struct hvm_function_table * __init
 return &vmx_function_table;
 }
 
+void __init prune_vmx(void)
+{
+/*
+ * Now that vmx_function_table was copied, populate all function pointers
+ * which may have been left at NULL, for __initdata_cf_clobber to have as
+ * much of an effect as possible.
+ */
+if ( !cpu_has_xen_ibt )
+return;
+
+vmx_function_table.set_descriptor_access_exiting =
+vmx_set_descriptor_access_exiting;
+
+vmx_function_table.update_eoi_exit_bitmap = vmx_update_eoi_exit_bitmap;
+vmx_function_table.process_isr= vmx_process_isr;
+vmx_function_table.handle_eoi = vmx_handle_eoi;
+
+vmx_function_table.pi_update_irte = vmx_pi_update_irte;
+
+vmx_function_table.deliver_posted_intr = vmx_deliver_posted_intr;
+vmx_function_table.sync_pir_to_irr = vmx_sync_pir_to_irr;
+vmx_function_table.test_pir= vmx_test_pir;
+}
+
 /*
  * Not all cases receive valid value in the VM-exit instruction length field.
  * Callers must know what they're doing!
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -250,6 +250,9 @@ extern s8 hvm_port80_allowed;
 extern const struct hvm_function_table *start_svm(void);
 extern const struct hvm_function_table *start_vmx(void);
 
+void prune_svm(void);
+void prune_vmx(void);
+
 int hvm_domain_initialise(struct domain *d,
   const struct xen_domctl_createdomain *config);
 void hvm_domain_relinquish_resources(struct domain *d);




[PATCH v2 07/15] VMX: drop vmcs_revision_id

2023-11-24 Thread Jan Beulich
It's effectively redundant with vmx_basic_msr. For the #define
replacement to work, struct vmcs_struct's respective field name also
needs to change: Drop the not really meaningful "vmcs_" prefix from it.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -174,7 +174,7 @@ static DEFINE_PER_CPU(paddr_t, current_v
 static DEFINE_PER_CPU(struct list_head, active_vmcs_list);
 DEFINE_PER_CPU(bool, vmxon);
 
-static u32 vmcs_revision_id __read_mostly;
+#define vmcs_revision_id (vmx_basic_msr & VMX_BASIC_REVISION_MASK)
 u64 __read_mostly vmx_basic_msr;
 
 static void __init vmx_display_features(void)
@@ -464,7 +464,6 @@ static int vmx_init_vmcs_config(bool bsp
 if ( !vmx_pin_based_exec_control )
 {
 /* First time through. */
-vmcs_revision_id   = vmx_basic_msr_low & 
VMX_BASIC_REVISION_MASK;
 vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
 vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
 vmx_secondary_exec_control = _vmx_secondary_exec_control;
@@ -572,7 +571,7 @@ static paddr_t vmx_alloc_vmcs(void)
 
 vmcs = __map_domain_page(pg);
 clear_page(vmcs);
-vmcs->vmcs_revision_id = vmcs_revision_id;
+vmcs->revision_id = vmcs_revision_id;
 unmap_domain_page(vmcs);
 
 return page_to_maddr(pg);
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1163,7 +1163,7 @@ static void nvmx_set_vmcs_pointer(struct
 paddr_t vvmcs_maddr = v->arch.hvm.vmx.vmcs_shadow_maddr;
 
 __vmpclear(vvmcs_maddr);
-vvmcs->vmcs_revision_id |= VMCS_RID_TYPE_MASK;
+vvmcs->revision_id |= VMCS_RID_TYPE_MASK;
 v->arch.hvm.vmx.secondary_exec_control |=
 SECONDARY_EXEC_ENABLE_VMCS_SHADOWING;
 __vmwrite(SECONDARY_VM_EXEC_CONTROL,
@@ -1178,7 +1178,7 @@ static void nvmx_clear_vmcs_pointer(stru
 paddr_t vvmcs_maddr = v->arch.hvm.vmx.vmcs_shadow_maddr;
 
 __vmpclear(vvmcs_maddr);
-vvmcs->vmcs_revision_id &= ~VMCS_RID_TYPE_MASK;
+vvmcs->revision_id &= ~VMCS_RID_TYPE_MASK;
 v->arch.hvm.vmx.secondary_exec_control &=
 ~SECONDARY_EXEC_ENABLE_VMCS_SHADOWING;
 __vmwrite(SECONDARY_VM_EXEC_CONTROL,
@@ -1794,10 +1794,10 @@ static int nvmx_handle_vmptrld(struct cp
 {
 struct vmcs_struct *vvmcs = vvmcx;
 
-if ( ((vvmcs->vmcs_revision_id ^ vmx_basic_msr) &
- VMX_BASIC_REVISION_MASK) ||
+if ( ((vvmcs->revision_id ^ vmx_basic_msr) &
+  VMX_BASIC_REVISION_MASK) ||
  (!cpu_has_vmx_vmcs_shadowing &&
-  (vvmcs->vmcs_revision_id & ~VMX_BASIC_REVISION_MASK)) )
+  (vvmcs->revision_id & ~VMX_BASIC_REVISION_MASK)) )
 {
 hvm_unmap_guest_frame(vvmcx, 1);
 vmfail(regs, VMX_INSN_VMPTRLD_INCORRECT_VMCS_ID);
@@ -2209,7 +2209,7 @@ int nvmx_msr_read_intercept(unsigned int
 map_domain_page(_mfn(PFN_DOWN(v->arch.hvm.vmx.vmcs_pa)));
 
 data = (host_data & (~0ul << 32)) |
-   (vmcs->vmcs_revision_id & 0x7fff);
+   (vmcs->revision_id & 0x7fff);
 unmap_domain_page(vmcs);
 
 if ( !cpu_has_vmx_vmcs_shadowing )
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -17,7 +17,7 @@ int cf_check vmx_cpu_up(void);
 void cf_check vmx_cpu_down(void);
 
 struct vmcs_struct {
-u32 vmcs_revision_id;
+uint32_t revision_id;
 unsigned char data [0]; /* vmcs size is read from MSR */
 };
 




[PATCH v2 08/15] VMX: convert vmx_basic_msr

2023-11-24 Thread Jan Beulich
... to a struct field, which is then going to be accompanied by other
capability/control data presently living in individual variables. As
this structure isn't supposed to be altered post-boot, put it in
.data.ro_after_init right away.

Suggested-by: Roger Pau Monné 
Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -161,6 +161,7 @@ static int cf_check parse_ept_param_runt
 #endif
 
 /* Dynamic (run-time adjusted) execution control flags. */
+struct vmx_caps __ro_after_init vmx_caps;
 u32 vmx_pin_based_exec_control __read_mostly;
 u32 vmx_cpu_based_exec_control __read_mostly;
 u32 vmx_secondary_exec_control __read_mostly;
@@ -174,8 +175,7 @@ static DEFINE_PER_CPU(paddr_t, current_v
 static DEFINE_PER_CPU(struct list_head, active_vmcs_list);
 DEFINE_PER_CPU(bool, vmxon);
 
-#define vmcs_revision_id (vmx_basic_msr & VMX_BASIC_REVISION_MASK)
-u64 __read_mostly vmx_basic_msr;
+#define vmcs_revision_id (vmx_caps.basic_msr & VMX_BASIC_REVISION_MASK)
 
 static void __init vmx_display_features(void)
 {
@@ -470,8 +470,8 @@ static int vmx_init_vmcs_config(bool bsp
 vmx_ept_vpid_cap   = _vmx_ept_vpid_cap;
 vmx_vmexit_control = _vmx_vmexit_control;
 vmx_vmentry_control= _vmx_vmentry_control;
-vmx_basic_msr  = ((u64)vmx_basic_msr_high << 32) |
- vmx_basic_msr_low;
+vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
+ vmx_basic_msr_low;
 vmx_vmfunc = _vmx_vmfunc;
 
 vmx_display_features();
@@ -522,7 +522,7 @@ static int vmx_init_vmcs_config(bool bsp
 mismatch = 1;
 }
 if ( (vmx_basic_msr_high & (VMX_BASIC_VMCS_SIZE_MASK >> 32)) !=
- ((vmx_basic_msr & VMX_BASIC_VMCS_SIZE_MASK) >> 32) )
+ ((vmx_caps.basic_msr & VMX_BASIC_VMCS_SIZE_MASK) >> 32) )
 {
 printk("VMX: CPU%d unexpected VMCS size %Lu\n",
smp_processor_id(),
@@ -2169,7 +2169,7 @@ int __init vmx_vmcs_init(void)
  * _vmx_vcpu_up() may have made it past feature identification.
  * Make sure all dependent features are off as well.
  */
-vmx_basic_msr  = 0;
+memset(&vmx_caps, 0, sizeof(vmx_caps));
 vmx_pin_based_exec_control = 0;
 vmx_cpu_based_exec_control = 0;
 vmx_secondary_exec_control = 0;
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -283,6 +283,12 @@ extern u64 vmx_ept_vpid_cap;
 
 #define VMX_TSC_MULTIPLIER_MAX  0xULL
 
+/* Capabilities and dynamic (run-time adjusted) execution control flags. */
+struct vmx_caps {
+uint64_t basic_msr;
+};
+extern struct vmx_caps vmx_caps;
+
 #define cpu_has_wbinvd_exiting \
 (vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
 #define cpu_has_vmx_virtualize_apic_accesses \
@@ -366,9 +372,8 @@ extern u64 vmx_ept_vpid_cap;
  */
 #define VMX_BASIC_DEFAULT1_ZERO(1ULL << 55)
 
-extern u64 vmx_basic_msr;
 #define cpu_has_vmx_ins_outs_instr_info \
-(!!(vmx_basic_msr & VMX_BASIC_INS_OUT_INFO))
+(!!(vmx_caps.basic_msr & VMX_BASIC_INS_OUT_INFO))
 
 /* Guest interrupt status */
 #define VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK  0x0FF
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1556,7 +1556,7 @@ static int nvmx_handle_vmxon(struct cpu_
 rc = hvm_copy_from_guest_phys(&nvmcs_revid, gpa, sizeof(nvmcs_revid));
 if ( rc != HVMTRANS_okay ||
  (nvmcs_revid & ~VMX_BASIC_REVISION_MASK) ||
- ((nvmcs_revid ^ vmx_basic_msr) & VMX_BASIC_REVISION_MASK) )
+ ((nvmcs_revid ^ vmx_caps.basic_msr) & VMX_BASIC_REVISION_MASK) )
 {
 vmfail_invalid(regs);
 return X86EMUL_OKAY;
@@ -1794,7 +1794,7 @@ static int nvmx_handle_vmptrld(struct cp
 {
 struct vmcs_struct *vvmcs = vvmcx;
 
-if ( ((vvmcs->revision_id ^ vmx_basic_msr) &
+if ( ((vvmcs->revision_id ^ vmx_caps.basic_msr) &
   VMX_BASIC_REVISION_MASK) ||
  (!cpu_has_vmx_vmcs_shadowing &&
   (vvmcs->revision_id & ~VMX_BASIC_REVISION_MASK)) )
@@ -2187,7 +2187,7 @@ int nvmx_msr_read_intercept(unsigned int
 case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
 case MSR_IA32_VMX_TRUE_EXIT_CTLS:
 case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
-if ( !(vmx_basic_msr & VMX_BASIC_DEFAULT1_ZERO) )
+if ( !(vmx_caps.basic_msr & VMX_BASIC_DEFAULT1_ZERO) )
 return 0;
 break;
 




[PATCH v2 10/15] VMX: convert vmx_cpu_based_exec_control

2023-11-24 Thread Jan Beulich
... to a field in the capability/controls struct.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-u32 vmx_cpu_based_exec_control __read_mostly;
 u32 vmx_secondary_exec_control __read_mostly;
 u32 vmx_vmexit_control __read_mostly;
 u32 vmx_vmentry_control __read_mostly;
@@ -238,7 +237,6 @@ static int vmx_init_vmcs_config(bool bsp
 {
 u32 vmx_basic_msr_low, vmx_basic_msr_high, min, opt;
 struct vmx_caps caps;
-u32 _vmx_cpu_based_exec_control;
 u32 _vmx_secondary_exec_control = 0;
 u64 _vmx_ept_vpid_cap = 0;
 u64 _vmx_misc_cap = 0;
@@ -274,12 +272,12 @@ static int vmx_init_vmcs_config(bool bsp
CPU_BASED_TPR_SHADOW |
CPU_BASED_MONITOR_TRAP_FLAG |
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
-_vmx_cpu_based_exec_control = adjust_vmx_controls(
+caps.cpu_based_exec_control = adjust_vmx_controls(
 "CPU-Based Exec Control", min, opt,
 MSR_IA32_VMX_PROCBASED_CTLS, &mismatch);
-_vmx_cpu_based_exec_control &= ~CPU_BASED_RDTSC_EXITING;
-if ( _vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW )
-_vmx_cpu_based_exec_control &=
+caps.cpu_based_exec_control &= ~CPU_BASED_RDTSC_EXITING;
+if ( caps.cpu_based_exec_control & CPU_BASED_TPR_SHADOW )
+caps.cpu_based_exec_control &=
 ~(CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING);
 
 rdmsrl(MSR_IA32_VMX_MISC, _vmx_misc_cap);
@@ -296,7 +294,7 @@ static int vmx_init_vmcs_config(bool bsp
 return -EINVAL;
 }
 
-if ( _vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS )
+if ( caps.cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS )
 {
 min = 0;
 opt = (SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
@@ -326,7 +324,7 @@ static int vmx_init_vmcs_config(bool bsp
  * "APIC Register Virtualization" and "Virtual Interrupt Delivery"
  * can be set only when "use TPR shadow" is set
  */
-if ( (_vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW) &&
+if ( (caps.cpu_based_exec_control & CPU_BASED_TPR_SHADOW) &&
  opt_apicv_enabled )
 opt |= SECONDARY_EXEC_APIC_REGISTER_VIRT |
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
@@ -464,7 +462,6 @@ static int vmx_init_vmcs_config(bool bsp
 {
 /* First time through. */
 vmx_caps = caps;
-vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
 vmx_secondary_exec_control = _vmx_secondary_exec_control;
 vmx_ept_vpid_cap   = _vmx_ept_vpid_cap;
 vmx_vmexit_control = _vmx_vmexit_control;
@@ -496,7 +493,7 @@ static int vmx_init_vmcs_config(bool bsp
 vmx_caps.pin_based_exec_control, caps.pin_based_exec_control);
 mismatch |= cap_check(
 "CPU-Based Exec Control",
-vmx_cpu_based_exec_control, _vmx_cpu_based_exec_control);
+vmx_caps.cpu_based_exec_control, caps.cpu_based_exec_control);
 mismatch |= cap_check(
 "Secondary Exec Control",
 vmx_secondary_exec_control, _vmx_secondary_exec_control);
@@ -1073,7 +1070,7 @@ static int construct_vmcs(struct vcpu *v
 /* VMCS controls. */
 __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_caps.pin_based_exec_control);
 
-v->arch.hvm.vmx.exec_control = vmx_cpu_based_exec_control;
+v->arch.hvm.vmx.exec_control = vmx_caps.cpu_based_exec_control;
 if ( d->arch.vtsc && !cpu_has_vmx_tsc_scaling )
 v->arch.hvm.vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
 
@@ -2169,7 +2166,6 @@ int __init vmx_vmcs_init(void)
  * Make sure all dependent features are off as well.
  */
 memset(&vmx_caps, 0, sizeof(vmx_caps));
-vmx_cpu_based_exec_control = 0;
 vmx_secondary_exec_control = 0;
 vmx_vmexit_control = 0;
 vmx_vmentry_control= 0;
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -208,7 +208,6 @@ void vmx_vmcs_reload(struct vcpu *v);
 #define CPU_BASED_MONITOR_EXITING 0x2000U
 #define CPU_BASED_PAUSE_EXITING   0x4000U
 #define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x8000U
-extern u32 vmx_cpu_based_exec_control;
 
 #define PIN_BASED_EXT_INTR_MASK 0x0001
 #define PIN_BASED_NMI_EXITING   0x0008
@@ -286,6 +285,7 @@ extern u64 vmx_ept_vpid_cap;
 struct vmx_caps {
 uint64_t basic_msr;
 uint32_t pin_based_exec_control;
+uint32_t cpu_based_exec_control;
 };
 extern struct vmx_caps vmx_caps;
 
@@ -294,13 +294,13 @@ extern struct vmx_caps vmx_caps;
 #define cpu_has_vmx_virtualize_apic_accesses \
 (vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)
 #define cpu_has_vmx_tpr_

[PATCH v2 09/15] VMX: convert vmx_pin_based_exec_control

2023-11-24 Thread Jan Beulich
... to a field in the capability/controls struct. Use an instance of
that struct also in vmx_init_vmcs_config().

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-u32 vmx_pin_based_exec_control __read_mostly;
 u32 vmx_cpu_based_exec_control __read_mostly;
 u32 vmx_secondary_exec_control __read_mostly;
 u32 vmx_vmexit_control __read_mostly;
@@ -238,7 +237,7 @@ static bool cap_check(const char *name,
 static int vmx_init_vmcs_config(bool bsp)
 {
 u32 vmx_basic_msr_low, vmx_basic_msr_high, min, opt;
-u32 _vmx_pin_based_exec_control;
+struct vmx_caps caps;
 u32 _vmx_cpu_based_exec_control;
 u32 _vmx_secondary_exec_control = 0;
 u64 _vmx_ept_vpid_cap = 0;
@@ -254,7 +253,7 @@ static int vmx_init_vmcs_config(bool bsp
PIN_BASED_NMI_EXITING);
 opt = (PIN_BASED_VIRTUAL_NMIS |
PIN_BASED_POSTED_INTERRUPT);
-_vmx_pin_based_exec_control = adjust_vmx_controls(
+caps.pin_based_exec_control = adjust_vmx_controls(
 "Pin-Based Exec Control", min, opt,
 MSR_IA32_VMX_PINBASED_CTLS, &mismatch);
 
@@ -406,7 +405,7 @@ static int vmx_init_vmcs_config(bool bsp
 if ( (_vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) &&
   ple_gap == 0 )
 {
-if ( !vmx_pin_based_exec_control )
+if ( !vmx_caps.pin_based_exec_control )
 printk(XENLOG_INFO "Disable Pause-Loop Exiting.\n");
 _vmx_secondary_exec_control &= ~ SECONDARY_EXEC_PAUSE_LOOP_EXITING;
 }
@@ -424,10 +423,10 @@ static int vmx_init_vmcs_config(bool bsp
  * is a minimal requirement, only check the former, which is optional.
  */
 if ( !(_vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) 
)
-_vmx_pin_based_exec_control &= ~PIN_BASED_POSTED_INTERRUPT;
+caps.pin_based_exec_control &= ~PIN_BASED_POSTED_INTERRUPT;
 
 if ( iommu_intpost &&
- !(_vmx_pin_based_exec_control & PIN_BASED_POSTED_INTERRUPT) )
+ !(caps.pin_based_exec_control & PIN_BASED_POSTED_INTERRUPT) )
 {
 printk("Intel VT-d Posted Interrupt is disabled for CPU-side Posted "
"Interrupt is not enabled\n");
@@ -461,10 +460,10 @@ static int vmx_init_vmcs_config(bool bsp
 if ( mismatch )
 return -EINVAL;
 
-if ( !vmx_pin_based_exec_control )
+if ( !vmx_caps.pin_based_exec_control )
 {
 /* First time through. */
-vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
+vmx_caps = caps;
 vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
 vmx_secondary_exec_control = _vmx_secondary_exec_control;
 vmx_ept_vpid_cap   = _vmx_ept_vpid_cap;
@@ -494,7 +493,7 @@ static int vmx_init_vmcs_config(bool bsp
 vmcs_revision_id, vmx_basic_msr_low & VMX_BASIC_REVISION_MASK);
 mismatch |= cap_check(
 "Pin-Based Exec Control",
-vmx_pin_based_exec_control, _vmx_pin_based_exec_control);
+vmx_caps.pin_based_exec_control, caps.pin_based_exec_control);
 mismatch |= cap_check(
 "CPU-Based Exec Control",
 vmx_cpu_based_exec_control, _vmx_cpu_based_exec_control);
@@ -1072,7 +1071,7 @@ static int construct_vmcs(struct vcpu *v
 vmx_vmcs_enter(v);
 
 /* VMCS controls. */
-__vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
+__vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_caps.pin_based_exec_control);
 
 v->arch.hvm.vmx.exec_control = vmx_cpu_based_exec_control;
 if ( d->arch.vtsc && !cpu_has_vmx_tsc_scaling )
@@ -2091,7 +2090,7 @@ void vmcs_dump_vcpu(struct vcpu *v)
 printk("TSC Offset = 0x%016lx  TSC Multiplier = 0x%016lx\n",
vmr(TSC_OFFSET), vmr(TSC_MULTIPLIER));
 if ( (v->arch.hvm.vmx.exec_control & CPU_BASED_TPR_SHADOW) ||
- (vmx_pin_based_exec_control & PIN_BASED_POSTED_INTERRUPT) )
+ (vmx_caps.pin_based_exec_control & PIN_BASED_POSTED_INTERRUPT) )
 printk("TPR Threshold = 0x%02x  PostedIntrVec = 0x%02x\n",
vmr32(TPR_THRESHOLD), vmr16(POSTED_INTR_NOTIFICATION_VECTOR));
 if ( (v->arch.hvm.vmx.secondary_exec_control &
@@ -2170,7 +2169,6 @@ int __init vmx_vmcs_init(void)
  * Make sure all dependent features are off as well.
  */
 memset(&vmx_caps, 0, sizeof(vmx_caps));
-vmx_pin_based_exec_control = 0;
 vmx_cpu_based_exec_control = 0;
 vmx_secondary_exec_control = 0;
 vmx_vmexit_control = 0;
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1054,7 +1054,7 @@ static void load_shadow_control(struct v
  * and EXCEPTION
  * Enforce the removed features
  */
-nvmx_update_pin_control(v, vmx_pin_based_exec_control);
+nvmx_update_pin_contr

[PATCH v2 11/15] VMX: convert vmx_secondary_exec_control

2023-11-24 Thread Jan Beulich
... to a field in the capability/controls struct.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-u32 vmx_secondary_exec_control __read_mostly;
 u32 vmx_vmexit_control __read_mostly;
 u32 vmx_vmentry_control __read_mostly;
 u64 vmx_ept_vpid_cap __read_mostly;
@@ -237,7 +236,6 @@ static int vmx_init_vmcs_config(bool bsp
 {
 u32 vmx_basic_msr_low, vmx_basic_msr_high, min, opt;
 struct vmx_caps caps;
-u32 _vmx_secondary_exec_control = 0;
 u64 _vmx_ept_vpid_cap = 0;
 u64 _vmx_misc_cap = 0;
 u32 _vmx_vmexit_control;
@@ -330,13 +328,13 @@ static int vmx_init_vmcs_config(bool bsp
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
 
-_vmx_secondary_exec_control = adjust_vmx_controls(
+caps.secondary_exec_control = adjust_vmx_controls(
 "Secondary Exec Control", min, opt,
 MSR_IA32_VMX_PROCBASED_CTLS2, &mismatch);
 }
 
 /* The IA32_VMX_EPT_VPID_CAP MSR exists only when EPT or VPID available */
-if ( _vmx_secondary_exec_control & (SECONDARY_EXEC_ENABLE_EPT |
+if ( caps.secondary_exec_control & (SECONDARY_EXEC_ENABLE_EPT |
 SECONDARY_EXEC_ENABLE_VPID) )
 {
 rdmsrl(MSR_IA32_VMX_EPT_VPID_CAP, _vmx_ept_vpid_cap);
@@ -358,7 +356,7 @@ static int vmx_init_vmcs_config(bool bsp
 if ( !(_vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_WB) ||
  !(_vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) ||
  !(_vmx_ept_vpid_cap & VMX_EPT_INVEPT_ALL_CONTEXT) )
-_vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
 
 /*
  * the CPU must support INVVPID all context invalidation, because we
@@ -367,14 +365,14 @@ static int vmx_init_vmcs_config(bool bsp
  * Or we just don't use VPID.
  */
 if ( !(_vmx_ept_vpid_cap & VMX_VPID_INVVPID_ALL_CONTEXT) )
-_vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
+caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
 
 /* EPT A/D bits is required for PML */
 if ( !(_vmx_ept_vpid_cap & VMX_EPT_AD_BIT) )
-_vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
+caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
 }
 
-if ( _vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT )
+if ( caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT )
 {
 /*
  * To use EPT we expect to be able to clear certain intercepts.
@@ -387,25 +385,25 @@ static int vmx_init_vmcs_config(bool bsp
 if ( must_be_one & (CPU_BASED_INVLPG_EXITING |
 CPU_BASED_CR3_LOAD_EXITING |
 CPU_BASED_CR3_STORE_EXITING) )
-_vmx_secondary_exec_control &=
+caps.secondary_exec_control &=
 ~(SECONDARY_EXEC_ENABLE_EPT |
   SECONDARY_EXEC_UNRESTRICTED_GUEST);
 }
 
 /* PML cannot be supported if EPT is not used */
-if ( !(_vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) )
-_vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
+if ( !(caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) )
+caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
 
 /* Turn off opt_ept_pml if PML feature is not present. */
-if ( !(_vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_PML) )
+if ( !(caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_PML) )
 opt_ept_pml = false;
 
-if ( (_vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) &&
+if ( (caps.secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) &&
   ple_gap == 0 )
 {
 if ( !vmx_caps.pin_based_exec_control )
 printk(XENLOG_INFO "Disable Pause-Loop Exiting.\n");
-_vmx_secondary_exec_control &= ~ SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+caps.secondary_exec_control &= ~ SECONDARY_EXEC_PAUSE_LOOP_EXITING;
 }
 
 min = VM_EXIT_ACK_INTR_ON_EXIT;
@@ -420,7 +418,7 @@ static int vmx_init_vmcs_config(bool bsp
  * delivery" and "acknowledge interrupt on exit" is set. For the latter
  * is a minimal requirement, only check the former, which is optional.
  */
-if ( !(_vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) 
)
+if ( !(caps.secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) 
)
 caps.pin_based_exec_control &= ~PIN_BASED_POSTED_INTERRUPT;
 
 if ( iommu_intpost &&
@@ -432,7 +430,7 @@ static int vmx_init_vmcs_config(bool bsp
 }
 
 /* The IA32_VMX_VMFUNC MSR exists only when VMFUNC is available */

[PATCH v2 12/15] VMX: convert vmx_vmexit_control

2023-11-24 Thread Jan Beulich
... to a field in the capability/controls struct.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-u32 vmx_vmexit_control __read_mostly;
 u32 vmx_vmentry_control __read_mostly;
 u64 vmx_ept_vpid_cap __read_mostly;
 static uint64_t __read_mostly vmx_vmfunc;
@@ -238,7 +237,6 @@ static int vmx_init_vmcs_config(bool bsp
 struct vmx_caps caps;
 u64 _vmx_ept_vpid_cap = 0;
 u64 _vmx_misc_cap = 0;
-u32 _vmx_vmexit_control;
 u32 _vmx_vmentry_control;
 u64 _vmx_vmfunc = 0;
 bool mismatch = false;
@@ -410,7 +408,7 @@ static int vmx_init_vmcs_config(bool bsp
 opt = (VM_EXIT_SAVE_GUEST_PAT | VM_EXIT_LOAD_HOST_PAT |
VM_EXIT_LOAD_HOST_EFER | VM_EXIT_CLEAR_BNDCFGS);
 min |= VM_EXIT_IA32E_MODE;
-_vmx_vmexit_control = adjust_vmx_controls(
+caps.vmexit_control = adjust_vmx_controls(
 "VMExit Control", min, opt, MSR_IA32_VMX_EXIT_CTLS, &mismatch);
 
 /*
@@ -461,7 +459,6 @@ static int vmx_init_vmcs_config(bool bsp
 /* First time through. */
 vmx_caps = caps;
 vmx_ept_vpid_cap   = _vmx_ept_vpid_cap;
-vmx_vmexit_control = _vmx_vmexit_control;
 vmx_vmentry_control= _vmx_vmentry_control;
 vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
  vmx_basic_msr_low;
@@ -496,7 +493,7 @@ static int vmx_init_vmcs_config(bool bsp
 vmx_caps.secondary_exec_control, caps.secondary_exec_control);
 mismatch |= cap_check(
 "VMExit Control",
-vmx_vmexit_control, _vmx_vmexit_control);
+vmx_caps.vmexit_control, caps.vmexit_control);
 mismatch |= cap_check(
 "VMEntry Control",
 vmx_vmentry_control, _vmx_vmentry_control);
@@ -1058,7 +1055,7 @@ void nocall vmx_asm_vmexit_handler(void)
 static int construct_vmcs(struct vcpu *v)
 {
 struct domain *d = v->domain;
-u32 vmexit_ctl = vmx_vmexit_control;
+uint32_t vmexit_ctl = vmx_caps.vmexit_control;
 u32 vmentry_ctl = vmx_vmentry_control;
 int rc = 0;
 
@@ -2163,7 +2160,6 @@ int __init vmx_vmcs_init(void)
  * Make sure all dependent features are off as well.
  */
 memset(&vmx_caps, 0, sizeof(vmx_caps));
-vmx_vmexit_control = 0;
 vmx_vmentry_control= 0;
 vmx_ept_vpid_cap   = 0;
 vmx_vmfunc = 0;
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1057,7 +1057,7 @@ static void load_shadow_control(struct v
 nvmx_update_pin_control(v, vmx_caps.pin_based_exec_control);
 vmx_update_cpu_exec_control(v);
 vmx_update_secondary_exec_control(v);
-nvmx_update_exit_control(v, vmx_vmexit_control);
+nvmx_update_exit_control(v, vmx_caps.vmexit_control);
 nvmx_update_entry_control(v);
 vmx_update_exception_bitmap(v);
 nvmx_update_apic_access_address(v);
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -225,7 +225,6 @@ void vmx_vmcs_reload(struct vcpu *v);
 #define VM_EXIT_LOAD_HOST_EFER  0x0020
 #define VM_EXIT_SAVE_PREEMPT_TIMER  0x0040
 #define VM_EXIT_CLEAR_BNDCFGS   0x0080
-extern u32 vmx_vmexit_control;
 
 #define VM_ENTRY_IA32E_MODE 0x0200
 #define VM_ENTRY_SMM0x0400
@@ -286,6 +285,7 @@ struct vmx_caps {
 uint32_t pin_based_exec_control;
 uint32_t cpu_based_exec_control;
 uint32_t secondary_exec_control;
+uint32_t vmexit_control;
 };
 extern struct vmx_caps vmx_caps;
 
@@ -341,7 +341,7 @@ extern struct vmx_caps vmx_caps;
 #define cpu_has_vmx_pml \
 (vmx_caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_PML)
 #define cpu_has_vmx_mpx \
-((vmx_vmexit_control & VM_EXIT_CLEAR_BNDCFGS) && \
+((vmx_caps.vmexit_control & VM_EXIT_CLEAR_BNDCFGS) && \
  (vmx_vmentry_control & VM_ENTRY_LOAD_BNDCFGS))
 #define cpu_has_vmx_xsaves \
 (vmx_caps.secondary_exec_control & SECONDARY_EXEC_XSAVES)




[PATCH v2 13/15] VMX: convert vmx_vmentry_control

2023-11-24 Thread Jan Beulich
... to a field in the capability/controls struct.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-u32 vmx_vmentry_control __read_mostly;
 u64 vmx_ept_vpid_cap __read_mostly;
 static uint64_t __read_mostly vmx_vmfunc;
 
@@ -237,7 +236,6 @@ static int vmx_init_vmcs_config(bool bsp
 struct vmx_caps caps;
 u64 _vmx_ept_vpid_cap = 0;
 u64 _vmx_misc_cap = 0;
-u32 _vmx_vmentry_control;
 u64 _vmx_vmfunc = 0;
 bool mismatch = false;
 
@@ -448,7 +446,7 @@ static int vmx_init_vmcs_config(bool bsp
 min = 0;
 opt = (VM_ENTRY_LOAD_GUEST_PAT | VM_ENTRY_LOAD_GUEST_EFER |
VM_ENTRY_LOAD_BNDCFGS);
-_vmx_vmentry_control = adjust_vmx_controls(
+caps.vmentry_control = adjust_vmx_controls(
 "VMEntry Control", min, opt, MSR_IA32_VMX_ENTRY_CTLS, &mismatch);
 
 if ( mismatch )
@@ -459,7 +457,6 @@ static int vmx_init_vmcs_config(bool bsp
 /* First time through. */
 vmx_caps = caps;
 vmx_ept_vpid_cap   = _vmx_ept_vpid_cap;
-vmx_vmentry_control= _vmx_vmentry_control;
 vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
  vmx_basic_msr_low;
 vmx_vmfunc = _vmx_vmfunc;
@@ -496,7 +493,7 @@ static int vmx_init_vmcs_config(bool bsp
 vmx_caps.vmexit_control, caps.vmexit_control);
 mismatch |= cap_check(
 "VMEntry Control",
-vmx_vmentry_control, _vmx_vmentry_control);
+vmx_caps.vmentry_control, caps.vmentry_control);
 mismatch |= cap_check(
 "EPT and VPID Capability",
 vmx_ept_vpid_cap, _vmx_ept_vpid_cap);
@@ -1056,7 +1053,7 @@ static int construct_vmcs(struct vcpu *v
 {
 struct domain *d = v->domain;
 uint32_t vmexit_ctl = vmx_caps.vmexit_control;
-u32 vmentry_ctl = vmx_vmentry_control;
+u32 vmentry_ctl = vmx_caps.vmentry_control;
 int rc = 0;
 
 vmx_vmcs_enter(v);
@@ -2160,7 +2157,6 @@ int __init vmx_vmcs_init(void)
  * Make sure all dependent features are off as well.
  */
 memset(&vmx_caps, 0, sizeof(vmx_caps));
-vmx_vmentry_control= 0;
 vmx_ept_vpid_cap   = 0;
 vmx_vmfunc = 0;
 }
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -233,7 +233,6 @@ void vmx_vmcs_reload(struct vcpu *v);
 #define VM_ENTRY_LOAD_GUEST_PAT 0x4000
 #define VM_ENTRY_LOAD_GUEST_EFER0x8000
 #define VM_ENTRY_LOAD_BNDCFGS   0x0001
-extern u32 vmx_vmentry_control;
 
 #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x0001U
 #define SECONDARY_EXEC_ENABLE_EPT   0x0002U
@@ -286,6 +285,7 @@ struct vmx_caps {
 uint32_t cpu_based_exec_control;
 uint32_t secondary_exec_control;
 uint32_t vmexit_control;
+uint32_t vmentry_control;
 };
 extern struct vmx_caps vmx_caps;
 
@@ -312,9 +312,9 @@ extern struct vmx_caps vmx_caps;
 #define cpu_has_monitor_trap_flag \
 (vmx_caps.cpu_based_exec_control & CPU_BASED_MONITOR_TRAP_FLAG)
 #define cpu_has_vmx_pat \
-(vmx_vmentry_control & VM_ENTRY_LOAD_GUEST_PAT)
+(vmx_caps.vmentry_control & VM_ENTRY_LOAD_GUEST_PAT)
 #define cpu_has_vmx_efer \
-(vmx_vmentry_control & VM_ENTRY_LOAD_GUEST_EFER)
+(vmx_caps.vmentry_control & VM_ENTRY_LOAD_GUEST_EFER)
 #define cpu_has_vmx_unrestricted_guest \
 (vmx_caps.secondary_exec_control & SECONDARY_EXEC_UNRESTRICTED_GUEST)
 #define vmx_unrestricted_guest(v)   \
@@ -342,7 +342,7 @@ extern struct vmx_caps vmx_caps;
 (vmx_caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_PML)
 #define cpu_has_vmx_mpx \
 ((vmx_caps.vmexit_control & VM_EXIT_CLEAR_BNDCFGS) && \
- (vmx_vmentry_control & VM_ENTRY_LOAD_BNDCFGS))
+ (vmx_caps.vmentry_control & VM_ENTRY_LOAD_BNDCFGS))
 #define cpu_has_vmx_xsaves \
 (vmx_caps.secondary_exec_control & SECONDARY_EXEC_XSAVES)
 #define cpu_has_vmx_tsc_scaling \




[PATCH v2 14/15] VMX: convert vmx_vmfunc

2023-11-24 Thread Jan Beulich
... to a field in the capability/controls struct.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-static uint64_t __read_mostly vmx_vmfunc;
 
 static DEFINE_PER_CPU_READ_MOSTLY(paddr_t, vmxon_region);
 static DEFINE_PER_CPU(paddr_t, current_vmcs);
@@ -234,7 +233,6 @@ static int vmx_init_vmcs_config(bool bsp
 u32 vmx_basic_msr_low, vmx_basic_msr_high, min, opt;
 struct vmx_caps caps;
 u64 _vmx_misc_cap = 0;
-u64 _vmx_vmfunc = 0;
 bool mismatch = false;
 
 rdmsr(MSR_IA32_VMX_BASIC, vmx_basic_msr_low, vmx_basic_msr_high);
@@ -426,14 +424,14 @@ static int vmx_init_vmcs_config(bool bsp
 /* The IA32_VMX_VMFUNC MSR exists only when VMFUNC is available */
 if ( caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_VM_FUNCTIONS )
 {
-rdmsrl(MSR_IA32_VMX_VMFUNC, _vmx_vmfunc);
+rdmsrl(MSR_IA32_VMX_VMFUNC, caps.vmfunc);
 
 /*
  * VMFUNC leaf 0 (EPTP switching) must be supported.
  *
  * Or we just don't use VMFUNC.
  */
-if ( !(_vmx_vmfunc & VMX_VMFUNC_EPTP_SWITCHING) )
+if ( !(caps.vmfunc & VMX_VMFUNC_EPTP_SWITCHING) )
 caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VM_FUNCTIONS;
 }
 
@@ -456,7 +454,6 @@ static int vmx_init_vmcs_config(bool bsp
 vmx_caps = caps;
 vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
  vmx_basic_msr_low;
-vmx_vmfunc = _vmx_vmfunc;
 
 vmx_display_features();
 
@@ -495,7 +492,7 @@ static int vmx_init_vmcs_config(bool bsp
 mismatch |= cap_check("VPID Capability", vmx_caps.vpid, caps.vpid);
 mismatch |= cap_check(
 "VMFUNC Capability",
-vmx_vmfunc, _vmx_vmfunc);
+vmx_caps.vmfunc, caps.vmfunc);
 if ( cpu_has_vmx_ins_outs_instr_info !=
  !!(vmx_basic_msr_high & (VMX_BASIC_INS_OUT_INFO >> 32)) )
 {
@@ -2153,7 +2150,6 @@ int __init vmx_vmcs_init(void)
  * Make sure all dependent features are off as well.
  */
 memset(&vmx_caps, 0, sizeof(vmx_caps));
-vmx_vmfunc = 0;
 }
 
 return ret;
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -287,6 +287,7 @@ struct vmx_caps {
 uint32_t vmentry_control;
 uint32_t ept;
 uint32_t vpid;
+uint64_t vmfunc;
 };
 extern struct vmx_caps vmx_caps;
 




[PATCH v2 14/15] VMX: convert vmx_ept_vpid_cap

2023-11-24 Thread Jan Beulich
... to fields in the capability/controls struct: Take the opportunity
and split the two halves into separate EPT and VPID fields.

Signed-off-by: Jan Beulich 
---
v2: New.

--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
 
 /* Dynamic (run-time adjusted) execution control flags. */
 struct vmx_caps __ro_after_init vmx_caps;
-u64 vmx_ept_vpid_cap __read_mostly;
 static uint64_t __read_mostly vmx_vmfunc;
 
 static DEFINE_PER_CPU_READ_MOSTLY(paddr_t, vmxon_region);
@@ -234,7 +233,6 @@ static int vmx_init_vmcs_config(bool bsp
 {
 u32 vmx_basic_msr_low, vmx_basic_msr_high, min, opt;
 struct vmx_caps caps;
-u64 _vmx_ept_vpid_cap = 0;
 u64 _vmx_misc_cap = 0;
 u64 _vmx_vmfunc = 0;
 bool mismatch = false;
@@ -333,10 +331,10 @@ static int vmx_init_vmcs_config(bool bsp
 if ( caps.secondary_exec_control & (SECONDARY_EXEC_ENABLE_EPT |
 SECONDARY_EXEC_ENABLE_VPID) )
 {
-rdmsrl(MSR_IA32_VMX_EPT_VPID_CAP, _vmx_ept_vpid_cap);
+rdmsr(MSR_IA32_VMX_EPT_VPID_CAP, caps.ept, caps.vpid);
 
 if ( !opt_ept_ad )
-_vmx_ept_vpid_cap &= ~VMX_EPT_AD_BIT;
+caps.ept &= ~VMX_EPT_AD_BIT;
 
 /*
  * Additional sanity checking before using EPT:
@@ -349,9 +347,9 @@ static int vmx_init_vmcs_config(bool bsp
  *
  * Or we just don't use EPT.
  */
-if ( !(_vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_WB) ||
- !(_vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) ||
- !(_vmx_ept_vpid_cap & VMX_EPT_INVEPT_ALL_CONTEXT) )
+if ( !(caps.ept & VMX_EPT_MEMORY_TYPE_WB) ||
+ !(caps.ept & VMX_EPT_WALK_LENGTH_4_SUPPORTED) ||
+ !(caps.ept & VMX_EPT_INVEPT_ALL_CONTEXT) )
 caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
 
 /*
@@ -360,11 +358,11 @@ static int vmx_init_vmcs_config(bool bsp
  *
  * Or we just don't use VPID.
  */
-if ( !(_vmx_ept_vpid_cap & VMX_VPID_INVVPID_ALL_CONTEXT) )
+if ( !(caps.vpid & VMX_VPID_INVVPID_ALL_CONTEXT) )
 caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
 
 /* EPT A/D bits is required for PML */
-if ( !(_vmx_ept_vpid_cap & VMX_EPT_AD_BIT) )
+if ( !(caps.ept & VMX_EPT_AD_BIT) )
 caps.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
 }
 
@@ -456,7 +454,6 @@ static int vmx_init_vmcs_config(bool bsp
 {
 /* First time through. */
 vmx_caps = caps;
-vmx_ept_vpid_cap   = _vmx_ept_vpid_cap;
 vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
  vmx_basic_msr_low;
 vmx_vmfunc = _vmx_vmfunc;
@@ -494,9 +491,8 @@ static int vmx_init_vmcs_config(bool bsp
 mismatch |= cap_check(
 "VMEntry Control",
 vmx_caps.vmentry_control, caps.vmentry_control);
-mismatch |= cap_check(
-"EPT and VPID Capability",
-vmx_ept_vpid_cap, _vmx_ept_vpid_cap);
+mismatch |= cap_check("EPT Capability", vmx_caps.ept, caps.ept);
+mismatch |= cap_check("VPID Capability", vmx_caps.vpid, caps.vpid);
 mismatch |= cap_check(
 "VMFUNC Capability",
 vmx_vmfunc, _vmx_vmfunc);
@@ -2157,7 +2153,6 @@ int __init vmx_vmcs_init(void)
  * Make sure all dependent features are off as well.
  */
 memset(&vmx_caps, 0, sizeof(vmx_caps));
-vmx_ept_vpid_cap   = 0;
 vmx_vmfunc = 0;
 }
 
--- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
@@ -265,12 +265,11 @@ void vmx_vmcs_reload(struct vcpu *v);
 #define VMX_EPT_AD_BIT  0x0020
 #define VMX_EPT_INVEPT_SINGLE_CONTEXT   0x0200
 #define VMX_EPT_INVEPT_ALL_CONTEXT  0x0400
-#define VMX_VPID_INVVPID_INSTRUCTION 0x001ULL
-#define VMX_VPID_INVVPID_INDIVIDUAL_ADDR 0x100ULL
-#define VMX_VPID_INVVPID_SINGLE_CONTEXT  0x200ULL
-#define VMX_VPID_INVVPID_ALL_CONTEXT 0x400ULL
-#define VMX_VPID_INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL 0x800ULL
-extern u64 vmx_ept_vpid_cap;
+#define VMX_VPID_INVVPID_INSTRUCTION0x0001
+#define VMX_VPID_INVVPID_INDIVIDUAL_ADDR0x0100
+#define VMX_VPID_INVVPID_SINGLE_CONTEXT 0x0200
+#define VMX_VPID_INVVPID_ALL_CONTEXT0x0400
+#define VMX_VPID_INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL0x0800
 
 #define VMX_MISC_PROC_TRACE 0x4000
 #define VMX_MISC_CR3_TARGET 0x01ff
@@ -286,6 +285,8 @@ struct vmx_caps {
 uint32_t secondary_exec_con

Re: [PATCH v2 15/15] VMX: convert vmx_vmfunc

2023-11-24 Thread Jan Beulich
On 24.11.2023 09:43, Jan Beulich wrote:
> ... to a field in the capability/controls struct.
> 
> Signed-off-by: Jan Beulich 
> ---
> v2: New.

I'm sorry, this really is 15/15 ($subject also adjusted).

Jan

> --- a/xen/arch/x86/hvm/vmx/vmcs.c
> +++ b/xen/arch/x86/hvm/vmx/vmcs.c
> @@ -162,7 +162,6 @@ static int cf_check parse_ept_param_runt
>  
>  /* Dynamic (run-time adjusted) execution control flags. */
>  struct vmx_caps __ro_after_init vmx_caps;
> -static uint64_t __read_mostly vmx_vmfunc;
>  
>  static DEFINE_PER_CPU_READ_MOSTLY(paddr_t, vmxon_region);
>  static DEFINE_PER_CPU(paddr_t, current_vmcs);
> @@ -234,7 +233,6 @@ static int vmx_init_vmcs_config(bool bsp
>  u32 vmx_basic_msr_low, vmx_basic_msr_high, min, opt;
>  struct vmx_caps caps;
>  u64 _vmx_misc_cap = 0;
> -u64 _vmx_vmfunc = 0;
>  bool mismatch = false;
>  
>  rdmsr(MSR_IA32_VMX_BASIC, vmx_basic_msr_low, vmx_basic_msr_high);
> @@ -426,14 +424,14 @@ static int vmx_init_vmcs_config(bool bsp
>  /* The IA32_VMX_VMFUNC MSR exists only when VMFUNC is available */
>  if ( caps.secondary_exec_control & SECONDARY_EXEC_ENABLE_VM_FUNCTIONS )
>  {
> -rdmsrl(MSR_IA32_VMX_VMFUNC, _vmx_vmfunc);
> +rdmsrl(MSR_IA32_VMX_VMFUNC, caps.vmfunc);
>  
>  /*
>   * VMFUNC leaf 0 (EPTP switching) must be supported.
>   *
>   * Or we just don't use VMFUNC.
>   */
> -if ( !(_vmx_vmfunc & VMX_VMFUNC_EPTP_SWITCHING) )
> +if ( !(caps.vmfunc & VMX_VMFUNC_EPTP_SWITCHING) )
>  caps.secondary_exec_control &= 
> ~SECONDARY_EXEC_ENABLE_VM_FUNCTIONS;
>  }
>  
> @@ -456,7 +454,6 @@ static int vmx_init_vmcs_config(bool bsp
>  vmx_caps = caps;
>  vmx_caps.basic_msr = ((uint64_t)vmx_basic_msr_high << 32) |
>   vmx_basic_msr_low;
> -vmx_vmfunc = _vmx_vmfunc;
>  
>  vmx_display_features();
>  
> @@ -495,7 +492,7 @@ static int vmx_init_vmcs_config(bool bsp
>  mismatch |= cap_check("VPID Capability", vmx_caps.vpid, caps.vpid);
>  mismatch |= cap_check(
>  "VMFUNC Capability",
> -vmx_vmfunc, _vmx_vmfunc);
> +vmx_caps.vmfunc, caps.vmfunc);
>  if ( cpu_has_vmx_ins_outs_instr_info !=
>   !!(vmx_basic_msr_high & (VMX_BASIC_INS_OUT_INFO >> 32)) )
>  {
> @@ -2153,7 +2150,6 @@ int __init vmx_vmcs_init(void)
>   * Make sure all dependent features are off as well.
>   */
>  memset(&vmx_caps, 0, sizeof(vmx_caps));
> -vmx_vmfunc = 0;
>  }
>  
>  return ret;
> --- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
> +++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h
> @@ -287,6 +287,7 @@ struct vmx_caps {
>  uint32_t vmentry_control;
>  uint32_t ept;
>  uint32_t vpid;
> +uint64_t vmfunc;
>  };
>  extern struct vmx_caps vmx_caps;
>  
> 
> 




xen | Successful pipeline for staging | 80c153c4

2023-11-24 Thread GitLab


Pipeline #1083711882 has passed!

Project: xen ( https://gitlab.com/xen-project/xen )
Branch: staging ( https://gitlab.com/xen-project/xen/-/commits/staging )

Commit: 80c153c4 ( 
https://gitlab.com/xen-project/xen/-/commit/80c153c48b255bae61948827241c26671207cf4e
 )
Commit Message: xen/sort: address violations of MISRA C:2012 Ru...
Commit Author: Federico Serafini
Committed by: Jan Beulich ( https://gitlab.com/jbeulich )



Pipeline #1083711882 ( 
https://gitlab.com/xen-project/xen/-/pipelines/1083711882 ) triggered by Ganis 
( https://gitlab.com/ganis )
successfully completed 129 jobs in 3 stages.

-- 
You're receiving this email because of your account on gitlab.com.





MISRA: Compatible declarations for sort and bsearch

2023-11-24 Thread Nicola Vetrini

Hi all,

in xen/lib.h and xen/sort.h there are definitions of the functions 
bsearch and sort that have no prior declarations, and therefore are 
subject to a violation of MISRA C Rule 8.4.


I'm wondering whether it would be preferred

1. to put a declaration just before the definition, in lib.h and sort.h
2. deviate these functions, as their signatures are well-known and 
somewhat standardized


other resolution strategies are possible, but I think these are the main 
ones.


--
Nicola Vetrini, BSc
Software Engineer, BUGSENG srl (https://bugseng.com)



[PATCH v6 2/5] xen/arm: Add asm/domain.h include to kernel.h

2023-11-24 Thread Luca Fancellu
The 'enum domain_type' is defined by 'asm/domain.h' which is not
included (directly or indirectly) by 'asm/kernel.h'.

This currently doesn't break the compilation because asm/domain.h will
included by the user of 'kernel.h'. But it would be better to avoid
relying on it. So add the include in 'asm/domain.h'.

Signed-off-by: Luca Fancellu 
Acked-by: Julien Grall 
---
Changes from v2:
 - add Ack-by Julien
Changes from v1:
 - Rephrased commit message (Julien)
---
 xen/arch/arm/include/asm/kernel.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xen/arch/arm/include/asm/kernel.h 
b/xen/arch/arm/include/asm/kernel.h
index 4617cdc83bac..0a23e86c2d37 100644
--- a/xen/arch/arm/include/asm/kernel.h
+++ b/xen/arch/arm/include/asm/kernel.h
@@ -7,6 +7,7 @@
 #define __ARCH_ARM_KERNEL_H__
 
 #include 
+#include 
 #include 
 
 /*
-- 
2.34.1




[PATCH v6 4/5] xen/arm: Move static memory build code in separate modules

2023-11-24 Thread Luca Fancellu
Move static memory and static shared memory code in separate modules
so that they are included only when the corresponding feature is
enabled, doing that we modularise the features and we remove some
ifdefs from the code to improve readability.

Move process_shm_node function from bootfdt module and make it
externally visible.

A static inline helper called process_shm_chosen is introduced, it
will call the process_shm function for the '/chosen' node, and will
be used by the function construct_dom0 instead of using directly
process_shm, allowing some #ifdef to be removed.

No functional changes are intended.

Signed-off-by: Luca Fancellu 
---
Changes from v5:
 - removed init_staticmem_pages prototype from setup.h, add
   static-memory.h include in arm{32,64}/mmu/mm.c, dropped
   Michal R-by given the changes
Changes from v4:
 - Removed header from static-*.{c,h} files, fixed style issue,
   renamed inclusion define __ARM_* to __ASM_*, fixed emacs
   local variables. (Michal)
Changes from v3:
 - Moved make_resv_memory_node from domain_build to static-shmem,
   make make_shm_memory_node static.
Changes from v2:
 - no changes
---
 xen/arch/arm/Makefile|   2 +
 xen/arch/arm/arm32/mmu/mm.c  |   1 +
 xen/arch/arm/arm64/mmu/mm.c  |   1 +
 xen/arch/arm/bootfdt.c   | 161 +-
 xen/arch/arm/dom0less-build.c|   4 +-
 xen/arch/arm/domain_build.c  | 654 +--
 xen/arch/arm/include/asm/domain_build.h  |  26 -
 xen/arch/arm/include/asm/setup.h |   1 -
 xen/arch/arm/include/asm/static-memory.h |  45 ++
 xen/arch/arm/include/asm/static-shmem.h  |  66 +++
 xen/arch/arm/setup.c |  24 -
 xen/arch/arm/static-memory.c | 287 ++
 xen/arch/arm/static-shmem.c  | 547 +++
 13 files changed, 954 insertions(+), 865 deletions(-)
 create mode 100644 xen/arch/arm/include/asm/static-memory.h
 create mode 100644 xen/arch/arm/include/asm/static-shmem.h
 create mode 100644 xen/arch/arm/static-memory.c
 create mode 100644 xen/arch/arm/static-shmem.c

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index d65920b0a8cf..2fcc3c2535fd 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -51,6 +51,8 @@ obj-y += setup.o
 obj-y += shutdown.o
 obj-y += smp.o
 obj-y += smpboot.o
+obj-$(CONFIG_STATIC_MEMORY) += static-memory.init.o
+obj-$(CONFIG_STATIC_SHM) += static-shmem.init.o
 obj-y += sysctl.o
 obj-y += time.o
 obj-y += traps.o
diff --git a/xen/arch/arm/arm32/mmu/mm.c b/xen/arch/arm/arm32/mmu/mm.c
index 94d6cab49cc9..cb441ca87c0d 100644
--- a/xen/arch/arm/arm32/mmu/mm.c
+++ b/xen/arch/arm/arm32/mmu/mm.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static unsigned long opt_xenheap_megabytes __initdata;
 integer_param("xenheap_megabytes", opt_xenheap_megabytes);
diff --git a/xen/arch/arm/arm64/mmu/mm.c b/xen/arch/arm/arm64/mmu/mm.c
index e05d54c850ac..d2651c948698 100644
--- a/xen/arch/arm/arm64/mmu/mm.c
+++ b/xen/arch/arm/arm64/mmu/mm.c
@@ -5,6 +5,7 @@
 #include 
 
 #include 
+#include 
 
 /* Override macros from asm/page.h to make them work with mfn_t */
 #undef virt_to_mfn
diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index d73f8e497193..b1f03eb2fcdd 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static bool __init device_tree_node_is_available(const void *fdt, int node)
 {
@@ -423,166 +424,6 @@ static int __init process_domain_node(const void *fdt, 
int node,
MEMBANK_STATIC_DOMAIN);
 }
 
-#ifdef CONFIG_STATIC_SHM
-static int __init process_shm_node(const void *fdt, int node,
-   uint32_t address_cells, uint32_t size_cells)
-{
-const struct fdt_property *prop, *prop_id, *prop_role;
-const __be32 *cell;
-paddr_t paddr, gaddr, size;
-struct meminfo *mem = &bootinfo.reserved_mem;
-unsigned int i;
-int len;
-bool owner = false;
-const char *shm_id;
-
-if ( address_cells < 1 || size_cells < 1 )
-{
-printk("fdt: invalid #address-cells or #size-cells for static shared 
memory node.\n");
-return -EINVAL;
-}
-
-/*
- * "xen,shm-id" property holds an arbitrary string with a strict limit
- * on the number of characters, MAX_SHM_ID_LENGTH
- */
-prop_id = fdt_get_property(fdt, node, "xen,shm-id", NULL);
-if ( !prop_id )
-return -ENOENT;
-shm_id = (const char *)prop_id->data;
-if ( strnlen(shm_id, MAX_SHM_ID_LENGTH) == MAX_SHM_ID_LENGTH )
-{
-printk("fdt: invalid xen,shm-id %s, it must be limited to %u 
characters\n",
-   shm_id, MAX_SHM_ID_LENGTH);
-return -EINVAL;
-}
-
-/*
- * "role" property is optional and if it is defined explicitly,
- * it must be either `owner` or `borrower`.
- */
-prop_role = fdt_get_property(fdt, node, "

[PATCH v6 1/5] arm/gicv2: make GICv2 driver and vGICv2 optional

2023-11-24 Thread Luca Fancellu
Introduce Kconfig GICV2 to be able to compile the GICv2 driver only
when needed, the option is active by default.

Introduce Kconfig VGICV2 that compiles the Generic Interrupt
Controller v2 emulation for domains, it is required only when using
GICv2 driver, otherwise using the GICv3 driver it is optional and can
be deselected if the user doesn't want to offer the v2 emulation to
domains or maybe its GICv3 hardware can't offer the GICv2 compatible
mode.

Signed-off-by: Luca Fancellu 
Reviewed-by: Julien Grall 
Reviewed-by: Michal Orzel 
---
Changes from v2:
 - No changes
---
 xen/arch/arm/Kconfig| 19 +++
 xen/arch/arm/Makefile   |  4 ++--
 xen/arch/arm/domain_build.c |  4 
 xen/arch/arm/gic-v3.c   |  4 
 xen/arch/arm/vgic.c |  2 ++
 xen/arch/arm/vgic/Makefile  |  4 ++--
 6 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 7b5b0c0c05e7..57dc9957124f 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -80,6 +80,14 @@ config ARM_EFI
  UEFI firmware. A UEFI stub is provided to allow Xen to
  be booted as an EFI application.
 
+config GICV2
+   bool "GICv2 driver"
+   default y
+   select VGICV2
+   help
+ Driver for the ARM Generic Interrupt Controller v2.
+ If unsure, say Y
+
 config GICV3
bool "GICv3 driver"
depends on !NEW_VGIC
@@ -99,11 +107,22 @@ config OVERLAY_DTB
help
  Dynamic addition/removal of Xen device tree nodes using a dtbo.
 
+config VGICV2
+   bool "vGICv2 interface for domains"
+   default y
+   help
+ Allow Xen to expose a Generic Interrupt Controller version 2 like to 
Xen
+ domains. This can be configured at the domain creation.
+ This option is mandatory when using GICv2.
+ For GICv3, this allows domain to use GICv2 when the hardware supports 
it.
+ If unsure say Y.
+
 config HVM
 def_bool y
 
 config NEW_VGIC
bool "Use new VGIC implementation"
+   select GICV2
---help---
 
This is an alternative implementation of the ARM GIC interrupt
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index c45b08b31eb0..d83dc25c0d8a 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -23,7 +23,7 @@ obj-y += domctl.o
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 obj-y += efi/
 obj-y += gic.o
-obj-y += gic-v2.o
+obj-$(CONFIG_GICV2) += gic-v2.o
 obj-$(CONFIG_GICV3) += gic-v3.o
 obj-$(CONFIG_HAS_ITS) += gic-v3-its.o
 obj-$(CONFIG_HAS_ITS) += gic-v3-lpi.o
@@ -58,7 +58,7 @@ obj-$(CONFIG_NEW_VGIC) += vgic/
 ifneq ($(CONFIG_NEW_VGIC),y)
 obj-y += gic-vgic.o
 obj-y += vgic.o
-obj-y += vgic-v2.o
+obj-$(CONFIG_VGICV2) += vgic-v2.o
 obj-$(CONFIG_GICV3) += vgic-v3.o
 obj-$(CONFIG_HAS_ITS) += vgic-v3-its.o
 endif
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 2dd2926b4144..814a41bcc502 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2491,6 +2491,7 @@ static int __init handle_node(struct domain *d, struct 
kernel_info *kinfo,
 return res;
 }
 
+#ifdef CONFIG_VGICV2
 static int __init make_gicv2_domU_node(struct kernel_info *kinfo)
 {
 void *fdt = kinfo->fdt;
@@ -2542,6 +2543,7 @@ static int __init make_gicv2_domU_node(struct kernel_info 
*kinfo)
 
 return res;
 }
+#endif
 
 #ifdef CONFIG_GICV3
 static int __init make_gicv3_domU_node(struct kernel_info *kinfo)
@@ -2617,8 +2619,10 @@ static int __init make_gic_domU_node(struct kernel_info 
*kinfo)
 case GIC_V3:
 return make_gicv3_domU_node(kinfo);
 #endif
+#ifdef CONFIG_VGICV2
 case GIC_V2:
 return make_gicv2_domU_node(kinfo);
+#endif
 default:
 panic("Unsupported GIC version\n");
 }
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 9b35a8c8a735..18289cd645ac 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1334,6 +1334,7 @@ static paddr_t __initdata dbase = INVALID_PADDR;
 static paddr_t __initdata vbase = INVALID_PADDR, vsize = 0;
 static paddr_t __initdata cbase = INVALID_PADDR, csize = 0;
 
+#ifdef CONFIG_VGICV2
 /* If the GICv3 supports GICv2, initialize it */
 static void __init gicv3_init_v2(void)
 {
@@ -1359,6 +1360,9 @@ static void __init gicv3_init_v2(void)
 
 vgic_v2_setup_hw(dbase, cbase, csize, vbase, 0);
 }
+#else
+static inline void gicv3_init_v2(void) { }
+#endif
 
 static void __init gicv3_ioremap_distributor(paddr_t dist_paddr)
 {
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index f6b49766f97a..c04fc4f83f96 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -96,10 +96,12 @@ int domain_vgic_register(struct domain *d, unsigned int 
*mmio_count)
return -ENODEV;
 break;
 #endif
+#ifdef CONFIG_VGICV2
 case GIC_V2:
 if ( vgic_v2_init(d, mmio_count) )
 return -ENODEV;
 break;
+#endif
 default:
 printk(XENLOG_G_ERR "d%d: Un

[PATCH v6 5/5] arm/dom0less: introduce Kconfig for dom0less feature

2023-11-24 Thread Luca Fancellu
Introduce a Kconfig for the dom0less feature, enabled by default,
to be able to choose if the feature should be compiled or not.

Provide static inline stubs when the option is disabled for the
functions externally visible.

Use the new Kconfig to remove dom0less DT binding from the efi-boot.h
code when the Kconfig is not enabled, do the same for
allocate_bank_memory inside domain_build.c that currently is used
only by dom0less-build.c module, but it's kept there provisioning
its usage by dom0 code.

Signed-off-by: Luca Fancellu 
Reviewed-by: Michal Orzel 
---
Changes from v5:
 - style fix, don't protect prototype (Michal), add R-by Michal
   since there are no rebase changes
Changes from v4:
 - No changes
Changes from v3:
 - Update Kconfig
Changes from v2:
 - protect allocate_bank_memory with the new Kconfig
---
 xen/arch/arm/Kconfig  |  8 
 xen/arch/arm/Makefile |  2 +-
 xen/arch/arm/domain_build.c   |  2 ++
 xen/arch/arm/efi/efi-boot.h   |  4 
 xen/arch/arm/include/asm/dom0less-build.h | 12 
 xen/common/Kconfig|  2 +-
 6 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 57dc9957124f..f73b62e50d00 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -88,6 +88,14 @@ config GICV2
  Driver for the ARM Generic Interrupt Controller v2.
  If unsure, say Y
 
+config DOM0LESS_BOOT
+   bool "Dom0less boot support" if EXPERT
+   default y
+   help
+ Dom0less boot support enables Xen to create and start domU guests 
during
+ Xen boot without the need of a control domain (Dom0), which could be
+ present anyway.
+
 config GICV3
bool "GICv3 driver"
depends on !NEW_VGIC
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 2fcc3c2535fd..809772417c14 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -16,7 +16,7 @@ obj-y += cpufeature.o
 obj-y += decode.o
 obj-y += device.o
 obj-$(CONFIG_IOREQ_SERVER) += dm.o
-obj-y += dom0less-build.init.o
+obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.init.o
 obj-y += domain.o
 obj-y += domain_build.init.o
 obj-$(CONFIG_ARCH_MAP_DOMAIN_PAGE) += domain_page.o
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 7eb766da9c63..df66fb88d8ec 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -416,6 +416,7 @@ static void __init allocate_memory_11(struct domain *d,
 }
 }
 
+#ifdef CONFIG_DOM0LESS_BOOT
 bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
  gfn_t sgfn, paddr_t tot_size)
 {
@@ -477,6 +478,7 @@ bool __init allocate_bank_memory(struct domain *d, struct 
kernel_info *kinfo,
 
 return true;
 }
+#endif
 
 /*
  * When PCI passthrough is available we want to keep the
diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h
index 6e6db2445566..0cb29f90a066 100644
--- a/xen/arch/arm/efi/efi-boot.h
+++ b/xen/arch/arm/efi/efi-boot.h
@@ -787,6 +787,7 @@ static int __init handle_module_node(const EFI_LOADED_IMAGE 
*loaded_image,
 return 1;
 }
 
+#ifdef CONFIG_DOM0LESS_BOOT
 /*
  * This function checks for boot modules under the domU guest domain node
  * in the DT.
@@ -834,6 +835,7 @@ static int __init handle_dom0less_domain_node(const 
EFI_LOADED_IMAGE *loaded_ima
 
 return mb_modules_found;
 }
+#endif
 
 /*
  * This function checks for xen domain nodes under the /chosen node for 
possible
@@ -861,6 +863,7 @@ static int __init efi_check_dt_boot(const EFI_LOADED_IMAGE 
*loaded_image)
 {
 int ret;
 
+#ifdef CONFIG_DOM0LESS_BOOT
 if ( !fdt_node_check_compatible(fdt_efi, node, "xen,domain") )
 {
 /* Found a node with compatible xen,domain; handle this node. */
@@ -869,6 +872,7 @@ static int __init efi_check_dt_boot(const EFI_LOADED_IMAGE 
*loaded_image)
 return ERROR_DT_MODULE_DOMU;
 }
 else
+#endif
 {
 ret = handle_module_node(loaded_image, &dir_handle, node, addr_len,
  size_len, false);
diff --git a/xen/arch/arm/include/asm/dom0less-build.h 
b/xen/arch/arm/include/asm/dom0less-build.h
index c5625925d940..00f92835eceb 100644
--- a/xen/arch/arm/include/asm/dom0less-build.h
+++ b/xen/arch/arm/include/asm/dom0less-build.h
@@ -3,9 +3,21 @@
 #ifndef __ASM_DOM0LESS_BUILD_H_
 #define __ASM_DOM0LESS_BUILD_H_
 
+#ifdef CONFIG_DOM0LESS_BOOT
+
 void create_domUs(void);
 bool is_dom0less_mode(void);
 
+#else /* !CONFIG_DOM0LESS_BOOT */
+
+static inline void create_domUs(void) {}
+static inline bool is_dom0less_mode(void)
+{
+return false;
+}
+
+#endif /* CONFIG_DOM0LESS_BOOT */
+
 #endif /* __ASM_DOM0LESS_BUILD_H_ */
 
 /*
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 4d6fe051641d..310ad4229cdf 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig

[PATCH v6 0/5] Fine granular configuration

2023-11-24 Thread Luca Fancellu
This serie aims to add more modularity to some feature that can be excluded
without issues from the build.

The first patch is already reviewed.

v2 update: So I've tried to see how to put the dom0less code in the common code,
but the amount of modifications are not trivial, even putting only the common
part and protecting them with ARM, leaving the ARM specific stuff under arch/
like gic etc... will leave a status that is not very nice, so I've decided for
now to keep everything on the arm architecture so that who is going to work
on unifying the code in common can just take from there and do the proper
rework.

Luca Fancellu (5):
  arm/gicv2: make GICv2 driver and vGICv2 optional
  xen/arm: Add asm/domain.h include to kernel.h
  arm/dom0less: put dom0less feature code in a separate module
  xen/arm: Move static memory build code in separate modules
  arm/dom0less: introduce Kconfig for dom0less feature

 xen/arch/arm/Kconfig  |   27 +
 xen/arch/arm/Makefile |7 +-
 xen/arch/arm/arm32/mmu/mm.c   |1 +
 xen/arch/arm/arm64/mmu/mm.c   |1 +
 xen/arch/arm/bootfdt.c|  161 +-
 xen/arch/arm/dom0less-build.c | 1018 ++
 xen/arch/arm/domain_build.c   | 3591 ++---
 xen/arch/arm/efi/efi-boot.h   |4 +
 xen/arch/arm/gic-v3.c |4 +
 xen/arch/arm/include/asm/dom0less-build.h |   30 +
 xen/arch/arm/include/asm/domain_build.h   |   34 +
 xen/arch/arm/include/asm/kernel.h |1 +
 xen/arch/arm/include/asm/setup.h  |2 -
 xen/arch/arm/include/asm/static-memory.h  |   45 +
 xen/arch/arm/include/asm/static-shmem.h   |   66 +
 xen/arch/arm/setup.c  |   57 +-
 xen/arch/arm/static-memory.c  |  287 ++
 xen/arch/arm/static-shmem.c   |  547 
 xen/arch/arm/vgic.c   |2 +
 xen/arch/arm/vgic/Makefile|4 +-
 xen/common/Kconfig|2 +-
 21 files changed, 3058 insertions(+), 2833 deletions(-)
 create mode 100644 xen/arch/arm/dom0less-build.c
 create mode 100644 xen/arch/arm/include/asm/dom0less-build.h
 create mode 100644 xen/arch/arm/include/asm/static-memory.h
 create mode 100644 xen/arch/arm/include/asm/static-shmem.h
 create mode 100644 xen/arch/arm/static-memory.c
 create mode 100644 xen/arch/arm/static-shmem.c

-- 
2.34.1




[PATCH v6 3/5] arm/dom0less: put dom0less feature code in a separate module

2023-11-24 Thread Luca Fancellu
Currently the dom0less feature code is mostly inside domain_build.c
and setup.c, it is a feature that may not be useful to everyone so
put the code in a different compilation module in order to make it
easier to disable the feature in the future.

Move gic_interrupt_t in domain_build.h to use it with the function
declaration, move its comment above the declaration.

The following functions are now visible externally from domain_build
because they are used also from the dom0less-build module:
 - get_allocation_size
 - set_interrupt
 - domain_fdt_begin_node
 - make_memory_node
 - make_resv_memory_node
 - make_hypervisor_node
 - make_psci_node
 - make_cpus_node
 - make_timer_node
 - handle_device_interrupts
 - construct_domain
 - process_shm
 - allocate_bank_memory

The functions allocate_static_memory and assign_static_memory_11
are now externally visible, so put their declarations into
domain_build.h and move the #else and stub definition in the header
as well.

Move is_dom0less_mode from setup.c to dom0less-build.c and make it
externally visible.

The function allocate_bank_memory is used only by dom0less code
at the moment, but it's been decided to leave it in domain_build.c
in case that in the future the dom0 code can use it.

Where spotted, fix code style issues.

No functional change is intended.

Signed-off-by: Luca Fancellu 
Reviewed-by: Michal Orzel 
---
Changes from v5:
 - remove unneeded include (Michal)
 - rebase on staging
Changes from v4:
 - fixed name in inclusion macro __ASM_* instead of __ARM_*, fixed
   emacs local variable 'end:', style fix (Michal)
Changes from v3:
 - remove header in dom0less-build.c (Michal)
Changes from v2:
 - move allocate_bank_memory back in domain_build.c, remove header
   from dom0less-build.c.
---
 xen/arch/arm/Makefile |1 +
 xen/arch/arm/dom0less-build.c | 1018 +
 xen/arch/arm/domain_build.c   | 1265 +++--
 xen/arch/arm/include/asm/dom0less-build.h |   18 +
 xen/arch/arm/include/asm/domain_build.h   |   60 +
 xen/arch/arm/include/asm/setup.h  |1 -
 xen/arch/arm/setup.c  |   33 +-
 7 files changed, 1238 insertions(+), 1158 deletions(-)
 create mode 100644 xen/arch/arm/dom0less-build.c
 create mode 100644 xen/arch/arm/include/asm/dom0less-build.h

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index d83dc25c0d8a..d65920b0a8cf 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -16,6 +16,7 @@ obj-y += cpufeature.o
 obj-y += decode.o
 obj-y += device.o
 obj-$(CONFIG_IOREQ_SERVER) += dm.o
+obj-y += dom0less-build.init.o
 obj-y += domain.o
 obj-y += domain_build.init.o
 obj-$(CONFIG_ARCH_MAP_DOMAIN_PAGE) += domain_page.o
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
new file mode 100644
index ..1ca9d39043d6
--- /dev/null
+++ b/xen/arch/arm/dom0less-build.c
@@ -0,0 +1,1018 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+bool __init is_dom0less_mode(void)
+{
+struct bootmodules *mods = &bootinfo.modules;
+struct bootmodule *mod;
+unsigned int i;
+bool dom0found = false;
+bool domUfound = false;
+
+/* Look into the bootmodules */
+for ( i = 0 ; i < mods->nr_mods ; i++ )
+{
+mod = &mods->module[i];
+/* Find if dom0 and domU kernels are present */
+if ( mod->kind == BOOTMOD_KERNEL )
+{
+if ( mod->domU == false )
+{
+dom0found = true;
+break;
+}
+else
+domUfound = true;
+}
+}
+
+/*
+ * If there is no dom0 kernel but at least one domU, then we are in
+ * dom0less mode
+ */
+return ( !dom0found && domUfound );
+}
+
+static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
+{
+unsigned int i;
+paddr_t bank_size;
+
+printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
+   /* Don't want format this as PRIpaddr (16 digit hex) */
+   (unsigned long)(kinfo->unassigned_mem >> 20), d);
+
+kinfo->mem.nr_banks = 0;
+bank_size = MIN(GUEST_RAM0_SIZE, kinfo->unassigned_mem);
+if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE),
+   bank_size) )
+goto fail;
+
+bank_size = MIN(GUEST_RAM1_SIZE, kinfo->unassigned_mem);
+if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE),
+   bank_size) )
+goto fail;
+
+if ( kinfo->unassigned_mem )
+goto fail;
+
+for( i = 0; i < kinfo->mem.nr_banks; i++ )
+{
+printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
+   d,
+   i,
+   kinfo->mem.bank[i].start,
+   kinfo->mem.bank

Re: [PATCH v6 0/5] Fine granular configuration

2023-11-24 Thread Luca Fancellu
+ CC Maintainers

> On 24 Nov 2023, at 09:48, Luca Fancellu  wrote:
> 
> This serie aims to add more modularity to some feature that can be excluded
> without issues from the build.
> 
> The first patch is already reviewed.
> 
> v2 update: So I've tried to see how to put the dom0less code in the common 
> code,
> but the amount of modifications are not trivial, even putting only the common
> part and protecting them with ARM, leaving the ARM specific stuff under arch/
> like gic etc... will leave a status that is not very nice, so I've decided for
> now to keep everything on the arm architecture so that who is going to work
> on unifying the code in common can just take from there and do the proper
> rework.
> 
> Luca Fancellu (5):
>  arm/gicv2: make GICv2 driver and vGICv2 optional
>  xen/arm: Add asm/domain.h include to kernel.h
>  arm/dom0less: put dom0less feature code in a separate module
>  xen/arm: Move static memory build code in separate modules
>  arm/dom0less: introduce Kconfig for dom0less feature
> 
> xen/arch/arm/Kconfig  |   27 +
> xen/arch/arm/Makefile |7 +-
> xen/arch/arm/arm32/mmu/mm.c   |1 +
> xen/arch/arm/arm64/mmu/mm.c   |1 +
> xen/arch/arm/bootfdt.c|  161 +-
> xen/arch/arm/dom0less-build.c | 1018 ++
> xen/arch/arm/domain_build.c   | 3591 ++---
> xen/arch/arm/efi/efi-boot.h   |4 +
> xen/arch/arm/gic-v3.c |4 +
> xen/arch/arm/include/asm/dom0less-build.h |   30 +
> xen/arch/arm/include/asm/domain_build.h   |   34 +
> xen/arch/arm/include/asm/kernel.h |1 +
> xen/arch/arm/include/asm/setup.h  |2 -
> xen/arch/arm/include/asm/static-memory.h  |   45 +
> xen/arch/arm/include/asm/static-shmem.h   |   66 +
> xen/arch/arm/setup.c  |   57 +-
> xen/arch/arm/static-memory.c  |  287 ++
> xen/arch/arm/static-shmem.c   |  547 
> xen/arch/arm/vgic.c   |2 +
> xen/arch/arm/vgic/Makefile|4 +-
> xen/common/Kconfig|2 +-
> 21 files changed, 3058 insertions(+), 2833 deletions(-)
> create mode 100644 xen/arch/arm/dom0less-build.c
> create mode 100644 xen/arch/arm/include/asm/dom0less-build.h
> create mode 100644 xen/arch/arm/include/asm/static-memory.h
> create mode 100644 xen/arch/arm/include/asm/static-shmem.h
> create mode 100644 xen/arch/arm/static-memory.c
> create mode 100644 xen/arch/arm/static-shmem.c

I sent this serie forgetting about adding the maintainers, CC them
now.

Cheers,
Luca




[PATCH v2 01/39] xen/riscv: disable unnecessary configs

2023-11-24 Thread Oleksii Kurochko
The patch also fixes the build script as conf util expects
to have each config on separate line.

Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - update the commit message.
 - remove xen/arch/riscv/Kconfig changes.
---
 automation/gitlab-ci/build.yaml | 122 
 automation/scripts/build|   4 +-
 xen/arch/riscv/configs/tiny64_defconfig |  18 
 3 files changed, 142 insertions(+), 2 deletions(-)

diff --git a/automation/gitlab-ci/build.yaml b/automation/gitlab-ci/build.yaml
index 32af30cced..f4ef81839a 100644
--- a/automation/gitlab-ci/build.yaml
+++ b/automation/gitlab-ci/build.yaml
@@ -522,6 +522,38 @@ archlinux-current-gcc-riscv64:
 CONTAINER: archlinux:current-riscv64
 KBUILD_DEFCONFIG: tiny64_defconfig
 HYPERVISOR_ONLY: y
+EXTRA_XEN_CONFIG:
+  CONFIG_COVERAGE=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SCHED_CREDIT=n
+  CONFIG_SCHED_CREDIT2=n
+  CONFIG_SCHED_RTDS=n
+  CONFIG_SCHED_NULL=n
+  CONFIG_SCHED_ARINC653=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_HYPFS=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SPECULATIVE_HARDEN_ARRAY=n
+  CONFIG_ARGO=n
+  CONFIG_HYPFS_CONFIG=n
+  CONFIG_CORE_PARKING=n
+  CONFIG_DEBUG_TRACE=n
+  CONFIG_IOREQ_SERVER=n
+  CONFIG_CRASH_DEBUG=n
+  CONFIG_KEXEC=n
+  CONFIG_LIVEPATCH=n
+  CONFIG_MEM_ACCESS=n
+  CONFIG_NUMA=n
+  CONFIG_PERF_COUNTERS=n
+  CONFIG_HAS_PMAP=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_XENOPROF=n
+  CONFIG_COMPAT=n
+  CONFIG_COVERAGE=n
+  CONFIG_UBSAN=n
+  CONFIG_NEEDS_LIBELF=n
+  CONFIG_XSM=n
+
 
 archlinux-current-gcc-riscv64-debug:
   extends: .gcc-riscv64-cross-build-debug
@@ -529,6 +561,38 @@ archlinux-current-gcc-riscv64-debug:
 CONTAINER: archlinux:current-riscv64
 KBUILD_DEFCONFIG: tiny64_defconfig
 HYPERVISOR_ONLY: y
+EXTRA_XEN_CONFIG:
+  CONFIG_COVERAGE=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SCHED_CREDIT=n
+  CONFIG_SCHED_CREDIT2=n
+  CONFIG_SCHED_RTDS=n
+  CONFIG_SCHED_NULL=n
+  CONFIG_SCHED_ARINC653=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_HYPFS=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SPECULATIVE_HARDEN_ARRAY=n
+  CONFIG_ARGO=n
+  CONFIG_HYPFS_CONFIG=n
+  CONFIG_CORE_PARKING=n
+  CONFIG_DEBUG_TRACE=n
+  CONFIG_IOREQ_SERVER=n
+  CONFIG_CRASH_DEBUG=n
+  CONFIG_KEXEC=n
+  CONFIG_LIVEPATCH=n
+  CONFIG_MEM_ACCESS=n
+  CONFIG_NUMA=n
+  CONFIG_PERF_COUNTERS=n
+  CONFIG_HAS_PMAP=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_XENOPROF=n
+  CONFIG_COMPAT=n
+  CONFIG_COVERAGE=n
+  CONFIG_UBSAN=n
+  CONFIG_NEEDS_LIBELF=n
+  CONFIG_XSM=n
+
 
 archlinux-current-gcc-riscv64-randconfig:
   extends: .gcc-riscv64-cross-build
@@ -538,6 +602,35 @@ archlinux-current-gcc-riscv64-randconfig:
 RANDCONFIG: y
 EXTRA_FIXED_RANDCONFIG:
   CONFIG_COVERAGE=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SCHED_CREDIT=n
+  CONFIG_SCHED_CREDIT2=n
+  CONFIG_SCHED_RTDS=n
+  CONFIG_SCHED_NULL=n
+  CONFIG_SCHED_ARINC653=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_HYPFS=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SPECULATIVE_HARDEN_ARRAY=n
+  CONFIG_ARGO=n
+  CONFIG_HYPFS_CONFIG=n
+  CONFIG_CORE_PARKING=n
+  CONFIG_DEBUG_TRACE=n
+  CONFIG_IOREQ_SERVER=n
+  CONFIG_CRASH_DEBUG=n
+  CONFIG_KEXEC=n
+  CONFIG_LIVEPATCH=n
+  CONFIG_MEM_ACCESS=n
+  CONFIG_NUMA=n
+  CONFIG_PERF_COUNTERS=n
+  CONFIG_HAS_PMAP=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_XENOPROF=n
+  CONFIG_COMPAT=n
+  CONFIG_COVERAGE=n
+  CONFIG_UBSAN=n
+  CONFIG_NEEDS_LIBELF=n
+  CONFIG_XSM=n
 
 archlinux-current-gcc-riscv64-debug-randconfig:
   extends: .gcc-riscv64-cross-build-debug
@@ -547,6 +640,35 @@ archlinux-current-gcc-riscv64-debug-randconfig:
 RANDCONFIG: y
 EXTRA_FIXED_RANDCONFIG:
   CONFIG_COVERAGE=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SCHED_CREDIT=n
+  CONFIG_SCHED_CREDIT2=n
+  CONFIG_SCHED_RTDS=n
+  CONFIG_SCHED_NULL=n
+  CONFIG_SCHED_ARINC653=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_HYPFS=n
+  CONFIG_GRANT_TABLE=n
+  CONFIG_SPECULATIVE_HARDEN_ARRAY=n
+  CONFIG_ARGO=n
+  CONFIG_HYPFS_CONFIG=n
+  CONFIG_CORE_PARKING=n
+  CONFIG_DEBUG_TRACE=n
+  CONFIG_IOREQ_SERVER=n
+  CONFIG_CRASH_DEBUG=n
+  CONFIG_KEXEC=n
+  CONFIG_LIVEPATCH=n
+  CONFIG_MEM_ACCESS=n
+  CONFIG_NUMA=n
+  CONFIG_PERF_COUNTERS=n
+  CONFIG_HAS_PMAP=n
+  CONFIG_TRACEBUFFER=n
+  CONFIG_XENOPROF=n
+  CONFIG_COMPAT=n
+  CONFIG_COVERAGE=n
+  CONFIG_UBSAN=n
+  CONFIG_NEEDS_LIBELF=n
+  CONFIG_XSM=n
 
 # Power cross-build
 debian-bullseye-gcc-ppc64le:
diff --git a/automation/scripts/build b/automation/scripts/build
index b3c71fb6fb..88287b9c46 100755
--- a/automation/scripts/build
+++ b/automation/scripts/build
@@ -14,7 +14,7 @@ if [[ "${RANDCONFIG}" == "y" ]]; then
 
 # App

[PATCH v2 04/39] xen/riscv: add public arch-riscv.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
- align with arch-arm.h.
---

 xen/include/public/arch-riscv.h | 93 +
 xen/include/public/xen.h|  2 +
 2 files changed, 95 insertions(+)
 create mode 100644 xen/include/public/arch-riscv.h

diff --git a/xen/include/public/arch-riscv.h b/xen/include/public/arch-riscv.h
new file mode 100644
index 00..168263b920
--- /dev/null
+++ b/xen/include/public/arch-riscv.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Guest OS interface to RISC-V Xen.
+ * Initially based on the ARM implementation.
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_RISCV_H__
+#define __XEN_PUBLIC_ARCH_RISCV_H__
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__) || defined(__GNUC__)
+#define  int64_aligned_t  int64_t __attribute__((__aligned__(8)))
+#define uint64_aligned_t uint64_t __attribute__((__aligned__(8)))
+#endif
+
+#ifndef __ASSEMBLY__
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type)  \
+typedef union { type *p; unsigned long q; } \
+__guest_handle_ ## name;\
+typedef union { type *p; uint64_aligned_t q; }  \
+__guest_handle_64_ ## name
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory. On RISCV is always 8 bytes sizes and 8 bytes
+ * aligned.
+ * XEN_GUEST_HANDLE_PARAM represents a guest pointer, when passed as an
+ * hypercall argument. It is 4 bytes on riscv32 and 8 bytes on riscv64.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+___DEFINE_XEN_GUEST_HANDLE(name, type);   \
+___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name)__guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE(name)  __XEN_GUEST_HANDLE(name)
+#define XEN_GUEST_HANDLE_PARAM(name)__guest_handle_ ## name
+#define set_xen_guest_handle_raw(hnd, val)  \
+do {\
+typeof(&(hnd)) sxghr_tmp_ = &(hnd); \
+sxghr_tmp_->q = 0;  \
+sxghr_tmp_->p = (val);  \
+} while ( 0 )
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn PRIx64
+#define PRIu_xen_pfn PRIu64
+
+typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong PRIx64
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+struct vcpu_guest_context {
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+
+struct xen_arch_domainconfig {
+};
+
+#endif
+
+/* TODO:  add a placeholder entry if no real ones surface */
+struct arch_vcpu_info {
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+/* TODO:  add a placeholder entry if no real ones surface */
+struct arch_shared_info {
+};
+typedef struct arch_shared_info arch_shared_info_t;
+
+/*
+ * Maximum number of virtual CPUs in legacy multi-processor guests.
+ * Only one. All other VCPUS must use VCPUOP_register_vcpu_info.
+ */
+#define XEN_LEGACY_MAX_VCPUS 1
+
+/* Stub definition of PMU structure */
+typedef struct xen_pmu_arch { uint8_t dummy; } xen_pmu_arch_t;
+#endif
+
+#endif /*  __XEN_PUBLIC_ARCH_RISCV_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index b812a0a324..b47d48d0e2 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -18,6 +18,8 @@
 #include "arch-arm.h"
 #elif defined(__powerpc64__)
 #include "arch-ppc.h"
+#elif defined(__riscv)
+#include "arch-riscv.h"
 #else
 #error "Unsupported architecture"
 #endif
-- 
2.42.0




[PATCH v2 02/39] xen/riscv: use some asm-generic headers

2023-11-24 Thread Oleksii Kurochko
Some headers are the same as asm-generic verions of them
so use them instead of arch-specific headers.

Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - New commit introduced in V2.
---
 xen/arch/riscv/include/asm/Makefile | 14 ++
 1 file changed, 14 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/Makefile

diff --git a/xen/arch/riscv/include/asm/Makefile 
b/xen/arch/riscv/include/asm/Makefile
new file mode 100644
index 00..4da0c70cc0
--- /dev/null
+++ b/xen/arch/riscv/include/asm/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+generic-y += altp2m.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += hardirq.h
+generic-y += hypercall.h
+generic-y += iocap.h
+generic-y += monitor.h
+generic-y += numa.h
+generic-y += paging.h
+generic-y += percpu.h
+generic-y += random.h
+generic-y += softirq.h
+generic-y += vm_event.h
-- 
2.42.0




[PATCH v2 06/39] xen/riscv: introduce fence.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/fence.h | 12 
 1 file changed, 12 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/fence.h

diff --git a/xen/arch/riscv/include/asm/fence.h 
b/xen/arch/riscv/include/asm/fence.h
new file mode 100644
index 00..2b443a3a48
--- /dev/null
+++ b/xen/arch/riscv/include/asm/fence.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_RISCV_FENCE_H
+#define _ASM_RISCV_FENCE_H
+
+#ifdef CONFIG_SMP
+#define RISCV_ACQUIRE_BARRIER  "\tfence r , rw\n"
+#define RISCV_RELEASE_BARRIER  "\tfence rw,  w\n"
+#else
+#define RISCV_ACQUIRE_BARRIER
+#define RISCV_RELEASE_BARRIER
+#endif
+
+#endif /* _ASM_RISCV_FENCE_H */
-- 
2.42.0




[PATCH v2 00/39] Enable build of full Xen for RISC-V

2023-11-24 Thread Oleksii Kurochko
This patch series performs all of the additions necessary to drop the
build overrides for RISCV and enable the full Xen build. Except in cases
where compatibile implementations already exist (e.g. atomic.h and
bitops.h), the newly added definitions are simple.

The patch series is based on the following patch series:
- [PATCH v2] xen: remove  [1]
- [PATCH v3 00/14] Introduce generic headers [2]

[1] 
https://lore.kernel.org/xen-devel/3d55bce44bd6ab9973cbe0ea2fc136cc44d35df2.1698759633.git.oleksii.kuroc...@gmail.com/
[2] 
https://lore.kernel.org/xen-devel/cover.1700221559.git.oleksii.kuroc...@gmail.com/

---
Changes in V2:
  - Drop the following patches as they are the part of [2]:
  [PATCH v1 06/57] xen/riscv: introduce paging.h
  [PATCH v1 08/57] xen/riscv: introduce asm/device.h
  [PATCH v1 10/57] xen/riscv: introduce asm/grant_table.h
  [PATCH v1 12/57] xen/riscv: introduce asm/hypercall.h
  [PATCH v1 13/57] xen/riscv: introduce asm/iocap.h
  [PATCH v1 15/57] xen/riscv: introduce asm/mem_access.h
  [PATCH v1 18/57] xen/riscv: introduce asm/random.h
  [PATCH v1 21/57] xen/riscv: introduce asm/xenoprof.h
  [PATCH v1 24/57] xen/riscv: introduce asm/percpu.h
  [PATCH v1 29/57] xen/riscv: introduce asm/hardirq.h
  [PATCH v1 33/57] xen/riscv: introduce asm/altp2m.h
  [PATCH v1 38/57] xen/riscv: introduce asm/monitor.h
  [PATCH v1 39/57] xen/riscv: introduce asm/numa.h
  [PATCH v1 42/57] xen/riscv: introduce asm/softirq.h
  - xen/lib.h in most of the cases were changed to xen/bug.h as
mostly functionilty of bug.h is used.
  - align arch-riscv.h with Arm's version of it.
  - change the Author of commit with introduction of asm/atomic.h.
  - update some definition from spinlock.h.
  - code style changes.
---

Bobby Eshleman (1):
  xen/riscv: introduce asm/atomic.h

Oleksii Kurochko (38):
  xen/riscv: disable unnecessary configs
  xen/riscv: use some asm-generic headers
  xen/riscv:introduce asm/byteorder.h
  xen/riscv: add public arch-riscv.h
  xen/riscv: introduce spinlock.h
  xen/riscv: introduce fence.h
  xen/riscv: introduce arch-riscv/hvm/save.h
  xen/riscv: introduce asm/cpufeature.h
  xen/riscv: introduce asm/guest_atomics.h
  xen/riscv: introduce asm/iommu.h
  xen/riscv: introduce asm/nospec.h
  xen/riscv: introduce asm/setup.h
  xen/riscv: introduce asm/system.h
  xen/riscv: introduce bitops.h
  xen/riscv: introduce flushtlb.h
  xen/riscv: introduce asm/smp.h
  xen/riscv: introduce cmpxchg.h
  xen/riscv: introduce asm/io.h
  xen/riscv: define bug frame tables in xen.lds.S
  xen/riscv: introduce bit operations
  xen/riscv: introduce asm/domain.h
  xen/riscv: introduce asm/guest_access.h
  xen/riscv: introduce asm/irq.h
  xen/riscv: introduce asm/p2m.h
  xen/riscv: introduce asm/regs.h
  xen/riscv: introduce asm/time.h
  xen/riscv: introduce asm/event.h
  xen/riscv: add definition of __read_mostly
  xen/riscv: define an address of frame table
  xen/riscv: add required things to asm/current.h
  xen/riscv: add minimal stuff to asm/page.h to build full Xen
  xen/riscv: add minimal stuff to asm/processor.h to build full Xen
  xen: add RISCV support for pmu.h
  xen: add necessary headers to common to build full Xen for RISC-V
  xen/riscv: add minimal stuff to asm/mm.h to build full Xen
  xen/rirscv: add minimal amount of stubs to build full Xen
  xen/riscv: enable full Xen build
  xen: fix compilation issue of serial.c

 automation/gitlab-ci/build.yaml| 122 ++
 automation/scripts/build   |   4 +-
 xen/arch/riscv/Makefile|  18 +-
 xen/arch/riscv/arch.mk |   4 -
 xen/arch/riscv/configs/tiny64_defconfig|  19 +-
 xen/arch/riscv/early_printk.c  | 168 
 xen/arch/riscv/include/asm/Makefile|  14 +
 xen/arch/riscv/include/asm/atomic.h| 375 ++
 xen/arch/riscv/include/asm/bitops.h| 288 ++
 xen/arch/riscv/include/asm/byteorder.h |  16 +
 xen/arch/riscv/include/asm/cache.h |   2 +
 xen/arch/riscv/include/asm/cmpxchg.h   | 379 ++
 xen/arch/riscv/include/asm/config.h|  21 +
 xen/arch/riscv/include/asm/cpufeature.h|  22 ++
 xen/arch/riscv/include/asm/current.h   |  20 +
 xen/arch/riscv/include/asm/domain.h|  43 +++
 xen/arch/riscv/include/asm/event.h |  34 ++
 xen/arch/riscv/include/asm/fence.h |  12 +
 xen/arch/riscv/include/asm/flushtlb.h  |  31 ++
 xen/arch/riscv/include/asm/guest_access.h  |  29 ++
 xen/arch/riscv/include/asm/guest_atomics.h |  48 +++
 xen/arch/riscv/include/asm/io.h| 134 +++
 xen/arch/riscv/include/asm/iommu.h |   7 +
 xen/arch/riscv/include/asm/irq.h   |  37 ++
 xen/arch/riscv/include/asm/mm.h| 270 -
 xen/arch/riscv/include/asm/nospec.h|  25 ++
 xen/arch/riscv/include/asm/p2m.h   | 105 +
 xen/arch/riscv/include/asm/page.h  |  21 +
 xen/arch/r

[PATCH v2 10/39] xen/riscv: introduce asm/iommu.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/iommu.h | 7 +++
 1 file changed, 7 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/iommu.h

diff --git a/xen/arch/riscv/include/asm/iommu.h 
b/xen/arch/riscv/include/asm/iommu.h
new file mode 100644
index 00..648b6fb922
--- /dev/null
+++ b/xen/arch/riscv/include/asm/iommu.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_RISCV_IOMMU_H__
+#define __ASM_RISCV_IOMMU_H__
+
+struct arch_iommu {
+};
+
+#endif /* __ASM_IOMMU_H__ */
-- 
2.42.0




[PATCH v2 12/39] xen/riscv: introduce asm/setup.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/setup.h | 6 ++
 1 file changed, 6 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/setup.h

diff --git a/xen/arch/riscv/include/asm/setup.h 
b/xen/arch/riscv/include/asm/setup.h
new file mode 100644
index 00..a1adb2be0d
--- /dev/null
+++ b/xen/arch/riscv/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_RISCV_SETUP_H__
+#define __ASM_RISCV_SETUP_H__
+
+#define max_init_domid (0)
+
+#endif /* __ASM_RISCV_SETUP_H__ */
-- 
2.42.0




[PATCH v2 08/39] xen/riscv: introduce asm/cpufeature.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/cpufeature.h | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/cpufeature.h

diff --git a/xen/arch/riscv/include/asm/cpufeature.h 
b/xen/arch/riscv/include/asm/cpufeature.h
new file mode 100644
index 00..211827f816
--- /dev/null
+++ b/xen/arch/riscv/include/asm/cpufeature.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_RISCV_CPUFEATURE_H
+#define __ASM_RISCV_CPUFEATURE_H
+
+#ifndef __ASSEMBLY__
+
+static inline int cpu_nr_siblings(unsigned int cpu)
+{
+return 1;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
-- 
2.42.0




[PATCH v2 15/39] xen/riscv: introduce flushtlb.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/flushtlb.h | 31 +++
 1 file changed, 31 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/flushtlb.h

diff --git a/xen/arch/riscv/include/asm/flushtlb.h 
b/xen/arch/riscv/include/asm/flushtlb.h
new file mode 100644
index 00..7059a53823
--- /dev/null
+++ b/xen/arch/riscv/include/asm/flushtlb.h
@@ -0,0 +1,31 @@
+#ifndef __ASM_RISCV_FLUSHTLB_H__
+#define __ASM_RISCV_FLUSHTLB_H__
+
+#include 
+
+/*
+ * Filter the given set of CPUs, removing those that definitely flushed their
+ * TLB since @page_timestamp.
+ */
+/* XXX lazy implementation just doesn't clear anything */
+static inline void tlbflush_filter(cpumask_t *mask, uint32_t page_timestamp) {}
+
+#define tlbflush_current_time() (0)
+
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+BUG();
+}
+
+/* Flush specified CPUs' TLBs */
+void arch_flush_tlb_mask(const cpumask_t *mask);
+
+#endif /* __ASM_RISCV_FLUSHTLB_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 17/39] xen/riscv: introduce asm/atomic.h

2023-11-24 Thread Oleksii Kurochko
From: Bobby Eshleman 

Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Change an author of commit. I got this header from Bobby's old repo.
---
 xen/arch/riscv/include/asm/atomic.h | 375 
 1 file changed, 375 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/atomic.h

diff --git a/xen/arch/riscv/include/asm/atomic.h 
b/xen/arch/riscv/include/asm/atomic.h
new file mode 100644
index 00..d4849cf282
--- /dev/null
+++ b/xen/arch/riscv/include/asm/atomic.h
@@ -0,0 +1,375 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Taken and modified from Linux.
+ * 
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ * Copyright (C) 2021 Vates SAS
+ */
+
+#ifndef _ASM_RISCV_ATOMIC_H
+#define _ASM_RISCV_ATOMIC_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void __bad_atomic_size(void);
+
+static always_inline void read_atomic_size(const volatile void *p,
+   void *res,
+   unsigned int size)
+{
+switch ( size ) {
+case 1: *(uint8_t *)res = readb((uint8_t *)p); break;
+case 2: *(uint16_t *)res = readw((uint16_t *)p); break;
+case 4: *(uint32_t *)res = readl((uint32_t *)p); break;
+case 8: *(uint32_t *)res  = readq((uint64_t *)p); break;
+default: __bad_atomic_size(); break;
+}
+}
+
+#define read_atomic(p) ({   \
+union { typeof(*p) val; char c[0]; } x_;\
+read_atomic_size(p, x_.c, sizeof(*p));  \
+x_.val; \
+})
+
+
+#define write_atomic(p, x) ({   \
+typeof(*p) __x = (x);   \
+switch ( sizeof(*p) ) { \
+case 1: writeb((uint8_t)__x,  (uint8_t *)  p); break;  \
+case 2: writew((uint16_t)__x, (uint16_t *) p); break;  \
+case 4: writel((uint32_t)__x, (uint32_t *) p); break;  \
+case 8: writeq((uint64_t)__x, (uint64_t *) p); break;  \
+default: __bad_atomic_size(); break;\
+}   \
+__x;\
+})
+
+/* TODO: Fix this */
+#define add_sized(p, x) ({  \
+typeof(*(p)) __x = (x); \
+switch ( sizeof(*(p)) ) \
+{   \
+case 1: writeb(read_atomic(p) + __x, (uint8_t *)(p)); break;\
+case 2: writew(read_atomic(p) + __x, (uint16_t *)(p)); break;   \
+case 4: writel(read_atomic(p) + __x, (uint32_t *)(p)); break;   \
+default: __bad_atomic_size(); break;\
+}   \
+})
+
+/*
+ *  __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
+ *   non-scalar types unchanged.
+ *
+ * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
+ * is not type-compatible with 'signed char', and we define a separate case.
+ */
+#define __scalar_type_to_expr_cases(type)   \
+unsigned type:  (unsigned type)0,   \
+signed type:(signed type)0
+
+#define __unqual_scalar_typeof(x) typeof(   \
+_Generic((x),   \
+char:  (char)0, \
+__scalar_type_to_expr_cases(char),  \
+__scalar_type_to_expr_cases(short), \
+__scalar_type_to_expr_cases(int),   \
+__scalar_type_to_expr_cases(long),  \
+__scalar_type_to_expr_cases(long long), \
+default: (x)))
+
+#define READ_ONCE(x)  (*(const volatile __unqual_scalar_typeof(x) *)&(x))
+#define WRITE_ONCE(x, val)  \
+do {\
+*(volatile typeof(x) *)&(x) = (val);\
+} while (0)
+
+#define __atomic_acquire_fence()   \
+   __asm__ __volatile__(RISCV_ACQUIRE_BARRIER "" ::: "memory")
+
+#define __atomic_release_fence()   \
+   __asm__ __volatile__(RISCV_RELEASE_BARRIER "" ::: "memory");
+
+static inline int atomic_read(const atomic_t *v)
+{
+   return READ_ONCE(v->counter);
+}
+
+static inline int _atomic_read(atomic_t v)
+{
+return v.counter;
+}
+
+static inline void atomic_set(atomic_t *v, int i)
+{
+   W

[PATCH v2 19/39] xen/riscv: introduce asm/io.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/io.h | 134 
 1 file changed, 134 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/io.h

diff --git a/xen/arch/riscv/include/asm/io.h b/xen/arch/riscv/include/asm/io.h
new file mode 100644
index 00..987fddf902
--- /dev/null
+++ b/xen/arch/riscv/include/asm/io.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Taken and modified from Linux.
+ *
+ * {read,write}{b,w,l,q} based on arch/arm64/include/asm/io.h
+ *   which was based on arch/arm/include/io.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2014 Regents of the University of California
+ */
+
+#ifndef _ASM_RISCV_IO_H
+#define _ASM_RISCV_IO_H
+
+#include 
+
+/*
+ * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't
+ * change the properties of memory regions.  This should be fixed by the
+ * upcoming platform spec.
+ */
+#define ioremap_nocache(addr, size) ioremap((addr), (size))
+#define ioremap_wc(addr, size) ioremap((addr), (size))
+#define ioremap_wt(addr, size) ioremap((addr), (size))
+
+/* Generic IO read/write.  These perform native-endian accesses. */
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+   asm volatile("sb %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+   asm volatile("sh %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+   asm volatile("sw %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+
+#ifdef CONFIG_64BIT
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+{
+   asm volatile("sd %0, 0(%1)" : : "r" (val), "r" (addr));
+}
+#endif
+
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+   u8 val;
+
+   asm volatile("lb %0, 0(%1)" : "=r" (val) : "r" (addr));
+   return val;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+   u16 val;
+
+   asm volatile("lh %0, 0(%1)" : "=r" (val) : "r" (addr));
+   return val;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+   u32 val;
+
+   asm volatile("lw %0, 0(%1)" : "=r" (val) : "r" (addr));
+   return val;
+}
+
+#ifdef CONFIG_64BIT
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+   u64 val;
+
+   asm volatile("ld %0, 0(%1)" : "=r" (val) : "r" (addr));
+   return val;
+}
+#endif
+
+/*
+ * Unordered I/O memory access primitives.  These are even more relaxed than
+ * the relaxed versions, as they don't even order accesses between successive
+ * operations to the I/O regions.
+ */
+#define readb_cpu(c)   ({ u8  __r = __raw_readb(c); __r; })
+#define readw_cpu(c)   ({ u16 __r = le16_to_cpu((__force 
__le16)__raw_readw(c)); __r; })
+#define readl_cpu(c)   ({ u32 __r = le32_to_cpu((__force 
__le32)__raw_readl(c)); __r; })
+
+#define writeb_cpu(v,c)((void)__raw_writeb((v),(c)))
+#define writew_cpu(v,c)((void)__raw_writew((__force 
u16)cpu_to_le16(v),(c)))
+#define writel_cpu(v,c)((void)__raw_writel((__force 
u32)cpu_to_le32(v),(c)))
+
+#ifdef CONFIG_64BIT
+#define readq_cpu(c)   ({ u64 __r = le64_to_cpu((__force 
__le64)__raw_readq(c)); __r; })
+#define writeq_cpu(v,c)((void)__raw_writeq((__force 
u64)cpu_to_le64(v),(c)))
+#endif
+
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.  The memory barriers here are necessary as RISC-V
+ * doesn't define any ordering between the memory space and the I/O space.
+ */
+#define __io_br()  do {} while (0)
+#define __io_ar(v) __asm__ __volatile__ ("fence i,r" : : : "memory");
+#define __io_bw()  __asm__ __volatile__ ("fence w,o" : : : "memory");
+#define __io_aw()  do { } while (0)
+
+#define readb(c)   ({ u8  __v; __io_br(); __v = readb_cpu(c); 
__io_ar(__v); __v; })
+#define readw(c)   ({ u16 __v; __io_br(); __v = readw_cpu(c); 
__io_ar(__v); __v; })
+#define readl(c)   ({ u32 __v; __io_br(); __v = readl_cpu(c); 
__io_ar(__v); __v; })
+
+#define writeb(v,c)({ __io_bw(); writeb_cpu((v),(c)); __io_aw(); })
+#define writew(v,c)({ __io_bw(); writew_cpu((v),(c)); __io_aw(); })
+#define writel(v,c)({ __io_bw(); writel_cpu((v),(c)); __io_aw(); })
+
+#ifdef CONFIG_64BIT
+#define readq(c)   ({ u64 __v; __io_br(); __v = readq_cpu(c); 
__io_ar(__v); __v; })
+#de

[PATCH v2 03/39] xen/riscv:introduce asm/byteorder.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/byteorder.h | 16 
 1 file changed, 16 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/byteorder.h

diff --git a/xen/arch/riscv/include/asm/byteorder.h 
b/xen/arch/riscv/include/asm/byteorder.h
new file mode 100644
index 00..320a03c88f
--- /dev/null
+++ b/xen/arch/riscv/include/asm/byteorder.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_RISCV_BYTEORDER_H__
+#define __ASM_RISCV_BYTEORDER_H__
+
+#define __BYTEORDER_HAS_U64__
+
+#include 
+
+#endif /* __ASM_RISCV_BYTEORDER_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 05/39] xen/riscv: introduce spinlock.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - update definition of arch_lock_signal() to not violate cod style.
 - update definition of arch_lock_signal_wmb() to use WMB aspect.
---
 xen/arch/riscv/include/asm/spinlock.h | 15 +++
 1 file changed, 15 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/spinlock.h

diff --git a/xen/arch/riscv/include/asm/spinlock.h 
b/xen/arch/riscv/include/asm/spinlock.h
new file mode 100644
index 00..bf45a7f005
--- /dev/null
+++ b/xen/arch/riscv/include/asm/spinlock.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_RISCV_SPINLOCK_H
+#define __ASM_RISCV_SPINLOCK_H
+
+#define arch_lock_acquire_barrier() smp_mb()
+#define arch_lock_release_barrier() smp_mb()
+
+#define arch_lock_relax() cpu_relax()
+#define arch_lock_signal() ((void)0)
+#define arch_lock_signal_wmb()  \
+({  \
+smp_wmb();  \
+arch_lock_signal(); \
+})
+
+#endif /* __ASM_RISCV_SPINLOCK_H */
-- 
2.42.0




[PATCH v2 11/39] xen/riscv: introduce asm/nospec.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/nospec.h | 25 +
 1 file changed, 25 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/nospec.h

diff --git a/xen/arch/riscv/include/asm/nospec.h 
b/xen/arch/riscv/include/asm/nospec.h
new file mode 100644
index 00..55087fa831
--- /dev/null
+++ b/xen/arch/riscv/include/asm/nospec.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
+
+#ifndef _ASM_RISCV_NOSPEC_H
+#define _ASM_RISCV_NOSPEC_H
+
+static inline bool evaluate_nospec(bool condition)
+{
+return condition;
+}
+
+static inline void block_speculation(void)
+{
+}
+
+#endif /* _ASM_RISCV_NOSPEC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 09/39] xen/riscv: introduce asm/guest_atomics.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/guest_atomics.h | 48 ++
 1 file changed, 48 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/guest_atomics.h

diff --git a/xen/arch/riscv/include/asm/guest_atomics.h 
b/xen/arch/riscv/include/asm/guest_atomics.h
new file mode 100644
index 00..9f14f76e92
--- /dev/null
+++ b/xen/arch/riscv/include/asm/guest_atomics.h
@@ -0,0 +1,48 @@
+#ifndef __ASM_RISCV_GUEST_ATOMICS_H
+#define __ASM_RISCV_GUEST_ATOMICS_H
+
+/*
+ * TODO: implement guest atomics
+ */
+
+#define guest_testop(name)  \
+static inline int guest_##name(struct domain *d, int nr, volatile void *p)  \
+{   \
+(void) d;   \
+(void) nr;  \
+(void) p;   \
+\
+return 0;   \
+}
+
+#define guest_bitop(name)   \
+static inline void guest_##name(struct domain *d, int nr, volatile void *p) \
+{   \
+(void) d;   \
+(void) nr;  \
+(void) p;   \
+}
+
+guest_bitop(set_bit)
+guest_bitop(clear_bit)
+guest_bitop(change_bit)
+
+#undef guest_bitop
+
+guest_testop(test_and_set_bit)
+guest_testop(test_and_clear_bit)
+guest_testop(test_and_change_bit)
+
+#undef guest_testop
+
+#define guest_test_bit(d, nr, p) ((void)(d), test_bit(nr, p))
+
+#endif /* __ASM_RISCV_GUEST_ATOMICS_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 13/39] xen/riscv: introduce asm/system.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/system.h | 79 +
 1 file changed, 79 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/system.h

diff --git a/xen/arch/riscv/include/asm/system.h 
b/xen/arch/riscv/include/asm/system.h
new file mode 100644
index 00..45bfed4e2b
--- /dev/null
+++ b/xen/arch/riscv/include/asm/system.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_RISCV_BARRIER_H
+#define _ASM_RISCV_BARRIER_H
+
+#include 
+
+#ifndef __ASSEMBLY__
+
+#define RISCV_FENCE(p, s) \
+__asm__ __volatile__ ("fence " #p "," #s : : : "memory")
+
+/* These barriers need to enforce ordering on both devices or memory. */
+#define mb()RISCV_FENCE(iorw,iorw)
+#define rmb()   RISCV_FENCE(ir,ir)
+#define wmb()   RISCV_FENCE(ow,ow)
+
+/* These barriers do not need to enforce ordering on devices, just memory. */
+#define smp_mb()RISCV_FENCE(rw,rw)
+#define smp_rmb()   RISCV_FENCE(r,r)
+#define smp_wmb()   RISCV_FENCE(w,w)
+#define smp_mb__before_atomic() smp_mb()
+#define smp_mb__after_atomic()  smp_mb()
+
+/*
+#define __smp_store_release(p, v)   \
+do {\
+   compiletime_assert_atomic_type(*p); \
+   RISCV_FENCE(rw,w);  \
+   WRITE_ONCE(*p, v);  \
+} while (0)
+
+#define __smp_load_acquire(p)   \
+({  \
+typeof(*p) ___p1 = READ_ONCE(*p);   \
+compiletime_assert_atomic_type(*p); \
+RISCV_FENCE(r,rw);  \
+___p1;  \
+})
+*/
+
+static inline unsigned long local_save_flags(void)
+{
+return csr_read(sstatus);
+}
+
+static inline void local_irq_enable(void)
+{
+csr_set(sstatus, SSTATUS_SIE);
+}
+
+static inline void local_irq_disable(void)
+{
+csr_clear(sstatus, SSTATUS_SIE);
+}
+
+#define local_irq_save(x)   \
+({  \
+x = csr_read_clear(CSR_SSTATUS, SSTATUS_SIE);   \
+local_irq_disable();\
+})
+
+static inline void local_irq_restore(unsigned long flags)
+{
+   csr_set(CSR_SSTATUS, flags & SSTATUS_SIE);
+}
+
+static inline int local_irq_is_enabled(void)
+{
+unsigned long flags = local_save_flags();
+
+return flags & SSTATUS_SIE;
+}
+
+#define arch_fetch_and_add(x, v) __sync_fetch_and_add(x, v)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_RISCV_BARRIER_H */
-- 
2.42.0




[PATCH v2 07/39] xen/riscv: introduce arch-riscv/hvm/save.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - remove copyright an the top of hvm/save.h as the header write now is a newly
   introduced empty header.
---
 xen/include/public/arch-riscv/hvm/save.h | 20 
 xen/include/public/hvm/save.h|  2 ++
 2 files changed, 22 insertions(+)
 create mode 100644 xen/include/public/arch-riscv/hvm/save.h

diff --git a/xen/include/public/arch-riscv/hvm/save.h 
b/xen/include/public/arch-riscv/hvm/save.h
new file mode 100644
index 00..1eb037830d
--- /dev/null
+++ b/xen/include/public/arch-riscv/hvm/save.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_SAVE_RISCV_H__
+#define __XEN_PUBLIC_HVM_SAVE_RISCV_H__
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h
index 2cf4238daa..80328c3216 100644
--- a/xen/include/public/hvm/save.h
+++ b/xen/include/public/hvm/save.h
@@ -91,6 +91,8 @@ DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end);
 #include "../arch-arm/hvm/save.h"
 #elif defined(__powerpc64__)
 #include "../arch-ppc.h"
+#elif defined(__riscv)
+#include "../arch-riscv/hvm/save.h"
 #else
 #error "unsupported architecture"
 #endif
-- 
2.42.0




[PATCH v2 16/39] xen/riscv: introduce asm/smp.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/smp.h | 23 +++
 1 file changed, 23 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/smp.h

diff --git a/xen/arch/riscv/include/asm/smp.h b/xen/arch/riscv/include/asm/smp.h
new file mode 100644
index 00..a7b4f94ce4
--- /dev/null
+++ b/xen/arch/riscv/include/asm/smp.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_RISCV_SMP_H
+#define __ASM_RISCV_SMP_H
+
+#ifndef __ASSEMBLY__
+#include 
+#include 
+#endif
+
+DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_mask);
+DECLARE_PER_CPU(cpumask_var_t, cpu_core_mask);
+
+#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
+
+/*
+ * Do we, for platform reasons, need to actually keep CPUs online when we
+ * would otherwise prefer them to be off?
+ */
+#define park_offline_cpus false
+
+/* TODO: need to be implemeted */
+#define smp_processor_id() (0)
+
+#endif
\ No newline at end of file
-- 
2.42.0




[PATCH v2 18/39] xen/riscv: introduce cmpxchg.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
- update the comment at the top of the header.
- change xen/lib.h to xen/bug.h.
- sort inclusion of headers properly.
---
 xen/arch/riscv/include/asm/cmpxchg.h | 379 +++
 1 file changed, 379 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/cmpxchg.h

diff --git a/xen/arch/riscv/include/asm/cmpxchg.h 
b/xen/arch/riscv/include/asm/cmpxchg.h
new file mode 100644
index 00..c535bc9660
--- /dev/null
+++ b/xen/arch/riscv/include/asm/cmpxchg.h
@@ -0,0 +1,379 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Taken and modified from Linux.
+ *
+ *  Copyright (C) 2014 Regents of the University of California
+ */
+
+#ifndef _ASM_RISCV_CMPXCHG_H
+#define _ASM_RISCV_CMPXCHG_H
+
+#include 
+
+#include 
+#include 
+
+#define __xchg_relaxed(ptr, new, size) \
+({ \
+   __typeof__(ptr) __ptr = (ptr);  \
+   __typeof__(new) __new = (new);  \
+   __typeof__(*(ptr)) __ret;   \
+   switch (size) { \
+   case 4: \
+   __asm__ __volatile__ (  \
+   "   amoswap.w %0, %2, %1\n" \
+   : "=r" (__ret), "+A" (*__ptr)   \
+   : "r" (__new)   \
+   : "memory");\
+   break;  \
+   case 8: \
+   __asm__ __volatile__ (  \
+   "   amoswap.d %0, %2, %1\n" \
+   : "=r" (__ret), "+A" (*__ptr)   \
+   : "r" (__new)   \
+   : "memory");\
+   break;  \
+   default:\
+   ASSERT_UNREACHABLE();   \
+   }   \
+   __ret;  \
+})
+
+#define xchg_relaxed(ptr, x)   \
+({ \
+   __typeof__(*(ptr)) _x_ = (x);   \
+   (__typeof__(*(ptr))) __xchg_relaxed((ptr),  \
+   _x_, sizeof(*(ptr)));   \
+})
+
+#define __xchg_acquire(ptr, new, size) \
+({ \
+   __typeof__(ptr) __ptr = (ptr);  \
+   __typeof__(new) __new = (new);  \
+   __typeof__(*(ptr)) __ret;   \
+   switch (size) { \
+   case 4: \
+   __asm__ __volatile__ (  \
+   "   amoswap.w %0, %2, %1\n" \
+   RISCV_ACQUIRE_BARRIER   \
+   : "=r" (__ret), "+A" (*__ptr)   \
+   : "r" (__new)   \
+   : "memory");\
+   break;  \
+   case 8: \
+   __asm__ __volatile__ (  \
+   "   amoswap.d %0, %2, %1\n" \
+   RISCV_ACQUIRE_BARRIER   \
+   : "=r" (__ret), "+A" (*__ptr)   \
+   : "r" (__new)   \
+   : "memory");\
+   break;  \
+   default:\
+   ASSERT_UNREACHABLE();   \
+   }   \
+   __ret;  \
+})
+
+#define xchg_acquire(ptr, x)   \
+({  

[RFC KERNEL PATCH v2 1/3] xen/pci: Add xen_reset_device_state function

2023-11-24 Thread Jiqian Chen
When device on dom0 side has been reset, the vpci on Xen side
won't get notification, so that the cached state in vpci is
all out of date with the real device state.
To solve that problem, this patch add a function to clear all
vpci device state when device is reset on dom0 side.

And call that function in pcistub_init_device. Because when
we use "pci-assignable-add" to assign a passthrough device in
Xen, it will reset passthrough device and the vpci state will
out of date, and then device will fail to restore bar state.

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 drivers/xen/pci.c  | 12 
 drivers/xen/xen-pciback/pci_stub.c |  3 +++
 include/xen/interface/physdev.h|  2 ++
 include/xen/pci.h  |  6 ++
 4 files changed, 23 insertions(+)

diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c
index 72d4e3f193af..e9b30bc09139 100644
--- a/drivers/xen/pci.c
+++ b/drivers/xen/pci.c
@@ -177,6 +177,18 @@ static int xen_remove_device(struct device *dev)
return r;
 }
 
+int xen_reset_device_state(const struct pci_dev *dev)
+{
+   struct physdev_pci_device device = {
+   .seg = pci_domain_nr(dev->bus),
+   .bus = dev->bus->number,
+   .devfn = dev->devfn
+   };
+
+   return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_state_reset, &device);
+}
+EXPORT_SYMBOL_GPL(xen_reset_device_state);
+
 static int xen_pci_notifier(struct notifier_block *nb,
unsigned long action, void *data)
 {
diff --git a/drivers/xen/xen-pciback/pci_stub.c 
b/drivers/xen/xen-pciback/pci_stub.c
index e34b623e4b41..5a96b6c66c07 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -421,6 +421,9 @@ static int pcistub_init_device(struct pci_dev *dev)
else {
dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
__pci_reset_function_locked(dev);
+   err = xen_reset_device_state(dev);
+   if (err)
+   goto config_release;
pci_restore_state(dev);
}
/* Now disable the device (this also ensures some private device
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
index a237af867873..231526f80f6c 100644
--- a/include/xen/interface/physdev.h
+++ b/include/xen/interface/physdev.h
@@ -263,6 +263,8 @@ struct physdev_pci_device {
 uint8_t devfn;
 };
 
+#define PHYSDEVOP_pci_device_state_reset 32
+
 #define PHYSDEVOP_DBGP_RESET_PREPARE1
 #define PHYSDEVOP_DBGP_RESET_DONE   2
 
diff --git a/include/xen/pci.h b/include/xen/pci.h
index b8337cf85fd1..b2e2e856efd6 100644
--- a/include/xen/pci.h
+++ b/include/xen/pci.h
@@ -4,10 +4,16 @@
 #define __XEN_PCI_H__
 
 #if defined(CONFIG_XEN_DOM0)
+int xen_reset_device_state(const struct pci_dev *dev);
 int xen_find_device_domain_owner(struct pci_dev *dev);
 int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
 int xen_unregister_device_domain_owner(struct pci_dev *dev);
 #else
+static inline int xen_reset_device_state(const struct pci_dev *dev)
+{
+   return -1;
+}
+
 static inline int xen_find_device_domain_owner(struct pci_dev *dev)
 {
return -1;
-- 
2.34.1




[RFC KERNEL PATCH v2 3/3] xen/privcmd: Add new syscall to get gsi from irq

2023-11-24 Thread Jiqian Chen
In PVH dom0, it uses the linux local interrupt mechanism,
when it allocs irq for a gsi, it is dynamic, and follow
the principle of applying first, distributing first. And
if you debug the codes, you will find the irq number is
alloced from small to large, but the applying gsi number
is not, may gsi 38 comes before gsi 28, it causes the irq
number is not equal with the gsi number.
And when we passthrough a device, QEMU will use device's gsi
number to do mapping actions, see xen_pt_realize->
xc_physdev_map_pirq, but the gsi number is got from file
/sys/bus/pci/devices/:xx:xx.x/irq, irq!= gsi, so it will
fail when mapping.
And in current linux codes, there is no method to translate
irq to gsi for userspace.

For above purpose, this patch record the relationship of gsi
and irq when PVH dom0 do acpi_register_gsi_ioapic for devices
and adds a new syscall into privcmd to let userspace can get
that translation when they have a need.

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 arch/x86/include/asm/apic.h  |  7 ++
 arch/x86/include/asm/xen/pci.h   |  5 
 arch/x86/kernel/acpi/boot.c  |  2 +-
 arch/x86/pci/xen.c   | 21 +
 drivers/xen/events/events_base.c | 39 
 drivers/xen/privcmd.c| 20 
 include/uapi/xen/privcmd.h   |  7 ++
 include/xen/events.h |  5 
 8 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index d21f48f1c242..5646444285ac 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -169,6 +169,8 @@ extern bool apic_needs_pit(void);
 
 extern void apic_send_IPI_allbutself(unsigned int vector);
 
+extern int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
+   int trigger, int polarity);
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 #define local_apic_timer_c2_ok 1
@@ -183,6 +185,11 @@ static inline void apic_intr_mode_init(void) { }
 static inline void lapic_assign_system_vectors(void) { }
 static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { }
 static inline bool apic_needs_pit(void) { return true; }
+static inline int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
+   int trigger, int polarity)
+{
+   return (int)gsi;
+}
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_X2APIC
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h
index 9015b888edd6..aa8ded61fc2d 100644
--- a/arch/x86/include/asm/xen/pci.h
+++ b/arch/x86/include/asm/xen/pci.h
@@ -5,6 +5,7 @@
 #if defined(CONFIG_PCI_XEN)
 extern int __init pci_xen_init(void);
 extern int __init pci_xen_hvm_init(void);
+extern int __init pci_xen_pvh_init(void);
 #define pci_xen 1
 #else
 #define pci_xen 0
@@ -13,6 +14,10 @@ static inline int pci_xen_hvm_init(void)
 {
return -1;
 }
+static inline int pci_xen_pvh_init(void)
+{
+   return -1;
+}
 #endif
 #ifdef CONFIG_XEN_PV_DOM0
 int __init pci_xen_initial_domain(void);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index d0918a75cb00..45b157e18c0b 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -739,7 +739,7 @@ static int acpi_register_gsi_pic(struct device *dev, u32 
gsi,
 }
 
 #ifdef CONFIG_X86_LOCAL_APIC
-static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
+int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
int trigger, int polarity)
 {
int irq = gsi;
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 652cd53e77f6..f056ab5c0a06 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -114,6 +114,21 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, 
u32 gsi,
 false /* no mapping of GSI to PIRQ */);
 }
 
+static int acpi_register_gsi_xen_pvh(struct device *dev, u32 gsi,
+   int trigger, int polarity)
+{
+   int irq;
+
+   irq = acpi_register_gsi_ioapic(dev, gsi, trigger, polarity);
+   if (irq < 0)
+   return irq;
+
+   if (xen_pvh_add_gsi_irq_map(gsi, irq) == -EEXIST)
+   printk(KERN_INFO "Already map the GSI :%u and IRQ: %d\n", gsi, 
irq);
+
+   return irq;
+}
+
 #ifdef CONFIG_XEN_PV_DOM0
 static int xen_register_gsi(u32 gsi, int triggering, int polarity)
 {
@@ -558,6 +573,12 @@ int __init pci_xen_hvm_init(void)
return 0;
 }
 
+int __init pci_xen_pvh_init(void)
+{
+   __acpi_register_gsi = acpi_register_gsi_xen_pvh;
+   return 0;
+}
+
 #ifdef CONFIG_XEN_PV_DOM0
 int __init pci_xen_initial_domain(void)
 {
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 6de6b084ea60..a02d62955509 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -957,6 +957,43 @@ int xen_irq_

[RFC KERNEL PATCH v2 2/3] xen/pvh: Unmask irq for passthrough device in PVH dom0

2023-11-24 Thread Jiqian Chen
This patch is to solve two problems we encountered when we try to
passthrough a device to hvm domU base on Xen PVH dom0.

First, hvm guest will alloc a pirq and irq for a passthrough device
by using gsi, before that, the gsi must first has a mapping in dom0,
see Xen code pci_add_dm_done->xc_domain_irq_permission, it will call
into Xen and check whether dom0 has the mapping. See
XEN_DOMCTL_irq_permission->pirq_access_permitted, "current" is PVH
dom0 and it return irq is 0, and then return -EPERM.
This is because the passthrough device doesn't do PHYSDEVOP_map_pirq
when thay are enabled.

Second, in PVH dom0, the gsi of a passthrough device doesn't get
registered, but gsi must be configured for it to be able to be
mapped into a domU.

After searching codes, we can find map_pirq and register_gsi will be
done in function vioapic_write_redirent->vioapic_hwdom_map_gsi when
the gsi(aka ioapic's pin) is unmasked in PVH dom0. So the problems
can be conclude to that the gsi of a passthrough device doesn't be
unmasked.

To solve the unmaske problem, this patch call the unmask_irq when we
assign a device to be passthrough. So that the gsi can get registered
and mapped in PVH dom0.

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 drivers/xen/xen-pciback/pci_stub.c | 7 +++
 include/linux/irq.h| 1 +
 kernel/irq/chip.c  | 1 +
 kernel/irq/internals.h | 1 -
 kernel/irq/irqdesc.c   | 2 +-
 5 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/xen/xen-pciback/pci_stub.c 
b/drivers/xen/xen-pciback/pci_stub.c
index 5a96b6c66c07..b83d02bcc76c 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -357,6 +357,7 @@ static int pcistub_match(struct pci_dev *dev)
 static int pcistub_init_device(struct pci_dev *dev)
 {
struct xen_pcibk_dev_data *dev_data;
+   struct irq_desc *desc = NULL;
int err = 0;
 
dev_dbg(&dev->dev, "initializing...\n");
@@ -399,6 +400,12 @@ static int pcistub_init_device(struct pci_dev *dev)
if (err)
goto config_release;
 
+   if (xen_initial_domain() && xen_pvh_domain()) {
+   if (dev->irq <= 0 || !(desc = irq_to_desc(dev->irq)))
+   goto config_release;
+   unmask_irq(desc);
+   }
+
if (dev->msix_cap) {
struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus),
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 90081afa10ce..44650ca178d9 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -659,6 +659,7 @@ extern void handle_percpu_irq(struct irq_desc *desc);
 extern void handle_percpu_devid_irq(struct irq_desc *desc);
 extern void handle_bad_irq(struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
+extern void unmask_irq(struct irq_desc *desc);
 
 extern void handle_fasteoi_nmi(struct irq_desc *desc);
 extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index dc94e0bf2c94..fd67b40b678d 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -439,6 +439,7 @@ void unmask_irq(struct irq_desc *desc)
irq_state_clr_masked(desc);
}
 }
+EXPORT_SYMBOL_GPL(unmask_irq);
 
 void unmask_threaded_irq(struct irq_desc *desc)
 {
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index bcc7f21db9ee..d08e3e7b2819 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -95,7 +95,6 @@ extern void irq_disable(struct irq_desc *desc);
 extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
 extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
 extern void mask_irq(struct irq_desc *desc);
-extern void unmask_irq(struct irq_desc *desc);
 extern void unmask_threaded_irq(struct irq_desc *desc);
 
 #ifdef CONFIG_SPARSE_IRQ
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 27ca1c866f29..5977efed31b5 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -380,7 +380,7 @@ struct irq_desc *irq_to_desc(unsigned int irq)
 {
return mtree_load(&sparse_irqs, irq);
 }
-#ifdef CONFIG_KVM_BOOK3S_64_HV_MODULE
+#if defined CONFIG_KVM_BOOK3S_64_HV_MODULE || defined CONFIG_XEN_PVH
 EXPORT_SYMBOL_GPL(irq_to_desc);
 #endif
 
-- 
2.34.1




[RFC KERNEL PATCH v2 0/3] Support device passthrough when dom0 is PVH on Xen

2023-11-24 Thread Jiqian Chen
Hi All,

This series of patches are the v2 of the implementation of passthrough when 
dom0 is PVH on Xen.
We sent the v1 to upstream before, but the v1 had so many problems and we got 
lots of suggestions.
I will introduce all issues that these patches try to fix and the differences 
between v1 and v2.

Issues we encountered:
1. pci_stub failed to write bar for a passthrough device.
Problem: when we run “sudo xl pci-assignable-add ” to assign a device, 
pci_stub will
call “pcistub_init_device() -> pci_restore_state() -> 
pci_restore_config_space() ->
pci_restore_config_space_range() -> pci_restore_config_dword() -> 
pci_write_config_dword()”,
the pci config write will trigger an io interrupt to bar_write() in the xen, 
but the
bar->enabled was set before, the write is not allowed now, and then when Qemu 
config the
passthrough device in xen_pt_realize(), it gets invalid bar values.

Reason: the reason is that we don't tell vPCI that the device has been reset, 
so the current
cached state in pdev->vpci is all out of date and is different from the real 
device state.

Solution: to solve this problem, the first patch of kernel(xen/pci: Add 
xen_reset_device_state
function) and the fist patch of xen(xen/vpci: Clear all vpci status of device) 
add a new
hypercall to reset the state stored in vPCI when the state of real device has 
changed.
Thank Roger for the suggestion of this v2, and it is different from v1
(https://lore.kernel.org/xen-devel/20230312075455.450187-3-ray.hu...@amd.com/), 
v1 simply allow
domU to write pci bar, it does not comply with the design principles of vPCI.

2. failed to do PHYSDEVOP_map_pirq when dom0 is PVH
Problem: HVM domU will do PHYSDEVOP_map_pirq for a passthrough device by using 
gsi. See
xen_pt_realize->xc_physdev_map_pirq and pci_add_dm_done->xc_physdev_map_pirq. 
Then
xc_physdev_map_pirq will call into Xen, but in hvm_physdev_op(), 
PHYSDEVOP_map_pirq is not allowed.

Reason: In hvm_physdev_op(), the variable "currd" is PVH dom0 and PVH has no 
X86_EMU_USE_PIRQ flag,
it will fail at has_pirq check.

Solution: I think we may need to allow PHYSDEVOP_map_pirq when "currd" is dom0 
(at present dom0 is
PVH). The second patch of xen(x86/pvh: Open PHYSDEVOP_map_pirq for PVH dom0) 
allow PVH dom0 do
PHYSDEVOP_map_pirq. This v2 patch is better than v1, v1 simply remove the 
has_pirq check(xen
https://lore.kernel.org/xen-devel/20230312075455.450187-4-ray.hu...@amd.com/).

3. the gsi of a passthrough device doesn't be unmasked
 3.1 failed to check the permission of pirq
 3.2 the gsi of passthrough device was not registered in PVH dom0

Problem:
3.1 callback function pci_add_dm_done() will be called when qemu config a 
passthrough device for domU.
This function will call xc_domain_irq_permission()-> pirq_access_permitted() to 
check if the gsi has
corresponding mappings in dom0. But it didn’t, so failed. See
XEN_DOMCTL_irq_permission->pirq_access_permitted, "current" is PVH dom0 and it 
return irq is 0.
3.2 it's possible for a gsi (iow: vIO-APIC pin) to never get registered on PVH 
dom0, because the
devices of PVH are using MSI(-X) interrupts. However, the IO-APIC pin must be 
configured for it to be
able to be mapped into a domU.

Reason: After searching codes, I find "map_pirq" and "register_gsi" will be 
done in function
vioapic_write_redirent->vioapic_hwdom_map_gsi when the gsi(aka ioapic's pin) is 
unmasked in PVH dom0.
So the two problems can be concluded to that the gsi of a passthrough device 
doesn't be unmasked.

Solution: to solve these problems, the second patch of kernel(xen/pvh: Unmask 
irq for passthrough
device in PVH dom0) call the unmask_irq() when we assign a device to be 
passthrough. So that
passthrough devices can have the mapping of gsi on PVH dom0 and gsi can be 
registered. This v2 patch
is different from the v1(
kernel 
https://lore.kernel.org/xen-devel/20230312120157.452859-5-ray.hu...@amd.com/,
kernel 
https://lore.kernel.org/xen-devel/20230312120157.452859-5-ray.hu...@amd.com/ and
xen 
https://lore.kernel.org/xen-devel/20230312075455.450187-5-ray.hu...@amd.com/),
v1 performed "map_pirq" and "register_gsi" on all pci devices on PVH dom0, 
which is unnecessary and
may cause multiple registration.

4. failed to map pirq for gsi
Problem: qemu will call xc_physdev_map_pirq() to map a passthrough device’s gsi 
to pirq in function
xen_pt_realize(). But failed.

Reason: According to the implement of xc_physdev_map_pirq(), it needs gsi 
instead of irq, but qemu
pass irq to it and treat irq as gsi, it is got from file 
/sys/bus/pci/devices/:xx:xx.x/irq in
function xen_host_pci_device_get(). But actually the gsi number is not equal 
with irq. On PVH dom0,
when it allocates irq for a gsi in function acpi_register_gsi_ioapic(), 
allocation is dynamic, and
follow the principle of applying first, distributing first. And if you debug 
the kernel codes(see
function __irq_alloc_descs), you will find the irq number is allocated from 
small to large by order,
but the applying

[PATCH v2 27/39] xen/riscv: introduce asm/time.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 -  change xen/lib.h to xen/bug.h
 - remove inclusion of  as it's not needed.
---
 xen/arch/riscv/include/asm/time.h | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/time.h

diff --git a/xen/arch/riscv/include/asm/time.h 
b/xen/arch/riscv/include/asm/time.h
new file mode 100644
index 00..3ce848deac
--- /dev/null
+++ b/xen/arch/riscv/include/asm/time.h
@@ -0,0 +1,19 @@
+#ifndef __ASM_RISCV_TIME_H__
+#define __ASM_RISCV_TIME_H__
+
+#include 
+#include 
+
+struct vcpu;
+
+/* TODO: implement */
+static inline void force_update_vcpu_system_time(struct vcpu *v) { BUG(); }
+
+typedef unsigned long cycles_t;
+
+static inline cycles_t get_cycles(void)
+{
+   return csr_read(CSR_TIME);
+}
+
+#endif /* __ASM_RISCV_TIME_H__ */
\ No newline at end of file
-- 
2.42.0




[PATCH v2 28/39] xen/riscv: introduce asm/event.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/event.h | 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/event.h

diff --git a/xen/arch/riscv/include/asm/event.h 
b/xen/arch/riscv/include/asm/event.h
new file mode 100644
index 00..48630c77b3
--- /dev/null
+++ b/xen/arch/riscv/include/asm/event.h
@@ -0,0 +1,34 @@
+#ifndef __ASM_RISCV_EVENT_H__
+#define __ASM_RISCV_EVENT_H__
+
+void vcpu_mark_events_pending(struct vcpu *v);
+
+static inline int vcpu_event_delivery_is_enabled(struct vcpu *v)
+{
+return 0;
+}
+
+static inline int local_events_need_delivery(void)
+{
+return 0;
+}
+
+static inline void local_event_delivery_enable(void)
+{
+}
+
+/* No arch specific virq definition now. Default to global. */
+static inline bool arch_virq_is_global(unsigned int virq)
+{
+return true;
+}
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 14/39] xen/riscv: introduce bitops.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/bitops.h | 288 
 1 file changed, 288 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/bitops.h

diff --git a/xen/arch/riscv/include/asm/bitops.h 
b/xen/arch/riscv/include/asm/bitops.h
new file mode 100644
index 00..24a49c499b
--- /dev/null
+++ b/xen/arch/riscv/include/asm/bitops.h
@@ -0,0 +1,288 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012 Regents of the University of California */
+
+#ifndef _ASM_RISCV_BITOPS_H
+#define _ASM_RISCV_BITOPS_H
+
+#include 
+
+#define BITOP_BITS_PER_WORD 32
+#define BITOP_MASK(nr) (1UL << ((nr) % BITOP_BITS_PER_WORD))
+#define BITOP_WORD(nr) ((nr) / BITOP_BITS_PER_WORD)
+#define BITS_PER_BYTE  8
+
+#define __set_bit(n,p)  set_bit(n,p)
+#define __clear_bit(n,p)clear_bit(n,p)
+
+#define __AMO(op)  "amo" #op ".w"
+
+#define __test_and_op_bit_ord(op, mod, nr, addr, ord)  \
+({ \
+   unsigned long __res, __mask;\
+   __mask = BITOP_MASK(nr);\
+   __asm__ __volatile__ (  \
+   __AMO(op) #ord " %0, %2, %1"\
+   : "=r" (__res), "+A" (addr[BITOP_WORD(nr)]) \
+   : "r" (mod(__mask)) \
+   : "memory");\
+   ((__res & __mask) != 0);\
+})
+
+#define __op_bit_ord(op, mod, nr, addr, ord)   \
+   __asm__ __volatile__ (  \
+   __AMO(op) #ord " zero, %1, %0"  \
+   : "+A" (addr[BITOP_WORD(nr)])   \
+   : "r" (mod(BITOP_MASK(nr))) \
+   : "memory");
+
+#define __test_and_op_bit(op, mod, nr, addr)   \
+   __test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
+
+#define __op_bit(op, mod, nr, addr)\
+   __op_bit_ord(op, mod, nr, addr, )
+
+/* Bitmask modifiers */
+#define __NOP(x)   (x)
+#define __NOT(x)   (~(x))
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation may be reordered on other architectures than x86.
+ */
+static inline int __test_and_set_bit(int nr, volatile void *p)
+{
+   volatile uint32_t *addr = p;
+
+   return __test_and_op_bit(or, __NOP, nr, addr);
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation can be reordered on other architectures other than x86.
+ */
+static inline int __test_and_clear_bit(int nr, volatile void *p)
+{
+   volatile uint32_t *addr = p;
+
+   return __test_and_op_bit(and, __NOT, nr, addr);
+}
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writing portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile void *p)
+{
+   volatile uint32_t *addr = p;
+
+   __op_bit(or, __NOP, nr, addr);
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writing portable code,
+ * make sure not to rely on its reordering guarantees.
+ */
+static inline void clear_bit(int nr, volatile void *p)
+{
+   volatile uint32_t *addr = p;
+
+   __op_bit(and, __NOT, nr, addr);
+}
+
+static inline int test_bit(int nr, const volatile void *p)
+{
+   const volatile uint32_t *addr = (const volatile uint32_t *)p;
+
+   return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITOP_BITS_PER_WORD-1)));
+}
+
+#undef __test_and_op_bit
+#undef __op_bit
+#undef __NOP
+#undef __NOT
+#undef __AMO
+
+static inline int fls(unsigned int x)
+{
+return generic_fls(x);
+}
+
+static inline int flsl(unsigned long x)
+{
+return generic_flsl(x);
+}
+
+#define test_and_set_bit   __test_and_set_bit
+#define test_and_clear_bit __test_and_clear_bit
+
+/* Based on linux/include/asm-generic/bitops/find.h */
+
+#ifndef find_next_bit
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
+extern unsigned long find_n

[PATCH v2 22/39] xen/riscv: introduce asm/domain.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/domain.h | 43 +
 1 file changed, 43 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/domain.h

diff --git a/xen/arch/riscv/include/asm/domain.h 
b/xen/arch/riscv/include/asm/domain.h
new file mode 100644
index 00..f2dccf370f
--- /dev/null
+++ b/xen/arch/riscv/include/asm/domain.h
@@ -0,0 +1,43 @@
+#ifndef __ASM_RISCV_DOMAIN_H__
+#define __ASM_RISCV_DOMAIN_H__
+
+#include 
+#include 
+
+struct hvm_domain
+{
+uint64_t  params[HVM_NR_PARAMS];
+};
+
+#define is_domain_direct_mapped(d) ((void)(d), 0)
+
+struct arch_vcpu_io {
+};
+
+struct arch_vcpu {
+};
+
+struct arch_domain {
+struct hvm_domain hvm;
+};
+
+#include 
+
+static inline struct vcpu_guest_context *alloc_vcpu_guest_context(void)
+{
+return xmalloc(struct vcpu_guest_context);
+}
+
+static inline void free_vcpu_guest_context(struct vcpu_guest_context *vgc)
+{
+xfree(vgc);
+}
+
+struct guest_memory_policy {};
+static inline void update_guest_memory_policy(struct vcpu *v,
+  struct guest_memory_policy *gmp)
+{}
+
+static inline void arch_vcpu_block(struct vcpu *v) {}
+
+#endif /* __ASM_RISCV_DOMAIN_H__ */
-- 
2.42.0




[PATCH v2 38/39] xen/riscv: enable full Xen build

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/Makefile | 16 +++-
 xen/arch/riscv/arch.mk  |  4 
 xen/arch/riscv/configs/tiny64_defconfig |  1 -
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 50c09469a0..9c02cb0ccf 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -12,10 +12,24 @@ $(TARGET): $(TARGET)-syms
$(OBJCOPY) -O binary -S $< $@
 
 $(TARGET)-syms: $(objtree)/prelink.o $(obj)/xen.lds
-   $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< $(build_id_linker) -o $@
+   $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< \
+   $(objtree)/common/symbols-dummy.o -o $(dot-target).0
+   $(NM) -pa --format=sysv $(dot-target).0 \
+   | $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
+   > $(dot-target).0.S
+   $(MAKE) $(build)=$(@D) $(dot-target).0.o
+   $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< \
+   $(dot-target).0.o -o $(dot-target).1
+   $(NM) -pa --format=sysv $(dot-target).1 \
+   | $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
+   > $(dot-target).1.S
+   $(MAKE) $(build)=$(@D) $(dot-target).1.o
+   $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< $(build_id_linker) \
+   $(dot-target).1.o -o $@
$(NM) -pa --format=sysv $@ \
| $(objtree)/tools/symbols --all-symbols --xensyms --sysv 
--sort \
> $@.map
+   rm -f $(@D)/.$(@F).[0-9]*
 
 $(obj)/xen.lds: $(src)/xen.lds.S FORCE
$(call if_changed_dep,cpp_lds_S)
diff --git a/xen/arch/riscv/arch.mk b/xen/arch/riscv/arch.mk
index 8403f96b6f..12b1673fae 100644
--- a/xen/arch/riscv/arch.mk
+++ b/xen/arch/riscv/arch.mk
@@ -13,7 +13,3 @@ riscv-march-$(CONFIG_RISCV_ISA_C)   := $(riscv-march-y)c
 # -mcmodel=medlow would force Xen into the lower half.
 
 CFLAGS += -march=$(riscv-march-y) -mstrict-align -mcmodel=medany
-
-# TODO: Drop override when more of the build is working
-override ALL_OBJS-y = arch/$(SRCARCH)/built_in.o
-override ALL_LIBS-y =
diff --git a/xen/arch/riscv/configs/tiny64_defconfig 
b/xen/arch/riscv/configs/tiny64_defconfig
index ce37c5ae00..4b488180ae 100644
--- a/xen/arch/riscv/configs/tiny64_defconfig
+++ b/xen/arch/riscv/configs/tiny64_defconfig
@@ -24,7 +24,6 @@
 # CONFIG_COVERAGE is not set
 # CONFIG_UBSAN is not set
 # CONFIG_NEEDS_LIBELF is not set
-
 CONFIG_RISCV_64=y
 CONFIG_DEBUG=y
 CONFIG_DEBUG_INFO=y
-- 
2.42.0




[PATCH v2 21/39] xen/riscv: introduce bit operations

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/Makefile|   1 +
 xen/arch/riscv/lib/Makefile|   1 +
 xen/arch/riscv/lib/find_next_bit.c | 278 +
 3 files changed, 280 insertions(+)
 create mode 100644 xen/arch/riscv/lib/Makefile
 create mode 100644 xen/arch/riscv/lib/find_next_bit.c

diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 2fefe14e7c..b08048948f 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 obj-y += entry.o
+obj-y += lib/
 obj-y += mm.o
 obj-$(CONFIG_RISCV_64) += riscv64/
 obj-y += sbi.o
diff --git a/xen/arch/riscv/lib/Makefile b/xen/arch/riscv/lib/Makefile
new file mode 100644
index 00..6fae6a1f10
--- /dev/null
+++ b/xen/arch/riscv/lib/Makefile
@@ -0,0 +1 @@
+obj-y += find_next_bit.o
diff --git a/xen/arch/riscv/lib/find_next_bit.c 
b/xen/arch/riscv/lib/find_next_bit.c
new file mode 100644
index 00..ac5a4687e3
--- /dev/null
+++ b/xen/arch/riscv/lib/find_next_bit.c
@@ -0,0 +1,278 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * find_next_bit.c: fallback find next bit implementation
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+#include 
+#include 
+#include 
+
+#ifndef find_next_bit
+/*
+ * Find the next set bit in a memory region.
+ */
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+   unsigned long offset)
+{
+   const unsigned long *p = addr + BIT_WORD(offset);
+   unsigned long result = offset & ~(BITS_PER_LONG-1);
+   unsigned long tmp;
+
+   if (offset >= size)
+   return size;
+   size -= result;
+   offset %= BITS_PER_LONG;
+   if (offset) {
+   tmp = *(p++);
+   tmp &= (~0UL << offset);
+   if (size < BITS_PER_LONG)
+   goto found_first;
+   if (tmp)
+   goto found_middle;
+   size -= BITS_PER_LONG;
+   result += BITS_PER_LONG;
+   }
+   while (size & ~(BITS_PER_LONG-1)) {
+   if ((tmp = *(p++)))
+   goto found_middle;
+   result += BITS_PER_LONG;
+   size -= BITS_PER_LONG;
+   }
+   if (!size)
+   return result;
+   tmp = *p;
+
+found_first:
+   tmp &= (~0UL >> (BITS_PER_LONG - size));
+   if (tmp == 0UL) /* Are any bits set? */
+   return result + size;   /* Nope. */
+found_middle:
+   return result + __ffs(tmp);
+}
+EXPORT_SYMBOL(find_next_bit);
+#endif
+
+#ifndef find_next_zero_bit
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+unsigned long offset)
+{
+   const unsigned long *p = addr + BIT_WORD(offset);
+   unsigned long result = offset & ~(BITS_PER_LONG-1);
+   unsigned long tmp;
+
+   if (offset >= size)
+   return size;
+   size -= result;
+   offset %= BITS_PER_LONG;
+   if (offset) {
+   tmp = *(p++);
+   tmp |= ~0UL >> (BITS_PER_LONG - offset);
+   if (size < BITS_PER_LONG)
+   goto found_first;
+   if (~tmp)
+   goto found_middle;
+   size -= BITS_PER_LONG;
+   result += BITS_PER_LONG;
+   }
+   while (size & ~(BITS_PER_LONG-1)) {
+   if (~(tmp = *(p++)))
+   goto found_middle;
+   result += BITS_PER_LONG;
+   size -= BITS_PER_LONG;
+   }
+   if (!size)
+   return result;
+   tmp = *p;
+
+found_first:
+   tmp |= ~0UL << size;
+   if (tmp == ~0UL)/* Are any bits zero? */
+   return result + size;   /* Nope. */
+found_middle:
+   return result + ffz(tmp);
+}
+EXPORT_SYMBOL(find_next_zero_bit);
+#endif
+
+#ifndef find_first_bit
+/*
+ * Find the first set bit in a memory region.
+ */
+unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
+{
+   const unsigned long *p = addr;
+   unsigned long result = 0;
+   unsigned long tmp;
+
+   while (size & ~(BITS_PER_LONG-1)) {
+   if ((tmp = *(p++)))
+   goto found;
+   result += BITS_PER_LONG;
+   size -= BITS_PER_LONG;
+   }
+   if (!size)
+   return result;
+
+   tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
+   if (tmp == 0UL) /* Are any bits set? */
+   return result + size;   /* Nope. */
+found:
+   return result + __ffs(tmp);
+}
+EXPORT_SYMBOL(find_first_bit);
+#endif
+
+#ifndef find_first_zero_bit
+/*
+ * Find the first cleared bit in

[PATCH v2 23/39] xen/riscv: introduce asm/guest_access.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - change xen/mm.h to xen/types.h
---
 xen/arch/riscv/include/asm/guest_access.h | 29 +++
 1 file changed, 29 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/guest_access.h

diff --git a/xen/arch/riscv/include/asm/guest_access.h 
b/xen/arch/riscv/include/asm/guest_access.h
new file mode 100644
index 00..122ecdc048
--- /dev/null
+++ b/xen/arch/riscv/include/asm/guest_access.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_RISCV_GUEST_ACCESS_H__
+#define __ASM_RISCV_GUEST_ACCESS_H__
+
+#include 
+
+unsigned long raw_copy_to_guest(void *to, const void *from, unsigned len);
+unsigned long raw_copy_from_guest(void *to, const void *from, unsigned len);
+
+#define __raw_copy_to_guest raw_copy_to_guest
+#define __raw_copy_from_guest raw_copy_from_guest
+
+#define guest_handle_okay(hnd, nr) (1)
+#define guest_handle_subrange_okay(hnd, first, last) (1)
+
+struct domain;
+unsigned long copy_to_guest_phys(struct domain *d,
+ paddr_t gpa,
+ void *buf,
+ unsigned int len);
+
+#endif /* __ASM_RISCV_GUEST_ACCESS_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 31/39] xen/riscv: add required things to asm/current.h

2023-11-24 Thread Oleksii Kurochko
Add minimal requied things to be able to build full Xen.

Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/current.h | 20 
 1 file changed, 20 insertions(+)

diff --git a/xen/arch/riscv/include/asm/current.h 
b/xen/arch/riscv/include/asm/current.h
index d84f15dc50..e105329bf3 100644
--- a/xen/arch/riscv/include/asm/current.h
+++ b/xen/arch/riscv/include/asm/current.h
@@ -3,6 +3,22 @@
 #ifndef __ASM_CURRENT_H
 #define __ASM_CURRENT_H
 
+#include 
+#include 
+
+#ifndef __ASSEMBLY__
+
+struct vcpu;
+
+/* Which VCPU is "current" on this PCPU. */
+DECLARE_PER_CPU(struct vcpu *, curr_vcpu);
+
+#define current(this_cpu(curr_vcpu))
+#define set_current(vcpu)  do { current = (vcpu); } while (0)
+#define get_cpu_current(cpu)  (per_cpu(curr_vcpu, cpu))
+
+#define guest_cpu_user_regs() (0)
+
 #define switch_stack_and_jump(stack, fn) do {   \
 asm volatile (  \
 "mv sp, %0\n"   \
@@ -10,4 +26,8 @@
 unreachable();  \
 } while ( false )
 
+#define get_per_cpu_offset() __per_cpu_offset[get_processor_id()]
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ASM_CURRENT_H */
-- 
2.42.0




[PATCH v2 24/39] xen/riscv: introduce asm/irq.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
- add ifdef CONFIG_HAS_DEVICE_TREE for things that shouldn't be
  in case !CONFIG_HAS_DEVICE_TREE
- use proper includes.
---
 xen/arch/riscv/include/asm/irq.h | 37 
 1 file changed, 37 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/irq.h

diff --git a/xen/arch/riscv/include/asm/irq.h b/xen/arch/riscv/include/asm/irq.h
new file mode 100644
index 00..ca49d3f9b4
--- /dev/null
+++ b/xen/arch/riscv/include/asm/irq.h
@@ -0,0 +1,37 @@
+#ifndef __ASM_RISCV_IRQ_H__
+#define __ASM_RISCV_IRQ_H__
+
+#include 
+#ifdef CONFIG_HAS_DEVICE_TREE
+#include 
+#endif
+
+/* TODO */
+#define nr_irqs 0U
+#define nr_static_irqs 0
+#define arch_hwdom_irqs(domid) 0U
+
+#define domain_pirq_to_irq(d, pirq) (pirq)
+
+#define arch_evtchn_bind_pirq(d, pirq) ((void)((d) + (pirq)))
+
+struct arch_pirq {
+};
+
+struct arch_irq_desc {
+unsigned int type;
+};
+
+static inline void arch_move_irqs(struct vcpu *v)
+{
+BUG();
+}
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+static inline int platform_get_irq(const struct dt_device_node *device, int 
index)
+{
+BUG();
+}
+#endif
+
+#endif /* __ASM_RISCV_IRQ_H__ */
-- 
2.42.0




[PATCH v2 34/39] xen: add RISCV support for pmu.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/include/public/pmu.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen/include/public/pmu.h b/xen/include/public/pmu.h
index 5a176b6ac3..af8b7babdd 100644
--- a/xen/include/public/pmu.h
+++ b/xen/include/public/pmu.h
@@ -13,6 +13,8 @@
 #include "arch-arm.h"
 #elif defined (__powerpc64__)
 #include "arch-ppc.h"
+#elif defined(__riscv)
+#include "arch-riscv.h"
 #else
 #error "Unsupported architecture"
 #endif
-- 
2.42.0




[PATCH v2 36/39] xen/riscv: add minimal stuff to asm/mm.h to build full Xen

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - define stub for arch_get_dma_bitsize(void)
---
 xen/arch/riscv/include/asm/mm.h | 270 +++-
 1 file changed, 268 insertions(+), 2 deletions(-)

diff --git a/xen/arch/riscv/include/asm/mm.h b/xen/arch/riscv/include/asm/mm.h
index 07c7a0abba..68460f6659 100644
--- a/xen/arch/riscv/include/asm/mm.h
+++ b/xen/arch/riscv/include/asm/mm.h
@@ -3,10 +3,271 @@
 #ifndef _ASM_RISCV_MM_H
 #define _ASM_RISCV_MM_H
 
+#include 
+#include 
+#include 
+
+#include 
 #include 
 
-#define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)
-#define paddr_to_pfn(pa)  ((unsigned long)((pa) >> PAGE_SHIFT))
+#define paddr_to_pdx(pa)mfn_to_pdx(maddr_to_mfn(pa))
+#define gfn_to_gaddr(gfn)   pfn_to_paddr(gfn_x(gfn))
+#define gaddr_to_gfn(ga)_gfn(paddr_to_pfn(ga))
+#define mfn_to_maddr(mfn)   pfn_to_paddr(mfn_x(mfn))
+#define maddr_to_mfn(ma)_mfn(paddr_to_pfn(ma))
+#define vmap_to_mfn(va) maddr_to_mfn(virt_to_maddr((vaddr_t)va))
+#define vmap_to_page(va)mfn_to_page(vmap_to_mfn(va))
+#define paddr_to_pdx(pa)mfn_to_pdx(maddr_to_mfn(pa))
+#define gfn_to_gaddr(gfn)   pfn_to_paddr(gfn_x(gfn))
+#define gaddr_to_gfn(ga)_gfn(paddr_to_pfn(ga))
+#define mfn_to_maddr(mfn)   pfn_to_paddr(mfn_x(mfn))
+#define maddr_to_mfn(ma)_mfn(paddr_to_pfn(ma))
+#define vmap_to_mfn(va) maddr_to_mfn(virt_to_maddr((vaddr_t)va))
+#define vmap_to_page(va)mfn_to_page(vmap_to_mfn(va))
+
+#define virt_to_maddr(va) ((paddr_t)((vaddr_t)(va) & PADDR_MASK))
+#define maddr_to_virt(pa) ((void *)((paddr_t)(pa) | XEN_VIRT_START))
+
+/* Convert between Xen-heap virtual addresses and machine frame numbers. */
+#define __virt_to_mfn(va) (virt_to_maddr(va) >> PAGE_SHIFT)
+#define __mfn_to_virt(mfn) (maddr_to_virt((paddr_t)(mfn) << PAGE_SHIFT))
+
+/* Convert between Xen-heap virtual addresses and page-info structures. */
+static inline struct page_info *virt_to_page(const void *v)
+{
+BUG();
+return NULL;
+}
+
+/*
+ * We define non-underscored wrappers for above conversion functions.
+ * These are overriden in various source files while underscored version
+ * remain intact.
+ */
+#define virt_to_mfn(va) __virt_to_mfn(va)
+#define mfn_to_virt(mfn)__mfn_to_virt(mfn)
+
+struct page_info
+{
+/* Each frame can be threaded onto a doubly-linked list. */
+struct page_list_entry list;
+
+/* Reference count and various PGC_xxx flags and fields. */
+unsigned long count_info;
+
+/* Context-dependent fields follow... */
+union {
+/* Page is in use: ((count_info & PGC_count_mask) != 0). */
+struct {
+/* Type reference count and various PGT_xxx flags and fields. */
+unsigned long type_info;
+} inuse;
+/* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
+union {
+struct {
+/*
+ * Index of the first *possibly* unscrubbed page in the buddy.
+ * One more bit than maximum possible order to accommodate
+ * INVALID_DIRTY_IDX.
+ */
+#define INVALID_DIRTY_IDX ((1UL << (MAX_ORDER + 1)) - 1)
+unsigned long first_dirty:MAX_ORDER + 1;
+
+/* Do TLBs need flushing for safety before next page use? */
+bool need_tlbflush:1;
+
+#define BUDDY_NOT_SCRUBBING0
+#define BUDDY_SCRUBBING1
+#define BUDDY_SCRUB_ABORT  2
+unsigned long scrub_state:2;
+};
+
+unsigned long val;
+} free;
+
+} u;
+
+union {
+/* Page is in use, but not as a shadow. */
+struct {
+/* Owner of this page (zero if page is anonymous). */
+struct domain *domain;
+} inuse;
+
+/* Page is on a free list. */
+struct {
+/* Order-size of the free chunk this page is the head of. */
+unsigned int order;
+} free;
+
+} v;
+
+union {
+/*
+ * Timestamp from 'TLB clock', used to avoid extra safety flushes.
+ * Only valid for: a) free pages, and b) pages with zero type count
+ */
+u32 tlbflush_timestamp;
+};
+u64 pad;
+};
+
+#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
+
+/* PDX of the first page in the frame table. */
+extern unsigned long frametable_base_pdx;
+
+/* Convert between machine frame numbers and page-info structures. */
+#define mfn_to_page(mfn)\
+(frame_table + (mfn_to_pdx(mfn) - frametable_base_pdx))
+#define page_to_mfn(pg) \
+pdx_to_mfn((unsigned long)((pg) - frame_table) + frametable_base_pdx)
+
+static inline void *page_to_virt(const struct page_info *pg)
+{
+return mfn_to_virt(mfn_x(page_to_mfn(pg)));
+}
+
+/*
+ * Common code requires get_page_type and put_page_type.
+ * We don't care about typecounts so we just do the minimum to m

[RFC XEN PATCH v2 0/3] Support device passthrough when dom0 is PVH on Xen

2023-11-24 Thread Jiqian Chen
Hi All,

This series of patches are the v2 of the implementation of passthrough when 
dom0 is PVH on Xen.
We sent the v1 to upstream before, but the v1 had so many problems and we got 
lots of suggestions.
I will introduce all issues that these patches try to fix and the differences 
between v1 and v2.

v2 on kernel side:
https://lore.kernel.org/lkml/20231124103123.3263471-1-jiqian.c...@amd.com/T/#t

Issues we encountered:
1. pci_stub failed to write bar for a passthrough device.
Problem: when we run “sudo xl pci-assignable-add ” to assign a device, 
pci_stub will
call “pcistub_init_device() -> pci_restore_state() -> 
pci_restore_config_space() ->
pci_restore_config_space_range() -> pci_restore_config_dword() -> 
pci_write_config_dword()”,
the pci config write will trigger an io interrupt to bar_write() in the xen, 
but the
bar->enabled was set before, the write is not allowed now, and then when Qemu 
config the
passthrough device in xen_pt_realize(), it gets invalid bar values.

Reason: the reason is that we don't tell vPCI that the device has been reset, 
so the current
cached state in pdev->vpci is all out of date and is different from the real 
device state.

Solution: to solve this problem, the first patch of kernel(xen/pci: Add 
xen_reset_device_state
function) and the fist patch of xen(xen/vpci: Clear all vpci status of device) 
add a new
hypercall to reset the state stored in vPCI when the state of real device has 
changed.
Thank Roger for the suggestion of this v2, and it is different from v1
(https://lore.kernel.org/xen-devel/20230312075455.450187-3-ray.hu...@amd.com/), 
v1 simply allow
domU to write pci bar, it does not comply with the design principles of vPCI.

2. failed to do PHYSDEVOP_map_pirq when dom0 is PVH
Problem: HVM domU will do PHYSDEVOP_map_pirq for a passthrough device by using 
gsi. See
xen_pt_realize->xc_physdev_map_pirq and pci_add_dm_done->xc_physdev_map_pirq. 
Then
xc_physdev_map_pirq will call into Xen, but in hvm_physdev_op(), 
PHYSDEVOP_map_pirq is not allowed.

Reason: In hvm_physdev_op(), the variable "currd" is PVH dom0 and PVH has no 
X86_EMU_USE_PIRQ flag,
it will fail at has_pirq check.

Solution: I think we may need to allow PHYSDEVOP_map_pirq when "currd" is dom0 
(at present dom0 is
PVH). The second patch of xen(x86/pvh: Open PHYSDEVOP_map_pirq for PVH dom0) 
allow PVH dom0 do
PHYSDEVOP_map_pirq. This v2 patch is better than v1, v1 simply remove the 
has_pirq check(xen
https://lore.kernel.org/xen-devel/20230312075455.450187-4-ray.hu...@amd.com/).

3. the gsi of a passthrough device doesn't be unmasked
 3.1 failed to check the permission of pirq
 3.2 the gsi of passthrough device was not registered in PVH dom0

Problem:
3.1 callback function pci_add_dm_done() will be called when qemu config a 
passthrough device for domU.
This function will call xc_domain_irq_permission()-> pirq_access_permitted() to 
check if the gsi has
corresponding mappings in dom0. But it didn’t, so failed. See
XEN_DOMCTL_irq_permission->pirq_access_permitted, "current" is PVH dom0 and it 
return irq is 0.
3.2 it's possible for a gsi (iow: vIO-APIC pin) to never get registered on PVH 
dom0, because the
devices of PVH are using MSI(-X) interrupts. However, the IO-APIC pin must be 
configured for it to be
able to be mapped into a domU.

Reason: After searching codes, I find "map_pirq" and "register_gsi" will be 
done in function
vioapic_write_redirent->vioapic_hwdom_map_gsi when the gsi(aka ioapic's pin) is 
unmasked in PVH dom0.
So the two problems can be concluded to that the gsi of a passthrough device 
doesn't be unmasked.

Solution: to solve these problems, the second patch of kernel(xen/pvh: Unmask 
irq for passthrough
device in PVH dom0) call the unmask_irq() when we assign a device to be 
passthrough. So that
passthrough devices can have the mapping of gsi on PVH dom0 and gsi can be 
registered. This v2 patch
is different from the v1(
kernel 
https://lore.kernel.org/xen-devel/20230312120157.452859-5-ray.hu...@amd.com/,
kernel 
https://lore.kernel.org/xen-devel/20230312120157.452859-5-ray.hu...@amd.com/ and
xen 
https://lore.kernel.org/xen-devel/20230312075455.450187-5-ray.hu...@amd.com/),
v1 performed "map_pirq" and "register_gsi" on all pci devices on PVH dom0, 
which is unnecessary and
may cause multiple registration.

4. failed to map pirq for gsi
Problem: qemu will call xc_physdev_map_pirq() to map a passthrough device’s gsi 
to pirq in function
xen_pt_realize(). But failed.

Reason: According to the implement of xc_physdev_map_pirq(), it needs gsi 
instead of irq, but qemu
pass irq to it and treat irq as gsi, it is got from file 
/sys/bus/pci/devices/:xx:xx.x/irq in
function xen_host_pci_device_get(). But actually the gsi number is not equal 
with irq. On PVH dom0,
when it allocates irq for a gsi in function acpi_register_gsi_ioapic(), 
allocation is dynamic, and
follow the principle of applying first, distributing first. And if you debug 
the kernel codes(see
function __irq_allo

[PATCH v2 37/39] xen/rirscv: add minimal amount of stubs to build full Xen

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - define udelay stub
 - remove 'select HAS_PDX' from RISC-V Kconfig because of
   
https://lore.kernel.org/xen-devel/20231006144405.1078260-1-andrew.coop...@citrix.com/
---
 xen/arch/riscv/Makefile   |   1 +
 xen/arch/riscv/early_printk.c | 168 --
 xen/arch/riscv/mm.c   |  52 -
 xen/arch/riscv/setup.c|   9 +-
 xen/arch/riscv/stubs.c| 426 ++
 xen/arch/riscv/traps.c|  25 ++
 6 files changed, 511 insertions(+), 170 deletions(-)
 create mode 100644 xen/arch/riscv/stubs.c

diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index b08048948f..50c09469a0 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -5,6 +5,7 @@ obj-y += mm.o
 obj-$(CONFIG_RISCV_64) += riscv64/
 obj-y += sbi.o
 obj-y += setup.o
+obj-y += stubs.o
 obj-y += traps.o
 
 $(TARGET): $(TARGET)-syms
diff --git a/xen/arch/riscv/early_printk.c b/xen/arch/riscv/early_printk.c
index 60742a042d..610c814f54 100644
--- a/xen/arch/riscv/early_printk.c
+++ b/xen/arch/riscv/early_printk.c
@@ -40,171 +40,3 @@ void early_printk(const char *str)
 str++;
 }
 }
-
-/*
- * The following #if 1 ... #endif should be removed after printk
- * and related stuff are ready.
- */
-#if 1
-
-#include 
-#include 
-
-/**
- * strlen - Find the length of a string
- * @s: The string to be sized
- */
-size_t (strlen)(const char * s)
-{
-const char *sc;
-
-for (sc = s; *sc != '\0'; ++sc)
-/* nothing */;
-return sc - s;
-}
-
-/**
- * memcpy - Copy one area of memory to another
- * @dest: Where to copy to
- * @src: Where to copy from
- * @count: The size of the area.
- *
- * You should not use this function to access IO space, use memcpy_toio()
- * or memcpy_fromio() instead.
- */
-void *(memcpy)(void *dest, const void *src, size_t count)
-{
-char *tmp = (char *) dest, *s = (char *) src;
-
-while (count--)
-*tmp++ = *s++;
-
-return dest;
-}
-
-int vsnprintf(char* str, size_t size, const char* format, va_list args)
-{
-size_t i = 0; /* Current position in the output string */
-size_t written = 0; /* Total number of characters written */
-char* dest = str;
-
-while ( format[i] != '\0' && written < size - 1 )
-{
-if ( format[i] == '%' )
-{
-i++;
-
-if ( format[i] == '\0' )
-break;
-
-if ( format[i] == '%' )
-{
-if ( written < size - 1 )
-{
-dest[written] = '%';
-written++;
-}
-i++;
-continue;
-}
-
-/*
- * Handle format specifiers.
- * For simplicity, only %s and %d are implemented here.
- */
-
-if ( format[i] == 's' )
-{
-char* arg = va_arg(args, char*);
-size_t arglen = strlen(arg);
-
-size_t remaining = size - written - 1;
-
-if ( arglen > remaining )
-arglen = remaining;
-
-memcpy(dest + written, arg, arglen);
-
-written += arglen;
-i++;
-}
-else if ( format[i] == 'd' )
-{
-int arg = va_arg(args, int);
-
-/* Convert the integer to string representation */
-char numstr[32]; /* Assumes a maximum of 32 digits */
-int numlen = 0;
-int num = arg;
-size_t remaining;
-
-if ( arg < 0 )
-{
-if ( written < size - 1 )
-{
-dest[written] = '-';
-written++;
-}
-
-num = -arg;
-}
-
-do
-{
-numstr[numlen] = '0' + num % 10;
-num = num / 10;
-numlen++;
-} while ( num > 0 );
-
-/* Reverse the string */
-for (int j = 0; j < numlen / 2; j++)
-{
-char tmp = numstr[j];
-numstr[j] = numstr[numlen - 1 - j];
-numstr[numlen - 1 - j] = tmp;
-}
-
-remaining = size - written - 1;
-
-if ( numlen > remaining )
-numlen = remaining;
-
-memcpy(dest + written, numstr, numlen);
-
-written += numlen;
-i++;
-}
-}
-else
-{
-if ( written < size - 1 )
-{
-dest[written] = format[i];
-written++;
-}
-i++;
-}
-}
-
-if ( size > 0 )
-dest[written] = '\0';
-
-return written;
-}
-
-void printk(const char *format, ...)
-{
-  

[RFC XEN PATCH v2 1/3] xen/vpci: Clear all vpci status of device

2023-11-24 Thread Jiqian Chen
When a device has been reset on dom0 side, the vpci on Xen
side won't get notification, so the cached state in vpci is
all out of date compare with the real device state.
To solve that problem, this patch add new hypercall to clear
all vpci device state. And when reset device happens on dom0
side, dom0 can call this hypercall to notify vpci.

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 xen/arch/x86/hvm/hypercall.c  |  1 +
 xen/drivers/passthrough/pci.c | 21 +
 xen/drivers/pci/physdev.c | 14 ++
 xen/drivers/vpci/vpci.c   |  9 +
 xen/include/public/physdev.h  |  2 ++
 xen/include/xen/pci.h |  1 +
 xen/include/xen/vpci.h|  6 ++
 7 files changed, 54 insertions(+)

diff --git a/xen/arch/x86/hvm/hypercall.c b/xen/arch/x86/hvm/hypercall.c
index eeb73e1aa5..6ad5b4d5f1 100644
--- a/xen/arch/x86/hvm/hypercall.c
+++ b/xen/arch/x86/hvm/hypercall.c
@@ -84,6 +84,7 @@ long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 case PHYSDEVOP_pci_mmcfg_reserved:
 case PHYSDEVOP_pci_device_add:
 case PHYSDEVOP_pci_device_remove:
+case PHYSDEVOP_pci_device_state_reset:
 case PHYSDEVOP_dbgp_op:
 if ( !is_hardware_domain(currd) )
 return -ENOSYS;
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 04d00c7c37..f871715585 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -824,6 +824,27 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
 return ret;
 }
 
+int pci_reset_device_state(u16 seg, u8 bus, u8 devfn)
+{
+struct pci_dev *pdev;
+int ret = -ENODEV;
+
+pcidevs_lock();
+
+pdev = pci_get_pdev(NULL, PCI_SBDF(seg, bus, devfn));
+if ( !pdev )
+goto error;
+
+ret = vpci_reset_device_state(pdev);
+if (ret)
+printk(XENLOG_ERR "PCI reset device %pp state failed\n", &pdev->sbdf);
+
+error:
+pcidevs_unlock();
+
+return ret;
+}
+
 /* Caller should hold the pcidevs_lock */
 static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus,
uint8_t devfn)
diff --git a/xen/drivers/pci/physdev.c b/xen/drivers/pci/physdev.c
index 42db3e6d13..cfdb545654 100644
--- a/xen/drivers/pci/physdev.c
+++ b/xen/drivers/pci/physdev.c
@@ -67,6 +67,20 @@ ret_t pci_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) 
arg)
 break;
 }
 
+case PHYSDEVOP_pci_device_state_reset: {
+struct physdev_pci_device dev;
+
+if ( !is_pci_passthrough_enabled() )
+return -EOPNOTSUPP;
+
+ret = -EFAULT;
+if ( copy_from_guest(&dev, arg, 1) != 0 )
+break;
+
+ret = pci_reset_device_state(dev.seg, dev.bus, dev.devfn);
+break;
+}
+
 default:
 ret = -ENOSYS;
 break;
diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c
index 3bec9a4153..e9c3eb1cd6 100644
--- a/xen/drivers/vpci/vpci.c
+++ b/xen/drivers/vpci/vpci.c
@@ -103,6 +103,15 @@ int vpci_add_handlers(struct pci_dev *pdev)
 
 return rc;
 }
+
+int vpci_reset_device_state(struct pci_dev *pdev)
+{
+ASSERT(pcidevs_locked());
+
+vpci_remove_device(pdev);
+return vpci_add_handlers(pdev);
+}
+
 #endif /* __XEN__ */
 
 static int vpci_register_cmp(const struct vpci_register *r1,
diff --git a/xen/include/public/physdev.h b/xen/include/public/physdev.h
index f0c0d4727c..4156948903 100644
--- a/xen/include/public/physdev.h
+++ b/xen/include/public/physdev.h
@@ -305,6 +305,8 @@ struct physdev_pci_device {
 typedef struct physdev_pci_device physdev_pci_device_t;
 DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_t);
 
+#define PHYSDEVOP_pci_device_state_reset  32
+
 #define PHYSDEVOP_DBGP_RESET_PREPARE1
 #define PHYSDEVOP_DBGP_RESET_DONE   2
 
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index 50d7dfb2a2..a0c28c5e6c 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -186,6 +186,7 @@ const unsigned long *pci_get_ro_map(u16 seg);
 int pci_add_device(u16 seg, u8 bus, u8 devfn,
const struct pci_dev_info *info, nodeid_t node);
 int pci_remove_device(u16 seg, u8 bus, u8 devfn);
+int pci_reset_device_state(u16 seg, u8 bus, u8 devfn);
 int pci_ro_device(int seg, int bus, int devfn);
 int pci_hide_device(unsigned int seg, unsigned int bus, unsigned int devfn);
 struct pci_dev *pci_get_pdev(const struct domain *d, pci_sbdf_t sbdf);
diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h
index d743d96a10..e2d6cd5fa3 100644
--- a/xen/include/xen/vpci.h
+++ b/xen/include/xen/vpci.h
@@ -30,6 +30,7 @@ int __must_check vpci_add_handlers(struct pci_dev *pdev);
 
 /* Remove all handlers and free vpci related structures. */
 void vpci_remove_device(struct pci_dev *pdev);
+int vpci_reset_device_state(struct pci_dev *pdev);
 
 /* Add/remove a register handler. */
 int __must_check vpci_add_register(struct vpci *vpci,
@@ -242,6 +243,11 @@ static inline int vpci_add_handlers(struct pci_dev *pdev)
 
 

[RFC XEN PATCH v2 2/3] x86/pvh: Open PHYSDEVOP_map_pirq for PVH dom0

2023-11-24 Thread Jiqian Chen
If we run Xen with PVH dom0 and hvm domU, hvm will map a pirq for
a passthrough device by using gsi, see xen_pt_realize->xc_physdev_map_pirq
and pci_add_dm_done->xc_physdev_map_pirq. Then xc_physdev_map_pirq will
call into Xen, but in hvm_physdev_op, PHYSDEVOP_map_pirq is not allowed
because currd is PVH dom0 and PVH has no X86_EMU_USE_PIRQ flag, it will
fail at has_pirq check.

So, I think we may need to allow PHYSDEVOP_map_pirq when currd is dom0 (at
present dom0 is PVH).

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 xen/arch/x86/hvm/hypercall.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen/arch/x86/hvm/hypercall.c b/xen/arch/x86/hvm/hypercall.c
index 6ad5b4d5f1..f9c4a2243a 100644
--- a/xen/arch/x86/hvm/hypercall.c
+++ b/xen/arch/x86/hvm/hypercall.c
@@ -74,6 +74,8 @@ long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
 case PHYSDEVOP_map_pirq:
 case PHYSDEVOP_unmap_pirq:
+if (is_hardware_domain(currd))
+break;
 case PHYSDEVOP_eoi:
 case PHYSDEVOP_irq_status_query:
 case PHYSDEVOP_get_free_pirq:
-- 
2.34.1




[RFC XEN PATCH v2 3/3] tools: Add new function to get gsi from irq

2023-11-24 Thread Jiqian Chen
In PVH dom0, it uses the linux local interrupt mechanism,
when it allocs irq for a gsi, it is dynamic, and follow
the principle of applying first, distributing first. And
if you debug the kernel codes, you will find the irq
number is alloced from small to large, but the applying
gsi number is not, may gsi 38 comes before gsi 28, that
causes the irq number is not equal with the gsi number.
And when we passthrough a device, QEMU will use its gsi
number to do mapping actions, see xen_pt_realize->
xc_physdev_map_pirq, but the gsi number is got from file
/sys/bus/pci/devices/:xx:xx.x/irq in current code,
so it will fail when mapping.
And in current codes, there is no method to translate
irq to gsi for userspace.

For above purpose, this patch adds new function to get
that translation. And then we can use the correct gsi
number to do map_pirq.

And call this function before xc_physdev_map_pirq

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 tools/include/xen-sys/Linux/privcmd.h |  7 +++
 tools/include/xencall.h   |  2 ++
 tools/include/xenctrl.h   |  2 ++
 tools/libs/call/core.c|  5 +
 tools/libs/call/libxencall.map|  2 ++
 tools/libs/call/linux.c   | 14 ++
 tools/libs/call/private.h |  9 +
 tools/libs/ctrl/xc_physdev.c  |  4 
 tools/libs/light/libxl_pci.c  |  1 +
 9 files changed, 46 insertions(+)

diff --git a/tools/include/xen-sys/Linux/privcmd.h 
b/tools/include/xen-sys/Linux/privcmd.h
index bc60e8fd55..ba4b8c3054 100644
--- a/tools/include/xen-sys/Linux/privcmd.h
+++ b/tools/include/xen-sys/Linux/privcmd.h
@@ -95,6 +95,11 @@ typedef struct privcmd_mmap_resource {
__u64 addr;
 } privcmd_mmap_resource_t;
 
+typedef struct privcmd_gsi_from_irq {
+   __u32 irq;
+   __u32 gsi;
+} privcmd_gsi_from_irq_t;
+
 /*
  * @cmd: IOCTL_PRIVCMD_HYPERCALL
  * @arg: &privcmd_hypercall_t
@@ -114,6 +119,8 @@ typedef struct privcmd_mmap_resource {
_IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
 #define IOCTL_PRIVCMD_MMAP_RESOURCE\
_IOC(_IOC_NONE, 'P', 7, sizeof(privcmd_mmap_resource_t))
+#define IOCTL_PRIVCMD_GSI_FROM_IRQ \
+   _IOC(_IOC_NONE, 'P', 10, sizeof(privcmd_gsi_from_irq_t))
 #define IOCTL_PRIVCMD_UNIMPLEMENTED\
_IOC(_IOC_NONE, 'P', 0xFF, 0)
 
diff --git a/tools/include/xencall.h b/tools/include/xencall.h
index fc95ed0fe5..962cb45e1f 100644
--- a/tools/include/xencall.h
+++ b/tools/include/xencall.h
@@ -113,6 +113,8 @@ int xencall5(xencall_handle *xcall, unsigned int op,
  uint64_t arg1, uint64_t arg2, uint64_t arg3,
  uint64_t arg4, uint64_t arg5);
 
+int xen_oscall_gsi_from_irq(xencall_handle *xcall, int irq);
+
 /* Variant(s) of the above, as needed, returning "long" instead of "int". */
 long xencall2L(xencall_handle *xcall, unsigned int op,
uint64_t arg1, uint64_t arg2);
diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index 2ef8b4e054..2b9d55d2c6 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -1641,6 +1641,8 @@ int xc_physdev_unmap_pirq(xc_interface *xch,
   uint32_t domid,
   int pirq);
 
+int xc_physdev_gsi_from_irq(xc_interface *xch, int irq);
+
 /*
  *  LOGGING AND ERROR REPORTING
  */
diff --git a/tools/libs/call/core.c b/tools/libs/call/core.c
index 02c4f8e1ae..6f79f3babd 100644
--- a/tools/libs/call/core.c
+++ b/tools/libs/call/core.c
@@ -173,6 +173,11 @@ int xencall5(xencall_handle *xcall, unsigned int op,
 return osdep_hypercall(xcall, &call);
 }
 
+int xen_oscall_gsi_from_irq(xencall_handle *xcall, int irq)
+{
+return osdep_oscall(xcall, irq);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/call/libxencall.map b/tools/libs/call/libxencall.map
index d18a3174e9..6cde8eda05 100644
--- a/tools/libs/call/libxencall.map
+++ b/tools/libs/call/libxencall.map
@@ -10,6 +10,8 @@ VERS_1.0 {
xencall4;
xencall5;
 
+   xen_oscall_gsi_from_irq;
+
xencall_alloc_buffer;
xencall_free_buffer;
xencall_alloc_buffer_pages;
diff --git a/tools/libs/call/linux.c b/tools/libs/call/linux.c
index 6d588e6bea..5267bceabf 100644
--- a/tools/libs/call/linux.c
+++ b/tools/libs/call/linux.c
@@ -85,6 +85,20 @@ long osdep_hypercall(xencall_handle *xcall, 
privcmd_hypercall_t *hypercall)
 return ioctl(xcall->fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
 }
 
+long osdep_oscall(xencall_handle *xcall, int irq)
+{
+privcmd_gsi_from_irq_t gsi_irq = {
+.irq = irq,
+.gsi = -1,
+};
+
+if (ioctl(xcall->fd, IOCTL_PRIVCMD_GSI_FROM_IRQ, &gsi_irq)) {
+return gsi_irq.irq;
+}
+
+return gsi_irq.gsi;
+}
+
 static void *alloc_pages_bufdev(xencall_handle *xcall, size_t npages)
 {
 void *p;
diff --git a/tools/libs/call/pri

[PATCH v2 20/39] xen/riscv: define bug frame tables in xen.lds.S

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/xen.lds.S | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/xen/arch/riscv/xen.lds.S b/xen/arch/riscv/xen.lds.S
index 3fa7db3bf9..a10e0ad87c 100644
--- a/xen/arch/riscv/xen.lds.S
+++ b/xen/arch/riscv/xen.lds.S
@@ -45,6 +45,16 @@ SECTIONS
 . = ALIGN(PAGE_SIZE);
 .rodata : {
 _srodata = .;  /* Read-only data */
+/* Bug frames table */
+__start_bug_frames = .;
+*(.bug_frames.0)
+__stop_bug_frames_0 = .;
+*(.bug_frames.1)
+__stop_bug_frames_1 = .;
+*(.bug_frames.2)
+__stop_bug_frames_2 = .;
+*(.bug_frames.3)
+__stop_bug_frames_3 = .;
 *(.rodata)
 *(.rodata.*)
 *(.data.rel.ro)
-- 
2.42.0




[PATCH v2 26/39] xen/riscv: introduce asm/regs.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - change xen/lib.h to xen/bug.h
 - remove unnecessary empty line
---
 xen/arch/riscv/include/asm/regs.h | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/regs.h

diff --git a/xen/arch/riscv/include/asm/regs.h 
b/xen/arch/riscv/include/asm/regs.h
new file mode 100644
index 00..8556837c65
--- /dev/null
+++ b/xen/arch/riscv/include/asm/regs.h
@@ -0,0 +1,26 @@
+#ifndef __ARM_RISCV_REGS_H__
+#define __ARM_RISCV_REGS_H__
+
+#ifndef __ASSEMBLY__
+
+#include 
+#include 
+
+#define hyp_mode(r) (0)
+
+static inline bool guest_mode(const struct cpu_user_regs *r)
+{
+BUG();
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARM_RISCV_REGS_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.42.0




[PATCH v2 33/39] xen/riscv: add minimal stuff to asm/processor.h to build full Xen

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/processor.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/xen/arch/riscv/include/asm/processor.h 
b/xen/arch/riscv/include/asm/processor.h
index 6db681d805..b6218a00a7 100644
--- a/xen/arch/riscv/include/asm/processor.h
+++ b/xen/arch/riscv/include/asm/processor.h
@@ -12,6 +12,9 @@
 
 #ifndef __ASSEMBLY__
 
+/* TODO: need to be implemeted */
+#define get_processor_id() 0
+
 /* On stack VCPU state */
 struct cpu_user_regs
 {
@@ -53,6 +56,18 @@ struct cpu_user_regs
 unsigned long pregs;
 };
 
+/* TODO: need to implement */
+#define cpu_to_core(_cpu)   (0)
+#define cpu_to_socket(_cpu) (0)
+
+static inline void cpu_relax(void)
+{
+   int dummy;
+   /* In lieu of a halt instruction, induce a long-latency stall. */
+   __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
+   barrier();
+}
+
 static inline void wfi(void)
 {
 __asm__ __volatile__ ("wfi");
-- 
2.42.0




[PATCH v2 29/39] xen/riscv: add definition of __read_mostly

2023-11-24 Thread Oleksii Kurochko
The definition of __read_mostly should be removed in:
https://lore.kernel.org/xen-devel/f25eb5c9-7c14-6e23-8535-2c66772b3...@suse.com/

The patch introduces it in arch-specific header to not
block enabling of full Xen build for RISC-V.

Signed-off-by: Oleksii Kurochko 
---
 - update the commit message
---
 xen/arch/riscv/include/asm/cache.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen/arch/riscv/include/asm/cache.h 
b/xen/arch/riscv/include/asm/cache.h
index 69573eb051..94bd94db53 100644
--- a/xen/arch/riscv/include/asm/cache.h
+++ b/xen/arch/riscv/include/asm/cache.h
@@ -3,4 +3,6 @@
 #ifndef _ASM_RISCV_CACHE_H
 #define _ASM_RISCV_CACHE_H
 
+#define __read_mostly __section(".data.read_mostly")
+
 #endif /* _ASM_RISCV_CACHE_H */
-- 
2.42.0




[PATCH v2 32/39] xen/riscv: add minimal stuff to asm/page.h to build full Xen

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/page.h | 21 +
 1 file changed, 21 insertions(+)

diff --git a/xen/arch/riscv/include/asm/page.h 
b/xen/arch/riscv/include/asm/page.h
index 95074e29b3..abbae75aaf 100644
--- a/xen/arch/riscv/include/asm/page.h
+++ b/xen/arch/riscv/include/asm/page.h
@@ -6,6 +6,7 @@
 #ifndef __ASSEMBLY__
 
 #include 
+#include 
 #include 
 
 #include 
@@ -32,6 +33,9 @@
 #define PTE_LEAF_DEFAULT(PTE_VALID | PTE_READABLE | PTE_WRITABLE)
 #define PTE_TABLE   (PTE_VALID)
 
+/* TODO */
+#define PAGE_HYPERVISOR 0
+
 /* Calculate the offsets into the pagetables for a given VA */
 #define pt_linear_offset(lvl, va)   ((va) >> XEN_PT_LEVEL_SHIFT(lvl))
 
@@ -46,6 +50,9 @@ typedef struct {
 #endif
 } pte_t;
 
+#define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)
+#define paddr_to_pfn(pa)  ((unsigned long)((pa) >> PAGE_SHIFT))
+
 static inline pte_t paddr_to_pte(paddr_t paddr,
  unsigned int permissions)
 {
@@ -62,6 +69,20 @@ static inline bool pte_is_valid(pte_t p)
 return p.pte & PTE_VALID;
 }
 
+static inline void invalidate_icache(void)
+{
+BUG();
+}
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(dp, sp) memcpy(dp, sp, PAGE_SIZE)
+
+/* TODO: Flush the dcache for an entire page. */
+static inline void flush_page_to_ram(unsigned long mfn, bool sync_icache)
+{
+BUG();
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_RISCV_PAGE_H */
-- 
2.42.0




Re: [PATCH v6 4/5] xen/arm: Move static memory build code in separate modules

2023-11-24 Thread Michal Orzel
Hi Luca,

+ CC others

On 24/11/2023 10:48, Luca Fancellu wrote:
> 
> 
> Move static memory and static shared memory code in separate modules
> so that they are included only when the corresponding feature is
> enabled, doing that we modularise the features and we remove some
> ifdefs from the code to improve readability.
> 
> Move process_shm_node function from bootfdt module and make it
> externally visible.
> 
> A static inline helper called process_shm_chosen is introduced, it
> will call the process_shm function for the '/chosen' node, and will
> be used by the function construct_dom0 instead of using directly
> process_shm, allowing some #ifdef to be removed.
> 
> No functional changes are intended.
> 
> Signed-off-by: Luca Fancellu 
Reviewed-by: Michal Orzel 

~Michal



[PATCH v2 25/39] xen/riscv: introduce asm/p2m.h

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/p2m.h | 105 +++
 1 file changed, 105 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/p2m.h

diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/p2m.h
new file mode 100644
index 00..993aec6d2c
--- /dev/null
+++ b/xen/arch/riscv/include/asm/p2m.h
@@ -0,0 +1,105 @@
+#ifndef __ASM_RISCV_P2M_H__
+#define __ASM_RISCV_P2M_H__
+
+#include 
+
+#define paddr_bits PADDR_BITS
+
+/*
+ * List of possible type for each page in the p2m entry.
+ * The number of available bit per page in the pte for this purpose is 4 bits.
+ * So it's possible to only have 16 fields. If we run out of value in the
+ * future, it's possible to use higher value for pseudo-type and don't store
+ * them in the p2m entry.
+ */
+typedef enum {
+p2m_invalid = 0,/* Nothing mapped here */
+p2m_ram_rw, /* Normal read/write guest RAM */
+p2m_ram_ro, /* Read-only; writes are silently dropped */
+p2m_mmio_direct_dev,/* Read/write mapping of genuine Device MMIO area */
+p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area 
non-cacheable */
+p2m_mmio_direct_c,  /* Read/write mapping of genuine MMIO area cacheable */
+p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */
+p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */
+p2m_grant_map_rw,   /* Read/write grant mapping */
+p2m_grant_map_ro,   /* Read-only grant mapping */
+/* The types below are only used to decide the page attribute in the P2M */
+p2m_iommu_map_rw,   /* Read/write iommu mapping */
+p2m_iommu_map_ro,   /* Read-only iommu mapping */
+p2m_max_real_type,  /* Types after this won't be store in the p2m */
+} p2m_type_t;
+
+#include 
+
+static inline int get_page_and_type(struct page_info *page,
+struct domain *domain,
+unsigned long type)
+{
+BUG();
+return 1;
+}
+
+/* Look up a GFN and take a reference count on the backing page. */
+typedef unsigned int p2m_query_t;
+#define P2M_ALLOC(1u<<0)   /* Populate PoD and paged-out entries */
+#define P2M_UNSHARE  (1u<<1)   /* Break CoW sharing */
+
+static inline struct page_info *get_page_from_gfn(
+struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q)
+{
+BUG();
+return NULL;
+}
+
+static inline void memory_type_changed(struct domain *d)
+{
+BUG();
+}
+
+
+static inline int guest_physmap_mark_populate_on_demand(struct domain *d, 
unsigned long gfn,
+unsigned int order)
+{
+BUG();
+return 1;
+}
+
+static inline int guest_physmap_add_entry(struct domain *d,
+gfn_t gfn,
+mfn_t mfn,
+unsigned long page_order,
+p2m_type_t t)
+{
+BUG();
+return 1;
+}
+
+/* Untyped version for RAM only, for compatibility */
+static inline int __must_check
+guest_physmap_add_page(struct domain *d, gfn_t gfn, mfn_t mfn,
+   unsigned int page_order)
+{
+return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
+}
+
+static inline mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn)
+{
+BUG();
+return _mfn(0);
+}
+
+static inline bool arch_acquire_resource_check(struct domain *d)
+{
+/*
+ * The reference counting of foreign entries in set_foreign_p2m_entry()
+ * is supported on RISCV.
+ */
+return true;
+}
+
+static inline void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
+{
+/* Not supported on RISCV. */
+}
+
+#endif /* __ASM_RISCV_P2M_H__ */
\ No newline at end of file
-- 
2.42.0




[PATCH v2 35/39] xen: add necessary headers to common to build full Xen for RISC-V

2023-11-24 Thread Oleksii Kurochko
Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/include/xen/domain.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 54d88bf5e3..a4e11342e3 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -4,6 +4,7 @@
 
 #include 
 
+#include 
 #include 
 
 struct guest_area {
-- 
2.42.0




[PATCH v2 39/39] xen: fix compilation issue of serial.c

2023-11-24 Thread Oleksii Kurochko
The following issue occurs on RISC-V platforms:
drivers/char/serial.c: In function 'serial_tx_interrupt':
drivers/char/serial.c:88:9: error: implicit declaration of function 'cpu_relax' 
[-Werror=implicit-function-declaration]
   88 | cpu_relax();

cpu_relax() is defined in  so it was added
an inclusion of the header to serial.c.

Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - New commit introduced in V2
---
 xen/drivers/char/serial.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
index 00efe69574..35df58fe33 100644
--- a/xen/drivers/char/serial.c
+++ b/xen/drivers/char/serial.c
@@ -13,6 +13,8 @@
 #include 
 #include 
 
+#include 
+
 /* Never drop characters, even if the async transmit buffer fills. */
 /* #define SERIAL_NEVER_DROP_CHARS 1 */
 
-- 
2.42.0




[RFC QEMU PATCH v2 0/1] Support device passthrough when dom0 is PVH on Xen

2023-11-24 Thread Jiqian Chen
Hi All,

This patch is the v2 of the implementation of passthrough when dom0 is PVH on 
Xen.

Issues we encountered:
1. failed to map pirq for gsi
Problem: qemu will call xc_physdev_map_pirq() to map a passthrough device’s gsi 
to pirq in function
xen_pt_realize(). But failed.

Reason: According to the implement of xc_physdev_map_pirq(), it needs gsi 
instead of irq, but qemu
pass irq to it and treat irq as gsi, it is got from file 
/sys/bus/pci/devices/:xx:xx.x/irq in
function xen_host_pci_device_get(). But actually the gsi number is not equal 
with irq. On PVH dom0,
when it allocates irq for a gsi in function acpi_register_gsi_ioapic(), 
allocation is dynamic, and
follow the principle of applying first, distributing first. And if you debug 
the kernel codes(see
function __irq_alloc_descs), you will find the irq number is allocated from 
small to large by order,
but the applying gsi number is not, gsi 38 may come before gsi 28, that causes 
gsi 38 get a smaller
irq number than gsi 28, and then gsi != irq.

Solution: we can record the relation between gsi and irq, then when 
userspace(qemu) want to use gsi,
we can do a translation. The third patch of kernel(xen/privcmd: Add new syscall 
to get gsi from irq)
records all the relations in acpi_register_gsi_xen_pvh() when dom0 initialize 
pci devices, and provide
a syscall for userspace to get the gsi from irq. The third patch of xen(tools: 
Add new function to get
gsi from irq) add a new function xc_physdev_gsi_from_irq() to call the new 
syscall added on kernel side.
And then userspace can use that function to get gsi. Then xc_physdev_map_pirq() 
will success.

This v2 on qemu side is the same as the v1 (
qemu 
https://lore.kernel.org/xen-devel/20230312092244.451465-19-ray.hu...@amd.com/), 
just call
xc_physdev_gsi_from_irq() to get gsi from irq.

v2 on kernel side:
https://lore.kernel.org/lkml/20231124103123.3263471-1-jiqian.c...@amd.com/T/#t

v2 on Xen side:
https://lore.kernel.org/xen-devel/20231124104136.3263722-1-jiqian.c...@amd.com/T/#t

Jiqian Chen (1):
  xen/pci: get gsi from irq for passthrough devices

 hw/xen/xen-host-pci-device.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

-- 
2.34.1




[RFC QEMU PATCH v2 1/1] xen/pci: get gsi from irq for passthrough devices

2023-11-24 Thread Jiqian Chen
In PVH dom0, it uses the linux local interrupt mechanism,
when it allocs irq for a gsi, it is dynamic, and follow
the principle of applying first, distributing first. And
if you debug the kernel codes, you will find the irq
number is alloced from small to large, but the applying
gsi number is not, may gsi 38 comes before gsi 28, that
causes the irq number is not equal with the gsi number.
And when we passthrough a device, QEMU will use its gsi
number to do mapping actions, see xen_pt_realize->
xc_physdev_map_pirq, but the gsi number is got from file
/sys/bus/pci/devices/:xx:xx.x/irq in current code,
that is irq not gsi, so it will fail when mapping.

For above reason, on Xen side, we add a new function to
translate irq to gsi. And at here, we call that function
to get the correct gsi number.

Signed-off-by: Jiqian Chen 
Signed-off-by: Huang Rui 
---
 hw/xen/xen-host-pci-device.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c
index 8c6e9a1716..00218f9080 100644
--- a/hw/xen/xen-host-pci-device.c
+++ b/hw/xen/xen-host-pci-device.c
@@ -10,6 +10,7 @@
 #include "qapi/error.h"
 #include "qemu/cutils.h"
 #include "xen-host-pci-device.h"
+#include "hw/xen/xen_native.h"
 
 #define XEN_HOST_PCI_MAX_EXT_CAP \
 ((PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE) / (PCI_CAP_SIZEOF + 4))
@@ -368,7 +369,7 @@ void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t 
domain,
 if (*errp) {
 goto error;
 }
-d->irq = v;
+d->irq = xc_physdev_gsi_from_irq(xen_xc, v);
 
 xen_host_pci_get_hex_value(d, "class", &v, errp);
 if (*errp) {
-- 
2.34.1




[PATCH v2 30/39] xen/riscv: define an address of frame table

2023-11-24 Thread Oleksii Kurochko
Also the patchs adds some helpful macros.

Signed-off-by: Oleksii Kurochko 
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/config.h | 21 +
 1 file changed, 21 insertions(+)

diff --git a/xen/arch/riscv/include/asm/config.h 
b/xen/arch/riscv/include/asm/config.h
index f0544c6a20..8d2103b3ce 100644
--- a/xen/arch/riscv/include/asm/config.h
+++ b/xen/arch/riscv/include/asm/config.h
@@ -77,12 +77,31 @@
   name:
 #endif
 
+#define VPN_BITS(9)
+#define OFFSET_BITS (12)
+
 #ifdef CONFIG_RISCV_64
+
+#define SLOTN_ENTRY_BITS(HYP_PT_ROOT_LEVEL * VPN_BITS + OFFSET_BITS)
+#define SLOTN(slot) (_AT(vaddr_t,slot) << SLOTN_ENTRY_BITS)
+#define SLOTN_ENTRY_SIZESLOTN(1)
+
 #define XEN_VIRT_START 0xC000 /* (_AC(-1, UL) + 1 - GB(1)) */
+
+#define FRAMETABLE_VIRT_START   SLOTN(196)
+#define FRAMETABLE_SIZE GB(3)
+#define FRAMETABLE_NR   (FRAMETABLE_SIZE / sizeof(*frame_table))
+#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + FRAMETABLE_SIZE - 1)
+
+#define VMAP_VIRT_START SLOTN(194)
+#define VMAP_VIRT_SIZE  GB(1)
+
 #else
 #error "RV32 isn't supported"
 #endif
 
+#define HYPERVISOR_VIRT_START XEN_VIRT_START
+
 #define SMP_CACHE_BYTES (1 << 6)
 
 #define STACK_SIZE PAGE_SIZE
@@ -95,6 +114,8 @@
 #define RV_STAGE1_MODE SATP_MODE_SV32
 #endif
 
+#define HYP_PT_ROOT_LEVEL (CONFIG_PAGING_LEVELS - 1)
+
 #define IDENT_AREA_SIZE 64
 
 #endif /* __RISCV_CONFIG_H__ */
-- 
2.42.0




Re: [PATCH v3 01/14] xen/asm-generic: introduce stub header paging.h

2023-11-24 Thread Julien Grall

Hi Oleksii,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

The patch introduces generic paging.h header for Arm, PPC and
RISC-V.

All mentioned above architectures use hardware virt extensions
and hardware pagetable extensions thereby it makes sense to set
paging_mode_translate and paging_mode_external by default.

Also in this patch Arm and PPC architectures are switched to
generic paging.h header.

Signed-off-by: Oleksii Kurochko 
Reviewed-by: Jan Beulich 


Acked-by: Julien Grall 

Cheers,

--
Julien Grall



Governance PR

2023-11-24 Thread Kelly Choi
Hi all,

Please see an updated Governance PR on GitLab here:
https://gitlab.com/xen-project/governance/governance/-/merge_requests/1

Comments:

Revise code of conduct for enhanced clarity, inclusivity, and accountability

In response to valuable feedback from community members and in alignment
with our ongoing commitment to creating a safe and welcoming space for
collaboration, this commit refines the code of conduct. The changes focus
on:

   - *Clarity:* Rewording sections to eliminate ambiguity and ensure that
   expectations are clearly communicated.
   - *Inclusivity:* Adding language to emphasize our dedication to
   diversity and inclusion, and providing examples to illustrate the types of
   behavior we encourage.

These updates aim to foster a more positive and collaborative atmosphere
within our community. Please review the changes and don't hesitate to
provide further input or suggestions.

Note that the patches should be read as a whole; I'm still learning git and
using the gitlab UI, which doesn't have a way to do history editing.
Many thanks,
Kelly Choi

Open Source Community Manager
XenServer, Cloud Software Group


Re: [PATCH v6 3/5] arm/dom0less: put dom0less feature code in a separate module

2023-11-24 Thread Michal Orzel
Hi Luca,

+ CC others

On 24/11/2023 10:48, Luca Fancellu wrote:
> 
> 
> Currently the dom0less feature code is mostly inside domain_build.c
> and setup.c, it is a feature that may not be useful to everyone so
> put the code in a different compilation module in order to make it
> easier to disable the feature in the future.
> 
> Move gic_interrupt_t in domain_build.h to use it with the function
> declaration, move its comment above the declaration.
> 
> The following functions are now visible externally from domain_build
> because they are used also from the dom0less-build module:
>  - get_allocation_size
>  - set_interrupt
>  - domain_fdt_begin_node
>  - make_memory_node
>  - make_resv_memory_node
>  - make_hypervisor_node
>  - make_psci_node
>  - make_cpus_node
>  - make_timer_node
>  - handle_device_interrupts
>  - construct_domain
>  - process_shm
>  - allocate_bank_memory
> 
> The functions allocate_static_memory and assign_static_memory_11
> are now externally visible, so put their declarations into
> domain_build.h and move the #else and stub definition in the header
> as well.
> 
> Move is_dom0less_mode from setup.c to dom0less-build.c and make it
> externally visible.
> 
> The function allocate_bank_memory is used only by dom0less code
> at the moment, but it's been decided to leave it in domain_build.c
> in case that in the future the dom0 code can use it.
> 
> Where spotted, fix code style issues.
> 
> No functional change is intended.
> 
> Signed-off-by: Luca Fancellu 
> Reviewed-by: Michal Orzel 
> ---
> Changes from v5:
>  - remove unneeded include (Michal)
Including asm/kernel.h was indeed not required. However, I'm thinking that if 
we want the header
to be self-contained and given that ...

[...]

> diff --git a/xen/arch/arm/include/asm/dom0less-build.h 
> b/xen/arch/arm/include/asm/dom0less-build.h
> new file mode 100644
> index ..c5625925d940
> --- /dev/null
> +++ b/xen/arch/arm/include/asm/dom0less-build.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +#ifndef __ASM_DOM0LESS_BUILD_H_
> +#define __ASM_DOM0LESS_BUILD_H_
> +
> +void create_domUs(void);
> +bool is_dom0less_mode(void);
here we use bool, I think we should include 

I think this change could be done on commit provided no remarks from other 
maintainers.

~Michal




Re: [PATCH v3 02/14] xen/asm-generic: introduce generic device.h

2023-11-24 Thread Julien Grall

Hi Oleksii,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

Arm, PPC and RISC-V use the same device.h thereby device.h
was moved to asm-generic. 


I read "was moved" as the patch should also contain some deleted lines. 
But below, I only see the file introduced. Did you intend to also remove 
the version in arm/include/asm?



Arm's device.h was taken as a base with
the following changes:
  - #ifdef PCI related things.
  - #ifdef ACPI related things.
  - Rename #ifdef guards.
  - Add SPDX tag.
  - #ifdef CONFIG_HAS_DEVICE_TREE related things.

Signed-off-by: Oleksii Kurochko 
---
It is still open question if device.h should be in asm-generic. Need more 
opinions.


I still think it should. But I guess you want others to answer? If so it 
would be worth to point out from who you seek opinions.



---
Changes in V3:
  - ifdef device tree related things.
  - update the commit message
---
Changes in V2:
- take ( as common ) device.h from Arm as PPC and RISC-V use it as a 
base.
- #ifdef PCI related things.
- #ifdef ACPI related things.
- rename DEVICE_GIC to DEVIC_IC.
- rename #ifdef guards.
- switch Arm and PPC to generic device.h
- add SPDX tag
- update the commit message

---
  xen/include/asm-generic/device.h | 147 +++
  1 file changed, 147 insertions(+)
  create mode 100644 xen/include/asm-generic/device.h

diff --git a/xen/include/asm-generic/device.h b/xen/include/asm-generic/device.h
new file mode 100644
index 00..7ef5aa955a
--- /dev/null
+++ b/xen/include/asm-generic/device.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_GENERIC_DEVICE_H__
+#define __ASM_GENERIC_DEVICE_H__
+
+enum device_type
+{
+#ifdef CONFIG_HAS_DEVICE_TREE
+DEV_DT,
+#endif
+
+#ifdef HAS_PCI
+DEV_PCI,
+#endif
+};
+
+struct dev_archdata {
+void *iommu;/* IOMMU private data */
+};
+
+/* struct device - The basic device structure */
+struct device
+{
+enum device_type type;
+#ifdef CONFIG_HAS_DEVICE_TREE
+struct dt_device_node *of_node; /* Used by drivers imported from Linux */
+#endif
+struct dev_archdata archdata;
+struct iommu_fwspec *iommu_fwspec; /* per-device IOMMU instance data */
+};
+
+typedef struct device device_t;
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+#include 
+#endif


NIT: Could we try to rationalize the number of #ifdef CONFIG_HAS_*? For 
example ...



+
+#ifdef HAS_PCI
+#define dev_is_pci(dev) ((dev)->type == DEV_PCI)
+#endif
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+#define dev_is_dt(dev)  ((dev)->type == DEV_DT)
+#endif


... this is another definition for Device-Tree only. It could be easily 
moved above the definitnion of dev_is_pci(). The others would be the 
DT_DEVICE_*() helpers.



+
+enum device_class
+{
+DEVICE_SERIAL,
+DEVICE_IOMMU,
+DEVICE_IC,


I guess you mean INTERRUPT_CONTROLLER? If so, can this be spelt out? (I 
don't think shorthand version is worth it here)


Cheers,

--
Julien Grall



Re: [PATCH v3 04/14] xen/asm-generic: introduce generic header iocap.h

2023-11-24 Thread Julien Grall

Hi Oleksii,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

iocap.h is common for Arm, PPC and RISC-V architectures thereby
it was moved to asm-generic.

Also Arm and PPC were switched to asm-generic version of iocap.h.

Signed-off-by: Oleksii Kurochko 


Acked-by: Julien Grall 

Cheers,

--
Julien Grall



Re: [PATCH v3 05/14] xen/asm-generic: introduce stub header

2023-11-24 Thread Julien Grall

Hi Oleksii,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

 is common for Arm, PPC and RISC-V thereby it
is moved to asm-generic.

Signed-off-by: Oleksii Kurochko 


Acked-by: Julien Grall 

Cheers,

--
Julien Grall



Re: Clang-format configuration discussion - pt 2

2023-11-24 Thread George Dunlap
On Thu, Nov 23, 2023 at 2:48 PM Luca Fancellu  wrote:
> AlignConsecutiveAssignments: None
>
> ---
> This one is disabled because of feedbacks from Stefano and Alejandro about 
> some weird behaviour on our
> codebase.
>
> This one could be phased along this line: “Consecutive assignments don't need 
> to be aligned.”, the issue is
> that in this way it seems that it’s optional, but clang-format is going to 
> remove the alignment anyway for
> assignment that are consecutive and aligned.

It's hard to agree on this one without seeing some of the examples of
what it does, some examples of the "weird behavior" Stefano &
Allejandro found, and some examples of places where it's going to
remove the alignment.

I had tried to apply your series before and didn't get very far with
it for some reason ISTR.  One way to see the effect of individual
features would be:

1. Make a branch with one big patch applying clang-format for a given style

2. Change just one style line, re-run clang format, and create a new
patch from that

Then it would be easy to see the difference between the two.  It might
actually be easier for individual reviewers to do that on their own
trees, rather than to ask you to try to generate and post such patches
somewhere.

 -George



Re: [PATCH v3 06/14] xen/asm-generic: introduce generic header percpu.h

2023-11-24 Thread Julien Grall

Hi Oleksii,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

The patch introduces generic percpu.h which was based on Arm's version
with the following changes:
  * makes __per_cpu_data_end[] constant
  * introduce get_per_cpu_offset() for macros this_cpu() and this_cpu_ptr()
  * add inclustion of  as get_per_cpu_offset() is located there.

Also it was changed a place where  is included in 
because asm-generic version of percpu.h started to include  which
requires definition of DECLARE_PER_CPU.

As well the patch switches Arm, PPC and x86 architectures to use asm-generic
version of percpu.h.

Signed-off-by: Oleksii Kurochko 
---
Changes in V3:
  - switch all architectures to asm-generic version of percpu.h
  - introduce get_per_cpu_offset() and implement it architectures.
  - make __per_cpu_data_end constamt.
  - update the commit message.
---
Changes in V2:
- use smp_processor_id() instead of get_processor_id().
- update commit message .
---
  xen/arch/arm/include/asm/Makefile |  1 +
  xen/arch/arm/include/asm/current.h|  3 +++


The changes for Arm and common looks good to me. I saw Jan thought the 
include movement is fragile, I don't have any strong opinion about the 
placement so long it compiles :). So feels free to add my ack:


Acked-by: Julien Grall 

Cheers,

--
Julien Grall



Re: [PATCH v3 07/14] xen/asm-generic: introduce generalized hardirq.h

2023-11-24 Thread Julien Grall

Hi Oleksii,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

 is common through archs thereby it is moved
to asm-generic.

Arm and PPC were switched to asm generic verstion of hardirq.h.

Signed-off-by: Oleksii Kurochko 


Acked-by: Julien Grall 

Cheers,

--
Julien Grall



Re: [PATCH v3 08/14] xen/asm-generic: introduce generic div64.h header

2023-11-24 Thread Julien Grall

Hi,

On 17/11/2023 12:24, Oleksii Kurochko wrote:

All archs have the do_div implementation for BITS_PER_LONG == 64
so do_div64.h is moved to asm-generic.


You are saying "all archs" but ...



x86 and PPC were switched to asm-generic version of div64.h.


... you only switch x86/PPC to div64.h.

I guess this is because for arm we have a different implementation for 
32-bits. The 64-bits version is the same as x86/PPC.


So I wonder if it is possible to include asm-generic/div64.h from 
arch/arm/include/asm/div64.h?


This will avoid duplicating some code.

Cheers,

--
Julien Grall



[xen-unstable-smoke test] 183851: tolerable all pass - PUSHED

2023-11-24 Thread osstest service owner
flight 183851 xen-unstable-smoke real [real]
http://logs.test-lab.xenproject.org/osstest/logs/183851/

Failures :-/ but no regressions.

Tests which did not succeed, but are not blocking:
 test-amd64-amd64-libvirt 15 migrate-support-checkfail   never pass
 test-arm64-arm64-xl-xsm  15 migrate-support-checkfail   never pass
 test-arm64-arm64-xl-xsm  16 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl  15 migrate-support-checkfail   never pass
 test-armhf-armhf-xl  16 saverestore-support-checkfail   never pass

version targeted for testing:
 xen  80c153c48b255bae61948827241c26671207cf4e
baseline version:
 xen  03d6720a4c62c283f9a9f09858eeccd24299b312

Last test of basis   183846  2023-11-23 19:02:06 Z0 days
Testing same since   183851  2023-11-24 09:03:53 Z0 days1 attempts


People who touched revisions under test:
  Andrew Cooper 
  Federico Serafini 
  Jan Beulich 
  Nicola Vetrini 
  Roger Pau Monné 

jobs:
 build-arm64-xsm  pass
 build-amd64  pass
 build-armhf  pass
 build-amd64-libvirt  pass
 test-armhf-armhf-xl  pass
 test-arm64-arm64-xl-xsm  pass
 test-amd64-amd64-xl-qemuu-debianhvm-amd64pass
 test-amd64-amd64-libvirt pass



sg-report-flight on osstest.test-lab.xenproject.org
logs: /home/logs/logs
images: /home/logs/images

Logs, config files, etc. are available at
http://logs.test-lab.xenproject.org/osstest/logs

Explanation of these reports, and of osstest in general, is at
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README.email;hb=master
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README;hb=master

Test harness code can be found at
http://xenbits.xen.org/gitweb?p=osstest.git;a=summary


Pushing revision :

To xenbits.xen.org:/home/xen/git/xen.git
   03d6720a4c..80c153c48b  80c153c48b255bae61948827241c26671207cf4e -> smoke



Re: [PATCH 1/2] livepatch-build-tools: remove usage of gawk

2023-11-24 Thread Ross Lagerwall
On Thu, Nov 23, 2023 at 4:08 PM Roger Pau Monne  wrote:
>
> And instead use plain awk.
>
> There's no need to use the --non-decimal-data option for gawk, since the
> numbers that we want to print are already prefixed with '0x', and so plain awk
> will do the conversion from hexadecimal to decimal just fine.

I don't think that's true (at least with gnu awk 5.1.1):

$ echo '   DW_AT_byte_size   : 0x14' | awk '{printf("%d\n", $4)}'
0

Having said that, my version of readelf actually gives the value in
decimal so the patch still works. But is that the case for all
versions of readelf? I assume the code was written like that for a
reason...

Ross



Re: Clang-format configuration discussion - pt 2

2023-11-24 Thread Luca Fancellu


> On 24 Nov 2023, at 11:12, George Dunlap  wrote:
> 
> On Thu, Nov 23, 2023 at 2:48 PM Luca Fancellu  wrote:
>> AlignConsecutiveAssignments: None
>> 
>> ---
>> This one is disabled because of feedbacks from Stefano and Alejandro about 
>> some weird behaviour on our
>> codebase.
>> 
>> This one could be phased along this line: “Consecutive assignments don't 
>> need to be aligned.”, the issue is
>> that in this way it seems that it’s optional, but clang-format is going to 
>> remove the alignment anyway for
>> assignment that are consecutive and aligned.
> 
> It's hard to agree on this one without seeing some of the examples of
> what it does, some examples of the "weird behavior" Stefano &
> Allejandro found,

I think there was a comment from Stefano for the RFC v1:
https://patchwork.kernel.org/project/xen-devel/cover/20230728081144.4124309-1-luca.fance...@arm.com/#25447625

> and some examples of places where it's going to
> remove the alignment.

Hi George,

You are right, with an example is better, so I’ve checked into the output:
https://gitlab.com/luca.fancellu/xen-clang/-/commit/8938bf2196be66b05693a48752ebbdf363e8d8e1.patch

And for this one, you can see here on line 6186 of that patch:

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 49792dd590..c229318450 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c

[...]

@@ -,19 +3318,18 @@ static int __init alloc_domain_evtchn(struct 
dt_device_node *node)
rc = evtchn_alloc_unbound(&alloc_unbound, domU1_port);
if ( rc < 0 )
{
- printk(XENLOG_ERR
- "evtchn_alloc_unbound() failure (Error %d) \n", rc);
+ printk(XENLOG_ERR "evtchn_alloc_unbound() failure (Error %d) \n", rc);
return rc;
}
- bind_interdomain.remote_dom = d1->domain_id;
+ bind_interdomain.remote_dom = d1->domain_id;
bind_interdomain.remote_port = domU1_port;
rc = evtchn_bind_interdomain(&bind_interdomain, d2, domU2_port);
if ( rc < 0 )
{

Assignment of bind_interdomain.remote_dom was aligned with the following line, 
but since the value
of this configurable is “None”, clang-format is modifying that to use only one 
space before the assignment
operator.



One example related to macros can be found on line 1663:

diff --git a/xen/arch/arm/arm32/insn.c b/xen/arch/arm/arm32/insn.c
index 49953a042a..1635c4b6d1 100644
--- a/xen/arch/arm/arm32/insn.c
+++ b/xen/arch/arm/arm32/insn.c
@@ -19,9 +19,9 @@
#include 
/* Mask of branch instructions' immediate. */
-#define BRANCH_INSN_IMM_MASK GENMASK(23, 0)
+#define BRANCH_INSN_IMM_MASK GENMASK(23, 0)
/* Shift of branch instructions' immediate. */
-#define BRANCH_INSN_IMM_SHIFT 0
+#define BRANCH_INSN_IMM_SHIFT 0

Clang format sees the comment between BRANCH_INSN_IMM_MASK and 
BRANCH_INSN_IMM_SHIFT and
even if before the value of the macros were aligned, it applies the rule of one 
space between the macro name
and the value.

> 
> I had tried to apply your series before and didn't get very far with
> it for some reason ISTR.

If you reach me we can see what issue you are facing, I think staging went 
ahead since my last push,
but I’ve put a SHA in the cover letter, anyway I can help on that if you want.


>  One way to see the effect of individual
> features would be:
> 
> 1. Make a branch with one big patch applying clang-format for a given style
> 
> 2. Change just one style line, re-run clang format, and create a new
> patch from that
> 
> Then it would be easy to see the difference between the two.  It might
> actually be easier for individual reviewers to do that on their own
> trees, rather than to ask you to try to generate and post such patches
> somewhere.
> 
> -George



Re: [PATCH 2/2] livepatch-build-tools: do not use readlink -m option

2023-11-24 Thread Ross Lagerwall
On Thu, Nov 23, 2023 at 4:08 PM Roger Pau Monne  wrote:
>
> Busybox readlink implementation only supports the -f option to follow 
> symlinks,
> so adjust the logic in order to keep the same behaviour without using the -m
> option.
>
> Singed-off-by: Roger Pau Monné 

Reviewed-by: Ross Lagerwall 

Thanks



Re: [PATCH v3 08/14] xen/asm-generic: introduce generic div64.h header

2023-11-24 Thread Oleksii
Hi Julien,

On Fri, 2023-11-24 at 11:29 +, Julien Grall wrote:
> Hi,
> 
> On 17/11/2023 12:24, Oleksii Kurochko wrote:
> > All archs have the do_div implementation for BITS_PER_LONG == 64
> > so do_div64.h is moved to asm-generic.
> 
> You are saying "all archs" but ...
> 
> > 
> > x86 and PPC were switched to asm-generic version of div64.h.
> 
> ... you only switch x86/PPC to div64.h.
You are right. I wasn't precise enough. Also RISC-V uses asm-generic
version of div64.h but for that I have separate patch series.

> 
> I guess this is because for arm we have a different implementation
> for 
> 32-bits. The 64-bits version is the same as x86/PPC.
> 
> So I wonder if it is possible to include asm-generic/div64.h from 
> arch/arm/include/asm/div64.h?
> 
> This will avoid duplicating some code.
Yes, you are right. Arm wasn't switched to asm-generic/div64.h because
of different implementaion for 32-bit.

I think we can include asm-generic/div64.h excplicitly for Arm. I made
a little test and it works so I started full CI and if it won't any
issue with Arm I'll update the patch.


Thanks for the comments.

> Cheers,
> 




[PATCH] automation: Switch u-boot boot command to bootz for arm32 tests

2023-11-24 Thread Michal Orzel
Thanks to recent changes added to ImageBuilder to support the bootz
command, which allows obtaining the effective image size (including NOLOAD
sections) from the zImage header, switch the BOOT_CMD for arm32 tests to
bootz. Among other scenarios, this change will enable us, in the future,
to add tests with UBSAN enabled Xen, which would otherwise fail due to
incorrect image placement resulting in overlapping.

Signed-off-by: Michal Orzel 
---
Before adding UBSAN CI tests, we still need to decide if we want to add support
to panic on UBSAN epilogue guarded by some config option or to just grep for
UBSAN message.

CI pipeline:
https://gitlab.com/xen-project/people/morzel/xen-orzelmichal/-/pipelines/1083821754
---
 automation/scripts/qemu-smoke-dom0-arm32.sh | 2 +-
 automation/scripts/qemu-smoke-dom0less-arm32.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/automation/scripts/qemu-smoke-dom0-arm32.sh 
b/automation/scripts/qemu-smoke-dom0-arm32.sh
index a4b487b08055..d91648905669 100755
--- a/automation/scripts/qemu-smoke-dom0-arm32.sh
+++ b/automation/scripts/qemu-smoke-dom0-arm32.sh
@@ -68,7 +68,7 @@ XEN_CMD="console=dtuart dom0_mem=1024M bootscrub=0 
console_timestamps=boot"
 NUM_DOMUS=0
 
 LOAD_CMD="tftpb"
-BOOT_CMD="bootm"
+BOOT_CMD="bootz"
 UBOOT_SOURCE="boot.source"
 UBOOT_SCRIPT="boot.scr"' > config
 
diff --git a/automation/scripts/qemu-smoke-dom0less-arm32.sh 
b/automation/scripts/qemu-smoke-dom0less-arm32.sh
index 7e3cfbe9c4d0..e31b6b9014e1 100755
--- a/automation/scripts/qemu-smoke-dom0less-arm32.sh
+++ b/automation/scripts/qemu-smoke-dom0less-arm32.sh
@@ -101,7 +101,7 @@ DOMU_MEM[0]="512"
 NUM_DOMUS=1
 
 LOAD_CMD="tftpb"
-BOOT_CMD="bootm"
+BOOT_CMD="bootz"
 UBOOT_SOURCE="boot.source"
 UBOOT_SCRIPT="boot.scr"' > config
 
-- 
2.25.1




Re: [PATCH 1/2] livepatch-build-tools: remove usage of gawk

2023-11-24 Thread Alejandro Vallejo

On 24/11/2023 11:43, Ross Lagerwall wrote:
> On Thu, Nov 23, 2023 at 4:08 PM Roger Pau Monne 
 wrote:

>>
>> And instead use plain awk.
>>
>> There's no need to use the --non-decimal-data option for gawk, since the
>> numbers that we want to print are already prefixed with '0x', and so 
plain awk

>> will do the conversion from hexadecimal to decimal just fine.
>
> I don't think that's true (at least with gnu awk 5.1.1):
>
> $ echo '   DW_AT_byte_size   : 0x14' | awk '{printf("%d\n", $4)}'
> 0
>

I think it's a FreeBSD quirk. From their man page:

>Historically,  awk did not accept "0x" as a hex string. 
However, since
>One True Awk used strtod to convert strings to floats, and 
since "0x12"
>is a valid hexadecimal representation of a floating  point 
number,  On
>FreeBSD, awk has accepted this notation as an extension since 
One True
>Awk was imported in FreeBSD 5.0. Upstream One True  Awk has 
restored
>the  historical behavior for better compatibility between the 
different
>awk implementations.  Both gawk and mawk already  behave 
similarly.
>Starting with FreeBSD 14.0 awk will no longer accept this 
extension.


I'm guessing the latest FreeBSD doesn't have that behaviour either?

Cheers,
Alejandro



Re: [PATCH v3 02/14] xen/asm-generic: introduce generic device.h

2023-11-24 Thread Oleksii
On Fri, 2023-11-24 at 11:01 +, Julien Grall wrote:
> Hi Oleksii,
> 
> On 17/11/2023 12:24, Oleksii Kurochko wrote:
> > Arm, PPC and RISC-V use the same device.h thereby device.h
> > was moved to asm-generic. 
> 
> I read "was moved" as the patch should also contain some deleted
> lines. 
> But below, I only see the file introduced. Did you intend to also
> remove 
> the version in arm/include/asm?
Yes, I just messed up with the patch version. Here is the version of
the patch which remove Arm's device.h:
https://gitlab.com/xen-project/people/olkur/xen/-/commit/ce845abfb57d27b0c08984f5433085c767550495
> 
> > Arm's device.h was taken as a base with
> > the following changes:
> >   - #ifdef PCI related things.
> >   - #ifdef ACPI related things.
> >   - Rename #ifdef guards.
> >   - Add SPDX tag.
> >   - #ifdef CONFIG_HAS_DEVICE_TREE related things.
> > 
> > Signed-off-by: Oleksii Kurochko 
> > ---
> > It is still open question if device.h should be in asm-generic.
> > Need more opinions.
> 
> I still think it should. But I guess you want others to answer? If so
> it 
> would be worth to point out from who you seek opinions.
> 
> > ---
> > Changes in V3:
> >   - ifdef device tree related things.
> >   - update the commit message
> > ---
> > Changes in V2:
> > - take ( as common ) device.h from Arm as PPC and RISC-V
> > use it as a base.
> > - #ifdef PCI related things.
> > - #ifdef ACPI related things.
> > - rename DEVICE_GIC to DEVIC_IC.
> > - rename #ifdef guards.
> > - switch Arm and PPC to generic device.h
> > - add SPDX tag
> > - update the commit message
> > 
> > ---
> >   xen/include/asm-generic/device.h | 147
> > +++
> >   1 file changed, 147 insertions(+)
> >   create mode 100644 xen/include/asm-generic/device.h
> > 
> > diff --git a/xen/include/asm-generic/device.h b/xen/include/asm-
> > generic/device.h
> > new file mode 100644
> > index 00..7ef5aa955a
> > --- /dev/null
> > +++ b/xen/include/asm-generic/device.h
> > @@ -0,0 +1,147 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +#ifndef __ASM_GENERIC_DEVICE_H__
> > +#define __ASM_GENERIC_DEVICE_H__
> > +
> > +enum device_type
> > +{
> > +#ifdef CONFIG_HAS_DEVICE_TREE
> > +    DEV_DT,
> > +#endif
> > +
> > +#ifdef HAS_PCI
> > +    DEV_PCI,
> > +#endif
> > +};
> > +
> > +struct dev_archdata {
> > +    void *iommu;    /* IOMMU private data */
> > +};
> > +
> > +/* struct device - The basic device structure */
> > +struct device
> > +{
> > +    enum device_type type;
> > +#ifdef CONFIG_HAS_DEVICE_TREE
> > +    struct dt_device_node *of_node; /* Used by drivers imported
> > from Linux */
> > +#endif
> > +    struct dev_archdata archdata;
> > +    struct iommu_fwspec *iommu_fwspec; /* per-device IOMMU
> > instance data */
> > +};
> > +
> > +typedef struct device device_t;
> > +
> > +#ifdef CONFIG_HAS_DEVICE_TREE
> > +#include 
> > +#endif
> 
> NIT: Could we try to rationalize the number of #ifdef CONFIG_HAS_*?
> For 
> example ...
> 
> > +
> > +#ifdef HAS_PCI
> > +#define dev_is_pci(dev) ((dev)->type == DEV_PCI)
> > +#endif
> > +
> > +#ifdef CONFIG_HAS_DEVICE_TREE
> > +#define dev_is_dt(dev)  ((dev)->type == DEV_DT)
> > +#endif
> 
> ... this is another definition for Device-Tree only. It could be
> easily 
> moved above the definitnion of dev_is_pci(). The others would be the 
> DT_DEVICE_*() helpers.
Yes, sure. I can combine CONFIG_HAS_DEVICE_TREE related things better.

> 
> > +
> > +enum device_class
> > +{
> > +    DEVICE_SERIAL,
> > +    DEVICE_IOMMU,
> > +    DEVICE_IC,
> 
> I guess you mean INTERRUPT_CONTROLLER? If so, can this be spelt out?
> (I 
> don't think shorthand version is worth it here)
Sure, I'll change to INTERRUPT_CONTROLLER.

~ Oleksii



Re: [PATCH] automation: Switch u-boot boot command to bootz for arm32 tests

2023-11-24 Thread Andrew Cooper
On 24/11/2023 12:09 pm, Michal Orzel wrote:
> Thanks to recent changes added to ImageBuilder to support the bootz
> command, which allows obtaining the effective image size (including NOLOAD
> sections) from the zImage header, switch the BOOT_CMD for arm32 tests to
> bootz. Among other scenarios, this change will enable us, in the future,
> to add tests with UBSAN enabled Xen, which would otherwise fail due to
> incorrect image placement resulting in overlapping.
>
> Signed-off-by: Michal Orzel 
> ---
> Before adding UBSAN CI tests, we still need to decide if we want to add 
> support
> to panic on UBSAN epilogue guarded by some config option or to just grep for
> UBSAN message.

CONFIG_UBSAN_FATAL please (name subject to taste.)

Grepping dmesg is never a reliable option (see how many recent fixes
we've had to console handling in the smoke tests), and reliability is
important.

~Andrew



Re: Clang-format configuration discussion - pt 2

2023-11-24 Thread Jan Beulich
On 24.11.2023 12:59, Luca Fancellu wrote:
> @@ -,19 +3318,18 @@ static int __init alloc_domain_evtchn(struct 
> dt_device_node *node)
> rc = evtchn_alloc_unbound(&alloc_unbound, domU1_port);
> if ( rc < 0 )
> {
> - printk(XENLOG_ERR
> - "evtchn_alloc_unbound() failure (Error %d) \n", rc);
> + printk(XENLOG_ERR "evtchn_alloc_unbound() failure (Error %d) \n", rc);
> return rc;
> }
> - bind_interdomain.remote_dom = d1->domain_id;
> + bind_interdomain.remote_dom = d1->domain_id;
> bind_interdomain.remote_port = domU1_port;
> rc = evtchn_bind_interdomain(&bind_interdomain, d2, domU2_port);
> if ( rc < 0 )
> {
> 
> Assignment of bind_interdomain.remote_dom was aligned with the following 
> line, but since the value
> of this configurable is “None”, clang-format is modifying that to use only 
> one space before the assignment
> operator.

Neither here nor ...

> One example related to macros can be found on line 1663:
> 
> diff --git a/xen/arch/arm/arm32/insn.c b/xen/arch/arm/arm32/insn.c
> index 49953a042a..1635c4b6d1 100644
> --- a/xen/arch/arm/arm32/insn.c
> +++ b/xen/arch/arm/arm32/insn.c
> @@ -19,9 +19,9 @@
> #include 
> /* Mask of branch instructions' immediate. */
> -#define BRANCH_INSN_IMM_MASK GENMASK(23, 0)
> +#define BRANCH_INSN_IMM_MASK GENMASK(23, 0)
> /* Shift of branch instructions' immediate. */
> -#define BRANCH_INSN_IMM_SHIFT 0
> +#define BRANCH_INSN_IMM_SHIFT 0
> 
> Clang format sees the comment between BRANCH_INSN_IMM_MASK and 
> BRANCH_INSN_IMM_SHIFT and
> even if before the value of the macros were aligned, it applies the rule of 
> one space between the macro name
> and the value.

... here there is any change in the formatting on the lines in question.
I was first suspecting a possible issue with my mail UI, but
https://lists.xen.org/archives/html/xen-devel/2023-11/msg02132.html
looks to confirm the issue to more likely be on your end (apparently also
resulting in leading whitespace having been dropped).

Jan



  1   2   >