Version in base suite: 4.20.0+68-g35cb38b222-1 Base version: xen_4.20.0+68-g35cb38b222-1 Target version: xen_4.20.2+7-g1badcf5035-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/x/xen/xen_4.20.0+68-g35cb38b222-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/x/xen/xen_4.20.2+7-g1badcf5035-0+deb13u1.dsc .gitlab-ci.yml | 2 Config.mk | 2 INSTALL | 2 MAINTAINERS | 1 automation/build/Makefile | 4 automation/build/alpine/3.18-arm64v8.dockerfile | 1 automation/eclair_analysis/ECLAIR/action.helpers | 10 automation/eclair_analysis/ECLAIR/action.settings | 30 + automation/eclair_analysis/ECLAIR/analysis.ecl | 2 automation/eclair_analysis/ECLAIR/analyze.sh | 2 automation/gitlab-ci/analyze.yaml | 1 automation/gitlab-ci/build.yaml | 42 -- automation/gitlab-ci/test.yaml | 172 +++++++++ automation/scripts/build | 5 automation/scripts/console.exp | 40 +- automation/scripts/qemu-alpine-x86_64.sh | 34 - automation/scripts/qemu-smoke-dom0-arm32.sh | 7 automation/scripts/qemu-smoke-dom0-arm64.sh | 32 - automation/scripts/qemu-smoke-dom0less-arm32.sh | 5 automation/scripts/qemu-smoke-dom0less-arm64.sh | 22 - automation/scripts/qemu-xtf-dom0less-arm64.sh | 1 automation/scripts/qubes-x86-64.sh | 169 +++++---- automation/scripts/run-tools-tests | 47 ++ automation/scripts/xilinx-smoke-dom0-x86_64.sh | 67 +-- automation/scripts/xilinx-smoke-dom0less-arm64.sh | 39 -- automation/tests-artifacts/Makefile | 4 automation/tests-artifacts/alpine/3.18-arm64v8.dockerfile | 66 --- automation/tests-artifacts/alpine/3.18.dockerfile | 67 --- automation/tests-artifacts/kernel/5.19-arm64v8.dockerfile | 37 -- automation/tests-artifacts/kernel/6.1.19.dockerfile | 41 -- debian/changelog | 29 + debian/patches/prefix-abiname/config-prefix.diff | 2 debian/salsa-ci.yml | 46 +- docs/man/xl.cfg.5.pod.in | 2 docs/misc/xen-command-line.pandoc | 13 tools/firmware/hvmloader/smbios.c | 178 +++++---- tools/firmware/hvmloader/smbios_types.h | 32 - tools/firmware/hvmloader/util.h | 3 tools/include/xen-tools/common-macros.h | 8 tools/include/xenctrl.h | 2 tools/libacpi/mk_dsdt.c | 9 tools/libs/ctrl/xc_physdev.c | 6 tools/libs/ctrl/xc_pm.c | 22 - tools/libs/light/libxl_cpuid.c | 1 tools/libs/light/libxl_pci.c | 9 tools/libs/light/libxl_x86.c | 24 - tools/misc/mktarball | 17 tools/misc/xen-cpuid.c | 1 tools/misc/xenpm.c | 48 +- tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile | 2 tools/tests/x86_emulator/Makefile | 5 tools/tests/x86_emulator/x86-emulate.h | 6 tools/xentrace/xenalyze.c | 8 tools/xl/xl.c | 2 xen/Kconfig | 2 xen/Makefile | 3 xen/arch/arm/include/asm/pci.h | 3 xen/arch/arm/p2m.c | 32 + xen/arch/x86/Kconfig | 5 xen/arch/x86/Makefile | 10 xen/arch/x86/acpi/boot.c | 2 xen/arch/x86/acpi/cpu_idle.c | 160 ++++---- xen/arch/x86/acpi/cpufreq/hwp.c | 2 xen/arch/x86/acpi/power.c | 3 xen/arch/x86/acpi/wakeup_prot.S | 2 xen/arch/x86/alternative.c | 68 +++ xen/arch/x86/apic.c | 3 xen/arch/x86/arch.mk | 3 xen/arch/x86/bhb-thunk.S | 19 - xen/arch/x86/boot/edd.S | 12 xen/arch/x86/boot/mkelf32.c | 18 xen/arch/x86/clear_page.S | 4 xen/arch/x86/copy_page.S | 4 xen/arch/x86/cpu-policy.c | 122 +++--- xen/arch/x86/cpu/common.c | 11 xen/arch/x86/cpu/intel.c | 33 + xen/arch/x86/cpu/mcheck/mce.c | 2 xen/arch/x86/cpu/mcheck/mce_intel.c | 20 - xen/arch/x86/cpu/microcode/amd-patch-digests.c | 144 +++++++ xen/arch/x86/cpu/microcode/amd.c | 164 ++++++++ xen/arch/x86/cpu/microcode/core.c | 16 xen/arch/x86/cpu/microcode/private.h | 2 xen/arch/x86/cpu/mwait-idle.c | 220 +++++++++++- xen/arch/x86/efi/check.c | 3 xen/arch/x86/extable.c | 11 xen/arch/x86/guest/xen/Makefile | 2 xen/arch/x86/guest/xen/hypercall.S | 50 ++ xen/arch/x86/guest/xen/hypercall_page.S | 76 ---- xen/arch/x86/guest/xen/xen.c | 48 ++ xen/arch/x86/hpet.c | 115 ++++-- xen/arch/x86/hvm/hvm.c | 12 xen/arch/x86/hvm/ioreq.c | 2 xen/arch/x86/hvm/svm/asid.c | 5 xen/arch/x86/hvm/svm/entry.S | 2 xen/arch/x86/hvm/viridian/synic.c | 4 xen/arch/x86/hvm/viridian/time.c | 8 xen/arch/x86/hvm/viridian/viridian.c | 27 - xen/arch/x86/hvm/vmx/vmcs.c | 63 --- xen/arch/x86/hvm/vmx/vmx.c | 2 xen/arch/x86/include/asm/alternative-asm.h | 2 xen/arch/x86/include/asm/alternative.h | 13 xen/arch/x86/include/asm/asm-defns.h | 6 xen/arch/x86/include/asm/cpufeature.h | 7 xen/arch/x86/include/asm/cpufeatures.h | 5 xen/arch/x86/include/asm/guest/xen-hcall.h | 24 - xen/arch/x86/include/asm/hardirq.h | 21 - xen/arch/x86/include/asm/hpet.h | 1 xen/arch/x86/include/asm/hvm/viridian.h | 1 xen/arch/x86/include/asm/hvm/vmx/vmcs.h | 1 xen/arch/x86/include/asm/hvm/vmx/vmx.h | 1 xen/arch/x86/include/asm/irq-vectors.h | 3 xen/arch/x86/include/asm/irq.h | 1 xen/arch/x86/include/asm/msr-index.h | 3 xen/arch/x86/include/asm/mwait.h | 3 xen/arch/x86/include/asm/pci.h | 13 xen/arch/x86/include/asm/processor.h | 20 - xen/arch/x86/include/asm/smp.h | 1 xen/arch/x86/include/asm/softirq.h | 48 ++ xen/arch/x86/include/asm/spec_ctrl.h | 39 +- xen/arch/x86/indirect-thunk.S | 38 ++ xen/arch/x86/irq.c | 17 xen/arch/x86/mm.c | 15 xen/arch/x86/mm/p2m-ept.c | 65 +++ xen/arch/x86/pci.c | 50 ++ xen/arch/x86/pv/emul-priv-op.c | 11 xen/arch/x86/pv/gpr_switch.S | 4 xen/arch/x86/setup.c | 8 xen/arch/x86/smpboot.c | 29 + xen/arch/x86/spec_ctrl.c | 210 ++++++++++- xen/arch/x86/time.c | 2 xen/arch/x86/traps.c | 2 xen/arch/x86/x86_64/compat/entry.S | 6 xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/mmconfig-shared.c | 3 xen/arch/x86/x86_emulate/0fc7.c | 2 xen/arch/x86/x86_emulate/blk.c | 36 + xen/arch/x86/x86_emulate/fpu.c | 18 xen/arch/x86/x86_emulate/private.h | 7 xen/arch/x86/x86_emulate/x86_emulate.c | 124 ++---- xen/arch/x86/xen.lds.S | 3 xen/common/Kconfig | 11 xen/common/efi/boot.c | 20 - xen/common/sched/arinc653.c | 40 +- xen/common/sched/credit2.c | 28 + xen/common/softirq.c | 8 xen/drivers/acpi/pmstat.c | 8 xen/drivers/cpufreq/cpufreq.c | 3 xen/drivers/cpufreq/utility.c | 3 xen/drivers/passthrough/amd/iommu_init.c | 11 xen/drivers/passthrough/amd/iommu_intr.c | 7 xen/drivers/passthrough/pci.c | 1 xen/drivers/passthrough/vtd/iommu.c | 11 xen/drivers/vpci/header.c | 11 xen/drivers/vpci/msix.c | 60 ++- xen/include/public/arch-x86/cpufeatureset.h | 9 xen/include/public/sysctl.h | 15 xen/include/xen/cpuidle.h | 2 xen/include/xen/irq_cpustat.h | 1 xen/include/xen/lib.h | 3 xen/include/xen/lib/x86/cpu-policy.h | 10 xen/include/xen/softirq.h | 16 xen/include/xen/xen.lds.h | 1 xen/lib/x86-generic-hweightl.c | 4 xen/lib/x86/cpuid.c | 2 xen/tools/gen-cpuid.py | 21 - xen/tools/symbols.c | 10 166 files changed, 2761 insertions(+), 1368 deletions(-) gpgv: Signature made Tue Dec 2 12:01:38 2025 UTC gpgv: using RSA key B6E62F3D12AC38495C0DA90510C293B6C37C4E36 gpgv: Note: signatures using the SHA1 algorithm are rejected gpgv: Can't check signature: Bad public key dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp7qapfdzb/xen_4.20.2+7-g1badcf5035-0+deb13u1.dsc: no acceptable signature found diff -Nru xen-4.20.0+68-g35cb38b222/.gitlab-ci.yml xen-4.20.2+7-g1badcf5035/.gitlab-ci.yml --- xen-4.20.0+68-g35cb38b222/.gitlab-ci.yml 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/.gitlab-ci.yml 2025-11-25 08:37:47.000000000 +0000 @@ -1,5 +1,7 @@ variables: XEN_REGISTRY: registry.gitlab.com/xen-project/xen + SELECTED_JOBS_ONLY: + description: "Regex to select only some jobs, must be enclosed with /. For example /job1|job2/" workflow: rules: diff -Nru xen-4.20.0+68-g35cb38b222/Config.mk xen-4.20.2+7-g1badcf5035/Config.mk --- xen-4.20.0+68-g35cb38b222/Config.mk 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/Config.mk 2025-11-25 08:37:47.000000000 +0000 @@ -229,7 +229,7 @@ OVMF_UPSTREAM_REVISION ?= ba91d0292e593df8528b66f99c1b0b14fadc8e16 QEMU_UPSTREAM_URL ?= https://xenbits.xen.org/git-http/qemu-xen.git -QEMU_UPSTREAM_REVISION ?= qemu-xen-4.20.0 +QEMU_UPSTREAM_REVISION ?= qemu-xen-4.20.1 MINIOS_UPSTREAM_URL ?= https://xenbits.xen.org/git-http/mini-os.git MINIOS_UPSTREAM_REVISION ?= xen-RELEASE-4.20.0 diff -Nru xen-4.20.0+68-g35cb38b222/INSTALL xen-4.20.2+7-g1badcf5035/INSTALL --- xen-4.20.0+68-g35cb38b222/INSTALL 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/INSTALL 2025-11-25 08:37:47.000000000 +0000 @@ -23,7 +23,7 @@ ============== Xen itself is configured via a `kconfig' system borrowed from Linux. -See docs/misc/kconfig.txt. +See https://www.kernel.org/doc/html/v5.4/kbuild/. Note that unlike with Linux, and contrary to that document, you cannot look at Kconfig files, or the default or generated config files etc., diff -Nru xen-4.20.0+68-g35cb38b222/MAINTAINERS xen-4.20.2+7-g1badcf5035/MAINTAINERS --- xen-4.20.0+68-g35cb38b222/MAINTAINERS 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/MAINTAINERS 2025-11-25 08:37:47.000000000 +0000 @@ -282,7 +282,6 @@ KCONFIG M: Doug Goldstein S: Supported -F: docs/misc/kconfig{,-language}.txt F: xen/tools/kconfig/ KDD DEBUGGER diff -Nru xen-4.20.0+68-g35cb38b222/automation/build/Makefile xen-4.20.2+7-g1badcf5035/automation/build/Makefile --- xen-4.20.0+68-g35cb38b222/automation/build/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/build/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -31,8 +31,8 @@ define CLEAN_RULE .PHONY: clean-$(1) clean-$(1): - if [ -n "$$$$(docker image ls -q $(REGISTRY)/$(subst /,:,$(1)))" ]; then \ - docker image rm $(REGISTRY)/$(subst /,:,$(1)); \ + if [ -n "$$$$($(DOCKER_CMD) image ls -q $(REGISTRY)/$(subst /,:,$(1)))" ]; then \ + $(DOCKER_CMD) image rm $(REGISTRY)/$(subst /,:,$(1)); \ fi endef diff -Nru xen-4.20.0+68-g35cb38b222/automation/build/alpine/3.18-arm64v8.dockerfile xen-4.20.2+7-g1badcf5035/automation/build/alpine/3.18-arm64v8.dockerfile --- xen-4.20.0+68-g35cb38b222/automation/build/alpine/3.18-arm64v8.dockerfile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/build/alpine/3.18-arm64v8.dockerfile 2025-11-25 08:37:47.000000000 +0000 @@ -48,3 +48,4 @@ # qubes test deps openssh-client \ fakeroot \ + expect \ diff -Nru xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/action.helpers xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/action.helpers --- xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/action.helpers 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/action.helpers 2025-11-25 08:37:47.000000000 +0000 @@ -58,7 +58,7 @@ ;; esac - currentDbReportsUrl="${eclairReportUrlPrefix}/fs${jobDir}/PROJECT.ecd;/by_service.html#service&kind" + currentDbReportsUrl="${eclairResultsUrl}/fs${jobDir}/PROJECT.ecd;/by_service.html#service&kind" if [ -z "${newReports}" ]; then fixedMsg="No fixed reports as there is no baseline" unfixedMsg="Unfixed reports: ${unfixedReports}" @@ -69,11 +69,11 @@ unfixedMsg="Unfixed reports: ${unfixedReports} [new: ${newReports}]" case "${event}" in pull_request | auto_pull_request) - referenceDbReportsUrl="${eclairReportUrlPrefix}/fs${jobDir}/base/PROJECT.ecd;/by_service.html#service&kind" + referenceDbReportsUrl="${eclairResultsUrl}/fs${jobDir}/base/PROJECT.ecd;/by_service.html#service&kind" reference_kind=base ;; push) - referenceDbReportsUrl="${eclairReportUrlPrefix}/fs${jobDir}/prev/PROJECT.ecd;/by_service.html#service&kind" + referenceDbReportsUrl="${eclairResultsUrl}/fs${jobDir}/prev/PROJECT.ecd;/by_service.html#service&kind" reference_kind=previous ;; *) @@ -92,7 +92,7 @@ ${fixedMsg}${eol} ${unfixedMsg} ${eol} - +

${jobHeadline}

Browse analysis summary @@ -106,7 +106,7 @@ fi cat <"${summaryTxt}" - + Analysis Summary diff -Nru xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/action.settings xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/action.settings --- xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/action.settings 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/action.settings 2025-11-25 08:37:47.000000000 +0000 @@ -14,9 +14,6 @@ # Customized autoPRBranch="${AUTO_PR_BRANCH:-}" -# Customized -artifactsRoot=/var/local/eclair - case "${ci}" in github) # To be customized @@ -166,16 +163,35 @@ ECLAIR_BIN_DIR=/opt/bugseng/eclair/bin/ -artifactsDir="${artifactsRoot}/xen-project.ecdf/${repository}/ECLAIR_${ANALYSIS_KIND}" +# Artifacts URL served by the eclair_report server +if [ -z "${ECLAIR_ECDF_DIR}" ] +then + echo "WARNING: No ecdf dir supplied, using default" +fi +artifactsEcdfDir="${ECLAIR_ECDF_DIR:-/var/local/eclair/xen-project.ecdf}" +artifactsDir="${artifactsEcdfDir}/${repository}/ECLAIR_${ANALYSIS_KIND}" subDir="${subDir}${variantSubDir}" jobHeadline="${jobHeadline}${variantHeadline}" -# Customized -eclairReportUrlPrefix=https://saas.eclairit.com:3787 +# Remote eclair_report hosting server +if [ -z "${ECLAIR_REPORT_HOST}" ] +then + echo "WARNING: No eclair_report host supplied, using default" +fi + +# URL to browse eclair reports +if [ -z "${ECLAIR_ANALYSIS_RESULTS}" ] +then + echo "WARNING: No URL to browse analysis results is set, using default" +fi + +eclairReportHost="${ECLAIR_REPORT_HOST:-saas.eclairit.com:3787}" +eclairReportUrlPrefix="https://${eclairReportHost}" +eclairResultsUrl="${ECLAIR_ANALYSIS_RESULTS:-${eclairReportUrlPrefix}}" jobDir="${artifactsDir}/${subDir}/${jobId}" updateLog="${analysisOutputDir}/update.log" cleanRegressionsLog="${analysisOutputDir}/clean_regressions.log" commentLog="${analysisOutputDir}/comment.json" -indexHtmlUrl="${eclairReportUrlPrefix}/fs${jobDir}/index.html" +indexHtmlUrl="${eclairResultsUrl}/fs${jobDir}/index.html" summaryTxt="${analysisOutputDir}/summary.txt" diff -Nru xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/analysis.ecl xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/analysis.ecl --- xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/analysis.ecl 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/analysis.ecl 2025-11-25 08:37:47.000000000 +0000 @@ -10,8 +10,6 @@ # strings_map("scheduled-analysis",500,"","^.*$",0) # map_strings("scheduled-analysis",analysis_kind) --verbose - -enable=B.REPORT.ECB -config=B.REPORT.ECB,output=join_paths(data_dir,"FRAME.@FRAME@.ecb") -config=B.REPORT.ECB,preprocessed=show diff -Nru xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/analyze.sh xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/analyze.sh --- xen-4.20.0+68-g35cb38b222/automation/eclair_analysis/ECLAIR/analyze.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/eclair_analysis/ECLAIR/analyze.sh 2025-11-25 08:37:47.000000000 +0000 @@ -91,11 +91,13 @@ sort | xargs cat | "${ECLAIR_BIN_DIR}eclair_report" \ "-create_db='${PROJECT_ECD}'" \ + -quiet \ -load=/dev/stdin > "${ECLAIR_REPORT_LOG}" 2>&1 # Create the Jenkins reports file. "${ECLAIR_BIN_DIR}eclair_report" \ "-db='${PROJECT_ECD}'" \ + -quiet \ "-eval_file='${SCRIPT_DIR}/report.ecl'" \ >> "${ECLAIR_REPORT_LOG}" 2>&1 diff -Nru xen-4.20.0+68-g35cb38b222/automation/gitlab-ci/analyze.yaml xen-4.20.2+7-g1badcf5035/automation/gitlab-ci/analyze.yaml --- xen-4.20.0+68-g35cb38b222/automation/gitlab-ci/analyze.yaml 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/gitlab-ci/analyze.yaml 2025-11-25 08:37:47.000000000 +0000 @@ -8,6 +8,7 @@ ENABLE_ECLAIR_BOT: "n" AUTO_PR_BRANCH: "staging" AUTO_PR_REPOSITORY: "xen-project/xen" + ECLAIR_ANALYSIS_RESULTS: "https://eclair-analysis-logs.xenproject.org" script: - ./automation/scripts/eclair 2>&1 | tee "${LOGFILE}" artifacts: diff -Nru xen-4.20.0+68-g35cb38b222/automation/gitlab-ci/build.yaml xen-4.20.2+7-g1badcf5035/automation/gitlab-ci/build.yaml --- xen-4.20.0+68-g35cb38b222/automation/gitlab-ci/build.yaml 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/gitlab-ci/build.yaml 2025-11-25 08:37:47.000000000 +0000 @@ -12,6 +12,12 @@ - '*/*.log' when: always needs: [] + rules: + - if: $SELECTED_JOBS_ONLY && $CI_JOB_NAME =~ $SELECTED_JOBS_ONLY + when: always + - if: $SELECTED_JOBS_ONLY + when: never + - when: on_success .gcc-tmpl: variables: &gcc @@ -258,28 +264,6 @@ # Arm test artifacts -alpine-3.18-arm64-rootfs-export: - extends: .test-jobs-artifact-common - image: registry.gitlab.com/xen-project/xen/tests-artifacts/alpine:3.18-arm64v8 - script: - - mkdir binaries && cp /initrd.tar.gz binaries/initrd.tar.gz - artifacts: - paths: - - binaries/initrd.tar.gz - tags: - - arm64 - -kernel-5.19-arm64-export: - extends: .test-jobs-artifact-common - image: registry.gitlab.com/xen-project/xen/tests-artifacts/kernel:5.19-arm64v8 - script: - - mkdir binaries && cp /Image binaries/Image - artifacts: - paths: - - binaries/Image - tags: - - arm64 - qemu-system-aarch64-6.0.0-arm64-export: extends: .test-jobs-artifact-common image: registry.gitlab.com/xen-project/xen/tests-artifacts/qemu-system-aarch64:6.0.0-arm64v8 @@ -302,19 +286,6 @@ tags: - arm64 -# x86_64 test artifacts - -kernel-6.1.19-export: - extends: .test-jobs-artifact-common - image: registry.gitlab.com/xen-project/xen/tests-artifacts/kernel:6.1.19 - script: - - mkdir binaries && cp /bzImage binaries/bzImage - artifacts: - paths: - - binaries/bzImage - tags: - - x86_64 - # Jobs below this line # Build jobs needed for tests @@ -335,6 +306,7 @@ CONFIG_ARGO=y CONFIG_UBSAN=y CONFIG_UBSAN_FATAL=y + CONFIG_XHCI=y debian-12-x86_64-gcc-debug: extends: .gcc-x86-64-build-debug diff -Nru xen-4.20.0+68-g35cb38b222/automation/gitlab-ci/test.yaml xen-4.20.2+7-g1badcf5035/automation/gitlab-ci/test.yaml --- xen-4.20.0+68-g35cb38b222/automation/gitlab-ci/test.yaml 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/gitlab-ci/test.yaml 2025-11-25 08:37:47.000000000 +0000 @@ -1,19 +1,33 @@ .test-jobs-common: stage: test image: ${XEN_REGISTRY}/${CONTAINER} + rules: + - if: $SELECTED_JOBS_ONLY && $CI_JOB_NAME =~ $SELECTED_JOBS_ONLY + - if: $SELECTED_JOBS_ONLY + when: never + - when: on_success .arm64-test-needs: &arm64-test-needs - - alpine-3.18-arm64-rootfs-export - - kernel-5.19-arm64-export + - project: xen-project/hardware/test-artifacts + job: linux-6.6.86-arm64 + ref: master + - project: xen-project/hardware/test-artifacts + job: alpine-3.18-arm64-rootfs + ref: master - qemu-system-aarch64-6.0.0-arm64-export .arm32-test-needs: &arm32-test-needs - qemu-system-aarch64-6.0.0-arm32-export .x86-64-test-needs: &x86-64-test-needs - - kernel-6.1.19-export - project: xen-project/hardware/test-artifacts - job: x86_64-rootfs-alpine-3.18 + job: linux-6.6.56-x86_64 + ref: master + - project: xen-project/hardware/test-artifacts + job: alpine-3.18-x86_64-rootfs + ref: master + - project: xen-project/hardware/test-artifacts + job: microcode-x86 ref: master .qemu-arm64: @@ -99,6 +113,9 @@ - '*.dtb' when: always rules: + - if: $SELECTED_JOBS_ONLY && $CI_JOB_NAME =~ $SELECTED_JOBS_ONLY + - if: $SELECTED_JOBS_ONLY + when: never - if: $XILINX_JOBS == "true" && $CI_COMMIT_REF_PROTECTED == "true" tags: - xilinx @@ -117,6 +134,9 @@ - '*.log' when: always rules: + - if: $SELECTED_JOBS_ONLY && $CI_JOB_NAME =~ $SELECTED_JOBS_ONLY + - if: $SELECTED_JOBS_ONLY + when: never - if: $XILINX_JOBS == "true" && $CI_COMMIT_REF_PROTECTED == "true" tags: - xilinx @@ -130,16 +150,31 @@ PCIDEV: "03:00.0" PCIDEV_INTR: "MSI-X" CONSOLE_OPTS: "console=com1 com1=115200,8n1" + SUT_ADDR: test-2.testnet artifacts: paths: - smoke.serial - '*.log' when: always rules: + - if: $SELECTED_JOBS_ONLY && $CI_JOB_NAME =~ $SELECTED_JOBS_ONLY + - if: $SELECTED_JOBS_ONLY + when: never - if: $QUBES_JOBS == "true" && $CI_COMMIT_REF_PROTECTED == "true" tags: - qubes-hw2 +.kbl-x86-64: + # it's really similar to the ADL one + extends: .adl-x86-64 + variables: + PCIDEV: "00:1f.6" + PCIDEV_INTR: "MSI" + CONSOLE_OPTS: "console=com1 com1=115200,8n1,pci,msi" + SUT_ADDR: test-3.testnet + tags: + - qubes-hw3 + .zen2-x86-64: # it's really similar to the above extends: .adl-x86-64 @@ -158,6 +193,7 @@ PCIDEV: "01:00.0" PCIDEV_INTR: "MSI-X" CONSOLE_OPTS: "console=com1 com1=115200,8n1,pci,msi" + SUT_ADDR: test-11.testnet tags: - qubes-hw11 @@ -209,13 +245,13 @@ needs: - alpine-3.18-gcc-debug - project: xen-project/hardware/test-artifacts - job: x86_64-kernel-linux-6.6.56 + job: linux-6.6.56-x86_64 ref: master - project: xen-project/hardware/test-artifacts - job: x86_64-rootfs-alpine-3.18 + job: alpine-3.18-x86_64-rootfs ref: master - project: xen-project/hardware/test-artifacts - job: x86_64-argo-linux-6.6.56 + job: microcode-x86 ref: master adl-smoke-x86-64-gcc-debug: @@ -274,6 +310,106 @@ - *x86-64-test-needs - alpine-3.18-gcc-debug +adl-tools-tests-pv-x86-64-gcc-debug: + extends: .adl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh tools-tests-pv 2>&1 | tee ${LOGFILE} + artifacts: + reports: + junit: tests-junit.xml + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +adl-tools-tests-pvh-x86-64-gcc-debug: + extends: .adl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh tools-tests-pvh 2>&1 | tee ${LOGFILE} + artifacts: + reports: + junit: tests-junit.xml + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-smoke-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-smoke-x86-64-dom0pvh-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh dom0pvh 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-smoke-x86-64-dom0pvh-hvm-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh dom0pvh-hvm 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-suspend-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh s3 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-pci-pv-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh pci-pv 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-pci-hvm-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh pci-hvm 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-pvshim-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh pvshim 2>&1 | tee ${LOGFILE} + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-tools-tests-pv-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh tools-tests-pv 2>&1 | tee ${LOGFILE} + artifacts: + reports: + junit: tests-junit.xml + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +kbl-tools-tests-pvh-x86-64-gcc-debug: + extends: .kbl-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh tools-tests-pvh 2>&1 | tee ${LOGFILE} + artifacts: + reports: + junit: tests-junit.xml + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + zen2-smoke-x86-64-gcc-debug: extends: .zen2-x86-64 script: @@ -329,6 +465,28 @@ needs: - *x86-64-test-needs - alpine-3.18-gcc-debug + +zen3p-tools-tests-pv-x86-64-gcc-debug: + extends: .zen3p-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh tools-tests-pv 2>&1 | tee ${LOGFILE} + artifacts: + reports: + junit: tests-junit.xml + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug + +zen3p-tools-tests-pvh-x86-64-gcc-debug: + extends: .zen3p-x86-64 + script: + - ./automation/scripts/qubes-x86-64.sh tools-tests-pvh 2>&1 | tee ${LOGFILE} + artifacts: + reports: + junit: tests-junit.xml + needs: + - *x86-64-test-needs + - alpine-3.18-gcc-debug qemu-smoke-dom0-arm64-gcc: extends: .qemu-arm64 diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/build xen-4.20.2+7-g1badcf5035/automation/scripts/build --- xen-4.20.0+68-g35cb38b222/automation/scripts/build 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/build 2025-11-25 08:37:47.000000000 +0000 @@ -67,7 +67,7 @@ collect_xen_artefacts else # Full build. Figure out our ./configure options - cfgargs=() + cfgargs=("--prefix=/usr") cfgargs+=("--enable-docs") # booleans for which compiler is in use @@ -108,6 +108,7 @@ # Note: Some smoke tests depending on finding binaries/xen on a full build # even though dist/ contains everything, while some containers don't even # build Xen - cp -r dist binaries/ + (cd dist/install; find | cpio -R 0:0 -o -H newc | gzip) > binaries/xen-tools.cpio.gz + cp -r tools/tests binaries/ collect_xen_artefacts fi diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/console.exp xen-4.20.2+7-g1badcf5035/automation/scripts/console.exp --- xen-4.20.0+68-g35cb38b222/automation/scripts/console.exp 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/console.exp 2025-11-25 08:37:47.000000000 +0000 @@ -1,4 +1,21 @@ #!/usr/bin/env expect +# +# Variables used by this script: +# - TEST_TIMEOUT: timeout between each *_MSG match +# - TEST_TIMEOUT_OVERRIDE: when set, overrides TEST_TIMEOUT +# - TEST_LOG: save console log to this file +# - TEST_CMD: commands that prints test system console output to stdout - in +# qemu tests that's usually qemu itself (with -serial stdio), in hardware +# tests that's a command to read serial console +# - UBOOT_CMD (optional): command to enter at u-boot prompt +# - BOOT_MSG (optional): initial Xen message to wait for (aka sign-of-life) +# - SUSPEND_MSG (optional): message signaling system is going to sleep, it's +# trigger for WAKEUP_CMD (see below) +# - WAKEUP_CMD (optional): command to execute to wakeup the system 30s after +# seeing SUSPEND_MSG +# - LOG_MSG (optional): final console message to wait for +# - PASSED: message to look for to consider test a success; if LOG_MSG is set, +# both LOG_MSG and PASSED must appear (in any order) for test to succeed if {[info exists env(TEST_TIMEOUT_OVERRIDE)]} { set timeout $env(TEST_TIMEOUT_OVERRIDE) @@ -28,21 +45,34 @@ send "$env(UBOOT_CMD)\r" } +if {[info exists env(BOOT_MSG)]} { + expect -re "$env(BOOT_MSG)" +} + +if {[info exists env(WAKEUP_CMD)]} { + expect -re "$env(SUSPEND_MSG)" + + # keep it suspended a bit, then wakeup + sleep 30 + + system "$env(WAKEUP_CMD)" +} + if {[info exists env(LOG_MSG)]} { expect { - "$env(PASSED)" { - expect "$env(LOG_MSG)" + -notransfer -re "$env(PASSED)" { + expect -re "$env(LOG_MSG)" exit 0 } - "$env(LOG_MSG)" { - expect "$env(PASSED)" + -notransfer -re "$env(LOG_MSG)" { + expect -re "$env(PASSED)" exit 0 } } } expect { - "$env(PASSED)" { + -re "$env(PASSED)" { exit 0 } } diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-alpine-x86_64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-alpine-x86_64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-alpine-x86_64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-alpine-x86_64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -25,44 +25,39 @@ chmod +x initrd/init # DomU rootfs cd initrd -find . | cpio --create --format='newc' | gzip > ../initrd.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip > ../domU-rootfs.cpio.gz cd .. -# initrd.tar.gz is Dom0 rootfs +# Dom0 rootfs +cp rootfs.cpio.gz dom0-rootfs.cpio.gz +cat xen-tools.cpio.gz >> dom0-rootfs.cpio.gz + +# test-local configuration mkdir -p rootfs cd rootfs -tar xvzf ../initrd.tar.gz -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run -cp -ar ../dist/install/* . -mv ../initrd.cpio.gz ./root +mkdir -p root etc/local.d +mv ../domU-rootfs.cpio.gz ./root cp ../bzImage ./root -echo "name=\"test\" +echo "name=\"domU\" memory=512 vcpus=1 kernel=\"/root/bzImage\" -ramdisk=\"/root/initrd.cpio.gz\" +ramdisk=\"/root/domU-rootfs.cpio.gz\" extra=\"console=hvc0 root=/dev/ram0 rdinit=/bin/sh\" -" > root/test.cfg +" > root/domU.cfg echo "#!/bin/bash set -x -export LD_LIBRARY_PATH=/usr/local/lib bash /etc/init.d/xencommons start xl list -xl create -c /root/test.cfg +xl -vvv create -c /root/domU.cfg " > etc/local.d/xen.start chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -# rebuild Dom0 rootfs -find . |cpio -H newc -o|gzip > ../xen-rootfs.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip >> ../dom0-rootfs.cpio.gz cd ../.. cat >> binaries/pxelinux.0 << EOF @@ -70,7 +65,7 @@ kernel xen console=com1 console_timestamps=boot module bzImage console=hvc0 -module xen-rootfs.cpio.gz +module dom0-rootfs.cpio.gz boot EOF @@ -85,6 +80,7 @@ -netdev user,id=n0,tftp=binaries,bootfile=/pxelinux.0" export TEST_LOG="smoke.serial" +export BOOT_MSG="Latest ChangeSet: " export LOG_MSG="Domain-0" export PASSED="BusyBox" diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0-arm32.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0-arm32.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0-arm32.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0-arm32.sh 2025-11-25 08:37:47.000000000 +0000 @@ -21,7 +21,7 @@ xl list -xl create -c /root/test.cfg +xl -vvv create -c /root/test.cfg " > ./root/xen.start echo "bash /root/xen.start" >> ./etc/init.d/xen-watchdog @@ -30,13 +30,13 @@ mkdir rootfs cd rootfs tar xvzf ../initrd.tar.gz -find . | cpio -H newc -o | gzip > ../root/initrd.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip > ../root/initrd.cpio.gz cd .. rm -rf rootfs rm initrd.tar.gz cp ../zImage ./root -find . | cpio -H newc -o | gzip > ../initrd.gz +find . | cpio -R 0:0 -H newc -o | gzip > ../initrd.gz cd .. # XXX QEMU looks for "efi-virtio.rom" even if it is unneeded @@ -92,6 +92,7 @@ export UBOOT_CMD="virtio scan; dhcp; tftpb 0x40000000 boot.scr; source 0x40000000" export TEST_LOG="${serial_log}" +export BOOT_MSG="Latest ChangeSet: " export LOG_MSG="Domain-0" export PASSED="/ #" diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0-arm64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0-arm64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0-arm64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0-arm64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -24,40 +24,37 @@ /bin/sh" > initrd/init chmod +x initrd/init cd initrd -find . | cpio --create --format='newc' | gzip > ../initrd.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip > ../domU-rootfs.cpio.gz cd .. +# Dom0 rootfs +cp rootfs.cpio.gz dom0-rootfs.cpio.gz +cat xen-tools.cpio.gz >> dom0-rootfs.cpio.gz + +# test-local configuration mkdir -p rootfs cd rootfs -tar xvzf ../initrd.tar.gz -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run -cp -ar ../dist/install/* . -mv ../initrd.cpio.gz ./root +mkdir -p etc/local.d root +mv ../domU-rootfs.cpio.gz ./root cp ../Image ./root -echo "name=\"test\" +echo "name=\"domU\" memory=512 vcpus=1 kernel=\"/root/Image\" -ramdisk=\"/root/initrd.cpio.gz\" +ramdisk=\"/root/domU-rootfs.cpio.gz\" extra=\"console=hvc0 root=/dev/ram0 rdinit=/bin/sh\" -" > root/test.cfg +" > root/domU.cfg echo "#!/bin/bash -export LD_LIBRARY_PATH=/usr/local/lib bash /etc/init.d/xencommons start xl list -xl create -c /root/test.cfg +xl -vvv create -c /root/domU.cfg " > etc/local.d/xen.start chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -find . |cpio -H newc -o|gzip > ../xen-rootfs.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip >> ../dom0-rootfs.cpio.gz cd ../.. # XXX QEMU looks for "efi-virtio.rom" even if it is unneeded @@ -78,7 +75,7 @@ DEVICE_TREE="virt-gicv2.dtb" XEN="xen" DOM0_KERNEL="Image" -DOM0_RAMDISK="xen-rootfs.cpio.gz" +DOM0_RAMDISK="dom0-rootfs.cpio.gz" XEN_CMD="console=dtuart dom0_mem=1024M console_timestamps=boot" NUM_DOMUS=0 @@ -104,6 +101,7 @@ -bios /usr/lib/u-boot/qemu_arm64/u-boot.bin" export UBOOT_CMD="virtio scan; dhcp; tftpb 0x40000000 boot.scr; source 0x40000000" +export BOOT_MSG="Latest ChangeSet: " export TEST_LOG="smoke.serial" export LOG_MSG="Domain-0" export PASSED="BusyBox" diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0less-arm32.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0less-arm32.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0less-arm32.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0less-arm32.sh 2025-11-25 08:37:47.000000000 +0000 @@ -11,7 +11,7 @@ cd binaries # Use the kernel from Debian -curl --fail --silent --show-error --location --output vmlinuz https://deb.debian.org/debian/dists/bullseye/main/installer-armhf/current/images/netboot/vmlinuz +curl --fail --silent --show-error --location --output vmlinuz https://deb.debian.org/debian/dists/bookworm/main/installer-armhf/current/images/netboot/vmlinuz # Use a tiny initrd based on busybox from Alpine Linux curl --fail --silent --show-error --location --output initrd.tar.gz https://dl-cdn.alpinelinux.org/alpine/v3.15/releases/armhf/alpine-minirootfs-3.15.1-armhf.tar.gz @@ -75,7 +75,7 @@ ${domU_check} /bin/sh" > init chmod +x init -find . | cpio -H newc -o | gzip > ../initrd.gz +find . | cpio -R 0:0 -H newc -o | gzip > ../initrd.gz cd .. # XXX QEMU looks for "efi-virtio.rom" even if it is unneeded @@ -144,6 +144,7 @@ -bios /usr/lib/u-boot/qemu_arm/u-boot.bin" export UBOOT_CMD="virtio scan; dhcp; tftpb 0x40000000 boot.scr; source 0x40000000" +export BOOT_MSG="Latest ChangeSet: " export TEST_LOG="${serial_log}" export LOG_MSG="${dom0_prompt}" export PASSED="${passed}" diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0less-arm64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0less-arm64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-smoke-dom0less-arm64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-smoke-dom0less-arm64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -108,26 +108,23 @@ /bin/sh" > initrd/init chmod +x initrd/init cd initrd -find . | cpio --create --format='newc' | gzip > ../binaries/initrd +find . | cpio -R 0:0 -o -H newc | gzip > ../binaries/initrd cd .. -# DOM0 rootfs +# Dom0 rootfs +cp binaries/rootfs.cpio.gz binaries/dom0-rootfs.cpio.gz +cat binaries/xen-tools.cpio.gz >> binaries/dom0-rootfs.cpio.gz + +# test-local configuration mkdir -p rootfs cd rootfs -tar xzf ../binaries/initrd.tar.gz -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run -cp -ar ../binaries/dist/install/* . +mkdir -p etc/local.d echo "#!/bin/bash -export LD_LIBRARY_PATH=/usr/local/lib bash /etc/init.d/xencommons start -/usr/local/lib/xen/bin/init-dom0less +/usr/lib/xen/bin/init-dom0less brctl addbr xenbr0 brctl addif xenbr0 eth0 @@ -139,8 +136,7 @@ ${dom0_check} " > etc/local.d/xen.start chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -find . | cpio -H newc -o | gzip > ../binaries/dom0-rootfs.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/dom0-rootfs.cpio.gz cd .. # ImageBuilder diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-xtf-dom0less-arm64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-xtf-dom0less-arm64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qemu-xtf-dom0less-arm64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qemu-xtf-dom0less-arm64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -61,6 +61,7 @@ -bios /usr/lib/u-boot/qemu_arm64/u-boot.bin" export UBOOT_CMD="virtio scan; dhcp; tftpb 0x40000000 boot.scr; source 0x40000000" +export BOOT_MSG="Latest ChangeSet: " export TEST_LOG="smoke.serial" export PASSED="${passed}" diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/qubes-x86-64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/qubes-x86-64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/qubes-x86-64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/qubes-x86-64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/sh -set -ex +set -ex -o pipefail # One of: # - "" PV dom0, PVH domU @@ -10,6 +10,8 @@ # - pci-pv PV dom0, PV domU + PCI Passthrough # - pvshim PV dom0, PVSHIM domU # - s3 PV dom0, S3 suspend/resume +# - tools-tests-pv PV dom0, run tests from tools/tests/* +# - tools-tests-pvh PVH dom0, run tests from tools/tests/* test_variant=$1 ### defaults @@ -19,6 +21,7 @@ domU_type="pvh" domU_vif="'bridge=xenbr0'," domU_extra_config= +retrieve_xml= case "${test_variant}" in ### test: smoke test & smoke test PVH & smoke test HVM & smoke test PVSHIM @@ -101,12 +104,14 @@ domU_check=" set -x -e interface=eth0 +while ! [ -e \"/sys/class/net/\$interface\" ]; do sleep 1; done ip link set \"\$interface\" up timeout 30s udhcpc -i \"\$interface\" pingip=\$(ip -o -4 r show default|cut -f 3 -d ' ') ping -c 10 \"\$pingip\" echo domU started -pcidevice=\$(basename \$(readlink /sys/class/net/\$interface/device)) +pcidevice=\$(realpath /sys/class/net/\$interface/device | + sed 's#.*pci0000:00/\\([^/]*\\).*#\\1#') lspci -vs \$pcidevice " if [ -n "$PCIDEV_INTR" ]; then @@ -119,13 +124,27 @@ " dom0_check=" -tail -F /var/log/xen/qemu-dm-domU.log & until grep -q \"^domU Welcome to Alpine Linux\" /var/log/xen/console/guest-domU.log; do sleep 1 done " ;; + ### tests: tools-tests-pv, tools-tests-pvh + "tools-tests-pv"|"tools-tests-pvh") + retrieve_xml=1 + passed="test passed" + domU_check="" + dom0_check=" +/tests/run-tools-tests /tests /tmp/tests-junit.xml && echo \"${passed}\" +nc -l -p 8080 < /tmp/tests-junit.xml >/dev/null & +" + if [ "${test_variant}" = "tools-tests-pvh" ]; then + extra_xen_opts="dom0=pvh" + fi + + ;; + *) echo "Unrecognised test_variant '${test_variant}'" >&2 exit 1 @@ -144,42 +163,44 @@ ${domU_extra_config} " -# DomU -mkdir -p rootfs -cd rootfs -# fakeroot is needed to preserve device nodes in rootless podman container -fakeroot -s ../fakeroot-save tar xzf ../binaries/initrd.tar.gz -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run -echo "#!/bin/sh +if [ -n "$domU_check" ]; then + # DomU rootfs + cp binaries/rootfs.cpio.gz binaries/domU-rootfs.cpio.gz + + # test-local configuration + mkdir -p rootfs + cd rootfs + mkdir -p etc/local.d + echo "#!/bin/sh + +echo 8 > /proc/sys/kernel/printk ${domU_check} " > etc/local.d/xen.start -chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -sed -i -e 's/^Welcome/domU \0/' etc/issue -find . | fakeroot -i ../fakeroot-save cpio -H newc -o | gzip > ../binaries/domU-rootfs.cpio.gz -cd .. -rm -rf rootfs + chmod +x etc/local.d/xen.start + echo "domU Welcome to Alpine Linux +Kernel \r on an \m (\l) + +" > etc/issue + find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/domU-rootfs.cpio.gz + cd .. + rm -rf rootfs +fi + +# Dom0 rootfs +cp binaries/ucode.cpio binaries/dom0-rootfs.cpio.gz +cat binaries/rootfs.cpio.gz >> binaries/dom0-rootfs.cpio.gz +cat binaries/xen-tools.cpio.gz >> binaries/dom0-rootfs.cpio.gz -# DOM0 rootfs +# test-local configuration mkdir -p rootfs cd rootfs -fakeroot -s ../fakeroot-save tar xzf ../binaries/initrd.tar.gz -mkdir boot -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run -cp -ar ../binaries/dist/install/* . +mkdir -p boot etc/local.d +cp -ar ../binaries/tests . +cp -a ../automation/scripts/run-tools-tests tests/ echo "#!/bin/bash -export LD_LIBRARY_PATH=/usr/local/lib bash /etc/init.d/xencommons start brctl addbr xenbr0 @@ -188,21 +209,37 @@ ifconfig xenbr0 up ifconfig xenbr0 192.168.0.1 +" > etc/local.d/xen.start + +if [ -n "$retrieve_xml" ]; then + echo "timeout 30s udhcpc -i xenbr0" >> etc/local.d/xen.start +fi + +if [ -n "$domU_check" ]; then + echo " # get domU console content into test log tail -F /var/log/xen/console/guest-domU.log 2>/dev/null | sed -e \"s/^/(domU) /\" & -xl create /etc/xen/domU.cfg +tail -F /var/log/xen/qemu-dm-domU.log 2>/dev/null | sed -e \"s/^/(qemu-dm) /\" & +xl -vvv create /etc/xen/domU.cfg ${dom0_check} -" > etc/local.d/xen.start +" >> etc/local.d/xen.start +else + echo "${dom0_check}" >> etc/local.d/xen.start +fi + chmod +x etc/local.d/xen.start +mkdir -p etc/xen echo "$domU_config" > etc/xen/domU.cfg -echo "rc_verbose=yes" >> etc/rc.conf +mkdir -p etc/default echo "XENCONSOLED_TRACE=all" >> etc/default/xencommons echo "QEMU_XEN=/bin/false" >> etc/default/xencommons mkdir -p var/log/xen/console cp ../binaries/bzImage boot/vmlinuz -cp ../binaries/domU-rootfs.cpio.gz boot/initrd-domU -find . | fakeroot -i ../fakeroot-save cpio -H newc -o | gzip > ../binaries/dom0-rootfs.cpio.gz +if [ -n "$domU_check" ]; then + cp ../binaries/domU-rootfs.cpio.gz boot/initrd-domU +fi +find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/dom0-rootfs.cpio.gz cd .. @@ -210,57 +247,43 @@ CONTROLLER=control@thor.testnet echo " -multiboot2 (http)/gitlab-ci/xen $CONSOLE_OPTS loglvl=all guest_loglvl=all dom0_mem=4G console_timestamps=boot $extra_xen_opts +multiboot2 (http)/gitlab-ci/xen $CONSOLE_OPTS loglvl=all guest_loglvl=all dom0_mem=4G console_timestamps=boot ucode=scan $extra_xen_opts module2 (http)/gitlab-ci/vmlinuz console=hvc0 root=/dev/ram0 earlyprintk=xen -module2 (http)/gitlab-ci/initrd-dom0 +module2 --nounzip (http)/gitlab-ci/initrd-dom0 " > $TFTP/grub.cfg +echo "#!ipxe + +kernel /gitlab-ci/xen $CONSOLE_OPTS loglvl=all guest_loglvl=all dom0_mem=4G console_timestamps=boot ucode=scan $extra_xen_opts || reboot +module /gitlab-ci/vmlinuz console=hvc0 root=/dev/ram0 earlyprintk=xen || reboot +module /gitlab-ci/initrd-dom0 || reboot +boot +" > $TFTP/boot.ipxe + cp -f binaries/xen $TFTP/xen cp -f binaries/bzImage $TFTP/vmlinuz cp -f binaries/dom0-rootfs.cpio.gz $TFTP/initrd-dom0 -# start logging the serial; this gives interactive console, don't close its -# stdin to not close it; the 'cat' is important, plain redirection would hang -# until somebody opens the pipe; opening and closing the pipe is used to close -# the console -mkfifo /tmp/console-stdin -cat /tmp/console-stdin |\ -ssh $CONTROLLER console | tee smoke.serial | sed 's/\r//' & - # start the system pointing at gitlab-ci predefined config ssh $CONTROLLER gitlabci poweron -trap "ssh $CONTROLLER poweroff; : > /tmp/console-stdin" EXIT +trap "ssh $CONTROLLER poweroff" EXIT if [ -n "$wait_and_wakeup" ]; then - # wait for suspend or a timeout - until grep "$wait_and_wakeup" smoke.serial || [ $timeout -le 0 ]; do - sleep 1; - : $((--timeout)) - done - if [ $timeout -le 0 ]; then - echo "ERROR: suspend timeout, aborting" - exit 1 - fi - # keep it suspended a bit, then wakeup - sleep 30 - ssh $CONTROLLER wake + export SUSPEND_MSG="$wait_and_wakeup" + export WAKEUP_CMD="ssh $CONTROLLER wake" fi -set +x -until grep "^Welcome to Alpine Linux" smoke.serial || [ $timeout -le 0 ]; do - sleep 1; - : $((--timeout)) -done -set -x - -tail -n 100 smoke.serial +export PASSED="${passed}" +export BOOT_MSG="Latest ChangeSet: " +export LOG_MSG="\nWelcome to Alpine Linux" +export TEST_CMD="ssh $CONTROLLER console" +export TEST_LOG="smoke.serial" +export TEST_TIMEOUT="$timeout" +./automation/scripts/console.exp | sed 's/\r\+$//' +TEST_RESULT=$? -if [ $timeout -le 0 ]; then - echo "ERROR: test timeout, aborting" - exit 1 +if [ -n "$retrieve_xml" ]; then + nc -w 10 "$SUT_ADDR" 8080 > tests-junit.xml \n' > "$xml_out" +printf '\n' >> "$xml_out" +printf ' \n' >> "$xml_out" +failed= +for dir in "$1"/*; do + [ -d "$dir" ] || continue + echo "Running test in $dir" + printf ' \n' "$dir" >> "$xml_out" + ret= + for f in "$dir"/*; do + [ -f "$f" ] || continue + [ -x "$f" ] || continue + "$f" 2>&1 | tee /tmp/out + ret=$? + if [ "$ret" -ne 0 ]; then + echo "FAILED: $ret" + failed+=" $dir" + printf ' \n' "$f" "$ret" >> "$xml_out" + # TODO: could use xml escaping... but current tests seems to + # produce sane output + cat /tmp/out >> "$xml_out" + printf ' \n' >> "$xml_out" + else + echo "PASSED" + fi + done + if [ -z "$ret" ]; then + printf ' \n' "$dir" >> "$xml_out" + fi + printf ' \n' >> "$xml_out" +done +printf ' \n' >> "$xml_out" +printf '\n' >> "$xml_out" + +if [ -n "$failed" ]; then + exit 1 +fi diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/xilinx-smoke-dom0-x86_64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/xilinx-smoke-dom0-x86_64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/xilinx-smoke-dom0-x86_64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/xilinx-smoke-dom0-x86_64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -15,7 +15,7 @@ TEST="$1" PASS_MSG="Test passed: ${TEST}" XEN_CMD_DOM0="dom0=pvh dom0_max_vcpus=4 dom0_mem=4G" -XEN_CMD_XEN="sched=null loglvl=all guest_loglvl=all console_timestamps=boot" +XEN_CMD_XEN="sched=null loglvl=all guest_loglvl=all console_timestamps=boot ucode=scan" XEN_CMD_EXTRA="" DOM0_CMD="" DOMU_CMD="" @@ -28,8 +28,6 @@ memory = 512 ' DOMU_CFG_EXTRA="" -copy_domU_files () { :; } -copy_dom0_files () { :; } # Select test variant. if [ "${TEST}" = "ping" ]; then @@ -49,7 +47,7 @@ ifconfig xenbr0 192.168.0.1 # get domU console content into test log tail -F /var/log/xen/console/guest-domU.log 2>/dev/null | sed -e \"s/^/(domU) /\" & -xl create /etc/xen/domU.cfg +xl -vvv create /etc/xen/domU.cfg set +x until grep -q \"${DOMU_MSG}\" /var/log/xen/console/guest-domU.log; do sleep 1 @@ -66,7 +64,7 @@ PASS_MSG="TEST: Message from DOMU" XEN_CMD_EXTRA="argo=1,mac-permissive=1" DOMU_CMD=" -insmod /root/xen-argo.ko +insmod /lib/modules/\$(uname -r)/updates/xen-argo.ko until false do echo \"${PASS_MSG}\" @@ -74,64 +72,62 @@ done | argo-exec -p 28333 -d 0 -- /bin/echo " DOM0_CMD=" -insmod /root/xen-argo.ko -xl create /etc/xen/domU.cfg +insmod /lib/modules/\$(uname -r)/updates/xen-argo.ko +xl -vvv create /etc/xen/domU.cfg argo-exec -l -p 28333 -- /bin/echo " -copy_dom0_files () -{ - cp "${WORKDIR}/binaries/xen-argo.ko" "root/" - cp -ar "${WORKDIR}/binaries/lib/"* "usr/local/lib/" - cp "${WORKDIR}/binaries/argo-exec" "usr/local/bin/" -} -copy_domU_files () { copy_dom0_files; } else fatal "Unknown test: ${TEST}" fi -# Set up domU rootfs. +# DomU rootfs +cp binaries/rootfs.cpio.gz binaries/domU-rootfs.cpio.gz +if [[ "${TEST}" == argo ]]; then + cat binaries/argo.cpio.gz >> binaries/domU-rootfs.cpio.gz +fi + +# test-local configuration mkdir -p rootfs cd rootfs -tar xzf ../binaries/initrd.tar.gz -mkdir proc run srv sys -rm var/run +mkdir -p etc/local.d echo "#!/bin/sh set -x -export LD_LIBRARY_PATH=/usr/local/lib -PATH=/usr/local/bin:/usr/local/sbin:\$PATH ${DOMU_CMD} " > etc/local.d/xen.start chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -sed -i -e 's/^Welcome/domU \0/' etc/issue -copy_domU_files -find . | cpio -H newc -o | gzip > ../binaries/domU-rootfs.cpio.gz +echo "domU Welcome to Alpine Linux +Kernel \r on an \m (\l) + +" > etc/issue +find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/domU-rootfs.cpio.gz cd .. rm -rf rootfs -# Set up dom0 rootfs. +# Dom0 rootfs +cp binaries/ucode.cpio binaries/dom0-rootfs.cpio.gz +cat binaries/rootfs.cpio.gz >> binaries/dom0-rootfs.cpio.gz +cat binaries/xen-tools.cpio.gz >> binaries/dom0-rootfs.cpio.gz +if [[ "${TEST}" == argo ]]; then + cat binaries/argo.cpio.gz >> binaries/dom0-rootfs.cpio.gz +fi + +# test-local configuration mkdir -p rootfs cd rootfs -tar xzf ../binaries/initrd.tar.gz -mkdir boot proc run srv sys -rm var/run -cp -ar ../binaries/dist/install/* . +mkdir -p boot etc/local.d etc/xen etc/default echo "#!/bin/bash set -x -export LD_LIBRARY_PATH=/usr/local/lib bash /etc/init.d/xencommons start ${DOM0_CMD} " > etc/local.d/xen.start chmod +x etc/local.d/xen.start echo "${DOMU_CFG}${DOMU_CFG_EXTRA}" > etc/xen/domU.cfg -echo "rc_verbose=yes" >> etc/rc.conf echo "XENCONSOLED_TRACE=all" >> etc/default/xencommons echo "QEMU_XEN=/bin/false" >> etc/default/xencommons mkdir -p var/log/xen/console cp ../binaries/bzImage boot/vmlinuz cp ../binaries/domU-rootfs.cpio.gz boot/initrd-domU -copy_dom0_files -find . | cpio -H newc -o | gzip > ../binaries/dom0-rootfs.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/dom0-rootfs.cpio.gz cd .. # Load software into TFTP server directory. @@ -144,7 +140,7 @@ net_default_server=10.0.6.1 multiboot2 (tftp)/${TEST_BOARD}/xen ${XEN_CMDLINE} sync_console module2 (tftp)/${TEST_BOARD}/vmlinuz console=hvc0 root=/dev/ram0 earlyprintk=xen -module2 (tftp)/${TEST_BOARD}/initrd-dom0 +module2 --nounzip (tftp)/${TEST_BOARD}/initrd-dom0 boot " > ${TFTP}/${TEST_BOARD}/grub.cfg @@ -155,10 +151,11 @@ sh /scratch/gitlab-runner/${TEST_BOARD}.sh 1 sleep 5 set +e -stty -F ${SERIAL_DEV} 57600 +stty -F ${SERIAL_DEV} 57600 -echo # Capture test result and power off board before exiting. export PASSED="${PASS_MSG}" +export BOOT_MSG="Latest ChangeSet: " export TEST_CMD="cat ${SERIAL_DEV}" export TEST_LOG="smoke.serial" diff -Nru xen-4.20.0+68-g35cb38b222/automation/scripts/xilinx-smoke-dom0less-arm64.sh xen-4.20.2+7-g1badcf5035/automation/scripts/xilinx-smoke-dom0less-arm64.sh --- xen-4.20.0+68-g35cb38b222/automation/scripts/xilinx-smoke-dom0less-arm64.sh 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/scripts/xilinx-smoke-dom0less-arm64.sh 2025-11-25 08:37:47.000000000 +0000 @@ -38,48 +38,40 @@ " fi -# DomU +# DomU rootfs +cp binaries/rootfs.cpio.gz binaries/domU-rootfs.cpio.gz + +# test-local configuration mkdir -p rootfs cd rootfs -tar xzf ../binaries/initrd.tar.gz -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run +mkdir -p etc/local.d echo "#!/bin/sh ${domU_check} /bin/sh" > etc/local.d/xen.start chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -find . | cpio -H newc -o | gzip > ../binaries/domU-rootfs.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/domU-rootfs.cpio.gz cd .. rm -rf rootfs -# DOM0 rootfs +# Dom0 rootfs +cp binaries/rootfs.cpio.gz binaries/dom0-rootfs.cpio.gz +cat binaries/xen-tools.cpio.gz >> binaries/dom0-rootfs.cpio.gz + +# test-local configuration mkdir -p rootfs cd rootfs -tar xzf ../binaries/initrd.tar.gz -mkdir proc -mkdir run -mkdir srv -mkdir sys -rm var/run -cp -ar ../binaries/dist/install/* . - +mkdir -p etc/local.d echo "#!/bin/bash -export LD_LIBRARY_PATH=/usr/local/lib bash /etc/init.d/xencommons start -/usr/local/lib/xen/bin/init-dom0less +/usr/lib/xen/bin/init-dom0less ${dom0_check} " > etc/local.d/xen.start chmod +x etc/local.d/xen.start -echo "rc_verbose=yes" >> etc/rc.conf -find . | cpio -H newc -o | gzip > ../binaries/dom0-rootfs.cpio.gz +find . | cpio -R 0:0 -H newc -o | gzip >> ../binaries/dom0-rootfs.cpio.gz cd .. @@ -136,10 +128,11 @@ # connect to serial SERIAL_DEV="/dev/serial/zynq" set +e -stty -F ${SERIAL_DEV} 115200 +stty -F ${SERIAL_DEV} 115200 -echo # Capture test result and power off board before exiting. export PASSED="${passed}" +export BOOT_MSG="Latest ChangeSet: " export LOG_MSG="Welcome to Alpine Linux" export TEST_CMD="cat ${SERIAL_DEV}" export TEST_LOG="smoke.serial" diff -Nru xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/Makefile xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/Makefile --- xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -10,9 +10,9 @@ @echo "To push container builds, set the env var PUSH" %: %.dockerfile ## Builds containers - docker build --pull -t $(REGISTRY)/$(@D):$(@F) -f $< $(> /etc/securetty && \ - echo "hvc0" >> /etc/securetty && \ - echo "ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100" >> /etc/inittab && \ - echo "hvc0::respawn:/sbin/getty -L hvc0 115200 vt100" >> /etc/inittab && \ - passwd -d "root" root && \ - \ - # Create rootfs - cd / && \ - tar cvzf /initrd.tar.gz bin dev etc home init lib mnt opt root sbin usr var diff -Nru xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/alpine/3.18.dockerfile xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/alpine/3.18.dockerfile --- xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/alpine/3.18.dockerfile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/alpine/3.18.dockerfile 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM --platform=linux/amd64 alpine:3.18 -LABEL maintainer.name="The Xen Project" \ - maintainer.email="xen-devel@lists.xenproject.org" - -ENV USER root - -RUN mkdir /build -WORKDIR /build - -RUN \ - # apk - apk update && \ - \ - # xen runtime deps - apk add musl && \ - apk add libgcc && \ - apk add openrc && \ - apk add busybox && \ - apk add sudo && \ - apk add dbus && \ - apk add bash && \ - apk add python3 && \ - apk add zlib && \ - apk add ncurses && \ - apk add yajl && \ - apk add libaio && \ - apk add xz && \ - apk add util-linux && \ - apk add argp-standalone && \ - apk add libfdt && \ - apk add glib && \ - apk add pixman && \ - apk add curl && \ - apk add udev && \ - apk add pciutils && \ - apk add libelf && \ - \ - # Xen - cd / && \ - # Minimal ramdisk environment in case of cpio output - rc-update add udev && \ - rc-update add udev-trigger && \ - rc-update add udev-settle && \ - rc-update add loopback sysinit && \ - rc-update add bootmisc boot && \ - rc-update add devfs sysinit && \ - rc-update add dmesg sysinit && \ - rc-update add hostname boot && \ - rc-update add hwclock boot && \ - rc-update add hwdrivers sysinit && \ - rc-update add modules boot && \ - rc-update add killprocs shutdown && \ - rc-update add mount-ro shutdown && \ - rc-update add savecache shutdown && \ - rc-update add local default && \ - cp -a /sbin/init /init && \ - echo "ttyS0" >> /etc/securetty && \ - echo "hvc0" >> /etc/securetty && \ - echo "ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100" >> /etc/inittab && \ - echo "hvc0::respawn:/sbin/getty -L hvc0 115200 vt100" >> /etc/inittab && \ - echo > /etc/modules && \ - passwd -d "root" root && \ - \ - # Create rootfs - cd / && \ - tar cvzf /initrd.tar.gz bin dev etc home init lib mnt opt root sbin usr var diff -Nru xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/kernel/5.19-arm64v8.dockerfile xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/kernel/5.19-arm64v8.dockerfile --- xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/kernel/5.19-arm64v8.dockerfile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/kernel/5.19-arm64v8.dockerfile 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM --platform=linux/arm64/v8 debian:bookworm -LABEL maintainer.name="The Xen Project" \ - maintainer.email="xen-devel@lists.xenproject.org" - -ENV DEBIAN_FRONTEND=noninteractive -ENV LINUX_VERSION=5.19 -ENV USER root - -RUN mkdir /build -WORKDIR /build - -# build depends -RUN apt-get update && \ - apt-get --quiet --yes install \ - build-essential \ - bc \ - curl \ - flex \ - bison \ - && \ - \ - # Build the kernel - curl -fsSLO https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-"$LINUX_VERSION".tar.xz && \ - tar xvJf linux-"$LINUX_VERSION".tar.xz && \ - cd linux-"$LINUX_VERSION" && \ - make defconfig && \ - sed -i 's/CONFIG_IPV6=m/CONFIG_IPV6=y/g' .config && \ - sed -i 's/CONFIG_BRIDGE=m/CONFIG_BRIDGE=y/g' .config && \ - sed -i 's/# CONFIG_XEN_NETDEV_BACKEND is not set/CONFIG_XEN_NETDEV_BACKEND=y/g' .config && \ - make -j$(nproc) Image.gz && \ - cp arch/arm64/boot/Image / && \ - cd /build && \ - rm -rf linux-"$LINUX_VERSION"* && \ - apt-get autoremove -y && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists* /tmp/* /var/tmp/* diff -Nru xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/kernel/6.1.19.dockerfile xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/kernel/6.1.19.dockerfile --- xen-4.20.0+68-g35cb38b222/automation/tests-artifacts/kernel/6.1.19.dockerfile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/automation/tests-artifacts/kernel/6.1.19.dockerfile 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM --platform=linux/amd64 debian:bookworm -LABEL maintainer.name="The Xen Project" \ - maintainer.email="xen-devel@lists.xenproject.org" - -ENV DEBIAN_FRONTEND=noninteractive -ENV LINUX_VERSION=6.1.19 -ENV USER root - -RUN mkdir /build -WORKDIR /build - -# build depends -RUN apt-get update && \ - apt-get --quiet --yes install \ - build-essential \ - bc \ - curl \ - flex \ - bison \ - libelf-dev \ - && \ - apt-get autoremove -y && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists* /tmp/* /var/tmp/* - -# Build the kernel -RUN curl -fsSLO https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-"$LINUX_VERSION".tar.xz && \ - tar xvJf linux-"$LINUX_VERSION".tar.xz && \ - cd linux-"$LINUX_VERSION" && \ - make defconfig && \ - make xen.config && \ - scripts/config --enable BRIDGE && \ - scripts/config --enable IGC && \ - scripts/config --enable TUN && \ - cp .config .config.orig && \ - cat .config.orig | grep XEN | grep =m |sed 's/=m/=y/g' >> .config && \ - make -j$(nproc) bzImage && \ - cp arch/x86/boot/bzImage / && \ - cd /build && \ - rm -rf linux-"$LINUX_VERSION"* diff -Nru xen-4.20.0+68-g35cb38b222/debian/changelog xen-4.20.2+7-g1badcf5035/debian/changelog --- xen-4.20.0+68-g35cb38b222/debian/changelog 2025-05-05 17:24:56.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/debian/changelog 2025-11-30 15:57:07.000000000 +0000 @@ -1,3 +1,32 @@ +xen (4.20.2+7-g1badcf5035-0+deb13u1) trixie-security; urgency=medium + + Significant changes: + * Update to new upstream version 4.20.2+7-g1badcf5035, which also contains + security fixes for the following issues: + (Closes: #1105193) (Closes: #1120075) + - x86: Indirect Target Selection + XSA-469 CVE-2024-28956 + - x86: Incorrect stubs exception handling for flags recovery + XSA-470 CVE-2025-27465 + - x86: Transitive Scheduler Attacks + XSA-471 CVE-2024-36350 CVE-2024-36357 + - Multiple vulnerabilities in the Viridian interface + XSA-472 CVE-2025-27466 CVE-2025-58142 CVE-2025-58143 + - Arm issues with page refcounting + XSA-473 CVE-2025-58144 CVE-2025-58145 + - x86: Incorrect input sanitisation in Viridian hypercalls + XSA-475 CVE-2025-58147 CVE-2025-58148 + - Incorrect removal of permissions on PCI device unplug + XSA-476 CVE-2025-58149 + * Note that the following XSA are not listed, because... + - XSA-468 applies to Windows PV drivers + - XSA-474 applies to XAPI which is not included in Debian + + Packaging minor fixes and improvements: + * debian/salsa-ci.yml: adjust for trixie and new salsa-ci pipeline + + -- Maximilian Engelhardt Sun, 30 Nov 2025 16:57:07 +0100 + xen (4.20.0+68-g35cb38b222-1) unstable; urgency=medium * Update to new upstream version 4.20.0+68-g35cb38b222. diff -Nru xen-4.20.0+68-g35cb38b222/debian/patches/prefix-abiname/config-prefix.diff xen-4.20.2+7-g1badcf5035/debian/patches/prefix-abiname/config-prefix.diff --- xen-4.20.0+68-g35cb38b222/debian/patches/prefix-abiname/config-prefix.diff 2025-05-05 17:24:56.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/debian/patches/prefix-abiname/config-prefix.diff 2025-11-30 15:57:07.000000000 +0000 @@ -9,7 +9,7 @@ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Config.mk b/Config.mk -index 74e57ae..08a4934 100644 +index 4bbb366..7a90957 100644 --- a/Config.mk +++ b/Config.mk @@ -78,7 +78,7 @@ EXTRA_LIB += $(EXTRA_PREFIX)/lib diff -Nru xen-4.20.0+68-g35cb38b222/debian/salsa-ci.yml xen-4.20.2+7-g1badcf5035/debian/salsa-ci.yml --- xen-4.20.0+68-g35cb38b222/debian/salsa-ci.yml 2025-05-05 17:24:56.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/debian/salsa-ci.yml 2025-11-30 15:57:07.000000000 +0000 @@ -2,40 +2,36 @@ include: - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml -extract-source: - before_script: - # convert into a gbp patches-unapplied branch using git-debrebase - - apt-get update - - apt-get --yes install git-debrebase - # git-debrebase needs git user setup - - git config user.email "salsa-ci@invalid.invalid" - - git config user.name "salsa-ci" - - git debrebase --force - - git debrebase convert-to-gbp - # work around gbp export-orig replacing variables in .gitarchive-info - - test -d .git/info || mkdir .git/info - - echo ".gitarchive-info -export-subst" >> .git/info/attributes +# for documentation about the templating magic (yaml anchors) see here: +# https://docs.gitlab.com/ci/yaml/yaml_optimization/ + +# run git-debrebase make-patches +.git-debrebase-prepare: &git-debrebase-prepare + - apt-get update + - apt-get --yes install git-debrebase + # git-debrebase needs git user setup + - git config user.email "salsa-ci@invalid.invalid" + - git config user.name "salsa-ci" + - git debrebase --force + - git debrebase make-patches + +.build-definition: &build-definition + extends: .build-definition-common + before_script: *git-debrebase-prepare + +build source: + extends: .build-source-only + before_script: *git-debrebase-prepare variables: # disable shallow cloning of git repository. This is needed for git-debrebase GIT_DEPTH: 0 - RELEASE: 'unstable' + RELEASE: 'trixie' # xen currently does not enable hardening when building the hypervisor so # disable blhc. SALSA_CI_DISABLE_BLHC: 1 - SALSA_CI_REPROTEST_ENABLE_DIFFOSCOPE: 1 - # We do not provide packages for i386 SALSA_CI_DISABLE_BUILD_PACKAGE_I386: 1 - - # cross building xen currently fails for the following reason: - # The following packages have unmet dependencies: - # ocaml:arm64 : Depends: gcc:arm64 but it is not installable - # Depends: binutils:arm64 but it is not installable - # - # It can be tried again when there are better chances of it building - # successfully. - SALSA_CI_DISABLE_CROSSBUILD_ARM64: 1 diff -Nru xen-4.20.0+68-g35cb38b222/docs/man/xl.cfg.5.pod.in xen-4.20.2+7-g1badcf5035/docs/man/xl.cfg.5.pod.in --- xen-4.20.0+68-g35cb38b222/docs/man/xl.cfg.5.pod.in 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/docs/man/xl.cfg.5.pod.in 2025-11-25 08:37:47.000000000 +0000 @@ -2461,7 +2461,7 @@ This is a special value that enables the default set of groups, which is currently the B, B, B, B, -B, B, B and B groups. +B, B and B groups. =item B diff -Nru xen-4.20.0+68-g35cb38b222/docs/misc/xen-command-line.pandoc xen-4.20.2+7-g1badcf5035/docs/misc/xen-command-line.pandoc --- xen-4.20.0+68-g35cb38b222/docs/misc/xen-command-line.pandoc 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/docs/misc/xen-command-line.pandoc 2025-11-25 08:37:47.000000000 +0000 @@ -2470,7 +2470,7 @@ > {ibrs,ibpb,ssbd,psfd, > eager-fpu,l1d-flush,branch-harden,srb-lock, > unpriv-mmio,gds-mit,div-scrub,lock-harden, -> bhi-dis-s,bp-spec-reduce}= ]` +> bhi-dis-s,bp-spec-reduce,ibpb-alt}= ]` Controls for speculative execution sidechannel mitigations. By default, Xen will pick the most appropriate mitigations based on compiled in support, @@ -2626,6 +2626,10 @@ to mitigate SRSO for HVM guests, and because it is a prerequisite to advertise SRSO_U/S_NO to PV guests. +On Sappire and Emerald Rapids CPUs with May 2025 microcode or later, the +`ibpb-alt=` option can be used to switch to the alternative mitigation for +Intel SA-00982. Intel suggest that some workloads will benefit from this. + ### sync_console > `= ` @@ -2768,9 +2772,10 @@ considered safer. The default value is `true`. The `digest-check=` option is active by default and controls whether to -perform additional authenticity checks. Collisions in the signature algorithm -used by AMD Fam17h/19h processors have been found. Xen contains a table of -digests of microcode patches with known-good provenance, and will block +perform additional authenticity checks. The Entrysign vulnerability (AMD +SB-7033, CVE-2024-36347) on Zen1-5 processors allows forging the signature on +arbitrary microcode such that it is accepted by the CPU. Xen contains a table +of digests of microcode patches with known-good provenance, and will block loading of patches that do not match. ### unrestricted_guest (Intel) diff -Nru xen-4.20.0+68-g35cb38b222/tools/firmware/hvmloader/smbios.c xen-4.20.2+7-g1badcf5035/tools/firmware/hvmloader/smbios.c --- xen-4.20.0+68-g35cb38b222/tools/firmware/hvmloader/smbios.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/firmware/hvmloader/smbios.c 2025-11-25 08:37:47.000000000 +0000 @@ -47,6 +47,8 @@ smbios_pt_init(void); static void* get_smbios_pt_struct(uint8_t type, uint32_t *length_out); +static void * +smbios_pt_copy(void *start, uint8_t type, uint16_t handle, size_t table_size); static void get_cpu_manufacturer(char *buf, int len); static int @@ -154,6 +156,24 @@ return NULL; } +static void * +smbios_pt_copy(void *start, uint8_t type, uint16_t handle, size_t min_size) +{ + struct smbios_structure_header *header = start; + void *pts; + uint32_t length; + + pts = get_smbios_pt_struct(type, &length); + if ( pts != NULL && length >= min_size ) + { + memcpy(start, pts, length); + header->handle = handle; + return start + length; + } + + return start; +} + static void get_cpu_manufacturer(char *buf, int len) { @@ -381,16 +401,17 @@ struct smbios_type_0 *p = (struct smbios_type_0 *)start; static const char *smbios_release_date = __SMBIOS_DATE__; const char *s; - void *pts; - uint32_t length; + void *next; - pts = get_smbios_pt_struct(0, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE0; - return (start + length); - } + /* + * Specification says Type 0 table has length of at least 18h for v2.4-3.0. + */ + + BUILD_BUG_ON(sizeof(*p) != 24); + + next = smbios_pt_copy(start, 0, SMBIOS_HANDLE_TYPE0, sizeof(*p)); + if ( next != start ) + return next; memset(p, 0, sizeof(*p)); @@ -440,16 +461,14 @@ char uuid_str[37]; struct smbios_type_1 *p = (struct smbios_type_1 *)start; const char *s; - void *pts; - uint32_t length; + void *next; - pts = get_smbios_pt_struct(1, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE1; - return (start + length); - } + /* Specification says Type 1 table has length of 1Bh for v2.4 and later. */ + BUILD_BUG_ON(sizeof(*p) != 27); + + next = smbios_pt_copy(start, 1, SMBIOS_HANDLE_TYPE1, sizeof(*p)); + if ( next != start ) + return next; memset(p, 0, sizeof(*p)); @@ -498,26 +517,29 @@ { struct smbios_type_2 *p = (struct smbios_type_2 *)start; const char *s; - uint8_t *ptr; - void *pts; - uint32_t length; + void *next; unsigned int counter = 0; - pts = get_smbios_pt_struct(2, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE2; + /* + * Specification says Type 2 table has length of at least 08h, + * which corresponds with the end of the "Serial Number" field. + */ + BUILD_BUG_ON(endof_field(struct smbios_type_2, serial_number_str) != 8); + + next = smbios_pt_copy(start, 2, SMBIOS_HANDLE_TYPE2, + endof_field(struct smbios_type_2, serial_number_str)); + if ( next != start ) + { /* Set current chassis handle if present */ - if ( p->header.length > 13 ) + if ( p->header.length >= endof_field(struct smbios_type_2, + chassis_handle) ) { - ptr = ((uint8_t*)start) + 11; - if ( *((uint16_t*)ptr) != 0 ) - *((uint16_t*)ptr) = SMBIOS_HANDLE_TYPE3; + if ( p->chassis_handle != 0 ) + p->chassis_handle = SMBIOS_HANDLE_TYPE3; } - return (start + length); + return next; } memset(p, 0, sizeof(*p)); @@ -593,18 +615,21 @@ { struct smbios_type_3 *p = (struct smbios_type_3 *)start; const char *s; - void *pts; - uint32_t length; + void *next; uint32_t counter = 0; - pts = get_smbios_pt_struct(3, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE3; - return (start + length); - } - + /* + * Specification says Type 3 table has length of at least 0Dh (for v2.1+), + * which corresponds with the end of the "Security Status" field. + */ + + BUILD_BUG_ON(endof_field(struct smbios_type_3, security_status) != 13); + + next = smbios_pt_copy(start, 3, SMBIOS_HANDLE_TYPE3, + offsetof(struct smbios_type_3, security_status)); + if ( next != start ) + return next; + memset(p, 0, sizeof(*p)); p->header.type = 3; @@ -656,6 +681,9 @@ struct smbios_type_4 *p = (struct smbios_type_4 *)start; uint32_t eax, ebx, ecx, edx; + /* Specification says Type 4 table has length of 23h for v2.3+. */ + BUILD_BUG_ON(sizeof(*p) != 35); + memset(p, 0, sizeof(*p)); p->header.type = 4; @@ -707,17 +735,15 @@ struct smbios_type_11 *p = (struct smbios_type_11 *)start; char path[20]; const char *s; + void *next; int i; - void *pts; - uint32_t length; - pts = get_smbios_pt_struct(11, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE11; - return (start + length); - } + /* Specification says Type 11 table has length of 05h. */ + BUILD_BUG_ON(sizeof(*p) != 5); + + next = smbios_pt_copy(start, 11, SMBIOS_HANDLE_TYPE11, sizeof(*p)); + if ( next != start ) + return next; p->header.type = 11; p->header.length = sizeof(struct smbios_type_11); @@ -756,6 +782,9 @@ { struct smbios_type_16 *p = (struct smbios_type_16*)start; + /* Specification says Type 16 table has length of 0Fh for v2.1-2.7. */ + BUILD_BUG_ON(sizeof(*p) != 15); + memset(p, 0, sizeof(*p)); p->header.type = 16; @@ -781,6 +810,9 @@ char buf[16]; struct smbios_type_17 *p = (struct smbios_type_17 *)start; + /* Specification says Type 17 table has length of 1Bh for v2.3-2.6. */ + BUILD_BUG_ON(sizeof(*p) != 27); + memset(p, 0, sizeof(*p)); p->header.type = 17; @@ -816,6 +848,9 @@ { struct smbios_type_19 *p = (struct smbios_type_19 *)start; + /* Specification says Type 19 table has length of 0Fh for v2.1-2.7. */ + BUILD_BUG_ON(sizeof(*p) != 15); + memset(p, 0, sizeof(*p)); p->header.type = 19; @@ -838,6 +873,9 @@ { struct smbios_type_20 *p = (struct smbios_type_20 *)start; + /* Specification says Type 20 table has length of 13h for v2.1-2.7. */ + BUILD_BUG_ON(sizeof(*p) != 19); + memset(p, 0, sizeof(*p)); p->header.type = 20; @@ -865,16 +903,14 @@ struct smbios_type_22 *p = (struct smbios_type_22 *)start; static const char *smbios_release_date = __SMBIOS_DATE__; const char *s; - void *pts; - uint32_t length; + void *next; - pts = get_smbios_pt_struct(22, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE22; - return (start + length); - } + /* Specification says Type 22 table has length of 1Ah. */ + BUILD_BUG_ON(sizeof(*p) != 26); + + next = smbios_pt_copy(start, 22, SMBIOS_HANDLE_TYPE22, sizeof(*p)); + if ( next != start ) + return next; s = xenstore_read(HVM_XS_SMBIOS_DEFAULT_BATTERY, "0"); if ( strncmp(s, "1", 1) != 0 ) @@ -929,6 +965,9 @@ { struct smbios_type_32 *p = (struct smbios_type_32 *)start; + /* Specification says Type 32 table has length of at least 0Bh. */ + BUILD_BUG_ON(sizeof(*p) != 11); + memset(p, 0, sizeof(*p)); p->header.type = 32; @@ -946,20 +985,17 @@ static void * smbios_type_39_init(void *start) { - struct smbios_type_39 *p = (struct smbios_type_39 *)start; - void *pts; - uint32_t length; + /* + * Specification says Type 39 table has length of at least 10h, + * which corresponds with the end of the "Characteristics" field. + * + * Only present when passed in. + */ - pts = get_smbios_pt_struct(39, &length); - if ( (pts != NULL)&&(length > 0) ) - { - memcpy(start, pts, length); - p->header.handle = SMBIOS_HANDLE_TYPE39; - return (start + length); - } + BUILD_BUG_ON(endof_field(struct smbios_type_39, characteristics) != 16); - /* Only present when passed in */ - return start; + return smbios_pt_copy(start, 39, SMBIOS_HANDLE_TYPE39, + endof_field(struct smbios_type_39, characteristics)); } static void * diff -Nru xen-4.20.0+68-g35cb38b222/tools/firmware/hvmloader/smbios_types.h xen-4.20.2+7-g1badcf5035/tools/firmware/hvmloader/smbios_types.h --- xen-4.20.0+68-g35cb38b222/tools/firmware/hvmloader/smbios_types.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/firmware/hvmloader/smbios_types.h 2025-11-25 08:37:47.000000000 +0000 @@ -90,13 +90,13 @@ uint8_t product_name_str; uint8_t version_str; uint8_t serial_number_str; - uint8_t asset_tag_str; - uint8_t feature_flags; - uint8_t location_in_chassis_str; - uint16_t chassis_handle; - uint8_t board_type; - uint8_t contained_handle_count; - uint16_t contained_handles[]; + uint8_t asset_tag_str; /* Optional */ + uint8_t feature_flags; /* Optional */ + uint8_t location_in_chassis_str; /* Optional */ + uint16_t chassis_handle; /* Optional */ + uint8_t board_type; /* Optional */ + uint8_t contained_handle_count; /* Optional */ + uint16_t contained_handles[]; /* Optional */ } __attribute__ ((packed)); /* System Enclosure - Contained Elements */ @@ -118,12 +118,12 @@ uint8_t power_supply_state; uint8_t thermal_state; uint8_t security_status; - uint32_t oem_specific; - uint8_t height; - uint8_t number_of_power_cords; - uint8_t contained_element_count; - uint8_t contained_element_length; - struct smbios_contained_element contained_elements[]; + uint32_t oem_specific; /* Optional */ + uint8_t height; /* Optional */ + uint8_t number_of_power_cords; /* Optional */ + uint8_t contained_element_count; /* Optional */ + uint8_t contained_element_length; /* Optional */ + struct smbios_contained_element contained_elements[]; /* Optional */ } __attribute__ ((packed)); /* SMBIOS type 4 - Processor Information */ @@ -252,9 +252,9 @@ uint8_t revision_level_str; uint16_t max_capacity; uint16_t characteristics; - uint16_t input_voltage_probe_handle; - uint16_t cooling_device_handle; - uint16_t input_current_probe_handle; + uint16_t input_voltage_probe_handle; /* Optional */ + uint16_t cooling_device_handle; /* Optional */ + uint16_t input_current_probe_handle; /* Optional */ } __attribute__ ((packed)); /* SMBIOS type 127 -- End-of-table */ diff -Nru xen-4.20.0+68-g35cb38b222/tools/firmware/hvmloader/util.h xen-4.20.2+7-g1badcf5035/tools/firmware/hvmloader/util.h --- xen-4.20.0+68-g35cb38b222/tools/firmware/hvmloader/util.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/firmware/hvmloader/util.h 2025-11-25 08:37:47.000000000 +0000 @@ -21,9 +21,6 @@ /* Cause xs_wire.h to give us xsd_errors[]. */ #define EINVAL EINVAL -#define __STR(...) #__VA_ARGS__ -#define STR(...) __STR(__VA_ARGS__) - /* GDT selector values. */ #define SEL_CODE16 0x0008 #define SEL_DATA16 0x0010 diff -Nru xen-4.20.0+68-g35cb38b222/tools/include/xen-tools/common-macros.h xen-4.20.2+7-g1badcf5035/tools/include/xen-tools/common-macros.h --- xen-4.20.0+68-g35cb38b222/tools/include/xen-tools/common-macros.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/include/xen-tools/common-macros.h 2025-11-25 08:37:47.000000000 +0000 @@ -83,11 +83,19 @@ #define __packed __attribute__((__packed__)) #endif +#define sizeof_field(type, member) sizeof(((type *)NULL)->member) + +#define endof_field(type, member) \ + (offsetof(type, member) + sizeof_field(type, member)) + #define container_of(ptr, type, member) ({ \ typeof(((type *)0)->member) *mptr__ = (ptr); \ (type *)((char *)mptr__ - offsetof(type, member)); \ }) +#define __STR(...) #__VA_ARGS__ +#define STR(...) __STR(__VA_ARGS__) + #define __AC(X, Y) (X ## Y) #define _AC(X, Y) __AC(X, Y) diff -Nru xen-4.20.0+68-g35cb38b222/tools/include/xenctrl.h xen-4.20.2+7-g1badcf5035/tools/include/xenctrl.h --- xen-4.20.0+68-g35cb38b222/tools/include/xenctrl.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/include/xenctrl.h 2025-11-25 08:37:47.000000000 +0000 @@ -1623,7 +1623,7 @@ int index, int *pirq, int devfn, - int bus, + int segbus, int entry_nr, uint64_t table_base); diff -Nru xen-4.20.0+68-g35cb38b222/tools/libacpi/mk_dsdt.c xen-4.20.2+7-g1badcf5035/tools/libacpi/mk_dsdt.c --- xen-4.20.0+68-g35cb38b222/tools/libacpi/mk_dsdt.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/libacpi/mk_dsdt.c 2025-11-25 08:37:47.000000000 +0000 @@ -237,6 +237,11 @@ pop_block(); /**** Processor end ****/ #else + if (dm_version == QEMU_NONE) { + pop_block(); + pop_block(); + return 0; + } /* Operation Region 'PRST': bitmask of online CPUs. */ stmt("OperationRegion", "PRST, SystemIO, %#x, %d", @@ -285,10 +290,6 @@ pop_block(); pop_block(); - if (dm_version == QEMU_NONE) { - pop_block(); - return 0; - } /**** Processor end ****/ diff -Nru xen-4.20.0+68-g35cb38b222/tools/libs/ctrl/xc_physdev.c xen-4.20.2+7-g1badcf5035/tools/libs/ctrl/xc_physdev.c --- xen-4.20.0+68-g35cb38b222/tools/libs/ctrl/xc_physdev.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/libs/ctrl/xc_physdev.c 2025-11-25 08:37:47.000000000 +0000 @@ -65,7 +65,7 @@ int index, int *pirq, int devfn, - int bus, + int segbus, int entry_nr, uint64_t table_base) { @@ -79,10 +79,10 @@ } memset(&map, 0, sizeof(struct physdev_map_pirq)); map.domid = domid; - map.type = MAP_PIRQ_TYPE_MSI; + map.type = MAP_PIRQ_TYPE_MSI_SEG; map.index = index; map.pirq = *pirq; - map.bus = bus; + map.bus = segbus; map.devfn = devfn; map.entry_nr = entry_nr; map.table_base = table_base; diff -Nru xen-4.20.0+68-g35cb38b222/tools/libs/ctrl/xc_pm.c xen-4.20.2+7-g1badcf5035/tools/libs/ctrl/xc_pm.c --- xen-4.20.0+68-g35cb38b222/tools/libs/ctrl/xc_pm.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/libs/ctrl/xc_pm.c 2025-11-25 08:37:47.000000000 +0000 @@ -45,36 +45,34 @@ int xc_pm_get_pxstat(xc_interface *xch, int cpuid, struct xc_px_stat *pxpt) { struct xen_sysctl sysctl = {}; - /* Sizes unknown until xc_pm_get_max_px */ - DECLARE_NAMED_HYPERCALL_BOUNCE(trans, pxpt->trans_pt, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH); - DECLARE_NAMED_HYPERCALL_BOUNCE(pt, pxpt->pt, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH); + DECLARE_NAMED_HYPERCALL_BOUNCE(trans, pxpt->trans_pt, + pxpt->total * pxpt->total * sizeof(uint64_t), + XC_HYPERCALL_BUFFER_BOUNCE_BOTH); + DECLARE_NAMED_HYPERCALL_BOUNCE(pt, pxpt->pt, + pxpt->total * sizeof(struct xc_px_val), + XC_HYPERCALL_BUFFER_BOUNCE_BOTH); - int max_px, ret; + int ret; if ( !pxpt->trans_pt || !pxpt->pt ) { errno = EINVAL; return -1; } - if ( (ret = xc_pm_get_max_px(xch, cpuid, &max_px)) != 0) - return ret; - - HYPERCALL_BOUNCE_SET_SIZE(trans, max_px * max_px * sizeof(uint64_t)); - HYPERCALL_BOUNCE_SET_SIZE(pt, max_px * sizeof(struct xc_px_val)); if ( xc_hypercall_bounce_pre(xch, trans) ) - return ret; + return -1; if ( xc_hypercall_bounce_pre(xch, pt) ) { xc_hypercall_bounce_post(xch, trans); - return ret; + return -1; } sysctl.cmd = XEN_SYSCTL_get_pmstat; sysctl.u.get_pmstat.type = PMSTAT_get_pxstat; sysctl.u.get_pmstat.cpuid = cpuid; - sysctl.u.get_pmstat.u.getpx.total = max_px; + sysctl.u.get_pmstat.u.getpx.total = pxpt->total; set_xen_guest_handle(sysctl.u.get_pmstat.u.getpx.trans_pt, trans); set_xen_guest_handle(sysctl.u.get_pmstat.u.getpx.pt, pt); diff -Nru xen-4.20.0+68-g35cb38b222/tools/libs/light/libxl_cpuid.c xen-4.20.2+7-g1badcf5035/tools/libs/light/libxl_cpuid.c --- xen-4.20.0+68-g35cb38b222/tools/libs/light/libxl_cpuid.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/libs/light/libxl_cpuid.c 2025-11-25 08:37:47.000000000 +0000 @@ -342,6 +342,7 @@ CPUID_ENTRY(0x00000007, 1, CPUID_REG_EDX), MSR_ENTRY(0x10a, CPUID_REG_EAX), MSR_ENTRY(0x10a, CPUID_REG_EDX), + CPUID_ENTRY(0x80000021, NA, CPUID_REG_ECX), #undef MSR_ENTRY #undef CPUID_ENTRY }; diff -Nru xen-4.20.0+68-g35cb38b222/tools/libs/light/libxl_pci.c xen-4.20.2+7-g1badcf5035/tools/libs/light/libxl_pci.c --- xen-4.20.0+68-g35cb38b222/tools/libs/light/libxl_pci.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/libs/light/libxl_pci.c 2025-11-25 08:37:47.000000000 +0000 @@ -2179,7 +2179,7 @@ { STATE_AO_GC(prs->aodev->ao); libxl_ctx *ctx = libxl__gc_owner(gc); - unsigned int start = 0, end = 0, flags = 0, size = 0; + uint64_t start = 0, end = 0, flags = 0, size = 0; int irq = 0, i, stubdomid = 0; const char *sysfs_path; FILE *f; @@ -2209,7 +2209,8 @@ } for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) { - if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3) + if (fscanf(f, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64"\n", + &start, &end, &flags) != 3) continue; size = end - start + 1; if (start) { @@ -2218,7 +2219,7 @@ size, 0); if (rc < 0) LOGED(ERROR, domid, - "xc_domain_ioport_permission error 0x%x/0x%x", + "xc_domain_ioport_permission error %#"PRIx64"/%#"PRIx64, start, size); } else { @@ -2228,7 +2229,7 @@ 0); if (rc < 0) LOGED(ERROR, domid, - "xc_domain_iomem_permission error 0x%x/0x%x", + "xc_domain_iomem_permission error %#"PRIx64"/%#"PRIx64, start, size); } diff -Nru xen-4.20.0+68-g35cb38b222/tools/libs/light/libxl_x86.c xen-4.20.2+7-g1badcf5035/tools/libs/light/libxl_x86.c --- xen-4.20.0+68-g35cb38b222/tools/libs/light/libxl_x86.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/libs/light/libxl_x86.c 2025-11-25 08:37:47.000000000 +0000 @@ -804,17 +804,19 @@ libxl_defbool_setdefault(&b_info->acpi, true); libxl_defbool_setdefault(&b_info->arch_x86.msr_relaxed, false); - /* - * The config parameter "altp2m" replaces the parameter "altp2mhvm". - * For legacy reasons, both parameters are accepted on x86 HVM guests. - * - * If the legacy field info->u.hvm.altp2m is set, activate altp2m. - * Otherwise set altp2m based on the field info->altp2m. - */ - libxl_defbool_setdefault(&b_info->u.hvm.altp2m, false); - if (b_info->altp2m == LIBXL_ALTP2M_MODE_DISABLED && - libxl_defbool_val(b_info->u.hvm.altp2m)) - b_info->altp2m = libxl_defbool_val(b_info->u.hvm.altp2m); + if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) { + /* + * The config parameter "altp2m" replaces the parameter "altp2mhvm". + * For legacy reasons, both parameters are accepted on x86 HVM guests. + * + * If the legacy field info->u.hvm.altp2m is set, activate altp2m. + * Otherwise set altp2m based on the field info->altp2m. + */ + libxl_defbool_setdefault(&b_info->u.hvm.altp2m, false); + if (b_info->altp2m == LIBXL_ALTP2M_MODE_DISABLED && + libxl_defbool_val(b_info->u.hvm.altp2m)) + b_info->altp2m = libxl_defbool_val(b_info->u.hvm.altp2m); + } return 0; } diff -Nru xen-4.20.0+68-g35cb38b222/tools/misc/mktarball xen-4.20.2+7-g1badcf5035/tools/misc/mktarball --- xen-4.20.0+68-g35cb38b222/tools/misc/mktarball 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/misc/mktarball 2025-11-25 08:37:47.000000000 +0000 @@ -5,14 +5,6 @@ # Takes 2 arguments, the path to the dist directory and the version set -ex -function git_archive_into { - mkdir -p "$2" - - git --git-dir="$1"/.git \ - archive --format=tar HEAD | \ - tar Cxf "$2" - -} - if [[ -z "$1" || -z "$2" ]] ; then echo "usage: $0 path-to-XEN_ROOT xen-version" exit 1 @@ -21,14 +13,15 @@ xen_root="$1" desc="$2" -tdir="$xen_root/dist/tmp.src-tarball" +tdir="$xen_root/dist" -rm -rf $tdir +rm -f $tdir/xen-$desc.tar* mkdir -p $tdir -git_archive_into $xen_root $tdir/xen-$desc +git --git-dir="$xen_root/.git" archive --format=tar HEAD --prefix=xen-$desc/ \ + >"$tdir/xen-$desc.tar" -GZIP=-9v tar cz -f $xen_root/dist/xen-$desc.tar.gz -C $tdir xen-$desc +gzip -9k "$tdir/xen-$desc.tar" echo "Source tarball in $xen_root/dist/xen-$desc.tar.gz" diff -Nru xen-4.20.0+68-g35cb38b222/tools/misc/xen-cpuid.c xen-4.20.2+7-g1badcf5035/tools/misc/xen-cpuid.c --- xen-4.20.0+68-g35cb38b222/tools/misc/xen-cpuid.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/misc/xen-cpuid.c 2025-11-25 08:37:47.000000000 +0000 @@ -37,6 +37,7 @@ { "CPUID 0x00000007:1.edx", "7d1" }, { "MSR_ARCH_CAPS.lo", "m10Al" }, { "MSR_ARCH_CAPS.hi", "m10Ah" }, + { "CPUID 0x80000021.ecx", "e21c" }, }; #define COL_ALIGN "24" diff -Nru xen-4.20.0+68-g35cb38b222/tools/misc/xenpm.c xen-4.20.2+7-g1badcf5035/tools/misc/xenpm.c --- xen-4.20.0+68-g35cb38b222/tools/misc/xenpm.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/misc/xenpm.c 2025-11-25 08:37:47.000000000 +0000 @@ -312,28 +312,42 @@ int ret = 0; int max_px_num = 0; - ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px_num); - if ( ret ) - return -errno; - if ( !pxstat) return -EINVAL; - pxstat->trans_pt = malloc(max_px_num * max_px_num * - sizeof(uint64_t)); - if ( !pxstat->trans_pt ) - return -ENOMEM; - pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); - if ( !pxstat->pt ) + for ( ; ; ) { - free(pxstat->trans_pt); - return -ENOMEM; - } + ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px_num); + if ( ret ) + return -errno; - ret = xc_pm_get_pxstat(xc_handle, cpuid, pxstat); - if( ret ) - { - ret = -errno; + pxstat->total = max_px_num; + pxstat->trans_pt = malloc(max_px_num * max_px_num * + sizeof(uint64_t)); + if ( !pxstat->trans_pt ) + return -ENOMEM; + pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); + if ( !pxstat->pt ) + { + free(pxstat->trans_pt); + return -ENOMEM; + } + + ret = xc_pm_get_pxstat(xc_handle, cpuid, pxstat); + if ( ret ) + { + ret = -errno; + free(pxstat->trans_pt); + free(pxstat->pt); + pxstat->trans_pt = NULL; + pxstat->pt = NULL; + break; + } + + if ( pxstat->total <= max_px_num ) + break; + + /* get_max_px changed under our feet so the data is incomplete. */ free(pxstat->trans_pt); free(pxstat->pt); pxstat->trans_pt = NULL; diff -Nru xen-4.20.0+68-g35cb38b222/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile xen-4.20.2+7-g1badcf5035/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile --- xen-4.20.0+68-g35cb38b222/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/ocaml/libs/xsd_glue/domain_getinfo_plugin_v1/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -11,7 +11,7 @@ INTF = $(foreach obj, $(OBJS),$(obj).cmi) LIBS = domain_getinfo_v1.cmxa domain_getinfo_v1.cmxs -LIBS_xsd_glue = $(call xenlibs-ldflags-ldlibs,xenctrl) +LIBS_domain_getinfo_v1 = $(call xenlibs-ldflags-ldlibs,ctrl) all: $(INTF) $(LIBS) $(PROGRAMS) diff -Nru xen-4.20.0+68-g35cb38b222/tools/tests/x86_emulator/Makefile xen-4.20.2+7-g1badcf5035/tools/tests/x86_emulator/Makefile --- xen-4.20.0+68-g35cb38b222/tools/tests/x86_emulator/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/tests/x86_emulator/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -98,7 +98,7 @@ # partially even with older compilers. TARGET-y := $(TARGET) -ifeq ($(filter run%,$(MAKECMDGOALS)),) +ifneq ($(filter-out run% clean% distclean,$(MAKECMDGOALS)),) define isa-check-cc TARGET-$(shell echo 'int i;' | $(CC) -x c -c -o /dev/null -m$(1) - || echo y) := @@ -261,7 +261,8 @@ .PHONY: clean clean: rm -rf $(TARGET) *.o *~ core *.bin x86_emulate - rm -rf $(TARGET) $(addsuffix .h,$(TESTCASES)) $(addsuffix -opmask.h,$(OPMASK)) + rm -rf $(addsuffix .h,$(TESTCASES)) $(addsuffix -opmask.h,$(OPMASK)) + rm -rf $(addsuffix .c,$(filter-out blowfish,$(TESTCASES))) .PHONY: distclean distclean: clean diff -Nru xen-4.20.0+68-g35cb38b222/tools/tests/x86_emulator/x86-emulate.h xen-4.20.2+7-g1badcf5035/tools/tests/x86_emulator/x86-emulate.h --- xen-4.20.0+68-g35cb38b222/tools/tests/x86_emulator/x86-emulate.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/tests/x86_emulator/x86-emulate.h 2025-11-25 08:37:47.000000000 +0000 @@ -77,6 +77,12 @@ #define is_canonical_address(x) (((int64_t)(x) >> 47) == ((int64_t)(x) >> 63)) +static inline void *place_ret(void *ptr) +{ + *(uint8_t *)ptr = 0xc3; + return ptr + 1; +} + extern uint32_t mxcsr_mask; extern struct cpu_policy cpu_policy; diff -Nru xen-4.20.0+68-g35cb38b222/tools/xentrace/xenalyze.c xen-4.20.2+7-g1badcf5035/tools/xentrace/xenalyze.c --- xen-4.20.0+68-g35cb38b222/tools/xentrace/xenalyze.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/xentrace/xenalyze.c 2025-11-25 08:37:47.000000000 +0000 @@ -321,11 +321,10 @@ (*p)->next=NULL; } - /* FIXME -- use SYMBOL_NAME_SIZE */ /* FIXME -- use regexp. This won't work for symbols with spaces (yes they exist) */ (*p)->symbols[(*p)->count].addr = 0xDEADBEEF; - if ( fscanf(symbol_file, "%llx %128s", - &(*p)->symbols[(*p)->count].addr, + if ( fscanf(symbol_file, "%llx %" STR(SYMBOL_NAME_SIZE) "s", + &(*p)->symbols[(*p)->count].addr, (*p)->symbols[(*p)->count].name) == 0 ) break; @@ -6513,7 +6512,8 @@ "register_runstate_memory_area", "set_periodic_timer", "stop_periodic_timer", "set_singleshot_timer", "stop_singleshot_timer", "register_vcpu_info", "send_nmi", "get_physid", - "register_vcpu_time_memory_area", + "register_vcpu_time_memory_area", "register_runstate_phys_area", + "register_vcpu_time_phys_area", }; static const char *sched_op_str[] = { diff -Nru xen-4.20.0+68-g35cb38b222/tools/xl/xl.c xen-4.20.2+7-g1badcf5035/tools/xl/xl.c --- xen-4.20.0+68-g35cb38b222/tools/xl/xl.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/tools/xl/xl.c 2025-11-25 08:37:47.000000000 +0000 @@ -79,7 +79,7 @@ int ret; info = libxl_get_version_info(ctx); - if (!info) + if (!info || !info->commandline) return 1; /* default to on */ #define SIZE_PATTERN "-?[0-9]+[bBkKmMgGtT]?" diff -Nru xen-4.20.0+68-g35cb38b222/xen/Kconfig xen-4.20.2+7-g1badcf5035/xen/Kconfig --- xen-4.20.0+68-g35cb38b222/xen/Kconfig 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/Kconfig 2025-11-25 08:37:47.000000000 +0000 @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see docs/misc/kconfig-language.txt +# see https://www.kernel.org/doc/html/v5.4/kbuild/kconfig-language.html # mainmenu "Xen/$(SRCARCH) $(XEN_FULLVERSION) Configuration" diff -Nru xen-4.20.0+68-g35cb38b222/xen/Makefile xen-4.20.2+7-g1badcf5035/xen/Makefile --- xen-4.20.0+68-g35cb38b222/xen/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -6,7 +6,7 @@ # All other places this is stored (eg. compile.h) should be autogenerated. export XEN_VERSION = 4 export XEN_SUBVERSION = 20 -export XEN_EXTRAVERSION ?= .1-pre$(XEN_VENDORVERSION) +export XEN_EXTRAVERSION ?= .3-pre$(XEN_VENDORVERSION) export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) -include xen-version @@ -396,6 +396,7 @@ CFLAGS-$(CONFIG_CC_SPLIT_SECTIONS) += -ffunction-sections -fdata-sections CFLAGS += -nostdinc -fno-builtin -fno-common +$(call cc-option-add,CFLAGS,CC,-fzero-init-padding-bits=all) CFLAGS += -Werror -Wredundant-decls -Wwrite-strings -Wno-pointer-arith CFLAGS += -Wdeclaration-after-statement -Wuninitialized $(call cc-option-add,CFLAGS,CC,-Wvla) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/arm/include/asm/pci.h xen-4.20.2+7-g1badcf5035/xen/arch/arm/include/asm/pci.h --- xen-4.20.0+68-g35cb38b222/xen/arch/arm/include/asm/pci.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/arm/include/asm/pci.h 2025-11-25 08:37:47.000000000 +0000 @@ -128,6 +128,9 @@ bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end); +static inline int pci_sanitize_bar_memory(struct rangeset *r) +{ return 0; } + #else /*!CONFIG_HAS_PCI*/ struct pci_dev; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/arm/p2m.c xen-4.20.2+7-g1badcf5035/xen/arch/arm/p2m.c --- xen-4.20.0+68-g35cb38b222/xen/arch/arm/p2m.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/arm/p2m.c 2025-11-25 08:37:47.000000000 +0000 @@ -53,18 +53,22 @@ struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn, p2m_type_t *t) { + struct p2m_domain *p2m = p2m_get_hostp2m(d); struct page_info *page; p2m_type_t p2mt; - mfn_t mfn = p2m_lookup(d, gfn, &p2mt); + mfn_t mfn; + + p2m_read_lock(p2m); + mfn = p2m_get_entry(p2m, gfn, &p2mt, NULL, NULL, NULL); if ( t ) *t = p2mt; - if ( !p2m_is_any_ram(p2mt) ) - return NULL; - - if ( !mfn_valid(mfn) ) + if ( !p2m_is_any_ram(p2mt) || !mfn_valid(mfn) ) + { + p2m_read_unlock(p2m); return NULL; + } page = mfn_to_page(mfn); @@ -74,12 +78,22 @@ */ if ( p2m_is_foreign(p2mt) ) { - struct domain *fdom = page_get_owner_and_reference(page); - ASSERT(fdom != NULL); - ASSERT(fdom != d); - return page; + const struct domain *fdom = page_get_owner_and_reference(page); + + p2m_read_unlock(p2m); + + if ( fdom ) + { + if ( fdom != d ) + return page; + ASSERT_UNREACHABLE(); + put_page(page); + } + return NULL; } + p2m_read_unlock(p2m); + return get_page(page, d) ? page : NULL; } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/Kconfig xen-4.20.2+7-g1badcf5035/xen/arch/x86/Kconfig --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/Kconfig 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/Kconfig 2025-11-25 08:37:47.000000000 +0000 @@ -38,9 +38,14 @@ default "arch/x86/configs/x86_64_defconfig" config CC_HAS_INDIRECT_THUNK + # GCC >= 8 or Clang >= 6 def_bool $(cc-option,-mindirect-branch-register) || \ $(cc-option,-mretpoline-external-thunk) +config CC_HAS_RETURN_THUNK + # GCC >= 8 or Clang >= 15 + def_bool $(cc-option,-mfunction-return=thunk-extern) + config HAS_AS_CET_SS # binutils >= 2.29 or LLVM >= 6 def_bool $(as-instr,wrssq %rax$(comma)0;setssbsy) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/Makefile xen-4.20.2+7-g1badcf5035/xen/arch/x86/Makefile --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -11,9 +11,7 @@ obj-y += x86_64/ obj-y += x86_emulate/ -alternative-y := alternative.init.o -alternative-$(CONFIG_LIVEPATCH) := -obj-bin-y += $(alternative-y) +obj-y += alternative.o obj-y += apic.o obj-y += bhb-thunk.o obj-y += bitops.o @@ -41,10 +39,11 @@ obj-y += i387.o obj-y += i8259.o obj-y += io_apic.o -obj-$(CONFIG_LIVEPATCH) += alternative.o livepatch.o +obj-$(CONFIG_LIVEPATCH) += livepatch.o obj-y += msi.o obj-y += msr.o obj-$(CONFIG_INDIRECT_THUNK) += indirect-thunk.o +obj-$(CONFIG_RETURN_THUNK) += indirect-thunk.o obj-$(CONFIG_PV) += ioport_emulate.o obj-y += irq.o obj-$(CONFIG_KEXEC) += machine_kexec.o @@ -127,8 +126,7 @@ $(TARGET): TMP = $(dot-target).elf32 $(TARGET): $(TARGET)-syms $(efi-y) $(obj)/boot/mkelf32 - $(obj)/boot/mkelf32 $(notes_phdrs) $(TARGET)-syms $(TMP) $(XEN_IMG_OFFSET) \ - `$(NM) $(TARGET)-syms | sed -ne 's/^\([^ ]*\) . __2M_rwdata_end$$/0x\1/p'` + $(obj)/boot/mkelf32 $(notes_phdrs) $(TARGET)-syms $(TMP) $(XEN_IMG_OFFSET) od -t x4 -N 8192 $(TMP) | grep 1badb002 > /dev/null || \ { echo "No Multiboot1 header found" >&2; false; } od -t x4 -N 32768 $(TMP) | grep e85250d6 > /dev/null || \ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/boot.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/boot.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/boot.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/boot.c 2025-11-25 08:37:47.000000000 +0000 @@ -748,8 +748,6 @@ acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); - acpi_mmcfg_init(); - erst_init(); acpi_hest_init(); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/cpu_idle.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/cpu_idle.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/cpu_idle.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/cpu_idle.c 2025-11-25 08:37:47.000000000 +0000 @@ -60,6 +60,33 @@ /*#define DEBUG_PM_CX*/ +static always_inline void monitor( + const void *addr, unsigned int ecx, unsigned int edx) +{ + alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, + [addr] "a" (addr)); + + /* + * The memory clobber is a compiler barrier. Subseqeunt reads from the + * monitored cacheline must not be reordered over MONITOR. + */ + asm volatile ( ".byte 0x0f, 0x01, 0xc8" /* monitor */ + :: "a" (addr), "c" (ecx), "d" (edx) : "memory" ); +} + +static always_inline void mwait(unsigned int eax, unsigned int ecx) +{ + asm volatile ( ".byte 0x0f, 0x01, 0xc9" /* mwait */ + :: "a" (eax), "c" (ecx) ); +} + +static always_inline void sti_mwait_cli(unsigned int eax, unsigned int ecx) +{ + /* STI shadow covers MWAIT. */ + asm volatile ( "sti; .byte 0x0f, 0x01, 0xc9;" /* mwait */ " cli" + :: "a" (eax), "c" (ecx) ); +} + #define GET_HW_RES_IN_NS(msr, val) \ do { rdmsrl(msr, val); val = tsc_ticks2ns(val); } while( 0 ) #define GET_MC6_RES(val) GET_HW_RES_IN_NS(0x664, val) @@ -420,78 +447,59 @@ } __initcall(cpu_idle_key_init); -/* - * The bit is set iff cpu use monitor/mwait to enter C state - * with this flag set, CPU can be waken up from C state - * by writing to specific memory address, instead of sending an IPI. - */ -static cpumask_t cpuidle_mwait_flags; - -void cpuidle_wakeup_mwait(cpumask_t *mask) +void mwait_idle_with_hints(unsigned int eax, unsigned int ecx) { - cpumask_t target; - unsigned int cpu; - - cpumask_and(&target, mask, &cpuidle_mwait_flags); - - /* CPU is MWAITing on the cpuidle_mwait_wakeup flag. */ - for_each_cpu(cpu, &target) - mwait_wakeup(cpu) = 0; - - cpumask_andnot(mask, mask, &target); -} - -/* Force sending of a wakeup IPI regardless of mwait usage. */ -bool __ro_after_init force_mwait_ipi_wakeup; + unsigned int cpu = smp_processor_id(); + struct cpu_info *info = get_cpu_info(); + irq_cpustat_t *stat = &irq_stat[cpu]; + const unsigned int *this_softirq_pending = &stat->__softirq_pending; -bool arch_skip_send_event_check(unsigned int cpu) -{ - if ( force_mwait_ipi_wakeup ) - return false; + /* + * Heuristic: if we're definitely not going to idle, bail early as the + * speculative safety can be expensive. This is a performance + * consideration not a correctness issue. + */ + if ( *this_softirq_pending ) + return; /* - * This relies on softirq_pending() and mwait_wakeup() to access data - * on the same cache line. + * By setting in_mwait, we promise to other CPUs that we'll notice changes + * to __softirq_pending without being sent an IPI. We achieve this by + * either not going to sleep, or by having hardware notice on our behalf. + * + * Some errata exist where MONITOR doesn't work properly, and the + * workaround is to force the use of an IPI. Cause this to happen by + * simply not advertising ourselves as being in_mwait. */ - smp_mb(); - return !!cpumask_test_cpu(cpu, &cpuidle_mwait_flags); -} + alternative_io("movb $1, %[in_mwait]", + "", X86_BUG_MONITOR, + [in_mwait] "=m" (stat->in_mwait)); -void mwait_idle_with_hints(unsigned int eax, unsigned int ecx) -{ - unsigned int cpu = smp_processor_id(); - s_time_t expires = per_cpu(timer_deadline, cpu); - const void *monitor_addr = &mwait_wakeup(cpu); + /* + * On AMD systems, side effects from VERW cancel MONITOR, causing MWAIT to + * wake up immediately. Therefore, VERW must come ahead of MONITOR. + */ + __spec_ctrl_enter_idle_verw(info); - if ( boot_cpu_has(X86_FEATURE_CLFLUSH_MONITOR) ) - { - mb(); - clflush(monitor_addr); - mb(); - } + monitor(this_softirq_pending, 0, 0); - __monitor(monitor_addr, 0, 0); - smp_mb(); + ASSERT(!local_irq_is_enabled()); - /* - * Timer deadline passing is the event on which we will be woken via - * cpuidle_mwait_wakeup. So check it now that the location is armed. - */ - if ( (expires > NOW() || expires == 0) && !softirq_pending(cpu) ) + if ( !*this_softirq_pending ) { - struct cpu_info *info = get_cpu_info(); + __spec_ctrl_enter_idle(info, false /* VERW handled above */); - cpumask_set_cpu(cpu, &cpuidle_mwait_flags); + if ( ecx & MWAIT_ECX_INTERRUPT_BREAK ) + mwait(eax, ecx); + else + sti_mwait_cli(eax, ecx); - spec_ctrl_enter_idle(info); - __mwait(eax, ecx); spec_ctrl_exit_idle(info); - - cpumask_clear_cpu(cpu, &cpuidle_mwait_flags); } - if ( expires <= NOW() && expires > 0 ) - raise_softirq(TIMER_SOFTIRQ); + alternative_io("movb $0, %[in_mwait]", + "", X86_BUG_MONITOR, + [in_mwait] "=m" (stat->in_mwait)); } static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) @@ -576,18 +584,24 @@ { #define INTEL_FAM6_MODEL(m) { X86_VENDOR_INTEL, 6, m, X86_FEATURE_ALWAYS } /* - * Errata AAJ72: EOI Transaction May Not be Sent if Software Enters - * Core C6 During an Interrupt Service Routine" + * Errata AAJ72, etc: EOI Transaction May Not be Sent if Software + * Enters Core C6 During an Interrupt Service Routine + * + * If core C6 is entered after the start of an interrupt service + * routine but before a write to the APIC EOI (End of Interrupt) + * register, and the core is woken up by an event other than a fixed + * interrupt source the core may drop the EOI transaction the next + * time APIC EOI register is written and further interrupts from the + * same or lower priority level will be blocked. * - * There was an errata with some Core i7 processors that an EOI - * transaction may not be sent if software enters core C6 during an - * interrupt service routine. So we don't enter deep Cx state if - * there is an EOI pending. + * Software should check the ISR register and if any interrupts are in + * service only enter C1. */ static const struct x86_cpu_id eoi_errata[] = { - INTEL_FAM6_MODEL(0x1a), + INTEL_FAM6_MODEL(0x1a), /* AAJ72 */ INTEL_FAM6_MODEL(0x1e), INTEL_FAM6_MODEL(0x1f), + INTEL_FAM6_MODEL(0x2e), /* BA106 */ INTEL_FAM6_MODEL(0x25), INTEL_FAM6_MODEL(0x2c), INTEL_FAM6_MODEL(0x2f), @@ -892,7 +906,7 @@ if ( cx->entry_method == ACPI_CSTATE_EM_FFH ) { - void *mwait_ptr = &mwait_wakeup(smp_processor_id()); + void *mwait_ptr = &softirq_pending(smp_processor_id()); /* * Cache must be flushed as the last operation before sleeping. @@ -904,20 +918,8 @@ while ( 1 ) { - /* - * 1. The CLFLUSH is a workaround for erratum AAI65 for - * the Xeon 7400 series. - * 2. The WBINVD is insufficient due to the spurious-wakeup - * case where we return around the loop. - * 3. Unlike wbinvd, clflush is a light weight but not serializing - * instruction, hence memory fence is necessary to make sure all - * load/store visible before flush cache line. - */ - mb(); - clflush(mwait_ptr); - __monitor(mwait_ptr, 0, 0); - mb(); - __mwait(cx->address, 0); + monitor(mwait_ptr, 0, 0); + mwait(cx->address, 0); } } else if ( (current_cpu_data.x86_vendor & diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/cpufreq/hwp.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/cpufreq/hwp.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/cpufreq/hwp.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/cpufreq/hwp.c 2025-11-25 08:37:47.000000000 +0000 @@ -17,7 +17,7 @@ static bool __ro_after_init feature_hwp_notification; static bool __ro_after_init feature_hwp_activity_window; -static bool __ro_after_init feature_hdc; +static bool __read_mostly feature_hdc; static bool __ro_after_init opt_cpufreq_hdc = true; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/power.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/power.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/power.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/power.c 2025-11-25 08:37:47.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -301,6 +302,7 @@ } update_mcu_opt_ctrl(); + update_pb_opt_ctrl(); /* * This should be before restoring CR4, but that is earlier in asm and @@ -331,6 +333,7 @@ thaw_domains(); system_state = SYS_STATE_active; spin_unlock(&pm_lock); + raise_softirq(TIMER_SOFTIRQ); return error; } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/wakeup_prot.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/wakeup_prot.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/acpi/wakeup_prot.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/acpi/wakeup_prot.S 2025-11-25 08:37:47.000000000 +0000 @@ -133,7 +133,7 @@ pop %r12 pop %rbx pop %rbp - ret + RET END(do_suspend_lowlevel) .data diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/alternative.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/alternative.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/alternative.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/alternative.c 2025-11-25 08:37:47.000000000 +0000 @@ -137,6 +137,49 @@ } } +void nocall __x86_return_thunk(void); + +/* + * Place a return at @ptr. @ptr must be in the writable alias of a stub. + * + * When CONFIG_RETURN_THUNK is active, this may be a JMP __x86_return_thunk + * instead, depending on the safety of @ptr with respect to Indirect Target + * Selection. + * + * Returns the next position to write into the stub. + */ +void *place_ret(void *ptr) +{ + unsigned long addr = (unsigned long)ptr; + uint8_t *p = ptr; + + /* + * When Return Thunks are used, if a RET would be unsafe at this location + * with respect to Indirect Target Selection (i.e. if addr is in the first + * half of a cacheline), insert a JMP __x86_return_thunk instead. + * + * The displacement needs to be relative to the executable alias of the + * stub, not to @ptr which is the writeable alias. + */ + if ( IS_ENABLED(CONFIG_RETURN_THUNK) && !(addr & 0x20) ) + { + long stub_va = (this_cpu(stubs.addr) & PAGE_MASK) + (addr & ~PAGE_MASK); + long disp = (long)__x86_return_thunk - (stub_va + 5); + + BUG_ON((int32_t)disp != disp); + + *p++ = 0xe9; + *(int32_t *)p = disp; + p += 4; + } + else + { + *p++ = 0xc3; + } + + return p; +} + /* * text_poke - Update instructions on a live kernel or non-executed code. * @addr: address to modify @@ -152,13 +195,18 @@ * You should run this with interrupts disabled or on code that is not * executing. * - * "noinline" to cause control flow change and thus invalidate I$ and - * cause refetch after modification. + * While the SDM continues to suggest using "noinline" would be sufficient, it + * may not be, e.g. due to errata. Issue a serializing insn afterwards, unless + * this is for live-patching, where we modify code before it goes live. Issue + * a serializing insn which is unlikely to be intercepted by a hypervisor, in + * case we run virtualized ourselves. */ -static void init_or_livepatch noinline +static void init_or_livepatch text_poke(void *addr, const void *opcode, size_t len) { memcpy(addr, opcode, len); + if ( system_state < SYS_STATE_active ) + asm volatile ( "mov %0, %%cr2" :: "r" (0L) : "memory" ); } extern void *const __initdata_cf_clobber_start[]; @@ -197,6 +245,8 @@ uint8_t *repl = ALT_REPL_PTR(a); uint8_t buf[MAX_PATCH_LEN]; unsigned int total_len = a->orig_len + a->pad_len; + unsigned int feat = a->cpuid & ~ALT_FLAG_NOT; + bool inv = a->cpuid & ALT_FLAG_NOT, replace; if ( a->repl_len > total_len ) { @@ -214,11 +264,11 @@ return -ENOSPC; } - if ( a->cpuid >= NCAPINTS * 32 ) + if ( feat >= NCAPINTS * 32 ) { printk(XENLOG_ERR "Alt for %ps, feature %#x outside of featureset range %#x\n", - ALT_ORIG_PTR(a), a->cpuid, NCAPINTS * 32); + ALT_ORIG_PTR(a), feat, NCAPINTS * 32); return -ERANGE; } @@ -243,8 +293,14 @@ continue; } + /* + * Should a replacement be performed? Most replacements have positive + * polarity, but we support negative polarity too. + */ + replace = boot_cpu_has(feat) ^ inv; + /* If there is no replacement to make, see about optimising the nops. */ - if ( !boot_cpu_has(a->cpuid) ) + if ( !replace ) { /* Origin site site already touched? Don't nop anything. */ if ( base->priv ) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/apic.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/apic.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/apic.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/apic.c 2025-11-25 08:37:47.000000000 +0000 @@ -65,7 +65,6 @@ unsigned int apic_lvt0; unsigned int apic_lvt1; unsigned int apic_lvterr; - unsigned int apic_tmict; unsigned int apic_tdcr; unsigned int apic_thmr; } apic_pm_state; @@ -658,7 +657,6 @@ apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); - apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); if (maxlvt >= 5) apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); @@ -718,7 +716,6 @@ apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); - apic_write(APIC_TMICT, apic_pm_state.apic_tmict); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/arch.mk xen-4.20.2+7-g1badcf5035/xen/arch/x86/arch.mk --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/arch.mk 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/arch.mk 2025-11-25 08:37:47.000000000 +0000 @@ -44,6 +44,9 @@ CFLAGS-$(CONFIG_CC_IS_CLANG) += -mretpoline-external-thunk endif +# Compile with return thunk support if selected. +CFLAGS-$(CONFIG_RETURN_THUNK) += -mfunction-return=thunk-extern + # Disable the addition of a .note.gnu.property section to object files when # livepatch support is enabled. The contents of that section can change # depending on the instructions used, and livepatch-build-tools doesn't know diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/bhb-thunk.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/bhb-thunk.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/bhb-thunk.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/bhb-thunk.S 2025-11-25 08:37:47.000000000 +0000 @@ -23,7 +23,7 @@ 0: .byte 0xc6, 0xf8, 0 /* xabort $0 */ int3 1: - ret + RET END(clear_bhb_tsx) /* @@ -50,7 +50,12 @@ * ret * * The CALL/RETs are necessary to prevent the Loop Stream Detector from - * interfering. The alignment is for performance and not safety. + * interfering. + * + * The .balign's are for performance, but they cause the RETs to be in unsafe + * positions with respect to Indirect Target Selection. The .skips are to + * move the RETs into ITS-safe positions, rather than using the slowpath + * through __x86_return_thunk. * * The "short" sequence (5 and 5) is for CPUs prior to Alder Lake / Sapphire * Rapids (i.e. Cores prior to Golden Cove and/or Gracemont). @@ -66,12 +71,14 @@ jmp 5f int3 - .align 64 + .balign 64 + .skip 32 - (.Lr1 - 1f), 0xcc 1: call 2f - ret +.Lr1: ret int3 - .align 64 + .balign 64 + .skip 32 - 18 /* (.Lr2 - 2f) but Clang IAS doesn't like this */, 0xcc 2: ALTERNATIVE "mov $5, %eax", "mov $7, %eax", X86_SPEC_BHB_LOOPS_LONG 3: jmp 4f @@ -83,7 +90,7 @@ sub $1, %ecx jnz 1b - ret +.Lr2: ret 5: /* * The Intel sequence has an LFENCE here. The purpose is to ensure diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/boot/edd.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/boot/edd.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/boot/edd.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/boot/edd.S 2025-11-25 08:37:47.000000000 +0000 @@ -25,7 +25,7 @@ get_edd: cmpb $2, bootsym(opt_edd) # edd=off ? - je edd_done + je .Ledd_done # Do the BIOS Enhanced Disk Drive calls # This consists of two calls: @@ -48,7 +48,7 @@ movb $0x41, %ah # 0x41 Check Extensions Present movw $0x55AA, %bx # magic int $0x13 # make the call - jc edd_done # no more BIOS devices + jc .Ledd_mbr_sig # no more BIOS devices cmpw $0xAA55, %bx # is magic right? jne edd_next # nope, next... @@ -96,13 +96,13 @@ edd_next: incb %dl # increment to next device - jz edd_done + jz .Ledd_mbr_sig cmpb $EDD_INFO_MAX,bootsym(boot_edd_info_nr) jb edd_check_ext -edd_done: +.Ledd_mbr_sig: cmpb $1, bootsym(opt_edd) # edd=skipmbr ? - je .Ledd_mbr_sig_skip + je .Ledd_done # Read the first sector of each BIOS disk device and store the 4-byte signature .Ledd_mbr_sig_start: @@ -160,7 +160,7 @@ jb .Ledd_mbr_sig_read .Ledd_mbr_sig_done: popw %es -.Ledd_mbr_sig_skip: +.Ledd_done: ret GLOBAL(boot_edd_info_nr) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/boot/mkelf32.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/boot/mkelf32.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/boot/mkelf32.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/boot/mkelf32.c 2025-11-25 08:37:47.000000000 +0000 @@ -248,7 +248,6 @@ int main(int argc, char **argv) { - uint64_t final_exec_addr; uint32_t loadbase, dat_siz, mem_siz, note_base, note_sz, offset; char *inimage, *outimage; int infd, outfd; @@ -261,22 +260,24 @@ Elf64_Ehdr in64_ehdr; Elf64_Phdr in64_phdr; - if ( argc < 5 ) + if ( argc < 4 ) { + help: fprintf(stderr, "Usage: mkelf32 [--notes] " - " \n"); + "\n"); return 1; } if ( !strcmp(argv[1], "--notes") ) { + if ( argc < 5 ) + goto help; i = 2; num_phdrs = 2; } inimage = argv[i++]; outimage = argv[i++]; loadbase = strtoul(argv[i++], NULL, 16); - final_exec_addr = strtoull(argv[i++], NULL, 16); infd = open(inimage, O_RDONLY); if ( infd == -1 ) @@ -339,9 +340,12 @@ (void)lseek(infd, in64_phdr.p_offset, SEEK_SET); dat_siz = (uint32_t)in64_phdr.p_filesz; - /* Do not use p_memsz: it does not include BSS alignment padding. */ - /*mem_siz = (uint32_t)in64_phdr.p_memsz;*/ - mem_siz = (uint32_t)(final_exec_addr - in64_phdr.p_vaddr); + /* + * We don't pad .bss in the linker script, but during early boot we map + * the Xen image using 2M pages. To avoid running into adjacent non-RAM + * regions, pad the segment to the next 2M boundary. + */ + mem_siz = ((uint32_t)in64_phdr.p_memsz + (1U << 20) - 1) & (-1U << 20); note_sz = note_base = offset = 0; if ( num_phdrs > 1 ) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/clear_page.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/clear_page.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/clear_page.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/clear_page.S 2025-11-25 08:37:47.000000000 +0000 @@ -1,6 +1,8 @@ .file __FILE__ #include + +#include #include FUNC(clear_page_sse2) @@ -16,5 +18,5 @@ jnz 0b sfence - ret + RET END(clear_page_sse2) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/copy_page.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/copy_page.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/copy_page.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/copy_page.S 2025-11-25 08:37:47.000000000 +0000 @@ -1,6 +1,8 @@ .file __FILE__ #include + +#include #include #define src_reg %rsi @@ -41,5 +43,5 @@ movnti tmp4_reg, 3*WORD_SIZE(dst_reg) sfence - ret + RET END(copy_page_sse2) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/common.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/common.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/common.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/common.c 2025-11-25 08:37:47.000000000 +0000 @@ -438,6 +438,13 @@ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); c->phys_proc_id = c->apicid; + /* + * Early init of Self Snoop support requires 0x1.edx, while there also + * set 0x1.ecx as the value is in context. + */ + c->x86_capability[FEATURESET_1c] = ecx; + c->x86_capability[FEATURESET_1d] = edx; + eax = cpuid_eax(0x80000000); if ((eax >> 16) == 0x8000) c->extended_cpuid_level = eax; @@ -478,7 +485,9 @@ if (c->extended_cpuid_level >= 0x80000008) c->x86_capability[FEATURESET_e8b] = cpuid_ebx(0x80000008); if (c->extended_cpuid_level >= 0x80000021) - c->x86_capability[FEATURESET_e21a] = cpuid_eax(0x80000021); + cpuid(0x80000021, + &c->x86_capability[FEATURESET_e21a], &tmp, + &c->x86_capability[FEATURESET_e21c], &tmp); /* Intel-defined flags: level 0x00000007 */ if (c->cpuid_level >= 7) { diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/intel.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/intel.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/intel.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/intel.c 2025-11-25 08:37:47.000000000 +0000 @@ -49,6 +49,34 @@ update_mcu_opt_ctrl(); } +static uint32_t __ro_after_init pb_opt_ctrl_mask; +static uint32_t __ro_after_init pb_opt_ctrl_val; + +void update_pb_opt_ctrl(void) +{ + uint32_t mask = pb_opt_ctrl_mask, lo, hi; + + if ( !mask ) + return; + + rdmsr(MSR_PB_OPT_CTRL, lo, hi); + + lo &= ~mask; + lo |= pb_opt_ctrl_val; + + wrmsr(MSR_PB_OPT_CTRL, lo, hi); +} + +void __init set_in_pb_opt_ctrl(uint32_t mask, uint32_t val) +{ + pb_opt_ctrl_mask |= mask; + + pb_opt_ctrl_val &= ~mask; + pb_opt_ctrl_val |= (val & mask); + + update_pb_opt_ctrl(); +} + /* * Processors which have self-snooping capability can handle conflicting * memory type across CPUs by snooping its own cache. However, there exists @@ -408,7 +436,7 @@ { printk(XENLOG_WARNING "Forcing IPI MWAIT wakeup due to CPU erratum\n"); - force_mwait_ipi_wakeup = true; + setup_force_cpu_cap(X86_BUG_MONITOR); } } @@ -418,6 +446,7 @@ * * Xeon 7400 erratum AAI65 (and further newer Xeons) * MONITOR/MWAIT may have excessive false wakeups + * https://web.archive.org/web/20090219054841/http://download.intel.com/design/xeon/specupdt/32033601.pdf */ static void Intel_errata_workarounds(struct cpuinfo_x86 *c) { @@ -435,7 +464,7 @@ if (c->x86 == 6 && cpu_has_clflush && (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47)) - __set_bit(X86_FEATURE_CLFLUSH_MONITOR, c->x86_capability); + setup_force_cpu_cap(X86_BUG_CLFLUSH_MONITOR); probe_c3_errata(c); if (system_state < SYS_STATE_smp_boot) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/mcheck/mce.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/mcheck/mce.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/mcheck/mce.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/mcheck/mce.c 2025-11-25 08:37:47.000000000 +0000 @@ -663,7 +663,7 @@ if ( !all ) return -ENOMEM; for ( i = 0; i < nr; i++ ) - mcabanks_set(i, mca_allbanks); + mcabanks_set(i, all); mcabanks_free(xchg(&mca_allbanks, all)); } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/mcheck/mce_intel.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/mcheck/mce_intel.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/mcheck/mce_intel.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/mcheck/mce_intel.c 2025-11-25 08:37:47.000000000 +0000 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -859,7 +860,7 @@ * other purposes. Despite the late addition of a CPUID bit (rendering * the MSR architectural), keep using the same detection logic there. */ - switch ( c->x86_model ) + switch ( c->x86 == 6 ? c->x86_model : 0 ) { uint64_t val; @@ -870,14 +871,15 @@ return; } fallthrough; - case 0x3e: /* IvyBridge X */ - case 0x3f: /* Haswell X */ - case 0x4f: /* Broadwell X */ - case 0x55: /* Skylake X */ - case 0x56: /* Broadwell Xeon D */ - case 0x6a: /* Icelake X */ - case 0x6c: /* Icelake D */ - case 0x8f: /* Sapphire Rapids X */ + case INTEL_FAM6_IVYBRIDGE_X: + case INTEL_FAM6_HASWELL_X: + case INTEL_FAM6_BROADWELL_X: + case INTEL_FAM6_BROADWELL_D: + case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_ICELAKE_X: + case INTEL_FAM6_ICELAKE_D: + case INTEL_FAM6_SAPPHIRERAPIDS_X: + case INTEL_FAM6_EMERALDRAPIDS_X: if ( (c != &boot_cpu_data && !ppin_msr) || rdmsr_safe(MSR_PPIN_CTL, val) ) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/amd-patch-digests.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/amd-patch-digests.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/amd-patch-digests.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/amd-patch-digests.c 2025-11-25 08:37:47.000000000 +0000 @@ -81,6 +81,15 @@ }, }, { + .patch_id = 0x0a0011d7, + .digest = { + 0x35, 0x07, 0xcd, 0x40, 0x94, 0xbc, 0x81, 0x6b, + 0xfc, 0x61, 0x56, 0x1a, 0xe2, 0xdb, 0x96, 0x12, + 0x1c, 0x1c, 0x31, 0xb1, 0x02, 0x6f, 0xe5, 0xd2, + 0xfe, 0x1b, 0x04, 0x03, 0x2c, 0x8f, 0x4c, 0x36, + }, +}, +{ .patch_id = 0x0a001238, .digest = { 0x72, 0xf7, 0x4b, 0x0c, 0x7d, 0x58, 0x65, 0xcc, @@ -90,6 +99,15 @@ }, }, { + .patch_id = 0x0a00123b, + .digest = { + 0xef, 0xa1, 0x1e, 0x71, 0xf1, 0xc3, 0x2c, 0xe2, + 0xc3, 0xef, 0x69, 0x41, 0x7a, 0x54, 0xca, 0xc3, + 0x8f, 0x62, 0x84, 0xee, 0xc2, 0x39, 0xd9, 0x28, + 0x95, 0xa7, 0x12, 0x49, 0x1e, 0x30, 0x71, 0x72, + }, +}, +{ .patch_id = 0x0a00820c, .digest = { 0xa8, 0x0c, 0x81, 0xc0, 0xa6, 0x00, 0xe7, 0xf3, @@ -99,6 +117,15 @@ }, }, { + .patch_id = 0x0a00820d, + .digest = { + 0xf9, 0x2a, 0xc0, 0xf4, 0x9e, 0xa4, 0x87, 0xa4, + 0x7d, 0x87, 0x00, 0xfd, 0xab, 0xda, 0x19, 0xca, + 0x26, 0x51, 0x32, 0xc1, 0x57, 0x91, 0xdf, 0xc1, + 0x05, 0xeb, 0x01, 0x7c, 0x5a, 0x95, 0x21, 0xb7, + }, +}, +{ .patch_id = 0x0a101148, .digest = { 0x20, 0xd5, 0x6f, 0x40, 0x4a, 0xf6, 0x48, 0x90, @@ -108,6 +135,15 @@ }, }, { + .patch_id = 0x0a10114c, + .digest = { + 0x9e, 0xb6, 0xa2, 0xd9, 0x87, 0x38, 0xc5, 0x64, + 0xd8, 0x88, 0xfa, 0x78, 0x98, 0xf9, 0x6f, 0x74, + 0x39, 0x90, 0x1b, 0xa5, 0xcf, 0x5e, 0xb4, 0x2a, + 0x02, 0xff, 0xd4, 0x8c, 0x71, 0x8b, 0xe2, 0xc0, + }, +}, +{ .patch_id = 0x0a101248, .digest = { 0xed, 0x3b, 0x95, 0xa6, 0x68, 0xa7, 0x77, 0x3e, @@ -117,6 +153,15 @@ }, }, { + .patch_id = 0x0a10124c, + .digest = { + 0x29, 0xea, 0xf1, 0x2c, 0xb2, 0xe4, 0xef, 0x90, + 0xa4, 0xcd, 0x1d, 0x86, 0x97, 0x17, 0x61, 0x46, + 0xfc, 0x22, 0xcb, 0x57, 0x75, 0x19, 0xc8, 0xcc, + 0x0c, 0xf5, 0xbc, 0xac, 0x81, 0x9d, 0x9a, 0xd2, + }, +}, +{ .patch_id = 0x0a108108, .digest = { 0xed, 0xc2, 0xec, 0xa1, 0x15, 0xc6, 0x65, 0xe9, @@ -126,6 +171,15 @@ }, }, { + .patch_id = 0x0a108109, + .digest = { + 0x85, 0xb4, 0xbd, 0x7c, 0x49, 0xa7, 0xbd, 0xfa, + 0x49, 0x36, 0x80, 0x81, 0xc5, 0xb7, 0x39, 0x1b, + 0x9a, 0xaa, 0x50, 0xde, 0x9b, 0xe9, 0x32, 0x35, + 0x42, 0x7e, 0x51, 0x4f, 0x52, 0x2c, 0x28, 0x59, + }, +}, +{ .patch_id = 0x0a20102d, .digest = { 0xf9, 0x6e, 0xf2, 0x32, 0xd3, 0x0f, 0x5f, 0x11, @@ -135,6 +189,15 @@ }, }, { + .patch_id = 0x0a20102e, + .digest = { + 0xbe, 0x1f, 0x32, 0x04, 0x0d, 0x3c, 0x9c, 0xdd, + 0xe1, 0xa4, 0xbf, 0x76, 0x3a, 0xec, 0xc2, 0xf6, + 0x11, 0x00, 0xa7, 0xaf, 0x0f, 0xe5, 0x02, 0xc5, + 0x54, 0x3a, 0x1f, 0x8c, 0x16, 0xb5, 0xff, 0xbe, + }, +}, +{ .patch_id = 0x0a201210, .digest = { 0xe8, 0x6d, 0x51, 0x6a, 0x8e, 0x72, 0xf3, 0xfe, @@ -144,6 +207,15 @@ }, }, { + .patch_id = 0x0a201211, + .digest = { + 0x69, 0xa1, 0x17, 0xec, 0xd0, 0xf6, 0x6c, 0x95, + 0xe2, 0x1e, 0xc5, 0x59, 0x1a, 0x52, 0x0a, 0x27, + 0xc4, 0xed, 0xd5, 0x59, 0x1f, 0xbf, 0x00, 0xff, + 0x08, 0x88, 0xb5, 0xe1, 0x12, 0xb6, 0xcc, 0x27, + }, +}, +{ .patch_id = 0x0a404107, .digest = { 0xbb, 0x04, 0x4e, 0x47, 0xdd, 0x5e, 0x26, 0x45, @@ -153,6 +225,15 @@ }, }, { + .patch_id = 0x0a404108, + .digest = { + 0x69, 0x67, 0x43, 0x06, 0xf8, 0x0c, 0x62, 0xdc, + 0xa4, 0x21, 0x30, 0x4f, 0x0f, 0x21, 0x2c, 0xcb, + 0xcc, 0x37, 0xf1, 0x1c, 0xc3, 0xf8, 0x2f, 0x19, + 0xdf, 0x53, 0x53, 0x46, 0xb1, 0x15, 0xea, 0x00, + }, +}, +{ .patch_id = 0x0a500011, .digest = { 0x23, 0x3d, 0x70, 0x7d, 0x03, 0xc3, 0xc4, 0xf4, @@ -162,6 +243,15 @@ }, }, { + .patch_id = 0x0a500012, + .digest = { + 0xeb, 0x74, 0x0d, 0x47, 0xa1, 0x8e, 0x09, 0xe4, + 0x93, 0x4c, 0xad, 0x03, 0x32, 0x4c, 0x38, 0x16, + 0x10, 0x39, 0xdd, 0x06, 0xaa, 0xce, 0xd6, 0x0f, + 0x62, 0x83, 0x9d, 0x8e, 0x64, 0x55, 0xbe, 0x63, + }, +}, +{ .patch_id = 0x0a601209, .digest = { 0x66, 0x48, 0xd4, 0x09, 0x05, 0xcb, 0x29, 0x32, @@ -171,6 +261,15 @@ }, }, { + .patch_id = 0x0a60120a, + .digest = { + 0x0c, 0x8b, 0x3d, 0xfd, 0x52, 0x52, 0x85, 0x7d, + 0x20, 0x3a, 0xe1, 0x7e, 0xa4, 0x21, 0x3b, 0x7b, + 0x17, 0x86, 0xae, 0xac, 0x13, 0xb8, 0x63, 0x9d, + 0x06, 0x01, 0xd0, 0xa0, 0x51, 0x9a, 0x91, 0x2c, + }, +}, +{ .patch_id = 0x0a704107, .digest = { 0xf3, 0xc6, 0x58, 0x26, 0xee, 0xac, 0x3f, 0xd6, @@ -180,6 +279,15 @@ }, }, { + .patch_id = 0x0a704108, + .digest = { + 0xd7, 0x55, 0x15, 0x2b, 0xfe, 0xc4, 0xbc, 0x93, + 0xec, 0x91, 0xa0, 0xae, 0x45, 0xb7, 0xc3, 0x98, + 0x4e, 0xff, 0x61, 0x77, 0x88, 0xc2, 0x70, 0x49, + 0xe0, 0x3a, 0x1d, 0x84, 0x38, 0x52, 0xbf, 0x5a, + }, +}, +{ .patch_id = 0x0a705206, .digest = { 0x8d, 0xc0, 0x76, 0xbd, 0x58, 0x9f, 0x8f, 0xa4, @@ -189,6 +297,15 @@ }, }, { + .patch_id = 0x0a705208, + .digest = { + 0x30, 0x1d, 0x55, 0x24, 0xbc, 0x6b, 0x5a, 0x19, + 0x0c, 0x7d, 0x1d, 0x74, 0xaa, 0xd1, 0xeb, 0xd2, + 0x16, 0x62, 0xf7, 0x5b, 0xe1, 0x1f, 0x18, 0x11, + 0x5c, 0xf0, 0x94, 0x90, 0x26, 0xec, 0x69, 0xff, + }, +}, +{ .patch_id = 0x0a708007, .digest = { 0x6b, 0x76, 0xcc, 0x78, 0xc5, 0x8a, 0xa3, 0xe3, @@ -198,6 +315,15 @@ }, }, { + .patch_id = 0x0a708008, + .digest = { + 0x08, 0x6e, 0xf0, 0x22, 0x4b, 0x8e, 0xc4, 0x46, + 0x58, 0x34, 0xe6, 0x47, 0xa2, 0x28, 0xfd, 0xab, + 0x22, 0x3d, 0xdd, 0xd8, 0x52, 0x9e, 0x1d, 0x16, + 0xfa, 0x01, 0x68, 0x14, 0x79, 0x3e, 0xe8, 0x6b, + }, +}, +{ .patch_id = 0x0a70c005, .digest = { 0x88, 0x5d, 0xfb, 0x79, 0x64, 0xd8, 0x46, 0x3b, @@ -207,6 +333,15 @@ }, }, { + .patch_id = 0x0a70c008, + .digest = { + 0x0f, 0xdb, 0x37, 0xa1, 0x10, 0xaf, 0xd4, 0x21, + 0x94, 0x0d, 0xa4, 0xa2, 0xe9, 0x86, 0x6c, 0x0e, + 0x85, 0x7c, 0x36, 0x30, 0xa3, 0x3a, 0x78, 0x66, + 0x18, 0x10, 0x60, 0x0d, 0x78, 0x3d, 0x44, 0xd0, + }, +}, +{ .patch_id = 0x0aa00116, .digest = { 0xe8, 0x4c, 0x2c, 0x88, 0xa1, 0xac, 0x24, 0x63, @@ -224,3 +359,12 @@ 0x68, 0x2f, 0x46, 0xee, 0xfe, 0xc6, 0x6d, 0xef, }, }, +{ + .patch_id = 0x0aa00216, + .digest = { + 0x79, 0xfb, 0x5b, 0x9f, 0xb6, 0xe6, 0xa8, 0xf5, + 0x4e, 0x7c, 0x4f, 0x8e, 0x1d, 0xad, 0xd0, 0x08, + 0xc2, 0x43, 0x7c, 0x8b, 0xe6, 0xdb, 0xd0, 0xd2, + 0xe8, 0x39, 0x26, 0xc1, 0xe5, 0x5a, 0x48, 0xf1, + }, +}, diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/amd.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/amd.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/amd.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/amd.c 2025-11-25 08:37:47.000000000 +0000 @@ -42,7 +42,10 @@ uint8_t mc_patch_data_id[2]; uint8_t mc_patch_data_len; uint8_t init_flag; - uint32_t mc_patch_data_checksum; + union { + uint32_t checksum; /* Fam12h and earlier */ + uint32_t min_rev; /* Zen3-5, post Entrysign */ + }; uint32_t nb_dev_id; uint32_t sb_dev_id; uint16_t processor_rev_id; @@ -99,6 +102,7 @@ } patch_digests[] = { #include "amd-patch-digests.c" }; +static bool __ro_after_init entrysign_mitigiated_in_firmware; static int cf_check cmp_patch_id(const void *key, const void *elem) { @@ -120,11 +124,11 @@ /* * Zen1 thru Zen5 CPUs are known to use a weak signature algorithm on - * microcode updates. Mitigate by checking the digest of the patch - * against a list of known provenance. + * microcode updates. If this has not been mitigated in firmware, check + * the digest of the patch against a list of known provenance. */ - if ( boot_cpu_data.x86 < 0x17 || - !opt_digest_check ) + if ( boot_cpu_data.x86 < 0x17 || boot_cpu_data.x86 > 0x1a || + entrysign_mitigiated_in_firmware || !opt_digest_check ) return true; pd = bsearch(&patch->patch_id, patch_digests, ARRAY_SIZE(patch_digests), @@ -271,6 +275,42 @@ return compare_revisions(old->patch_id, new->patch_id); } +/* + * Check whether this patch has a minimum revision given, and whether the + * condition is satisfied. + * + * In linux-firmware for CPUs suffering from the Entrysign vulnerability, + * ucodes signed with the updated signature algorithm have reused the checksum + * field as a min-revision field. From public archives, the checksum field + * appears to have been unused since Fam12h. + * + * Returns false if there is a min revision given, and it suggests that that + * the patch cannot be loaded on the current system. True otherwise. + */ +static bool check_min_rev(const struct microcode_patch *patch) +{ + ASSERT(microcode_fits_cpu(patch)); + + if ( patch->processor_rev_id < 0xa000 || /* pre Zen3? */ + patch->min_rev == 0 ) /* No min rev specified */ + return true; + + /* + * Sanity check, as this is a reused field. If this is a true + * min_revision field, it will differ only in the bottom byte from the + * patch_id. Otherwise, it's probably a checksum. + */ + if ( (patch->patch_id ^ patch->min_rev) & ~0xff ) + { + printk(XENLOG_WARNING + "microcode: patch %#x has unexpected min_rev %#x\n", + patch->patch_id, patch->min_rev); + return true; + } + + return this_cpu(cpu_sig).rev >= patch->min_rev; +} + static int cf_check apply_microcode(const struct microcode_patch *patch, unsigned int flags) { @@ -300,6 +340,14 @@ return -ENXIO; } + if ( !ucode_force && !check_min_rev(patch) ) + { + printk(XENLOG_ERR + "microcode: CPU%u current rev %#x below patch min_rev %#x\n", + cpu, sig->rev, patch->min_rev); + return -ENXIO; + } + hw_err = wrmsr_safe(MSR_AMD_PATCHLOADER, (unsigned long)patch); /* get patch id after patching */ @@ -517,10 +565,15 @@ void __init ucode_probe_amd(struct microcode_ops *ops) { - if ( !opt_digest_check && boot_cpu_data.x86 >= 0x17 ) + /* + * The Entrysign vulnerability (SB-7033, CVE-2024-36347) affects Zen1-5 + * CPUs. Taint Xen if digest checking is turned off. + */ + if ( boot_cpu_data.x86 >= 0x17 && boot_cpu_data.x86 <= 0x1a && + !opt_digest_check ) { printk(XENLOG_WARNING - "Microcode patch additional digest checks disabled"); + "Microcode patch additional digest checks disabled\n"); add_taint(TAINT_CPU_OUT_OF_SPEC); } @@ -529,3 +582,100 @@ *ops = amd_ucode_ops; } + +#if 0 /* Manual CONFIG_SELF_TESTS */ +static void __init __constructor test_digests_sorted(void) +{ + for ( unsigned int i = 1; i < ARRAY_SIZE(patch_digests); ++i ) + { + if ( patch_digests[i - 1].patch_id < patch_digests[i].patch_id ) + continue; + + panic("patch_digests[] not sorted: %08x >= %08x\n", + patch_digests[i - 1].patch_id, + patch_digests[i].patch_id); + } +} +#endif /* CONFIG_SELF_TESTS */ + +/* + * The Entrysign vulnerability affects all Zen1 thru Zen5 CPUs. Firmware + * fixes were produced from Nov 2024. Zen3 thru Zen5 can continue to take + * OS-loadable microcode updates using a new signature scheme, as long as + * firmware has been updated first. + */ +void __init amd_check_entrysign(void) +{ + unsigned int curr_rev; + uint8_t fixed_rev; + + if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD || + boot_cpu_data.x86 < 0x17 || + boot_cpu_data.x86 > 0x1a ) + return; + + /* + * Table taken from Linux, which is the only known source of information + * about client revisions. Note, Linux expresses "last-vulnerable-rev" + * while Xen wants "first-fixed-rev". + */ + curr_rev = this_cpu(cpu_sig).rev; + switch ( curr_rev >> 8 ) + { + case 0x080012: fixed_rev = 0x78; break; + case 0x080082: fixed_rev = 0x10; break; + case 0x083010: fixed_rev = 0x7d; break; + case 0x086001: fixed_rev = 0x0f; break; + case 0x086081: fixed_rev = 0x09; break; + case 0x087010: fixed_rev = 0x35; break; + case 0x08a000: fixed_rev = 0x0b; break; + case 0x0a0010: fixed_rev = 0x7b; break; + case 0x0a0011: fixed_rev = 0xdb; break; + case 0x0a0012: fixed_rev = 0x44; break; + case 0x0a0082: fixed_rev = 0x0f; break; + case 0x0a1011: fixed_rev = 0x54; break; + case 0x0a1012: fixed_rev = 0x4f; break; + case 0x0a1081: fixed_rev = 0x0a; break; + case 0x0a2010: fixed_rev = 0x30; break; + case 0x0a2012: fixed_rev = 0x13; break; + case 0x0a4041: fixed_rev = 0x0a; break; + case 0x0a5000: fixed_rev = 0x14; break; + case 0x0a6012: fixed_rev = 0x0b; break; + case 0x0a7041: fixed_rev = 0x0a; break; + case 0x0a7052: fixed_rev = 0x09; break; + case 0x0a7080: fixed_rev = 0x0a; break; + case 0x0a70c0: fixed_rev = 0x0a; break; + case 0x0aa001: fixed_rev = 0x17; break; + case 0x0aa002: fixed_rev = 0x19; break; + case 0x0b0021: fixed_rev = 0x47; break; + case 0x0b0081: fixed_rev = 0x12; break; + case 0x0b1010: fixed_rev = 0x47; break; + case 0x0b2040: fixed_rev = 0x32; break; + case 0x0b4040: fixed_rev = 0x32; break; + case 0x0b4041: fixed_rev = 0x02; break; + case 0x0b6000: fixed_rev = 0x32; break; + case 0x0b6080: fixed_rev = 0x32; break; + case 0x0b7000: fixed_rev = 0x32; break; + default: + printk(XENLOG_WARNING + "Unrecognised CPU %02x-%02x-%02x ucode 0x%08x, assuming vulnerable to Entrysign\n", + boot_cpu_data.x86, boot_cpu_data.x86_model, + boot_cpu_data.x86_mask, curr_rev); + return; + } + + /* + * This check is best-effort. If the platform looks to be out of date, it + * probably is. If the platform looks to be fixed, it either genuinely + * is, or malware has gotten in before Xen booted and all bets are off. + */ + if ( (uint8_t)curr_rev >= fixed_rev ) + { + entrysign_mitigiated_in_firmware = true; + return; + } + + printk(XENLOG_WARNING + "WARNING: Platform vulnerable to Entrysign (SB-7033, CVE-2024-36347) - firmware update required\n"); + add_taint(TAINT_CPU_OUT_OF_SPEC); +} diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/core.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/core.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/core.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/core.c 2025-11-25 08:37:47.000000000 +0000 @@ -260,7 +260,9 @@ { cpumask_set_cpu(smp_processor_id(), &cpu_callin_map); - return wait_for_state(LOADING_EXIT) ? 0 : -EBUSY; + wait_for_state(LOADING_EXIT); + + return 0; } static int primary_thread_work(const struct microcode_patch *patch, @@ -271,7 +273,7 @@ cpumask_set_cpu(smp_processor_id(), &cpu_callin_map); if ( !wait_for_state(LOADING_ENTER) ) - return -EBUSY; + return 0; ret = alternative_call(ucode_ops.apply_microcode, patch, flags); if ( !ret ) @@ -313,7 +315,7 @@ static int secondary_thread_fn(void) { if ( !wait_for_state(LOADING_CALLIN) ) - return -EBUSY; + return 0; self_nmi(); @@ -336,7 +338,7 @@ unsigned int flags) { if ( !wait_for_state(LOADING_CALLIN) ) - return -EBUSY; + return 0; if ( ucode_in_nmi ) { @@ -392,10 +394,10 @@ atomic_inc(&cpu_updated); atomic_inc(&cpu_out); - if ( ret == -EIO ) + if ( ret ) { printk(XENLOG_ERR - "Late loading aborted: CPU%u failed to update ucode\n", cpu); + "Late loading aborted: CPU%u failed to update ucode: %d\n", cpu, ret); goto out; } @@ -750,6 +752,8 @@ int idx = opt_mod_idx; int rc; + amd_check_entrysign(); + /* * Cmdline parsing ensures this invariant holds, so that we don't end up * trying to mix multiple ways of finding the microcode. diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/private.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/private.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/microcode/private.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/microcode/private.h 2025-11-25 08:37:47.000000000 +0000 @@ -81,8 +81,10 @@ */ #ifdef CONFIG_AMD void ucode_probe_amd(struct microcode_ops *ops); +void amd_check_entrysign(void); #else static inline void ucode_probe_amd(struct microcode_ops *ops) {} +static inline void amd_check_entrysign(void) {} #endif #ifdef CONFIG_INTEL diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/mwait-idle.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/mwait-idle.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu/mwait-idle.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu/mwait-idle.c 2025-11-25 08:37:47.000000000 +0000 @@ -678,6 +678,62 @@ {} }; +static const struct cpuidle_state mtl_l_cstates[] = { + { + .name = "C1E", + .flags = MWAIT2flg(0x01), + .exit_latency = 1, + .target_residency = 1, + }, + { + .name = "C6", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 140, + .target_residency = 420, + }, + { + .name = "C10", + .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 310, + .target_residency = 930, + }, + {} +}; + +static const struct cpuidle_state gmt_cstates[] = { + { + .name = "C1", + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_DISABLED, + .exit_latency = 1, + .target_residency = 1, + }, + { + .name = "C1E", + .flags = MWAIT2flg(0x01), + .exit_latency = 2, + .target_residency = 4, + }, + { + .name = "C6", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 195, + .target_residency = 585, + }, + { + .name = "C8", + .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 260, + .target_residency = 1040, + }, + { + .name = "C10", + .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 660, + .target_residency = 1980, + }, + {} +}; + static struct cpuidle_state __read_mostly spr_cstates[] = { { .name = "C1", @@ -700,6 +756,62 @@ {} }; +static const struct cpuidle_state gnr_cstates[] = { + { + .name = "C1", + .flags = MWAIT2flg(0x00), + .exit_latency = 1, + .target_residency = 1, + }, + { + .name = "C1E", + .flags = MWAIT2flg(0x01), + .exit_latency = 4, + .target_residency = 4, + }, + { + .name = "C6", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 170, + .target_residency = 650, + }, + { + .name = "C6P", + .flags = MWAIT2flg(0x21) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 210, + .target_residency = 1000, + }, + {} +}; + +static const struct cpuidle_state gnrd_cstates[] = { + { + .name = "C1", + .flags = MWAIT2flg(0x00), + .exit_latency = 1, + .target_residency = 1, + }, + { + .name = "C1E", + .flags = MWAIT2flg(0x01), + .exit_latency = 4, + .target_residency = 4, + }, + { + .name = "C6", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 220, + .target_residency = 650, + }, + { + .name = "C6P", + .flags = MWAIT2flg(0x21) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 240, + .target_residency = 750, + }, + {} +}; + static const struct cpuidle_state atom_cstates[] = { { .name = "C1E", @@ -872,10 +984,59 @@ {} }; +static const struct cpuidle_state grr_cstates[] = { + { + .name = "C1", + .flags = MWAIT2flg(0x00), + .exit_latency = 1, + .target_residency = 1, + }, + { + .name = "C1E", + .flags = MWAIT2flg(0x01), + .exit_latency = 2, + .target_residency = 10, + }, + { + .name = "C6S", + .flags = MWAIT2flg(0x22) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 140, + .target_residency = 500, + }, + {} +}; + +static const struct cpuidle_state srf_cstates[] = { + { + .name = "C1", + .flags = MWAIT2flg(0x00), + .exit_latency = 1, + .target_residency = 1, + }, + { + .name = "C1E", + .flags = MWAIT2flg(0x01), + .exit_latency = 2, + .target_residency = 10, + }, + { + .name = "C6S", + .flags = MWAIT2flg(0x22) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 270, + .target_residency = 700, + }, + { + .name = "C6SP", + .flags = MWAIT2flg(0x23) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 310, + .target_residency = 900, + }, + {} +}; + static void cf_check mwait_idle(void) { unsigned int cpu = smp_processor_id(); - struct cpu_info *info = get_cpu_info(); struct acpi_processor_power *power = processor_powers[cpu]; struct acpi_processor_cx *cx = NULL; unsigned int next_state; @@ -902,6 +1063,8 @@ pm_idle_save(); else { + struct cpu_info *info = get_cpu_info(); + spec_ctrl_enter_idle(info); safe_halt(); spec_ctrl_exit_idle(info); @@ -928,11 +1091,6 @@ if ((cx->type >= 3) && errata_c6_workaround()) cx = power->safe_state; - if (cx->ibrs_disable) { - ASSERT(!cx->irq_enable_early); - spec_ctrl_enter_idle(info); - } - #if 0 /* XXX Can we/do we need to do something similar on Xen? */ /* * leave_mm() to avoid costly and often unnecessary wakeups @@ -950,12 +1108,8 @@ update_last_cx_stat(power, cx, before); - if (cx->irq_enable_early) - local_irq_enable(); - - mwait_idle_with_hints(cx->address, MWAIT_ECX_INTERRUPT_BREAK); - - local_irq_disable(); + mwait_idle_with_hints(cx->address, + cx->irq_enable_early ? 0 : MWAIT_ECX_INTERRUPT_BREAK); after = alternative_call(cpuidle_get_tick); @@ -964,10 +1118,6 @@ /* Now back in C0. */ update_idle_stats(power, cx, before, after); - - if (cx->ibrs_disable) - spec_ctrl_exit_idle(info); - local_irq_enable(); TRACE_TIME(TRC_PM_IDLE_EXIT, cx->type, after, @@ -1095,11 +1245,29 @@ .state_table = adl_l_cstates, }; +static const struct idle_cpu idle_cpu_mtl_l = { + .state_table = mtl_l_cstates, +}; + +static const struct idle_cpu idle_cpu_gmt = { + .state_table = gmt_cstates, +}; + static struct idle_cpu __read_mostly idle_cpu_spr = { .state_table = spr_cstates, .c1e_promotion = C1E_PROMOTION_DISABLE, }; +static const struct idle_cpu idle_cpu_gnr = { + .state_table = gnr_cstates, + .c1e_promotion = C1E_PROMOTION_DISABLE, +}; + +static const struct idle_cpu idle_cpu_gnrd = { + .state_table = gnrd_cstates, + .c1e_promotion = C1E_PROMOTION_DISABLE, +}; + static const struct idle_cpu idle_cpu_avn = { .state_table = avn_cstates, .c1e_promotion = C1E_PROMOTION_DISABLE, @@ -1120,6 +1288,16 @@ .c1e_promotion = C1E_PROMOTION_DISABLE, }; +static const struct idle_cpu idle_cpu_grr = { + .state_table = grr_cstates, + .c1e_promotion = C1E_PROMOTION_DISABLE, +}; + +static const struct idle_cpu idle_cpu_srf = { + .state_table = srf_cstates, + .c1e_promotion = C1E_PROMOTION_DISABLE, +}; + #define ICPU(model, cpu) \ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ ## model, X86_FEATURE_ALWAYS, \ &idle_cpu_ ## cpu} @@ -1160,11 +1338,19 @@ ICPU(ICELAKE_D, icx), ICPU(ALDERLAKE, adl), ICPU(ALDERLAKE_L, adl_l), + ICPU(METEORLAKE_L, mtl_l), + ICPU(ATOM_GRACEMONT, gmt), ICPU(SAPPHIRERAPIDS_X, spr), + ICPU(EMERALDRAPIDS_X, spr), + ICPU(GRANITERAPIDS_X, gnr), + ICPU(GRANITERAPIDS_D, gnrd), ICPU(ATOM_GOLDMONT, bxt), ICPU(ATOM_GOLDMONT_PLUS, bxt), ICPU(ATOM_GOLDMONT_D, dnv), ICPU(ATOM_TREMONT_D, snr), + ICPU(ATOM_CRESTMONT, grr), + ICPU(ATOM_CRESTMONT_X, srf), + ICPU(ATOM_DARKMONT_X, srf), {} }; @@ -1394,10 +1580,12 @@ skx_idle_state_table_update(); break; case INTEL_FAM6_SAPPHIRERAPIDS_X: + case INTEL_FAM6_EMERALDRAPIDS_X: spr_idle_state_table_update(); break; case INTEL_FAM6_ALDERLAKE: case INTEL_FAM6_ALDERLAKE_L: + case INTEL_FAM6_ATOM_GRACEMONT: adl_idle_state_table_update(); break; } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu-policy.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu-policy.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/cpu-policy.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/cpu-policy.c 2025-11-25 08:37:47.000000000 +0000 @@ -329,6 +329,8 @@ p->extd.raw[0x1e] = EMPTY_LEAF; /* TopoExt APIC ID/Core/Node */ p->extd.raw[0x1f] = EMPTY_LEAF; /* SEV */ p->extd.raw[0x20] = EMPTY_LEAF; /* Platform QoS */ + p->extd.raw[0x21].b = 0; + p->extd.raw[0x21].d = 0; break; } } @@ -415,8 +417,9 @@ static void __init guest_common_max_feature_adjustments(uint32_t *fs) { - if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) + switch ( boot_cpu_data.x86_vendor ) { + case X86_VENDOR_INTEL: /* * MSR_ARCH_CAPS is just feature data, and we can offer it to guests * unconditionally, although limit it to Intel systems as it is highly @@ -461,6 +464,33 @@ boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X && raw_cpu_policy.feat.clwb ) __set_bit(X86_FEATURE_CLWB, fs); + + /* + * To mitigate Native-BHI, one option is to use a TSX Abort on capable + * systems. This is safe even if RTM has been disabled for other + * reasons via MSR_TSX_{CTRL,FORCE_ABORT}. However, a guest kernel + * doesn't get to know this type of information. + * + * Therefore the meaning of RTM_ALWAYS_ABORT has been adjusted, to + * instead mean "XBEGIN won't fault". This is enough for a guest + * kernel to make an informed choice WRT mitigating Native-BHI. + * + * If RTM-capable, we can run a VM which has seen RTM_ALWAYS_ABORT. + */ + if ( test_bit(X86_FEATURE_RTM, fs) ) + __set_bit(X86_FEATURE_RTM_ALWAYS_ABORT, fs); + break; + + case X86_VENDOR_AMD: + /* + * This bit indicates that the VERW instruction may have gained + * scrubbing side effects. With pooling, it means "you might migrate + * somewhere where scrubbing is necessary", and may need exposing on + * unaffected hardware. This is fine, because the VERW instruction + * has been around since the 286. + */ + __set_bit(X86_FEATURE_VERW_CLEAR, fs); + break; } /* @@ -472,27 +502,13 @@ */ __set_bit(X86_FEATURE_HTT, fs); __set_bit(X86_FEATURE_CMP_LEGACY, fs); - - /* - * To mitigate Native-BHI, one option is to use a TSX Abort on capable - * systems. This is safe even if RTM has been disabled for other reasons - * via MSR_TSX_{CTRL,FORCE_ABORT}. However, a guest kernel doesn't get to - * know this type of information. - * - * Therefore the meaning of RTM_ALWAYS_ABORT has been adjusted, to instead - * mean "XBEGIN won't fault". This is enough for a guest kernel to make - * an informed choice WRT mitigating Native-BHI. - * - * If RTM-capable, we can run a VM which has seen RTM_ALWAYS_ABORT. - */ - if ( test_bit(X86_FEATURE_RTM, fs) ) - __set_bit(X86_FEATURE_RTM_ALWAYS_ABORT, fs); } static void __init guest_common_default_feature_adjustments(uint32_t *fs) { - if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) + switch ( boot_cpu_data.x86_vendor ) { + case X86_VENDOR_INTEL: /* * IvyBridge client parts suffer from leakage of RDRAND data due to SRBDS * (XSA-320 / CVE-2020-0543), and won't be receiving microcode to @@ -515,17 +531,14 @@ * reasons, so reset the default policy back to the host values in * case we're unaffected. */ - __clear_bit(X86_FEATURE_MD_CLEAR, fs); - if ( cpu_has_md_clear ) - __set_bit(X86_FEATURE_MD_CLEAR, fs); - - __clear_bit(X86_FEATURE_FB_CLEAR, fs); - if ( cpu_has_fb_clear ) - __set_bit(X86_FEATURE_FB_CLEAR, fs); - - __clear_bit(X86_FEATURE_RFDS_CLEAR, fs); - if ( cpu_has_rfds_clear ) - __set_bit(X86_FEATURE_RFDS_CLEAR, fs); + if ( !cpu_has_md_clear ) + __clear_bit(X86_FEATURE_MD_CLEAR, fs); + + if ( !cpu_has_fb_clear ) + __clear_bit(X86_FEATURE_FB_CLEAR, fs); + + if ( !cpu_has_rfds_clear ) + __clear_bit(X86_FEATURE_RFDS_CLEAR, fs); /* * The Gather Data Sampling microcode mitigation (August 2023) has an @@ -539,34 +552,45 @@ boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X && raw_cpu_policy.feat.clwb ) __clear_bit(X86_FEATURE_CLWB, fs); + + /* + * On certain hardware, speculative or errata workarounds can result + * in TSX being placed in "force-abort" mode, where it doesn't + * actually function as expected, but is technically compatible with + * the ISA. + * + * Do not advertise RTM to guests by default if it won't actually + * work. Instead, advertise RTM_ALWAYS_ABORT indicating that TSX + * Aborts are safe to use, e.g. for mitigating Native-BHI. + */ + if ( rtm_disabled ) + { + __clear_bit(X86_FEATURE_RTM, fs); + __set_bit(X86_FEATURE_RTM_ALWAYS_ABORT, fs); + } + break; + + case X86_VENDOR_AMD: + /* + * This bit indicate that the VERW instruction may have gained + * scrubbing side effects. The max policy has it set for migration + * reasons, so reset the default policy back to the host value in case + * we're unaffected. + */ + if ( !cpu_has_verw_clear ) + __clear_bit(X86_FEATURE_VERW_CLEAR, fs); + break; } /* * Topology information is at the toolstack's discretion so these are * unconditionally set in max, but pick a default which matches the host. */ - __clear_bit(X86_FEATURE_HTT, fs); - if ( cpu_has_htt ) - __set_bit(X86_FEATURE_HTT, fs); - - __clear_bit(X86_FEATURE_CMP_LEGACY, fs); - if ( cpu_has_cmp_legacy ) - __set_bit(X86_FEATURE_CMP_LEGACY, fs); + if ( !cpu_has_htt ) + __clear_bit(X86_FEATURE_HTT, fs); - /* - * On certain hardware, speculative or errata workarounds can result in - * TSX being placed in "force-abort" mode, where it doesn't actually - * function as expected, but is technically compatible with the ISA. - * - * Do not advertise RTM to guests by default if it won't actually work. - * Instead, advertise RTM_ALWAYS_ABORT indicating that TSX Aborts are safe - * to use, e.g. for mitigating Native-BHI. - */ - if ( rtm_disabled ) - { - __clear_bit(X86_FEATURE_RTM, fs); - __set_bit(X86_FEATURE_RTM_ALWAYS_ABORT, fs); - } + if ( !cpu_has_cmp_legacy ) + __clear_bit(X86_FEATURE_CMP_LEGACY, fs); } static void __init guest_common_feature_adjustments(uint32_t *fs) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/efi/check.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/efi/check.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/efi/check.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/efi/check.c 2025-11-25 08:37:47.000000000 +0000 @@ -3,6 +3,9 @@ return i; } +/* In case -mfunction-return is in use. */ +void __x86_return_thunk(void) {}; + /* * Populate an array with "addresses" of relocatable and absolute values. * This is to probe ld for (a) emitting base relocations at all and (b) not diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/extable.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/extable.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/extable.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/extable.c 2025-11-25 08:37:47.000000000 +0000 @@ -151,20 +151,20 @@ int __init cf_check stub_selftest(void) { static const struct { - uint8_t opc[8]; + uint8_t opc[7]; uint64_t rax; union stub_exception_token res; } tests[] __initconst = { #define endbr64 0xf3, 0x0f, 0x1e, 0xfa - { .opc = { endbr64, 0x0f, 0xb9, 0xc3, 0xc3 }, /* ud1 */ + { .opc = { endbr64, 0x0f, 0xb9, 0x90 }, /* ud1 */ .res.fields.trapnr = X86_EXC_UD }, - { .opc = { endbr64, 0x90, 0x02, 0x00, 0xc3 }, /* nop; add (%rax),%al */ + { .opc = { endbr64, 0x90, 0x02, 0x00 }, /* nop; add (%rax),%al */ .rax = 0x0123456789abcdef, .res.fields.trapnr = X86_EXC_GP }, - { .opc = { endbr64, 0x02, 0x04, 0x04, 0xc3 }, /* add (%rsp,%rax),%al */ + { .opc = { endbr64, 0x02, 0x04, 0x04 }, /* add (%rsp,%rax),%al */ .rax = 0xfedcba9876543210UL, .res.fields.trapnr = X86_EXC_SS }, - { .opc = { endbr64, 0xcc, 0xc3, 0xc3, 0xc3 }, /* int3 */ + { .opc = { endbr64, 0xcc, 0x90, 0x90 }, /* int3 */ .res.fields.trapnr = X86_EXC_BP }, #undef endbr64 }; @@ -183,6 +183,7 @@ memset(ptr, 0xcc, STUB_BUF_SIZE / 2); memcpy(ptr, tests[i].opc, ARRAY_SIZE(tests[i].opc)); + place_ret(ptr + ARRAY_SIZE(tests[i].opc)); unmap_domain_page(ptr); asm volatile ( "INDIRECT_CALL %[stb]\n" diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/Makefile xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/Makefile --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/Makefile 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/Makefile 2025-11-25 08:37:47.000000000 +0000 @@ -1,4 +1,4 @@ -obj-y += hypercall_page.o +obj-bin-y += hypercall.init.o obj-y += xen.o obj-bin-$(CONFIG_PVH_GUEST) += pvh-boot.init.o diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/hypercall.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/hypercall.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/hypercall.S 1970-01-01 00:00:00.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/hypercall.S 2025-11-25 08:37:47.000000000 +0000 @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include + + .section .init.text, "ax", @progbits + + /* + * Used during early boot, before alternatives have run and inlined + * the appropriate instruction. Called using the hypercall ABI. + */ +FUNC(early_hypercall) + cmpb $0, early_hypercall_insn(%rip) + jl .L_setup + je 1f + + vmmcall + ret + +1: vmcall + ret + +.L_setup: + /* + * When setting up the first time around, all registers need + * preserving. Save the non-callee-saved ones. + */ + push %r11 + push %r10 + push %r9 + push %r8 + push %rdi + push %rsi + push %rdx + push %rcx + push %rax + + call early_hypercall_setup + + pop %rax + pop %rcx + pop %rdx + pop %rsi + pop %rdi + pop %r8 + pop %r9 + pop %r10 + pop %r11 + + jmp early_hypercall +END(early_hypercall) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/hypercall_page.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/hypercall_page.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/hypercall_page.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/hypercall_page.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -#include -#include -#include - - .section ".text.page_aligned", "ax", @progbits - -DATA(hypercall_page, PAGE_SIZE) - /* Poisoned with `ret` for safety before hypercalls are set up. */ - .fill PAGE_SIZE, 1, 0xc3 -END(hypercall_page) - -/* - * Identify a specific hypercall in the hypercall page - * @param name Hypercall name. - */ -#define DECLARE_HYPERCALL(name) \ - .globl HYPERCALL_ ## name; \ - .type HYPERCALL_ ## name, STT_FUNC; \ - .size HYPERCALL_ ## name, 32; \ - .set HYPERCALL_ ## name, hypercall_page + __HYPERVISOR_ ## name * 32 - -DECLARE_HYPERCALL(set_trap_table) -DECLARE_HYPERCALL(mmu_update) -DECLARE_HYPERCALL(set_gdt) -DECLARE_HYPERCALL(stack_switch) -DECLARE_HYPERCALL(set_callbacks) -DECLARE_HYPERCALL(fpu_taskswitch) -DECLARE_HYPERCALL(sched_op_compat) -DECLARE_HYPERCALL(platform_op) -DECLARE_HYPERCALL(set_debugreg) -DECLARE_HYPERCALL(get_debugreg) -DECLARE_HYPERCALL(update_descriptor) -DECLARE_HYPERCALL(memory_op) -DECLARE_HYPERCALL(multicall) -DECLARE_HYPERCALL(update_va_mapping) -DECLARE_HYPERCALL(set_timer_op) -DECLARE_HYPERCALL(event_channel_op_compat) -DECLARE_HYPERCALL(xen_version) -DECLARE_HYPERCALL(console_io) -DECLARE_HYPERCALL(physdev_op_compat) -DECLARE_HYPERCALL(grant_table_op) -DECLARE_HYPERCALL(vm_assist) -DECLARE_HYPERCALL(update_va_mapping_otherdomain) -DECLARE_HYPERCALL(iret) -DECLARE_HYPERCALL(vcpu_op) -DECLARE_HYPERCALL(set_segment_base) -DECLARE_HYPERCALL(mmuext_op) -DECLARE_HYPERCALL(xsm_op) -DECLARE_HYPERCALL(nmi_op) -DECLARE_HYPERCALL(sched_op) -DECLARE_HYPERCALL(callback_op) -DECLARE_HYPERCALL(xenoprof_op) -DECLARE_HYPERCALL(event_channel_op) -DECLARE_HYPERCALL(physdev_op) -DECLARE_HYPERCALL(hvm_op) -DECLARE_HYPERCALL(sysctl) -DECLARE_HYPERCALL(domctl) -DECLARE_HYPERCALL(kexec_op) -DECLARE_HYPERCALL(argo_op) -DECLARE_HYPERCALL(xenpmu_op) - -DECLARE_HYPERCALL(arch_0) -DECLARE_HYPERCALL(arch_1) -DECLARE_HYPERCALL(arch_2) -DECLARE_HYPERCALL(arch_3) -DECLARE_HYPERCALL(arch_4) -DECLARE_HYPERCALL(arch_5) -DECLARE_HYPERCALL(arch_6) -DECLARE_HYPERCALL(arch_7) - -/* - * Local variables: - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/xen.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/xen.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/guest/xen/xen.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/guest/xen/xen.c 2025-11-25 08:37:47.000000000 +0000 @@ -26,7 +26,6 @@ bool __read_mostly xen_guest; uint32_t __read_mostly xen_cpuid_base; -extern char hypercall_page[]; static struct rangeset *mem; DEFINE_PER_CPU(unsigned int, vcpu_id); @@ -35,6 +34,50 @@ static unsigned long vcpu_info_mapped[BITS_TO_LONGS(NR_CPUS)]; DEFINE_PER_CPU(struct vcpu_info *, vcpu_info); +/* + * Which instruction to use for early hypercalls: + * < 0 setup + * 0 vmcall + * > 0 vmmcall + */ +int8_t __initdata early_hypercall_insn = -1; + +/* + * Called once during the first hypercall to figure out which instruction to + * use. Error handling options are limited. + */ +void asmlinkage __init early_hypercall_setup(void) +{ + BUG_ON(early_hypercall_insn != -1); + + if ( !boot_cpu_data.x86_vendor ) + { + unsigned int eax, ebx, ecx, edx; + + cpuid(0, &eax, &ebx, &ecx, &edx); + + boot_cpu_data.x86_vendor = x86_cpuid_lookup_vendor(ebx, ecx, edx); + } + + switch ( boot_cpu_data.x86_vendor ) + { + case X86_VENDOR_INTEL: + case X86_VENDOR_CENTAUR: + case X86_VENDOR_SHANGHAI: + early_hypercall_insn = 0; + setup_force_cpu_cap(X86_FEATURE_USE_VMCALL); + break; + + case X86_VENDOR_AMD: + case X86_VENDOR_HYGON: + early_hypercall_insn = 1; + break; + + default: + BUG(); + } +} + static void __init find_xen_leaves(void) { uint32_t eax, ebx, ecx, edx, base; @@ -337,9 +380,6 @@ if ( !xen_cpuid_base ) return NULL; - /* Fill the hypercall page. */ - wrmsrl(cpuid_ebx(xen_cpuid_base + 2), __pa(hypercall_page)); - xen_guest = true; return &ops; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hpet.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hpet.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hpet.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hpet.c 2025-11-25 08:37:47.000000000 +0000 @@ -9,17 +9,19 @@ #include #include #include +#include #include #include #include #include #include -#include #include +#include +#include #include +#include #include -#include #define MAX_DELTA_NS MILLISECS(10*1000) #define MIN_DELTA_NS MICROSECS(20) @@ -188,15 +190,13 @@ if ( __cpumask_test_and_clear_cpu(cpu, mask) ) raise_softirq(TIMER_SOFTIRQ); - cpuidle_wakeup_mwait(mask); - if ( !cpumask_empty(mask) ) cpumask_raise_softirq(mask, TIMER_SOFTIRQ); } static void cf_check handle_hpet_broadcast(struct hpet_event_channel *ch) { - cpumask_t mask; + cpumask_t *scratch = this_cpu(hpet_scratch_cpumask); s_time_t now, next_event; unsigned int cpu; unsigned long flags; @@ -209,7 +209,7 @@ spin_unlock_irqrestore(&ch->lock, flags); next_event = STIME_MAX; - cpumask_clear(&mask); + cpumask_clear(scratch); now = NOW(); /* find all expired events */ @@ -218,13 +218,13 @@ s_time_t deadline = ACCESS_ONCE(per_cpu(timer_deadline, cpu)); if ( deadline <= now ) - __cpumask_set_cpu(cpu, &mask); + __cpumask_set_cpu(cpu, scratch); else if ( deadline < next_event ) next_event = deadline; } /* wakeup the cpus which have an expired event. */ - evt_do_broadcast(&mask); + evt_do_broadcast(scratch); if ( next_event != STIME_MAX ) { @@ -253,10 +253,9 @@ ch->event_handler(ch); } -static void cf_check hpet_msi_unmask(struct irq_desc *desc) +static void hpet_enable_channel(struct hpet_event_channel *ch) { u32 cfg; - struct hpet_event_channel *ch = desc->action->dev_id; cfg = hpet_read32(HPET_Tn_CFG(ch->idx)); cfg |= HPET_TN_ENABLE; @@ -264,6 +263,11 @@ ch->msi.msi_attrib.host_masked = 0; } +static void cf_check hpet_msi_unmask(struct irq_desc *desc) +{ + hpet_enable_channel(desc->action->dev_id); +} + static void cf_check hpet_msi_mask(struct irq_desc *desc) { u32 cfg; @@ -293,36 +297,21 @@ return 0; } -static unsigned int cf_check hpet_msi_startup(struct irq_desc *desc) -{ - hpet_msi_unmask(desc); - return 0; -} - #define hpet_msi_shutdown hpet_msi_mask -static void cf_check hpet_msi_ack(struct irq_desc *desc) -{ - irq_complete_move(desc); - move_native_irq(desc); - ack_APIC_irq(); -} - static void cf_check hpet_msi_set_affinity( struct irq_desc *desc, const cpumask_t *mask) { struct hpet_event_channel *ch = desc->action->dev_id; struct msi_msg msg = ch->msi.msg; - msg.dest32 = set_desc_affinity(desc, mask); - if ( msg.dest32 == BAD_APICID ) - return; + /* This really is only for dump_irqs(). */ + cpumask_copy(desc->arch.cpu_mask, mask); - msg.data &= ~MSI_DATA_VECTOR_MASK; - msg.data |= MSI_DATA_VECTOR(desc->arch.vector); + msg.dest32 = cpu_mask_to_apicid(mask); msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(msg.dest32); - if ( msg.data != ch->msi.msg.data || msg.dest32 != ch->msi.msg.dest32 ) + if ( msg.dest32 != ch->msi.msg.dest32 ) hpet_msi_write(ch, &msg); } @@ -331,11 +320,12 @@ */ static hw_irq_controller hpet_msi_type = { .typename = "HPET-MSI", - .startup = hpet_msi_startup, + .startup = irq_startup_none, .shutdown = hpet_msi_shutdown, .enable = hpet_msi_unmask, .disable = hpet_msi_mask, - .ack = hpet_msi_ack, + .ack = irq_actor_none, + .end = end_nonmaskable_irq, .set_affinity = hpet_msi_set_affinity, }; @@ -353,6 +343,16 @@ u32 cfg = hpet_read32(HPET_Tn_CFG(ch->idx)); irq_desc_t *desc = irq_to_desc(ch->msi.irq); + clear_irq_vector(ch->msi.irq); + /* + * Technically we don't want to bind the IRQ to any CPU yet, but we need to + * specify at least one online one here. Use the BSP. + */ + ret = bind_irq_vector(ch->msi.irq, HPET_BROADCAST_VECTOR, cpumask_of(0)); + if ( ret ) + return ret; + cpumask_setall(desc->affinity); + if ( iommu_intremap != iommu_intremap_off ) { ch->msi.hpet_id = hpet_blockid; @@ -482,19 +482,50 @@ static void set_channel_irq_affinity(struct hpet_event_channel *ch) { struct irq_desc *desc = irq_to_desc(ch->msi.irq); + struct msi_msg msg = ch->msi.msg; ASSERT(!local_irq_is_enabled()); spin_lock(&desc->lock); - hpet_msi_mask(desc); - hpet_msi_set_affinity(desc, cpumask_of(ch->cpu)); - hpet_msi_unmask(desc); + + per_cpu(vector_irq, ch->cpu)[HPET_BROADCAST_VECTOR] = ch->msi.irq; + + /* + * Open-coding a reduced form of hpet_msi_set_affinity() here. With the + * actual update below (either of the IRTE or of [just] message address; + * with interrupt remapping message address/data don't change) now being + * atomic, we can avoid masking the IRQ around the update. As a result + * we're no longer at risk of missing IRQs (provided hpet_broadcast_enter() + * keeps setting the new deadline only afterwards). + */ + cpumask_copy(desc->arch.cpu_mask, cpumask_of(ch->cpu)); + spin_unlock(&desc->lock); - spin_unlock(&ch->lock); + msg.dest32 = cpu_physical_id(ch->cpu); + msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; + msg.address_lo |= MSI_ADDR_DEST_ID(msg.dest32); + if ( msg.dest32 != ch->msi.msg.dest32 ) + { + ch->msi.msg = msg; - /* We may have missed an interrupt due to the temporary masking. */ - if ( ch->event_handler && ch->next_event < NOW() ) - ch->event_handler(ch); + if ( iommu_intremap != iommu_intremap_off ) + { + int rc = iommu_update_ire_from_msi(&ch->msi, &msg); + + ASSERT(rc <= 0); + if ( rc >= 0 ) + { + ASSERT(msg.data == hpet_read32(HPET_Tn_ROUTE(ch->idx))); + ASSERT(msg.address_lo == + hpet_read32(HPET_Tn_ROUTE(ch->idx) + 4)); + } + } + else + hpet_write32(msg.address_lo, HPET_Tn_ROUTE(ch->idx) + 4); + } + + hpet_enable_channel(ch); + spin_unlock(&ch->lock); } static void hpet_attach_channel(unsigned int cpu, @@ -530,6 +561,8 @@ spin_unlock_irq(&ch->lock); else if ( (next = cpumask_first(ch->cpumask)) >= nr_cpu_ids ) { + hpet_write32(hpet_read32(HPET_COUNTER), HPET_Tn_CMP(ch->idx)); + ch->next_event = STIME_MAX; ch->cpu = -1; clear_bit(HPET_EVT_USED_BIT, &ch->flags); spin_unlock_irq(&ch->lock); @@ -630,6 +663,12 @@ hpet_events->flags = HPET_EVT_LEGACY; } +void __init hpet_broadcast_late_init(void) +{ + if ( !num_hpets_used ) + free_lopriority_vector(HPET_BROADCAST_VECTOR); +} + void hpet_broadcast_resume(void) { u32 cfg; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/hvm.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/hvm.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/hvm.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/hvm.c 2025-11-25 08:37:47.000000000 +0000 @@ -557,9 +557,15 @@ ASSERT(bytes == 1 && port == XEN_HVM_DEBUGCONS_IOPORT); - /* Deny any input requests. */ - if ( dir != IOREQ_WRITE ) - return X86EMUL_UNHANDLEABLE; + if ( dir == IOREQ_READ ) + { + /* + * According to Bochs documentation, reading from the E9 port should + * return 0xE9 if the "port E9 hack" is implemented. + */ + *val = XEN_HVM_DEBUGCONS_IOPORT; + return X86EMUL_OKAY; + } /* Accept only printable characters, newline, and horizontal tab. */ if ( !isprint(c) && (c != '\n') && (c != '\t') ) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/ioreq.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/ioreq.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/ioreq.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/ioreq.c 2025-11-25 08:37:47.000000000 +0000 @@ -63,7 +63,7 @@ for ( i = HVM_PARAM_IOREQ_PFN; i <= HVM_PARAM_BUFIOREQ_PFN; i++ ) { - if ( !test_and_clear_bit(i, &d->arch.hvm.ioreq_gfn.legacy_mask) ) + if ( test_and_clear_bit(i, &d->arch.hvm.ioreq_gfn.legacy_mask) ) return _gfn(d->arch.hvm.params[i]); } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/svm/asid.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/svm/asid.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/svm/asid.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/svm/asid.c 2025-11-25 08:37:47.000000000 +0000 @@ -46,9 +46,8 @@ if ( vmcb_get_asid(vmcb) != p_asid->asid ) vmcb_set_asid(vmcb, p_asid->asid); - vmcb->tlb_control = - !need_flush ? TLB_CTRL_NO_FLUSH : - cpu_has_svm_flushbyasid ? TLB_CTRL_FLUSH_ASID : TLB_CTRL_FLUSH_ALL; + /* We can't rely on TLB_CTRL_FLUSH_ASID as all ASIDs are stale here. */ + vmcb->tlb_control = need_flush ? TLB_CTRL_FLUSH_ALL : TLB_CTRL_NO_FLUSH; } /* diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/svm/entry.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/svm/entry.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/svm/entry.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/svm/entry.S 2025-11-25 08:37:47.000000000 +0000 @@ -99,6 +99,8 @@ pop %rsi pop %rdi + SPEC_CTRL_COND_VERW /* Req: %rsp=eframe Clob: efl */ + vmrun SAVE_ALL diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/viridian/synic.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/viridian/synic.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/viridian/synic.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/viridian/synic.c 2025-11-25 08:37:47.000000000 +0000 @@ -338,6 +338,10 @@ .DeliveryTime = delivery, }; + /* Don't assume SIM page to be mapped. */ + if ( !msg ) + return false; + /* * To avoid using an atomic test-and-set, and barrier before calling * vlapic_set_irq(), this function must be called in context of the diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/viridian/time.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/viridian/time.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/viridian/time.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/viridian/time.c 2025-11-25 08:37:47.000000000 +0000 @@ -26,6 +26,10 @@ HV_REFERENCE_TSC_PAGE *p = rt->ptr; uint32_t seq; + /* Reference TSC page might not be mapped even if the MSR is enabled. */ + if ( !p ) + return; + if ( initialize ) clear_page(p); @@ -104,8 +108,10 @@ trc->off = (int64_t)trc->val - trc_val(d, 0); + spin_lock(&vd->lock); if ( vd->reference_tsc.msr.enabled ) update_reference_tsc(d, false); + spin_unlock(&vd->lock); } static uint64_t time_ref_count(const struct domain *d) @@ -327,6 +333,7 @@ if ( !(viridian_feature_mask(d) & HVMPV_reference_tsc) ) return X86EMUL_EXCEPTION; + spin_lock(&vd->lock); viridian_unmap_guest_page(&vd->reference_tsc); vd->reference_tsc.msr.raw = val; viridian_dump_guest_page(v, "REFERENCE_TSC", &vd->reference_tsc); @@ -335,6 +342,7 @@ viridian_map_guest_page(d, &vd->reference_tsc); update_reference_tsc(d, true); } + spin_unlock(&vd->lock); break; case HV_X64_MSR_TIME_REF_COUNT: diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/viridian/viridian.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/viridian/viridian.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/viridian/viridian.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/viridian/viridian.c 2025-11-25 08:37:47.000000000 +0000 @@ -494,6 +494,8 @@ if ( !d->arch.hvm.viridian ) return -ENOMEM; + spin_lock_init(&d->arch.hvm.viridian->lock); + rc = viridian_synic_domain_init(d); if ( rc ) goto fail; @@ -560,7 +562,8 @@ if ( mask & 1 ) { - ASSERT(vp < HVM_MAX_VCPUS); + if ( vp >= HVM_MAX_VCPUS ) + break; __set_bit(vp, vpmask->mask); } @@ -574,26 +577,6 @@ bitmap_fill(vpmask->mask, HVM_MAX_VCPUS); } -static unsigned int vpmask_first(const struct hypercall_vpmask *vpmask) -{ - return find_first_bit(vpmask->mask, HVM_MAX_VCPUS); -} - -static unsigned int vpmask_next(const struct hypercall_vpmask *vpmask, - unsigned int vp) -{ - /* - * If vp + 1 > HVM_MAX_VCPUS then find_next_bit() will return - * HVM_MAX_VCPUS, ensuring the for_each_vp ( ... ) loop terminates. - */ - return find_next_bit(vpmask->mask, HVM_MAX_VCPUS, vp + 1); -} - -#define for_each_vp(vpmask, vp) \ - for ( (vp) = vpmask_first(vpmask); \ - (vp) < HVM_MAX_VCPUS; \ - (vp) = vpmask_next(vpmask, vp) ) - static unsigned int vpmask_nr(const struct hypercall_vpmask *vpmask) { return bitmap_weight(vpmask->mask, HVM_MAX_VCPUS); @@ -810,7 +793,7 @@ if ( nr > 1 ) cpu_raise_softirq_batch_begin(); - for_each_vp ( vpmask, vp ) + bitmap_for_each ( vp, vpmask->mask, currd->max_vcpus ) { struct vlapic *vlapic = vcpu_vlapic(currd->vcpu[vp]); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/vmx/vmcs.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/vmx/vmcs.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/vmx/vmcs.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/vmx/vmcs.c 2025-11-25 08:37:47.000000000 +0000 @@ -1150,9 +1150,11 @@ else { v->arch.hvm.vmx.secondary_exec_control &= - ~(SECONDARY_EXEC_ENABLE_EPT | + ~(SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_UNRESTRICTED_GUEST | SECONDARY_EXEC_ENABLE_INVPCID); + v->arch.hvm.vmx.tertiary_exec_control &= + ~(TERTIARY_EXEC_EPT_PAGING_WRITE); vmexit_ctl &= ~(VM_EXIT_SAVE_GUEST_PAT | VM_EXIT_LOAD_HOST_PAT); vmentry_ctl &= ~VM_ENTRY_LOAD_GUEST_PAT; @@ -1686,7 +1688,7 @@ return; /* Make sure we don't lose any logged GPAs. */ - vmx_vcpu_flush_pml_buffer(v); + ept_vcpu_flush_pml_buffer(v); vmx_vmcs_enter(v); @@ -1700,61 +1702,6 @@ v->arch.hvm.vmx.pml_pg = NULL; } -void vmx_vcpu_flush_pml_buffer(struct vcpu *v) -{ - uint64_t *pml_buf; - unsigned long pml_idx; - - ASSERT((v == current) || (!vcpu_runnable(v) && !v->is_running)); - ASSERT(vmx_vcpu_pml_enabled(v)); - - vmx_vmcs_enter(v); - - __vmread(GUEST_PML_INDEX, &pml_idx); - - /* Do nothing if PML buffer is empty. */ - if ( pml_idx == (NR_PML_ENTRIES - 1) ) - goto out; - - pml_buf = __map_domain_page(v->arch.hvm.vmx.pml_pg); - - /* - * PML index can be either 2^16-1 (buffer is full), or 0 ~ NR_PML_ENTRIES-1 - * (buffer is not full), and in latter case PML index always points to next - * available entity. - */ - if ( pml_idx >= NR_PML_ENTRIES ) - pml_idx = 0; - else - pml_idx++; - - for ( ; pml_idx < NR_PML_ENTRIES; pml_idx++ ) - { - unsigned long gfn = pml_buf[pml_idx] >> PAGE_SHIFT; - - /* - * Need to change type from log-dirty to normal memory for logged GFN. - * hap_track_dirty_vram depends on it to work. And we mark all logged - * GFNs to be dirty, as we cannot be sure whether it's safe to ignore - * GFNs on which p2m_change_type_one returns failure. The failure cases - * are very rare, and additional cost is negligible, but a missing mark - * is extremely difficult to debug. - */ - p2m_change_type_one(v->domain, gfn, p2m_ram_logdirty, p2m_ram_rw); - - /* HVM guest: pfn == gfn */ - paging_mark_pfn_dirty(v->domain, _pfn(gfn)); - } - - unmap_domain_page(pml_buf); - - /* Reset PML index */ - __vmwrite(GUEST_PML_INDEX, NR_PML_ENTRIES - 1); - - out: - vmx_vmcs_exit(v); -} - bool vmx_domain_pml_enabled(const struct domain *d) { return d->arch.hvm.vmx.status & VMX_DOMAIN_PML_ENABLED; @@ -1828,7 +1775,7 @@ return; for_each_vcpu ( d, v ) - vmx_vcpu_flush_pml_buffer(v); + ept_vcpu_flush_pml_buffer(v); } static void vmx_vcpu_update_eptp(struct vcpu *v, u64 eptp) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/vmx/vmx.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/vmx/vmx.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/hvm/vmx/vmx.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/hvm/vmx/vmx.c 2025-11-25 08:37:47.000000000 +0000 @@ -4694,7 +4694,7 @@ !(idtv_info & INTR_INFO_VALID_MASK) ) undo_nmis_unblocked_by_iret(); - vmx_vcpu_flush_pml_buffer(v); + ept_vcpu_flush_pml_buffer(v); break; case EXIT_REASON_XSAVES: diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/alternative-asm.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/alternative-asm.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/alternative-asm.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/alternative-asm.h 2025-11-25 08:37:47.000000000 +0000 @@ -12,7 +12,7 @@ * instruction. See apply_alternatives(). */ .macro altinstruction_entry orig, repl, feature, orig_len, repl_len, pad_len - .if \feature >= NCAPINTS * 32 + .if ((\feature) & ~ALT_FLAG_NOT) >= NCAPINTS * 32 .error "alternative feature outside of featureset range" .endif .long \orig - . diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/alternative.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/alternative.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/alternative.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/alternative.h 2025-11-25 08:37:47.000000000 +0000 @@ -1,6 +1,13 @@ #ifndef __X86_ALTERNATIVE_H__ #define __X86_ALTERNATIVE_H__ +/* + * Common to both C and ASM. Express a replacement when a feature is not + * available. + */ +#define ALT_FLAG_NOT (1 << 15) +#define ALT_NOT(x) (ALT_FLAG_NOT | (x)) + #ifdef __ASSEMBLY__ #include #else @@ -12,7 +19,7 @@ struct __packed alt_instr { int32_t orig_offset; /* original instruction */ int32_t repl_offset; /* offset to replacement instruction */ - uint16_t cpuid; /* cpuid bit set for replacement */ + uint16_t cpuid; /* cpuid bit set for replacement (top bit is polarity) */ uint8_t orig_len; /* length of original instruction */ uint8_t repl_len; /* length of new instruction */ uint8_t pad_len; /* length of build-time padding */ @@ -24,6 +31,8 @@ #define ALT_REPL_PTR(a) __ALT_PTR(a, repl_offset) extern void add_nops(void *insns, unsigned int len); +void *place_ret(void *ptr); + /* Similar to alternative_instructions except it can be run with IRQs enabled. */ extern int apply_alternatives(struct alt_instr *start, struct alt_instr *end); extern void alternative_instructions(void); @@ -60,7 +69,7 @@ alt_repl_len(n2)) "-" alt_orig_len) #define ALTINSTR_ENTRY(feature, num) \ - " .if " STR(feature) " >= " STR(NCAPINTS * 32) "\n" \ + " .if (" STR(feature & ~ALT_FLAG_NOT) ") >= " STR(NCAPINTS * 32) "\n" \ " .error \"alternative feature outside of featureset range\"\n" \ " .endif\n" \ " .long .LXEN%=_orig_s - .\n" /* label */ \ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/asm-defns.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/asm-defns.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/asm-defns.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/asm-defns.h 2025-11-25 08:37:47.000000000 +0000 @@ -58,6 +58,12 @@ .endif .endm +#ifdef CONFIG_RETURN_THUNK +# define RET jmp __x86_return_thunk +#else +# define RET ret +#endif + #ifdef CONFIG_XEN_IBT # define ENDBR64 endbr64 #else diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/cpufeature.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/cpufeature.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/cpufeature.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/cpufeature.h 2025-11-25 08:37:47.000000000 +0000 @@ -194,6 +194,7 @@ /* CPUID level 0x80000021.eax */ #define cpu_has_lfence_dispatch boot_cpu_has(X86_FEATURE_LFENCE_DISPATCH) +#define cpu_has_verw_clear boot_cpu_has(X86_FEATURE_VERW_CLEAR) #define cpu_has_nscb boot_cpu_has(X86_FEATURE_NSCB) /* CPUID level 0x00000007:1.edx */ @@ -218,6 +219,12 @@ #define cpu_has_gds_no boot_cpu_has(X86_FEATURE_GDS_NO) #define cpu_has_rfds_no boot_cpu_has(X86_FEATURE_RFDS_NO) #define cpu_has_rfds_clear boot_cpu_has(X86_FEATURE_RFDS_CLEAR) +#define cpu_has_pb_opt_ctrl boot_cpu_has(X86_FEATURE_PB_OPT_CTRL) +#define cpu_has_its_no boot_cpu_has(X86_FEATURE_ITS_NO) + +/* CPUID level 0x80000021.ecx */ +#define cpu_has_tsa_sq_no boot_cpu_has(X86_FEATURE_TSA_SQ_NO) +#define cpu_has_tsa_l1_no boot_cpu_has(X86_FEATURE_TSA_L1_NO) /* Synthesized. */ #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/cpufeatures.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/cpufeatures.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/cpufeatures.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/cpufeatures.h 2025-11-25 08:37:47.000000000 +0000 @@ -19,7 +19,7 @@ XEN_CPUFEATURE(TSC_RELIABLE, X86_SYNTH( 4)) /* TSC is known to be reliable */ XEN_CPUFEATURE(XTOPOLOGY, X86_SYNTH( 5)) /* cpu topology enum extensions */ XEN_CPUFEATURE(CPUID_FAULTING, X86_SYNTH( 6)) /* cpuid faulting */ -XEN_CPUFEATURE(CLFLUSH_MONITOR, X86_SYNTH( 7)) /* clflush reqd with monitor */ +/* Bit 7 unused */ XEN_CPUFEATURE(APERFMPERF, X86_SYNTH( 8)) /* APERFMPERF */ XEN_CPUFEATURE(MFENCE_RDTSC, X86_SYNTH( 9)) /* MFENCE synchronizes RDTSC */ XEN_CPUFEATURE(XEN_SMEP, X86_SYNTH(10)) /* SMEP gets used by Xen itself */ @@ -42,6 +42,7 @@ XEN_CPUFEATURE(XEN_IBT, X86_SYNTH(27)) /* Xen uses CET Indirect Branch Tracking */ XEN_CPUFEATURE(IBPB_ENTRY_PV, X86_SYNTH(28)) /* MSR_PRED_CMD used by Xen for PV */ XEN_CPUFEATURE(IBPB_ENTRY_HVM, X86_SYNTH(29)) /* MSR_PRED_CMD used by Xen for HVM */ +XEN_CPUFEATURE(USE_VMCALL, X86_SYNTH(30)) /* Use VMCALL instead of VMMCALL */ /* Bug words follow the synthetic words. */ #define X86_NR_BUG 1 @@ -51,6 +52,8 @@ #define X86_BUG_NULL_SEG X86_BUG( 1) /* NULL-ing a selector preserves the base and limit. */ #define X86_BUG_CLFLUSH_MFENCE X86_BUG( 2) /* MFENCE needed to serialise CLFLUSH */ #define X86_BUG_IBPB_NO_RET X86_BUG( 3) /* IBPB doesn't flush the RSB/RAS */ +#define X86_BUG_CLFLUSH_MONITOR X86_BUG( 4) /* MONITOR requires CLFLUSH */ +#define X86_BUG_MONITOR X86_BUG( 5) /* MONITOR doesn't always notice writes (force IPIs) */ #define X86_SPEC_NO_LFENCE_ENTRY_PV X86_BUG(16) /* (No) safety LFENCE for SPEC_CTRL_ENTRY_PV. */ #define X86_SPEC_NO_LFENCE_ENTRY_INTR X86_BUG(17) /* (No) safety LFENCE for SPEC_CTRL_ENTRY_INTR. */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/guest/xen-hcall.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/guest/xen-hcall.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/guest/xen-hcall.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/guest/xen-hcall.h 2025-11-25 08:37:47.000000000 +0000 @@ -30,9 +30,11 @@ ({ \ long res, tmp__; \ asm volatile ( \ - "call hypercall_page + %c[offset]" \ + ALTERNATIVE_2("call early_hypercall", \ + "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \ + "vmcall", X86_FEATURE_USE_VMCALL) \ : "=a" (res), "=D" (tmp__) ASM_CALL_CONSTRAINT \ - : [offset] "i" (hcall * 32), \ + : "0" (hcall), \ "1" ((long)(a1)) \ : "memory" ); \ (type)res; \ @@ -42,10 +44,12 @@ ({ \ long res, tmp__; \ asm volatile ( \ - "call hypercall_page + %c[offset]" \ + ALTERNATIVE_2("call early_hypercall", \ + "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \ + "vmcall", X86_FEATURE_USE_VMCALL) \ : "=a" (res), "=D" (tmp__), "=S" (tmp__) \ ASM_CALL_CONSTRAINT \ - : [offset] "i" (hcall * 32), \ + : "0" (hcall), \ "1" ((long)(a1)), "2" ((long)(a2)) \ : "memory" ); \ (type)res; \ @@ -55,10 +59,12 @@ ({ \ long res, tmp__; \ asm volatile ( \ - "call hypercall_page + %c[offset]" \ + ALTERNATIVE_2("call early_hypercall", \ + "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \ + "vmcall", X86_FEATURE_USE_VMCALL) \ : "=a" (res), "=D" (tmp__), "=S" (tmp__), "=d" (tmp__) \ ASM_CALL_CONSTRAINT \ - : [offset] "i" (hcall * 32), \ + : "0" (hcall), \ "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)) \ : "memory" ); \ (type)res; \ @@ -69,10 +75,12 @@ long res, tmp__; \ register long _a4 asm ("r10") = ((long)(a4)); \ asm volatile ( \ - "call hypercall_page + %c[offset]" \ + ALTERNATIVE_2("call early_hypercall", \ + "vmmcall", ALT_NOT(X86_FEATURE_USE_VMCALL), \ + "vmcall", X86_FEATURE_USE_VMCALL) \ : "=a" (res), "=D" (tmp__), "=S" (tmp__), "=d" (tmp__), \ "=&r" (tmp__) ASM_CALL_CONSTRAINT \ - : [offset] "i" (hcall * 32), \ + : "0" (hcall), \ "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \ "4" (_a4) \ : "memory" ); \ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hardirq.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hardirq.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hardirq.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hardirq.h 2025-11-25 08:37:47.000000000 +0000 @@ -5,11 +5,22 @@ #include typedef struct { - unsigned int __softirq_pending; - unsigned int __local_irq_count; - unsigned int nmi_count; - unsigned int mce_count; - bool __mwait_wakeup; + /* + * The layout is important. Any CPU can set bits in __softirq_pending, + * but in_mwait is a status bit owned by the CPU. softirq_mwait_raw must + * cover both, and must be in a single cacheline. + */ + union { + struct { + unsigned int __softirq_pending; + bool in_mwait; + }; + uint64_t softirq_mwait_raw; + }; + + unsigned int __local_irq_count; + unsigned int nmi_count; + unsigned int mce_count; } __cacheline_aligned irq_cpustat_t; #include /* Standard mappings for irq_cpustat_t above */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hpet.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hpet.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hpet.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hpet.h 2025-11-25 08:37:47.000000000 +0000 @@ -90,6 +90,7 @@ * rather than using the LAPIC timer. Used for Cx state entry. */ void hpet_broadcast_init(void); +void hpet_broadcast_late_init(void); void hpet_broadcast_resume(void); void cf_check hpet_broadcast_enter(void); void cf_check hpet_broadcast_exit(void); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hvm/viridian.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hvm/viridian.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hvm/viridian.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hvm/viridian.h 2025-11-25 08:37:47.000000000 +0000 @@ -71,6 +71,7 @@ DECLARE_BITMAP(hypercall_flags, _HCALL_nr); struct viridian_time_ref_count time_ref_count; struct viridian_page reference_tsc; + spinlock_t lock; }; void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf, diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hvm/vmx/vmcs.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hvm/vmx/vmcs.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hvm/vmx/vmcs.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hvm/vmx/vmcs.h 2025-11-25 08:37:47.000000000 +0000 @@ -720,7 +720,6 @@ bool vmx_vcpu_pml_enabled(const struct vcpu *v); int vmx_vcpu_enable_pml(struct vcpu *v); void vmx_vcpu_disable_pml(struct vcpu *v); -void vmx_vcpu_flush_pml_buffer(struct vcpu *v); bool vmx_domain_pml_enabled(const struct domain *d); int vmx_domain_enable_pml(struct domain *d); void vmx_domain_disable_pml(struct domain *d); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hvm/vmx/vmx.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hvm/vmx/vmx.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/hvm/vmx/vmx.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/hvm/vmx/vmx.h 2025-11-25 08:37:47.000000000 +0000 @@ -588,6 +588,7 @@ bool ept_handle_misconfig(uint64_t gpa); int epte_get_entry_emt(struct domain *d, gfn_t gfn, mfn_t mfn, unsigned int order, bool *ipat, p2m_type_t type); +void ept_vcpu_flush_pml_buffer(struct vcpu *v); void setup_ept_dump(void); /* Locate an alternate p2m by its EPTP */ unsigned int p2m_find_altp2m_by_eptp(struct domain *d, uint64_t eptp); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/irq-vectors.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/irq-vectors.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/irq-vectors.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/irq-vectors.h 2025-11-25 08:37:47.000000000 +0000 @@ -22,6 +22,9 @@ #define FIRST_LEGACY_VECTOR FIRST_DYNAMIC_VECTOR #define LAST_LEGACY_VECTOR (FIRST_LEGACY_VECTOR + 0xf) +/* HPET broadcast is statically allocated and wants to be low priority. */ +#define HPET_BROADCAST_VECTOR (LAST_LEGACY_VECTOR + 1) + #ifdef CONFIG_PV32 #define HYPERCALL_VECTOR 0x82 #endif diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/irq.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/irq.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/irq.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/irq.h 2025-11-25 08:37:47.000000000 +0000 @@ -116,6 +116,7 @@ void cf_check irq_move_cleanup_interrupt(void); uint8_t alloc_hipriority_vector(void); +void free_lopriority_vector(uint8_t vector); void set_direct_apic_vector(uint8_t vector, void (*handler)(void)); void alloc_direct_apic_vector(uint8_t *vector, void (*handler)(void)); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/msr-index.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/msr-index.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/msr-index.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/msr-index.h 2025-11-25 08:37:47.000000000 +0000 @@ -56,6 +56,9 @@ #define MSR_MISC_PACKAGE_CTRL 0x000000bc #define PGK_CTRL_ENERGY_FILTER_EN (_AC(1, ULL) << 0) +#define MSR_PB_OPT_CTRL 0x000000bf +#define PB_OPT_IBPB_ALT (_AC(1, ULL) << 0) + #define MSR_CORE_CAPABILITIES 0x000000cf #define CORE_CAPS_SPLITLOCK_DETECT (_AC(1, ULL) << 5) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/mwait.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/mwait.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/mwait.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/mwait.h 2025-11-25 08:37:47.000000000 +0000 @@ -13,9 +13,6 @@ #define MWAIT_ECX_INTERRUPT_BREAK 0x1 -/* Force sending of a wakeup IPI regardless of mwait usage. */ -extern bool force_mwait_ipi_wakeup; - void mwait_idle_with_hints(unsigned int eax, unsigned int ecx); #ifdef CONFIG_INTEL bool mwait_pc10_supported(void); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/pci.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/pci.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/pci.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/pci.h 2025-11-25 08:37:47.000000000 +0000 @@ -57,14 +57,9 @@ void arch_pci_init_pdev(struct pci_dev *pdev); -static inline bool pci_check_bar(const struct pci_dev *pdev, - mfn_t start, mfn_t end) -{ - /* - * Check if BAR is not overlapping with any memory region defined - * in the memory map. - */ - return is_memory_hole(start, end); -} +bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end); + +struct rangeset; +int pci_sanitize_bar_memory(struct rangeset *r); #endif /* __X86_PCI_H__ */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/processor.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/processor.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/processor.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/processor.h 2025-11-25 08:37:47.000000000 +0000 @@ -315,23 +315,6 @@ cr4_pv32_mask |= (mask & XEN_CR4_PV32_BITS); } -static always_inline void __monitor(const void *eax, unsigned long ecx, - unsigned long edx) -{ - /* "monitor %eax,%ecx,%edx;" */ - asm volatile ( - ".byte 0x0f,0x01,0xc8;" - : : "a" (eax), "c" (ecx), "d"(edx) ); -} - -static always_inline void __mwait(unsigned long eax, unsigned long ecx) -{ - /* "mwait %eax,%ecx;" */ - asm volatile ( - ".byte 0x0f,0x01,0xc9;" - : : "a" (eax), "c" (ecx) ); -} - #define IOBMP_BYTES 8192 #define IOBMP_INVALID_OFFSET 0x8000 @@ -512,6 +495,9 @@ void update_mcu_opt_ctrl(void); void set_in_mcu_opt_ctrl(uint32_t mask, uint32_t val); +void update_pb_opt_ctrl(void); +void set_in_pb_opt_ctrl(uint32_t mask, uint32_t val); + enum ap_boot_method { AP_BOOT_NORMAL, AP_BOOT_SKINIT, diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/smp.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/smp.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/smp.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/smp.h 2025-11-25 08:37:47.000000000 +0000 @@ -22,6 +22,7 @@ DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_mask); DECLARE_PER_CPU(cpumask_var_t, cpu_core_mask); DECLARE_PER_CPU(cpumask_var_t, scratch_cpumask); +DECLARE_PER_CPU(cpumask_var_t, hpet_scratch_cpumask); DECLARE_PER_CPU(cpumask_var_t, send_ipi_cpumask); /* diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/softirq.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/softirq.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/softirq.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/softirq.h 2025-11-25 08:37:47.000000000 +0000 @@ -1,6 +1,8 @@ #ifndef __ASM_SOFTIRQ_H__ #define __ASM_SOFTIRQ_H__ +#include + #define NMI_SOFTIRQ (NR_COMMON_SOFTIRQS + 0) #define TIME_CALIBRATE_SOFTIRQ (NR_COMMON_SOFTIRQS + 1) #define VCPU_KICK_SOFTIRQ (NR_COMMON_SOFTIRQS + 2) @@ -9,6 +11,50 @@ #define HVM_DPCI_SOFTIRQ (NR_COMMON_SOFTIRQS + 4) #define NR_ARCH_SOFTIRQS 5 -bool arch_skip_send_event_check(unsigned int cpu); +/* + * Ensure softirq @nr is pending on @cpu. Return true if an IPI can be + * skipped, false if the IPI cannot be skipped. + * + * We use a CMPXCHG covering both __softirq_pending and in_mwait, in order to + * set softirq @nr while also observing in_mwait in a race-free way. + */ +static always_inline bool arch_set_softirq(unsigned int nr, unsigned int cpu) +{ + uint64_t *ptr = &irq_stat[cpu].softirq_mwait_raw; + uint64_t prev, old, new; + unsigned int softirq = 1U << nr; + + old = ACCESS_ONCE(*ptr); + + for ( ;; ) + { + if ( old & softirq ) + /* Softirq already pending, nothing to do. */ + return true; + + new = old | softirq; + + prev = cmpxchg(ptr, old, new); + if ( prev == old ) + break; + + old = prev; + } + + /* + * We have caused the softirq to become pending. If in_mwait was set, the + * target CPU will notice the modification and act on it. + * + * We can't access the in_mwait field nicely, so use some BUILD_BUG_ON()'s + * to cross-check the (1UL << 32) opencoding. + */ + BUILD_BUG_ON(sizeof(irq_stat[0].softirq_mwait_raw) != 8); + BUILD_BUG_ON((offsetof(irq_cpustat_t, in_mwait) - + offsetof(irq_cpustat_t, softirq_mwait_raw)) != 4); + + return new & (1UL << 32) /* in_mwait */; + +} +#define arch_set_softirq arch_set_softirq #endif /* __ASM_SOFTIRQ_H__ */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/spec_ctrl.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/spec_ctrl.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/include/asm/spec_ctrl.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/include/asm/spec_ctrl.h 2025-11-25 08:37:47.000000000 +0000 @@ -115,8 +115,22 @@ info->verw_sel = __HYPERVISOR_DS32; } +static always_inline void __spec_ctrl_enter_idle_verw(struct cpu_info *info) +{ + /* + * Flush/scrub structures which are statically partitioned between active + * threads. Otherwise data of ours (of unknown sensitivity) will become + * available to our sibling when we go idle. + * + * Note: VERW must be encoded with a memory operand, as it is only that + * form with side effects. + */ + alternative_input("", "verw %[sel]", X86_FEATURE_SC_VERW_IDLE, + [sel] "m" (info->verw_sel)); +} + /* WARNING! `ret`, `call *`, `jmp *` not safe after this call. */ -static always_inline void spec_ctrl_enter_idle(struct cpu_info *info) +static always_inline void __spec_ctrl_enter_idle(struct cpu_info *info, bool verw) { uint32_t val = 0; @@ -135,21 +149,8 @@ "a" (val), "c" (MSR_SPEC_CTRL), "d" (0)); barrier(); - /* - * Microarchitectural Store Buffer Data Sampling: - * - * On vulnerable systems, store buffer entries are statically partitioned - * between active threads. When entering idle, our store buffer entries - * are re-partitioned to allow the other threads to use them. - * - * Flush the buffers to ensure that no sensitive data of ours can be - * leaked by a sibling after it gets our store buffer entries. - * - * Note: VERW must be encoded with a memory operand, as it is only that - * form which causes a flush. - */ - alternative_input("", "verw %[sel]", X86_FEATURE_SC_VERW_IDLE, - [sel] "m" (info->verw_sel)); + if ( verw ) /* Expected to be const-propagated. */ + __spec_ctrl_enter_idle_verw(info); /* * Cross-Thread Return Address Predictions: @@ -167,6 +168,12 @@ : "rax", "rcx"); } +/* WARNING! `ret`, `call *`, `jmp *` not safe after this call. */ +static always_inline void spec_ctrl_enter_idle(struct cpu_info *info) +{ + __spec_ctrl_enter_idle(info, true /* VERW */); +} + /* WARNING! `ret`, `call *`, `jmp *` not safe before this call. */ static always_inline void spec_ctrl_exit_idle(struct cpu_info *info) { diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/indirect-thunk.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/indirect-thunk.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/indirect-thunk.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/indirect-thunk.S 2025-11-25 08:37:47.000000000 +0000 @@ -11,6 +11,12 @@ #include +/* Alignment is dealt with explicitly here; override the respective macro. */ +#undef SYM_ALIGN +#define SYM_ALIGN(align...) + +#ifdef CONFIG_INDIRECT_THUNK + .macro IND_THUNK_RETPOLINE reg:req call 1f int3 @@ -35,6 +41,16 @@ .macro GEN_INDIRECT_THUNK reg:req .section .text.__x86_indirect_thunk_\reg, "ax", @progbits + /* + * The Indirect Target Selection speculative vulnerability means that + * indirect branches (including RETs) are unsafe when in the first + * half of a cacheline. Arrange for them to be in the second half. + * + * Align to 64, then skip 32. + */ + .balign 64 + .fill 32, 1, 0xcc + FUNC(__x86_indirect_thunk_\reg) ALTERNATIVE_2 __stringify(IND_THUNK_RETPOLINE \reg), \ __stringify(IND_THUNK_LFENCE \reg), X86_FEATURE_IND_THUNK_LFENCE, \ @@ -48,3 +64,25 @@ .irp reg, ax, cx, dx, bx, bp, si, di, 8, 9, 10, 11, 12, 13, 14, 15 GEN_INDIRECT_THUNK reg=r\reg .endr + +#endif /* CONFIG_INDIRECT_THUNK */ + +#ifdef CONFIG_RETURN_THUNK + .section .text.entry.__x86_return_thunk, "ax", @progbits + + /* + * The Indirect Target Selection speculative vulnerability means that + * indirect branches (including RETs) are unsafe when in the first + * half of a cacheline. Arrange for them to be in the second half. + * + * Align to 64, then skip 32. + */ + .balign 64 + .fill 32, 1, 0xcc + +FUNC(__x86_return_thunk) + ret + int3 /* Halt straight-line speculation */ +END(__x86_return_thunk) + +#endif /* CONFIG_RETURN_THUNK */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/irq.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/irq.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/irq.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/irq.c 2025-11-25 08:37:47.000000000 +0000 @@ -289,9 +289,9 @@ mask = NULL; } ret = assign_irq_vector(irq, mask); - } - ASSERT(desc->arch.creator_domid == DOMID_INVALID); + ASSERT(desc->arch.creator_domid == DOMID_INVALID); + } if (ret < 0) { @@ -468,6 +468,12 @@ vector++ ) __set_bit(vector, used_vectors); + /* + * Prevent the HPET broadcast vector from being used, until it is known + * whether it's actually needed. + */ + __set_bit(HPET_BROADCAST_VECTOR, used_vectors); + return 0; } @@ -991,6 +997,13 @@ spin_unlock(&lock); } +/* This could free any vectors, but is needed only for low-prio ones. */ +void __init free_lopriority_vector(uint8_t vector) +{ + ASSERT(vector < FIRST_HIPRIORITY_VECTOR); + clear_bit(vector, used_vectors); +} + static void cf_check irq_ratelimit_timer_fn(void *data) { struct irq_desc *desc, *tmp; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/mm/p2m-ept.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/mm/p2m-ept.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/mm/p2m-ept.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/mm/p2m-ept.c 2025-11-25 08:37:47.000000000 +0000 @@ -1373,6 +1373,71 @@ vmx_domain_flush_pml_buffers(p2m->domain); } +void ept_vcpu_flush_pml_buffer(struct vcpu *v) +{ + struct domain *d = v->domain; + struct p2m_domain *p2m = p2m_get_hostp2m(d); + uint64_t *pml_buf; + unsigned long pml_idx; + + ASSERT((v == current) || (!vcpu_runnable(v) && !v->is_running)); + ASSERT(vmx_vcpu_pml_enabled(v)); + + vmx_vmcs_enter(v); + + __vmread(GUEST_PML_INDEX, &pml_idx); + + /* Do nothing if PML buffer is empty. */ + if ( pml_idx == (NR_PML_ENTRIES - 1) ) + goto out; + + pml_buf = __map_domain_page(v->arch.hvm.vmx.pml_pg); + + /* + * PML index can be either 2^16-1 (buffer is full), or 0 ~ NR_PML_ENTRIES-1 + * (buffer is not full), and in latter case PML index always points to next + * available entity. + */ + if ( pml_idx >= NR_PML_ENTRIES ) + pml_idx = 0; + else + pml_idx++; + + /* + * Take the lock outside of the loop, so all the type changes are done + * inside of the same locked region and the EPT flush is deferred until the + * end of the loop. + */ + p2m_lock(p2m); + for ( ; pml_idx < NR_PML_ENTRIES; pml_idx++ ) + { + unsigned long gfn = pml_buf[pml_idx] >> PAGE_SHIFT; + + /* + * Need to change type from log-dirty to normal memory for logged GFN. + * hap_track_dirty_vram depends on it to work. And we mark all loqgged + * GFNs to be dirty, as we cannot be sure whether it's safe to ignore + * GFNs on which p2m_change_type_one returns failure. The failure cases + * are very rare, and additional cost is negligible, but a missing mark + * is extremely difficult to debug. + */ + p2m_change_type_one(d, gfn, p2m_ram_logdirty, p2m_ram_rw); + + /* HVM guest: pfn == gfn */ + paging_mark_pfn_dirty(d, _pfn(gfn)); + } + p2m_unlock(p2m); + + unmap_domain_page(pml_buf); + + /* Reset PML index */ + __vmwrite(GUEST_PML_INDEX, NR_PML_ENTRIES - 1); + + out: + vmx_vmcs_exit(v); + +} + int ept_p2m_init(struct p2m_domain *p2m) { struct ept_data *ept = &p2m->ept; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/mm.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/mm.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/mm.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/mm.c 2025-11-25 08:37:47.000000000 +0000 @@ -3811,14 +3811,11 @@ break; case MMUEXT_FLUSH_CACHE: - if ( unlikely(currd != pg_owner) ) - rc = -EPERM; - else if ( unlikely(!cache_flush_permitted(currd)) ) - rc = -EACCES; - else - wbinvd(); - break; - + /* + * Dirty pCPU caches where the current vCPU has been scheduled are + * not tracked, and hence we need to resort to a global cache + * flush for correctness. + */ case MMUEXT_FLUSH_CACHE_GLOBAL: if ( unlikely(currd != pg_owner) ) rc = -EPERM; @@ -3835,7 +3832,7 @@ flush_mask(mask, FLUSH_CACHE); } else - rc = -EINVAL; + rc = -EACCES; break; case MMUEXT_SET_LDT: diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/pci.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/pci.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/pci.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/pci.c 2025-11-25 08:37:47.000000000 +0000 @@ -98,3 +98,53 @@ return rc; } + +bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end) +{ + /* + * Check if BAR is not overlapping with any memory region defined + * in the memory map. + */ + if ( !is_memory_hole(start, end) ) + gdprintk(XENLOG_WARNING, + "%pp: BAR at [%"PRI_mfn", %"PRI_mfn"] not in memory map hole\n", + &pdev->sbdf, mfn_x(start), mfn_x(end)); + + /* + * Unconditionally return true, pci_sanitize_bar_memory() will remove any + * non-hole regions. + */ + return true; +} + +/* Remove overlaps with any ranges defined in the host memory map. */ +int pci_sanitize_bar_memory(struct rangeset *r) +{ + unsigned int i; + + for ( i = 0; i < e820.nr_map; i++ ) + { + const struct e820entry *entry = &e820.map[i]; + int rc; + + if ( !entry->size ) + continue; + + rc = rangeset_remove_range(r, PFN_DOWN(entry->addr), + PFN_DOWN(entry->addr + entry->size - 1)); + if ( rc ) + return rc; + } + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/pv/emul-priv-op.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/pv/emul-priv-op.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/pv/emul-priv-op.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/pv/emul-priv-op.c 2025-11-25 08:37:47.000000000 +0000 @@ -76,7 +76,6 @@ 0x41, 0x5c, /* pop %r12 */ 0x5d, /* pop %rbp */ 0x5b, /* pop %rbx */ - 0xc3, /* ret */ }; const struct stubs *this_stubs = &this_cpu(stubs); @@ -126,11 +125,13 @@ APPEND_CALL(save_guest_gprs); APPEND_BUFF(epilogue); + p = place_ret(p); /* Build-time best effort attempt to catch problems. */ BUILD_BUG_ON(STUB_BUF_SIZE / 2 < (sizeof(prologue) + sizeof(epilogue) + 10 /* 2x call */ + - MAX(3 /* default stub */, IOEMUL_QUIRK_STUB_BYTES))); + MAX(3 /* default stub */, IOEMUL_QUIRK_STUB_BYTES) + + (IS_ENABLED(CONFIG_RETURN_THUNK) ? 5 : 1) /* ret */)); /* Runtime confirmation that we haven't clobbered an adjacent stub. */ BUG_ON(STUB_BUF_SIZE / 2 < (p - ctxt->io_emul_stub)); @@ -1197,13 +1198,11 @@ if ( !cache_flush_permitted(current->domain) ) /* * Non-physdev domain attempted WBINVD; ignore for now since - * newer linux uses this in some start-of-day timing loops. + * Linux uses this in some start-of-day code. */ ; - else if ( op == x86emul_wbnoinvd /* && cpu_has_wbnoinvd */ ) - wbnoinvd(); else - wbinvd(); + flush_all(FLUSH_CACHE); return X86EMUL_OKAY; } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/pv/gpr_switch.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/pv/gpr_switch.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/pv/gpr_switch.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/pv/gpr_switch.S 2025-11-25 08:37:47.000000000 +0000 @@ -26,7 +26,7 @@ movq UREGS_r15(%rdi), %r15 movq UREGS_rcx(%rdi), %rcx movq UREGS_rdi(%rdi), %rdi - ret + RET END(load_guest_gprs) /* Save guest GPRs. Parameter on the stack above the return address. */ @@ -48,5 +48,5 @@ movq %rbx, UREGS_rbx(%rdi) movq %rdx, UREGS_rdx(%rdi) movq %rcx, UREGS_rcx(%rdi) - ret + RET END(save_guest_gprs) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/setup.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/setup.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/setup.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/setup.c 2025-11-25 08:37:47.000000000 +0000 @@ -682,7 +682,7 @@ #undef BOOTSTRAP_MAP_LIMIT static uint64_t __init consider_modules( - uint64_t s, uint64_t e, uint32_t size, const struct boot_module mods[], + uint64_t s, uint64_t e, uint32_t size, const struct boot_module *mods, unsigned int nr_mods, unsigned int this_mod) { unsigned int i; @@ -1898,6 +1898,12 @@ setup_system_domains(); /* + * Initialize PCI (create segment 0, setup MMCFG access) ahead of IOMMU + * setup, as devices in segment > 0 must also be discoverable. + */ + acpi_mmcfg_init(); + + /* * IOMMU-related ACPI table parsing has to happen before APIC probing, for * check_x2apic_preenabled() to be able to observe respective findings, in * particular iommu_intremap having got turned off. diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/smpboot.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/smpboot.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/smpboot.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/smpboot.c 2025-11-25 08:37:47.000000000 +0000 @@ -52,6 +52,9 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, scratch_cpumask); static cpumask_t scratch_cpu0mask; +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, hpet_scratch_cpumask); +static cpumask_t hpet_scratch_cpu0mask; + DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, send_ipi_cpumask); static cpumask_t send_ipi_cpu0mask; @@ -366,7 +369,9 @@ cpu_init(); - initialize_cpu_data(cpu); + /* During resume, must not clear previously collected data. */ + if ( system_state != SYS_STATE_resume ) + initialize_cpu_data(cpu); microcode_update_one(); @@ -381,6 +386,7 @@ info->last_spec_ctrl = default_xen_spec_ctrl; } update_mcu_opt_ctrl(); + update_pb_opt_ctrl(); tsx_init(); /* Needs microcode. May change HLE/RTM feature bits. */ @@ -959,7 +965,13 @@ unsigned int socket = cpu_to_socket(cpu); struct cpuinfo_x86 *c = cpu_data; - if ( cpumask_empty(socket_cpumask[socket]) ) + /* + * We may come here without the CPU having run through CPU identification. + * In that case the socket number cannot be relied upon, but the respective + * socket_cpumask[] slot also wouldn't have been set. + */ + if ( c[cpu].apicid != boot_cpu_data.apicid && + cpumask_empty(socket_cpumask[socket]) ) { xfree(socket_cpumask[socket]); socket_cpumask[socket] = NULL; @@ -969,14 +981,19 @@ if ( remove ) { - c[cpu].phys_proc_id = XEN_INVALID_SOCKET_ID; - c[cpu].cpu_core_id = XEN_INVALID_CORE_ID; - c[cpu].compute_unit_id = INVALID_CUID; + if ( system_state != SYS_STATE_suspend ) + { + c[cpu].phys_proc_id = XEN_INVALID_SOCKET_ID; + c[cpu].cpu_core_id = XEN_INVALID_CORE_ID; + c[cpu].compute_unit_id = INVALID_CUID; + } FREE_CPUMASK_VAR(per_cpu(cpu_sibling_mask, cpu)); FREE_CPUMASK_VAR(per_cpu(cpu_core_mask, cpu)); if ( per_cpu(scratch_cpumask, cpu) != &scratch_cpu0mask ) FREE_CPUMASK_VAR(per_cpu(scratch_cpumask, cpu)); + if ( per_cpu(hpet_scratch_cpumask, cpu) != &hpet_scratch_cpu0mask ) + FREE_CPUMASK_VAR(per_cpu(hpet_scratch_cpumask, cpu)); if ( per_cpu(send_ipi_cpumask, cpu) != &send_ipi_cpu0mask ) FREE_CPUMASK_VAR(per_cpu(send_ipi_cpumask, cpu)); } @@ -1107,6 +1124,7 @@ if ( !(cond_zalloc_cpumask_var(&per_cpu(cpu_sibling_mask, cpu)) && cond_zalloc_cpumask_var(&per_cpu(cpu_core_mask, cpu)) && cond_alloc_cpumask_var(&per_cpu(scratch_cpumask, cpu)) && + cond_alloc_cpumask_var(&per_cpu(hpet_scratch_cpumask, cpu)) && cond_alloc_cpumask_var(&per_cpu(send_ipi_cpumask, cpu))) ) goto out; @@ -1234,6 +1252,7 @@ cpumask_set_cpu(cpu, &cpu_present_map); #if NR_CPUS > 2 * BITS_PER_LONG per_cpu(scratch_cpumask, cpu) = &scratch_cpu0mask; + per_cpu(hpet_scratch_cpumask, cpu) = &hpet_scratch_cpu0mask; per_cpu(send_ipi_cpumask, cpu) = &send_ipi_cpu0mask; #endif diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/spec_ctrl.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/spec_ctrl.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/spec_ctrl.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/spec_ctrl.c 2025-11-25 08:37:47.000000000 +0000 @@ -85,6 +85,8 @@ static int8_t __initdata opt_div_scrub = -1; bool __ro_after_init opt_bp_spec_reduce = true; +static bool __initdata opt_ibpb_alt; + static int __init cf_check parse_spec_ctrl(const char *s) { const char *ss; @@ -369,6 +371,8 @@ opt_div_scrub = val; else if ( (val = parse_boolean("bp-spec-reduce", s, ss)) >= 0 ) opt_bp_spec_reduce = val; + else if ( (val = parse_boolean("ibpb-alt", s, ss)) >= 0 ) + opt_ibpb_alt = val; else rc = -EINVAL; @@ -490,7 +494,7 @@ static void __init print_details(enum ind_thunk thunk) { - unsigned int _7d0 = 0, _7d2 = 0, e8b = 0, e21a = 0, max = 0, tmp; + unsigned int _7d0 = 0, _7d2 = 0, e8b = 0, e21a = 0, e21c = 0, max = 0, tmp; uint64_t caps = 0; /* Collect diagnostics about available mitigations. */ @@ -501,7 +505,7 @@ if ( boot_cpu_data.extended_cpuid_level >= 0x80000008U ) cpuid(0x80000008U, &tmp, &e8b, &tmp, &tmp); if ( boot_cpu_data.extended_cpuid_level >= 0x80000021U ) - cpuid(0x80000021U, &e21a, &tmp, &tmp, &tmp); + cpuid(0x80000021U, &e21a, &tmp, &e21c, &tmp); if ( cpu_has_arch_caps ) rdmsrl(MSR_ARCH_CAPABILITIES, caps); @@ -511,7 +515,7 @@ * Hardware read-only information, stating immunity to certain issues, or * suggestions of which mitigation to use. */ - printk(" Hardware hints:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + printk(" Hardware hints:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", (caps & ARCH_CAPS_RDCL_NO) ? " RDCL_NO" : "", (caps & ARCH_CAPS_EIBRS) ? " EIBRS" : "", (caps & ARCH_CAPS_RSBA) ? " RSBA" : "", @@ -536,10 +540,12 @@ (e8b & cpufeat_mask(X86_FEATURE_IBPB_RET)) ? " IBPB_RET" : "", (e21a & cpufeat_mask(X86_FEATURE_IBPB_BRTYPE)) ? " IBPB_BRTYPE" : "", (e21a & cpufeat_mask(X86_FEATURE_SRSO_NO)) ? " SRSO_NO" : "", - (e21a & cpufeat_mask(X86_FEATURE_SRSO_US_NO)) ? " SRSO_US_NO" : ""); + (e21a & cpufeat_mask(X86_FEATURE_SRSO_US_NO)) ? " SRSO_US_NO" : "", + (e21c & cpufeat_mask(X86_FEATURE_TSA_SQ_NO)) ? " TSA_SQ_NO" : "", + (e21c & cpufeat_mask(X86_FEATURE_TSA_L1_NO)) ? " TSA_L1_NO" : ""); /* Hardware features which need driving to mitigate issues. */ - printk(" Hardware features:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + printk(" Hardware features:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", (e8b & cpufeat_mask(X86_FEATURE_IBPB)) || (_7d0 & cpufeat_mask(X86_FEATURE_IBRSB)) ? " IBPB" : "", (e8b & cpufeat_mask(X86_FEATURE_IBRS)) || @@ -559,7 +565,8 @@ (caps & ARCH_CAPS_GDS_CTRL) ? " GDS_CTRL" : "", (caps & ARCH_CAPS_RFDS_CLEAR) ? " RFDS_CLEAR" : "", (e21a & cpufeat_mask(X86_FEATURE_SBPB)) ? " SBPB" : "", - (e21a & cpufeat_mask(X86_FEATURE_SRSO_MSR_FIX)) ? " SRSO_MSR_FIX" : ""); + (e21a & cpufeat_mask(X86_FEATURE_SRSO_MSR_FIX)) ? " SRSO_MSR_FIX" : "", + (e21a & cpufeat_mask(X86_FEATURE_VERW_CLEAR)) ? " VERW_CLEAR" : ""); /* Compiled-in support which pertains to mitigations. */ if ( IS_ENABLED(CONFIG_INDIRECT_THUNK) || IS_ENABLED(CONFIG_SHADOW_PAGING) || @@ -571,6 +578,9 @@ #ifdef CONFIG_INDIRECT_THUNK " INDIRECT_THUNK" #endif +#ifdef CONFIG_RETURN_THUNK + " RETURN_THUNK" +#endif #ifdef CONFIG_SHADOW_PAGING " SHADOW_PAGING" #endif @@ -1517,6 +1527,77 @@ setup_force_cpu_cap(X86_FEATURE_RFDS_NO); } +/* + * Transient Scheduler Attacks + * + * https://www.amd.com/content/dam/amd/en/documents/resources/bulletin/technical-guidance-for-mitigating-transient-scheduler-attacks.pdf + */ +static void __init tsa_calculations(void) +{ + unsigned int curr_rev, min_rev; + + /* TSA is only known to affect AMD processors at this time. */ + if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ) + return; + + /* If we're virtualised, don't attempt to synthesise anything. */ + if ( cpu_has_hypervisor ) + return; + + /* + * According to the whitepaper, some Fam1A CPUs (Models 0x00...0x4f, + * 0x60...0x7f) are not vulnerable but don't enumerate TSA_{SQ,L1}_NO. If + * we see either enumerated, assume both are correct ... + */ + if ( cpu_has_tsa_sq_no || cpu_has_tsa_l1_no ) + return; + + /* + * ... otherwise, synthesise them. CPUs other than Fam19 (Zen3/4) are + * stated to be not vulnerable. + */ + if ( boot_cpu_data.x86 != 0x19 ) + { + setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO); + setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO); + return; + } + + /* + * Fam19 CPUs get VERW_CLEAR with new enough microcode, but must + * synthesise the CPUID bit. + */ + curr_rev = this_cpu(cpu_sig).rev; + switch ( curr_rev >> 8 ) + { + case 0x0a0011: min_rev = 0x0a0011d7; break; + case 0x0a0012: min_rev = 0x0a00123b; break; + case 0x0a0082: min_rev = 0x0a00820d; break; + case 0x0a1011: min_rev = 0x0a10114c; break; + case 0x0a1012: min_rev = 0x0a10124c; break; + case 0x0a1081: min_rev = 0x0a108109; break; + case 0x0a2010: min_rev = 0x0a20102e; break; + case 0x0a2012: min_rev = 0x0a201211; break; + case 0x0a4041: min_rev = 0x0a404108; break; + case 0x0a5000: min_rev = 0x0a500012; break; + case 0x0a6012: min_rev = 0x0a60120a; break; + case 0x0a7041: min_rev = 0x0a704108; break; + case 0x0a7052: min_rev = 0x0a705208; break; + case 0x0a7080: min_rev = 0x0a708008; break; + case 0x0a70c0: min_rev = 0x0a70c008; break; + case 0x0aa002: min_rev = 0x0aa00216; break; + default: + printk(XENLOG_WARNING + "Unrecognised CPU %02x-%02x-%02x, ucode 0x%08x for TSA mitigation\n", + boot_cpu_data.x86, boot_cpu_data.x86_model, + boot_cpu_data.x86_mask, curr_rev); + return; + } + + if ( curr_rev >= min_rev ) + setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR); +} + static bool __init cpu_has_gds(void) { /* @@ -1757,6 +1838,90 @@ } } +/* + * https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/indirect-target-selection.html + */ +static void __init its_calculations(void) +{ + /* + * Indirect Target Selection is a Branch Prediction bug whereby certain + * indirect branches (including RETs) get predicted using a direct branch + * target, rather than a suitable indirect target, bypassing hardware + * isolation protections. + * + * ITS affects Core (but not Atom) processors starting from the + * introduction of eIBRS, up to but not including Golden Cove cores + * (checked here with BHI_CTRL). + * + * The ITS_NO feature is not expected to be enumerated by hardware, and is + * only for VMMs to synthesise for guests. + * + * ITS comes in 3 flavours: + * + * 1) Across-IBPB. Indirect branches after the IBPB can be controlled + * by direct targets which existed prior to the IBPB. This is + * addressed in the IPU 2025.1 microcode drop, and has no other + * software interaction. + * + * 2) Guest/Host. Indirect branches in the VMM can be controlled by + * direct targets from the guest. This applies equally to PV guests + * (Ring3) and HVM guests (VMX), and applies to all Skylake-uarch + * cores with eIBRS. + * + * 3) Intra-mode. Indirect branches in the VMM can be controlled by + * other execution in the same mode. + */ + + /* + * If we can see ITS_NO, or we're virtualised, do nothing. We are or may + * migrate somewhere unsafe. + */ + if ( cpu_has_its_no || cpu_has_hypervisor ) + return; + + /* ITS is only known to affect Intel processors at this time. */ + if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) + return; + + /* + * ITS does not exist on: + * - non-Family 6 CPUs + * - those without eIBRS + * - those with BHI_CTRL + * but we still need to synthesise ITS_NO. + */ + if ( boot_cpu_data.x86 != 6 || !cpu_has_eibrs || + boot_cpu_has(X86_FEATURE_BHI_CTRL) ) + goto synthesise; + + switch ( boot_cpu_data.x86_model ) + { + /* These Skylake-uarch cores suffer cases #2 and #3. */ + case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_KABYLAKE_L: + case INTEL_FAM6_KABYLAKE: + case INTEL_FAM6_COMETLAKE: + case INTEL_FAM6_COMETLAKE_L: + return; + + /* These Sunny/Willow/Cypress Cove cores suffer case #3. */ + case INTEL_FAM6_ICELAKE_X: + case INTEL_FAM6_ICELAKE_D: + case INTEL_FAM6_ICELAKE_L: + case INTEL_FAM6_TIGERLAKE_L: + case INTEL_FAM6_TIGERLAKE: + case INTEL_FAM6_ROCKETLAKE: + return; + + default: + break; + } + + /* Platforms remaining are not believed to be vulnerable to ITS. */ + synthesise: + setup_force_cpu_cap(X86_FEATURE_ITS_NO); +} + void spec_ctrl_init_domain(struct domain *d) { bool pv = is_pv_domain(d); @@ -2130,6 +2295,7 @@ * https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/intel-analysis-microarchitectural-data-sampling.html * https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/processor-mmio-stale-data-vulnerabilities.html * https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/register-file-data-sampling.html + * https://www.amd.com/content/dam/amd/en/documents/resources/bulletin/technical-guidance-for-mitigating-transient-scheduler-attacks.pdf * * Relevant ucodes: * @@ -2162,9 +2328,18 @@ * * - March 2023, for RFDS. Enumerate RFDS_CLEAR to mean that VERW now * scrubs non-architectural entries from certain register files. + * + * - July 2025, for TSA. Introduces VERW side effects to mitigate + * TSA_{SQ/L1}. Xen must synthesise the VERW_CLEAR feature based on + * microcode version. + * + * Note, these microcode updates were produced before the remediation of + * the microcode signature issues, and are included in the firwmare + * updates fixing the entrysign vulnerability from ~December 2024. */ mds_calculations(); rfds_calculations(); + tsa_calculations(); /* * Parts which enumerate FB_CLEAR are those with now-updated microcode @@ -2196,21 +2371,27 @@ * MLPDS/MFBDS when SMT is enabled. */ if ( opt_verw_pv == -1 ) - opt_verw_pv = cpu_has_useful_md_clear || cpu_has_rfds_clear; + opt_verw_pv = (cpu_has_useful_md_clear || cpu_has_rfds_clear || + cpu_has_verw_clear); if ( opt_verw_hvm == -1 ) - opt_verw_hvm = cpu_has_useful_md_clear || cpu_has_rfds_clear; + opt_verw_hvm = (cpu_has_useful_md_clear || cpu_has_rfds_clear || + cpu_has_verw_clear); /* - * If SMT is active, and we're protecting against MDS or MMIO stale data, + * If SMT is active, and we're protecting against any of: + * - MSBDS + * - MMIO stale data + * - TSA-SQ * we need to scrub before going idle as well as on return to guest. * Various pipeline resources are repartitioned amongst non-idle threads. * - * We don't need to scrub on idle for RFDS. There are no affected cores - * which support SMT, despite there being affected cores in hybrid systems - * which have SMT elsewhere in the platform. + * We don't need to scrub on idle for: + * - RFDS (no SMT affected cores) + * - TSA-L1 (utags never shared between threads) */ if ( ((cpu_has_useful_md_clear && (opt_verw_pv || opt_verw_hvm)) || + (cpu_has_verw_clear && !cpu_has_tsa_sq_no) || opt_verw_mmio) && hw_smt_enabled ) setup_force_cpu_cap(X86_FEATURE_SC_VERW_IDLE); @@ -2313,6 +2494,8 @@ bhi_calculations(); + its_calculations(); + print_details(thunk); /* @@ -2405,6 +2588,9 @@ wrmsrl(MSR_SPEC_CTRL, val); info->last_spec_ctrl = val; } + + if ( cpu_has_pb_opt_ctrl ) + set_in_pb_opt_ctrl(PB_OPT_IBPB_ALT, opt_ibpb_alt); } static void __init __maybe_unused build_assertions(void) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/time.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/time.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/time.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/time.c 2025-11-25 08:37:47.000000000 +0000 @@ -2675,6 +2675,8 @@ "Force enable with 'cpuidle'.\n"); } + hpet_broadcast_late_init(); + return 0; } __initcall(disable_pit_irq); diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/traps.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/traps.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/traps.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/traps.c 2025-11-25 08:37:47.000000000 +0000 @@ -2040,7 +2040,7 @@ return; } - pv_inject_DB(0 /* N/A, already merged */); + pv_inject_DB(dr6 ^ X86_DR6_DEFAULT); } void asmlinkage do_entry_CP(struct cpu_user_regs *regs) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_64/compat/entry.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_64/compat/entry.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_64/compat/entry.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_64/compat/entry.S 2025-11-25 08:37:47.000000000 +0000 @@ -180,7 +180,7 @@ or cr4_pv32_mask(%rip), %rax mov %rax, %cr4 mov %rax, (%rcx) - ret + RET 0: #ifndef NDEBUG /* Check that _all_ of the bits intended to be set actually are. */ @@ -198,7 +198,7 @@ 1: #endif xor %eax, %eax - ret + RET END(cr4_pv32_restore) FUNC(compat_syscall) @@ -329,7 +329,7 @@ xor %eax, %eax mov %ax, TRAPBOUNCE_cs(%rdx) mov %al, TRAPBOUNCE_flags(%rdx) - ret + RET .section .fixup,"ax" .Lfx13: diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_64/entry.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_64/entry.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_64/entry.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_64/entry.S 2025-11-25 08:37:47.000000000 +0000 @@ -604,7 +604,7 @@ xor %eax, %eax mov %rax, TRAPBOUNCE_eip(%rdx) mov %al, TRAPBOUNCE_flags(%rdx) - ret + RET .pushsection .fixup, "ax", @progbits # Numeric tags below represent the intended overall %rsi adjustment. diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_64/mmconfig-shared.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_64/mmconfig-shared.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_64/mmconfig-shared.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_64/mmconfig-shared.c 2025-11-25 08:37:47.000000000 +0000 @@ -404,6 +404,9 @@ pci_segments_init(); + if ( acpi_disabled ) + return; + /* MMCONFIG disabled */ if ((pci_probe & PCI_PROBE_MMCONF) == 0) return; diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/0fc7.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/0fc7.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/0fc7.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/0fc7.c 2025-11-25 08:37:47.000000000 +0000 @@ -102,6 +102,8 @@ if ( carry ) regs->eflags |= X86_EFLAGS_CF; break; +#else + return X86EMUL_UNIMPLEMENTED; #endif } } diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/blk.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/blk.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/blk.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/blk.c 2025-11-25 08:37:47.000000000 +0000 @@ -81,17 +81,19 @@ if ( !s->rex_prefix ) { /* Convert 32-bit real/vm86 to 32-bit prot format. */ - unsigned int fip = fpstate.env.mode.real.fip_lo + - (fpstate.env.mode.real.fip_hi << 16); - unsigned int fdp = fpstate.env.mode.real.fdp_lo + - (fpstate.env.mode.real.fdp_hi << 16); + unsigned int fip = fpstate.env.mode.real.fip_lo & 0xf; + unsigned int fcs = (fpstate.env.mode.real.fip_lo >> 4) | + (fpstate.env.mode.real.fip_hi << 12); + unsigned int fdp = fpstate.env.mode.real.fdp_lo & 0xf; + unsigned int fds = (fpstate.env.mode.real.fdp_lo >> 4) | + (fpstate.env.mode.real.fdp_hi << 12); unsigned int fop = fpstate.env.mode.real.fop; - fpstate.env.mode.prot.fip = fip & 0xf; - fpstate.env.mode.prot.fcs = fip >> 4; + fpstate.env.mode.prot.fip = fip; + fpstate.env.mode.prot.fcs = fcs; fpstate.env.mode.prot.fop = fop; - fpstate.env.mode.prot.fdp = fdp & 0xf; - fpstate.env.mode.prot.fds = fdp >> 4; + fpstate.env.mode.prot.fdp = fdp; + fpstate.env.mode.prot.fds = fds; } if ( bytes == sizeof(fpstate.env) ) @@ -121,17 +123,19 @@ else { /* Convert 16-bit real/vm86 to 32-bit prot format. */ - unsigned int fip = env->mode.real.fip_lo + - (env->mode.real.fip_hi << 16); - unsigned int fdp = env->mode.real.fdp_lo + - (env->mode.real.fdp_hi << 16); + unsigned int fip = env->mode.real.fip_lo & 0xf; + unsigned int fcs = (env->mode.real.fip_lo >> 4) | + (env->mode.real.fip_hi << 12); + unsigned int fdp = env->mode.real.fdp_lo & 0xf; + unsigned int fds = (env->mode.real.fdp_lo >> 4) | + (env->mode.real.fdp_hi << 12); unsigned int fop = env->mode.real.fop; - fpstate.env.mode.prot.fip = fip & 0xf; - fpstate.env.mode.prot.fcs = fip >> 4; + fpstate.env.mode.prot.fip = fip; + fpstate.env.mode.prot.fcs = fcs; fpstate.env.mode.prot.fop = fop; - fpstate.env.mode.prot.fdp = fdp & 0xf; - fpstate.env.mode.prot.fds = fdp >> 4; + fpstate.env.mode.prot.fdp = fdp; + fpstate.env.mode.prot.fds = fds; } if ( bytes == sizeof(*env) ) diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/fpu.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/fpu.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/fpu.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/fpu.c 2025-11-25 08:37:47.000000000 +0000 @@ -32,36 +32,42 @@ #define emulate_fpu_insn_memdst(opc, ext, arg) \ do { \ + void *_p = get_stub(stub); \ /* ModRM: mod=0, reg=ext, rm=0, i.e. a (%rax) operand */ \ *insn_bytes = 2; \ - memcpy(get_stub(stub), \ - ((uint8_t[]){ opc, ((ext) & 7) << 3, 0xc3 }), 3); \ + memcpy(_p, ((uint8_t[]){ opc, ((ext) & 7) << 3 }), 2); _p += 2; \ + place_ret(_p); \ invoke_stub("", "", "+m" (arg) : "a" (&(arg))); \ put_stub(stub); \ } while (0) #define emulate_fpu_insn_memsrc(opc, ext, arg) \ do { \ + void *_p = get_stub(stub); \ /* ModRM: mod=0, reg=ext, rm=0, i.e. a (%rax) operand */ \ - memcpy(get_stub(stub), \ - ((uint8_t[]){ opc, ((ext) & 7) << 3, 0xc3 }), 3); \ + memcpy(_p, ((uint8_t[]){ opc, ((ext) & 7) << 3 }), 2); _p += 2; \ + place_ret(_p); \ invoke_stub("", "", "=m" (dummy) : "m" (arg), "a" (&(arg))); \ put_stub(stub); \ } while (0) #define emulate_fpu_insn_stub(bytes...) \ do { \ + void *_p = get_stub(stub); \ unsigned int nr_ = sizeof((uint8_t[]){ bytes }); \ - memcpy(get_stub(stub), ((uint8_t[]){ bytes, 0xc3 }), nr_ + 1); \ + memcpy(_p, ((uint8_t[]){ bytes }), nr_); _p += nr_; \ + place_ret(_p); \ invoke_stub("", "", "=m" (dummy) : "i" (0)); \ put_stub(stub); \ } while (0) #define emulate_fpu_insn_stub_eflags(bytes...) \ do { \ + void *_p = get_stub(stub); \ unsigned int nr_ = sizeof((uint8_t[]){ bytes }); \ unsigned long tmp_; \ - memcpy(get_stub(stub), ((uint8_t[]){ bytes, 0xc3 }), nr_ + 1); \ + memcpy(_p, ((uint8_t[]){ bytes }), nr_); _p += nr_; \ + place_ret(_p); \ invoke_stub(_PRE_EFLAGS("[eflags]", "[mask]", "[tmp]"), \ _POST_EFLAGS("[eflags]", "[mask]", "[tmp]"), \ [eflags] "+g" (regs->eflags), [tmp] "=&r" (tmp_) \ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/private.h xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/private.h --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/private.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/private.h 2025-11-25 08:37:47.000000000 +0000 @@ -705,12 +705,15 @@ stub_exn.info = (union stub_exception_token) { .raw = ~0 }; \ stub_exn.line = __LINE__; /* Utility outweighs livepatching cost */ \ block_speculation(); /* SCSB */ \ - asm volatile ( pre "\n\tINDIRECT_CALL %[stub]\n\t" post "\n" \ + asm volatile ( pre "\n\t" \ + "INDIRECT_CALL %[stub]\n" \ ".Lret%=:\n\t" \ + post "\n\t" \ + ".Lskip%=:\n\t" \ ".pushsection .fixup,\"ax\"\n" \ ".Lfix%=:\n\t" \ "pop %[exn]\n\t" \ - "jmp .Lret%=\n\t" \ + "jmp .Lskip%=\n\t" \ ".popsection\n\t" \ _ASM_EXTABLE(.Lret%=, .Lfix%=) \ : [exn] "+g" (stub_exn.info) ASM_CALL_CONSTRAINT, \ diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/x86_emulate.c xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/x86_emulate.c --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/x86_emulate/x86_emulate.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/x86_emulate/x86_emulate.c 2025-11-25 08:37:47.000000000 +0000 @@ -1398,7 +1398,7 @@ stb[3] = 0x91; stb[4] = evex.opmsk << 3; insn_bytes = 5; - stb[5] = 0xc3; + place_ret(&stb[5]); invoke_stub("", "", "+m" (op_mask) : "a" (&op_mask)); @@ -3631,7 +3631,7 @@ } opc[1] = (modrm & 0x38) | 0xc0; insn_bytes = EVEX_PFX_BYTES + 2; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_EVEX(opc, evex); invoke_stub("", "", "=g" (dummy) : "a" (src.val)); @@ -3698,7 +3698,7 @@ insn_bytes = PFX_BYTES + 2; copy_REX_VEX(opc, rex_prefix, vex); } - opc[2] = 0xc3; + place_ret(&opc[2]); ea.reg = decode_gpr(&_regs, modrm_reg); invoke_stub("", "", "=a" (*ea.reg) : "c" (mmvalp), "m" (*mmvalp)); @@ -3772,7 +3772,7 @@ insn_bytes = PFX_BYTES + 2; copy_REX_VEX(opc, rex_prefix, vex); } - opc[2] = 0xc3; + place_ret(&opc[2]); _regs.eflags &= ~EFLAGS_MASK; invoke_stub("", @@ -4008,7 +4008,7 @@ opc[1] = modrm & 0xc7; insn_bytes = PFX_BYTES + 2; simd_0f_to_gpr: - opc[insn_bytes - PFX_BYTES] = 0xc3; + place_ret(&opc[insn_bytes - PFX_BYTES]); generate_exception_if(ea.type != OP_REG, X86_EXC_UD); @@ -4405,7 +4405,7 @@ vex.w = 0; opc[1] = modrm & 0x38; insn_bytes = PFX_BYTES + 2; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_REX_VEX(opc, rex_prefix, vex); invoke_stub("", "", "+m" (src.val) : "a" (&src.val)); @@ -4442,7 +4442,7 @@ evex.w = 0; opc[1] = modrm & 0x38; insn_bytes = EVEX_PFX_BYTES + 2; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_EVEX(opc, evex); invoke_stub("", "", "+m" (src.val) : "a" (&src.val)); @@ -4637,7 +4637,7 @@ #endif /* X86EMUL_NO_SIMD */ simd_0f_reg_only: - opc[insn_bytes - PFX_BYTES] = 0xc3; + place_ret(&opc[insn_bytes - PFX_BYTES]); copy_REX_VEX(opc, rex_prefix, vex); invoke_stub("", "", [dummy_out] "=g" (dummy) : [dummy_in] "i" (0) ); @@ -4971,7 +4971,7 @@ if ( !mode_64bit() ) vex.w = 0; opc[1] = modrm & 0xf8; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_VEX(opc, vex); ea.reg = decode_gpr(&_regs, modrm_rm); @@ -5014,7 +5014,7 @@ if ( !mode_64bit() ) vex.w = 0; opc[1] = modrm & 0xc7; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_VEX(opc, vex); invoke_stub("", "", "=a" (dst.val) : [dummy] "i" (0)); @@ -5044,7 +5044,7 @@ opc = init_prefixes(stub); opc[0] = b; opc[1] = modrm; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_VEX(opc, vex); _regs.eflags &= ~EFLAGS_MASK; @@ -5268,62 +5268,26 @@ break; case X86EMUL_OPC(0x0f, 0xbc): /* bsf or tzcnt */ - { - bool zf; - - asm ( "bsf %2,%0" ASM_FLAG_OUT(, "; setz %1") - : "=r" (dst.val), ASM_FLAG_OUT("=@ccz", "=qm") (zf) - : "rm" (src.val) ); - _regs.eflags &= ~X86_EFLAGS_ZF; - if ( (vex.pfx == vex_f3) && vcpu_has_bmi1() ) - { - _regs.eflags &= ~X86_EFLAGS_CF; - if ( zf ) - { - _regs.eflags |= X86_EFLAGS_CF; - dst.val = op_bytes * 8; - } - else if ( !dst.val ) - _regs.eflags |= X86_EFLAGS_ZF; - } - else if ( zf ) + if ( vex.pfx == vex_f3 ) + emulate_2op_SrcV_srcmem("rep; bsf", src, dst, _regs.eflags); + else { - _regs.eflags |= X86_EFLAGS_ZF; - dst.type = OP_NONE; + emulate_2op_SrcV_srcmem("bsf", src, dst, _regs.eflags); + if ( _regs.eflags & X86_EFLAGS_ZF ) + dst.type = OP_NONE; } break; - } case X86EMUL_OPC(0x0f, 0xbd): /* bsr or lzcnt */ - { - bool zf; - - asm ( "bsr %2,%0" ASM_FLAG_OUT(, "; setz %1") - : "=r" (dst.val), ASM_FLAG_OUT("=@ccz", "=qm") (zf) - : "rm" (src.val) ); - _regs.eflags &= ~X86_EFLAGS_ZF; - if ( (vex.pfx == vex_f3) && vcpu_has_lzcnt() ) - { - _regs.eflags &= ~X86_EFLAGS_CF; - if ( zf ) - { - _regs.eflags |= X86_EFLAGS_CF; - dst.val = op_bytes * 8; - } - else - { - dst.val = op_bytes * 8 - 1 - dst.val; - if ( !dst.val ) - _regs.eflags |= X86_EFLAGS_ZF; - } - } - else if ( zf ) + if ( vex.pfx == vex_f3 ) + emulate_2op_SrcV_srcmem("rep; bsr", src, dst, _regs.eflags); + else { - _regs.eflags |= X86_EFLAGS_ZF; - dst.type = OP_NONE; + emulate_2op_SrcV_srcmem("bsr", src, dst, _regs.eflags); + if ( _regs.eflags & X86_EFLAGS_ZF ) + dst.type = OP_NONE; } break; - } case X86EMUL_OPC(0x0f, 0xbe): /* movsx rm8,r{16,32,64} */ /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */ @@ -5612,7 +5576,7 @@ if ( !mode_64bit() ) vex.w = 0; opc[1] = modrm & 0xc7; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_REX_VEX(opc, rex_prefix, vex); invoke_stub("", "", "=a" (ea.val) : [dummy] "i" (0)); @@ -5730,7 +5694,7 @@ opc[1] &= 0x38; } insn_bytes = PFX_BYTES + 2; - opc[2] = 0xc3; + place_ret(&opc[2]); if ( vex.opcx == vex_none ) { /* Cover for extra prefix byte. */ @@ -6010,7 +5974,7 @@ pvex->b = !mode_64bit() || (vex.reg >> 3); opc[1] = 0xc0 | (~vex.reg & 7); pvex->reg = 0xf; - opc[2] = 0xc3; + place_ret(&opc[2]); invoke_stub("", "", "=a" (ea.val) : [dummy] "i" (0)); put_stub(stub); @@ -6284,7 +6248,7 @@ evex.w = 0; opc[1] = modrm & 0xf8; insn_bytes = EVEX_PFX_BYTES + 2; - opc[2] = 0xc3; + place_ret(&opc[2]); copy_EVEX(opc, evex); invoke_stub("", "", "=g" (dummy) : "a" (src.val)); @@ -6383,7 +6347,7 @@ pvex->b = 1; opc[1] = (modrm_reg & 7) << 3; pvex->reg = 0xf; - opc[2] = 0xc3; + place_ret(&opc[2]); invoke_stub("", "", "=m" (*mmvalp) : "a" (mmvalp)); @@ -6453,7 +6417,7 @@ pvex->b = 1; opc[1] = (modrm_reg & 7) << 3; pvex->reg = 0xf; - opc[2] = 0xc3; + place_ret(&opc[2]); invoke_stub("", "", "+m" (*mmvalp) : "a" (mmvalp)); @@ -6509,7 +6473,7 @@ pevex->b = 1; opc[1] = (modrm_reg & 7) << 3; pevex->RX = 1; - opc[2] = 0xc3; + place_ret(&opc[2]); invoke_stub("", "", "=m" (*mmvalp) : "a" (mmvalp)); @@ -6574,7 +6538,7 @@ pevex->b = 1; opc[1] = (modrm_reg & 7) << 3; pevex->RX = 1; - opc[2] = 0xc3; + place_ret(&opc[2]); invoke_stub("", "", "+m" (*mmvalp) : "a" (mmvalp)); @@ -6588,7 +6552,7 @@ opc[2] = 0x90; /* Use (%rax) as source. */ opc[3] = evex.opmsk << 3; - opc[4] = 0xc3; + place_ret(&opc[4]); invoke_stub("", "", "+m" (op_mask) : "a" (&op_mask)); put_stub(stub); @@ -6664,7 +6628,7 @@ pevex->b = 1; opc[1] = (modrm_reg & 7) << 3; pevex->RX = 1; - opc[2] = 0xc3; + place_ret(&opc[2]); invoke_stub("", "", "=m" (*mmvalp) : "a" (mmvalp)); @@ -6741,7 +6705,7 @@ opc[2] = 0x90; /* Use (%rax) as source. */ opc[3] = evex.opmsk << 3; - opc[4] = 0xc3; + place_ret(&opc[4]); invoke_stub("", "", "+m" (op_mask) : "a" (&op_mask)); put_stub(stub); @@ -6940,7 +6904,7 @@ pvex->reg = 0xf; /* rAX */ buf[3] = b; buf[4] = 0x09; /* reg=rCX r/m=(%rCX) */ - buf[5] = 0xc3; + place_ret(&buf[5]); src.reg = decode_vex_gpr(vex.reg, &_regs, ctxt); emulate_stub([dst] "=&c" (dst.val), "[dst]" (&src.val), "a" (*src.reg)); @@ -6976,7 +6940,7 @@ pvex->reg = 0xf; /* rAX */ buf[3] = b; buf[4] = (modrm & 0x38) | 0x01; /* r/m=(%rCX) */ - buf[5] = 0xc3; + place_ret(&buf[5]); dst.reg = decode_vex_gpr(vex.reg, &_regs, ctxt); emulate_stub("=&a" (dst.val), "c" (&src.val)); @@ -7217,7 +7181,7 @@ evex.w = vex.w = 0; opc[1] = modrm & 0x38; opc[2] = imm1; - opc[3] = 0xc3; + place_ret(&opc[3]); if ( vex.opcx == vex_none ) { /* Cover for extra prefix byte. */ @@ -7384,7 +7348,7 @@ insn_bytes = PFX_BYTES + 3; copy_VEX(opc, vex); } - opc[3] = 0xc3; + place_ret(&opc[3]); /* Latch MXCSR - we may need to restore it below. */ invoke_stub("stmxcsr %[mxcsr]", "", @@ -7630,7 +7594,7 @@ } opc[2] = imm1; insn_bytes = PFX_BYTES + 3; - opc[3] = 0xc3; + place_ret(&opc[3]); if ( vex.opcx == vex_none ) { /* Cover for extra prefix byte. */ @@ -7976,7 +7940,7 @@ pxop->reg = 0xf; /* rAX */ buf[3] = b; buf[4] = (modrm & 0x38) | 0x01; /* r/m=(%rCX) */ - buf[5] = 0xc3; + place_ret(&buf[5]); dst.reg = decode_vex_gpr(vex.reg, &_regs, ctxt); emulate_stub([dst] "=&a" (dst.val), "c" (&src.val)); @@ -8085,7 +8049,7 @@ buf[3] = b; buf[4] = 0x09; /* reg=rCX r/m=(%rCX) */ *(uint32_t *)(buf + 5) = imm1; - buf[9] = 0xc3; + place_ret(&buf[9]); emulate_stub([dst] "=&c" (dst.val), "[dst]" (&src.val)); @@ -8181,12 +8145,12 @@ if ( evex_encoded() ) { - opc[insn_bytes - EVEX_PFX_BYTES] = 0xc3; + place_ret(&opc[insn_bytes - EVEX_PFX_BYTES]); copy_EVEX(opc, evex); } else { - opc[insn_bytes - PFX_BYTES] = 0xc3; + place_ret(&opc[insn_bytes - PFX_BYTES]); copy_REX_VEX(opc, rex_prefix, vex); } @@ -8510,7 +8474,7 @@ pvex->reg = 0xf; /* rAX */ buf[3] = ctxt->opcode; buf[4] = 0x11; /* reg=rDX r/m=(%RCX) */ - buf[5] = 0xc3; + place_ret(&buf[5]); *eflags &= ~EFLAGS_MASK; invoke_stub("", diff -Nru xen-4.20.0+68-g35cb38b222/xen/arch/x86/xen.lds.S xen-4.20.2+7-g1badcf5035/xen/arch/x86/xen.lds.S --- xen-4.20.0+68-g35cb38b222/xen/arch/x86/xen.lds.S 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/arch/x86/xen.lds.S 2025-11-25 08:37:47.000000000 +0000 @@ -83,6 +83,7 @@ . = ALIGN(PAGE_SIZE); _stextentry = .; *(.text.entry) + *(.text.entry.*) . = ALIGN(PAGE_SIZE); _etextentry = .; @@ -172,6 +173,8 @@ __note_gnu_build_id_end = .; } PHDR(note) PHDR(text) #elif defined(BUILD_ID_EFI) + /* Workaround bug in binutils < 2.36 */ + . = ALIGN(32); DECL_SECTION(.buildid) { __note_gnu_build_id_start = .; *(.buildid) diff -Nru xen-4.20.0+68-g35cb38b222/xen/common/Kconfig xen-4.20.2+7-g1badcf5035/xen/common/Kconfig --- xen-4.20.0+68-g35cb38b222/xen/common/Kconfig 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/common/Kconfig 2025-11-25 08:37:47.000000000 +0000 @@ -136,6 +136,17 @@ When enabled, indirect branches are implemented using a new construct called "retpoline" that prevents speculation. +config RETURN_THUNK + bool "Out-of-line Returns" + depends on CC_HAS_RETURN_THUNK + default INDIRECT_THUNK + help + Compile Xen with out-of-line returns. + + This allows Xen to mitigate a variety of speculative vulnerabilities + by choosing a hardware-dependent instruction sequence to implement + function returns safely. + config SPECULATIVE_HARDEN_ARRAY bool "Speculative Array Hardening" default y diff -Nru xen-4.20.0+68-g35cb38b222/xen/common/efi/boot.c xen-4.20.2+7-g1badcf5035/xen/common/efi/boot.c --- xen-4.20.0+68-g35cb38b222/xen/common/efi/boot.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/common/efi/boot.c 2025-11-25 08:37:47.000000000 +0000 @@ -327,10 +327,11 @@ if ( argc ) { + argc = 0; cmdline = data + *offset; /* EFI_LOAD_OPTION does not supply an image name as first component. */ if ( *offset ) - *argv++ = NULL; + argv[argc++] = NULL; } else if ( size > sizeof(*cmdline) && !(size % sizeof(*cmdline)) && (wmemchr(data, 0, size / sizeof(*cmdline)) == @@ -391,14 +392,14 @@ ++argc; else if ( prev && wstrcmp(prev, L"--") == 0 ) { - --argv; + --argc; if ( options ) *options = cmdline; break; } else { - *argv++ = prev = ptr; + argv[argc++] = prev = ptr; *ptr = *cmdline; *++ptr = 0; } @@ -406,7 +407,7 @@ prev_sep = cur_sep; } if ( argv ) - *argv = NULL; + argv[argc] = NULL; return argc; } @@ -1302,8 +1303,8 @@ (argc + 1) * sizeof(*argv) + loaded_image->LoadOptionsSize, (void **)&argv) == EFI_SUCCESS ) - get_argv(argc, argv, loaded_image->LoadOptions, - loaded_image->LoadOptionsSize, &offset, &options); + argc = get_argv(argc, argv, loaded_image->LoadOptions, + loaded_image->LoadOptionsSize, &offset, &options); else argc = 0; for ( i = 1; i < argc; ++i ) @@ -1484,8 +1485,11 @@ efi_arch_cfg_file_late(loaded_image, dir_handle, section.s); - efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size)); - cfg.addr = 0; + if ( cfg.need_to_free ) + { + efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size)); + cfg.need_to_free = false; + } dir_handle->Close(dir_handle); diff -Nru xen-4.20.0+68-g35cb38b222/xen/common/sched/arinc653.c xen-4.20.2+7-g1badcf5035/xen/common/sched/arinc653.c --- xen-4.20.0+68-g35cb38b222/xen/common/sched/arinc653.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/common/sched/arinc653.c 2025-11-25 08:37:47.000000000 +0000 @@ -361,6 +361,8 @@ ops->sched_data = prv; prv->next_major_frame = 0; + prv->major_frame = DEFAULT_TIMESLICE; + prv->schedule[0].runtime = DEFAULT_TIMESLICE; spin_lock_init(&prv->lock); INIT_LIST_HEAD(&prv->unit_list); @@ -526,27 +528,31 @@ spin_lock_irqsave(&sched_priv->lock, flags); - if ( sched_priv->num_schedule_entries < 1 ) - sched_priv->next_major_frame = now + DEFAULT_TIMESLICE; - else if ( now >= sched_priv->next_major_frame ) + ASSERT(sched_priv->major_frame > 0); + + /* Switch to next major frame using a modulo operation */ + if ( now >= sched_priv->next_major_frame ) { - /* time to enter a new major frame - * the first time this function is called, this will be true */ - /* start with the first domain in the schedule */ + s_time_t major_frame = sched_priv->major_frame; + s_time_t remainder = (now - sched_priv->next_major_frame) % major_frame; + + /* + * major_frame and schedule[0].runtime contain DEFAULT_TIMESLICE + * if num_schedule_entries is zero. + */ sched_priv->sched_index = 0; - sched_priv->next_major_frame = now + sched_priv->major_frame; - sched_priv->next_switch_time = now + sched_priv->schedule[0].runtime; + sched_priv->next_major_frame = now - remainder + major_frame; + sched_priv->next_switch_time = now - remainder + + sched_priv->schedule[0].runtime; } - else + + /* Switch minor frame or find correct minor frame after a miss */ + while ( (now >= sched_priv->next_switch_time) && + (sched_priv->sched_index < sched_priv->num_schedule_entries) ) { - while ( (now >= sched_priv->next_switch_time) && - (sched_priv->sched_index < sched_priv->num_schedule_entries) ) - { - /* time to switch to the next domain in this major frame */ - sched_priv->sched_index++; - sched_priv->next_switch_time += - sched_priv->schedule[sched_priv->sched_index].runtime; - } + sched_priv->sched_index++; + sched_priv->next_switch_time += + sched_priv->schedule[sched_priv->sched_index].runtime; } /* diff -Nru xen-4.20.0+68-g35cb38b222/xen/common/sched/credit2.c xen-4.20.2+7-g1badcf5035/xen/common/sched/credit2.c --- xen-4.20.0+68-g35cb38b222/xen/common/sched/credit2.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/common/sched/credit2.c 2025-11-25 08:37:47.000000000 +0000 @@ -3278,13 +3278,14 @@ /* How long should we let this unit run for? */ static s_time_t csched2_runtime(const struct scheduler *ops, int cpu, - struct csched2_unit *snext, s_time_t now) + struct csched2_unit *snext, s_time_t now, int inflight_credit) { s_time_t time, min_time; int rt_credit; /* Proposed runtime measured in credits */ struct csched2_runqueue_data *rqd = c2rqd(cpu); struct list_head *runq = &rqd->runq; const struct csched2_private *prv = csched2_priv(ops); + int swait_credit = 0; /* * If we're idle, just stay so. Others (or external events) @@ -3320,17 +3321,21 @@ /* * 2) If there's someone waiting whose credit is positive, * run until your credit ~= his. + * Note that this someone might be the one who was just + * running and is about to be placed back on the runqueue. */ if ( ! list_empty(runq) ) { struct csched2_unit *swait = runq_elem(runq->next); - if ( ! is_idle_unit(swait->unit) - && swait->credit > 0 ) - { - rt_credit = snext->credit - swait->credit; - } + if ( !is_idle_unit(swait->unit) && swait->credit > 0 ) + swait_credit = swait->credit; } + if ( swait_credit < inflight_credit ) + swait_credit = inflight_credit; + + if ( swait_credit > 0 ) + rt_credit = snext->credit - swait_credit; /* * The next guy on the runqueue may actually have a higher credit, @@ -3582,6 +3587,7 @@ struct csched2_runqueue_data *rqd; struct csched2_unit * const scurr = csched2_unit(currunit); struct csched2_unit *snext = NULL; + int inflight_credit = 0; bool tickled; bool migrated = false; @@ -3716,6 +3722,13 @@ balance_load(ops, sched_cpu, now); } + /* + * This must occur after the potential credit reset above, + * otherwise it would capture a negative credit. + */ + if ( test_bit(__CSFLAG_delayed_runq_add, &scurr->flags) ) + inflight_credit = scurr->credit; + snext->start_time = now; snext->tickled_cpu = -1; @@ -3756,7 +3769,8 @@ /* * Return task to run next... */ - currunit->next_time = csched2_runtime(ops, sched_cpu, snext, now); + currunit->next_time = csched2_runtime(ops, sched_cpu, snext, now, + inflight_credit); currunit->next_task = snext->unit; snext->unit->migrated = migrated; diff -Nru xen-4.20.0+68-g35cb38b222/xen/common/softirq.c xen-4.20.2+7-g1badcf5035/xen/common/softirq.c --- xen-4.20.0+68-g35cb38b222/xen/common/softirq.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/common/softirq.c 2025-11-25 08:37:47.000000000 +0000 @@ -94,9 +94,7 @@ raise_mask = &per_cpu(batch_mask, this_cpu); for_each_cpu(cpu, mask) - if ( !test_and_set_bit(nr, &softirq_pending(cpu)) && - cpu != this_cpu && - !arch_skip_send_event_check(cpu) ) + if ( !arch_set_softirq(nr, cpu) && cpu != this_cpu ) __cpumask_set_cpu(cpu, raise_mask); if ( raise_mask == &send_mask ) @@ -107,9 +105,7 @@ { unsigned int this_cpu = smp_processor_id(); - if ( test_and_set_bit(nr, &softirq_pending(cpu)) - || (cpu == this_cpu) - || arch_skip_send_event_check(cpu) ) + if ( arch_set_softirq(nr, cpu) || cpu == this_cpu ) return; if ( !per_cpu(batching, this_cpu) || in_irq() ) diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/acpi/pmstat.c xen-4.20.2+7-g1badcf5035/xen/drivers/acpi/pmstat.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/acpi/pmstat.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/acpi/pmstat.c 2025-11-25 08:37:47.000000000 +0000 @@ -103,8 +103,14 @@ cpufreq_residency_update(op->cpuid, pxpt->u.cur); + /* + * Avoid partial copying of 2-D array, whereas partial copying of a + * simple vector (further down) is deemed okay. + */ ct = pmpt->perf.state_count; - if ( copy_to_guest(op->u.getpx.trans_pt, pxpt->u.trans_pt, ct*ct) ) + if ( ct > op->u.getpx.total ) + ct = op->u.getpx.total; + else if ( copy_to_guest(op->u.getpx.trans_pt, pxpt->u.trans_pt, ct * ct) ) { spin_unlock(cpufreq_statistic_lock); ret = -EFAULT; diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/cpufreq/cpufreq.c xen-4.20.2+7-g1badcf5035/xen/drivers/cpufreq/cpufreq.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/cpufreq/cpufreq.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/cpufreq/cpufreq.c 2025-11-25 08:37:47.000000000 +0000 @@ -511,7 +511,7 @@ } } - if ( perf->flags & XEN_PX_PSS ) + if ( perf->flags & XEN_PX_PSS && !pxpt->states ) { /* capability check */ if ( perf->state_count <= 1 ) @@ -528,6 +528,7 @@ } if ( copy_from_guest(pxpt->states, perf->states, perf->state_count) ) { + XFREE(pxpt->states); ret = -EFAULT; goto out; } diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/cpufreq/utility.c xen-4.20.2+7-g1badcf5035/xen/drivers/cpufreq/utility.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/cpufreq/utility.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/cpufreq/utility.c 2025-11-25 08:37:47.000000000 +0000 @@ -113,7 +113,6 @@ spin_unlock(cpufreq_statistic_lock); return -ENOMEM; } - per_cpu(cpufreq_statistic_data, cpu) = pxpt; pxpt->u.trans_pt = xzalloc_array(uint64_t, count * count); if (!pxpt->u.trans_pt) { @@ -139,6 +138,8 @@ pxpt->prev_state_wall = NOW(); pxpt->prev_idle_wall = get_cpu_idle_time(cpu); + per_cpu(cpufreq_statistic_data, cpu) = pxpt; + spin_unlock(cpufreq_statistic_lock); return 0; diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/amd/iommu_init.c xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/amd/iommu_init.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/amd/iommu_init.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/amd/iommu_init.c 2025-11-25 08:37:47.000000000 +0000 @@ -429,8 +429,6 @@ unsigned long flags; struct amd_iommu *iommu = desc->action->dev_id; - irq_complete_move(desc); - spin_lock_irqsave(&iommu->lock, flags); amd_iommu_msi_enable(iommu, IOMMU_CONTROL_DISABLED); spin_unlock_irqrestore(&iommu->lock, flags); @@ -443,6 +441,13 @@ return 0; } +static void cf_check iommu_msi_ack(struct irq_desc *desc) +{ + irq_complete_move(desc); + iommu_msi_mask(desc); + move_masked_irq(desc); +} + static void cf_check iommu_msi_end(struct irq_desc *desc, u8 vector) { iommu_msi_unmask(desc); @@ -456,7 +461,7 @@ .shutdown = iommu_msi_mask, .enable = iommu_msi_unmask, .disable = iommu_msi_mask, - .ack = iommu_msi_mask, + .ack = iommu_msi_ack, .end = iommu_msi_end, .set_affinity = set_msi_affinity, }; diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/amd/iommu_intr.c xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/amd/iommu_intr.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/amd/iommu_intr.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/amd/iommu_intr.c 2025-11-25 08:37:47.000000000 +0000 @@ -551,6 +551,13 @@ for ( i = 1; i < nr; ++i ) msi_desc[i].remap_index = msi_desc->remap_index + i; msg->data = data; + /* + * While the low address bits don't matter, "canonicalize" the address + * by zapping the bits that were transferred to the IRTE. This way + * callers can check for there actually needing to be an update to + * wherever the address is put. + */ + msg->address_lo &= ~(MSI_ADDR_DESTMODE_MASK | MSI_ADDR_DEST_ID_MASK); } return rc; diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/pci.c xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/pci.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/pci.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/pci.c 2025-11-25 08:37:47.000000000 +0000 @@ -752,6 +752,7 @@ printk(XENLOG_WARNING "SR-IOV device %pp with vf BAR%u in IO space\n", &pdev->sbdf, i); + ++i; continue; } ret = pci_size_mem_bar(pdev->sbdf, idx, NULL, diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/vtd/iommu.c xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/vtd/iommu.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/passthrough/vtd/iommu.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/passthrough/vtd/iommu.c 2025-11-25 08:37:47.000000000 +0000 @@ -1498,6 +1498,11 @@ ASSERT(pcidevs_locked()); spin_lock(&iommu->lock); maddr = bus_to_context_maddr(iommu, bus); + if ( !maddr ) + { + spin_unlock(&iommu->lock); + return -ENOMEM; + } context_entries = (struct context_entry *)map_vtd_domain_page(maddr); context = &context_entries[devfn]; old = (lctxt = *context).full; @@ -1852,6 +1857,12 @@ spin_lock(&iommu->lock); maddr = bus_to_context_maddr(iommu, bus); + if ( !maddr ) + { + ASSERT_UNREACHABLE(); + spin_unlock(&iommu->lock); + return 0; + } context_entries = (struct context_entry *)map_vtd_domain_page(maddr); context = &context_entries[devfn]; diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/vpci/header.c xen-4.20.2+7-g1badcf5035/xen/drivers/vpci/header.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/vpci/header.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/vpci/header.c 2025-11-25 08:37:47.000000000 +0000 @@ -394,6 +394,15 @@ return rc; } } + + rc = pci_sanitize_bar_memory(bar->mem); + if ( rc ) + { + gprintk(XENLOG_WARNING, + "%pp: failed to sanitize BAR#%u memory: %d\n", + &pdev->sbdf, i, rc); + return rc; + } } /* Remove any MSIX regions if present. */ @@ -1007,7 +1016,7 @@ pci_conf_write16(pdev->sbdf, PCI_COMMAND, cmd); return rc; } -REGISTER_VPCI_INIT(init_header, VPCI_PRIORITY_MIDDLE); +REGISTER_VPCI_INIT(init_header, VPCI_PRIORITY_HIGH); /* * Local variables: diff -Nru xen-4.20.0+68-g35cb38b222/xen/drivers/vpci/msix.c xen-4.20.2+7-g1badcf5035/xen/drivers/vpci/msix.c --- xen-4.20.0+68-g35cb38b222/xen/drivers/vpci/msix.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/drivers/vpci/msix.c 2025-11-25 08:37:47.000000000 +0000 @@ -17,6 +17,7 @@ * License along with this program; If not, see . */ +#include #include #include @@ -723,6 +724,51 @@ if ( !msix ) return -ENOMEM; + msix->tables[VPCI_MSIX_TABLE] = + pci_conf_read32(pdev->sbdf, msix_table_offset_reg(msix_offset)); + msix->tables[VPCI_MSIX_PBA] = + pci_conf_read32(pdev->sbdf, msix_pba_offset_reg(msix_offset)); + + /* Check that the referenced BAR(s) regions are valid. */ + for ( i = 0; i < ARRAY_SIZE(msix->tables); i++ ) + { + const char *name = (i == VPCI_MSIX_TABLE) ? "vector" : "PBA"; + const struct vpci_bar *bars = pdev->vpci->header.bars; + unsigned int bir = msix->tables[i] & PCI_MSIX_BIRMASK; + unsigned int type; + unsigned int offset = msix->tables[i] & ~PCI_MSIX_BIRMASK; + unsigned int size = + (i == VPCI_MSIX_TABLE) ? max_entries * PCI_MSIX_ENTRY_SIZE + : ROUNDUP(DIV_ROUND_UP(max_entries, 8), 8); + + if ( bir >= ARRAY_SIZE(pdev->vpci->header.bars) ) + { + printk(XENLOG_ERR DEV_BUG_PREFIX + "%pp: MSI-X %s table with out of range BIR %u\n", + &pdev->sbdf, name, bir); + invalid: + xfree(msix); + return -ENODEV; + } + + type = bars[bir].type; + if ( type != VPCI_BAR_MEM32 && type != VPCI_BAR_MEM64_LO ) + { + printk(XENLOG_ERR DEV_BUG_PREFIX + "%pp: MSI-X %s table at invalid BAR%u with type %u\n", + &pdev->sbdf, name, bir, type); + goto invalid; + } + + if ( (uint64_t)offset + size > bars[bir].size ) + { + printk(XENLOG_ERR DEV_BUG_PREFIX + "%pp: MSI-X %s table offset %#x size %#x outside of BAR%u size %#lx\n", + &pdev->sbdf, name, offset, size, bir, bars[bir].size); + goto invalid; + } + } + rc = vpci_add_register(pdev->vpci, control_read, control_write, msix_control_reg(msix_offset), 2, msix); if ( rc ) @@ -734,11 +780,6 @@ msix->max_entries = max_entries; msix->pdev = pdev; - msix->tables[VPCI_MSIX_TABLE] = - pci_conf_read32(pdev->sbdf, msix_table_offset_reg(msix_offset)); - msix->tables[VPCI_MSIX_PBA] = - pci_conf_read32(pdev->sbdf, msix_pba_offset_reg(msix_offset)); - for ( i = 0; i < max_entries; i++) { msix->entries[i].masked = true; @@ -751,9 +792,14 @@ pdev->vpci->msix = msix; list_add(&msix->next, &d->arch.hvm.msix_tables); - return 0; + /* + * vPCI header initialization will have mapped the whole BAR into the + * p2m, as MSI-X capability was not yet initialized. Crave a hole for + * the MSI-X table here, so that Xen can trap accesses. + */ + return vpci_make_msix_hole(pdev); } -REGISTER_VPCI_INIT(init_msix, VPCI_PRIORITY_HIGH); +REGISTER_VPCI_INIT(init_msix, VPCI_PRIORITY_MIDDLE); /* * Local variables: diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/public/arch-x86/cpufeatureset.h xen-4.20.2+7-g1badcf5035/xen/include/public/arch-x86/cpufeatureset.h --- xen-4.20.0+68-g35cb38b222/xen/include/public/arch-x86/cpufeatureset.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/public/arch-x86/cpufeatureset.h 2025-11-25 08:37:47.000000000 +0000 @@ -315,6 +315,7 @@ XEN_CPUFEATURE(NO_NEST_BP, 11*32+ 0) /*A No Nested Data Breakpoints */ XEN_CPUFEATURE(FS_GS_NS, 11*32+ 1) /*S| FS/GS base MSRs non-serialising */ XEN_CPUFEATURE(LFENCE_DISPATCH, 11*32+ 2) /*A LFENCE always serializing */ +XEN_CPUFEATURE(VERW_CLEAR, 11*32+ 5) /*!A| VERW clears microarchitectural buffers */ XEN_CPUFEATURE(NSCB, 11*32+ 6) /*A Null Selector Clears Base (and limit too) */ XEN_CPUFEATURE(AUTO_IBRS, 11*32+ 8) /*S Automatic IBRS */ XEN_CPUFEATURE(AMD_FSRS, 11*32+10) /*A Fast Short REP STOSB */ @@ -379,7 +380,13 @@ XEN_CPUFEATURE(RFDS_NO, 16*32+27) /*A No Register File Data Sampling */ XEN_CPUFEATURE(RFDS_CLEAR, 16*32+28) /*!A| Register File(s) cleared by VERW */ -/* Intel-defined CPU features, MSR_ARCH_CAPS 0x10a.edx, word 17 */ +/* Intel-defined CPU features, MSR_ARCH_CAPS 0x10a.edx, word 17 (express in terms of word 16) */ +XEN_CPUFEATURE(PB_OPT_CTRL, 16*32+32) /* MSR_PB_OPT_CTRL.IBPB_ALT */ +XEN_CPUFEATURE(ITS_NO, 16*32+62) /*!A No Indirect Target Selection */ + +/* AMD-defined CPU features, CPUID level 0x80000021.ecx, word 18 */ +XEN_CPUFEATURE(TSA_SQ_NO, 18*32+ 1) /*A No Store Queue Transitive Scheduler Attacks */ +XEN_CPUFEATURE(TSA_L1_NO, 18*32+ 2) /*A No L1D Transitive Scheduler Attacks */ #endif /* XEN_CPUFEATURE */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/public/sysctl.h xen-4.20.2+7-g1badcf5035/xen/include/public/sysctl.h --- xen-4.20.0+68-g35cb38b222/xen/include/public/sysctl.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/public/sysctl.h 2025-11-25 08:37:47.000000000 +0000 @@ -215,11 +215,22 @@ DEFINE_XEN_GUEST_HANDLE(pm_px_val_t); struct pm_px_stat { - uint8_t total; /* total Px states */ + /* + * IN: Number of elements in pt, number of rows/columns in trans_pt + * (PMSTAT_get_pxstat) + * OUT: total Px states (PMSTAT_get_max_px, PMSTAT_get_pxstat) + */ + uint8_t total; uint8_t usable; /* usable Px states */ uint8_t last; /* last Px state */ uint8_t cur; /* current Px state */ - XEN_GUEST_HANDLE_64(uint64) trans_pt; /* Px transition table */ + /* + * OUT: Px transition table. This should have total * total elements. + * As it is a 2-D array, this will not be copied if input total is + * less than output total. (PMSTAT_get_pxstat) + */ + XEN_GUEST_HANDLE_64(uint64) trans_pt; + /* OUT: This should have total elements (PMSTAT_get_pxstat) */ XEN_GUEST_HANDLE_64(pm_px_val_t) pt; }; diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/xen/cpuidle.h xen-4.20.2+7-g1badcf5035/xen/include/xen/cpuidle.h --- xen-4.20.0+68-g35cb38b222/xen/include/xen/cpuidle.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/xen/cpuidle.h 2025-11-25 08:37:47.000000000 +0000 @@ -92,8 +92,6 @@ bool cpuidle_using_deep_cstate(void); void cpuidle_disable_deep_cstate(void); -extern void cpuidle_wakeup_mwait(cpumask_t *mask); - #define CPUIDLE_DRIVER_STATE_START 1 extern void menu_get_trace_data(u32 *expected, u32 *pred); diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/xen/irq_cpustat.h xen-4.20.2+7-g1badcf5035/xen/include/xen/irq_cpustat.h --- xen-4.20.0+68-g35cb38b222/xen/include/xen/irq_cpustat.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/xen/irq_cpustat.h 2025-11-25 08:37:47.000000000 +0000 @@ -24,6 +24,5 @@ /* arch independent irq_stat fields */ #define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending) #define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count) -#define mwait_wakeup(cpu) __IRQ_STAT((cpu), __mwait_wakeup) #endif /* __irq_cpustat_h */ diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/xen/lib/x86/cpu-policy.h xen-4.20.2+7-g1badcf5035/xen/include/xen/lib/x86/cpu-policy.h --- xen-4.20.0+68-g35cb38b222/xen/include/xen/lib/x86/cpu-policy.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/xen/lib/x86/cpu-policy.h 2025-11-25 08:37:47.000000000 +0000 @@ -22,6 +22,7 @@ #define FEATURESET_7d1 15 /* 0x00000007:1.edx */ #define FEATURESET_m10Al 16 /* 0x0000010a.eax */ #define FEATURESET_m10Ah 17 /* 0x0000010a.edx */ +#define FEATURESET_e21c 18 /* 0x80000021.ecx */ struct cpuid_leaf { @@ -325,7 +326,14 @@ uint32_t e21a; struct { DECL_BITFIELD(e21a); }; }; - uint32_t /* b */:32, /* c */:32, /* d */:32; + uint16_t ucode_size; /* Units of 16 bytes */ + uint8_t rap_size; /* Units of 8 entries */ + uint8_t :8; + union { + uint32_t e21c; + struct { DECL_BITFIELD(e21c); }; + }; + uint32_t /* d */:32; }; } extd; diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/xen/lib.h xen-4.20.2+7-g1badcf5035/xen/include/xen/lib.h --- xen-4.20.0+68-g35cb38b222/xen/include/xen/lib.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/xen/lib.h 2025-11-25 08:37:47.000000000 +0000 @@ -58,6 +58,9 @@ debugtrace_printk(const char *fmt, ...) {} #endif +/* Common log prefixes for platform related issues. */ +#define DEV_BUG_PREFIX "DEVICE BUG: " + extern void printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2), cold)); void vprintk(const char *fmt, va_list args) diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/xen/softirq.h xen-4.20.2+7-g1badcf5035/xen/include/xen/softirq.h --- xen-4.20.0+68-g35cb38b222/xen/include/xen/softirq.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/xen/softirq.h 2025-11-25 08:37:47.000000000 +0000 @@ -21,6 +21,22 @@ #define NR_SOFTIRQS (NR_COMMON_SOFTIRQS + NR_ARCH_SOFTIRQS) +/* + * Ensure softirq @nr is pending on @cpu. Return true if an IPI can be + * skipped, false if the IPI cannot be skipped. + */ +#ifndef arch_set_softirq +static always_inline bool arch_set_softirq(unsigned int nr, unsigned int cpu) +{ + /* + * Try to set the softirq pending. If we set the bit (i.e. the old bit + * was 0), we're responsible to send the IPI. If the softirq was already + * pending (i.e. the old bit was 1), no IPI is needed. + */ + return test_and_set_bit(nr, &softirq_pending(cpu)); +} +#endif + typedef void (*softirq_handler)(void); void do_softirq(void); diff -Nru xen-4.20.0+68-g35cb38b222/xen/include/xen/xen.lds.h xen-4.20.2+7-g1badcf5035/xen/include/xen/xen.lds.h --- xen-4.20.0+68-g35cb38b222/xen/include/xen/xen.lds.h 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/include/xen/xen.lds.h 2025-11-25 08:37:47.000000000 +0000 @@ -56,6 +56,7 @@ DECL_DEBUG2(.debug_info, .gnu.linkonce.wi.*, 1) \ DECL_DEBUG(.debug_types, 1) \ DECL_DEBUG(.debug_str, 1) \ + DECL_DEBUG(.debug_str_offsets, 4) \ DECL_DEBUG2(.debug_line, .debug_line.*, 1) \ DECL_DEBUG(.debug_line_str, 1) \ DECL_DEBUG(.debug_names, 4) \ diff -Nru xen-4.20.0+68-g35cb38b222/xen/lib/x86/cpuid.c xen-4.20.2+7-g1badcf5035/xen/lib/x86/cpuid.c --- xen-4.20.0+68-g35cb38b222/xen/lib/x86/cpuid.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/lib/x86/cpuid.c 2025-11-25 08:37:47.000000000 +0000 @@ -81,6 +81,7 @@ fs[FEATURESET_7d1] = p->feat._7d1; fs[FEATURESET_m10Al] = p->arch_caps.lo; fs[FEATURESET_m10Ah] = p->arch_caps.hi; + fs[FEATURESET_e21c] = p->extd.e21c; } void x86_cpu_featureset_to_policy( @@ -104,6 +105,7 @@ p->feat._7d1 = fs[FEATURESET_7d1]; p->arch_caps.lo = fs[FEATURESET_m10Al]; p->arch_caps.hi = fs[FEATURESET_m10Ah]; + p->extd.e21c = fs[FEATURESET_e21c]; } void x86_cpu_policy_recalc_synth(struct cpu_policy *p) diff -Nru xen-4.20.0+68-g35cb38b222/xen/lib/x86-generic-hweightl.c xen-4.20.2+7-g1badcf5035/xen/lib/x86-generic-hweightl.c --- xen-4.20.0+68-g35cb38b222/xen/lib/x86-generic-hweightl.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/lib/x86-generic-hweightl.c 2025-11-25 08:37:47.000000000 +0000 @@ -51,7 +51,11 @@ "pop %rdx\n\t" "pop %rdi\n\t" +#ifdef CONFIG_RETURN_THUNK + "jmp __x86_return_thunk\n\t" +#else "ret\n\t" +#endif ".size arch_generic_hweightl, . - arch_generic_hweightl\n\t" ); diff -Nru xen-4.20.0+68-g35cb38b222/xen/tools/gen-cpuid.py xen-4.20.2+7-g1badcf5035/xen/tools/gen-cpuid.py --- xen-4.20.0+68-g35cb38b222/xen/tools/gen-cpuid.py 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/tools/gen-cpuid.py 2025-11-25 08:37:47.000000000 +0000 @@ -51,7 +51,7 @@ r"\s+/\*([\w!|]*) .*$") word_regex = re.compile( - r"^/\* .* word (\d*) \*/$") + r"^/\* .* word (\d*) .*\*/$") last_word = -1 this = sys.modules[__name__] @@ -168,6 +168,10 @@ state.hvm_shadow_max = state.pv_max | state.raw['S'] | state.raw['s'] state.hvm_hap_max = state.hvm_shadow_max | state.raw['H'] | state.raw['h'] + def feat_range(start, last): + """ Select all known features in the given range """ + return [ x for x in state.names.keys() if start <= x <= last ] + # # Feature dependency information. # @@ -334,7 +338,7 @@ PSFD: [EPSF], # The ARCH_CAPS CPUID bit enumerates the availability of the whole register. - ARCH_CAPS: list(range(RDCL_NO, RDCL_NO + 64)), + ARCH_CAPS: feat_range(RDCL_NO, RDCL_NO + 63), # The behaviour described by RRSBA depend on eIBRS being active. EIBRS: [RRSBA], @@ -350,7 +354,7 @@ for feat in deep_features: - seen = [feat] + seen = [] to_process = list(deps[feat]) while len(to_process): @@ -358,19 +362,22 @@ # To debug, uncomment the following lines: # def repl(l): # return "[" + ", ".join((state.names[x] for x in l)) + "]" - # sys.stderr.write("Feature %s, seen %s, to_process %s \n" % \ + # sys.stderr.write("Feature %s, seen %s, to_process %s\n" % # (state.names[feat], repl(seen), repl(to_process))) f = to_process.pop(0) + if f == feat: + raise Fail("ERROR: Cycle found when processing %s" % + (state.names[f], )) + if f in seen: - raise Fail("ERROR: Cycle found with %s when processing %s" - % (state.names[f], state.names[feat])) + continue seen.append(f) to_process = list(set(to_process + deps.get(f, []))) - state.deep_deps[feat] = seen[1:] + state.deep_deps[feat] = seen state.deep_features = deps.keys() state.nr_deep_deps = len(state.deep_deps.keys()) diff -Nru xen-4.20.0+68-g35cb38b222/xen/tools/symbols.c xen-4.20.2+7-g1badcf5035/xen/tools/symbols.c --- xen-4.20.0+68-g35cb38b222/xen/tools/symbols.c 2025-04-29 09:47:50.000000000 +0000 +++ xen-4.20.2+7-g1badcf5035/xen/tools/symbols.c 2025-11-25 08:37:47.000000000 +0000 @@ -213,6 +213,16 @@ if (strstr((char *)s->sym + offset, "_compiled.")) return 0; + /* At least GNU ld 2.25 may emit bogus file symbols referencing a + * section name while linking xen.efi. In COFF symbol tables the + * "value" of file symbols is a link (symbol table index) to the next + * file symbol. Since file (and other) symbols (can) come with one + * (or in principle more) auxiliary symbol table entries, the value in + * this heuristic is bounded to twice the number of symbols we have + * found. See also read_symbol() as to the '?' checked for here. */ + if (s->sym[0] == '?' && s->sym[1] == '.' && s->addr < table_cnt * 2) + return 0; + return 1; }