From c15428b39a1de6365e960167eabc13d5fe905eee Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 18 Mar 2026 11:24:19 +1100 Subject: [PATCH 01/42] initial x86_64 support Add virtualisation of x86 ACPI, APIC, CMOS, COM port, cpuid, guest memory, HPET, instruction decoding, Port I/O, MSRs and PCI. Currently, only booting raw Linux kernel and initial ramdisk is supported. UEFI, virtio, PCI passthrough, etc not yet supported as of this commit. See github.com/au-ts/libvmm/tree/x86_64_rebased for original development history. Signed-off-by: Bill Nguyen --- .reuse/dep5 | 5 + LICENSES/BSD-3-Clause-acpica.txt | 183 +++++++ LICENSES/Intel-ACPI.txt | 183 +++++++ build.zig | 51 +- dep/sddf | 2 +- include/libvmm/arch/x86_64/acpi.h | 303 +++++++++++ include/libvmm/arch/x86_64/apic.h | 102 ++++ include/libvmm/arch/x86_64/cmos.h | 13 + include/libvmm/arch/x86_64/com.h | 14 + include/libvmm/arch/x86_64/cpuid.h | 11 + include/libvmm/arch/x86_64/e820.h | 23 + include/libvmm/arch/x86_64/fault.h | 29 + include/libvmm/arch/x86_64/hpet.h | 20 + include/libvmm/arch/x86_64/instruction.h | 86 +++ include/libvmm/arch/x86_64/ioports.h | 31 ++ include/libvmm/arch/x86_64/linux.h | 72 +++ include/libvmm/arch/x86_64/memory_space.h | 25 + include/libvmm/arch/x86_64/msr.h | 12 + include/libvmm/arch/x86_64/pci.h | 21 + include/libvmm/arch/x86_64/util.h | 28 + include/libvmm/arch/x86_64/vcpu.h | 56 ++ include/libvmm/arch/x86_64/virq.h | 28 + include/libvmm/arch/x86_64/vmcs.h | 198 +++++++ include/libvmm/guest.h | 10 + include/libvmm/libvmm.h | 18 + include/libvmm/util/util.h | 15 +- include/libvmm/virq.h | 7 + src/arch/aarch64/guest.c | 12 + src/arch/x86_64/acpi.c | 523 ++++++++++++++++++ src/arch/x86_64/apic.c | 560 +++++++++++++++++++ src/arch/x86_64/cmos.c | 122 +++++ src/arch/x86_64/com.c | 93 ++++ src/arch/x86_64/cpuid.c | 418 ++++++++++++++ src/arch/x86_64/fault.c | 636 ++++++++++++++++++++++ src/arch/x86_64/guest.c | 117 ++++ src/arch/x86_64/hpet.c | 589 ++++++++++++++++++++ src/arch/x86_64/instruction.c | 409 ++++++++++++++ src/arch/x86_64/ioports.c | 247 +++++++++ src/arch/x86_64/linux.c | 291 ++++++++++ src/arch/x86_64/msr.c | 212 ++++++++ src/arch/x86_64/pci.c | 247 +++++++++ src/arch/x86_64/util.c | 45 ++ src/arch/x86_64/vcpu.c | 172 ++++++ src/arch/x86_64/virq.c | 129 +++++ src/guest.c | 84 ++- vmm.mk | 52 +- 46 files changed, 6468 insertions(+), 36 deletions(-) create mode 100644 LICENSES/BSD-3-Clause-acpica.txt create mode 100644 LICENSES/Intel-ACPI.txt create mode 100644 include/libvmm/arch/x86_64/acpi.h create mode 100644 include/libvmm/arch/x86_64/apic.h create mode 100644 include/libvmm/arch/x86_64/cmos.h create mode 100644 include/libvmm/arch/x86_64/com.h create mode 100644 include/libvmm/arch/x86_64/cpuid.h create mode 100644 include/libvmm/arch/x86_64/e820.h create mode 100644 include/libvmm/arch/x86_64/fault.h create mode 100644 include/libvmm/arch/x86_64/hpet.h create mode 100644 include/libvmm/arch/x86_64/instruction.h create mode 100644 include/libvmm/arch/x86_64/ioports.h create mode 100644 include/libvmm/arch/x86_64/linux.h create mode 100644 include/libvmm/arch/x86_64/memory_space.h create mode 100644 include/libvmm/arch/x86_64/msr.h create mode 100644 include/libvmm/arch/x86_64/pci.h create mode 100644 include/libvmm/arch/x86_64/util.h create mode 100644 include/libvmm/arch/x86_64/vcpu.h create mode 100644 include/libvmm/arch/x86_64/virq.h create mode 100644 include/libvmm/arch/x86_64/vmcs.h create mode 100644 src/arch/aarch64/guest.c create mode 100644 src/arch/x86_64/acpi.c create mode 100644 src/arch/x86_64/apic.c create mode 100644 src/arch/x86_64/cmos.c create mode 100644 src/arch/x86_64/com.c create mode 100644 src/arch/x86_64/cpuid.c create mode 100644 src/arch/x86_64/fault.c create mode 100644 src/arch/x86_64/guest.c create mode 100644 src/arch/x86_64/hpet.c create mode 100644 src/arch/x86_64/instruction.c create mode 100644 src/arch/x86_64/ioports.c create mode 100644 src/arch/x86_64/linux.c create mode 100644 src/arch/x86_64/msr.c create mode 100644 src/arch/x86_64/pci.c create mode 100644 src/arch/x86_64/util.c create mode 100644 src/arch/x86_64/vcpu.c create mode 100644 src/arch/x86_64/virq.c diff --git a/.reuse/dep5 b/.reuse/dep5 index e4a041002..188aaf872 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -43,3 +43,8 @@ Files: examples/*/board/*/rootfs.cpio.gz Copyright: Buildroot License: GPL-2.0-or-later + +Files: + examples/simple/board/x86_64_generic_vtx/simple_dsdt.aml +Copyright: Intel +License: Intel-ACPI OR BSD-3-Clause-acpica diff --git a/LICENSES/BSD-3-Clause-acpica.txt b/LICENSES/BSD-3-Clause-acpica.txt new file mode 100644 index 000000000..ca650533c --- /dev/null +++ b/LICENSES/BSD-3-Clause-acpica.txt @@ -0,0 +1,183 @@ +Most of ACPICA is under the following license: + +1. Copyright Notice + +Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp. +All rights reserved. + +2. License + +2.1. This is your license from Intel Corp. under its intellectual property +rights. You may have additional license terms from the party that provided +you this software, covering your right to use that party's intellectual +property rights. + +2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a +copy of the source code appearing in this file ("Covered Code") an +irrevocable, perpetual, worldwide license under Intel's copyrights in the +base code distributed originally by Intel ("Original Intel Code") to copy, +make derivatives, distribute, use and display any portion of the Covered +Code in any form, with the right to sublicense such rights; and + +2.3. Intel grants Licensee a non-exclusive and non-transferable patent +license (with the right to sublicense), under only those claims of Intel +patents that are infringed by the Original Intel Code, to make, use, sell, +offer to sell, and import the Covered Code and derivative works thereof +solely to the minimum extent necessary to exercise the above copyright +license, and in no event shall the patent license extend to any additions +to or modifications of the Original Intel Code. No other license or right +is granted directly or by implication, estoppel or otherwise; + +The above copyright and patent license is granted only if the following +conditions are met: + +3. Conditions + +3.1. Redistribution of Source with Rights to Further Distribute Source. +Redistribution of source code of any substantial portion of the Covered +Code or modification with rights to further distribute source must include +the above Copyright Notice, the above License, this list of Conditions, +and the following Disclaimer and Export Compliance provision. In addition, +Licensee must cause all Covered Code to which Licensee contributes to +contain a file documenting the changes Licensee made to create that Covered +Code and the date of any change. Licensee must include in that file the +documentation of any changes made by any predecessor Licensee. Licensee +must include a prominent statement that the modification is derived, +directly or indirectly, from Original Intel Code. + +3.2. Redistribution of Source with no Rights to Further Distribute Source. +Redistribution of source code of any substantial portion of the Covered +Code or modification without rights to further distribute source must +include the following Disclaimer and Export Compliance provision in the +documentation and/or other materials provided with distribution. In +addition, Licensee may not authorize further sublicense of source of any +portion of the Covered Code, and must include terms to the effect that the +license from Licensee to its licensee is limited to the intellectual +property embodied in the software Licensee provides to its licensee, and +not to intellectual property embodied in modifications its licensee may +make. + +3.3. Redistribution of Executable. Redistribution in executable form of any +substantial portion of the Covered Code or modification must reproduce the +above Copyright Notice, and the following Disclaimer and Export Compliance +provision in the documentation and/or other materials provided with the +distribution. + +3.4. Intel retains all right, title, and interest in and to the Original +Intel Code. + +3.5. Neither the name Intel nor any other trademark owned or controlled by +Intel shall be used in advertising or otherwise to promote the sale, use or +other dealings in products derived from or relating to the Covered Code +without prior written authorization from Intel. + +4. Disclaimer and Export Compliance + +4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED +HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE +IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, +INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY +UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY +IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A +PARTICULAR PURPOSE. + +4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES +OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR +COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, +SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY +CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL +HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS +SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY +LIMITED REMEDY. + +4.3. Licensee shall not export, either directly or indirectly, any of this +software or system incorporating such software without first obtaining any +required license or other approval from the U. S. Department of Commerce or +any other agency or department of the United States Government. In the +event Licensee exports any such software from the United States or +re-exports any such software from a foreign destination, Licensee shall +ensure that the distribution and export/re-export of the software is in +compliance with all laws, regulations, orders, or other restrictions of the +U.S. Export Administration Regulations. Licensee agrees that neither it nor +any of its subsidiaries will export/re-export any technical data, process, +software, or service, directly or indirectly, to any country for which the +United States government or any agency thereof requires an export license, +other governmental approval, or letter of assurance, without first obtaining +such license, approval or letter. + +*************************************************************************** + +Submitting Contributions to ACPICA: +Any contribution (including patches, bug fixes, improvements, or new features) +submitted to the ACPICA project is governed by the “simplified” BSD license +reproduced below. Contributions to ACPICA are accepted under this license in +order to preserve ACPICA’s ability to license ACPICA under all three of the +licenses described above. The way to submit patches and/or bug reports or +fixes is by creating the appropriate ticket (Issue, PR) on our GitHub page. + +License for Contributions to ACPICA: +Copyright © 2000 – 2025 Intel Corp. +All rights reserved. + +Alternatively, you may choose to be licensed under the terms of the +following license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. Redistributions in binary form must reproduce at minimum a disclaimer + substantially similar to the "NO WARRANTY" disclaimer below + ("Disclaimer") and any redistribution must be conditioned upon + including a substantially similar Disclaimer requirement for further + binary redistribution. +3. Neither the names of the above-listed copyright holders nor the names + of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Alternatively, you may choose to be licensed under the terms of the +GNU General Public License ("GPL") version 2 as published by the Free +Software Foundation. + +---------------------------------- +tests/misc/grammar.asl is under the following license: + +Some or all of this work - Copyright (c) 2006 - 2025, Intel Corp. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/Intel-ACPI.txt b/LICENSES/Intel-ACPI.txt new file mode 100644 index 000000000..ca650533c --- /dev/null +++ b/LICENSES/Intel-ACPI.txt @@ -0,0 +1,183 @@ +Most of ACPICA is under the following license: + +1. Copyright Notice + +Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp. +All rights reserved. + +2. License + +2.1. This is your license from Intel Corp. under its intellectual property +rights. You may have additional license terms from the party that provided +you this software, covering your right to use that party's intellectual +property rights. + +2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a +copy of the source code appearing in this file ("Covered Code") an +irrevocable, perpetual, worldwide license under Intel's copyrights in the +base code distributed originally by Intel ("Original Intel Code") to copy, +make derivatives, distribute, use and display any portion of the Covered +Code in any form, with the right to sublicense such rights; and + +2.3. Intel grants Licensee a non-exclusive and non-transferable patent +license (with the right to sublicense), under only those claims of Intel +patents that are infringed by the Original Intel Code, to make, use, sell, +offer to sell, and import the Covered Code and derivative works thereof +solely to the minimum extent necessary to exercise the above copyright +license, and in no event shall the patent license extend to any additions +to or modifications of the Original Intel Code. No other license or right +is granted directly or by implication, estoppel or otherwise; + +The above copyright and patent license is granted only if the following +conditions are met: + +3. Conditions + +3.1. Redistribution of Source with Rights to Further Distribute Source. +Redistribution of source code of any substantial portion of the Covered +Code or modification with rights to further distribute source must include +the above Copyright Notice, the above License, this list of Conditions, +and the following Disclaimer and Export Compliance provision. In addition, +Licensee must cause all Covered Code to which Licensee contributes to +contain a file documenting the changes Licensee made to create that Covered +Code and the date of any change. Licensee must include in that file the +documentation of any changes made by any predecessor Licensee. Licensee +must include a prominent statement that the modification is derived, +directly or indirectly, from Original Intel Code. + +3.2. Redistribution of Source with no Rights to Further Distribute Source. +Redistribution of source code of any substantial portion of the Covered +Code or modification without rights to further distribute source must +include the following Disclaimer and Export Compliance provision in the +documentation and/or other materials provided with distribution. In +addition, Licensee may not authorize further sublicense of source of any +portion of the Covered Code, and must include terms to the effect that the +license from Licensee to its licensee is limited to the intellectual +property embodied in the software Licensee provides to its licensee, and +not to intellectual property embodied in modifications its licensee may +make. + +3.3. Redistribution of Executable. Redistribution in executable form of any +substantial portion of the Covered Code or modification must reproduce the +above Copyright Notice, and the following Disclaimer and Export Compliance +provision in the documentation and/or other materials provided with the +distribution. + +3.4. Intel retains all right, title, and interest in and to the Original +Intel Code. + +3.5. Neither the name Intel nor any other trademark owned or controlled by +Intel shall be used in advertising or otherwise to promote the sale, use or +other dealings in products derived from or relating to the Covered Code +without prior written authorization from Intel. + +4. Disclaimer and Export Compliance + +4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED +HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE +IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, +INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY +UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY +IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A +PARTICULAR PURPOSE. + +4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES +OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR +COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, +SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY +CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL +HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS +SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY +LIMITED REMEDY. + +4.3. Licensee shall not export, either directly or indirectly, any of this +software or system incorporating such software without first obtaining any +required license or other approval from the U. S. Department of Commerce or +any other agency or department of the United States Government. In the +event Licensee exports any such software from the United States or +re-exports any such software from a foreign destination, Licensee shall +ensure that the distribution and export/re-export of the software is in +compliance with all laws, regulations, orders, or other restrictions of the +U.S. Export Administration Regulations. Licensee agrees that neither it nor +any of its subsidiaries will export/re-export any technical data, process, +software, or service, directly or indirectly, to any country for which the +United States government or any agency thereof requires an export license, +other governmental approval, or letter of assurance, without first obtaining +such license, approval or letter. + +*************************************************************************** + +Submitting Contributions to ACPICA: +Any contribution (including patches, bug fixes, improvements, or new features) +submitted to the ACPICA project is governed by the “simplified” BSD license +reproduced below. Contributions to ACPICA are accepted under this license in +order to preserve ACPICA’s ability to license ACPICA under all three of the +licenses described above. The way to submit patches and/or bug reports or +fixes is by creating the appropriate ticket (Issue, PR) on our GitHub page. + +License for Contributions to ACPICA: +Copyright © 2000 – 2025 Intel Corp. +All rights reserved. + +Alternatively, you may choose to be licensed under the terms of the +following license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. Redistributions in binary form must reproduce at minimum a disclaimer + substantially similar to the "NO WARRANTY" disclaimer below + ("Disclaimer") and any redistribution must be conditioned upon + including a substantially similar Disclaimer requirement for further + binary redistribution. +3. Neither the names of the above-listed copyright holders nor the names + of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Alternatively, you may choose to be licensed under the terms of the +GNU General Public License ("GPL") version 2 as published by the Free +Software Foundation. + +---------------------------------- +tests/misc/grammar.asl is under the following license: + +Some or all of this work - Copyright (c) 2006 - 2025, Intel Corp. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/build.zig b/build.zig index fb1f697bf..959b6e371 100644 --- a/build.zig +++ b/build.zig @@ -22,6 +22,7 @@ const src_aarch64 = [_][]const u8{ "src/arch/aarch64/vgic/vgic_v2.c", "src/arch/aarch64/vgic/vgic_v3.c", "src/arch/aarch64/vgic/vgic_v3_cpuif.c", + "src/arch/aarch64/guest.c", "src/arch/aarch64/fault.c", "src/arch/aarch64/psci.c", "src/arch/aarch64/smc.c", @@ -32,6 +33,25 @@ const src_aarch64 = [_][]const u8{ "src/arch/aarch64/cpuif.c", }; +const src_x86_64 = [_][]const u8{ + "src/arch/x86_64/guest.c", + "src/arch/x86_64/linux.c", + "src/arch/x86_64/fault.c", + "src/arch/x86_64/vcpu.c", + "src/arch/x86_64/virq.c", + "src/arch/x86_64/cpuid.c", + "src/arch/x86_64/msr.c", + "src/arch/x86_64/acpi.c", + "src/arch/x86_64/apic.c", + "src/arch/x86_64/hpet.c", + "src/arch/x86_64/instruction.c", + "src/arch/x86_64/pci.c", + "src/arch/x86_64/ioports.c", + "src/arch/x86_64/util.c", + "src/arch/x86_64/cmos.c", + "src/arch/x86_64/com.c", +}; + /// Convert the target for Microkit (e.g freestanding AArch64 or RISC-V) to the Linux /// equivalent. Assumes musllibc will be used. fn linuxTarget(b: *std.Build, target: std.Build.ResolvedTarget) std.Build.ResolvedTarget { @@ -72,21 +92,34 @@ pub fn build(b: *std.Build) !void { switch (target.result.cpu.arch) { .aarch64 => { try srcs.appendSlice(b.allocator, &src_aarch64); + + libvmm.addCSourceFiles(.{ + .files = srcs.items, + .flags = &.{ + "-Wall", + "-Werror", + "-Wno-unused-function", + "-mstrict-align", + } + }); + }, + .x86_64 => { + try srcs.appendSlice(b.allocator, &src_x86_64); + + libvmm.addCSourceFiles(.{ + .files = srcs.items, + .flags = &.{ + "-Wall", + "-Werror", + "-Wno-unused-function", + } + }); }, else => { std.log.err("Unsupported libvmm architecture given '{s}'", .{ @tagName(target.result.cpu.arch) }); std.posix.exit(1); } } - libvmm.addCSourceFiles(.{ - .files = srcs.items, - .flags = &.{ - "-Wall", - "-Werror", - "-Wno-unused-function", - "-mstrict-align", - } - }); libvmm.addIncludePath(b.path("include")); libvmm.addIncludePath(sddf.path("include")); diff --git a/dep/sddf b/dep/sddf index 315675d86..cdbd7bbb5 160000 --- a/dep/sddf +++ b/dep/sddf @@ -1 +1 @@ -Subproject commit 315675d8621f0b54990129d7b4e54dcab464d443 +Subproject commit cdbd7bbb53bcc00401c6ccc04cf565d06ca16bbf diff --git a/include/libvmm/arch/x86_64/acpi.h b/include/libvmm/arch/x86_64/acpi.h new file mode 100644 index 000000000..6ade3be90 --- /dev/null +++ b/include/libvmm/arch/x86_64/acpi.h @@ -0,0 +1,303 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +/* Documents referenced: + * [1] Advanced Configuration and Power Interface (ACPI) Specification Release 6.5 UEFI Forum, Inc. Aug 29, 2022 + * [1a] "5.2.5.3 Root System Description Pointer (RSDP) Structure" + * [1b] "5.2.6 System Description Table Header" + * [1c] "5.2.8 Extended System Description Table (XSDT)" + * [2] IA-PC HPET (High Precision Event Timers) Specification Revision: 1.0a Date: October 2004 + * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf + * [2a] "3.2.4 The ACPI 2.0 HPET Description Table (HPET)" + */ + +/* XSDP (Root System Description Pointer) -> XSDT (Extended System Description Table) + * | + * v + * other ACPI tables + */ + +/* [1a] */ +#define XSDP_SIGNATURE "RSD PTR " +#define XSDP_SIG_LEN 8 +#define XSDP_OEM_ID_LEN 6 +#define XSDP_REVISION 2 +#define XSDP_ALIGN 16 +struct xsdp { + char signature[XSDP_SIG_LEN]; + uint8_t checksum; + char oem_id[XSDP_OEM_ID_LEN]; + uint8_t revision; + uint32_t rsdp_gpa; + + uint32_t length; + uint64_t xsdt_gpa; + uint8_t ext_checksum; + uint8_t reserved[3]; +} __attribute__((packed)); + +//////////////////////////////////////// + +/* [1b] All system description tables begin with the following structure */ +#define DST_HDR_SIG_LEN 4 +#define DST_HDR_OEM_ID_LEN 6 +#define DST_HDR_OEM_TABLE_ID_LEN 8 +struct dst_header { + char signature[DST_HDR_SIG_LEN]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[DST_HDR_OEM_ID_LEN]; + char oem_table_id[DST_HDR_OEM_TABLE_ID_LEN]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +} __attribute__((packed)); + +//////////////////////////////////////// + +/* [1c] Root System Description Table */ +#define XSDT_SIGNATURE "XSDT" +#define XSDT_ENTRIES 3 +// #define XSDT_MAX_ENTRIES 16 // arbitrary, can be increased easily by editing this number +struct xsdt { + struct dst_header h; + /* A list of guest physical addresses to other ACPI tables. */ + uint64_t tables[XSDT_ENTRIES]; +} __attribute__((packed)); + +//////////////////////////////////////// + +#define MADT_ENTRY_TYPE_LAPIC 0x0 +#define MADT_ENTRY_TYPE_IOAPIC 0x1 + +#define MADT_ENTRY_LAPIC_LENGTH 0x8 +#define MADT_ENTRY_IOAPIC_LENGTH 0xc + +struct madt_irq_controller { + uint8_t type; + /* Note that the length includes this MADT IRQ controller header. */ + uint8_t length; +} __attribute__((packed)); + +#define MADT_LAPIC_FLAGS (1 << 0) | (1 << 1) + +struct madt_lapic { + struct madt_irq_controller entry; + uint8_t acpi_processor_id; + uint8_t apic_id; + uint32_t flags; +} __attribute__((packed)); + +struct madt_ioapic { + struct madt_irq_controller entry; + uint8_t id; + /* Reserved */ + uint8_t res; + uint32_t address; + uint32_t global_system_irq_base; +} __attribute__((packed)); + +struct madt_ioapic_source_override { + struct madt_irq_controller entry; + uint8_t bus; + uint8_t source; + uint32_t gsi; + uint16_t flags; +} __attribute__((packed)); + +#define MADT_REVISION 5 +#define MADT_FLAGS BIT(0) // PCAT_COMPAT, dual 8259 present as a direct mapping to I/O APIC 0 + +struct madt { + struct dst_header h; + uint32_t apic_addr; + uint32_t flags; + + // @billn doing it this way make it hard for user code to add more entries, + // but for now it make things way easier as we can just do sizeof(struct madt) as it + // is statically sized. + struct madt_lapic lapic_entry; + struct madt_ioapic ioapic_0_entry; + struct madt_ioapic_source_override hpet_source_override_entry; +} __attribute__((packed)); + +//////////////////////////////////////// + +/* [2a] HPET Description Table */ +#define HPET_SIGNATURE "HPET" +#define HPET_REVISION 0x1 + +#define HPET_VENDOR_MASK (0x5E14ull << 16) +#define HPET_64B_COUNTER BIT(13) +#define HPET_LEGACY_IRQ_CAPABLE BIT(15) +#define HPET_NUM_COMPARATORS_VALUE 3 +#define HPET_NUM_COMPARATORS_SHIFT 8 + +struct address_structure { + uint8_t address_space_id; // 0 - MMIO, 1 - I/O port, 2 - PCI config space + uint8_t register_bit_width; + uint8_t register_bit_offset; + uint8_t access_size; // 0 - undefied, 1 - byte, 2 - word, 3 - dword, 4 - qword + uint64_t address; +} __attribute__((packed)); + +struct hpet { + struct dst_header h; + uint32_t evt_timer_block_id; + struct address_structure address_desc; + uint8_t hpet_number; + uint16_t minimum_clk_tick; + uint8_t page_protection; +} __attribute__((packed)); + +//////////////////////////////////////// + +/* PCI Express Memory-mapped Configuration Space base address description table */ +#define MCFG_SIGNATURE "MCFG" +#define MCFG_REVISION 1 +#define MCFG_NUM_CONFIG_SPACES 1 + +struct pcie_config_space_addr_structure { + uint64_t base_address; + uint16_t pci_segment_group; + uint8_t start_bus; + uint8_t end_bus; + uint32_t reserved; +} __attribute__((packed)); + +struct mcfg { + struct dst_header h; + uint8_t reserved[8]; + struct pcie_config_space_addr_structure config_spaces[MCFG_NUM_CONFIG_SPACES]; +} __attribute__((packed)); + +//////////////////////////////////////// + +/* Firmware ACPI Control Structure (FACS) */ +#define FACS_SIGNATURE "FACS" + +struct facs { + uint32_t signature; + uint32_t length; + uint32_t hw_sig; + uint32_t fw_waking_vector; + uint32_t global_lock; + uint32_t flags; + uint64_t x_fw_waking_vector; + uint8_t version; + uint8_t _reserved1[3]; + uint32_t ospm_flags; + uint8_t _reserved2[24]; +}; + +_Static_assert(sizeof(struct facs) == 64, "facs must be 64 bytes large"); + +//////////////////////////////////////// +#define PM1A_EVT_BLK_PIO_ADDR 0x600 +#define PM1A_EVT_BLK_PIO_LEN 4 +#define PM1A_CNT_BLK_PIO_ADDR 0x604 +#define PM1A_CNT_BLK_PIO_LEN 2 +#define PM_TMR_BLK_PIO_ADDR 0x608 +#define PM_TMR_BLK_PIO_LEN 4 + +#define SMI_CMD_PIO_ADDR 0x60c +#define ACPI_ENABLE 0x12 +#define ACPI_DISABLE 0x13 + +// @billn have a way to detect and warn about collision +#define ACPI_SCI_IRQ_PIN 7 +#define ACPI_PMT_FREQ_HZ 3579545 +#define ACPI_PMT_MAX_COUNT (1 << 24) + +struct FADT { + struct dst_header h; + uint32_t FirmwareCtrl; + uint32_t Dsdt; + + // field used in ACPI 1.0; no longer in use, for compatibility only + uint8_t Reserved; + + uint8_t PreferredPowerManagementProfile; + uint16_t SCI_Interrupt; + uint32_t SMI_CommandPort; + uint8_t AcpiEnable; + uint8_t AcpiDisable; + uint8_t S4BIOS_REQ; + uint8_t PSTATE_Control; + uint32_t PM1aEventBlock; + uint32_t PM1bEventBlock; + uint32_t PM1aControlBlock; + uint32_t PM1bControlBlock; + uint32_t PM2ControlBlock; + uint32_t PMTimerBlock; + uint32_t GPE0Block; + uint32_t GPE1Block; + uint8_t PM1EventLength; + uint8_t PM1ControlLength; + uint8_t PM2ControlLength; + uint8_t PMTimerLength; + uint8_t GPE0Length; + uint8_t GPE1Length; + uint8_t GPE1Base; + uint8_t CStateControl; + uint16_t WorstC2Latency; + uint16_t WorstC3Latency; + uint16_t FlushSize; + uint16_t FlushStride; + uint8_t DutyOffset; + uint8_t DutyWidth; + uint8_t DayAlarm; + uint8_t MonthAlarm; + uint8_t Century; + + // reserved in ACPI 1.0; used since ACPI 2.0+ + uint16_t BootArchitectureFlags; + + uint8_t Reserved2; + uint32_t Flags; + + struct address_structure ResetReg; + + uint8_t ResetValue; + uint8_t Reserved3[3]; + + // 64bit pointers - Available on ACPI 2.0+ + uint64_t X_FirmwareControl; + uint64_t X_Dsdt; + + struct address_structure X_PM1aEventBlock; + struct address_structure X_PM1bEventBlock; + struct address_structure X_PM1aControlBlock; + struct address_structure X_PM1bControlBlock; + struct address_structure X_PM2ControlBlock; + struct address_structure X_PMTimerBlock; + struct address_structure X_GPE0Block; + struct address_structure X_GPE1Block; +} __attribute__((packed)); +; + +//////////////////////////////////////// + +// bool acpi_pm_timer_irq_enabled(void); + +size_t facs_build(struct facs *facs); +size_t madt_build(struct madt *madt); +size_t hpet_build(struct hpet *hpet); +size_t fadt_build(struct FADT *fadt, uint64_t dsdt_gpa, uint64_t facs_gpa); +size_t xsdt_build(struct xsdt *xsdt, uint64_t *table_ptrs, size_t num_table_ptrs); +size_t mcfg_build(struct mcfg *mcfg); +size_t xsdp_build(struct xsdp *xsdp, uint64_t xsdt_gpa); + +// Create all the ACPI tables from guest's ram_top. +// Returns GPA of the XSDP. +// The contiguous range of memory used by all ACPI tables are written to acpi_start_gpa and acpi_end_gpa +// Assume that the Guest-Physical Address of RAM is 0!!! +uint64_t acpi_build_all(uintptr_t guest_ram_vaddr, void *dsdt_blob, uint64_t dsdt_blob_size, uint64_t ram_top, + uint64_t *acpi_start_gpa, uint64_t *acpi_end_gpa); diff --git a/include/libvmm/arch/x86_64/apic.h b/include/libvmm/arch/x86_64/apic.h new file mode 100644 index 000000000..582a47642 --- /dev/null +++ b/include/libvmm/arch/x86_64/apic.h @@ -0,0 +1,102 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#pragma once + +#include +#include +#include +#include +#include + +#define TIMER_DRV_CH_FOR_LAPIC 11 + +#define LAPIC_NUM_ISR_IRR_TMR_32B 8 +#define MIN_VECTOR 32 +#define MAX_VECTOR (LAPIC_NUM_ISR_IRR_TMR_32B * 32) + +// Table 11-1. Local APIC Register Address Map +#define REG_LAPIC_ID 0x20 +#define REG_LAPIC_REV 0x30 +#define REG_LAPIC_TPR 0x80 +#define REG_LAPIC_APR 0x90 +#define REG_LAPIC_PPR 0xa0 +#define REG_LAPIC_EOI 0xb0 +#define REG_LAPIC_LDR 0xd0 +#define REG_LAPIC_DFR 0xe0 +#define REG_LAPIC_SVR 0xf0 +#define REG_LAPIC_ISR_0 0x100 +#define REG_LAPIC_ISR_1 0x110 +#define REG_LAPIC_ISR_2 0x120 +#define REG_LAPIC_ISR_3 0x130 +#define REG_LAPIC_ISR_4 0x140 +#define REG_LAPIC_ISR_5 0x150 +#define REG_LAPIC_ISR_6 0x160 +#define REG_LAPIC_ISR_7 0x170 +#define REG_LAPIC_TMR_0 0x180 +#define REG_LAPIC_TMR_1 0x190 +#define REG_LAPIC_TMR_2 0x1A0 +#define REG_LAPIC_TMR_3 0x1B0 +#define REG_LAPIC_TMR_4 0x1C0 +#define REG_LAPIC_TMR_5 0x1D0 +#define REG_LAPIC_TMR_6 0x1E0 +#define REG_LAPIC_TMR_7 0x1F0 +#define REG_LAPIC_IRR_0 0x200 +#define REG_LAPIC_IRR_1 0x210 +#define REG_LAPIC_IRR_2 0x220 +#define REG_LAPIC_IRR_3 0x230 +#define REG_LAPIC_IRR_4 0x240 +#define REG_LAPIC_IRR_5 0x250 +#define REG_LAPIC_IRR_6 0x260 +#define REG_LAPIC_IRR_7 0x270 +#define REG_LAPIC_ESR 0x280 +#define REG_LAPIC_CMCI 0x2f0 +#define REG_LAPIC_ICR_LOW 0x300 +#define REG_LAPIC_ICR_HIGH 0x310 +#define REG_LAPIC_TIMER 0x320 +#define REG_LAPIC_THERMAL 0x330 +#define REG_LAPIC_PERF_MON_CNTER 0x340 +#define REG_LAPIC_LVT_LINT0 0x350 +#define REG_LAPIC_LVT_LINT1 0x360 +#define REG_LAPIC_LVT_ERR 0x370 +#define REG_LAPIC_INIT_CNT 0x380 +#define REG_LAPIC_CURR_CNT 0x390 +#define REG_LAPIC_DCR 0x3e0 + +#define REG_IOAPIC_IOREGSEL_MMIO_OFF 0x0 +#define REG_IOAPIC_IOWIN_MMIO_OFF 0x10 +#define REG_IOAPIC_IOAPICID_REG_OFF 0x0 +#define REG_IOAPIC_IOAPICVER_REG_OFF 0x1 +#define REG_IOAPIC_IOAPICARB_REG_OFF 0x2 +#define REG_IOAPIC_IOREDTBL_FIRST_OFF 0x10 +#define REG_IOAPIC_IOREDTBL_LAST_OFF 0x40 + +#define IOAPIC_LAST_INDIRECT_INDEX 0x17 +#define IOAPIC_NUM_PINS (IOAPIC_LAST_INDIRECT_INDEX + 1) + +struct ioapic_regs { + uint32_t selected_reg; + + uint32_t ioapicid; + uint32_t ioapicver; + uint32_t ioapicarb; + uint64_t ioredtbl[IOAPIC_NUM_PINS]; + + struct ioapic_virq_handle virq_passthrough_map[IOAPIC_NUM_PINS]; +}; + +uint32_t vapic_read_reg(int offset); +void vapic_write_reg(int offset, uint32_t value); + +bool lapic_read_fault_handle(uint64_t offset, uint32_t *result); +bool lapic_write_fault_handle(uint64_t offset, uint32_t data); +bool ioapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, + decoded_instruction_ret_t decoded_ins); + +bool inject_lapic_irq(size_t vcpu_id, uint8_t vector); +bool inject_ioapic_irq(int ioapic, int pin); +bool ioapic_ack_passthrough_irq(uint8_t vector); + +bool handle_lapic_timer_nftn(size_t vcpu_id); diff --git a/include/libvmm/arch/x86_64/cmos.h b/include/libvmm/arch/x86_64/cmos.h new file mode 100644 index 000000000..1b9c04ddd --- /dev/null +++ b/include/libvmm/arch/x86_64/cmos.h @@ -0,0 +1,13 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +bool emulate_cmos_access(seL4_VCPUContext *vctx, uint16_t port_addr, bool is_read, ioport_access_width_t access_width); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/com.h b/include/libvmm/arch/x86_64/com.h new file mode 100644 index 000000000..fe540ddf9 --- /dev/null +++ b/include/libvmm/arch/x86_64/com.h @@ -0,0 +1,14 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +void emulate_com(seL4_VCPUContext *vctx, size_t idx, size_t reg_offset, bool is_read, bool is_rep, bool is_string, + ioport_access_width_t access_width); diff --git a/include/libvmm/arch/x86_64/cpuid.h b/include/libvmm/arch/x86_64/cpuid.h new file mode 100644 index 000000000..3d0e07d8b --- /dev/null +++ b/include/libvmm/arch/x86_64/cpuid.h @@ -0,0 +1,11 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +bool emulate_cpuid(seL4_VCPUContext *vctx); diff --git a/include/libvmm/arch/x86_64/e820.h b/include/libvmm/arch/x86_64/e820.h new file mode 100644 index 000000000..cdbeedecb --- /dev/null +++ b/include/libvmm/arch/x86_64/e820.h @@ -0,0 +1,23 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +/* Documents referenced: Linux: arch/x86/include/uapi/asm/e820.h */ + +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 +#define E820_NVS 4 +#define E820_UNUSABLE 5 +#define E820_PMEM 7 + +struct boot_e820_entry { + uint64_t addr; + uint64_t size; + uint32_t type; +} __attribute__((packed)); diff --git a/include/libvmm/arch/x86_64/fault.h b/include/libvmm/arch/x86_64/fault.h new file mode 100644 index 000000000..2f4b18b7d --- /dev/null +++ b/include/libvmm/arch/x86_64/fault.h @@ -0,0 +1,29 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +#include + +char *fault_to_string(int exit_reason); +/* @billn revisit, seL4 vmexit doesnt have msginfo! */ + +bool fault_handle(size_t vcpu_id, uint64_t *new_rip); + +typedef bool (*ept_exception_callback_t)(size_t vcpu_id, size_t offset, size_t qualification, + decoded_instruction_ret_t decoded_ins, seL4_VCPUContext *vctx, void *cookie); + +bool fault_update_ept_exception_handler(uintptr_t base, uintptr_t new_base); +bool fault_register_ept_exception_handler(uintptr_t base, size_t size, ept_exception_callback_t callback, void *cookie); + +typedef bool (*pio_exception_callback_t)(size_t vcpu_id, uint16_t port_offset, size_t qualification, + seL4_VCPUContext *vctx, void *cookie); +bool fault_register_pio_exception_handler(uint16_t base, uint16_t size, pio_exception_callback_t callback, + void *cookie); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/hpet.h b/include/libvmm/arch/x86_64/hpet.h new file mode 100644 index 000000000..697ae5e27 --- /dev/null +++ b/include/libvmm/arch/x86_64/hpet.h @@ -0,0 +1,20 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#pragma once + +#include +#include +#include +#include + +#define TIMER_DRV_CH_FOR_HPET_CH0 12 +#define TIMER_DRV_CH_FOR_HPET_CH1 13 +#define TIMER_DRV_CH_FOR_HPET_CH2 14 + +void hpet_handle_timer_ntfn(microkit_channel ch); + +bool hpet_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, + decoded_instruction_ret_t decoded_ins); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/instruction.h b/include/libvmm/arch/x86_64/instruction.h new file mode 100644 index 000000000..4d96c3fd2 --- /dev/null +++ b/include/libvmm/arch/x86_64/instruction.h @@ -0,0 +1,86 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +// Index of registers in a `seL4_VCPUContext`. +typedef enum register_idx { + RAX_IDX = 0, + RBX_IDX, + RCX_IDX, + RDX_IDX, + RSI_IDX, + RDI_IDX, + RBP_IDX, + R8_IDX, + R9_IDX, + R10_IDX, + R11_IDX, + R12_IDX, + R13_IDX, + R14_IDX, + R15_IDX +} register_idx_t; + +typedef struct decode_fail_instruction_data { +} decode_fail_instruction_data_t; + +typedef enum memory_access_width { + BYTE_ACCESS_WIDTH, // 1-byte + WORD_ACCESS_WIDTH, // 2-byte + DWORD_ACCESS_WIDTH, // 4-byte + QWORD_ACCESS_WIDTH, // 8-byte +} memory_access_width_t; + +typedef struct memory_instruction_data { + // We don't store the memory access direction as the CPU would + // tell us via the fault qualification. + bool zero_extend; + register_idx_t target_reg; + memory_access_width_t access_width; +} memory_instruction_data_t; + +typedef struct write_imm_instruction_data { + uint64_t value; + memory_access_width_t access_width; +} write_imm_instruction_data_t; + +typedef union instruction_data { + decode_fail_instruction_data_t decode_fail; + memory_instruction_data_t memory_instruction; + write_imm_instruction_data_t write_imm_instruction; +} instruction_data_t; + +typedef enum instruction_type { + INSTRUCTION_DECODE_FAIL, + INSTRUCTION_MEMORY, + INSTRUCTION_WRITE_IMM, +} instruction_type_t; + +#define X86_MAX_INSTRUCTION_LENGTH 15 + +typedef struct decoded_instruction_ret { + /* For debugging purpose */ + char raw[X86_MAX_INSTRUCTION_LENGTH]; + int raw_len; + + instruction_type_t type; + instruction_data_t decoded; +} decoded_instruction_ret_t; + +decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4_Word instruction_len); + +void debug_print_instruction(decoded_instruction_ret_t decode_result); + +int mem_access_width_to_bytes(decoded_instruction_ret_t decoded_ins); + +bool mem_write_get_data(decoded_instruction_ret_t decoded_ins, size_t ept_fault_qualification, seL4_VCPUContext *vctx, + uint64_t *ret); + +bool mem_read_set_data(decoded_instruction_ret_t decoded_ins, size_t ept_fault_qualification, seL4_VCPUContext *vctx, + uint64_t data); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/ioports.h b/include/libvmm/arch/x86_64/ioports.h new file mode 100644 index 000000000..7ecc75eb5 --- /dev/null +++ b/include/libvmm/arch/x86_64/ioports.h @@ -0,0 +1,31 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +// intel manual +// [1] Table 28-5. Exit Qualification for I/O Instructions + +// [1] +typedef enum ioport_access_width_qualification { + IOPORT_BYTE_ACCESS_QUAL = 0, + IOPORT_WORD_ACCESS_QUAL = 1, // 2-byte + IOPORT_DWORD_ACCESS_QUAL = 3, // 4-byte +} ioport_access_width_t; + +int ioports_access_width_to_bytes(ioport_access_width_t access_width); + +int emulate_ioport_string_write(seL4_VCPUContext *vctx, char *dest, size_t data_len, bool is_rep, + ioport_access_width_t access_width); + +// returns how many bytes were written to guest ram. +int emulate_ioport_string_read(seL4_VCPUContext *vctx, char *data, size_t data_len, bool is_rep, + ioport_access_width_t access_width); + +bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification); diff --git a/include/libvmm/arch/x86_64/linux.h b/include/libvmm/arch/x86_64/linux.h new file mode 100644 index 000000000..324c2703d --- /dev/null +++ b/include/libvmm/arch/x86_64/linux.h @@ -0,0 +1,72 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +// Documents referenced. +// 1. https://www.kernel.org/doc/html/v6.1/x86/boot.html +// 2. Linux: arch/x86/include/uapi/asm/bootparam.h +// 3. Linux: include/uapi/linux/edd.h +// 4. Linux: arch/x86/include/uapi/asm/setup_data.h + +// [2] +struct setup_header { + uint8_t setup_sects; + uint16_t root_flags; + uint32_t syssize; + uint16_t ram_size; + uint16_t vid_mode; + uint16_t root_dev; + uint16_t boot_flag; + uint16_t jump; + uint32_t header; + uint16_t version; + uint32_t realmode_swtch; + uint16_t start_sys_seg; + uint16_t kernel_version; + uint8_t type_of_loader; + uint8_t loadflags; + uint16_t setup_move_size; + uint32_t code32_start; + uint32_t ramdisk_image; + uint32_t ramdisk_size; + uint32_t bootsect_kludge; + uint16_t heap_end_ptr; + uint8_t ext_loader_ver; + uint8_t ext_loader_type; + uint32_t cmd_line_ptr; + uint32_t initrd_addr_max; + uint32_t kernel_alignment; + uint8_t relocatable_kernel; + uint8_t min_alignment; + uint16_t xloadflags; + uint32_t cmdline_size; + uint32_t hardware_subarch; + uint64_t hardware_subarch_data; + uint32_t payload_offset; + uint32_t payload_length; + uint64_t setup_data; + uint64_t pref_address; + uint32_t init_size; + uint32_t handover_offset; + uint32_t kernel_info_offset; +} __attribute__((packed)); + +typedef struct linux_setup_ret { + uintptr_t kernel_entry_gpa; + uintptr_t pml4_gpa; + uintptr_t zero_page_gpa; + uintptr_t gdt_gpa; + uint64_t gdt_limit; +} linux_x86_setup_ret_t; + +bool linux_setup_images(uintptr_t ram_start, size_t ram_size, uintptr_t kernel, size_t kernel_size, + uintptr_t initrd_src, size_t initrd_size, void *dsdt_blob, uint64_t dsdt_blob_size, + char *cmdline, linux_x86_setup_ret_t *ret); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/memory_space.h b/include/libvmm/arch/x86_64/memory_space.h new file mode 100644 index 000000000..bcd51bf4e --- /dev/null +++ b/include/libvmm/arch/x86_64/memory_space.h @@ -0,0 +1,25 @@ +/* + * Copyright 2026, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +/* Document layout of guest RAM */ + +#define LOW_RAM_START_GPA 0x0 + +#define ECAM_GPA 0xD0000000 +// 1 bus, 32 devices per bus, 8 functions per device, 4k config space per function +#define ECAM_SIZE (1 * 32 * 8 * 4096) + +#define IOAPIC_GPA 0xFEC00000 +#define IOAPIC_SIZE 0x1000 + +// This just matches the x86 CPU default physical address from +// See bit 9 of 'Table 1-20. More on Feature Information Returned in the EDX Register'. +#define LAPIC_GPA 0xFEE00000 +#define LAPIC_SIZE 0x1000 + +#define HPET_GPA 0xFED00000 +#define HPET_SIZE 0x1000 \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/msr.h b/include/libvmm/arch/x86_64/msr.h new file mode 100644 index 000000000..469ed3ffd --- /dev/null +++ b/include/libvmm/arch/x86_64/msr.h @@ -0,0 +1,12 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +bool emulate_rdmsr(seL4_VCPUContext *vctx); +bool emulate_wrmsr(seL4_VCPUContext *vctx); diff --git a/include/libvmm/arch/x86_64/pci.h b/include/libvmm/arch/x86_64/pci.h new file mode 100644 index 000000000..927884043 --- /dev/null +++ b/include/libvmm/arch/x86_64/pci.h @@ -0,0 +1,21 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +#define PCI_CONFIG_ADDRESS_START_PORT 0xCF8 +#define PCI_CONFIG_ADDRESS_PORT_SIZE 4 +#define PCI_CONFIG_ADDRESS_END_PORT (PCI_CONFIG_ADDRESS_START_PORT + PCI_CONFIG_ADDRESS_PORT_SIZE) + +#define PCI_CONFIG_DATA_START_PORT 0xCFC +#define PCI_CONFIG_DATA_PORT_SIZE 4 +#define PCI_CONFIG_DATA_END_PORT (PCI_CONFIG_DATA_START_PORT + PCI_CONFIG_DATA_PORT_SIZE) + +bool pci_x86_init(void); diff --git a/include/libvmm/arch/x86_64/util.h b/include/libvmm/arch/x86_64/util.h new file mode 100644 index 000000000..f3682a3c1 --- /dev/null +++ b/include/libvmm/arch/x86_64/util.h @@ -0,0 +1,28 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +extern bool fault_cond; + +// #define DEBUG_FAULT +#if defined(DEBUG_FAULT) +#define LOG_FAULT(...) do{ if (fault_cond) { printf("%s|FAULT: ", microkit_name); printf(__VA_ARGS__); } }while(0) +#else +#define LOG_FAULT(...) do{}while(0) +#endif + +bool ept_fault_is_read(seL4_Word qualification); +bool ept_fault_is_write(seL4_Word qualification); + +bool pte_present(uint64_t pte); +uint64_t pte_to_gpa(uint64_t pte); +bool pt_page_size(uint64_t pte); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/vcpu.h b/include/libvmm/arch/x86_64/vcpu.h new file mode 100644 index 000000000..f3583c652 --- /dev/null +++ b/include/libvmm/arch/x86_64/vcpu.h @@ -0,0 +1,56 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#include +#include + +/* Document referenced: + * [1] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 Order Number: 325462-080US June 2023 + * [1a] Location: "SYSTEM ARCHITECTURE OVERVIEW", page: "Vol. 3A 2-15" + * [1b] Location: "SYSTEM ARCHITECTURE OVERVIEW", page: "Vol. 3A 2-17" + * [1c] Location: "SYSTEM ARCHITECTURE OVERVIEW", page: "Vol. 3A 2-9" + * [1d] Location: "BASIC EXECUTION ENVIRONMENT", page: "3-16 Vol. 1" + */ + +/* "CR0 — Contains system control flags that control operating mode and states of the processor." + * Consult [1a] for more details + */ +#define CR0_PG BIT_LOW(31) /* Paging On */ +#define CR0_PE BIT_LOW(0) /* Protection Enable */ + +#define CR0_DEFAULT (CR0_PG | CR0_PE) + +/* "CR4 — Contains a group of flags that enable several architectural extensions, and indicate + * operating system or executive support for specific processor capabilities." + * Consult [1b] for more details + */ +#define CR4_PAE BIT_LOW(5) /* Physical Address Extension */ +// @billn do we need CR4.PGE and CR4.MCE as well? + +#define CR4_DEFAULT (CR4_PAE) + +/* Extended Feature Enable Register: "provides several fields related to IA-32e mode + * enabling and operation" + * Note: "IA-32e" is just Intel's name for long mode. + * Consult [1c] for more details + */ +#define IA32_EFER_LME (BIT_LOW(8) | BIT_LOW(10)) /* Enable IA-32e mode operation */ + +#define IA32_EFER_DEFAULT (IA32_EFER_LME) + +/* The 32-bit EFLAGS/RFLAGS register contains a group of status flags, a control flag, and a group of system flags. + * We don't use anything here during boot to mask all IRQs, but the 2nd bit must always be set as 1. See [1d] + */ +#define RFLAGS_DEFAULT BIT(1) + +void vcpu_set_up_reset_state(uint64_t vapic_page_paddr, uint64_t apic_access_page_paddr); +void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, uint64_t vapic_page_paddr, + uint64_t apic_access_page_paddr); + +void vcpu_print_regs(size_t vcpu_id); diff --git a/include/libvmm/arch/x86_64/virq.h b/include/libvmm/arch/x86_64/virq.h new file mode 100644 index 000000000..728043b60 --- /dev/null +++ b/include/libvmm/arch/x86_64/virq.h @@ -0,0 +1,28 @@ +/* + * Copyright 2024, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +typedef void (*virq_ioapic_ack_fn_t)(int ioapic, int pin, void *cookie); + +bool virq_ioapic_register(int ioapic, int pin, virq_ioapic_ack_fn_t ack_fn, void *ack_data); + +bool virq_ioapic_register_passthrough(int ioapic, int pin, microkit_channel irq_ch); +bool virq_ioapic_handle_passthrough(microkit_channel irq_ch); + +// @billn sus +#define IOAPIC_IRQ_HANDLE_NO_CH (-1) +struct ioapic_virq_handle { + bool valid; + int ch; + virq_ioapic_ack_fn_t ack_fn; + void *ack_data; +}; +void virq_ioapic_passthrough_ack(int ioapic, int pin, void *cookie); \ No newline at end of file diff --git a/include/libvmm/arch/x86_64/vmcs.h b/include/libvmm/arch/x86_64/vmcs.h new file mode 100644 index 000000000..98e2039b5 --- /dev/null +++ b/include/libvmm/arch/x86_64/vmcs.h @@ -0,0 +1,198 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#include + +/* + * Document referenced: + * [1] include/arch/x86/arch/object/vcpu.h + * [2] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 Order Number: 325462-080US June 2023 + * [2a] Location: "VIRTUAL MACHINE CONTROL STRUCTURES", page: "25-10 Vol. 3C" + * [2b] Location: "VIRTUAL MACHINE CONTROL STRUCTURES", page: "25-12 Vol. 3C" + */ + +// [1] Virtual Machine Control Structure (VMCS) field selectors used by seL4 +#define VCPU_VMCS_SIZE 4096 +#define VCPU_IOBITMAP_SIZE 8192 + +#define VMX_CONTROL_VPID 0x00000000 + +#define VMX_GUEST_ES_SELECTOR 0x00000800 +#define VMX_GUEST_CS_SELECTOR 0x00000802 +#define VMX_GUEST_SS_SELECTOR 0x00000804 +#define VMX_GUEST_DS_SELECTOR 0x00000806 +#define VMX_GUEST_FS_SELECTOR 0x00000808 +#define VMX_GUEST_GS_SELECTOR 0x0000080A +#define VMX_GUEST_LDTR_SELECTOR 0x0000080C +#define VMX_GUEST_TR_SELECTOR 0x0000080E +#define VMX_GUEST_INTERRUPT_STATUS 0x00000810 + +#define VMX_HOST_ES_SELECTOR 0x00000C00 +#define VMX_HOST_CS_SELECTOR 0x00000C02 +#define VMX_HOST_SS_SELECTOR 0x00000C04 +#define VMX_HOST_DS_SELECTOR 0x00000C06 +#define VMX_HOST_FS_SELECTOR 0x00000C08 +#define VMX_HOST_GS_SELECTOR 0x00000C0A +#define VMX_HOST_TR_SELECTOR 0x00000C0C + +#define VMX_CONTROL_IOA_ADDRESS 0x00002000 +#define VMX_CONTROL_IOB_ADDRESS 0x00002002 +#define VMX_CONTROL_MSR_ADDRESS 0x00002004 +#define VMX_CONTROL_EXIT_MSR_STORE_ADDRESS 0x00002006 +#define VMX_CONTROL_EXIT_MSR_LOAD_ADDRESS 0x00002008 +#define VMX_CONTROL_ENTRY_MSR_LOAD_ADDRESS 0x0000200A +#define VMX_CONTROL_EXECUTIVE_VMCS_POINTER 0x0000200C +#define VMX_CONTROL_TSC_OFFSET 0x00002010 +#define VMX_CONTROL_VIRTUAL_APIC_ADDRESS 0x00002012 +#define VMX_CONTROL_APIC_ACCESS_ADDRESS 0x00002014 +#define VMX_CONTROL_EPT_POINTER 0x0000201A +#define VMX_CONTROL_EOI_EXIT_BITMAP_0 0x0000201C +#define VMX_CONTROL_EOI_EXIT_BITMAP_1 0x0000201E +#define VMX_CONTROL_EOI_EXIT_BITMAP_2 0x00002020 +#define VMX_CONTROL_EOI_EXIT_BITMAP_3 0x00002022 + +#define VMX_DATA_GUEST_PHYSICAL 0x00002400 + +#define VMX_GUEST_VMCS_LINK_POINTER 0x00002800 +#define VMX_GUEST_VMCS_LINK_POINTER_HIGH 0x00002801 +#define VMX_GUEST_DEBUGCTRL 0x00002802 +#define VMX_GUEST_PAT 0x00002804 +#define VMX_GUEST_EFER 0x00002806 +#define VMX_GUEST_PERF_GLOBAL_CTRL 0x00002808 +#define VMX_GUEST_PDPTE0 0x0000280A +#define VMX_GUEST_PDPTE1 0x0000280C +#define VMX_GUEST_PDPTE2 0x0000280E +#define VMX_GUEST_PDPTE3 0x00002810 + +#define VMX_HOST_PAT 0x00002C00 +#define VMX_HOST_EFER 0x00002C02 +#define VMX_HOST_PERF_GLOBAL_CTRL 0x00002C04 + +#define VMX_CONTROL_PIN_EXECUTION_CONTROLS 0x00004000 +#define VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS 0x00004002 +#define VMX_CONTROL_EXCEPTION_BITMAP 0x00004004 +#define VMX_CONTROL_PAGE_FAULT_MASK 0x00004006 +#define VMX_CONTROL_PAGE_FAULT_MATCH 0x00004008 +#define VMX_CONTROL_CR3_TARGET_COUNT 0x0000400A +#define VMX_CONTROL_EXIT_CONTROLS 0x0000400C +#define VMX_CONTROL_EXIT_MSR_STORE_COUNT 0x0000400E +#define VMX_CONTROL_EXIT_MSR_LOAD_COUNT 0x00004010 +#define VMX_CONTROL_ENTRY_CONTROLS 0x00004012 +#define VMX_CONTROL_ENTRY_MSR_LOAD_COUNT 0x00004014 +#define VMX_CONTROL_ENTRY_INTERRUPTION_INFO 0x00004016 +#define VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE 0x00004018 +#define VMX_CONTROL_ENTRY_INSTRUCTION_LENGTH 0x0000401A +#define VMX_CONTROL_TPR_THRESHOLD 0x0000401C +#define VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS 0x0000401E +#define VMX_CONTROL_PLE_GAP 0x00004020 +#define VMX_CONTROL_PLE_WINDOW 0x00004022 + +#define VMX_DATA_INSTRUCTION_ERROR 0x00004400 +#define VMX_DATA_EXIT_REASON 0x00004402 +#define VMX_DATA_EXIT_INTERRUPT_INFO 0x00004404 +#define VMX_DATA_EXIT_INTERRUPT_ERROR 0x00004406 +#define VMX_DATA_IDT_VECTOR_INFO 0x00004408 +#define VMX_DATA_IDT_VECTOR_ERROR 0x0000440A +#define VMX_DATA_EXIT_INSTRUCTION_LENGTH 0x0000440C +#define VMX_DATA_EXIT_INSTRUCTION_INFO 0x0000440E + +#define VMX_GUEST_ES_LIMIT 0x00004800 +#define VMX_GUEST_CS_LIMIT 0x00004802 +#define VMX_GUEST_SS_LIMIT 0x00004804 +#define VMX_GUEST_DS_LIMIT 0x00004806 +#define VMX_GUEST_FS_LIMIT 0x00004808 +#define VMX_GUEST_GS_LIMIT 0x0000480A +#define VMX_GUEST_LDTR_LIMIT 0x0000480C +#define VMX_GUEST_TR_LIMIT 0x0000480E +#define VMX_GUEST_GDTR_LIMIT 0x00004810 +#define VMX_GUEST_IDTR_LIMIT 0x00004812 +#define VMX_GUEST_ES_ACCESS_RIGHTS 0x00004814 +#define VMX_GUEST_CS_ACCESS_RIGHTS 0x00004816 +#define VMX_GUEST_SS_ACCESS_RIGHTS 0x00004818 +#define VMX_GUEST_DS_ACCESS_RIGHTS 0x0000481A +#define VMX_GUEST_FS_ACCESS_RIGHTS 0x0000481C +#define VMX_GUEST_GS_ACCESS_RIGHTS 0x0000481E +#define VMX_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 +#define VMX_GUEST_TR_ACCESS_RIGHTS 0x00004822 +#define VMX_GUEST_INTERRUPTABILITY 0x00004824 +#define VMX_GUEST_ACTIVITY 0x00004826 +#define VMX_GUEST_SMBASE 0x00004828 +#define VMX_GUEST_SYSENTER_CS 0x0000482A +#define VMX_GUEST_PREEMPTION_TIMER_VALUE 0x0000482E + +#define VMX_HOST_SYSENTER_CS 0x00004C00 + +#define VMX_CONTROL_CR0_MASK 0x00006000 +#define VMX_CONTROL_CR4_MASK 0x00006002 +#define VMX_CONTROL_CR0_READ_SHADOW 0x00006004 +#define VMX_CONTROL_CR4_READ_SHADOW 0x00006006 +#define VMX_CONTROL_CR3_TARGET0 0x00006008 +#define VMX_CONTROL_CR3_TARGET1 0x0000600A +#define VMX_CONTROL_CR3_TARGET2 0x0000600C +#define VMX_CONTROL_CR3_TARGET3 0x0000600E + +#define VMX_DATA_EXIT_QUALIFICATION 0x00006400 +#define VMX_DATA_IO_RCX 0x00006402 +#define VMX_DATA_IO_RSI 0x00006404 +#define VMX_DATA_IO_RDI 0x00006406 +#define VMX_DATA_IO_RIP 0x00006408 +#define VMX_DATA_GUEST_LINEAR_ADDRESS 0x0000640A + +#define VMX_GUEST_CR0 0x00006800 +#define VMX_GUEST_CR3 0x00006802 +#define VMX_GUEST_CR4 0x00006804 +#define VMX_GUEST_ES_BASE 0x00006806 +#define VMX_GUEST_CS_BASE 0x00006808 +#define VMX_GUEST_SS_BASE 0x0000680A +#define VMX_GUEST_DS_BASE 0x0000680C +#define VMX_GUEST_FS_BASE 0x0000680E +#define VMX_GUEST_GS_BASE 0x00006810 +#define VMX_GUEST_LDTR_BASE 0x00006812 +#define VMX_GUEST_TR_BASE 0x00006814 +#define VMX_GUEST_GDTR_BASE 0x00006816 +#define VMX_GUEST_IDTR_BASE 0x00006818 +#define VMX_GUEST_DR7 0x0000681A +#define VMX_GUEST_RSP 0x0000681C +#define VMX_GUEST_RIP 0x0000681E +#define VMX_GUEST_RFLAGS 0x00006820 +#define VMX_GUEST_PENDING_DEBUG_EXCEPTIONS 0x00006822 +#define VMX_GUEST_SYSENTER_ESP 0x00006824 +#define VMX_GUEST_SYSENTER_EIP 0x00006826 + +#define VMX_HOST_CR0 0x00006C00 +#define VMX_HOST_CR3 0x00006C02 +#define VMX_HOST_CR4 0x00006C04 +#define VMX_HOST_FS_BASE 0x00006C06 +#define VMX_HOST_GS_BASE 0x00006C08 +#define VMX_HOST_TR_BASE 0x00006C0A +#define VMX_HOST_GDTR_BASE 0x00006C0C +#define VMX_HOST_IDTR_BASE 0x00006C0E +#define VMX_HOST_SYSENTER_ESP 0x00006C10 +#define VMX_HOST_SYSENTER_EIP 0x00006C12 +#define VMX_HOST_RSP 0x00006C14 +#define VMX_HOST_RIP 0x00006C16 + +// [2a] Primary Processor-Based VM-Execution Controls Register +#define VMCS_PPC_ACTIVATE_SECONDARY_CTRL BIT(31) +#define VMCS_PPC_USE_TPR_SHADOW BIT(21) + +#define VMCS_PPC_IRQ_WINDOW_EXITING BIT(2) + +#define VMCS_PCC_DEFAULT (VMCS_PPC_USE_TPR_SHADOW | VMCS_PPC_ACTIVATE_SECONDARY_CTRL) +#define VMCS_PCC_EXIT_IRQ_WINDOW (VMCS_PCC_DEFAULT | VMCS_PPC_IRQ_WINDOW_EXITING) + +// [2b] Secondary Processor-Based VM-Execution Controls Register +#define VMCS_SPC_ENABLE_EPT BIT(1) +#define VMCS_SPC_ENABLE_XSAVE BIT(20) + +#define VMCS_SPC_ENABLE_VAPIC BIT(0) +#define VMCS_SPC_ENABLE_APIC_REG_VIRT BIT(8) +#define VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY BIT(9) + +#define VMCS_SPC_DEFAULT (VMCS_SPC_ENABLE_EPT | VMCS_SPC_ENABLE_XSAVE | VMCS_SPC_ENABLE_VAPIC | VMCS_SPC_ENABLE_APIC_REG_VIRT | VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY) diff --git a/include/libvmm/guest.h b/include/libvmm/guest.h index 4f4c22f03..216f1ddc9 100644 --- a/include/libvmm/guest.h +++ b/include/libvmm/guest.h @@ -37,3 +37,13 @@ bool guest_init(arch_guest_init_t init_args); bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd); void guest_stop(); bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size); + +// Convert guest physical address to the VMM's virtual memory address. +void *gpa_to_vaddr(uint64_t gpa); + +#if defined(CONFIG_ARCH_X86) +bool guest_paging_on(void); +bool guest_in_64_bits(void); +bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, uint64_t *bytes_remaining); +uint64_t gpa_to_pa(uint64_t gpa); +#endif \ No newline at end of file diff --git a/include/libvmm/libvmm.h b/include/libvmm/libvmm.h index 31ea7052a..fdddcbe8c 100644 --- a/include/libvmm/libvmm.h +++ b/include/libvmm/libvmm.h @@ -23,4 +23,22 @@ #include #include #include +#elif defined(CONFIG_ARCH_X86) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif diff --git a/include/libvmm/util/util.h b/include/libvmm/util/util.h index 2d61daa87..9da271e9f 100644 --- a/include/libvmm/util/util.h +++ b/include/libvmm/util/util.h @@ -27,11 +27,7 @@ #define LOG_VMM(...) do{ printf("%s|INFO: ", microkit_name); printf(__VA_ARGS__); }while(0) #define LOG_VMM_ERR(...) do{ printf("%s|ERROR (%s:%lu): ", microkit_name, __FUNCTION__, __LINE__); printf(__VA_ARGS__); }while(0) -static void assert_fail( - const char *assertion, - const char *file, - unsigned int line, - const char *function) +static void assert_fail(const char *assertion, const char *file, unsigned int line, const char *function) { printf("Failed assertion '%s' at %s:%u in function %s\n", assertion, file, line, function); __builtin_trap(); @@ -67,3 +63,12 @@ void print_mem_hex(uintptr_t addr, size_t size); #endif #endif + +#if defined(CONFIG_ARCH_X86_64) +static __inline__ uint64_t rdtsc(void) +{ + uint32_t lo, hi; + __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)hi << 32) | lo; +} +#endif diff --git a/include/libvmm/virq.h b/include/libvmm/virq.h index bf3712388..86eb38287 100644 --- a/include/libvmm/virq.h +++ b/include/libvmm/virq.h @@ -14,11 +14,18 @@ typedef void (*virq_ack_fn_t)(size_t vcpu_id, int irq, void *cookie); +#if defined(CONFIG_ARCH_ARM) /* * Initialise the architecture-depedent virtual interrupt controller. * On ARM, this is the virtual Generic Interrupt Controller (vGIC). */ bool virq_controller_init(); +#elif defined(CONFIG_ARCH_X86) +/* + * Initialise the virtual LAPIC and I/O APIC. + */ +bool virq_controller_init(uint64_t native_tsc_hz, uintptr_t guest_vapic_vaddr); +#endif bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data); /* diff --git a/src/arch/aarch64/guest.c b/src/arch/aarch64/guest.c new file mode 100644 index 000000000..39eba3eb9 --- /dev/null +++ b/src/arch/aarch64/guest.c @@ -0,0 +1,12 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +void *gpa_to_vaddr(uint64_t gpa) +{ + return (void *)gpa; +} diff --git a/src/arch/x86_64/acpi.c b/src/arch/x86_64/acpi.c new file mode 100644 index 000000000..dcb985002 --- /dev/null +++ b/src/arch/x86_64/acpi.c @@ -0,0 +1,523 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_ACPI_INFO(...) do{ printf("%s|ACPI INFO: ", microkit_name); printf(__VA_ARGS__); }while(0) +#define LOG_ACPI_ERR(...) do{ printf("%s|ACPI ERR: ", microkit_name); printf(__VA_ARGS__); }while(0) + +#define PAGE_SIZE_4K 0x1000 +#define ACPI_OEMID "libvmm" + +/* Documents referenced: + * [1] Advanced Configuration and Power Interface (ACPI) Specification Release 6.5 UEFI Forum, Inc. Aug 29, 2022 + * [1a] "5.2.5.3 Root System Description Pointer (RSDP) Structure" + * [1b] "5.2.6 System Description Table Header" + * [1c] "5.2.8 Extended System Description Table (XSDT)" + * [2] IA-PC HPET (High Precision Event Timers) Specification Revision: 1.0a Date: October 2004 + * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf + * [2a] "3.2.4 The ACPI 2.0 HPET Description Table (HPET)" + */ + +static uint8_t acpi_table_sum(char *table, int size) +{ + uint8_t sum = 0; + for (int i = 0; i < size; i++) { + sum += (unsigned char)table[i]; + } + return sum; +} + +static bool acpi_checksum_ok(char *table, int size) +{ + return acpi_table_sum(table, size) == 0; +} + +static uint8_t acpi_compute_checksum(char *table, int size) +{ + return 0x100 - acpi_table_sum(table, size); +} + +// TODO: when creating MADT, get the user to pass the address of APIC that is definitely +// outside of RAM, or determine it ourselves. + +// static void madt_add_entry(struct madt *madt, uintptr_t dest, void *entry) +// { +// struct madt_irq_controller *madt_entry = (struct madt_irq_controller *)entry; + +// madt->h.length += madt_entry->length; + +// memcpy((void *)dest, entry, madt_entry->length); +// } + +size_t madt_build(struct madt *madt) +{ + memcpy(madt->h.signature, "APIC", 4); + madt->h.revision = MADT_REVISION; + // TODO: not very elegant, maybe do something better. + memcpy(madt->h.oem_id, ACPI_OEMID, 6); + memcpy(madt->h.oem_table_id, ACPI_OEMID, 6); + madt->h.oem_revision = 1; + + madt->h.length = sizeof(struct madt); + + madt->h.creator_id = 1; + madt->h.creator_revision = 1; + + madt->lapic_entry = (struct madt_lapic) { + .entry = { + .type = MADT_ENTRY_TYPE_LAPIC, + .length = MADT_ENTRY_LAPIC_LENGTH, + }, + .acpi_processor_id = 0, + .apic_id = 0, + .flags = MADT_LAPIC_FLAGS, + }; + + madt->ioapic_0_entry = (struct madt_ioapic) { + .entry = { + .type = MADT_ENTRY_TYPE_IOAPIC, + .length = MADT_ENTRY_IOAPIC_LENGTH, + }, + .id = 0, + .res = 0, + .address = IOAPIC_GPA, + .global_system_irq_base = 0, + }; + + // Connect ISA IRQ 0 from the legacy Programmable Interval Timer (PIT) + // to I/O APIC pin 2, which is where the HPET in legacy replacement code is connected. + madt->hpet_source_override_entry = (struct madt_ioapic_source_override) { + .entry = { .type = 2, .length = 10 }, + .bus = 0, + .source = 0, + .gsi = 2, + .flags = 0, + }; + + madt->apic_addr = LAPIC_GPA; + madt->flags = MADT_FLAGS; + + // Finished building, now do the checksum. + madt->h.checksum = acpi_compute_checksum((char *)madt, madt->h.length); + assert(acpi_checksum_ok((char *)madt, madt->h.length)); + + return madt->h.length; +} + +size_t hpet_build(struct hpet *hpet) +{ + memcpy(hpet->h.signature, HPET_SIGNATURE, 4); + hpet->h.length = sizeof(struct hpet); + hpet->h.revision = HPET_REVISION; + memcpy(hpet->h.oem_id, ACPI_OEMID, 6); + memcpy(hpet->h.oem_table_id, ACPI_OEMID, 6); + hpet->h.creator_id = 1; + hpet->h.creator_revision = 1; + + hpet->evt_timer_block_id = HPET_LEGACY_IRQ_CAPABLE | (HPET_NUM_COMPARATORS_VALUE << HPET_NUM_COMPARATORS_SHIFT) + | HPET_64B_COUNTER | HPET_VENDOR_MASK; + + hpet->address_desc.address_space_id = 0; + hpet->address_desc.register_bit_width = 32; + hpet->address_desc.address = HPET_GPA; + + hpet->hpet_number = 0; + hpet->minimum_clk_tick = 1; // @billn ??? revisit + hpet->page_protection = 0; + + hpet->h.checksum = acpi_compute_checksum((char *)hpet, hpet->h.length); + assert(acpi_checksum_ok((char *)hpet, hpet->h.length)); + + return sizeof(struct hpet); +} + +size_t mcfg_build(struct mcfg *mcfg) +{ + memcpy(mcfg->h.signature, MCFG_SIGNATURE, 4); + mcfg->h.length = sizeof(struct mcfg); + mcfg->h.revision = MCFG_REVISION; + memcpy(mcfg->h.oem_id, ACPI_OEMID, 6); + memcpy(mcfg->h.oem_table_id, ACPI_OEMID, 6); + mcfg->h.creator_id = 1; + mcfg->h.creator_revision = 1; + + mcfg->config_spaces[0].base_address = ECAM_GPA; + mcfg->config_spaces[0].pci_segment_group = 0; + mcfg->config_spaces[0].start_bus = 0; + mcfg->config_spaces[0].end_bus = 0; + + mcfg->h.checksum = acpi_compute_checksum((char *)mcfg, mcfg->h.length); + assert(acpi_checksum_ok((char *)mcfg, mcfg->h.length)); + + return sizeof(struct mcfg); +} + +static uint16_t pm1_enable_reg = 0; +static uint16_t pm1_control_reg = 0; +static uint16_t pm1_status_reg = 0; + +#define TMR_EN BIT(0) /* Timer Enable */ +#define GBL_EN BIT(5) /* Global Enable */ +bool acpi_pm_timer_can_irq(void) +{ + return (pm1_enable_reg & BIT(0)) && (pm1_enable_reg & BIT(5)); +} + +bool pm1a_cnt_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qualification, seL4_VCPUContext *vctx, + void *cookie) +{ + uint64_t is_read = qualification & BIT(3); + uint64_t is_string = qualification & BIT(4); + // TODO: handle unused variable + // uint16_t port_addr = (qualification >> 16) & 0xffff; + ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); + int access_width_bytes = ioports_access_width_to_bytes(access_width); + assert(!is_string); + assert(access_width_bytes == 2); + + if (port_offset == 0) { + if (is_read) { + // LOG_VMM("PM1 control reg read 0x%x\n", pm1_control_reg); + vctx->eax = pm1_control_reg; + } else { + pm1_control_reg = vctx->eax & 0xffff; + // LOG_VMM("PM1 control reg write 0x%x\n", pm1_control_reg); + } + + } else { + return false; + } + + return true; +} + +bool pm1a_evt_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qualification, seL4_VCPUContext *vctx, + void *cookie) +{ + uint64_t is_read = qualification & BIT(3); + uint64_t is_string = qualification & BIT(4); + // TODO: handle unused variable + // uint16_t port_addr = (qualification >> 16) & 0xffff; + ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); + int access_width_bytes = ioports_access_width_to_bytes(access_width); + assert(!is_string); + assert(access_width_bytes == 2); + + if (port_offset == 2) { + if (is_read) { + vctx->eax = pm1_enable_reg; + } else { + pm1_enable_reg = vctx->eax; + if (acpi_pm_timer_can_irq()) { + LOG_ACPI_INFO("ACPI PM Timer Overflow IRQ ON!\n"); + assert(false); + } + } + } else if (port_offset == 0) { + if (is_read) { + vctx->eax = pm1_status_reg; + } else { + // @billn sus implement proper set to clear + pm1_status_reg = vctx->eax; + } + } else { + return false; + } + + return true; +} + +bool pm_timer_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qualification, seL4_VCPUContext *vctx, + void *cookie) +{ + uint64_t is_read = qualification & BIT(3); + uint64_t is_string = qualification & BIT(4); + // TODO: handle unused variable + // uint16_t port_addr = (qualification >> 16) & 0xffff; + ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); + int access_width_bytes = ioports_access_width_to_bytes(access_width); + assert(!is_string); + assert(access_width_bytes == 4); + assert(port_offset == 0); + assert(is_read); + + uint64_t timer_ns = sddf_timer_time_now(TIMER_DRV_CH_FOR_LAPIC); + vctx->eax = (uint64_t)(((double)timer_ns / (double)NS_IN_S) * ACPI_PMT_FREQ_HZ); + + return true; +} + +bool smi_cmd_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qualification, seL4_VCPUContext *vctx, + void *cookie) +{ + uint64_t is_read = qualification & BIT(3); + uint64_t is_string = qualification & BIT(4); + // TODO: handle unused variable + // uint16_t port_addr = (qualification >> 16) & 0xffff; + ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); + int access_width_bytes = ioports_access_width_to_bytes(access_width); + assert(!is_string); + assert(access_width_bytes == 1); + assert(port_offset == 0); + assert(!is_read); + + uint8_t cmd = vctx->eax & 0xff; + // LOG_VMM("smi cmd write 0x%x\n", cmd); + + if (cmd == ACPI_ENABLE) { + pm1_control_reg |= BIT(0); + } else if (cmd == ACPI_DISABLE) { + pm1_control_reg |= ~BIT(0); + } + + return true; +} + +size_t facs_build(struct facs *facs) +{ + // @billn figure out if wake vector is important + + memset(facs, 0, sizeof(struct facs)); + memcpy(&facs->signature, FACS_SIGNATURE, 4); + + facs->length = sizeof(struct facs); + + return sizeof(struct facs); +} + +size_t fadt_build(struct FADT *fadt, uint64_t dsdt_gpa, uint64_t facs_gpa) +{ + /* Despite the table being called 'FADT', this table was FACP in an earlier ACPI version, + * hence the inconsistency. */ + memset(fadt, 0, sizeof(struct FADT)); + + memcpy(fadt->h.signature, "FACP", 4); + + fadt->h.length = sizeof(struct FADT); + fadt->h.revision = 6; + + memcpy(fadt->h.oem_id, ACPI_OEMID, 6); + memcpy(fadt->h.oem_table_id, ACPI_OEMID, 6); + fadt->h.oem_revision = 1; + + fadt->h.creator_id = 1; + fadt->h.creator_revision = 1; + + /* Fill out data fields of FADT */ + + assert(dsdt_gpa < (1ull << 32)); + assert(facs_gpa < (1ull << 32)); + + fadt->Dsdt = 0; + fadt->X_Dsdt = dsdt_gpa; + fadt->FirmwareCtrl = 0; + fadt->X_FirmwareControl = facs_gpa; + fadt->Flags = 0; // Not hardware reduced, ACPI PM timer 24-bit wide + + fadt->PreferredPowerManagementProfile = 0; /* Unspecified Power Profile */ + + fadt->SCI_Interrupt = ACPI_SCI_IRQ_PIN; + + fadt->BootArchitectureFlags = + BIT(1) /* Support PS/2 KB+M */ | BIT(3) /* MSI not supported */ | BIT(2) /* No ISA VGA */; + + fadt->SMI_CommandPort = SMI_CMD_PIO_ADDR; + fadt->AcpiEnable = ACPI_ENABLE; + fadt->AcpiDisable = ACPI_DISABLE; + { + bool success = fault_register_pio_exception_handler(SMI_CMD_PIO_ADDR, 1, smi_cmd_pio_fault_handle, NULL); + assert(success); + } + + fadt->PM1aEventBlock = PM1A_EVT_BLK_PIO_ADDR; + fadt->PM1EventLength = PM1A_EVT_BLK_PIO_LEN; + fadt->X_PM1aEventBlock.address_space_id = 1; + fadt->X_PM1aEventBlock.register_bit_width = 32; + fadt->X_PM1aEventBlock.register_bit_offset = 0; + fadt->X_PM1aEventBlock.access_size = 2; + fadt->X_PM1aEventBlock.address = PM1A_EVT_BLK_PIO_ADDR; + { + bool success = fault_register_pio_exception_handler(PM1A_EVT_BLK_PIO_ADDR, PM1A_EVT_BLK_PIO_LEN, + pm1a_evt_pio_fault_handle, NULL); + assert(success); + } + + fadt->PM1aControlBlock = PM1A_CNT_BLK_PIO_ADDR; + fadt->PM1ControlLength = PM1A_CNT_BLK_PIO_LEN; + fadt->X_PM1aControlBlock.address_space_id = 1; + fadt->X_PM1aControlBlock.register_bit_width = 16; + fadt->X_PM1aControlBlock.register_bit_offset = 0; + fadt->X_PM1aControlBlock.access_size = 2; + fadt->X_PM1aControlBlock.address = PM1A_CNT_BLK_PIO_ADDR; + { + bool success = fault_register_pio_exception_handler(PM1A_CNT_BLK_PIO_ADDR, PM1A_CNT_BLK_PIO_LEN, + pm1a_cnt_pio_fault_handle, NULL); + assert(success); + } + + fadt->PMTimerBlock = PM_TMR_BLK_PIO_ADDR; + fadt->PMTimerLength = PM_TMR_BLK_PIO_LEN; + fadt->X_PMTimerBlock.address_space_id = 1; + fadt->X_PMTimerBlock.register_bit_width = 32; + fadt->X_PMTimerBlock.register_bit_offset = 0; + fadt->X_PMTimerBlock.access_size = 3; + fadt->X_PMTimerBlock.address = PM_TMR_BLK_PIO_ADDR; + { + bool success = fault_register_pio_exception_handler(PM_TMR_BLK_PIO_ADDR, PM_TMR_BLK_PIO_LEN, + pm_timer_pio_fault_handle, NULL); + assert(success); + } + // @billn sus, OVMF always think that its running on Xen, which places the ACPI PM timer is at 0xb008 + // Not sure if this is it's quirk or our fault somewhwere + { + bool success = fault_register_pio_exception_handler(0xb008, PM_TMR_BLK_PIO_LEN, pm_timer_pio_fault_handle, + NULL); + assert(success); + } + + fadt->h.checksum = acpi_compute_checksum((char *)fadt, fadt->h.length); + assert(acpi_checksum_ok((char *)fadt, fadt->h.length)); + + return fadt->h.length; +} + +size_t xsdt_build(struct xsdt *xsdt, uint64_t *table_ptrs, size_t num_table_ptrs) +{ + memcpy(xsdt->h.signature, "XSDT", 4); + + /* length is the size of the header and the memory footprint of pointers to other tables. */ + uint32_t length = sizeof(struct xsdt); + + xsdt->h.length = length; + xsdt->h.revision = XSDP_REVISION; + + // TODO: not very elegant, maybe do something better. + memcpy(xsdt->h.oem_id, ACPI_OEMID, 6); + memcpy(xsdt->h.oem_table_id, ACPI_OEMID, 6); + xsdt->h.oem_revision = 1; + + xsdt->h.creator_id = 1; + xsdt->h.creator_revision = 1; + + // TODO: remove limitation + assert(num_table_ptrs == XSDT_ENTRIES); + for (int i = 0; i < num_table_ptrs; i++) { + xsdt->tables[i] = table_ptrs[i]; + } + + xsdt->h.checksum = acpi_compute_checksum((char *)xsdt, xsdt->h.length); + assert(acpi_checksum_ok((char *)xsdt, xsdt->h.length)); + + return xsdt->h.length; +} + +size_t xsdp_build(struct xsdp *xsdp, uint64_t xsdt_gpa) +{ + memset(xsdp, 0, sizeof(struct xsdp)); + + // memcpy as we do not want to null-termiante + memcpy(xsdp->signature, XSDP_SIGNATURE, strlen(XSDP_SIGNATURE)); + memcpy(xsdp->oem_id, ACPI_OEMID, strlen(ACPI_OEMID)); + xsdp->revision = XSDP_REVISION; + xsdp->length = sizeof(struct xsdp); + + xsdp->xsdt_gpa = xsdt_gpa; + + // // @billn sus + // assert(xsdt_gpa < (1ull << 32)); + // xsdp->rsdp_gpa = xsdt_gpa; + + xsdp->checksum = acpi_compute_checksum((char *)xsdp, offsetof(struct xsdp, length)); + assert(acpi_checksum_ok((char *)xsdp, offsetof(struct xsdp, length))); + xsdp->ext_checksum = acpi_compute_checksum((char *)xsdp, sizeof(struct xsdp)); + assert(acpi_checksum_ok((char *)xsdp, sizeof(struct xsdp))); + + return sizeof(struct xsdp); +} + +uint64_t acpi_top; + +uint64_t acpi_allocate_gpa(size_t length) +{ + assert(length); + acpi_top -= length; + + return acpi_top; +} + +uint64_t acpi_build_all(uintptr_t guest_ram_vaddr, void *dsdt_blob, uint64_t dsdt_blob_size, uint64_t ram_top, + uint64_t *acpi_start_gpa, uint64_t *acpi_end_gpa) +{ + acpi_top = ram_top; + // Step 1: create the Root System Description Pointer structure. + + // We want to place everything at "ram_top", do that we can carve out a chunk + // at the end and mark it as "ACPI" memory in the E820 table. + uint64_t xsdp_gpa = acpi_allocate_gpa(sizeof(struct xsdp)); + struct xsdp *xsdp = (struct xsdp *)(guest_ram_vaddr + xsdp_gpa); + + // All the other tables "grow down" from the XSDP, here we pre-allocate the XSDT + // so that we can compute the XSDP checksum. + uint64_t xsdt_gpa = acpi_allocate_gpa(sizeof(struct xsdt)); + xsdp_build(xsdp, xsdt_gpa); + + // TODO: hack + uint64_t madt_gpa = acpi_allocate_gpa(sizeof(struct madt)); + struct madt *madt = (struct madt *)(guest_ram_vaddr + madt_gpa); + madt_build(madt); + assert(madt->h.length <= 0x1000); + + // @billn todo really need some sort of memory range allocator + uint64_t hpet_gpa = acpi_allocate_gpa(sizeof(struct hpet)); + struct hpet *hpet = (struct hpet *)(guest_ram_vaddr + hpet_gpa); + hpet_build(hpet); + assert(hpet->h.length <= 0x1000); + + // Differentiated System Description Table + // Used for things that cannot be described by other tables or probed. + // An example is legacy I/O Port serial IRQ pin. + // It is in a binary format from the ASL compiler, which just needs to be copied to guest RAM. + assert(dsdt_blob_size < 0x1000); + uint64_t dsdt_gpa = acpi_allocate_gpa(0x1000); + memcpy((void *)(guest_ram_vaddr + dsdt_gpa), dsdt_blob, dsdt_blob_size); + + uint64_t facs_gpa = acpi_allocate_gpa(0x1000); + facs_gpa = ROUND_UP(facs_gpa, 64); + assert(facs_gpa % 64 == 0); + struct facs *facs = (struct facs *)(guest_ram_vaddr + facs_gpa); + facs_build(facs); + + uint64_t fadt_gpa = acpi_allocate_gpa(sizeof(struct FADT)); + struct FADT *fadt = (struct FADT *)(guest_ram_vaddr + fadt_gpa); + fadt_build(fadt, dsdt_gpa, facs_gpa); + assert(fadt->h.length <= 0x1000); + + // uint64_t mcfg_gpa = acpi_allocate_gpa(sizeof(struct mcfg)); + // struct mcfg *mcfg = (struct mcfg *)(guest_ram_vaddr + mcfg_gpa); + // mcfg_build(mcfg); + // assert(mcfg->h.length <= 0x1000); + + struct xsdt *xsdt = (struct xsdt *)(guest_ram_vaddr + xsdp->xsdt_gpa); + + memset(xsdt, 0, sizeof(struct xsdt)); + uint64_t xsdt_table_ptrs[XSDT_ENTRIES] = { madt_gpa, hpet_gpa, fadt_gpa }; + xsdt_build(xsdt, xsdt_table_ptrs, XSDT_ENTRIES); + + *acpi_start_gpa = ROUND_DOWN(acpi_top, PAGE_SIZE_4K); + *acpi_end_gpa = ram_top; + + return xsdp_gpa; +} diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c new file mode 100644 index 000000000..79bbad407 --- /dev/null +++ b/src/arch/x86_64/apic.c @@ -0,0 +1,560 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// @billn there seems to be a big problem with this code. If the host CPU load is high, the fault +// and IRQ injection latency will also be high. Which will cause the timer value to skew and linux +// will complain that TSC isn't stable. I don't know if this is a problem with the code or just how it is... + +// @billn the APIC timer doesn't need to be tied to the TSC, I did it like this originally because +// I didn't know anything about x86 architecture. But for simplicity it could be tied to the sDDF timer +// instead. + +// https://wiki.osdev.org/APIC + +/* Uncomment this to enable debug logging */ +// #define DEBUG_APIC + +extern bool fault_cond; + +#if defined(DEBUG_APIC) +#define LOG_APIC(...) do{ printf("%s|APIC: ", microkit_name); printf(__VA_ARGS__); }while(0) +#else +#define LOG_APIC(...) do{}while(0) +#endif + +// https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf +extern uintptr_t vapic_vaddr; +extern struct ioapic_regs ioapic_regs; +extern uint64_t tsc_hz; + +// @billn revisit for multiple vcpus +uint64_t native_scaled_tsc_when_timer_starts; + +static uint64_t ticks_to_ns(uint64_t hz, uint64_t ticks) +{ + __uint128_t tmp = (__uint128_t)ticks * (uint64_t)NS_IN_S; + tmp += hz / 2; + return (uint64_t)(tmp / hz); +} + +static int get_next_pending_irq_vector(void) +{ + // scan IRRs for *a* pending interrupt + // do it "right-to-left" as the higer vector is higher prio + for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { + for (int j = 31; j >= 0; j--) { + int irr_reg_off = REG_LAPIC_IRR_0 + (i * 0x10); + if (vapic_read_reg(irr_reg_off) & BIT(j)) { + uint8_t candidate_vector = i * 32 + j; + return candidate_vector; + } + } + } + return -1; +} + +static void debug_print_lapic_pending_irqs(void) +{ + for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { + for (int j = 31; j >= 0; j--) { + uint32_t irr = vapic_read_reg(REG_LAPIC_IRR_0 + (i * 0x10)); + if (irr & BIT(j)) { + LOG_VMM("irq vector %d is pending\n", i * 32 + j); + } + } + } +} + +uint32_t vapic_read_reg(int offset) +{ + assert(offset < 0x1000); + return *((uint32_t *)(vapic_vaddr + offset)); +} + +void vapic_write_reg(int offset, uint32_t value) +{ + assert(offset < 0x1000); + volatile uint32_t *reg = (uint32_t *)(vapic_vaddr + offset); + *reg = value; +} + +bool vcpu_can_take_irq(size_t vcpu_id) +{ + // Not executing anything that blocks IRQs + if (microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_INTERRUPTABILITY) != 0) { + return false; + } + // IRQ on in cpu register + if (!(microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_RFLAGS) & BIT(9))) { + return false; + } + return true; +} + +int lapic_dcr_to_divider(void) +{ + // Figure 11-10. Divide Configuration Register + switch (vapic_read_reg(REG_LAPIC_DCR)) { + case 0: + return 2; + case 1: + return 4; + case 2: + return 8; + case 3: + return 16; + case 8: + return 32; + case 9: + return 64; + case 10: + return 128; + case 11: + return 1; + default: + LOG_VMM_ERR("unknown LAPIC DCR register encoding: 0x%x\n", vapic_read_reg(REG_LAPIC_DCR)); + assert(false); + } + + return -1; +} + +uint8_t ioapic_pin_to_vector(int ioapic, int pin) +{ + assert(ioapic == 0); + return ioapic_regs.ioredtbl[pin] & 0xff; +} + +enum lapic_timer_mode { + LAPIC_TIMER_ONESHOT, + LAPIC_TIMER_PERIODIC, + LAPIC_TIMER_TSC_DEADLINE, +}; + +enum lapic_timer_mode lapic_parse_timer_reg(void) +{ + // Figure 11-8. Local Vector Table (LVT) + uint32_t timer_reg = vapic_read_reg(REG_LAPIC_TIMER); + switch (((timer_reg >> 17) & 0x3)) { + case 0: + return LAPIC_TIMER_ONESHOT; + case 1: + return LAPIC_TIMER_PERIODIC; + case 2: + // not advertised in cpuid, unreachable! + assert(false); + return LAPIC_TIMER_TSC_DEADLINE; + default: + LOG_VMM_ERR("unknown LAPIC timer mode register encoding: 0x%x\n", timer_reg); + assert(false); + } + + return -1; +} + +uint64_t tsc_now_scaled(void) +{ + return rdtsc() / lapic_dcr_to_divider(); +} + +bool lapic_read_fault_handle(uint64_t offset, uint32_t *result) +{ + switch (offset) { + case REG_LAPIC_CURR_CNT: { + if (vapic_read_reg(REG_LAPIC_INIT_CNT) == 0) { + *result = 0; + } else { + uint64_t tsc_tick_now_scaled = tsc_now_scaled(); + uint64_t elapsed_scaled_tsc_tick = tsc_tick_now_scaled - native_scaled_tsc_when_timer_starts; + + uint64_t remaining = 0; + if (elapsed_scaled_tsc_tick < vapic_read_reg(REG_LAPIC_INIT_CNT)) { + remaining = vapic_read_reg(REG_LAPIC_INIT_CNT) - elapsed_scaled_tsc_tick; + } + *result = remaining; + LOG_APIC("current count read 0x%lx\n", remaining); + } + break; + } + default: + LOG_VMM_ERR("Reading unknown LAPIC register offset 0x%x\n", offset); + return false; + } + + return true; +} + +bool lapic_write_fault_handle(uint64_t offset, uint32_t data) +{ + switch (offset) { + + case REG_LAPIC_SVR: + case REG_LAPIC_LVT_LINT0: + case REG_LAPIC_LVT_LINT1: + case REG_LAPIC_LVT_ERR: + case REG_LAPIC_ESR: + case REG_LAPIC_TIMER: + case REG_LAPIC_DCR: + case REG_LAPIC_DFR: + case REG_LAPIC_LDR: + case REG_LAPIC_THERMAL: + case REG_LAPIC_PERF_MON_CNTER: + vapic_write_reg(offset, data); + break; + + case REG_LAPIC_INIT_CNT: { + // Figure 11-8. Local Vector Table (LVT) + uint32_t init_count = data; + if (init_count > 0) { + uint32_t timer_reg = vapic_read_reg(REG_LAPIC_TIMER); + (void)timer_reg; + LOG_APIC("LAPIC timer started, mode 0x%x, irq masked %d\n", (timer_reg >> 17) % 0x3, + !!(timer_reg & BIT(16))); + + uint64_t delay_ns = ticks_to_ns(tsc_hz, init_count * lapic_dcr_to_divider()); + LOG_APIC("setting timeout for 0x%lx ns, from init count 0x%lx\n", delay_ns, init_count); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_LAPIC, delay_ns); + + native_scaled_tsc_when_timer_starts = tsc_now_scaled(); + } + break; + } + + case REG_LAPIC_ICR_LOW: { + // Figure 11-12. Interrupt Command Register (ICR) + // 11-20 Vol. 3A: "The act of writing to the low doubleword of the ICR causes the IPI to be sent." + uint64_t icr = (uint64_t)data | (((uint64_t)vapic_read_reg(REG_LAPIC_ICR_HIGH)) << 32); + + // @billn sus, handle other types of IPIs + uint8_t delivery_mode = ((icr >> 8) & 0x7); + uint8_t destination = (icr >> 56) & 0xff; + if (delivery_mode == 0 || delivery_mode == 5) { + // fixed mode + if (destination != 0) { + LOG_VMM_ERR("trying to send IPI to unknown APIC ID %d\n", destination); + return true; + } + uint8_t vector = icr & 0xff; + if (!inject_lapic_irq(GUEST_BOOT_VCPU_ID, vector)) { + LOG_VMM_ERR("failed to send IPI\n"); + return false; + } else { + // LOG_VMM("sent ipi\n"); + } + } else { + LOG_VMM_ERR("LAPIC received requuest to send IPI of unknown delivery mode 0x%x, destination 0x%x\n", + delivery_mode, destination); + } + + // LOG_VMM("icr write 0x%lx, current TPL is 0x%x\n", icr, vapic_read_reg(REG_LAPIC_TPR)); + break; + } + + default: + LOG_VMM_ERR("Writing unknown LAPIC register offset 0x%x\n", offset); + return false; + } + + return true; +} + +bool ioapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, + decoded_instruction_ret_t decoded_ins) +{ + if (ept_fault_is_read(qualification)) { + LOG_APIC("handling I/O APIC read at MMIO offset 0x%lx\n", offset); + } else if (ept_fault_is_write(qualification)) { + LOG_APIC("handling I/O APIC write at MMIO offset 0x%lx\n", offset); + } + + if (ept_fault_is_read(qualification)) { + if (offset == REG_IOAPIC_IOWIN_MMIO_OFF) { + uint64_t data; + + if (ioapic_regs.selected_reg == REG_IOAPIC_IOAPICID_REG_OFF) { + data = ioapic_regs.ioapicid; + } else if (ioapic_regs.selected_reg == REG_IOAPIC_IOAPICVER_REG_OFF) { + data = ioapic_regs.ioapicver; + } else if (ioapic_regs.selected_reg == REG_IOAPIC_IOAPICARB_REG_OFF) { + data = ioapic_regs.ioapicarb; + } else if (ioapic_regs.selected_reg >= REG_IOAPIC_IOREDTBL_FIRST_OFF + && ioapic_regs.selected_reg <= REG_IOAPIC_IOREDTBL_LAST_OFF) { + int redirection_reg_idx = ((ioapic_regs.selected_reg - REG_IOAPIC_IOREDTBL_FIRST_OFF) & ~((uint64_t)1)) + / 2; + int is_high = ioapic_regs.selected_reg & 0x1; + + // LOG_VMM("reading indirect register 0x%x, is high %d\n", redirection_reg_idx, is_high); + + if (is_high) { + data = ioapic_regs.ioredtbl[redirection_reg_idx] >> 32; + } else { + data = ioapic_regs.ioredtbl[redirection_reg_idx] & 0xffffffff; + } + + } else { + LOG_VMM_ERR("Reading unknown I/O APIC register offset 0x%x\n", ioapic_regs.selected_reg); + return false; + } + + assert(mem_read_set_data(decoded_ins, qualification, vctx, data)); + } else { + LOG_VMM_ERR("Reading unknown I/O APIC MMIO register 0x%x\n", offset); + return false; + } + } else { + uint64_t data; + assert(mem_write_get_data(decoded_ins, qualification, vctx, &data)); + + if (offset == REG_IOAPIC_IOREGSEL_MMIO_OFF) { + ioapic_regs.selected_reg = data & 0xff; + // LOG_VMM("selecting I/O APIC register 0x%x for write\n", ioapic_regs.selected_reg); + + } else if (offset == REG_IOAPIC_IOWIN_MMIO_OFF) { + if (ioapic_regs.selected_reg == REG_IOAPIC_IOAPICID_REG_OFF) { + LOG_APIC("Written to I/O APIC ID register: 0x%lx\n", data); + } else if (ioapic_regs.selected_reg == REG_IOAPIC_IOAPICVER_REG_OFF) { + LOG_APIC("Written to I/O APIC VER register: 0x%lx\n", data); + } else if (ioapic_regs.selected_reg >= REG_IOAPIC_IOREDTBL_FIRST_OFF + && ioapic_regs.selected_reg <= REG_IOAPIC_IOREDTBL_LAST_OFF) { + int redirection_reg_idx = ((ioapic_regs.selected_reg - REG_IOAPIC_IOREDTBL_FIRST_OFF) & ~((uint64_t)1)) + / 2; + int is_high = ioapic_regs.selected_reg & 0x1; + + uint64_t old_reg = ioapic_regs.ioredtbl[redirection_reg_idx]; + + if (is_high) { + uint64_t new_high = data << 32; + uint64_t low = ioapic_regs.ioredtbl[redirection_reg_idx] & 0xffffffff; + ioapic_regs.ioredtbl[redirection_reg_idx] = low | new_high; + } else { + uint64_t high = (ioapic_regs.ioredtbl[redirection_reg_idx] >> 32) << 32; + uint64_t new_low = data & 0xffffffff; + ioapic_regs.ioredtbl[redirection_reg_idx] = new_low | high; + } + + uint64_t new_reg = ioapic_regs.ioredtbl[redirection_reg_idx]; + + LOG_APIC("ioapic pin %d reprogram 0x%lx, masked %d\n", redirection_reg_idx, new_reg, + !!(ioapic_regs.ioredtbl[redirection_reg_idx] & BIT(16))); + + // If an I/O APIC IRQ pin goes from masked to unmasked and there are passed through + // IRQ on that pin, ack it so that if HW triggered an IRQ before the guest unmask the line + // in the virtual I/O APIC, the real IRQ doesn't get stuck in waiting for ACK. + if ((old_reg & BIT(16)) && !(new_reg & BIT(16))) { + for (int i = 0; i < IOAPIC_NUM_PINS; i++) { + if (i == redirection_reg_idx) { + if (ioapic_regs.virq_passthrough_map[i].ack_fn) { + ioapic_regs.virq_passthrough_map[i].ack_fn( + 0, i, ioapic_regs.virq_passthrough_map[i].ack_data); + } + break; + } + } + } + + } else { + LOG_VMM_ERR("Writing unknown I/O APIC register offset 0x%x\n", ioapic_regs.selected_reg); + return false; + } + } else { + LOG_VMM_ERR("Writing unknown I/O APIC MMIO register 0x%x\n", offset); + return false; + } + } + + return true; +} + +bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) +{ + assert(vcpu_id == 0); + + if (!(vapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { + // APIC software disable + return false; + } + + int irr_n = vector / 32; + int irr_idx = vector % 32; + + int irr_reg_off = REG_LAPIC_IRR_0 + (irr_n * 0x10); + assert(irr_reg_off <= REG_LAPIC_IRR_7); + + // Mark as pending for injection, let hardware handle the rest + vapic_write_reg(irr_reg_off, vapic_read_reg(irr_reg_off) | BIT(irr_idx)); + + // page 26-8 Vol. 3C "Guest interrupt status" + int highest_vector_pending = get_next_pending_irq_vector(); + assert(highest_vector_pending != -1); + uint16_t guest_irq_status = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_INTERRUPT_STATUS); + guest_irq_status &= 0xff00; + guest_irq_status |= (uint8_t)highest_vector_pending; + microkit_vcpu_x86_write_vmcs(0, VMX_GUEST_INTERRUPT_STATUS, guest_irq_status); + + return true; +} + +bool handle_lapic_timer_nftn(size_t vcpu_id) +{ + if (!(vapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { + // APIC software disable + return true; + } + + // restart timeout if periodic + uint32_t init_count = vapic_read_reg(REG_LAPIC_INIT_CNT); + if (lapic_parse_timer_reg() == LAPIC_TIMER_PERIODIC && init_count > 0) { + native_scaled_tsc_when_timer_starts = tsc_now_scaled(); + uint64_t delay_ns = ticks_to_ns(tsc_hz, init_count * lapic_dcr_to_divider()); + LOG_APIC("restarting periodic timeout for 0x%lx ns\n", delay_ns); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_LAPIC, delay_ns); + } + + // but only inject IRQ if it is not masked + uint32_t timer_reg = vapic_read_reg(REG_LAPIC_TIMER); + if (!(timer_reg & BIT(16))) { + uint8_t vector = timer_reg & 0xff; + if (!inject_lapic_irq(vcpu_id, vector)) { + // LOG_VMM_ERR("failed to inject LAPIC timer IRQ vector 0x%x\n", vector); + return false; + } + } + + return true; +} + +bool inject_ioapic_irq(int ioapic, int pin) +{ + // only 1 chip right now, which is a direct map to the dual 8259 + assert(ioapic == 0); + + if (pin >= IOAPIC_LAST_INDIRECT_INDEX) { + LOG_VMM_ERR("trying to inject IRQ to out of bound I/O APIC pin %d\n", pin); + return false; + } + + // check if the irq is masked + if (ioapic_regs.ioredtbl[pin] & BIT(16)) { + return false; + } + + // @billn sus + uint8_t delivery_mode = (ioapic_regs.ioredtbl[pin] >> 8) & 0x7; + + // @billn sus revisit delivery mode 1 for multiple vcpu + if (delivery_mode != 0 && delivery_mode != 1) { + LOG_VMM_ERR("unknown I/O APIC delivery mode for injection on pin %d, mode 0x%x\n", pin, delivery_mode); + assert(false); + } + // uint8_t level_trigger = (ioapic_regs.ioredtbl[pin] >> 15) & 0x1; + // assert(!level_trigger); + + uint8_t vector = ioapic_pin_to_vector(ioapic, pin); + + // For any passed through interrupts: + // When the guest EOIs the interrupt, we must trigger a vmexit to run the ack func + if (ioapic_regs.virq_passthrough_map[pin].valid) { + + int eoi_bitmap_n = vector / 64; + int n_bitmap_i = vector % 64; + switch (eoi_bitmap_n) { + case 0: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_0, bitmap | BIT(n_bitmap_i)); + break; + } + case 1: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_1); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_1, bitmap | BIT(n_bitmap_i)); + break; + } + case 2: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_2); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_2, bitmap | BIT(n_bitmap_i)); + break; + } + case 3: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_3); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_3, bitmap | BIT(n_bitmap_i)); + break; + } + default: + LOG_VMM_ERR("bug: eoi_bitmap_n > 3\n"); + return false; + } + } + + // @billn need to read cpu id from redirection register + return inject_lapic_irq(0, vector); +} + +bool ioapic_ack_passthrough_irq(uint8_t vector) +{ + for (int i = 0; i < IOAPIC_NUM_PINS; i++) { + if (ioapic_regs.virq_passthrough_map[i].valid) { + uint8_t candidate_vector = ioapic_pin_to_vector(0, i); + if (candidate_vector == vector) { + if (ioapic_regs.virq_passthrough_map[i].ack_fn) { + ioapic_regs.virq_passthrough_map[i].ack_fn(0, i, ioapic_regs.virq_passthrough_map[i].ack_data); + + // Now clear the vector's bit in EOI exit bitmap + int eoi_bitmap_n = vector / 64; + int n_bitmap_i = vector % 64; + switch (eoi_bitmap_n) { + case 0: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, + VMX_CONTROL_EOI_EXIT_BITMAP_0); + bitmap &= ~BIT(n_bitmap_i); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_0, bitmap); + break; + } + case 1: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, + VMX_CONTROL_EOI_EXIT_BITMAP_1); + bitmap &= ~BIT(n_bitmap_i); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_1, bitmap); + break; + } + case 2: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, + VMX_CONTROL_EOI_EXIT_BITMAP_2); + bitmap &= ~BIT(n_bitmap_i); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_2, bitmap); + break; + } + case 3: { + uint64_t bitmap = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, + VMX_CONTROL_EOI_EXIT_BITMAP_3); + bitmap &= ~BIT(n_bitmap_i); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_EOI_EXIT_BITMAP_3, bitmap); + break; + } + default: + LOG_VMM_ERR("bug: eoi_bitmap_n > 3\n"); + return false; + } + + return true; + } + } + } + } + + return false; +} \ No newline at end of file diff --git a/src/arch/x86_64/cmos.c b/src/arch/x86_64/cmos.c new file mode 100644 index 000000000..7507280ab --- /dev/null +++ b/src/arch/x86_64/cmos.c @@ -0,0 +1,122 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +// @billn hack, there should be a `init_cmos()` call that either pass or not pass the real CMOS +#define CMOS_ADDR_PORT_ID 36 +#define CMOS_DATA_PORT_ID 37 + +// Emulates enough of the CMOS and Real-Time Clock (RTC) needed for OVMF UEFI firmware. +// https://wiki.osdev.org/CMOS +// https://www.ti.com/lit/ds/symlink/bq3285.pdf?ts=1767742813264&ref_url=https%253A%252F%252Fwww.google.com%252F + +/* Uncomment this to enable debug logging */ +// #define DEBUG_CMOS + +#if defined(DEBUG_CMOS) +#define LOG_CMOS(...) do{ printf("%s|CMOS: ", microkit_name); printf(__VA_ARGS__); }while(0) +#else +#define LOG_CMOS(...) do{}while(0) +#endif + +#define STATUS_REG_A 0xa +#define STATUS_REG_B 0xb +#define STATUS_REG_C 0xc +#define STATUS_REG_D 0xd + +struct cmos_regs { + uint8_t selected_reg; + uint8_t status_registers[4]; // status regs A/B/C/D +}; + +static struct cmos_regs cmos_regs = { + .status_registers[3] = 0x80 // VRT bit set meaning device OK. +}; + +bool emulate_cmos_access(seL4_VCPUContext *vctx, uint16_t port_addr, bool is_read, ioport_access_width_t access_width) +{ + assert(access_width == IOPORT_BYTE_ACCESS_QUAL); + + if (port_addr == 0x70) { + if (is_read) { + vctx->eax = microkit_x86_ioport_read_8(CMOS_ADDR_PORT_ID, 0x70); + } else { + cmos_regs.selected_reg = vctx->eax & 0x7f; + microkit_x86_ioport_write_8(CMOS_ADDR_PORT_ID, 0x70, vctx->eax); + LOG_CMOS("selecting register 0x%x\n", cmos_regs.selected_reg); + } + } else if (port_addr == 0x71) { + if (is_read) { + if (cmos_regs.selected_reg > 0xd) { + vctx->eax = 0; + } else { + vctx->eax = microkit_x86_ioport_read_8(CMOS_DATA_PORT_ID, 0x71); + } + } else { + microkit_x86_ioport_write_8(CMOS_DATA_PORT_ID, 0x71, vctx->eax); + } + } + + return true; + + // if (port_addr == 0x70) { + // if (is_read) { + // vctx->eax = cmos_regs.selected_reg; + // } else { + // cmos_regs.selected_reg = vctx->eax & 0x7f; + // } + // } else if (port_addr == 0x71) { + // if (is_read) { + // LOG_CMOS("reading CMOS register 0x%x\n", cmos_regs.selected_reg); + // switch (cmos_regs.selected_reg) { + // case STATUS_REG_A: + // vctx->eax = cmos_regs.status_registers[0]; + // break; + // case STATUS_REG_B: + // vctx->eax = cmos_regs.status_registers[1]; + // break; + // case STATUS_REG_C: + // vctx->eax = cmos_regs.status_registers[2]; + // // whenever this register is read it is cleared + // cmos_regs.status_registers[2] = 0; + // break; + // case STATUS_REG_D: + // vctx->eax = cmos_regs.status_registers[3]; + // break; + // } + // } else { + // LOG_CMOS("writing CMOS register 0x%x, value 0x%x\n", cmos_regs.selected_reg, vctx->eax); + // switch (cmos_regs.selected_reg) { + // case STATUS_REG_A: + // cmos_regs.status_registers[0] = vctx->eax; + + // // uint8_t freq_select = cmos_regs.status_registers[0] & 0xf; + // // uint8_t oscillator_ctl = (cmos_regs.status_registers[0] >> 4) & 0x7; + + // break; + // case STATUS_REG_B: + // cmos_regs.status_registers[1] = vctx->eax; + // break; + // case STATUS_REG_C: + // cmos_regs.status_registers[2] = vctx->eax; + // break; + // case STATUS_REG_D: + // // cmos_regs.status_registers[3] = vctx->eax; + // break; + // } + // } + + // } else { + // LOG_VMM_ERR("emulate_cmos_access() called with unknown port address 0x%x\n", port_addr); + // return false; + // } + + // return true; +} \ No newline at end of file diff --git a/src/arch/x86_64/com.c b/src/arch/x86_64/com.c new file mode 100644 index 000000000..e2efad6d4 --- /dev/null +++ b/src/arch/x86_64/com.c @@ -0,0 +1,93 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +static uint8_t com_scratch[5]; + +void emulate_com(seL4_VCPUContext *vctx, size_t idx, size_t reg_offset, bool is_read, bool is_rep, bool is_string, + ioport_access_width_t access_width) +{ + // LOG_VMM("com port %d, reg_offset %d, is_read %d\n", idx, reg_offset, is_read); + + // TODO: sort this out + char buf[100]; + size_t string_bytes_written; + if (is_string) { + assert(reg_offset == 0x0 && !is_read); + + string_bytes_written = emulate_ioport_string_write(vctx, buf, 100, is_rep, access_width); + } + + assert(idx < sizeof(com_scratch) / sizeof(uint8_t)); + switch (reg_offset) { + case 0x7: { + if (is_read) { + vctx->eax = com_scratch[idx]; + } else { + com_scratch[idx] = vctx->eax; + } + break; + } + case 0x0: { + // com2 FIFO + if (is_read) { + vctx->eax = 0; + } else { + // LOG_VMM("com2 out: %c\n", vctx->eax); + if (is_string) { + for (int i = 0; i < string_bytes_written; i++) { + microkit_dbg_putc(buf[i]); + } + } else { + microkit_dbg_putc(vctx->eax); + } + } + break; + } + case 0x4: + // Modem Control Register + break; + case 0x2: { + if (is_read) { + // Interrupt Identification Register + vctx->eax = 0; + } else { + // First In First Out Control Register + // LOG_VMM("FIFO write %x\n", vctx->eax); + } + break; + } + case 0x5: { + // Line Status Register + if (is_read) { + vctx->eax = BIT(5) | BIT(6); + } else { + assert(false); + } + break; + } + case 0x3: { + // Line Control Register + if (is_read) { + vctx->eax = BIT(7); + } else { + // LOG_VMM("LCR write %x\n", vctx->eax); + } + break; + } + case 0x6: + // Modem Status Register + break; + default: + // LOG_VMM_ERR("unknown COM offset 0%lx\n", reg_offset); + break; + } +} diff --git a/src/arch/x86_64/cpuid.c b/src/arch/x86_64/cpuid.c new file mode 100644 index 000000000..62bdd1ba3 --- /dev/null +++ b/src/arch/x86_64/cpuid.c @@ -0,0 +1,418 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +#define CACHE_LINE_SIZE 64 +#define NUM_LOGICAL_PROCESSORS 1 + +extern uint64_t tsc_hz; + +// Table 3-11. More on Feature Information Returned in the EDX Register +#define CPUID_01_ECX_SSE3 BIT(0) +#define CPUID_01_ECX_PCLMULQDQ BIT(1) +#define CPUID_01_ECX_DTES64 BIT(2) // DTES64: 64-bit DS area +#define CPUID_01_ECX_DS_CPL BIT(4) // DS-CPL: CPL qualified debug store +#define CPUID_01_ECX_EST BIT(7) // EST: Enhanced Intel SpeedStep Technology +#define CPUID_01_ECX_TM2 BIT(8) // TM2: Thermal Monitor 2 +#define CPUID_01_ECX_SSSE3 BIT(9) +#define CPUID_01_ECX_FMA BIT(12) +#define CPUID_01_ECX_CMPXCHG16B BIT(13) +#define CPUID_01_ECX_XTPR BIT(14) // xTPR update control +#define CPUID_01_ECX_PDCM BIT(15) // PDCM - Perfmon and Debug Capability MSR +#define CPUID_01_ECX_SSE4_1 BIT(19) +#define CPUID_01_ECX_SSE4_2 BIT(20) +#define CPUID_01_ECX_MOVBE BIT(22) +#define CPUID_01_ECX_POPCNT BIT(23) +#define CPUID_01_ECX_AES BIT(25) +#define CPUID_01_ECX_XSAVE BIT(26) +#define CPUID_01_ECX_OSXSAVE BIT(27) +#define CPUID_01_ECX_AVX BIT(28) +#define CPUID_01_ECX_F16C BIT(29) +#define CPUID_01_ECX_RDRAND BIT(30) +#define CPUID_01_ECX_HYP BIT(31) // Running on hypervisor, correspond to X86_FEATURE_HYPERVISOR in linux source + +#define CPUID_01_EDX_FPU BIT(0) +#define CPUID_01_EDX_VME BIT(1) // VME: Virtual-8086 Mode enhancements +#define CPUID_01_EDX_DE BIT(2) // DE: Debug Extensions (I/O breakpoints) +#define CPUID_01_EDX_PSE BIT(3) // PSE: Page Size Extensions +#define CPUID_01_EDX_TSC BIT(4) +#define CPUID_01_EDX_MSR BIT(5) +#define CPUID_01_EDX_PAE BIT(6) +#define CPUID_01_EDX_MCE BIT(7) // MCE: Machine Check Exception +#define CPUID_01_EDX_CX8 BIT(8) +#define CPUID_01_EDX_APIC BIT(9) +#define CPUID_01_EDX_MTRR BIT(12) // MTRR: Memory Type Range Reg +#define CPUID_01_EDX_PGE BIT(13) // PGE/PTE Global Bit +#define CPUID_01_EDX_MCA BIT(14) // MCA: Machine Check Architecture +#define CPUID_01_EDX_CMOV BIT(15) +#define CPUID_01_EDX_PAT BIT(16) +#define CPUID_01_EDX_PSE36 BIT(17) // PSE-36: Physical Address Extensions +#define CPUID_01_EDX_CLFLUSH BIT(19) +#define CPUID_01_EDX_DEBUG_STORE BIT(21) +#define CPUID_01_EDX_ACPI BIT(22) // ACPI: Thermal Monitor and Software Controlled Clock Facilities +#define CPUID_01_EDX_MMX BIT(23) +#define CPUID_01_EDX_FXSR BIT(24) +#define CPUID_01_EDX_SSE1 BIT(25) +#define CPUID_01_EDX_SSE2 BIT(26) +#define CPUID_01_EDX_SELF_SNOOP BIT(27) +#define CPUID_01_EDX_TM BIT(29) // TM: Thermal Monitor +#define CPUID_01_EDX_PBE BIT(31) // PBE: Pending Break Enable + +#define CPUID_06_EAX_ARAT BIT(2) // APIC-Timer-always-running + +#define CPUID_01_EDX_WINDOWS_MANDATORY 0x789f3fdull + +#define CPUID_07_00_EBX_FSGSBASE BIT(0) +#define CPUID_07_00_EBX_BMI1 BIT(3) +#define CPUID_07_00_EBX_AVX2 BIT(5) +#define CPUID_07_00_EBX_SMEP BIT(7) // SMEP: Supervisor Mode Execution Protection +#define CPUID_07_00_EBX_BMI2 BIT(8) +#define CPUID_07_00_EBX_DEPRECATE_FCS_FDS BIT(13) // Deprecates FPU CS and FPU DS values +#define CPUID_07_00_EBX_ADX BIT(19) // ADCX/ADOX instructions support +#define CPUID_07_00_EBX_SMAP BIT(20) // SMAP: Supervisor Mode Access Prevention +#define CPUID_07_00_EBX_CLFLUSHOPT BIT(23) +#define CPUID_07_00_EBX_CLWB BIT(24) + +#define CPUID_80000001_ECX_LM_LAHF_SAHF BIT(0) // LAHF/SAHF instructions support in 64-bit mode +#define CPUID_80000001_ECX_LM_LZCNT BIT(5) // LZCNT: LZCNT instruction support +#define CPUID_80000001_ECX_PREFETCHW BIT(8) + +#define CPUID_80000001_EDX_SCALL_SRET BIT(11) // SYSCALL/SYSRET support +#define CPUID_80000001_EDX_NX BIT(20) // No execute +#define CPUID_80000001_EDX_1GB_PAGE BIT(26) +#define CPUID_80000001_EDX_RDTSCP BIT(27) +#define CPUID_80000001_EDX_LONG_MODE BIT(29) + +// TODO: do this instead +// #define CPUID_01_BASELINE_EDX (CPUID_01_EDX_CMOV | +// CPUID_01_EDX_CX8 | +// CPUID_01_EDX_FPU | +// CPUID_01_EDX_FXSR | +// CPUID_01_EDX_MMX | +// CPUID_01_EDX_SSE1 | +// CPUID_01_EDX_SSE2) + +// #define CPUID_01_X86_64_V2_EDX (CPUID_01_ECX_CMPXCHG16B | +// CPUID_01_ECX_LAHF_SAHF | + +// ) + +static const char brand_string[48] = "Trustworthy Systems CPU"; + +static inline void cpuid(uint32_t leaf, uint32_t subleaf, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ + __asm__ __volatile__("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "a"(leaf), "c"(subleaf)); +} + +bool emulate_cpuid(seL4_VCPUContext *vctx) +{ + LOG_FAULT("handling CPUID 0x%x\n", vctx->eax); + + // @billn todo revisit likely need to turn on some important features. + // 3-218 Vol. 2A + + switch (vctx->eax) { + case 0x0: + // 3-240 Vol. 2A + // Maxiumum Input Value for Basic CPUID Information. + vctx->eax = 0x16; + // "GenuineIntel" + vctx->ebx = 0x756e6547; + vctx->edx = 0x49656e69; + vctx->ecx = 0x6c65746e; + break; + case 0x1: { + // https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.cc + vctx->eax = 0x00050054; + vctx->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (NUM_LOGICAL_PROCESSORS << 16); + vctx->ecx = CPUID_01_ECX_DTES64 | 0 /* No qualified debug store */ + | 0 /* No Intel Enhanced SpeedStep */ | 0 /* No Thermal Monitor 2 */ | CPUID_01_ECX_XTPR + | 0 /* No Perfmon */ | CPUID_01_ECX_SSE3 | CPUID_01_ECX_PCLMULQDQ + | 0 /* No MONITOR MWAIT*/ | 0 /* No VMX*/ | CPUID_01_ECX_SSSE3 | CPUID_01_ECX_FMA + | CPUID_01_ECX_CMPXCHG16B + | 0 /* No PCID, seL4 in Microkit isn't built with it */ | CPUID_01_ECX_SSE4_1 | CPUID_01_ECX_SSE4_2 + | 0 /* No x2APIC */ | CPUID_01_ECX_MOVBE | CPUID_01_ECX_POPCNT + | 0 /* No TSC deadline */ | CPUID_01_ECX_AES | CPUID_01_ECX_XSAVE | CPUID_01_ECX_OSXSAVE + | CPUID_01_ECX_AVX | CPUID_01_ECX_F16C | 0 /* No RDRAND */ | CPUID_01_ECX_HYP; + + vctx->edx = 0 /* No Debug Store */ | 0 /* No ACPI Thermal Monitor */ | CPUID_01_EDX_SELF_SNOOP + | 0/* No THermal Monitor */ + | CPUID_01_EDX_PBE | CPUID_01_EDX_FPU | 0 /* No virtual 8086 mode */ | CPUID_01_EDX_DE + | CPUID_01_EDX_PSE | CPUID_01_EDX_TSC | CPUID_01_EDX_MSR | CPUID_01_EDX_PAE | CPUID_01_EDX_MCE + | CPUID_01_EDX_CX8 | CPUID_01_EDX_APIC | CPUID_01_EDX_MTRR | CPUID_01_EDX_PGE | CPUID_01_EDX_MCA + | CPUID_01_EDX_CMOV | CPUID_01_EDX_PAT | CPUID_01_EDX_PSE36 | CPUID_01_EDX_MMX | CPUID_01_EDX_FXSR + | CPUID_01_EDX_SSE2 | CPUID_01_EDX_SSE1 | CPUID_01_EDX_CLFLUSH; + + // LOG_VMM("edx = 0x%x, mandatory = 0x%x, (vctx->edx & CPUID_01_EDX_WINDOWS_MANDATORY) = 0x%x\n", vctx->edx, CPUID_01_EDX_WINDOWS_MANDATORY, (vctx->edx & CPUID_01_EDX_WINDOWS_MANDATORY)); + + for (int i = 0; i < 32; i++) { + if (!(vctx->edx & BIT(i)) && (CPUID_01_EDX_WINDOWS_MANDATORY & BIT(i))) { + LOG_VMM("we are missing bit %d\n", i); + } + } + + assert(((uint64_t)(vctx->edx) & CPUID_01_EDX_WINDOWS_MANDATORY) == CPUID_01_EDX_WINDOWS_MANDATORY); + // assert(0); + + break; + } + + case 0x2: { + // https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.cc + // Cache and TLB description + vctx->eax = 0x76036301; + vctx->ebx = 0x00f0b5ff; + vctx->ecx = 0x00000000; + vctx->edx = 0x00c30000; + break; + } + + case 0x4: { + // https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.cc + // Deterministic Cache Parameters + switch (vctx->ecx) { + case 0: + vctx->eax = 0x1c004121; + vctx->ebx = 0x01c0003f; + vctx->ecx = 0x0000003f; + vctx->edx = 0x00000000; + break; + case 1: + vctx->eax = 0x1c004122; + vctx->ebx = 0x01c0003f; + vctx->ecx = 0x0000003f; + vctx->edx = 0x00000000; + break; + case 2: + vctx->eax = 0x1c004143; + vctx->ebx = 0x03c0003f; + vctx->ecx = 0x000003ff; + vctx->edx = 0x00000000; + break; + case 3: + vctx->eax = 0x1c03c163; + vctx->ebx = 0x0280003f; + vctx->ecx = 0x00002fff; + vctx->edx = 0x00000004; + break; + default: + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + break; + } + break; + } + + case 0x7: { + if (vctx->ecx == 0) { + vctx->eax = 0; + vctx->ebx = CPUID_07_00_EBX_FSGSBASE | CPUID_07_00_EBX_BMI1 | CPUID_07_00_EBX_BMI2 + | 0 /* No TSC adjust */ | 0 /* No AVX2 */ | CPUID_07_00_EBX_SMEP + | 0 /* No INVPCID */ | CPUID_07_00_EBX_DEPRECATE_FCS_FDS + | 0 /* No AVX512 */ | 0 /* No RDSEED */ | CPUID_07_00_EBX_ADX | CPUID_07_00_EBX_SMAP + | CPUID_07_00_EBX_CLFLUSHOPT | CPUID_07_00_EBX_CLWB; + vctx->ecx = 0; + vctx->edx = 0; + } else { + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + } + break; + } + + case 0xb: { + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = vctx->ecx; + vctx->edx = 0; // x2apic id, though we don't use x2apic + break; + } + + // sus + case 0xd: { + uint32_t ecx = vctx->ecx; + cpuid(0xd, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, + (uint32_t *)&vctx->edx); + if (ecx == 0) { + // TODO: this is a complete hack because we know seL4 will set the XCR + // to 0x3. + vctx->eax = 0x3; + } + if (ecx == 1) { +#if !defined(CONFIG_XSAVE_XSAVEC) + if (vctx->eax & BIT(1)) { + vctx->eax &= ~BIT(1); + // LOG_VMM("XSAVEC is available in CPU but not available in seL4, disabling for guest\n"); + } +#endif +#if !defined(CONFIG_XSAVE_XSAVEOPT) + if (vctx->eax & BIT(0)) { + vctx->eax &= ~BIT(0); + // LOG_VMM("XSAVEOPT is available in CPU but not available in seL4, disabling for guest\n"); + } +#endif +#if !defined(CONFIG_XSAVE_XSAVES) + if (vctx->eax & BIT(3)) { + vctx->eax &= ~BIT(3); + // LOG_VMM("XSAVES is available in CPU but not available in seL4, disabling for guest\n"); + } +#endif + } + break; + } + case 0x15: { + // Time Stamp Counter and Nominal Core Crystal Clock + vctx->eax = 1; + vctx->ebx = 1; + vctx->ecx = tsc_hz; + vctx->edx = 0; + break; + } + case 0x16: + // Table 3-8. Information Returned by CPUID Instruction (Contd.) + // page "3-232 Vol. 2A" + // processor and bus clock in MHz + // Linux can measure this itself but it needs the PIT, + // which we aren't emulating. + vctx->eax = tsc_hz / 1000000; + vctx->ebx = tsc_hz / 1000000; + vctx->ecx = tsc_hz / 1000000; + vctx->edx = 0; + break; + case 0x80000000: + vctx->eax = 0x80000008; // max input value for extended function cpuid information + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + break; + case 0x80000001: + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = CPUID_80000001_ECX_LM_LAHF_SAHF | CPUID_80000001_ECX_LM_LZCNT | CPUID_80000001_ECX_PREFETCHW; + vctx->edx = 0 /* No RDTSCP */ | CPUID_80000001_EDX_NX | CPUID_80000001_EDX_LONG_MODE + | CPUID_80000001_EDX_1GB_PAGE; + if (guest_in_64_bits()) { + vctx->edx |= CPUID_80000001_EDX_SCALL_SRET; + } + break; + + case 0x80000002: + memcpy(&(vctx->eax), brand_string, 4); + memcpy(&(vctx->ebx), brand_string + 4, 4); + memcpy(&(vctx->ecx), brand_string + 8, 4); + memcpy(&(vctx->edx), brand_string + 12, 4); + break; + case 0x80000003: + memcpy(&(vctx->eax), brand_string + 16, 4); + memcpy(&(vctx->ebx), brand_string + 20, 4); + memcpy(&(vctx->ecx), brand_string + 24, 4); + memcpy(&(vctx->edx), brand_string + 28, 4); + break; + case 0x80000004: + memcpy(&(vctx->eax), brand_string + 32, 4); + memcpy(&(vctx->ebx), brand_string + 36, 4); + memcpy(&(vctx->ecx), brand_string + 40, 4); + memcpy(&(vctx->edx), brand_string + 44, 4); + break; + + case 0x80000006: + // L2 cache topology + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = 0x01006040; + vctx->edx = 0; + break; + + case 0x80000007: + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + + { + uint32_t a, b, c, d; + cpuid(vctx->eax, 0, &a, &b, &c, &d); + if (d & BIT(8)) { + // Turn on invariant TSC if available + vctx->edx = BIT(8); + } + } + + break; + + case 0x80000008: + cpuid(vctx->eax, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, + (uint32_t *)&vctx->edx); + break; + + case 0x6: + vctx->eax = CPUID_06_EAX_ARAT; /* Always running APIC timer */ + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + break; + // @billn todo double check if these are needed + case 0x3: + case 0x5: + case 0x8: + case 0x9: + case 0xa: + case 0xc: + case 0xe: + case 0xf: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + case 0x21: + case 0x40000000 ... 0x4fffffff: + case 0x80000005: + // some AMD specific stuff beyond 0x80000009 inclusive + case 0x80000009 ... 0x8000001f: + case 0x80000026: + /* Highest Xeon Phi Function Implemented */ + case 0x20000000: + /* Transmeta */ + case 0x80860000: + /* Highest Centaur Extended Function */ + case 0xc0000000: + /* Zhaoxin Feature Information */ + case 0xc0000006: + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + break; + default: + LOG_VMM_ERR("invalid cpuid eax value: 0x%x, returning zero\n", vctx->eax); + vctx->eax = 0; + vctx->ebx = 0; + vctx->ecx = 0; + vctx->edx = 0; + break; + } + return true; +} \ No newline at end of file diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c new file mode 100644 index 000000000..02f367e00 --- /dev/null +++ b/src/arch/x86_64/fault.c @@ -0,0 +1,636 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// @billn sus +extern struct lapic_regs lapic_regs; + +bool fault_cond = false; + +/* Documents referenced: + * [1] seL4: include/arch/x86/arch/object/vcpu.h + * [2] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 Order Number: 325462-080US June 2023 + * [2a] Location: Table C-1 "VMX BASIC EXIT REASONS", page: "Vol. 3D C-1" + */ + +/* Exit reasons. + * From [1] + */ +enum exit_reasons { + EXCEPTION_OR_NMI = 0x00, + EXTERNAL_INTERRUPT = 0x01, + TRIPLE_FAULT = 0x02, + INIT_SIGNAL = 0x03, + SIPI = 0x04, + /*IO_SMI = 0x05, + * OTHER_SMI = 0x06,*/ + INTERRUPT_WINDOW = 0x07, + NMI_WINDOW = 0x08, + TASK_SWITCH = 0x09, + CPUID = 0x0A, + GETSEC = 0x0B, + HLT = 0x0C, + INVD = 0x0D, + INVLPG = 0x0E, + RDPMC = 0x0F, + RDTSC = 0x10, + RSM = 0x11, + VMCALL = 0x12, + VMCLEAR = 0x13, + VMLAUNCH = 0x14, + VMPTRLD = 0x15, + VMPTRST = 0x16, + VMREAD = 0x17, + VMRESUME = 0x18, + VMWRITE = 0x19, + VMXOFF = 0x1A, + VMXON = 0x1B, + CONTROL_REGISTER = 0x1C, + MOV_DR = 0x1D, + IO = 0x1E, + RDMSR = 0x1F, + WRMSR = 0x20, + INVALID_GUEST_STATE = 0x21, + MSR_LOAD_FAIL = 0x22, + /* 0x23 */ + MWAIT = 0x24, + MONITOR_TRAP_FLAG = 0x25, + /* 0x26 */ + MONITOR = 0x27, + PAUSE = 0x28, + MACHINE_CHECK = 0x29, + /* 0x2A */ + TPR_BELOW_THRESHOLD = 0x2B, + APIC_ACCESS = 0x2C, + VIRTUALIZED_EOI = 0x2D, + GDTR_OR_IDTR = 0x2E, + LDTR_OR_TR = 0x2F, + EPT_VIOLATION = 0x30, + EPT_MISCONFIGURATION = 0x31, + INVEPT = 0x32, + RDTSCP = 0x33, + VMX_PREEMPTION_TIMER = 0x34, + INVVPID = 0x35, + WBINVD = 0x36, + XSETBV = 0x37, + APIC_WRITE = 0x38, + NUM_EXIT_REASONS = 0x39, +}; + +/* [2a] */ +static char *exit_reason_strs[] = { "Exception or non-maskable interrupt (NMI)", + "External interrupt", + "Triple Fault", + "INIT signal", + "Start-up IPI (SIPI)", + "I/O system-management interrupt (SMI)", + "Other SMI", + "Interrupt window", + "NMI window", + "Task switch", + "CPUID", + "GETSEC", + "HLT", + "INVD", + "INVLPG", + "RDPMC", + "RDTSC", + "RSM", + "VMCALL", + "VMCLEAR", + "VMLAUNCH", + "VMPTRLD", + "VMPTRST", + "VMREAD", + "VMRESUME", + "VMWRITE", + "VMXOFF", + "VMXON", + "Control-register accesses", + "MOV DR", + "I/O instruction", + "RDMSR", + "WRMSR", + "VM-entry failure due to invalid guest state", + "VM-entry failure due to MSR loading", + "", + "MWAIT", + "Monitor trap flag", + "", + "MONITOR", + "PAUSE", + "VM-entry failure due to machine-check event", + "", + "TPR below threshold", + "APIC access", + "Virtualized EOI", + "Access to GDTR or IDTR", + "Access to LDTR or TR", + "EPT violation", + "EPT misconfiguration", + "INVEPT", + "RDTSCP", + "VMX-preemption timer expired", + "INVVPID", + "WBINVD or WBNOINVD", + "XSETBV", + "APIC Write" }; + +_Static_assert(sizeof(exit_reason_strs) / sizeof(char *) == NUM_EXIT_REASONS, + "Exit reason strings table is not correct length"); + +char *fault_to_string(int exit_reason) +{ + assert(exit_reason < NUM_EXIT_REASONS); + assert(exit_reason_strs[exit_reason] != NULL); + return exit_reason_strs[exit_reason]; +} + +bool fault_is_trap_like(int exit_reason) +{ + switch (exit_reason) { + case APIC_WRITE: + case VIRTUALIZED_EOI: + return true; + default: + return false; + } +} + +struct ept_exception_handler { + uintptr_t base; + uintptr_t end; + ept_exception_callback_t callback; + void *cookie; +}; +#define MAX_EPT_EXCEPTION_HANDLERS 16 +static struct ept_exception_handler registered_ept_exception_handlers[MAX_EPT_EXCEPTION_HANDLERS]; +static size_t ept_exception_handler_index = 0; + +bool fault_update_ept_exception_handler(uintptr_t base, uintptr_t new_base) +{ + for (int i = 0; i < ept_exception_handler_index; i++) { + struct ept_exception_handler *curr = ®istered_ept_exception_handlers[i]; + if (curr->base == base) { + curr->base = new_base; + return true; + } + } + + LOG_VMM("failed to update EPT exception handler, none exists for base 0x%lx\n", base); + + return false; +} + +bool fault_register_ept_exception_handler(uintptr_t base, size_t size, ept_exception_callback_t callback, void *cookie) +{ + if (ept_exception_handler_index == MAX_EPT_EXCEPTION_HANDLERS - 1) { + LOG_VMM_ERR("maximum number of EPT exception handlers registered"); + return false; + } + + if (size == 0) { + LOG_VMM_ERR("registered EPT exception handler with size 0\n"); + return false; + } + + for (int i = 0; i < ept_exception_handler_index; i++) { + struct ept_exception_handler *curr = ®istered_ept_exception_handlers[i]; + if (!(base >= curr->end || base + size <= curr->base)) { + LOG_VMM_ERR("EPT exception handler [0x%lx..0x%lx), overlaps with another handler [0x%lx..0x%lx)\n", base, + base + size, curr->base, curr->end); + return false; + } + } + + registered_ept_exception_handlers[ept_exception_handler_index] = (struct ept_exception_handler) { + .base = base, + .end = base + size, + .callback = callback, + .cookie = cookie, + }; + ept_exception_handler_index += 1; + + return true; +} + +static bool handle_ept_fault(seL4_VCPUContext *vctx, seL4_Word qualification, decoded_instruction_ret_t decoded_ins) +{ + uint64_t addr = microkit_mr_get(SEL4_VMENTER_FAULT_GUEST_PHYSICAL_MR); + // LOG_VMM("handling EPT fault on GPA 0x%lx, qualification: 0x%lx\n", addr, qualification); + + if (addr >= IOAPIC_GPA && addr < IOAPIC_GPA + IOAPIC_SIZE) { + LOG_FAULT("handling IO APIC 0x%lx\n", addr); + return ioapic_fault_handle(vctx, addr - IOAPIC_GPA, qualification, decoded_ins); + } else if (addr >= HPET_GPA && addr < HPET_GPA + HPET_SIZE) { + LOG_FAULT("handling HPET 0x%lx\n", addr); + return hpet_fault_handle(vctx, addr - HPET_GPA, qualification, decoded_ins); + // } else if (addr >= ECAM_GPA && addr < ECAM_GPA + ECAM_SIZE) { + // return pci_x86_emulate_ecam_access(vctx, addr - ECAM_GPA, qualification, decoded_mem_ins); + } else { + LOG_FAULT("handling other EPT 0x%lx\n", addr); + for (int i = 0; i < MAX_EPT_EXCEPTION_HANDLERS; i++) { + uintptr_t base = registered_ept_exception_handlers[i].base; + uintptr_t end = registered_ept_exception_handlers[i].end; + ept_exception_callback_t callback = registered_ept_exception_handlers[i].callback; + void *cookie = registered_ept_exception_handlers[i].cookie; + if (addr >= base && addr < end) { + bool success = callback(0, addr - base, qualification, decoded_ins, vctx, cookie); + if (!success) { + LOG_VMM_ERR("registered EPT exception handler for region [0x%lx..0x%lx) at address " + "0x%lx failed\n", + base, end, addr); + } + + return success; + } + } + + LOG_VMM_ERR("failed to find EPT handler for address 0x%lx\n", addr); + } + + // LOG_VMM("done\n"); + + return false; +} + +struct pio_exception_handler { + uint16_t base; + uint16_t end; + pio_exception_callback_t callback; + void *cookie; +}; +#define MAX_PIO_EXCEPTION_HANDLERS 16 +static struct pio_exception_handler registered_pio_exception_handlers[MAX_PIO_EXCEPTION_HANDLERS]; +static size_t pio_exception_handler_index = 0; + +bool fault_register_pio_exception_handler(uint16_t base, uint16_t size, pio_exception_callback_t callback, void *cookie) +{ + if (pio_exception_handler_index == MAX_PIO_EXCEPTION_HANDLERS - 1) { + LOG_VMM_ERR("maximum number of PIO exception handlers registered"); + return false; + } + + if (size == 0) { + LOG_VMM_ERR("registered PIO exception handler with size 0\n"); + return false; + } + + uint64_t size_64 = (uint64_t)base + (uint64_t)size; + if (size_64 > 0xffff) { + LOG_VMM_ERR("base + size = 0x%lx exceed uint16_t max\n", size_64); + return false; + } + + for (int i = 0; i < pio_exception_handler_index; i++) { + struct pio_exception_handler *curr = ®istered_pio_exception_handlers[i]; + if (!(base >= curr->end || base + size <= curr->base)) { + LOG_VMM_ERR("PIO exception handler [0x%lx..0x%lx), overlaps with another handler [0x%lx..0x%lx)\n", base, + base + size, curr->base, curr->end); + return false; + } + } + + registered_pio_exception_handlers[pio_exception_handler_index] = (struct pio_exception_handler) { + .base = base, + .end = base + size, + .callback = callback, + .cookie = cookie, + }; + pio_exception_handler_index += 1; + + return true; +} + +static bool handle_pio_fault(seL4_VCPUContext *vctx, seL4_Word qualification) +{ + uint16_t port_addr = (qualification >> 16) & 0xffff; + // TODO: pass access width to the callbacks? + // ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); + + if (port_addr >= 0x3f8 && port_addr <= 0x3f8 + 8) { + } else if (port_addr >= 0x2f8 && port_addr <= 0x2f8 + 8) { + } else if (port_addr >= 0x3e8 && port_addr <= 0x3e8 + 8) { + } else if (port_addr >= 0x2ef && port_addr <= 0x2ef + 8) { + } else { + LOG_FAULT("handling PIO 0x%lx\n", port_addr); + } + + for (int i = 0; i < MAX_PIO_EXCEPTION_HANDLERS; i++) { + uint16_t base = registered_pio_exception_handlers[i].base; + uint16_t end = registered_pio_exception_handlers[i].end; + pio_exception_callback_t callback = registered_pio_exception_handlers[i].callback; + void *cookie = registered_pio_exception_handlers[i].cookie; + if (port_addr >= base && port_addr < end) { + bool success = callback(0, port_addr - base, qualification, vctx, cookie); + if (!success) { + LOG_VMM_ERR("registered PIO exception handler for region [0x%lx..0x%lx) at address " + "0x%lx failed\n", + base, end, port_addr); + } + + return success; + } + } + + return emulate_ioports(vctx, qualification); +} + +// static uint64_t prev_valid_idt_entries = 0; + +uint64_t *cr_fault_reg_idx_to_vctx_ptr(int idx, seL4_VCPUContext *vctx) +{ + switch (idx) { + case 0: + return &vctx->eax; + case 1: + return &vctx->ecx; + case 2: + return &vctx->edx; + case 3: + return &vctx->ebx; + // case 4: + // return stack pointer; + case 5: + return &vctx->ebp; + case 6: + return &vctx->esi; + case 7: + return &vctx->edi; + case 8: + return &vctx->r8; + case 9: + return &vctx->r9; + case 10: + return &vctx->r10; + case 11: + return &vctx->r11; + case 12: + return &vctx->r12; + case 13: + return &vctx->r13; + case 14: + return &vctx->r14; + case 15: + return &vctx->r15; + default: + return NULL; + } +} + +uint64_t n_faults = 0; +uint64_t n_vmexit_reasons[NUM_EXIT_REASONS] = { 0 }; + +uint64_t n_notifieds = 0; + +bool fault_handle(size_t vcpu_id, uint64_t *new_rip) +{ + bool success = false; + decoded_instruction_ret_t decoded_ins; + + seL4_Word f_reason = microkit_mr_get(SEL4_VMENTER_FAULT_REASON_MR); + seL4_Word ins_len = microkit_mr_get(SEL4_VMENTER_FAULT_INSTRUCTION_LEN_MR); + seL4_Word qualification = microkit_mr_get(SEL4_VMENTER_FAULT_QUALIFICATION_MR); + seL4_Word rip = microkit_mr_get(SEL4_VMENTER_CALL_EIP_MR); + + // if (rip > 0xfffff00000000000) { + // LOG_FAULT("vmm exit in kernel at rip 0x%lx\n", rip); + // fault_cond = true; + // } else { + // fault_cond = false; + // } + + LOG_FAULT("handling vmexit reason %s\n", fault_to_string(f_reason)); + + seL4_VCPUContext vctx; + vctx.eax = microkit_mr_get(SEL4_VMENTER_FAULT_EAX); + vctx.ebx = microkit_mr_get(SEL4_VMENTER_FAULT_EBX); + vctx.ecx = microkit_mr_get(SEL4_VMENTER_FAULT_ECX); + vctx.edx = microkit_mr_get(SEL4_VMENTER_FAULT_EDX); + vctx.esi = microkit_mr_get(SEL4_VMENTER_FAULT_ESI); + vctx.edi = microkit_mr_get(SEL4_VMENTER_FAULT_EDI); + vctx.ebp = microkit_mr_get(SEL4_VMENTER_FAULT_EBP); + vctx.r8 = microkit_mr_get(SEL4_VMENTER_FAULT_R8); + vctx.r9 = microkit_mr_get(SEL4_VMENTER_FAULT_R9); + vctx.r10 = microkit_mr_get(SEL4_VMENTER_FAULT_R10); + vctx.r11 = microkit_mr_get(SEL4_VMENTER_FAULT_R11); + vctx.r12 = microkit_mr_get(SEL4_VMENTER_FAULT_R12); + vctx.r13 = microkit_mr_get(SEL4_VMENTER_FAULT_R13); + vctx.r14 = microkit_mr_get(SEL4_VMENTER_FAULT_R14); + vctx.r15 = microkit_mr_get(SEL4_VMENTER_FAULT_R15); + + switch (f_reason) { + case CPUID: + success = emulate_cpuid(&vctx); + break; + case RDMSR: + success = emulate_rdmsr(&vctx); + break; + case WRMSR: + success = emulate_wrmsr(&vctx); + break; + case EPT_VIOLATION: + decoded_ins = decode_instruction(vcpu_id, rip, ins_len); + if (decoded_ins.type == INSTRUCTION_DECODE_FAIL) { + success = false; + } else { + success = handle_ept_fault(&vctx, qualification, decoded_ins); + } + break; + case IO: + success = handle_pio_fault(&vctx, qualification); + break; + // case APIC_ACCESS: + case VIRTUALIZED_EOI: { + uint8_t eoi_vector = qualification; + // if we get here then the guest has ack'ed a passed through I/O APIC irq, + // find and run the ack function, the clear the vector from the bitmap + // @billn the whole clearing vector from bitmap thing could be done more efficiently, e.g. + // only do it when the guest reprogram the vector + + success = ioapic_ack_passthrough_irq(eoi_vector); + break; + } + case APIC_WRITE: { + // 32.4.3.3 APIC-Write VM Exits + // "The exit qualification is the page offset of the write access that led to the VM exit." + uint64_t lapic_reg_offset = qualification; + success = lapic_write_fault_handle(lapic_reg_offset, vapic_read_reg(lapic_reg_offset)); + break; + } + case APIC_ACCESS: { + uint16_t offset = qualification & 0x7ff; + uint8_t access_type = (qualification >> 12) & 0xf; + + // only handle reads and writes due to instruciton execution + + // LOG_VMM("offset 0x%x, access type %d\n", offset, access_type); + + if (access_type == 0) { + uint32_t data; + success = lapic_read_fault_handle(offset, &data); + decoded_ins = decode_instruction(vcpu_id, rip, ins_len); + assert(decoded_ins.type == INSTRUCTION_MEMORY); + uint64_t *vctx_raw = (uint64_t *)&vctx; + vctx_raw[decoded_ins.decoded.memory_instruction.target_reg] = data; + } else if (access_type == 1) { + decoded_ins = decode_instruction(vcpu_id, rip, ins_len); + assert(decoded_ins.type == INSTRUCTION_MEMORY); + // TODO: probably do not have this assert + assert(mem_access_width_to_bytes(decoded_ins) == 4); + uint64_t *vctx_raw = (uint64_t *)&vctx; + // TODO: probably use wrapper for getting write value. + success = lapic_write_fault_handle(offset, vctx_raw[decoded_ins.decoded.memory_instruction.target_reg]); + } else { + LOG_VMM_ERR("unsupported access type %d for apic access vm exit\n", access_type); + success = false; + } + break; + } + case XSETBV: + // LOG_VMM("XSETBV, rip 0x%lx\n", rip); + success = true; + break; + default: + LOG_VMM_ERR("unhandled fault: 0x%x\n", f_reason); + }; + + // n_vmexit_reasons[f_reason] += 1; + // n_faults += 1; + // if (n_faults % 50000 == 0) { + // LOG_VMM("vm exit stats:\n"); + // for (int i = 0; i < NUM_EXIT_REASONS; i++) { + // char *reason_human = fault_to_string(i); + // uint64_t n_fault = n_vmexit_reasons[i]; + // if (reason_human[0] != 0 && n_fault) { + // LOG_VMM("%s: %lu\n", reason_human, n_fault); + // } + // } + // LOG_VMM("number of notifieds: %lu\n", n_notifieds); + // } + + *new_rip = rip; + if (success && f_reason != INTERRUPT_WINDOW) { + // uint64_t cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); + // if (cr4 & BIT(18)) { + // LOG_VMM("======== HELLO OSXSAVE IS ON!!!!\n"); + // } + + // uint64_t idtr_gva = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_BASE); + // uint64_t idtr_limit = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_LIMIT); + // uint64_t idtr_gpa, _bytes_remaining; + // bool idtr_valid = gva_to_gpa(0, idtr_gva, &idtr_gpa, &_bytes_remaining); + // uint8_t idt_entry_size = guest_in_64_bits() ? 16 : 8; + // uint16_t idt_num_entries = (idtr_limit + 1) / idt_entry_size; + // uint16_t num_present_entries = 0; + // for (int i = 0; i < idt_num_entries; i++) { + // uint32_t entry[4]; + // uint64_t entry_gpa = idtr_gpa + (i * idt_entry_size); + // entry[0] = *((uint64_t *) gpa_to_vaddr(entry_gpa)); + // entry[1] = *((uint64_t *) gpa_to_vaddr(entry_gpa + 4)); + // entry[2] = *((uint64_t *) gpa_to_vaddr(entry_gpa + 8)); + // entry[3] = *((uint64_t *) gpa_to_vaddr(entry_gpa + 12)); + + // uint32_t present = (entry[1] & BIT(15)); + // if (present) + // num_present_entries++; + // } + + // if (num_present_entries != prev_valid_idt_entries) { + // LOG_VMM("+_+_+_+_+ IDT have %d valid entries\n", num_present_entries); + // LOG_VMM_ERR("IDTR gpa: 0x%lx\n", idtr_gpa); + // } + + // prev_valid_idt_entries = num_present_entries; + + // TODO hack force osxsave on so that windows doesnt #UD on xgetbv/xsetbv + uint64_t cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4, cr4 | BIT(18)); + + microkit_vcpu_x86_write_regs(vcpu_id, &vctx); + + if (!fault_is_trap_like(f_reason)) { + *new_rip = rip + ins_len; + } + } else if (!success) { + LOG_VMM_ERR("failed handling fault: '%s' (0x%x)\n", fault_to_string(f_reason), f_reason); + LOG_VMM_ERR("paging on: %s\n", guest_paging_on() ? "YES" : "NO"); + if (guest_paging_on()) { + uint64_t _sp_gpa, _bytes_remaining; + bool sp_valid = gva_to_gpa(0, microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RSP), &_sp_gpa, &_bytes_remaining); + LOG_VMM_ERR("stack pointer valid: %s\n", sp_valid ? "YES" : "NO"); + + uint64_t idtr_gva = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_BASE); + uint64_t idtr_limit = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_LIMIT); + uint64_t idtr_gpa; + bool idtr_valid = gva_to_gpa(0, idtr_gva, &idtr_gpa, &_bytes_remaining); + LOG_VMM_ERR("IDTR gva: 0x%lx\n", idtr_gva); + LOG_VMM_ERR("IDTR limit: 0x%lx\n", idtr_limit); + LOG_VMM_ERR("IDTR gpa: 0x%lx\n", idtr_gpa); + LOG_VMM_ERR("IDTR valid: %s\n", idtr_valid ? "YES" : "NO"); + uint8_t idt_entry_size = guest_in_64_bits() ? 16 : 8; + uint16_t idt_num_entries = (idtr_limit + 1) / idt_entry_size; + LOG_VMM_ERR("IDTR num entries: %d\n", idt_num_entries); + + uint16_t idt_num_valid_entries = 0; + for (int i = 0; i < idt_num_entries; i++) { + uint32_t entry[4]; + uint64_t entry_gpa = idtr_gpa + (i * idt_entry_size); + entry[0] = *((uint64_t *)gpa_to_vaddr(entry_gpa)); + entry[1] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 4)); + entry[2] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 8)); + entry[3] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 12)); + + uint32_t present = (entry[1] & BIT(15)); + // LOG_VMM("IDT entry %d is present: %s\n", i, present ? "YES" : "NO"); + if (present) { + idt_num_valid_entries += 1; + } + } + + LOG_VMM_ERR("IDTR num valid entries: %d\n", idt_num_valid_entries); + } + // if (ins_len) { + // uint64_t gpa; + // int bytes_remaining; + // assert(gva_to_gpa(0, rip, &gpa, &bytes_remaining)); + // assert(bytes_remaining >= ins_len); + // LOG_VMM_ERR("faulting instruction:\n"); + // uint8_t *ins = gpa_to_vaddr(gpa); + // for (int i = 0; i < ins_len; i++) { + // LOG_VMM_ERR("0x%02x\n", ins[i]); + // bytes_remaining--; + // } + + // LOG_VMM_ERR("proceeding instructions:\n"); + // for (int i = 0; i < MIN(bytes_remaining, 16); i++) { + // LOG_VMM_ERR("0x%02x\n", ins[i + ins_len]); + // bytes_remaining--; + // } + // } + vcpu_print_regs(vcpu_id); + } + + return success; +} \ No newline at end of file diff --git a/src/arch/x86_64/guest.c b/src/arch/x86_64/guest.c new file mode 100644 index 000000000..fb9d702b4 --- /dev/null +++ b/src/arch/x86_64/guest.c @@ -0,0 +1,117 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +extern uintptr_t guest_ram_vaddr; +extern uintptr_t guest_flash_vaddr; +extern uintptr_t guest_high_ram_size; + +bool guest_paging_on(void) +{ + return microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_CR0) & BIT(31); +} + +bool guest_in_64_bits(void) +{ + return guest_paging_on() && (microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_EFER) & BIT(10)); +} + +void *gpa_to_vaddr(uint64_t gpa) +{ + // @billn ugly hack + uint64_t firmware_region_base_gpa = 0xffa00000; + uint64_t high_ram_base_gpa = 0x100000000; + if (gpa < firmware_region_base_gpa) { + return (void *)(guest_ram_vaddr + gpa); + } else if (gpa >= high_ram_base_gpa && gpa < high_ram_base_gpa + guest_high_ram_size) { + // @billn ugly one-to-one hack + return (void *)gpa; + } else if (gpa >= firmware_region_base_gpa && gpa < high_ram_base_gpa) { + return (void *)(guest_flash_vaddr + (gpa - firmware_region_base_gpa)); + } else { + LOG_VMM_ERR("gpa_to_vaddr(): GPA 0x%lx not in any valid guest memory regions\n", gpa); + return NULL; + } +} + +uint64_t gpa_to_pa(uint64_t gpa) +{ + // @billn ugly hack + uint64_t ram_base_gpa = 0x20000000; + uint64_t high_ram_base_gpa = 0x100000000; + if (gpa >= high_ram_base_gpa && gpa < high_ram_base_gpa + guest_high_ram_size) { + // @billn ugly one-to-one hack + return gpa; + } else if (gpa < high_ram_base_gpa) { + return ram_base_gpa + gpa; + } else { + LOG_VMM_ERR("gpa_to_pa(): GPA 0x%lx not in any valid guest memory regions\n", gpa); + return 0; + } +} + +bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, uint64_t *bytes_remaining) +{ + // Make sure that paging is on + if (!guest_paging_on()) { + *gpa = gva; + } + + uint64_t pml4_gpa = microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_CR3) & ~0xfff; + uint64_t *pml4 = gpa_to_vaddr(pml4_gpa); + uint64_t pml4_idx = (gva >> (12 + (9 * 3))) & 0x1ff; + uint64_t pml4_pte = pml4[pml4_idx]; + if (!pte_present(pml4_pte)) { + LOG_VMM_ERR("PML4 PTE not present when converting GVA 0x%lx to GPA\n", gva); + return false; + } + + uint64_t pdpt_gpa = pte_to_gpa(pml4_pte); + uint64_t *pdpt = gpa_to_vaddr(pdpt_gpa); + uint64_t pdpt_idx = (gva >> (12 + (9 * 2))) & 0x1ff; + uint64_t pdpt_pte = pdpt[pdpt_idx]; + if (!pte_present(pdpt_pte)) { + LOG_VMM_ERR("PDPT PTE not present when converting GVA 0x%lx to GPA\n", gva); + return false; + } + + uint64_t pd_gpa = pte_to_gpa(pdpt_pte); + uint64_t *pd = gpa_to_vaddr(pd_gpa); + uint64_t pd_idx = (gva >> (12 + (9 * 1))) & 0x1ff; + uint64_t pd_pte = pd[pd_idx]; + if (!pte_present(pd_pte)) { + LOG_VMM_ERR("PD PTE not present when converting GVA 0x%lx to GPA\n", gva); + return false; + } + + if (pt_page_size(pd_pte) && pte_present(pd_pte)) { + // 2MiB page + uint64_t page_gpa = pte_to_gpa(pd_pte); + uint64_t page_offset = (gva & 0x1fffff); + *gpa = page_gpa + page_offset; + *bytes_remaining = 0x200000 - page_offset; + } else { + // 4k page + uint64_t pt_gpa = pte_to_gpa(pd_pte); + uint64_t *pt = gpa_to_vaddr(pt_gpa); + uint64_t pt_idx = (gva >> (12)) & 0x1ff; + uint64_t pt_pte = pt[pt_idx]; + if (!pte_present(pt_pte)) { + LOG_VMM_ERR("PT PTE not present when converting GVA 0x%lx to GPA\n", gva); + return 0; + } + + uint64_t page_gpa = pte_to_gpa(pt_pte); + uint64_t page_offset = (gva & 0xfff); + *gpa = page_gpa + page_offset; + *bytes_remaining = 0x1000 - page_offset; + } + + return true; +} \ No newline at end of file diff --git a/src/arch/x86_64/hpet.c b/src/arch/x86_64/hpet.c new file mode 100644 index 000000000..83983b349 --- /dev/null +++ b/src/arch/x86_64/hpet.c @@ -0,0 +1,589 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Implements a minimum HPET specification (3 comparators with 1 being periodic capable) + +// https://wiki.osdev.org/HPET +// https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf + +/* Uncomment this to enable debug logging */ +// #define DEBUG_HPET + +#if defined(DEBUG_HPET) +#define LOG_HPET(...) do{ if (fault_cond) { printf("%s|HPET: ", microkit_name); printf(__VA_ARGS__); } } while(0) +#else +#define LOG_HPET(...) do{}while(0) +#endif + +#define GENERAL_CAP_REG_MMIO_OFF 0x0 +#define GENERAL_CAP_REG_HIGH_MMIO_OFF 0x4 + +#define GENERAL_CONFIG_REG_MMIO_OFF 0x10 +#define GENERAL_CONFIG_REG_HIGH_MMIO_OFF 0x14 + +#define GENERAL_ISR_MMIO_OFF 0x20 + +#define MAIN_COUNTER_VALUE_MMIO_OFF 0xf0 +#define MAIN_COUNTER_VALUE_HIGH_MMIO_OFF 0xf4 + +// General Capability register +#define NS_IN_FS 1000000ul +// Main counter tick period in femtosecond. 10MHz tick +#define COUNTER_CLK_PERIOD_VAL (NS_IN_FS * 100) +#define COUNTER_CLK_PERIOD_SHIFT 32 +// Legacy IRQ replacement capable (replace the old PIT) +#define LEG_RT_CAP BIT(15) +// 64-bit main counter +#define COUNT_SIZE_CAP BIT(13) +// 3 comparators +#define NUM_TIM_CAP_VAL 2ul // last index +#define NUM_TIM_CAP_SHIFT 8 +#define REV_ID 1ul +#define VENDOR_ID (0x5E14ull << 16) + +// General Config register +#define LEG_RT_CNF BIT(1) // legacy routing on +#define ENABLE_CNF BIT(0) // counter and irq on + +// Comparator config register +#define Tn_32MODE_CNF BIT(8) // if software set this bit, comparator is in 32 bits mode +#define Tn_VAL_SET_CNF BIT(6) // Software writes 1 to this bit to change the comparator +#define Tn_SIZE_CAP BIT(5) // 64-bit +#define Tn_PER_INT_CAP BIT(4) // Periodic capable +#define Tn_INT_ENB_CNF BIT(2) // irq on +#define Tn_INT_TYPE_CNF BIT(1) // irq type, 0 = edge, 1 = level +#define Tn_TYPE_CNF BIT(3) // periodic mode on +#define Tn_INT_ROUTE_CNF_SHIFT 9 +#define Tn_INT_ROUTE_CAP_SHIFT 32 + +// I/O APIC routing if no legacy +#define TIM0_IOAPIC_PIN 13 +#define TIM1_IOAPIC_PIN 14 +#define TIM2_IOAPIC_PIN 15 + +struct comparator_regs { + uint64_t config; + uint64_t config_mask; + uint64_t current_comparator; + uint64_t armed_comparator; + uint64_t comparator_increment; +}; + +struct hpet_regs { + uint64_t general_capabilities; // RO + uint64_t general_config; // RW + uint64_t isr; // RW + struct comparator_regs comparators[NUM_TIM_CAP_VAL + 1]; +}; + +static uint64_t hpet_frozen_counter = 0; +static uint64_t hpet_counter_offset = 0; + +#define GENERAL_CAP_MASK ((REV_ID | (NUM_TIM_CAP_VAL << NUM_TIM_CAP_SHIFT) | LEG_RT_CAP | (COUNTER_CLK_PERIOD_VAL << COUNTER_CLK_PERIOD_SHIFT)) | VENDOR_ID | COUNT_SIZE_CAP) +#define TIM0_CONF_MASK (Tn_SIZE_CAP | Tn_PER_INT_CAP | (BIT(TIM0_IOAPIC_PIN) << Tn_INT_ROUTE_CAP_SHIFT)) +#define TIM1_CONF_MASK (Tn_SIZE_CAP | (BIT(TIM1_IOAPIC_PIN) << Tn_INT_ROUTE_CAP_SHIFT)) +#define TIM2_CONF_MASK (Tn_SIZE_CAP | (BIT(TIM2_IOAPIC_PIN) << Tn_INT_ROUTE_CAP_SHIFT)) + +static struct hpet_regs hpet_regs = { + // 64-bit main counter, 3 comparators (only 1 periodic capable), legacy IRQ routing capable, and + // tick period = 10MHz + .general_capabilities = GENERAL_CAP_MASK, + .comparators[0] = { .config = TIM0_CONF_MASK, .config_mask = TIM0_CONF_MASK }, + .comparators[1] = { .config = TIM1_CONF_MASK, .config_mask = TIM1_CONF_MASK }, + .comparators[2] = { .config = TIM2_CONF_MASK, .config_mask = TIM2_CONF_MASK }, +}; + +static uint64_t time_now_64(void) +{ + return sddf_timer_time_now(TIMER_DRV_CH_FOR_HPET_CH0) / (uint64_t)100; +} + +static bool counter_on(void) +{ + return (hpet_regs.general_config & ENABLE_CNF); +} + +static uint64_t main_counter_value(void) +{ + if (counter_on()) { + return time_now_64() - hpet_counter_offset; + } else { + return hpet_frozen_counter; + } +} + +static void reset_main_counter(void) +{ + hpet_counter_offset = time_now_64(); +} + +static bool timer_n_forced_32(int n) +{ + return !!(hpet_regs.comparators[n].config & Tn_32MODE_CNF); +} + +static uint64_t counter_value_in_terms_of_timer(int n) +{ + uint64_t counter = main_counter_value(); + if (timer_n_forced_32(n)) { + counter &= 0xffffffff; + } + return counter; +} + +static int timer_n_config_reg_mmio_off(int n) +{ + return 0x100 + (0x20 * n); +} + +static int timer_n_comparator_mmio_off(int n) +{ + return 0x108 + (0x20 * n); +} + +static uint8_t get_timer_n_ioapic_pin(int n) +{ + assert(n <= NUM_TIM_CAP_VAL); + if (hpet_regs.general_config & LEG_RT_CNF) { + // legacy routing + if (n == 0) { + return 2; + } else if (n == 1) { + return 8; + } + } + return (hpet_regs.comparators[n].config >> 9) & 0x1f; // Tn_INT_ROUTE_CNF +} + +static bool timer_n_can_interrupt(int n) +{ + return counter_on() && !!(hpet_regs.comparators[n].config & Tn_INT_ENB_CNF); +} + +static bool timer_n_in_periodic_mode(int n) +{ + return !!(hpet_regs.comparators[n].config & Tn_TYPE_CNF); +} + +static bool timer_n_irq_edge_triggered(int n) +{ + return (hpet_regs.comparators[n].config & Tn_INT_TYPE_CNF) == 0; +} + +uint64_t timer_n_compute_timeout_ns(int n, uint64_t main_counter_val) +{ + uint64_t delay_ns = 0; + + if (main_counter_val < hpet_regs.comparators[n].current_comparator) { + delay_ns = hpet_regs.comparators[n].current_comparator - main_counter_val; + } else if (main_counter_val > hpet_regs.comparators[n].current_comparator && timer_n_forced_32(n)) { + // detect counter overflow + LOG_HPET("comparator %d have overflown. counter = %ld, comparator = %ld, is 32b %d\n", n, main_counter_val, + hpet_regs.comparators[n].current_comparator, timer_n_forced_32(n)); + LOG_HPET("handling overflow, %ld + %ld = %ld\n", (1ULL << 32) - main_counter_val, + hpet_regs.comparators[n].current_comparator, delay_ns); + + delay_ns += (1ull << 32) - main_counter_val; + delay_ns += hpet_regs.comparators[n].current_comparator; + } + + return delay_ns * 100; +} + +bool bug_check_irq_at_correct_time(int comparator, uint64_t main_counter_val) +{ + uint64_t expected_counter_val = hpet_regs.comparators[comparator].armed_comparator; + uint64_t difference_units; + // Our virtual HPET is 10MHz, so allow for 1ms drift by (NS_IN_MS / 100) + uint64_t tolerance_units = (NS_IN_MS / 100); + + if (expected_counter_val > main_counter_val) { + difference_units = expected_counter_val - main_counter_val; + if (difference_units > tolerance_units) { + LOG_VMM_ERR("HPET timer irq too early!!! comp %d, counter %lu, comparator %lu, diff %lu > margin %lu\n", + comparator, main_counter_val, hpet_regs.comparators[comparator].armed_comparator, + difference_units, tolerance_units); + return false; + } + } else { + difference_units = main_counter_val - expected_counter_val; + if (difference_units > tolerance_units) { + // LOG_VMM_ERR("HPET timer irq too late!!! comp %d, counter %lu, comparator %lu, diff %lu > margin %lu\n", comparator, + // main_counter_val, hpet_regs.comparators[comparator].armed_comparator, difference_units, tolerance_units); + return false; + } + } + + return true; +} + +void hpet_handle_timer_ntfn(microkit_channel ch) +{ + // bool maintenance = false; + + if (!counter_on()) { + return; + } + + if (ch == TIMER_DRV_CH_FOR_HPET_CH0) { + uint64_t main_counter_val = counter_value_in_terms_of_timer(0); + bug_check_irq_at_correct_time(0, main_counter_val); + if (timer_n_can_interrupt(0)) { + int ioapic_pin = get_timer_n_ioapic_pin(0); + if (!inject_ioapic_irq(0, ioapic_pin)) { + LOG_HPET("IRQ dropped on HPET comp 0, pin %d\n", ioapic_pin); + } + } + if (timer_n_in_periodic_mode(0) && hpet_regs.comparators[0].comparator_increment) { + hpet_regs.comparators[0].current_comparator = main_counter_val + + hpet_regs.comparators[0].comparator_increment; + if (timer_n_forced_32(0)) { + hpet_regs.comparators[0].current_comparator &= 0xffffffff; + } + + uint64_t delay_ns = timer_n_compute_timeout_ns(0, main_counter_val); + if (delay_ns) { + LOG_HPET("t0 re-arm for %ld ns\n", delay_ns); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_HPET_CH0, delay_ns); + hpet_regs.comparators[0].armed_comparator = hpet_regs.comparators[0].current_comparator; + } + } + } else if (ch == TIMER_DRV_CH_FOR_HPET_CH1) { + uint64_t main_counter_val = counter_value_in_terms_of_timer(1); + bug_check_irq_at_correct_time(1, main_counter_val); + if (timer_n_can_interrupt(1)) { + int ioapic_pin = get_timer_n_ioapic_pin(1); + if (!inject_ioapic_irq(0, ioapic_pin)) { + LOG_HPET("IRQ dropped on HPET comp 1, pin %d\n", ioapic_pin); + } + } + + assert(!timer_n_in_periodic_mode(1)); + } else if (ch == TIMER_DRV_CH_FOR_HPET_CH2) { + uint64_t main_counter_val = counter_value_in_terms_of_timer(2); + bug_check_irq_at_correct_time(2, main_counter_val); + if (timer_n_can_interrupt(2)) { + int ioapic_pin = get_timer_n_ioapic_pin(2); + if (!inject_ioapic_irq(0, ioapic_pin)) { + LOG_HPET("IRQ dropped on HPET comp 2, pin %d\n", ioapic_pin); + } + } + + assert(!timer_n_in_periodic_mode(2)); + } +} + +bool hpet_maintenance(uint8_t comparator) +{ + if (!counter_on()) { + return true; + } + + // @billn sus + assert(timer_n_irq_edge_triggered(0)); + assert(timer_n_irq_edge_triggered(1)); + assert(timer_n_irq_edge_triggered(2)); + + if (comparator == 0) { + uint64_t main_counter_val = counter_value_in_terms_of_timer(0); + + if (timer_n_in_periodic_mode(0) && hpet_regs.comparators[0].comparator_increment == 0) { + // Halted + return true; + } + + // No need to update the comparator, as the guest's first write to comparator is already + // timestamp + time out. + + if (timer_n_forced_32(0)) { + hpet_regs.comparators[0].current_comparator &= 0xffffffff; + } + + LOG_HPET("hpet_maintenance(): timer 0 can irq %d, is periodic %d, is 32b %d\n", timer_n_can_interrupt(0), + timer_n_in_periodic_mode(0), timer_n_forced_32(0)); + LOG_HPET("timer 0: counter < cur comp | 0x%lx < 0x%lx\n", main_counter_val, + hpet_regs.comparators[0].current_comparator); + + uint64_t delay_ns = timer_n_compute_timeout_ns(0, main_counter_val); + + if (delay_ns) { + LOG_HPET("HPET timeout requested, delay ns = %u, is periodic %d\n", delay_ns, timer_n_in_periodic_mode(0)); + LOG_HPET("... is edge triggered %u, ioapic pin %d\n", timer_n_irq_edge_triggered(0), + get_timer_n_ioapic_pin(0)); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_HPET_CH0, delay_ns); + hpet_regs.comparators[0].armed_comparator = hpet_regs.comparators[0].current_comparator; + } + } + + if (comparator == 1) { + uint64_t main_counter_val = counter_value_in_terms_of_timer(1); + + LOG_HPET("hpet_maintenance(): timer 1 can irq %d, is periodic %d, is 32b %d\n", timer_n_can_interrupt(1), + timer_n_in_periodic_mode(1), timer_n_forced_32(1)); + uint64_t delay_ns = timer_n_compute_timeout_ns(1, main_counter_val); + if (delay_ns) { + LOG_HPET("HPET timeout requested, delay ns = %u, is periodic %d\n", delay_ns, timer_n_in_periodic_mode(1)); + LOG_HPET("... is edge triggered %u, ioapic pin %d\n", timer_n_irq_edge_triggered(1), + get_timer_n_ioapic_pin(1)); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_HPET_CH1, delay_ns); + hpet_regs.comparators[1].armed_comparator = hpet_regs.comparators[1].current_comparator; + } + } + + if (comparator == 2) { + uint64_t main_counter_val = counter_value_in_terms_of_timer(2); + + LOG_HPET("hpet_maintenance(): timer 2 can irq %d, is periodic %d, is 32b %d\n", timer_n_can_interrupt(2), + timer_n_in_periodic_mode(2), timer_n_forced_32(2)); + uint64_t delay_ns = timer_n_compute_timeout_ns(2, main_counter_val); + if (delay_ns) { + LOG_HPET("HPET timeout requested, delay ns = %u, is periodic %d\n", delay_ns, timer_n_in_periodic_mode(2)); + LOG_HPET("... is edge triggered %u, ioapic pin %d\n", timer_n_irq_edge_triggered(2), + get_timer_n_ioapic_pin(2)); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_HPET_CH2, delay_ns); + hpet_regs.comparators[2].armed_comparator = hpet_regs.comparators[2].current_comparator; + } + } + + return true; +} + +static bool hpet_fault_on_config(uint64_t offset, uint8_t *comparator) +{ + if (offset == timer_n_config_reg_mmio_off(0)) { + *comparator = 0; + } else if (offset == timer_n_config_reg_mmio_off(1)) { + *comparator = 1; + } else if (offset == timer_n_config_reg_mmio_off(2)) { + *comparator = 2; + } else { + return false; + } + + return true; +} + +static bool hpet_fault_on_comparator(uint64_t offset, uint8_t *comparator) +{ + if (offset == timer_n_comparator_mmio_off(0)) { + *comparator = 0; + } else if (offset == timer_n_comparator_mmio_off(1)) { + *comparator = 1; + } else if (offset == timer_n_comparator_mmio_off(2)) { + *comparator = 2; + } else { + return false; + } + + return true; +} + +static bool hpet_fault_handle_config_read(uint8_t comparator, uint64_t *data, decoded_instruction_ret_t decoded_ins) +{ + assert(comparator <= 2); + if (mem_access_width_to_bytes(decoded_ins) == 4) { + *data = hpet_regs.comparators[comparator].config & 0xffffffff; + } else if (mem_access_width_to_bytes(decoded_ins) == 8) { + *data = hpet_regs.comparators[comparator].config; + } else { + LOG_VMM_ERR("Unsupported access width on HPET config register, comparator 0x%x\n", comparator); + return false; + } + + return true; +} + +static bool hpet_fault_handle_comparator_read(uint8_t comparator, uint64_t *data, decoded_instruction_ret_t decoded_ins) +{ + assert(comparator <= 2); + if (mem_access_width_to_bytes(decoded_ins) == 4) { + *data = hpet_regs.comparators[comparator].current_comparator & 0xffffffff; + } else if (mem_access_width_to_bytes(decoded_ins) == 8) { + *data = hpet_regs.comparators[comparator].current_comparator; + } else { + LOG_VMM_ERR("Unsupported access width on HPET comparator register, comparator 0x%x\n", comparator); + return false; + } + + return true; +} + +static bool hpet_fault_handle_config_write(uint8_t comparator, uint64_t data, decoded_instruction_ret_t decoded_ins) +{ + assert(comparator <= 2); + bool periodic_old = timer_n_in_periodic_mode(comparator); + + struct comparator_regs *regs = &hpet_regs.comparators[comparator]; + // uint64_t reg_old = regs->config; + + if (mem_access_width_to_bytes(decoded_ins) == 4) { + uint64_t curr_hi = (regs->config >> 32) << 32; + uint64_t new_low = data & 0xffffffff; + regs->config = curr_hi | new_low; + } else if (mem_access_width_to_bytes(decoded_ins) == 8) { + regs->config = data; + } else { + LOG_VMM_ERR("Unsupported access width on HPET comparator 0x%x\n", comparator); + return false; + } + + LOG_HPET("comp %d write %lx, old 0x%lx\n", comparator, data, reg_old); + + regs->config |= regs->config_mask; + + bool periodic_new = timer_n_in_periodic_mode(comparator); + + if (periodic_old && !periodic_new) { + assert(comparator == 0); + LOG_HPET("timer 0 periodic off!\n"); + } + + return true; +} + +static bool hpet_fault_handle_comparator_write(uint8_t comparator, uint64_t data, decoded_instruction_ret_t decoded_ins) +{ + assert(comparator <= 2); + + struct comparator_regs *regs = &hpet_regs.comparators[comparator]; + if (timer_n_in_periodic_mode(comparator)) { + // only first comparator expected to be periodic. + assert(comparator == 0); + + if (regs->config & Tn_VAL_SET_CNF) { + // writing expiry + regs->current_comparator = data; + regs->config &= ~Tn_VAL_SET_CNF; + return hpet_maintenance(comparator); + } else { + // writing the increment + regs->comparator_increment = data; + return true; + } + } else { + regs->current_comparator = data; + regs->comparator_increment = 0; + return hpet_maintenance(comparator); + } +} + +bool hpet_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, + decoded_instruction_ret_t decoded_ins) +{ + // if (ept_fault_is_read(qualification)) { + // assert(decoded_ins.type == INSTRUCTION_MEMORY); + // LOG_HPET("handling HPET read at offset 0x%lx, acc width %d bytes, reg idx %d\n", offset, + // mem_access_width_to_bytes(decoded_ins), decoded_ins.decoded.memory_instruction.target_reg); + // } else if (ept_fault_is_write(qualification)) { + // uint64_t data; + // assert(mem_write_get_data(decoded_ins, qualification, vctx, &data)); + // LOG_HPET("handling HPET write at offset 0x%lx, value 0x%x\n", offset, data); + // } + + // vcpu_print_regs(0); + + uint8_t comparator; + if (ept_fault_is_read(qualification)) { + uint64_t data; + if (offset == GENERAL_CAP_REG_MMIO_OFF) { + if (mem_access_width_to_bytes(decoded_ins) == 4) { + data = hpet_regs.general_capabilities & 0xffffffff; + } else if (mem_access_width_to_bytes(decoded_ins) == 8) { + data = hpet_regs.general_capabilities; + } else { + LOG_VMM_ERR("Unsupported access width on HPET offset 0x%x\n", offset); + return false; + } + + } else if (offset == GENERAL_CAP_REG_HIGH_MMIO_OFF) { + if (mem_access_width_to_bytes(decoded_ins) == 4) { + data = hpet_regs.general_capabilities >> 32; + } else { + LOG_VMM_ERR("Unsupported access width on HPET offset 0x%x\n", offset); + return false; + } + + } else if (offset == GENERAL_CONFIG_REG_MMIO_OFF) { + data = hpet_regs.general_config; + + } else if (offset == MAIN_COUNTER_VALUE_MMIO_OFF) { + if (mem_access_width_to_bytes(decoded_ins) == 4) { + data = main_counter_value() & 0xffffffff; + } else if (mem_access_width_to_bytes(decoded_ins) == 8) { + data = main_counter_value(); + } else { + LOG_VMM_ERR("Unsupported access width on HPET offset 0x%x\n", offset); + return false; + } + + } else if (offset == MAIN_COUNTER_VALUE_HIGH_MMIO_OFF) { + data = main_counter_value() >> 32; + + } else if (hpet_fault_on_config(offset, &comparator)) { + return hpet_fault_handle_config_read(comparator, &data, decoded_ins); + } else if (hpet_fault_on_comparator(offset, &comparator)) { + return hpet_fault_handle_comparator_read(comparator, &data, decoded_ins); + } else { + LOG_VMM_ERR("Reading unknown HPET register offset 0x%x\n", offset); + return false; + } + assert(mem_read_set_data(decoded_ins, qualification, vctx, data)); + } else { + uint64_t data; + assert(mem_write_get_data(decoded_ins, qualification, vctx, &data)); + + if (offset == GENERAL_CONFIG_REG_MMIO_OFF) { + uint64_t old_config = hpet_regs.general_config; + + if (mem_access_width_to_bytes(decoded_ins) == 4) { + uint64_t curr_hi = (hpet_regs.general_config >> 32) << 32; + uint64_t new_low = data & 0xffffffff; + hpet_regs.general_config = curr_hi | new_low; + } else if (mem_access_width_to_bytes(decoded_ins) == 8) { + hpet_regs.general_config = data; + } else { + LOG_VMM_ERR("Unsupported access width on HPET offset 0x%x\n", offset); + return false; + } + + if (!(old_config & ENABLE_CNF) && hpet_regs.general_config & ENABLE_CNF) { + // Restarts the timers if the main counter have been restarted + reset_main_counter(); + LOG_HPET("main counter restart!\n"); + hpet_maintenance(0); + hpet_maintenance(1); + hpet_maintenance(2); + } else if ((old_config & ENABLE_CNF) && !(hpet_regs.general_config & ENABLE_CNF)) { + hpet_frozen_counter = main_counter_value(); + } + + } else if (offset == MAIN_COUNTER_VALUE_MMIO_OFF || offset == MAIN_COUNTER_VALUE_HIGH_MMIO_OFF) { + reset_main_counter(); + } else if (hpet_fault_on_config(offset, &comparator)) { + return hpet_fault_handle_config_write(comparator, data, decoded_ins); + } else if (hpet_fault_on_comparator(offset, &comparator)) { + return hpet_fault_handle_comparator_write(comparator, data, decoded_ins); + } else { + LOG_VMM_ERR("Writing unknown HPET register offset 0x%x\n", offset); + return false; + } + } + + return true; +} diff --git a/src/arch/x86_64/instruction.c b/src/arch/x86_64/instruction.c new file mode 100644 index 000000000..997dc5e42 --- /dev/null +++ b/src/arch/x86_64/instruction.c @@ -0,0 +1,409 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// https://wiki.osdev.org/X86-64_Instruction_Encoding + +// https://c9x.me/x86/html/file_module_x86_id_176.html +#define NUM_MOV_OPCODES 4 +#define OPCODE_MOV_BYTE_TO_MEM 0x88 +#define OPCODE_MOV_WORD_TO_MEM 0x89 +#define OPCODE_MOV_BYTE_FROM_MEM 0x8a +#define OPCODE_MOV_WORD_FROM_MEM 0x8b +static uint8_t mov_opcodes[NUM_MOV_OPCODES] = { OPCODE_MOV_BYTE_TO_MEM, OPCODE_MOV_WORD_TO_MEM, + OPCODE_MOV_BYTE_FROM_MEM, OPCODE_MOV_WORD_FROM_MEM }; + +#define NUM_MOV_IMM_OPCODES 1 +#define OPCODE_MOV_IMM_WORD_TO_MEM 0xc7 +static uint8_t mov_imm_opcodes[NUM_MOV_IMM_OPCODES] = { OPCODE_MOV_IMM_WORD_TO_MEM }; + +static uint8_t opcode_movzx_byte_from_mem[2] = { 0x0f, 0xb6 }; +static uint8_t opcode_movzx_word_from_mem[2] = { 0x0f, 0xb7 }; + +static int access_width_decode(memory_access_width_t access_width) +{ + switch (access_width) { + case BYTE_ACCESS_WIDTH: + return 1; + case WORD_ACCESS_WIDTH: + return 2; + case DWORD_ACCESS_WIDTH: + return 4; + case QWORD_ACCESS_WIDTH: + return 8; + default: + LOG_VMM_ERR("access_width_decode() unknown access width %d\n", access_width); + return 0; + } +} + +int mem_access_width_to_bytes(decoded_instruction_ret_t decoded_ins) +{ + int access_width_bytes; + switch (decoded_ins.type) { + case INSTRUCTION_MEMORY: + access_width_bytes = access_width_decode(decoded_ins.decoded.memory_instruction.access_width); + break; + case INSTRUCTION_WRITE_IMM: + access_width_bytes = access_width_decode(decoded_ins.decoded.write_imm_instruction.access_width); + break; + default: + access_width_bytes = 0; + LOG_VMM_ERR("mem_access_width_to_bytes() not a memory access instruction\n"); + break; + } + return access_width_bytes; +} + +bool mem_write_get_data(decoded_instruction_ret_t decoded_ins, size_t ept_fault_qualification, seL4_VCPUContext *vctx, + uint64_t *ret) +{ + uint64_t *vctx_raw = (uint64_t *)vctx; + bool success = true; + + int access_width_bytes = mem_access_width_to_bytes(decoded_ins); + assert(access_width_bytes != 0); + assert(access_width_bytes <= 8); + + switch (decoded_ins.type) { + case INSTRUCTION_MEMORY: + if (ept_fault_is_read(ept_fault_qualification)) { + LOG_VMM_ERR("mem_write_get_data() got a read fault\n"); + success = false; + } else { + *ret = vctx_raw[decoded_ins.decoded.memory_instruction.target_reg]; + } + break; + case INSTRUCTION_WRITE_IMM: + assert(ept_fault_is_write(ept_fault_qualification)); + *ret = decoded_ins.decoded.write_imm_instruction.value; + break; + default: + LOG_VMM_ERR("mem_write_get_data() not a memory access instruction\n"); + return false; + } + + switch (access_width_bytes) { + case 1: + *ret &= 0xff; + break; + case 2: + *ret &= 0xffff; + break; + case 4: + *ret &= 0xffffffff; + break; + } + + return success; +} + +bool mem_read_set_data(decoded_instruction_ret_t decoded_ins, size_t ept_fault_qualification, seL4_VCPUContext *vctx, + uint64_t data) +{ + if (ept_fault_is_write(ept_fault_qualification)) { + LOG_VMM_ERR("mem_read_set_data() got a write fault\n"); + return false; + } + if (decoded_ins.type != INSTRUCTION_MEMORY) { + LOG_VMM_ERR("mem_read_set_data() not a memory access instruction\n"); + return false; + } + + uint64_t *vctx_raw = (uint64_t *)vctx; + vctx_raw[decoded_ins.decoded.memory_instruction.target_reg] = data; + return true; +} + +static register_idx_t modrm_reg_to_vctx_idx(uint8_t reg, bool rex_r) +{ + // the REX.R prefix will expand the register index to be 4-bits wide + uint8_t idx = (reg & 0x7) | (rex_r ? 0x8 : 0); + + switch (idx) { + case 0: + return RAX_IDX; + case 1: + return RCX_IDX; + case 2: + return RDX_IDX; + case 3: + return RBX_IDX; + case 5: + return RBP_IDX; + case 6: + return RSI_IDX; + case 7: + return RDI_IDX; + case 8: + return R8_IDX; + case 9: + return R9_IDX; + case 10: + return R10_IDX; + case 11: + return R11_IDX; + case 12: + return R12_IDX; + case 13: + return R13_IDX; + case 14: + return R14_IDX; + case 15: + return R15_IDX; + default: + LOG_VMM_ERR("unknown register idx: 0x%x, reg: 0x%x, REX.R: %d\n", idx, reg, rex_r); + assert(false); + } + + return -1; +} + +static char *vctx_idx_to_name(int vctx_idx) +{ + switch (vctx_idx) { + case RAX_IDX: + return "rax"; + case RBX_IDX: + return "rbx"; + case RCX_IDX: + return "rcx"; + case RDX_IDX: + return "rdx"; + case RSI_IDX: + return "rsi"; + case RDI_IDX: + return "rdi"; + case RBP_IDX: + return "rbp"; + case R8_IDX: + return "r8"; + case R9_IDX: + return "r9"; + case R10_IDX: + return "r10"; + case R11_IDX: + return "r11"; + case R12_IDX: + return "r12"; + case R13_IDX: + return "r13"; + case R14_IDX: + return "r14"; + case R15_IDX: + return "r15"; + default: + assert(false); + return ""; + } +} + +void debug_print_instruction(decoded_instruction_ret_t decode_result) +{ + assert(decode_result.raw_len < X86_MAX_INSTRUCTION_LENGTH); + + LOG_VMM("debug_print_instruction(): decoder result:\n"); + LOG_VMM("instruction length: %d\n", decode_result.raw_len); + LOG_VMM("raw instruction:\n"); + for (int i = 0; i < decode_result.raw_len; i++) { + LOG_VMM("0x%hhx\n", decode_result.raw[i]); + } + + switch (decode_result.type) { + case INSTRUCTION_DECODE_FAIL: + LOG_VMM("type: failed to decode\n"); + break; + + case INSTRUCTION_WRITE_IMM: + LOG_VMM("type: write to memory from immediate\n"); + LOG_VMM("immediate: 0x%lx\n", decode_result.decoded.write_imm_instruction.value); + LOG_VMM("access width bytes: %d\n", mem_access_width_to_bytes(decode_result)); + break; + + case INSTRUCTION_MEMORY: + LOG_VMM("type: memory access\n"); + LOG_VMM("zero extend: %d\n", decode_result.decoded.memory_instruction.zero_extend); + LOG_VMM("target reg: %s\n", vctx_idx_to_name(decode_result.decoded.memory_instruction.target_reg)); + LOG_VMM("access width bytes: %d\n", mem_access_width_to_bytes(decode_result)); + break; + + default: + LOG_VMM("type: unknown!\n"); + break; + } +} + +decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4_Word instruction_len) +{ + uint8_t instruction_buf[X86_MAX_INSTRUCTION_LENGTH]; + memset(instruction_buf, 0, X86_MAX_INSTRUCTION_LENGTH); + + uint64_t rip_gpa; + uint64_t bytes_remaining; + assert(gva_to_gpa(vcpu_id, rip, &rip_gpa, &bytes_remaining)); + + // @billn fix lazyness + assert(bytes_remaining >= instruction_len); + + assert(instruction_len <= X86_MAX_INSTRUCTION_LENGTH); + memcpy(instruction_buf, gpa_to_vaddr(rip_gpa), instruction_len); + + // @billn I really think something more "industrial grade" should be used for a job like this. + // Such as https://github.com/zyantific/zydis which is no-malloc and no-libc, but it uses cmake...yuck + // But then we introduce a dependency... + decoded_instruction_ret_t ret = { .type = INSTRUCTION_DECODE_FAIL, .decoded = {} }; + memcpy(&ret.raw, gpa_to_vaddr(rip_gpa), instruction_len); + ret.raw_len = instruction_len; + + bool opcode_valid = false; + int parsed_byte = 0; + bool rex_w = false; // 64-bit operand size + bool rex_r = false; // 4-bit operand, rather than 3-bit + // bool rex_x = false; // 4-bit SIB.index + // bool rex_b = false; // 4-bit MODRM.rm field or the SIB.base field + bool opd_size_override = false; + + for (int i = 0; i < instruction_len; i++) { + // scan for REX byte, which is always 0b0100WRXB + if (instruction_buf[parsed_byte] >> 4 == 4) { + uint8_t rex_byte = instruction_buf[parsed_byte]; + parsed_byte += 1; + + rex_w = (rex_byte & BIT(3)) != 0; + rex_r = (rex_byte & BIT(2)) != 0; + // rex_x = (rex_byte & BIT(1)) != 0; + // rex_b = (rex_byte & BIT(0)) != 0; + } + + // scan for the "operand-size override" prefix, which switch the operand size + // from 32 to 16 bits, though the REX prefix have more precendence + if (instruction_buf[parsed_byte] == 0x66) { + opd_size_override = true; + parsed_byte += 1; + } + } + + // match the opcode against a list of known opcodes that we provide decoding logic for. + // An opcode can be multi-bytes, first match for 1 byte opcode + for (int i = 0; i < NUM_MOV_OPCODES; i++) { + if (instruction_buf[parsed_byte] == mov_opcodes[i]) { + opcode_valid = true; + uint8_t opcode = instruction_buf[parsed_byte]; + + // An opcode byte is followed by a ModR/M byte to encode src/dest register. + uint8_t modrm = instruction_buf[parsed_byte + 1]; + // uint8_t mod = modrm >> 6; + uint8_t reg = (modrm >> 3) & 0x7; + // uint8_t rm = modrm & 0x7; + + ret.type = INSTRUCTION_MEMORY; + if (rex_w) { + ret.decoded.memory_instruction.access_width = QWORD_ACCESS_WIDTH; + } else { + switch (opcode) { + case OPCODE_MOV_BYTE_TO_MEM: + case OPCODE_MOV_BYTE_FROM_MEM: + ret.decoded.memory_instruction.access_width = BYTE_ACCESS_WIDTH; + break; + case OPCODE_MOV_WORD_TO_MEM: + case OPCODE_MOV_WORD_FROM_MEM: + if (opd_size_override) { + ret.decoded.memory_instruction.access_width = WORD_ACCESS_WIDTH; + } else { + ret.decoded.memory_instruction.access_width = DWORD_ACCESS_WIDTH; + } + break; + default: + LOG_VMM_ERR("internal bug: unhandled 1 byte mov opcode 0x%x\n", opcode); + assert(false); + break; + } + } + ret.decoded.memory_instruction.zero_extend = false; + ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); + + break; + } + } + + // no match, now try the 2 bytes movzx opcodes + if (instruction_len - parsed_byte >= 3 && !opcode_valid) { + if (instruction_buf[parsed_byte] == opcode_movzx_byte_from_mem[0] + && instruction_buf[parsed_byte + 1] == opcode_movzx_byte_from_mem[1]) { + opcode_valid = true; + uint8_t modrm = instruction_buf[parsed_byte + 2]; + uint8_t reg = (modrm >> 3) & 0x7; + ret.type = INSTRUCTION_MEMORY; + ret.decoded.memory_instruction.access_width = BYTE_ACCESS_WIDTH; + ret.decoded.memory_instruction.zero_extend = true; + ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); + } else if (instruction_buf[parsed_byte] == opcode_movzx_word_from_mem[0] + && instruction_buf[parsed_byte + 1] == opcode_movzx_word_from_mem[1]) { + opcode_valid = true; + uint8_t modrm = instruction_buf[parsed_byte + 2]; + uint8_t reg = (modrm >> 3) & 0x7; + ret.type = INSTRUCTION_MEMORY; + ret.decoded.memory_instruction.access_width = WORD_ACCESS_WIDTH; + ret.decoded.memory_instruction.zero_extend = true; + ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); + } + } + + // no match, try the mov immediate instruciton + for (int i = 0; i < NUM_MOV_IMM_OPCODES; i++) { + if (instruction_buf[parsed_byte] == mov_imm_opcodes[i]) { + opcode_valid = true; + // TODO: handle unused variable + // uint8_t opcode = instruction_buf[parsed_byte]; + + assert(guest_in_64_bits()); + + ret.type = INSTRUCTION_WRITE_IMM; + if (rex_w) { + ret.decoded.write_imm_instruction.access_width = QWORD_ACCESS_WIDTH; + } else { + if (opd_size_override) { + ret.decoded.write_imm_instruction.access_width = WORD_ACCESS_WIDTH; + } else { + ret.decoded.write_imm_instruction.access_width = DWORD_ACCESS_WIDTH; + } + } + + // Not going to bother with checking for mod r/m or sib bytes as the CPU already decoded them for us + // just skipping to the immediate + int immediate_bytes = mem_access_width_to_bytes(ret); + assert(instruction_len > immediate_bytes); + memcpy(&(ret.decoded.write_imm_instruction.value), &instruction_buf[instruction_len - immediate_bytes], + immediate_bytes); + + break; + } + } + + if (!opcode_valid) { + LOG_VMM_ERR("uh-oh can't decode instruction, bail\n"); + for (int i = 0; i < instruction_len; i++) { + LOG_VMM_ERR("ins byte 0x%x\n", instruction_buf[i]); + } + vcpu_print_regs(0); + assert(opcode_valid); + } + + // LOG_VMM("raw instruction:\n"); + // for (int i = 0; i < instruction_len; i++) { + // LOG_VMM("[%d]: 0x%x\n", i, instruction_buf[i]); + // } + return ret; +} \ No newline at end of file diff --git a/src/arch/x86_64/ioports.c b/src/arch/x86_64/ioports.c new file mode 100644 index 000000000..b111a0769 --- /dev/null +++ b/src/arch/x86_64/ioports.c @@ -0,0 +1,247 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern uint64_t primary_ata_cmd_pio_id; +extern uint64_t primary_ata_cmd_pio_addr; + +extern uint64_t primary_ata_ctrl_pio_id; +extern uint64_t primary_ata_ctrl_pio_addr; + +extern uint64_t second_ata_cmd_pio_id; +extern uint64_t second_ata_cmd_pio_addr; + +extern uint64_t second_ata_ctrl_pio_id; +extern uint64_t second_ata_ctrl_pio_addr; + +extern struct pci_bus pci_bus_state; + +// TODO: hack +#define TIMER_DRV_CH_FOR_LAPIC 11 + +int ioports_access_width_to_bytes(ioport_access_width_t access_width) +{ + switch (access_width) { + case IOPORT_BYTE_ACCESS_QUAL: + return 1; + case IOPORT_WORD_ACCESS_QUAL: + return 2; + case IOPORT_DWORD_ACCESS_QUAL: + return 4; + default: + return 0; + } +} + +int emulate_ioport_string_write(seL4_VCPUContext *vctx, char *dest, size_t data_len, bool is_rep, + ioport_access_width_t access_width) +{ + int data_index = 0; + int max_iterations = 1; + uint64_t eflags = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RFLAGS); + + if (is_rep) { + max_iterations = vctx->ecx; + } + + int iteration = 0; + for (; iteration < max_iterations && data_index < data_len; iteration++) { + uint64_t src_gpa; + uint64_t bytes_to_page_boundary; + assert(gva_to_gpa(0, vctx->esi, &src_gpa, &bytes_to_page_boundary)); + char *src = gpa_to_vaddr(src_gpa); + + assert(bytes_to_page_boundary >= ioports_access_width_to_bytes(access_width)); + + memcpy(&dest[data_index], src, ioports_access_width_to_bytes(access_width)); + + if (eflags & BIT(10)) { + vctx->esi -= ioports_access_width_to_bytes(access_width); + } else { + vctx->esi += ioports_access_width_to_bytes(access_width); + } + data_index += ioports_access_width_to_bytes(access_width); + } + + return ioports_access_width_to_bytes(access_width) * data_index; +} + +int emulate_ioport_string_read(seL4_VCPUContext *vctx, char *data, size_t data_len, bool is_rep, + ioport_access_width_t access_width) +{ + int data_index = 0; + int max_iterations = 1; + uint64_t eflags = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RFLAGS); + + if (is_rep) { + max_iterations = vctx->ecx; + } + + int iteration = 0; + for (; iteration < max_iterations && data_index < data_len; iteration++) { + uint64_t dest_gpa; + uint64_t bytes_to_page_boundary; + assert(gva_to_gpa(0, vctx->edi, &dest_gpa, &bytes_to_page_boundary)); + char *dest = gpa_to_vaddr(dest_gpa); + + assert(bytes_to_page_boundary >= ioports_access_width_to_bytes(access_width)); + + memcpy(dest, &data[data_index], ioports_access_width_to_bytes(access_width)); + + if (eflags & BIT(10)) { + vctx->edi -= ioports_access_width_to_bytes(access_width); + } else { + vctx->edi += ioports_access_width_to_bytes(access_width); + } + data_index += ioports_access_width_to_bytes(access_width); + } + + return ioports_access_width_to_bytes(access_width) * data_index; +} + +bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) +{ + uint64_t is_read = f_qualification & BIT(3); + uint64_t is_string = f_qualification & BIT(4); + uint64_t is_rep = f_qualification & BIT(5); + uint16_t port_addr = (f_qualification >> 16) & 0xffff; + ioport_access_width_t access_width = (ioport_access_width_t)(f_qualification & 0x7); + + bool success = false; + + if (is_read) { + // prime the result + vctx->eax = 0; + } + + if (port_addr >= 0xC000 && port_addr < 0xCFFF) { + assert(!is_string); + if (is_read) { + // invalid read to simulate no device on pci bus + vctx->eax = 0xffffffff; + } + success = true; + } else if (port_addr == 0xA0 || port_addr == 0xA1 || port_addr == 0x20 || port_addr == 0x21 || port_addr == 0x4d1 + || port_addr == 0x4d0) { + assert(!is_string); + // PIC1/2 access + if (is_read) { + // invalid read + vctx->eax = 0xffffffff; + } + success = true; + } else if (port_addr == 0x70 || port_addr == 0x71) { + // cmos + assert(!is_string); + success = emulate_cmos_access(vctx, port_addr, is_read, access_width); + } else if (port_addr == 0x80) { + assert(!is_string); + // io port access delay, no-op + if (!is_read) { + success = true; + } + } else if (port_addr == 0x3f2) { + assert(!is_string); + // floppy disk, seems sus, when booting memtest in nixos, it will write IRQ enable to this register and hangs... + success = true; + + } else if (port_addr == 0x87 || (port_addr >= 0 && port_addr <= 0x1f)) { + assert(!is_string); + // dma controller + success = true; + + } else if (port_addr == 0x2f9) { + assert(!is_string); + // parallel port + success = true; + + } else if (port_addr == 0x3e9 || port_addr == 0x2e9) { + assert(!is_string); + // some sort of serial device + success = true; + + } else if (port_addr >= 0x60 && port_addr <= 0x64) { + assert(!is_string); + // PS2 controller + success = true; + } else if (port_addr >= 0xAF00 && port_addr <= 0xaf00 + 12) { + /* See https://www.qemu.org/docs/master/specs/acpi_cpu_hotplug.html for details. + * Basically we want to emulate QEMU_CPUHP_R_CMD_DATA2 so that the guest does not try to + * use modern CPU hot plugging functionality which invovles more emulation. + */ + if (port_addr == 0xAF00) { + vctx->eax = 0x1; + } + success = true; + } else if (port_addr == 0x92) { + // TODO: handle properly, I don't understand why UEFI is touching A20 gate register + assert(!is_string); + success = true; + } else if (port_addr >= 0x3f8 && port_addr <= 0x3f8 + 8) { + emulate_com(vctx, 0, port_addr - 0x3f8, is_read, is_rep, is_string, access_width); + success = true; + } else if (port_addr >= 0x2f8 && port_addr <= 0x2f8 + 8) { + emulate_com(vctx, 1, port_addr - 0x2f8, is_read, is_rep, is_string, access_width); + success = true; + } else if (port_addr >= 0x3e8 && port_addr <= 0x3e8 + 8) { + emulate_com(vctx, 2, port_addr - 0x3e8, is_read, is_rep, is_string, access_width); + success = true; + } else if (port_addr >= 0x2ef && port_addr <= 0x2ef + 8) { + emulate_com(vctx, 3, port_addr - 0x2ef, is_read, is_rep, is_string, access_width); + success = true; + } else if (port_addr >= 0x2e8 && port_addr <= 0x2e8 + 8) { + emulate_com(vctx, 4, port_addr - 0x2e8, is_read, is_rep, is_string, access_width); + success = true; + } else if (port_addr == 0xb004) { + vctx->eax = 0; + success = true; + } else if (port_addr == 0x5658 || port_addr == 0x5659) { + // vmware backdoor + // https://wiki.osdev.org/VMware_tools + success = true; + } else if (port_addr == 0x4e || port_addr == 0x4f || port_addr == 0x2e || port_addr == 0x2f + || (port_addr >= 0xc80 && port_addr <= 0xc84) || (port_addr >= 0x1c80 && port_addr <= 0x1c84) + || (port_addr >= 0x2c80 && port_addr <= 0x2c84) || (port_addr >= 0x3c80 && port_addr <= 0x3c84) + || (port_addr >= 0x4c80 && port_addr <= 0x4c84) || (port_addr >= 0x5c80 && port_addr <= 0x5c84) + || (port_addr >= 0x6c80 && port_addr <= 0x6c84) || (port_addr >= 0x7c80 && port_addr <= 0x7c84) + || (port_addr >= 0x8c80 && port_addr <= 0x8c84) || (port_addr >= 0x9c80 && port_addr <= 0x9c84) + || (port_addr >= 0xac80 && port_addr <= 0xac84) || (port_addr >= 0xbc80 && port_addr <= 0xbc84) + || (port_addr >= 0xcc80 && port_addr <= 0xcc84) || (port_addr >= 0xdc80 && port_addr <= 0xdc84) + || (port_addr >= 0xec80 && port_addr <= 0xec84) || (port_addr >= 0xfc80 && port_addr <= 0xfc84)) { + if (is_read) { + vctx->eax = 0; + } + success = true; + } else if (port_addr == 0x3BE || port_addr == 0x7BE || port_addr == 0x3BD || port_addr == 0x3BC + || port_addr == 0x37A || port_addr == 0x77A || port_addr == 0x379 || port_addr == 0x378 + || port_addr == 0x27A || port_addr == 0x67a || port_addr == 0x279 || port_addr == 0x278) { + // parallel/printer port + if (is_read) { + vctx->eax = 0; + } + success = true; + } else { + if (is_read) { + LOG_VMM_ERR("unhandled io port read 0x%x\n", port_addr); + } else { + LOG_VMM_ERR("unhandled io port write 0x%x (value: 0x%lx)\n", port_addr, vctx->eax); + } + } + + return success; +} \ No newline at end of file diff --git a/src/arch/x86_64/linux.c b/src/arch/x86_64/linux.c new file mode 100644 index 000000000..c71abb40b --- /dev/null +++ b/src/arch/x86_64/linux.c @@ -0,0 +1,291 @@ + +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Documents referenced: + * [1] https://www.kernel.org/doc/html/v6.1/x86/boot.html + * [2] https://www.kernel.org/doc/html/v6.1/x86/zero-page.html + * [3] Linux: arch/x86/include/uapi/asm/e820.h + * [4] https://wiki.osdev.org/Paging + * [5] Linux: arch/x86/include/uapi/asm/bootparam.h + */ + +#define MINIMUM_BOOT_PROT_MAJOR 2 +/* Minimum kernel 3.8, as we need: + * 1. relocatable kernel support, and + * 2. `xloadflags` field to assert that the kernel supports 64-bit entry + */ +#define MINIMUM_BOOT_PROT_MINOR 12 + +#define IMAGE_SETUP_HEADER_OFFSET 0x1f1 +#define HEADER_MAGIC 0x53726448 + +/* [5] */ +#define XLF_KERNEL_64 BIT(0) // Kernel have 64-bits entry + +#define E820_MAX_ENTRIES_ZEROPAGE 128 + +/* We do not have an assigned ID in the table of loader IDs, so we do 0xff. */ +#define SETUP_HDR_TYPE_OF_LOADER 0xff +#define SETUP_HDR_VGA_MODE_NORMAL 0xffff + +#define ZERO_PAGE_ACPI_RSDP_OFFSET 0x70 +#define ZERO_PAGE_E820_ENTRIES_OFFSET 0x1e8 +#define ZERO_PAGE_E820_TABLE_OFFSET 0x2d0 + +#define PAGE_SIZE_4K 0x1000 +#define PAGE_SIZE_2M 0x200000 + +#define RAM_START_GPA 0x0 +#define ZERO_PAGE_GPA 0x0 +#define CMDLINE_GPA 0x1000 +#define GDT_GPA 0x2000 +#define BZIMAGE_LOAD_GPA 0x100000 + +#define KERNEL_64_HANDOVER_OFFSET 0x200 + +/* [4] */ +#define PTE_PRESENT_BIT BIT(0) +#define PTE_RW_BIT BIT(1) +#define PTE_PS_BIT BIT(7) // 1 if point to a page instead of paging structure +#define PTE_ADDR_MASK (0xfffffffff000ull) // @billn check number of Fs + +// Assume 2MiB large page +static bool map_page(uintptr_t pml4_gpa, uintptr_t target_gpa, uintptr_t guest_ram_vaddr, uint64_t *n_pt_created) +{ + assert(target_gpa % PAGE_SIZE_2M == 0); + + uint16_t pml4_idx = (target_gpa >> (12 + 9 + 9 + 9)) & 0x1ff; + uint16_t pdpt_idx = (target_gpa >> (12 + 9 + 9)) & 0x1ff; + uint16_t pd_idx = (target_gpa >> (12 + 9)) & 0x1ff; + + // Check if PML4 pointer to PDPT is present, create PDPT obj and point to it if not. + uint64_t *pml4_entries = (uint64_t *)(guest_ram_vaddr + pml4_gpa); + uint64_t pml4_entry = pml4_entries[pml4_idx]; + uint64_t pdpt_gpa; + if (pml4_entry & PTE_PRESENT_BIT) { + pdpt_gpa = pml4_entry & PTE_ADDR_MASK; + } else { + pdpt_gpa = pml4_gpa - (PAGE_SIZE_4K * (*n_pt_created + 1)); + memset((void *)(guest_ram_vaddr + pdpt_gpa), 0, PAGE_SIZE_4K); + *n_pt_created = *n_pt_created + 1; + + pml4_entries[pml4_idx] = PTE_PRESENT_BIT | PTE_RW_BIT | (pdpt_gpa & PTE_ADDR_MASK); + } + + // Same thing, but PDPT -> PT + uint64_t *pdpt_entries = (uint64_t *)(guest_ram_vaddr + pdpt_gpa); + uint64_t pdpt_entry = pdpt_entries[pdpt_idx]; + uint64_t pd_gpa; + if (pdpt_entry & PTE_PRESENT_BIT) { + pd_gpa = pdpt_entry & PTE_ADDR_MASK; + } else { + pd_gpa = pml4_gpa - (PAGE_SIZE_4K * (*n_pt_created + 1)); + memset((void *)(guest_ram_vaddr + pd_gpa), 0, PAGE_SIZE_4K); + *n_pt_created = *n_pt_created + 1; + + pdpt_entries[pdpt_idx] = PTE_PRESENT_BIT | PTE_RW_BIT | (pd_gpa & PTE_ADDR_MASK); + } + + // Now PT -> Large page + uint64_t *pd_entries = (uint64_t *)(guest_ram_vaddr + pd_gpa); + uint64_t pd_entry = pd_entries[pd_idx]; + if (pd_entry & PTE_PRESENT_BIT) { + return false; + } else { + pd_entries[pd_idx] = PTE_PRESENT_BIT | PTE_RW_BIT | PTE_PS_BIT | (target_gpa & PTE_ADDR_MASK); + return true; + } +} + +// Create an initial identity page table, paging objects will grow "downwards" +// Returns GPA to the PML4 object. +// The contiguous range of memory used by all paging structures are written to pt_objs_start_gpa and pt_objs_end_gpa +// Not correct for SMP where each guest needs their own page table. +static uintptr_t build_initial_kernel_page_table(uintptr_t guest_ram_vaddr, size_t ram_size, + uint64_t ident_map_start_gpa, uint64_t ident_map_end_gpa, + uint64_t *pt_objs_start_gpa, uint64_t *pt_objs_end_gpa) +{ + assert(ram_size % PAGE_SIZE_4K == 0); + uint64_t n_pt_created = 0; + uintptr_t pml4_gpa = (RAM_START_GPA + ram_size) - PAGE_SIZE_4K; + n_pt_created += 1; + + memset((void *)(guest_ram_vaddr + pml4_gpa), 0, PAGE_SIZE_4K); + + int num_init_pages = ((ROUND_UP(ident_map_end_gpa, PAGE_SIZE_2M) - ROUND_DOWN(ident_map_start_gpa, PAGE_SIZE_2M))) + / PAGE_SIZE_2M; + uint64_t current_gpa = ROUND_DOWN(ident_map_start_gpa, PAGE_SIZE_2M); + for (int i = 0; i < num_init_pages; i += 1) { + uint64_t base_page_gpa = current_gpa + (i * PAGE_SIZE_2M); + assert(map_page(pml4_gpa, base_page_gpa, guest_ram_vaddr, &n_pt_created)); + } + + *pt_objs_start_gpa = pml4_gpa - ((n_pt_created - 1) * PAGE_SIZE_4K); + *pt_objs_end_gpa = pml4_gpa + PAGE_SIZE_4K; + return pml4_gpa; +} + +bool linux_setup_images(uintptr_t ram_start, size_t ram_size, uintptr_t kernel, size_t kernel_size, + uintptr_t initrd_src, size_t initrd_size, void *dsdt_blob, uint64_t dsdt_blob_size, + char *cmdline, linux_x86_setup_ret_t *ret) +{ + /* See [3] for details of operations done in this function. */ + + // @billn todo check that we got a bzImage and not something else. + + if (ram_size % PAGE_SIZE_4K) { + LOG_VMM_ERR("expected ram size to be page aligned, but got 0x%x\n", ram_size); + return false; + } + + LOG_VMM("Linux kernel size: %dMiB (%ld bytes)\n", kernel_size / 1024 / 1024, kernel_size); + + struct setup_header *setup_header_src = (struct setup_header *)((char *)kernel + IMAGE_SETUP_HEADER_OFFSET); + + /* Make a copy as we don't want to mutate the original image. */ + struct setup_header setup_header; + memcpy(&setup_header, setup_header_src, sizeof(struct setup_header)); + + if (setup_header.header != HEADER_MAGIC) { + LOG_VMM_ERR("invalid Linux kernel magic or boot protocol too old (< 2.0): expected magic 0x%x, got 0x%x\n", + HEADER_MAGIC, setup_header.header); + return false; + } + + uint16_t protocol_version = setup_header.version; + uint8_t protocol_version_major = protocol_version >> 8; + uint8_t protocol_version_minor = protocol_version & 0xff; + if (protocol_version_major < MINIMUM_BOOT_PROT_MAJOR || protocol_version_minor < MINIMUM_BOOT_PROT_MINOR) { + LOG_VMM_ERR("boot protocol too old (< %d.%d): got %d.%d\n", MINIMUM_BOOT_PROT_MAJOR, MINIMUM_BOOT_PROT_MINOR, + protocol_version_major, protocol_version_minor); + return false; + } + + LOG_VMM("Linux boot protocol %d.%d\n", protocol_version_major, protocol_version_minor); + + // @billn hack, assumes guest ram starts from 0 + uint64_t initrd_gpa = ram_size - 0x2000000; + LOG_VMM("Ramdisk GPA 0x%x, size 0x%x\n", initrd_gpa, initrd_size); + memcpy((void *)ram_start + initrd_gpa, (void *)initrd_src, initrd_size); + + uint16_t kernel_version_offset = setup_header.kernel_version; + if (kernel_version_offset != 0) { + char *kernel_version = (char *)(kernel + kernel_version_offset + 0x200); + LOG_VMM("Linux kernel version string: %s\n", kernel_version); + } + + /* Fill in bootloader "obligatory fields" then copy it into guest RAM. + * See "1.3. Details of Header Fields" of [1] + */ + setup_header.vid_mode = SETUP_HDR_VGA_MODE_NORMAL; + setup_header.type_of_loader = SETUP_HDR_TYPE_OF_LOADER; + setup_header.ramdisk_image = initrd_gpa; + setup_header.ramdisk_size = initrd_size; // @billn for now + setup_header.cmd_line_ptr = CMDLINE_GPA; + assert(strlen(cmdline) <= setup_header.cmdline_size); + strcpy((char *)(ram_start + CMDLINE_GPA), cmdline); + LOG_VMM("Linux command line: '%s'\n", (char *)(ram_start + CMDLINE_GPA)); + + if (!(setup_header.xloadflags & XLF_KERNEL_64)) { + LOG_VMM_ERR("Kernel must support the 64-bit entry point flag XLF_KERNEL_64\n"); + return false; + } + + uintptr_t kernel_load_gpa = BZIMAGE_LOAD_GPA; + /* See "1.10. Loading The Rest of The Kernel" of [1] */ + uint64_t setup_sects = setup_header.setup_sects; + if (setup_sects == 0) { + setup_sects = 4; + } + uint64_t setup_size = (setup_sects + 1) * 512; + + LOG_VMM("Linux load GPA 0x%x\n", kernel_load_gpa); + + /* Copy over the important things: kernel code and the "zero page" which contains `struct setup_header` */ + memcpy((void *)ram_start + kernel_load_gpa, (const void *)(kernel + setup_size), setup_header.syssize * 16); + memset((void *)ram_start + ZERO_PAGE_GPA, 0, PAGE_SIZE_4K); + memcpy((void *)ram_start + ZERO_PAGE_GPA + IMAGE_SETUP_HEADER_OFFSET, &setup_header, sizeof(struct setup_header)); + + /* Since we are booting into long mode, we must set up a minimal page table for Linux to start + * and read the configuration structures. It must covers the zero page, cmdline, GDT and kernel decompressor working set. */ + uint64_t kernel_entry_gpa = BZIMAGE_LOAD_GPA + KERNEL_64_HANDOVER_OFFSET; + uint64_t ident_map_start_gpa = MIN(ZERO_PAGE_GPA, kernel_entry_gpa); + uint64_t ident_map_end_gpa = ROUND_UP(kernel_entry_gpa + setup_header.init_size, PAGE_SIZE_2M); + /* Map in a bunch more page to prevent the decompressor from crashing, won't cost more memory as we only need 3 paging + * structures to map 1GiB worth of memory. */ + ident_map_end_gpa += PAGE_SIZE_2M * 50; + + LOG_VMM("Identity page table coverage GPA: [0x%x..0x%x)\n", ident_map_start_gpa, ident_map_end_gpa); + uint64_t pt_objs_start_gpa, pt_objs_end_gpa; + uintptr_t pml4_gpa = build_initial_kernel_page_table(ram_start, ram_size, ident_map_start_gpa, ident_map_end_gpa, + &pt_objs_start_gpa, &pt_objs_end_gpa); + LOG_VMM("Identity paging objects GPA: [0x%x..0x%x)\n", pt_objs_start_gpa, pt_objs_end_gpa); + + /* Now create the ACPI tables and get the RSDP. */ + uint64_t acpi_start_gpa, acpi_end_gpa; + /* Pass pt_objs_start_gpa as "ram_top" so that the ACPI tables live straight below the initial paging objects. */ + + // When the size of the DSDT crosses 255 bytes, it seens like the initial paging objects are overwritten, so we hack + // by leaving a page of room, TODO investigate. + uint64_t acpi_rsdp_gpa = acpi_build_all(ram_start, dsdt_blob, dsdt_blob_size, pt_objs_start_gpa - 0x1000, + &acpi_start_gpa, &acpi_end_gpa); + LOG_VMM("ACPI RSDP 0x%x, ACPI tables GPA: [0x%x..0x%x)\n", acpi_rsdp_gpa, acpi_start_gpa, acpi_end_gpa); + + assert(acpi_end_gpa < pt_objs_start_gpa); + + /* Now fill in important bits in the "zero page": the ACPI RDSP and E820 memory table. */ + uint64_t *acpi_rsdp = (uint64_t *)(ram_start + ZERO_PAGE_GPA + ZERO_PAGE_ACPI_RSDP_OFFSET); + *acpi_rsdp = acpi_rsdp_gpa; + + /* Fill out real RAM, ACPI reclaimable region and initial paging objects range. */ + uint8_t *e820_entries = (uint8_t *)(ram_start + ZERO_PAGE_GPA + ZERO_PAGE_E820_ENTRIES_OFFSET); + *e820_entries = 4; + struct boot_e820_entry *e820_table = (struct boot_e820_entry *)(ram_start + ZERO_PAGE_GPA + + ZERO_PAGE_E820_TABLE_OFFSET); + assert(*e820_entries <= E820_MAX_ENTRIES_ZEROPAGE); + e820_table[0] = (struct boot_e820_entry) { + .addr = pt_objs_start_gpa, + .size = pt_objs_end_gpa - pt_objs_start_gpa, + .type = E820_RESERVED, + }; + e820_table[1] = (struct boot_e820_entry) { + .addr = acpi_start_gpa, + .size = acpi_end_gpa - acpi_start_gpa, + .type = E820_ACPI, + }; + e820_table[2] = (struct boot_e820_entry) { + .addr = 0, + .size = acpi_start_gpa, + .type = E820_RAM, + }; + e820_table[3] = (struct boot_e820_entry) { + .addr = ECAM_GPA, + .size = ECAM_SIZE, + .type = E820_RESERVED, + }; + + /* Build GDT */ + uint64_t *gdt = (uint64_t *)(ram_start + GDT_GPA); + gdt[0] = 0; + gdt[1] = 0x00AF9A000000FFFFull; // @billn breakdown + gdt[2] = 0x00AF92000000FFFFull; + + ret->kernel_entry_gpa = kernel_entry_gpa; + ret->pml4_gpa = pml4_gpa; + ret->zero_page_gpa = ZERO_PAGE_GPA; + ret->gdt_gpa = GDT_GPA; + ret->gdt_limit = 24; // 8 * 3 entries + + return true; +} \ No newline at end of file diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c new file mode 100644 index 000000000..b7353f4b1 --- /dev/null +++ b/src/arch/x86_64/msr.c @@ -0,0 +1,212 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Table 2-2. IA-32 Architectural MSRs + +#define IA32_TIME_STAMP_COUNTER (0x10) +#define IA32_PLATFORM_ID (0x17) +#define IA32_SPEC_CTRL (0x48) +#define IA32_PRED_CMD (0x49) +#define IA32_PPIN_CTL (0x4e) +#define IA32_BIOS_UPDT_TRIG (0x79) +#define IA32_MKTME_KEYID_PARTITIONING (0x87) +#define IA32_BIOS_SIGN_ID (0x8b) +#define IA32_CORE_CAPABILITIES (0xcf) +#define IA32_MISC_ENABLE (0x1a0) +#define IA32_MCG_CAP (0x179) +#define IA32_XSS (0xda0) + +#define IA32_MTRRCAP (0xfe) +#define IA32_MTRR_DEF_TYPE (0x2ff) +#define IA32_PAT (0x277) +#define IA32_MCG_STATUS (0x17a) + +#define MSR_RAPL_POWER_UNIT (0x606) +#define MSR_PKG_ENERGY_STATUS (0x611) +#define MSR_PP0_ENERGY_STATUS (0x639) +#define MSR_DRAM_ENERGY_STATUS (0x619) +#define MSR_PP1_ENERGY_STATUS (0x641) +#define MSR_PLATFORM_ENERGY_COUNTER (0x64d) +#define MSR_PPERF (0x64e) +#define MSR_SMI_COUNT (0x34) +#define MSR_CORE_C3_RESIDENCY (0x3fc) +#define MSR_CORE_C6_RESIDENCY (0x3fd) +#define MSR_CORE_C7_RESIDENCY (0x3fe) +#define MSR_PKG_C2_RESIDENCY (0x60d) +#define MSR_PKG_C2_RESIDENCY_ALT (0x3f8) +#define MSR_PKG_C4_RESIDENCY (0x3f9) +#define MSR_PKG_C6_RESIDENCY (0x3fa) +// #define MSR_OS_MAILBOX_INTERFACE 0xB0 +// #define MSR_OS_MAILBOX_DATA 0xB1 + +// @billn seems to be some sort of fencing instruction control +// https://gruss.cc/files/msrtemplating.pdf +#define MSR_UNKNOWN1 (0xc0011029) + +#define IA32_APIC_BASE (0x1b) +#define IA32_FEATURE_CONTROL (0x3a) +#define MISC_FEATURE_ENABLES (0x140) +#define MSR_PLATFORM_INFO (0xce) + +#define MSR_TEST_CTRL (0x33) + +/* x86-64 specific MSRs */ +#define MSR_EFER 0xc0000080 /* extended feature register */ +#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */ +#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */ +#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */ +#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ +// #define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ +// #define MSR_GS_BASE 0xc0000101 /* 64bit GS base */ +// #define MSR_SHADOW_GS_BASE 0xc0000102 /* SwapGS GS shadow */ +// #define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */ + +static uint64_t misc_enable = 0; +static uint64_t mtrr_def_type = 0; +static uint64_t pat = 0; + +bool emulate_rdmsr(seL4_VCPUContext *vctx) +{ + uint64_t result = 0; + + switch (vctx->ecx) { + case MSR_EFER: { + result = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER); + break; + } + case IA32_TIME_STAMP_COUNTER: + result = __rdtsc(); + break; + case IA32_MISC_ENABLE: + result = misc_enable; + break; + case MSR_STAR: + case MSR_LSTAR: + case MSR_CSTAR: + case MSR_SYSCALL_MASK: + result = microkit_vcpu_x86_read_msr(GUEST_BOOT_VCPU_ID, vctx->ecx); + break; + case IA32_PLATFORM_ID: + case IA32_CORE_CAPABILITIES: + case IA32_MKTME_KEYID_PARTITIONING: + case IA32_BIOS_SIGN_ID: + case IA32_MCG_CAP: + case MSR_TEST_CTRL: + case MSR_RAPL_POWER_UNIT: + case MSR_PKG_ENERGY_STATUS: + case MSR_PP0_ENERGY_STATUS: + case MSR_PP1_ENERGY_STATUS: + case MSR_PLATFORM_ENERGY_COUNTER: + case MSR_DRAM_ENERGY_STATUS: + case MSR_PPERF: + case MSR_SMI_COUNT: + case MSR_CORE_C3_RESIDENCY: + case MSR_CORE_C6_RESIDENCY: + case MSR_CORE_C7_RESIDENCY: + case MSR_PKG_C2_RESIDENCY: + case MSR_PKG_C2_RESIDENCY_ALT: + case MSR_PKG_C4_RESIDENCY: + case MSR_PKG_C6_RESIDENCY: + case MISC_FEATURE_ENABLES: + case MSR_PLATFORM_INFO: + case MSR_UNKNOWN1: + case IA32_SPEC_CTRL: + case IA32_PRED_CMD: + case IA32_MTRRCAP: + case IA32_MCG_STATUS: + // case MSR_OS_MAILBOX_INTERFACE: + // case MSR_OS_MAILBOX_DATA: + case 0xc0010131: // @billn AMD SEV + case 0x150: // cpu voltage control? + break; + case IA32_APIC_BASE: + // Figure 11-5. IA32_APIC_BASE MSR (APIC_BASE_MSR in P6 Family) + // enable is boot cpu + result = LAPIC_GPA | BIT(11) | BIT(8); + break; + case IA32_FEATURE_CONTROL: + result = 1; // locked + break; + case IA32_PPIN_CTL: + result = 1; // locked + break; + case IA32_MTRR_DEF_TYPE: + result = mtrr_def_type; + break; + case IA32_PAT: + result = pat; + break; + default: + LOG_VMM_ERR("unknown rdmsr 0x%x\n", vctx->ecx); + return false; + } + + LOG_FAULT("handling RDMSR 0x%x, result 0x%lx\n", vctx->ecx, result); + + vctx->eax = result & 0xffffffff; + vctx->edx = (result >> 32) & 0xffffffff; + return true; +} + +bool emulate_wrmsr(seL4_VCPUContext *vctx) +{ + uint64_t value = (uint64_t)((vctx->edx & 0xffffffff) << 32) | (uint64_t)(vctx->eax & 0xffffffff); + + LOG_FAULT("handling WRMSR 0x%x, value 0x%lx\n", vctx->ecx, value); + + switch (vctx->ecx) { + case MSR_EFER: + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER, value); + break; + case IA32_BIOS_SIGN_ID: + case MISC_FEATURE_ENABLES: + case IA32_XSS: + case IA32_SPEC_CTRL: + case IA32_PRED_CMD: + case IA32_BIOS_UPDT_TRIG: + case IA32_MCG_STATUS: + // case MSR_OS_MAILBOX_INTERFACE: + // case MSR_OS_MAILBOX_DATA: + case 0x150: // cpu voltage control? + return true; + case MSR_TEST_CTRL: + case MSR_STAR: + case MSR_LSTAR: + case MSR_CSTAR: + case MSR_SYSCALL_MASK: + microkit_vcpu_x86_write_msr(GUEST_BOOT_VCPU_ID, vctx->ecx, value); + return true; + case IA32_MISC_ENABLE: + misc_enable = value; + return true; + case IA32_MTRR_DEF_TYPE: + mtrr_def_type = value; + break; + case IA32_PAT: + pat = value; + break; + // case MSR_KVM_WALL_CLOCK_NEW: + // case MSR_KVM_SYSTEM_TIME_NEW: + // pvclock_write_fault_handle(MSR_KVM_SYSTEM_TIME_NEW, value); + // break; + default: + LOG_VMM("unknown wrmsr 0x%x, value 0x%lx\n", vctx->ecx, value); + return false; + } + + return true; +} diff --git a/src/arch/x86_64/pci.c b/src/arch/x86_64/pci.c new file mode 100644 index 000000000..7c916a8d6 --- /dev/null +++ b/src/arch/x86_64/pci.c @@ -0,0 +1,247 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Uncomment this to enable debug logging */ +// #define DEBUG_PCI_PIO + +#if defined(DEBUG_PCI_PIO) +#define LOG_PCI_PIO(...) do{ printf("%s|PCI PIO: ", microkit_name); printf(__VA_ARGS__); }while(0) +#else +#define LOG_PCI_PIO(...) do{}while(0) +#endif + +// #define DEBUG_PCI_ECAM + +#if defined(DEBUG_PCI_ECAM) +#define LOG_PCI_ECAM(...) do{ printf("%s|PCI ECAM: ", microkit_name); printf(__VA_ARGS__); }while(0) +#else +#define LOG_PCI_ECAM(...) do{}while(0) +#endif + +#define INTEL_82441_DEVICE_ID 0x1237 + +struct pci_x86_state { + uint32_t selected_pio_addr_reg; + // Backing storage for any virtual PCI devices' configuration space, + // Laid out as an ECAM region, so that when we add virtio devices and UEFI support it's simpler. + char ecam[ECAM_SIZE]; +}; + +struct pci_x86_state pci_x86_state; + +// x86 PIO access +static bool pci_pio_addr_reg_enable(void) +{ + return !!(pci_x86_state.selected_pio_addr_reg >> 31); +} + +static uint8_t pci_pio_addr_reg_bus(void) +{ + return (pci_x86_state.selected_pio_addr_reg >> 16) & 0x7f; +} + +static uint8_t pci_pio_addr_reg_dev(void) +{ + return (pci_x86_state.selected_pio_addr_reg >> 11) & 0x1f; +} + +static uint8_t pci_pio_addr_reg_func(void) +{ + return (pci_x86_state.selected_pio_addr_reg >> 8) & 0x7; +} + +static uint8_t pci_pio_addr_reg_offset(void) +{ + return pci_x86_state.selected_pio_addr_reg & 0xff; +} + +static void pci_invalid_pio_read(seL4_VCPUContext *vctx) +{ + uint64_t *vctx_raw = (uint64_t *)vctx; + vctx_raw[RAX_IDX] = ~0ull; +} + +static char *pci_get_ecam(void) +{ + return (char *)&pci_x86_state.ecam; +} + +// Translate PCI Geographic Address, represented as Bus:Device.Function, to an offset in the ECAM region +static uint32_t pci_geo_addr_to_ecam_offset(uint8_t bus, uint8_t dev, uint8_t func) +{ + return (bus << 20) | ((dev & 0x1f) << 15) | ((func & 0x7) << 12); +} + +static bool pci_pio_select_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qualification, + seL4_VCPUContext *vctx, void *cookie) +{ + uint64_t is_read = qualification & BIT(3); + uint16_t port_addr = (qualification >> 16) & 0xffff; + + if (is_read) { + LOG_PCI_PIO("reg select read: 0x%x\n", pci_x86_state.selected_pio_addr_reg); + assert(port_addr == PCI_CONFIG_ADDRESS_START_PORT); + vctx->eax = pci_x86_state.selected_pio_addr_reg; + } else { + uint32_t value = vctx->eax; + LOG_PCI_PIO("reg select write: 0x%x\n", value); + + if (value >> 31) { + // @billn revisit + // vcpu_print_regs(0); + // assert(port_addr == PCI_CONFIG_ADDRESS_START_PORT); + pci_x86_state.selected_pio_addr_reg = value; + + LOG_PCI_PIO("selecting bus %d, device %d, func %d, reg_offset 0x%x\n", pci_host_bridge_pio_addr_reg_bus(), + pci_host_bridge_pio_addr_reg_dev(), pci_host_bridge_pio_addr_reg_func(), + pci_host_bridge_pio_addr_reg_offset()); + } else { + pci_x86_state.selected_pio_addr_reg = 0; + } + } + + return true; +} + +static bool pci_config_space_read_access(uint8_t bus, uint8_t dev, uint8_t func, uint16_t reg_off, seL4_Word *data, + int access_width_bytes) +{ + uint32_t config_space_ecam_off = pci_geo_addr_to_ecam_offset(bus, dev, func); + uint8_t *bytes = (uint8_t *)(pci_get_ecam() + config_space_ecam_off + reg_off); + *data = 0; + memcpy(data, bytes, access_width_bytes); + return true; +} + +static bool pci_config_space_write_access(uint8_t bus, uint8_t dev, uint8_t func, uint16_t reg_off, uint32_t data, + int access_width_bytes) +{ + + uint32_t config_space_ecam_off = pci_geo_addr_to_ecam_offset(bus, dev, func); + struct pci_config_space *config_space = (struct pci_config_space *)(pci_get_ecam() + config_space_ecam_off); + + // Make sure the guest can't clobber the common header + if (reg_off >= 0x40) { + uint8_t *bytes = (uint8_t *)((uintptr_t)config_space + reg_off); + memcpy(bytes, &data, access_width_bytes); + } + + return true; +} + +static bool pci_pio_data_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qualification, + seL4_VCPUContext *vctx, void *cookie) +{ + // @billn make helpers + uint64_t is_read = qualification & BIT(3); + // uint16_t port_addr = (qualification >> 16) & 0xffff; + ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); + + uint64_t is_string = qualification & BIT(4); + assert(!is_string); + + if (!pci_pio_addr_reg_enable()) { + pci_invalid_pio_read(vctx); + return true; + } else if (pci_pio_addr_reg_bus() > 0) { + // the real backing ECAM only have enough space for 1 bus + pci_invalid_pio_read(vctx); + return true; + } else { + uint8_t bus = pci_pio_addr_reg_bus(); + uint8_t dev = pci_pio_addr_reg_dev(); + uint8_t func = pci_pio_addr_reg_func(); + uint8_t reg_off = pci_pio_addr_reg_offset() + port_offset; + + LOG_PCI_PIO("accessing bus %d, dev %d, func %d, reg off 0x%x, is read $d\n", bus, dev, func, reg_off, is_read); + + if (is_read) { + return pci_config_space_read_access(bus, dev, func, reg_off, &(vctx->eax), + ioports_access_width_to_bytes(access_width)); + } else { + return pci_config_space_write_access(bus, dev, func, reg_off, vctx->eax, + ioports_access_width_to_bytes(access_width)); + } + } +} + +bool pci_ecam_add_device(uint8_t bus, uint8_t dev, uint8_t func, struct pci_config_space *config_space) +{ + uint32_t offset = pci_geo_addr_to_ecam_offset(bus, dev, func); + struct pci_config_space *config_space_dest = (struct pci_config_space *)(pci_get_ecam() + offset); + memcpy(config_space_dest, config_space, sizeof(struct pci_config_space)); + return true; +} + +bool pci_x86_init(void) +{ + // Invalidate all configuration spaces in the ECAM + int bus = 0; + for (int dev = 0; dev <= 0x1f; dev++) { + for (int func = 0; func <= 0x7; func++) { + struct pci_config_space *config_space = + (struct pci_config_space *)(pci_get_ecam() + pci_geo_addr_to_ecam_offset(bus, dev, func)); + config_space->vendor_id = 0xffff; + } + } + + // Register Port I/O handlers for configuration access mechanism #1 + bool success = fault_register_pio_exception_handler(PCI_CONFIG_ADDRESS_START_PORT, PCI_CONFIG_ADDRESS_PORT_SIZE, + pci_pio_select_fault_handle, NULL); + if (!success) { + LOG_VMM_ERR("Could not register PIO fault handler for PCI mech #1 select register!\n"); + return success; + } + success = fault_register_pio_exception_handler(PCI_CONFIG_DATA_START_PORT, PCI_CONFIG_DATA_PORT_SIZE, + pci_pio_data_fault_handle, NULL); + if (!success) { + LOG_VMM_ERR("Could not register PIO fault handler for PCI mech #1 data register!\n"); + return success; + } + + // Populate the PCI bus with the host and ISA bridges + struct pci_config_space host_bridge; + memset(&host_bridge, 0, sizeof(struct pci_config_space)); + + host_bridge = (struct pci_config_space) { + .device_id = INTEL_82441_DEVICE_ID, + .vendor_id = 0x8086, + .class_code = 0x6, + .subclass = 0, + .header_type = 0, + .command = 7 // device responds to PIO and MMIO access and DMA capable + }; + + struct pci_config_space isa_bridge; + memset(&isa_bridge, 0, sizeof(struct pci_config_space)); + + isa_bridge = (struct pci_config_space) { .device_id = 0x7000, + .vendor_id = 0x8086, + .class_code = 0x6, + .subclass = 1, + .header_type = 0x80, // bit 7 multifunction + .command = 7 }; + + assert(pci_ecam_add_device(0, 0, 0, &host_bridge)); + assert(pci_ecam_add_device(0, 1, 0, &isa_bridge)); + // Power management function + assert(pci_ecam_add_device(0, 1, 3, &isa_bridge)); + + return true; +} diff --git a/src/arch/x86_64/util.c b/src/arch/x86_64/util.c new file mode 100644 index 000000000..00a760c71 --- /dev/null +++ b/src/arch/x86_64/util.c @@ -0,0 +1,45 @@ + +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +// @billn shouldn't be here, there should be a `initialise_guest_ram()` function that the VMM call to set these up +extern uintptr_t guest_ram_vaddr; +extern uintptr_t guest_high_ram_vaddr; +extern uint64_t guest_high_ram_size; +extern uintptr_t guest_flash_vaddr; + +/* Table 28-7. Exit Qualification for EPT Violations */ +#define EPT_VIOLATION_READ (1 << 0) +#define EPT_VIOLATION_WRITE (1 << 1) + +bool ept_fault_is_read(seL4_Word qualification) +{ + return qualification & EPT_VIOLATION_READ; +} + +bool ept_fault_is_write(seL4_Word qualification) +{ + return qualification & EPT_VIOLATION_WRITE; +} + +uint64_t pte_to_gpa(uint64_t pte) +{ + assert(pte & 1); + return pte & 0xffffffffff000; +} + +bool pte_present(uint64_t pte) +{ + return pte & BIT(0); +} + +bool pt_page_size(uint64_t pte) +{ + return pte & BIT(7); +} diff --git a/src/arch/x86_64/vcpu.c b/src/arch/x86_64/vcpu.c new file mode 100644 index 000000000..14a4b6aa7 --- /dev/null +++ b/src/arch/x86_64/vcpu.c @@ -0,0 +1,172 @@ +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, uint64_t vapic_page_paddr, + uint64_t apic_access_page_paddr) +{ + // @billn explain + + // Set up system registers + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR0, CR0_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR3, cr3); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4, CR4_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER, IA32_EFER_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_RFLAGS, RFLAGS_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GDTR_BASE, gdt_gpa); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GDTR_LIMIT, gdt_limit); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS, VMCS_PCC_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS, VMCS_SPC_DEFAULT); + + // These asserts will fail if your host CPU doesn't support all the VT-x features + // that libvmm uses. + uint64_t read_back_ppc = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS); + uint64_t read_back_spc = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS); + assert((read_back_ppc & VMCS_PCC_DEFAULT) == VMCS_PCC_DEFAULT); + assert((read_back_spc & VMCS_SPC_DEFAULT) == VMCS_SPC_DEFAULT); + + // @billn explain + // @billn todo add other important bits + + // prevent the guest from turning off VMX mode + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_CR4_MASK, 1 << 13); + // @billn todo add other registers with mask + + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_BASE, 0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_BASE, 0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_ES_BASE, 0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_SS_BASE, 0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_BASE, 0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_BASE, 0); + + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_SELECTOR, 8); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_SELECTOR, 16); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_ES_SELECTOR, 16); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_SS_SELECTOR, 16); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_SELECTOR, 0); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_SELECTOR, 0); + + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_LIMIT, 0xfffff); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_LIMIT, 0xfffff); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_ES_LIMIT, 0xfffff); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_SS_LIMIT, 0xfffff); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_LIMIT, 0xfffff); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_LIMIT, 0xfffff); + + // 25-4 Vol. 3C @billn explain + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_ACCESS_RIGHTS, 0xA09B); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_ES_ACCESS_RIGHTS, 0xC093); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_SS_ACCESS_RIGHTS, 0xC093); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_ACCESS_RIGHTS, 0x3 | 1 << 4 | 1 << 7 | 1 << 15); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_ACCESS_RIGHTS, 0x3 | 1 << 4 | 1 << 7 | 1 << 15); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_LDTR_ACCESS_RIGHTS, 0x2 | 1 << 7); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_TR_ACCESS_RIGHTS, 0xb | 1 << 7); + + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_VIRTUAL_APIC_ADDRESS, vapic_page_paddr); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_APIC_ACCESS_ADDRESS, apic_access_page_paddr); + + // Table 25-16. Definitions of VM-Entry Controls + // load EFER on entry + uint64_t entry_controls = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS); + entry_controls |= BIT(15) | BIT(9); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS, entry_controls); +} + +void vcpu_print_regs(size_t vcpu_id) +{ + seL4_Word cppc = microkit_mr_get(SEL4_VMENTER_CALL_CONTROL_PPC_MR); + seL4_Word irq_info = microkit_mr_get(SEL4_VMENTER_CALL_INTERRUPT_INFO_MR); + seL4_Word f_reason = microkit_mr_get(SEL4_VMENTER_FAULT_REASON_MR); + seL4_Word f_qual = microkit_mr_get(SEL4_VMENTER_FAULT_QUALIFICATION_MR); + seL4_Word ins_len = microkit_mr_get(SEL4_VMENTER_FAULT_INSTRUCTION_LEN_MR); + seL4_Word g_p_addr = microkit_mr_get(SEL4_VMENTER_FAULT_GUEST_PHYSICAL_MR); + seL4_Word rflags = microkit_mr_get(SEL4_VMENTER_FAULT_RFLAGS_MR); + seL4_Word interruptability = microkit_mr_get(SEL4_VMENTER_FAULT_GUEST_INT_MR); + seL4_Word cr3 = microkit_mr_get(SEL4_VMENTER_FAULT_CR3_MR); + + seL4_Word rip = microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_RIP); + seL4_Word rsp = microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_RSP); + + seL4_Word eax = microkit_mr_get(SEL4_VMENTER_FAULT_EAX); + seL4_Word ebx = microkit_mr_get(SEL4_VMENTER_FAULT_EBX); + seL4_Word ecx = microkit_mr_get(SEL4_VMENTER_FAULT_ECX); + seL4_Word edx = microkit_mr_get(SEL4_VMENTER_FAULT_EDX); + seL4_Word esi = microkit_mr_get(SEL4_VMENTER_FAULT_ESI); + seL4_Word edi = microkit_mr_get(SEL4_VMENTER_FAULT_EDI); + seL4_Word ebp = microkit_mr_get(SEL4_VMENTER_FAULT_EBP); + + seL4_Word r8 = microkit_mr_get(SEL4_VMENTER_FAULT_R8); + seL4_Word r9 = microkit_mr_get(SEL4_VMENTER_FAULT_R9); + seL4_Word r10 = microkit_mr_get(SEL4_VMENTER_FAULT_R10); + seL4_Word r11 = microkit_mr_get(SEL4_VMENTER_FAULT_R11); + seL4_Word r12 = microkit_mr_get(SEL4_VMENTER_FAULT_R12); + seL4_Word r13 = microkit_mr_get(SEL4_VMENTER_FAULT_R13); + seL4_Word r14 = microkit_mr_get(SEL4_VMENTER_FAULT_R14); + seL4_Word r15 = microkit_mr_get(SEL4_VMENTER_FAULT_R15); + + seL4_Word efer = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER); + + LOG_VMM("dumping VCPU (ID 0x%lx) registers:\n", vcpu_id); + LOG_VMM(" vm primary processor control = 0x%lx\n", cppc); + LOG_VMM(" vm enter irq = 0x%lx\n", irq_info); + LOG_VMM(" fault reason = 0x%lx (%s)\n", f_reason, fault_to_string(f_reason)); + LOG_VMM(" fault qualification = 0x%lx\n", f_qual); + LOG_VMM(" instruction length = 0x%lx\n", ins_len); + LOG_VMM(" guest physical addr = 0x%lx\n", g_p_addr); + LOG_VMM(" rflags = 0x%lx\n", rflags); + LOG_VMM(" interruptability = 0x%lx\n", interruptability); + LOG_VMM(" cr0 = 0x%lx\n", microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_CR0)); + LOG_VMM(" cr3 = 0x%lx\n", cr3); + LOG_VMM(" cr4 = 0x%lx\n", microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4)); + LOG_VMM(" efer = 0x%lx\n", efer); + LOG_VMM("=========================\n"); + LOG_VMM(" rip = 0x%lx\n", rip); + LOG_VMM(" rsp = 0x%lx\n", rsp); + LOG_VMM(" rax = 0x%lx\n", eax); + LOG_VMM(" rbx = 0x%lx\n", ebx); + LOG_VMM(" rcx = 0x%lx\n", ecx); + LOG_VMM(" rdx = 0x%lx\n", edx); + LOG_VMM(" rsi = 0x%lx\n", esi); + LOG_VMM(" rdi = 0x%lx\n", edi); + LOG_VMM(" rbp = 0x%lx\n", ebp); + LOG_VMM(" r8 = 0x%lx\n", r8); + LOG_VMM(" r9 = 0x%lx\n", r9); + LOG_VMM(" r10 = 0x%lx\n", r10); + LOG_VMM(" r11 = 0x%lx\n", r11); + LOG_VMM(" r12 = 0x%lx\n", r12); + LOG_VMM(" r13 = 0x%lx\n", r13); + LOG_VMM(" r14 = 0x%lx\n", r14); + LOG_VMM(" r15 = 0x%lx\n", r15); + LOG_VMM("=========================\n"); + + if (guest_paging_on()) { + if (ins_len) { + uint64_t gpa; + uint64_t bytes_remaining; + assert(gva_to_gpa(0, rip, &gpa, &bytes_remaining)); + assert(bytes_remaining >= ins_len); + LOG_VMM_ERR("faulting instruction:\n"); + uint8_t *ins = gpa_to_vaddr(gpa); + for (int i = 0; i < ins_len; i++) { + LOG_VMM_ERR("0x%02x\n", ins[i]); + bytes_remaining--; + } + } + } +} diff --git a/src/arch/x86_64/virq.c b/src/arch/x86_64/virq.c new file mode 100644 index 000000000..7a96c18ab --- /dev/null +++ b/src/arch/x86_64/virq.c @@ -0,0 +1,129 @@ + +/* + * Copyright 2025, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include +#include +#include + +uintptr_t vapic_vaddr; +struct ioapic_regs ioapic_regs; +uint64_t tsc_hz; + +bool virq_controller_init(uint64_t native_tsc_hz, uintptr_t guest_vapic_vaddr) +{ + tsc_hz = native_tsc_hz; + + LOG_VMM("initialising IRQ book-keeping structures\n"); + memset(&ioapic_regs, 0, sizeof(struct ioapic_regs)); + + LOG_VMM("initialising LAPIC\n"); + + vapic_vaddr = guest_vapic_vaddr; + + // Figure 11-7. Local APIC Version Register + // "For processors based on the Nehalem microarchitecture (which has 7 LVT entries) and onward, the value returned is 6." + vapic_write_reg(REG_LAPIC_REV, (uint32_t)0x10 | (uint32_t)6 << 16); + // Figure 11-23. Spurious-Interrupt Vector Register (SVR) + vapic_write_reg(REG_LAPIC_SVR, (uint32_t)0xff); // reset value + // LVT Timer Register + vapic_write_reg(REG_LAPIC_TIMER, 0x10000); // reset value, masked. + // "Specifies interrupt delivery when an interrupt is signaled at the LINT0 pin" + // Figure 11-8. Local Vector Table (LVT) + vapic_write_reg(REG_LAPIC_LVT_LINT0, 0x10000); // reset value + vapic_write_reg(REG_LAPIC_LVT_LINT1, 0x10000); // reset value + // Figure 11-14. Destination Format Register (DFR) + vapic_write_reg(REG_LAPIC_DFR, 0xffffffff); // reset value + + LOG_VMM("initialising I/O APIC\n"); + // https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf + // default value for the Intel 82093AA IOAPIC. + // supports 0x17 indirection entries. + ioapic_regs.ioapicver = 0x11 | (IOAPIC_LAST_INDIRECT_INDEX << 16); + // Wire up all the IRQs + for (int i = 0; i <= IOAPIC_LAST_INDIRECT_INDEX; i++) { + // fixed intr deivery, all zero + // destination mode, physical mode to apic 0, all zero + // delivery status, all zero + // Interrupt Input Pin Polarity, high active, all zero + // edge triggered, all zero + // interrupt mask bit 16, mask all irq: + ioapic_regs.ioredtbl[i] |= BIT(16); + + ioapic_regs.virq_passthrough_map[i].valid = false; + ioapic_regs.virq_passthrough_map[i].ch = IOAPIC_IRQ_HANDLE_NO_CH; + } + + return true; +} + +void virq_ioapic_passthrough_ack(int ioapic, int pin, void *cookie) +{ + /* We are down-casting to microkit_channel so must first cast to size_t */ + microkit_irq_ack((microkit_channel)(size_t)cookie); +} + +bool virq_ioapic_register(int ioapic, int pin, virq_ioapic_ack_fn_t ack_fn, void *ack_data) +{ + if (ioapic != 0) { + LOG_VMM_ERR("Invalid I/O APIC chip number given '0x%lx' for passthrough virtual I/O APIC #%d IRQ pin 0x%lx\n", + ioapic, ioapic, pin); + return false; + } + + if (pin >= IOAPIC_NUM_PINS) { + LOG_VMM_ERR("Invalid I/O APIC pin number given '0x%lx' for passthrough virtual I/O APIC #%d IRQ pin 0x%lx\n", + pin, ioapic, pin); + return false; + } + + if (ioapic_regs.virq_passthrough_map[pin].valid) { + LOG_VMM_ERR("Pin %d is already registered on virtual I/O APIC\n", pin); + return false; + } + + ioapic_regs.virq_passthrough_map[pin].valid = true; + ioapic_regs.virq_passthrough_map[pin].ack_fn = ack_fn; + ioapic_regs.virq_passthrough_map[pin].ack_data = ack_data; + + return true; +} + +bool virq_ioapic_register_passthrough(int ioapic, int pin, microkit_channel irq_ch) +{ + if (irq_ch >= MICROKIT_MAX_CHANNELS) { + LOG_VMM_ERR("Invalid channel number given '0x%lx' for passthrough virtual I/O APIC #%d IRQ pin 0x%lx\n", irq_ch, + ioapic, pin); + return false; + } + + bool success = virq_ioapic_register(ioapic, pin, virq_ioapic_passthrough_ack, (void *)(uint64_t)irq_ch); + if (success) { + ioapic_regs.virq_passthrough_map[pin].ch = irq_ch; + } + + return success; +} + +bool virq_ioapic_handle_passthrough(microkit_channel irq_ch) +{ + if (irq_ch >= MICROKIT_MAX_CHANNELS) { + LOG_VMM_ERR("attempted to handle invalid passthrough IRQ channel 0x%lx\n", irq_ch); + return false; + } + + for (int i = 0; i < IOAPIC_NUM_PINS; i++) { + if (ioapic_regs.virq_passthrough_map[i].valid) { + if (ioapic_regs.virq_passthrough_map[i].ch == irq_ch) { + return inject_ioapic_irq(0, i); + } + } + } + + LOG_VMM_ERR("attempted to handle unregistered passthrough IRQ channel 0x%lx\n", irq_ch); + return false; +} diff --git a/src/guest.c b/src/guest.c index 130052e03..89e54db45 100644 --- a/src/guest.c +++ b/src/guest.c @@ -36,6 +36,14 @@ bool guest_init(arch_guest_init_t init_args) return success; } +#if defined(CONFIG_ARCH_X86_64) +#include +#include +#include +#include +#include +#endif + bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { /* @@ -44,28 +52,77 @@ bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) * any other kind of guest. However, even though the library is open to supporting other * guests, there is no point in prematurely generalising this code. */ - seL4_UserContext regs = {0}; +#if defined(CONFIG_ARCH_AARCH64) + seL4_UserContext regs = { 0 }; regs.x0 = dtb; regs.spsr = 5; // PMODE_EL1h regs.pc = kernel_pc; +#elif defined(CONFIG_ARCH_X86_64) +#else +#error "Unsupported guest architecture" +#endif /* Write out all the TCB registers */ - seL4_Word err = seL4_TCB_WriteRegisters( - BASE_VM_TCB_CAP + GUEST_BOOT_VCPU_ID, - false, // We'll explcitly start the guest below rather than in this call - 0, // No flags - 4, // Writing to x0, pc, and spsr. Due to the ordering of seL4_UserContext the count must be 4. - ®s); + +#if defined(CONFIG_ARCH_AARCH64) + seL4_Word err = seL4_TCB_WriteRegisters(BASE_VM_TCB_CAP + GUEST_BOOT_VCPU_ID, + false, // We'll explcitly start the guest below rather than in this call + 0, // No flags + sizeof(seL4_UserContext) / sizeof(seL4_Word), ®s); assert(err == seL4_NoError); if (err != seL4_NoError) { LOG_VMM_ERR("Failed to write registers to boot vCPU's TCB (id is 0x%lx), error is: 0x%lx\n", GUEST_BOOT_VCPU_ID, err); return false; } - LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", regs.pc, regs.x0, initrd); + LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", kernel_pc, dtb, initrd); - vcpu_set_on(GUEST_BOOT_VCPU_ID, true); + // @billn revisit + // vcpu_set_on(GUEST_BOOT_VCPU_ID, true); /* Restart the boot vCPU to the program counter of the TCB associated with it */ - microkit_vcpu_restart(GUEST_BOOT_VCPU_ID, regs.pc); + microkit_vcpu_restart(GUEST_BOOT_VCPU_ID, kernel_pc); + +#elif defined(CONFIG_ARCH_X86_64) + LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", kernel_pc, dtb, initrd); + + microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, kernel_pc); + microkit_mr_set(SEL4_VMENTER_CALL_CONTROL_PPC_MR, VMCS_PCC_DEFAULT); + microkit_mr_set(SEL4_VMENTER_CALL_INTERRUPT_INFO_MR, 0); + + while (true) { + seL4_Word badge; + seL4_Word ret = seL4_VMEnter(&badge); + + if (ret == SEL4_VMENTER_RESULT_NOTIF) { + // @billn refactor + uint64_t rip = microkit_mr_get(SEL4_VMENTER_CALL_EIP_MR); + + // @billn highly fucking sus, need to incorporate vmenter into the microkit event loop + uint64_t is_endpoint = badge >> 63; + uint64_t is_fault = (badge >> 62) & 1; + + assert(!is_endpoint); + assert(!is_fault); + + unsigned int idx = 0; + do { + if (badge & 1) { + notified(idx); + } + badge >>= 1; + idx++; + } while (badge != 0); + + microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, rip); + } else if (ret == SEL4_VMENTER_RESULT_FAULT) { + uint64_t new_rip; + assert(fault_handle(GUEST_BOOT_VCPU_ID, &new_rip)); + microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, new_rip); + } else { + LOG_VMM_ERR("unexpected VM exit reason 0x%x\n", ret); + } + } + LOG_VMM("done\n"); +#endif return true; } @@ -73,7 +130,10 @@ bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) void guest_stop() { LOG_VMM("Stopping guest\n"); +#if !defined(CONFIG_VTX) + // @billn revisit, not possible on x86 microkit_vcpu_stop(GUEST_BOOT_VCPU_ID); +#endif LOG_VMM("Stopped guest\n"); } @@ -81,7 +141,9 @@ bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size) { LOG_VMM("Attempting to restart guest\n"); // First, stop the guest +#if !defined(CONFIG_VTX) microkit_vcpu_stop(GUEST_BOOT_VCPU_ID); +#endif LOG_VMM("Stopped guest\n"); // Then, we need to clear all of RAM LOG_VMM("Clearing guest RAM\n"); @@ -92,7 +154,7 @@ bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size) // LOG_VMM_ERR("Failed to initialise guest images\n"); // return false; // } - vcpu_reset(GUEST_BOOT_VCPU_ID); + // vcpu_reset(GUEST_BOOT_VCPU_ID); // Now we need to re-initialise all the VMM state // vmm_init(); // linux_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); diff --git a/vmm.mk b/vmm.mk index 01f1db659..bb1cb3b01 100644 --- a/vmm.mk +++ b/vmm.mk @@ -16,12 +16,32 @@ AARCH64_FILES := src/arch/aarch64/fault.c \ src/arch/aarch64/tcb.c \ src/arch/aarch64/vcpu.c \ src/arch/aarch64/virq.c \ + src/arch/aarch64/guest.c \ src/arch/aarch64/vgic/vgic.c \ src/arch/aarch64/vgic/vgic_v2.c \ src/arch/aarch64/vgic/vgic_v3.c \ - src/arch/aarch64/vgic/vgic_v3_cpuif.c - -# VIRTIO MMIO depends on sddf + src/arch/aarch64/vgic/vgic_v3_cpuif.c \ + src/virtio/mmio.c \ + ${VGIC_FILES} + +X86_64_FILES = src/arch/x86_64/fault.c \ + src/arch/x86_64/guest.c \ + src/arch/x86_64/linux.c \ + src/arch/x86_64/vcpu.c \ + src/arch/x86_64/virq.c \ + src/arch/x86_64/cpuid.c \ + src/arch/x86_64/msr.c \ + src/arch/x86_64/acpi.c \ + src/arch/x86_64/apic.c \ + src/arch/x86_64/instruction.c \ + src/arch/x86_64/ioports.c \ + src/arch/x86_64/hpet.c \ + src/arch/x86_64/pci.c \ + src/arch/x86_64/util.c \ + src/arch/x86_64/cmos.c \ + src/arch/x86_64/com.c + +# VIRTIO MMIO and PCI depends on sddf ifeq ($(strip $(SDDF)),) $(error libvmm needs the location of the SDDF to build virtIO components) endif @@ -37,23 +57,30 @@ endif ARCH_INDEP_FILES := src/util/printf.c \ src/util/util.c \ - src/virtio/block.c \ + src/guest.c + +VIRTIO_FILES := src/virtio/block.c \ src/virtio/console.c \ - src/virtio/mmio.c \ src/virtio/pci.c \ src/virtio/net.c \ src/virtio/sound.c \ src/virtio/virtio.c \ src/guest.c -CFILES := ${AARCH64_FILES} ${ARCH_INDEP_FILES} +ifeq ($(ARCH),aarch64) +CFILES := ${AARCH64_FILES} ${VIRTIO_FILES} +else ifeq ($(ARCH),x86_64) +CFILES := ${X86_64_FILES} +endif + +CFILES += ${ARCH_INDEP_FILES} OBJECTS := $(subst src,libvmm,${CFILES:.c=.o}) # Enable LLVM UBSAN to trap on detected undefined behaviour CFLAGS += -fsanitize=undefined -fsanitize-trap=undefined # Generate dependencies automatically -CFLAGS += -MD +CFLAGS += -MD -Wall -Werror -Wno-unused-function # Force rebuid if CFLAGS changes. # This will pick up (among other things} changes @@ -65,16 +92,21 @@ CHECK_LIBVMM_CFLAGS:=.libvmm_cflags.$(shell echo ${CFLAGS} | shasum | sed 's/ *- # This is ugly, but needed to distinguish directories in the BUILD area # from directories in the source area. -libvmm/arch/aarch64/vgic: +.PHONY: directories +directories: +ifeq ($(ARCH),aarch64) mkdir -p libvmm/arch/aarch64/vgic/ +else ifeq ($(ARCH),x86_64) + mkdir -p libvmm/arch/x86_64/qemu/ +endif mkdir -p libvmm/util mkdir -p libvmm/virtio libvmm.a: ${OBJECTS} ${AR} crv $@ $^ -${OBJECTS}: ${SDDF}/include -${OBJECTS}: ${CHECK_LIBVMM_CFLAGS} |libvmm/arch/aarch64/vgic $(LIBVMM_LIBC_INCLUDE) +${OBJECTS}: directories ${SDDF}/include +${OBJECTS}: ${CHECK_LIBVMM_CFLAGS} | $(LIBVMM_LIBC_INCLUDE) libvmm/%.o: src/%.c ${CC} ${CFLAGS} -c -o $@ $< From 03370178dba503159972634463b71b807a0e888d Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 18 Mar 2026 11:25:10 +1100 Subject: [PATCH 02/42] examples/simple: add x86_64 support See github.com/au-ts/libvmm/tree/x86_64_rebased for original development history. Signed-off-by: Bill Nguyen --- examples/simple/Makefile | 2 +- examples/simple/README.md | 3 + .../{images => aarch64_images}/README.md | 2 +- .../buildroot_config | 0 .../{images => aarch64_images}/linux_config | 0 examples/simple/board/maaxboard/simple.system | 2 +- examples/simple/board/odroidc4/simple.system | 2 +- .../board/qemu_virt_aarch64/simple.system | 2 +- .../board/x86_64_generic_vtx/simple.system | 69 + .../board/x86_64_generic_vtx/simple_dsdt.aml | Bin 0 -> 193 bytes .../board/x86_64_generic_vtx/simple_dsdt.dsl | 68 + examples/simple/build.zig | 120 +- examples/simple/build.zig.zon | 14 +- examples/simple/simple.mk | 60 +- examples/simple/{vmm.c => vmm_aarch64.c} | 0 examples/simple/vmm_x86_64.c | 126 + examples/simple/x86_64_images/README.md | 52 + .../simple/x86_64_images/buildroot_config | 5102 +++++++++++++++ examples/simple/x86_64_images/linux_config | 5478 +++++++++++++++++ 19 files changed, 11055 insertions(+), 47 deletions(-) rename examples/simple/{images => aarch64_images}/README.md (98%) rename examples/simple/{images => aarch64_images}/buildroot_config (100%) rename examples/simple/{images => aarch64_images}/linux_config (100%) create mode 100644 examples/simple/board/x86_64_generic_vtx/simple.system create mode 100644 examples/simple/board/x86_64_generic_vtx/simple_dsdt.aml create mode 100644 examples/simple/board/x86_64_generic_vtx/simple_dsdt.dsl rename examples/simple/{vmm.c => vmm_aarch64.c} (100%) create mode 100644 examples/simple/vmm_x86_64.c create mode 100644 examples/simple/x86_64_images/README.md create mode 100644 examples/simple/x86_64_images/buildroot_config create mode 100644 examples/simple/x86_64_images/linux_config diff --git a/examples/simple/Makefile b/examples/simple/Makefile index 4b8880159..ccac6d401 100644 --- a/examples/simple/Makefile +++ b/examples/simple/Makefile @@ -19,11 +19,11 @@ endif export BUILD_DIR := $(abspath $(BUILD_DIR)) export EXAMPLE_DIR := $(abspath .) -export TARGET := aarch64-none-elf export CC := clang export LD := ld.lld export AS := llvm-as export AR := llvm-ar +export OBJCOPY := llvm-objcopy export DTC := dtc export RANLIB := llvm-ranlib export MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit diff --git a/examples/simple/README.md b/examples/simple/README.md index 24d1f7928..2e6db9f9e 100644 --- a/examples/simple/README.md +++ b/examples/simple/README.md @@ -14,6 +14,7 @@ The example currently works on the following platforms: * QEMU virt AArch64 * HardKernel Odroid-C4 * Avnet MaaXBoard +* x86_64 ## Building with Make @@ -26,6 +27,7 @@ Where `` is one of: * `qemu_virt_aarch64` * `odroidc4` * `maaxboard` +* `x86_64_generic_vtx` Other configuration options can be passed to the Makefile such as `MICROKIT_CONFIG` and `BUILD_DIR`, see the Makefile for details. @@ -64,6 +66,7 @@ Where `` is one of: * `qemu_virt_aarch64` * `odroidc4` * `maaxboard` +* `x86_64_generic_vtx` If you are building for QEMU then you can also run QEMU by doing: ```sh diff --git a/examples/simple/images/README.md b/examples/simple/aarch64_images/README.md similarity index 98% rename from examples/simple/images/README.md rename to examples/simple/aarch64_images/README.md index bec1a8a40..b16d4d112 100644 --- a/examples/simple/images/README.md +++ b/examples/simple/aarch64_images/README.md @@ -5,7 +5,7 @@ # Guest images used -We use the same images (Linux kernel and initrd/rootfs) for all platforms. +We use the same images (Linux kernel and initrd/rootfs) for all ARM platforms. Below are instructions for reproducing them. diff --git a/examples/simple/images/buildroot_config b/examples/simple/aarch64_images/buildroot_config similarity index 100% rename from examples/simple/images/buildroot_config rename to examples/simple/aarch64_images/buildroot_config diff --git a/examples/simple/images/linux_config b/examples/simple/aarch64_images/linux_config similarity index 100% rename from examples/simple/images/linux_config rename to examples/simple/aarch64_images/linux_config diff --git a/examples/simple/board/maaxboard/simple.system b/examples/simple/board/maaxboard/simple.system index 3feb3e3fc..514412c61 100644 --- a/examples/simple/board/maaxboard/simple.system +++ b/examples/simple/board/maaxboard/simple.system @@ -21,7 +21,7 @@ - + diff --git a/examples/simple/board/odroidc4/simple.system b/examples/simple/board/odroidc4/simple.system index 93c58f5d3..d3f92bb9f 100644 --- a/examples/simple/board/odroidc4/simple.system +++ b/examples/simple/board/odroidc4/simple.system @@ -20,7 +20,7 @@ - + diff --git a/examples/simple/board/qemu_virt_aarch64/simple.system b/examples/simple/board/qemu_virt_aarch64/simple.system index b1b4eaf9d..e4c368e7c 100644 --- a/examples/simple/board/qemu_virt_aarch64/simple.system +++ b/examples/simple/board/qemu_virt_aarch64/simple.system @@ -27,7 +27,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/simple/board/x86_64_generic_vtx/simple_dsdt.aml b/examples/simple/board/x86_64_generic_vtx/simple_dsdt.aml new file mode 100644 index 0000000000000000000000000000000000000000..7052affea2cf5f5bce12015e87177376f898150f GIT binary patch literal 193 zcmZ<>b_qGiz`($io|BnWmYWM985kIWVxE2>K0-pO3IaZy@xe~<(M{UU{=SAB@gANo zJdPJw89CxZJzapLb5O9L02i-2;}7N^%nTe#0t}T5(M|4b0nVNVFx6blKy_e!TpTcc z!LIHM9Pv(0en1jrhAEd(2QLE?5724`hW{Xf5y)rcVFoe31BHL^!1=uYK?*)sG5`P; C?kWKQ literal 0 HcmV?d00001 diff --git a/examples/simple/board/x86_64_generic_vtx/simple_dsdt.dsl b/examples/simple/board/x86_64_generic_vtx/simple_dsdt.dsl new file mode 100644 index 000000000..e067b1e16 --- /dev/null +++ b/examples/simple/board/x86_64_generic_vtx/simple_dsdt.dsl @@ -0,0 +1,68 @@ +// Copyright 2025, UNSW +// SPDX-License-Identifier: BSD-2-Clause + +// Compile with `iasl -tc simple_dsdt.dsl` +// This is used to build the ACPI DSDT. Which is needed for the FADT, and +// the FADT is needed for Linux's ACPI core to initialise and serial IRQ to be discovered. + +DefinitionBlock ("", "DSDT", 2, "libvmm", "libvmm", 0x1) +{ + Scope (\_SB) + { + Device (COM1) + { + Name (_HID, EisaId ("PNP0501")) + Name (_UID, One) + Name (_CRS, ResourceTemplate () + { + IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08) + IRQNoFlags () { 4 } + }) + } + + Device (PCI0) + { + // PCI root bridge + Name (_HID, EisaId ("PNP0A03")) + // Compatible with PCIe root + Name (_CID, EisaId ("PNP0A08")) + Name (_UID, One) + // PCI segment and base bus number 0 + Name (_SEG, Zero) + Name (_BBN, Zero) + + // @billn add I/O Port ranges that the host bridge decodes, + // so that we can get rid of "pci=nocrs" in cmdline + + Name (_CRS, ResourceTemplate () + { + // Bus numbers this root bridge owns + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Granularity + 0x0000, // Min + 0x00FF, // Max + 0x0000, // Translation + 0x0100 // Length + ) + + // I/O port window(s) forwarded to PCI below this root bridge. + // Precisely host bridge actually decodes. + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Granularity + 0x0000, // Min + 0x0CF7, // Max + 0x0000, // Translation + 0x0CF8 // Length + ) + + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Granularity + 0x0D00, // Min + 0xFFFF, // Max + 0x0000, // Translation + 0xF300 // Length (0xFFFF - 0x0D00 + 1) + ) + }) + } + } +} diff --git a/examples/simple/build.zig b/examples/simple/build.zig index d10bc0b18..391747214 100644 --- a/examples/simple/build.zig +++ b/examples/simple/build.zig @@ -7,6 +7,7 @@ const MicrokitBoard = enum { qemu_virt_aarch64, odroidc4, maaxboard, + x86_64_generic_vtx, }; const Target = struct { @@ -45,6 +46,15 @@ const targets = [_]Target { .abi = .none, }, }, + .{ + .board = MicrokitBoard.x86_64_generic_vtx, + .zig_target = std.Target.Query{ + .cpu_arch = .x86_64, + .cpu_model = .{ .explicit = std.Target.Cpu.Model.generic(.x86_64) }, + .os_tag = .freestanding, + .abi = .none, + }, + } }; fn findTarget(board: MicrokitBoard) std.Target.Query { @@ -64,6 +74,18 @@ const ConfigOptions = enum { benchmark }; +fn linuxKernelImageName(arch: std.Target.Cpu.Arch) ?[]const u8 { + if (arch == .x86_64) { + return "bzImage"; + } else if (arch == .aarch64) { + return "linux"; + } else { + std.log.err("Unsupported architecture {}", .{arch}); + return null; + } +} + + pub fn build(b: *std.Build) !void { const optimize = b.standardOptimizeOption(.{}); const microkit_sdk = b.option(LazyPath, "sdk", "Path to Microkit SDK") orelse { @@ -105,7 +127,7 @@ pub fn build(b: *std.Build) !void { }); const exe = b.addExecutable(.{ - .name = "vmm.elf", + .name = b.fmt("vmm_{s}.elf", .{ @tagName(target.result.cpu.arch) }), .root_module = b.createModule(.{ .target = target, .optimize = optimize, @@ -116,22 +138,28 @@ pub fn build(b: *std.Build) !void { }), }); - const base_dts_path = b.fmt("board/{s}/linux.dts", .{ microkit_board }); - const overlay = b.fmt("board/{s}/overlay.dts", .{ microkit_board }); - const dts_cat_cmd = b.addSystemCommand(&[_][]const u8{ - "sh", "../../tools/dtscat", base_dts_path, overlay - }); - dts_cat_cmd.addFileInput(b.path(base_dts_path)); - dts_cat_cmd.addFileInput(b.path(overlay)); - const final_dts = dts_cat_cmd.captureStdOut(); + const dtb = blk: { + if (target.result.cpu.arch != .x86_64) { + const base_dts_path = b.fmt("board/{s}/linux.dts", .{ microkit_board }); + const overlay = b.fmt("board/{s}/overlay.dts", .{ microkit_board }); + const dts_cat_cmd = b.addSystemCommand(&[_][]const u8{ + "sh", "../../tools/dtscat", base_dts_path, overlay + }); + dts_cat_cmd.addFileInput(b.path(base_dts_path)); + dts_cat_cmd.addFileInput(b.path(overlay)); + const final_dts = dts_cat_cmd.captureStdOut(); - // For actually compiling the DTS into a DTB - const dtc_cmd = b.addSystemCommand(&[_][]const u8{ - "dtc", "-q", "-I", "dts", "-O", "dtb" - }); - dtc_cmd.addFileArg(.{ .cwd_relative = b.getInstallPath(.prefix, "final.dts") }); - dtc_cmd.step.dependOn(&b.addInstallFileWithDir(final_dts, .prefix, "final.dts").step); - const dtb = dtc_cmd.captureStdOut(); + // For actually compiling the DTS into a DTB + const dtc_cmd = b.addSystemCommand(&[_][]const u8{ + "dtc", "-q", "-I", "dts", "-O", "dtb" + }); + dtc_cmd.addFileArg(.{ .cwd_relative = b.getInstallPath(.prefix, "final.dts") }); + dtc_cmd.step.dependOn(&b.addInstallFileWithDir(final_dts, .prefix, "final.dts").step); + break :blk dtc_cmd.captureStdOut(); + } else { + break :blk null; + } + }; // Add microkit.h to be used by the API wrapper. exe.addIncludePath(libmicrokit_include); @@ -147,12 +175,11 @@ pub fn build(b: *std.Build) !void { exe.linkLibrary(sddf_dep.artifact("util")); exe.addCSourceFiles(.{ - .files = &.{"vmm.c"}, + .files = &.{ b.fmt("vmm_{s}.c", .{ @tagName(target.result.cpu.arch) }) }, .flags = &.{ "-Wall", "-Werror", "-Wno-unused-function", - "-mstrict-align", b.fmt("-DBOARD_{s}", .{ microkit_board }) } }); @@ -164,16 +191,19 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, }), }); - // We need to produce the DTB from the DTS before doing anything to produce guest_images - guest_images.step.dependOn(&b.addInstallFileWithDir(dtb, .prefix, "linux.dtb").step); + + if (dtb != null) { + // We need to produce the DTB from the DTS before doing anything to produce guest_images + guest_images.step.dependOn(&b.addInstallFileWithDir(dtb.?, .prefix, "linux.dtb").step); + } const linux_image_dep = b.lazyDependency(b.fmt("linux_{t}", .{ target.result.cpu.arch }), .{}); const initrd_image_dep = b.lazyDependency(b.fmt("initrd_{t}", .{ target.result.cpu.arch }), .{}); if (custom_linux) |c| { - guest_images.step.dependOn(&b.addInstallFileWithDir(.{ .cwd_relative = c }, .prefix, "linux").step); + guest_images.step.dependOn(&b.addInstallFileWithDir(.{ .cwd_relative = c }, .prefix, linuxKernelImageName(target.result.cpu.arch).?).step); } else if (linux_image_dep) |linux_image| { - guest_images.step.dependOn(&b.addInstallFileWithDir(linux_image.path("linux"), .prefix, "linux").step); + guest_images.step.dependOn(&b.addInstallFileWithDir(linux_image.path(linuxKernelImageName(target.result.cpu.arch).?), .prefix, linuxKernelImageName(target.result.cpu.arch).?).step); } if (custom_initrd) |c| { @@ -182,9 +212,12 @@ pub fn build(b: *std.Build) !void { guest_images.step.dependOn(&b.addInstallFileWithDir(initrd_image.path("rootfs.cpio.gz"), .prefix, "rootfs.cpio.gz").step); } - const kernel_image_arg = b.fmt("-DGUEST_KERNEL_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "linux") }); + const kernel_image_arg = b.fmt("-DGUEST_KERNEL_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, linuxKernelImageName(target.result.cpu.arch).?) }); const initrd_image_arg = b.fmt("-DGUEST_INITRD_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "rootfs.cpio.gz") }); - const dtb_image_arg = b.fmt("-DGUEST_DTB_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "linux.dtb") }); + var dtb_image_arg: []const u8 = ""; + if (dtb != null) { + dtb_image_arg = b.fmt("-DGUEST_DTB_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "linux.dtb") }); + } guest_images.addCSourceFile(.{ .file = libvmm_dep.path("tools/package_guest_images.S"), .flags = &.{ @@ -199,6 +232,11 @@ pub fn build(b: *std.Build) !void { exe.addObject(guest_images); b.installArtifact(exe); + var timer_driver: ?*std.Build.Step.InstallArtifact = null; + if (target.result.cpu.arch == .x86_64) { + timer_driver = b.addInstallArtifact(sddf_dep.artifact("driver_timer_hpet.elf"), .{ .dest_sub_path = "timer_driver_x86_64.elf" }); + } + const system_description_path = b.fmt("board/{s}/simple.system", .{ microkit_board }); const final_image_dest = b.getInstallPath(.bin, "./loader.img"); const microkit_tool_cmd = std.Build.Step.Run.create(b, "run microkit tool"); @@ -221,12 +259,15 @@ pub fn build(b: *std.Build) !void { // Add the "microkit" step, and make it the default step when we execute `zig build` const microkit_step = b.step("microkit", "Compile and build the final bootable image"); microkit_step.dependOn(µkit_tool_cmd.step); + if (timer_driver) |timer| { + microkit_step.dependOn(&timer.step); + } b.default_step = microkit_step; // This is setting up a `qemu` command for running the system using QEMU, // which we only want to do when we have a board that we can actually simulate. - const loader_arg = b.fmt("loader,file={s},addr=0x70000000,cpu-num=0", .{ final_image_dest }); if (microkit_board_option == .qemu_virt_aarch64) { + const loader_arg = b.fmt("loader,file={s},addr=0x70000000,cpu-num=0", .{ final_image_dest }); const qemu_cmd = b.addSystemCommand(&[_][]const u8{ "qemu-system-aarch64", "-machine", @@ -244,5 +285,34 @@ pub fn build(b: *std.Build) !void { qemu_cmd.step.dependOn(b.default_step); const simulate_step = b.step("qemu", "Simulate the image using QEMU"); simulate_step.dependOn(&qemu_cmd.step); + } else if (microkit_board_option == .x86_64_generic_vtx) { + const kernel = microkit_board_dir.path(b, "elf/sel4.elf"); + const kernel_objcopy = b.addSystemCommand(&.{ + "llvm-objcopy", "-O", "elf32-i386" + }); + kernel_objcopy.addFileArg(kernel); + kernel_objcopy.addFileInput(kernel); + const kernel32 = kernel_objcopy.addOutputFileArg("kernel32.elf"); + + const qemu_cmd = b.addSystemCommand(&[_][]const u8{ + "qemu-system-x86_64", + "-cpu", + "Nehalem,+fsgsbase,+pdpe1gb,+pcid,+invpcid,+xsave,+xsaves,+xsaveopt,+vmx,+vme", + "-accel", + "kvm", + "-m", + "4G", + "-display", "none", + "-serial", + "mon:stdio", + "-kernel", + b.getInstallPath(.prefix, "kernel32.elf"), + "-initrd", + b.getInstallPath(.bin, "loader.img"), + }); + qemu_cmd.step.dependOn(&b.addInstallFileWithDir(kernel32, .prefix, "kernel32.elf").step); + qemu_cmd.step.dependOn(b.default_step); + const simulate_step = b.step("qemu", "Simulate the image via QEMU"); + simulate_step.dependOn(&qemu_cmd.step); } } diff --git a/examples/simple/build.zig.zon b/examples/simple/build.zig.zon index b79fe42a8..e4b68877c 100644 --- a/examples/simple/build.zig.zon +++ b/examples/simple/build.zig.zon @@ -3,9 +3,7 @@ .version = "0.0.0", .dependencies = .{ - .libvmm = .{ - .path = "../../" - }, + .libvmm = .{ .path = "../../" }, .sddf = .{ .path = "../../dep/sddf", }, @@ -19,6 +17,16 @@ .hash = "rootfs_cpio_gz-0.0.0-AAAAAFuyCwDpUITQ72Vk5neE9sZHvBPQTXdJFAvR05wM", .lazy = true }, + .linux_x86_64 = .{ + .url = "https://trustworthy.systems/Downloads/libvmm/images/be4206493bcc7234a8713319b7c6280fa04f9c5a-bzImage.tar.gz", + .hash = "linux_x86_64-0.0.0-AAAAAADU3ADWi6sVP6IFUJ-PsCs8fDTAwv3hAIxaidVW", + .lazy = true + }, + .initrd_x86_64 = .{ + .url = "https://trustworthy.systems/Downloads/libvmm/images/d887a642236a92610a9537ab9f4a4aa1a966ad3a-rootfs.cpio.gz.tar.gz", + .hash = "initrd_x86_64-0.0.0-AAAAAJKgKADVLj-nFcMEMcipVGtzNapm0uqv_bYVsRef", + .lazy = true + } }, .paths = .{ "build.zig", diff --git a/examples/simple/simple.mk b/examples/simple/simple.mk index f4af1d865..5d2f8a3e6 100644 --- a/examples/simple/simple.mk +++ b/examples/simple/simple.mk @@ -3,7 +3,6 @@ # # SPDX-License-Identifier: BSD-2-Clause # -QEMU := qemu-system-aarch64 MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit @@ -18,13 +17,29 @@ SDDF_CUSTOM_LIBC := 1 vpath %.c $(LIBVMM) $(EXAMPLE_DIR) -IMAGES := vmm.elf - -LINUX ?= 85000f3f42a882e4476e57003d53f2bbec8262b0-linux -INITRD ?= 6dcd1debf64e6d69b178cd0f46b8c4ae7cebe2a5-rootfs.cpio.gz +ifeq ($(ARCH),aarch64) + LINUX ?= 85000f3f42a882e4476e57003d53f2bbec8262b0-linux + INITRD ?= 6dcd1debf64e6d69b178cd0f46b8c4ae7cebe2a5-rootfs.cpio.gz + ARCH_FLAGS := -target aarch64-none-elf -mstrict-align + VMM_NAME := vmm_aarch64 + IMAGES = $(VMM_NAME).elf + + QEMU := qemu-system-aarch64 + QEMU_ARCH_ARGS := -machine virt,virtualization=on -cpu cortex-a53 -device loader,file=$(IMAGE_FILE),addr=0x70000000,cpu-num=0 +else ifeq ($(ARCH),x86_64) + LINUX ?= be4206493bcc7234a8713319b7c6280fa04f9c5a-bzImage + INITRD ?= d887a642236a92610a9537ab9f4a4aa1a966ad3a-rootfs.cpio.gz + ARCH_FLAGS := -target x86_64-unknown-elf + VMM_NAME := vmm_x86_64 + IMAGES = $(VMM_NAME).elf timer_driver.elf + + QEMU := qemu-system-x86_64 + QEMU_ARCH_ARGS := -accel kvm -cpu host,+fsgsbase,+pdpe1gb,+xsaveopt,+xsave,+vmx,+vme -kernel $(KERNEL32) -initrd $(IMAGE_FILE) +else +$(error Unsupported ARCH given) +endif CFLAGS := \ - -mstrict-align \ -ffreestanding \ -g3 -O3 -Wall \ -Wno-unused-function \ @@ -36,7 +51,7 @@ CFLAGS := \ -I$(SDDF)/include/microkit \ -MD \ -MP \ - -target $(TARGET) + $(ARCH_FLAGS) LDFLAGS := -L$(BOARD_DIR)/lib LIBS := --start-group -lmicrokit -Tmicrokit.ld libvmm.a libsddf_util_debug.a --end-group @@ -47,7 +62,7 @@ $(CHECK_FLAGS_BOARD_MD5): -rm -f .board_cflags-* touch $@ -vmm.elf: vmm.o images.o +$(VMM_NAME).elf: vmm.o images.o $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ all: loader.img @@ -63,7 +78,11 @@ ${LINUX}: curl -L https://trustworthy.systems/Downloads/libvmm/images/${LINUX}.tar.gz -o $@.tar.gz mkdir -p linux_download_dir tar -xf $@.tar.gz -C linux_download_dir +ifeq ($(ARCH),aarch64) cp linux_download_dir/${LINUX}/linux ${LINUX} +else ifeq ($(ARCH),x86_64) + cp linux_download_dir/${LINUX}/bzImage ${LINUX} +endif ${INITRD}: curl -L https://trustworthy.systems/Downloads/libvmm/images/${INITRD}.tar.gz -o $@.tar.gz @@ -77,26 +96,39 @@ vm.dts: $(SYSTEM_DIR)/linux.dts $(SYSTEM_DIR)/overlay.dts vm.dtb: vm.dts $(DTC) -q -I dts -O dtb $< > $@ -vmm.o: $(EXAMPLE_DIR)/vmm.c $(CHECK_FLAGS_BOARD_MD5) +vmm.o: $(EXAMPLE_DIR)/$(VMM_NAME).c $(CHECK_FLAGS_BOARD_MD5) $(CC) $(CFLAGS) -c -o $@ $< +ifeq ($(ARCH),x86_64) +images.o: $(LIBVMM)/tools/package_guest_images.S $(LINUX) $(INITRD) + $(CC) -c -g3 -x assembler-with-cpp \ + -DGUEST_KERNEL_IMAGE_PATH=\"${LINUX}\" \ + -DGUEST_INITRD_IMAGE_PATH=\"${INITRD}\" \ + $(ARCH_FLAGS) \ + $(LIBVMM)/tools/package_guest_images.S -o $@ +else images.o: $(LIBVMM)/tools/package_guest_images.S $(LINUX) $(INITRD) vm.dtb $(CC) -c -g3 -x assembler-with-cpp \ -DGUEST_KERNEL_IMAGE_PATH=\"${LINUX}\" \ -DGUEST_DTB_IMAGE_PATH=\"vm.dtb\" \ -DGUEST_INITRD_IMAGE_PATH=\"${INITRD}\" \ - -target $(TARGET) \ + $(ARCH_FLAGS) \ $(LIBVMM)/tools/package_guest_images.S -o $@ +endif include $(LIBVMM)/vmm.mk include ${SDDF}/util/util.mk +ifeq ($(strip $(MICROKIT_BOARD)), x86_64_generic_vtx) +TIMER_DRIVER_DIR := hpet +TIMER_DRIVER := $(SDDF)/drivers/timer/$(TIMER_DRIVER_DIR) +include ${TIMER_DRIVER}/timer_driver.mk +endif + qemu: $(IMAGE_FILE) - if ! command -v $(QEMU) > /dev/null 2>&1; then echo "Could not find dependency: qemu-system-aarch64"; exit 1; fi - $(QEMU) -machine virt,virtualization=on,highmem=off,secure=off \ - -cpu cortex-a53 \ + if ! command -v $(QEMU) > /dev/null 2>&1; then echo "Could not find dependency: $(QEMU)"; exit 1; fi + $(QEMU) $(QEMU_ARCH_ARGS) \ -serial mon:stdio \ - -device loader,file=$(IMAGE_FILE),addr=0x70000000,cpu-num=0 \ -m size=2G \ -nographic diff --git a/examples/simple/vmm.c b/examples/simple/vmm_aarch64.c similarity index 100% rename from examples/simple/vmm.c rename to examples/simple/vmm_aarch64.c diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c new file mode 100644 index 000000000..e1e407d9a --- /dev/null +++ b/examples/simple/vmm_x86_64.c @@ -0,0 +1,126 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include +#include + +#include + +// @billn sus, use package asm script +#include "board/x86_64_generic_vtx/simple_dsdt.hex" + +uint64_t com1_ioport_id; +uint64_t com1_ioport_addr; +uint64_t com1_ioport_size = 8; + +#define COM1_IRQ_CH 0 + +#define GUEST_CMDLINE "earlyprintk=serial,0x3f8,115200 debug console=ttyS0,115200 earlycon=serial,0x3f8,115200 loglevel=8" + +/* Data for the guest's kernel image. */ +extern char _guest_kernel_image[]; +extern char _guest_kernel_image_end[]; +/* Data for the initial RAM disk to be passed to the kernel. */ +extern char _guest_initrd_image[]; +extern char _guest_initrd_image_end[]; +/* Microkit will set this variable to the start of the guest RAM memory region. */ +uintptr_t guest_ram_vaddr; +uint64_t guest_ram_size; + +uintptr_t guest_ecam_vaddr; +uint64_t guest_ecam_size; + +uintptr_t guest_vapic_vaddr; +uint64_t guest_vapic_size; +uint64_t guest_vapic_paddr; + +uintptr_t guest_apic_access_vaddr; +uint64_t guest_apic_access_size; +uint64_t guest_apic_access_paddr; + +// @billn unused, but have to leave it here otherwise linker complains, revisit +uintptr_t guest_flash_vaddr; +uint64_t guest_flash_size; +uintptr_t guest_high_ram_vaddr; +uint64_t guest_high_ram_size; + +bool tsc_calibrating = true; +linux_x86_setup_ret_t linux_setup; +uint64_t tsc_pre, tsc_post, measured_tsc_hz; + +void init(void) +{ + /* Initialise the VMM, the VCPU(s), and start the guest */ + LOG_VMM("starting \"%s\"\n", microkit_name); + /* Place all the binaries in the right locations before starting the guest */ + size_t kernel_size = _guest_kernel_image_end - _guest_kernel_image; + size_t initrd_size = _guest_initrd_image_end - _guest_initrd_image; + + if (!linux_setup_images(guest_ram_vaddr, guest_ram_size, (uintptr_t)_guest_kernel_image, kernel_size, + (uintptr_t)_guest_initrd_image, initrd_size, simple_dsdt_aml_code, + sizeof(simple_dsdt_aml_code), GUEST_CMDLINE, &linux_setup)) { + LOG_VMM_ERR("Failed to initialise guest images\n"); + return; + } + + assert(guest_vapic_size == 0x1000); + assert(guest_apic_access_size == 0x1000); + memset((void *)guest_vapic_vaddr, 0, guest_vapic_size); + memset((void *)guest_apic_access_vaddr, 0, guest_apic_access_size); + vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit, guest_vapic_paddr, + guest_apic_access_paddr); + + // Set up the PCI bus + assert(pci_x86_init()); + + /* Pass through COM1 serial port */ + microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, com1_ioport_id, com1_ioport_addr, com1_ioport_size); + microkit_irq_ack(COM1_IRQ_CH); + + LOG_VMM("Measuring TSC frequency...\n"); + sddf_timer_set_timeout(TIMER_DRV_CH_FOR_LAPIC, NS_IN_S); + tsc_pre = rdtsc(); +} + +void notified(microkit_channel ch) +{ + switch (ch) { + case TIMER_DRV_CH_FOR_LAPIC: { + if (tsc_calibrating) { + tsc_post = rdtsc(); + measured_tsc_hz = tsc_post - tsc_pre; + LOG_VMM("TSC frequency is %lu Hz\n", measured_tsc_hz); + tsc_calibrating = false; + + /* Initialise the virtual APIC */ + bool success = virq_controller_init(measured_tsc_hz, guest_vapic_vaddr); + if (!success) { + LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); + return; + } + + /* Pass through serial IRQs */ + assert(virq_ioapic_register_passthrough(0, 4, COM1_IRQ_CH)); + + guest_start(linux_setup.kernel_entry_gpa, 0, 0); + } else { + handle_lapic_timer_nftn(GUEST_BOOT_VCPU_ID); + } + break; + } + case TIMER_DRV_CH_FOR_HPET_CH0: + case TIMER_DRV_CH_FOR_HPET_CH1: + case TIMER_DRV_CH_FOR_HPET_CH2: + hpet_handle_timer_ntfn(ch); + break; + default: + if (!virq_ioapic_handle_passthrough(ch)) { + LOG_VMM_ERR("failed to passthrough IRQ ch %d\n", ch); + }; + } +} diff --git a/examples/simple/x86_64_images/README.md b/examples/simple/x86_64_images/README.md new file mode 100644 index 000000000..d60e431e8 --- /dev/null +++ b/examples/simple/x86_64_images/README.md @@ -0,0 +1,52 @@ + + +# Guest images used + +We use the mainline Linux kernel. + +Below are instructions for reproducing them. + +## Linux kernel + +### Details + +* Config name: `linux_config`, equivalent to `x86_64_defconfig` +* Git remote: https://github.com/torvalds/linux.git +* Tag: v6.19 (commit hash: `05f7e89ab9731565d8a62e3b5d1ec206485eeb0b`) +* Toolchain: `gcc` + * Version: gcc (Debian 15.2.0-15) 15.2.0 + +You can also get the Linux config used after booting by running the following +command in userspace: `zcat /proc/config.gz`. + +### Building + +```sh +git clone --depth 1 --branch v6.19 https://github.com/torvalds/linux.git +cp x86_64_defconfig linux/.config +make -C linux ARCH=x86_64 all -j$(nproc) +``` + +The path to the image is: `linux/arch/x86_64/boot/bzImage`. + +## Buildroot RootFS image + +### Details + +* Config name: `buildroot_config` +* Version: 2025.11-rc2 + +### Building + +```sh +wget https://buildroot.org/downloads/buildroot-2025.11-rc2.tar.xz +tar xvf buildroot-2025.11-rc2.tar.xz +cp buildroot_config buildroot-2025.11-rc2/.config +make -C buildroot-2025.11-rc2 +``` + +The root filesystem will be located at: `buildroot-2025.11-rc2/output/images/rootfs.cpio.gz` along +with the other buildroot artefacts. diff --git a/examples/simple/x86_64_images/buildroot_config b/examples/simple/x86_64_images/buildroot_config new file mode 100644 index 000000000..2dede0543 --- /dev/null +++ b/examples/simple/x86_64_images/buildroot_config @@ -0,0 +1,5102 @@ +# +# Automatically generated file; DO NOT EDIT. +# Buildroot 2025.11-rc2-5-gbd1831d161 Configuration +# +BR2_HAVE_DOT_CONFIG=y +BR2_HOST_GCC_AT_LEAST_4_9=y +BR2_HOST_GCC_AT_LEAST_5=y +BR2_HOST_GCC_AT_LEAST_6=y +BR2_HOST_GCC_AT_LEAST_7=y +BR2_HOST_GCC_AT_LEAST_8=y +BR2_HOST_GCC_AT_LEAST_9=y +BR2_HOST_GCC_AT_LEAST_10=y +BR2_HOST_GCC_AT_LEAST_11=y +BR2_HOST_GCC_AT_LEAST_12=y +BR2_HOST_GCC_AT_LEAST_13=y +BR2_HOST_GCC_AT_LEAST_14=y +BR2_HOST_GCC_AT_LEAST_15=y + +# +# Target options +# +BR2_USE_MMU=y +# BR2_arcle is not set +# BR2_arceb is not set +# BR2_arm is not set +# BR2_armeb is not set +# BR2_aarch64 is not set +# BR2_aarch64_be is not set +BR2_i386=y +# BR2_loongarch64 is not set +# BR2_m68k is not set +# BR2_microblazeel is not set +# BR2_microblazebe is not set +# BR2_mips is not set +# BR2_mipsel is not set +# BR2_mips64 is not set +# BR2_mips64el is not set +# BR2_or1k is not set +# BR2_powerpc is not set +# BR2_powerpc64 is not set +# BR2_powerpc64le is not set +# BR2_riscv is not set +# BR2_s390x is not set +# BR2_sh is not set +# BR2_sparc is not set +# BR2_sparc64 is not set +# BR2_x86_64 is not set +# BR2_xtensa is not set +BR2_ARCH_HAS_TOOLCHAIN_BUILDROOT=y +BR2_ARCH="i686" +BR2_NORMALIZED_ARCH="i386" +BR2_ENDIAN="LITTLE" +BR2_GCC_TARGET_ARCH="i686" +BR2_BINFMT_SUPPORTS_SHARED=y +BR2_READELF_ARCH_NAME="Intel 80386" +# BR2_x86_i486 is not set +# BR2_x86_i586 is not set +# BR2_x86_x1000 is not set +BR2_x86_i686=y +# BR2_x86_pentiumpro is not set +# BR2_x86_pentium_mmx is not set +# BR2_x86_pentium_m is not set +# BR2_x86_pentium2 is not set +# BR2_x86_pentium3 is not set +# BR2_x86_pentium4 is not set +# BR2_x86_prescott is not set +# BR2_x86_nocona is not set +# BR2_x86_core2 is not set +# BR2_x86_corei7 is not set +# BR2_x86_nehalem is not set +# BR2_x86_westmere is not set +# BR2_x86_corei7_avx is not set +# BR2_x86_sandybridge is not set +# BR2_x86_ivybridge is not set +# BR2_x86_core_avx2 is not set +# BR2_x86_haswell is not set +# BR2_x86_broadwell is not set +# BR2_x86_skylake is not set +# BR2_x86_atom is not set +# BR2_x86_bonnell is not set +# BR2_x86_silvermont is not set +# BR2_x86_goldmont is not set +# BR2_x86_goldmont_plus is not set +# BR2_x86_tremont is not set +# BR2_x86_sierraforest is not set +# BR2_x86_grandridge is not set +# BR2_x86_skylake_avx512 is not set +# BR2_x86_cannonlake is not set +# BR2_x86_icelake_client is not set +# BR2_x86_icelake_server is not set +# BR2_x86_cascadelake is not set +# BR2_x86_cooperlake is not set +# BR2_x86_tigerlake is not set +# BR2_x86_sapphirerapids is not set +# BR2_x86_alderlake is not set +# BR2_x86_rocketlake is not set +# BR2_x86_graniterapids is not set +# BR2_x86_graniterapids_d is not set +# BR2_x86_k6 is not set +# BR2_x86_k6_2 is not set +# BR2_x86_athlon is not set +# BR2_x86_athlon_4 is not set +# BR2_x86_opteron is not set +# BR2_x86_opteron_sse3 is not set +# BR2_x86_barcelona is not set +# BR2_x86_bobcat is not set +# BR2_x86_jaguar is not set +# BR2_x86_bulldozer is not set +# BR2_x86_piledriver is not set +# BR2_x86_steamroller is not set +# BR2_x86_excavator is not set +# BR2_x86_zen is not set +# BR2_x86_zen2 is not set +# BR2_x86_zen3 is not set +# BR2_x86_zen4 is not set +# BR2_x86_geode is not set +# BR2_x86_c3 is not set +# BR2_x86_c32 is not set +# BR2_x86_winchip_c6 is not set +# BR2_x86_winchip2 is not set +BR2_BINFMT_ELF=y + +# +# Toolchain +# +BR2_TOOLCHAIN=y +BR2_TOOLCHAIN_USES_GLIBC=y +BR2_TOOLCHAIN_BUILDROOT=y +# BR2_TOOLCHAIN_EXTERNAL is not set + +# +# Toolchain Buildroot Options +# +BR2_TOOLCHAIN_BUILDROOT_VENDOR="buildroot" +# BR2_TOOLCHAIN_BUILDROOT_UCLIBC is not set +BR2_TOOLCHAIN_BUILDROOT_GLIBC=y +# BR2_TOOLCHAIN_BUILDROOT_MUSL is not set +BR2_TOOLCHAIN_BUILDROOT_LIBC="glibc" + +# +# Kernel Header Options +# +# BR2_KERNEL_HEADERS_5_4 is not set +# BR2_KERNEL_HEADERS_5_10 is not set +# BR2_KERNEL_HEADERS_5_15 is not set +# BR2_KERNEL_HEADERS_6_1 is not set +# BR2_KERNEL_HEADERS_6_6 is not set +# BR2_KERNEL_HEADERS_6_12 is not set +BR2_KERNEL_HEADERS_6_17=y +# BR2_KERNEL_HEADERS_VERSION is not set +# BR2_KERNEL_HEADERS_CUSTOM_TARBALL is not set +# BR2_KERNEL_HEADERS_CUSTOM_GIT is not set +BR2_KERNEL_HEADERS_LATEST=y +BR2_DEFAULT_KERNEL_HEADERS="6.17.10" +BR2_PACKAGE_LINUX_HEADERS=y +BR2_PACKAGE_MUSL_ARCH_SUPPORTS=y +BR2_PACKAGE_MUSL_SUPPORTS=y +BR2_PACKAGE_UCLIBC_ARCH_SUPPORTS=y +BR2_PACKAGE_UCLIBC_SUPPORTS=y +BR2_PACKAGE_GLIBC_ARCH_SUPPORTS=y +BR2_PACKAGE_GLIBC_SUPPORTS=y + +# +# Glibc Options +# +BR2_PACKAGE_GLIBC=y +# BR2_PACKAGE_GLIBC_KERNEL_COMPAT is not set +# BR2_PACKAGE_GLIBC_UTILS is not set + +# +# Binutils Options +# +BR2_PACKAGE_HOST_BINUTILS_SUPPORTS_CFI=y +# BR2_BINUTILS_VERSION_2_42_X is not set +BR2_BINUTILS_VERSION_2_43_X=y +# BR2_BINUTILS_VERSION_2_44_X is not set +BR2_BINUTILS_VERSION="2.43.1" +# BR2_BINUTILS_GPROFNG is not set +BR2_BINUTILS_EXTRA_CONFIG_OPTIONS="" + +# +# GCC Options +# +# BR2_GCC_VERSION_13_X is not set +BR2_GCC_VERSION_14_X=y +# BR2_GCC_VERSION_15_X is not set +BR2_GCC_VERSION="14.3.0" +BR2_EXTRA_GCC_CONFIG_OPTIONS="" +# BR2_TOOLCHAIN_BUILDROOT_CXX is not set +# BR2_TOOLCHAIN_BUILDROOT_FORTRAN is not set +# BR2_GCC_ENABLE_OPENMP is not set +# BR2_GCC_ENABLE_GRAPHITE is not set +BR2_PACKAGE_GCC_FINAL=y +BR2_PACKAGE_HOST_GDB_ARCH_SUPPORTS=y + +# +# Host GDB Options +# +# BR2_PACKAGE_HOST_GDB is not set + +# +# Toolchain Generic Options +# +BR2_TOOLCHAIN_SUPPORTS_ALWAYS_LOCKFREE_ATOMIC_INTS=y +BR2_TOOLCHAIN_SUPPORTS_VARIADIC_MI_THUNK=y +BR2_USE_WCHAR=y +BR2_ENABLE_LOCALE=y +BR2_TOOLCHAIN_HAS_THREADS=y +BR2_TOOLCHAIN_HAS_THREADS_DEBUG=y +BR2_TOOLCHAIN_HAS_THREADS_NPTL=y +BR2_TOOLCHAIN_HAS_SSP=y +BR2_TOOLCHAIN_HAS_SSP_STRONG=y +BR2_TOOLCHAIN_HAS_UCONTEXT=y +BR2_TOOLCHAIN_SUPPORTS_PIE=y +# BR2_TOOLCHAIN_GLIBC_GCONV_LIBS_COPY is not set +BR2_TOOLCHAIN_EXTRA_LIBS="" +BR2_TOOLCHAIN_HAS_FULL_GETTEXT=y +BR2_TARGET_OPTIMIZATION="" +BR2_TARGET_LDFLAGS="" +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_0=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_1=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_2=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_3=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_4=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_5=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_6=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_7=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_8=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_9=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_10=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_11=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_12=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_13=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_14=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_15=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_16=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_17=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_18=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_19=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_0=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_1=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_2=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_3=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_4=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_5=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_6=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_7=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_8=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_9=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_10=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_11=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_12=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_13=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_14=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_15=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_16=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_17=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_18=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_19=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_4_20=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_0=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_1=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_2=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_3=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_4=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_5=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_6=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_7=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_8=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_9=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_10=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_11=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_12=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_13=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_14=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_15=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_16=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_17=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_18=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_5_19=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_0=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_1=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_2=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_3=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_4=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_5=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_6=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_7=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_8=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_9=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_10=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_11=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_12=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_13=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_14=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_15=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_16=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST_6_17=y +BR2_TOOLCHAIN_HEADERS_LATEST=y +BR2_TOOLCHAIN_HEADERS_AT_LEAST="6.17" +BR2_TOOLCHAIN_GCC_AT_LEAST_4_3=y +BR2_TOOLCHAIN_GCC_AT_LEAST_4_4=y +BR2_TOOLCHAIN_GCC_AT_LEAST_4_5=y +BR2_TOOLCHAIN_GCC_AT_LEAST_4_6=y +BR2_TOOLCHAIN_GCC_AT_LEAST_4_7=y +BR2_TOOLCHAIN_GCC_AT_LEAST_4_8=y +BR2_TOOLCHAIN_GCC_AT_LEAST_4_9=y +BR2_TOOLCHAIN_GCC_AT_LEAST_5=y +BR2_TOOLCHAIN_GCC_AT_LEAST_6=y +BR2_TOOLCHAIN_GCC_AT_LEAST_7=y +BR2_TOOLCHAIN_GCC_AT_LEAST_8=y +BR2_TOOLCHAIN_GCC_AT_LEAST_9=y +BR2_TOOLCHAIN_GCC_AT_LEAST_10=y +BR2_TOOLCHAIN_GCC_AT_LEAST_11=y +BR2_TOOLCHAIN_GCC_AT_LEAST_12=y +BR2_TOOLCHAIN_GCC_AT_LEAST_13=y +BR2_TOOLCHAIN_GCC_AT_LEAST_14=y +BR2_TOOLCHAIN_GCC_AT_LEAST="14" +BR2_TOOLCHAIN_HAS_MNAN_OPTION=y +BR2_TOOLCHAIN_HAS_SYNC_1=y +BR2_TOOLCHAIN_HAS_SYNC_2=y +BR2_TOOLCHAIN_HAS_SYNC_4=y +BR2_TOOLCHAIN_X86_HAS_SYNC_8=y +BR2_TOOLCHAIN_HAS_SYNC_8=y +BR2_TOOLCHAIN_HAS_LIBATOMIC=y +BR2_TOOLCHAIN_HAS_ATOMIC=y +BR2_TOOLCHAIN_HAS_LIBQUADMATH=y + +# +# Bare metal toolchain +# +# BR2_TOOLCHAIN_BARE_METAL_BUILDROOT is not set + +# +# Build options +# + +# +# Commands +# +BR2_CURL="curl -q --ftp-pasv --retry 3 --connect-timeout 10" +BR2_WGET="wget -nd -t 3 --connect-timeout=10" +BR2_SVN="svn --non-interactive --config-option servers:global:http-timeout=10" +BR2_BZR="bzr" +BR2_GIT="git" +BR2_CVS="cvs" +BR2_LOCALFILES="cp" +BR2_SCP="scp -o ConnectTimeout=10" +BR2_SFTP="sftp -o ConnectTimeout=10" +BR2_HG="hg" +BR2_ZCAT="gzip -d -c" +BR2_BZCAT="bzcat" +BR2_XZCAT="xzcat" +BR2_LZCAT="lzip -d -c" +BR2_ZSTDCAT="zstdcat" +BR2_TAR_OPTIONS="" +BR2_DEFCONFIG="$(CONFIG_DIR)/defconfig" +BR2_DL_DIR="$(TOPDIR)/dl" +BR2_HOST_DIR="$(BASE_DIR)/host" + +# +# Mirrors and Download locations +# +BR2_PRIMARY_SITE="" +BR2_BACKUP_SITE="https://sources.buildroot.net" +BR2_KERNEL_MIRROR="https://cdn.kernel.org/pub" +BR2_GNU_MIRROR="https://ftpmirror.gnu.org" +BR2_LUAROCKS_MIRROR="http://rocks.moonscript.org" +BR2_CPAN_MIRROR="https://cpan.metacpan.org" +BR2_JLEVEL=0 +# BR2_CCACHE is not set +# BR2_ENABLE_DEBUG is not set +# BR2_ENABLE_RUNTIME_DEBUG is not set +BR2_STRIP_strip=y +BR2_STRIP_EXCLUDE_FILES="" +BR2_STRIP_EXCLUDE_DIRS="" +# BR2_OPTIMIZE_0 is not set +# BR2_OPTIMIZE_1 is not set +BR2_OPTIMIZE_2=y +# BR2_OPTIMIZE_3 is not set +# BR2_OPTIMIZE_G is not set +# BR2_OPTIMIZE_S is not set +# BR2_OPTIMIZE_FAST is not set +# BR2_ENABLE_LTO is not set + +# +# static only needs a toolchain w/ uclibc or musl +# +BR2_SHARED_LIBS=y +# BR2_SHARED_STATIC_LIBS is not set +BR2_PACKAGE_OVERRIDE_FILE="$(CONFIG_DIR)/local.mk" +BR2_GLOBAL_PATCH_DIR="" + +# +# Advanced +# +# BR2_FORCE_HOST_BUILD is not set +# BR2_DOWNLOAD_FORCE_CHECK_HASHES is not set +# BR2_REPRODUCIBLE is not set +# BR2_PER_PACKAGE_DIRECTORIES is not set +# BR2_TIME_BITS_64 is not set + +# +# Security Hardening Options +# +BR2_PIC_PIE_ARCH_SUPPORTS=y +BR2_PIC_PIE=y +# BR2_SSP_NONE is not set +# BR2_SSP_REGULAR is not set +BR2_SSP_STRONG=y +# BR2_SSP_ALL is not set +BR2_SSP_OPTION="-fstack-protector-strong" +# BR2_RELRO_NONE is not set +# BR2_RELRO_PARTIAL is not set +BR2_RELRO_FULL=y +BR2_FORTIFY_SOURCE_ARCH_SUPPORTS=y +# BR2_FORTIFY_SOURCE_NONE is not set +BR2_FORTIFY_SOURCE_1=y +# BR2_FORTIFY_SOURCE_2 is not set +# BR2_FORTIFY_SOURCE_3 is not set + +# +# System configuration +# +BR2_ROOTFS_SKELETON_DEFAULT=y +# BR2_ROOTFS_SKELETON_CUSTOM is not set +BR2_TARGET_GENERIC_HOSTNAME="buildroot" +BR2_TARGET_GENERIC_ISSUE="Welcome to Buildroot" +BR2_TARGET_GENERIC_PASSWD_SHA256=y +# BR2_TARGET_GENERIC_PASSWD_SHA512 is not set +BR2_TARGET_GENERIC_PASSWD_METHOD="sha-256" + +# +# General purpose +# +BR2_INIT_BUSYBOX=y +# BR2_INIT_SYSV is not set +# BR2_INIT_OPENRC is not set +# BR2_INIT_SYSTEMD is not set + +# +# Special purpose (read help) +# +# BR2_INIT_CATATONIT is not set +# BR2_INIT_TINI is not set +# BR2_INIT_TINYINIT is not set +# BR2_INIT_NONE is not set +# BR2_ROOTFS_DEVICE_CREATION_STATIC is not set +BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_DEVTMPFS=y +# BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV is not set +# BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV is not set +BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt" +# BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES is not set +# BR2_ROOTFS_MERGED_USR is not set +BR2_TARGET_ENABLE_ROOT_LOGIN=y +BR2_TARGET_GENERIC_ROOT_PASSWD="" +BR2_SYSTEM_BIN_SH_BUSYBOX=y + +# +# bash, dash, mksh, zsh need BR2_PACKAGE_BUSYBOX_SHOW_OTHERS +# +# BR2_SYSTEM_BIN_SH_NONE is not set +BR2_TARGET_GENERIC_GETTY=y +BR2_TARGET_GENERIC_GETTY_PORT="console" +BR2_TARGET_GENERIC_GETTY_BAUDRATE_KEEP=y +# BR2_TARGET_GENERIC_GETTY_BAUDRATE_9600 is not set +# BR2_TARGET_GENERIC_GETTY_BAUDRATE_19200 is not set +# BR2_TARGET_GENERIC_GETTY_BAUDRATE_38400 is not set +# BR2_TARGET_GENERIC_GETTY_BAUDRATE_57600 is not set +# BR2_TARGET_GENERIC_GETTY_BAUDRATE_115200 is not set +BR2_TARGET_GENERIC_GETTY_BAUDRATE="0" +BR2_TARGET_GENERIC_GETTY_TERM="vt100" +BR2_TARGET_GENERIC_GETTY_OPTIONS="" +BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW=y +BR2_SYSTEM_DHCP="" +BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin" +BR2_ENABLE_LOCALE_PURGE=y +BR2_ENABLE_LOCALE_WHITELIST="C en_US" +BR2_GENERATE_LOCALE="" +# BR2_SYSTEM_ENABLE_NLS is not set +# BR2_TARGET_TZ_INFO is not set +BR2_ROOTFS_USERS_TABLES="" +BR2_ROOTFS_OVERLAY="" +BR2_ROOTFS_PRE_BUILD_SCRIPT="" +BR2_ROOTFS_POST_BUILD_SCRIPT="" +BR2_ROOTFS_POST_FAKEROOT_SCRIPT="" +BR2_ROOTFS_POST_IMAGE_SCRIPT="" + +# +# Kernel +# +# BR2_LINUX_KERNEL is not set + +# +# Target packages +# +BR2_PACKAGE_BUSYBOX=y +BR2_PACKAGE_BUSYBOX_CONFIG="package/busybox/busybox.config" +BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="" +# BR2_PACKAGE_BUSYBOX_SHOW_OTHERS is not set +# BR2_PACKAGE_BUSYBOX_INDIVIDUAL_BINARIES is not set +# BR2_PACKAGE_BUSYBOX_HTTPD is not set +# BR2_PACKAGE_BUSYBOX_WATCHDOG is not set +BR2_PACKAGE_SKELETON=y +BR2_PACKAGE_HAS_SKELETON=y +BR2_PACKAGE_PROVIDES_SKELETON="skeleton-init-sysv" +BR2_PACKAGE_SKELETON_INIT_COMMON=y +BR2_PACKAGE_SKELETON_INIT_SYSV=y + +# +# Audio and video applications +# +# BR2_PACKAGE_ALSA_UTILS is not set +# BR2_PACKAGE_ATEST is not set +# BR2_PACKAGE_AUMIX is not set +# BR2_PACKAGE_BLUEZ_ALSA is not set +# BR2_PACKAGE_DVBLAST is not set +# BR2_PACKAGE_DVDAUTHOR is not set + +# +# dvdrw-tools needs a toolchain w/ threads, C++, wchar +# + +# +# espeak needs a toolchain w/ C++, wchar, threads, dynamic library +# +# BR2_PACKAGE_FAAD2 is not set +BR2_PACKAGE_FFMPEG_ARCH_SUPPORTS=y +# BR2_PACKAGE_FFMPEG is not set +# BR2_PACKAGE_FLAC is not set +# BR2_PACKAGE_FLITE is not set +# BR2_PACKAGE_FLUID_SOUNDFONT is not set + +# +# fluidsynth needs a toolchain w/ threads, wchar, dynamic library, C++ +# +# BR2_PACKAGE_GMRENDER_RESURRECT is not set +# BR2_PACKAGE_GSTREAMER1 is not set +# BR2_PACKAGE_JACK1 is not set + +# +# jack2 needs a toolchain w/ threads, C++, dynamic library +# + +# +# kodi needs udev support for gbm +# + +# +# kodi needs an OpenGL EGL backend with OpenGL or GLES support +# +# BR2_PACKAGE_LAME is not set +# BR2_PACKAGE_MADPLAY is not set +# BR2_PACKAGE_MINIMODEM is not set + +# +# miraclecast needs systemd and a glibc toolchain w/ threads and wchar +# + +# +# mjpegtools needs a toolchain w/ C++, threads +# + +# +# modplugtools needs a toolchain w/ C++ +# +# BR2_PACKAGE_MOTION is not set + +# +# mpd needs a toolchain w/ C++, threads, wchar, host-gcc 10, gcc 12, headers 5.6 +# +# BR2_PACKAGE_MPD_MPC is not set +# BR2_PACKAGE_MPG123 is not set + +# +# mpv needs a toolchain w/ C++, NPTL, gcc >= 4.9 +# +# BR2_PACKAGE_MULTICAT is not set +# BR2_PACKAGE_MUSEPACK is not set + +# +# ncmpc needs a toolchain w/ C++, wchar, threads, gcc >= 10 +# +# BR2_PACKAGE_OPUS_TOOLS is not set +# BR2_PACKAGE_PIPEWIRE is not set +BR2_PACKAGE_PULSEAUDIO_HAS_ATOMIC=y +# BR2_PACKAGE_PULSEAUDIO is not set +# BR2_PACKAGE_SOX is not set +# BR2_PACKAGE_SPEECHD is not set +# BR2_PACKAGE_SQUEEZELITE is not set +# BR2_PACKAGE_TINYCOMPRESS is not set +# BR2_PACKAGE_TSTOOLS is not set +# BR2_PACKAGE_TWOLAME is not set +# BR2_PACKAGE_UDPXY is not set + +# +# upmpdcli needs a toolchain w/ C++, NPTL, gcc >= 4.9 +# + +# +# v4l2grab needs a toolchain w/ threads, dynamic library, C++ and headers >= 3.0 +# + +# +# v4l2loopback needs a Linux kernel to be built +# + +# +# vlc needs a toolchain w/ C++, dynamic library, wchar, threads, gcc >= 4.9, headers >= 3.7 +# +# BR2_PACKAGE_VORBIS_TOOLS is not set +# BR2_PACKAGE_WAVPACK is not set +# BR2_PACKAGE_YAVTA is not set +# BR2_PACKAGE_YMPD is not set + +# +# zynaddsubfx needs a toolchain w/ C++11 and threads +# + +# +# Compressors and decompressors +# +# BR2_PACKAGE_BROTLI is not set +# BR2_PACKAGE_BZIP2 is not set + +# +# lrzip needs a toolchain w/ wchar, threads, C++ +# + +# +# lzip needs a toolchain w/ C++ +# +# BR2_PACKAGE_LZOP is not set + +# +# p7zip needs a toolchain w/ threads, wchar, C++ +# +# BR2_PACKAGE_PIGZ is not set +# BR2_PACKAGE_PIXZ is not set + +# +# unrar needs a toolchain w/ C++, wchar, threads, gcc >= 4.8 +# +# BR2_PACKAGE_XZ is not set +# BR2_PACKAGE_ZIP is not set +# BR2_PACKAGE_ZSTD is not set + +# +# Debugging, profiling and benchmark +# +# BR2_PACKAGE_BABELTRACE2 is not set + +# +# bcc needs a glibc toolchain, C++, wchar, threads, dynamic libs, gcc >= 7, host gcc >= 7 +# +# BR2_PACKAGE_BLKTRACE is not set + +# +# bonnie++ needs a toolchain w/ C++ +# +BR2_PACKAGE_BPFTOOL_ARCH_SUPPORTS=y +# BR2_PACKAGE_BPFTOOL is not set +# BR2_PACKAGE_CACHE_CALIBRATOR is not set + +# +# clinfo needs an OpenCL provider +# + +# +# clpeak needs an OpenCL provider, a toolchain w/ C++, gcc >= 4.8 +# +# BR2_PACKAGE_COREMARK is not set +# BR2_PACKAGE_COREMARK_PRO is not set + +# +# dacapo needs OpenJDK +# +BR2_PACKAGE_DELVE_ARCH_SUPPORTS=y +# BR2_PACKAGE_DELVE is not set +# BR2_PACKAGE_DHRYSTONE is not set +# BR2_PACKAGE_DIEHARDER is not set +# BR2_PACKAGE_DMALLOC is not set +# BR2_PACKAGE_DROPWATCH is not set +# BR2_PACKAGE_DSTAT is not set +# BR2_PACKAGE_DT is not set + +# +# duma needs a toolchain w/ C++, threads, dynamic library +# +# BR2_PACKAGE_FIO is not set +BR2_PACKAGE_FWTS_ARCH_SUPPORTS=y +# BR2_PACKAGE_FWTS is not set +BR2_PACKAGE_GDB_ARCH_SUPPORTS=y + +# +# gdb/gdbserver >= 8.x needs a toolchain w/ C++, gcc >= 4.8 +# +BR2_PACKAGE_GOOGLE_BREAKPAD_ARCH_SUPPORTS=y + +# +# google-breakpad requires a glibc toolchain w/ wchar, threads, C++, gcc >= 7 +# +# BR2_PACKAGE_HYPERFINE is not set +# BR2_PACKAGE_IOZONE is not set +BR2_PACKAGE_KEXEC_ARCH_SUPPORTS=y +# BR2_PACKAGE_KEXEC is not set +# BR2_PACKAGE_KMEMD is not set +BR2_PACKAGE_KVM_UNIT_TESTS_ARCH_SUPPORTS=y +# BR2_PACKAGE_KVM_UNIT_TESTS is not set +# BR2_PACKAGE_LIBBPF is not set +# BR2_PACKAGE_LIBTRACEEVENT is not set +# BR2_PACKAGE_LIBTRACEFS is not set +# BR2_PACKAGE_LMBENCH is not set +BR2_PACKAGE_LTP_TESTSUITE_ARCH_SUPPORTS=y +# BR2_PACKAGE_LTP_TESTSUITE is not set +BR2_PACKAGE_LTRACE_ARCH_SUPPORTS=y +# BR2_PACKAGE_LTRACE is not set +# BR2_PACKAGE_LTTNG_BABELTRACE is not set + +# +# lttng-modules needs a Linux kernel to be built +# + +# +# lttng-tools needs a toolchain w/ threads, dynamic library, C++ +# +# BR2_PACKAGE_MBPOLL is not set +# BR2_PACKAGE_MBW is not set +# BR2_PACKAGE_MCELOG is not set +# BR2_PACKAGE_MEMSTAT is not set +# BR2_PACKAGE_NETPERF is not set + +# +# netsniff-ng needs a toolchain w/ NPTL, C++, headers >= 3.0 +# +# BR2_PACKAGE_NMON is not set +BR2_PACKAGE_OPROFILE_ARCH_SUPPORTS=y + +# +# oprofile needs a toolchain w/ C++, wchar +# +# BR2_PACKAGE_PAX_UTILS is not set + +# +# pcm-tools needs a toolchain w/ C++, NPTL +# +BR2_PACKAGE_PERFTEST_ARCH_SUPPORTS=y +# BR2_PACKAGE_PERFTEST is not set + +# +# piglit needs a glibc or musl toolchain w/ C++, gcc >= 9, host gcc >= 9 +# +# BR2_PACKAGE_POKE is not set +# BR2_PACKAGE_PV is not set + +# +# racehound needs an Linux kernel >= 3.14 to be built +# + +# +# racehound needs a toolchain w/ C++, wchar, dynamic library, threads +# +# BR2_PACKAGE_RT_TESTS is not set + +# +# rwmem needs a toolchain w/ C++, wchar, gcc >= 10 +# + +# +# sentry-native needs a glibc toolchain with w/ wchar, threads, C++, gcc >= 7 +# + +# +# signal-estimator needs a toochain w/ C++, threads, gcc >= 7 +# +# BR2_PACKAGE_SPIDEV_TEST is not set +# BR2_PACKAGE_STRACE is not set +# BR2_PACKAGE_STRESS is not set +# BR2_PACKAGE_STRESS_NG is not set + +# +# sysdig needs a glibc toolchain w/ C++, threads, gcc >= 8, dynamic library, a Linux kernel, and luajit or lua 5.1 to be built +# + +# +# sysprof needs a toolchain w/ dynamic library, wchar, threads, C++, gcc >= 7, headers >= 5.12 +# + +# +# tbtools needs udev /dev management w/ glibc toolchain +# +# BR2_PACKAGE_TCF_AGENT is not set +BR2_PACKAGE_TCF_AGENT_ARCH="i686" +BR2_PACKAGE_TCF_AGENT_ARCH_SUPPORTS=y +# BR2_PACKAGE_TRACE_CMD is not set +BR2_PACKAGE_TRINITY_ARCH_SUPPORTS=y +# BR2_PACKAGE_TRINITY is not set +# BR2_PACKAGE_UCLIBC_NG_TEST is not set +BR2_PACKAGE_UFTRACE_ARCH_SUPPORTS=y +# BR2_PACKAGE_UFTRACE is not set +BR2_PACKAGE_VALGRIND_ARCH_SUPPORTS=y +# BR2_PACKAGE_VALGRIND is not set +# BR2_PACKAGE_VMTOUCH is not set +# BR2_PACKAGE_WHETSTONE is not set + +# +# Development tools +# +# BR2_PACKAGE_AVOCADO is not set +# BR2_PACKAGE_BINUTILS is not set +# BR2_PACKAGE_BITWISE is not set +# BR2_PACKAGE_CHECK is not set +BR2_PACKAGE_CMAKE_ARCH_SUPPORTS=y + +# +# ctest needs a toolchain w/ C++, wchar, dynamic library, gcc >= 4.9, NPTL +# + +# +# cppunit needs a toolchain w/ C++, dynamic library +# +# BR2_PACKAGE_CUKINIA is not set +# BR2_PACKAGE_CUNIT is not set +# BR2_PACKAGE_CVS is not set + +# +# cxxtest needs a toolchain w/ C++ support +# +# BR2_PACKAGE_FD is not set +# BR2_PACKAGE_FLEX is not set +# BR2_PACKAGE_GETTEXT is not set +BR2_PACKAGE_PROVIDES_HOST_GETTEXT="host-gettext-tiny" +# BR2_PACKAGE_GIT is not set + +# +# git-crypt needs a toolchain w/ C++, gcc >= 4.9 +# + +# +# gperf needs a toolchain w/ C++ +# +# BR2_PACKAGE_JO is not set +# BR2_PACKAGE_JQ is not set +# BR2_PACKAGE_LIBTOOL is not set +# BR2_PACKAGE_MAKE is not set +# BR2_PACKAGE_MAWK is not set +# BR2_PACKAGE_PKGCONF is not set +# BR2_PACKAGE_RIPGREP is not set +# BR2_PACKAGE_SUBVERSION is not set +# BR2_PACKAGE_TIG is not set +# BR2_PACKAGE_TREE is not set +# BR2_PACKAGE_UNIFDEF is not set +# BR2_PACKAGE_YASM is not set + +# +# Filesystem and flash utilities +# +# BR2_PACKAGE_ABOOTIMG is not set +# BR2_PACKAGE_AUTOFS is not set + +# +# bmap-writer needs a toolchain w/ C++, wchar +# +# BR2_PACKAGE_BTRFS_PROGS is not set +# BR2_PACKAGE_CIFS_UTILS is not set +# BR2_PACKAGE_CPIO is not set +# BR2_PACKAGE_CRAMFS is not set +# BR2_PACKAGE_CURLFTPFS is not set +# BR2_PACKAGE_DAVFS2 is not set +# BR2_PACKAGE_DOSFSTOOLS is not set +# BR2_PACKAGE_DUST is not set +# BR2_PACKAGE_E2FSPROGS is not set +# BR2_PACKAGE_E2TOOLS is not set +# BR2_PACKAGE_ECRYPTFS_UTILS is not set +# BR2_PACKAGE_EROFS_UTILS is not set +# BR2_PACKAGE_EXFAT is not set +# BR2_PACKAGE_EXFAT_UTILS is not set +# BR2_PACKAGE_EXFATPROGS is not set +# BR2_PACKAGE_F2FS_TOOLS is not set +# BR2_PACKAGE_FIRMWARE_UTILS is not set +# BR2_PACKAGE_FLASHBENCH is not set +# BR2_PACKAGE_FSCRYPTCTL is not set +# BR2_PACKAGE_FUSE_OVERLAYFS is not set +# BR2_PACKAGE_FWUP is not set +# BR2_PACKAGE_GENEXT2FS is not set +# BR2_PACKAGE_GENPART is not set +# BR2_PACKAGE_GOCRYPTFS is not set +# BR2_PACKAGE_IMX_USB_LOADER is not set +# BR2_PACKAGE_MMC_UTILS is not set +# BR2_PACKAGE_MTD is not set +# BR2_PACKAGE_MTOOLS is not set +# BR2_PACKAGE_NFS_UTILS is not set +# BR2_PACKAGE_NILFS_UTILS is not set +# BR2_PACKAGE_NTFS_3G is not set +# BR2_PACKAGE_SP_OOPS_EXTRACT is not set +# BR2_PACKAGE_SQUASHFS is not set +# BR2_PACKAGE_SSHFS is not set +# BR2_PACKAGE_UDFTOOLS is not set +# BR2_PACKAGE_UFS_UTILS is not set +# BR2_PACKAGE_UNIONFS is not set + +# +# xfsprogs needs a toolchain w/ threads, C++ +# +# BR2_PACKAGE_ZEROFREE is not set + +# +# zfs needs a Linux kernel to be built +# + +# +# Fonts, cursors, icons, sounds and themes +# + +# +# Cursors +# +# BR2_PACKAGE_COMIX_CURSORS is not set + +# +# Fonts +# +# BR2_PACKAGE_BITSTREAM_VERA is not set +# BR2_PACKAGE_CANTARELL is not set +# BR2_PACKAGE_DEJAVU is not set +# BR2_PACKAGE_FONT_AWESOME is not set +# BR2_PACKAGE_GHOSTSCRIPT_FONTS is not set +# BR2_PACKAGE_INCONSOLATA is not set +# BR2_PACKAGE_LIBERATION is not set +# BR2_PACKAGE_WQY_ZENHEI is not set + +# +# Icons +# +# BR2_PACKAGE_HICOLOR_ICON_THEME is not set + +# +# Sounds +# +# BR2_PACKAGE_SOUND_THEME_BOREALIS is not set +# BR2_PACKAGE_SOUND_THEME_FREEDESKTOP is not set + +# +# Games +# +# BR2_PACKAGE_ASCII_INVADERS is not set +# BR2_PACKAGE_CHOCOLATE_DOOM is not set + +# +# flare-engine needs a toolchain w/ C++, dynamic library +# + +# +# gnuchess needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LBREAKOUT2 is not set +# BR2_PACKAGE_LTRIS is not set + +# +# minetest needs a toolchain w/ C++, gcc >= 9, threads +# +# BR2_PACKAGE_OPENTYRIAN is not set +# BR2_PACKAGE_PRBOOM is not set +# BR2_PACKAGE_SL is not set + +# +# solarus needs OpenGL and a toolchain w/ C++, gcc >= 9, NPTL, dynamic library, and luajit or lua 5.1 +# + +# +# stella needs a toolchain w/ dynamic library, C++, threads, gcc >= 7 +# +# BR2_PACKAGE_XORCURSES is not set + +# +# Graphic libraries and applications (graphic/text) +# + +# +# Graphic applications +# + +# +# cage needs udev, EGL and OpenGL ES support +# + +# +# cog needs wpewebkit and a toolchain w/ threads +# + +# +# flutter packages need flutter-engine +# + +# +# flutter-pi needs GBM, systemd, and udev +# +# BR2_PACKAGE_FOOT is not set +# BR2_PACKAGE_FSWEBCAM is not set +# BR2_PACKAGE_GHOSTSCRIPT is not set + +# +# glmark2 needs a toolchain w/ C++, gcc >= 4.9 +# + +# +# glslsandbox-player needs openGL ES and EGL driver +# +# BR2_PACKAGE_GNUPLOT is not set + +# +# igt-gpu-tools needs udev /dev management and toolchain w/ NPTL, wchar, dynamic library, locale, headers >= 4.11 +# +# BR2_PACKAGE_JHEAD is not set + +# +# kmscube needs EGL, GBM and OpenGL ES, and a toolchain w/ thread support +# + +# +# libva-utils needs a toolchain w/ C++, threads, dynamic library +# +BR2_PACKAGE_NETSURF_ARCH_SUPPORTS=y +# BR2_PACKAGE_NETSURF is not set +# BR2_PACKAGE_PNGQUANT is not set +# BR2_PACKAGE_RRDTOOL is not set + +# +# spirv-translator needs a toolchain w/ wchar, threads, C++, gcc >= 7, dynamic library, host gcc >= 7 +# + +# +# spirv-tools needs a toolchain w/ C++, dynamic library, gcc >= 8 +# + +# +# stellarium needs Qt5 and an OpenGL provider +# + +# +# sway needs systemd, udev, EGL and OpenGL ES support +# + +# +# sway needs a toolchain w/ wchar, threads, C++, dynamic library, gcc >= 4.9 +# +# BR2_PACKAGE_SWAYBG is not set + +# +# tesseract-ocr needs a toolchain w/ threads, C++, gcc >= 8, dynamic library, wchar +# +# BR2_PACKAGE_TINIFIER is not set + +# +# wmenu needs a toolchain w/ wchar, threads, C++, dynamic library, gcc >= 4.9 +# + +# +# Graphic libraries +# + +# +# cegui needs a toolchain w/ C++, threads, dynamic library, wchar, gcc >= 5 +# + +# +# efl needs a toolchain w/ C++, dynamic library, gcc >= 4.9, host gcc >= 4.9, threads, wchar +# +# BR2_PACKAGE_FB_TEST_APP is not set +# BR2_PACKAGE_FBDUMP is not set +# BR2_PACKAGE_FBGRAB is not set + +# +# fbterm needs a toolchain w/ C++, wchar, locale +# +# BR2_PACKAGE_FBV is not set + +# +# freerdp needs a toolchain w/ wchar, dynamic library, threads, C++ +# +# BR2_PACKAGE_GRAPHICSMAGICK is not set +# BR2_PACKAGE_IMAGEMAGICK is not set +# BR2_PACKAGE_LIBGLVND is not set + +# +# mesa3d needs a toolchain w/ gcc >=8, C++, NPTL, dynamic library +# + +# +# ocrad needs a toolchain w/ C++ +# + +# +# ogre needs a toolchain w/ C++, dynamic library, gcc >= 4.8, threads, wchar +# +# BR2_PACKAGE_PSPLASH is not set +# BR2_PACKAGE_SDL is not set +# BR2_PACKAGE_SDL2 is not set + +# +# spirv-headers needs a toolchain w/ C++ +# + +# +# vulkan-headers needs a toolchain w/ C++ +# + +# +# vulkan-loader needs a toolchain w/ C++, dynamic library, threads +# + +# +# Vulkan-SDK needs toolchain w/ C++, dynamic library +# + +# +# vulkan-tools needs a toolchain w/ C++, dynamic library, threads, gcc >= 4.9 +# + +# +# Other GUIs +# +BR2_PACKAGE_QT5_JSCORE_AVAILABLE=y + +# +# Qt5 needs host g++ >= 5.0, and a toolchain w/ gcc >= 5.0, wchar, NPTL, C++, dynamic library +# +BR2_PACKAGE_QT6_ARCH_SUPPORTS=y + +# +# qt6 needs a toolchain w/ C++, threads, wchar, dynamic library, gcc >= 8, host gcc >= 8 +# + +# +# tekui needs a Lua interpreter and a toolchain w/ threads, dynamic library +# + +# +# weston needs udev and a toolchain w/ locale, threads, dynamic library, headers >= 3.0 +# +# BR2_PACKAGE_XORG7 is not set + +# +# apitrace needs a toolchain w/ C++, wchar, dynamic library, threads, gcc >= 7 +# + +# +# mupdf needs a toolchain w/ C++, gcc >= 4.9 +# + +# +# pcmanfm a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# + +# +# pcmanfm needs X.org with an OpenGL backend +# + +# +# vte needs a uClibc or glibc toolchain w/ wchar, threads, C++, gcc >= 10 +# + +# +# vte needs an OpenGL or an OpenGL-EGL backend +# + +# +# yad needs libgtk3 w/ X11 backend +# +# BR2_PACKAGE_XKEYBOARD_CONFIG is not set + +# +# Hardware handling +# + +# +# Firmware +# +# BR2_PACKAGE_ARMBIAN_FIRMWARE is not set +# BR2_PACKAGE_B43_FIRMWARE is not set +# BR2_PACKAGE_BRCMFMAC_SDIO_FIRMWARE_RPI is not set +# BR2_PACKAGE_LINUX_FIRMWARE is not set +# BR2_PACKAGE_MURATA_CYW_FW is not set +# BR2_PACKAGE_NXP_BT_WIFI_FIRMWARE is not set +# BR2_PACKAGE_ODROIDC2_FIRMWARE is not set +# BR2_PACKAGE_PANEL_MIPI_DBI_FIRMWARE is not set +# BR2_PACKAGE_QCOM_DB410C_FIRMWARE is not set +# BR2_PACKAGE_QORIQ_DDR_PHY_BINARY is not set +# BR2_PACKAGE_QORIQ_FIRMWARE_INPHI is not set +# BR2_PACKAGE_QORIQ_FM_UCODE is not set +# BR2_PACKAGE_QORIQ_MC_BINARY is not set +# BR2_PACKAGE_QORIQ_MC_UTILS is not set +# BR2_PACKAGE_RCW_SMARC_SAL28 is not set +# BR2_PACKAGE_UX500_FIRMWARE is not set +# BR2_PACKAGE_WILC1000_FIRMWARE is not set +# BR2_PACKAGE_WILC3000_FIRMWARE is not set +# BR2_PACKAGE_WILINK_BT_FIRMWARE is not set +# BR2_PACKAGE_ZD1211_FIRMWARE is not set +# BR2_PACKAGE_18XX_TI_UTILS is not set +# BR2_PACKAGE_ACPICA is not set +# BR2_PACKAGE_ACPID is not set + +# +# acpitool needs a toolchain w/ threads, C++, dynamic library +# +# BR2_PACKAGE_AER_INJECT is not set +# BR2_PACKAGE_ALTERA_STAPL is not set + +# +# apcupsd needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_AVRDUDE is not set + +# +# bcache-tools needs udev /dev management +# +# BR2_PACKAGE_BFSCRIPTS is not set + +# +# brickd needs udev /dev management, a toolchain w/ threads, wchar +# +# BR2_PACKAGE_BRLTTY is not set + +# +# cc-tool needs a toolchain w/ C++, threads, wchar, gcc >= 4.9 +# +# BR2_PACKAGE_CDRKIT is not set +# BR2_PACKAGE_CRUCIBLE is not set +# BR2_PACKAGE_CRYPTSETUP is not set +# BR2_PACKAGE_CWIID is not set + +# +# dahdi-linux needs a Linux kernel to be built +# + +# +# dahdi-tools needs a toolchain w/ threads and a Linux kernel to be built +# +# BR2_PACKAGE_DBUS is not set + +# +# dbusbroker needs systemd and a toolchain w/ threads +# + +# +# dbus-cxx needs a toolchain w/ C++, threads, gcc >= 7 and dynamic library support +# +# BR2_PACKAGE_DFU_PROGRAMMER is not set +# BR2_PACKAGE_DFU_UTIL is not set +# BR2_PACKAGE_DMIDECODE is not set +# BR2_PACKAGE_DMRAID is not set + +# +# dt-utils needs udev /dev management +# + +# +# dtbocfg needs a Linux kernel to be built +# +# BR2_PACKAGE_DTV_SCAN_TABLES is not set +# BR2_PACKAGE_DUMP1090 is not set + +# +# edid-decode needs a toolchain w/ C++, gcc >= 4.7 +# + +# +# esp-hosted needs a Linux kernel to be built +# + +# +# espflash needs udev /dev management +# + +# +# eudev needs eudev /dev management +# +# BR2_PACKAGE_EVEMU is not set +# BR2_PACKAGE_EVTEST is not set +BR2_PACKAGE_FLASHROM_ARCH_SUPPORTS=y +# BR2_PACKAGE_FLASHROM is not set +# BR2_PACKAGE_FMTOOLS is not set +# BR2_PACKAGE_FREEIPMI is not set +# BR2_PACKAGE_FWUPD is not set +# BR2_PACKAGE_FWUPD_EFI is not set +# BR2_PACKAGE_FXLOAD is not set +# BR2_PACKAGE_GPM is not set +# BR2_PACKAGE_GPSD is not set + +# +# gptfdisk needs a toolchain w/ C++ +# +# BR2_PACKAGE_GVFS is not set +# BR2_PACKAGE_HDDTEMP is not set +# BR2_PACKAGE_HWDATA is not set +# BR2_PACKAGE_HWLOC is not set +# BR2_PACKAGE_I7Z is not set +# BR2_PACKAGE_INPUT_EVENT_DAEMON is not set +# BR2_PACKAGE_INTEL_MICROCODE is not set +# BR2_PACKAGE_IOTOOLS is not set +# BR2_PACKAGE_IPMITOOL is not set +# BR2_PACKAGE_IPMIUTIL is not set +# BR2_PACKAGE_IRDA_UTILS is not set +# BR2_PACKAGE_IUCODE_TOOL is not set +# BR2_PACKAGE_KBD is not set +# BR2_PACKAGE_LCDPROC is not set + +# +# ledmon needs udev and a toolchain w/ threads +# + +# +# libiec61850 needs a toolchain w/ C++, threads, dynamic library +# + +# +# libmanette needs a toolchain w/ wchar, NPTL threads, gcc >= 4.9, headers >= 4.16, udev +# +# BR2_PACKAGE_LIBUBOOTENV is not set +# BR2_PACKAGE_LIBUIO is not set + +# +# linux-backports needs a Linux kernel to be built +# +# BR2_PACKAGE_LINUX_SERIAL_TEST is not set +# BR2_PACKAGE_LINUXCONSOLETOOLS is not set + +# +# lirc-tools needs a toolchain w/ threads, dynamic library, C++ +# +# BR2_PACKAGE_LM_SENSORS is not set + +# +# lshw needs a toolchain w/ C++, wchar +# +# BR2_PACKAGE_LSSCSI is not set +# BR2_PACKAGE_LSUIO is not set +# BR2_PACKAGE_LUKSMETA is not set +# BR2_PACKAGE_LVM2 is not set + +# +# mali-driver needs a Linux kernel to be built +# +# BR2_PACKAGE_MBPFAN is not set +# BR2_PACKAGE_MDADM is not set +# BR2_PACKAGE_MDEVD is not set + +# +# mdio-tools needs a Linux kernel to be built +# +# BR2_PACKAGE_MEMTEST86 is not set +# BR2_PACKAGE_MEMTESTER is not set +# BR2_PACKAGE_MEMTOOL is not set +# BR2_PACKAGE_MHZ is not set +# BR2_PACKAGE_MINICOM is not set +# BR2_PACKAGE_MSR_TOOLS is not set +# BR2_PACKAGE_MXT_APP is not set +# BR2_PACKAGE_NANOCOM is not set +# BR2_PACKAGE_NEARD is not set +# BR2_PACKAGE_NVIDIA_DRIVER is not set +# BR2_PACKAGE_NVIDIA_MODPROBE is not set +# BR2_PACKAGE_NVIDIA_PERSISTENCED is not set +# BR2_PACKAGE_NVME is not set + +# +# nxp-mwifiex needs a Linux kernel to be built +# +# BR2_PACKAGE_OFONO is not set +# BR2_PACKAGE_OPEN2300 is not set + +# +# openfpgaloader needs a toolchain w/ threads, C++, gcc >= 4.9 +# +# BR2_PACKAGE_OPENIPMI is not set +# BR2_PACKAGE_OPENOCD is not set + +# +# openpowerlink needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_PARTED is not set +BR2_PACKAGE_PCIUTILS=y +# BR2_PACKAGE_PDBG is not set +# BR2_PACKAGE_PICOCOM is not set + +# +# picotool needs a toolchain w/ C++, threads, gcc >= 4.9 +# + +# +# powertop needs a toolchain w/ C++, threads, wchar +# +# BR2_PACKAGE_PPS_TOOLS is not set + +# +# pulseview needs a toolchain w/ locale, wchar, threads, dynamic library, C++, gcc >= 7, host gcc >= 5 +# +# BR2_PACKAGE_QORIQ_CADENCE_DP_FIRMWARE is not set +# BR2_PACKAGE_RASPI_GPIO is not set +# BR2_PACKAGE_RDMA_CORE is not set +# BR2_PACKAGE_READ_EDID is not set +# BR2_PACKAGE_RNG_TOOLS is not set +# BR2_PACKAGE_RS485CONF is not set +# BR2_PACKAGE_RTC_TOOLS is not set + +# +# rtl8188eu needs a Linux kernel to be built +# + +# +# rtl8189es needs a Linux kernel to be built +# + +# +# rtl8189fs needs a Linux kernel to be built +# + +# +# rtl8192eu needs a Linux kernel to be built +# + +# +# rtl8723bu needs a Linux kernel to be built +# + +# +# rtl8723ds needs a Linux kernel to be built +# +# BR2_PACKAGE_RTL8723DS_BT is not set + +# +# rtl8812au-aircrack-ng needs a Linux kernel to be built +# + +# +# rtl8821au needs a Linux kernel to be built +# + +# +# rtl8821cu needs a Linux kernel to be built +# + +# +# rl8822cs needs a Linux kernel to be built +# +# BR2_PACKAGE_SANE_AIRSCAN is not set +# BR2_PACKAGE_SANE_BACKENDS is not set +# BR2_PACKAGE_SDPARM is not set +BR2_PACKAGE_SEDUTIL_ARCH_SUPPORTS=y + +# +# sedutil needs a toolchain w/ C++, gcc >= 4.8, headers >= 3.12 +# +# BR2_PACKAGE_SETSERIAL is not set +# BR2_PACKAGE_SG3_UTILS is not set +# BR2_PACKAGE_SIGROK_CLI is not set +# BR2_PACKAGE_SISPMCTL is not set + +# +# smartmontools needs a toolchain w/ C++ +# +# BR2_PACKAGE_SMSTOOLS3 is not set +# BR2_PACKAGE_SPI_TOOLS is not set +# BR2_PACKAGE_SREDIRD is not set +# BR2_PACKAGE_STATSERIAL is not set +# BR2_PACKAGE_STM32FLASH is not set +# BR2_PACKAGE_SUPERIOTOOL is not set +# BR2_PACKAGE_SYSSTAT is not set +# BR2_PACKAGE_TI_UIM is not set +# BR2_PACKAGE_TI_UTILS is not set + +# +# tio needs lua (but not luajit) +# +# BR2_PACKAGE_TRIGGERHAPPY is not set +# BR2_PACKAGE_UBOOT_BOOTCOUNT is not set +# BR2_PACKAGE_UBOOT_TOOLS is not set +# BR2_PACKAGE_UBUS is not set + +# +# udisks needs udev /dev management +# +# BR2_PACKAGE_UHUBCTL is not set +# BR2_PACKAGE_UMTPRD is not set + +# +# upower needs udev /dev management +# +# BR2_PACKAGE_USB_MODESWITCH is not set +# BR2_PACKAGE_USB_MODESWITCH_DATA is not set + +# +# usbguard needs a toolchain w/ C++, threads, dynamic library, gcc >= 8 +# + +# +# usbip needs udev /dev management +# + +# +# usbmount requires udev to be enabled +# + +# +# usbutils needs udev /dev management and toolchain w/ threads, gcc >= 4.9 +# + +# +# wf111 needs a Linux kernel to be built +# + +# +# wilc kernel module needs a Linux kernel to be built +# +# BR2_PACKAGE_WIPE is not set +# BR2_PACKAGE_XORRISO is not set + +# +# xr819-xradio driver needs a Linux kernel to be built +# + +# +# Interpreter languages and scripting +# +# BR2_PACKAGE_4TH is not set +# BR2_PACKAGE_CHICKEN is not set +# BR2_PACKAGE_ENSCRIPT is not set +BR2_PACKAGE_HOST_ERLANG_ARCH_SUPPORTS=y +BR2_PACKAGE_ERLANG_ARCH_SUPPORTS=y +# BR2_PACKAGE_ERLANG is not set +# BR2_PACKAGE_EXECLINE is not set +# BR2_PACKAGE_FICL is not set +BR2_PACKAGE_GAUCHE_ARCH_SUPPORTS=y +# BR2_PACKAGE_GAUCHE is not set +# BR2_PACKAGE_GUILE is not set +# BR2_PACKAGE_HASERL is not set +# BR2_PACKAGE_JANET is not set +# BR2_PACKAGE_JIMTCL is not set +# BR2_PACKAGE_LUA is not set +BR2_PACKAGE_PROVIDES_HOST_LUAINTERPRETER="host-lua" +BR2_PACKAGE_LUAJIT_ARCH_SUPPORTS=y +# BR2_PACKAGE_LUAJIT is not set +# BR2_PACKAGE_MICROPYTHON is not set +# BR2_PACKAGE_MOARVM is not set +BR2_PACKAGE_HOST_MONO_ARCH_SUPPORTS=y +BR2_PACKAGE_MONO_ARCH_SUPPORTS=y + +# +# mono needs a toolchain w/ C++, NPTL, dynamic library +# +BR2_PACKAGE_NODEJS_ARCH_SUPPORTS=y + +# +# nodejs needs a toolchain w/ C++, dynamic library, NPTL, gcc >= 10, wchar, host gcc >= 10 +# +BR2_PACKAGE_PROVIDES_NODEJS="nodejs-src" + +# +# octave needs a toolchain w/ C++ and fortran, gcc >= 7 +# +BR2_PACKAGE_HOST_OPENJDK_BIN_ARCH_SUPPORTS=y +BR2_PACKAGE_OPENJDK_ARCH_SUPPORTS=y + +# +# openjdk needs X.Org +# + +# +# openjdk needs glibc, and a toolchain w/ wchar, dynamic library, threads, C++, gcc >= 4.9, host gcc >= 4.9 +# +# BR2_PACKAGE_PERL is not set +BR2_PACKAGE_PHP_ARCH_SUPPORTS=y +# BR2_PACKAGE_PHP is not set +# BR2_PACKAGE_PYTHON3 is not set +# BR2_PACKAGE_QUICKJS is not set +# BR2_PACKAGE_RUBY is not set +BR2_PACKAGE_SWIPL_ARCH_SUPPORTS=y +# BR2_PACKAGE_SWIPL is not set +# BR2_PACKAGE_TCL is not set + +# +# Libraries +# + +# +# Audio/Sound +# +# BR2_PACKAGE_ALSA_LIB is not set + +# +# alure needs a toolchain w/ C++, gcc >= 9, NPTL, wchar +# +# BR2_PACKAGE_AUBIO is not set +# BR2_PACKAGE_BCG729 is not set + +# +# caps needs a toolchain w/ C++, dynamic library +# +BR2_PACKAGE_FDK_AAC_ARCH_SUPPORTS=y + +# +# fdk-aac needs a toolchain w/ C++ +# +BR2_PACKAGE_GTKIOSTREAM_ARCH_SUPPORTS=y + +# +# gtkiostream needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBAO is not set +# BR2_PACKAGE_LIBBROADVOICE is not set +# BR2_PACKAGE_LIBCANBERRA is not set +# BR2_PACKAGE_LIBCDAUDIO is not set +# BR2_PACKAGE_LIBCDDB is not set +# BR2_PACKAGE_LIBCDIO is not set +# BR2_PACKAGE_LIBCDIO_PARANOIA is not set +# BR2_PACKAGE_LIBCODEC2 is not set +# BR2_PACKAGE_LIBCUE is not set +# BR2_PACKAGE_LIBCUEFILE is not set +# BR2_PACKAGE_LIBG7221 is not set +# BR2_PACKAGE_LIBGSM is not set +# BR2_PACKAGE_LIBID3TAG is not set +# BR2_PACKAGE_LIBILBC is not set +# BR2_PACKAGE_LIBLO is not set +# BR2_PACKAGE_LIBMAD is not set + +# +# libmodplug needs a toolchain w/ C++ +# +# BR2_PACKAGE_LIBMPDCLIENT is not set + +# +# libopenmpt needs a toolchain w/ threads, C++, gcc >= 7 +# +# BR2_PACKAGE_LIBREPLAYGAIN is not set +# BR2_PACKAGE_LIBSAMPLERATE is not set + +# +# libsidplay2 needs a toolchain w/ C++ +# +# BR2_PACKAGE_LIBSILK is not set +# BR2_PACKAGE_LIBSNDFILE is not set + +# +# libsoundtouch needs a toolchain w/ C++ +# +# BR2_PACKAGE_LIBSOXR is not set +# BR2_PACKAGE_LIBVORBIS is not set +# BR2_PACKAGE_LILV is not set +# BR2_PACKAGE_LV2 is not set + +# +# mp4v2 needs a toolchain w/ C++ +# +BR2_PACKAGE_OPENAL_ARCH_SUPPORTS=y + +# +# openal needs a toolchain w/ NPTL, C++, gcc >= 7 +# + +# +# opencore-amr needs a toolchain w/ C++ +# +# BR2_PACKAGE_OPUS is not set +# BR2_PACKAGE_OPUSFILE is not set +# BR2_PACKAGE_PORTAUDIO is not set +# BR2_PACKAGE_RNNOISE is not set +# BR2_PACKAGE_SBC is not set +# BR2_PACKAGE_SPANDSP is not set +# BR2_PACKAGE_SPEEX is not set +# BR2_PACKAGE_SPEEXDSP is not set +# BR2_PACKAGE_SRATOM is not set + +# +# taglib needs a toolchain w/ C++, wchar +# +# BR2_PACKAGE_TINYALSA is not set +# BR2_PACKAGE_TREMOR is not set +# BR2_PACKAGE_VO_AACENC is not set +BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING_ARCH_SUPPORTS=y + +# +# webrtc-audio-processing needs a toolchain w/ C++, NPTL, dynamic library, gcc >= 8 +# + +# +# Compression and decompression +# +# BR2_PACKAGE_LIBARCHIVE is not set +# BR2_PACKAGE_LIBDEFLATE is not set +# BR2_PACKAGE_LIBJCAT is not set +# BR2_PACKAGE_LIBMSPACK is not set + +# +# libsquish needs a toolchain w/ C++ +# +# BR2_PACKAGE_LIBZIP is not set +# BR2_PACKAGE_LZ4 is not set +# BR2_PACKAGE_LZO is not set +# BR2_PACKAGE_MINIZIP is not set +# BR2_PACKAGE_MINIZIP_ZLIB is not set + +# +# snappy needs a toolchain w/ C++ +# +# BR2_PACKAGE_SZIP is not set +# BR2_PACKAGE_ZCHUNK is not set +BR2_PACKAGE_ZLIB_NG_ARCH_SUPPORTS=y +# BR2_PACKAGE_ZLIB is not set +BR2_PACKAGE_PROVIDES_HOST_ZLIB="host-libzlib" +# BR2_PACKAGE_ZZIPLIB is not set + +# +# Crypto +# +# BR2_PACKAGE_BEARSSL is not set +BR2_PACKAGE_BOTAN_ARCH_SUPPORTS=y + +# +# botan needs a toolchain w/ threads, C++, gcc >= 11 +# +# BR2_PACKAGE_CA_CERTIFICATES is not set + +# +# cryptodev-linux needs a Linux kernel to be built +# + +# +# cryptopp needs a toolchain w/ C++, dynamic library, wchar +# +# BR2_PACKAGE_GCR is not set +# BR2_PACKAGE_GNUTLS is not set +# BR2_PACKAGE_LIBARGON2 is not set +# BR2_PACKAGE_LIBASSUAN is not set +# BR2_PACKAGE_LIBB2 is not set +# BR2_PACKAGE_LIBGCRYPT is not set +BR2_PACKAGE_LIBGPG_ERROR_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBGPG_ERROR is not set +BR2_PACKAGE_LIBGPG_ERROR_SYSCFG="i686-pc-linux-gnu" +# BR2_PACKAGE_LIBGPGME is not set +# BR2_PACKAGE_LIBKCAPI is not set +# BR2_PACKAGE_LIBKSBA is not set +# BR2_PACKAGE_LIBMD is not set +# BR2_PACKAGE_LIBMHASH is not set +# BR2_PACKAGE_LIBNSS is not set +# BR2_PACKAGE_LIBP11 is not set +# BR2_PACKAGE_LIBSCRYPT is not set +# BR2_PACKAGE_LIBSECRET is not set +# BR2_PACKAGE_LIBSHA1 is not set +# BR2_PACKAGE_LIBSODIUM is not set +BR2_PACKAGE_LIBSPDM_CPU_FAMILY="ia32" +BR2_PACKAGE_LIBSPDM_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBSPDM is not set +# BR2_PACKAGE_LIBSSH is not set +# BR2_PACKAGE_LIBSSH2 is not set +# BR2_PACKAGE_LIBTOMCRYPT is not set +# BR2_PACKAGE_LIBUECC is not set +# BR2_PACKAGE_LIBXCRYPT is not set +# BR2_PACKAGE_MBEDTLS is not set +# BR2_PACKAGE_NETTLE is not set +# BR2_PACKAGE_OATH_TOOLKIT is not set +BR2_PACKAGE_LIBRESSL_ARCH_SUPPORTS=y +# BR2_PACKAGE_OPENSSL is not set +BR2_PACKAGE_PROVIDES_HOST_OPENSSL="host-libopenssl" +# BR2_PACKAGE_PARSEC is not set +# BR2_PACKAGE_PARSEC_TOOL is not set +# BR2_PACKAGE_PKCS11_HELPER is not set +# BR2_PACKAGE_RHASH is not set +# BR2_PACKAGE_TINYDTLS is not set +# BR2_PACKAGE_TPM2_OPENSSL is not set +# BR2_PACKAGE_TPM2_PKCS11 is not set +# BR2_PACKAGE_TPM2_TSS is not set +# BR2_PACKAGE_TROUSERS is not set +# BR2_PACKAGE_USTREAM_SSL is not set +# BR2_PACKAGE_WOLFSSL is not set +# BR2_PACKAGE_WOLFTPM is not set + +# +# Database +# +# BR2_PACKAGE_BERKELEYDB is not set +# BR2_PACKAGE_GDBM is not set +# BR2_PACKAGE_HIREDIS is not set + +# +# kompexsqlite needs a toolchain w/ C++, wchar, threads, dynamic library +# + +# +# leveldb needs a toolchain w/ C++, threads, gcc >= 4.8 +# +# BR2_PACKAGE_LIBDBI is not set +# BR2_PACKAGE_LIBDBI_DRIVERS is not set +# BR2_PACKAGE_LIBGIT2 is not set +# BR2_PACKAGE_LIBMDBX is not set + +# +# libodb needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LMDB is not set + +# +# mariadb needs a toolchain w/ dynamic library, C++, threads, wchar +# +# BR2_PACKAGE_POSTGRESQL is not set + +# +# redis needs a toolchain w/ gcc>=4.9, dynamic library, nptl, C++ +# + +# +# redis-plus-plus needs a toolchain w/ C++, threads +# +BR2_PACKAGE_ROCKSDB_ARCH_SUPPORTS=y + +# +# rocksdb needs a toolchain w/ C++, threads, wchar, gcc >= 4.8 +# +# BR2_PACKAGE_SQLCIPHER is not set +# BR2_PACKAGE_SQLITE is not set + +# +# sqlitecpp needs a toolchain w/ C++11, gcc >= 4.9 +# +# BR2_PACKAGE_UNIXODBC is not set + +# +# Filesystem +# +# BR2_PACKAGE_LIBCONFIG is not set +# BR2_PACKAGE_LIBCONFUSE is not set +# BR2_PACKAGE_LIBFUSE is not set +# BR2_PACKAGE_LIBFUSE3 is not set +# BR2_PACKAGE_LIBLOCKFILE is not set +# BR2_PACKAGE_LIBNFS is not set +# BR2_PACKAGE_LIBSYSFS is not set +# BR2_PACKAGE_LOCKDEV is not set + +# +# physfs needs a toolchain w/ C++, threads +# + +# +# Graphics +# + +# +# assimp needs a toolchain w/ C++, wchar, gcc >= 7 +# +# BR2_PACKAGE_AT_SPI2_CORE is not set + +# +# atkmm needs a toolchain w/ C++, wchar, threads, gcc >= 7, dynamic library +# + +# +# atkmm (2.28.x) needs a toolchain w/ C++, wchar, threads, gcc >= 4.9, dynamic library +# + +# +# bullet needs a toolchain w/ C++, dynamic library, threads, wchar +# +# BR2_PACKAGE_CAIRO is not set + +# +# cairomm needs a toolchain w/ C++, wchar, threads, gcc >= 7 +# + +# +# cairomm (1.14.x) needs a toolchain w/ C++, wchar, threads, gcc >= 4.9 +# + +# +# chipmunk needs an OpenGL backend +# + +# +# exempi needs a toolchain w/ C++, dynamic library, threads, wchar +# + +# +# exiv2 needs a uClibc or glibc toolchain w/ C++, wchar, dynamic library, threads +# +# BR2_PACKAGE_FONTCONFIG is not set +# BR2_PACKAGE_FREETYPE is not set +# BR2_PACKAGE_GD is not set +# BR2_PACKAGE_GDK_PIXBUF is not set +# BR2_PACKAGE_GIFLIB is not set + +# +# granite needs libgtk3 and a toolchain w/ wchar, threads, gcc >= 4.9 +# +# BR2_PACKAGE_GRAPHENE is not set + +# +# graphite2 needs a toolchain w/ C++ +# + +# +# gtkmm3 needs libgtk3 and a toolchain w/ C++, wchar, threads, gcc >= 4.9, dynamic library +# + +# +# harfbuzz needs a toolchain w/ C++, gcc >= 4.9 +# +# BR2_PACKAGE_IJS is not set +# BR2_PACKAGE_IMLIB2 is not set + +# +# intel-gmmlib needs a toolchain w/ dynamic library, C++, threads +# + +# +# irrlicht needs a toolchain w/ C++ +# +# BR2_PACKAGE_JASPER is not set +# BR2_PACKAGE_JBIG2DEC is not set +# BR2_PACKAGE_JPEG is not set + +# +# kms++ needs a toolchain w/ threads, C++, gcc >= 4.8, headers >= 4.11, wchar +# +# BR2_PACKAGE_LCMS2 is not set + +# +# lensfun needs a toolchain w/ C++, threads, wchar +# +# BR2_PACKAGE_LEPTONICA is not set +# BR2_PACKAGE_LIBART is not set +# BR2_PACKAGE_LIBAVIF is not set + +# +# libdecor needs a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# +# BR2_PACKAGE_LIBDMTX is not set +# BR2_PACKAGE_LIBDRM is not set + +# +# libepoxy needs an OpenGL and/or OpenGL EGL backend +# +# BR2_PACKAGE_LIBEXIF is not set + +# +# libfm a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# + +# +# libfm needs X.org with an OpenGL backend +# +# BR2_PACKAGE_LIBFM_EXTRA is not set + +# +# libfreeglut depends on X.org and needs an OpenGL backend +# + +# +# libfreeimage needs a toolchain w/ C++, dynamic library, wchar +# + +# +# libgeotiff needs a toolchain w/ C++, gcc >= 4.7, NPTL, wchar +# + +# +# libglew depends on X.org and needs an OpenGL backend +# + +# +# libglfw depends on X.org or Wayland and an OpenGL or GLES backend +# + +# +# libglu needs an OpenGL backend +# +# BR2_PACKAGE_LIBGTA is not set + +# +# libgtk3 needs a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# + +# +# libgtk3 needs an OpenGL or an OpenGL-EGL backend +# + +# +# libgtk4 needs a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# + +# +# libgtk4 needs an OpenGL(ES) EGL backend +# + +# +# libjxl needs a toolchain with C++, threads, gcc >= 7, dynamic library +# +# BR2_PACKAGE_LIBMEDIAART is not set +# BR2_PACKAGE_LIBMNG is not set +# BR2_PACKAGE_LIBPNG is not set +# BR2_PACKAGE_LIBQRENCODE is not set + +# +# libraw needs a toolchain w/ C++ +# + +# +# librsvg needs a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# +# BR2_PACKAGE_LIBSVG is not set +# BR2_PACKAGE_LIBSVG_CAIRO is not set +# BR2_PACKAGE_LIBVA is not set +# BR2_PACKAGE_LIBVA_INTEL_DRIVER is not set + +# +# libvips needs a toolchain w/ wchar, threads, C++ +# + +# +# libwpe needs a toolchain w/ C++, dynamic library and an OpenEGL-capable backend +# +# BR2_PACKAGE_MENU_CACHE is not set +# BR2_PACKAGE_OPENCL_HEADERS is not set + +# +# opencv3 needs a toolchain w/ C++, NPTL, wchar, dynamic library +# + +# +# opencv4 needs a toolchain w/ C++, NPTL, wchar, dynamic library, gcc >= 4.8 +# +# BR2_PACKAGE_OPENJPEG is not set + +# +# pango needs a toolchain w/ wchar, threads, C++, gcc >= 4.9 +# + +# +# pangomm needs a toolchain w/ C++, wchar, threads, gcc >= 7 +# + +# +# pangomm (2.46.x) needs a toolchain w/ C++, wchar, threads, gcc >= 4.9 +# +# BR2_PACKAGE_PIXMAN is not set + +# +# poppler needs a toolchain w/ wchar, C++, threads, dynamic library, gcc >= 7 +# +# BR2_PACKAGE_STB is not set +# BR2_PACKAGE_TIFF is not set +# BR2_PACKAGE_WAYLAND is not set +BR2_PACKAGE_WEBKITGTK_ARCH_SUPPORTS=y + +# +# webkitgtk needs libgtk3 or libgtk4 and a toolchain w/ C++, wchar, NPTL, dynamic library, gcc >= 11, host gcc >= 4.9 +# +# BR2_PACKAGE_WEBP is not set + +# +# wlroots needs udev, EGL, OpenGL ES and GBM support +# + +# +# woff2 needs a toolchain w/ C++ +# + +# +# wpebackend-fdo needs a toolchain w/ C++, wchar, threads, dynamic library and EGL support +# +BR2_PACKAGE_WPEWEBKIT_ARCH_SUPPORTS=y + +# +# wpewebkit needs a toolchain w/ C++, wchar, NPTL, dynamic library, gcc >= 11, host gcc >= 4.9 +# + +# +# wpewebkit needs an OpenGL ES w/ EGL-capable Wayland backend +# + +# +# zbar needs a toolchain w/ threads, C++ and headers >= 3.0 +# + +# +# zxing-cpp needs a toolchain w/ C++, wchar, dynamic library, threads +# + +# +# Hardware handling +# +# BR2_PACKAGE_ACSCCID is not set +# BR2_PACKAGE_C_PERIPHERY is not set +# BR2_PACKAGE_CCID is not set +BR2_PACKAGE_CPUINFO_ARCH_SUPPORTS=y +# BR2_PACKAGE_CPUINFO is not set +# BR2_PACKAGE_DTC is not set +BR2_PACKAGE_GNU_EFI_ARCH_SUPPORTS=y +# BR2_PACKAGE_GNU_EFI is not set +# BR2_PACKAGE_HACKRF is not set + +# +# hidapi needs udev /dev management and a toolchain w/ NPTL, gcc >= 4.9 +# +# BR2_PACKAGE_JITTERENTROPY_LIBRARY is not set + +# +# lcdapi needs a toolchain w/ C++, threads +# + +# +# let-me-create needs a toolchain w/ C++, threads, dynamic library +# +# BR2_PACKAGE_LIBAIO is not set + +# +# libatasmart requires udev to be enabled +# + +# +# libblockdev needs udev /dev management and a toolchain w/ wchar, threads, dynamic library, locale +# + +# +# libcec needs a toolchain w/ C++, wchar, threads, dynamic library, gcc >= 4.7 +# +# BR2_PACKAGE_LIBDISPLAY_INFO is not set +# BR2_PACKAGE_LIBFREEFARE is not set +# BR2_PACKAGE_LIBFTDI is not set +# BR2_PACKAGE_LIBFTDI1 is not set +# BR2_PACKAGE_LIBGPHOTO2 is not set +# BR2_PACKAGE_LIBGPIOD is not set +# BR2_PACKAGE_LIBGPIOD2 is not set + +# +# libgudev needs udev /dev handling and a toolchain w/ wchar, threads +# +# BR2_PACKAGE_LIBIIO is not set + +# +# libinput needs udev /dev management +# +# BR2_PACKAGE_LIBIQRF is not set +# BR2_PACKAGE_LIBLLCP is not set +# BR2_PACKAGE_LIBMBIM is not set +# BR2_PACKAGE_LIBNFC is not set +# BR2_PACKAGE_LIBNVME is not set +# BR2_PACKAGE_LIBPCIACCESS is not set +# BR2_PACKAGE_LIBPHIDGET is not set + +# +# libpri needs a Linux kernel to be built +# +# BR2_PACKAGE_LIBQMI is not set +# BR2_PACKAGE_LIBQRTR_GLIB is not set +# BR2_PACKAGE_LIBRAW1394 is not set +# BR2_PACKAGE_LIBRTLSDR is not set + +# +# libserial needs a toolchain w/ C++, gcc >= 5, threads, wchar +# +# BR2_PACKAGE_LIBSERIALPORT is not set +# BR2_PACKAGE_LIBSIGROK is not set +# BR2_PACKAGE_LIBSIGROKDECODE is not set +# BR2_PACKAGE_LIBSOC is not set + +# +# libss7 needs a Linux kernel to be built +# +# BR2_PACKAGE_LIBUSB is not set +# BR2_PACKAGE_LIBUSBGX is not set + +# +# libv4l needs a toolchain w/ threads, C++ and headers >= 3.0 +# +# BR2_PACKAGE_LIBXKBCOMMON is not set +BR2_PACKAGE_MRAA_ARCH_SUPPORTS=y +# BR2_PACKAGE_MRAA is not set +# BR2_PACKAGE_MTDEV is not set +# BR2_PACKAGE_NEARDAL is not set +# BR2_PACKAGE_OPENSC is not set +# BR2_PACKAGE_OWFS is not set +# BR2_PACKAGE_PCSC_LITE is not set +# BR2_PACKAGE_PICO_SDK is not set + +# +# SoapySDR needs a toolchain w/ C++, threads, dynamic library +# +# BR2_PACKAGE_TSLIB is not set + +# +# uhd needs a toolchain w/ C++, NPTL, wchar, dynamic library, gcc >= 7 +# + +# +# urg needs a toolchain w/ C++ +# + +# +# Javascript +# +# BR2_PACKAGE_BOOTSTRAP is not set +# BR2_PACKAGE_CHARTJS is not set +# BR2_PACKAGE_DATATABLES is not set +# BR2_PACKAGE_DUKTAPE is not set +# BR2_PACKAGE_EXPLORERCANVAS is not set +# BR2_PACKAGE_FLOT is not set +# BR2_PACKAGE_FORGE is not set +# BR2_PACKAGE_JQUERY is not set +# BR2_PACKAGE_JSMIN is not set +# BR2_PACKAGE_JSON_JAVASCRIPT is not set +# BR2_PACKAGE_JSZIP is not set +# BR2_PACKAGE_OPENLAYERS is not set +# BR2_PACKAGE_VIS_NETWORK is not set +# BR2_PACKAGE_VUEJS is not set + +# +# JSON/XML +# + +# +# benejson needs a toolchain w/ C++ +# +# BR2_PACKAGE_CJSON is not set +# BR2_PACKAGE_EXPAT is not set +# BR2_PACKAGE_JANSSON is not set +# BR2_PACKAGE_JOSE is not set +# BR2_PACKAGE_JSMN is not set +# BR2_PACKAGE_JSON_C is not set + +# +# json-for-modern-cpp needs a toolchain w/ C++, gcc >= 4.9 +# +# BR2_PACKAGE_JSON_GLIB is not set + +# +# jsoncpp needs a toolchain w/ C++, gcc >= 4.7 +# +# BR2_PACKAGE_LIBFASTJSON is not set + +# +# libjson needs a toolchain w/ C++ +# +# BR2_PACKAGE_LIBROXML is not set +# BR2_PACKAGE_LIBUCL is not set +# BR2_PACKAGE_LIBXML2 is not set +# BR2_PACKAGE_LIBXMLB is not set + +# +# libxml++ needs a toolchain w/ C++, wchar, threads, gcc >= 7 +# +# BR2_PACKAGE_LIBXMLRPC is not set +# BR2_PACKAGE_LIBXSLT is not set +# BR2_PACKAGE_LIBYAML is not set +# BR2_PACKAGE_MXML is not set + +# +# pugixml needs a toolchain w/ C++ +# + +# +# rapidjson needs a toolchain w/ C++ +# +# BR2_PACKAGE_RAPIDXML is not set +# BR2_PACKAGE_RAPTOR is not set +# BR2_PACKAGE_SERD is not set +# BR2_PACKAGE_SORD is not set + +# +# tinyxml needs a toolchain w/ C++ +# + +# +# tinyxml2 needs a toolchain w/ C++ +# + +# +# valijson needs a toolchain w/ C++ +# + +# +# xerces-c++ needs a toolchain w/ C++, dynamic library, wchar +# + +# +# xml-security-c needs a toolchain w/ C++, wchar, dynamic library, threads, gcc >= 4.7 +# +# BR2_PACKAGE_YAJL is not set + +# +# yaml-cpp needs a toolchain w/ C++, gcc >= 4.7 +# + +# +# Logging +# + +# +# glog needs a toolchain w/ C++, threads, gcc >= 6 +# + +# +# hawktracer needs a toolchain w/ C++, gcc >= 4.8 +# +# BR2_PACKAGE_LIBLOG4C_LOCALTIME is not set +# BR2_PACKAGE_LIBLOGGING is not set + +# +# log4cplus needs a toolchain w/ C++, wchar, threads, gcc >= 4.8 +# + +# +# log4cpp needs a toolchain w/ C++, threads +# + +# +# log4cxx needs a toolchain w/ C++, threads, dynamic library, wchar +# + +# +# log4qt needs qt5 +# + +# +# opentracing-cpp needs a toolchain w/ C++, threads, dynamic library, gcc >= 4.8 +# + +# +# spdlog needs a toolchain w/ C++, threads, wchar +# + +# +# ulog needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_ZLOG is not set + +# +# Multimedia +# + +# +# bento4 support needs a toolchain with C++ +# +# BR2_PACKAGE_BITSTREAM is not set +# BR2_PACKAGE_DAV1D is not set + +# +# kvazaar needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBAACS is not set + +# +# libass needs a toolchain w/ C++, gcc >= 4.9 +# +# BR2_PACKAGE_LIBBDPLUS is not set +# BR2_PACKAGE_LIBBLURAY is not set +BR2_PACKAGE_LIBCAMERA_ARCH_SUPPORTS=y + +# +# libcamera needs a toolchain w/ C++, threads, wchar, dynamic library, gcc >= 8 +# + +# +# libcamera-apps needs a toolchain w/ C++, threads, wchar, dynamic library, gcc >= 8, headers >= 5.5 +# + +# +# libde265 needs a toolchain w/ threads, C++ +# +# BR2_PACKAGE_LIBDVBCSA is not set +# BR2_PACKAGE_LIBDVBPSI is not set + +# +# libdvbsi++ needs a toolchain w/ C++, wchar, threads +# +# BR2_PACKAGE_LIBDVDCSS is not set +# BR2_PACKAGE_LIBDVDNAV is not set +# BR2_PACKAGE_LIBDVDREAD is not set + +# +# libebml needs a toolchain w/ C++, wchar, gcc >= 4.9 +# +# BR2_PACKAGE_LIBHDHOMERUN is not set + +# +# libheif needs a toolchain w/ C++, threads, gcc >= 4.8 +# + +# +# libmatroska needs a toolchain w/ C++, wchar, gcc >= 4.9 +# +# BR2_PACKAGE_LIBMMS is not set +# BR2_PACKAGE_LIBMPEG2 is not set +# BR2_PACKAGE_LIBOGG is not set +# BR2_PACKAGE_LIBOPENAPTX is not set +BR2_PACKAGE_LIBOPENH264_ARCH_SUPPORTS=y + +# +# libopenh264 needs a toolchain w/ C++, dynamic library, threads +# +# BR2_PACKAGE_LIBOPUSENC is not set +# BR2_PACKAGE_LIBTHEORA is not set +# BR2_PACKAGE_LIBUDFREAD is not set +# BR2_PACKAGE_LIBVPX is not set + +# +# libyuv needs a toolchain w/ C++, dynamic library +# + +# +# live555 needs a toolchain w/ C++ +# +# BR2_PACKAGE_X264 is not set + +# +# x265 needs a toolchain w/ C++, threads, dynamic library +# + +# +# Networking +# + +# +# agent++ needs a toolchain w/ threads, C++, dynamic library +# + +# +# azmq needs a toolchain w/ C++11, wchar and threads +# + +# +# azure-iot-sdk-c needs a toolchain w/ C++, NPTL and wchar +# + +# +# batman-adv needs a Linux kernel to be built +# +# BR2_PACKAGE_C_ARES is not set +# BR2_PACKAGE_CNI_PLUGINS is not set + +# +# cpp-httplib needs a toolchain w/ C++, wchar, threads +# + +# +# cppzmq needs a toolchain w/ C++, threads +# + +# +# curlpp needs a toolchain w/ C++, dynamic library +# + +# +# czmq needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_DAQ is not set +# BR2_PACKAGE_DAQ3 is not set +# BR2_PACKAGE_DAVICI is not set +# BR2_PACKAGE_DHT is not set +# BR2_PACKAGE_ENET is not set + +# +# filemq needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_FREERADIUS_CLIENT is not set +# BR2_PACKAGE_GENSIO is not set +# BR2_PACKAGE_GEOIP is not set +# BR2_PACKAGE_GLIB_NETWORKING is not set + +# +# grpc needs a toolchain w/ C++, threads, dynamic library, gcc >= 8 +# +# BR2_PACKAGE_GSSDP is not set +# BR2_PACKAGE_GUPNP is not set +# BR2_PACKAGE_GUPNP_AV is not set +# BR2_PACKAGE_GUPNP_DLNA is not set + +# +# ibrcommon needs a toolchain w/ C++, threads +# + +# +# ibrdtn needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBCGI is not set + +# +# libcgicc needs a toolchain w/ C++ +# +# BR2_PACKAGE_LIBCOAP is not set + +# +# libcpprestsdk needs a toolchain w/ NPTL, C++, wchar, locale +# +# BR2_PACKAGE_LIBCURL is not set +# BR2_PACKAGE_LIBDNET is not set +# BR2_PACKAGE_LIBEXOSIP2 is not set +# BR2_PACKAGE_LIBEST is not set +# BR2_PACKAGE_LIBFCGI is not set +# BR2_PACKAGE_LIBGSASL is not set +# BR2_PACKAGE_LIBHTP is not set +# BR2_PACKAGE_LIBHTTPPARSER is not set + +# +# libhttpserver needs a toolchain w/ C++, threads, gcc >= 7 +# +# BR2_PACKAGE_LIBIDN is not set +# BR2_PACKAGE_LIBIDN2 is not set +# BR2_PACKAGE_LIBISCSI is not set +# BR2_PACKAGE_LIBKRB5 is not set +# BR2_PACKAGE_LIBLDNS is not set +# BR2_PACKAGE_LIBMAXMINDDB is not set +# BR2_PACKAGE_LIBMBUS is not set + +# +# libmemcached needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBMICROHTTPD is not set +# BR2_PACKAGE_LIBMINIUPNPC is not set +# BR2_PACKAGE_LIBMNL is not set +# BR2_PACKAGE_LIBMODBUS is not set + +# +# libmodsecurity needs a toolchain w/ C++, threads, dynamic library +# +# BR2_PACKAGE_LIBNATPMP is not set +# BR2_PACKAGE_LIBNDP is not set +# BR2_PACKAGE_LIBNET is not set +# BR2_PACKAGE_LIBNETCONF2 is not set +# BR2_PACKAGE_LIBNETFILTER_ACCT is not set +# BR2_PACKAGE_LIBNETFILTER_CONNTRACK is not set +# BR2_PACKAGE_LIBNETFILTER_CTHELPER is not set +# BR2_PACKAGE_LIBNETFILTER_CTTIMEOUT is not set +# BR2_PACKAGE_LIBNETFILTER_LOG is not set +# BR2_PACKAGE_LIBNETFILTER_QUEUE is not set +# BR2_PACKAGE_LIBNFNETLINK is not set +# BR2_PACKAGE_LIBNFTNL is not set +# BR2_PACKAGE_LIBNICE is not set +# BR2_PACKAGE_LIBNIDS is not set +# BR2_PACKAGE_LIBNL is not set + +# +# libnpupnp needs a toolchain w/ C++, threads, gcc >= 4.9 +# +# BR2_PACKAGE_LIBOPING is not set +# BR2_PACKAGE_LIBOSIP2 is not set +# BR2_PACKAGE_LIBPAGEKITE is not set +# BR2_PACKAGE_LIBPCAP is not set + +# +# libpjsip needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBPSL is not set +# BR2_PACKAGE_LIBRELP is not set +# BR2_PACKAGE_LIBRSYNC is not set +# BR2_PACKAGE_LIBSHAIRPLAY is not set +# BR2_PACKAGE_LIBSHOUT is not set +# BR2_PACKAGE_LIBSOCKETCAN is not set +# BR2_PACKAGE_LIBSOUP is not set +# BR2_PACKAGE_LIBSOUP3 is not set +# BR2_PACKAGE_LIBSRTP is not set +# BR2_PACKAGE_LIBSTROPHE is not set +# BR2_PACKAGE_LIBTEAM is not set +# BR2_PACKAGE_LIBTELNET is not set +# BR2_PACKAGE_LIBTIRPC is not set + +# +# libtorrent needs a toolchain w/ C++, threads +# + +# +# libtorrent-rasterbar needs a toolchain w/ C++, threads, wchar, gcc >= 4.9 +# +# BR2_PACKAGE_LIBUEV is not set +# BR2_PACKAGE_LIBUHTTPD is not set +# BR2_PACKAGE_LIBUPNP is not set + +# +# libupnpp needs a toolchain w/ C++, threads, gcc >= 4.9 +# +# BR2_PACKAGE_LIBURIPARSER is not set + +# +# libutp support needs a toolchain with C++ +# +# BR2_PACKAGE_LIBUWSC is not set +# BR2_PACKAGE_LIBVNCSERVER is not set +# BR2_PACKAGE_LIBWEBSOCKETS is not set +# BR2_PACKAGE_LIBYANG is not set +# BR2_PACKAGE_LIBZENOH_PICO is not set +# BR2_PACKAGE_LKSCTP_TOOLS is not set +# BR2_PACKAGE_MBUFFER is not set +# BR2_PACKAGE_MDNSD is not set +# BR2_PACKAGE_MONGOOSE is not set +# BR2_PACKAGE_NANOMSG is not set +# BR2_PACKAGE_NEON is not set + +# +# netopeer2 needs a toolchain w/ gcc >= 4.8, C++, threads, dynamic library +# +# BR2_PACKAGE_NGHTTP2 is not set + +# +# norm needs a toolchain w/ C++, threads, dynamic library +# +# BR2_PACKAGE_NSS_MYHOSTNAME is not set +# BR2_PACKAGE_NSS_PAM_LDAPD is not set + +# +# oatpp needs a toolchain w/ C++, threads +# + +# +# omniORB needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_OPEN_ISNS is not set +# BR2_PACKAGE_OPEN62541 is not set +# BR2_PACKAGE_OPENLDAP is not set + +# +# openmpi needs a toolchain w/ dynamic library, NPTL, wchar, C++ +# +# BR2_PACKAGE_OPENPGM is not set + +# +# openzwave needs a toolchain w/ C++, dynamic library, NPTL, wchar +# +# BR2_PACKAGE_PAHO_MQTT_C is not set + +# +# paho-mqtt-cpp needs a toolchain w/ threads, C++ +# + +# +# pistache needs a toolchain w/ C++, gcc >= 7, NPTL, wchar +# +# BR2_PACKAGE_QDECODER is not set + +# +# qpid-proton needs a toolchain w/ C++, dynamic library, threads +# +# BR2_PACKAGE_RABBITMQ_C is not set + +# +# resiprocate needs a toolchain w/ C++, threads, wchar +# + +# +# restclient-cpp needs a toolchain w/ C++, gcc >= 4.8 +# +# BR2_PACKAGE_RTMPDUMP is not set +# BR2_PACKAGE_SIPROXD is not set +# BR2_PACKAGE_SLIRP is not set +# BR2_PACKAGE_SLIRP4NETNS is not set + +# +# snmp++ needs a toolchain w/ threads, C++, dynamic library +# +# BR2_PACKAGE_SOFIA_SIP is not set +# BR2_PACKAGE_SSCEP is not set + +# +# sysrepo needs a toolchain w/ C++, NPTL, dynamic library, gcc >= 4.8 +# + +# +# thrift needs a toolchain w/ C++, wchar, threads +# +# BR2_PACKAGE_USBREDIR is not set + +# +# wampcc needs a toolchain w/ C++, NPTL, dynamic library, gcc >= 4.9 +# + +# +# websocketpp needs a toolchain w/ C++ and gcc >= 4.8 +# + +# +# zeromq needs a toolchain w/ C++, threads +# + +# +# zmqpp needs a toolchain w/ C++, threads, gcc >= 4.7 +# + +# +# zyre needs a toolchain w/ C++, threads +# + +# +# Other +# + +# +# ACE needs a glibc toolchain, dynamic library, C++, gcc >= 4.9 +# +# BR2_PACKAGE_APR is not set +# BR2_PACKAGE_APR_UTIL is not set + +# +# atf needs a toolchain w/ C++ +# +# BR2_PACKAGE_AVRO_C is not set +# BR2_PACKAGE_BASU is not set +# BR2_PACKAGE_BDWGC is not set + +# +# boost needs a toolchain w/ C++, threads, wchar +# + +# +# c-capnproto needs host and target gcc >= 5 w/ C++14, threads, atomic, ucontext and not gcc bug 64735 +# + +# +# capnproto needs host and target gcc >= 5 w/ C++14, threads, atomic, ucontext and not gcc bug 64735 +# + +# +# catch2 needs a toolchain w/ C++, wchar, threads, gcc >= 5 +# + +# +# cctz needs a toolchain w/ C++, threads, gcc >= 4.8 +# + +# +# cereal needs a toolchain w/ C++, gcc >= 4.7, threads, wchar +# + +# +# clang needs a toolchain w/ wchar, threads, C++, gcc >= 7, dynamic library, host gcc >= 7 +# +# BR2_PACKAGE_CMOCKA is not set + +# +# cppcms needs a toolchain w/ C++, NPTL, wchar, dynamic library +# +# BR2_PACKAGE_CRACKLIB is not set + +# +# dawgdic needs a toolchain w/ C++, gcc >= 4.6 +# +# BR2_PACKAGE_DING_LIBS is not set + +# +# dlib needs a toolchain w/ C++, threads, wchar +# +# BR2_PACKAGE_DOTCONF is not set + +# +# double-conversion needs a toolchain w/ C++ +# + +# +# eigen needs a toolchain w/ C++ +# +# BR2_PACKAGE_ELFUTILS is not set +# BR2_PACKAGE_ELL is not set + +# +# farmhash needs a toolchain w/ C++11 +# +# BR2_PACKAGE_FFT2D is not set +# BR2_PACKAGE_FFTW is not set + +# +# flann needs a toolchain w/ C++, dynamic library, gcc >= 4.7 +# + +# +# flatbuffers needs a toolchain w/ C++, gcc >= 4.7 +# +# BR2_PACKAGE_FLATCC is not set +# BR2_PACKAGE_FP16 is not set +# BR2_PACKAGE_FXDIV is not set +# BR2_PACKAGE_GCONF is not set + +# +# gdal needs a toolchain w/ C++, dynamic library, gcc >= 4.7, NPTL, wchar +# + +# +# gemmlowp needs a toolchain w/ C++11 +# + +# +# gflags needs a toolchain w/ C++ +# + +# +# gli needs a toolchain w/ C++ +# + +# +# glibmm needs a toolchain w/ C++, wchar, threads, gcc >= 7 +# + +# +# glibmm (2.66.x) needs a toolchain w/ C++, wchar, threads, gcc >= 4.9 +# + +# +# glm needs a toolchain w/ C++ +# +# BR2_PACKAGE_GMP is not set +BR2_PACKAGE_GOBJECT_INTROSPECTION_ARCH_SUPPORTS=y + +# +# gobject-introspection needs python3 +# +# BR2_PACKAGE_GSL is not set + +# +# gtest needs a toolchain w/ C++, wchar, threads, gcc >= 7 +# +# BR2_PACKAGE_GUMBO_PARSER is not set + +# +# highway needs a toolchain w/ C++, gcc >= 7 +# +BR2_PACKAGE_JEMALLOC_ARCH_SUPPORTS=y +# BR2_PACKAGE_JEMALLOC is not set +BR2_PACKAGE_LAPACK_ARCH_SUPPORTS=y + +# +# lapack/blas needs a toolchain w/ fortran +# +BR2_PACKAGE_LIBABSEIL_CPP_ARCH_SUPPORTS=y + +# +# libabseil-cpp needs a toolchain w/ gcc >= 8, C++, threads, dynamic library +# +BR2_PACKAGE_LIBATOMIC_OPS_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBATOMIC_OPS is not set +# BR2_PACKAGE_LIBAVL is not set +# BR2_PACKAGE_LIBB64 is not set +# BR2_PACKAGE_LIBBACKTRACE is not set +BR2_PACKAGE_LIBBSD_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBBSD is not set +# BR2_PACKAGE_LIBBYTESIZE is not set +# BR2_PACKAGE_LIBCAP is not set +# BR2_PACKAGE_LIBCAP_NG is not set + +# +# libcgroup needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBCLC is not set +# BR2_PACKAGE_LIBCORRECT is not set + +# +# libcrossguid needs a toolchain w/ C++, gcc >= 4.7 +# +# BR2_PACKAGE_LIBCSV is not set +# BR2_PACKAGE_LIBDAEMON is not set +# BR2_PACKAGE_LIBDEX is not set +# BR2_PACKAGE_LIBDILL is not set +BR2_PACKAGE_LIBEASTL_ARCH_SUPPORTS=y + +# +# libeastl needs a toolchain w/ C++, threads, gcc >= 4.9 +# +# BR2_PACKAGE_LIBEE is not set +# BR2_PACKAGE_LIBEV is not set +# BR2_PACKAGE_LIBEVDEV is not set +# BR2_PACKAGE_LIBEVENT is not set + +# +# libexecinfo needs a musl or uclibc toolchain w/ dynamic library +# +# BR2_PACKAGE_LIBFFI is not set + +# +# libfutils needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBGEE is not set + +# +# libgeos needs a toolchain w/ C++, wchar, gcc >= 7, threads +# +# BR2_PACKAGE_LIBGLIB2 is not set +# BR2_PACKAGE_LIBGLOB is not set + +# +# libical needs a toolchain w/ C++, dynamic library, wchar +# +# BR2_PACKAGE_LIBITE is not set + +# +# libks needs a toolchain w/ C++, NPTL, dynamic library +# + +# +# liblinear needs a toolchain w/ C++ +# + +# +# libloki needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBNPTH is not set +BR2_PACKAGE_LIBNSPR_ARCH_SUPPORT=y +# BR2_PACKAGE_LIBNSPR is not set + +# +# libosmium needs a toolchain w/ C++, wchar, threads, gcc >= 5 +# + +# +# libpeas needs python3 +# +# BR2_PACKAGE_LIBPFM4 is not set + +# +# libplist needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_LIBPTHREAD_STUBS is not set +# BR2_PACKAGE_LIBPTHSEM is not set +# BR2_PACKAGE_LIBPWQUALITY is not set +# BR2_PACKAGE_LIBQB is not set +BR2_PACKAGE_LIBSECCOMP_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBSECCOMP is not set + +# +# libshdata needs a toolchain w/ C++, threads +# + +# +# libsigc++ needs a toolchain w/ C++, gcc >= 7 +# + +# +# libsigc++ (2.x.x) needs a toolchain w/ C++, gcc >= 4.9 +# +BR2_PACKAGE_LIBSIGSEGV_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBSIGSEGV is not set +# BR2_PACKAGE_LIBSOLV is not set + +# +# libspatialindex needs a toolchain w/ C++, gcc >= 4.7 +# +# BR2_PACKAGE_LIBTALLOC is not set +# BR2_PACKAGE_LIBTASN1 is not set +# BR2_PACKAGE_LIBTOMMATH is not set +# BR2_PACKAGE_LIBTPL is not set +# BR2_PACKAGE_LIBUBOX is not set +# BR2_PACKAGE_LIBUCI is not set +BR2_PACKAGE_LIBUNWIND_ARCH_SUPPORTS=y +# BR2_PACKAGE_LIBUNWIND is not set +BR2_PACKAGE_LIBURCU_ARCH_SUPPORTS=y + +# +# liburcu needs a toolchain w/ threads, C++ +# +# BR2_PACKAGE_LIBURING is not set +# BR2_PACKAGE_LIBUTEMPTER is not set +# BR2_PACKAGE_LIBUV is not set +# BR2_PACKAGE_LIGHTNING is not set +# BR2_PACKAGE_LINUX_PAM is not set +# BR2_PACKAGE_LIQUID_DSP is not set +BR2_PACKAGE_LLAMA_CPP_ARCH_SUPPORTS=y + +# +# llama-cpp needs a toolchain w/ C++, wchar, threads, and gcc >= 9 +# +BR2_PACKAGE_LLVM_ARCH_SUPPORTS=y +BR2_PACKAGE_LLVM_TARGET_ARCH="X86" + +# +# llvm needs a toolchain w/ wchar, threads, C++, gcc >= 7, dynamic library, host gcc >= 7 +# + +# +# lttng-libust needs a toolchain w/ dynamic library, wchar, threads, C++ +# +# BR2_PACKAGE_MATIO is not set +# BR2_PACKAGE_MPC is not set +# BR2_PACKAGE_MPDECIMAL is not set +# BR2_PACKAGE_MPFR is not set +# BR2_PACKAGE_MPIR is not set + +# +# msgpack needs a toolchain w/ C++ +# +# BR2_PACKAGE_MSGPACK_C is not set +# BR2_PACKAGE_NEON_2_SSE is not set +# BR2_PACKAGE_ORC is not set +# BR2_PACKAGE_P11_KIT is not set +BR2_PACKAGE_POCO_ARCH_SUPPORTS=y + +# +# poco needs a toolchain w/ wchar, NPTL, C++, dynamic library, gcc >= 8 +# +BR2_PACKAGE_HOST_PROTOBUF_ARCH_SUPPORTS=y +BR2_PACKAGE_PROTOBUF_ARCH_SUPPORTS=y + +# +# protobuf needs a toolchain w/ C++, threads, dynamic library, gcc >= 8 +# + +# +# protobuf-c needs a toolchain w/ C++, threads, host gcc >= 7 +# + +# +# protozero needs a toolchain w/ C++, gcc >= 4.7 +# +# BR2_PACKAGE_PSIMD is not set +# BR2_PACKAGE_PTHREADPOOL is not set + +# +# qhull needs a toolchain w/ C++, gcc >= 4.4 +# +# BR2_PACKAGE_QLIBC is not set +# BR2_PACKAGE_REPROC is not set + +# +# riemann-c-client needs a toolchain w/ C++, threads, host gcc >= 7 +# +BR2_PACKAGE_RUY_ARCH_SUPPORTS=y + +# +# ruy needs a toolchain w/ C++14, threads +# + +# +# shapelib needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_SKALIBS is not set +# BR2_PACKAGE_SPHINXBASE is not set + +# +# tbb needs a glibc or musl toolchain w/ dynamic library, threads, C++ +# +BR2_PACKAGE_TENSORFLOW_LITE_ARCH_SUPPORTS=y + +# +# tensorflow-lite needs a toolchain w/ gcc >= 8, C++, threads +# +# BR2_PACKAGE_TINYCBOR is not set + +# +# tl-expected needs a toolchain w/ C++, gcc >= 4.8 +# +# BR2_PACKAGE_TLLIST is not set + +# +# uvw needs a toolchain w/ NPTL, dynamic library, C++, gcc >= 7 +# + +# +# volk needs a toolchain w/ C++, NPTL, wchar, dynamic library +# + +# +# xapian needs a toolchain w/ C++ +# +BR2_PACKAGE_XNNPACK_ARCH_SUPPORTS=y + +# +# xnnpack needs a toolchain w/ C++14, threads +# + +# +# Security +# +# BR2_PACKAGE_LIBAPPARMOR is not set +# BR2_PACKAGE_LIBSELINUX is not set +# BR2_PACKAGE_LIBSEMANAGE is not set +# BR2_PACKAGE_LIBSEPOL is not set +# BR2_PACKAGE_SAFECLIB is not set + +# +# softhsm2 needs a toolchain w/ C++, threads, gcc >= 4.8 and dynamic library support +# + +# +# Text and terminal handling +# +# BR2_PACKAGE_AUGEAS is not set + +# +# cli11 needs a toolchain w/ C++, gcc >= 4.8 +# + +# +# docopt-cpp needs a toolchain w/ C++, gcc >= 4.7 +# + +# +# enchant needs a toolchain w/ C++, threads, wchar +# +# BR2_PACKAGE_FCFT is not set + +# +# fmt needs a toolchain w/ C++, wchar +# +# BR2_PACKAGE_FSTRCMP is not set + +# +# icu needs a toolchain w/ C++, wchar, threads, gcc >= 4.9, host gcc >= 4.9 +# +# BR2_PACKAGE_INIH is not set +# BR2_PACKAGE_LIBCLI is not set +# BR2_PACKAGE_LIBECOLI is not set +# BR2_PACKAGE_LIBEDIT is not set +# BR2_PACKAGE_LIBENCA is not set +# BR2_PACKAGE_LIBESTR is not set +# BR2_PACKAGE_LIBFRIBIDI is not set +# BR2_PACKAGE_LIBUNIBREAK is not set +# BR2_PACKAGE_LIBUNISTRING is not set +# BR2_PACKAGE_LINENOISE is not set +# BR2_PACKAGE_NCURSES is not set +# BR2_PACKAGE_NEWT is not set +# BR2_PACKAGE_ONIGURUMA is not set +# BR2_PACKAGE_PCRE is not set +# BR2_PACKAGE_PCRE2 is not set +# BR2_PACKAGE_POPT is not set + +# +# re2 needs a toolchain w/ C++, threads, dynamic library, gcc >= 8 +# +# BR2_PACKAGE_READLINE is not set +# BR2_PACKAGE_SLANG is not set + +# +# tclap needs a toolchain w/ C++ +# + +# +# termcolor needs a toolchain w/ C++, gcc >= 4.8 +# +# BR2_PACKAGE_UTF8PROC is not set + +# +# taglib needs a toolchain w/ C++ +# + +# +# Mail +# +# BR2_PACKAGE_DOVECOT is not set +# BR2_PACKAGE_EXIM is not set +# BR2_PACKAGE_FETCHMAIL is not set +# BR2_PACKAGE_HEIRLOOM_MAILX is not set +# BR2_PACKAGE_LIBESMTP is not set +# BR2_PACKAGE_MSMTP is not set +# BR2_PACKAGE_MUTT is not set + +# +# Miscellaneous +# +# BR2_PACKAGE_AESPIPE is not set +# BR2_PACKAGE_BC is not set +BR2_PACKAGE_BITCOIN_ARCH_SUPPORTS=y + +# +# bitcoin needs a toolchain w/ C++, threads, wchar, gcc >= 11 +# + +# +# clamav needs a toolchain w/ C++, dynamic library, threads, wchar +# +# BR2_PACKAGE_COLLECTD is not set +# BR2_PACKAGE_COLLECTL is not set + +# +# domoticz needs lua 5.3 and a toolchain w/ C++, gcc >= 6, NPTL, wchar, dynamic library +# +# BR2_PACKAGE_EMPTY is not set +# BR2_PACKAGE_FFT_EVAL is not set +# BR2_PACKAGE_GITLAB_RUNNER is not set + +# +# gnuradio needs a toolchain w/ C++, NPTL, wchar, dynamic library, gcc >= 8 +# +# BR2_PACKAGE_GOOGLEFONTDIRECTORY is not set + +# +# gqrx needs a toolchain w/ C++, threads, wchar, dynamic library, gcc >= 8 +# + +# +# gqrx needs qt5 +# +# BR2_PACKAGE_GSETTINGS_DESKTOP_SCHEMAS is not set +# BR2_PACKAGE_HAVEGED is not set +# BR2_PACKAGE_LINUX_SYSCALL_SUPPORT is not set +# BR2_PACKAGE_MOBILE_BROADBAND_PROVIDER_INFO is not set +# BR2_PACKAGE_NETDATA is not set + +# +# proj needs a toolchain w/ C++, gcc >= 4.7, NPTL, wchar +# +BR2_PACKAGE_QEMU_ARCH_SUPPORTS_TARGET=y +# BR2_PACKAGE_QEMU is not set + +# +# qpdf needs a toolchain w/ C++, gcc >= 5 +# +# BR2_PACKAGE_RTL_433 is not set +# BR2_PACKAGE_SHARED_MIME_INFO is not set +# BR2_PACKAGE_SNOOZE is not set + +# +# sunwait needs a toolchain w/ C++ +# + +# +# taskd needs a toolchain w/ C++, wchar, dynamic library +# +BR2_PACKAGE_WINE_ARCH_SUPPORTS=y +# BR2_PACKAGE_WINE is not set +BR2_PACKAGE_XMRIG_ARCH_SUPPORTS=y + +# +# xmrig needs a glibc or musl toolchain w/ NPTL, dynamic library, C++, gcc >= 4.9 +# +# BR2_PACKAGE_XUTIL_UTIL_MACROS is not set +BR2_PACKAGE_Z3_ARCH_SUPPORTS=y + +# +# Networking applications +# +# BR2_PACKAGE_AARDVARK_DNS is not set + +# +# aircrack-ng needs a toolchain w/ dynamic library, threads, C++ +# +# BR2_PACKAGE_ALFRED is not set +# BR2_PACKAGE_AOETOOLS is not set +# BR2_PACKAGE_APACHE is not set +# BR2_PACKAGE_ARGUS is not set +# BR2_PACKAGE_ARP_SCAN is not set +# BR2_PACKAGE_ARPTABLES is not set + +# +# asterisk needs a glibc or uClibc toolchain w/ C++, dynamic library, threads, wchar +# +# BR2_PACKAGE_ATFTP is not set +# BR2_PACKAGE_AVAHI is not set +# BR2_PACKAGE_AXEL is not set +# BR2_PACKAGE_BABELD is not set +# BR2_PACKAGE_BANDWIDTHD is not set +# BR2_PACKAGE_BATCTL is not set + +# +# bcusdk needs a toolchain w/ C++ +# +# BR2_PACKAGE_BIND is not set +# BR2_PACKAGE_BIRD is not set +# BR2_PACKAGE_BLUEZ5_UTILS is not set +# BR2_PACKAGE_BMON is not set +# BR2_PACKAGE_BMX7 is not set + +# +# boinc needs a toolchain w/ dynamic library, C++, threads, gcc >= 4.8 +# +# BR2_PACKAGE_BRCM_PATCHRAM_PLUS is not set +# BR2_PACKAGE_BRIDGE_UTILS is not set +# BR2_PACKAGE_BWM_NG is not set +# BR2_PACKAGE_C_ICAP is not set +# BR2_PACKAGE_CAN_UTILS is not set + +# +# cannelloni needs a toolchain w/ C++, threads, dynamic library, gcc >= 8 +# +# BR2_PACKAGE_CASYNC is not set +# BR2_PACKAGE_CASYNC_NANO is not set +# BR2_PACKAGE_CFM is not set +# BR2_PACKAGE_CHRONY is not set +# BR2_PACKAGE_CIVETWEB is not set +# BR2_PACKAGE_CLOUDFLARED is not set +# BR2_PACKAGE_CONNMAN is not set + +# +# connman-gtk needs libgtk3 and a glibc or uClibc toolchain w/ wchar, threads, resolver, dynamic library +# +# BR2_PACKAGE_CONNTRACK_TOOLS is not set +# BR2_PACKAGE_CORKSCREW is not set +# BR2_PACKAGE_CRDA is not set + +# +# ctorrent needs a toolchain w/ C++ +# + +# +# cups needs a toolchain w/ C++, threads +# + +# +# cups-filters needs a toolchain w/ wchar, C++, threads and dynamic library, gcc >= 5 +# +# BR2_PACKAGE_DANTE is not set +# BR2_PACKAGE_DARKHTTPD is not set +# BR2_PACKAGE_DEHYDRATED is not set +# BR2_PACKAGE_DHCPCD is not set +# BR2_PACKAGE_DHCPDUMP is not set +# BR2_PACKAGE_DNSMASQ is not set +# BR2_PACKAGE_DRBD_UTILS is not set +# BR2_PACKAGE_DROPBEAR is not set +# BR2_PACKAGE_EASYFRAMES is not set +# BR2_PACKAGE_EBTABLES is not set + +# +# ejabberd needs erlang, toolchain w/ C++ +# +# BR2_PACKAGE_ETHTOOL is not set +# BR2_PACKAGE_FAIFA is not set +# BR2_PACKAGE_FASTD is not set +# BR2_PACKAGE_FCGIWRAP is not set +# BR2_PACKAGE_FIREWALLD is not set +# BR2_PACKAGE_FLANNEL is not set +# BR2_PACKAGE_FPING is not set +# BR2_PACKAGE_FREERADIUS_SERVER is not set + +# +# freeswitch needs a toolchain w/ C++, dynamic library, threads, wchar +# +# BR2_PACKAGE_FRR is not set + +# +# protobuf support for frr needs a toolchain w/ protobuf, C++, host gcc >= 7 +# + +# +# gerbera needs a toolchain w/ C++, dynamic library, threads, wchar, gcc >= 8 +# +# BR2_PACKAGE_GESFTPSERVER is not set + +# +# gloox needs a toolchain w/ C++ +# +# BR2_PACKAGE_GLORYTUN is not set + +# +# gupnp-tools needs libgtk3 +# + +# +# hans needs a toolchain w/ C++ +# +BR2_PACKAGE_HAPROXY_ARCH_SUPPORTS=y +# BR2_PACKAGE_HAPROXY is not set +# BR2_PACKAGE_HOSTAPD is not set +# BR2_PACKAGE_HTPDATE is not set +# BR2_PACKAGE_HTTPING is not set + +# +# i2pd needs a toolchain w/ C++, NPTL, wchar +# +# BR2_PACKAGE_IANA_ASSIGNMENTS is not set + +# +# ibrdtn-tools needs a toolchain w/ C++, threads +# + +# +# ibrdtnd needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_IFMETRIC is not set +# BR2_PACKAGE_IFTOP is not set +BR2_PACKAGE_IFUPDOWN_SCRIPTS=y +# BR2_PACKAGE_IGD2_FOR_LINUX is not set + +# +# igh-ethercat needs a Linux kernel to be built +# +# BR2_PACKAGE_IGMPPROXY is not set +# BR2_PACKAGE_INADYN is not set +# BR2_PACKAGE_IODINE is not set + +# +# iperf needs a toolchain w/ C++ +# +# BR2_PACKAGE_IPERF3 is not set +# BR2_PACKAGE_IPROUTE2 is not set +# BR2_PACKAGE_IPSET is not set +# BR2_PACKAGE_IPTABLES is not set +# BR2_PACKAGE_IPTRAF_NG is not set +# BR2_PACKAGE_IPUTILS is not set +# BR2_PACKAGE_IRSSI is not set +# BR2_PACKAGE_IW is not set +# BR2_PACKAGE_IWD is not set +# BR2_PACKAGE_JANUS_GATEWAY is not set +# BR2_PACKAGE_KEEPALIVED is not set + +# +# kismet needs a toolchain w/ threads, C++, gcc >= 5, host gcc >= 7 +# +# BR2_PACKAGE_KNOCK is not set +# BR2_PACKAGE_KSMBD_TOOLS is not set +# BR2_PACKAGE_LEAFNODE2 is not set +# BR2_PACKAGE_LFT is not set + +# +# lftp requires a toolchain w/ C++, wchar +# +# BR2_PACKAGE_LIGHTTPD is not set + +# +# linknx needs a toolchain w/ C++ +# +# BR2_PACKAGE_LINKS is not set +# BR2_PACKAGE_LINUX_ZIGBEE is not set +# BR2_PACKAGE_LINUXPTP is not set +# BR2_PACKAGE_LLDPD is not set +# BR2_PACKAGE_LPAC is not set +# BR2_PACKAGE_LRZSZ is not set +# BR2_PACKAGE_LYNX is not set +# BR2_PACKAGE_MACCHANGER is not set +# BR2_PACKAGE_MEMCACHED is not set +# BR2_PACKAGE_MII_DIAG is not set +# BR2_PACKAGE_MINI_SNMPD is not set +# BR2_PACKAGE_MINIDLNA is not set +# BR2_PACKAGE_MINISSDPD is not set +# BR2_PACKAGE_MJPG_STREAMER is not set +# BR2_PACKAGE_MODEM_MANAGER is not set + +# +# mosh needs a toolchain w/ C++, threads, dynamic library, wchar, gcc >= 8 +# +# BR2_PACKAGE_MOSQUITTO is not set +# BR2_PACKAGE_MROUTED is not set +# BR2_PACKAGE_MRP is not set +# BR2_PACKAGE_MSTPD is not set +# BR2_PACKAGE_MTR is not set +# BR2_PACKAGE_NBD is not set +# BR2_PACKAGE_NCFTP is not set +# BR2_PACKAGE_NDISC6 is not set +# BR2_PACKAGE_NETATALK is not set +# BR2_PACKAGE_NETAVARK is not set +# BR2_PACKAGE_NETCALC is not set + +# +# nethogs needs a toolchain w/ C++ +# +# BR2_PACKAGE_NETPLUG is not set +# BR2_PACKAGE_NETSNMP is not set + +# +# NetworkManager needs udev /dev management and a glibc or musl toolchain w/ headers >= 5.4, dynamic library, wchar, threads, gcc >= 4.9 +# +# BR2_PACKAGE_NFACCT is not set +# BR2_PACKAGE_NFTABLES is not set +# BR2_PACKAGE_NGINX is not set +# BR2_PACKAGE_NGIRCD is not set +# BR2_PACKAGE_NGREP is not set + +# +# nload needs a toolchain w/ C++ +# + +# +# nmap-nmap needs a toolchain w/ C++, threads +# +# BR2_PACKAGE_NOIP is not set +# BR2_PACKAGE_NTP is not set +# BR2_PACKAGE_NTPSEC is not set +# BR2_PACKAGE_NUTTCP is not set +# BR2_PACKAGE_ODHCP6C is not set +# BR2_PACKAGE_ODHCPLOC is not set +# BR2_PACKAGE_OLSR is not set +# BR2_PACKAGE_OPEN_ISCSI is not set +# BR2_PACKAGE_OPEN_LLDP is not set +# BR2_PACKAGE_OPEN_PLC_UTILS is not set +# BR2_PACKAGE_OPENCONNECT is not set +# BR2_PACKAGE_OPENNTPD is not set +# BR2_PACKAGE_OPENOBEX is not set +# BR2_PACKAGE_OPENRESOLV is not set +# BR2_PACKAGE_OPENSSH is not set +# BR2_PACKAGE_OPENSWAN is not set +# BR2_PACKAGE_OPENVPN is not set +# BR2_PACKAGE_P910ND is not set +# BR2_PACKAGE_PARPROUTED is not set +# BR2_PACKAGE_PASST is not set +# BR2_PACKAGE_PHIDGETWEBSERVICE is not set +# BR2_PACKAGE_PHYTOOL is not set +# BR2_PACKAGE_PIMD is not set +# BR2_PACKAGE_PIXIEWPS is not set +# BR2_PACKAGE_POUND is not set +# BR2_PACKAGE_PPPD is not set +# BR2_PACKAGE_PPTP_LINUX is not set +# BR2_PACKAGE_PRIVOXY is not set +# BR2_PACKAGE_PROFTPD is not set + +# +# prosody needs the lua interpreter, dynamic library +# +# BR2_PACKAGE_PROXYCHAINS_NG is not set +# BR2_PACKAGE_PTPD is not set +# BR2_PACKAGE_PTPD2 is not set +# BR2_PACKAGE_PURE_FTPD is not set +# BR2_PACKAGE_PUTTY is not set +# BR2_PACKAGE_RADVD is not set +# BR2_PACKAGE_REAVER is not set +# BR2_PACKAGE_REDIR is not set +# BR2_PACKAGE_RP_PPPOE is not set +# BR2_PACKAGE_RPCBIND is not set +# BR2_PACKAGE_RSH_REDONE is not set +# BR2_PACKAGE_RSYNC is not set + +# +# rtorrent needs a toolchain w/ C++, threads, wchar, gcc >= 4.9 +# +# BR2_PACKAGE_RTPTOOLS is not set +# BR2_PACKAGE_S6_DNS is not set +# BR2_PACKAGE_S6_NETWORKING is not set +# BR2_PACKAGE_SAMBA4 is not set + +# +# sconeserver needs a toolchain with dynamic library, C++, NPTL +# +# BR2_PACKAGE_SER2NET is not set +# BR2_PACKAGE_SHADOWSOCKS_LIBEV is not set + +# +# shairport-sync needs a toolchain w/ C++, NPTL +# +# BR2_PACKAGE_SHELLINABOX is not set +# BR2_PACKAGE_SMCROUTE is not set +# BR2_PACKAGE_SNGREP is not set +# BR2_PACKAGE_SNORT is not set + +# +# snort3 needs a toolchain w/ C++, wchar, threads, dynamic library, gcc >= 4.9 +# +# BR2_PACKAGE_SOCAT is not set +# BR2_PACKAGE_SOCKETCAND is not set +# BR2_PACKAGE_SOFTETHER is not set +# BR2_PACKAGE_SPAWN_FCGI is not set + +# +# spice server needs a toolchain w/ wchar, threads, C++ +# +# BR2_PACKAGE_SPICE_PROTOCOL is not set + +# +# squid needs a toolchain w/ C++, threads, gcc >= 8, host gcc >= 8 +# +# BR2_PACKAGE_SSDP_RESPONDER is not set +# BR2_PACKAGE_SSHGUARD is not set +# BR2_PACKAGE_SSHPASS is not set +# BR2_PACKAGE_SSLH is not set +# BR2_PACKAGE_STRONGSWAN is not set +# BR2_PACKAGE_STUNNEL is not set +# BR2_PACKAGE_SURICATA is not set +# BR2_PACKAGE_TAILSCALE is not set +# BR2_PACKAGE_TCPDUMP is not set +# BR2_PACKAGE_TCPING is not set +# BR2_PACKAGE_TCPREPLAY is not set +# BR2_PACKAGE_TINC is not set +# BR2_PACKAGE_TINYPROXY is not set +# BR2_PACKAGE_TINYSSH is not set +# BR2_PACKAGE_TIPIDEE is not set +# BR2_PACKAGE_TOR is not set +# BR2_PACKAGE_TRACEROUTE is not set + +# +# transmission needs a toolchain w/ dynamic library, threads, C++, gcc >= 7 +# +# BR2_PACKAGE_TUNCTL is not set +# BR2_PACKAGE_TVHEADEND is not set +# BR2_PACKAGE_UACME is not set +# BR2_PACKAGE_UDPCAST is not set +# BR2_PACKAGE_UFTP is not set +# BR2_PACKAGE_UHTTPD is not set +# BR2_PACKAGE_ULOGD is not set +# BR2_PACKAGE_UNBOUND is not set +# BR2_PACKAGE_UQMI is not set +# BR2_PACKAGE_UREDIR is not set +# BR2_PACKAGE_USHARE is not set +# BR2_PACKAGE_USSP_PUSH is not set +# BR2_PACKAGE_USTREAMER is not set +# BR2_PACKAGE_VDE2 is not set + +# +# vdr needs a toolchain w/ C++, dynamic library, NPTL, wchar, headers >= 3.9 +# +# BR2_PACKAGE_VNSTAT is not set +# BR2_PACKAGE_VPNC is not set +# BR2_PACKAGE_VSFTPD is not set +# BR2_PACKAGE_VTUN is not set +# BR2_PACKAGE_WAVEMON is not set + +# +# wireguard-linux-compat needs a Linux kernel to be built +# +# BR2_PACKAGE_WIREGUARD_TOOLS is not set +# BR2_PACKAGE_WIRELESS_REGDB is not set +# BR2_PACKAGE_WIRELESS_TOOLS is not set + +# +# wireshark needs a toolchain w/ wchar, threads, dynamic library, C++ +# +# BR2_PACKAGE_WPA_SUPPLICANT is not set +# BR2_PACKAGE_WPAN_TOOLS is not set +# BR2_PACKAGE_XINETD is not set +# BR2_PACKAGE_XL2TP is not set + +# +# xtables-addons needs a Linux kernel to be built +# +# BR2_PACKAGE_ZABBIX is not set + +# +# zeek needs a toolchain w/ C++, wchar, threads, dynamic library, gcc >= 7, host gcc >= 7 +# + +# +# znc needs a toolchain w/ C++, dynamic library, gcc >= 8, threads +# + +# +# Package managers +# + +# +# ------------------------------------------------------- +# + +# +# Please note: +# + +# +# - Buildroot does *not* generate binary packages, +# + +# +# - Buildroot does *not* install any package database. +# + +# +# * +# + +# +# It is up to you to provide those by yourself if you +# + +# +# want to use any of those package managers. +# + +# +# * +# + +# +# See the manual: +# + +# +# http://buildroot.org/manual.html#faq-no-binary-packages +# + +# +# ------------------------------------------------------- +# +# BR2_PACKAGE_OPKG is not set +# BR2_PACKAGE_OPKG_UTILS is not set + +# +# Real-Time +# +BR2_PACKAGE_XENOMAI_COBALT_ARCH_SUPPORTS=y +# BR2_PACKAGE_XENOMAI is not set + +# +# Security +# + +# +# apparmor needs a toolchain w/ headers >= 3.16, threads, C++ +# +# BR2_PACKAGE_CHECKPOLICY is not set +# BR2_PACKAGE_IMA_EVM_UTILS is not set +# BR2_PACKAGE_LYNIS is not set +# BR2_PACKAGE_OPTEE_CLIENT is not set +# BR2_PACKAGE_PAXTEST is not set +# BR2_PACKAGE_POLICYCOREUTILS is not set +# BR2_PACKAGE_REFPOLICY is not set +# BR2_PACKAGE_RESTORECOND is not set +# BR2_PACKAGE_SELINUX_PYTHON is not set +# BR2_PACKAGE_SEMODULE_UTILS is not set + +# +# setools needs python3 +# +BR2_PACKAGE_URANDOM_SCRIPTS=y + +# +# Shell and utilities +# + +# +# Shells +# +# BR2_PACKAGE_MKSH is not set +# BR2_PACKAGE_NUSHELL is not set +# BR2_PACKAGE_ZSH is not set + +# +# Utilities +# +# BR2_PACKAGE_APG is not set +# BR2_PACKAGE_AT is not set +# BR2_PACKAGE_CATATONIT is not set +# BR2_PACKAGE_CCRYPT is not set +# BR2_PACKAGE_DIALOG is not set +# BR2_PACKAGE_DTACH is not set +# BR2_PACKAGE_EASY_RSA is not set +# BR2_PACKAGE_EZA is not set +# BR2_PACKAGE_FILE is not set +# BR2_PACKAGE_GNUPG is not set +BR2_PACKAGE_GNUPG2_DEPENDS=y +# BR2_PACKAGE_GNUPG2 is not set +# BR2_PACKAGE_INOTIFY_TOOLS is not set +# BR2_PACKAGE_LOCKFILE_PROGS is not set +# BR2_PACKAGE_LOGROTATE is not set +# BR2_PACKAGE_LOWDOWN is not set + +# +# lowdown needs a toolchain w/ wchar and shared library support +# +# BR2_PACKAGE_MINISIGN is not set +# BR2_PACKAGE_PDMENU is not set +# BR2_PACKAGE_PINENTRY is not set +# BR2_PACKAGE_QPRINT is not set +# BR2_PACKAGE_RANGER is not set +# BR2_PACKAGE_RLWRAP is not set +# BR2_PACKAGE_RTTY is not set +# BR2_PACKAGE_SCREEN is not set +# BR2_PACKAGE_SEXPECT is not set +# BR2_PACKAGE_SUDO is not set +# BR2_PACKAGE_TINI is not set +# BR2_PACKAGE_TMUX is not set +# BR2_PACKAGE_TTYD is not set + +# +# uuu needs a toolchain w/ C++14, threads, atomic, wchar +# +# BR2_PACKAGE_WTFUTIL is not set +# BR2_PACKAGE_XMLSTARLET is not set +# BR2_PACKAGE_XXHASH is not set +# BR2_PACKAGE_YTREE is not set +# BR2_PACKAGE_ZOXIDE is not set + +# +# System tools +# +# BR2_PACKAGE_ACL is not set +# BR2_PACKAGE_AMAZON_ECR_CREDENTIAL_HELPER is not set +# BR2_PACKAGE_ANDROID_TOOLS is not set +# BR2_PACKAGE_ATOP is not set +# BR2_PACKAGE_ATTR is not set +BR2_PACKAGE_AUDIT_ARCH_SUPPORTS=y +# BR2_PACKAGE_AUDIT is not set +# BR2_PACKAGE_BALENA_ENGINE is not set +# BR2_PACKAGE_BUBBLEWRAP is not set +# BR2_PACKAGE_CGROUPFS_MOUNT is not set +# BR2_PACKAGE_CGROUPFS_V2_MOUNT is not set + +# +# circus needs Python 3 and a toolchain w/ C++, threads +# +# BR2_PACKAGE_CONMON is not set +# BR2_PACKAGE_CONTAINERD is not set +# BR2_PACKAGE_CONTAINERS_IMAGE_CONFIG is not set +# BR2_PACKAGE_CPULIMIT is not set +# BR2_PACKAGE_CPULOAD is not set +# BR2_PACKAGE_CRUN is not set +# BR2_PACKAGE_DAEMON is not set +# BR2_PACKAGE_DC3DD is not set + +# +# ddrescue needs a toolchain w/ C++ +# +# BR2_PACKAGE_DISTRIBUTION_REGISTRY is not set +# BR2_PACKAGE_DOCKER_CLI is not set +# BR2_PACKAGE_DOCKER_CLI_BUILDX is not set + +# +# docker-compose needs docker-cli and a toolchain w/ threads +# +# BR2_PACKAGE_DOCKER_CREDENTIAL_ACR_ENV is not set +# BR2_PACKAGE_DOCKER_CREDENTIAL_GCR is not set +# BR2_PACKAGE_DOCKER_ENGINE is not set +# BR2_PACKAGE_EARLYOOM is not set +# BR2_PACKAGE_EFIBOOTMGR is not set +BR2_PACKAGE_EFIVAR_ARCH_SUPPORTS=y +# BR2_PACKAGE_EFIVAR is not set +# BR2_PACKAGE_EMBIGGEN_DISK is not set + +# +# emlog needs a Linux kernel to be built +# +# BR2_PACKAGE_FLUENT_BIT is not set +# BR2_PACKAGE_FTOP is not set +# BR2_PACKAGE_GETENT is not set +# BR2_PACKAGE_GKRELLM is not set +# BR2_PACKAGE_HTOP is not set +# BR2_PACKAGE_HWCLOCK_INITSCRIPT is not set +# BR2_PACKAGE_IBM_SW_TPM2 is not set +BR2_PACKAGE_INITSCRIPTS=y + +# +# iotop depends on python3 +# +# BR2_PACKAGE_IPRUTILS is not set +# BR2_PACKAGE_IRQBALANCE is not set +# BR2_PACKAGE_KEYUTILS is not set +# BR2_PACKAGE_KMOD is not set +# BR2_PACKAGE_KMON is not set +# BR2_PACKAGE_KVMTOOL is not set +# BR2_PACKAGE_LIBOSTREE is not set +BR2_PACKAGE_LIBVIRT_ARCH_SUPPORTS=y + +# +# libvirt needs udev /dev management, a toolchain w/ threads, dynamic library, wchar, kernel headers >= 3.12 (4.11 for AArch64) +# +# BR2_PACKAGE_LXC is not set +BR2_PACKAGE_MAKEDUMPFILE_ARCH_SUPPORTS=y +# BR2_PACKAGE_MAKEDUMPFILE is not set +# BR2_PACKAGE_MENDER is not set +# BR2_PACKAGE_MENDER_CONNECT is not set + +# +# mender-update-modules needs mender +# +# BR2_PACKAGE_MFOC is not set +# BR2_PACKAGE_MOBY_BUILDKIT is not set +# BR2_PACKAGE_MOKUTIL is not set +# BR2_PACKAGE_MONIT is not set + +# +# multipath-tools needs udev and a toolchain w/ threads, dynamic library, C++ +# +# BR2_PACKAGE_NCDU is not set +# BR2_PACKAGE_NERDCTL is not set + +# +# netifrc needs openrc as init system +# +# BR2_PACKAGE_NUMACTL is not set + +# +# nut needs a toolchain w/ C++, threads +# +BR2_PACKAGE_OPENVMTOOLS_ARCH_SUPPORTS=y +# BR2_PACKAGE_OPENVMTOOLS is not set + +# +# pamtester depends on linux-pam +# + +# +# petitboot needs a toolchain w/ wchar, dynamic library, threads, udev /dev management +# +# BR2_PACKAGE_PODMAN is not set +# BR2_PACKAGE_POLKIT is not set +# BR2_PACKAGE_PROCS is not set +# BR2_PACKAGE_PWGEN is not set +# BR2_PACKAGE_QBEE_AGENT is not set +# BR2_PACKAGE_QUOTA is not set +# BR2_PACKAGE_QUOTATOOL is not set +# BR2_PACKAGE_RAUC is not set +# BR2_PACKAGE_RAUC_HAWKBIT_UPDATER is not set +# BR2_PACKAGE_RUNC is not set +# BR2_PACKAGE_S6 is not set +# BR2_PACKAGE_S6_LINUX_INIT is not set +# BR2_PACKAGE_S6_LINUX_UTILS is not set +# BR2_PACKAGE_S6_PORTABLE_UTILS is not set +# BR2_PACKAGE_S6_RC is not set +# BR2_PACKAGE_SCRUB is not set +# BR2_PACKAGE_SCRYPT is not set + +# +# sdbus-c++ needs systemd and a toolchain w/ C++, gcc >= 8 +# + +# +# sdbusplus needs systemd and a toolchain w/ C++, gcc >= 7 +# +# BR2_PACKAGE_SEATD is not set +# BR2_PACKAGE_SHADOW is not set +# BR2_PACKAGE_SKOPEO is not set +# BR2_PACKAGE_SMACK is not set + +# +# supervisor needs a python interpreter +# +# BR2_PACKAGE_SWUPDATE is not set +BR2_PACKAGE_SYSTEMD_ARCH_SUPPORTS=y +BR2_PACKAGE_SYSTEMD_BOOTCHART_ARCH_SUPPORTS=y +# BR2_PACKAGE_TEALDEER is not set + +# +# thermald needs a toolchain w/ C++, wchar, threads +# + +# +# thermald needs udev /dev management +# +# BR2_PACKAGE_TPM_TOOLS is not set +# BR2_PACKAGE_TPM2_ABRMD is not set +# BR2_PACKAGE_TPM2_TOOLS is not set +# BR2_PACKAGE_TPM2_TOTP is not set +# BR2_PACKAGE_UNSCD is not set +# BR2_PACKAGE_UTIL_LINUX is not set +# BR2_PACKAGE_WATCHDOG is not set +# BR2_PACKAGE_WATCHDOGD is not set +# BR2_PACKAGE_XDG_DBUS_PROXY is not set + +# +# Text editors and viewers +# +# BR2_PACKAGE_BAT is not set +# BR2_PACKAGE_BROOT is not set +# BR2_PACKAGE_BVI is not set +# BR2_PACKAGE_ED is not set +# BR2_PACKAGE_JOE is not set +# BR2_PACKAGE_MC is not set +# BR2_PACKAGE_MG is not set +# BR2_PACKAGE_MOST is not set +# BR2_PACKAGE_NANO is not set +# BR2_PACKAGE_NNN is not set +# BR2_PACKAGE_UEMACS is not set + +# +# Filesystem images +# +# BR2_TARGET_ROOTFS_BTRFS is not set +# BR2_TARGET_ROOTFS_CLOOP is not set +BR2_TARGET_ROOTFS_CPIO=y +BR2_TARGET_ROOTFS_CPIO_FULL=y +# BR2_TARGET_ROOTFS_CPIO_DRACUT is not set +# BR2_TARGET_ROOTFS_CPIO_NONE is not set +BR2_TARGET_ROOTFS_CPIO_GZIP=y +# BR2_TARGET_ROOTFS_CPIO_BZIP2 is not set +# BR2_TARGET_ROOTFS_CPIO_LZ4 is not set +# BR2_TARGET_ROOTFS_CPIO_LZMA is not set +# BR2_TARGET_ROOTFS_CPIO_LZO is not set +# BR2_TARGET_ROOTFS_CPIO_XZ is not set +# BR2_TARGET_ROOTFS_CPIO_ZSTD is not set +# BR2_TARGET_ROOTFS_CPIO_UIMAGE is not set +# BR2_TARGET_ROOTFS_CRAMFS is not set +# BR2_TARGET_ROOTFS_EROFS is not set +# BR2_TARGET_ROOTFS_EXT2 is not set +# BR2_TARGET_ROOTFS_F2FS is not set + +# +# initramfs needs a Linux kernel to be built +# + +# +# iso image needs a Linux kernel and either grub2 or isolinux to be built +# +# BR2_TARGET_ROOTFS_JFFS2 is not set +# BR2_TARGET_ROOTFS_OCI is not set +# BR2_TARGET_ROOTFS_SQUASHFS is not set +BR2_TARGET_ROOTFS_TAR=y +BR2_TARGET_ROOTFS_TAR_NONE=y +# BR2_TARGET_ROOTFS_TAR_GZIP is not set +# BR2_TARGET_ROOTFS_TAR_BZIP2 is not set +# BR2_TARGET_ROOTFS_TAR_LZ4 is not set +# BR2_TARGET_ROOTFS_TAR_LZMA is not set +# BR2_TARGET_ROOTFS_TAR_LZO is not set +# BR2_TARGET_ROOTFS_TAR_XZ is not set +# BR2_TARGET_ROOTFS_TAR_ZSTD is not set +BR2_TARGET_ROOTFS_TAR_OPTIONS="" +# BR2_TARGET_ROOTFS_UBI is not set +# BR2_TARGET_ROOTFS_UBIFS is not set +# BR2_TARGET_ROOTFS_YAFFS2 is not set + +# +# Bootloaders +# +# BR2_TARGET_BAREBOX is not set +BR2_TARGET_EDK2_ARCH_SUPPORTS=y +# BR2_TARGET_EDK2 is not set +BR2_TARGET_GRUB2_ARCH_SUPPORTS=y +# BR2_TARGET_GRUB2 is not set +BR2_PACKAGE_SHIM_ARCH_SUPPORTS=y +# BR2_TARGET_SHIM is not set +# BR2_TARGET_SYSLINUX is not set +# BR2_TARGET_UBOOT is not set + +# +# Host utilities +# +# BR2_PACKAGE_HOST_ABOOTIMG is not set +# BR2_PACKAGE_HOST_AESPIPE is not set +# BR2_PACKAGE_HOST_AGENT_PROXY is not set +# BR2_PACKAGE_HOST_AMLOGIC_BOOT_FIP is not set +# BR2_PACKAGE_HOST_ANDROID_TOOLS is not set +BR2_PACKAGE_HOST_ARM_GNU_TOOLCHAIN_SUPPORTS=y +# BR2_PACKAGE_HOST_ASN1C is not set +# BR2_PACKAGE_HOST_BABELTRACE2 is not set +# BR2_PACKAGE_HOST_BMAP_TOOLS is not set +# BR2_PACKAGE_HOST_BMAP_WRITER is not set +# BR2_PACKAGE_HOST_BOOTGEN is not set +# BR2_PACKAGE_HOST_BTRFS_PROGS is not set +# BR2_PACKAGE_HOST_CASYNC_NANO is not set +# BR2_PACKAGE_HOST_CHECKPOLICY is not set +# BR2_PACKAGE_HOST_CHECKSEC is not set +# BR2_PACKAGE_HOST_CMAKE is not set +BR2_HOST_CMAKE_AT_LEAST="3.18" +# BR2_PACKAGE_HOST_COMPOSER is not set +# BR2_PACKAGE_HOST_CRAMFS is not set +# BR2_PACKAGE_HOST_CRUDINI is not set +# BR2_PACKAGE_HOST_CRYPTSETUP is not set +# BR2_PACKAGE_HOST_DBUS_PYTHON is not set +# BR2_PACKAGE_HOST_DELVE is not set +# BR2_PACKAGE_HOST_DEPOT_TOOLS is not set +# BR2_PACKAGE_HOST_DFU_UTIL is not set +# BR2_PACKAGE_HOST_DOS2UNIX is not set +# BR2_PACKAGE_HOST_DOSFSTOOLS is not set +# BR2_PACKAGE_HOST_DOXYGEN is not set +# BR2_PACKAGE_HOST_DTC is not set +# BR2_PACKAGE_HOST_E2FSPROGS is not set +# BR2_PACKAGE_HOST_E2TOOLS is not set +# BR2_PACKAGE_HOST_ENVIRONMENT_SETUP is not set +# BR2_PACKAGE_HOST_EROFS_UTILS is not set +# BR2_PACKAGE_HOST_EXFATPROGS is not set +# BR2_PACKAGE_HOST_F2FS_TOOLS is not set +# BR2_PACKAGE_HOST_FAKETIME is not set +# BR2_PACKAGE_HOST_FATCAT is not set +# BR2_PACKAGE_HOST_FIRMWARE_UTILS is not set +BR2_PACKAGE_HOST_FLUTTER_SDK_BIN_ARCH_SUPPORTS=y +# BR2_PACKAGE_HOST_FLUTTER_SDK_BIN is not set +# BR2_PACKAGE_HOST_FWUP is not set +# BR2_PACKAGE_HOST_GENEXT2FS is not set +# BR2_PACKAGE_HOST_GENIMAGE is not set +# BR2_PACKAGE_HOST_GENPART is not set +# BR2_PACKAGE_HOST_GNUPG is not set +# BR2_PACKAGE_HOST_GNUPG2 is not set +BR2_PACKAGE_HOST_GO_TARGET_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GO_TARGET_CGO_LINKING_SUPPORTS=y +BR2_PACKAGE_HOST_GO_HOST_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GO_HOST_CGO_LINKING_SUPPORTS=y +# BR2_PACKAGE_HOST_GO is not set +BR2_PACKAGE_PROVIDES_HOST_GO="host-go-bin" +BR2_PACKAGE_HOST_GO_BIN_HOST_ARCH="amd64" +BR2_PACKAGE_HOST_GO_BIN_HOST_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GO_BOOTSTRAP_STAGE1_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GO_BOOTSTRAP_STAGE2_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GO_BOOTSTRAP_STAGE3_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GO_BOOTSTRAP_STAGE4_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_GOOGLE_BREAKPAD_ARCH_SUPPORTS=y +# BR2_PACKAGE_HOST_GPTFDISK is not set +# BR2_PACKAGE_HOST_IMAGEMAGICK is not set +# BR2_PACKAGE_HOST_IMX_MKIMAGE is not set +# BR2_PACKAGE_HOST_JQ is not set +# BR2_PACKAGE_HOST_JSMIN is not set +# BR2_PACKAGE_HOST_KMOD is not set +# BR2_PACKAGE_HOST_LIBP11 is not set +# BR2_PACKAGE_HOST_LLD is not set +# BR2_PACKAGE_HOST_LPC3250LOADER is not set +# BR2_PACKAGE_HOST_LTTNG_BABELTRACE is not set +# BR2_PACKAGE_HOST_LZMA_ALONE is not set +# BR2_PACKAGE_HOST_MENDER_ARTIFACT is not set +# BR2_PACKAGE_HOST_MESON_TOOLS is not set +# BR2_PACKAGE_HOST_MICROCHIP_HSS_PAYLOAD_GENERATOR is not set +# BR2_PACKAGE_HOST_MINISIGN is not set +# BR2_PACKAGE_HOST_MKPASSWD is not set +# BR2_PACKAGE_HOST_MOBY_BUILDKIT is not set +# BR2_PACKAGE_HOST_MOSQUITTO is not set +# BR2_PACKAGE_HOST_MTD is not set +# BR2_PACKAGE_HOST_MTOOLS is not set +BR2_PACKAGE_HOST_NODEJS_BIN_ARCH_SUPPORTS=y +# BR2_PACKAGE_HOST_NODEJS is not set +BR2_PACKAGE_PROVIDES_HOST_NODEJS="host-nodejs-bin" +# BR2_PACKAGE_HOST_ODB is not set +# BR2_PACKAGE_HOST_OPENOCD is not set +# BR2_PACKAGE_HOST_OPKG_UTILS is not set +# BR2_PACKAGE_HOST_PAHOLE is not set +# BR2_PACKAGE_HOST_PARTED is not set +BR2_PACKAGE_HOST_PATCHELF=y +# BR2_PACKAGE_HOST_PIGZ is not set +# BR2_PACKAGE_HOST_PKGCONF is not set +# BR2_PACKAGE_HOST_PWGEN is not set +# BR2_PACKAGE_HOST_PYTHON_CYTHON is not set +# BR2_PACKAGE_HOST_PYTHON_GREENLET is not set +# BR2_PACKAGE_HOST_PYTHON_INIPARSE is not set +# BR2_PACKAGE_HOST_PYTHON_LXML is not set +# BR2_PACKAGE_HOST_PYTHON_PYYAML is not set +# BR2_PACKAGE_HOST_PYTHON_SIX is not set +# BR2_PACKAGE_HOST_PYTHON_USWID is not set +# BR2_PACKAGE_HOST_PYTHON_XLRD is not set +# BR2_PACKAGE_HOST_PYTHON3 is not set +BR2_PACKAGE_HOST_QEMU_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_QEMU_SYSTEM_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_QEMU_USER_ARCH_SUPPORTS=y +# BR2_PACKAGE_HOST_QEMU is not set +# BR2_PACKAGE_HOST_QORIQ_RCW is not set +# BR2_PACKAGE_HOST_RAUC is not set +# BR2_PACKAGE_HOST_RISCV_ISA_SIM is not set +# BR2_PACKAGE_HOST_RUNC is not set +BR2_PACKAGE_HOST_RUSTC_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_RUSTC_TARGET_TIER1_PLATFORMS=y +BR2_PACKAGE_HOST_RUSTC_TARGET_ARCH_SUPPORTS=y +BR2_PACKAGE_HOST_RUSTC_ARCH="i686" +# BR2_PACKAGE_HOST_RUSTC is not set +BR2_PACKAGE_PROVIDES_HOST_RUSTC="host-rust-bin" +# BR2_PACKAGE_HOST_SAM_BA is not set +# BR2_PACKAGE_HOST_SDBUS_CPP is not set +# BR2_PACKAGE_HOST_SDBUSPLUS is not set +# BR2_PACKAGE_HOST_SENTRY_CLI is not set +# BR2_PACKAGE_HOST_SKOPEO is not set +# BR2_PACKAGE_HOST_SLOCI_IMAGE is not set +# BR2_PACKAGE_HOST_SNAGBOOT is not set +# BR2_PACKAGE_HOST_SQUASHFS is not set +# BR2_PACKAGE_HOST_SWIG is not set +# BR2_PACKAGE_HOST_SWTPM is not set +# BR2_PACKAGE_HOST_SWUGENERATOR is not set +# BR2_PACKAGE_HOST_TIPIDEE is not set +# BR2_PACKAGE_HOST_UBOOT_TOOLS is not set +# BR2_PACKAGE_HOST_UTIL_LINUX is not set +# BR2_PACKAGE_HOST_UTP_COM is not set +# BR2_PACKAGE_HOST_UUU is not set +# BR2_PACKAGE_HOST_VBOOT_UTILS is not set +# BR2_PACKAGE_HOST_XORRISO is not set +# BR2_PACKAGE_HOST_ZIP is not set +# BR2_PACKAGE_HOST_ZSTD is not set + +# +# Legacy config options +# + +# +# Legacy options removed in 2025.11 +# +# BR2_PACKAGE_LIBARGTABLE2 is not set +# BR2_PACKAGE_OLA is not set +# BR2_PACKAGE_BATMAN_ADV_NC is not set +# BR2_PACKAGE_DVBSNOOP is not set +# BR2_PACKAGE_PROCRANK_LINUX is not set +# BR2_PACKAGE_MONGREL2 is not set +# BR2_PACKAGE_EXPECT is not set +# BR2_PACKAGE_BCTOOLBOX is not set +# BR2_PACKAGE_ORTP is not set +# BR2_PACKAGE_MEDIASTREAMER is not set +# BR2_PACKAGE_BELR is not set +# BR2_PACKAGE_BELLE_SIP is not set +# BR2_PACKAGE_LINPHONE is not set +# BR2_PACKAGE_LIBJWT is not set +# BR2_PACKAGE_RAMSPEED is not set +# BR2_PACKAGE_LESSTIF is not set +# BR2_KERNEL_HEADERS_6_16 is not set +# BR2_PACKAGE_MURATA_CYW_FW_CYW4339_1CK is not set +# BR2_PACKAGE_MURATA_CYW_FW_CYW4339_ZP is not set +# BR2_PACKAGE_LIBBSON is not set +# BR2_TARGET_ROOTFS_AXFS is not set +# BR2_PACKAGE_LOGSURFER is not set +# BR2_LINUX_KERNEL_EXT_FBTFT is not set +# BR2_PACKAGE_DMENU_WAYLAND is not set +# BR2_PACKAGE_SYLPHEED is not set +# BR2_PACKAGE_PINENTRY_GTK2 is not set +# BR2_PACKAGE_OPENCV4_WITH_GTK is not set +# BR2_PACKAGE_OPENCV3_WITH_GTK is not set +# BR2_PACKAGE_NETSURF_GTK is not set +# BR2_PACKAGE_METACITY is not set +# BR2_PACKAGE_LIBSEXY is not set +# BR2_PACKAGE_LIBGLADE is not set +# BR2_PACKAGE_LEAFPAD is not set +# BR2_PACKAGE_GTKPERF is not set +# BR2_PACKAGE_GTK2_ENGINES is not set +# BR2_PACKAGE_GKRELLM_CLIENT is not set +# BR2_PACKAGE_CWIID_WMGUI is not set +# BR2_LINUX_KERNEL_EXT_AUFS is not set +# BR2_PACKAGE_AUFS_UTIL is not set +# BR2_TOOLCHAIN_EXTERNAL_LINARO_ARMEB is not set +# BR2_TOOLCHAIN_EXTERNAL_LINARO_ARM is not set +# BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64_BE is not set +# BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64 is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_MIPS is not set +# BR2_LINUX_KERNEL_EXT_EV3DEV_LINUX_DRIVERS is not set + +# +# Legacy options removed in 2025.08 +# +# BR2_PACKAGE_NETSTAT_NAT is not set +# BR2_PACKAGE_LIGHTTPD_LIBEV is not set +# BR2_PACKAGE_LIBSVGTINY is not set +# BR2_PACKAGE_THTTPD is not set +# BR2_KERNEL_HEADERS_6_15 is not set +# BR2_PACKAGE_LIBCURL_BEARSSL is not set +# BR2_PACKAGE_LIBOLM is not set +# BR2_PACKAGE_LIBWEBSOCK is not set +# BR2_TARGET_EDK2_PLATFORM_SOCIONEXT_DEVELOPERBOX is not set +# BR2_PACKAGE_LIBEBUR128 is not set +# BR2_KERNEL_HEADERS_6_14 is not set +# BR2_PACKAGE_GPSD_OCEANSERVER is not set +# BR2_PACKAGE_MESA3D_OSMESA_GALLIUM is not set +# BR2_PACKAGE_ALSA_LIB_ALISP is not set + +# +# Legacy options removed in 2025.05 +# +# BR2_GCC_VERSION_12_X is not set +# BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST is not set +# BR2_PACKAGE_MBEDTLS_COMPRESSION is not set +# BR2_KERNEL_HEADERS_6_13 is not set +# BR2_PACKAGE_MPD_SOUNDCLOUD is not set +# BR2_PACKAGE_DOCKER_ENGINE_DOCKER_INIT is not set + +# +# Legacy options removed in 2025.02 +# +# BR2_PACKAGE_SQLITE_ENABLE_JSON1 is not set +# BR2_PACKAGE_ANGULARJS is not set +# BR2_PACKAGE_ANGULAR_WEBSOCKET is not set +# BR2_PACKAGE_LATENCYTOP is not set +# BR2_PACKAGE_OBSIDIAN_CURSORS is not set +# BR2_PACKAGE_W_SCAN is not set +# BR2_PACKAGE_GENROMFS is not set +# BR2_TARGET_ROOTFS_ROMFS is not set +# BR2_BINUTILS_VERSION_2_41_X is not set +# BR2_TARGET_ROOTFS_EXT2_2r0 is not set +# BR2_GDB_VERSION_13 is not set +# BR2_nios2 is not set +# BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_NIOS2_GLIBC_BLEEDING_EDGE is not set +# BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_NIOS2_GLIBC_STABLE is not set +# BR2_PACKAGE_DIRECTFB is not set +# BR2_PACKAGE_GST_OMX is not set +# BR2_PACKAGE_MIMIC is not set +# BR2_PACKAGE_SDL2_DIRECTFB is not set +# BR2_PACKAGE_SDL_DIRECTFB is not set +# BR2_PACKAGE_QT5BASE_DIRECTFB is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_DIRECTFB is not set +# BR2_PACKAGE_LITE is not set +# BR2_PACKAGE_LINUX_FUSION is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES is not set +# BR2_PACKAGE_HIAWATHA is not set +# BR2_PACKAGE_MONGODB is not set +# BR2_PACKAGE_PYTHON_M2CRYPTO is not set +# BR2_KERNEL_HEADERS_4_19 is not set +# BR2_KERNEL_HEADERS_6_11 is not set +# BR2_PACKAGE_GIBLIB is not set +# BR2_PACKAGE_FCONFIG is not set +# BR2_PACKAGE_LIBHID is not set +# BR2_PACKAGE_QUAGGA is not set +# BR2_PACKAGE_RAMSMP is not set + +# +# Legacy options removed in 2024.11 +# +# BR2_PACKAGE_BSDIFF is not set +# BR2_PACKAGE_PROCPS_NS_ORIGINAL_TOP is not set +# BR2_PACKAGE_QEMU_TARGET_NIOS2 is not set +# BR2_PACKAGE_POPPERJS is not set +# BR2_KERNEL_HEADERS_6_10 is not set +BR2_PACKAGE_IPMITOOL_PEN_REG_URI="" +# BR2_PACKAGE_ERLANG_P1_YAML is not set +# BR2_PACKAGE_ERLANG_P1_XMPP is not set +# BR2_PACKAGE_ERLANG_P1_XML is not set +# BR2_PACKAGE_ERLANG_P1_STUN is not set +# BR2_PACKAGE_FBV_GIF is not set +# BR2_BINUTILS_VERSION_2_40_X is not set + +# +# Legacy options removed in 2024.08 +# +# BR2_PACKAGE_MIDORI is not set +# BR2_PACKAGE_FROTZ is not set +# BR2_PACKAGE_FAN_CTRL is not set +# BR2_PACKAGE_FLUTTER_DYNAMIC_LAYOUTS_EXAMPLE is not set +# BR2_KERNEL_HEADERS_6_9 is not set +# BR2_x86_knightslanding is not set +# BR2_x86_knightsmill is not set +# BR2_PACKAGE_DVB_APPS is not set +# BR2_PACKAGE_GAMIN is not set +# BR2_PACKAGE_CAIRO_SVG is not set +# BR2_PACKAGE_CAIRO_SCRIPT is not set +# BR2_PACKAGE_CAIRO_PS is not set +# BR2_PACKAGE_CAIRO_PDF is not set +# BR2_PACKAGE_CAIRO_XML is not set +# BR2_GDB_VERSION_12 is not set +# BR2_TARGET_BEAGLEV_DDRINIT is not set +# BR2_TARGET_BEAGLEV_SECONDBOOT is not set +# BR2_PACKAGE_ONEVPL_INTEL_GPU is not set +# BR2_PACKAGE_CGIC is not set +# BR2_PACKAGE_BEECRYPT is not set +# BR2_PACKAGE_VERSAL_FIRMWARE is not set +# BR2_KERNEL_HEADERS_6_8 is not set +# BR2_TARGET_AT91BOOTSTRAP is not set +# BR2_TARGET_AT91DATAFLASHBOOT is not set +# BR2_PACKAGE_ON2_8170_MODULES is not set +# BR2_PACKAGE_ON2_8170_LIBS is not set +# BR2_GCC_VERSION_11_X is not set +# BR2_BINFMT_FLAT_SHARED is not set +# BR2_PACKAGE_OMXPLAYER is not set +# BR2_KERNEL_HEADERS_6_7 is not set +# BR2_TARGET_TI_K3_IMAGE_GEN is not set +# BR2_TARGET_UBOOT_NEEDS_TI_K3_DM is not set +# BR2_PACKAGE_FLUTTER_GALLERY is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESCAPE_IMG_MIPS is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESCAPE_MTI_MIPS is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_AARCH64 is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_ARM is not set +# BR2_BINUTILS_VERSION_2_39_X is not set + +# +# Legacy options removed in 2024.02 +# +# BR2_PACKAGE_MYSQL is not set +# BR2_PACKAGE_ORACLE_MYSQL is not set +# BR2_PACKAGE_STRONGSWAN_SCEP is not set +# BR2_PACKAGE_SHADOW_UTMPX is not set +# BR2_PACKAGE_TINYMEMBENCH is not set +# BR2_PACKAGE_DAVINCI_BOOTCOUNT is not set +# BR2_PACKAGE_PYTHON_CROSSBAR is not set +# BR2_PACKAGE_PYTHON_PYGAME is not set +# BR2_KERNEL_HEADERS_4_14 is not set +# BR2_GDB_VERSION_11 is not set +# BR2_PACKAGE_LIBMPD is not set +# BR2_PACKAGE_GMPC is not set +# BR2_PACKAGE_FLICKCURL is not set +# BR2_PACKAGE_ONEVPL is not set +# BR2_KERNEL_HEADERS_6_5 is not set +BR2_PACKAGE_WATCHDOGD_GENERIC_POLL=0 +BR2_PACKAGE_WATCHDOGD_LOADAVG_POLL=0 +BR2_PACKAGE_WATCHDOGD_FILENR_POLL=0 +BR2_PACKAGE_WATCHDOGD_MEMINFO_POLL=0 + +# +# Legacy options removed in 2023.11 +# +# BR2_PACKAGE_PYTHON_PYXB is not set +# BR2_PACKAGE_OPENJDK_VERSION_11 is not set +# BR2_KERNEL_HEADERS_6_4 is not set +# BR2_PACKAGE_GOOGLE_MATERIAL_DESIGN_ICONS is not set +# BR2_GDB_VERSION_10 is not set + +# +# Legacy options removed in 2023.08 +# +# BR2_TARGET_LPC32XXCDL is not set +# BR2_BINUTILS_VERSION_2_38_X is not set +# BR2_GCC_VERSION_10_X is not set +# BR2_KERNEL_HEADERS_6_3 is not set +# BR2_PACKAGE_TOVID is not set +# BR2_PACKAGE_LIBASPLIB is not set +# BR2_PACKAGE_OCF_LINUX is not set +# BR2_BINUTILS_VERSION_2_37_X is not set + +# +# Legacy options removed in 2023.05 +# +# BR2_KERNEL_HEADERS_6_2 is not set +# BR2_PACKAGE_ATK is not set +# BR2_PACKAGE_AT_SPI2_ATK is not set +# BR2_PACKAGE_OPTEE_BENCHMARK is not set +# BR2_PACAKGE_OPENFPGALOADER_CMSIS is not set + +# +# Legacy options removed in 2023.02 +# +# BR2_PACKAGE_PUGIXML_HEADER_ONLY is not set +# BR2_PACKAGE_UCCP420WLAN is not set +# BR2_PACKAGE_IMX_GPU_G2D_EXAMPLES is not set +# BR2_KERNEL_HEADERS_6_0 is not set +# BR2_KERNEL_HEADERS_4_9 is not set +# BR2_PACKAGE_DOCKER_PROXY is not set +# BR2_PACKAGE_PYTHON_BUNCH is not set +# BR2_TARGET_GUMMIBOOT is not set +# BR2_PACKAGE_IPUTILS_NINFOD is not set +# BR2_PACKAGE_IPUTILS_RARPD is not set +# BR2_PACKAGE_IPUTILS_RDISC is not set +# BR2_PACKAGE_IPUTILS_RDISC_SERVER is not set +# BR2_PACKAGE_GST1_PLUGINS_UGLY_PLUGIN_XINGMUX is not set +# BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_VIDEOSCALE is not set +# BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_VIDEOCONVERT is not set +# BR2_PACKAGE_IMX_GPU_VIV_OUTPUT_X11 is not set +# BR2_PACKAGE_XDRIVER_XF86_VIDEO_IMX_VIV is not set +BR2_PACKAGE_QEMU_CUSTOM_TARGETS="" +# BR2_PACKAGE_XDRIVER_XF86_INPUT_KEYBOARD is not set +# BR2_TARGET_SUN20I_D1_SPL is not set +# BR2_PACKAGE_PYTHON_M2R is not set +# BR2_PACKAGE_MESA3D_XVMC is not set +# BR2_KERNEL_HEADERS_5_19 is not set +# BR2_PACKAGE_XDRIVER_XF86_VIDEO_TGA is not set +# BR2_PACKAGE_XDRIVER_XF86_VIDEO_GLINT is not set +# BR2_PACKAGE_USBREDIR_SERVER is not set + +# +# Legacy options removed in 2022.11 +# +# BR2_BINUTILS_VERSION_2_36_X is not set +# BR2_PACKAGE_RABBITMQ_SERVER is not set +# BR2_PACKAGE_LIBOPENSSL_ENABLE_RC5 is not set +# BR2_PACKAGE_LIBDCADEC is not set +# BR2_KERNEL_HEADERS_5_17 is not set +# BR2_iwmmxt is not set +# BR2_PACKAGE_UHD_N230 is not set +# BR2_PACKAGE_UHD_RFNOC is not set +# BR2_PACKAGE_GPSD_OLDSTYLE is not set +# BR2_GDB_VERSION_9_2 is not set + +# +# Legacy options removed in 2022.08 +# +# BR2_ECLIPSE_REGISTER is not set +# BR2_csky is not set +# BR2_PACKAGE_MESA3D_DRI_DRIVER_I915 is not set +# BR2_PACKAGE_MESA3D_DRI_DRIVER_I965 is not set +# BR2_PACKAGE_MESA3D_DRI_DRIVER_NOUVEAU is not set +# BR2_PACKAGE_MESA3D_DRI_DRIVER_RADEON is not set +# BR2_GCC_VERSION_9_X is not set +# BR2_PACKAGE_PHP_EXT_WDDX is not set +# BR2_nds32 is not set +# BR2_PACKAGE_RTL8723BS is not set + +# +# Legacy options removed in 2022.05 +# +# BR2_PACKAGE_KTAP is not set +# BR2_KERNEL_HEADERS_5_16 is not set +# BR2_KERNEL_HEADERS_4_4 is not set +# BR2_BINUTILS_VERSION_2_32_X is not set +# BR2_sh2a is not set +# BR2_BINUTILS_VERSION_2_35_X is not set +# BR2_PACKAGE_BOOST_LAYOUT_TAGGED is not set +# BR2_PACKAGE_BOOST_LAYOUT_VERSIONED is not set + +# +# Legacy options removed in 2022.02 +# +BR2_TARGET_ROOTFS_OCI_ENTRYPOINT_ARGS="" +# BR2_PACKAGE_LIBCURL_LIBNSS is not set +# BR2_PACKAGE_WESTON_DEFAULT_FBDEV is not set +# BR2_PACKAGE_WESTON_FBDEV is not set +# BR2_PACKAGE_PYTHON_PYCLI is not set +# BR2_PACKAGE_LINUX_TOOLS_BPFTOOL is not set +# BR2_TARGET_UBOOT_NEEDS_PYTHON2 is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_LIBMMS is not set +# BR2_PACKAGE_PYTHON_FUNCTOOLS32 is not set +# BR2_PACKAGE_PYTHON_ENUM34 is not set +# BR2_PACKAGE_PYTHON_ENUM is not set +# BR2_PACKAGE_PYTHON_DIALOG is not set +# BR2_PACKAGE_PYTHON_YIELDFROM is not set +# BR2_PACKAGE_PYTHON_TYPING is not set +# BR2_PACKAGE_PYTHON_SUBPROCESS32 is not set +# BR2_PACKAGE_PYTHON_SINGLEDISPATCH is not set +# BR2_PACKAGE_PYTHON_PYRO is not set +# BR2_PACKAGE_PYTHON_PYPCAP is not set +# BR2_PACKAGE_PYTHON_PATHLIB2 is not set +# BR2_PACKAGE_PYTHON_PAM is not set +# BR2_PACKAGE_PYTHON_NFC is not set +# BR2_PACKAGE_PYTHON_MAD is not set +# BR2_PACKAGE_PYTHON_IPADDRESS is not set +# BR2_PACKAGE_PYTHON_IPADDR is not set +# BR2_PACKAGE_PYTHON_ID3 is not set +# BR2_PACKAGE_PYTHON_FUTURES is not set +# BR2_PACKAGE_PYTHON_BACKPORTS_SSL_MATCH_HOSTNAME is not set +# BR2_PACKAGE_PYTHON_BACKPORTS_SHUTIL_GET_TERMINAL_SIZE is not set +# BR2_PACKAGE_PYTHON_BACKPORTS_ABC is not set +# BR2_PACKAGE_PYTHON is not set +# BR2_TARGET_UBOOT_ZYNQ_IMAGE is not set +# BR2_PACKAGE_HOST_GDB_PYTHON is not set +# BR2_PACKAGE_GSTREAMER1_MM is not set +# BR2_KERNEL_HEADERS_5_14 is not set +# BR2_PACKAGE_PYTHON_BACKPORTS_FUNCTOOLS_LRU_CACHE is not set +# BR2_PACKAGE_CIVETWEB_WITH_LUA is not set +# BR2_PACKAGE_SUNXI_MALI_MAINLINE_DRIVER is not set +# BR2_PACKAGE_SUNXI_MALI_MAINLINE is not set +# BR2_PACKAGE_SUNXI_MALI_MAINLINE_R6P2 is not set +# BR2_PACKAGE_SUNXI_MALI_MAINLINE_R8P1 is not set +# BR2_PACKAGE_QT5WEBKIT_EXAMPLES is not set +# BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_RISCV64_GLIBC_BLEEDING_EDGE is not set +# BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_RISCV64_MUSL_BLEEDING_EDGE is not set +# BR2_PACKAGE_IPUTILS_TFTPD is not set +# BR2_PACKAGE_IPUTILS_TRACEROUTE6 is not set +# BR2_PACKAGE_LIBMEDIAART_BACKEND_NONE is not set +# BR2_PACKAGE_MPD_UPNP is not set + +# +# Legacy options removed in 2021.11 +# +# BR2_OPENJDK_VERSION_LTS is not set +# BR2_OPENJDK_VERSION_LATEST is not set +# BR2_PACKAGE_MPD_TIDAL is not set +# BR2_PACKAGE_MROUTED_RSRR is not set +# BR2_BINUTILS_VERSION_CSKY is not set +# BR2_GCC_VERSION_CSKY is not set +# BR2_PACKAGE_CANFESTIVAL is not set +# BR2_PACKAGE_NMAP_NDIFF is not set +# BR2_GDB_VERSION_8_3 is not set +# BR2_PACKAGE_PYTHON_MELD3 is not set +# BR2_PACKAGE_STRONGSWAN_EAP is not set +# BR2_PACKAGE_GNURADIO_PAGER is not set +# BR2_KERNEL_HEADERS_5_11 is not set +# BR2_KERNEL_HEADERS_5_12 is not set +# BR2_KERNEL_HEADERS_5_13 is not set + +# +# Legacy options removed in 2021.08 +# +BR2_TARGET_GRUB2_BUILTIN_MODULES="" +BR2_TARGET_GRUB2_BUILTIN_CONFIG="" +# BR2_PACKAGE_LIBMCRYPT is not set +# BR2_PACKAGE_MCRYPT is not set +# BR2_PACKAGE_PHP_EXT_MCRYPT is not set +# BR2_BINUTILS_VERSION_2_34_X is not set +# BR2_PACKAGE_LIBSOIL is not set +# BR2_PACKAGE_CLAPACK is not set +# BR2_PACKAGE_SPIDERMONKEY is not set +# BR2_PACKAGE_KODI_LIBVA is not set +# BR2_PACKAGE_PYTHON_COHERENCE is not set +# BR2_PACKAGE_PHP_EXT_XMLRPC is not set +# BR2_GCC_VERSION_8_X is not set + +# +# Legacy options removed in 2021.05 +# +# BR2_PACKAGE_UDISKS_LVM2 is not set +# BR2_PACKAGE_LVM2_APP_LIBRARY is not set +# BR2_PACKAGE_LVM2_LVMETAD is not set +# BR2_PACKAGE_MONKEY is not set +# BR2_PACKAGE_DOCKER_CONTAINERD is not set +# BR2_PACKAGE_IOSTAT is not set +# BR2_PACKAGE_SCONESERVER_HTTP_SCONESITE_IMAGE is not set +# BR2_PACKAGE_XSERVER_XORG_SERVER_KDRIVE_EVDEV is not set +# BR2_PACKAGE_XSERVER_XORG_SERVER_KDRIVE_KBD is not set +# BR2_PACKAGE_XSERVER_XORG_SERVER_KDRIVE_MOUSE is not set +# BR2_PACKAGE_MESA3D_OSMESA_CLASSIC is not set +# BR2_PACKAGE_MESA3D_DRI_DRIVER_SWRAST is not set +# BR2_PACKAGE_KODI_SCREENSAVER_CRYSTALMORPH is not set + +# +# Legacy options removed in 2021.02 +# +# BR2_PACKAGE_MPD_AUDIOFILE is not set +# BR2_PACKAGE_AUDIOFILE is not set +# BR2_BINUTILS_VERSION_2_33_X is not set +# BR2_PACKAGE_LIBUPNP18 is not set +# BR2_PACKAGE_BOA is not set +# BR2_PACKAGE_LINUX_FIRMWARE_IMX_SDMA is not set +# BR2_GDB_VERSION_8_2 is not set +# BR2_PACKAGE_HOST_RCW is not set +# BR2_KERNEL_HEADERS_5_9 is not set +# BR2_KERNEL_HEADERS_5_8 is not set +# BR2_powerpc_601 is not set +# BR2_PACKAGE_TI_SGX_LIBGBM is not set +# BR2_PACKAGE_IPSEC_TOOLS is not set + +# +# Legacy options removed in 2020.11 +# +# BR2_PACKAGE_GPSD_FIXED_PORT_SPEED is not set +# BR2_PACKAGE_GPSD_RECONFIGURE is not set +# BR2_PACKAGE_GPSD_CONTROLSEND is not set +# BR2_PACKAGE_OPENCV is not set +# BR2_PACKAGE_LIBCROCO is not set +# BR2_PACKAGE_BELLAGIO is not set +# BR2_PACKAGE_SYSTEMD_JOURNAL_GATEWAY is not set +# BR2_TARGET_UBOOT_BOOT_SCRIPT is not set +# BR2_TARGET_UBOOT_ENVIMAGE is not set +# BR2_PACKAGE_KISMET_CLIENT is not set +# BR2_PACKAGE_KISMET_DRONE is not set +# BR2_GCC_VERSION_7_X is not set +# BR2_PACKAGE_GST1_VALIDATE is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_YADIF is not set +# BR2_PACKAGE_GQVIEW is not set +# BR2_PACKAGE_WESTON_IMX is not set +# BR2_KERNEL_HEADERS_5_7 is not set +# BR2_PACKAGE_TINYHTTPD is not set +# BR2_PACKAGE_XSERVER_XORG_SERVER_AIGLX is not set +# BR2_PACKAGE_AMD_CATALYST is not set +# BR2_PACKAGE_NVIDIA_TEGRA23 is not set +# BR2_GDB_VERSION_8_1 is not set + +# +# Legacy options removed in 2020.08 +# +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_AMD64 is not set +# BR2_KERNEL_HEADERS_5_6 is not set +# BR2_KERNEL_HEADERS_5_5 is not set +# BR2_BINUTILS_VERSION_2_31_X is not set +# BR2_PACKAGE_KODI_PERIPHERAL_STEAMCONTROLLER is not set + +# +# Legacy options removed in 2020.05 +# +# BR2_PACKAGE_WIRINGPI is not set +# BR2_PACKAGE_PYTHON_PYCRYPTO is not set +# BR2_PACKAGE_MTDEV2TUIO is not set +# BR2_PACKAGE_EZXML is not set +# BR2_PACKAGE_COLLECTD_LVM is not set +# BR2_PACKAGE_PYTHON_PYASN is not set +# BR2_PACKAGE_PYTHON_PYASN_MODULES is not set +# BR2_PACKAGE_LINUX_FIRMWARE_ATHEROS_10K_QCA6174 is not set +# BR2_PACKAGE_QT5CANVAS3D is not set +# BR2_PACKAGE_KODI_LIBTHEORA is not set +# BR2_PACKAGE_CEGUI06 is not set +# BR2_GCC_VERSION_5_X is not set + +# +# Legacy options removed in 2020.02 +# +# BR2_PACKAGE_JAMVM is not set +# BR2_PACKAGE_CLASSPATH is not set +# BR2_PACKAGE_QT5_VERSION_5_6 is not set +# BR2_PACKAGE_CURL is not set +# BR2_PACKAGE_GSTREAMER is not set +# BR2_PACKAGE_NVIDIA_TEGRA23_BINARIES_GSTREAMER_PLUGINS is not set +# BR2_PACKAGE_NVIDIA_TEGRA23_BINARIES_NV_SAMPLE_APPS is not set +# BR2_PACKAGE_FREERDP_GSTREAMER is not set +# BR2_PACKAGE_OPENCV3_WITH_GSTREAMER is not set +# BR2_PACKAGE_OPENCV_WITH_GSTREAMER is not set +# BR2_PACKAGE_LIBPLAYER is not set +# BR2_GCC_VERSION_OR1K is not set +# BR2_PACKAGE_BLUEZ_UTILS is not set +# BR2_PACKAGE_GADGETFS_TEST is not set +# BR2_PACKAGE_FIS is not set +BR2_PACKAGE_REFPOLICY_POLICY_VERSION="" +# BR2_PACKAGE_CELT051 is not set +# BR2_PACKAGE_WIREGUARD is not set +# BR2_PACKAGE_PERL_NET_PING is not set +# BR2_PACKAGE_PERL_MIME_BASE64 is not set +# BR2_PACKAGE_PERL_DIGEST_MD5 is not set +# BR2_PACKAGE_ERLANG_P1_ICONV is not set +# BR2_KERNEL_HEADERS_5_3 is not set +# BR2_PACKAGE_PYTHON_SCAPY3K is not set +# BR2_BINUTILS_VERSION_2_30_X is not set +# BR2_PACKAGE_RPI_USERLAND_START_VCFILED is not set +# BR2_PACKAGE_TI_SGX_KM_AM335X is not set +# BR2_PACKAGE_TI_SGX_KM_AM437X is not set +# BR2_PACKAGE_TI_SGX_KM_AM4430 is not set +# BR2_PACKAGE_TI_SGX_KM_AM5430 is not set + +# +# Legacy options removed in 2019.11 +# +# BR2_PACKAGE_OPENVMTOOLS_PROCPS is not set +# BR2_PACKAGE_ALLJOYN is not set +# BR2_PACKAGE_ALLJOYN_BASE is not set +# BR2_PACKAGE_ALLJOYN_BASE_CONTROLPANEL is not set +# BR2_PACKAGE_ALLJOYN_BASE_NOTIFICATION is not set +# BR2_PACKAGE_ALLJOYN_BASE_ONBOARDING is not set +# BR2_PACKAGE_ALLJOYN_TCL_BASE is not set +# BR2_PACKAGE_ALLJOYN_TCL is not set +BR2_TOOLCHAIN_EXTRA_EXTERNAL_LIBS="" +# BR2_PACKAGE_PYTHON_PYSNMP_APPS is not set +# BR2_KERNEL_HEADERS_5_2 is not set +# BR2_TARGET_RISCV_PK is not set +# BR2_PACKAGE_SQLITE_STAT3 is not set +# BR2_KERNEL_HEADERS_5_1 is not set +# BR2_PACKAGE_DEVMEM2 is not set +# BR2_PACKAGE_USTR is not set +# BR2_PACKAGE_KODI_SCREENSAVER_PLANESTATE is not set +# BR2_PACKAGE_KODI_VISUALISATION_WAVEFORHUE is not set +# BR2_PACKAGE_KODI_AUDIODECODER_OPUS is not set +# BR2_PACKAGE_MESA3D_OSMESA is not set +# BR2_PACKAGE_HOSTAPD_DRIVER_RTW is not set +# BR2_PACKAGE_WPA_SUPPLICANT_DBUS_NEW is not set +# BR2_PACKAGE_WPA_SUPPLICANT_DBUS_OLD is not set + +# +# Legacy options removed in 2019.08 +# +# BR2_TARGET_TS4800_MBRBOOT is not set +# BR2_PACKAGE_LIBAMCODEC is not set +# BR2_PACKAGE_ODROID_SCRIPTS is not set +# BR2_PACKAGE_ODROID_MALI is not set +# BR2_PACKAGE_KODI_PLATFORM_AML is not set +# BR2_GCC_VERSION_6_X is not set +# BR2_GCC_VERSION_4_9_X is not set +# BR2_GDB_VERSION_7_12 is not set +# BR2_PACKAGE_XAPP_MKFONTDIR is not set +# BR2_GDB_VERSION_8_0 is not set +# BR2_KERNEL_HEADERS_4_20 is not set +# BR2_KERNEL_HEADERS_5_0 is not set + +# +# Legacy options removed in 2019.05 +# +# BR2_CSKY_DSP is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_COMPOSITOR is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_IQA is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_OPENCV is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_STEREO is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_VCD is not set +# BR2_PACKAGE_LUNIT is not set +# BR2_PACKAGE_FFMPEG_FFSERVER is not set +# BR2_PACKAGE_LIBUMP is not set +# BR2_PACKAGE_SUNXI_MALI is not set +# BR2_BINUTILS_VERSION_2_29_X is not set +# BR2_BINUTILS_VERSION_2_28_X is not set +# BR2_PACKAGE_GST_PLUGINS_BAD_PLUGIN_APEXSINK is not set + +# +# Legacy options removed in 2019.02 +# +# BR2_PACKAGE_QT is not set +# BR2_PACKAGE_QTUIO is not set +# BR2_PACKAGE_PINENTRY_QT4 is not set +# BR2_PACKAGE_POPPLER_QT is not set +# BR2_PACKAGE_OPENCV3_WITH_QT is not set +# BR2_PACKAGE_OPENCV_WITH_QT is not set +# BR2_PACKAGE_AMD_CATALYST_CCCLE is not set +# BR2_PACKAGE_SDL_QTOPIA is not set +# BR2_PACKAGE_PYTHON_PYQT is not set +# BR2_PACKAGE_LUACRYPTO is not set +# BR2_PACKAGE_TN5250 is not set +# BR2_PACKAGE_BOOST_SIGNALS is not set +# BR2_PACKAGE_FFTW_PRECISION_SINGLE is not set +# BR2_PACKAGE_FFTW_PRECISION_DOUBLE is not set +# BR2_PACKAGE_FFTW_PRECISION_LONG_DOUBLE is not set +# BR2_PACKAGE_FFTW_PRECISION_QUAD is not set +# BR2_PACKAGE_LUA_5_2 is not set +# BR2_TARGET_GENERIC_PASSWD_MD5 is not set + +# +# Legacy options removed in 2018.11 +# +# BR2_TARGET_XLOADER is not set +# BR2_PACKAGE_TIDSP_BINARIES is not set +# BR2_PACKAGE_DSP_TOOLS is not set +# BR2_PACKAGE_GST_DSP is not set +# BR2_PACKAGE_BOOTUTILS is not set +# BR2_PACKAGE_EXPEDITE is not set +# BR2_PACKAGE_MESA3D_OPENGL_TEXTURE_FLOAT is not set +# BR2_KERNEL_HEADERS_4_10 is not set +# BR2_KERNEL_HEADERS_4_11 is not set +# BR2_KERNEL_HEADERS_4_12 is not set +# BR2_KERNEL_HEADERS_4_13 is not set +# BR2_KERNEL_HEADERS_4_15 is not set +# BR2_KERNEL_HEADERS_4_17 is not set +# BR2_PACKAGE_LIBNFTNL_XML is not set +# BR2_KERNEL_HEADERS_3_2 is not set +# BR2_KERNEL_HEADERS_4_1 is not set +# BR2_KERNEL_HEADERS_4_16 is not set +# BR2_KERNEL_HEADERS_4_18 is not set + +# +# Legacy options removed in 2018.08 +# +# BR2_PACKAGE_DOCKER_ENGINE_STATIC_CLIENT is not set +# BR2_PACKAGE_XPROTO_APPLEWMPROTO is not set +# BR2_PACKAGE_XPROTO_BIGREQSPROTO is not set +# BR2_PACKAGE_XPROTO_COMPOSITEPROTO is not set +# BR2_PACKAGE_XPROTO_DAMAGEPROTO is not set +# BR2_PACKAGE_XPROTO_DMXPROTO is not set +# BR2_PACKAGE_XPROTO_DRI2PROTO is not set +# BR2_PACKAGE_XPROTO_DRI3PROTO is not set +# BR2_PACKAGE_XPROTO_FIXESPROTO is not set +# BR2_PACKAGE_XPROTO_FONTCACHEPROTO is not set +# BR2_PACKAGE_XPROTO_FONTSPROTO is not set +# BR2_PACKAGE_XPROTO_GLPROTO is not set +# BR2_PACKAGE_XPROTO_INPUTPROTO is not set +# BR2_PACKAGE_XPROTO_KBPROTO is not set +# BR2_PACKAGE_XPROTO_PRESENTPROTO is not set +# BR2_PACKAGE_XPROTO_RANDRPROTO is not set +# BR2_PACKAGE_XPROTO_RECORDPROTO is not set +# BR2_PACKAGE_XPROTO_RENDERPROTO is not set +# BR2_PACKAGE_XPROTO_RESOURCEPROTO is not set +# BR2_PACKAGE_XPROTO_SCRNSAVERPROTO is not set +# BR2_PACKAGE_XPROTO_VIDEOPROTO is not set +# BR2_PACKAGE_XPROTO_WINDOWSWMPROTO is not set +# BR2_PACKAGE_XPROTO_XCMISCPROTO is not set +# BR2_PACKAGE_XPROTO_XEXTPROTO is not set +# BR2_PACKAGE_XPROTO_XF86BIGFONTPROTO is not set +# BR2_PACKAGE_XPROTO_XF86DGAPROTO is not set +# BR2_PACKAGE_XPROTO_XF86DRIPROTO is not set +# BR2_PACKAGE_XPROTO_XF86VIDMODEPROTO is not set +# BR2_PACKAGE_XPROTO_XINERAMAPROTO is not set +# BR2_PACKAGE_XPROTO_XPROTO is not set +# BR2_PACKAGE_XPROTO_XPROXYMANAGEMENTPROTOCOL is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_OPENGL is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_GLES2 is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_GLX is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_EGL is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_X11 is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_WAYLAND is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_LIB_OPENGL_DISPMANX is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_AUDIOMIXER is not set +# BR2_PACKAGE_GST1_PLUGINS_UGLY_PLUGIN_LAME is not set +# BR2_PACKAGE_GST1_PLUGINS_UGLY_PLUGIN_MPG123 is not set +# BR2_GDB_VERSION_7_11 is not set +# BR2_GDB_VERSION_7_10 is not set + +# +# Legacy options removed in 2018.05 +# +# BR2_PACKAGE_MEDIAART_BACKEND_NONE is not set +# BR2_PACKAGE_MEDIAART_BACKEND_GDK_PIXBUF is not set +# BR2_PACKAGE_MEDIAART_BACKEND_QT is not set +# BR2_PACKAGE_TI_SGX_AM335X is not set +# BR2_PACKAGE_TI_SGX_AM437X is not set +# BR2_PACKAGE_TI_SGX_AM4430 is not set +# BR2_PACKAGE_TI_SGX_AM5430 is not set +# BR2_PACKAGE_JANUS_AUDIO_BRIDGE is not set +# BR2_PACKAGE_JANUS_ECHO_TEST is not set +# BR2_PACKAGE_JANUS_RECORDPLAY is not set +# BR2_PACKAGE_JANUS_SIP_GATEWAY is not set +# BR2_PACKAGE_JANUS_STREAMING is not set +# BR2_PACKAGE_JANUS_TEXT_ROOM is not set +# BR2_PACKAGE_JANUS_VIDEO_CALL is not set +# BR2_PACKAGE_JANUS_VIDEO_ROOM is not set +# BR2_PACKAGE_JANUS_MQTT is not set +# BR2_PACKAGE_JANUS_RABBITMQ is not set +# BR2_PACKAGE_JANUS_REST is not set +# BR2_PACKAGE_JANUS_UNIX_SOCKETS is not set +# BR2_PACKAGE_JANUS_WEBSOCKETS is not set +# BR2_PACKAGE_IPSEC_SECCTX_DISABLE is not set +# BR2_PACKAGE_IPSEC_SECCTX_ENABLE is not set +# BR2_PACKAGE_IPSEC_SECCTX_KERNEL is not set +# BR2_PACKAGE_LIBTFDI_CPP is not set +# BR2_PACKAGE_JQUERY_UI_THEME_BLACK_TIE is not set +# BR2_PACKAGE_JQUERY_UI_THEME_BLITZER is not set +# BR2_PACKAGE_JQUERY_UI_THEME_CUPERTINO is not set +# BR2_PACKAGE_JQUERY_UI_THEME_DARK_HIVE is not set +# BR2_PACKAGE_JQUERY_UI_THEME_DOT_LUV is not set +# BR2_PACKAGE_JQUERY_UI_THEME_EGGPLANT is not set +# BR2_PACKAGE_JQUERY_UI_THEME_EXCITE_BIKE is not set +# BR2_PACKAGE_JQUERY_UI_THEME_FLICK is not set +# BR2_PACKAGE_JQUERY_UI_THEME_HOT_SNEAKS is not set +# BR2_PACKAGE_JQUERY_UI_THEME_HUMANITY is not set +# BR2_PACKAGE_JQUERY_UI_THEME_LE_FROG is not set +# BR2_PACKAGE_JQUERY_UI_THEME_MINT_CHOC is not set +# BR2_PACKAGE_JQUERY_UI_THEME_OVERCAST is not set +# BR2_PACKAGE_JQUERY_UI_THEME_PEPPER_GRINDER is not set +# BR2_PACKAGE_JQUERY_UI_THEME_REDMOND is not set +# BR2_PACKAGE_JQUERY_UI_THEME_SMOOTHNESS is not set +# BR2_PACKAGE_JQUERY_UI_THEME_SOUTH_STREET is not set +# BR2_PACKAGE_JQUERY_UI_THEME_START is not set +# BR2_PACKAGE_JQUERY_UI_THEME_SUNNY is not set +# BR2_PACKAGE_JQUERY_UI_THEME_SWANKY_PURSE is not set +# BR2_PACKAGE_JQUERY_UI_THEME_TRONTASTIC is not set +# BR2_PACKAGE_JQUERY_UI_THEME_UI_DARKNESS is not set +# BR2_PACKAGE_JQUERY_UI_THEME_UI_LIGHTNESS is not set +# BR2_PACKAGE_JQUERY_UI_THEME_VADER is not set +# BR2_PACKAGE_BLUEZ5_PLUGINS_HEALTH is not set +# BR2_PACKAGE_BLUEZ5_PLUGINS_MIDI is not set +# BR2_PACKAGE_BLUEZ5_PLUGINS_NFC is not set +# BR2_PACKAGE_BLUEZ5_PLUGINS_SAP is not set +# BR2_PACKAGE_BLUEZ5_PLUGINS_SIXAXIS is not set +# BR2_PACKAGE_TRANSMISSION_REMOTE is not set +# BR2_PACKAGE_LIBKCAPI_APPS is not set +# BR2_PACKAGE_MPLAYER is not set +# BR2_PACKAGE_MPLAYER_MPLAYER is not set +# BR2_PACKAGE_MPLAYER_MENCODER is not set +# BR2_PACKAGE_LIBPLAYER_MPLAYER is not set +# BR2_PACKAGE_IQVLINUX is not set +# BR2_BINFMT_FLAT_SEP_DATA is not set +# BR2_bfin is not set +# BR2_PACKAGE_KODI_ADSP_BASIC is not set +# BR2_PACKAGE_KODI_ADSP_FREESURROUND is not set + +# +# Legacy options removed in 2018.02 +# +# BR2_KERNEL_HEADERS_3_4 is not set +# BR2_KERNEL_HEADERS_3_10 is not set +# BR2_KERNEL_HEADERS_3_12 is not set +# BR2_BINUTILS_VERSION_2_27_X is not set +# BR2_PACKAGE_EEPROG is not set +# BR2_PACKAGE_GNUPG2_GPGV2 is not set +# BR2_PACKAGE_IMX_GPU_VIV_APITRACE is not set +# BR2_PACKAGE_IMX_GPU_VIV_G2D is not set + +# +# Legacy options removed in 2017.11 +# +# BR2_PACKAGE_RFKILL is not set +# BR2_PACKAGE_UTIL_LINUX_RESET is not set +# BR2_PACKAGE_POLICYCOREUTILS_AUDIT2ALLOW is not set +# BR2_PACKAGE_POLICYCOREUTILS_RESTORECOND is not set +# BR2_PACKAGE_SEPOLGEN is not set +# BR2_PACKAGE_OPENOBEX_BLUEZ is not set +# BR2_PACKAGE_OPENOBEX_LIBUSB is not set +# BR2_PACKAGE_OPENOBEX_APPS is not set +# BR2_PACKAGE_OPENOBEX_SYSLOG is not set +# BR2_PACKAGE_OPENOBEX_DUMP is not set +# BR2_PACKAGE_AICCU is not set +# BR2_PACKAGE_UTIL_LINUX_LOGIN_UTILS is not set + +# +# Legacy options removed in 2017.08 +# +# BR2_TARGET_GRUB is not set +# BR2_PACKAGE_SIMICSFS is not set +# BR2_BINUTILS_VERSION_2_26_X is not set +BR2_XTENSA_OVERLAY_DIR="" +BR2_XTENSA_CUSTOM_NAME="" +# BR2_PACKAGE_HOST_MKE2IMG is not set +BR2_TARGET_ROOTFS_EXT2_BLOCKS=0 +BR2_TARGET_ROOTFS_EXT2_EXTRA_INODES=0 +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_CDXAPARSE is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_DATAURISRC is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_DCCP is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_HDVPARSE is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_MVE is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_NUVDEMUX is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_PATCHDETECT is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_SDI is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_TTA is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_VIDEOMEASURE is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_APEXSINK is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_SDL is not set +# BR2_PACKAGE_GST1_PLUGINS_UGLY_PLUGIN_MAD is not set +# BR2_STRIP_none is not set +# BR2_PACKAGE_BEECRYPT_CPP is not set +# BR2_PACKAGE_SPICE_CLIENT is not set +# BR2_PACKAGE_SPICE_GUI is not set +# BR2_PACKAGE_SPICE_TUNNEL is not set +# BR2_PACKAGE_INPUT_TOOLS is not set +# BR2_PACKAGE_INPUT_TOOLS_INPUTATTACH is not set +# BR2_PACKAGE_INPUT_TOOLS_JSCAL is not set +# BR2_PACKAGE_INPUT_TOOLS_JSTEST is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_SH is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_X86 is not set +# BR2_GCC_VERSION_4_8_X is not set + +# +# Legacy options removed in 2017.05 +# +# BR2_PACKAGE_SUNXI_MALI_R2P4 is not set +# BR2_PACKAGE_NODEJS_MODULES_COFFEESCRIPT is not set +# BR2_PACKAGE_NODEJS_MODULES_EXPRESS is not set +# BR2_PACKAGE_BLUEZ5_UTILS_GATTTOOL is not set +# BR2_PACKAGE_OPENOCD_FT2XXX is not set +# BR2_PACKAGE_KODI_RTMPDUMP is not set +# BR2_PACKAGE_KODI_VISUALISATION_FOUNTAIN is not set +# BR2_PACKAGE_PORTMAP is not set +# BR2_BINUTILS_VERSION_2_25_X is not set +# BR2_TOOLCHAIN_BUILDROOT_INET_RPC is not set +BR2_TARGET_ROOTFS_EXT2_EXTRA_BLOCKS=0 +# BR2_PACKAGE_SYSTEMD_KDBUS is not set +# BR2_PACKAGE_POLARSSL is not set +# BR2_NBD_CLIENT is not set +# BR2_NBD_SERVER is not set +# BR2_PACKAGE_GMOCK is not set +# BR2_KERNEL_HEADERS_4_8 is not set +# BR2_KERNEL_HEADERS_3_18 is not set +# BR2_GLIBC_VERSION_2_22 is not set + +# +# Legacy options removed in 2017.02 +# +# BR2_PACKAGE_PERL_DB_FILE is not set +# BR2_KERNEL_HEADERS_4_7 is not set +# BR2_KERNEL_HEADERS_4_6 is not set +# BR2_KERNEL_HEADERS_4_5 is not set +# BR2_KERNEL_HEADERS_3_14 is not set +# BR2_TOOLCHAIN_EXTERNAL_MUSL_CROSS is not set +# BR2_UCLIBC_INSTALL_TEST_SUITE is not set +# BR2_TOOLCHAIN_EXTERNAL_BLACKFIN_UCLINUX is not set +# BR2_PACKAGE_MAKEDEVS is not set +# BR2_TOOLCHAIN_EXTERNAL_ARAGO_ARMV7A is not set +# BR2_TOOLCHAIN_EXTERNAL_ARAGO_ARMV5TE is not set +# BR2_PACKAGE_SNOWBALL_HDMISERVICE is not set +# BR2_PACKAGE_SNOWBALL_INIT is not set +# BR2_GDB_VERSION_7_9 is not set + +# +# Legacy options removed in 2016.11 +# +# BR2_PACKAGE_PHP_SAPI_CLI_CGI is not set +# BR2_PACKAGE_PHP_SAPI_CLI_FPM is not set +# BR2_PACKAGE_WVSTREAMS is not set +# BR2_PACKAGE_WVDIAL is not set +# BR2_PACKAGE_WEBKITGTK24 is not set +# BR2_PACKAGE_TORSMO is not set +# BR2_PACKAGE_SSTRIP is not set +# BR2_KERNEL_HEADERS_4_3 is not set +# BR2_KERNEL_HEADERS_4_2 is not set +# BR2_PACKAGE_KODI_ADDON_XVDR is not set +# BR2_PACKAGE_IPKG is not set +# BR2_GCC_VERSION_4_7_X is not set +# BR2_BINUTILS_VERSION_2_24_X is not set +# BR2_PACKAGE_WESTON_RPI is not set +# BR2_GCC_VERSION_4_8_ARC is not set +# BR2_KERNEL_HEADERS_4_0 is not set +# BR2_KERNEL_HEADERS_3_19 is not set +# BR2_PACKAGE_LIBEVAS_GENERIC_LOADERS is not set +# BR2_PACKAGE_ELEMENTARY is not set +# BR2_LINUX_KERNEL_CUSTOM_LOCAL is not set + +# +# Legacy options removed in 2016.08 +# +# BR2_PACKAGE_EFL_JP2K is not set +# BR2_PACKAGE_SYSTEMD_COMPAT is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_LIVEADDER is not set +# BR2_PACKAGE_LIBFSLVPUWRAP is not set +# BR2_PACKAGE_LIBFSLPARSER is not set +# BR2_PACKAGE_LIBFSLCODEC is not set +# BR2_PACKAGE_UBOOT_TOOLS_MKIMAGE_FIT_SIGNATURE_SUPPORT is not set +# BR2_PTHREADS_OLD is not set +# BR2_BINUTILS_VERSION_2_23_X is not set +# BR2_TOOLCHAIN_BUILDROOT_EGLIBC is not set +# BR2_GDB_VERSION_7_8 is not set + +# +# Legacy options removed in 2016.05 +# +# BR2_PACKAGE_OPENVPN_CRYPTO_POLARSSL is not set +# BR2_PACKAGE_NGINX_HTTP_SPDY_MODULE is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_RTP is not set +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_MPG123 is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_POWERPC is not set +# BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_POWERPC_E500V2 is not set +# BR2_x86_i386 is not set +# BR2_PACKAGE_QT5QUICK1 is not set +BR2_TARGET_UBOOT_CUSTOM_PATCH_DIR="" +# BR2_PACKAGE_XDRIVER_XF86_INPUT_VOID is not set +# BR2_KERNEL_HEADERS_3_17 is not set +# BR2_GDB_VERSION_7_7 is not set +# BR2_PACKAGE_FOOMATIC_FILTERS is not set +# BR2_PACKAGE_SAMBA is not set +# BR2_PACKAGE_KODI_WAVPACK is not set +# BR2_PACKAGE_KODI_RSXS is not set +# BR2_PACKAGE_KODI_GOOM is not set +# BR2_PACKAGE_SYSTEMD_ALL_EXTRAS is not set +# BR2_GCC_VERSION_4_5_X is not set +# BR2_PACKAGE_SQLITE_READLINE is not set + +# +# Legacy options removed in 2016.02 +# +# BR2_PACKAGE_DOVECOT_BZIP2 is not set +# BR2_PACKAGE_DOVECOT_ZLIB is not set +# BR2_PACKAGE_E2FSPROGS_FINDFS is not set +# BR2_PACKAGE_OPENPOWERLINK_DEBUG_LEVEL is not set +# BR2_PACKAGE_OPENPOWERLINK_KERNEL_MODULE is not set +# BR2_PACKAGE_OPENPOWERLINK_LIBPCAP is not set +# BR2_LINUX_KERNEL_SAME_AS_HEADERS is not set +# BR2_PACKAGE_CUPS_PDFTOPS is not set +# BR2_KERNEL_HEADERS_3_16 is not set +# BR2_PACKAGE_PYTHON_PYXML is not set +# BR2_ENABLE_SSP is not set +# BR2_PACKAGE_DIRECTFB_CLE266 is not set +# BR2_PACKAGE_DIRECTFB_UNICHROME is not set +# BR2_PACKAGE_LIBELEMENTARY is not set +# BR2_PACKAGE_LIBEINA is not set +# BR2_PACKAGE_LIBEET is not set +# BR2_PACKAGE_LIBEVAS is not set +# BR2_PACKAGE_LIBECORE is not set +# BR2_PACKAGE_LIBEDBUS is not set +# BR2_PACKAGE_LIBEFREET is not set +# BR2_PACKAGE_LIBEIO is not set +# BR2_PACKAGE_LIBEMBRYO is not set +# BR2_PACKAGE_LIBEDJE is not set +# BR2_PACKAGE_LIBETHUMB is not set +# BR2_PACKAGE_INFOZIP is not set +# BR2_BR2_PACKAGE_NODEJS_0_10_X is not set +# BR2_BR2_PACKAGE_NODEJS_0_12_X is not set +# BR2_BR2_PACKAGE_NODEJS_4_X is not set + +# +# Legacy options removed in 2015.11 +# +# BR2_PACKAGE_GST1_PLUGINS_BAD_PLUGIN_REAL is not set +# BR2_PACKAGE_MEDIA_CTL is not set +# BR2_PACKAGE_SCHIFRA is not set +# BR2_PACKAGE_ZXING is not set +# BR2_PACKAGE_BLACKBOX is not set +# BR2_KERNEL_HEADERS_3_0 is not set +# BR2_KERNEL_HEADERS_3_11 is not set +# BR2_KERNEL_HEADERS_3_13 is not set +# BR2_KERNEL_HEADERS_3_15 is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_ANDI is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_BLTLOAD is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_CPULOAD is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_DATABUFFER is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_DIOLOAD is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_DOK is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_DRIVERTEST is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_FIRE is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_FLIP is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_FONTS is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_INPUT is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_JOYSTICK is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_KNUCKLES is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_LAYER is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_MATRIX is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_MATRIX_WATER is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_NEO is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_NETLOAD is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_PALETTE is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_PARTICLE is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_PORTER is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_STRESS is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_TEXTURE is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_VIDEO is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_VIDEO_PARTICLE is not set +# BR2_PACKAGE_DIRECTFB_EXAMPLES_WINDOW is not set +# BR2_PACKAGE_KOBS_NG is not set +# BR2_PACKAGE_SAWMAN is not set +# BR2_PACKAGE_DIVINE is not set + +# +# Legacy options removed in 2015.08 +# +# BR2_PACKAGE_KODI_PVR_ADDONS is not set +# BR2_BINUTILS_VERSION_2_23_2 is not set +# BR2_BINUTILS_VERSION_2_24 is not set +# BR2_BINUTILS_VERSION_2_25 is not set +# BR2_PACKAGE_PERF is not set +# BR2_BINUTILS_VERSION_2_22 is not set +# BR2_PACKAGE_GPU_VIV_BIN_MX6Q is not set +# BR2_TARGET_UBOOT_NETWORK is not set diff --git a/examples/simple/x86_64_images/linux_config b/examples/simple/x86_64_images/linux_config new file mode 100644 index 000000000..66ab962b7 --- /dev/null +++ b/examples/simple/x86_64_images/linux_config @@ -0,0 +1,5478 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/x86_64 6.19.0 Kernel Configuration +# +CONFIG_CC_VERSION_TEXT="gcc (Debian 15.2.0-15) 15.2.0" +CONFIG_CC_IS_GCC=y +CONFIG_GCC_VERSION=150200 +CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=24600 +CONFIG_LD_IS_BFD=y +CONFIG_LD_VERSION=24600 +CONFIG_LLD_VERSION=0 +CONFIG_RUSTC_VERSION=108700 +CONFIG_RUSTC_LLVM_VERSION=200101 +CONFIG_CC_CAN_LINK=y +CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y +CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_CC_HAS_ASM_INLINE=y +CONFIG_CC_HAS_ASSUME=y +CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y +CONFIG_CC_HAS_COUNTED_BY=y +CONFIG_CC_HAS_MULTIDIMENSIONAL_NONSTRING=y +CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY=y +CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED=y +CONFIG_RUSTC_HAS_COERCE_POINTEE=y +CONFIG_PAHOLE_VERSION=0 +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_TABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +CONFIG_WERROR=y +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_BUILD_SALT="" +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +CONFIG_HAVE_KERNEL_ZSTD=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +# CONFIG_KERNEL_LZ4 is not set +# CONFIG_KERNEL_ZSTD is not set +CONFIG_DEFAULT_INIT="" +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_WATCH_QUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y +CONFIG_GENERIC_IRQ_RESERVATION_MODE=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +# end of IRQ subsystem + +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_ARCH_CLOCKSOURCE_INIT=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST_IDLE=y +CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US=125 +# CONFIG_POSIX_AUX_CLOCKS is not set +# end of Timers subsystem + +CONFIG_BPF=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y + +# +# BPF subsystem +# +# CONFIG_BPF_SYSCALL is not set +# CONFIG_BPF_JIT is not set +# end of BPF subsystem + +CONFIG_PREEMPT_BUILD=y +CONFIG_ARCH_HAS_PREEMPT_LAZY=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_PREEMPT_LAZY is not set +CONFIG_PREEMPT_COUNT=y +CONFIG_PREEMPTION=y +CONFIG_PREEMPT_DYNAMIC=y +# CONFIG_SCHED_CORE is not set + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_PSI is not set +# end of CPU/Task time and stats accounting + +CONFIG_CPU_ISOLATION=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU_GENERIC=y +CONFIG_NEED_TASKS_RCU=y +CONFIG_TASKS_RCU=y +CONFIG_TASKS_TRACE_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +# end of RCU Subsystem + +# CONFIG_IKCONFIG is not set +# CONFIG_IKHEADERS is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +# CONFIG_PRINTK_INDEX is not set +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y + +# +# Scheduler features +# +# CONFIG_UCLAMP_TASK is not set +# end of Scheduler features + +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y +CONFIG_CC_HAS_INT128=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_GCC10_NO_ARRAY_BOUNDS=y +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_GCC_NO_STRINGOP_OVERFLOW=y +CONFIG_CC_NO_STRINGOP_OVERFLOW=y +CONFIG_ARCH_SUPPORTS_INT128=y +# CONFIG_NUMA_BALANCING is not set +CONFIG_CGROUPS=y +CONFIG_PAGE_COUNTER=y +# CONFIG_CGROUP_FAVOR_DYNMODS is not set +# CONFIG_MEMCG is not set +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_SCHED=y +CONFIG_GROUP_SCHED_WEIGHT=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_SCHED_MM_CID=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y +# CONFIG_CGROUP_DMEM is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +# CONFIG_CPUSETS_V1 is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_MISC=y +CONFIG_CGROUP_DEBUG=y +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_TIME_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_RD_ZSTD=y +# CONFIG_BOOT_CONFIG is not set +CONFIG_CMDLINE_LOG_WRAP_IDEAL_LEN=1021 +CONFIG_INITRAMFS_PRESERVE_MTIME=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_LD_ORPHAN_WARN=y +CONFIG_LD_ORPHAN_WARN_LEVEL="error" +CONFIG_SYSCTL=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_SYSFS_SYSCALL is not set +CONFIG_HAVE_PCSPKR_PLATFORM=y +# CONFIG_EXPERT is not set +CONFIG_UID16=y +CONFIG_MULTIUSER=y +CONFIG_SGETMASK_SYSCALL=y +CONFIG_FHANDLE=y +CONFIG_POSIX_TIMERS=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_FUTEX_PRIVATE_HASH=y +CONFIG_FUTEX_MPOL=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_IO_URING=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_MEMBARRIER=y +CONFIG_KCMP=y +CONFIG_RSEQ=y +CONFIG_CACHESTAT_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_SELFTEST is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS=y +CONFIG_HAVE_PERF_EVENTS=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# end of Kernel Performance Events And Counters + +CONFIG_SYSTEM_DATA_VERIFICATION=y +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y + +# +# Kexec and crash features +# +CONFIG_CRASH_RESERVE=y +CONFIG_VMCORE_INFO=y +CONFIG_KEXEC_CORE=y +CONFIG_KEXEC=y +# CONFIG_KEXEC_FILE is not set +# CONFIG_KEXEC_JUMP is not set +CONFIG_CRASH_DUMP=y +CONFIG_CRASH_HOTPLUG=y +CONFIG_CRASH_MAX_MEMORY_RANGES=8192 +# end of Kexec and crash features + +# +# Live Update and Kexec HandOver +# +# CONFIG_KEXEC_HANDOVER is not set +# end of Live Update and Kexec HandOver +# end of General setup + +CONFIG_64BIT=y +CONFIG_X86_64=y +CONFIG_X86=y +CONFIG_INSTRUCTION_DECODER=y +CONFIG_OUTPUT_FORMAT="elf64-x86-64" +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=28 +CONFIG_ARCH_MMAP_RND_BITS_MAX=32 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_AUDIT_ARCH=y +CONFIG_HAVE_INTEL_TXT=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=5 + +# +# Processor type and features +# +CONFIG_SMP=y +CONFIG_X86_X2APIC=y +CONFIG_X86_MPPARSE=y +# CONFIG_X86_CPU_RESCTRL is not set +# CONFIG_X86_FRED is not set +CONFIG_X86_EXTENDED_PLATFORM=y +# CONFIG_X86_NUMACHIP is not set +# CONFIG_X86_VSMP is not set +# CONFIG_X86_UV is not set +# CONFIG_X86_INTEL_MID is not set +# CONFIG_X86_GOLDFISH is not set +# CONFIG_X86_INTEL_LPSS is not set +# CONFIG_X86_AMD_PLATFORM_DEVICE is not set +CONFIG_IOSF_MBI=y +# CONFIG_IOSF_MBI_DEBUG is not set +CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PARAVIRT=y +# CONFIG_PARAVIRT_DEBUG is not set +# CONFIG_PARAVIRT_SPINLOCKS is not set +CONFIG_X86_HV_CALLBACK_VECTOR=y +# CONFIG_XEN is not set +CONFIG_KVM_GUEST=y +CONFIG_ARCH_CPUIDLE_HALTPOLL=y +# CONFIG_PVH is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +CONFIG_PARAVIRT_CLOCK=y +# CONFIG_JAILHOUSE_GUEST is not set +# CONFIG_ACRN_GUEST is not set +# CONFIG_BHYVE_GUEST is not set +# CONFIG_INTEL_TDX_GUEST is not set +CONFIG_CC_HAS_MARCH_NATIVE=y +# CONFIG_X86_NATIVE_CPU is not set +CONFIG_X86_INTERNODE_CACHE_SHIFT=6 +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_TSC=y +CONFIG_X86_HAVE_PAE=y +CONFIG_X86_CX8=y +CONFIG_X86_CMOV=y +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_DEBUGCTLMSR=y +CONFIG_IA32_FEAT_CTL=y +CONFIG_X86_VMX_FEATURE_NAMES=y +CONFIG_BROADCAST_TLB_FLUSH=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_HYGON=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_CPU_SUP_ZHAOXIN=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_DMI=y +# CONFIG_GART_IOMMU is not set +# CONFIG_MAXSMP is not set +CONFIG_NR_CPUS_RANGE_BEGIN=2 +CONFIG_NR_CPUS_RANGE_END=512 +CONFIG_NR_CPUS_DEFAULT=64 +CONFIG_NR_CPUS=64 +CONFIG_SCHED_MC_PRIO=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_ACPI_MADT_WAKEUP=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +CONFIG_X86_MCE=y +# CONFIG_X86_MCELOG_LEGACY is not set +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MCE_AMD=y +CONFIG_X86_MCE_THRESHOLD=y +# CONFIG_X86_MCE_INJECT is not set + +# +# Performance monitoring +# +CONFIG_PERF_EVENTS_INTEL_UNCORE=y +CONFIG_PERF_EVENTS_INTEL_RAPL=y +CONFIG_PERF_EVENTS_INTEL_CSTATE=y +# CONFIG_PERF_EVENTS_AMD_POWER is not set +CONFIG_PERF_EVENTS_AMD_UNCORE=y +# CONFIG_PERF_EVENTS_AMD_BRS is not set +# end of Performance monitoring + +CONFIG_X86_16BIT=y +CONFIG_X86_ESPFIX64=y +CONFIG_X86_VSYSCALL_EMULATION=y +CONFIG_X86_IOPL_IOPERM=y +CONFIG_MICROCODE=y +# CONFIG_MICROCODE_LATE_LOADING is not set +# CONFIG_MICROCODE_DBG is not set +CONFIG_X86_MSR=y +CONFIG_X86_CPUID=y +CONFIG_X86_DIRECT_GBPAGES=y +# CONFIG_X86_CPA_STATISTICS is not set +# CONFIG_AMD_MEM_ENCRYPT is not set +CONFIG_NUMA=y +CONFIG_AMD_NUMA=y +CONFIG_X86_64_ACPI_NUMA=y +CONFIG_NODES_SHIFT=6 +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +# CONFIG_X86_PMEM_LEGACY is not set +CONFIG_X86_CHECK_BIOS_CORRUPTION=y +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +CONFIG_MTRR=y +# CONFIG_MTRR_SANITIZER is not set +CONFIG_X86_PAT=y +CONFIG_X86_UMIP=y +CONFIG_CC_HAS_IBT=y +CONFIG_X86_CET=y +CONFIG_X86_KERNEL_IBT=y +CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y +CONFIG_ARCH_PKEY_BITS=4 +CONFIG_X86_INTEL_TSX_MODE_OFF=y +# CONFIG_X86_INTEL_TSX_MODE_ON is not set +# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set +# CONFIG_X86_SGX is not set +# CONFIG_X86_USER_SHADOW_STACK is not set +CONFIG_EFI=y +CONFIG_EFI_STUB=y +CONFIG_EFI_HANDOVER_PROTOCOL=y +CONFIG_EFI_MIXED=y +CONFIG_EFI_RUNTIME_MAP=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SUPPORTS_KEXEC=y +CONFIG_ARCH_SUPPORTS_KEXEC_FILE=y +CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY=y +CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_SIG_FORCE=y +CONFIG_ARCH_SUPPORTS_KEXEC_BZIMAGE_VERIFY_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_JUMP=y +CONFIG_ARCH_SUPPORTS_KEXEC_HANDOVER=y +CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y +CONFIG_ARCH_DEFAULT_CRASH_DUMP=y +CONFIG_ARCH_SUPPORTS_CRASH_HOTPLUG=y +CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION=y +CONFIG_PHYSICAL_START=0x1000000 +CONFIG_RELOCATABLE=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_X86_NEED_RELOCS=y +CONFIG_PHYSICAL_ALIGN=0x200000 +CONFIG_RANDOMIZE_MEMORY=y +CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0x0 +CONFIG_HOTPLUG_CPU=y +# CONFIG_COMPAT_VDSO is not set +CONFIG_LEGACY_VSYSCALL_XONLY=y +# CONFIG_LEGACY_VSYSCALL_NONE is not set +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MODIFY_LDT_SYSCALL=y +# CONFIG_STRICT_SIGALTSTACK_SIZE is not set +CONFIG_HAVE_LIVEPATCH=y +CONFIG_HAVE_KLP_BUILD=y +CONFIG_X86_BUS_LOCK_DETECT=y +# end of Processor type and features + +CONFIG_CC_HAS_NAMED_AS=y +CONFIG_CC_HAS_NAMED_AS_FIXED_SANITIZERS=y +CONFIG_USE_X86_SEG_SUPPORT=y +CONFIG_CC_HAS_SLS=y +CONFIG_CC_HAS_RETURN_THUNK=y +CONFIG_CC_HAS_ENTRY_PADDING=y +CONFIG_FUNCTION_PADDING_CFI=11 +CONFIG_FUNCTION_PADDING_BYTES=16 +CONFIG_CALL_PADDING=y +CONFIG_HAVE_CALL_THUNKS=y +CONFIG_CALL_THUNKS=y +CONFIG_PREFIX_SYMBOLS=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_MITIGATION_PAGE_TABLE_ISOLATION=y +CONFIG_MITIGATION_RETPOLINE=y +CONFIG_MITIGATION_RETHUNK=y +CONFIG_MITIGATION_UNRET_ENTRY=y +CONFIG_MITIGATION_CALL_DEPTH_TRACKING=y +# CONFIG_CALL_THUNKS_DEBUG is not set +CONFIG_MITIGATION_IBPB_ENTRY=y +CONFIG_MITIGATION_IBRS_ENTRY=y +CONFIG_MITIGATION_SRSO=y +# CONFIG_MITIGATION_SLS is not set +CONFIG_MITIGATION_GDS=y +CONFIG_MITIGATION_RFDS=y +CONFIG_MITIGATION_SPECTRE_BHI=y +CONFIG_MITIGATION_MDS=y +CONFIG_MITIGATION_TAA=y +CONFIG_MITIGATION_MMIO_STALE_DATA=y +CONFIG_MITIGATION_L1TF=y +CONFIG_MITIGATION_RETBLEED=y +CONFIG_MITIGATION_SPECTRE_V1=y +CONFIG_MITIGATION_SPECTRE_V2=y +CONFIG_MITIGATION_SRBDS=y +CONFIG_MITIGATION_SSB=y +CONFIG_MITIGATION_ITS=y +CONFIG_MITIGATION_TSA=y +CONFIG_ARCH_HAS_ADD_PAGES=y + +# +# Power management and ACPI options +# +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +CONFIG_HIBERNATION_SNAPSHOT_DEV=y +CONFIG_HIBERNATION_COMP_LZO=y +CONFIG_HIBERNATION_DEF_COMP="lzo" +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_USERSPACE_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_SLEEP_DEBUG=y +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +# CONFIG_ENERGY_MODEL is not set +CONFIG_ARCH_SUPPORTS_ACPI=y +CONFIG_ACPI=y +CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y +CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y +CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y +CONFIG_ACPI_THERMAL_LIB=y +# CONFIG_ACPI_DEBUGGER is not set +CONFIG_ACPI_SPCR_TABLE=y +# CONFIG_ACPI_FPDT is not set +CONFIG_ACPI_LPIT=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y +CONFIG_ACPI_EC=y +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_AC=y +CONFIG_ACPI_BATTERY=y +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_VIDEO=y +CONFIG_ACPI_FAN=y +# CONFIG_ACPI_TAD is not set +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_CPU_FREQ_PSS=y +CONFIG_ACPI_PROCESSOR_CSTATE=y +CONFIG_ACPI_PROCESSOR_IDLE=y +CONFIG_ACPI_CPPC_LIB=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set +CONFIG_ACPI_THERMAL=y +CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y +CONFIG_ACPI_TABLE_UPGRADE=y +CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_HOTPLUG_IOAPIC=y +# CONFIG_ACPI_SBS is not set +# CONFIG_ACPI_HED is not set +CONFIG_ACPI_BGRT=y +CONFIG_ACPI_NHLT=y +# CONFIG_ACPI_NFIT is not set +CONFIG_ACPI_NUMA=y +# CONFIG_ACPI_HMAT is not set +CONFIG_HAVE_ACPI_APEI=y +CONFIG_HAVE_ACPI_APEI_NMI=y +# CONFIG_ACPI_APEI is not set +# CONFIG_ACPI_DPTF is not set +# CONFIG_ACPI_CONFIGFS is not set +# CONFIG_ACPI_PFRUT is not set +CONFIG_ACPI_PCC=y +# CONFIG_ACPI_FFH is not set +CONFIG_ACPI_MRRM=y +# CONFIG_PMIC_OPREGION is not set +CONFIG_ACPI_PRMT=y +CONFIG_X86_PM_TIMER=y + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_STAT is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_X86_INTEL_PSTATE=y +# CONFIG_X86_PCC_CPUFREQ is not set +CONFIG_X86_AMD_PSTATE=y +CONFIG_X86_AMD_PSTATE_DEFAULT_MODE=3 +# CONFIG_X86_AMD_PSTATE_UT is not set +CONFIG_X86_ACPI_CPUFREQ=y +CONFIG_X86_ACPI_CPUFREQ_CPB=y +# CONFIG_X86_POWERNOW_K8 is not set +# CONFIG_X86_AMD_FREQ_SENSITIVITY is not set +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +# CONFIG_X86_P4_CLOCKMOD is not set + +# +# shared options +# +CONFIG_CPUFREQ_ARCH_CUR_FREQ=y +# end of CPU Frequency scaling + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_GOV_LADDER is not set +CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_CPU_IDLE_GOV_TEO is not set +CONFIG_CPU_IDLE_GOV_HALTPOLL=y +CONFIG_HALTPOLL_CPUIDLE=y +# end of CPU Idle + +# CONFIG_INTEL_IDLE is not set +# end of Power management and ACPI options + +# +# Bus options (PCI etc.) +# +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_MMCONF_FAM10H=y +CONFIG_ISA_DMA_API=y +CONFIG_AMD_NB=y +CONFIG_AMD_NODE=y +# end of Bus options (PCI etc.) + +# +# Binary Emulations +# +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_EMULATION_DEFAULT_DISABLED is not set +# CONFIG_X86_X32_ABI is not set +CONFIG_COMPAT_32=y +CONFIG_COMPAT=y +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y +# end of Binary Emulations + +CONFIG_VIRTUALIZATION=y +# CONFIG_KVM is not set +CONFIG_X86_REQUIRED_FEATURE_ALWAYS=y +CONFIG_X86_REQUIRED_FEATURE_NOPL=y +CONFIG_X86_REQUIRED_FEATURE_CX8=y +CONFIG_X86_REQUIRED_FEATURE_CMOV=y +CONFIG_X86_REQUIRED_FEATURE_CPUID=y +CONFIG_X86_REQUIRED_FEATURE_FPU=y +CONFIG_X86_REQUIRED_FEATURE_PAE=y +CONFIG_X86_REQUIRED_FEATURE_PSE=y +CONFIG_X86_REQUIRED_FEATURE_PGE=y +CONFIG_X86_REQUIRED_FEATURE_MSR=y +CONFIG_X86_REQUIRED_FEATURE_FXSR=y +CONFIG_X86_REQUIRED_FEATURE_XMM=y +CONFIG_X86_REQUIRED_FEATURE_XMM2=y +CONFIG_X86_REQUIRED_FEATURE_LM=y +CONFIG_X86_DISABLED_FEATURE_VME=y +CONFIG_X86_DISABLED_FEATURE_K6_MTRR=y +CONFIG_X86_DISABLED_FEATURE_CYRIX_ARR=y +CONFIG_X86_DISABLED_FEATURE_CENTAUR_MCR=y +CONFIG_X86_DISABLED_FEATURE_LAM=y +CONFIG_X86_DISABLED_FEATURE_ENQCMD=y +CONFIG_X86_DISABLED_FEATURE_SGX=y +CONFIG_X86_DISABLED_FEATURE_XENPV=y +CONFIG_X86_DISABLED_FEATURE_TDX_GUEST=y +CONFIG_X86_DISABLED_FEATURE_USER_SHSTK=y +CONFIG_X86_DISABLED_FEATURE_FRED=y +CONFIG_X86_DISABLED_FEATURE_SEV_SNP=y +CONFIG_AS_WRUSS=y +CONFIG_ARCH_CONFIGURES_CPU_MITIGATIONS=y + +# +# General architecture-dependent options +# +CONFIG_HOTPLUG_SMT=y +CONFIG_ARCH_SUPPORTS_SCHED_SMT=y +CONFIG_ARCH_SUPPORTS_SCHED_CLUSTER=y +CONFIG_ARCH_SUPPORTS_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_SCHED_CLUSTER=y +CONFIG_SCHED_MC=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CORE_SYNC_FULL=y +CONFIG_HOTPLUG_SPLIT_STARTUP=y +CONFIG_HOTPLUG_PARALLEL=y +CONFIG_GENERIC_IRQ_ENTRY=y +CONFIG_GENERIC_SYSCALL=y +CONFIG_GENERIC_ENTRY=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +# CONFIG_STATIC_CALL_SELFTEST is not set +CONFIG_OPTPROBES=y +CONFIG_UPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_KRETPROBES=y +CONFIG_KRETPROBE_ON_RETHOOK=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_KPROBES_ON_FTRACE=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y +CONFIG_HAVE_NMI=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y +CONFIG_ARCH_HAS_CPU_PASID=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_HAVE_ASM_MODVERSIONS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_RUST=y +CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y +CONFIG_HAVE_USER_RETURN_NOTIFIER=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y +CONFIG_UNWIND_USER=y +CONFIG_HAVE_UNWIND_USER_FP=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y +CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MMU_GATHER_RCU_TABLE_FREE=y +CONFIG_MMU_GATHER_MERGE_VMAS=y +CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_ARCH_HAVE_EXTRA_ELF_NOTES=y +CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y +CONFIG_HAVE_ARCH_SECCOMP=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP=y +CONFIG_SECCOMP_FILTER=y +# CONFIG_SECCOMP_CACHE_DEBUG is not set +CONFIG_HAVE_ARCH_KSTACK_ERASE=y +CONFIG_HAVE_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y +CONFIG_LTO_NONE=y +CONFIG_ARCH_SUPPORTS_AUTOFDO_CLANG=y +CONFIG_ARCH_SUPPORTS_PROPELLER_CLANG=y +CONFIG_ARCH_SUPPORTS_CFI=y +CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y +CONFIG_HAVE_CONTEXT_TRACKING_USER=y +CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PUD=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_ARCH_HUGE_VMALLOC=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_HAVE_ARCH_SOFT_DIRTY=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_EXECMEM_ROX=y +CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_HAVE_EXIT_THREAD=y +CONFIG_ARCH_MMAP_RND_BITS=28 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8 +CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y +CONFIG_HAVE_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SHIFT=12 +CONFIG_HAVE_OBJTOOL=y +CONFIG_HAVE_JUMP_LABEL_HACK=y +CONFIG_HAVE_NOINSTR_HACK=y +CONFIG_HAVE_NOINSTR_VALIDATION=y +CONFIG_HAVE_UACCESS_VALIDATION=y +CONFIG_HAVE_STACK_VALIDATION=y +CONFIG_HAVE_RELIABLE_STACKTRACE=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_ARCH_SUPPORTS_RT=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y +CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y +CONFIG_RANDOMIZE_KSTACK_OFFSET=y +# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y +# CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_ARCH_HAS_MEM_ENCRYPT=y +CONFIG_HAVE_STATIC_CALL=y +CONFIG_HAVE_STATIC_CALL_INLINE=y +CONFIG_HAVE_PREEMPT_DYNAMIC=y +CONFIG_HAVE_PREEMPT_DYNAMIC_CALL=y +CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y +CONFIG_ARCH_HAS_ELFCORE_COMPAT=y +CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y +CONFIG_DYNAMIC_SIGFRAME=y +CONFIG_ARCH_HAS_HW_PTE_YOUNG=y +CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=y +CONFIG_ARCH_HAS_KERNEL_FPU_SUPPORT=y +CONFIG_ARCH_VMLINUX_NEEDS_RELOCS=y +CONFIG_HAVE_GENERIC_TIF_BITS=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +# end of GCOV-based kernel profiling + +CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FUNCTION_ALIGNMENT_16B=y +CONFIG_FUNCTION_ALIGNMENT=16 +CONFIG_CC_HAS_MIN_FUNCTION_ALIGNMENT=y +CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y +CONFIG_ARCH_HAS_CPU_ATTACK_VECTORS=y +# end of General architecture-dependent options + +CONFIG_RT_MUTEXES=y +CONFIG_MODULES=y +# CONFIG_MODULE_DEBUG is not set +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +CONFIG_MODPROBE_PATH="/sbin/modprobe" +# CONFIG_TRIM_UNUSED_KSYMS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLOCK_LEGACY_AUTOLOAD=y +CONFIG_BLK_RQ_ALLOC_TIME=y +CONFIG_BLK_DEV_BSG_COMMON=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_DEV_WRITE_MOUNTED=y +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_DEV_THROTTLING is not set +# CONFIG_BLK_WBT is not set +CONFIG_BLK_CGROUP_IOLATENCY=y +CONFIG_BLK_CGROUP_IOCOST=y +CONFIG_BLK_CGROUP_IOPRIO=y +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_SED_OPAL is not set +# CONFIG_BLK_INLINE_ENCRYPTION is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y +# end of Partition Types + +CONFIG_BLK_PM=y +CONFIG_BLOCK_HOLDER_DEPRECATED=y +CONFIG_BLK_MQ_STACKING=y + +# +# IO Schedulers +# +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_IOSCHED_BFQ is not set +# end of IO Schedulers + +CONFIG_PADATA=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y +CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y +CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y +CONFIG_FREEZER=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +CONFIG_BINFMT_MISC=y +CONFIG_COREDUMP=y +# end of Executable file formats + +# +# Memory Management options +# +CONFIG_SWAP=y +# CONFIG_ZSWAP is not set + +# +# Slab allocator options +# +CONFIG_SLUB=y +CONFIG_KVFREE_RCU_BATCHED=y +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLAB_FREELIST_RANDOM is not set +# CONFIG_SLAB_FREELIST_HARDENED is not set +# CONFIG_SLAB_BUCKETS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_RANDOM_KMALLOC_CACHES is not set +# end of Slab allocator options + +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_PREINIT=y +CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=y +CONFIG_ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP=y +CONFIG_ARCH_WANT_HUGETLB_VMEMMAP_PREINIT=y +CONFIG_HAVE_GUP_FAST=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_SPLIT_PMD_PTLOCKS=y +CONFIG_COMPACTION=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_PAGE_REPORTING is not set +CONFIG_MIGRATION=y +CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y +CONFIG_PCP_BATCH_SCALE_MAX=5 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_MMU_NOTIFIER=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +# CONFIG_MEMORY_FAILURE is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANTS_THP_SWAP=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set +CONFIG_PAGE_MAPCOUNT=y +CONFIG_PGTABLE_HAS_HUGE_LEAVES=y +CONFIG_HAVE_GIGANTIC_FOLIOS=y +CONFIG_ASYNC_KERNEL_PGTABLE_FREE=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +# CONFIG_CMA is not set +CONFIG_PAGE_BLOCK_MAX_ORDER=10 +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y +CONFIG_ZONE_DMA=y +CONFIG_ZONE_DMA32=y +CONFIG_VMAP_PFN=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y +CONFIG_ARCH_HAS_PKEYS=y +CONFIG_ARCH_USES_PG_ARCH_2=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_PERCPU_STATS is not set +# CONFIG_GUP_TEST is not set +# CONFIG_DMAPOOL_TEST is not set +CONFIG_ARCH_HAS_PTE_SPECIAL=y +CONFIG_MEMFD_CREATE=y +CONFIG_SECRETMEM=y +# CONFIG_ANON_VMA_NAME is not set +# CONFIG_USERFAULTFD is not set +# CONFIG_LRU_GEN is not set +CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y +CONFIG_PER_VMA_LOCK=y +CONFIG_LOCK_MM_AND_FIND_VMA=y +CONFIG_IOMMU_MM_DATA=y +CONFIG_EXECMEM=y +CONFIG_NUMA_MEMBLKS=y +# CONFIG_NUMA_EMU is not set +CONFIG_ARCH_SUPPORTS_PT_RECLAIM=y +CONFIG_PT_RECLAIM=y + +# +# Data Access Monitoring +# +# CONFIG_DAMON is not set +# end of Data Access Monitoring +# end of Memory Management options + +CONFIG_NET=y +CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_SKB_EXTENSIONS=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +# CONFIG_INET_PSP is not set +CONFIG_UNIX=y +CONFIG_AF_UNIX_OOB=y +# CONFIG_UNIX_DIAG is not set +# CONFIG_TLS is not set +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_USER_COMPAT is not set +# CONFIG_XFRM_INTERFACE is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_AH=y +CONFIG_XFRM_ESP=y +# CONFIG_NET_KEY is not set +# CONFIG_XFRM_IPTFS is not set +# CONFIG_DIBS is not set +CONFIG_NET_HANDSHAKE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +CONFIG_IP_MROUTE_COMMON=y +CONFIG_IP_MROUTE=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 +CONFIG_INET_TUNNEL=y +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_NV is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_CDG is not set +# CONFIG_TCP_CONG_BBR is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_AO is not set +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +# CONFIG_INET6_ESP_OFFLOAD is not set +# CONFIG_INET6_ESPINTCP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_ILA is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_IOAM6_LWTUNNEL is not set +CONFIG_NETLABEL=y +# CONFIG_MPTCP is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_ADVANCED is not set + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_EGRESS=y +CONFIG_NETFILTER_SKIP_EGRESS=y +CONFIG_NETFILTER_NETLINK=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_SYSLOG=m +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_PROCFS is not set +# CONFIG_NF_CONNTRACK_LABELS is not set +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_IRC=y +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +CONFIG_NF_CONNTRACK_SIP=y +CONFIG_NF_CT_NETLINK=y +# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_FTP=y +CONFIG_NF_NAT_IRC=y +CONFIG_NF_NAT_SIP=y +CONFIG_NF_NAT_MASQUERADE=y +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y +# CONFIG_NETFILTER_XTABLES_COMPAT is not set +# CONFIG_NETFILTER_XTABLES_LEGACY is not set + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_LOG=m +# CONFIG_NETFILTER_XT_NAT is not set +# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +# end of Core Netfilter Configuration + +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +# CONFIG_NF_SOCKET_IPV4 is not set +# CONFIG_NF_TPROXY_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_IP_NF_IPTABLES=y +# end of IP: Netfilter Configuration + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_SOCKET_IPV6 is not set +# CONFIG_NF_TPROXY_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +# end of IPv6: Netfilter Configuration + +CONFIG_NF_DEFRAG_IPV6=y +# CONFIG_NF_CONNTRACK_BRIDGE is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_CBS is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_TAPRIO is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_SKBPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_CAKE is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_PLUG is not set +# CONFIG_NET_SCH_ETS is not set +# CONFIG_NET_SCH_DUALPI2 is not set +# CONFIG_NET_SCH_DEFAULT is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_CLS_CGROUP=y +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_MATCHALL is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +# CONFIG_NET_EMATCH_CMP is not set +# CONFIG_NET_EMATCH_NBYTE is not set +# CONFIG_NET_EMATCH_U32 is not set +# CONFIG_NET_EMATCH_META is not set +# CONFIG_NET_EMATCH_TEXT is not set +# CONFIG_NET_EMATCH_IPT is not set +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_SAMPLE is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_ACT_MPLS is not set +# CONFIG_NET_ACT_VLAN is not set +# CONFIG_NET_ACT_BPF is not set +# CONFIG_NET_ACT_SKBMOD is not set +# CONFIG_NET_ACT_IFE is not set +# CONFIG_NET_ACT_TUNNEL_KEY is not set +# CONFIG_NET_ACT_GATE is not set +# CONFIG_NET_TC_SKB_EXT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_QRTR is not set +# CONFIG_NET_NCSI is not set +CONFIG_PCPU_DEV_REFCNT=y +CONFIG_MAX_SKB_FRAGS=17 +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_XPS=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# end of Network testing +# end of Networking options + +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +# CONFIG_MCTP is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +# CONFIG_CFG80211_WEXT is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +CONFIG_RFKILL=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=y +CONFIG_NET_9P_FD=y +CONFIG_NET_9P_VIRTIO=y +# CONFIG_NET_9P_DEBUG is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set +# CONFIG_LWTUNNEL is not set +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +CONFIG_NET_SELFTESTS=y +CONFIG_FAILOVER=y +CONFIG_ETHTOOL_NETLINK=y + +# +# Device Drivers +# +CONFIG_HAVE_PCI=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_PCIEAER is not set +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +# CONFIG_PCIE_PTM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +CONFIG_PCI_ATS=y +# CONFIG_PCI_TSM is not set +# CONFIG_PCI_DOE is not set +CONFIG_PCI_LOCKLESS_CONFIG=y +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_NPEM is not set +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +# CONFIG_PCIE_TPH is not set +CONFIG_PCI_LABEL=y +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_ACPI is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_OCTEONEP is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# PCI controller drivers +# +# CONFIG_VMD is not set + +# +# Cadence-based PCIe controllers +# +# end of Cadence-based PCIe controllers + +# +# DesignWare-based PCIe controllers +# +# CONFIG_PCI_MESON is not set +# CONFIG_PCIE_DW_PLAT_HOST is not set +# end of DesignWare-based PCIe controllers + +# +# Mobiveil-based PCIe controllers +# +# end of Mobiveil-based PCIe controllers + +# +# PLDA-based PCIe controllers +# +# end of PLDA-based PCIe controllers +# end of PCI controller drivers + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set +# end of PCI Endpoint + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set +# end of PCI switch controller drivers + +# CONFIG_PCI_PWRCTRL_SLOT is not set +# CONFIG_PCI_PWRCTRL_TC9563 is not set +# CONFIG_CXL_BUS is not set +CONFIG_PCCARD=y +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set +CONFIG_PCCARD_NONSTATIC=y +# CONFIG_RAPIDIO is not set + +# +# Generic Driver Options +# +CONFIG_AUXILIARY_BUS=y +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_DEVTMPFS_SAFE is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Firmware loader +# +CONFIG_FW_LOADER=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER is not set +# CONFIG_FW_LOADER_COMPRESS is not set +CONFIG_FW_CACHE=y +# CONFIG_FW_UPLOAD is not set +# end of Firmware loader + +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_DEVRES=y +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_REGMAP=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_DMA_FENCE_TRACE is not set +# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set +# end of Generic Driver Options + +# +# Bus devices +# +# CONFIG_MHI_BUS is not set +# CONFIG_MHI_BUS_EP is not set +# end of Bus devices + +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Firmware Drivers +# + +# +# ARM System Control and Management Interface Protocol +# +# end of ARM System Control and Management Interface Protocol + +# CONFIG_EDD is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_DMIID=y +# CONFIG_DMI_SYSFS is not set +CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y +# CONFIG_ISCSI_IBFT is not set +# CONFIG_FW_CFG_SYSFS is not set +# CONFIG_SYSFB_SIMPLEFB is not set +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_ESRT=y +CONFIG_EFI_DXE_MEM_ATTRIBUTES=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +# CONFIG_EFI_BOOTLOADER_CONTROL is not set +# CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_TEST is not set +# CONFIG_APPLE_PROPERTIES is not set +# CONFIG_RESET_ATTACK_MITIGATION is not set +# CONFIG_EFI_RCI2_TABLE is not set +# CONFIG_EFI_DISABLE_PCI_DMA is not set +CONFIG_EFI_EARLYCON=y +CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y +# CONFIG_EFI_DISABLE_RUNTIME is not set +# CONFIG_EFI_COCO_SECRET is not set +# CONFIG_OVMF_DEBUG_LOG is not set +CONFIG_EFI_SBAT_FILE="" +# end of EFI (Extensible Firmware Interface) Support + +# +# Qualcomm firmware drivers +# +# end of Qualcomm firmware drivers + +# +# Tegra firmware driver +# +# end of Tegra firmware driver +# end of Firmware Drivers + +# CONFIG_FWCTL is not set +# CONFIG_GNSS is not set +# CONFIG_MTD is not set +# CONFIG_OF is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_FD is not set +CONFIG_CDROM=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_ZRAM is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_VIRTIO_BLK=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_UBLK is not set + +# +# NVME Support +# +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set +# CONFIG_NVME_TARGET is not set +# end of NVME Support + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_RPMB is not set +# CONFIG_TI_FPC202 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_SRAM is not set +# CONFIG_DW_XDATA_PCIE is not set +# CONFIG_PCI_ENDPOINT_TEST is not set +# CONFIG_XILINX_SDFEC is not set +# CONFIG_NTSYNC is not set +# CONFIG_NSM is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=y +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_EEPROM_EE1004 is not set +# CONFIG_EEPROM_M24LR is not set +# end of EEPROM support + +# CONFIG_CB710_CORE is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_ALTERA_STAPL is not set +CONFIG_INTEL_MEI=y +CONFIG_INTEL_MEI_ME=y +# CONFIG_INTEL_MEI_TXE is not set +# CONFIG_INTEL_MEI_GSC is not set +# CONFIG_INTEL_MEI_HDCP is not set +# CONFIG_INTEL_MEI_PXP is not set +# CONFIG_INTEL_MEI_GSC_PROXY is not set +# CONFIG_VMWARE_VMCI is not set +# CONFIG_GENWQE is not set +# CONFIG_BCM_VK is not set +# CONFIG_MISC_ALCOR_PCI is not set +# CONFIG_MISC_RTSX_PCI is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_UACCE is not set +# CONFIG_PVPANIC is not set +# CONFIG_KEBA_CP500 is not set +# end of Misc devices + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI_COMMON=y +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_SG=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# end of SCSI Transports + +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPI3MR is not set +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_MYRB is not set +# CONFIG_SCSI_MYRS is not set +# CONFIG_VMWARE_PVSCSI is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FDOMAIN_PCI is not set +# CONFIG_SCSI_ISCI is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +CONFIG_SCSI_VIRTIO=y +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# end of SCSI device support + +CONFIG_ATA=y +CONFIG_SATA_HOST=y +CONFIG_PATA_TIMINGS=y +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_FORCE=y +CONFIG_ATA_ACPI=y +# CONFIG_SATA_ZPODD is not set +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=3 +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_AHCI_DWC is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +CONFIG_ATA_PIIX=y +# CONFIG_SATA_DWC is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +CONFIG_PATA_AMD=y +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +CONFIG_PATA_OLDPIIX=y +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +CONFIG_PATA_SCH=y +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_PCMCIA is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_ACPI is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_BITMAP=y +# CONFIG_MD_LLBITMAP is not set +CONFIG_MD_AUTODETECT=y +CONFIG_MD_BITMAP_FILE=y +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID10 is not set +# CONFIG_MD_RAID456 is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_UNSTRIPED is not set +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_WRITECACHE is not set +# CONFIG_DM_EBS is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_CLONE is not set +CONFIG_DM_MIRROR=y +# CONFIG_DM_LOG_USERSPACE is not set +# CONFIG_DM_RAID is not set +CONFIG_DM_ZERO=y +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_DUST is not set +# CONFIG_DM_INIT is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_VERITY is not set +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_DM_INTEGRITY is not set +# CONFIG_DM_AUDIT is not set +# CONFIG_DM_VDO is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# end of IEEE 1394 (FireWire) support + +CONFIG_MACINTOSH_DRIVERS=y +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_WIREGUARD is not set +# CONFIG_OVPN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +# CONFIG_BAREUDP is not set +# CONFIG_GTP is not set +# CONFIG_PFCP is not set +# CONFIG_AMT is not set +# CONFIG_MACSEC is not set +CONFIG_NETCONSOLE=y +# CONFIG_NETCONSOLE_EXTENDED_LOG is not set +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_TUN is not set +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALACRITECH=y +# CONFIG_SLICOSS is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y +# CONFIG_ENA_ETHERNET is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_PDS_CORE is not set +CONFIG_NET_VENDOR_AQUANTIA=y +# CONFIG_AQTION is not set +CONFIG_NET_VENDOR_ARC=y +CONFIG_NET_VENDOR_ASIX=y +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +# CONFIG_CX_ECAT is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +CONFIG_TIGON3=y +CONFIG_TIGON3_HWMON=y +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_BNXT is not set +# CONFIG_BNGE is not set +CONFIG_NET_VENDOR_CADENCE=y +CONFIG_NET_VENDOR_CAVIUM=y +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_THUNDER_NIC_VF is not set +# CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_RGX is not set +# CONFIG_CAVIUM_PTP is not set +# CONFIG_LIQUIDIO is not set +# CONFIG_LIQUIDIO_VF is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +CONFIG_NET_VENDOR_CORTINA=y +CONFIG_NET_VENDOR_DAVICOM=y +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +# CONFIG_TULIP is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_PCMCIA_XIRCOM is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_ENGLEDER=y +# CONFIG_TSNEP is not set +CONFIG_NET_VENDOR_EZCHIP=y +CONFIG_NET_VENDOR_FUJITSU=y +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_NET_VENDOR_FUNGIBLE=y +# CONFIG_FUN_ETH is not set +CONFIG_NET_VENDOR_GOOGLE=y +# CONFIG_GVE is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIBMCGE is not set +CONFIG_NET_VENDOR_HUAWEI=y +# CONFIG_HINIC is not set +# CONFIG_HINIC3 is not set +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=y +CONFIG_E1000=y +CONFIG_E1000E=y +CONFIG_E1000E_HWTS=y +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_ICE is not set +# CONFIG_FM10K is not set +# CONFIG_IGC is not set +# CONFIG_IDPF is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_LITEX=y +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +CONFIG_SKY2=y +# CONFIG_SKY2_DEBUG is not set +# CONFIG_OCTEON_EP is not set +# CONFIG_OCTEON_EP_VF is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set +CONFIG_NET_VENDOR_META=y +# CONFIG_FBNIC is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_LAN743X is not set +# CONFIG_VCAP is not set +CONFIG_NET_VENDOR_MICROSEMI=y +CONFIG_NET_VENDOR_MICROSOFT=y +CONFIG_NET_VENDOR_MUCSE=y +# CONFIG_MGBE is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NI=y +# CONFIG_NI_XGE_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_NETERION=y +# CONFIG_S2IO is not set +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_PCMCIA_PCNET is not set +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=y +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_PACKET_ENGINES=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_PENSANDO=y +# CONFIG_IONIC is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_QED is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCOM_EMAC is not set +# CONFIG_RMNET is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +CONFIG_8139TOO=y +CONFIG_8139TOO_PIO=y +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R8169=y +# CONFIG_RTASE is not set +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +CONFIG_NET_VENDOR_SOLARFLARE=y +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +# CONFIG_SFC_SIENA is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +# CONFIG_TEHUTI_TN40 is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_PHY_SEL is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VERTEXCOM=y +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WANGXUN=y +# CONFIG_NGBE is not set +# CONFIG_TXGBEVF is not set +# CONFIG_NGBEVF is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_XILINX=y +# CONFIG_XILINX_EMACLITE is not set +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_NET_VENDOR_XIRCOM=y +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_MDIO_BUS=y +CONFIG_PHYLIB=y +CONFIG_SWPHY=y +# CONFIG_LED_TRIGGER_PHY is not set +CONFIG_FIXED_PHY=y + +# +# MII PHY device drivers +# +# CONFIG_AS21XXX_PHY is not set +# CONFIG_AIR_EN8811H_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_ADIN_PHY is not set +# CONFIG_ADIN1100_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AX88796B_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM84881_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_88Q2XXX_PHY is not set +# CONFIG_MARVELL_88X2222_PHY is not set +# CONFIG_MAXLINEAR_GPHY is not set +# CONFIG_MAXLINEAR_86110_PHY is not set +# CONFIG_MEDIATEK_GE_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_T1S_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROCHIP_T1_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_MOTORCOMM_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_NXP_CBTX_PHY is not set +# CONFIG_NXP_C45_TJA11XX_PHY is not set +# CONFIG_NXP_TJA11XX_PHY is not set +# CONFIG_NCN26000_PHY is not set +# CONFIG_QCA83XX_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QSEMI_PHY is not set +CONFIG_REALTEK_PHY=y +# CONFIG_REALTEK_PHY_HWMON is not set +# CONFIG_RENESAS_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83TC811_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83869_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_DP83TG720_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set +CONFIG_FWNODE_MDIO=y +CONFIG_ACPI_MDIO=y +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MDIO_THUNDER is not set + +# +# MDIO Multiplexers +# + +# +# PCS device drivers +# +# CONFIG_PCS_XPCS is not set +# end of PCS device drivers + +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_IPHETH is not set +CONFIG_WLAN=y +CONFIG_WLAN_VENDOR_ADMTEK=y +# CONFIG_ADM8211 is not set +CONFIG_WLAN_VENDOR_ATH=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K is not set +# CONFIG_ATH5K_PCI is not set +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_CARL9170 is not set +# CONFIG_ATH6KL is not set +# CONFIG_AR5523 is not set +# CONFIG_WIL6210 is not set +# CONFIG_ATH10K is not set +# CONFIG_WCN36XX is not set +# CONFIG_ATH11K is not set +# CONFIG_ATH12K is not set +CONFIG_WLAN_VENDOR_ATMEL=y +# CONFIG_AT76C50X_USB is not set +CONFIG_WLAN_VENDOR_BROADCOM=y +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_BRCMSMAC is not set +# CONFIG_BRCMFMAC is not set +CONFIG_WLAN_VENDOR_INTEL=y +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +# CONFIG_IWLWIFI is not set +CONFIG_WLAN_VENDOR_INTERSIL=y +# CONFIG_P54_COMMON is not set +CONFIG_WLAN_VENDOR_MARVELL=y +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_MWIFIEX is not set +# CONFIG_MWL8K is not set +CONFIG_WLAN_VENDOR_MEDIATEK=y +# CONFIG_MT7601U is not set +# CONFIG_MT76x0U is not set +# CONFIG_MT76x0E is not set +# CONFIG_MT76x2E is not set +# CONFIG_MT76x2U is not set +# CONFIG_MT7603E is not set +# CONFIG_MT7615E is not set +# CONFIG_MT7663U is not set +# CONFIG_MT7915E is not set +# CONFIG_MT7921E is not set +# CONFIG_MT7921U is not set +# CONFIG_MT7996E is not set +# CONFIG_MT7925E is not set +# CONFIG_MT7925U is not set +CONFIG_WLAN_VENDOR_MICROCHIP=y +CONFIG_WLAN_VENDOR_PURELIFI=y +# CONFIG_PLFXLC is not set +CONFIG_WLAN_VENDOR_RALINK=y +# CONFIG_RT2X00 is not set +CONFIG_WLAN_VENDOR_REALTEK=y +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +CONFIG_RTL_CARDS=y +# CONFIG_RTL8192CE is not set +# CONFIG_RTL8192SE is not set +# CONFIG_RTL8192DE is not set +# CONFIG_RTL8723AE is not set +# CONFIG_RTL8723BE is not set +# CONFIG_RTL8188EE is not set +# CONFIG_RTL8192EE is not set +# CONFIG_RTL8821AE is not set +# CONFIG_RTL8192CU is not set +# CONFIG_RTL8192DU is not set +# CONFIG_RTL8XXXU is not set +# CONFIG_RTW88 is not set +# CONFIG_RTW89 is not set +CONFIG_WLAN_VENDOR_RSI=y +# CONFIG_RSI_91X is not set +CONFIG_WLAN_VENDOR_SILABS=y +CONFIG_WLAN_VENDOR_ST=y +# CONFIG_CW1200 is not set +CONFIG_WLAN_VENDOR_TI=y +# CONFIG_WL1251 is not set +# CONFIG_WL12XX is not set +# CONFIG_WL18XX is not set +# CONFIG_WLCORE is not set +CONFIG_WLAN_VENDOR_ZYDAS=y +# CONFIG_ZD1211RW is not set +CONFIG_WLAN_VENDOR_QUANTENNA=y +# CONFIG_QTNFMAC_PCIE is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_WAN is not set + +# +# Wireless WAN +# +# CONFIG_WWAN is not set +# end of Wireless WAN + +# CONFIG_VMXNET3 is not set +# CONFIG_FUJITSU_ES is not set +# CONFIG_NETDEVSIM is not set +CONFIG_NET_FAILOVER=y +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_SPARSEKMAP=y +# CONFIG_INPUT_MATRIXKMAP is not set +CONFIG_INPUT_VIVALDIFMAP=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_PS2_VMMOUSE is not set +CONFIG_MOUSE_PS2_SMBUS=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +# CONFIG_JOYSTICK_XPAD is not set +# CONFIG_JOYSTICK_PXRC is not set +# CONFIG_JOYSTICK_QWIIC is not set +# CONFIG_JOYSTICK_FSIA6B is not set +# CONFIG_JOYSTICK_SENSEHAT is not set +# CONFIG_JOYSTICK_SEESAW is not set +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_USB_PEGASUS is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP5 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HIMAX_HX852X is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX is not set +# CONFIG_TOUCHSCREEN_HYNITRON_CST816X is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS is not set +# CONFIG_TOUCHSCREEN_IMAGIS is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_STMFTS is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_IQS7211 is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set +# CONFIG_TOUCHSCREEN_HIMAX_HX83112B is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_AW86927 is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_PCSPKR is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_APANEL is not set +# CONFIG_INPUT_ATLAS_BTNS is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set +# CONFIG_INPUT_IQS7222 is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_RMI4_CORE is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set +# end of Hardware I/O ports +# end of Input device support + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_LEGACY_TIOCSTI=y +CONFIG_LDISC_AUTOLOAD=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_PNP=y +# CONFIG_SERIAL_8250_16550A_VARIANTS is not set +# CONFIG_SERIAL_8250_FINTEK is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_PCILIB=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_EXAR=y +# CONFIG_SERIAL_8250_CS is not set +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +# CONFIG_SERIAL_8250_PCI1XXXX is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_DWLIB=y +# CONFIG_SERIAL_8250_DW is not set +# CONFIG_SERIAL_8250_RT288X is not set +CONFIG_SERIAL_8250_LPSS=y +CONFIG_SERIAL_8250_MID=y +CONFIG_SERIAL_8250_PERICOM=y +# CONFIG_SERIAL_8250_NI is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_LANTIQ is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# end of Serial drivers + +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_N_HDLC is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_N_GSM is not set +# CONFIG_NOZOMI is not set +# CONFIG_NULL_TTY is not set +CONFIG_HVC_DRIVER=y +# CONFIG_SERIAL_DEV_BUS is not set +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM_INTEL is not set +# CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_BA431 is not set +CONFIG_HW_RANDOM_VIA=y +# CONFIG_HW_RANDOM_VIRTIO is not set +# CONFIG_HW_RANDOM_XIPHERA is not set +# CONFIG_APPLICOM is not set +# CONFIG_MWAVE is not set +CONFIG_DEVMEM=y +CONFIG_NVRAM=y +CONFIG_DEVPORT=y +CONFIG_HPET=y +# CONFIG_HPET_MMAP is not set +# CONFIG_HANGCHECK_TIMER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +# CONFIG_XILLYBUS is not set +# CONFIG_XILLYUSB is not set +# end of Character devices + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_SMBUS=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_AMD_MP2 is not set +CONFIG_I2C_I801=y +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_ISMT is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_NVIDIA_GPU is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_ZHAOXIN is not set + +# +# ACPI drivers +# +# CONFIG_I2C_SCMI is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_CORE is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_CP2615 is not set +# CONFIG_I2C_PCI1XXXX is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_MLXCPLD is not set +# CONFIG_I2C_VIRTIO is not set +# end of I2C Hardware Bus support + +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# end of I2C support + +# CONFIG_I3C is not set +# CONFIG_SPI is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set +# CONFIG_PPS_GENERATOR is not set + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PTP_1588_CLOCK_KVM=y +CONFIG_PTP_1588_CLOCK_VMCLOCK=y +# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set +# CONFIG_PTP_1588_CLOCK_IDTCM is not set +# CONFIG_PTP_1588_CLOCK_FC3W is not set +# CONFIG_PTP_1588_CLOCK_MOCK is not set +# CONFIG_PTP_1588_CLOCK_VMW is not set +# CONFIG_PTP_NETC_V4_TIMER is not set +# end of PTP clock support + +# +# DPLL device support +# +# CONFIG_ZL3073X_I2C is not set +# end of DPLL device support + +# CONFIG_PINCTRL is not set +CONFIG_GPIOLIB_LEGACY=y +# CONFIG_GPIOLIB is not set +# CONFIG_W1 is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_SEQUENCING is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y +# CONFIG_IP5XXX_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_CHARGER_ADP5061 is not set +# CONFIG_BATTERY_CHAGALL is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SAMSUNG_SDI is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_CHARGER_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_MAX1720X is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_LTC4162L is not set +# CONFIG_CHARGER_MAX77976 is not set +# CONFIG_CHARGER_MAX8971 is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_GOLDFISH is not set +# CONFIG_BATTERY_RT5033 is not set +# CONFIG_CHARGER_RT9756 is not set +# CONFIG_CHARGER_BD99954 is not set +# CONFIG_BATTERY_UG3105 is not set +# CONFIG_FUEL_GAUGE_MM8013 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AHT10 is not set +# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASUS_ROG_RYUJIN is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_K8TEMP is not set +# CONFIG_SENSORS_K10TEMP is not set +# CONFIG_SENSORS_FAM15H_POWER is not set +# CONFIG_SENSORS_APPLESMC is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CHIPCAP2 is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_CORSAIR_PSU is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DELL_SMM is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FSCHMD is not set +# CONFIG_SENSORS_FTSTEUTATES is not set +# CONFIG_SENSORS_GIGABYTE_WATERFORCE is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPD is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HS3001 is not set +# CONFIG_SENSORS_HTU31 is not set +# CONFIG_SENSORS_I5500 is not set +# CONFIG_SENSORS_CORETEMP is not set +# CONFIG_SENSORS_ISL28022 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWERZ is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LENOVO_EC is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2991 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LTC4282 is not set +# CONFIG_SENSORS_MAX127 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX31760 is not set +# CONFIG_MAX31827 is not set +# CONFIG_SENSORS_MAX6620 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MC34VR500 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_TPS23861 is not set +# CONFIG_SENSORS_MR75203 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT6775_I2C is not set +# CONFIG_SENSORS_NCT7363 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_NZXT_KRAKEN2 is not set +# CONFIG_SENSORS_NZXT_KRAKEN3 is not set +# CONFIG_SENSORS_NZXT_SMART2 is not set +# CONFIG_SENSORS_OCC_P8_I2C is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PT5161L is not set +# CONFIG_SENSORS_SBTSI is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHT4x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC2305 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA238 is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_SPD5118 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP464 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_TSC1641 is not set +# CONFIG_SENSORS_VIA_CPUTEMP is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_XGENE is not set + +# +# ACPI drivers +# +# CONFIG_SENSORS_ACPI_POWER is not set +# CONFIG_SENSORS_ATK0110 is not set +# CONFIG_SENSORS_ASUS_WMI is not set +# CONFIG_SENSORS_ASUS_EC is not set +# CONFIG_SENSORS_HP_WMI is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_NETLINK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_THERMAL_DEBUGFS is not set +# CONFIG_THERMAL_CORE_TESTING is not set +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_PCIE_THERMAL is not set +# CONFIG_THERMAL_EMULATION is not set + +# +# Intel thermal drivers +# +# CONFIG_INTEL_POWERCLAMP is not set +CONFIG_X86_THERMAL_VECTOR=y +CONFIG_INTEL_TCC=y +CONFIG_X86_PKG_TEMP_THERMAL=m +# CONFIG_INTEL_SOC_DTS_THERMAL is not set + +# +# ACPI INT340X thermal drivers +# +# CONFIG_INT340X_THERMAL is not set +# end of ACPI INT340X thermal drivers + +# CONFIG_INTEL_PCH_THERMAL is not set +# CONFIG_INTEL_TCC_COOLING is not set +# CONFIG_INTEL_HFI_THERMAL is not set +# end of Intel thermal drivers + +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +# CONFIG_WATCHDOG_SYSFS is not set +# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set + +# +# Watchdog Pretimeout Governors +# + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_LENOVO_SE10_WDT is not set +# CONFIG_LENOVO_SE30_WDT is not set +# CONFIG_WDAT_WDT is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_ADVANTECH_EC_WDT is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_EBC_C384_WDT is not set +# CONFIG_EXAR_WDT is not set +# CONFIG_F71808E_WDT is not set +# CONFIG_SP5100_TCO is not set +# CONFIG_SBC_FITPC2_WATCHDOG is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_IBMASR is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_IE6XX_WDT is not set +# CONFIG_INTEL_OC_WATCHDOG is not set +# CONFIG_ITCO_WDT is not set +# CONFIG_IT8712F_WDT is not set +# CONFIG_IT87_WDT is not set +# CONFIG_HP_WATCHDOG is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_PC87413_WDT is not set +# CONFIG_NV_TCO is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SMSC_SCH311X_WDT is not set +# CONFIG_SMSC37B787_WDT is not set +# CONFIG_TQMX86_WDT is not set +# CONFIG_VIA_WDT is not set +# CONFIG_W83627HF_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_W83977F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set +# CONFIG_INTEL_MEI_WDT is not set +# CONFIG_NI903X_WDT is not set +# CONFIG_NIC7018_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_SMPRO is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_CGBC is not set +# CONFIG_MFD_CS40L50_I2C is not set +# CONFIG_MFD_CS42L43_I2C is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MP2629 is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_INTEL_LPSS_ACPI is not set +# CONFIG_MFD_INTEL_LPSS_PCI is not set +# CONFIG_MFD_INTEL_PMC_BXT is not set +# CONFIG_MFD_IQS62X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX5970 is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77541 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77705 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6370 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_MFD_NCT6694 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_SY7636A is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RT4831 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RT5120 is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_BQ257XX is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS6594_I2C is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ATC260X_I2C is not set +# CONFIG_MFD_UPBOARD_FPGA is not set +# CONFIG_MFD_MAX7360 is not set +# end of Multifunction device drivers + +# CONFIG_REGULATOR is not set +# CONFIG_RC_CORE is not set + +# +# CEC support +# +# CONFIG_MEDIA_CEC_SUPPORT is not set +# end of CEC support + +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +CONFIG_APERTURE_HELPERS=y +CONFIG_SCREEN_INFO=y +CONFIG_VIDEO=y +# CONFIG_AUXDISPLAY is not set +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set +CONFIG_INTEL_GTT=y +# CONFIG_VGA_SWITCHEROO is not set +CONFIG_DRM=y + +# +# DRM debugging options +# +# CONFIG_DRM_DEBUG_MM is not set +# end of DRM debugging options + +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_PANIC is not set +CONFIG_DRM_CLIENT_SELECTION=y + +# +# Supported DRM clients +# +# CONFIG_DRM_FBDEV_EMULATION is not set +# CONFIG_DRM_CLIENT_LOG is not set +# end of Supported DRM clients + +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_DISPLAY_HELPER=y +# CONFIG_DRM_DISPLAY_DP_AUX_CEC is not set +# CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is not set +CONFIG_DRM_DISPLAY_DP_HELPER=y +CONFIG_DRM_DISPLAY_DSC_HELPER=y +CONFIG_DRM_DISPLAY_HDCP_HELPER=y +CONFIG_DRM_DISPLAY_HDMI_HELPER=y +CONFIG_DRM_TTM=y +CONFIG_DRM_BUDDY=y +CONFIG_DRM_GEM_SHMEM_HELPER=y + +# +# Drivers for system framebuffers +# +# CONFIG_DRM_EFIDRM is not set +# CONFIG_DRM_SIMPLEDRM is not set +# CONFIG_DRM_VESADRM is not set +# end of Drivers for system framebuffers + +# +# ARM devices +# +# end of ARM devices + +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_NOUVEAU is not set +CONFIG_DRM_I915=y +CONFIG_DRM_I915_FORCE_PROBE="" +CONFIG_DRM_I915_CAPTURE_ERROR=y +CONFIG_DRM_I915_COMPRESS_ERROR=y +CONFIG_DRM_I915_USERPTR=y +CONFIG_DRM_I915_REQUEST_TIMEOUT=20000 +CONFIG_DRM_I915_FENCE_TIMEOUT=10000 +CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=250 +CONFIG_DRM_I915_HEARTBEAT_INTERVAL=2500 +CONFIG_DRM_I915_PREEMPT_TIMEOUT=640 +CONFIG_DRM_I915_PREEMPT_TIMEOUT_COMPUTE=7500 +CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT=8000 +CONFIG_DRM_I915_STOP_TIMEOUT=100 +CONFIG_DRM_I915_TIMESLICE_DURATION=1 +# CONFIG_DRM_XE is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_DRM_VMWGFX is not set +# CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_QXL is not set +CONFIG_DRM_VIRTIO_GPU=y +CONFIG_DRM_VIRTIO_GPU_KMS=y +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# end of Display Panels + +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# end of Display Interface Bridges + +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_APPLETBDRM is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_GM12U320 is not set +# CONFIG_DRM_VBOXVIDEO is not set +# CONFIG_DRM_GUD is not set +# CONFIG_DRM_ST7571_I2C is not set +# CONFIG_DRM_SSD130X is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y + +# +# Frame buffer Devices +# +# CONFIG_FB is not set +# end of Frame buffer Devices + +# +# Backlight & LCD device support +# +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_AW99706 is not set +# CONFIG_BACKLIGHT_KTZ8866 is not set +# CONFIG_BACKLIGHT_APPLE is not set +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3509 is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# end of Backlight & LCD device support + +CONFIG_HDMI=y +# CONFIG_FIRMWARE_EDID is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +# end of Console display driver support + +# CONFIG_TRACE_GPU_MEM is not set +# end of Graphics support + +# CONFIG_DRM_ACCEL is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_SEQ_DEVICE=y +CONFIG_SND_JACK=y +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_OSSEMUL is not set +CONFIG_SND_PCM_TIMER=y +CONFIG_SND_HRTIMER=y +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_CTL_FAST_LOOKUP=y +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_CTL_INPUT_VALIDATION is not set +# CONFIG_SND_UTIMER is not set +CONFIG_SND_VMASTER=y +CONFIG_SND_DMA_SGBUF=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +# CONFIG_SND_SEQ_UMP is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_PCSP is not set +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_PCMTEST is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ASIHPI is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SE6X is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +CONFIG_SND_HDA=y +CONFIG_SND_HDA_HWDEP=y +# CONFIG_SND_HDA_RECONFIG is not set +# CONFIG_SND_HDA_INPUT_BEEP is not set +# CONFIG_SND_HDA_PATCH_LOADER is not set +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +# CONFIG_SND_HDA_CTL_DEV_ID is not set +CONFIG_SND_HDA_PREALLOC_SIZE=0 +CONFIG_SND_HDA_INTEL=y +# CONFIG_SND_HDA_ACPI is not set +# CONFIG_SND_HDA_CODEC_ANALOG is not set +# CONFIG_SND_HDA_CODEC_SIGMATEL is not set +# CONFIG_SND_HDA_CODEC_VIA is not set +# CONFIG_SND_HDA_CODEC_CONEXANT is not set +# CONFIG_SND_HDA_CODEC_SENARYTECH is not set +# CONFIG_SND_HDA_CODEC_CA0110 is not set +# CONFIG_SND_HDA_CODEC_CA0132 is not set +# CONFIG_SND_HDA_CODEC_CMEDIA is not set +# CONFIG_SND_HDA_CODEC_CM9825 is not set +# CONFIG_SND_HDA_CODEC_SI3054 is not set +# CONFIG_SND_HDA_GENERIC is not set +# CONFIG_SND_HDA_CODEC_REALTEK is not set +# CONFIG_SND_HDA_CODEC_CIRRUS is not set +# CONFIG_SND_HDA_CODEC_HDMI is not set +CONFIG_SND_HDA_CORE=y +CONFIG_SND_HDA_COMPONENT=y +CONFIG_SND_HDA_I915=y +CONFIG_SND_INTEL_NHLT=y +CONFIG_SND_INTEL_DSP_CONFIG=y +CONFIG_SND_INTEL_SOUNDWIRE_ACPI=y +# end of HD-Audio + +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_USX2Y is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_US122L is not set +# CONFIG_SND_USB_US144MKII is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_PCMCIA=y +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set +# CONFIG_SND_SOC is not set +CONFIG_SND_X86=y +# CONFIG_HDMI_LPE_AUDIO is not set +# CONFIG_SND_VIRTIO is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +CONFIG_HIDRAW=y +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y +# CONFIG_HID_HAPTIC is not set + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +# CONFIG_HID_ACCUTOUCH is not set +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_APPLETB_BL is not set +# CONFIG_HID_APPLETB_KBD is not set +# CONFIG_HID_ASUS is not set +# CONFIG_HID_AUREAL is not set +CONFIG_HID_BELKIN=y +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_BIGBEN_FF is not set +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CREATIVE_SB0540 is not set +CONFIG_HID_CYPRESS=y +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELAN is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EVISION is not set +CONFIG_HID_EZKEY=y +# CONFIG_HID_FT260 is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_GLORIOUS is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GOOGLE_STADIA_FF is not set +# CONFIG_HID_VIVALDI is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_KYSONA is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_VRC2 is not set +# CONFIG_HID_XIAOMI is not set +CONFIG_HID_GYRATION=y +# CONFIG_HID_ICADE is not set +CONFIG_HID_ITE=y +# CONFIG_HID_JABRA is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LED is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LETSKETCH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_MEGAWORLD_FF is not set +CONFIG_HID_REDRAGON=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NINTENDO is not set +# CONFIG_HID_NTI is not set +CONFIG_HID_NTRIG=y +# CONFIG_HID_ORTEK is not set +CONFIG_HID_PANTHERLORD=y +CONFIG_PANTHERLORD_FF=y +# CONFIG_HID_PENMOUNT is not set +CONFIG_HID_PETALYNX=y +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PXRC is not set +# CONFIG_HID_RAZER is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_RETRODE is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +CONFIG_HID_SAMSUNG=y +# CONFIG_HID_SEMITEK is not set +# CONFIG_HID_SIGMAMICRO is not set +CONFIG_HID_SONY=y +# CONFIG_SONY_FF is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +CONFIG_HID_SUNPLUS=y +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +CONFIG_HID_TOPSEED=y +# CONFIG_HID_TOPRE is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_U2FZERO is not set +# CONFIG_HID_UNIVERSAL_PIDFF is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_WINWING is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set +# CONFIG_HID_MCP2221 is not set +# end of Special HID drivers + +# +# HID-BPF support +# +# end of HID-BPF support + +CONFIG_I2C_HID=y +# CONFIG_I2C_HID_ACPI is not set +# CONFIG_I2C_HID_OF is not set + +# +# Intel ISH HID support +# +# CONFIG_INTEL_ISH_HID is not set +# end of Intel ISH HID support + +# +# AMD SFH HID Support +# +# CONFIG_AMD_SFH_HID is not set +# end of AMD SFH HID Support + +# +# Intel THC HID Support +# +# CONFIG_INTEL_THC_HID is not set +# end of Intel THC HID Support + +# +# USB HID support +# +CONFIG_USB_HID=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +# end of USB HID support + +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +# CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_PCI=y +CONFIG_USB_PCI_AMD=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=1 +CONFIG_USB_MON=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_PCI=y +# CONFIG_USB_XHCI_PCI_RENESAS is not set +# CONFIG_USB_XHCI_PLATFORM is not set +# CONFIG_USB_XHCI_SIDEBAND is not set +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_FSL is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +CONFIG_USB_PRINTER=y +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set + +# +# USB dual-mode controller drivers +# +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_USB_LJCA is not set +# CONFIG_USB_USBIO is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_ISP1301 is not set +# end of USB Physical Layer drivers + +# CONFIG_USB_GADGET is not set +# CONFIG_TYPEC is not set +# CONFIG_USB_ROLE_SWITCH is not set +# CONFIG_MMC is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_CLASS_MULTICOLOR is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +# CONFIG_LEDS_APU is not set +# CONFIG_LEDS_AW200XX is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3532 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA995X is not set +# CONFIG_LEDS_BD2606MVV is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_MLXCPLD is not set +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_USER is not set +# CONFIG_LEDS_NIC78BX is not set + +# +# Flash and Torch LED drivers +# + +# +# RGB LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_DISK is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_PANIC is not set +# CONFIG_LEDS_TRIGGER_NETDEV is not set +# CONFIG_LEDS_TRIGGER_PATTERN is not set +# CONFIG_LEDS_TRIGGER_TTY is not set +# CONFIG_LEDS_TRIGGER_INPUT_EVENTS is not set + +# +# Simatic LED drivers +# +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_RTC_LIB=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABEOZ9 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_NVIDIA_VRS10 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8111 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV3032 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_SD2405AL is not set +# CONFIG_RTC_DRV_SD3078 is not set + +# +# SPI RTC drivers +# +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RX6110 is not set + +# +# Platform RTC drivers +# +CONFIG_RTC_DRV_CMOS=y +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_RP5C01 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_GOLDFISH is not set + +# +# HID Sensor RTC drivers +# +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DMA_ACPI=y +# CONFIG_ALTERA_MSGDMA is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_INTEL_IDXD is not set +# CONFIG_INTEL_IDXD_COMPAT is not set +# CONFIG_INTEL_IOATDMA is not set +# CONFIG_PLX_DMA is not set +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_XDMA is not set +# CONFIG_AMD_PTDMA is not set +# CONFIG_AMD_QDMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_HIDMA is not set +CONFIG_DW_DMAC_CORE=y +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_DW_EDMA is not set +CONFIG_HSU_DMA=y +# CONFIG_SF_PDMA is not set +# CONFIG_INTEL_LDMA is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set + +# +# DMABUF options +# +CONFIG_SYNC_FILE=y +# CONFIG_SW_SYNC is not set +# CONFIG_UDMABUF is not set +# CONFIG_DMABUF_MOVE_NOTIFY is not set +# CONFIG_DMABUF_DEBUG is not set +# CONFIG_DMABUF_SELFTESTS is not set +# CONFIG_DMABUF_HEAPS is not set +# CONFIG_DMABUF_SYSFS_STATS is not set +# end of DMABUF options + +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRTIO_ANCHOR=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_PCI_LIB=y +CONFIG_VIRTIO_PCI_LIB_LEGACY=y +CONFIG_VIRTIO_MENU=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_PCI_ADMIN_LEGACY=y +CONFIG_VIRTIO_PCI_LEGACY=y +# CONFIG_VIRTIO_BALLOON is not set +CONFIG_VIRTIO_INPUT=y +# CONFIG_VIRTIO_MMIO is not set +CONFIG_VIRTIO_DMA_SHARED_BUFFER=y +# CONFIG_VIRTIO_DEBUG is not set +# CONFIG_VIRTIO_RTC is not set +# CONFIG_VDPA is not set +CONFIG_VHOST_MENU=y +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set +CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y + +# +# Microsoft Hyper-V guest support +# +# CONFIG_HYPERV is not set +# end of Microsoft Hyper-V guest support + +# CONFIG_GREYBUS is not set +# CONFIG_COMEDI is not set +# CONFIG_GPIB is not set +# CONFIG_STAGING is not set +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_MELLANOX_PLATFORM is not set +CONFIG_SURFACE_PLATFORMS=y +# CONFIG_SURFACE_3_POWER_OPREGION is not set +# CONFIG_SURFACE_GPE is not set +# CONFIG_SURFACE_PRO3_BUTTON is not set +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_WMI_BMOF=y +# CONFIG_HUAWEI_WMI is not set +# CONFIG_X86_PLATFORM_DRIVERS_UNIWILL is not set +# CONFIG_MXM_WMI is not set +# CONFIG_NVIDIA_WMI_EC_BACKLIGHT is not set +# CONFIG_XIAOMI_WMI is not set +# CONFIG_REDMI_WMI is not set +# CONFIG_GIGABYTE_WMI is not set +# CONFIG_ACERHDF is not set +# CONFIG_ACER_WIRELESS is not set +# CONFIG_ACER_WMI is not set + +# +# AMD HSMP Driver +# +# CONFIG_AMD_HSMP_ACPI is not set +# CONFIG_AMD_HSMP_PLAT is not set +# end of AMD HSMP Driver + +# CONFIG_AMD_PMC is not set +# CONFIG_AMD_HFI is not set +# CONFIG_AMD_3D_VCACHE is not set +# CONFIG_AMD_WBRF is not set +# CONFIG_AMD_ISP_PLATFORM is not set +# CONFIG_ADV_SWBUTTON is not set +# CONFIG_APPLE_GMUX is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_ASUS_WIRELESS is not set +# CONFIG_ASUS_WMI is not set +# CONFIG_AYANEO_EC is not set +CONFIG_EEEPC_LAPTOP=y +# CONFIG_X86_PLATFORM_DRIVERS_DELL is not set +# CONFIG_AMILO_RFKILL is not set +# CONFIG_FUJITSU_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_GPD_POCKET_FAN is not set +# CONFIG_X86_PLATFORM_DRIVERS_HP is not set +# CONFIG_WIRELESS_HOTKEY is not set +# CONFIG_IBM_RTL is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_INTEL_ATOMISP2_PM is not set +# CONFIG_INTEL_IFS is not set +# CONFIG_INTEL_SAR_INT1092 is not set + +# +# Intel Speed Select Technology interface support +# +# CONFIG_INTEL_SPEED_SELECT_INTERFACE is not set +# end of Intel Speed Select Technology interface support + +# CONFIG_INTEL_WMI_SBL_FW_UPDATE is not set +# CONFIG_INTEL_WMI_THUNDERBOLT is not set + +# +# Intel Uncore Frequency Control +# +# CONFIG_INTEL_UNCORE_FREQ_CONTROL is not set +# end of Intel Uncore Frequency Control + +# CONFIG_INTEL_HID_EVENT is not set +# CONFIG_INTEL_VBTN is not set +# CONFIG_INTEL_EHL_PSE_IO is not set +# CONFIG_INTEL_OAKTRAIL is not set +# CONFIG_INTEL_PUNIT_IPC is not set +# CONFIG_INTEL_RST is not set +# CONFIG_INTEL_SMARTCONNECT is not set +# CONFIG_INTEL_TURBO_MAX_3 is not set +# CONFIG_INTEL_VSEC is not set +# CONFIG_IDEAPAD_LAPTOP is not set +# CONFIG_LENOVO_WMI_HOTKEY_UTILITIES is not set +# CONFIG_LENOVO_WMI_CAMERA is not set +# CONFIG_THINKPAD_ACPI is not set +# CONFIG_THINKPAD_LMI is not set +# CONFIG_YOGABOOK is not set +# CONFIG_LENOVO_WMI_GAMEZONE is not set +# CONFIG_LENOVO_WMI_TUNING is not set +# CONFIG_ACPI_QUICKSTART is not set +# CONFIG_MSI_EC is not set +# CONFIG_MSI_LAPTOP is not set +# CONFIG_MSI_WMI is not set +# CONFIG_MSI_WMI_PLATFORM is not set +# CONFIG_SAMSUNG_GALAXYBOOK is not set +# CONFIG_SAMSUNG_LAPTOP is not set +# CONFIG_SAMSUNG_Q10 is not set +# CONFIG_TOSHIBA_BT_RFKILL is not set +# CONFIG_TOSHIBA_HAPS is not set +# CONFIG_TOSHIBA_WMI is not set +# CONFIG_ACPI_CMPC is not set +# CONFIG_COMPAL_LAPTOP is not set +# CONFIG_LG_LAPTOP is not set +# CONFIG_PANASONIC_LAPTOP is not set +# CONFIG_SONY_LAPTOP is not set +# CONFIG_SYSTEM76_ACPI is not set +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_SERIAL_MULTI_INSTANTIATE is not set +# CONFIG_INSPUR_PLATFORM_PROFILE is not set +# CONFIG_DASHARO_ACPI is not set +# CONFIG_INTEL_IPS is not set +# CONFIG_INTEL_SCU_PCI is not set +# CONFIG_INTEL_SCU_PLATFORM is not set +# CONFIG_SIEMENS_SIMATIC_IPC is not set +# CONFIG_WINMATE_FM07_KEYS is not set +# CONFIG_OXP_EC is not set +# CONFIG_TUXEDO_NB04_WMI_AB is not set +CONFIG_P2SB=y +CONFIG_ACPI_WMI=y +# CONFIG_ACPI_WMI_LEGACY_DEVICE_NAMES is not set +# CONFIG_COMMON_CLK is not set +# CONFIG_HWSPINLOCK is not set + +# +# Clock Source drivers +# +CONFIG_CLKEVT_I8253=y +CONFIG_I8253_LOCK=y +CONFIG_CLKBLD_I8253=y +# end of Clock Source drivers + +CONFIG_MAILBOX=y +CONFIG_PCC=y +# CONFIG_ALTERA_MBOX is not set +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# end of Generic IOMMU Pagetable Support + +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set +CONFIG_IOMMU_DEFAULT_DMA_LAZY=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_SVA=y +CONFIG_IOMMU_IOPF=y +CONFIG_AMD_IOMMU=y +CONFIG_DMAR_TABLE=y +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_SVM is not set +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON=y +CONFIG_INTEL_IOMMU_PERF_EVENTS=y +# CONFIG_IOMMUFD is not set +# CONFIG_IRQ_REMAP is not set +# CONFIG_VIRTIO_IOMMU is not set +CONFIG_GENERIC_PT=y +# CONFIG_DEBUG_GENERIC_PT is not set +CONFIG_IOMMU_PT=y +CONFIG_IOMMU_PT_AMDV1=y +CONFIG_IOMMU_PT_VTDSS=y +CONFIG_IOMMU_PT_X86_64=y + +# +# Remoteproc drivers +# +# CONFIG_REMOTEPROC is not set +# end of Remoteproc drivers + +# +# Rpmsg drivers +# +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +# CONFIG_RPMSG_VIRTIO is not set +# end of Rpmsg drivers + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# +# end of Amlogic SoC drivers + +# +# Broadcom SoC drivers +# +# end of Broadcom SoC drivers + +# +# NXP/Freescale QorIQ SoC drivers +# +# end of NXP/Freescale QorIQ SoC drivers + +# +# fujitsu SoC drivers +# +# end of fujitsu SoC drivers + +# +# i.MX SoC drivers +# +# end of i.MX SoC drivers + +# +# Enable LiteX SoC Builder specific drivers +# +# end of Enable LiteX SoC Builder specific drivers + +# CONFIG_WPCM450_SOC is not set + +# +# Qualcomm SoC drivers +# +# end of Qualcomm SoC drivers + +# CONFIG_SOC_TI is not set + +# +# Xilinx SoC drivers +# +# end of Xilinx SoC drivers +# end of SOC (System On Chip) specific Drivers + +# +# PM Domains +# + +# +# Amlogic PM Domains +# +# end of Amlogic PM Domains + +# +# Broadcom PM Domains +# +# end of Broadcom PM Domains + +# +# i.MX PM Domains +# +# end of i.MX PM Domains + +# +# Qualcomm PM Domains +# +# end of Qualcomm PM Domains +# end of PM Domains + +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_NTB is not set +# CONFIG_PWM is not set + +# +# IRQ chip support +# +CONFIG_IRQ_MSI_LIB=y +# end of IRQ chip support + +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set + +# +# PHY Subsystem +# +# CONFIG_GENERIC_PHY is not set +# CONFIG_USB_LGM_PHY is not set +# CONFIG_PHY_CAN_TRANSCEIVER is not set + +# +# PHY drivers for Broadcom platforms +# +# CONFIG_BCM_KONA_USB2_PHY is not set +# end of PHY drivers for Broadcom platforms + +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_INTEL_LGM_EMMC is not set +# end of PHY Subsystem + +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +# CONFIG_DWC_PCIE_PMU is not set +# end of Performance monitor support + +# CONFIG_RAS is not set +# CONFIG_USB4 is not set + +# +# Android +# +# CONFIG_ANDROID_BINDER_IPC is not set +# end of Android + +# CONFIG_LIBNVDIMM is not set +# CONFIG_DAX is not set +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +# CONFIG_NVMEM_LAYOUTS is not set +# CONFIG_NVMEM_RMEM is not set + +# +# HW tracing support +# +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set +# end of HW tracing support + +# CONFIG_FPGA is not set +# CONFIG_TEE is not set +# CONFIG_SIOX is not set +# CONFIG_SLIMBUS is not set +# CONFIG_INTERCONNECT is not set +# CONFIG_COUNTER is not set +# CONFIG_PECI is not set +# CONFIG_HTE is not set +# end of Device Drivers + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_VALIDATE_FS_PARSER is not set +CONFIG_FS_IOMAP=y +CONFIG_BUFFER_HEAD=y +CONFIG_LEGACY_DIRECT_IO=y +# CONFIG_EXT2_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +# CONFIG_FS_VERITY is not set +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=y +# CONFIG_FUSE_FS is not set +# CONFIG_OVERLAY_FS is not set + +# +# Caches +# +CONFIG_NETFS_SUPPORT=y +# CONFIG_NETFS_STATS is not set +# CONFIG_NETFS_DEBUG is not set +# CONFIG_FSCACHE is not set +# end of Caches + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set +# end of CD-ROM/DVD Filesystems + +# +# DOS/FAT/EXFAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_EXFAT_FS is not set +# CONFIG_NTFS3_FS is not set +# CONFIG_NTFS_FS is not set +# end of DOS/FAT/EXFAT/NT Filesystems + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_VMCORE=y +# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_PID_ARCH_STATUS=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_TMPFS_INODE64 is not set +# CONFIG_TMPFS_QUOTA is not set +CONFIG_ARCH_SUPPORTS_HUGETLBFS=y +CONFIG_HUGETLBFS=y +# CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON is not set +CONFIG_HUGETLB_PAGE=y +CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP=y +CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y +# CONFIG_CONFIGFS_FS is not set +CONFIG_EFIVAR_FS=m +# end of Pseudo filesystems + +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_UFS_FS is not set +# CONFIG_EROFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_FSCACHE is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFS_DISABLE_UDP_SUPPORT=y +# CONFIG_NFSD is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_SMB_SERVER is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=y +# CONFIG_9P_FS_POSIX_ACL is not set +# CONFIG_9P_FS_SECURITY is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_UNICODE is not set +CONFIG_IO_WQ=y +# end of File systems + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_PROC_MEM_ALWAYS_FORCE=y +# CONFIG_PROC_MEM_FORCE_PTRACE is not set +# CONFIG_PROC_MEM_NO_FORCE is not set +# CONFIG_MSEAL_SYSTEM_MAPPINGS is not set +CONFIG_SECURITY=y +CONFIG_HAS_SECURITY_AUDIT=y +# CONFIG_SECURITYFS is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +# CONFIG_INTEL_TXT is not set +CONFIG_LSM_MMAP_MIN_ADDR=65536 +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9 +CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256 +CONFIG_SECURITY_SELINUX_AVC_HASH_BITS=9 +# CONFIG_SECURITY_SELINUX_DEBUG is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_LOADPIN is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_SECURITY_SAFESETID is not set +# CONFIG_SECURITY_LOCKDOWN_LSM is not set +# CONFIG_SECURITY_LANDLOCK is not set +CONFIG_INTEGRITY=y +# CONFIG_INTEGRITY_SIGNATURE is not set +CONFIG_INTEGRITY_AUDIT=y +# CONFIG_IMA is not set +# CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,ipe,bpf" + +# +# Kernel hardening options +# + +# +# Memory initialization +# +CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y +# CONFIG_INIT_STACK_NONE is not set +# CONFIG_INIT_STACK_ALL_PATTERN is not set +CONFIG_INIT_STACK_ALL_ZERO=y +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y +# CONFIG_ZERO_CALL_USED_REGS is not set +# end of Memory initialization + +# +# Bounds checking +# +# CONFIG_FORTIFY_SOURCE is not set +# CONFIG_HARDENED_USERCOPY is not set +# end of Bounds checking + +# +# Hardening of kernel data structures +# +# CONFIG_LIST_HARDENED is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# end of Hardening of kernel data structures + +CONFIG_RANDSTRUCT_NONE=y +# end of Kernel hardening options +# end of Security options + +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_SIG=y +CONFIG_CRYPTO_SIG2=y +CONFIG_CRYPTO_SKCIPHER=y +CONFIG_CRYPTO_SKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_KRB5ENC is not set +# CONFIG_CRYPTO_BENCHMARK is not set +# end of Crypto core or helper + +# +# Public-key cryptography +# +CONFIG_CRYPTO_RSA=y +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECRDSA is not set +# end of Public-key cryptography + +# +# Block ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_TWOFISH is not set +# end of Block ciphers + +# +# Length-preserving ciphers and modes +# +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_CHACHA20 is not set +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# end of Length-preserving ciphers and modes + +# +# AEAD (authenticated encryption with associated data) ciphers +# +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GENIV=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=y +# CONFIG_CRYPTO_ESSIV is not set +# end of AEAD (authenticated encryption with associated data) ciphers + +# +# Hashes, digests, and MACs +# +# CONFIG_CRYPTO_BLAKE2B is not set +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_SHA1 is not set +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA3=y +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XXHASH is not set +# end of Hashes, digests, and MACs + +# +# CRCs (cyclic redundancy checks) +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CRC32 is not set +# end of CRCs (cyclic redundancy checks) + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set +# end of Compression + +# +# Random number generation +# +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +# end of Random number generation + +# +# Userspace interface +# +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# end of Userspace interface + +# +# Accelerated Cryptographic Algorithms for CPU (x86) +# +# CONFIG_CRYPTO_AES_NI_INTEL is not set +# CONFIG_CRYPTO_BLOWFISH_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set +# CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAST6_AVX_X86_64 is not set +# CONFIG_CRYPTO_DES3_EDE_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set +# CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64 is not set +# CONFIG_CRYPTO_TWOFISH_X86_64 is not set +# CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set +# CONFIG_CRYPTO_TWOFISH_AVX_X86_64 is not set +# CONFIG_CRYPTO_ARIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_ARIA_AESNI_AVX2_X86_64 is not set +# CONFIG_CRYPTO_ARIA_GFNI_AVX512_X86_64 is not set +# CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set +# CONFIG_CRYPTO_NHPOLY1305_SSE2 is not set +# CONFIG_CRYPTO_NHPOLY1305_AVX2 is not set +# CONFIG_CRYPTO_SM3_AVX_X86_64 is not set +# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set +# end of Accelerated Cryptographic Algorithms for CPU (x86) + +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_PADLOCK is not set +# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C62X is not set +# CONFIG_CRYPTO_DEV_QAT_4XXX is not set +# CONFIG_CRYPTO_DEV_QAT_420XX is not set +# CONFIG_CRYPTO_DEV_QAT_6XXX is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set +# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set +# CONFIG_CRYPTO_DEV_VIRTIO is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +# CONFIG_FIPS_SIGNATURE_SELFTEST is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +# end of Certificates for signature checking + +# CONFIG_CRYPTO_KRB5 is not set +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +# CONFIG_PACKING is not set +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +# CONFIG_CORDIC is not set +# CONFIG_PRIME_NUMBERS is not set +CONFIG_RATIONAL=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +CONFIG_ARCH_USE_SYM_ANNOTATIONS=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRC32=y +CONFIG_CRC32_ARCH=y +CONFIG_CRC_OPTIMIZATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_ARC4=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_BLAKE2S_ARCH=y +CONFIG_CRYPTO_LIB_MD5=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA1_ARCH=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_SHA256_ARCH=y +CONFIG_CRYPTO_LIB_SHA512=y +CONFIG_CRYPTO_LIB_SHA512_ARCH=y +CONFIG_CRYPTO_LIB_SHA3=y +# end of Crypto library routines + +CONFIG_XXHASH=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_ARM64=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_RISCV=y +# CONFIG_XZ_DEC_MICROLZMA is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_DECOMPRESS_ZSTD=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_INTERVAL_TREE=y +CONFIG_XARRAY_MULTI=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_NEED_SG_DMA_FLAGS=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_SWIOTLB=y +# CONFIG_SWIOTLB_DYNAMIC is not set +CONFIG_DMA_NEED_SYNC=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_DMA_MAP_BENCHMARK is not set +CONFIG_SGL_ALLOC=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_CLZ_TAB=y +# CONFIG_IRQ_POLL is not set +CONFIG_MPILIB=y +CONFIG_DIMLIB=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_HAVE_GENERIC_VDSO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_FONT_SUPPORT=y +CONFIG_FONT_8x16=y +CONFIG_FONT_AUTOSELECT=y +CONFIG_SG_POOL=y +CONFIG_ARCH_HAS_PMEM_API=y +CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION=y +CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y +CONFIG_ARCH_HAS_COPY_MC=y +CONFIG_ARCH_STACKWALK=y +CONFIG_STACKDEPOT=y +CONFIG_STACKDEPOT_MAX_FRAMES=64 +CONFIG_SBITMAP=y +# CONFIG_LWQ_TEST is not set +# end of Library routines + +CONFIG_FIRMWARE_TABLE=y +CONFIG_UNION_FIND=y + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_CALLER is not set +# CONFIG_STACKTRACE_BUILD_ID is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DYNAMIC_DEBUG_CORE is not set +CONFIG_SYMBOLIC_ERRNAME=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE_DETAILED is not set +# end of printk and dmesg options + +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y + +# +# Compile-time checks and compiler options +# +CONFIG_AS_HAS_NON_CONST_ULEB128=y +CONFIG_DEBUG_INFO_NONE=y +# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_HEADERS_INSTALL is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_OBJTOOL=y +# CONFIG_OBJTOOL_WERROR is not set +CONFIG_NOINSTR_VALIDATION=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# end of Compile-time checks and compiler options + +# +# Generic Kernel Debugging Instruments +# +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN=y +# CONFIG_UBSAN is not set +CONFIG_HAVE_ARCH_KCSAN=y +CONFIG_HAVE_KCSAN_COMPILER=y +# CONFIG_KCSAN is not set +# end of Generic Kernel Debugging Instruments + +# +# Networking Debugging +# +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_DEBUG_NET is not set +# CONFIG_DEBUG_NET_SMALL_RTNL is not set +# end of Networking Debugging + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_TABLE_CHECK is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_ARCH_HAS_DEBUG_WX=y +CONFIG_DEBUG_WX=y +CONFIG_ARCH_HAS_PTDUMP=y +CONFIG_PTDUMP=y +# CONFIG_PTDUMP_DEBUGFS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_PER_VMA_LOCK_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SHRINKER_DEBUG is not set +CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_SCHED_STACK_END_CHECK is not set +CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VFS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_PGTABLE is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y +# CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP is not set +# CONFIG_MEM_ALLOC_PROFILING is not set +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_HAVE_ARCH_KASAN_VMALLOC=y +CONFIG_CC_HAS_KASAN_GENERIC=y +CONFIG_CC_HAS_KASAN_SW_TAGS=y +CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y +# CONFIG_KASAN is not set +CONFIG_HAVE_ARCH_KFENCE=y +# CONFIG_KFENCE is not set +CONFIG_HAVE_ARCH_KMSAN=y +# end of Memory Debugging + +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Oops, Lockups and Hangs +# +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SOFTLOCKUP_DETECTOR is not set +CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set +# CONFIG_TEST_LOCKUP is not set +# end of Debug Oops, Lockups and Hangs + +# +# Scheduler Debugging +# +CONFIG_SCHED_INFO=y +CONFIG_SCHEDSTATS=y +# end of Scheduler Debugging + +# CONFIG_DEBUG_PREEMPT is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set +# end of Lock Debugging (spinlocks, mutexes, etc...) + +# CONFIG_NMI_CHECK_CPU is not set +# CONFIG_DEBUG_IRQFLAGS is not set +CONFIG_STACKTRACE=y +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set + +# +# Debug kernel data structures +# +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_MAPLE_TREE is not set +# end of Debug kernel data structures + +# +# RCU Debugging +# +# CONFIG_RCU_SCALE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 +# CONFIG_RCU_CPU_STALL_CPUTIME is not set +CONFIG_RCU_TRACE=y +# CONFIG_RCU_EQS_DEBUG is not set +# end of RCU Debugging + +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_CGROUP_REF is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_NOP_TRACER=y +CONFIG_HAVE_RETHOOK=y +CONFIG_RETHOOK=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_HAVE_FTRACE_REGS_HAVING_PT_REGS=y +CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_JMP=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_FENTRY=y +CONFIG_HAVE_OBJTOOL_MCOUNT=y +CONFIG_HAVE_OBJTOOL_NOP_MCOUNT=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED=y +# CONFIG_BOOTTIME_TRACING is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_HWLAT_TRACER is not set +# CONFIG_OSNOISE_TRACER is not set +# CONFIG_TIMERLAT_TRACER is not set +# CONFIG_MMIOTRACE is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_KPROBE_EVENTS=y +CONFIG_UPROBE_EVENTS=y +CONFIG_EPROBE_EVENTS=y +CONFIG_DYNAMIC_EVENTS=y +CONFIG_PROBE_EVENTS=y +# CONFIG_SYNTH_EVENTS is not set +# CONFIG_USER_EVENTS is not set +# CONFIG_HIST_TRIGGERS is not set +# CONFIG_TRACE_EVENT_INJECT is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_KPROBE_EVENT_GEN_TEST is not set +# CONFIG_RV is not set +CONFIG_PROVIDE_OHCI1394_DMA_INIT=y +# CONFIG_SAMPLES is not set +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set + +# +# x86 Debugging +# +CONFIG_EARLY_PRINTK_USB=y +CONFIG_X86_VERBOSE_BOOTUP=y +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_DBGP=y +# CONFIG_EARLY_PRINTK_USB_XDBC is not set +# CONFIG_EFI_PGT_DUMP is not set +# CONFIG_DEBUG_TLBFLUSH is not set +CONFIG_HAVE_MMIOTRACE_SUPPORT=y +# CONFIG_X86_DECODER_SELFTEST is not set +CONFIG_IO_DELAY_0X80=y +# CONFIG_IO_DELAY_0XED is not set +# CONFIG_IO_DELAY_UDELAY is not set +# CONFIG_IO_DELAY_NONE is not set +CONFIG_DEBUG_BOOT_PARAMS=y +# CONFIG_CPA_DEBUG is not set +CONFIG_DEBUG_ENTRY=y +# CONFIG_DEBUG_NMI_SELFTEST is not set +CONFIG_X86_DEBUG_FPU=y +# CONFIG_PUNIT_ATOM_DEBUG is not set +CONFIG_UNWINDER_ORC=y +# CONFIG_UNWINDER_FRAME_POINTER is not set +# end of x86 Debugging + +# +# Kernel Testing and Coverage +# +# CONFIG_KUNIT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FUNCTION_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_ARCH_HAS_KCOV=y +# CONFIG_KCOV is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_TEST_DHRY is not set +# CONFIG_LKDTM is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_DIV64 is not set +# CONFIG_TEST_MULDIV64 is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_TEST_REF_TRACKER is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_XARRAY is not set +# CONFIG_TEST_MAPLE_TREE is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_BPF is not set +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KALLSYMS is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_FPU is not set +# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set +# CONFIG_TEST_OBJPOOL is not set +CONFIG_ARCH_USE_MEMTEST=y +# CONFIG_MEMTEST is not set +# end of Kernel Testing and Coverage + +# +# Rust hacking +# +# end of Rust hacking +# end of Kernel hacking From ff7461de4961b8e73401379cdff7d818ea57709c Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 19 Mar 2026 15:49:53 +1100 Subject: [PATCH 03/42] x86_64: APICv proper prototype Signed-off-by: Bill Nguyen --- .../board/x86_64_generic_vtx/simple.system | 13 +------------ examples/simple/vmm_x86_64.c | 7 +------ include/libvmm/arch/x86_64/vcpu.h | 3 +-- src/arch/x86_64/apic.c | 16 ++++++++++------ src/arch/x86_64/vcpu.c | 7 +++---- 5 files changed, 16 insertions(+), 30 deletions(-) diff --git a/examples/simple/board/x86_64_generic_vtx/simple.system b/examples/simple/board/x86_64_generic_vtx/simple.system index dd3b1007c..2033ac66b 100644 --- a/examples/simple/board/x86_64_generic_vtx/simple.system +++ b/examples/simple/board/x86_64_generic_vtx/simple.system @@ -8,26 +8,15 @@ - - - - - - - - - - - + - diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c index e1e407d9a..63f38e781 100644 --- a/examples/simple/vmm_x86_64.c +++ b/examples/simple/vmm_x86_64.c @@ -68,12 +68,7 @@ void init(void) return; } - assert(guest_vapic_size == 0x1000); - assert(guest_apic_access_size == 0x1000); - memset((void *)guest_vapic_vaddr, 0, guest_vapic_size); - memset((void *)guest_apic_access_vaddr, 0, guest_apic_access_size); - vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit, guest_vapic_paddr, - guest_apic_access_paddr); + vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit); // Set up the PCI bus assert(pci_x86_init()); diff --git a/include/libvmm/arch/x86_64/vcpu.h b/include/libvmm/arch/x86_64/vcpu.h index f3583c652..b02b430a7 100644 --- a/include/libvmm/arch/x86_64/vcpu.h +++ b/include/libvmm/arch/x86_64/vcpu.h @@ -50,7 +50,6 @@ #define RFLAGS_DEFAULT BIT(1) void vcpu_set_up_reset_state(uint64_t vapic_page_paddr, uint64_t apic_access_page_paddr); -void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, uint64_t vapic_page_paddr, - uint64_t apic_access_page_paddr); +void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit); void vcpu_print_regs(size_t vcpu_id); diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index 79bbad407..7ed995e7a 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -84,13 +84,15 @@ static void debug_print_lapic_pending_irqs(void) uint32_t vapic_read_reg(int offset) { assert(offset < 0x1000); - return *((uint32_t *)(vapic_vaddr + offset)); + // @billn fix hardcoded vaddr + return *((volatile uint32_t *)(0x101000ull + offset)); } void vapic_write_reg(int offset, uint32_t value) { assert(offset < 0x1000); - volatile uint32_t *reg = (uint32_t *)(vapic_vaddr + offset); + // @billn fix hardcoded vaddr + volatile uint32_t *reg = (uint32_t *)(0x101000ull + offset); *reg = value; } @@ -462,8 +464,10 @@ bool inject_ioapic_irq(int ioapic, int pin) LOG_VMM_ERR("unknown I/O APIC delivery mode for injection on pin %d, mode 0x%x\n", pin, delivery_mode); assert(false); } - // uint8_t level_trigger = (ioapic_regs.ioredtbl[pin] >> 15) & 0x1; - // assert(!level_trigger); + + // @billn sus only support edge triggered interrupts right now + uint8_t level_trigger = (ioapic_regs.ioredtbl[pin] >> 15) & 0x1; + assert(!level_trigger); uint8_t vector = ioapic_pin_to_vector(ioapic, pin); @@ -495,7 +499,7 @@ bool inject_ioapic_irq(int ioapic, int pin) break; } default: - LOG_VMM_ERR("bug: eoi_bitmap_n > 3\n"); + LOG_VMM_ERR("impossible: eoi_bitmap_n %d > 3\n", eoi_bitmap_n); return false; } } @@ -546,7 +550,7 @@ bool ioapic_ack_passthrough_irq(uint8_t vector) break; } default: - LOG_VMM_ERR("bug: eoi_bitmap_n > 3\n"); + LOG_VMM_ERR("impossible: eoi_bitmap_n %d > 3\n", eoi_bitmap_n); return false; } diff --git a/src/arch/x86_64/vcpu.c b/src/arch/x86_64/vcpu.c index 14a4b6aa7..27a21d590 100644 --- a/src/arch/x86_64/vcpu.c +++ b/src/arch/x86_64/vcpu.c @@ -16,8 +16,7 @@ #include #include -void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, uint64_t vapic_page_paddr, - uint64_t apic_access_page_paddr) +void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit) { // @billn explain @@ -78,8 +77,8 @@ void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, u microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_LDTR_ACCESS_RIGHTS, 0x2 | 1 << 7); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_TR_ACCESS_RIGHTS, 0xb | 1 << 7); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_VIRTUAL_APIC_ADDRESS, vapic_page_paddr); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_APIC_ACCESS_ADDRESS, apic_access_page_paddr); + // microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_VIRTUAL_APIC_ADDRESS, vapic_page_paddr); + // microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_APIC_ACCESS_ADDRESS, apic_access_page_paddr); // Table 25-16. Definitions of VM-Entry Controls // load EFER on entry From c8c1de491d856ca2ab8d5ea110ad99effaa19109 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 26 Mar 2026 13:57:18 +1100 Subject: [PATCH 04/42] x86_64: update sDDF for optimised x86 timer driver Signed-off-by: Bill Nguyen --- examples/simple/board/x86_64_generic_vtx/simple.system | 2 +- examples/simple/build.zig | 2 +- examples/simple/simple.mk | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/simple/board/x86_64_generic_vtx/simple.system b/examples/simple/board/x86_64_generic_vtx/simple.system index 2033ac66b..f53be8a61 100644 --- a/examples/simple/board/x86_64_generic_vtx/simple.system +++ b/examples/simple/board/x86_64_generic_vtx/simple.system @@ -29,7 +29,7 @@ - + diff --git a/examples/simple/build.zig b/examples/simple/build.zig index 391747214..175dbc8bc 100644 --- a/examples/simple/build.zig +++ b/examples/simple/build.zig @@ -234,7 +234,7 @@ pub fn build(b: *std.Build) !void { var timer_driver: ?*std.Build.Step.InstallArtifact = null; if (target.result.cpu.arch == .x86_64) { - timer_driver = b.addInstallArtifact(sddf_dep.artifact("driver_timer_hpet.elf"), .{ .dest_sub_path = "timer_driver_x86_64.elf" }); + timer_driver = b.addInstallArtifact(sddf_dep.artifact("driver_timer_tsc_hpet.elf"), .{ .dest_sub_path = "timer_driver_x86_64.elf" }); } const system_description_path = b.fmt("board/{s}/simple.system", .{ microkit_board }); diff --git a/examples/simple/simple.mk b/examples/simple/simple.mk index 5d2f8a3e6..1987dd610 100644 --- a/examples/simple/simple.mk +++ b/examples/simple/simple.mk @@ -120,7 +120,7 @@ include $(LIBVMM)/vmm.mk include ${SDDF}/util/util.mk ifeq ($(strip $(MICROKIT_BOARD)), x86_64_generic_vtx) -TIMER_DRIVER_DIR := hpet +TIMER_DRIVER_DIR := tsc_hpet TIMER_DRIVER := $(SDDF)/drivers/timer/$(TIMER_DRIVER_DIR) include ${TIMER_DRIVER}/timer_driver.mk endif From 9af32e2176aed5bd716f985f45f0d66a0bf7a9c7 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 26 Mar 2026 13:59:42 +1100 Subject: [PATCH 05/42] x86_64: abstract TSC measurement behind a library Signed-off-by: Bill Nguyen --- examples/simple/vmm_x86_64.c | 46 +++++------ include/libvmm/arch/x86_64/tsc.h | 18 ++++ include/libvmm/libvmm.h | 1 + include/libvmm/util/util.h | 7 +- src/arch/x86_64/cpuid.c | 5 -- src/arch/x86_64/tsc.c | 137 +++++++++++++++++++++++++++++++ vmm.mk | 3 +- 7 files changed, 184 insertions(+), 33 deletions(-) create mode 100644 include/libvmm/arch/x86_64/tsc.h create mode 100644 src/arch/x86_64/tsc.c diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c index 63f38e781..1cf32ec06 100644 --- a/examples/simple/vmm_x86_64.c +++ b/examples/simple/vmm_x86_64.c @@ -49,9 +49,7 @@ uint64_t guest_flash_size; uintptr_t guest_high_ram_vaddr; uint64_t guest_high_ram_size; -bool tsc_calibrating = true; linux_x86_setup_ret_t linux_setup; -uint64_t tsc_pre, tsc_post, measured_tsc_hz; void init(void) { @@ -70,42 +68,38 @@ void init(void) vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit); - // Set up the PCI bus + /* Set up the virtual PCI bus */ assert(pci_x86_init()); /* Pass through COM1 serial port */ microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, com1_ioport_id, com1_ioport_addr, com1_ioport_size); microkit_irq_ack(COM1_IRQ_CH); - LOG_VMM("Measuring TSC frequency...\n"); - sddf_timer_set_timeout(TIMER_DRV_CH_FOR_LAPIC, NS_IN_S); - tsc_pre = rdtsc(); + /* Retrieve the TSC frequency from hardware */ + x86_host_tsc_t tsc_metadata = get_host_tsc(TIMER_DRV_CH_FOR_LAPIC); + if (!tsc_metadata.valid) { + LOG_VMM_ERR("cannot retrieve TSC frequency\n"); + return; + } + + /* Initialise the virtual Local and I/O APICs */ + bool success = virq_controller_init(tsc_metadata.freq_hz, guest_vapic_vaddr); + if (!success) { + LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); + return; + } + + /* Pass through serial IRQs */ + assert(virq_ioapic_register_passthrough(0, 4, COM1_IRQ_CH)); + + guest_start(linux_setup.kernel_entry_gpa, 0, 0); } void notified(microkit_channel ch) { switch (ch) { case TIMER_DRV_CH_FOR_LAPIC: { - if (tsc_calibrating) { - tsc_post = rdtsc(); - measured_tsc_hz = tsc_post - tsc_pre; - LOG_VMM("TSC frequency is %lu Hz\n", measured_tsc_hz); - tsc_calibrating = false; - - /* Initialise the virtual APIC */ - bool success = virq_controller_init(measured_tsc_hz, guest_vapic_vaddr); - if (!success) { - LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); - return; - } - - /* Pass through serial IRQs */ - assert(virq_ioapic_register_passthrough(0, 4, COM1_IRQ_CH)); - - guest_start(linux_setup.kernel_entry_gpa, 0, 0); - } else { - handle_lapic_timer_nftn(GUEST_BOOT_VCPU_ID); - } + handle_lapic_timer_nftn(GUEST_BOOT_VCPU_ID); break; } case TIMER_DRV_CH_FOR_HPET_CH0: diff --git a/include/libvmm/arch/x86_64/tsc.h b/include/libvmm/arch/x86_64/tsc.h new file mode 100644 index 000000000..3cc272fe3 --- /dev/null +++ b/include/libvmm/arch/x86_64/tsc.h @@ -0,0 +1,18 @@ +/* + * Copyright 2026, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +typedef struct x86_host_tsc { + bool valid; + bool invariant; + uint64_t freq_hz; +} x86_host_tsc_t; + +x86_host_tsc_t get_host_tsc(microkit_channel timer_ch); \ No newline at end of file diff --git a/include/libvmm/libvmm.h b/include/libvmm/libvmm.h index fdddcbe8c..dcffb1a82 100644 --- a/include/libvmm/libvmm.h +++ b/include/libvmm/libvmm.h @@ -41,4 +41,5 @@ #include #include #include +#include #endif diff --git a/include/libvmm/util/util.h b/include/libvmm/util/util.h index 9da271e9f..ba12f14c0 100644 --- a/include/libvmm/util/util.h +++ b/include/libvmm/util/util.h @@ -65,10 +65,15 @@ void print_mem_hex(uintptr_t addr, size_t size); #endif #if defined(CONFIG_ARCH_X86_64) -static __inline__ uint64_t rdtsc(void) +static inline uint64_t rdtsc(void) { uint32_t lo, hi; __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); return ((uint64_t)hi << 32) | lo; } + +static inline void cpuid(uint32_t leaf, uint32_t subleaf, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ + __asm__ __volatile__("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "a"(leaf), "c"(subleaf)); +} #endif diff --git a/src/arch/x86_64/cpuid.c b/src/arch/x86_64/cpuid.c index 62bdd1ba3..102bc0f15 100644 --- a/src/arch/x86_64/cpuid.c +++ b/src/arch/x86_64/cpuid.c @@ -108,11 +108,6 @@ extern uint64_t tsc_hz; static const char brand_string[48] = "Trustworthy Systems CPU"; -static inline void cpuid(uint32_t leaf, uint32_t subleaf, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) -{ - __asm__ __volatile__("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "a"(leaf), "c"(subleaf)); -} - bool emulate_cpuid(seL4_VCPUContext *vctx) { LOG_FAULT("handling CPUID 0x%x\n", vctx->eax); diff --git a/src/arch/x86_64/tsc.c b/src/arch/x86_64/tsc.c new file mode 100644 index 000000000..7fa0ff057 --- /dev/null +++ b/src/arch/x86_64/tsc.c @@ -0,0 +1,137 @@ +/* + * Copyright 2026, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Uncomment this to enable debug logging */ +#define DEBUG_TSC + +#if defined(DEBUG_TSC) +#define LOG_TSC(...) do{ printf("%s|TSC: ", microkit_name); printf(__VA_ARGS__); } while(0) +#else +#define LOG_TSC(...) do{}while(0) +#endif + +/* Documents referenced: + * 1. Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 + * Order Number: 325462-080US June 2023 + * 2. Linux v6.17 source: native_calibrate_tsc() arch/x86/kernel/tsc.c + */ + +/* CPUID related definitions for TSC detection. */ + +/* [1] "Vendor Identification String" page "3-240 Vol. 2A" */ +#define CPUID_VENDOR_ID_LEAF 0x0 + +/* [1] "Time Stamp Counter and Nominal Core Crystal Clock Information Leaf" page "Vol. 2A 3-231" */ +#define CPUID_TSC_LEAF 0x15 + +/* [1] "Processor Frequency Information Leaf" page "3-232 Vol. 2A" */ +#define CPUID_PROC_FREQ_LEAF 0x16 + +/* [1] "Maximum Input Value for Extended Function CPUID Information." page "Vol. 2A 3-245" */ +#define CPUID_MAX_EXT_LEAF 0x80000000 + +/* [1] "Invariant TSC available if 1" page "Vol. 2A 3-239" */ +#define CPUID_INVARIANT_TSC_LEAF 0x80000007 +#define CPUID_INVARIANT_TSC_EDX_BIT 8 + +static bool is_intel_cpu(void) +{ + uint32_t a, b, c, d; + cpuid(CPUID_VENDOR_ID_LEAF, 0, &a, &b, &c, &d); + return b == CPUID_0H_GENUINEINTEL_EBX && d == CPUID_0H_GENUINEINTEL_EDX && c == CPUID_0H_GENUINEINTEL_ECX; +} + +static uint64_t get_tsc_frequency(void) +{ + uint32_t max_basic_leaf, b, c, d; + /* Checks whether the CPU expose TSC/Crystal ratio and Crystal frequency via cpuid leaf 0x15. */ + cpuid(CPUID_VENDOR_ID_LEAF, 0, &max_basic_leaf, &b, &c, &d); + if (max_basic_leaf < CPUID_TSC_LEAF) { + LOG_TSC("CPU does not expose TSC leaf.\n"); + return 0; + } + + uint32_t denominator, numerator, crystal_khz; + cpuid(CPUID_TSC_LEAF, 0, &denominator, &numerator, &crystal_khz, &d); + if (!denominator || !numerator) { + LOG_TSC("TSC/Crystal ratio cannot be calculated.\n"); + return 0; + } + + uint32_t crystal_hz; + if (!crystal_khz) { + LOG_TSC("CPU does not report Crystal frequency, deriving...\n"); + + /* From [2]: "Some Intel SoCs like Skylake and Kabylake don't report the crystal + * clock, but we can easily calculate it to a high degree of accuracy + * by considering the crystal ratio and the CPU speed." */ + if (max_basic_leaf < CPUID_PROC_FREQ_LEAF) { + return 0; + } + + uint32_t proc_base_mhz; + cpuid(CPUID_PROC_FREQ_LEAF, 0, &proc_base_mhz, &b, &c, &d); + crystal_hz = proc_base_mhz * 1000 * 1000 * (denominator / (double)numerator); + + LOG_TSC("Processor base speed is %u MHz\n", proc_base_mhz); + LOG_TSC("Crystal clock is %u Hz\n", crystal_hz); + } else { + crystal_hz = crystal_khz * 1000; + } + + /* From [1]: + * EAX: denominator of the TSC/”core crystal clock” ratio. + * EBX: numerator of the TSC/”core crystal clock” ratio. + * ECX: nominal frequency of the core crystal clock in Hz. + * So “TSC frequency” = “core crystal clock frequency” * EBX/EAX. + */ + + uint64_t tsc_hz = (uint64_t)crystal_hz * (numerator / (double)denominator); + LOG_TSC("TSC frequency is %u * (%u / %u) = %lu Hz\n", crystal_hz, numerator, denominator, tsc_hz); + return tsc_hz; +} + +static uint64_t measure_tsc_frequency(microkit_channel timer_ch) +{ + /* Measure TSC frequency */ + uint64_t unused, tsc_pre, tsc_post; + // @billn hack + tsc_pre = rdtsc(); + sddf_timer_set_timeout(timer_ch, NS_IN_S); + seL4_Wait(BASE_ENDPOINT_CAP + timer_ch, &unused); + tsc_post = rdtsc(); + + uint64_t tsc_hz = tsc_post - tsc_pre; + return tsc_hz; +} + +x86_host_tsc_t get_host_tsc(microkit_channel timer_ch) +{ + x86_host_tsc_t tsc_metadata = { + .valid = true, + .invariant = false, + .freq_hz = 0, + }; + + tsc_metadata.freq_hz = measure_tsc_frequency(timer_ch); + if (tsc_metadata.freq_hz == 0) { + tsc_metadata.valid = false; + } else { + LOG_TSC("TSC frequency: %llu Hz\n", tsc_metadata.freq_hz); + } + + tsc_metadata.invariant = true; + + return tsc_metadata; +} \ No newline at end of file diff --git a/vmm.mk b/vmm.mk index bb1cb3b01..0c3b2492e 100644 --- a/vmm.mk +++ b/vmm.mk @@ -39,7 +39,8 @@ X86_64_FILES = src/arch/x86_64/fault.c \ src/arch/x86_64/pci.c \ src/arch/x86_64/util.c \ src/arch/x86_64/cmos.c \ - src/arch/x86_64/com.c + src/arch/x86_64/com.c \ + src/arch/x86_64/tsc.c # VIRTIO MMIO and PCI depends on sddf ifeq ($(strip $(SDDF)),) From 92f23da290a381b426f53b71ea290e275428d0da Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 26 Mar 2026 14:40:22 +1100 Subject: [PATCH 06/42] x86_64: package DSDT AML with asm script Rather than hackily including the C header emitted by the AML compiler. Signed-off-by: Bill Nguyen --- examples/simple/simple.mk | 2 ++ examples/simple/vmm_x86_64.c | 19 +++++++++---------- tools/package_guest_images.S | 8 ++++++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/simple/simple.mk b/examples/simple/simple.mk index 1987dd610..32aa508e7 100644 --- a/examples/simple/simple.mk +++ b/examples/simple/simple.mk @@ -29,6 +29,7 @@ ifeq ($(ARCH),aarch64) else ifeq ($(ARCH),x86_64) LINUX ?= be4206493bcc7234a8713319b7c6280fa04f9c5a-bzImage INITRD ?= d887a642236a92610a9537ab9f4a4aa1a966ad3a-rootfs.cpio.gz + DSDT_AML ?= $(SYSTEM_DIR)/simple_dsdt.aml ARCH_FLAGS := -target x86_64-unknown-elf VMM_NAME := vmm_x86_64 IMAGES = $(VMM_NAME).elf timer_driver.elf @@ -104,6 +105,7 @@ images.o: $(LIBVMM)/tools/package_guest_images.S $(LINUX) $(INITRD) $(CC) -c -g3 -x assembler-with-cpp \ -DGUEST_KERNEL_IMAGE_PATH=\"${LINUX}\" \ -DGUEST_INITRD_IMAGE_PATH=\"${INITRD}\" \ + -DGUEST_DSDT_AML_PATH=\"${DSDT_AML}\" \ $(ARCH_FLAGS) \ $(LIBVMM)/tools/package_guest_images.S -o $@ else diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c index 1cf32ec06..09aac67bc 100644 --- a/examples/simple/vmm_x86_64.c +++ b/examples/simple/vmm_x86_64.c @@ -8,18 +8,12 @@ #include #include #include - #include -// @billn sus, use package asm script -#include "board/x86_64_generic_vtx/simple_dsdt.hex" - uint64_t com1_ioport_id; uint64_t com1_ioport_addr; uint64_t com1_ioport_size = 8; -#define COM1_IRQ_CH 0 - #define GUEST_CMDLINE "earlyprintk=serial,0x3f8,115200 debug console=ttyS0,115200 earlycon=serial,0x3f8,115200 loglevel=8" /* Data for the guest's kernel image. */ @@ -28,6 +22,10 @@ extern char _guest_kernel_image_end[]; /* Data for the initial RAM disk to be passed to the kernel. */ extern char _guest_initrd_image[]; extern char _guest_initrd_image_end[]; +/* Data for the guest's ACPI Differentiated System Description Table (DSDT). */ +extern char _guest_dsdt_aml[]; +extern char _guest_dsdt_aml_end[]; + /* Microkit will set this variable to the start of the guest RAM memory region. */ uintptr_t guest_ram_vaddr; uint64_t guest_ram_size; @@ -58,10 +56,11 @@ void init(void) /* Place all the binaries in the right locations before starting the guest */ size_t kernel_size = _guest_kernel_image_end - _guest_kernel_image; size_t initrd_size = _guest_initrd_image_end - _guest_initrd_image; + size_t dsdt_aml_size = _guest_dsdt_aml_end - _guest_dsdt_aml; if (!linux_setup_images(guest_ram_vaddr, guest_ram_size, (uintptr_t)_guest_kernel_image, kernel_size, - (uintptr_t)_guest_initrd_image, initrd_size, simple_dsdt_aml_code, - sizeof(simple_dsdt_aml_code), GUEST_CMDLINE, &linux_setup)) { + (uintptr_t)_guest_initrd_image, initrd_size, _guest_dsdt_aml, dsdt_aml_size, GUEST_CMDLINE, + &linux_setup)) { LOG_VMM_ERR("Failed to initialise guest images\n"); return; } @@ -73,7 +72,7 @@ void init(void) /* Pass through COM1 serial port */ microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, com1_ioport_id, com1_ioport_addr, com1_ioport_size); - microkit_irq_ack(COM1_IRQ_CH); + microkit_irq_ack(com1_ioport_id); /* Retrieve the TSC frequency from hardware */ x86_host_tsc_t tsc_metadata = get_host_tsc(TIMER_DRV_CH_FOR_LAPIC); @@ -90,7 +89,7 @@ void init(void) } /* Pass through serial IRQs */ - assert(virq_ioapic_register_passthrough(0, 4, COM1_IRQ_CH)); + assert(virq_ioapic_register_passthrough(0, 4, com1_ioport_id)); guest_start(linux_setup.kernel_entry_gpa, 0, 0); } diff --git a/tools/package_guest_images.S b/tools/package_guest_images.S index 702ac7905..7755e7fde 100644 --- a/tools/package_guest_images.S +++ b/tools/package_guest_images.S @@ -43,3 +43,11 @@ _guest_initrd_image: .incbin GUEST_INITRD_IMAGE_PATH _guest_initrd_image_end: #endif + +#if defined(GUEST_DSDT_AML_PATH) +.section .guest_dsdt_aml, "aw", @progbits +.global _guest_dsdt_aml, _guest_dsdt_aml_end +_guest_dsdt_aml: +.incbin GUEST_DSDT_AML_PATH +_guest_dsdt_aml_end: +#endif From dfc5a85108a4d54bc6738b6605719f21d8e40399 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 26 Mar 2026 14:48:00 +1100 Subject: [PATCH 07/42] x86_64: Removed VCPU resume hack, used proper API Signed-off-by: Bill Nguyen --- examples/simple/vmm_x86_64.c | 16 ++++++++++++++ src/guest.c | 41 ++---------------------------------- 2 files changed, 18 insertions(+), 39 deletions(-) diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c index 09aac67bc..b49e6baf1 100644 --- a/examples/simple/vmm_x86_64.c +++ b/examples/simple/vmm_x86_64.c @@ -112,3 +112,19 @@ void notified(microkit_channel ch) }; } } + +/* + * The primary purpose of the VMM after initialisation is to act as a fault-handler. + * Whenever our guest causes an exception, it gets delivered to this entry point for + * the VMM to handle. + */ +seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) +{ + uint64_t new_rip; + bool success = fault_handle(child, &new_rip); + if (success) { + microkit_vcpu_x86_deferred_resume(new_rip, VMCS_PCC_DEFAULT, 0); + } + + return seL4_True; +} diff --git a/src/guest.c b/src/guest.c index 89e54db45..0e2aa55a8 100644 --- a/src/guest.c +++ b/src/guest.c @@ -82,46 +82,9 @@ bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) microkit_vcpu_restart(GUEST_BOOT_VCPU_ID, kernel_pc); #elif defined(CONFIG_ARCH_X86_64) - LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", kernel_pc, dtb, initrd); - - microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, kernel_pc); - microkit_mr_set(SEL4_VMENTER_CALL_CONTROL_PPC_MR, VMCS_PCC_DEFAULT); - microkit_mr_set(SEL4_VMENTER_CALL_INTERRUPT_INFO_MR, 0); - - while (true) { - seL4_Word badge; - seL4_Word ret = seL4_VMEnter(&badge); - - if (ret == SEL4_VMENTER_RESULT_NOTIF) { - // @billn refactor - uint64_t rip = microkit_mr_get(SEL4_VMENTER_CALL_EIP_MR); + LOG_VMM("starting guest at 0x%lx, initial RAM disk at 0x%lx\n", kernel_pc, dtb); + microkit_vcpu_x86_deferred_resume(kernel_pc, VMCS_PCC_DEFAULT, 0); - // @billn highly fucking sus, need to incorporate vmenter into the microkit event loop - uint64_t is_endpoint = badge >> 63; - uint64_t is_fault = (badge >> 62) & 1; - - assert(!is_endpoint); - assert(!is_fault); - - unsigned int idx = 0; - do { - if (badge & 1) { - notified(idx); - } - badge >>= 1; - idx++; - } while (badge != 0); - - microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, rip); - } else if (ret == SEL4_VMENTER_RESULT_FAULT) { - uint64_t new_rip; - assert(fault_handle(GUEST_BOOT_VCPU_ID, &new_rip)); - microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, new_rip); - } else { - LOG_VMM_ERR("unexpected VM exit reason 0x%x\n", ret); - } - } - LOG_VMM("done\n"); #endif return true; From 58245017906bac54d9d808ae9b9b214e6ce89b8d Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 26 Mar 2026 15:00:24 +1100 Subject: [PATCH 08/42] x86_64: removed COM+CMOS emulation from initial PR As it is not needed to boot bare Linux and Buildroot. Signed-off-by: Bill Nguyen --- build.zig | 1 - .../board/x86_64_generic_vtx/simple.system | 9 +- include/libvmm/arch/x86_64/cmos.h | 13 -- include/libvmm/libvmm.h | 1 - src/arch/x86_64/cmos.c | 122 ------------------ src/arch/x86_64/com.c | 93 ------------- src/arch/x86_64/ioports.c | 20 +-- vmm.mk | 2 - 8 files changed, 5 insertions(+), 256 deletions(-) delete mode 100644 include/libvmm/arch/x86_64/cmos.h delete mode 100644 src/arch/x86_64/cmos.c delete mode 100644 src/arch/x86_64/com.c diff --git a/build.zig b/build.zig index 959b6e371..2b3c50c9e 100644 --- a/build.zig +++ b/build.zig @@ -48,7 +48,6 @@ const src_x86_64 = [_][]const u8{ "src/arch/x86_64/pci.c", "src/arch/x86_64/ioports.c", "src/arch/x86_64/util.c", - "src/arch/x86_64/cmos.c", "src/arch/x86_64/com.c", }; diff --git a/examples/simple/board/x86_64_generic_vtx/simple.system b/examples/simple/board/x86_64_generic_vtx/simple.system index f53be8a61..4b34def4d 100644 --- a/examples/simple/board/x86_64_generic_vtx/simple.system +++ b/examples/simple/board/x86_64_generic_vtx/simple.system @@ -19,19 +19,18 @@ + - + - - - - + + diff --git a/include/libvmm/arch/x86_64/cmos.h b/include/libvmm/arch/x86_64/cmos.h deleted file mode 100644 index 1b9c04ddd..000000000 --- a/include/libvmm/arch/x86_64/cmos.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2025, UNSW - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -bool emulate_cmos_access(seL4_VCPUContext *vctx, uint16_t port_addr, bool is_read, ioport_access_width_t access_width); \ No newline at end of file diff --git a/include/libvmm/libvmm.h b/include/libvmm/libvmm.h index dcffb1a82..15846df36 100644 --- a/include/libvmm/libvmm.h +++ b/include/libvmm/libvmm.h @@ -26,7 +26,6 @@ #elif defined(CONFIG_ARCH_X86) #include #include -#include #include #include #include diff --git a/src/arch/x86_64/cmos.c b/src/arch/x86_64/cmos.c deleted file mode 100644 index 7507280ab..000000000 --- a/src/arch/x86_64/cmos.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2025, UNSW - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include - -// @billn hack, there should be a `init_cmos()` call that either pass or not pass the real CMOS -#define CMOS_ADDR_PORT_ID 36 -#define CMOS_DATA_PORT_ID 37 - -// Emulates enough of the CMOS and Real-Time Clock (RTC) needed for OVMF UEFI firmware. -// https://wiki.osdev.org/CMOS -// https://www.ti.com/lit/ds/symlink/bq3285.pdf?ts=1767742813264&ref_url=https%253A%252F%252Fwww.google.com%252F - -/* Uncomment this to enable debug logging */ -// #define DEBUG_CMOS - -#if defined(DEBUG_CMOS) -#define LOG_CMOS(...) do{ printf("%s|CMOS: ", microkit_name); printf(__VA_ARGS__); }while(0) -#else -#define LOG_CMOS(...) do{}while(0) -#endif - -#define STATUS_REG_A 0xa -#define STATUS_REG_B 0xb -#define STATUS_REG_C 0xc -#define STATUS_REG_D 0xd - -struct cmos_regs { - uint8_t selected_reg; - uint8_t status_registers[4]; // status regs A/B/C/D -}; - -static struct cmos_regs cmos_regs = { - .status_registers[3] = 0x80 // VRT bit set meaning device OK. -}; - -bool emulate_cmos_access(seL4_VCPUContext *vctx, uint16_t port_addr, bool is_read, ioport_access_width_t access_width) -{ - assert(access_width == IOPORT_BYTE_ACCESS_QUAL); - - if (port_addr == 0x70) { - if (is_read) { - vctx->eax = microkit_x86_ioport_read_8(CMOS_ADDR_PORT_ID, 0x70); - } else { - cmos_regs.selected_reg = vctx->eax & 0x7f; - microkit_x86_ioport_write_8(CMOS_ADDR_PORT_ID, 0x70, vctx->eax); - LOG_CMOS("selecting register 0x%x\n", cmos_regs.selected_reg); - } - } else if (port_addr == 0x71) { - if (is_read) { - if (cmos_regs.selected_reg > 0xd) { - vctx->eax = 0; - } else { - vctx->eax = microkit_x86_ioport_read_8(CMOS_DATA_PORT_ID, 0x71); - } - } else { - microkit_x86_ioport_write_8(CMOS_DATA_PORT_ID, 0x71, vctx->eax); - } - } - - return true; - - // if (port_addr == 0x70) { - // if (is_read) { - // vctx->eax = cmos_regs.selected_reg; - // } else { - // cmos_regs.selected_reg = vctx->eax & 0x7f; - // } - // } else if (port_addr == 0x71) { - // if (is_read) { - // LOG_CMOS("reading CMOS register 0x%x\n", cmos_regs.selected_reg); - // switch (cmos_regs.selected_reg) { - // case STATUS_REG_A: - // vctx->eax = cmos_regs.status_registers[0]; - // break; - // case STATUS_REG_B: - // vctx->eax = cmos_regs.status_registers[1]; - // break; - // case STATUS_REG_C: - // vctx->eax = cmos_regs.status_registers[2]; - // // whenever this register is read it is cleared - // cmos_regs.status_registers[2] = 0; - // break; - // case STATUS_REG_D: - // vctx->eax = cmos_regs.status_registers[3]; - // break; - // } - // } else { - // LOG_CMOS("writing CMOS register 0x%x, value 0x%x\n", cmos_regs.selected_reg, vctx->eax); - // switch (cmos_regs.selected_reg) { - // case STATUS_REG_A: - // cmos_regs.status_registers[0] = vctx->eax; - - // // uint8_t freq_select = cmos_regs.status_registers[0] & 0xf; - // // uint8_t oscillator_ctl = (cmos_regs.status_registers[0] >> 4) & 0x7; - - // break; - // case STATUS_REG_B: - // cmos_regs.status_registers[1] = vctx->eax; - // break; - // case STATUS_REG_C: - // cmos_regs.status_registers[2] = vctx->eax; - // break; - // case STATUS_REG_D: - // // cmos_regs.status_registers[3] = vctx->eax; - // break; - // } - // } - - // } else { - // LOG_VMM_ERR("emulate_cmos_access() called with unknown port address 0x%x\n", port_addr); - // return false; - // } - - // return true; -} \ No newline at end of file diff --git a/src/arch/x86_64/com.c b/src/arch/x86_64/com.c deleted file mode 100644 index e2efad6d4..000000000 --- a/src/arch/x86_64/com.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2026, UNSW - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include - -static uint8_t com_scratch[5]; - -void emulate_com(seL4_VCPUContext *vctx, size_t idx, size_t reg_offset, bool is_read, bool is_rep, bool is_string, - ioport_access_width_t access_width) -{ - // LOG_VMM("com port %d, reg_offset %d, is_read %d\n", idx, reg_offset, is_read); - - // TODO: sort this out - char buf[100]; - size_t string_bytes_written; - if (is_string) { - assert(reg_offset == 0x0 && !is_read); - - string_bytes_written = emulate_ioport_string_write(vctx, buf, 100, is_rep, access_width); - } - - assert(idx < sizeof(com_scratch) / sizeof(uint8_t)); - switch (reg_offset) { - case 0x7: { - if (is_read) { - vctx->eax = com_scratch[idx]; - } else { - com_scratch[idx] = vctx->eax; - } - break; - } - case 0x0: { - // com2 FIFO - if (is_read) { - vctx->eax = 0; - } else { - // LOG_VMM("com2 out: %c\n", vctx->eax); - if (is_string) { - for (int i = 0; i < string_bytes_written; i++) { - microkit_dbg_putc(buf[i]); - } - } else { - microkit_dbg_putc(vctx->eax); - } - } - break; - } - case 0x4: - // Modem Control Register - break; - case 0x2: { - if (is_read) { - // Interrupt Identification Register - vctx->eax = 0; - } else { - // First In First Out Control Register - // LOG_VMM("FIFO write %x\n", vctx->eax); - } - break; - } - case 0x5: { - // Line Status Register - if (is_read) { - vctx->eax = BIT(5) | BIT(6); - } else { - assert(false); - } - break; - } - case 0x3: { - // Line Control Register - if (is_read) { - vctx->eax = BIT(7); - } else { - // LOG_VMM("LCR write %x\n", vctx->eax); - } - break; - } - case 0x6: - // Modem Status Register - break; - default: - // LOG_VMM_ERR("unknown COM offset 0%lx\n", reg_offset); - break; - } -} diff --git a/src/arch/x86_64/ioports.c b/src/arch/x86_64/ioports.c index b111a0769..9edf2113d 100644 --- a/src/arch/x86_64/ioports.c +++ b/src/arch/x86_64/ioports.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -118,9 +117,7 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) { uint64_t is_read = f_qualification & BIT(3); uint64_t is_string = f_qualification & BIT(4); - uint64_t is_rep = f_qualification & BIT(5); uint16_t port_addr = (f_qualification >> 16) & 0xffff; - ioport_access_width_t access_width = (ioport_access_width_t)(f_qualification & 0x7); bool success = false; @@ -148,7 +145,7 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) } else if (port_addr == 0x70 || port_addr == 0x71) { // cmos assert(!is_string); - success = emulate_cmos_access(vctx, port_addr, is_read, access_width); + success = true; } else if (port_addr == 0x80) { assert(!is_string); // io port access delay, no-op @@ -192,21 +189,6 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) // TODO: handle properly, I don't understand why UEFI is touching A20 gate register assert(!is_string); success = true; - } else if (port_addr >= 0x3f8 && port_addr <= 0x3f8 + 8) { - emulate_com(vctx, 0, port_addr - 0x3f8, is_read, is_rep, is_string, access_width); - success = true; - } else if (port_addr >= 0x2f8 && port_addr <= 0x2f8 + 8) { - emulate_com(vctx, 1, port_addr - 0x2f8, is_read, is_rep, is_string, access_width); - success = true; - } else if (port_addr >= 0x3e8 && port_addr <= 0x3e8 + 8) { - emulate_com(vctx, 2, port_addr - 0x3e8, is_read, is_rep, is_string, access_width); - success = true; - } else if (port_addr >= 0x2ef && port_addr <= 0x2ef + 8) { - emulate_com(vctx, 3, port_addr - 0x2ef, is_read, is_rep, is_string, access_width); - success = true; - } else if (port_addr >= 0x2e8 && port_addr <= 0x2e8 + 8) { - emulate_com(vctx, 4, port_addr - 0x2e8, is_read, is_rep, is_string, access_width); - success = true; } else if (port_addr == 0xb004) { vctx->eax = 0; success = true; diff --git a/vmm.mk b/vmm.mk index 0c3b2492e..58ee44756 100644 --- a/vmm.mk +++ b/vmm.mk @@ -38,8 +38,6 @@ X86_64_FILES = src/arch/x86_64/fault.c \ src/arch/x86_64/hpet.c \ src/arch/x86_64/pci.c \ src/arch/x86_64/util.c \ - src/arch/x86_64/cmos.c \ - src/arch/x86_64/com.c \ src/arch/x86_64/tsc.c # VIRTIO MMIO and PCI depends on sddf From 752e84abf78db772f1335c446179ce3c7201323b Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 26 Mar 2026 15:07:50 +1100 Subject: [PATCH 09/42] x86_64: Enabled HPET bug check, removed dead code Signed-off-by: Bill Nguyen --- src/arch/x86_64/acpi.c | 33 +-------- src/arch/x86_64/apic.c | 40 ++--------- src/arch/x86_64/fault.c | 132 +--------------------------------- src/arch/x86_64/hpet.c | 18 +---- src/arch/x86_64/instruction.c | 8 +-- src/arch/x86_64/msr.c | 4 -- 6 files changed, 14 insertions(+), 221 deletions(-) diff --git a/src/arch/x86_64/acpi.c b/src/arch/x86_64/acpi.c index dcb985002..bc2867633 100644 --- a/src/arch/x86_64/acpi.c +++ b/src/arch/x86_64/acpi.c @@ -50,23 +50,10 @@ static uint8_t acpi_compute_checksum(char *table, int size) return 0x100 - acpi_table_sum(table, size); } -// TODO: when creating MADT, get the user to pass the address of APIC that is definitely -// outside of RAM, or determine it ourselves. - -// static void madt_add_entry(struct madt *madt, uintptr_t dest, void *entry) -// { -// struct madt_irq_controller *madt_entry = (struct madt_irq_controller *)entry; - -// madt->h.length += madt_entry->length; - -// memcpy((void *)dest, entry, madt_entry->length); -// } - size_t madt_build(struct madt *madt) { memcpy(madt->h.signature, "APIC", 4); madt->h.revision = MADT_REVISION; - // TODO: not very elegant, maybe do something better. memcpy(madt->h.oem_id, ACPI_OEMID, 6); memcpy(madt->h.oem_table_id, ACPI_OEMID, 6); madt->h.oem_revision = 1; @@ -181,8 +168,6 @@ bool pm1a_cnt_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qual { uint64_t is_read = qualification & BIT(3); uint64_t is_string = qualification & BIT(4); - // TODO: handle unused variable - // uint16_t port_addr = (qualification >> 16) & 0xffff; ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); int access_width_bytes = ioports_access_width_to_bytes(access_width); assert(!is_string); @@ -190,11 +175,9 @@ bool pm1a_cnt_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qual if (port_offset == 0) { if (is_read) { - // LOG_VMM("PM1 control reg read 0x%x\n", pm1_control_reg); vctx->eax = pm1_control_reg; } else { pm1_control_reg = vctx->eax & 0xffff; - // LOG_VMM("PM1 control reg write 0x%x\n", pm1_control_reg); } } else { @@ -209,8 +192,6 @@ bool pm1a_evt_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qual { uint64_t is_read = qualification & BIT(3); uint64_t is_string = qualification & BIT(4); - // TODO: handle unused variable - // uint16_t port_addr = (qualification >> 16) & 0xffff; ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); int access_width_bytes = ioports_access_width_to_bytes(access_width); assert(!is_string); @@ -245,8 +226,6 @@ bool pm_timer_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t qual { uint64_t is_read = qualification & BIT(3); uint64_t is_string = qualification & BIT(4); - // TODO: handle unused variable - // uint16_t port_addr = (qualification >> 16) & 0xffff; ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); int access_width_bytes = ioports_access_width_to_bytes(access_width); assert(!is_string); @@ -265,8 +244,6 @@ bool smi_cmd_pio_fault_handle(size_t vcpu_id, uint16_t port_offset, size_t quali { uint64_t is_read = qualification & BIT(3); uint64_t is_string = qualification & BIT(4); - // TODO: handle unused variable - // uint16_t port_addr = (qualification >> 16) & 0xffff; ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); int access_width_bytes = ioports_access_width_to_bytes(access_width); assert(!is_string); @@ -404,7 +381,6 @@ size_t xsdt_build(struct xsdt *xsdt, uint64_t *table_ptrs, size_t num_table_ptrs xsdt->h.length = length; xsdt->h.revision = XSDP_REVISION; - // TODO: not very elegant, maybe do something better. memcpy(xsdt->h.oem_id, ACPI_OEMID, 6); memcpy(xsdt->h.oem_table_id, ACPI_OEMID, 6); xsdt->h.oem_revision = 1; @@ -427,8 +403,6 @@ size_t xsdt_build(struct xsdt *xsdt, uint64_t *table_ptrs, size_t num_table_ptrs size_t xsdp_build(struct xsdp *xsdp, uint64_t xsdt_gpa) { memset(xsdp, 0, sizeof(struct xsdp)); - - // memcpy as we do not want to null-termiante memcpy(xsdp->signature, XSDP_SIGNATURE, strlen(XSDP_SIGNATURE)); memcpy(xsdp->oem_id, ACPI_OEMID, strlen(ACPI_OEMID)); xsdp->revision = XSDP_REVISION; @@ -436,10 +410,6 @@ size_t xsdp_build(struct xsdp *xsdp, uint64_t xsdt_gpa) xsdp->xsdt_gpa = xsdt_gpa; - // // @billn sus - // assert(xsdt_gpa < (1ull << 32)); - // xsdp->rsdp_gpa = xsdt_gpa; - xsdp->checksum = acpi_compute_checksum((char *)xsdp, offsetof(struct xsdp, length)); assert(acpi_checksum_ok((char *)xsdp, offsetof(struct xsdp, length))); xsdp->ext_checksum = acpi_compute_checksum((char *)xsdp, sizeof(struct xsdp)); @@ -474,13 +444,12 @@ uint64_t acpi_build_all(uintptr_t guest_ram_vaddr, void *dsdt_blob, uint64_t dsd uint64_t xsdt_gpa = acpi_allocate_gpa(sizeof(struct xsdt)); xsdp_build(xsdp, xsdt_gpa); - // TODO: hack uint64_t madt_gpa = acpi_allocate_gpa(sizeof(struct madt)); struct madt *madt = (struct madt *)(guest_ram_vaddr + madt_gpa); madt_build(madt); + // TODO: hack assert(madt->h.length <= 0x1000); - // @billn todo really need some sort of memory range allocator uint64_t hpet_gpa = acpi_allocate_gpa(sizeof(struct hpet)); struct hpet *hpet = (struct hpet *)(guest_ram_vaddr + hpet_gpa); hpet_build(hpet); diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index 7ed995e7a..86d50a277 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -23,22 +23,21 @@ // @billn the APIC timer doesn't need to be tied to the TSC, I did it like this originally because // I didn't know anything about x86 architecture. But for simplicity it could be tied to the sDDF timer -// instead. +// instead. The only case where the TSC comes into play is the TSC deadline mode, but we don't support right now +// Documents referenced: // https://wiki.osdev.org/APIC +// https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf -/* Uncomment this to enable debug logging */ +// Uncomment this to enable debug logging // #define DEBUG_APIC -extern bool fault_cond; - #if defined(DEBUG_APIC) #define LOG_APIC(...) do{ printf("%s|APIC: ", microkit_name); printf(__VA_ARGS__); }while(0) #else #define LOG_APIC(...) do{}while(0) #endif -// https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf extern uintptr_t vapic_vaddr; extern struct ioapic_regs ioapic_regs; extern uint64_t tsc_hz; @@ -96,19 +95,6 @@ void vapic_write_reg(int offset, uint32_t value) *reg = value; } -bool vcpu_can_take_irq(size_t vcpu_id) -{ - // Not executing anything that blocks IRQs - if (microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_INTERRUPTABILITY) != 0) { - return false; - } - // IRQ on in cpu register - if (!(microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_RFLAGS) & BIT(9))) { - return false; - } - return true; -} - int lapic_dcr_to_divider(void) { // Figure 11-10. Divide Configuration Register @@ -256,15 +242,11 @@ bool lapic_write_fault_handle(uint64_t offset, uint32_t data) if (!inject_lapic_irq(GUEST_BOOT_VCPU_ID, vector)) { LOG_VMM_ERR("failed to send IPI\n"); return false; - } else { - // LOG_VMM("sent ipi\n"); } } else { LOG_VMM_ERR("LAPIC received requuest to send IPI of unknown delivery mode 0x%x, destination 0x%x\n", delivery_mode, destination); } - - // LOG_VMM("icr write 0x%lx, current TPL is 0x%x\n", icr, vapic_read_reg(REG_LAPIC_TPR)); break; } @@ -300,9 +282,6 @@ bool ioapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qual int redirection_reg_idx = ((ioapic_regs.selected_reg - REG_IOAPIC_IOREDTBL_FIRST_OFF) & ~((uint64_t)1)) / 2; int is_high = ioapic_regs.selected_reg & 0x1; - - // LOG_VMM("reading indirect register 0x%x, is high %d\n", redirection_reg_idx, is_high); - if (is_high) { data = ioapic_regs.ioredtbl[redirection_reg_idx] >> 32; } else { @@ -325,7 +304,6 @@ bool ioapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qual if (offset == REG_IOAPIC_IOREGSEL_MMIO_OFF) { ioapic_regs.selected_reg = data & 0xff; - // LOG_VMM("selecting I/O APIC register 0x%x for write\n", ioapic_regs.selected_reg); } else if (offset == REG_IOAPIC_IOWIN_MMIO_OFF) { if (ioapic_regs.selected_reg == REG_IOAPIC_IOAPICID_REG_OFF) { @@ -401,7 +379,7 @@ bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) // Mark as pending for injection, let hardware handle the rest vapic_write_reg(irr_reg_off, vapic_read_reg(irr_reg_off) | BIT(irr_idx)); - // page 26-8 Vol. 3C "Guest interrupt status" + // Intel manual page 26-8 Vol. 3C "Guest interrupt status" int highest_vector_pending = get_next_pending_irq_vector(); assert(highest_vector_pending != -1); uint16_t guest_irq_status = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_INTERRUPT_STATUS); @@ -433,7 +411,6 @@ bool handle_lapic_timer_nftn(size_t vcpu_id) if (!(timer_reg & BIT(16))) { uint8_t vector = timer_reg & 0xff; if (!inject_lapic_irq(vcpu_id, vector)) { - // LOG_VMM_ERR("failed to inject LAPIC timer IRQ vector 0x%x\n", vector); return false; } } @@ -456,10 +433,8 @@ bool inject_ioapic_irq(int ioapic, int pin) return false; } - // @billn sus - uint8_t delivery_mode = (ioapic_regs.ioredtbl[pin] >> 8) & 0x7; - // @billn sus revisit delivery mode 1 for multiple vcpu + uint8_t delivery_mode = (ioapic_regs.ioredtbl[pin] >> 8) & 0x7; if (delivery_mode != 0 && delivery_mode != 1) { LOG_VMM_ERR("unknown I/O APIC delivery mode for injection on pin %d, mode 0x%x\n", pin, delivery_mode); assert(false); @@ -474,7 +449,6 @@ bool inject_ioapic_irq(int ioapic, int pin) // For any passed through interrupts: // When the guest EOIs the interrupt, we must trigger a vmexit to run the ack func if (ioapic_regs.virq_passthrough_map[pin].valid) { - int eoi_bitmap_n = vector / 64; int n_bitmap_i = vector % 64; switch (eoi_bitmap_n) { @@ -504,7 +478,7 @@ bool inject_ioapic_irq(int ioapic, int pin) } } - // @billn need to read cpu id from redirection register + // @billn need to read cpu id from redirection register, revisit for multi vcpu return inject_lapic_irq(0, vector); } diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 02f367e00..e7f57723a 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -238,7 +238,6 @@ bool fault_register_ept_exception_handler(uintptr_t base, size_t size, ept_excep static bool handle_ept_fault(seL4_VCPUContext *vctx, seL4_Word qualification, decoded_instruction_ret_t decoded_ins) { uint64_t addr = microkit_mr_get(SEL4_VMENTER_FAULT_GUEST_PHYSICAL_MR); - // LOG_VMM("handling EPT fault on GPA 0x%lx, qualification: 0x%lx\n", addr, qualification); if (addr >= IOAPIC_GPA && addr < IOAPIC_GPA + IOAPIC_SIZE) { LOG_FAULT("handling IO APIC 0x%lx\n", addr); @@ -246,8 +245,6 @@ static bool handle_ept_fault(seL4_VCPUContext *vctx, seL4_Word qualification, de } else if (addr >= HPET_GPA && addr < HPET_GPA + HPET_SIZE) { LOG_FAULT("handling HPET 0x%lx\n", addr); return hpet_fault_handle(vctx, addr - HPET_GPA, qualification, decoded_ins); - // } else if (addr >= ECAM_GPA && addr < ECAM_GPA + ECAM_SIZE) { - // return pci_x86_emulate_ecam_access(vctx, addr - ECAM_GPA, qualification, decoded_mem_ins); } else { LOG_FAULT("handling other EPT 0x%lx\n", addr); for (int i = 0; i < MAX_EPT_EXCEPTION_HANDLERS; i++) { @@ -270,8 +267,6 @@ static bool handle_ept_fault(seL4_VCPUContext *vctx, seL4_Word qualification, de LOG_VMM_ERR("failed to find EPT handler for address 0x%lx\n", addr); } - // LOG_VMM("done\n"); - return false; } @@ -326,8 +321,6 @@ bool fault_register_pio_exception_handler(uint16_t base, uint16_t size, pio_exce static bool handle_pio_fault(seL4_VCPUContext *vctx, seL4_Word qualification) { uint16_t port_addr = (qualification >> 16) & 0xffff; - // TODO: pass access width to the callbacks? - // ioport_access_width_t access_width = (ioport_access_width_t)(qualification & 0x7); if (port_addr >= 0x3f8 && port_addr <= 0x3f8 + 8) { } else if (port_addr >= 0x2f8 && port_addr <= 0x2f8 + 8) { @@ -357,53 +350,6 @@ static bool handle_pio_fault(seL4_VCPUContext *vctx, seL4_Word qualification) return emulate_ioports(vctx, qualification); } -// static uint64_t prev_valid_idt_entries = 0; - -uint64_t *cr_fault_reg_idx_to_vctx_ptr(int idx, seL4_VCPUContext *vctx) -{ - switch (idx) { - case 0: - return &vctx->eax; - case 1: - return &vctx->ecx; - case 2: - return &vctx->edx; - case 3: - return &vctx->ebx; - // case 4: - // return stack pointer; - case 5: - return &vctx->ebp; - case 6: - return &vctx->esi; - case 7: - return &vctx->edi; - case 8: - return &vctx->r8; - case 9: - return &vctx->r9; - case 10: - return &vctx->r10; - case 11: - return &vctx->r11; - case 12: - return &vctx->r12; - case 13: - return &vctx->r13; - case 14: - return &vctx->r14; - case 15: - return &vctx->r15; - default: - return NULL; - } -} - -uint64_t n_faults = 0; -uint64_t n_vmexit_reasons[NUM_EXIT_REASONS] = { 0 }; - -uint64_t n_notifieds = 0; - bool fault_handle(size_t vcpu_id, uint64_t *new_rip) { bool success = false; @@ -414,13 +360,6 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) seL4_Word qualification = microkit_mr_get(SEL4_VMENTER_FAULT_QUALIFICATION_MR); seL4_Word rip = microkit_mr_get(SEL4_VMENTER_CALL_EIP_MR); - // if (rip > 0xfffff00000000000) { - // LOG_FAULT("vmm exit in kernel at rip 0x%lx\n", rip); - // fault_cond = true; - // } else { - // fault_cond = false; - // } - LOG_FAULT("handling vmexit reason %s\n", fault_to_string(f_reason)); seL4_VCPUContext vctx; @@ -461,7 +400,6 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) case IO: success = handle_pio_fault(&vctx, qualification); break; - // case APIC_ACCESS: case VIRTUALIZED_EOI: { uint8_t eoi_vector = qualification; // if we get here then the guest has ack'ed a passed through I/O APIC irq, @@ -484,9 +422,6 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) uint8_t access_type = (qualification >> 12) & 0xf; // only handle reads and writes due to instruciton execution - - // LOG_VMM("offset 0x%x, access type %d\n", offset, access_type); - if (access_type == 0) { uint32_t data; success = lapic_read_fault_handle(offset, &data); @@ -516,55 +451,9 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) LOG_VMM_ERR("unhandled fault: 0x%x\n", f_reason); }; - // n_vmexit_reasons[f_reason] += 1; - // n_faults += 1; - // if (n_faults % 50000 == 0) { - // LOG_VMM("vm exit stats:\n"); - // for (int i = 0; i < NUM_EXIT_REASONS; i++) { - // char *reason_human = fault_to_string(i); - // uint64_t n_fault = n_vmexit_reasons[i]; - // if (reason_human[0] != 0 && n_fault) { - // LOG_VMM("%s: %lu\n", reason_human, n_fault); - // } - // } - // LOG_VMM("number of notifieds: %lu\n", n_notifieds); - // } - *new_rip = rip; if (success && f_reason != INTERRUPT_WINDOW) { - // uint64_t cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); - // if (cr4 & BIT(18)) { - // LOG_VMM("======== HELLO OSXSAVE IS ON!!!!\n"); - // } - - // uint64_t idtr_gva = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_BASE); - // uint64_t idtr_limit = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_LIMIT); - // uint64_t idtr_gpa, _bytes_remaining; - // bool idtr_valid = gva_to_gpa(0, idtr_gva, &idtr_gpa, &_bytes_remaining); - // uint8_t idt_entry_size = guest_in_64_bits() ? 16 : 8; - // uint16_t idt_num_entries = (idtr_limit + 1) / idt_entry_size; - // uint16_t num_present_entries = 0; - // for (int i = 0; i < idt_num_entries; i++) { - // uint32_t entry[4]; - // uint64_t entry_gpa = idtr_gpa + (i * idt_entry_size); - // entry[0] = *((uint64_t *) gpa_to_vaddr(entry_gpa)); - // entry[1] = *((uint64_t *) gpa_to_vaddr(entry_gpa + 4)); - // entry[2] = *((uint64_t *) gpa_to_vaddr(entry_gpa + 8)); - // entry[3] = *((uint64_t *) gpa_to_vaddr(entry_gpa + 12)); - - // uint32_t present = (entry[1] & BIT(15)); - // if (present) - // num_present_entries++; - // } - - // if (num_present_entries != prev_valid_idt_entries) { - // LOG_VMM("+_+_+_+_+ IDT have %d valid entries\n", num_present_entries); - // LOG_VMM_ERR("IDTR gpa: 0x%lx\n", idtr_gpa); - // } - - // prev_valid_idt_entries = num_present_entries; - - // TODO hack force osxsave on so that windows doesnt #UD on xgetbv/xsetbv + // TODO hack force osxsave on so that Windows doesnt #UD on xgetbv/xsetbv uint64_t cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4, cr4 | BIT(18)); @@ -603,7 +492,6 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) entry[3] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 12)); uint32_t present = (entry[1] & BIT(15)); - // LOG_VMM("IDT entry %d is present: %s\n", i, present ? "YES" : "NO"); if (present) { idt_num_valid_entries += 1; } @@ -611,24 +499,6 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) LOG_VMM_ERR("IDTR num valid entries: %d\n", idt_num_valid_entries); } - // if (ins_len) { - // uint64_t gpa; - // int bytes_remaining; - // assert(gva_to_gpa(0, rip, &gpa, &bytes_remaining)); - // assert(bytes_remaining >= ins_len); - // LOG_VMM_ERR("faulting instruction:\n"); - // uint8_t *ins = gpa_to_vaddr(gpa); - // for (int i = 0; i < ins_len; i++) { - // LOG_VMM_ERR("0x%02x\n", ins[i]); - // bytes_remaining--; - // } - - // LOG_VMM_ERR("proceeding instructions:\n"); - // for (int i = 0; i < MIN(bytes_remaining, 16); i++) { - // LOG_VMM_ERR("0x%02x\n", ins[i + ins_len]); - // bytes_remaining--; - // } - // } vcpu_print_regs(vcpu_id); } diff --git a/src/arch/x86_64/hpet.c b/src/arch/x86_64/hpet.c index 83983b349..fc977cff2 100644 --- a/src/arch/x86_64/hpet.c +++ b/src/arch/x86_64/hpet.c @@ -224,8 +224,9 @@ bool bug_check_irq_at_correct_time(int comparator, uint64_t main_counter_val) } else { difference_units = main_counter_val - expected_counter_val; if (difference_units > tolerance_units) { - // LOG_VMM_ERR("HPET timer irq too late!!! comp %d, counter %lu, comparator %lu, diff %lu > margin %lu\n", comparator, - // main_counter_val, hpet_regs.comparators[comparator].armed_comparator, difference_units, tolerance_units); + LOG_VMM_ERR("HPET timer irq too late!!! comp %d, counter %lu, comparator %lu, diff %lu > margin %lu\n", + comparator, main_counter_val, hpet_regs.comparators[comparator].armed_comparator, + difference_units, tolerance_units); return false; } } @@ -430,7 +431,6 @@ static bool hpet_fault_handle_config_write(uint8_t comparator, uint64_t data, de bool periodic_old = timer_n_in_periodic_mode(comparator); struct comparator_regs *regs = &hpet_regs.comparators[comparator]; - // uint64_t reg_old = regs->config; if (mem_access_width_to_bytes(decoded_ins) == 4) { uint64_t curr_hi = (regs->config >> 32) << 32; @@ -486,18 +486,6 @@ static bool hpet_fault_handle_comparator_write(uint8_t comparator, uint64_t data bool hpet_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, decoded_instruction_ret_t decoded_ins) { - // if (ept_fault_is_read(qualification)) { - // assert(decoded_ins.type == INSTRUCTION_MEMORY); - // LOG_HPET("handling HPET read at offset 0x%lx, acc width %d bytes, reg idx %d\n", offset, - // mem_access_width_to_bytes(decoded_ins), decoded_ins.decoded.memory_instruction.target_reg); - // } else if (ept_fault_is_write(qualification)) { - // uint64_t data; - // assert(mem_write_get_data(decoded_ins, qualification, vctx, &data)); - // LOG_HPET("handling HPET write at offset 0x%lx, value 0x%x\n", offset, data); - // } - - // vcpu_print_regs(0); - uint8_t comparator; if (ept_fault_is_read(qualification)) { uint64_t data; diff --git a/src/arch/x86_64/instruction.c b/src/arch/x86_64/instruction.c index 997dc5e42..16e57e5c1 100644 --- a/src/arch/x86_64/instruction.c +++ b/src/arch/x86_64/instruction.c @@ -14,9 +14,10 @@ #include #include +// Documents referenced: // https://wiki.osdev.org/X86-64_Instruction_Encoding - // https://c9x.me/x86/html/file_module_x86_id_176.html + #define NUM_MOV_OPCODES 4 #define OPCODE_MOV_BYTE_TO_MEM 0x88 #define OPCODE_MOV_WORD_TO_MEM 0x89 @@ -400,10 +401,5 @@ decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4 vcpu_print_regs(0); assert(opcode_valid); } - - // LOG_VMM("raw instruction:\n"); - // for (int i = 0; i < instruction_len; i++) { - // LOG_VMM("[%d]: 0x%x\n", i, instruction_buf[i]); - // } return ret; } \ No newline at end of file diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index b7353f4b1..5b5fb411c 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -199,10 +199,6 @@ bool emulate_wrmsr(seL4_VCPUContext *vctx) case IA32_PAT: pat = value; break; - // case MSR_KVM_WALL_CLOCK_NEW: - // case MSR_KVM_SYSTEM_TIME_NEW: - // pvclock_write_fault_handle(MSR_KVM_SYSTEM_TIME_NEW, value); - // break; default: LOG_VMM("unknown wrmsr 0x%x, value 0x%lx\n", vctx->ecx, value); return false; From 58f9fe363102058637411cf7cf7627b44c99b4fb Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Fri, 27 Mar 2026 14:22:31 +1100 Subject: [PATCH 10/42] x86_64: resume VCPU in fault_handle instead of VMM To prevent cases where users forgets to in VMM, and so that the library have more control over fault handling. As in certain cases for certain VM exits, we must inject a fault into the VCPU. Signed-off-by: Bill Nguyen --- examples/simple/vmm_x86_64.c | 7 +------ include/libvmm/arch/x86_64/fault.h | 2 +- src/arch/x86_64/fault.c | 7 ++++--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c index b49e6baf1..f9582e8b0 100644 --- a/examples/simple/vmm_x86_64.c +++ b/examples/simple/vmm_x86_64.c @@ -120,11 +120,6 @@ void notified(microkit_channel ch) */ seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) { - uint64_t new_rip; - bool success = fault_handle(child, &new_rip); - if (success) { - microkit_vcpu_x86_deferred_resume(new_rip, VMCS_PCC_DEFAULT, 0); - } - + fault_handle(child); return seL4_True; } diff --git a/include/libvmm/arch/x86_64/fault.h b/include/libvmm/arch/x86_64/fault.h index 2f4b18b7d..31addf977 100644 --- a/include/libvmm/arch/x86_64/fault.h +++ b/include/libvmm/arch/x86_64/fault.h @@ -15,7 +15,7 @@ char *fault_to_string(int exit_reason); /* @billn revisit, seL4 vmexit doesnt have msginfo! */ -bool fault_handle(size_t vcpu_id, uint64_t *new_rip); +bool fault_handle(size_t vcpu_id); typedef bool (*ept_exception_callback_t)(size_t vcpu_id, size_t offset, size_t qualification, decoded_instruction_ret_t decoded_ins, seL4_VCPUContext *vctx, void *cookie); diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index e7f57723a..14767d340 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -350,7 +350,7 @@ static bool handle_pio_fault(seL4_VCPUContext *vctx, seL4_Word qualification) return emulate_ioports(vctx, qualification); } -bool fault_handle(size_t vcpu_id, uint64_t *new_rip) +bool fault_handle(size_t vcpu_id) { bool success = false; decoded_instruction_ret_t decoded_ins; @@ -451,7 +451,6 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) LOG_VMM_ERR("unhandled fault: 0x%x\n", f_reason); }; - *new_rip = rip; if (success && f_reason != INTERRUPT_WINDOW) { // TODO hack force osxsave on so that Windows doesnt #UD on xgetbv/xsetbv uint64_t cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); @@ -459,9 +458,11 @@ bool fault_handle(size_t vcpu_id, uint64_t *new_rip) microkit_vcpu_x86_write_regs(vcpu_id, &vctx); + uint64_t resume_rip = rip; if (!fault_is_trap_like(f_reason)) { - *new_rip = rip + ins_len; + resume_rip += ins_len; } + microkit_vcpu_x86_deferred_resume(resume_rip, VMCS_PCC_DEFAULT, 0); } else if (!success) { LOG_VMM_ERR("failed handling fault: '%s' (0x%x)\n", fault_to_string(f_reason), f_reason); LOG_VMM_ERR("paging on: %s\n", guest_paging_on() ? "YES" : "NO"); From 46290c4fc4db545a432cf5c680ab37e184a9611e Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Fri, 27 Mar 2026 14:40:57 +1100 Subject: [PATCH 11/42] x86_64: read/write MSR raise GP rather than succes Signed-off-by: Bill Nguyen --- include/libvmm/arch/x86_64/fault.h | 2 + src/arch/x86_64/fault.c | 15 +++++ src/arch/x86_64/msr.c | 96 +++++------------------------- 3 files changed, 32 insertions(+), 81 deletions(-) diff --git a/include/libvmm/arch/x86_64/fault.h b/include/libvmm/arch/x86_64/fault.h index 31addf977..a5f432b1a 100644 --- a/include/libvmm/arch/x86_64/fault.h +++ b/include/libvmm/arch/x86_64/fault.h @@ -12,6 +12,8 @@ #include +#define GP_VECTOR 13 + char *fault_to_string(int exit_reason); /* @billn revisit, seL4 vmexit doesnt have msginfo! */ diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 14767d340..fa3d3962b 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -32,6 +32,9 @@ bool fault_cond = false; * [1] seL4: include/arch/x86/arch/object/vcpu.h * [2] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 Order Number: 325462-080US June 2023 * [2a] Location: Table C-1 "VMX BASIC EXIT REASONS", page: "Vol. 3D C-1" + * [2b] Location: "RDMSR—Read From Model Specific Register", page: "Vol. 2B 4-537" + * [2c] Location: Table 25-17 "Format of the VM-Entry Interruption-Information Field" + * [3] https://wiki.osdev.org/Interrupt_Vector_Table */ /* Exit reasons. @@ -463,6 +466,18 @@ bool fault_handle(size_t vcpu_id) resume_rip += ins_len; } microkit_vcpu_x86_deferred_resume(resume_rip, VMCS_PCC_DEFAULT, 0); + } else if (!success && (f_reason == RDMSR || f_reason == WRMSR)) { + // From [2b] "Specifying a reserved or unimplemented MSR address in ECX will also cause a + // general protection exception." + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE, 0); + + // [2c] and [3] + uint64_t interruption = GP_VECTOR; // General protection fault vector + interruption |= 3ull << 8; // Hardware exception + interruption |= BIT(11); // deliver error code + interruption |= BIT(31); // valid + + microkit_vcpu_x86_deferred_resume(rip, VMCS_PCC_DEFAULT, interruption); } else if (!success) { LOG_VMM_ERR("failed handling fault: '%s' (0x%x)\n", fault_to_string(f_reason), f_reason); LOG_VMM_ERR("paging on: %s\n", guest_paging_on() ? "YES" : "NO"); diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index 5b5fb411c..46764b3dc 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -26,14 +26,13 @@ #define IA32_MKTME_KEYID_PARTITIONING (0x87) #define IA32_BIOS_SIGN_ID (0x8b) #define IA32_CORE_CAPABILITIES (0xcf) +#define IA32_MTRRCAP (0xfe) #define IA32_MISC_ENABLE (0x1a0) #define IA32_MCG_CAP (0x179) -#define IA32_XSS (0xda0) - -#define IA32_MTRRCAP (0xfe) -#define IA32_MTRR_DEF_TYPE (0x2ff) -#define IA32_PAT (0x277) #define IA32_MCG_STATUS (0x17a) +#define IA32_PAT (0x277) +#define IA32_MTRR_DEF_TYPE (0x2ff) +#define IA32_XSS (0xda0) #define MSR_RAPL_POWER_UNIT (0x606) #define MSR_PKG_ENERGY_STATUS (0x611) @@ -50,8 +49,8 @@ #define MSR_PKG_C2_RESIDENCY_ALT (0x3f8) #define MSR_PKG_C4_RESIDENCY (0x3f9) #define MSR_PKG_C6_RESIDENCY (0x3fa) -// #define MSR_OS_MAILBOX_INTERFACE 0xB0 -// #define MSR_OS_MAILBOX_DATA 0xB1 +#define MSR_OS_MAILBOX_INTERFACE 0xB0 +#define MSR_OS_MAILBOX_DATA 0xB1 // @billn seems to be some sort of fencing instruction control // https://gruss.cc/files/msrtemplating.pdf @@ -70,14 +69,6 @@ #define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */ #define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */ #define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ -// #define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ -// #define MSR_GS_BASE 0xc0000101 /* 64bit GS base */ -// #define MSR_SHADOW_GS_BASE 0xc0000102 /* SwapGS GS shadow */ -// #define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */ - -static uint64_t misc_enable = 0; -static uint64_t mtrr_def_type = 0; -static uint64_t pat = 0; bool emulate_rdmsr(seL4_VCPUContext *vctx) { @@ -91,67 +82,28 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) case IA32_TIME_STAMP_COUNTER: result = __rdtsc(); break; - case IA32_MISC_ENABLE: - result = misc_enable; - break; case MSR_STAR: case MSR_LSTAR: case MSR_CSTAR: case MSR_SYSCALL_MASK: result = microkit_vcpu_x86_read_msr(GUEST_BOOT_VCPU_ID, vctx->ecx); break; - case IA32_PLATFORM_ID: - case IA32_CORE_CAPABILITIES: - case IA32_MKTME_KEYID_PARTITIONING: - case IA32_BIOS_SIGN_ID: - case IA32_MCG_CAP: - case MSR_TEST_CTRL: - case MSR_RAPL_POWER_UNIT: - case MSR_PKG_ENERGY_STATUS: - case MSR_PP0_ENERGY_STATUS: - case MSR_PP1_ENERGY_STATUS: - case MSR_PLATFORM_ENERGY_COUNTER: - case MSR_DRAM_ENERGY_STATUS: - case MSR_PPERF: - case MSR_SMI_COUNT: - case MSR_CORE_C3_RESIDENCY: - case MSR_CORE_C6_RESIDENCY: - case MSR_CORE_C7_RESIDENCY: - case MSR_PKG_C2_RESIDENCY: - case MSR_PKG_C2_RESIDENCY_ALT: - case MSR_PKG_C4_RESIDENCY: - case MSR_PKG_C6_RESIDENCY: - case MISC_FEATURE_ENABLES: - case MSR_PLATFORM_INFO: - case MSR_UNKNOWN1: - case IA32_SPEC_CTRL: - case IA32_PRED_CMD: - case IA32_MTRRCAP: - case IA32_MCG_STATUS: - // case MSR_OS_MAILBOX_INTERFACE: - // case MSR_OS_MAILBOX_DATA: - case 0xc0010131: // @billn AMD SEV - case 0x150: // cpu voltage control? - break; case IA32_APIC_BASE: // Figure 11-5. IA32_APIC_BASE MSR (APIC_BASE_MSR in P6 Family) // enable is boot cpu result = LAPIC_GPA | BIT(11) | BIT(8); break; - case IA32_FEATURE_CONTROL: - result = 1; // locked - break; - case IA32_PPIN_CTL: - result = 1; // locked - break; + case IA32_MCG_CAP: + case IA32_MCG_STATUS: + case IA32_MTRRCAP: case IA32_MTRR_DEF_TYPE: - result = mtrr_def_type; - break; case IA32_PAT: - result = pat; + // @billn revisit above 5 + case IA32_SPEC_CTRL: + // @billn revisit, I think we should use Virtualize IA32_SPEC_CTRL + // in Tertiary Processor-Based VM-Execution Controls break; default: - LOG_VMM_ERR("unknown rdmsr 0x%x\n", vctx->ecx); return false; } @@ -172,32 +124,14 @@ bool emulate_wrmsr(seL4_VCPUContext *vctx) case MSR_EFER: microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER, value); break; - case IA32_BIOS_SIGN_ID: - case MISC_FEATURE_ENABLES: - case IA32_XSS: - case IA32_SPEC_CTRL: - case IA32_PRED_CMD: - case IA32_BIOS_UPDT_TRIG: - case IA32_MCG_STATUS: - // case MSR_OS_MAILBOX_INTERFACE: - // case MSR_OS_MAILBOX_DATA: - case 0x150: // cpu voltage control? - return true; - case MSR_TEST_CTRL: case MSR_STAR: case MSR_LSTAR: case MSR_CSTAR: case MSR_SYSCALL_MASK: microkit_vcpu_x86_write_msr(GUEST_BOOT_VCPU_ID, vctx->ecx, value); return true; - case IA32_MISC_ENABLE: - misc_enable = value; - return true; - case IA32_MTRR_DEF_TYPE: - mtrr_def_type = value; - break; - case IA32_PAT: - pat = value; + case IA32_PRED_CMD: + // @billn revisit, security concerns same as IA32_SPEC_CTRL, as they are used for speculative exec controls break; default: LOG_VMM("unknown wrmsr 0x%x, value 0x%lx\n", vctx->ecx, value); From ab4ca3b973ad69e5956cfacd0c1f8cc2cd8a0a61 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Fri, 27 Mar 2026 14:47:51 +1100 Subject: [PATCH 12/42] x86_64: fix fault printing UB Signed-off-by: Bill Nguyen --- src/arch/x86_64/fault.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index fa3d3962b..879c904c8 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -502,10 +502,10 @@ bool fault_handle(size_t vcpu_id) for (int i = 0; i < idt_num_entries; i++) { uint32_t entry[4]; uint64_t entry_gpa = idtr_gpa + (i * idt_entry_size); - entry[0] = *((uint64_t *)gpa_to_vaddr(entry_gpa)); - entry[1] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 4)); - entry[2] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 8)); - entry[3] = *((uint64_t *)gpa_to_vaddr(entry_gpa + 12)); + entry[0] = *((uint32_t *)gpa_to_vaddr(entry_gpa)); + entry[1] = *((uint32_t *)gpa_to_vaddr(entry_gpa + 4)); + entry[2] = *((uint32_t *)gpa_to_vaddr(entry_gpa + 8)); + entry[3] = *((uint32_t *)gpa_to_vaddr(entry_gpa + 12)); uint32_t present = (entry[1] & BIT(15)); if (present) { @@ -516,6 +516,8 @@ bool fault_handle(size_t vcpu_id) LOG_VMM_ERR("IDTR num valid entries: %d\n", idt_num_valid_entries); } vcpu_print_regs(vcpu_id); + + LOG_VMM_ERR("VCPU will not be resumed.\n"); } return success; From e6967b132b0f389c166281c66e8ff412c71c91b4 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Fri, 27 Mar 2026 16:04:20 +1100 Subject: [PATCH 13/42] examples/simple: unified x86 and ARM VMM C source Signed-off-by: Bill Nguyen --- examples/simple/board/maaxboard/simple.system | 2 +- examples/simple/board/odroidc4/simple.system | 2 +- .../board/qemu_virt_aarch64/simple.system | 2 +- .../board/x86_64_generic_vtx/simple.system | 11 +- examples/simple/build.zig | 2 +- examples/simple/simple.mk | 11 +- examples/simple/{vmm_aarch64.c => vmm.c} | 118 ++++++++++++++++- examples/simple/vmm_x86_64.c | 125 ------------------ 8 files changed, 127 insertions(+), 146 deletions(-) rename examples/simple/{vmm_aarch64.c => vmm.c} (53%) delete mode 100644 examples/simple/vmm_x86_64.c diff --git a/examples/simple/board/maaxboard/simple.system b/examples/simple/board/maaxboard/simple.system index 514412c61..3feb3e3fc 100644 --- a/examples/simple/board/maaxboard/simple.system +++ b/examples/simple/board/maaxboard/simple.system @@ -21,7 +21,7 @@ - + diff --git a/examples/simple/board/odroidc4/simple.system b/examples/simple/board/odroidc4/simple.system index d3f92bb9f..93c58f5d3 100644 --- a/examples/simple/board/odroidc4/simple.system +++ b/examples/simple/board/odroidc4/simple.system @@ -20,7 +20,7 @@ - + diff --git a/examples/simple/board/qemu_virt_aarch64/simple.system b/examples/simple/board/qemu_virt_aarch64/simple.system index e4c368e7c..b1b4eaf9d 100644 --- a/examples/simple/board/qemu_virt_aarch64/simple.system +++ b/examples/simple/board/qemu_virt_aarch64/simple.system @@ -27,7 +27,7 @@ - + - - - - - + + @@ -20,10 +17,10 @@ - + - + diff --git a/examples/simple/build.zig b/examples/simple/build.zig index 175dbc8bc..96e6b6dda 100644 --- a/examples/simple/build.zig +++ b/examples/simple/build.zig @@ -127,7 +127,7 @@ pub fn build(b: *std.Build) !void { }); const exe = b.addExecutable(.{ - .name = b.fmt("vmm_{s}.elf", .{ @tagName(target.result.cpu.arch) }), + .name = b.fmt("vmm.elf", .{ @tagName(target.result.cpu.arch) }), .root_module = b.createModule(.{ .target = target, .optimize = optimize, diff --git a/examples/simple/simple.mk b/examples/simple/simple.mk index 32aa508e7..0d42f2651 100644 --- a/examples/simple/simple.mk +++ b/examples/simple/simple.mk @@ -17,12 +17,12 @@ SDDF_CUSTOM_LIBC := 1 vpath %.c $(LIBVMM) $(EXAMPLE_DIR) +IMAGES := vmm.elf + ifeq ($(ARCH),aarch64) LINUX ?= 85000f3f42a882e4476e57003d53f2bbec8262b0-linux INITRD ?= 6dcd1debf64e6d69b178cd0f46b8c4ae7cebe2a5-rootfs.cpio.gz ARCH_FLAGS := -target aarch64-none-elf -mstrict-align - VMM_NAME := vmm_aarch64 - IMAGES = $(VMM_NAME).elf QEMU := qemu-system-aarch64 QEMU_ARCH_ARGS := -machine virt,virtualization=on -cpu cortex-a53 -device loader,file=$(IMAGE_FILE),addr=0x70000000,cpu-num=0 @@ -31,8 +31,7 @@ else ifeq ($(ARCH),x86_64) INITRD ?= d887a642236a92610a9537ab9f4a4aa1a966ad3a-rootfs.cpio.gz DSDT_AML ?= $(SYSTEM_DIR)/simple_dsdt.aml ARCH_FLAGS := -target x86_64-unknown-elf - VMM_NAME := vmm_x86_64 - IMAGES = $(VMM_NAME).elf timer_driver.elf + IMAGES += timer_driver.elf QEMU := qemu-system-x86_64 QEMU_ARCH_ARGS := -accel kvm -cpu host,+fsgsbase,+pdpe1gb,+xsaveopt,+xsave,+vmx,+vme -kernel $(KERNEL32) -initrd $(IMAGE_FILE) @@ -63,7 +62,7 @@ $(CHECK_FLAGS_BOARD_MD5): -rm -f .board_cflags-* touch $@ -$(VMM_NAME).elf: vmm.o images.o +vmm.elf: vmm.o images.o $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ all: loader.img @@ -97,7 +96,7 @@ vm.dts: $(SYSTEM_DIR)/linux.dts $(SYSTEM_DIR)/overlay.dts vm.dtb: vm.dts $(DTC) -q -I dts -O dtb $< > $@ -vmm.o: $(EXAMPLE_DIR)/$(VMM_NAME).c $(CHECK_FLAGS_BOARD_MD5) +vmm.o: $(EXAMPLE_DIR)/vmm.c $(CHECK_FLAGS_BOARD_MD5) $(CC) $(CFLAGS) -c -o $@ $< ifeq ($(ARCH),x86_64) diff --git a/examples/simple/vmm_aarch64.c b/examples/simple/vmm.c similarity index 53% rename from examples/simple/vmm_aarch64.c rename to examples/simple/vmm.c index 9a9430a6e..5923d54a7 100644 --- a/examples/simple/vmm_aarch64.c +++ b/examples/simple/vmm.c @@ -8,6 +8,7 @@ #include #include #include +#include /* * As this is just an example, for simplicity we just make the size of the @@ -25,6 +26,8 @@ #elif defined(BOARD_maaxboard) #define GUEST_DTB_VADDR 0x4f000000 #define GUEST_INIT_RAM_DISK_VADDR 0x4c000000 +#elif defined(BOARD_x86_64_generic_vtx) +#define GUEST_CMDLINE "earlyprintk=serial,0x3f8,115200 debug console=ttyS0,115200 earlycon=serial,0x3f8,115200 loglevel=8" #else #error Need to define guest kernel image address and DTB address #endif @@ -39,6 +42,12 @@ #define SERIAL_IRQ 225 #elif defined(BOARD_maaxboard) #define SERIAL_IRQ 58 +#elif defined(BOARD_x86_64_generic_vtx) +#define COM1_IOAPIC_CHIP 0 +#define COM1_IOAPIC_PIN 4 +#define COM1_IO_PORT_ID 0 +#define COM1_IO_PORT_ADDR 0x3F8 +#define COM1_IO_PORT_SIZE 8 #else #error Need to define serial interrupt #endif @@ -46,12 +55,26 @@ /* Data for the guest's kernel image. */ extern char _guest_kernel_image[]; extern char _guest_kernel_image_end[]; -/* Data for the device tree to be passed to the kernel. */ -extern char _guest_dtb_image[]; -extern char _guest_dtb_image_end[]; /* Data for the initial RAM disk to be passed to the kernel. */ extern char _guest_initrd_image[]; extern char _guest_initrd_image_end[]; + +#if defined(BOARD_x86_64_generic_vtx) +/* Data for the guest's ACPI Differentiated System Description Table (DSDT). */ +extern char _guest_dsdt_aml[]; +extern char _guest_dsdt_aml_end[]; + +// @billn sort out ridiculousness +uintptr_t guest_high_ram_vaddr; +uintptr_t guest_flash_vaddr; +uint64_t guest_high_ram_size; + +#else +/* Data for the device tree to be passed to the kernel. */ +extern char _guest_dtb_image[]; +extern char _guest_dtb_image_end[]; +#endif + /* Microkit will set this variable to the start of the guest RAM memory region. */ uintptr_t guest_ram_vaddr; @@ -61,8 +84,69 @@ void init(void) LOG_VMM("starting \"%s\"\n", microkit_name); /* Place all the binaries in the right locations before starting the guest */ size_t kernel_size = _guest_kernel_image_end - _guest_kernel_image; - size_t dtb_size = _guest_dtb_image_end - _guest_dtb_image; size_t initrd_size = _guest_initrd_image_end - _guest_initrd_image; + + if (!kernel_size) { + LOG_VMM_ERR("Kernel image is empty\n"); + return; + } + + if (!initrd_size) { + LOG_VMM_ERR("Initial ramdisk image is empty\n"); + return; + } + +#if defined(BOARD_x86_64_generic_vtx) + linux_x86_setup_ret_t linux_setup; + size_t dsdt_aml_size = _guest_dsdt_aml_end - _guest_dsdt_aml; + + if (!dsdt_aml_size) { + LOG_VMM_ERR("DSDT AML image is empty\n"); + return; + } + + if (!linux_setup_images(guest_ram_vaddr, GUEST_RAM_SIZE, (uintptr_t)_guest_kernel_image, kernel_size, + (uintptr_t)_guest_initrd_image, initrd_size, _guest_dsdt_aml, dsdt_aml_size, GUEST_CMDLINE, + &linux_setup)) { + LOG_VMM_ERR("Failed to initialise guest images\n"); + return; + } + + vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit); + + /* Set up the virtual PCI bus */ + assert(pci_x86_init()); + + /* Pass through COM1 serial port */ + microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, COM1_IO_PORT_ID, COM1_IO_PORT_ADDR, COM1_IO_PORT_SIZE); + microkit_irq_ack(SERIAL_IRQ_CH); + + /* Retrieve the TSC frequency from hardware */ + x86_host_tsc_t tsc_metadata = get_host_tsc(TIMER_DRV_CH_FOR_LAPIC); + if (!tsc_metadata.valid) { + LOG_VMM_ERR("cannot retrieve TSC frequency\n"); + return; + } + + /* Initialise the virtual Local and I/O APICs */ + // @billn revisit vapic vaddr + bool success = virq_controller_init(tsc_metadata.freq_hz, 0xfffffffffffffff); + if (!success) { + LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); + return; + } + + /* Pass through serial IRQs */ + assert(virq_ioapic_register_passthrough(COM1_IOAPIC_CHIP, COM1_IOAPIC_PIN, SERIAL_IRQ_CH)); + + guest_start(linux_setup.kernel_entry_gpa, 0, 0); +#else + size_t dtb_size = _guest_dtb_image_end - _guest_dtb_image; + if (!dtb_size) { + LOG_VMM_ERR("DTB image is empty\n"); + return; + } + uintptr_t kernel_pc = linux_setup_images(guest_ram_vaddr, (uintptr_t)_guest_kernel_image, kernel_size, (uintptr_t)_guest_dtb_image, GUEST_DTB_VADDR, dtb_size, (uintptr_t)_guest_initrd_image, GUEST_INIT_RAM_DISK_VADDR, initrd_size); @@ -70,6 +154,7 @@ void init(void) LOG_VMM_ERR("Failed to initialise guest images\n"); return; } + arch_guest_init_t args = { .num_vcpus = 1 }; bool success = guest_init(args); if (!success) { @@ -80,11 +165,30 @@ void init(void) assert(success); /* Finally start the guest */ guest_start(kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); +#endif } void notified(microkit_channel ch) { switch (ch) { +#if defined(BOARD_x86_64_generic_vtx) + case TIMER_DRV_CH_FOR_LAPIC: { + handle_lapic_timer_nftn(GUEST_BOOT_VCPU_ID); + break; + } + case TIMER_DRV_CH_FOR_HPET_CH0: + case TIMER_DRV_CH_FOR_HPET_CH1: + case TIMER_DRV_CH_FOR_HPET_CH2: + hpet_handle_timer_ntfn(ch); + break; + case SERIAL_IRQ_CH: { + bool success = virq_ioapic_handle_passthrough(ch); + if (!success) { + LOG_VMM_ERR("I/O APIC IRQ pin %d dropped\n", COM1_IOAPIC_PIN); + } + break; + } +#else case SERIAL_IRQ_CH: { bool success = virq_handle_passthrough(ch); if (!success) { @@ -94,6 +198,7 @@ void notified(microkit_channel ch) } default: printf("Unexpected channel, ch: 0x%lx\n", ch); +#endif } } @@ -104,6 +209,10 @@ void notified(microkit_channel ch) */ seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) { +#if defined(BOARD_x86_64_generic_vtx) + fault_handle(child); + return seL4_True; +#else bool success = fault_handle(child, msginfo); if (success) { /* Now that we have handled the fault successfully, we reply to it so @@ -113,4 +222,5 @@ seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo } return seL4_False; +#endif } diff --git a/examples/simple/vmm_x86_64.c b/examples/simple/vmm_x86_64.c deleted file mode 100644 index f9582e8b0..000000000 --- a/examples/simple/vmm_x86_64.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2025, UNSW - * - * SPDX-License-Identifier: BSD-2-Clause - */ -#include -#include -#include -#include -#include -#include - -uint64_t com1_ioport_id; -uint64_t com1_ioport_addr; -uint64_t com1_ioport_size = 8; - -#define GUEST_CMDLINE "earlyprintk=serial,0x3f8,115200 debug console=ttyS0,115200 earlycon=serial,0x3f8,115200 loglevel=8" - -/* Data for the guest's kernel image. */ -extern char _guest_kernel_image[]; -extern char _guest_kernel_image_end[]; -/* Data for the initial RAM disk to be passed to the kernel. */ -extern char _guest_initrd_image[]; -extern char _guest_initrd_image_end[]; -/* Data for the guest's ACPI Differentiated System Description Table (DSDT). */ -extern char _guest_dsdt_aml[]; -extern char _guest_dsdt_aml_end[]; - -/* Microkit will set this variable to the start of the guest RAM memory region. */ -uintptr_t guest_ram_vaddr; -uint64_t guest_ram_size; - -uintptr_t guest_ecam_vaddr; -uint64_t guest_ecam_size; - -uintptr_t guest_vapic_vaddr; -uint64_t guest_vapic_size; -uint64_t guest_vapic_paddr; - -uintptr_t guest_apic_access_vaddr; -uint64_t guest_apic_access_size; -uint64_t guest_apic_access_paddr; - -// @billn unused, but have to leave it here otherwise linker complains, revisit -uintptr_t guest_flash_vaddr; -uint64_t guest_flash_size; -uintptr_t guest_high_ram_vaddr; -uint64_t guest_high_ram_size; - -linux_x86_setup_ret_t linux_setup; - -void init(void) -{ - /* Initialise the VMM, the VCPU(s), and start the guest */ - LOG_VMM("starting \"%s\"\n", microkit_name); - /* Place all the binaries in the right locations before starting the guest */ - size_t kernel_size = _guest_kernel_image_end - _guest_kernel_image; - size_t initrd_size = _guest_initrd_image_end - _guest_initrd_image; - size_t dsdt_aml_size = _guest_dsdt_aml_end - _guest_dsdt_aml; - - if (!linux_setup_images(guest_ram_vaddr, guest_ram_size, (uintptr_t)_guest_kernel_image, kernel_size, - (uintptr_t)_guest_initrd_image, initrd_size, _guest_dsdt_aml, dsdt_aml_size, GUEST_CMDLINE, - &linux_setup)) { - LOG_VMM_ERR("Failed to initialise guest images\n"); - return; - } - - vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit); - - /* Set up the virtual PCI bus */ - assert(pci_x86_init()); - - /* Pass through COM1 serial port */ - microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, com1_ioport_id, com1_ioport_addr, com1_ioport_size); - microkit_irq_ack(com1_ioport_id); - - /* Retrieve the TSC frequency from hardware */ - x86_host_tsc_t tsc_metadata = get_host_tsc(TIMER_DRV_CH_FOR_LAPIC); - if (!tsc_metadata.valid) { - LOG_VMM_ERR("cannot retrieve TSC frequency\n"); - return; - } - - /* Initialise the virtual Local and I/O APICs */ - bool success = virq_controller_init(tsc_metadata.freq_hz, guest_vapic_vaddr); - if (!success) { - LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); - return; - } - - /* Pass through serial IRQs */ - assert(virq_ioapic_register_passthrough(0, 4, com1_ioport_id)); - - guest_start(linux_setup.kernel_entry_gpa, 0, 0); -} - -void notified(microkit_channel ch) -{ - switch (ch) { - case TIMER_DRV_CH_FOR_LAPIC: { - handle_lapic_timer_nftn(GUEST_BOOT_VCPU_ID); - break; - } - case TIMER_DRV_CH_FOR_HPET_CH0: - case TIMER_DRV_CH_FOR_HPET_CH1: - case TIMER_DRV_CH_FOR_HPET_CH2: - hpet_handle_timer_ntfn(ch); - break; - default: - if (!virq_ioapic_handle_passthrough(ch)) { - LOG_VMM_ERR("failed to passthrough IRQ ch %d\n", ch); - }; - } -} - -/* - * The primary purpose of the VMM after initialisation is to act as a fault-handler. - * Whenever our guest causes an exception, it gets delivered to this entry point for - * the VMM to handle. - */ -seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) -{ - fault_handle(child); - return seL4_True; -} From 12ab9255dbc4a18ab64c824971aeb83127489772 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Mon, 30 Mar 2026 14:36:24 +1100 Subject: [PATCH 14/42] x86_64: refactor CPUID, passthrough CPU cache info Signed-off-by: Bill Nguyen --- include/libvmm/arch/x86_64/cpuid.h | 175 ++++++++++++++++ src/arch/x86_64/cpuid.c | 319 ++++++----------------------- src/arch/x86_64/msr.c | 10 +- 3 files changed, 244 insertions(+), 260 deletions(-) diff --git a/include/libvmm/arch/x86_64/cpuid.h b/include/libvmm/arch/x86_64/cpuid.h index 3d0e07d8b..665f8511f 100644 --- a/include/libvmm/arch/x86_64/cpuid.h +++ b/include/libvmm/arch/x86_64/cpuid.h @@ -8,4 +8,179 @@ #include +#define CACHE_LINE_SIZE 64 +#define NUM_LOGICAL_PROCESSORS 1 + +/* [1] Table 3-8. Information Returned by CPUID Instruction */ +#define CPUID_0H_EAX_MAX_BASIC_LEAF 0x16 +#define CPUID_0H_GENUINEINTEL_EBX 0x756e6547 /* "GenuineIntel" */ +#define CPUID_0H_GENUINEINTEL_EDX 0x49656e69 +#define CPUID_0H_GENUINEINTEL_ECX 0x6c65746e + +#define CPUID_1H_EAX 0x00050054 /* [3] Intel Core i7-7800X Skylake */ +#define CPUID_1H_EBX ((CACHE_LINE_SIZE / 8) << 8) | (NUM_LOGICAL_PROCESSORS << 16) + +/* [1] Table 3-10. More on Feature Information Returned in the ECX Register */ +#define CPUID_1H_ECX_SSE3 BIT(0) +#define CPUID_1H_ECX_PCLMULQDQ BIT(1) +#define CPUID_1H_ECX_DTES64 BIT(2) // DTES64: 64-bit DS area +#define CPUID_1H_ECX_DS_CPL BIT(4) // DS-CPL: CPL qualified debug store +#define CPUID_1H_ECX_SSSE3 BIT(9) +#define CPUID_1H_ECX_FMA BIT(12) +#define CPUID_1H_ECX_CMPXCHG16B BIT(13) +#define CPUID_1H_ECX_XTPR BIT(14) // xTPR update control +#define CPUID_1H_ECX_SSE4_1 BIT(19) +#define CPUID_1H_ECX_SSE4_2 BIT(20) +#define CPUID_1H_ECX_MOVBE BIT(22) +#define CPUID_1H_ECX_POPCNT BIT(23) +#define CPUID_1H_ECX_AES BIT(25) +#define CPUID_1H_ECX_XSAVE BIT(26) +#define CPUID_1H_ECX_OSXSAVE BIT(27) +#define CPUID_1H_ECX_AVX BIT(28) +#define CPUID_1H_ECX_F16C BIT(29) +#define CPUID_1H_ECX_RDRAND BIT(30) + +/* [1] Table 3-11. More on Feature Information Returned in the EDX Register */ +#define CPUID_1H_EDX_FPU BIT(0) +#define CPUID_1H_EDX_VME BIT(1) // VME: Virtual-8086 Mode enhancements +#define CPUID_1H_EDX_DE BIT(2) // DE: Debug Extensions (I/O breakpoints) +#define CPUID_1H_EDX_PSE BIT(3) // PSE: Page Size Extensions +#define CPUID_1H_EDX_TSC BIT(4) +#define CPUID_1H_EDX_MSR BIT(5) +#define CPUID_1H_EDX_PAE BIT(6) +#define CPUID_1H_EDX_CX8 BIT(8) +#define CPUID_1H_EDX_APIC BIT(9) +#define CPUID_1H_EDX_PGE BIT(13) // PGE/PTE Global Bit +#define CPUID_1H_EDX_CMOV BIT(15) +#define CPUID_1H_EDX_PSE36 BIT(17) // PSE-36: Physical Address Extensions +#define CPUID_1H_EDX_CLFLUSH BIT(19) +#define CPUID_1H_EDX_MMX BIT(23) +#define CPUID_1H_EDX_FXSR BIT(24) +#define CPUID_1H_EDX_SSE1 BIT(25) +#define CPUID_1H_EDX_SSE2 BIT(26) +#define CPUID_1H_EDX_SELF_SNOOP BIT(27) +#define CPUID_1H_EDX_PBE BIT(31) // PBE: Pending Break Enable + +/* [1] Table 3-8. Information Returned by CPUID Instruction */ +#define CPUID_7H_EAX_MAX_SUBLEAF 0 + +#define CPUID_7H_00_EBX_FSGSBASE BIT(0) +#define CPUID_7H_00_EBX_BMI1 BIT(3) +#define CPUID_7H_00_EBX_AVX2 BIT(5) +#define CPUID_7H_00_EBX_SMEP BIT(7) // SMEP: Supervisor Mode Execution Protection +#define CPUID_7H_00_EBX_BMI2 BIT(8) +#define CPUID_7H_00_EBX_DEPRECATE_FCS_FDS BIT(13) // Deprecates FPU CS and FPU DS values +#define CPUID_7H_00_EBX_ADX BIT(19) // ADCX/ADOX instructions support +#define CPUID_7H_00_EBX_SMAP BIT(20) // SMAP: Supervisor Mode Access Prevention +#define CPUID_7H_00_EBX_CLFLUSHOPT BIT(23) +#define CPUID_7H_00_EBX_CLWB BIT(24) + +#define CPUID_80000000H_EAX_MAX_EXT_LEAF 0x80000008 + +#define CPUID_80000001_ECX_LM_LAHF_SAHF BIT(0) // LAHF/SAHF instructions support in 64-bit mode +#define CPUID_80000001_ECX_LM_LZCNT BIT(5) // LZCNT: LZCNT instruction support +#define CPUID_80000001_ECX_PREFETCHW BIT(8) + +#define CPUID_80000001_EDX_SCALL_SRET BIT(11) // SYSCALL/SYSRET support +#define CPUID_80000001_EDX_NX BIT(20) // No execute +#define CPUID_80000001_EDX_1GB_PAGE BIT(26) +#define CPUID_80000001_EDX_LONG_MODE BIT(29) + +/* [2] x86-64_v2 baseline CPUID, which modern Linux distros and Windows 10 requires. */ + +/* No: + * qualified debug store + * Intel Enhanced SpeedStep + * Thermal Monitor 2 + * Perfmon + * MONITOR MWAIT + * VMX + * PCID, seL4 in Microkit isn't built with it + * x2APIC + * TSC deadline mode for LAPIC timer + */ +#define CPUID_1H_X64_V2_BASELINE_ECX ( \ + CPUID_1H_ECX_SSE3 | \ + CPUID_1H_ECX_PCLMULQDQ | \ + CPUID_1H_ECX_DTES64 | \ + CPUID_1H_ECX_DS_CPL | \ + CPUID_1H_ECX_SSSE3 | \ + CPUID_1H_ECX_FMA | \ + CPUID_1H_ECX_CMPXCHG16B | \ + CPUID_1H_ECX_XTPR | \ + CPUID_1H_ECX_SSE4_1 | \ + CPUID_1H_ECX_SSE4_2 | \ + CPUID_1H_ECX_MOVBE | \ + CPUID_1H_ECX_POPCNT | \ + CPUID_1H_ECX_AES | \ + CPUID_1H_ECX_XSAVE | \ + CPUID_1H_ECX_OSXSAVE | \ + CPUID_1H_ECX_AVX | \ + CPUID_1H_ECX_F16C | \ + CPUID_1H_ECX_RDRAND \ +) + +/* No: + * Debug Store + * ACPI Thermal Monitor + * Thermal Monitor + * virtual 8086 + * MTRR + * PAT + * MCE + */ +#define CPUID_1H_X64_V2_BASELINE_EDX ( \ + CPUID_1H_EDX_FPU | \ + CPUID_1H_EDX_VME | \ + CPUID_1H_EDX_DE | \ + CPUID_1H_EDX_PSE | \ + CPUID_1H_EDX_TSC | \ + CPUID_1H_EDX_MSR | \ + CPUID_1H_EDX_PAE | \ + CPUID_1H_EDX_CX8 | \ + CPUID_1H_EDX_APIC | \ + CPUID_1H_EDX_PGE | \ + CPUID_1H_EDX_CMOV | \ + CPUID_1H_EDX_PSE36 | \ + CPUID_1H_EDX_CLFLUSH | \ + CPUID_1H_EDX_MMX | \ + CPUID_1H_EDX_FXSR | \ + CPUID_1H_EDX_SSE1 | \ + CPUID_1H_EDX_SSE2 | \ + CPUID_1H_EDX_SELF_SNOOP | \ + CPUID_1H_EDX_PBE \ +) + +/* No: + * TSC adjust + * AVX512 + * INVPCID + * RDSEED + */ +#define CPUID_7H_0_X64_V2_BASELINE_EBX ( \ + CPUID_7H_00_EBX_FSGSBASE | \ + CPUID_7H_00_EBX_BMI1 | \ + CPUID_7H_00_EBX_AVX2 | \ + CPUID_7H_00_EBX_SMEP | \ + CPUID_7H_00_EBX_BMI2 | \ + CPUID_7H_00_EBX_DEPRECATE_FCS_FDS | \ + CPUID_7H_00_EBX_ADX | \ + CPUID_7H_00_EBX_SMAP | \ + CPUID_7H_00_EBX_CLFLUSHOPT | \ + CPUID_7H_00_EBX_CLWB \ +) + +#define CPUID_80000001H_X64_V2_BASELINE_ECX ( \ + CPUID_80000001_ECX_LM_LAHF_SAHF | \ + CPUID_80000001_ECX_LM_LZCNT | \ + CPUID_80000001_ECX_PREFETCHW \ +) + +/* No RDTSCP */ +#define CPUID_80000001H_X64_V2_BASELINE_EDX ( \ + CPUID_80000001_EDX_NX | \ + CPUID_80000001_EDX_1GB_PAGE | \ + CPUID_80000001_EDX_LONG_MODE \ +) + bool emulate_cpuid(seL4_VCPUContext *vctx); diff --git a/src/arch/x86_64/cpuid.c b/src/arch/x86_64/cpuid.c index 102bc0f15..1b6f6c292 100644 --- a/src/arch/x86_64/cpuid.c +++ b/src/arch/x86_64/cpuid.c @@ -11,232 +11,69 @@ #include #include -#define CACHE_LINE_SIZE 64 -#define NUM_LOGICAL_PROCESSORS 1 - -extern uint64_t tsc_hz; - -// Table 3-11. More on Feature Information Returned in the EDX Register -#define CPUID_01_ECX_SSE3 BIT(0) -#define CPUID_01_ECX_PCLMULQDQ BIT(1) -#define CPUID_01_ECX_DTES64 BIT(2) // DTES64: 64-bit DS area -#define CPUID_01_ECX_DS_CPL BIT(4) // DS-CPL: CPL qualified debug store -#define CPUID_01_ECX_EST BIT(7) // EST: Enhanced Intel SpeedStep Technology -#define CPUID_01_ECX_TM2 BIT(8) // TM2: Thermal Monitor 2 -#define CPUID_01_ECX_SSSE3 BIT(9) -#define CPUID_01_ECX_FMA BIT(12) -#define CPUID_01_ECX_CMPXCHG16B BIT(13) -#define CPUID_01_ECX_XTPR BIT(14) // xTPR update control -#define CPUID_01_ECX_PDCM BIT(15) // PDCM - Perfmon and Debug Capability MSR -#define CPUID_01_ECX_SSE4_1 BIT(19) -#define CPUID_01_ECX_SSE4_2 BIT(20) -#define CPUID_01_ECX_MOVBE BIT(22) -#define CPUID_01_ECX_POPCNT BIT(23) -#define CPUID_01_ECX_AES BIT(25) -#define CPUID_01_ECX_XSAVE BIT(26) -#define CPUID_01_ECX_OSXSAVE BIT(27) -#define CPUID_01_ECX_AVX BIT(28) -#define CPUID_01_ECX_F16C BIT(29) -#define CPUID_01_ECX_RDRAND BIT(30) -#define CPUID_01_ECX_HYP BIT(31) // Running on hypervisor, correspond to X86_FEATURE_HYPERVISOR in linux source - -#define CPUID_01_EDX_FPU BIT(0) -#define CPUID_01_EDX_VME BIT(1) // VME: Virtual-8086 Mode enhancements -#define CPUID_01_EDX_DE BIT(2) // DE: Debug Extensions (I/O breakpoints) -#define CPUID_01_EDX_PSE BIT(3) // PSE: Page Size Extensions -#define CPUID_01_EDX_TSC BIT(4) -#define CPUID_01_EDX_MSR BIT(5) -#define CPUID_01_EDX_PAE BIT(6) -#define CPUID_01_EDX_MCE BIT(7) // MCE: Machine Check Exception -#define CPUID_01_EDX_CX8 BIT(8) -#define CPUID_01_EDX_APIC BIT(9) -#define CPUID_01_EDX_MTRR BIT(12) // MTRR: Memory Type Range Reg -#define CPUID_01_EDX_PGE BIT(13) // PGE/PTE Global Bit -#define CPUID_01_EDX_MCA BIT(14) // MCA: Machine Check Architecture -#define CPUID_01_EDX_CMOV BIT(15) -#define CPUID_01_EDX_PAT BIT(16) -#define CPUID_01_EDX_PSE36 BIT(17) // PSE-36: Physical Address Extensions -#define CPUID_01_EDX_CLFLUSH BIT(19) -#define CPUID_01_EDX_DEBUG_STORE BIT(21) -#define CPUID_01_EDX_ACPI BIT(22) // ACPI: Thermal Monitor and Software Controlled Clock Facilities -#define CPUID_01_EDX_MMX BIT(23) -#define CPUID_01_EDX_FXSR BIT(24) -#define CPUID_01_EDX_SSE1 BIT(25) -#define CPUID_01_EDX_SSE2 BIT(26) -#define CPUID_01_EDX_SELF_SNOOP BIT(27) -#define CPUID_01_EDX_TM BIT(29) // TM: Thermal Monitor -#define CPUID_01_EDX_PBE BIT(31) // PBE: Pending Break Enable - -#define CPUID_06_EAX_ARAT BIT(2) // APIC-Timer-always-running - -#define CPUID_01_EDX_WINDOWS_MANDATORY 0x789f3fdull - -#define CPUID_07_00_EBX_FSGSBASE BIT(0) -#define CPUID_07_00_EBX_BMI1 BIT(3) -#define CPUID_07_00_EBX_AVX2 BIT(5) -#define CPUID_07_00_EBX_SMEP BIT(7) // SMEP: Supervisor Mode Execution Protection -#define CPUID_07_00_EBX_BMI2 BIT(8) -#define CPUID_07_00_EBX_DEPRECATE_FCS_FDS BIT(13) // Deprecates FPU CS and FPU DS values -#define CPUID_07_00_EBX_ADX BIT(19) // ADCX/ADOX instructions support -#define CPUID_07_00_EBX_SMAP BIT(20) // SMAP: Supervisor Mode Access Prevention -#define CPUID_07_00_EBX_CLFLUSHOPT BIT(23) -#define CPUID_07_00_EBX_CLWB BIT(24) - -#define CPUID_80000001_ECX_LM_LAHF_SAHF BIT(0) // LAHF/SAHF instructions support in 64-bit mode -#define CPUID_80000001_ECX_LM_LZCNT BIT(5) // LZCNT: LZCNT instruction support -#define CPUID_80000001_ECX_PREFETCHW BIT(8) - -#define CPUID_80000001_EDX_SCALL_SRET BIT(11) // SYSCALL/SYSRET support -#define CPUID_80000001_EDX_NX BIT(20) // No execute -#define CPUID_80000001_EDX_1GB_PAGE BIT(26) -#define CPUID_80000001_EDX_RDTSCP BIT(27) -#define CPUID_80000001_EDX_LONG_MODE BIT(29) - -// TODO: do this instead -// #define CPUID_01_BASELINE_EDX (CPUID_01_EDX_CMOV | -// CPUID_01_EDX_CX8 | -// CPUID_01_EDX_FPU | -// CPUID_01_EDX_FXSR | -// CPUID_01_EDX_MMX | -// CPUID_01_EDX_SSE1 | -// CPUID_01_EDX_SSE2) - -// #define CPUID_01_X86_64_V2_EDX (CPUID_01_ECX_CMPXCHG16B | -// CPUID_01_ECX_LAHF_SAHF | +/* Documents referenced: + * 1. Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 + * Order Number: 325462-080US June 2023 + * 2. https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels + * 3. https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.txt + */ -// ) +/* 4 chars per 32-bit register, 4 registers per leaf, 3 leafs */ +#define CPUID_BRAND_STR_LEN (4 * 4 * 3) +static const char brand_string[CPUID_BRAND_STR_LEN] = "Trustworthy Systems CPU"; -static const char brand_string[48] = "Trustworthy Systems CPU"; +extern uint64_t tsc_hz; bool emulate_cpuid(seL4_VCPUContext *vctx) { + uint32_t a, b, c, d; LOG_FAULT("handling CPUID 0x%x\n", vctx->eax); - // @billn todo revisit likely need to turn on some important features. - // 3-218 Vol. 2A - switch (vctx->eax) { - case 0x0: - // 3-240 Vol. 2A - // Maxiumum Input Value for Basic CPUID Information. - vctx->eax = 0x16; - // "GenuineIntel" - vctx->ebx = 0x756e6547; - vctx->edx = 0x49656e69; - vctx->ecx = 0x6c65746e; + case 0x0: /* Basic CPUID Information */ + vctx->eax = CPUID_0H_EAX_MAX_BASIC_LEAF; + vctx->ebx = CPUID_0H_GENUINEINTEL_EBX; + vctx->edx = CPUID_0H_GENUINEINTEL_EDX; + vctx->ecx = CPUID_0H_GENUINEINTEL_ECX; break; - case 0x1: { - // https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.cc - vctx->eax = 0x00050054; - vctx->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (NUM_LOGICAL_PROCESSORS << 16); - vctx->ecx = CPUID_01_ECX_DTES64 | 0 /* No qualified debug store */ - | 0 /* No Intel Enhanced SpeedStep */ | 0 /* No Thermal Monitor 2 */ | CPUID_01_ECX_XTPR - | 0 /* No Perfmon */ | CPUID_01_ECX_SSE3 | CPUID_01_ECX_PCLMULQDQ - | 0 /* No MONITOR MWAIT*/ | 0 /* No VMX*/ | CPUID_01_ECX_SSSE3 | CPUID_01_ECX_FMA - | CPUID_01_ECX_CMPXCHG16B - | 0 /* No PCID, seL4 in Microkit isn't built with it */ | CPUID_01_ECX_SSE4_1 | CPUID_01_ECX_SSE4_2 - | 0 /* No x2APIC */ | CPUID_01_ECX_MOVBE | CPUID_01_ECX_POPCNT - | 0 /* No TSC deadline */ | CPUID_01_ECX_AES | CPUID_01_ECX_XSAVE | CPUID_01_ECX_OSXSAVE - | CPUID_01_ECX_AVX | CPUID_01_ECX_F16C | 0 /* No RDRAND */ | CPUID_01_ECX_HYP; - - vctx->edx = 0 /* No Debug Store */ | 0 /* No ACPI Thermal Monitor */ | CPUID_01_EDX_SELF_SNOOP - | 0/* No THermal Monitor */ - | CPUID_01_EDX_PBE | CPUID_01_EDX_FPU | 0 /* No virtual 8086 mode */ | CPUID_01_EDX_DE - | CPUID_01_EDX_PSE | CPUID_01_EDX_TSC | CPUID_01_EDX_MSR | CPUID_01_EDX_PAE | CPUID_01_EDX_MCE - | CPUID_01_EDX_CX8 | CPUID_01_EDX_APIC | CPUID_01_EDX_MTRR | CPUID_01_EDX_PGE | CPUID_01_EDX_MCA - | CPUID_01_EDX_CMOV | CPUID_01_EDX_PAT | CPUID_01_EDX_PSE36 | CPUID_01_EDX_MMX | CPUID_01_EDX_FXSR - | CPUID_01_EDX_SSE2 | CPUID_01_EDX_SSE1 | CPUID_01_EDX_CLFLUSH; - - // LOG_VMM("edx = 0x%x, mandatory = 0x%x, (vctx->edx & CPUID_01_EDX_WINDOWS_MANDATORY) = 0x%x\n", vctx->edx, CPUID_01_EDX_WINDOWS_MANDATORY, (vctx->edx & CPUID_01_EDX_WINDOWS_MANDATORY)); - - for (int i = 0; i < 32; i++) { - if (!(vctx->edx & BIT(i)) && (CPUID_01_EDX_WINDOWS_MANDATORY & BIT(i))) { - LOG_VMM("we are missing bit %d\n", i); - } - } - - assert(((uint64_t)(vctx->edx) & CPUID_01_EDX_WINDOWS_MANDATORY) == CPUID_01_EDX_WINDOWS_MANDATORY); - // assert(0); + case 0x1: + vctx->eax = CPUID_1H_EAX; + vctx->ebx = CPUID_1H_EBX; + vctx->ecx = CPUID_1H_X64_V2_BASELINE_ECX; + vctx->edx = CPUID_1H_X64_V2_BASELINE_EDX; break; - } - case 0x2: { - // https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.cc - // Cache and TLB description - vctx->eax = 0x76036301; - vctx->ebx = 0x00f0b5ff; - vctx->ecx = 0x00000000; - vctx->edx = 0x00c30000; - break; - } + case 0x2: /* Cache and TLB Information */ - case 0x4: { - // https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.cc - // Deterministic Cache Parameters - switch (vctx->ecx) { - case 0: - vctx->eax = 0x1c004121; - vctx->ebx = 0x01c0003f; - vctx->ecx = 0x0000003f; - vctx->edx = 0x00000000; - break; - case 1: - vctx->eax = 0x1c004122; - vctx->ebx = 0x01c0003f; - vctx->ecx = 0x0000003f; - vctx->edx = 0x00000000; - break; - case 2: - vctx->eax = 0x1c004143; - vctx->ebx = 0x03c0003f; - vctx->ecx = 0x000003ff; - vctx->edx = 0x00000000; - break; - case 3: - vctx->eax = 0x1c03c163; - vctx->ebx = 0x0280003f; - vctx->ecx = 0x00002fff; - vctx->edx = 0x00000004; - break; - default: - vctx->eax = 0; - vctx->ebx = 0; - vctx->ecx = 0; - vctx->edx = 0; - break; - } + case 0x4: /* Deterministic Cache Parameters */ + /* Passthrough host's values */ + cpuid(vctx->eax, vctx->ecx, &a, &b, &c, &d); + vctx->eax = a; + vctx->ebx = b; + vctx->ecx = c; + vctx->edx = d; break; - } - case 0x7: { - if (vctx->ecx == 0) { - vctx->eax = 0; - vctx->ebx = CPUID_07_00_EBX_FSGSBASE | CPUID_07_00_EBX_BMI1 | CPUID_07_00_EBX_BMI2 - | 0 /* No TSC adjust */ | 0 /* No AVX2 */ | CPUID_07_00_EBX_SMEP - | 0 /* No INVPCID */ | CPUID_07_00_EBX_DEPRECATE_FCS_FDS - | 0 /* No AVX512 */ | 0 /* No RDSEED */ | CPUID_07_00_EBX_ADX | CPUID_07_00_EBX_SMAP - | CPUID_07_00_EBX_CLFLUSHOPT | CPUID_07_00_EBX_CLWB; - vctx->ecx = 0; - vctx->edx = 0; - } else { - vctx->eax = 0; - vctx->ebx = 0; - vctx->ecx = 0; - vctx->edx = 0; + case 0x7: /* Structured Extended Feature Flags Enumeration */ + if (vctx->ecx == CPUID_7H_EAX_MAX_SUBLEAF && vctx->ecx == 0) { + vctx->ebx = CPUID_7H_0_X64_V2_BASELINE_EBX; } + vctx->eax = 0; + vctx->ecx = 0; + vctx->edx = 0; break; - } - case 0xb: { + case 0xb: /* Extended Topology Enumeration Leaf */ + // @billn revisit for multiple VCPUs vctx->eax = 0; vctx->ebx = 0; vctx->ecx = vctx->ecx; vctx->edx = 0; // x2apic id, though we don't use x2apic break; - } - // sus + // sus @billn revisit case 0xd: { uint32_t ecx = vctx->ecx; cpuid(0xd, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, @@ -268,43 +105,40 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) } break; } - case 0x15: { - // Time Stamp Counter and Nominal Core Crystal Clock - vctx->eax = 1; + + case 0x15: /* Time Stamp Counter and Nominal Core Crystal Clock */ + vctx->eax = 1; /* Making ratio between Crystal and TSC 1-to-1 */ vctx->ebx = 1; vctx->ecx = tsc_hz; vctx->edx = 0; break; - } - case 0x16: - // Table 3-8. Information Returned by CPUID Instruction (Contd.) - // page "3-232 Vol. 2A" - // processor and bus clock in MHz - // Linux can measure this itself but it needs the PIT, - // which we aren't emulating. + + case 0x16: /* Processor Frequency Information Leaf */ + /* CPU base, max and bus frequency in MHz */ vctx->eax = tsc_hz / 1000000; vctx->ebx = tsc_hz / 1000000; vctx->ecx = tsc_hz / 1000000; vctx->edx = 0; break; - case 0x80000000: - vctx->eax = 0x80000008; // max input value for extended function cpuid information + + case 0x80000000: /* Extended Function CPUID Information */ + vctx->eax = CPUID_80000000H_EAX_MAX_EXT_LEAF; /* max input value for extended function cpuid information */ vctx->ebx = 0; vctx->ecx = 0; vctx->edx = 0; break; - case 0x80000001: + case 0x80000001: /* Extended Processor Signature and Feature Bits */ vctx->eax = 0; vctx->ebx = 0; - vctx->ecx = CPUID_80000001_ECX_LM_LAHF_SAHF | CPUID_80000001_ECX_LM_LZCNT | CPUID_80000001_ECX_PREFETCHW; - vctx->edx = 0 /* No RDTSCP */ | CPUID_80000001_EDX_NX | CPUID_80000001_EDX_LONG_MODE - | CPUID_80000001_EDX_1GB_PAGE; + vctx->ecx = CPUID_80000001H_X64_V2_BASELINE_ECX; + vctx->edx = CPUID_80000001H_X64_V2_BASELINE_EDX; if (guest_in_64_bits()) { + /* [1] "This feature flag is always enumerated as 0 outside 64-bit mode." */ vctx->edx |= CPUID_80000001_EDX_SCALL_SRET; } break; - case 0x80000002: + case 0x80000002: /* Processor Brand String. */ memcpy(&(vctx->eax), brand_string, 4); memcpy(&(vctx->ebx), brand_string + 4, 4); memcpy(&(vctx->ecx), brand_string + 8, 4); @@ -323,45 +157,20 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) memcpy(&(vctx->edx), brand_string + 44, 4); break; - case 0x80000006: - // L2 cache topology - vctx->eax = 0; - vctx->ebx = 0; - vctx->ecx = 0x01006040; - vctx->edx = 0; - break; - - case 0x80000007: - vctx->eax = 0; - vctx->ebx = 0; - vctx->ecx = 0; - vctx->edx = 0; - - { - uint32_t a, b, c, d; - cpuid(vctx->eax, 0, &a, &b, &c, &d); - if (d & BIT(8)) { - // Turn on invariant TSC if available - vctx->edx = BIT(8); - } - } - - break; - - case 0x80000008: - cpuid(vctx->eax, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, - (uint32_t *)&vctx->edx); + case 0x80000006: /* L2 cache topology */ + case 0x80000007: /* Invariant TSC */ + case 0x80000008: /* Physical Address size */ + /* Passthrough host's values */ + cpuid(vctx->eax, vctx->ecx, &a, &b, &c, &d); + vctx->eax = a; + vctx->ebx = b; + vctx->ecx = c; + vctx->edx = d; break; - case 0x6: - vctx->eax = CPUID_06_EAX_ARAT; /* Always running APIC timer */ - vctx->ebx = 0; - vctx->ecx = 0; - vctx->edx = 0; - break; - // @billn todo double check if these are needed case 0x3: case 0x5: + case 0x6: case 0x8: case 0x9: case 0xa: @@ -385,7 +194,7 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) case 0x21: case 0x40000000 ... 0x4fffffff: case 0x80000005: - // some AMD specific stuff beyond 0x80000009 inclusive + /* some AMD specific stuff beyond 0x80000009 inclusive */ case 0x80000009 ... 0x8000001f: case 0x80000026: /* Highest Xeon Phi Function Implemented */ diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index 46764b3dc..7af99f16c 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -93,11 +93,11 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) // enable is boot cpu result = LAPIC_GPA | BIT(11) | BIT(8); break; - case IA32_MCG_CAP: - case IA32_MCG_STATUS: - case IA32_MTRRCAP: - case IA32_MTRR_DEF_TYPE: - case IA32_PAT: + // case IA32_MCG_CAP: + // case IA32_MCG_STATUS: + // case IA32_MTRRCAP: + // case IA32_MTRR_DEF_TYPE: + // case IA32_PAT: // @billn revisit above 5 case IA32_SPEC_CTRL: // @billn revisit, I think we should use Virtualize IA32_SPEC_CTRL From af411e0700e3e0b1c2843f6c1755283b7b6aee10 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Mon, 30 Mar 2026 20:42:16 +1100 Subject: [PATCH 15/42] x86_64: detect precise TSC frequency on hardware Rather than manually measuring it which is error prone and can cause Linux's timer watchdog to go off Signed-off-by: Bill Nguyen --- examples/simple/vmm.c | 10 +++++----- include/libvmm/arch/x86_64/tsc.h | 12 +++++------- src/arch/x86_64/tsc.c | 30 ++++++++++++++++-------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index 5923d54a7..e8c2de3be 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -121,16 +121,16 @@ void init(void) microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, COM1_IO_PORT_ID, COM1_IO_PORT_ADDR, COM1_IO_PORT_SIZE); microkit_irq_ack(SERIAL_IRQ_CH); - /* Retrieve the TSC frequency from hardware */ - x86_host_tsc_t tsc_metadata = get_host_tsc(TIMER_DRV_CH_FOR_LAPIC); - if (!tsc_metadata.valid) { - LOG_VMM_ERR("cannot retrieve TSC frequency\n"); + /* Determine the CPU's TSC frequency */ + uint64_t tsc_hz = get_host_tsc_hz(TIMER_DRV_CH_FOR_LAPIC); + if (!tsc_hz) { + LOG_VMM_ERR("cannot determine TSC frequency\n"); return; } /* Initialise the virtual Local and I/O APICs */ // @billn revisit vapic vaddr - bool success = virq_controller_init(tsc_metadata.freq_hz, 0xfffffffffffffff); + bool success = virq_controller_init(tsc_hz, 0xfffffffffffffff); if (!success) { LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); return; diff --git a/include/libvmm/arch/x86_64/tsc.h b/include/libvmm/arch/x86_64/tsc.h index 3cc272fe3..509ba9461 100644 --- a/include/libvmm/arch/x86_64/tsc.h +++ b/include/libvmm/arch/x86_64/tsc.h @@ -9,10 +9,8 @@ #include #include -typedef struct x86_host_tsc { - bool valid; - bool invariant; - uint64_t freq_hz; -} x86_host_tsc_t; - -x86_host_tsc_t get_host_tsc(microkit_channel timer_ch); \ No newline at end of file +/* Determines the host CPU's TSC frequency. First attempt to + calculate it from values in the appropriate CPUID leafs. If + they aren't enumerated, which happens under QEMU. Measure + it with the timer. */ +uint64_t get_host_tsc_hz(microkit_channel timer_ch); \ No newline at end of file diff --git a/src/arch/x86_64/tsc.c b/src/arch/x86_64/tsc.c index 7fa0ff057..fa12a7acb 100644 --- a/src/arch/x86_64/tsc.c +++ b/src/arch/x86_64/tsc.c @@ -98,7 +98,7 @@ static uint64_t get_tsc_frequency(void) */ uint64_t tsc_hz = (uint64_t)crystal_hz * (numerator / (double)denominator); - LOG_TSC("TSC frequency is %u * (%u / %u) = %lu Hz\n", crystal_hz, numerator, denominator, tsc_hz); + LOG_TSC("detected TSC frequency is %u * (%u / %u) = %lu Hz\n", crystal_hz, numerator, denominator, tsc_hz); return tsc_hz; } @@ -113,25 +113,27 @@ static uint64_t measure_tsc_frequency(microkit_channel timer_ch) tsc_post = rdtsc(); uint64_t tsc_hz = tsc_post - tsc_pre; + LOG_TSC("measured TSC frequency %lu Hz\n", tsc_hz); return tsc_hz; } -x86_host_tsc_t get_host_tsc(microkit_channel timer_ch) +uint64_t get_host_tsc_hz(microkit_channel timer_ch) { - x86_host_tsc_t tsc_metadata = { - .valid = true, - .invariant = false, - .freq_hz = 0, - }; - - tsc_metadata.freq_hz = measure_tsc_frequency(timer_ch); - if (tsc_metadata.freq_hz == 0) { - tsc_metadata.valid = false; + uint64_t tsc_hz = 0; + if (!is_intel_cpu()) { + LOG_TSC("Not an Intel CPU.\n"); + return 0; } else { - LOG_TSC("TSC frequency: %llu Hz\n", tsc_metadata.freq_hz); + tsc_hz = get_tsc_frequency(); + if (!tsc_hz) { + LOG_TSC("cannot detect TSC frequency via cpuid, manually measuring.\n"); + } } - tsc_metadata.invariant = true; + if (!tsc_hz) { + /* Likely running on QEMU under nested virtualisation. QEMU doesn't enumerate TSC cpuid leafs */ + tsc_hz = measure_tsc_frequency(timer_ch); + } - return tsc_metadata; + return tsc_hz; } \ No newline at end of file From 3798f428c771be75063bd40d4e6e0ff44b742723 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Mon, 30 Mar 2026 21:14:06 +1100 Subject: [PATCH 16/42] examples/simple: fix zig build regression Signed-off-by: Bill Nguyen --- build.zig | 2 +- examples/simple/build.zig | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/build.zig b/build.zig index 2b3c50c9e..1aa9e2b2b 100644 --- a/build.zig +++ b/build.zig @@ -48,7 +48,7 @@ const src_x86_64 = [_][]const u8{ "src/arch/x86_64/pci.c", "src/arch/x86_64/ioports.c", "src/arch/x86_64/util.c", - "src/arch/x86_64/com.c", + "src/arch/x86_64/tsc.c", }; /// Convert the target for Microkit (e.g freestanding AArch64 or RISC-V) to the Linux diff --git a/examples/simple/build.zig b/examples/simple/build.zig index 96e6b6dda..0ea1539ae 100644 --- a/examples/simple/build.zig +++ b/examples/simple/build.zig @@ -127,7 +127,7 @@ pub fn build(b: *std.Build) !void { }); const exe = b.addExecutable(.{ - .name = b.fmt("vmm.elf", .{ @tagName(target.result.cpu.arch) }), + .name = "vmm.elf", .root_module = b.createModule(.{ .target = target, .optimize = optimize, @@ -138,7 +138,10 @@ pub fn build(b: *std.Build) !void { }), }); - const dtb = blk: { + // Architecture-specific system description file + // on ARM this is the device tree + // on x86 this is the ACPI Differentiated System Description Table + const arch_sys_desc = blk: { if (target.result.cpu.arch != .x86_64) { const base_dts_path = b.fmt("board/{s}/linux.dts", .{ microkit_board }); const overlay = b.fmt("board/{s}/overlay.dts", .{ microkit_board }); @@ -157,7 +160,8 @@ pub fn build(b: *std.Build) !void { dtc_cmd.step.dependOn(&b.addInstallFileWithDir(final_dts, .prefix, "final.dts").step); break :blk dtc_cmd.captureStdOut(); } else { - break :blk null; + const dsdt_aml_path = b.fmt("board/{s}/simple_dsdt.aml", .{microkit_board}); + break :blk b.path(dsdt_aml_path); } }; @@ -175,7 +179,7 @@ pub fn build(b: *std.Build) !void { exe.linkLibrary(sddf_dep.artifact("util")); exe.addCSourceFiles(.{ - .files = &.{ b.fmt("vmm_{s}.c", .{ @tagName(target.result.cpu.arch) }) }, + .files = &.{"vmm.c"}, .flags = &.{ "-Wall", "-Werror", @@ -192,9 +196,11 @@ pub fn build(b: *std.Build) !void { }), }); - if (dtb != null) { + if (microkit_board_option != .x86_64_generic_vtx) { // We need to produce the DTB from the DTS before doing anything to produce guest_images - guest_images.step.dependOn(&b.addInstallFileWithDir(dtb.?, .prefix, "linux.dtb").step); + guest_images.step.dependOn(&b.addInstallFileWithDir(arch_sys_desc, .prefix, "linux.dtb").step); + } else { + guest_images.step.dependOn(&b.addInstallFileWithDir(arch_sys_desc, .prefix, "dsdt.aml").step); } const linux_image_dep = b.lazyDependency(b.fmt("linux_{t}", .{ target.result.cpu.arch }), .{}); @@ -214,15 +220,17 @@ pub fn build(b: *std.Build) !void { const kernel_image_arg = b.fmt("-DGUEST_KERNEL_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, linuxKernelImageName(target.result.cpu.arch).?) }); const initrd_image_arg = b.fmt("-DGUEST_INITRD_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "rootfs.cpio.gz") }); - var dtb_image_arg: []const u8 = ""; - if (dtb != null) { - dtb_image_arg = b.fmt("-DGUEST_DTB_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "linux.dtb") }); + var arch_sys_desc_image_arg: []const u8 = ""; + if (microkit_board_option != .x86_64_generic_vtx) { + arch_sys_desc_image_arg = b.fmt("-DGUEST_DTB_IMAGE_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "linux.dtb") }); + } else { + arch_sys_desc_image_arg = b.fmt("-DGUEST_DSDT_AML_PATH=\"{s}\"", .{ b.getInstallPath(.prefix, "dsdt.aml") }); } guest_images.addCSourceFile(.{ .file = libvmm_dep.path("tools/package_guest_images.S"), .flags = &.{ kernel_image_arg, - dtb_image_arg, + arch_sys_desc_image_arg, initrd_image_arg, "-x", "assembler-with-cpp", @@ -234,7 +242,7 @@ pub fn build(b: *std.Build) !void { var timer_driver: ?*std.Build.Step.InstallArtifact = null; if (target.result.cpu.arch == .x86_64) { - timer_driver = b.addInstallArtifact(sddf_dep.artifact("driver_timer_tsc_hpet.elf"), .{ .dest_sub_path = "timer_driver_x86_64.elf" }); + timer_driver = b.addInstallArtifact(sddf_dep.artifact("driver_timer_tsc_hpet.elf"), .{ .dest_sub_path = "timer_driver.elf" }); } const system_description_path = b.fmt("board/{s}/simple.system", .{ microkit_board }); From 3704c323f3540a772d3c17ed35537255d82c42b1 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 31 Mar 2026 12:17:52 +1100 Subject: [PATCH 17/42] x86_64: properly virtualise XSAVE, XGETBV, and AVX Allow guests to properly use AVX extension if enabled by seL4. By default seL4 doesn't enable AVX so there isn't an immediate benefit from the commit. But if you enable AVX in seL4 then it will automatically be enabled for the guest. Signed-off-by: Bill Nguyen --- build.zig | 1 + include/libvmm/arch/x86_64/fpu.h | 14 +++++++++++++ src/arch/x86_64/cpuid.c | 33 ++++++++++-------------------- src/arch/x86_64/fault.c | 6 +++--- src/arch/x86_64/fpu.c | 35 ++++++++++++++++++++++++++++++++ src/arch/x86_64/msr.c | 5 +++++ vmm.mk | 3 ++- 7 files changed, 71 insertions(+), 26 deletions(-) create mode 100644 include/libvmm/arch/x86_64/fpu.h create mode 100644 src/arch/x86_64/fpu.c diff --git a/build.zig b/build.zig index 1aa9e2b2b..4f55f2302 100644 --- a/build.zig +++ b/build.zig @@ -49,6 +49,7 @@ const src_x86_64 = [_][]const u8{ "src/arch/x86_64/ioports.c", "src/arch/x86_64/util.c", "src/arch/x86_64/tsc.c", + "src/arch/x86_64/fpu.c", }; /// Convert the target for Microkit (e.g freestanding AArch64 or RISC-V) to the Linux diff --git a/include/libvmm/arch/x86_64/fpu.h b/include/libvmm/arch/x86_64/fpu.h new file mode 100644 index 000000000..bb06c181f --- /dev/null +++ b/include/libvmm/arch/x86_64/fpu.h @@ -0,0 +1,14 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +/* Higher level fault handling logic must raise general protection exception #GP(0) + * if the return value is false */ +bool emulate_xsetbv(seL4_VCPUContext *vctx); \ No newline at end of file diff --git a/src/arch/x86_64/cpuid.c b/src/arch/x86_64/cpuid.c index 1b6f6c292..f30984b7e 100644 --- a/src/arch/x86_64/cpuid.c +++ b/src/arch/x86_64/cpuid.c @@ -27,7 +27,6 @@ extern uint64_t tsc_hz; bool emulate_cpuid(seL4_VCPUContext *vctx) { - uint32_t a, b, c, d; LOG_FAULT("handling CPUID 0x%x\n", vctx->eax); switch (vctx->eax) { @@ -49,11 +48,8 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) case 0x4: /* Deterministic Cache Parameters */ /* Passthrough host's values */ - cpuid(vctx->eax, vctx->ecx, &a, &b, &c, &d); - vctx->eax = a; - vctx->ebx = b; - vctx->ecx = c; - vctx->edx = d; + cpuid(vctx->eax, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, + (uint32_t *)&vctx->edx); break; case 0x7: /* Structured Extended Feature Flags Enumeration */ @@ -73,35 +69,31 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) vctx->edx = 0; // x2apic id, though we don't use x2apic break; - // sus @billn revisit - case 0xd: { + case 0xd: { /* Processor Extended State Enumeration */ uint32_t ecx = vctx->ecx; cpuid(0xd, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, (uint32_t *)&vctx->edx); if (ecx == 0) { - // TODO: this is a complete hack because we know seL4 will set the XCR - // to 0x3. - vctx->eax = 0x3; + /* Main leaf, only report XCR0 bits that seL4 is configured to support. */ + vctx->eax = CONFIG_XSAVE_FEATURE_SET; } if (ecx == 1) { + /* Sub-leaf */ #if !defined(CONFIG_XSAVE_XSAVEC) if (vctx->eax & BIT(1)) { vctx->eax &= ~BIT(1); - // LOG_VMM("XSAVEC is available in CPU but not available in seL4, disabling for guest\n"); } -#endif +#endif /* !CONFIG_XSAVE_XSAVEC */ #if !defined(CONFIG_XSAVE_XSAVEOPT) if (vctx->eax & BIT(0)) { vctx->eax &= ~BIT(0); - // LOG_VMM("XSAVEOPT is available in CPU but not available in seL4, disabling for guest\n"); } -#endif +#endif /* !CONFIG_XSAVE_XSAVEOPT */ #if !defined(CONFIG_XSAVE_XSAVES) if (vctx->eax & BIT(3)) { vctx->eax &= ~BIT(3); - // LOG_VMM("XSAVES is available in CPU but not available in seL4, disabling for guest\n"); } -#endif +#endif /* !CONFIG_XSAVE_XSAVES */ } break; } @@ -161,11 +153,8 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) case 0x80000007: /* Invariant TSC */ case 0x80000008: /* Physical Address size */ /* Passthrough host's values */ - cpuid(vctx->eax, vctx->ecx, &a, &b, &c, &d); - vctx->eax = a; - vctx->ebx = b; - vctx->ecx = c; - vctx->edx = d; + cpuid(vctx->eax, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, + (uint32_t *)&vctx->edx); break; case 0x3: diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 879c904c8..7b655ec68 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -447,8 +448,7 @@ bool fault_handle(size_t vcpu_id) break; } case XSETBV: - // LOG_VMM("XSETBV, rip 0x%lx\n", rip); - success = true; + success = emulate_xsetbv(&vctx); break; default: LOG_VMM_ERR("unhandled fault: 0x%x\n", f_reason); @@ -466,7 +466,7 @@ bool fault_handle(size_t vcpu_id) resume_rip += ins_len; } microkit_vcpu_x86_deferred_resume(resume_rip, VMCS_PCC_DEFAULT, 0); - } else if (!success && (f_reason == RDMSR || f_reason == WRMSR)) { + } else if (!success && (f_reason == RDMSR || f_reason == WRMSR || f_reason == XSETBV)) { // From [2b] "Specifying a reserved or unimplemented MSR address in ECX will also cause a // general protection exception." microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE, 0); diff --git a/src/arch/x86_64/fpu.c b/src/arch/x86_64/fpu.c new file mode 100644 index 000000000..3d064cddb --- /dev/null +++ b/src/arch/x86_64/fpu.c @@ -0,0 +1,35 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* Document referenced + * 1. https://www.felixcloutier.com/x86/xsetbv + * 2. seL4 source: src/arch/x86/machine/fpu.c + */ + +#include +#include +#include + +bool emulate_xsetbv(seL4_VCPUContext *vctx) +{ + /* "Writes the contents of registers EDX:EAX into the 64-bit + * extended control register (XCR) specified in the ECX register." */ + + /* "Currently, only XCR0 is supported. Thus, all other values of ECX are reserved and will cause a #GP(0)." */ + if (vctx->ecx != 0) { + return false; + } + + /* seL4 will set the host XCR0 to CONFIG_XSAVE_FEATURE_SET, so we + * just need to make sure that the guest is setting the same value. + * See [2] Arch_initFpu() */ + uint64_t value = (uint64_t)((vctx->edx & 0xffffffff) << 32) | (uint64_t)(vctx->eax & 0xffffffff); + if (value != CONFIG_XSAVE_FEATURE_SET) { + return false; + } + + return true; +} \ No newline at end of file diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index 7af99f16c..e6d06f0a6 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -133,6 +133,11 @@ bool emulate_wrmsr(seL4_VCPUContext *vctx) case IA32_PRED_CMD: // @billn revisit, security concerns same as IA32_SPEC_CTRL, as they are used for speculative exec controls break; + case IA32_XSS: + if (value != 0) { + LOG_VMM_ERR("unexpected value 0x%lx written to IA32_XSS\n", value); + } + break; default: LOG_VMM("unknown wrmsr 0x%x, value 0x%lx\n", vctx->ecx, value); return false; diff --git a/vmm.mk b/vmm.mk index 58ee44756..5b1976157 100644 --- a/vmm.mk +++ b/vmm.mk @@ -38,7 +38,8 @@ X86_64_FILES = src/arch/x86_64/fault.c \ src/arch/x86_64/hpet.c \ src/arch/x86_64/pci.c \ src/arch/x86_64/util.c \ - src/arch/x86_64/tsc.c + src/arch/x86_64/tsc.c \ + src/arch/x86_64/fpu.c # VIRTIO MMIO and PCI depends on sddf ifeq ($(strip $(SDDF)),) From 3616d48f4c438d4a2d1cc655dfca85710381486d Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 31 Mar 2026 13:36:47 +1100 Subject: [PATCH 18/42] x86_64: enable VPID for guest performance boost Signed-off-by: Bill Nguyen --- include/libvmm/arch/x86_64/vmcs.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/include/libvmm/arch/x86_64/vmcs.h b/include/libvmm/arch/x86_64/vmcs.h index 98e2039b5..212a01ae3 100644 --- a/include/libvmm/arch/x86_64/vmcs.h +++ b/include/libvmm/arch/x86_64/vmcs.h @@ -13,8 +13,6 @@ * Document referenced: * [1] include/arch/x86/arch/object/vcpu.h * [2] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 Order Number: 325462-080US June 2023 - * [2a] Location: "VIRTUAL MACHINE CONTROL STRUCTURES", page: "25-10 Vol. 3C" - * [2b] Location: "VIRTUAL MACHINE CONTROL STRUCTURES", page: "25-12 Vol. 3C" */ // [1] Virtual Machine Control Structure (VMCS) field selectors used by seL4 @@ -178,21 +176,18 @@ #define VMX_HOST_RSP 0x00006C14 #define VMX_HOST_RIP 0x00006C16 -// [2a] Primary Processor-Based VM-Execution Controls Register +/* [2] "Primary Processor-Based VM-Execution Controls Register" */ #define VMCS_PPC_ACTIVATE_SECONDARY_CTRL BIT(31) #define VMCS_PPC_USE_TPR_SHADOW BIT(21) -#define VMCS_PPC_IRQ_WINDOW_EXITING BIT(2) - #define VMCS_PCC_DEFAULT (VMCS_PPC_USE_TPR_SHADOW | VMCS_PPC_ACTIVATE_SECONDARY_CTRL) -#define VMCS_PCC_EXIT_IRQ_WINDOW (VMCS_PCC_DEFAULT | VMCS_PPC_IRQ_WINDOW_EXITING) - -// [2b] Secondary Processor-Based VM-Execution Controls Register -#define VMCS_SPC_ENABLE_EPT BIT(1) -#define VMCS_SPC_ENABLE_XSAVE BIT(20) -#define VMCS_SPC_ENABLE_VAPIC BIT(0) -#define VMCS_SPC_ENABLE_APIC_REG_VIRT BIT(8) +/* [2] "Definitions of Secondary Processor-Based VM-Execution Controls" */ +#define VMCS_SPC_ENABLE_VAPIC BIT(0) +#define VMCS_SPC_ENABLE_EPT BIT(1) +#define VMCS_SPC_ENABLE_VPID BIT(5) +#define VMCS_SPC_ENABLE_APIC_REG_VIRT BIT(8) #define VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY BIT(9) +#define VMCS_SPC_ENABLE_XSAVES BIT(20) -#define VMCS_SPC_DEFAULT (VMCS_SPC_ENABLE_EPT | VMCS_SPC_ENABLE_XSAVE | VMCS_SPC_ENABLE_VAPIC | VMCS_SPC_ENABLE_APIC_REG_VIRT | VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY) +#define VMCS_SPC_DEFAULT (VMCS_SPC_ENABLE_EPT | VMCS_SPC_ENABLE_VPID | VMCS_SPC_ENABLE_XSAVES | VMCS_SPC_ENABLE_VAPIC | VMCS_SPC_ENABLE_APIC_REG_VIRT | VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY) From 33de4aa7fd3f8e85303ef4278fa08ac3f0251c42 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 31 Mar 2026 14:40:00 +1100 Subject: [PATCH 19/42] x86_64: verify required CR and VT-x features To prevent undefined behaviours. Signed-off-by: Bill Nguyen --- examples/simple/vmm.c | 5 +- include/libvmm/arch/x86_64/vcpu.h | 21 ++++--- include/libvmm/arch/x86_64/vmcs.h | 8 +++ include/libvmm/util/util.h | 7 +++ src/arch/x86_64/vcpu.c | 95 ++++++++++++++++++++----------- src/util/util.c | 15 +++++ 6 files changed, 109 insertions(+), 42 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index e8c2de3be..ca1cbe105 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -112,7 +112,10 @@ void init(void) return; } - vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit); + if (!vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit)) { + LOG_VMM_ERR("Failed to set up virtual CPU\n"); + return; + } /* Set up the virtual PCI bus */ assert(pci_x86_init()); diff --git a/include/libvmm/arch/x86_64/vcpu.h b/include/libvmm/arch/x86_64/vcpu.h index b02b430a7..5e9e45211 100644 --- a/include/libvmm/arch/x86_64/vcpu.h +++ b/include/libvmm/arch/x86_64/vcpu.h @@ -21,8 +21,8 @@ /* "CR0 — Contains system control flags that control operating mode and states of the processor." * Consult [1a] for more details */ -#define CR0_PG BIT_LOW(31) /* Paging On */ -#define CR0_PE BIT_LOW(0) /* Protection Enable */ +#define CR0_PG BIT(31) /* Paging On */ +#define CR0_PE BIT(0) /* Protection Enable */ #define CR0_DEFAULT (CR0_PG | CR0_PE) @@ -30,26 +30,29 @@ * operating system or executive support for specific processor capabilities." * Consult [1b] for more details */ -#define CR4_PAE BIT_LOW(5) /* Physical Address Extension */ -// @billn do we need CR4.PGE and CR4.MCE as well? +#define CR4_PAE BIT(5) /* Physical Address Extension */ +#define CR4_OSFXSR BIT(9) /* Operating system support for FXSAVE and FXRSTOR instructions */ +#define CR4_VMXE BIT(13) /* Virtual Machine Extensions Enable */ +#define CR4_OSXSAVE BIT(18) /* XSAVE and Processor Extended States Enable */ -#define CR4_DEFAULT (CR4_PAE) +#define CR4_DEFAULT (CR4_PAE | CR4_OSFXSR | CR4_OSXSAVE) +#define CR4_EN_MASK (CR4_VMXE) /* Extended Feature Enable Register: "provides several fields related to IA-32e mode * enabling and operation" * Note: "IA-32e" is just Intel's name for long mode. * Consult [1c] for more details */ -#define IA32_EFER_LME (BIT_LOW(8) | BIT_LOW(10)) /* Enable IA-32e mode operation */ +#define IA32_EFER_LME (BIT(8) | BIT(10)) /* Enable IA-32e mode operation */ -#define IA32_EFER_DEFAULT (IA32_EFER_LME) +/* Long mode default */ +#define IA32_EFER_LM_DEFAULT (IA32_EFER_LME) /* The 32-bit EFLAGS/RFLAGS register contains a group of status flags, a control flag, and a group of system flags. * We don't use anything here during boot to mask all IRQs, but the 2nd bit must always be set as 1. See [1d] */ #define RFLAGS_DEFAULT BIT(1) -void vcpu_set_up_reset_state(uint64_t vapic_page_paddr, uint64_t apic_access_page_paddr); -void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit); +bool vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit); void vcpu_print_regs(size_t vcpu_id); diff --git a/include/libvmm/arch/x86_64/vmcs.h b/include/libvmm/arch/x86_64/vmcs.h index 212a01ae3..5660cd471 100644 --- a/include/libvmm/arch/x86_64/vmcs.h +++ b/include/libvmm/arch/x86_64/vmcs.h @@ -191,3 +191,11 @@ #define VMCS_SPC_ENABLE_XSAVES BIT(20) #define VMCS_SPC_DEFAULT (VMCS_SPC_ENABLE_EPT | VMCS_SPC_ENABLE_VPID | VMCS_SPC_ENABLE_XSAVES | VMCS_SPC_ENABLE_VAPIC | VMCS_SPC_ENABLE_APIC_REG_VIRT | VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY) + +/* [2] "Definitions of VM-Entry Controls" */ +#define VMCS_VEC_ENABLE_IA32E BIT(9) +#define VMCS_VEC_LOAD_IA32_PAT BIT(14) +#define VMCS_VEC_LOAD_IA32_EFER BIT(15) + +/* Long mode default */ +#define VMCS_VEC_LM_DEFAULT (VMCS_VEC_ENABLE_IA32E | VMCS_VEC_LOAD_IA32_EFER) \ No newline at end of file diff --git a/include/libvmm/util/util.h b/include/libvmm/util/util.h index ba12f14c0..94129743d 100644 --- a/include/libvmm/util/util.h +++ b/include/libvmm/util/util.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -64,6 +65,12 @@ void print_mem_hex(uintptr_t addr, size_t size); #endif #endif +/* Returns true if all set bits in `baseline` are also set in `actual` */ +bool check_baseline_bits(uint64_t baseline, uint64_t actual); + +/* Print all bit indexes that are set in `baseline` but not set in `actual` */ +void print_missing_baseline_bits(uint64_t baseline, uint64_t actual); + #if defined(CONFIG_ARCH_X86_64) static inline uint64_t rdtsc(void) { diff --git a/src/arch/x86_64/vcpu.c b/src/arch/x86_64/vcpu.c index 27a21d590..9780f22cb 100644 --- a/src/arch/x86_64/vcpu.c +++ b/src/arch/x86_64/vcpu.c @@ -16,35 +16,73 @@ #include #include -void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit) -{ - // @billn explain +/* Document referenced: + * [1] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 + * Order Number: 325462-080US June 2023 + */ - // Set up system registers +bool vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit) +{ + /* Set up control registers */ microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR0, CR0_DEFAULT); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR3, cr3); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4, CR4_DEFAULT); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER, IA32_EFER_DEFAULT); + /* Prevent guest from turning off VM mode */ + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_CR4_MASK, CR4_EN_MASK); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_EFER, IA32_EFER_LM_DEFAULT); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_RFLAGS, RFLAGS_DEFAULT); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GDTR_BASE, gdt_gpa); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GDTR_LIMIT, gdt_limit); + + /* Check that all CR0 and CR4 features we need are supported by the host. + * We perform this check because seL4 will clear any unsupported feature bits. */ + uint64_t read_back_cr0 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR0); + if (!check_baseline_bits(CR0_DEFAULT, read_back_cr0)) { + LOG_VMM_ERR("required Control Register 0 (CR0) features not supported.\n"); + LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", CR0_DEFAULT, read_back_cr0); + print_missing_baseline_bits(CR0_DEFAULT, read_back_cr0); + return false; + } + + uint64_t read_back_cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); + if (!check_baseline_bits(CR4_DEFAULT, read_back_cr4)) { + LOG_VMM_ERR("required Control Register 4 (CR4) features not supported.\n"); + LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", CR4_DEFAULT, read_back_cr4); + print_missing_baseline_bits(CR4_DEFAULT, read_back_cr4); + return false; + } + + /* Set up VMCS control registers */ microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS, VMCS_PCC_DEFAULT); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS, VMCS_SPC_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS, VMCS_VEC_LM_DEFAULT); - // These asserts will fail if your host CPU doesn't support all the VT-x features - // that libvmm uses. + /* Check that all the VT-x features we need are supported by the host. */ uint64_t read_back_ppc = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS); - uint64_t read_back_spc = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS); - assert((read_back_ppc & VMCS_PCC_DEFAULT) == VMCS_PCC_DEFAULT); - assert((read_back_spc & VMCS_SPC_DEFAULT) == VMCS_SPC_DEFAULT); + if (!check_baseline_bits(VMCS_PCC_DEFAULT, read_back_ppc)) { + LOG_VMM_ERR("required Primary Processor-Based VM-Execution Controls features not supported.\n"); + LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", VMCS_PCC_DEFAULT, read_back_ppc); + print_missing_baseline_bits(VMCS_PCC_DEFAULT, read_back_ppc); + return false; + } - // @billn explain - // @billn todo add other important bits + uint64_t read_back_spc = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS); + if (!check_baseline_bits(VMCS_SPC_DEFAULT, read_back_spc)) { + LOG_VMM_ERR("required Secondary Processor-Based VM-Execution Controls features not supported.\n"); + LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", VMCS_SPC_DEFAULT, read_back_spc); + print_missing_baseline_bits(VMCS_SPC_DEFAULT, read_back_spc); + return false; + } - // prevent the guest from turning off VMX mode - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_CR4_MASK, 1 << 13); - // @billn todo add other registers with mask + uint64_t read_back_vec = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS); + if (!check_baseline_bits(VMCS_VEC_LM_DEFAULT, read_back_vec)) { + LOG_VMM_ERR("required VM-Entry Controls features not supported.\n"); + LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", VMCS_VEC_LM_DEFAULT, read_back_vec); + print_missing_baseline_bits(VMCS_VEC_LM_DEFAULT, read_back_vec); + return false; + } + /* These aren't useful in long mode so we just leave them in a sane default enough to boot a guest kernel. */ microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_BASE, 0); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_BASE, 0); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_ES_BASE, 0); @@ -66,25 +104,18 @@ void vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit) microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_LIMIT, 0xfffff); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_LIMIT, 0xfffff); - // 25-4 Vol. 3C @billn explain - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_ACCESS_RIGHTS, 0xA09B); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); + /* See [1] "Table 25-2. Format of Access Rights" */ + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CS_ACCESS_RIGHTS, + 0xA09B); // present ring-0 executable 64-bit code segment + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); // present ring-0 data segment microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_ES_ACCESS_RIGHTS, 0xC093); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_SS_ACCESS_RIGHTS, 0xC093); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_ACCESS_RIGHTS, 0x3 | 1 << 4 | 1 << 7 | 1 << 15); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_ACCESS_RIGHTS, 0x3 | 1 << 4 | 1 << 7 | 1 << 15); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_LDTR_ACCESS_RIGHTS, 0x2 | 1 << 7); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_TR_ACCESS_RIGHTS, 0xb | 1 << 7); - - // microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_VIRTUAL_APIC_ADDRESS, vapic_page_paddr); - // microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_APIC_ACCESS_ADDRESS, apic_access_page_paddr); - - // Table 25-16. Definitions of VM-Entry Controls - // load EFER on entry - uint64_t entry_controls = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS); - entry_controls |= BIT(15) | BIT(9); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS, entry_controls); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_FS_ACCESS_RIGHTS, BIT(16)); // not present + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_GS_ACCESS_RIGHTS, BIT(16)); // not present + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_LDTR_ACCESS_RIGHTS, BIT(16)); // not present + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_TR_ACCESS_RIGHTS, 0xb | 1 << 7); // busy 32-bit TSS + + return true; } void vcpu_print_regs(size_t vcpu_id) diff --git a/src/util/util.c b/src/util/util.c index 7561347e0..c49d6f680 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include @@ -27,3 +28,17 @@ void print_mem_hex(uintptr_t addr, size_t size) printf("\n"); #endif } + +bool check_baseline_bits(uint64_t baseline, uint64_t actual) +{ + return (actual & baseline) == baseline; +} + +void print_missing_baseline_bits(uint64_t baseline, uint64_t actual) +{ + for (int i = 0; i < 64; i++) { + if ((baseline & BIT(i)) != (actual & BIT(i))) { + printf("missing bit %d\n", i); + } + } +} From 54fc6cb74c51d253156e98e03df7e6c9b10c93d3 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 31 Mar 2026 14:49:50 +1100 Subject: [PATCH 20/42] examples/simple: bump x86 march to x86-64-v2 Signed-off-by: Bill Nguyen --- examples/simple/build.zig | 2 +- examples/simple/simple.mk | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/simple/build.zig b/examples/simple/build.zig index 0ea1539ae..63ebfc4ed 100644 --- a/examples/simple/build.zig +++ b/examples/simple/build.zig @@ -50,7 +50,7 @@ const targets = [_]Target { .board = MicrokitBoard.x86_64_generic_vtx, .zig_target = std.Target.Query{ .cpu_arch = .x86_64, - .cpu_model = .{ .explicit = std.Target.Cpu.Model.generic(.x86_64) }, + .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 }, .os_tag = .freestanding, .abi = .none, }, diff --git a/examples/simple/simple.mk b/examples/simple/simple.mk index 0d42f2651..3987c8e3e 100644 --- a/examples/simple/simple.mk +++ b/examples/simple/simple.mk @@ -30,7 +30,8 @@ else ifeq ($(ARCH),x86_64) LINUX ?= be4206493bcc7234a8713319b7c6280fa04f9c5a-bzImage INITRD ?= d887a642236a92610a9537ab9f4a4aa1a966ad3a-rootfs.cpio.gz DSDT_AML ?= $(SYSTEM_DIR)/simple_dsdt.aml - ARCH_FLAGS := -target x86_64-unknown-elf +# -march=x86-64-v2 so that we get extra optimisations without AVX, since seL4 doesnt't enable it by default + ARCH_FLAGS := -target x86_64-unknown-elf -march=x86-64-v2 IMAGES += timer_driver.elf QEMU := qemu-system-x86_64 From 1edede118dd308d177665f50bb51cdd35c392e59 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 31 Mar 2026 16:35:58 +1100 Subject: [PATCH 21/42] x86_64: verify required CPUID feature bits Signed-off-by: Bill Nguyen --- examples/simple/vmm.c | 6 ++ include/libvmm/arch/x86_64/cpuid.h | 26 ++++--- src/arch/x86_64/cpuid.c | 112 ++++++++++++++++++++++++----- src/util/util.c | 2 +- 4 files changed, 112 insertions(+), 34 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index ca1cbe105..5fbcd316c 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -131,6 +131,12 @@ void init(void) return; } + /* Initialise CPUID */ + if (!initialise_cpuid(tsc_hz)) { + LOG_VMM_ERR("cannot initialise CPUID\n"); + return; + } + /* Initialise the virtual Local and I/O APICs */ // @billn revisit vapic vaddr bool success = virq_controller_init(tsc_hz, 0xfffffffffffffff); diff --git a/include/libvmm/arch/x86_64/cpuid.h b/include/libvmm/arch/x86_64/cpuid.h index 665f8511f..29b030617 100644 --- a/include/libvmm/arch/x86_64/cpuid.h +++ b/include/libvmm/arch/x86_64/cpuid.h @@ -8,6 +8,14 @@ #include +/* Documents referenced: + * 1. Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 + * Order Number: 325462-080US June 2023 + * 2. https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels + * 3. https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.txt + */ + #define CACHE_LINE_SIZE 64 #define NUM_LOGICAL_PROCESSORS 1 @@ -23,12 +31,9 @@ /* [1] Table 3-10. More on Feature Information Returned in the ECX Register */ #define CPUID_1H_ECX_SSE3 BIT(0) #define CPUID_1H_ECX_PCLMULQDQ BIT(1) -#define CPUID_1H_ECX_DTES64 BIT(2) // DTES64: 64-bit DS area -#define CPUID_1H_ECX_DS_CPL BIT(4) // DS-CPL: CPL qualified debug store #define CPUID_1H_ECX_SSSE3 BIT(9) #define CPUID_1H_ECX_FMA BIT(12) #define CPUID_1H_ECX_CMPXCHG16B BIT(13) -#define CPUID_1H_ECX_XTPR BIT(14) // xTPR update control #define CPUID_1H_ECX_SSE4_1 BIT(19) #define CPUID_1H_ECX_SSE4_2 BIT(20) #define CPUID_1H_ECX_MOVBE BIT(22) @@ -59,21 +64,18 @@ #define CPUID_1H_EDX_SSE1 BIT(25) #define CPUID_1H_EDX_SSE2 BIT(26) #define CPUID_1H_EDX_SELF_SNOOP BIT(27) -#define CPUID_1H_EDX_PBE BIT(31) // PBE: Pending Break Enable /* [1] Table 3-8. Information Returned by CPUID Instruction */ #define CPUID_7H_EAX_MAX_SUBLEAF 0 #define CPUID_7H_00_EBX_FSGSBASE BIT(0) #define CPUID_7H_00_EBX_BMI1 BIT(3) -#define CPUID_7H_00_EBX_AVX2 BIT(5) #define CPUID_7H_00_EBX_SMEP BIT(7) // SMEP: Supervisor Mode Execution Protection #define CPUID_7H_00_EBX_BMI2 BIT(8) #define CPUID_7H_00_EBX_DEPRECATE_FCS_FDS BIT(13) // Deprecates FPU CS and FPU DS values #define CPUID_7H_00_EBX_ADX BIT(19) // ADCX/ADOX instructions support #define CPUID_7H_00_EBX_SMAP BIT(20) // SMAP: Supervisor Mode Access Prevention #define CPUID_7H_00_EBX_CLFLUSHOPT BIT(23) -#define CPUID_7H_00_EBX_CLWB BIT(24) #define CPUID_80000000H_EAX_MAX_EXT_LEAF 0x80000008 @@ -102,12 +104,9 @@ #define CPUID_1H_X64_V2_BASELINE_ECX ( \ CPUID_1H_ECX_SSE3 | \ CPUID_1H_ECX_PCLMULQDQ | \ - CPUID_1H_ECX_DTES64 | \ - CPUID_1H_ECX_DS_CPL | \ CPUID_1H_ECX_SSSE3 | \ CPUID_1H_ECX_FMA | \ CPUID_1H_ECX_CMPXCHG16B | \ - CPUID_1H_ECX_XTPR | \ CPUID_1H_ECX_SSE4_1 | \ CPUID_1H_ECX_SSE4_2 | \ CPUID_1H_ECX_MOVBE | \ @@ -147,8 +146,7 @@ CPUID_1H_EDX_FXSR | \ CPUID_1H_EDX_SSE1 | \ CPUID_1H_EDX_SSE2 | \ - CPUID_1H_EDX_SELF_SNOOP | \ - CPUID_1H_EDX_PBE \ + CPUID_1H_EDX_SELF_SNOOP \ ) /* No: @@ -160,14 +158,12 @@ #define CPUID_7H_0_X64_V2_BASELINE_EBX ( \ CPUID_7H_00_EBX_FSGSBASE | \ CPUID_7H_00_EBX_BMI1 | \ - CPUID_7H_00_EBX_AVX2 | \ CPUID_7H_00_EBX_SMEP | \ CPUID_7H_00_EBX_BMI2 | \ CPUID_7H_00_EBX_DEPRECATE_FCS_FDS | \ CPUID_7H_00_EBX_ADX | \ CPUID_7H_00_EBX_SMAP | \ - CPUID_7H_00_EBX_CLFLUSHOPT | \ - CPUID_7H_00_EBX_CLWB \ + CPUID_7H_00_EBX_CLFLUSHOPT \ ) #define CPUID_80000001H_X64_V2_BASELINE_ECX ( \ @@ -183,4 +179,6 @@ CPUID_80000001_EDX_LONG_MODE \ ) +bool initialise_cpuid(uint64_t tsc_hz); + bool emulate_cpuid(seL4_VCPUContext *vctx); diff --git a/src/arch/x86_64/cpuid.c b/src/arch/x86_64/cpuid.c index f30984b7e..1dad4b15e 100644 --- a/src/arch/x86_64/cpuid.c +++ b/src/arch/x86_64/cpuid.c @@ -15,22 +15,96 @@ * 1. Intel® 64 and IA-32 Architectures Software Developer’s Manual * Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 * Order Number: 325462-080US June 2023 - * 2. https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels - * 3. https://github.com/bochs-emu/Bochs/blob/master/bochs/cpu/cpudb/intel/corei7_skylake-x.txt */ /* 4 chars per 32-bit register, 4 registers per leaf, 3 leafs */ #define CPUID_BRAND_STR_LEN (4 * 4 * 3) static const char brand_string[CPUID_BRAND_STR_LEN] = "Trustworthy Systems CPU"; -extern uint64_t tsc_hz; +struct cpuid_state { + bool valid; + uint64_t tsc_hz; +}; + +static struct cpuid_state cpuid_state = { .valid = false }; + +bool initialise_cpuid(uint64_t tsc_hz) +{ + /* Same idea as vcpu.c, we need to check that all CPU features advertised to the guest are + * supported by the host CPU. Otherwise guests can crash with undefined opcode. */ + + uint32_t a, b, c, d; + + /* Make sure that leaf 0.."Processor Extended State Enumeration" inclusive are enumerated. + * Because we also passthrough values for leafs in this range. + */ + uint32_t max_basic_leaf; + cpuid(0, 0, &max_basic_leaf, &b, &c, &d); + if (max_basic_leaf < 0xd) { + LOG_VMM_ERR("Host CPU does not enumerate basic CPUID leafs up to and including 0xd\n"); + return false; + } + + /* Check baseline of basic leafs */ + cpuid(0x1, 0, &a, &b, &c, &d); + if (!check_baseline_bits(CPUID_1H_X64_V2_BASELINE_ECX, c)) { + LOG_VMM_ERR("Missing required features in host CPUID leaf 0x1 ECX\n"); + LOG_VMM_ERR("Baseline: 0x%lx, actual: 0x%lx\n", CPUID_1H_X64_V2_BASELINE_ECX, c); + print_missing_baseline_bits(CPUID_1H_X64_V2_BASELINE_ECX, c); + return false; + } + if (!check_baseline_bits(CPUID_1H_X64_V2_BASELINE_EDX, d)) { + LOG_VMM_ERR("Missing required features in host CPUID leaf 0x1 EDX\n"); + LOG_VMM_ERR("Baseline: 0x%lx, actual: 0x%lx\n", CPUID_1H_X64_V2_BASELINE_EDX, d); + print_missing_baseline_bits(CPUID_1H_X64_V2_BASELINE_EDX, d); + return false; + } + + cpuid(0x7, 0, &a, &b, &c, &d); + if (!check_baseline_bits(CPUID_7H_0_X64_V2_BASELINE_EBX, b)) { + LOG_VMM_ERR("Missing required features in host CPUID leaf 0x7 EBX\n"); + LOG_VMM_ERR("Baseline: 0x%lx, actual: 0x%lx\n", CPUID_7H_0_X64_V2_BASELINE_EBX, b); + print_missing_baseline_bits(CPUID_7H_0_X64_V2_BASELINE_EBX, b); + return false; + } + + /* Now check whether the host CPU enumerates "Extended Processor Signature and Feature Bits" */ + uint32_t max_ext_leaf; + cpuid(0x80000000, 0, &max_ext_leaf, &b, &c, &d); + if (max_ext_leaf < 0x80000001) { + LOG_VMM_ERR("Host CPU does not enumerate Extended Processor Signature and Feature Bits leaf\n"); + return false; + } + + /* Then check extended leaf feature baseline */ + cpuid(0x80000001, 0, &max_ext_leaf, &b, &c, &d); + if (!check_baseline_bits(CPUID_80000001H_X64_V2_BASELINE_ECX, c)) { + LOG_VMM_ERR("Missing required features in host CPUID leaf 0x800000001 ECX\n"); + LOG_VMM_ERR("Baseline: 0x%lx, actual: 0x%lx\n", CPUID_80000001H_X64_V2_BASELINE_ECX, c); + print_missing_baseline_bits(CPUID_80000001H_X64_V2_BASELINE_ECX, c); + return false; + } + + if (!check_baseline_bits(CPUID_80000001H_X64_V2_BASELINE_EDX, d)) { + LOG_VMM_ERR("Missing required features in host CPUID leaf 0x800000001 EDX\n"); + LOG_VMM_ERR("Baseline: 0x%lx, actual: 0x%lx\n", CPUID_80000001H_X64_V2_BASELINE_EDX, d); + print_missing_baseline_bits(CPUID_80000001H_X64_V2_BASELINE_EDX, d); + return false; + } + + cpuid_state = (struct cpuid_state) { + .valid = true, + .tsc_hz = tsc_hz, + }; + return true; +} bool emulate_cpuid(seL4_VCPUContext *vctx) { LOG_FAULT("handling CPUID 0x%x\n", vctx->eax); switch (vctx->eax) { - case 0x0: /* Basic CPUID Information */ + case 0x0: /* "Basic CPUID Information" */ vctx->eax = CPUID_0H_EAX_MAX_BASIC_LEAF; vctx->ebx = CPUID_0H_GENUINEINTEL_EBX; vctx->edx = CPUID_0H_GENUINEINTEL_EDX; @@ -44,16 +118,16 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) vctx->edx = CPUID_1H_X64_V2_BASELINE_EDX; break; - case 0x2: /* Cache and TLB Information */ + case 0x2: /* "Cache and TLB Information" */ - case 0x4: /* Deterministic Cache Parameters */ + case 0x4: /* "Deterministic Cache Parameters" */ /* Passthrough host's values */ cpuid(vctx->eax, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, (uint32_t *)&vctx->edx); break; - case 0x7: /* Structured Extended Feature Flags Enumeration */ - if (vctx->ecx == CPUID_7H_EAX_MAX_SUBLEAF && vctx->ecx == 0) { + case 0x7: /* "Structured Extended Feature Flags Enumeration" */ + if (vctx->ecx == 0) { vctx->ebx = CPUID_7H_0_X64_V2_BASELINE_EBX; } vctx->eax = 0; @@ -61,7 +135,7 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) vctx->edx = 0; break; - case 0xb: /* Extended Topology Enumeration Leaf */ + case 0xb: /* "Extended Topology Enumeration Leaf" */ // @billn revisit for multiple VCPUs vctx->eax = 0; vctx->ebx = 0; @@ -69,7 +143,7 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) vctx->edx = 0; // x2apic id, though we don't use x2apic break; - case 0xd: { /* Processor Extended State Enumeration */ + case 0xd: { /* "Processor Extended State Enumeration" */ uint32_t ecx = vctx->ecx; cpuid(0xd, vctx->ecx, (uint32_t *)&vctx->eax, (uint32_t *)&vctx->ebx, (uint32_t *)&vctx->ecx, (uint32_t *)&vctx->edx); @@ -98,28 +172,28 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) break; } - case 0x15: /* Time Stamp Counter and Nominal Core Crystal Clock */ + case 0x15: /* "Time Stamp Counter and Nominal Core Crystal Clock" */ vctx->eax = 1; /* Making ratio between Crystal and TSC 1-to-1 */ vctx->ebx = 1; - vctx->ecx = tsc_hz; + vctx->ecx = cpuid_state.tsc_hz; vctx->edx = 0; break; - case 0x16: /* Processor Frequency Information Leaf */ + case 0x16: /* "Processor Frequency Information Leaf" */ /* CPU base, max and bus frequency in MHz */ - vctx->eax = tsc_hz / 1000000; - vctx->ebx = tsc_hz / 1000000; - vctx->ecx = tsc_hz / 1000000; + vctx->eax = cpuid_state.tsc_hz / 1000000; + vctx->ebx = cpuid_state.tsc_hz / 1000000; + vctx->ecx = cpuid_state.tsc_hz / 1000000; vctx->edx = 0; break; - case 0x80000000: /* Extended Function CPUID Information */ + case 0x80000000: /* "Extended Function CPUID Information" */ vctx->eax = CPUID_80000000H_EAX_MAX_EXT_LEAF; /* max input value for extended function cpuid information */ vctx->ebx = 0; vctx->ecx = 0; vctx->edx = 0; break; - case 0x80000001: /* Extended Processor Signature and Feature Bits */ + case 0x80000001: /* "Extended Processor Signature and Feature Bits" */ vctx->eax = 0; vctx->ebx = 0; vctx->ecx = CPUID_80000001H_X64_V2_BASELINE_ECX; @@ -130,7 +204,7 @@ bool emulate_cpuid(seL4_VCPUContext *vctx) } break; - case 0x80000002: /* Processor Brand String. */ + case 0x80000002: /* "Processor Brand String." */ memcpy(&(vctx->eax), brand_string, 4); memcpy(&(vctx->ebx), brand_string + 4, 4); memcpy(&(vctx->ecx), brand_string + 8, 4); diff --git a/src/util/util.c b/src/util/util.c index c49d6f680..0e332c067 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -37,7 +37,7 @@ bool check_baseline_bits(uint64_t baseline, uint64_t actual) void print_missing_baseline_bits(uint64_t baseline, uint64_t actual) { for (int i = 0; i < 64; i++) { - if ((baseline & BIT(i)) != (actual & BIT(i))) { + if ((baseline & BIT(i)) && !(actual & BIT(i))) { printf("missing bit %d\n", i); } } From 45a295858e8f4769caf530595ea118d3f5320fdb Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 1 Apr 2026 11:46:34 +1100 Subject: [PATCH 22/42] x86_64: remove PIO string ops for initial PR Signed-off-by: Bill Nguyen --- src/arch/x86_64/ioports.c | 78 +-------------------------------------- 1 file changed, 2 insertions(+), 76 deletions(-) diff --git a/src/arch/x86_64/ioports.c b/src/arch/x86_64/ioports.c index 9edf2113d..ee716e430 100644 --- a/src/arch/x86_64/ioports.c +++ b/src/arch/x86_64/ioports.c @@ -47,78 +47,14 @@ int ioports_access_width_to_bytes(ioport_access_width_t access_width) } } -int emulate_ioport_string_write(seL4_VCPUContext *vctx, char *dest, size_t data_len, bool is_rep, - ioport_access_width_t access_width) -{ - int data_index = 0; - int max_iterations = 1; - uint64_t eflags = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RFLAGS); - - if (is_rep) { - max_iterations = vctx->ecx; - } - - int iteration = 0; - for (; iteration < max_iterations && data_index < data_len; iteration++) { - uint64_t src_gpa; - uint64_t bytes_to_page_boundary; - assert(gva_to_gpa(0, vctx->esi, &src_gpa, &bytes_to_page_boundary)); - char *src = gpa_to_vaddr(src_gpa); - - assert(bytes_to_page_boundary >= ioports_access_width_to_bytes(access_width)); - - memcpy(&dest[data_index], src, ioports_access_width_to_bytes(access_width)); - - if (eflags & BIT(10)) { - vctx->esi -= ioports_access_width_to_bytes(access_width); - } else { - vctx->esi += ioports_access_width_to_bytes(access_width); - } - data_index += ioports_access_width_to_bytes(access_width); - } - - return ioports_access_width_to_bytes(access_width) * data_index; -} - -int emulate_ioport_string_read(seL4_VCPUContext *vctx, char *data, size_t data_len, bool is_rep, - ioport_access_width_t access_width) -{ - int data_index = 0; - int max_iterations = 1; - uint64_t eflags = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RFLAGS); - - if (is_rep) { - max_iterations = vctx->ecx; - } - - int iteration = 0; - for (; iteration < max_iterations && data_index < data_len; iteration++) { - uint64_t dest_gpa; - uint64_t bytes_to_page_boundary; - assert(gva_to_gpa(0, vctx->edi, &dest_gpa, &bytes_to_page_boundary)); - char *dest = gpa_to_vaddr(dest_gpa); - - assert(bytes_to_page_boundary >= ioports_access_width_to_bytes(access_width)); - - memcpy(dest, &data[data_index], ioports_access_width_to_bytes(access_width)); - - if (eflags & BIT(10)) { - vctx->edi -= ioports_access_width_to_bytes(access_width); - } else { - vctx->edi += ioports_access_width_to_bytes(access_width); - } - data_index += ioports_access_width_to_bytes(access_width); - } - - return ioports_access_width_to_bytes(access_width) * data_index; -} - bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) { uint64_t is_read = f_qualification & BIT(3); uint64_t is_string = f_qualification & BIT(4); uint16_t port_addr = (f_qualification >> 16) & 0xffff; + assert(!is_string); + bool success = false; if (is_read) { @@ -127,7 +63,6 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) } if (port_addr >= 0xC000 && port_addr < 0xCFFF) { - assert(!is_string); if (is_read) { // invalid read to simulate no device on pci bus vctx->eax = 0xffffffff; @@ -135,7 +70,6 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) success = true; } else if (port_addr == 0xA0 || port_addr == 0xA1 || port_addr == 0x20 || port_addr == 0x21 || port_addr == 0x4d1 || port_addr == 0x4d0) { - assert(!is_string); // PIC1/2 access if (is_read) { // invalid read @@ -144,36 +78,29 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) success = true; } else if (port_addr == 0x70 || port_addr == 0x71) { // cmos - assert(!is_string); success = true; } else if (port_addr == 0x80) { - assert(!is_string); // io port access delay, no-op if (!is_read) { success = true; } } else if (port_addr == 0x3f2) { - assert(!is_string); // floppy disk, seems sus, when booting memtest in nixos, it will write IRQ enable to this register and hangs... success = true; } else if (port_addr == 0x87 || (port_addr >= 0 && port_addr <= 0x1f)) { - assert(!is_string); // dma controller success = true; } else if (port_addr == 0x2f9) { - assert(!is_string); // parallel port success = true; } else if (port_addr == 0x3e9 || port_addr == 0x2e9) { - assert(!is_string); // some sort of serial device success = true; } else if (port_addr >= 0x60 && port_addr <= 0x64) { - assert(!is_string); // PS2 controller success = true; } else if (port_addr >= 0xAF00 && port_addr <= 0xaf00 + 12) { @@ -187,7 +114,6 @@ bool emulate_ioports(seL4_VCPUContext *vctx, uint64_t f_qualification) success = true; } else if (port_addr == 0x92) { // TODO: handle properly, I don't understand why UEFI is touching A20 gate register - assert(!is_string); success = true; } else if (port_addr == 0xb004) { vctx->eax = 0; From 93bee54fbddd7dc9d6648c053142012ed3ac81bb Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 1 Apr 2026 11:50:41 +1100 Subject: [PATCH 23/42] x86_64: properly manage RAM and GPA translations Signed-off-by: Bill Nguyen --- examples/simple/vmm.c | 8 +- include/libvmm/arch/x86_64/guest_ram.h | 38 +++++ include/libvmm/arch/x86_64/memory_space.h | 25 ---- include/libvmm/guest.h | 4 +- include/libvmm/libvmm.h | 1 + include/libvmm/util/util.h | 3 + src/arch/aarch64/guest.c | 7 +- src/arch/x86_64/acpi.c | 2 +- src/arch/x86_64/fault.c | 38 +---- src/arch/x86_64/guest.c | 98 ------------- src/arch/x86_64/guest_ram.c | 164 ++++++++++++++++++++++ src/arch/x86_64/instruction.c | 12 +- src/arch/x86_64/linux.c | 2 +- src/arch/x86_64/msr.c | 8 +- src/arch/x86_64/pci.c | 2 +- src/arch/x86_64/util.c | 6 - src/arch/x86_64/vcpu.c | 15 -- src/util/util.c | 5 + vmm.mk | 3 +- 19 files changed, 234 insertions(+), 207 deletions(-) create mode 100644 include/libvmm/arch/x86_64/guest_ram.h delete mode 100644 include/libvmm/arch/x86_64/memory_space.h create mode 100644 src/arch/x86_64/guest_ram.c diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index 5fbcd316c..70b2dc78e 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -63,12 +63,6 @@ extern char _guest_initrd_image_end[]; /* Data for the guest's ACPI Differentiated System Description Table (DSDT). */ extern char _guest_dsdt_aml[]; extern char _guest_dsdt_aml_end[]; - -// @billn sort out ridiculousness -uintptr_t guest_high_ram_vaddr; -uintptr_t guest_flash_vaddr; -uint64_t guest_high_ram_size; - #else /* Data for the device tree to be passed to the kernel. */ extern char _guest_dtb_image[]; @@ -105,6 +99,8 @@ void init(void) return; } + assert(guest_ram_add_region(LOW_RAM_START_GPA, guest_ram_vaddr, GUEST_RAM_SIZE)); + if (!linux_setup_images(guest_ram_vaddr, GUEST_RAM_SIZE, (uintptr_t)_guest_kernel_image, kernel_size, (uintptr_t)_guest_initrd_image, initrd_size, _guest_dsdt_aml, dsdt_aml_size, GUEST_CMDLINE, &linux_setup)) { diff --git a/include/libvmm/arch/x86_64/guest_ram.h b/include/libvmm/arch/x86_64/guest_ram.h new file mode 100644 index 000000000..7658daf0c --- /dev/null +++ b/include/libvmm/arch/x86_64/guest_ram.h @@ -0,0 +1,38 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +/* Document layout of guest RAM */ +#define LOW_RAM_START_GPA 0x0 + +#define ECAM_GPA 0xD0000000 +/* 1 bus, 32 devices per bus, 8 functions per device, 4k config space per function */ +#define ECAM_SIZE (1 * 32 * 8 * 4096) + +#define IOAPIC_GPA 0xFEC00000 +#define IOAPIC_SIZE 0x1000 + +/* This just matches the x86 CPU default physical address from + * See bit 9 of 'Table 1-20. More on Feature Information Returned in the EDX Register'. + */ +#define LAPIC_GPA 0xFEE00000 +#define LAPIC_SIZE 0x1000 + +/* Standard x86 PC convention */ +#define HPET_GPA 0xFED00000 +#define HPET_SIZE 0x1000 + +#define HIGH_RAM_START_GPA 0x100000000 +/* End of guest RAM layout */ + +/* enough for low RAM + high RAM and a firmware region */ +#define MAX_GUEST_RAM_REGIONS 3 + +bool guest_ram_add_region(uint64_t gpa, uintptr_t vmm_vaddr, uint64_t size); diff --git a/include/libvmm/arch/x86_64/memory_space.h b/include/libvmm/arch/x86_64/memory_space.h deleted file mode 100644 index bcd51bf4e..000000000 --- a/include/libvmm/arch/x86_64/memory_space.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2026, UNSW - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -/* Document layout of guest RAM */ - -#define LOW_RAM_START_GPA 0x0 - -#define ECAM_GPA 0xD0000000 -// 1 bus, 32 devices per bus, 8 functions per device, 4k config space per function -#define ECAM_SIZE (1 * 32 * 8 * 4096) - -#define IOAPIC_GPA 0xFEC00000 -#define IOAPIC_SIZE 0x1000 - -// This just matches the x86 CPU default physical address from -// See bit 9 of 'Table 1-20. More on Feature Information Returned in the EDX Register'. -#define LAPIC_GPA 0xFEE00000 -#define LAPIC_SIZE 0x1000 - -#define HPET_GPA 0xFED00000 -#define HPET_SIZE 0x1000 \ No newline at end of file diff --git a/include/libvmm/guest.h b/include/libvmm/guest.h index 216f1ddc9..722fc519d 100644 --- a/include/libvmm/guest.h +++ b/include/libvmm/guest.h @@ -39,11 +39,11 @@ void guest_stop(); bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size); // Convert guest physical address to the VMM's virtual memory address. -void *gpa_to_vaddr(uint64_t gpa); +bool gpa_to_vaddr(uint64_t gpa, void **ret, int *bytes_remaining); #if defined(CONFIG_ARCH_X86) bool guest_paging_on(void); bool guest_in_64_bits(void); -bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, uint64_t *bytes_remaining); +bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, int *bytes_remaining); uint64_t gpa_to_pa(uint64_t gpa); #endif \ No newline at end of file diff --git a/include/libvmm/libvmm.h b/include/libvmm/libvmm.h index 15846df36..d8477cd20 100644 --- a/include/libvmm/libvmm.h +++ b/include/libvmm/libvmm.h @@ -41,4 +41,5 @@ #include #include #include +#include #endif diff --git a/include/libvmm/util/util.h b/include/libvmm/util/util.h index 94129743d..b2b93c1d9 100644 --- a/include/libvmm/util/util.h +++ b/include/libvmm/util/util.h @@ -71,6 +71,9 @@ bool check_baseline_bits(uint64_t baseline, uint64_t actual); /* Print all bit indexes that are set in `baseline` but not set in `actual` */ void print_missing_baseline_bits(uint64_t baseline, uint64_t actual); +/* Returns true if two [x..y) ranges overlap. */ +bool ranges_overlap(uint64_t left_start, uint64_t left_size, uint64_t right_start, uint64_t right_size); + #if defined(CONFIG_ARCH_X86_64) static inline uint64_t rdtsc(void) { diff --git a/src/arch/aarch64/guest.c b/src/arch/aarch64/guest.c index 39eba3eb9..48feb0632 100644 --- a/src/arch/aarch64/guest.c +++ b/src/arch/aarch64/guest.c @@ -6,7 +6,10 @@ #include -void *gpa_to_vaddr(uint64_t gpa) +bool gpa_to_vaddr(uint64_t gpa, void **ret, int *bytes_remaining) { - return (void *)gpa; + /* On ARM we make have 1 to 1 mapping so nothing to do. */ + *bytes_remaining = 0; + *ret = (void *) gpa; + return true; } diff --git a/src/arch/x86_64/acpi.c b/src/arch/x86_64/acpi.c index bc2867633..705a00d58 100644 --- a/src/arch/x86_64/acpi.c +++ b/src/arch/x86_64/acpi.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 7b655ec68..20d79e429 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -480,43 +480,7 @@ bool fault_handle(size_t vcpu_id) microkit_vcpu_x86_deferred_resume(rip, VMCS_PCC_DEFAULT, interruption); } else if (!success) { LOG_VMM_ERR("failed handling fault: '%s' (0x%x)\n", fault_to_string(f_reason), f_reason); - LOG_VMM_ERR("paging on: %s\n", guest_paging_on() ? "YES" : "NO"); - if (guest_paging_on()) { - uint64_t _sp_gpa, _bytes_remaining; - bool sp_valid = gva_to_gpa(0, microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RSP), &_sp_gpa, &_bytes_remaining); - LOG_VMM_ERR("stack pointer valid: %s\n", sp_valid ? "YES" : "NO"); - - uint64_t idtr_gva = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_BASE); - uint64_t idtr_limit = microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_IDTR_LIMIT); - uint64_t idtr_gpa; - bool idtr_valid = gva_to_gpa(0, idtr_gva, &idtr_gpa, &_bytes_remaining); - LOG_VMM_ERR("IDTR gva: 0x%lx\n", idtr_gva); - LOG_VMM_ERR("IDTR limit: 0x%lx\n", idtr_limit); - LOG_VMM_ERR("IDTR gpa: 0x%lx\n", idtr_gpa); - LOG_VMM_ERR("IDTR valid: %s\n", idtr_valid ? "YES" : "NO"); - uint8_t idt_entry_size = guest_in_64_bits() ? 16 : 8; - uint16_t idt_num_entries = (idtr_limit + 1) / idt_entry_size; - LOG_VMM_ERR("IDTR num entries: %d\n", idt_num_entries); - - uint16_t idt_num_valid_entries = 0; - for (int i = 0; i < idt_num_entries; i++) { - uint32_t entry[4]; - uint64_t entry_gpa = idtr_gpa + (i * idt_entry_size); - entry[0] = *((uint32_t *)gpa_to_vaddr(entry_gpa)); - entry[1] = *((uint32_t *)gpa_to_vaddr(entry_gpa + 4)); - entry[2] = *((uint32_t *)gpa_to_vaddr(entry_gpa + 8)); - entry[3] = *((uint32_t *)gpa_to_vaddr(entry_gpa + 12)); - - uint32_t present = (entry[1] & BIT(15)); - if (present) { - idt_num_valid_entries += 1; - } - } - - LOG_VMM_ERR("IDTR num valid entries: %d\n", idt_num_valid_entries); - } vcpu_print_regs(vcpu_id); - LOG_VMM_ERR("VCPU will not be resumed.\n"); } diff --git a/src/arch/x86_64/guest.c b/src/arch/x86_64/guest.c index fb9d702b4..e8dfe209b 100644 --- a/src/arch/x86_64/guest.c +++ b/src/arch/x86_64/guest.c @@ -8,10 +8,6 @@ #include #include -extern uintptr_t guest_ram_vaddr; -extern uintptr_t guest_flash_vaddr; -extern uintptr_t guest_high_ram_size; - bool guest_paging_on(void) { return microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_CR0) & BIT(31); @@ -21,97 +17,3 @@ bool guest_in_64_bits(void) { return guest_paging_on() && (microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_EFER) & BIT(10)); } - -void *gpa_to_vaddr(uint64_t gpa) -{ - // @billn ugly hack - uint64_t firmware_region_base_gpa = 0xffa00000; - uint64_t high_ram_base_gpa = 0x100000000; - if (gpa < firmware_region_base_gpa) { - return (void *)(guest_ram_vaddr + gpa); - } else if (gpa >= high_ram_base_gpa && gpa < high_ram_base_gpa + guest_high_ram_size) { - // @billn ugly one-to-one hack - return (void *)gpa; - } else if (gpa >= firmware_region_base_gpa && gpa < high_ram_base_gpa) { - return (void *)(guest_flash_vaddr + (gpa - firmware_region_base_gpa)); - } else { - LOG_VMM_ERR("gpa_to_vaddr(): GPA 0x%lx not in any valid guest memory regions\n", gpa); - return NULL; - } -} - -uint64_t gpa_to_pa(uint64_t gpa) -{ - // @billn ugly hack - uint64_t ram_base_gpa = 0x20000000; - uint64_t high_ram_base_gpa = 0x100000000; - if (gpa >= high_ram_base_gpa && gpa < high_ram_base_gpa + guest_high_ram_size) { - // @billn ugly one-to-one hack - return gpa; - } else if (gpa < high_ram_base_gpa) { - return ram_base_gpa + gpa; - } else { - LOG_VMM_ERR("gpa_to_pa(): GPA 0x%lx not in any valid guest memory regions\n", gpa); - return 0; - } -} - -bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, uint64_t *bytes_remaining) -{ - // Make sure that paging is on - if (!guest_paging_on()) { - *gpa = gva; - } - - uint64_t pml4_gpa = microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_CR3) & ~0xfff; - uint64_t *pml4 = gpa_to_vaddr(pml4_gpa); - uint64_t pml4_idx = (gva >> (12 + (9 * 3))) & 0x1ff; - uint64_t pml4_pte = pml4[pml4_idx]; - if (!pte_present(pml4_pte)) { - LOG_VMM_ERR("PML4 PTE not present when converting GVA 0x%lx to GPA\n", gva); - return false; - } - - uint64_t pdpt_gpa = pte_to_gpa(pml4_pte); - uint64_t *pdpt = gpa_to_vaddr(pdpt_gpa); - uint64_t pdpt_idx = (gva >> (12 + (9 * 2))) & 0x1ff; - uint64_t pdpt_pte = pdpt[pdpt_idx]; - if (!pte_present(pdpt_pte)) { - LOG_VMM_ERR("PDPT PTE not present when converting GVA 0x%lx to GPA\n", gva); - return false; - } - - uint64_t pd_gpa = pte_to_gpa(pdpt_pte); - uint64_t *pd = gpa_to_vaddr(pd_gpa); - uint64_t pd_idx = (gva >> (12 + (9 * 1))) & 0x1ff; - uint64_t pd_pte = pd[pd_idx]; - if (!pte_present(pd_pte)) { - LOG_VMM_ERR("PD PTE not present when converting GVA 0x%lx to GPA\n", gva); - return false; - } - - if (pt_page_size(pd_pte) && pte_present(pd_pte)) { - // 2MiB page - uint64_t page_gpa = pte_to_gpa(pd_pte); - uint64_t page_offset = (gva & 0x1fffff); - *gpa = page_gpa + page_offset; - *bytes_remaining = 0x200000 - page_offset; - } else { - // 4k page - uint64_t pt_gpa = pte_to_gpa(pd_pte); - uint64_t *pt = gpa_to_vaddr(pt_gpa); - uint64_t pt_idx = (gva >> (12)) & 0x1ff; - uint64_t pt_pte = pt[pt_idx]; - if (!pte_present(pt_pte)) { - LOG_VMM_ERR("PT PTE not present when converting GVA 0x%lx to GPA\n", gva); - return 0; - } - - uint64_t page_gpa = pte_to_gpa(pt_pte); - uint64_t page_offset = (gva & 0xfff); - *gpa = page_gpa + page_offset; - *bytes_remaining = 0x1000 - page_offset; - } - - return true; -} \ No newline at end of file diff --git a/src/arch/x86_64/guest_ram.c b/src/arch/x86_64/guest_ram.c new file mode 100644 index 000000000..f551b0d75 --- /dev/null +++ b/src/arch/x86_64/guest_ram.c @@ -0,0 +1,164 @@ +/* + * Copyright 2026, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct guest_ram_region { + uint64_t gpa_start; + uint64_t gpa_end; + uintptr_t vmm_vaddr; +}; + +int guest_ram_regions_len = 0; +struct guest_ram_region guest_ram_regions[MAX_GUEST_RAM_REGIONS]; + +#define X86_PAGING_OBJECT_SIZE 0x1000 + +bool guest_ram_add_region(uint64_t gpa, uintptr_t vmm_vaddr, uint64_t size) +{ + if (guest_ram_regions_len == MAX_GUEST_RAM_REGIONS) { + LOG_VMM_ERR("guest_ram_add_region(): bookkeeping array is full\n"); + return false; + } + + uint64_t gpa_end = gpa + size; + + for (int i = 0; i < guest_ram_regions_len; i++) { + if (ranges_overlap(gpa, gpa_end, guest_ram_regions[i].gpa_start, guest_ram_regions[i].gpa_end)) { + LOG_VMM_ERR("guest_ram_add_region(): region [0x%lx..0x%lx) overlaps with existing region [0x%lx..0x%lx)\n", + gpa, gpa_end, guest_ram_regions[i].gpa_start, guest_ram_regions[i].gpa_end); + } + return false; + } + + guest_ram_regions[guest_ram_regions_len] = (struct guest_ram_region) { + .gpa_start = gpa, + .gpa_end = gpa_end, + .vmm_vaddr = vmm_vaddr, + }; + guest_ram_regions_len++; + + return true; +} + +bool gpa_to_vaddr(uint64_t gpa, void **ret, int *bytes_remaining) +{ + for (int i = 0; i < guest_ram_regions_len; i++) { + // LOG_VMM("chekcing 0x%lx, start 0x%lx, end 0x%lx\n", gpa, guest_ram_regions[i].gpa_start, guest_ram_regions[i].gpa_end); + if (gpa >= guest_ram_regions[i].gpa_start && gpa < guest_ram_regions[i].gpa_end) { + uint64_t offset = gpa - guest_ram_regions[i].gpa_start; + *ret = (void *) (guest_ram_regions[i].vmm_vaddr + offset); + *bytes_remaining = guest_ram_regions[i].gpa_end - gpa; + return true; + } + } + return false; +} + +bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, int *bytes_remaining) +{ + // Make sure that paging is on + if (!guest_paging_on()) { + *gpa = gva; + } + + int pt_bytes_remaining; + + uint64_t pml4_gpa = microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_CR3) & ~0xfff; + uint64_t *pml4; + if (!gpa_to_vaddr(pml4_gpa, (void *) &pml4, &pt_bytes_remaining)) { + LOG_VMM_ERR("PML4 GPA 0x%lx not in any valid guest RAM regions\n", pml4_gpa); + return false; + } + if (pt_bytes_remaining < X86_PAGING_OBJECT_SIZE) { + LOG_VMM_ERR("PML4 GPA 0x%lx overflows guest RAM regions\n", pml4_gpa); + return false; + } + + uint64_t pml4_idx = (gva >> (12 + (9 * 3))) & 0x1ff; + uint64_t pml4_pte = pml4[pml4_idx]; + if (!pte_present(pml4_pte)) { + LOG_VMM_ERR("PML4 PTE not present when converting GVA 0x%lx to GPA\n", gva); + return false; + } + + uint64_t pdpt_gpa = pte_to_gpa(pml4_pte); + uint64_t *pdpt; + if (!gpa_to_vaddr(pdpt_gpa, (void *) &pdpt, &pt_bytes_remaining)) { + LOG_VMM_ERR("PDPT GPA 0x%lx not in any valid guest RAM regions\n", pdpt_gpa); + return false; + } + if (pt_bytes_remaining < X86_PAGING_OBJECT_SIZE) { + LOG_VMM_ERR("PDPT GPA 0x%lx overflows guest RAM regions\n", pdpt_gpa); + return false; + } + + uint64_t pdpt_idx = (gva >> (12 + (9 * 2))) & 0x1ff; + uint64_t pdpt_pte = pdpt[pdpt_idx]; + if (!pte_present(pdpt_pte)) { + LOG_VMM_ERR("PDPT PTE not present when converting GVA 0x%lx to GPA\n", gva); + return false; + } + + uint64_t pd_gpa = pte_to_gpa(pdpt_pte); + uint64_t *pd; + if (!gpa_to_vaddr(pd_gpa, (void *) &pd, &pt_bytes_remaining)) { + LOG_VMM_ERR("PD GPA 0x%lx not in any valid guest RAM regions\n", pd_gpa); + return false; + } + if (pt_bytes_remaining < X86_PAGING_OBJECT_SIZE) { + LOG_VMM_ERR("PD GPA 0x%lx overflows guest RAM regions\n", pd_gpa); + return false; + } + + uint64_t pd_idx = (gva >> (12 + (9 * 1))) & 0x1ff; + uint64_t pd_pte = pd[pd_idx]; + if (!pte_present(pd_pte)) { + LOG_VMM_ERR("PD PTE not present when converting GVA 0x%lx to GPA\n", gva); + return false; + } + + if (pt_page_size(pd_pte) && pte_present(pd_pte)) { + // 2MiB page + uint64_t page_gpa = pte_to_gpa(pd_pte); + uint64_t page_offset = (gva & 0x1fffff); + *gpa = page_gpa + page_offset; + *bytes_remaining = 0x200000 - page_offset; + } else { + // 4k page + uint64_t pt_gpa = pte_to_gpa(pd_pte); + uint64_t *pt; + if (!gpa_to_vaddr(pt_gpa, (void *) &pt, &pt_bytes_remaining)) { + LOG_VMM_ERR("PT GPA 0x%lx not in any valid guest RAM regions\n", pt_gpa); + return false; + } + if (pt_bytes_remaining < X86_PAGING_OBJECT_SIZE) { + LOG_VMM_ERR("PT GPA 0x%lx overflows guest RAM regions\n", pt_gpa); + return false; + } + + uint64_t pt_idx = (gva >> (12)) & 0x1ff; + uint64_t pt_pte = pt[pt_idx]; + if (!pte_present(pt_pte)) { + LOG_VMM_ERR("PT PTE not present when converting GVA 0x%lx to GPA\n", gva); + return 0; + } + + uint64_t page_gpa = pte_to_gpa(pt_pte); + uint64_t page_offset = (gva & 0xfff); + *gpa = page_gpa + page_offset; + *bytes_remaining = 0x1000 - page_offset; + } + + return true; +} \ No newline at end of file diff --git a/src/arch/x86_64/instruction.c b/src/arch/x86_64/instruction.c index 16e57e5c1..5a7fd613d 100644 --- a/src/arch/x86_64/instruction.c +++ b/src/arch/x86_64/instruction.c @@ -252,20 +252,22 @@ decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4 memset(instruction_buf, 0, X86_MAX_INSTRUCTION_LENGTH); uint64_t rip_gpa; - uint64_t bytes_remaining; + int bytes_remaining; assert(gva_to_gpa(vcpu_id, rip, &rip_gpa, &bytes_remaining)); - // @billn fix lazyness + // @billn fix lazyness, crashes if the instruction crosses a page boundary assert(bytes_remaining >= instruction_len); - assert(instruction_len <= X86_MAX_INSTRUCTION_LENGTH); - memcpy(instruction_buf, gpa_to_vaddr(rip_gpa), instruction_len); + + void *instruction_vaddr; + assert(gpa_to_vaddr(rip_gpa, &instruction_vaddr, &bytes_remaining)); + memcpy(instruction_buf, instruction_vaddr, instruction_len); // @billn I really think something more "industrial grade" should be used for a job like this. // Such as https://github.com/zyantific/zydis which is no-malloc and no-libc, but it uses cmake...yuck // But then we introduce a dependency... decoded_instruction_ret_t ret = { .type = INSTRUCTION_DECODE_FAIL, .decoded = {} }; - memcpy(&ret.raw, gpa_to_vaddr(rip_gpa), instruction_len); + memcpy(&ret.raw, instruction_vaddr, instruction_len); ret.raw_len = instruction_len; bool opcode_valid = false; diff --git a/src/arch/x86_64/linux.c b/src/arch/x86_64/linux.c index c71abb40b..3fa880f89 100644 --- a/src/arch/x86_64/linux.c +++ b/src/arch/x86_64/linux.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /* Documents referenced: diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index e6d06f0a6..c64a0cabc 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include @@ -93,12 +93,6 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) // enable is boot cpu result = LAPIC_GPA | BIT(11) | BIT(8); break; - // case IA32_MCG_CAP: - // case IA32_MCG_STATUS: - // case IA32_MTRRCAP: - // case IA32_MTRR_DEF_TYPE: - // case IA32_PAT: - // @billn revisit above 5 case IA32_SPEC_CTRL: // @billn revisit, I think we should use Virtualize IA32_SPEC_CTRL // in Tertiary Processor-Based VM-Execution Controls diff --git a/src/arch/x86_64/pci.c b/src/arch/x86_64/pci.c index 7c916a8d6..eef6a05a6 100644 --- a/src/arch/x86_64/pci.c +++ b/src/arch/x86_64/pci.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include /* Uncomment this to enable debug logging */ diff --git a/src/arch/x86_64/util.c b/src/arch/x86_64/util.c index 00a760c71..5605db96e 100644 --- a/src/arch/x86_64/util.c +++ b/src/arch/x86_64/util.c @@ -8,12 +8,6 @@ #include #include -// @billn shouldn't be here, there should be a `initialise_guest_ram()` function that the VMM call to set these up -extern uintptr_t guest_ram_vaddr; -extern uintptr_t guest_high_ram_vaddr; -extern uint64_t guest_high_ram_size; -extern uintptr_t guest_flash_vaddr; - /* Table 28-7. Exit Qualification for EPT Violations */ #define EPT_VIOLATION_READ (1 << 0) #define EPT_VIOLATION_WRITE (1 << 1) diff --git a/src/arch/x86_64/vcpu.c b/src/arch/x86_64/vcpu.c index 9780f22cb..3bb7d7680 100644 --- a/src/arch/x86_64/vcpu.c +++ b/src/arch/x86_64/vcpu.c @@ -184,19 +184,4 @@ void vcpu_print_regs(size_t vcpu_id) LOG_VMM(" r14 = 0x%lx\n", r14); LOG_VMM(" r15 = 0x%lx\n", r15); LOG_VMM("=========================\n"); - - if (guest_paging_on()) { - if (ins_len) { - uint64_t gpa; - uint64_t bytes_remaining; - assert(gva_to_gpa(0, rip, &gpa, &bytes_remaining)); - assert(bytes_remaining >= ins_len); - LOG_VMM_ERR("faulting instruction:\n"); - uint8_t *ins = gpa_to_vaddr(gpa); - for (int i = 0; i < ins_len; i++) { - LOG_VMM_ERR("0x%02x\n", ins[i]); - bytes_remaining--; - } - } - } } diff --git a/src/util/util.c b/src/util/util.c index 0e332c067..b9eb9735d 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -42,3 +42,8 @@ void print_missing_baseline_bits(uint64_t baseline, uint64_t actual) } } } + +bool ranges_overlap(uint64_t left_start, uint64_t left_end, uint64_t right_start, uint64_t right_end) +{ + return !(left_end <= right_start || right_end <= left_start); +} diff --git a/vmm.mk b/vmm.mk index 5b1976157..d1b27a143 100644 --- a/vmm.mk +++ b/vmm.mk @@ -39,7 +39,8 @@ X86_64_FILES = src/arch/x86_64/fault.c \ src/arch/x86_64/pci.c \ src/arch/x86_64/util.c \ src/arch/x86_64/tsc.c \ - src/arch/x86_64/fpu.c + src/arch/x86_64/fpu.c \ + src/arch/x86_64/guest_ram.c # VIRTIO MMIO and PCI depends on sddf ifeq ($(strip $(SDDF)),) From b6c04795b27af7cfd2c0094d766fd8767135a25d Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 1 Apr 2026 11:53:52 +1100 Subject: [PATCH 24/42] x86_64: remove hacks Signed-off-by: Bill Nguyen --- include/libvmm/arch/x86_64/util.h | 4 +--- src/arch/aarch64/guest.c | 2 +- src/arch/x86_64/fault.c | 9 --------- src/arch/x86_64/guest_ram.c | 10 +++++----- src/arch/x86_64/ioports.c | 12 ------------ 5 files changed, 7 insertions(+), 30 deletions(-) diff --git a/include/libvmm/arch/x86_64/util.h b/include/libvmm/arch/x86_64/util.h index f3682a3c1..e1aafd65a 100644 --- a/include/libvmm/arch/x86_64/util.h +++ b/include/libvmm/arch/x86_64/util.h @@ -11,11 +11,9 @@ #include #include -extern bool fault_cond; - // #define DEBUG_FAULT #if defined(DEBUG_FAULT) -#define LOG_FAULT(...) do{ if (fault_cond) { printf("%s|FAULT: ", microkit_name); printf(__VA_ARGS__); } }while(0) +#define LOG_FAULT(...) do{ printf("%s|FAULT: ", microkit_name); printf(__VA_ARGS__); }while(0) #else #define LOG_FAULT(...) do{}while(0) #endif diff --git a/src/arch/aarch64/guest.c b/src/arch/aarch64/guest.c index 48feb0632..a45aeb6ce 100644 --- a/src/arch/aarch64/guest.c +++ b/src/arch/aarch64/guest.c @@ -10,6 +10,6 @@ bool gpa_to_vaddr(uint64_t gpa, void **ret, int *bytes_remaining) { /* On ARM we make have 1 to 1 mapping so nothing to do. */ *bytes_remaining = 0; - *ret = (void *) gpa; + *ret = (void *)gpa; return true; } diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 20d79e429..b7929ba82 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -24,11 +24,6 @@ #include #include -// @billn sus -extern struct lapic_regs lapic_regs; - -bool fault_cond = false; - /* Documents referenced: * [1] seL4: include/arch/x86/arch/object/vcpu.h * [2] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 Order Number: 325462-080US June 2023 @@ -455,10 +450,6 @@ bool fault_handle(size_t vcpu_id) }; if (success && f_reason != INTERRUPT_WINDOW) { - // TODO hack force osxsave on so that Windows doesnt #UD on xgetbv/xsetbv - uint64_t cr4 = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4); - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_GUEST_CR4, cr4 | BIT(18)); - microkit_vcpu_x86_write_regs(vcpu_id, &vctx); uint64_t resume_rip = rip; diff --git a/src/arch/x86_64/guest_ram.c b/src/arch/x86_64/guest_ram.c index f551b0d75..388bc77f0 100644 --- a/src/arch/x86_64/guest_ram.c +++ b/src/arch/x86_64/guest_ram.c @@ -57,7 +57,7 @@ bool gpa_to_vaddr(uint64_t gpa, void **ret, int *bytes_remaining) // LOG_VMM("chekcing 0x%lx, start 0x%lx, end 0x%lx\n", gpa, guest_ram_regions[i].gpa_start, guest_ram_regions[i].gpa_end); if (gpa >= guest_ram_regions[i].gpa_start && gpa < guest_ram_regions[i].gpa_end) { uint64_t offset = gpa - guest_ram_regions[i].gpa_start; - *ret = (void *) (guest_ram_regions[i].vmm_vaddr + offset); + *ret = (void *)(guest_ram_regions[i].vmm_vaddr + offset); *bytes_remaining = guest_ram_regions[i].gpa_end - gpa; return true; } @@ -76,7 +76,7 @@ bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, int *bytes_remainin uint64_t pml4_gpa = microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_CR3) & ~0xfff; uint64_t *pml4; - if (!gpa_to_vaddr(pml4_gpa, (void *) &pml4, &pt_bytes_remaining)) { + if (!gpa_to_vaddr(pml4_gpa, (void *)&pml4, &pt_bytes_remaining)) { LOG_VMM_ERR("PML4 GPA 0x%lx not in any valid guest RAM regions\n", pml4_gpa); return false; } @@ -94,7 +94,7 @@ bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, int *bytes_remainin uint64_t pdpt_gpa = pte_to_gpa(pml4_pte); uint64_t *pdpt; - if (!gpa_to_vaddr(pdpt_gpa, (void *) &pdpt, &pt_bytes_remaining)) { + if (!gpa_to_vaddr(pdpt_gpa, (void *)&pdpt, &pt_bytes_remaining)) { LOG_VMM_ERR("PDPT GPA 0x%lx not in any valid guest RAM regions\n", pdpt_gpa); return false; } @@ -112,7 +112,7 @@ bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, int *bytes_remainin uint64_t pd_gpa = pte_to_gpa(pdpt_pte); uint64_t *pd; - if (!gpa_to_vaddr(pd_gpa, (void *) &pd, &pt_bytes_remaining)) { + if (!gpa_to_vaddr(pd_gpa, (void *)&pd, &pt_bytes_remaining)) { LOG_VMM_ERR("PD GPA 0x%lx not in any valid guest RAM regions\n", pd_gpa); return false; } @@ -138,7 +138,7 @@ bool gva_to_gpa(size_t vcpu_id, uint64_t gva, uint64_t *gpa, int *bytes_remainin // 4k page uint64_t pt_gpa = pte_to_gpa(pd_pte); uint64_t *pt; - if (!gpa_to_vaddr(pt_gpa, (void *) &pt, &pt_bytes_remaining)) { + if (!gpa_to_vaddr(pt_gpa, (void *)&pt, &pt_bytes_remaining)) { LOG_VMM_ERR("PT GPA 0x%lx not in any valid guest RAM regions\n", pt_gpa); return false; } diff --git a/src/arch/x86_64/ioports.c b/src/arch/x86_64/ioports.c index ee716e430..472713502 100644 --- a/src/arch/x86_64/ioports.c +++ b/src/arch/x86_64/ioports.c @@ -16,18 +16,6 @@ #include #include -extern uint64_t primary_ata_cmd_pio_id; -extern uint64_t primary_ata_cmd_pio_addr; - -extern uint64_t primary_ata_ctrl_pio_id; -extern uint64_t primary_ata_ctrl_pio_addr; - -extern uint64_t second_ata_cmd_pio_id; -extern uint64_t second_ata_cmd_pio_addr; - -extern uint64_t second_ata_ctrl_pio_id; -extern uint64_t second_ata_ctrl_pio_addr; - extern struct pci_bus pci_bus_state; // TODO: hack From e69178bbad63d1e24cfb0307e34f74b0fd4caf4b Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 7 Apr 2026 16:56:06 +1000 Subject: [PATCH 25/42] Unified guest RAM management across x86 and ARM Signed-off-by: Bill Nguyen --- build.zig | 2 +- examples/rust/rust_vmm.system | 2 +- examples/rust/src/vmm.rs | 27 ++-- examples/simple/board/maaxboard/simple.system | 2 +- .../board/qemu_virt_aarch64/simple.system | 12 +- examples/simple/vmm.c | 35 +++-- examples/virtio/client_vmm.c | 7 +- examples/virtio_pci/client_vmm.c | 5 + examples/zig/src/vmm.zig | 22 ++- examples/zig/zig_vmm.system | 12 +- include/libvmm/arch/aarch64/linux.h | 12 +- .../x86_64/{guest_ram.h => memory_space.h} | 6 - include/libvmm/arch/x86_64/util.h | 5 +- include/libvmm/guest.h | 17 +-- include/libvmm/guest_ram.h | 27 ++++ include/libvmm/libvmm.h | 3 +- src/arch/aarch64/guest.c | 71 +++++++++- src/arch/aarch64/linux.c | 94 ++++++++----- src/arch/x86_64/acpi.c | 2 +- src/arch/x86_64/fault.c | 2 +- src/arch/x86_64/guest.c | 23 +++- src/arch/x86_64/guest_ram.c | 107 ++------------- src/arch/x86_64/instruction.c | 6 +- src/arch/x86_64/linux.c | 2 +- src/arch/x86_64/msr.c | 2 +- src/arch/x86_64/pci.c | 3 +- src/arch/x86_64/util.c | 10 ++ src/guest.c | 126 ------------------ src/guest_ram.c | 82 ++++++++++++ vmm.mk | 2 +- 30 files changed, 378 insertions(+), 350 deletions(-) rename include/libvmm/arch/x86_64/{guest_ram.h => memory_space.h} (79%) create mode 100644 include/libvmm/guest_ram.h delete mode 100644 src/guest.c create mode 100644 src/guest_ram.c diff --git a/build.zig b/build.zig index 4f55f2302..f267e7efd 100644 --- a/build.zig +++ b/build.zig @@ -5,7 +5,7 @@ const std = @import("std"); const LazyPath = std.Build.LazyPath; const src = [_][]const u8{ - "src/guest.c", + "src/guest_ram.c", "src/util/util.c", "src/util/printf.c", "src/virtio/mmio.c", diff --git a/examples/rust/rust_vmm.system b/examples/rust/rust_vmm.system index 32bbf9f62..8fae8608c 100644 --- a/examples/rust/rust_vmm.system +++ b/examples/rust/rust_vmm.system @@ -17,7 +17,7 @@ - + diff --git a/examples/rust/src/vmm.rs b/examples/rust/src/vmm.rs index b122b916d..1de54efb9 100644 --- a/examples/rust/src/vmm.rs +++ b/examples/rust/src/vmm.rs @@ -9,9 +9,12 @@ use core::{include_bytes}; use sel4_microkit::{protection_domain, MessageInfo, Channel, Child, Handler, debug_println}; -const GUEST_RAM_VADDR: usize = 0x40000000; -const GUEST_DTB_VADDR: usize = 0x4f000000; -const GUEST_INIT_RAM_DISK_VADDR: usize = 0x4d700000; +const GUEST_RAM_VMM_VADDR: usize = 0x20000000; +/* For ARM, these constants depends on what's defined in your DTB. */ +const GUEST_RAM_START_GPA: usize = 0x40000000; +const GUEST_DTB_GPA: usize = 0x4f000000; +const GUEST_INIT_RAM_DISK_GPA: usize = 0x4d700000; +const GUEST_RAM_SIZE: usize = 0x10000000; const GUEST_BOOT_VCPU_ID: usize = 0; /// On the QEMU virt AArch64 platform the UART we are using has an IRQ number of 33. @@ -32,15 +35,18 @@ const UART_CH: Channel = Channel::new(1); #[link(name = "vmm", kind = "static")] #[link(name = "microkit", kind = "static")] extern "C" { - fn linux_setup_images(ram_start: usize, + fn linux_setup_images(ram_start_gpa: usize, kernel: usize, kernel_size: usize, dtb_src: usize, dtb_dest: usize, dtb_size: usize, initrd_src: usize, initrd_dest: usize, initrd_size: usize) -> usize; fn guest_init(init_args: arch_guest_init) -> bool; + dtb_src: usize, dtb_dest_gpa: usize, dtb_size: usize, + initrd_src: usize, initrd_dest_gpa: usize, initrd_size: usize) -> usize; fn virq_register_passthrough(vcpu_id: usize, irq: i32, irq_ch: u32) -> bool; fn virq_handle_passthrough(irq_ch: u32) -> bool; fn guest_start(kernel_pc: usize, dtb: usize, initrd: usize) -> bool; fn fault_handle(vcpu_id: usize, msginfo: MessageInfo) -> bool; + fn guest_ram_add_region(gpa: usize, vmm_vaddr: usize, size: usize) -> bool; } #[repr(C)] @@ -64,18 +70,23 @@ fn init() -> VmmHandler { let initrd_addr = initrd.as_ptr() as usize; unsafe { - let guest_pc = linux_setup_images(GUEST_RAM_VADDR, + let success = guest_ram_add_region(GUEST_RAM_START_GPA, GUEST_RAM_VMM_VADDR, GUEST_RAM_SIZE); + assert!(success); + + let guest_pc = linux_setup_images(GUEST_RAM_START_GPA, linux_addr, linux.len(), - dtb_addr, GUEST_DTB_VADDR, dtb.len(), - initrd_addr, GUEST_INIT_RAM_DISK_VADDR, initrd.len() + dtb_addr, GUEST_DTB_GPA, dtb.len(), + initrd_addr, GUEST_INIT_RAM_DISK_GPA, initrd.len() ); + assert(guest_pc != 0); + let success = guest_init(arch_guest_init { num_vcpus: 1, }); assert!(success); let success = virq_register_passthrough(GUEST_BOOT_VCPU_ID, UART_IRQ as i32, UART_CH.index() as u32); assert!(success); - guest_start(guest_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); + guest_start(guest_pc, GUEST_DTB_GPA, GUEST_INIT_RAM_DISK_GPA); } VmmHandler {} diff --git a/examples/simple/board/maaxboard/simple.system b/examples/simple/board/maaxboard/simple.system index 3feb3e3fc..35ed0e840 100644 --- a/examples/simple/board/maaxboard/simple.system +++ b/examples/simple/board/maaxboard/simple.system @@ -22,7 +22,7 @@ - + diff --git a/examples/simple/board/qemu_virt_aarch64/simple.system b/examples/simple/board/qemu_virt_aarch64/simple.system index b1b4eaf9d..410fcaf89 100644 --- a/examples/simple/board/qemu_virt_aarch64/simple.system +++ b/examples/simple/board/qemu_virt_aarch64/simple.system @@ -28,14 +28,10 @@ - - + + - + + + diff --git a/include/libvmm/arch/x86_64/memory_space.h b/include/libvmm/arch/x86_64/memory_space.h index b037d92f6..d3eec0905 100644 --- a/include/libvmm/arch/x86_64/memory_space.h +++ b/include/libvmm/arch/x86_64/memory_space.h @@ -17,7 +17,17 @@ */ /* Document layout of guest RAM */ -#define LOW_RAM_START_GPA 0x0 + +/* We start guest memory from GPA 0 for 2 reasons: + * 1. modern Linux prefers to be loaded at 0x100000, so if we start guest ram from 0, + * we can use large 2MiB pages for guest RAM. + * 2. Linux also assumes that RAM starts from zero, for example, if you start RAM at + * 0x1000, the kernel complains, but it isn't fatal per se: + * [ 0.000000] BIOS-provided physical RAM map: + * [ 0.000000] BIOS-e820: [gap 0x0000000000000000-0x0000000000000fff] + * [ 0.000000] BIOS-e820: [mem 0x0000000000001000-0x0000000003e61fff] System RAM + */ +#define LOW_RAM_START_GPA 0 #define ECAM_GPA 0xD0000000 /* 1 bus, 32 devices per bus, 8 functions per device, 4k config space per function */ From eae986e12d3d02e9ca9cd2904f97abd23565a4d4 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 16 Apr 2026 14:10:15 +1000 Subject: [PATCH 34/42] x86_64: fix Zig build regression Signed-off-by: Bill Nguyen --- build.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.zig b/build.zig index f267e7efd..07384f037 100644 --- a/build.zig +++ b/build.zig @@ -49,6 +49,8 @@ const src_x86_64 = [_][]const u8{ "src/arch/x86_64/ioports.c", "src/arch/x86_64/util.c", "src/arch/x86_64/tsc.c", + "src/arch/x86_64/guest_time.c", + "src/arch/x86_64/guest_ram.c", "src/arch/x86_64/fpu.c", }; From 358f9407a1d0ed8bde445ce2e1838b826fefb754 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 29 Apr 2026 18:43:34 +0700 Subject: [PATCH 35/42] x86_64: switch clockevent to VMX-preemption timer It is working now, and would scale better in terms of multi core than relying on an external timer driver that's based on a global timer device. Signed-off-by: Bill Nguyen --- src/arch/x86_64/fault.c | 1 + src/arch/x86_64/guest_time.c | 88 ++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index a07115f9d..81052ac3f 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -169,6 +169,7 @@ bool fault_is_trap_like(int exit_reason) switch (exit_reason) { case APIC_WRITE: case VIRTUALIZED_EOI: + case VMX_PREEMPTION_TIMER: return true; default: return false; diff --git a/src/arch/x86_64/guest_time.c b/src/arch/x86_64/guest_time.c index 7bd105779..28ce10bd4 100644 --- a/src/arch/x86_64/guest_time.c +++ b/src/arch/x86_64/guest_time.c @@ -14,20 +14,14 @@ #include #include -/* By default the clocksource and calculation unit is always TSC. But the timeout mechanism can be - * configured to use either the sDDF timer timeout or the VMX-preemption timer. - * Right now VMX-preemption timer does not work for some reasons and isn't - * officially supported by seL4 anyways. As the kernel does not allow us to read IA32_VMX_MISC - * which contains data needed for us to compute the VMX-preemption timer frequency. */ - -// #define GUEST_TIME_USE_VMX_TIMER +/* The clocksource and calculation unit is always TSC for the best performance. */ #define IA32_VMX_MISC 0x485 /* Enough for local APIC timer + 3 HPET comparators, increase this if you add more timer devices. */ #define MAX_CONCURRENT_TIMEOUT 4 -struct virtual_timer_time_out { +typedef struct virtual_timer_time_out { bool valid; uint64_t absolute_expiry_tsc; size_t cookie; @@ -39,7 +33,7 @@ struct guest_timekeeping { uint64_t tsc_hz; microkit_channel timer_ch; - struct virtual_timer_time_out timeouts[MAX_CONCURRENT_TIMEOUT]; + virtual_timer_time_out_t timeouts[MAX_CONCURRENT_TIMEOUT]; /* VMX-preemption timer only ticks after 2^vmx_timer_shift TSC ticks */ uint8_t vmx_timer_shift; @@ -52,6 +46,8 @@ struct guest_timekeeping { static struct guest_timekeeping guest_timekeeping; +// @billn revisit removing timer_ch +// by implementing "setvar_tsc_freq" or similar in Microkit bool initialise_guest_time(microkit_channel timer_ch) { guest_timekeeping.timer_ch = timer_ch; @@ -60,10 +56,12 @@ bool initialise_guest_time(microkit_channel timer_ch) guest_timekeeping.timeouts[i].valid = false; } -#if defined(GUEST_TIME_USE_VMX_TIMER) - guest_timekeeping.vmx_timer_shift = seL4_X86DangerousRDMSR(IA32_VMX_MISC) & 0x1f; - LOG_VMM("vmx timer shift is %u\n", guest_timekeeping.vmx_timer_shift); -#endif + /* "The IA32_VMX_MISC MSR (index 485H) consists of the following fields: + Bits 4:0 report a value X that specifies the relationship between the rate of the VMX-preemption timer and that + of the timestamp counter (TSC). Specifically, the VMX-preemption timer (if it is active) counts down by 1 every + time bit X in the TSC changes due to a TSC increment. + */ + guest_timekeeping.vmx_timer_shift = microkit_vcpu_x86_read_msr(0, IA32_VMX_MISC) & 0x1f; guest_timekeeping.valid = true; return true; @@ -106,27 +104,35 @@ static int guest_time_get_soonest_absolute_expiry_tsc(void) return min_idx; } +static void guest_time_service_timeouts(void) +{ + uint64_t tsc_now = guest_time_tsc_now(); + for (int i = 0; i < MAX_CONCURRENT_TIMEOUT; i++) { + if (guest_timekeeping.timeouts[i].valid) { + if (guest_timekeeping.timeouts[i].absolute_expiry_tsc <= tsc_now) { + guest_timekeeping.timeouts[i].valid = false; + guest_timekeeping.timeouts[i].callback_fn(guest_timekeeping.timeouts[i].cookie); + } + } + } +} + static void guest_time_set_timeout(uint64_t tsc_delta) { guest_timekeeping.tsc_ticks_to_timeout = tsc_delta; guest_timekeeping.timer_primed = true; guest_timekeeping.tsc_at_timer_prime = guest_time_tsc_now(); -#if defined(GUEST_TIME_USE_VMX_TIMER) uint64_t vmx_timer_value = guest_timekeeping.tsc_ticks_to_timeout >> guest_timekeeping.vmx_timer_shift; if (vmx_timer_value > UINT32_MAX) { - LOG_VMM_ERR("VMX-preemption timer value 0x%lx, from TSC ticks to time out 0x%lx, exceeds 32-bit!\n", - vmx_timer_value, guest_timekeeping.tsc_ticks_to_timeout); - assert(false); + vmx_timer_value = UINT32_MAX; + guest_timekeeping.tsc_ticks_to_timeout = (uint64_t)UINT32_MAX << guest_timekeeping.vmx_timer_shift; } + microkit_vcpu_x86_write_vmcs(0, VMX_GUEST_PREEMPTION_TIMER_VALUE, vmx_timer_value); /* We don't need read-set-write as the kernel does that for us. */ microkit_vcpu_x86_write_vmcs(0, VMX_CONTROL_PIN_EXECUTION_CONTROLS, BIT(6)); -#else - uint64_t delay_ns = convert_ticks_by_frequency(guest_timekeeping.tsc_ticks_to_timeout, guest_time_tsc_hz(), - NS_IN_S); - sddf_timer_set_timeout(guest_timekeeping.timer_ch, delay_ns); -#endif + microkit_vcpu_x86_write_vmcs(0, VMX_CONTROL_EXIT_CONTROLS, BIT(22)); } static void guest_time_schedule_timeout(void) @@ -138,28 +144,33 @@ static void guest_time_schedule_timeout(void) if (soonest_timeout_idx == -1) { return; } - uint64_t soonest_absolute_expiry_tsc = guest_timekeeping.timeouts[soonest_timeout_idx].absolute_expiry_tsc; + uint64_t soonest_absolute_expiry_tsc = guest_timekeeping.timeouts[soonest_timeout_idx].absolute_expiry_tsc; uint64_t tsc_now = guest_time_tsc_now(); - if (soonest_absolute_expiry_tsc <= tsc_now) { + uint64_t tsc_ticks_to_timeout = soonest_absolute_expiry_tsc - tsc_now; + + if (tsc_now >= soonest_absolute_expiry_tsc) { + guest_time_set_timeout(0); // Force immediate VM exit upon entry return; } bool timer_need_update = false; - uint64_t tsc_ticks_to_timeout; if (!guest_timekeeping.timer_primed) { timer_need_update = true; - tsc_ticks_to_timeout = soonest_absolute_expiry_tsc - tsc_now; } else { /* There is a pending timeout. How many TSC ticks have passed since the timer was last primed, * and how long until said timeout? */ uint64_t elapsed_tsc = tsc_now - guest_timekeeping.tsc_at_timer_prime; uint64_t tsc_ticks_remaining_until_next_timeout = guest_timekeeping.tsc_ticks_to_timeout - elapsed_tsc; - if ((soonest_absolute_expiry_tsc - tsc_now) < tsc_ticks_remaining_until_next_timeout) { + if (elapsed_tsc >= guest_timekeeping.tsc_ticks_to_timeout) { + /* Timer will expire on next VM entry, no need to do anything. */ + return; + } + + if (tsc_ticks_to_timeout < tsc_ticks_remaining_until_next_timeout) { /* Need an earlier timeout. */ timer_need_update = true; - tsc_ticks_to_timeout = soonest_absolute_expiry_tsc - tsc_now; } } @@ -207,12 +218,6 @@ bool guest_time_cancel_timeout(guest_timeout_handle_t handle) } guest_timekeeping.timeouts[handle].valid = false; -#if defined(GUEST_TIME_USE_VMX_TIMER) - microkit_vcpu_x86_write_vmcs(0, VMX_CONTROL_PIN_EXECUTION_CONTROLS, 0); -#else - /* Can't cancel a sDDF timeout so do nothing */ -#endif - return true; } @@ -221,19 +226,12 @@ void guest_time_handle_timer_ntfn(void) guest_time_user_error_check(); guest_timekeeping.timer_primed = false; -#if defined(GUEST_TIME_USE_VMX_TIMER) + /* Turn off the VMX-preemption timer. No need for read-clear-write as the kernel will do that for us, + * this is only a problem if we set other bits somewhere else in the VMM but we don't right now. */ microkit_vcpu_x86_write_vmcs(0, VMX_CONTROL_PIN_EXECUTION_CONTROLS, 0); -#endif + microkit_vcpu_x86_write_vmcs(0, VMX_CONTROL_EXIT_CONTROLS, 0); - uint64_t tsc_now = guest_time_tsc_now(); - for (int i = 0; i < MAX_CONCURRENT_TIMEOUT; i++) { - if (guest_timekeeping.timeouts[i].valid) { - if (guest_timekeeping.timeouts[i].absolute_expiry_tsc <= tsc_now) { - guest_timekeeping.timeouts[i].valid = false; - guest_timekeeping.timeouts[i].callback_fn(guest_timekeeping.timeouts[i].cookie); - } - } - } + guest_time_service_timeouts(); guest_time_schedule_timeout(); } \ No newline at end of file From cbee0b4a813a01c4207b27269c998e7e594cb252 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 30 Apr 2026 16:07:19 +0700 Subject: [PATCH 36/42] all arch: unified arch specific inits behind lib Signed-off-by: Bill Nguyen --- examples/simple/vmm.c | 60 ++++++++++++++------------------ include/libvmm/arch/x86_64/msr.h | 1 + include/libvmm/guest.h | 19 +++++++++- include/libvmm/libvmm.h | 5 +-- src/arch/aarch64/guest.c | 11 ++++++ src/arch/x86_64/guest.c | 50 +++++++++++++++++++++++++- src/arch/x86_64/msr.c | 34 +++++++++++++++--- 7 files changed, 136 insertions(+), 44 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index b27fa177b..5e7e59cf7 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -65,7 +65,7 @@ extern char _guest_kernel_image_end[]; extern char _guest_initrd_image[]; extern char _guest_initrd_image_end[]; -#if defined(BOARD_x86_64_generic_vtx) +#if defined(CONFIG_ARCH_X86_64) /* Data for the guest's ACPI Differentiated System Description Table (DSDT). */ extern char _guest_dsdt_aml[]; extern char _guest_dsdt_aml_end[]; @@ -96,9 +96,27 @@ void init(void) return; } - assert(guest_ram_add_region(GUEST_RAM_START_GPA, (void *)guest_ram_vaddr, GUEST_RAM_SIZE)); + if (!guest_ram_add_region(GUEST_RAM_START_GPA, (void *)guest_ram_vaddr, GUEST_RAM_SIZE)) { + LOG_VMM_ERR("Failed to bookkeep guest RAM region\n"); + return; + } + +#if defined(CONFIG_ARCH_X86_64) + arch_guest_init_t guest_init_args = (arch_guest_init_t) { + .bsp = true, + .apic_id = 0, + .timer_ch = TIMER_DRV_CH, + }; +#elif defined(CONFIG_ARCH_ARM) + arch_guest_init_t guest_init_args; +#endif -#if defined(BOARD_x86_64_generic_vtx) + if (!guest_init(guest_init_args)) { + LOG_VMM_ERR("Failed to initialise VMM\n"); + return; + } + +#if defined(CONFIG_ARCH_X86_64) size_t dsdt_aml_size = _guest_dsdt_aml_end - _guest_dsdt_aml; if (!dsdt_aml_size) { @@ -114,42 +132,15 @@ void init(void) return; } - if (!vcpu_set_up_long_mode(linux_setup.pml4_gpa, linux_setup.gdt_gpa, linux_setup.gdt_limit)) { - LOG_VMM_ERR("Failed to set up virtual CPU\n"); - return; - } - - /* Set up the virtual PCI bus */ - assert(pci_x86_init()); - /* Pass through COM1 serial port */ microkit_vcpu_x86_enable_ioport(GUEST_BOOT_VCPU_ID, COM1_IO_PORT_ID, COM1_IO_PORT_ADDR, COM1_IO_PORT_SIZE); microkit_irq_ack(SERIAL_IRQ_CH); - /* Initialise guest time library */ - if (!initialise_guest_time(TIMER_DRV_CH)) { - LOG_VMM_ERR("cannot initialise guest time keeper.\n"); - return; - } - - /* Initialise CPUID */ - if (!initialise_cpuid(guest_time_tsc_hz())) { - LOG_VMM_ERR("cannot initialise CPUID\n"); - return; - } - - /* Initialise the virtual Local and I/O APICs */ - // @billn revisit vapic vaddr - bool success = virq_controller_init(guest_time_tsc_hz(), 0xfffffffffffffff); - if (!success) { - LOG_VMM_ERR("Failed to initialise virtual IRQ controller\n"); - return; - } - /* Pass through serial IRQs */ assert(virq_ioapic_register_passthrough(COM1_IOAPIC_CHIP, COM1_IOAPIC_PIN, SERIAL_IRQ_CH)); - guest_start(linux_setup.kernel_entry_gpa, &initial_regs); + guest_start_long_mode(linux_setup.kernel_entry_gpa, linux_setup.pml4_gpa, linux_setup.gdt_gpa, + linux_setup.gdt_limit, &initial_regs); #else size_t dtb_size = _guest_dtb_image_end - _guest_dtb_image; if (!dtb_size) { @@ -171,6 +162,7 @@ void init(void) LOG_VMM_ERR("Failed to initialise guest\n"); return; } + success = virq_register_passthrough(GUEST_BOOT_VCPU_ID, SERIAL_IRQ, SERIAL_IRQ_CH); assert(success); /* Finally start the guest */ @@ -181,7 +173,7 @@ void init(void) void notified(microkit_channel ch) { switch (ch) { -#if defined(BOARD_x86_64_generic_vtx) +#if defined(CONFIG_ARCH_X86_64) case TIMER_DRV_CH: { guest_time_handle_timer_ntfn(); break; @@ -214,7 +206,7 @@ void notified(microkit_channel ch) */ seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) { -#if defined(BOARD_x86_64_generic_vtx) +#if defined(CONFIG_ARCH_X86_64) fault_handle(child); return seL4_True; #else diff --git a/include/libvmm/arch/x86_64/msr.h b/include/libvmm/arch/x86_64/msr.h index 469ed3ffd..b59ca7f36 100644 --- a/include/libvmm/arch/x86_64/msr.h +++ b/include/libvmm/arch/x86_64/msr.h @@ -8,5 +8,6 @@ #include +bool initialise_msrs(bool bsp); bool emulate_rdmsr(seL4_VCPUContext *vctx); bool emulate_wrmsr(seL4_VCPUContext *vctx); diff --git a/include/libvmm/guest.h b/include/libvmm/guest.h index 4f321a10c..07d603d8a 100644 --- a/include/libvmm/guest.h +++ b/include/libvmm/guest.h @@ -5,6 +5,8 @@ */ #pragma once +#pragma once + #include #include #include @@ -21,6 +23,19 @@ #define GUEST_MAX_NUM_VCPUS 4 #endif +#if defined(CONFIG_ARCH_X86_64) +typedef struct arch_guest_init { + /* Is Boot Strap Processor? */ + bool bsp; + /* A unique identifier of the processor from the guest's perspective. + * We are virtualising xAPIC so it is only 8-bits, but in the future if + * we support x2APIC then it will need to be a u32. */ + uint8_t apic_id; + /* Channel to a timer driver to measure the host CPU's TSC frequency + * if it cannot be inferred from CPUID. */ + microkit_channel timer_ch; +} arch_guest_init_t; +#elif defined(CONFIG_ARCH_ARM) typedef struct guest { size_t num_vcpus; bool vcpu_on_state[GUEST_MAX_NUM_VCPUS]; @@ -29,6 +44,7 @@ typedef struct guest { typedef struct arch_guest_init { size_t num_vcpus; } arch_guest_init_t; +#endif /* Initialise the architecture specific subsystems of the VMM library such as the * interrupt controller(s), etc. Note that the VCPU architectural state itself won't be @@ -40,7 +56,8 @@ bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd); void guest_stop(); bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size); #elif defined(CONFIG_ARCH_X86_64) -bool guest_start(uintptr_t kernel_rip, seL4_VCPUContext *initial_regs); +bool guest_start_long_mode(uint64_t kernel_rip, uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, + seL4_VCPUContext *initial_regs); #else #error "Unsupported guest architecture" #endif diff --git a/include/libvmm/libvmm.h b/include/libvmm/libvmm.h index 8e84cad11..dd1ab3e22 100644 --- a/include/libvmm/libvmm.h +++ b/include/libvmm/libvmm.h @@ -25,13 +25,10 @@ #include #include #elif defined(CONFIG_ARCH_X86) -#include -#include -#include #include +#include #include #include -#include #include #include #endif diff --git a/src/arch/aarch64/guest.c b/src/arch/aarch64/guest.c index 44e4af493..12c33aebb 100644 --- a/src/arch/aarch64/guest.c +++ b/src/arch/aarch64/guest.c @@ -6,9 +6,20 @@ #include #include #include +#include #include #include +bool guest_init(arch_guest_init_t init_args) +{ + /* Initialise the virtual GIC driver */ + bool success = virq_controller_init(); + if (!success) { + LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); + } + return success; +} + bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { /* diff --git a/src/arch/x86_64/guest.c b/src/arch/x86_64/guest.c index a45a3805b..1c88b3a5f 100644 --- a/src/arch/x86_64/guest.c +++ b/src/arch/x86_64/guest.c @@ -9,6 +9,11 @@ #include #if defined(CONFIG_ARCH_X86_64) +#include +#include +#include +#include +#include #include #include #include @@ -16,8 +21,51 @@ #include #endif -bool guest_start(uintptr_t kernel_rip, seL4_VCPUContext *initial_regs) +bool guest_init(arch_guest_init_t init_args) { + /* Set up the virtual PCI bus */ + if (!pci_x86_init()) { + LOG_VMM_ERR("failed to initialise virtual PCI bus.\n"); + return false; + } + + /* Initialise guest time library */ + if (!initialise_guest_time(init_args.timer_ch)) { + LOG_VMM_ERR("failed to initialise guest time keeper.\n"); + return false; + } + + /* Initialise CPUID */ + if (!initialise_cpuid(guest_time_tsc_hz())) { + LOG_VMM_ERR("failed to initialise CPUID\n"); + return false; + } + + /* Initialise MSRs */ + if (!initialise_msrs(init_args.bsp)) { + LOG_VMM_ERR("failed to initialise MSRs\n"); + return false; + } + + /* Initialise the virtual Local and I/O APICs */ + // @billn revisit vapic vaddr + bool success = virq_controller_init(guest_time_tsc_hz(), 0xfffffffffffffff); + if (!success) { + LOG_VMM_ERR("Failed to initialise virtual IRQ controllers\n"); + return false; + } + + return true; +} + +bool guest_start_long_mode(uint64_t kernel_rip, uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit, + seL4_VCPUContext *initial_regs) +{ + if (!vcpu_set_up_long_mode(cr3, gdt_gpa, gdt_limit)) { + LOG_VMM_ERR("Failed to set up virtual CPU\n"); + return false; + } + /* Write out the initial CPU registers. This is required when there is some sort of ABI between the guest software being booted and us acting as the "bootloader". For example, Linux expects the GPA of the "zero page" to be in RSI when the CPU diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index 270782bd2..ddd582733 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -75,8 +75,29 @@ #define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */ #define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ +static bool msrs_initialised = false; +static uint32_t apic_base_msr_mask = 0; + +bool initialise_msrs(bool bsp) +{ + if (bsp) { + /* Figure 11-5. IA32_APIC_BASE MSR (APIC_BASE_MSR in P6 Family) + * Is a boot strap processor. */ + apic_base_msr_mask = BIT(8); + } + + msrs_initialised = true; + + return true; +} + bool emulate_rdmsr(seL4_VCPUContext *vctx) { + if (!msrs_initialised) { + LOG_VMM_ERR("MSRs not initialised!\n"); + return false; + } + uint64_t result = 0; switch (vctx->ecx) { @@ -85,7 +106,7 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) break; } case IA32_TIME_STAMP_COUNTER: - result = __rdtsc(); + result = rdtsc(); break; case MSR_STAR: case MSR_LSTAR: @@ -94,9 +115,9 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) result = microkit_vcpu_x86_read_msr(GUEST_BOOT_VCPU_ID, vctx->ecx); break; case IA32_APIC_BASE: - // Figure 11-5. IA32_APIC_BASE MSR (APIC_BASE_MSR in P6 Family) - // enable is boot cpu - result = LAPIC_GPA | BIT(11) | BIT(8); + /* Figure 11-5. IA32_APIC_BASE MSR (APIC_BASE_MSR in P6 Family) + * enable is boot cpu? */ + result = LAPIC_GPA | BIT(11) | apic_base_msr_mask; break; case IA32_SPEC_CTRL: // @billn revisit, I think we should use Virtualize IA32_SPEC_CTRL @@ -115,6 +136,11 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) bool emulate_wrmsr(seL4_VCPUContext *vctx) { + if (!msrs_initialised) { + LOG_VMM_ERR("MSRs not initialised!\n"); + return false; + } + uint64_t value = (uint64_t)((vctx->edx & 0xffffffff) << 32) | (uint64_t)(vctx->eax & 0xffffffff); LOG_FAULT("handling WRMSR 0x%x, value 0x%lx\n", vctx->ecx, value); From 93abc1f52cd31a8d8b248d97defa86f8ada32334 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Tue, 5 May 2026 22:59:26 +1000 Subject: [PATCH 37/42] fix rebase issue, as cbee0b4 was backported to main Signed-off-by: Bill Nguyen --- examples/simple/vmm.c | 13 ++++--------- src/arch/aarch64/guest.c | 19 +++++++++++++++++++ vmm.mk | 3 +-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index 5e7e59cf7..3a1426260 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -108,7 +108,9 @@ void init(void) .timer_ch = TIMER_DRV_CH, }; #elif defined(CONFIG_ARCH_ARM) - arch_guest_init_t guest_init_args; + arch_guest_init_t guest_init_args = (arch_guest_init_t) { + .num_vcpus = 1, + }; #endif if (!guest_init(guest_init_args)) { @@ -156,14 +158,7 @@ void init(void) return; } - arch_guest_init_t args = { .num_vcpus = 1 }; - bool success = guest_init(args); - if (!success) { - LOG_VMM_ERR("Failed to initialise guest\n"); - return; - } - - success = virq_register_passthrough(GUEST_BOOT_VCPU_ID, SERIAL_IRQ, SERIAL_IRQ_CH); + bool success = virq_register_passthrough(GUEST_BOOT_VCPU_ID, SERIAL_IRQ, SERIAL_IRQ_CH); assert(success); /* Finally start the guest */ guest_start(kernel_pc, GUEST_DTB_GPA, GUEST_INIT_RAM_DISK_GPA); diff --git a/src/arch/aarch64/guest.c b/src/arch/aarch64/guest.c index 12c33aebb..f7d0e6b8b 100644 --- a/src/arch/aarch64/guest.c +++ b/src/arch/aarch64/guest.c @@ -10,13 +10,32 @@ #include #include +/* Global state for managing the guest. */ +guest_t guest; + bool guest_init(arch_guest_init_t init_args) { + if (init_args.num_vcpus == 0) { + LOG_VMM_ERR("number of guest vCPUs must be greater than zero"); + return false; + } + + if (init_args.num_vcpus > GUEST_MAX_NUM_VCPUS) { + LOG_VMM_ERR("number of guest vCPUs (%lu) is more than maximum (%lu)", init_args.num_vcpus, GUEST_MAX_NUM_VCPUS); + return false; + } + + guest.num_vcpus = init_args.num_vcpus; + for (int i = 0; i < guest.num_vcpus; i++) { + guest.vcpu_on_state[i] = false; + } + /* Initialise the virtual GIC driver */ bool success = virq_controller_init(); if (!success) { LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); } + return success; } diff --git a/vmm.mk b/vmm.mk index ef487317b..390993a02 100644 --- a/vmm.mk +++ b/vmm.mk @@ -66,8 +66,7 @@ VIRTIO_FILES := src/virtio/block.c \ src/virtio/pci.c \ src/virtio/net.c \ src/virtio/sound.c \ - src/virtio/virtio.c \ - src/guest.c + src/virtio/virtio.c ifeq ($(ARCH),aarch64) CFILES := ${AARCH64_FILES} ${VIRTIO_FILES} From 4fae3e20bf68b58b060f229a1659b0c495161fb8 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Wed, 6 May 2026 10:15:05 +1000 Subject: [PATCH 38/42] x86_64: various APIC refactors in preparation for software APIC fallback Signed-off-by: Bill Nguyen --- include/libvmm/arch/x86_64/apic.h | 4 +- src/arch/x86_64/apic.c | 236 ++++++++++++++++-------------- src/arch/x86_64/fault.c | 2 +- src/arch/x86_64/guest.c | 3 +- src/arch/x86_64/msr.c | 3 +- src/arch/x86_64/virq.c | 12 +- 6 files changed, 141 insertions(+), 119 deletions(-) diff --git a/include/libvmm/arch/x86_64/apic.h b/include/libvmm/arch/x86_64/apic.h index 7ecdf118f..ce78b5c41 100644 --- a/include/libvmm/arch/x86_64/apic.h +++ b/include/libvmm/arch/x86_64/apic.h @@ -98,8 +98,8 @@ struct ioapic_regs { struct ioapic_virq_handle virq_passthrough_map[IOAPIC_NUM_PINS]; }; -uint32_t vapic_read_reg(int offset); -void vapic_write_reg(int offset, uint32_t value); +uint32_t lapic_read_reg(int offset); +void lapic_write_reg(int offset, uint32_t value); bool lapic_read_fault_handle(uint64_t offset, uint32_t *result); bool lapic_write_fault_handle(uint64_t offset, uint32_t data); diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index 6efe1ee0d..7d28854f1 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -59,6 +59,21 @@ uint64_t native_scaled_apic_ticks_when_timer_starts; bool timeout_handle_valid; guest_timeout_handle_t timeout_handle; +uint32_t lapic_read_reg(int offset) +{ + assert(offset < 0x1000); + // @billn fix hardcoded vaddr + return *((volatile uint32_t *)(0x101000ull + offset)); +} + +void lapic_write_reg(int offset, uint32_t value) +{ + assert(offset < 0x1000); + // @billn fix hardcoded vaddr + volatile uint32_t *reg = (uint32_t *)(0x101000ull + offset); + *reg = value; +} + static int get_next_pending_irq_vector(void) { /* Scans IRRs for *a* pending interrupt, @@ -67,7 +82,7 @@ static int get_next_pending_irq_vector(void) for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { for (int j = 31; j >= 0; j--) { int irr_reg_off = REG_LAPIC_IRR_0 + (i * 0x10); - if (vapic_read_reg(irr_reg_off) & BIT(j)) { + if (lapic_read_reg(irr_reg_off) & BIT(j)) { uint8_t candidate_vector = i * 32 + j; return candidate_vector; } @@ -80,7 +95,7 @@ static void debug_print_lapic_pending_irqs(void) { for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { for (int j = 31; j >= 0; j--) { - uint32_t irr = vapic_read_reg(REG_LAPIC_IRR_0 + (i * 0x10)); + uint32_t irr = lapic_read_reg(REG_LAPIC_IRR_0 + (i * 0x10)); if (irr & BIT(j)) { LOG_VMM("irq vector %d is pending\n", i * 32 + j); } @@ -88,25 +103,10 @@ static void debug_print_lapic_pending_irqs(void) } } -uint32_t vapic_read_reg(int offset) -{ - assert(offset < 0x1000); - // @billn fix hardcoded vaddr - return *((volatile uint32_t *)(0x101000ull + offset)); -} - -void vapic_write_reg(int offset, uint32_t value) -{ - assert(offset < 0x1000); - // @billn fix hardcoded vaddr - volatile uint32_t *reg = (uint32_t *)(0x101000ull + offset); - *reg = value; -} - -int lapic_dcr_to_divider(void) +static int lapic_dcr_to_divider(void) { /* [1] "Figure 12-10. Divide Configuration Register" */ - switch (vapic_read_reg(REG_LAPIC_DCR)) { + switch (lapic_read_reg(REG_LAPIC_DCR)) { case 0: return 2; case 1: @@ -124,14 +124,14 @@ int lapic_dcr_to_divider(void) case 11: return 1; default: - LOG_VMM_ERR("unknown LAPIC DCR register encoding: 0x%x\n", vapic_read_reg(REG_LAPIC_DCR)); + LOG_VMM_ERR("unknown LAPIC DCR register encoding: 0x%x\n", lapic_read_reg(REG_LAPIC_DCR)); assert(false); } return -1; } -uint8_t ioapic_pin_to_vector(int ioapic, int pin) +static uint8_t ioapic_pin_to_vector(int ioapic, int pin) { assert(ioapic == 0); return ioapic_regs.ioredtbl[pin] & 0xff; @@ -143,10 +143,10 @@ enum lapic_timer_mode { LAPIC_TIMER_TSC_DEADLINE, }; -enum lapic_timer_mode lapic_parse_timer_reg(void) +static enum lapic_timer_mode lapic_parse_timer_reg(void) { // [1] "Figure 12-8. Local Vector Table (LVT)" - uint32_t timer_reg = vapic_read_reg(REG_LAPIC_TIMER); + uint32_t timer_reg = lapic_read_reg(REG_LAPIC_TIMER); switch (((timer_reg >> 17) & 0x3)) { case 0: return LAPIC_TIMER_ONESHOT; @@ -164,58 +164,46 @@ enum lapic_timer_mode lapic_parse_timer_reg(void) return -1; } -uint64_t apic_time_now_scaled(void) +static uint64_t lapic_time_now_scaled(void) { - return rdtsc() / lapic_dcr_to_divider(); + return guest_time_tsc_now() / lapic_dcr_to_divider(); } -bool lapic_read_fault_handle(uint64_t offset, uint32_t *result) +static uint32_t lapic_read_curr_count_reg(void) { - switch (offset) { - case REG_LAPIC_CURR_CNT: { - /* [1] "12.5.4 APIC Timer" */ - if (vapic_read_reg(REG_LAPIC_INIT_CNT) == 0) { - *result = 0; - } else { - uint64_t apic_tick_now_scaled = apic_time_now_scaled(); - uint64_t elapsed_scaled_apic_tick = apic_tick_now_scaled - native_scaled_apic_ticks_when_timer_starts; + uint32_t result = 0; - uint64_t remaining = 0; - if (elapsed_scaled_apic_tick < vapic_read_reg(REG_LAPIC_INIT_CNT)) { - remaining = vapic_read_reg(REG_LAPIC_INIT_CNT) - elapsed_scaled_apic_tick; - } - *result = remaining; - LOG_APIC("current count read 0x%lx\n", remaining); + /* [1] "12.5.4 APIC Timer" */ + if (lapic_read_reg(REG_LAPIC_INIT_CNT) != 0) { + uint64_t apic_tick_now_scaled = lapic_time_now_scaled(); + uint64_t elapsed_scaled_apic_tick = apic_tick_now_scaled - native_scaled_apic_ticks_when_timer_starts; + + uint64_t remaining = 0; + if (elapsed_scaled_apic_tick < lapic_read_reg(REG_LAPIC_INIT_CNT)) { + remaining = lapic_read_reg(REG_LAPIC_INIT_CNT) - elapsed_scaled_apic_tick; } - break; - } - case REG_LAPIC_CMCI: { - *result = 0; - break; - } - default: - LOG_VMM_ERR("Reading unknown LAPIC register offset 0x%x\n", offset); - return false; + result = remaining; + LOG_APIC("current count read 0x%lx\n", remaining); } - return true; + return result; } static void handle_lapic_timer_nftn(size_t vcpu_id) { - if (!(vapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { + assert(timeout_handle_valid); + guest_time_cancel_timeout(timeout_handle); + + if (!(lapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { /* [1] "Figure 12-23. Spurious-Interrupt Vector Register (SVR)" * APIC Software Disable bit */ return; } - assert(timeout_handle_valid); - guest_time_cancel_timeout(timeout_handle); - /* Restart timeout if periodic */ - uint32_t init_count = vapic_read_reg(REG_LAPIC_INIT_CNT); + uint32_t init_count = lapic_read_reg(REG_LAPIC_INIT_CNT); if (lapic_parse_timer_reg() == LAPIC_TIMER_PERIODIC && init_count > 0) { - native_scaled_apic_ticks_when_timer_starts = apic_time_now_scaled(); + native_scaled_apic_ticks_when_timer_starts = lapic_time_now_scaled(); uint64_t delay_ticks = init_count * lapic_dcr_to_divider(); LOG_APIC("restarting periodic timeout for 0x%lx ticks\n", delay_ticks); @@ -225,13 +213,92 @@ static void handle_lapic_timer_nftn(size_t vcpu_id) } /* But only inject IRQ if it is not masked */ - uint32_t timer_reg = vapic_read_reg(REG_LAPIC_TIMER); + uint32_t timer_reg = lapic_read_reg(REG_LAPIC_TIMER); if (!(timer_reg & BIT(16))) { uint8_t vector = timer_reg & 0xff; assert(inject_lapic_irq(vcpu_id, vector)); } } +static void lapic_write_init_count_reg(uint32_t data) +{ + /* [1] "12.5.4 APIC Timer" */ + lapic_write_reg(REG_LAPIC_INIT_CNT, data); + if (data) { + uint32_t timer_reg = lapic_read_reg(REG_LAPIC_TIMER); + (void)timer_reg; + LOG_APIC("LAPIC timer started, mode 0x%x, irq masked %d\n", (timer_reg >> 17) % 0x3, + !!(timer_reg & BIT(16))); + + uint64_t delay_ticks = data * lapic_dcr_to_divider(); + LOG_APIC("setting timeout for 0x%lx ticks\n", data); + + if (timeout_handle_valid) { + /* Guest kernel has changed the timeout */ + guest_time_cancel_timeout(timeout_handle); + timeout_handle_valid = false; + } + + timeout_handle = guest_time_request_timeout(delay_ticks, &handle_lapic_timer_nftn, 0); + assert(timeout_handle != TIMEOUT_HANDLE_INVALID); + timeout_handle_valid = true; + + native_scaled_apic_ticks_when_timer_starts = lapic_time_now_scaled(); + } else { + if (timeout_handle_valid) { + /* Guest kernel has cancelled the timeout */ + guest_time_cancel_timeout(timeout_handle); + timeout_handle_valid = false; + } + } +} + +static void lapic_write_icr_low(uint32_t data) +{ + lapic_write_reg(REG_LAPIC_ICR_LOW, data); + + /* [1] "12.6.1 Interrupt Command Register (ICR)" + * "The act of writing to the low doubleword of the ICR causes the IPI to be sent." + */ + uint64_t icr = (uint64_t)data | (((uint64_t)lapic_read_reg(REG_LAPIC_ICR_HIGH)) << 32); + + // @billn sus, handle other types of IPIs + uint8_t delivery_mode = ((icr >> 8) & 0x7); + uint8_t destination = (icr >> 56) & 0xff; + if (delivery_mode == 0 || delivery_mode == 5) { + // fixed mode + if (destination != 0) { + LOG_VMM_ERR("trying to send IPI to unknown APIC ID %d\n", destination); + } + uint8_t vector = icr & 0xff; + if (!inject_lapic_irq(GUEST_BOOT_VCPU_ID, vector)) { + LOG_VMM_ERR("failed to send IPI\n"); + } + } else { + LOG_VMM_ERR("LAPIC received requuest to send IPI of unknown delivery mode 0x%x, destination 0x%x\n", + delivery_mode, destination); + } +} + +bool lapic_read_fault_handle(uint64_t offset, uint32_t *result) +{ + switch (offset) { + case REG_LAPIC_CURR_CNT: { + *result = lapic_read_curr_count_reg(); + break; + } + case REG_LAPIC_CMCI: { + *result = 0; + break; + } + default: + LOG_VMM_ERR("Reading unknown LAPIC register offset 0x%x\n", offset); + return false; + } + + return true; +} + bool lapic_write_fault_handle(uint64_t offset, uint32_t data) { switch (offset) { @@ -248,60 +315,15 @@ bool lapic_write_fault_handle(uint64_t offset, uint32_t data) case REG_LAPIC_THERMAL: case REG_LAPIC_PERF_MON_CNTER: case REG_LAPIC_CMCI: - vapic_write_reg(offset, data); + lapic_write_reg(offset, data); break; case REG_LAPIC_INIT_CNT: { - /* [1] "12.5.4 APIC Timer" */ - uint32_t init_count = data; - if (init_count > 0) { - uint32_t timer_reg = vapic_read_reg(REG_LAPIC_TIMER); - (void)timer_reg; - LOG_APIC("LAPIC timer started, mode 0x%x, irq masked %d\n", (timer_reg >> 17) % 0x3, - !!(timer_reg & BIT(16))); - - uint64_t delay_ticks = init_count * lapic_dcr_to_divider(); - LOG_APIC("setting timeout for 0x%lx ticks\n", init_count); - - if (timeout_handle_valid) { - /* Guest kernel has changed the timeout */ - guest_time_cancel_timeout(timeout_handle); - timeout_handle_valid = false; - } - - timeout_handle = guest_time_request_timeout(delay_ticks, &handle_lapic_timer_nftn, 0); - assert(timeout_handle != TIMEOUT_HANDLE_INVALID); - timeout_handle_valid = true; - - native_scaled_apic_ticks_when_timer_starts = apic_time_now_scaled(); - } + lapic_write_init_count_reg(data); break; } - case REG_LAPIC_ICR_LOW: { - /* [1] "12.6.1 Interrupt Command Register (ICR)" - * "The act of writing to the low doubleword of the ICR causes the IPI to be sent." - */ - uint64_t icr = (uint64_t)data | (((uint64_t)vapic_read_reg(REG_LAPIC_ICR_HIGH)) << 32); - - // @billn sus, handle other types of IPIs - uint8_t delivery_mode = ((icr >> 8) & 0x7); - uint8_t destination = (icr >> 56) & 0xff; - if (delivery_mode == 0 || delivery_mode == 5) { - // fixed mode - if (destination != 0) { - LOG_VMM_ERR("trying to send IPI to unknown APIC ID %d\n", destination); - return true; - } - uint8_t vector = icr & 0xff; - if (!inject_lapic_irq(GUEST_BOOT_VCPU_ID, vector)) { - LOG_VMM_ERR("failed to send IPI\n"); - return false; - } - } else { - LOG_VMM_ERR("LAPIC received requuest to send IPI of unknown delivery mode 0x%x, destination 0x%x\n", - delivery_mode, destination); - } + lapic_write_icr_low(data); break; } @@ -420,7 +442,7 @@ bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) { assert(vcpu_id == 0); - if (!(vapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { + if (!(lapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { /* [1] "Figure 12-23. Spurious-Interrupt Vector Register (SVR)" * APIC Software Disable bit */ return false; @@ -433,7 +455,7 @@ bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) assert(irr_reg_off <= REG_LAPIC_IRR_7); /* Mark as pending for injection, let hardware handle the rest */ - vapic_write_reg(irr_reg_off, vapic_read_reg(irr_reg_off) | BIT(irr_idx)); + lapic_write_reg(irr_reg_off, lapic_read_reg(irr_reg_off) | BIT(irr_idx)); /* See "26.4.2 Guest Non-Register State" for "Guest interrupt status" layout */ int highest_vector_pending = get_next_pending_irq_vector(); diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 81052ac3f..43ee191b0 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -406,7 +406,7 @@ bool fault_handle(size_t vcpu_id) * "The exit qualification is the page offset of the write access that led to the VM exit." */ uint64_t lapic_reg_offset = qualification; - success = lapic_write_fault_handle(lapic_reg_offset, vapic_read_reg(lapic_reg_offset)); + success = lapic_write_fault_handle(lapic_reg_offset, lapic_read_reg(lapic_reg_offset)); break; } case APIC_ACCESS: { diff --git a/src/arch/x86_64/guest.c b/src/arch/x86_64/guest.c index 1c88b3a5f..a167b4338 100644 --- a/src/arch/x86_64/guest.c +++ b/src/arch/x86_64/guest.c @@ -48,8 +48,7 @@ bool guest_init(arch_guest_init_t init_args) } /* Initialise the virtual Local and I/O APICs */ - // @billn revisit vapic vaddr - bool success = virq_controller_init(guest_time_tsc_hz(), 0xfffffffffffffff); + bool success = virq_controller_init(guest_time_tsc_hz(), 0); if (!success) { LOG_VMM_ERR("Failed to initialise virtual IRQ controllers\n"); return false; diff --git a/src/arch/x86_64/msr.c b/src/arch/x86_64/msr.c index ddd582733..8828c30e7 100644 --- a/src/arch/x86_64/msr.c +++ b/src/arch/x86_64/msr.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -106,7 +107,7 @@ bool emulate_rdmsr(seL4_VCPUContext *vctx) break; } case IA32_TIME_STAMP_COUNTER: - result = rdtsc(); + result = guest_time_tsc_now(); break; case MSR_STAR: case MSR_LSTAR: diff --git a/src/arch/x86_64/virq.c b/src/arch/x86_64/virq.c index 94e50a661..4eb9f98ce 100644 --- a/src/arch/x86_64/virq.c +++ b/src/arch/x86_64/virq.c @@ -35,18 +35,18 @@ bool virq_controller_init(uint64_t native_tsc_hz, uintptr_t guest_vapic_vaddr) // [1] "12.4.8 Local APIC Version Register" // "For processors based on the Nehalem microarchitecture (which has 7 LVT entries) and onward, the value returned is 6." - vapic_write_reg(REG_LAPIC_REV, (uint32_t)0x10 | (uint32_t)6 << 16); + lapic_write_reg(REG_LAPIC_REV, (uint32_t)0x10 | (uint32_t)6 << 16); // [1] "Figure 12-23. Spurious-Interrupt Vector Register (SVR)" - vapic_write_reg(REG_LAPIC_SVR, (uint32_t)0xff); // reset value + lapic_write_reg(REG_LAPIC_SVR, (uint32_t)0xff); // reset value // [1] "Figure 12-8. Local Vector Table (LVT)" // LVT Timer Register - vapic_write_reg(REG_LAPIC_TIMER, 0x10000); // reset value, masked. + lapic_write_reg(REG_LAPIC_TIMER, 0x10000); // reset value, masked. // [1] "Figure 12-8. Local Vector Table (LVT)" // "Specifies interrupt delivery when an interrupt is signaled at the LINT0 pin" - vapic_write_reg(REG_LAPIC_LVT_LINT0, 0x10000); // reset value - vapic_write_reg(REG_LAPIC_LVT_LINT1, 0x10000); // reset value + lapic_write_reg(REG_LAPIC_LVT_LINT0, 0x10000); // reset value + lapic_write_reg(REG_LAPIC_LVT_LINT1, 0x10000); // reset value // [1] "Figure 12-14. Destination Format Register (DFR)" - vapic_write_reg(REG_LAPIC_DFR, 0xffffffff); // reset value + lapic_write_reg(REG_LAPIC_DFR, 0xffffffff); // reset value LOG_VMM("initialising I/O APIC\n"); // [2] default value for the Intel 82093AA IOAPIC. From 71a4e40ba3a4960e4d5f03251392f3bbbb02b158 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 7 May 2026 11:16:45 +1000 Subject: [PATCH 39/42] x86_64: silence APIC error that may happen normally As printing it causes the timer to stop and the guest to hang, presumably because the print is taking a long time and interfering with the timer math. Signed-off-by: Bill Nguyen --- src/arch/x86_64/apic.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index 7d28854f1..ab49074e7 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -271,9 +271,7 @@ static void lapic_write_icr_low(uint32_t data) LOG_VMM_ERR("trying to send IPI to unknown APIC ID %d\n", destination); } uint8_t vector = icr & 0xff; - if (!inject_lapic_irq(GUEST_BOOT_VCPU_ID, vector)) { - LOG_VMM_ERR("failed to send IPI\n"); - } + inject_lapic_irq(GUEST_BOOT_VCPU_ID, vector); } else { LOG_VMM_ERR("LAPIC received requuest to send IPI of unknown delivery mode 0x%x, destination 0x%x\n", delivery_mode, destination); @@ -442,6 +440,11 @@ bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) { assert(vcpu_id == 0); + if (vector < MIN_VECTOR) { + /* Architecturally reserved vector. */ + return false; + } + if (!(lapic_read_reg(REG_LAPIC_SVR) & BIT(8))) { /* [1] "Figure 12-23. Spurious-Interrupt Vector Register (SVR)" * APIC Software Disable bit */ From 19b6a957d87bb058df00a63a5243f5962d8d9f9c Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 7 May 2026 11:16:56 +1000 Subject: [PATCH 40/42] examples/simple: makefile fix for x86 Signed-off-by: Bill Nguyen --- examples/simple/simple.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple/simple.mk b/examples/simple/simple.mk index 3987c8e3e..1727f1c47 100644 --- a/examples/simple/simple.mk +++ b/examples/simple/simple.mk @@ -35,7 +35,7 @@ else ifeq ($(ARCH),x86_64) IMAGES += timer_driver.elf QEMU := qemu-system-x86_64 - QEMU_ARCH_ARGS := -accel kvm -cpu host,+fsgsbase,+pdpe1gb,+xsaveopt,+xsave,+vmx,+vme -kernel $(KERNEL32) -initrd $(IMAGE_FILE) + QEMU_ARCH_ARGS := -accel kvm -cpu host,+fsgsbase,+pdpe1gb,+xsaveopt,+xsave,+vmx,+vme -kernel sel4_32.elf -initrd $(IMAGE_FILE) else $(error Unsupported ARCH given) endif From 6314fdcf8306749fb4c3e49106e688f8ffbcd006 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 7 May 2026 11:31:21 +1000 Subject: [PATCH 41/42] x86_64: reimplemented instruction decoding... Previously we relied on the silicon telling us the instruction length on an EPT fault. But I discovered that Intel actually defined that the instruction length is invalid on an EPT exit. We got by previously as the silicon told us anyway and Linux KVM pass it through, but Windows Hyper-V is more strict so the VMM breaks on WSL2. The decoder will now deduce the instruction length by itself. Signed-off-by: Bill Nguyen --- include/libvmm/arch/x86_64/instruction.h | 4 +- src/arch/x86_64/fault.c | 5 +- src/arch/x86_64/instruction.c | 174 +++++++++++++++-------- 3 files changed, 119 insertions(+), 64 deletions(-) diff --git a/include/libvmm/arch/x86_64/instruction.h b/include/libvmm/arch/x86_64/instruction.h index 4d96c3fd2..cfb9c46ed 100644 --- a/include/libvmm/arch/x86_64/instruction.h +++ b/include/libvmm/arch/x86_64/instruction.h @@ -67,13 +67,13 @@ typedef enum instruction_type { typedef struct decoded_instruction_ret { /* For debugging purpose */ char raw[X86_MAX_INSTRUCTION_LENGTH]; - int raw_len; + int len; instruction_type_t type; instruction_data_t decoded; } decoded_instruction_ret_t; -decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4_Word instruction_len); +decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip); void debug_print_instruction(decoded_instruction_ret_t decode_result); diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index 43ee191b0..c885eb066 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -380,10 +380,13 @@ bool fault_handle(size_t vcpu_id) success = emulate_wrmsr(&vctx); break; case EPT_VIOLATION: - decoded_ins = decode_instruction(vcpu_id, rip, ins_len); + decoded_ins = decode_instruction(vcpu_id, rip); if (decoded_ins.type == INSTRUCTION_DECODE_FAIL) { success = false; } else { + /* See "30.2.5 Information for VM Exits Due to Instruction Execution" + * Note that for EPT faults the instruction length won't be valid. */ + ins_len = decoded_ins.len; success = handle_ept_fault(&vctx, qualification, decoded_ins); } break; diff --git a/src/arch/x86_64/instruction.c b/src/arch/x86_64/instruction.c index 3dc77c52e..e31181012 100644 --- a/src/arch/x86_64/instruction.c +++ b/src/arch/x86_64/instruction.c @@ -215,12 +215,12 @@ static char *vctx_idx_to_name(int vctx_idx) void debug_print_instruction(decoded_instruction_ret_t decode_result) { - assert(decode_result.raw_len < X86_MAX_INSTRUCTION_LENGTH); + assert(decode_result.len <= X86_MAX_INSTRUCTION_LENGTH); LOG_VMM("debug_print_instruction(): decoder result:\n"); - LOG_VMM("instruction length: %d\n", decode_result.raw_len); + LOG_VMM("instruction length: %d\n", decode_result.len); LOG_VMM("raw instruction:\n"); - for (int i = 0; i < decode_result.raw_len; i++) { + for (int i = 0; i < decode_result.len; i++) { LOG_VMM("0x%hhx\n", decode_result.raw[i]); } @@ -248,69 +248,60 @@ void debug_print_instruction(decoded_instruction_ret_t decode_result) } } -decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4_Word instruction_len) +decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip) { uint8_t instruction_buf[X86_MAX_INSTRUCTION_LENGTH]; - memset(instruction_buf, 0, X86_MAX_INSTRUCTION_LENGTH); - uint64_t rip_gpa; size_t bytes_remaining; assert(gva_to_gpa(vcpu_id, rip, &rip_gpa, &bytes_remaining)); // @billn fix lazyness, crashes if the instruction crosses a page boundary - assert(bytes_remaining >= instruction_len); - assert(instruction_len <= X86_MAX_INSTRUCTION_LENGTH); + assert(bytes_remaining >= X86_MAX_INSTRUCTION_LENGTH); + /* Copy 15 bytes of instruction from guest RAM, the actual number of bytes parsed will be less. + * We have to derive the instruction length ourselves, as the silicon won't tell us... */ void *instruction_vaddr = gpa_to_vaddr_or_crash(rip_gpa, &bytes_remaining); - memcpy(instruction_buf, instruction_vaddr, instruction_len); + memcpy(instruction_buf, instruction_vaddr, X86_MAX_INSTRUCTION_LENGTH); - // @billn I really think something more "industrial grade" should be used for a job like this. - // Such as https://github.com/zyantific/zydis which is no-malloc and no-libc, but it uses cmake...yuck - // But then we introduce a dependency... decoded_instruction_ret_t ret = { .type = INSTRUCTION_DECODE_FAIL, .decoded = {} }; - memcpy(&ret.raw, instruction_vaddr, instruction_len); - ret.raw_len = instruction_len; - bool opcode_valid = false; int parsed_byte = 0; bool rex_w = false; // 64-bit operand size bool rex_r = false; // 4-bit operand, rather than 3-bit - // bool rex_x = false; // 4-bit SIB.index - // bool rex_b = false; // 4-bit MODRM.rm field or the SIB.base field bool opd_size_override = false; - for (int i = 0; i < instruction_len; i++) { - // scan for REX byte, which is always 0b0100WRXB + /* First step is to match any prefixes, since we are mainly concerned with the `mov` instruction. + * The only prefixes we care about are the REX and "operand-size override". Since they can appear + * in any order, parse them in a loop. */ + bool parsing_prefix = true; + while (parsing_prefix && parsed_byte < X86_MAX_INSTRUCTION_LENGTH) { if (instruction_buf[parsed_byte] >> 4 == 4) { + /* Match for REX byte, which is always 0b0100WRXB */ uint8_t rex_byte = instruction_buf[parsed_byte]; parsed_byte += 1; - rex_w = (rex_byte & BIT(3)) != 0; rex_r = (rex_byte & BIT(2)) != 0; - // rex_x = (rex_byte & BIT(1)) != 0; - // rex_b = (rex_byte & BIT(0)) != 0; - } - - // scan for the "operand-size override" prefix, which switch the operand size - // from 32 to 16 bits, though the REX prefix have more precendence - if (instruction_buf[parsed_byte] == 0x66) { + } else if (instruction_buf[parsed_byte] == 0x66) { + /* Match for the "operand-size override" prefix, which switch the operand size + * from 32 to 16 bits, though the REX prefix have more precendence */ opd_size_override = true; parsed_byte += 1; + } else { + parsing_prefix = false; } } - // match the opcode against a list of known opcodes that we provide decoding logic for. - // An opcode can be multi-bytes, first match for 1 byte opcode + /* Should still have something left to parse! */ + assert(parsed_byte < X86_MAX_INSTRUCTION_LENGTH); + + /* Match the opcode against a list of known opcodes that we provide decoding logic for. + * An opcode can be multi-bytes, first match for 1 byte opcode */ + bool opcode_valid = false; for (int i = 0; i < NUM_MOV_OPCODES; i++) { if (instruction_buf[parsed_byte] == mov_opcodes[i]) { opcode_valid = true; uint8_t opcode = instruction_buf[parsed_byte]; - - // An opcode byte is followed by a ModR/M byte to encode src/dest register. - uint8_t modrm = instruction_buf[parsed_byte + 1]; - // uint8_t mod = modrm >> 6; - uint8_t reg = (modrm >> 3) & 0x7; - // uint8_t rm = modrm & 0x7; + parsed_byte++; ret.type = INSTRUCTION_MEMORY; if (rex_w) { @@ -336,41 +327,34 @@ decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4 } } ret.decoded.memory_instruction.zero_extend = false; - ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); - break; } } - // no match, now try the 2 bytes movzx opcodes - if (instruction_len - parsed_byte >= 3 && !opcode_valid) { + /* no match, now try the 2 bytes movzx opcodes */ + if (!opcode_valid) { if (instruction_buf[parsed_byte] == opcode_movzx_byte_from_mem[0] && instruction_buf[parsed_byte + 1] == opcode_movzx_byte_from_mem[1]) { opcode_valid = true; - uint8_t modrm = instruction_buf[parsed_byte + 2]; - uint8_t reg = (modrm >> 3) & 0x7; + parsed_byte += 2; ret.type = INSTRUCTION_MEMORY; ret.decoded.memory_instruction.access_width = BYTE_ACCESS_WIDTH; ret.decoded.memory_instruction.zero_extend = true; - ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); } else if (instruction_buf[parsed_byte] == opcode_movzx_word_from_mem[0] && instruction_buf[parsed_byte + 1] == opcode_movzx_word_from_mem[1]) { opcode_valid = true; - uint8_t modrm = instruction_buf[parsed_byte + 2]; - uint8_t reg = (modrm >> 3) & 0x7; + parsed_byte += 2; ret.type = INSTRUCTION_MEMORY; ret.decoded.memory_instruction.access_width = WORD_ACCESS_WIDTH; ret.decoded.memory_instruction.zero_extend = true; - ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); } } - // no match, try the mov immediate instruciton + /* no match, try the mov immediate opcode */ for (int i = 0; i < NUM_MOV_IMM_OPCODES; i++) { if (instruction_buf[parsed_byte] == mov_imm_opcodes[i]) { opcode_valid = true; - // TODO: handle unused variable - // uint8_t opcode = instruction_buf[parsed_byte]; + parsed_byte++; assert(guest_in_64_bits()); @@ -384,25 +368,93 @@ decoded_instruction_ret_t decode_instruction(size_t vcpu_id, seL4_Word rip, seL4 ret.decoded.write_imm_instruction.access_width = DWORD_ACCESS_WIDTH; } } - - // Not going to bother with checking for mod r/m or sib bytes as the CPU already decoded them for us - // just skipping to the immediate - int immediate_bytes = mem_access_width_to_bytes(ret); - assert(instruction_len > immediate_bytes); - memcpy(&(ret.decoded.write_imm_instruction.value), &instruction_buf[instruction_len - immediate_bytes], - immediate_bytes); - break; } } - if (!opcode_valid) { - LOG_VMM_ERR("uh-oh can't decode instruction, bail\n"); - for (int i = 0; i < instruction_len; i++) { - LOG_VMM_ERR("ins byte 0x%x\n", instruction_buf[i]); + if (opcode_valid) { + /* Successfully matched against a known opcode, and `parsed_byte` point to the first byte + * after the opcode in `instruction_buf`. Now parse the ModR/M, SIB, and Displacement */ + + /* "The ModR/M byte encodes a register or an opcode extension, and a register or a memory address" + * 6 4 0 + * +---+---+---+---+---+---+---+---+ + * | mod | reg | rm | + * +---+---+---+---+---+---+---+---+ + */ + uint8_t modrm = instruction_buf[parsed_byte]; + uint8_t mod = (modrm >> 6) & 0x3; /* Addressing mode (register vs memory, and displacement size) */ + uint8_t reg = (modrm >> 3) & 0x7; /* Register operand, or opcode extension */ + uint8_t rm = modrm & 0x7; /* Register or memory operand */ + parsed_byte++; + + /* Save the target register now that we have it */ + if (ret.type == INSTRUCTION_MEMORY) { + ret.decoded.memory_instruction.target_reg = modrm_reg_to_vctx_idx(reg, rex_r); + } + + bool has_sib = false; + uint8_t sib = 0; + + /* Parse SIB (Scale-Index-Base) + * If `mod` != 3 (meaning we are accessing memory, not just a register) + * AND `rm` == 4 (binary 100), it's an x86 escape code meaning "a SIB byte follows". */ + if (mod != 3 && rm == 4) { + has_sib = true; + sib = instruction_buf[parsed_byte]; + parsed_byte++; /* consume SIB */ + } + + /* Calculate Displacement Length + * Displacement is a constant byte offset added to the memory address. */ + int disp_bytes = 0; + if (mod == 0) { + /* mod == 0 usually means no displacement. However, there are two exceptions: + * 1. rm == 5: In 64-bit, this means RIP-relative addressing. + * 2. has_sib && base == 5 (sib & 0x7 isolates the SIB base register): Means no base register. + * Both of these special cases require a mandatory 32-bit (4-byte) displacement. */ + if (rm == 5 || (has_sib && (sib & 0x7) == 5)) { + disp_bytes = 4; + } + } else if (mod == 1) { + disp_bytes = 1; + } else if (mod == 2) { + disp_bytes = 4; + } + + parsed_byte += disp_bytes; + + /* Parse Immediate (if applicable) */ + if (ret.type == INSTRUCTION_WRITE_IMM) { + int immediate_bytes = mem_access_width_to_bytes(ret); + if (immediate_bytes > 4) { + /* The 0xC7 opcode (MOV to memory/reg) can write up to 64 bits of data, + * but the instruction encoding limits the actual immediate value to 32 bits maximum. */ + immediate_bytes = 4; + } + + memcpy(&(ret.decoded.write_imm_instruction.value), &instruction_buf[parsed_byte], immediate_bytes); + + /* Manual sign extension if REX.W was used with a 32-bit immediate. + * Because the 0xC7 instruction limits immediates to 32 bits (4 bytes) even when + * writing to a 64-bit (8 bytes) destination, the CPU sign-extends the value. + * We must emulate that behavior here. */ + if (immediate_bytes == 4 && mem_access_width_to_bytes(ret) == 8) { + int32_t signed_imm = (int32_t)ret.decoded.write_imm_instruction.value; + ret.decoded.write_imm_instruction.value = (uint64_t)signed_imm; + } + + parsed_byte += immediate_bytes; + } + } else { + LOG_VMM_ERR("failed to decode instruction due to an unknown opcode.\n"); + for (int i = 0; i < X86_MAX_INSTRUCTION_LENGTH; i++) { + LOG_VMM_ERR("instruction byte: 0x%x\n", instruction_buf[i]); } vcpu_print_regs(0); - assert(opcode_valid); } + + memcpy(&ret.raw, instruction_vaddr, X86_MAX_INSTRUCTION_LENGTH); + ret.len = parsed_byte; return ret; } \ No newline at end of file From 955ffb48770c67afdc500711ec7c3529c4eb749e Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Thu, 7 May 2026 15:52:06 +1000 Subject: [PATCH 42/42] WIP x86_64: add software APIC and proper VCPU state management Signed-off-by: Bill Nguyen --- .../board/x86_64_generic_vtx/simple.system | 2 +- examples/simple/vmm.c | 11 + include/libvmm/arch/x86_64/apic.h | 18 + include/libvmm/arch/x86_64/vcpu.h | 16 + include/libvmm/arch/x86_64/vmcs.h | 22 +- src/arch/x86_64/apic.c | 343 ++++++++++++++++-- src/arch/x86_64/fault.c | 86 ++--- src/arch/x86_64/guest.c | 5 +- src/arch/x86_64/vcpu.c | 177 ++++++++- 9 files changed, 606 insertions(+), 74 deletions(-) diff --git a/examples/simple/board/x86_64_generic_vtx/simple.system b/examples/simple/board/x86_64_generic_vtx/simple.system index e25142558..a899f8585 100644 --- a/examples/simple/board/x86_64_generic_vtx/simple.system +++ b/examples/simple/board/x86_64_generic_vtx/simple.system @@ -12,7 +12,7 @@ - + diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index 3a1426260..1039b4e51 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -167,6 +167,13 @@ void init(void) void notified(microkit_channel ch) { +#if defined(CONFIG_ARCH_X86_64) + /* In our case a VCPU is always running, so if we get notified then it must've mean that a + * VCPU was stopped, we need to save the context of the VCPU so that we can resume it again + * later, since the IPC buffer maybe clobbered. */ + vcpu_init_exit_state(true); +#endif + switch (ch) { #if defined(CONFIG_ARCH_X86_64) case TIMER_DRV_CH: { @@ -192,6 +199,10 @@ void notified(microkit_channel ch) printf("Unexpected channel, ch: 0x%lx\n", ch); #endif } + +#if defined(CONFIG_ARCH_X86_64) + vcpu_exit_resume(); +#endif } /* diff --git a/include/libvmm/arch/x86_64/apic.h b/include/libvmm/arch/x86_64/apic.h index ce78b5c41..ffd657711 100644 --- a/include/libvmm/arch/x86_64/apic.h +++ b/include/libvmm/arch/x86_64/apic.h @@ -11,6 +11,13 @@ #include #include +/* Virtual Local APIC and I/O APIC facility. */ + +/* Use the software emulation implementation, uncomment to use Intel APICv hardware acceleration. + * This is useful when you don't have APICv for whatever reasons, e.g. triple nested virtualisation under WSL2, + * or using an older CPU. */ +#define SOFTWARE_APIC + /* Documents referenced: * 1. Intel® 64 and IA-32 Architectures Software Developer’s Manual * Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 @@ -101,8 +108,19 @@ struct ioapic_regs { uint32_t lapic_read_reg(int offset); void lapic_write_reg(int offset, uint32_t value); +#if defined(SOFTWARE_APIC) +/* Inject a highest priority interrupt that is eligible to be delivered. + * Assumes that the vCPU's architectural state allow injection! */ +void lapic_maintenance(void); +/* Handle an EPT fault on the virtual local APIC. */ +bool lapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, + decoded_instruction_ret_t decoded_ins); +#endif + +/* Read and write the virtual local APIC registers directly */ bool lapic_read_fault_handle(uint64_t offset, uint32_t *result); bool lapic_write_fault_handle(uint64_t offset, uint32_t data); + bool ioapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, decoded_instruction_ret_t decoded_ins); diff --git a/include/libvmm/arch/x86_64/vcpu.h b/include/libvmm/arch/x86_64/vcpu.h index 5e9e45211..091549489 100644 --- a/include/libvmm/arch/x86_64/vcpu.h +++ b/include/libvmm/arch/x86_64/vcpu.h @@ -55,4 +55,20 @@ bool vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit); +/* Keep track of the VCPU state when a VM Exit happens. */ +void vcpu_init_exit_state(bool exit_from_ntfn); +uint64_t vcpu_exit_get_rip(void); +void vcpu_exit_update_ppvc(uint64_t ppvc); +uint64_t vcpu_exit_get_irq(void); +void vcpu_exit_inject_irq(uint64_t irq); +uint64_t vcpu_exit_get_reason(void); +uint64_t vcpu_exit_get_qualification(void); +uint64_t vcpu_exit_get_instruction_len(void); +uint64_t vcpu_exit_get_rflags(void); +uint64_t vcpu_exit_get_interruptability(void); +uint64_t vcpu_exit_get_cr3(void); +seL4_VCPUContext *vcpu_exit_get_context(void); +void vcpu_exit_advance_rip(unsigned rip_additive); +void vcpu_exit_resume(void); + void vcpu_print_regs(size_t vcpu_id); diff --git a/include/libvmm/arch/x86_64/vmcs.h b/include/libvmm/arch/x86_64/vmcs.h index 5660cd471..f99429b66 100644 --- a/include/libvmm/arch/x86_64/vmcs.h +++ b/include/libvmm/arch/x86_64/vmcs.h @@ -6,7 +6,7 @@ #pragma once #include - +#include #include /* @@ -177,10 +177,18 @@ #define VMX_HOST_RIP 0x00006C16 /* [2] "Primary Processor-Based VM-Execution Controls Register" */ -#define VMCS_PPC_ACTIVATE_SECONDARY_CTRL BIT(31) -#define VMCS_PPC_USE_TPR_SHADOW BIT(21) - -#define VMCS_PCC_DEFAULT (VMCS_PPC_USE_TPR_SHADOW | VMCS_PPC_ACTIVATE_SECONDARY_CTRL) +#define VMCS_PPVC_IRQ_WINDOW_EXIT BIT(2) +#define VMCS_PPVC_CR8_LOAD_EXIT BIT(19) +#define VMCS_PPVC_CR8_SAVE_EXIT BIT(20) +#define VMCS_PPVC_USE_TPR_SHADOW BIT(21) +#define VMCS_PPVC_ACTIVATE_SECONDARY_CTRL BIT(31) + +#if defined(SOFTWARE_APIC) +#define VMCS_PPVC_DEFAULT (VMCS_PPVC_ACTIVATE_SECONDARY_CTRL | VMCS_PPVC_CR8_LOAD_EXIT | VMCS_PPVC_CR8_SAVE_EXIT) +#define VMCS_PPVC_WAIT_IRQ_WINDOW (VMCS_PPVC_DEFAULT | VMCS_PPVC_IRQ_WINDOW_EXIT) +#else +#define VMCS_PPVC_DEFAULT (VMCS_PPVC_ACTIVATE_SECONDARY_CTRL | VMCS_PPVC_USE_TPR_SHADOW) +#endif /* [2] "Definitions of Secondary Processor-Based VM-Execution Controls" */ #define VMCS_SPC_ENABLE_VAPIC BIT(0) @@ -190,7 +198,11 @@ #define VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY BIT(9) #define VMCS_SPC_ENABLE_XSAVES BIT(20) +#if defined(SOFTWARE_APIC) +#define VMCS_SPC_DEFAULT (VMCS_SPC_ENABLE_EPT | VMCS_SPC_ENABLE_VPID | VMCS_SPC_ENABLE_XSAVES) +#else #define VMCS_SPC_DEFAULT (VMCS_SPC_ENABLE_EPT | VMCS_SPC_ENABLE_VPID | VMCS_SPC_ENABLE_XSAVES | VMCS_SPC_ENABLE_VAPIC | VMCS_SPC_ENABLE_APIC_REG_VIRT | VMCS_SPC_ENABLE_VIRT_IRQ_DELIVERY) +#endif /* [2] "Definitions of VM-Entry Controls" */ #define VMCS_VEC_ENABLE_IA32E BIT(9) diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index ab49074e7..45f4f7e24 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -18,6 +18,15 @@ #include #include +/* Implementation of a virtual Local APIC and I/O APIC. */ + +#if defined(SOFTWARE_APIC) + +#define LAPIC_REG_BLOCK_SIZE 0x1000 +char lapic_regs[LAPIC_REG_BLOCK_SIZE]; + +#endif + // Uncomment this to enable debug logging // #define DEBUG_APIC @@ -42,6 +51,7 @@ #define LAPIC_NUM_ISR_IRR_TMR_32B 8 #define MAX_VECTOR (LAPIC_NUM_ISR_IRR_TMR_32B * 32) +#define IRR_ISR_MULTIPLIER 0x10 #if defined(DEBUG_APIC) #define LOG_APIC(...) do{ printf("%s|APIC: ", microkit_name); printf(__VA_ARGS__); }while(0) @@ -62,15 +72,29 @@ guest_timeout_handle_t timeout_handle; uint32_t lapic_read_reg(int offset) { assert(offset < 0x1000); + +#if defined(SOFTWARE_APIC) + uintptr_t lapic_regs_ptr = (uintptr_t)(&lapic_regs); +#else // @billn fix hardcoded vaddr - return *((volatile uint32_t *)(0x101000ull + offset)); + uintptr_t lapic_regs_ptr = 0x101000ull; +#endif + + return *((volatile uint32_t *)(lapic_regs_ptr + offset)); } void lapic_write_reg(int offset, uint32_t value) { assert(offset < 0x1000); + +#if defined(SOFTWARE_APIC) + uintptr_t lapic_regs_ptr = (uintptr_t)(&lapic_regs); +#else // @billn fix hardcoded vaddr - volatile uint32_t *reg = (uint32_t *)(0x101000ull + offset); + uintptr_t lapic_regs_ptr = 0x101000ull; +#endif + + volatile uint32_t *reg = (uint32_t *)(lapic_regs_ptr + offset); *reg = value; } @@ -81,7 +105,7 @@ static int get_next_pending_irq_vector(void) */ for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { for (int j = 31; j >= 0; j--) { - int irr_reg_off = REG_LAPIC_IRR_0 + (i * 0x10); + int irr_reg_off = REG_LAPIC_IRR_0 + (i * IRR_ISR_MULTIPLIER); if (lapic_read_reg(irr_reg_off) & BIT(j)) { uint8_t candidate_vector = i * 32 + j; return candidate_vector; @@ -91,16 +115,15 @@ static int get_next_pending_irq_vector(void) return -1; } -static void debug_print_lapic_pending_irqs(void) +static void mark_irq_pending(uint8_t vector) { - for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { - for (int j = 31; j >= 0; j--) { - uint32_t irr = lapic_read_reg(REG_LAPIC_IRR_0 + (i * 0x10)); - if (irr & BIT(j)) { - LOG_VMM("irq vector %d is pending\n", i * 32 + j); - } - } - } + int irr_n = vector / 32; + int irr_idx = vector % 32; + + int irr_reg_off = REG_LAPIC_IRR_0 + (irr_n * IRR_ISR_MULTIPLIER); + assert(irr_reg_off <= REG_LAPIC_IRR_7); + + lapic_write_reg(irr_reg_off, lapic_read_reg(irr_reg_off) | BIT(irr_idx)); } static int lapic_dcr_to_divider(void) @@ -137,6 +160,215 @@ static uint8_t ioapic_pin_to_vector(int ioapic, int pin) return ioapic_regs.ioredtbl[pin] & 0xff; } +#if defined(SOFTWARE_APIC) +static void mark_irq_in_service(uint8_t vector) +{ + int irr_n = vector / 32; + int irr_idx = vector % 32; + + int irr_reg_off = REG_LAPIC_IRR_0 + (irr_n * IRR_ISR_MULTIPLIER); + assert(irr_reg_off <= REG_LAPIC_IRR_7); + + /* Should have been pending! */ + assert(lapic_read_reg(irr_reg_off) | BIT(irr_idx)); + + /* Clear pending bit */ + lapic_write_reg(irr_reg_off, lapic_read_reg(irr_reg_off) & ~BIT(irr_idx)); + + /* Set in service bit */ + int isr_reg_off = REG_LAPIC_ISR_0 + (irr_n * IRR_ISR_MULTIPLIER); + lapic_write_reg(isr_reg_off, lapic_read_reg(isr_reg_off) | BIT(irr_idx)); +} + +static bool is_irq_in_service(uint8_t vector) +{ + int isr_n = vector / 32; + int isr_idx = vector % 32; + + int isr_reg_off = REG_LAPIC_ISR_0 + (isr_n * IRR_ISR_MULTIPLIER); + assert(isr_reg_off <= REG_LAPIC_ISR_7); + + return !!(lapic_read_reg(isr_reg_off) & BIT(isr_idx)); +} + +static bool get_highest_vector_in_service(uint8_t *ret) +{ + for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { + for (int j = 31; j >= 0; j--) { + int isr_reg_off = REG_LAPIC_ISR_0 + (i * IRR_ISR_MULTIPLIER); + if (lapic_read_reg(isr_reg_off) & BIT(j)) { + *ret = i * 32 + j; + return true; + } + } + } + return false; +} + +static int get_next_eligible_irq_vector(void) +{ + // uint8_t ppr = get_ppr(); + + // scan IRRs for *a* pending interrupt + // do it "right-to-left" as the higer vector is higher prio (generally) + for (int i = LAPIC_NUM_ISR_IRR_TMR_32B - 1; i >= 0; i--) { + for (int j = 31; j >= 0; j--) { + int irr_reg_off = REG_LAPIC_IRR_0 + (i * IRR_ISR_MULTIPLIER); + if (lapic_read_reg(irr_reg_off) & BIT(j)) { + uint8_t candidate_vector = i * 32 + j; + // @billn highly sus, revisit PPR calculation + if (candidate_vector >> 4 > lapic_read_reg(REG_LAPIC_TPR) >> 4) { + return candidate_vector; + } else { + // highest pending vector is lower than highest eligible priority, so do nothing + return -1; + } + } + } + } + return -1; +} + +static uint8_t get_ppr(void) +{ + uint8_t ppr; + + /* [1] "Figure 12-19. Processor-Priority Register (PPR)" */ + uint8_t highest_vector_in_service = 0; + get_highest_vector_in_service(&highest_vector_in_service); + uint8_t highest_priority_in_service = highest_vector_in_service >> 4; + uint8_t task_priority_register = lapic_read_reg(REG_LAPIC_TPR); + uint8_t task_priority_class = task_priority_register >> 4; + uint8_t task_priority_subclass = task_priority_register & 0xf; + uint8_t proc_priority_class = MAX(task_priority_class, highest_priority_in_service); + uint8_t proc_priority_subclass = 0; + + if (task_priority_class >= highest_priority_in_service) { + proc_priority_subclass = task_priority_subclass; + } + ppr = proc_priority_subclass | (proc_priority_class << 4); + return ppr; +} + +static bool vcpu_can_take_irq(size_t vcpu_id) +{ + // Not executing anything that blocks IRQs + if (microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_INTERRUPTABILITY) != 0) { + return false; + } + // IRQ on in cpu register + if (!(microkit_vcpu_x86_read_vmcs(vcpu_id, VMX_GUEST_RFLAGS) & BIT(9))) { + return false; + } + return true; +} + +void lapic_write_tpr(uint8_t tpr) +{ + uint8_t old_tpr = lapic_read_reg(REG_LAPIC_TPR); + lapic_write_reg(REG_LAPIC_TPR, tpr); + if (tpr != old_tpr && vcpu_can_take_irq(0)) { + int vector = get_next_queued_irq_vector(); + if (vector != -1) { + assert(inject_lapic_irq(0, vector)); + } + } +} + +/* Inject a highest priority interrupt that is eligible to be delivered. + * Assumes that the vCPU's architectural state allow injection! */ +void lapic_maintenance(void) +{ + int vector = get_next_eligible_irq_vector(); + if (vector == -1) { + /* no pending IRQ to inject */ + vcpu_exit_update_ppvc(VMCS_PPVC_DEFAULT); + return; + } + + if (is_irq_in_service(vector)) { + /* selected interrupt already in service, remains queued until guest issues EOI + * so we don't loose it. */ + // @billn sus, might break level trigger + vcpu_exit_update_ppvc(VMCS_PPVC_DEFAULT); + return; + } + + if (vcpu_exit_get_irq() & BIT(31)) { + /* Another interrupt is awaiting injection, don't do anything for now + * to prevent interrupt overwriting. */ + return; + } + + /* Move IRQ from pending to in-service */ + mark_irq_in_service(vector); + + /* Tell the hardware to inject an irq on next vmenter. + * Table 26-17. Format of the VM-Entry Interruption-Information Field */ + uint32_t vm_entry_interruption = (uint32_t)vector; + vm_entry_interruption |= BIT(31); // valid bit + + vcpu_exit_update_ppvc(VMCS_PPVC_DEFAULT); + vcpu_exit_inject_irq(vm_entry_interruption); +} + +void lapic_write_eoi(void) +{ + uint8_t done_vector; + if (!get_highest_vector_in_service(&done_vector)) { + return; + } + + /* Clear it from being in service */ + int isr_n = done_vector / 32; + int isr_idx = done_vector % 32; + int isr_reg_off = REG_LAPIC_ISR_0 + (isr_n * IRR_ISR_MULTIPLIER); + lapic_write_reg(isr_reg_off, lapic_read_reg(isr_reg_off) & ~BIT(isr_idx)); + + /* if it is a passed through I/O APIC IRQ, run the ack function */ + for (int i = 0; i < IOAPIC_NUM_PINS; i++) { + if (ioapic_regs.virq_passthrough_map[i].valid) { + uint8_t candidate_vector = ioapic_pin_to_vector(0, i); + if (candidate_vector == done_vector) { + if (ioapic_regs.virq_passthrough_map[i].ack_fn) { + ioapic_regs.virq_passthrough_map[i].ack_fn(0, i, + ioapic_regs.virq_passthrough_map[i].ack_data); + } + return; + } + } + } + + int next_irq_vector = get_next_queued_irq_vector(); + if (next_irq_vector != -1) { + inject_lapic_irq(GUEST_BOOT_VCPU_ID, next_irq_vector); + } +} + +bool lapic_fault_handle(seL4_VCPUContext *vctx, uint64_t offset, seL4_Word qualification, + decoded_instruction_ret_t decoded_ins) +{ + assert(mem_access_width_to_bytes(decoded_ins) == 4); + assert(offset % 4 == 0); + + bool success; + + if (ept_fault_is_read(qualification)) { + uint32_t data; + success = lapic_read_fault_handle(offset, &data); + if (success) { + assert(mem_read_set_data(decoded_ins, qualification, vctx, data)); + } + } else { + uint64_t data; + assert(mem_write_get_data(decoded_ins, qualification, vctx, &data)); + success = lapic_write_fault_handle(offset, data); + } + + return success; +} +#endif /* SOFTWARE_APIC */ + enum lapic_timer_mode { LAPIC_TIMER_ONESHOT, LAPIC_TIMER_PERIODIC, @@ -281,12 +513,61 @@ static void lapic_write_icr_low(uint32_t data) bool lapic_read_fault_handle(uint64_t offset, uint32_t *result) { switch (offset) { +#if defined(SOFTWARE_APIC) + case REG_LAPIC_ID: + case REG_LAPIC_REV: + case REG_LAPIC_APR: + case REG_LAPIC_DFR: + case REG_LAPIC_LDR: + case REG_LAPIC_SVR: + case REG_LAPIC_IRR_0: + case REG_LAPIC_IRR_1: + case REG_LAPIC_IRR_2: + case REG_LAPIC_IRR_3: + case REG_LAPIC_IRR_4: + case REG_LAPIC_IRR_5: + case REG_LAPIC_IRR_6: + case REG_LAPIC_IRR_7: + case REG_LAPIC_ISR_0: + case REG_LAPIC_ISR_1: + case REG_LAPIC_ISR_2: + case REG_LAPIC_ISR_3: + case REG_LAPIC_ISR_4: + case REG_LAPIC_ISR_5: + case REG_LAPIC_ISR_6: + case REG_LAPIC_ISR_7: + case REG_LAPIC_TMR_0: + case REG_LAPIC_TMR_1: + case REG_LAPIC_TMR_2: + case REG_LAPIC_TMR_3: + case REG_LAPIC_TMR_4: + case REG_LAPIC_TMR_5: + case REG_LAPIC_TMR_6: + case REG_LAPIC_TMR_7: + case REG_LAPIC_TIMER: + case REG_LAPIC_LVT_ERR: + case REG_LAPIC_THERMAL: + case REG_LAPIC_INIT_CNT: + case REG_LAPIC_ESR: + case REG_LAPIC_PERF_MON_CNTER: + case REG_LAPIC_ICR_LOW: + case REG_LAPIC_ICR_HIGH: + case REG_LAPIC_LVT_LINT0: + case REG_LAPIC_LVT_LINT1: + case REG_LAPIC_DCR: + case REG_LAPIC_TPR: + *result = lapic_read_reg(offset); + break; + case REG_LAPIC_PPR: + *result = get_ppr(); + break; +#endif case REG_LAPIC_CURR_CNT: { *result = lapic_read_curr_count_reg(); break; } case REG_LAPIC_CMCI: { - *result = 0; + *result = lapic_read_reg(offset); break; } default: @@ -313,6 +594,9 @@ bool lapic_write_fault_handle(uint64_t offset, uint32_t data) case REG_LAPIC_THERMAL: case REG_LAPIC_PERF_MON_CNTER: case REG_LAPIC_CMCI: +#if defined(SOFTWARE_APIC) + case REG_LAPIC_ICR_HIGH: +#endif lapic_write_reg(offset, data); break; @@ -324,7 +608,16 @@ bool lapic_write_fault_handle(uint64_t offset, uint32_t data) lapic_write_icr_low(data); break; } - +#if defined(SOFTWARE_APIC) + case REG_LAPIC_TPR: { + lapic_write_tpr(data); + break; + } + case REG_LAPIC_EOI: { + lapic_write_eoi(); + break; + } +#endif default: LOG_VMM_ERR("Writing unknown LAPIC register offset 0x%x\n", offset); return false; @@ -451,15 +744,16 @@ bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) return false; } - int irr_n = vector / 32; - int irr_idx = vector % 32; - - int irr_reg_off = REG_LAPIC_IRR_0 + (irr_n * 0x10); - assert(irr_reg_off <= REG_LAPIC_IRR_7); - - /* Mark as pending for injection, let hardware handle the rest */ - lapic_write_reg(irr_reg_off, lapic_read_reg(irr_reg_off) | BIT(irr_idx)); + /* If this IRQ vector is already pending then it will get coalesced. */ + mark_irq_pending(vector); +#if defined(SOFTWARE_APIC) + if (vcpu_can_take_irq(0)) { + lapic_maintenance(); + } else { + vcpu_exit_update_ppvc(VMCS_PPVC_WAIT_IRQ_WINDOW); + } +#else /* See "26.4.2 Guest Non-Register State" for "Guest interrupt status" layout */ int highest_vector_pending = get_next_pending_irq_vector(); assert(highest_vector_pending != -1); @@ -467,6 +761,7 @@ bool inject_lapic_irq(size_t vcpu_id, uint8_t vector) guest_irq_status &= 0xff00; guest_irq_status |= (uint8_t)highest_vector_pending; microkit_vcpu_x86_write_vmcs(0, VMX_GUEST_INTERRUPT_STATUS, guest_irq_status); +#endif return true; } @@ -499,6 +794,7 @@ bool inject_ioapic_irq(int ioapic, int pin) uint8_t vector = ioapic_pin_to_vector(ioapic, pin); +#if !defined(SOFTWARE_APIC) /* For any passed through interrupts: * When the guest EOIs the interrupt, we must trigger a vmexit to run the ack func */ @@ -531,6 +827,7 @@ bool inject_ioapic_irq(int ioapic, int pin) return false; } } +#endif // @billn need to read cpu id from redirection register, revisit for multi vcpu return inject_lapic_irq(0, vector); @@ -545,6 +842,7 @@ bool ioapic_ack_passthrough_irq(uint8_t vector) if (ioapic_regs.virq_passthrough_map[i].ack_fn) { ioapic_regs.virq_passthrough_map[i].ack_fn(0, i, ioapic_regs.virq_passthrough_map[i].ack_data); +#if !defined(SOFTWARE_APIC) /* Now clear the vector's bit in EOI exit bitmap */ int eoi_bitmap_n = vector / 64; int n_bitmap_i = vector % 64; @@ -581,6 +879,7 @@ bool ioapic_ack_passthrough_irq(uint8_t vector) LOG_VMM_ERR("impossible: eoi_bitmap_n %d > 3\n", eoi_bitmap_n); return false; } +#endif return true; } diff --git a/src/arch/x86_64/fault.c b/src/arch/x86_64/fault.c index c885eb066..fbd43d7a1 100644 --- a/src/arch/x86_64/fault.c +++ b/src/arch/x86_64/fault.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -170,6 +171,7 @@ bool fault_is_trap_like(int exit_reason) case APIC_WRITE: case VIRTUALIZED_EOI: case VMX_PREEMPTION_TIMER: + case INTERRUPT_WINDOW: return true; default: return false; @@ -243,6 +245,11 @@ static bool handle_ept_fault(seL4_VCPUContext *vctx, seL4_Word qualification, de } else if (addr >= HPET_GPA && addr < HPET_GPA + HPET_SIZE) { LOG_FAULT("handling HPET 0x%lx\n", addr); return hpet_fault_handle(vctx, addr - HPET_GPA, qualification, decoded_ins); +#if defined(SOFTWARE_APIC) + } else if (addr >= LAPIC_GPA && addr < LAPIC_GPA + LAPIC_SIZE) { + LOG_FAULT("handling LAPIC 0x%lx\n", addr); + return lapic_fault_handle(vctx, addr - LAPIC_GPA, qualification, decoded_ins); +#endif } else { LOG_FAULT("handling other EPT 0x%lx\n", addr); for (int i = 0; i < MAX_EPT_EXCEPTION_HANDLERS; i++) { @@ -345,54 +352,44 @@ bool fault_handle(size_t vcpu_id) bool success = false; decoded_instruction_ret_t decoded_ins; - seL4_Word f_reason = microkit_mr_get(SEL4_VMENTER_FAULT_REASON_MR); - seL4_Word ins_len = microkit_mr_get(SEL4_VMENTER_FAULT_INSTRUCTION_LEN_MR); - seL4_Word qualification = microkit_mr_get(SEL4_VMENTER_FAULT_QUALIFICATION_MR); - seL4_Word rip = microkit_mr_get(SEL4_VMENTER_CALL_EIP_MR); + vcpu_init_exit_state(false); - LOG_FAULT("handling vmexit reason %s\n", fault_to_string(f_reason)); + seL4_Word f_reason = vcpu_exit_get_reason(); + seL4_Word qualification = vcpu_exit_get_qualification(); + seL4_Word rip = vcpu_exit_get_rip(); + seL4_VCPUContext *vctx = vcpu_exit_get_context(); - seL4_VCPUContext vctx; - vctx.eax = microkit_mr_get(SEL4_VMENTER_FAULT_EAX); - vctx.ebx = microkit_mr_get(SEL4_VMENTER_FAULT_EBX); - vctx.ecx = microkit_mr_get(SEL4_VMENTER_FAULT_ECX); - vctx.edx = microkit_mr_get(SEL4_VMENTER_FAULT_EDX); - vctx.esi = microkit_mr_get(SEL4_VMENTER_FAULT_ESI); - vctx.edi = microkit_mr_get(SEL4_VMENTER_FAULT_EDI); - vctx.ebp = microkit_mr_get(SEL4_VMENTER_FAULT_EBP); - vctx.r8 = microkit_mr_get(SEL4_VMENTER_FAULT_R8); - vctx.r9 = microkit_mr_get(SEL4_VMENTER_FAULT_R9); - vctx.r10 = microkit_mr_get(SEL4_VMENTER_FAULT_R10); - vctx.r11 = microkit_mr_get(SEL4_VMENTER_FAULT_R11); - vctx.r12 = microkit_mr_get(SEL4_VMENTER_FAULT_R12); - vctx.r13 = microkit_mr_get(SEL4_VMENTER_FAULT_R13); - vctx.r14 = microkit_mr_get(SEL4_VMENTER_FAULT_R14); - vctx.r15 = microkit_mr_get(SEL4_VMENTER_FAULT_R15); + LOG_FAULT("handling vmexit reason %s\n", fault_to_string(f_reason)); switch (f_reason) { case CPUID: - success = emulate_cpuid(&vctx); + success = emulate_cpuid(vctx); break; case RDMSR: - success = emulate_rdmsr(&vctx); + success = emulate_rdmsr(vctx); break; case WRMSR: - success = emulate_wrmsr(&vctx); + success = emulate_wrmsr(vctx); break; case EPT_VIOLATION: decoded_ins = decode_instruction(vcpu_id, rip); if (decoded_ins.type == INSTRUCTION_DECODE_FAIL) { success = false; } else { - /* See "30.2.5 Information for VM Exits Due to Instruction Execution" - * Note that for EPT faults the instruction length won't be valid. */ - ins_len = decoded_ins.len; - success = handle_ept_fault(&vctx, qualification, decoded_ins); + success = handle_ept_fault(vctx, qualification, decoded_ins); } break; case IO: - success = handle_pio_fault(&vctx, qualification); + success = handle_pio_fault(vctx, qualification); + break; + case XSETBV: + success = emulate_xsetbv(vctx); break; + case VMX_PREEMPTION_TIMER: + guest_time_handle_timer_ntfn(); + success = true; + break; +#if !defined(SOFTWARE_APIC) case VIRTUALIZED_EOI: { uint8_t eoi_vector = qualification; /* If we get here then the guest has ack'ed a passed through I/O APIC irq, @@ -439,25 +436,30 @@ bool fault_handle(size_t vcpu_id) } break; } - case XSETBV: - success = emulate_xsetbv(&vctx); - break; - case VMX_PREEMPTION_TIMER: - guest_time_handle_timer_ntfn(); +#else + case INTERRUPT_WINDOW: + lapic_maintenance(); success = true; break; +#endif default: LOG_VMM_ERR("unhandled fault: 0x%x\n", f_reason); }; - if (success && f_reason != INTERRUPT_WINDOW) { - microkit_vcpu_x86_write_regs(vcpu_id, &vctx); - - uint64_t resume_rip = rip; + if (success) { + unsigned rip_additive = 0; if (!fault_is_trap_like(f_reason)) { - resume_rip += ins_len; + if (f_reason == EPT_VIOLATION) { + /* Note that for EPT faults the instruction length won't be valid. + * See "30.2.5 Information for VM Exits Due to Instruction Execution" + */ + rip_additive = decoded_ins.len; + } else { + rip_additive = vcpu_exit_get_instruction_len(); + } } - microkit_vcpu_x86_deferred_resume(resume_rip, VMCS_PCC_DEFAULT, 0); + vcpu_exit_advance_rip(rip_additive); + vcpu_exit_resume(); } else if (!success && (f_reason == RDMSR || f_reason == WRMSR || f_reason == XSETBV)) { /* [2] "RDMSR—Read From Model Specific Register": * "Specifying a reserved or unimplemented MSR address in ECX will also cause a general protection exception." */ @@ -469,7 +471,9 @@ bool fault_handle(size_t vcpu_id) interruption |= BIT(11); // deliver error code interruption |= BIT(31); // valid - microkit_vcpu_x86_deferred_resume(rip, VMCS_PCC_DEFAULT, interruption); + vcpu_exit_inject_irq(interruption); + /* Don't advance rip */ + vcpu_exit_resume(); } else if (!success) { LOG_VMM_ERR("failed handling fault: '%s' (0x%x)\n", fault_to_string(f_reason), f_reason); vcpu_print_regs(vcpu_id); diff --git a/src/arch/x86_64/guest.c b/src/arch/x86_64/guest.c index a167b4338..2725e0204 100644 --- a/src/arch/x86_64/guest.c +++ b/src/arch/x86_64/guest.c @@ -72,6 +72,9 @@ bool guest_start_long_mode(uint64_t kernel_rip, uint64_t cr3, uint64_t gdt_gpa, microkit_vcpu_x86_write_regs(GUEST_BOOT_VCPU_ID, initial_regs); LOG_VMM("starting guest at 0x%lx\n", kernel_rip); - microkit_vcpu_x86_deferred_resume(kernel_rip, VMCS_PCC_DEFAULT, 0); + microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, kernel_rip); + microkit_mr_set(SEL4_VMENTER_CALL_CONTROL_PPC_MR, VMCS_PPVC_DEFAULT); + microkit_mr_set(SEL4_VMENTER_CALL_INTERRUPT_INFO_MR, 0); + microkit_vcpu_x86_deferred_resume(); return true; } diff --git a/src/arch/x86_64/vcpu.c b/src/arch/x86_64/vcpu.c index 3bb7d7680..049998a6b 100644 --- a/src/arch/x86_64/vcpu.c +++ b/src/arch/x86_64/vcpu.c @@ -10,12 +10,35 @@ #include #include #include +#include #include #include #include #include #include +struct vcpu_fault_state { + bool valid; + bool exit_from_ntfn; + + uint64_t original_rip; + uint64_t resume_rip; + uint64_t ppvc; + uint64_t irq; + + uint64_t reason; + uint64_t qualification; + uint64_t instruction_length; + uint64_t gpa; + uint64_t rflags; + uint64_t interruptability; + uint64_t cr3; + + seL4_VCPUContext vctx; +}; + +static struct vcpu_fault_state vcpu_fault_state; + /* Document referenced: * [1] Title: Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 * Order Number: 325462-080US June 2023 @@ -53,16 +76,16 @@ bool vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit) } /* Set up VMCS control registers */ - microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS, VMCS_PCC_DEFAULT); + microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS, VMCS_PPVC_DEFAULT); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS, VMCS_SPC_DEFAULT); microkit_vcpu_x86_write_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_ENTRY_CONTROLS, VMCS_VEC_LM_DEFAULT); /* Check that all the VT-x features we need are supported by the host. */ uint64_t read_back_ppc = microkit_vcpu_x86_read_vmcs(GUEST_BOOT_VCPU_ID, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS); - if (!check_baseline_bits(VMCS_PCC_DEFAULT, read_back_ppc)) { + if (!check_baseline_bits(VMCS_PPVC_DEFAULT, read_back_ppc)) { LOG_VMM_ERR("required Primary Processor-Based VM-Execution Controls features not supported.\n"); - LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", VMCS_PCC_DEFAULT, read_back_ppc); - print_missing_baseline_bits(VMCS_PCC_DEFAULT, read_back_ppc); + LOG_VMM_ERR("Baseline: 0x%lx, bits sticked: 0x%lx\n", VMCS_PPVC_DEFAULT, read_back_ppc); + print_missing_baseline_bits(VMCS_PPVC_DEFAULT, read_back_ppc); return false; } @@ -118,6 +141,152 @@ bool vcpu_set_up_long_mode(uint64_t cr3, uint64_t gdt_gpa, uint64_t gdt_limit) return true; } +void vcpu_init_exit_state(bool exit_from_ntfn) +{ + /* Prevent state overwriting, if this goes off then you probably called this or didn't call + * `vcpu_exit_resume()` at the correct time. */ + assert(!vcpu_fault_state.valid); + + vcpu_fault_state.original_rip = microkit_mr_get(SEL4_VMENTER_CALL_EIP_MR); + vcpu_fault_state.resume_rip = vcpu_fault_state.original_rip; + vcpu_fault_state.ppvc = microkit_mr_get(SEL4_VMENTER_CALL_CONTROL_PPC_MR); + vcpu_fault_state.irq = microkit_mr_get(SEL4_VMENTER_CALL_INTERRUPT_INFO_MR); + + if (!exit_from_ntfn) { + /* These message registers are only valid if a VM Exit was caused by a fault rather + * than a notification. */ + vcpu_fault_state.reason = microkit_mr_get(SEL4_VMENTER_FAULT_REASON_MR); + vcpu_fault_state.qualification = microkit_mr_get(SEL4_VMENTER_FAULT_QUALIFICATION_MR); + vcpu_fault_state.instruction_length = microkit_mr_get(SEL4_VMENTER_FAULT_INSTRUCTION_LEN_MR); + vcpu_fault_state.gpa = microkit_mr_get(SEL4_VMENTER_FAULT_GUEST_PHYSICAL_MR); + vcpu_fault_state.rflags = microkit_mr_get(SEL4_VMENTER_FAULT_RFLAGS_MR); + vcpu_fault_state.interruptability = microkit_mr_get(SEL4_VMENTER_FAULT_GUEST_INT_MR); + vcpu_fault_state.cr3 = microkit_mr_get(SEL4_VMENTER_FAULT_CR3_MR); + + vcpu_fault_state.vctx.eax = microkit_mr_get(SEL4_VMENTER_FAULT_EAX); + vcpu_fault_state.vctx.ebx = microkit_mr_get(SEL4_VMENTER_FAULT_EBX); + vcpu_fault_state.vctx.ecx = microkit_mr_get(SEL4_VMENTER_FAULT_ECX); + vcpu_fault_state.vctx.edx = microkit_mr_get(SEL4_VMENTER_FAULT_EDX); + vcpu_fault_state.vctx.esi = microkit_mr_get(SEL4_VMENTER_FAULT_ESI); + vcpu_fault_state.vctx.edi = microkit_mr_get(SEL4_VMENTER_FAULT_EDI); + vcpu_fault_state.vctx.ebp = microkit_mr_get(SEL4_VMENTER_FAULT_EBP); + vcpu_fault_state.vctx.r8 = microkit_mr_get(SEL4_VMENTER_FAULT_R8); + vcpu_fault_state.vctx.r9 = microkit_mr_get(SEL4_VMENTER_FAULT_R9); + vcpu_fault_state.vctx.r10 = microkit_mr_get(SEL4_VMENTER_FAULT_R10); + vcpu_fault_state.vctx.r11 = microkit_mr_get(SEL4_VMENTER_FAULT_R11); + vcpu_fault_state.vctx.r12 = microkit_mr_get(SEL4_VMENTER_FAULT_R12); + vcpu_fault_state.vctx.r13 = microkit_mr_get(SEL4_VMENTER_FAULT_R13); + vcpu_fault_state.vctx.r14 = microkit_mr_get(SEL4_VMENTER_FAULT_R14); + vcpu_fault_state.vctx.r15 = microkit_mr_get(SEL4_VMENTER_FAULT_R15); + } + + vcpu_fault_state.exit_from_ntfn = exit_from_ntfn; + vcpu_fault_state.valid = true; +} + +uint64_t vcpu_exit_get_rip(void) +{ + assert(vcpu_fault_state.valid); + return vcpu_fault_state.resume_rip; +} + +void vcpu_exit_update_ppvc(uint64_t ppvc) +{ + assert(vcpu_fault_state.valid); + vcpu_fault_state.ppvc = ppvc; +} + +uint64_t vcpu_exit_get_irq(void) +{ + assert(vcpu_fault_state.valid); + return vcpu_fault_state.irq; +} + +void vcpu_exit_inject_irq(uint64_t irq) +{ + assert(vcpu_fault_state.valid); + vcpu_fault_state.irq = irq; +} + +uint64_t vcpu_exit_get_reason(void) +{ + assert(vcpu_fault_state.valid); + + /* Shouldn't be called when the VCPU exit is caused by a notification! */ + assert(!vcpu_fault_state.exit_from_ntfn); + + return vcpu_fault_state.reason; +} + +uint64_t vcpu_exit_get_qualification(void) +{ + assert(vcpu_fault_state.valid); + assert(!vcpu_fault_state.exit_from_ntfn); + return vcpu_fault_state.qualification; +} + +uint64_t vcpu_exit_get_instruction_len(void) +{ + assert(vcpu_fault_state.valid); + assert(!vcpu_fault_state.exit_from_ntfn); + return vcpu_fault_state.instruction_length; +} + +uint64_t vcpu_exit_get_rflags(void) +{ + assert(vcpu_fault_state.valid); + + if (vcpu_fault_state.exit_from_ntfn) { + return microkit_vcpu_x86_read_vmcs(0, VMX_GUEST_RFLAGS); + } else { + return vcpu_fault_state.rflags; + } +} + +uint64_t vcpu_exit_get_interruptability(void) +{ + assert(vcpu_fault_state.valid); + return vcpu_fault_state.interruptability; +} + +uint64_t vcpu_exit_get_cr3(void) +{ + assert(vcpu_fault_state.valid); + return vcpu_fault_state.cr3; +} + +seL4_VCPUContext *vcpu_exit_get_context(void) +{ + assert(vcpu_fault_state.valid); + + if (vcpu_fault_state.exit_from_ntfn) { + return NULL; + } else { + return &vcpu_fault_state.vctx; + } +} + +void vcpu_exit_advance_rip(unsigned rip_additive) +{ + assert(vcpu_fault_state.valid); + vcpu_fault_state.resume_rip += rip_additive; +} + +void vcpu_exit_resume(void) +{ + assert(vcpu_fault_state.valid); + + if (!vcpu_fault_state.exit_from_ntfn) { + microkit_vcpu_x86_write_regs(0, &vcpu_fault_state.vctx); + } + + microkit_mr_set(SEL4_VMENTER_CALL_EIP_MR, vcpu_fault_state.resume_rip); + microkit_mr_set(SEL4_VMENTER_CALL_CONTROL_PPC_MR, vcpu_fault_state.ppvc); + microkit_mr_set(SEL4_VMENTER_CALL_INTERRUPT_INFO_MR, vcpu_fault_state.irq); + microkit_vcpu_x86_deferred_resume(); + vcpu_fault_state.valid = false; +} + void vcpu_print_regs(size_t vcpu_id) { seL4_Word cppc = microkit_mr_get(SEL4_VMENTER_CALL_CONTROL_PPC_MR);