From 7498407f90a5e7858df43bc65f50c753beaf8564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Wed, 3 Jan 2024 17:51:54 +0000 Subject: [PATCH 1/7] add helper function for checking platform field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be useful for checking some new fields introduced in Xen-4.15+ Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index 96aa1037166..72e1c51837c 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -288,6 +288,27 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = sprintf "Guest type %s unavailable" (if hvm then "HVM" else "PV") ) ; + let get_platform_key ~key ~default check = + let platformdata = vm_info.platformdata in + let unknown = List.assoc_opt key platformdata |> Option.value ~default:"" in + let on_error msg = + error "VM = %s; %s platform/%s=\"%s\"." (Uuidx.to_string uuid) msg key + unknown ; + invalid_arg (Printf.sprintf "platform/%s=%s" key unknown) + in + if not @@ Platform.is_valid ~key ~platformdata then + on_error "Unrecognized value" ; + let wants = Platform.is_true ~key ~platformdata ~default in + match check wants with Ok () -> wants | Error msg -> on_error msg + in + + let require_hvm wants : (_, _) result = + if wants && not hvm then + Error "HVM required for" + else + Ok () + in + (* HVM guests must select a paging mode of either HAP "Hardware Assisted Paging" or Shadow. *) let hap = @@ -298,17 +319,9 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = unconditionally and raise an error if unavailable. Otherwise, use HAP if available, falling back to Shadow if not. *) let hap = - match List.assoc_opt "hap" vm_info.platformdata with - | Some "true" -> - true - | Some "false" -> - false - | Some unknown -> - error "VM = %s; Unrecognized value platform/hap=\"%s\"." - (Uuidx.to_string uuid) unknown ; - invalid_arg ("platform/hap=" ^ unknown) - | None -> - List.mem CAP_HAP host_info.capabilities + get_platform_key ~key:"hap" + (fun _ -> Ok ()) + ~default:(List.mem CAP_HAP host_info.capabilities) in (* HAP depends on 2nd Gen VT-x/SVM, or firmware/Xen settings. Shadow From 664de7608df8460cc3517f708b31f887059c83c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Wed, 3 Jan 2024 17:53:10 +0000 Subject: [PATCH 2/7] Xen-4.15+: CDF_NESTED_VIRT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only `platform:nested-virt=true` sets this field. The previous experimental field `platform:exp-nested-hvm=true` is now dropped. `platform:nested-virt` has been present in the product since Dundee, any users of `exp-nested-hvm` can be updated to use that instead. This doesn't mean that nested virt is supported yet: its implementation is still incomplete. Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index 72e1c51837c..c39d6698058 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -66,6 +66,7 @@ type domain_create_flag = Xenctrl.domain_create_flag = | CDF_OOS_OFF | CDF_XS_DOMAIN | CDF_IOMMU + | CDF_NESTED_VIRT [@@deriving rpcty] type domain_create_iommu_opts = Xenctrl.domain_create_iommu_opts = @@ -340,18 +341,25 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = let iommu = vm_info.pci_passthrough in if iommu then assert_capability CAP_DirectIO ~on_error:(fun () -> "IOMMU unavailable") ; + let nested_virt = get_platform_key ~key:"nested_virt" ~default:false require_hvm in - info "VM = %s; Creating %s%s%s" (Uuidx.to_string uuid) + info "VM = %s; Creating %s%s%s%s" (Uuidx.to_string uuid) (if hvm then "HVM" else "PV") (if hap then " HAP" else "") - (if iommu then " IOMMU" else "") ; + (if iommu then " IOMMU" else "") + (if nested_virt then " NESTEDVIRT" else "") ; let config = { ssidref= vm_info.ssidref ; handle= Uuidx.to_string uuid ; flags= - [(hvm, CDF_HVM); (hap, CDF_HAP); (iommu, CDF_IOMMU)] + [ + (hvm, CDF_HVM) + ; (hap, CDF_HAP) + ; (iommu, CDF_IOMMU) + ; (nested_virt, CDF_NESTED_VIRT) + ] |> List.filter_map (fun (cond, flag) -> if cond then Some flag else None) ; iommu_opts= ( match no_sharept with From 7c969cfc59a32ef0bb265aea8d179c9db8df9dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Wed, 3 Jan 2024 18:03:55 +0000 Subject: [PATCH 3/7] Xen 4.15+: X86_MSR_RELAXED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `platform:msr-relaxed=true` Signed-off-by: Andrew Cooper Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 6 ++++++ ocaml/xenopsd/xc/domain.mli | 3 +++ ocaml/xenopsd/xc/xenops_server_xen.ml | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index c39d6698058..affb6ddc4ba 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -49,8 +49,14 @@ type x86_arch_emulation_flags = Xenctrl.x86_arch_emulation_flags = | X86_EMU_VPCI [@@deriving rpcty] +type x86_arch_misc_flags = Xenctrl.x86_arch_misc_flags = X86_MSR_RELAXED +[@@deriving rpcty] + type xen_x86_arch_domainconfig = Xenctrl.xen_x86_arch_domainconfig = { emulation_flags: x86_arch_emulation_flags list + ; misc_flags: x86_arch_misc_flags list [@default [X86_MSR_RELAXED]] + (* misc_flags is missing when migrating from old version. + set the default to relaxed MSR for backwards compatibility *) } [@@deriving rpcty] diff --git a/ocaml/xenopsd/xc/domain.mli b/ocaml/xenopsd/xc/domain.mli index 0f18579ecfc..b7b275a6efd 100644 --- a/ocaml/xenopsd/xc/domain.mli +++ b/ocaml/xenopsd/xc/domain.mli @@ -59,9 +59,12 @@ val emulation_flags_pvh : x86_arch_emulation_flags list val emulation_flags_all : x86_arch_emulation_flags list +type x86_arch_misc_flags = X86_MSR_RELAXED + type xen_x86_arch_domainconfig = { (* Xenctrl.xen_x86_arch_domainconfig = *) emulation_flags: x86_arch_emulation_flags list + ; misc_flags: x86_arch_misc_flags list } type arch_domainconfig = diff --git a/ocaml/xenopsd/xc/xenops_server_xen.ml b/ocaml/xenopsd/xc/xenops_server_xen.ml index bc1c1c77d30..a04dabe98c6 100644 --- a/ocaml/xenopsd/xc/xenops_server_xen.ml +++ b/ocaml/xenopsd/xc/xenops_server_xen.ml @@ -134,13 +134,22 @@ module VmExtra = struct let domain_config_of_vm vm = let open Vm in let open Domain in + let misc_flags = + if + Platform.is_true ~key:"msr-relaxed" + ~platformdata:vm.Xenops_interface.Vm.platformdata ~default:false + then + [X86_MSR_RELAXED] + else + [] + in match vm.ty with | PV _ -> - X86 {emulation_flags= []} + X86 {emulation_flags= []; misc_flags} | PVinPVH _ | PVH _ -> - X86 {emulation_flags= emulation_flags_pvh} + X86 {emulation_flags= emulation_flags_pvh; misc_flags} | HVM _ -> - X86 {emulation_flags= emulation_flags_all} + X86 {emulation_flags= emulation_flags_all; misc_flags} (* Known versions of the VM persistent metadata created by xenopsd *) let persistent_version_pre_lima = 0 From cb53852a56a7abe3863ed88403d69c7cdf75b5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Wed, 3 Jan 2024 18:04:30 +0000 Subject: [PATCH 4/7] Xen 4.16+: CDF_VPMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `platform:vpmu=true`. For this to work the Xen cmdline also needs to be edited to remove the watchdog, and enable vpmu. In the future this may become easier. VPMU doesn't require HVM. Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index affb6ddc4ba..62ce9d65c29 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -73,6 +73,7 @@ type domain_create_flag = Xenctrl.domain_create_flag = | CDF_XS_DOMAIN | CDF_IOMMU | CDF_NESTED_VIRT + | CDF_VPMU [@@deriving rpcty] type domain_create_iommu_opts = Xenctrl.domain_create_iommu_opts = @@ -348,12 +349,14 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = if iommu then assert_capability CAP_DirectIO ~on_error:(fun () -> "IOMMU unavailable") ; let nested_virt = get_platform_key ~key:"nested_virt" ~default:false require_hvm in + let vpmu = get_platform_key ~key:"vpmu" ~default:false (fun _ -> Ok()) in - info "VM = %s; Creating %s%s%s%s" (Uuidx.to_string uuid) + info "VM = %s; Creating %s%s%s%s%s" (Uuidx.to_string uuid) (if hvm then "HVM" else "PV") (if hap then " HAP" else "") (if iommu then " IOMMU" else "") - (if nested_virt then " NESTEDVIRT" else "") ; + (if nested_virt then " NESTEDVIRT" else "") + (if vpmu then " VPMU" else "") ; let config = { @@ -365,6 +368,7 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = ; (hap, CDF_HAP) ; (iommu, CDF_IOMMU) ; (nested_virt, CDF_NESTED_VIRT) + ; (vpmu, CDF_VPMU) ] |> List.filter_map (fun (cond, flag) -> if cond then Some flag else None) ; iommu_opts= From 4ee7a734e78961580e501b92637cc7b693e38140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Wed, 3 Jan 2024 17:30:16 +0000 Subject: [PATCH 5/7] Xen-4.16+: support max_grant_version field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set to 2 if the host supports it. Signed-off-by: Andrew Cooper Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index 62ce9d65c29..7e29ab4e882 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -105,6 +105,7 @@ type domctl_create_config = Xenctrl.domctl_create_config = { ; max_evtchn_port: int ; max_grant_frames: int ; max_maptrack_frames: int + ; max_grant_version: int ; arch: arch_domainconfig } [@@deriving rpcty] @@ -390,6 +391,8 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = int_of_string (List.assoc "max_maptrack_frames" vm_info.platformdata) with _ -> 1024 ) + ; max_grant_version= + (if List.mem CAP_Gnttab_v2 host_info.capabilities then 2 else 1) ; arch= domain_config } in From bcc44277034e705cfef4dc9566dc86ab84422996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Wed, 3 Jan 2024 17:30:47 +0000 Subject: [PATCH 6/7] Xen-4.17+: cpupool_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always set to 0. Signed-off-by: Andrew Cooper Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index 7e29ab4e882..205ba9794fb 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -106,6 +106,7 @@ type domctl_create_config = Xenctrl.domctl_create_config = { ; max_grant_frames: int ; max_maptrack_frames: int ; max_grant_version: int + ; cpupool_id: int32 ; arch: arch_domainconfig } [@@deriving rpcty] @@ -393,6 +394,7 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = ) ; max_grant_version= (if List.mem CAP_Gnttab_v2 host_info.capabilities then 2 else 1) + ; cpupool_id= 0l ; arch= domain_config } in From 96d012a1e1941ec505f81944fd5f611f9e9ea4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Thu, 1 Feb 2024 10:48:59 +0000 Subject: [PATCH 7/7] [maintenance]: fix formatting after Xen-4.17 merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Edwin Török --- ocaml/xenopsd/xc/domain.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index 205ba9794fb..bd17e5d284a 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -350,8 +350,10 @@ let make ~xc ~xs vm_info vcpus domain_config uuid final_uuid no_sharept = let iommu = vm_info.pci_passthrough in if iommu then assert_capability CAP_DirectIO ~on_error:(fun () -> "IOMMU unavailable") ; - let nested_virt = get_platform_key ~key:"nested_virt" ~default:false require_hvm in - let vpmu = get_platform_key ~key:"vpmu" ~default:false (fun _ -> Ok()) in + let nested_virt = + get_platform_key ~key:"nested_virt" ~default:false require_hvm + in + let vpmu = get_platform_key ~key:"vpmu" ~default:false (fun _ -> Ok ()) in info "VM = %s; Creating %s%s%s%s%s" (Uuidx.to_string uuid) (if hvm then "HVM" else "PV")