Michalis Pappas [Fri, 23 Jun 2023 09:26:34 +0000 (11:26 +0200)]
plat/kvm/arm: Obtain dtb address from x0 when using lxboot
According to the arm64 linux boot protocol [1] the address of the
fdt blob is passed on x0. This is unlike the QEMU virt boot protocol
when an ELF is loaded that uses a fixed address at 0x40000000. Update
the entry code to handle this case.
Sergiu Moga [Tue, 23 May 2023 16:44:01 +0000 (19:44 +0300)]
plat/drivers/gic: Remove `fdt` argument from initialization methods
Now that we have separated the ways we probe the `GIC` (`Devicetree`
vs `ACPI`) and the `Devicetree` parts can fetch the `Devicetree` on
their own, remove the no longer necessary `fdt` function parameters
from the related functions.
Sergiu Moga [Tue, 23 May 2023 16:26:55 +0000 (19:26 +0300)]
plat/drivers/gic: Enable `GICv3` probing through `ACPI`
If `ACPI` is enabled, rely on it for probing the `GICv3`. Thus, we
need to take two steps for this:
- fetch the GIC Redistributor's base address and address range length
from the `GICR` `MADT` entry. Normally we should check first if there
exists a Redistributor. If there is none then we must get its address
from the `GICC` structure, since that means that the Redistributors
are not in an always-on power domain. Otherwise there could be a `GICR`
for each Redistributor region and the `DT` probe version does not
support multiple regions anyway. So, until there is need for
that (not the case for QEMU Virt), align `ACPI` probe with `DT` probe
and assume we only have one Redistributor region.
- fetch the `GIC Distributor`'s physical base address from `MADT`'s
`GICD` structure and check that the size is compliant with that of
`GICv3`.
Furthermore, separate the two ways of probing `GICv3` in two:
one for `ACPI` and one for `Devicetree`.
As a reminder, add a `TODO` in the `DT` probe for when someone decides
to actually improve this driver.
Sergiu Moga [Tue, 23 May 2023 13:00:27 +0000 (16:00 +0300)]
plat/drivers/gic: Enable `GICv2` probing through `ACPI`
If `ACPI` is enabled, rely on it for probing the `GICv2`. Thus, we
need to take two steps for this:
- fetch the GIC CPU interface's base address and default length from
the `GICC` `MADT` entry. Since there is only one `Redistributor`, all
`GICC`'s must have the same physical base address.
- fetch the `GIC Distributor`'s physical base
address from `MADT`'s `GICD` structure and check that the size is
compliant with that of `GICv2`.
`GICR Base Address` must be set to 0, otherwise this is `GICv3/4`.
Furthermore, separate the two ways of probing `GICv2` in two:
one for `ACPI` and one for `Devicetree`.
Sergiu Moga [Tue, 23 May 2023 12:52:42 +0000 (15:52 +0300)]
plat/drivers/gic: Add a method for fetching the `GICD` from `MADT`
Since this applies for both `GICv2` and `GICv3`, implement a generic
method of fetching the unique `GICD` structure from the `MADT`.
Unlike `Devicetree`'s `reg` property, `ACPI` does not inform us of
the length of the `GIC Distributor`'s address space and therefore
one must assume the page-aligned default size from the specification:
- for GICv2: ARM Generic Interrupt Controller Architecture version
2.0 Issue B.b
- for GICv3: ARM Generic Interrupt Controller Architecture version
3 and version 4 Issue H
Sergiu Moga [Sun, 21 May 2023 13:17:50 +0000 (16:17 +0300)]
plat: Enable secondary cores allocation through `ACPI` on `ARM64`
Split secondary cores enumeration in two methods:
- if CONFIG_UKPLAT_ACPI is enabled then get the information
through the `MADT`'s `GICC` structures
- else rely on the `Devicetree`'s `cpu@` nodes
Simon Kuenzer [Fri, 11 Aug 2023 13:10:37 +0000 (15:10 +0200)]
plat/kvm: Add configuration hint for EFI
Adds an hint in `menuconfig` that appears if the configuration dependencies
are not met for building a QEMU image compatible to boot from an EFI
firmware.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Sergiu Moga <sergiu@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1038
Sergiu Moga [Fri, 11 Aug 2023 12:45:13 +0000 (15:45 +0300)]
plat/common/x86: Fix `libukreloc` error for non-`PIE` `SMP` builds
After the merge of
commit cf8cc65cb0ae ("plat/kvm/x86: Make SMP init code resolve its own `start16` relocations")
SMP builds that were not built with `libukreloc` would fail due to
external references to `x86_start16_*` symbols no longer being declared.
Thus, fix this by making their declaration present regardless of
`CONFIG_LIBUKRELOC` being enabled or not. Furthermore, guard the no
longer necessary `START16_UKRELOC_*` macro's, as they are not needed
if the previously mentioned configuration is not enabled.
Signed-off-by: Sergiu Moga <sergiu@unikraft.io> Reviewed-by: Marco Schlumpp <marco@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1037
Andrei Tatar [Tue, 18 Jul 2023 18:08:54 +0000 (20:08 +0200)]
build: Add library registration for tree build
This change adds `addlib_tree` and `addlib_tree_s` as library
registration functions that enable build products to be placed in a
directory tree mirroring the source files. This is useful for code that
shares source filenames across multiple directories.
Signed-off-by: Andrei Tatar <andrei@unikraft.io> Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com> Reviewed-by: Marco Schlumpp <marco@unikraft.io> Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com> Reviewed-by: Simon Kuenzer <simon@unikraft.io> Approved-by: Simon Kuenzer <simon@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1001
Andrei Tatar [Wed, 28 Jun 2023 14:14:25 +0000 (16:14 +0200)]
build: Add option to place build objects in a tree
This adds the feature to place build products in a directory tree
mirroring the tree their source files are in.
This feature piggy-backs on top of the $(LIBNAME)__BUILDTREE flag from 87065c2f (build: Add option for dedicated build directory).
In addition, the $(LIBNAME)_SRC make variable must point to the common
prefix of a library's source file paths. Any intermediate directories
are created automatically.
Signed-off-by: Andrei Tatar <andrei@unikraft.io> Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com> Reviewed-by: Marco Schlumpp <marco@unikraft.io> Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com> Reviewed-by: Simon Kuenzer <simon@unikraft.io> Approved-by: Simon Kuenzer <simon@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1001
Andrei Tatar [Wed, 28 Jun 2023 13:47:28 +0000 (15:47 +0200)]
build: Add option for dedicated build directory
This change adds the option to place build files in a dedicated
`.../build/` directory under the library build path.
This feature is opt-in per-library and enabled if the $(LIBNAME)__BUILDTREE
make variable is set.
Signed-off-by: Andrei Tatar <andrei@unikraft.io> Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com> Reviewed-by: Marco Schlumpp <marco@unikraft.io> Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com> Reviewed-by: Simon Kuenzer <simon@unikraft.io> Approved-by: Simon Kuenzer <simon@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1001
Write the code in such a manner that the same set of functions can
accommodate any version of ACPI. Thus, remove `acpi10_*` functions
and define an ACPI table generic fetching function `acpi_get_table`.
Sergiu Moga [Sun, 21 May 2023 08:36:15 +0000 (11:36 +0300)]
support/scripts/mkukimg: Add support for `EFI` Disk images
Begin by taking the setting up of the `EFI System Partition` layout
from `mkukefiiso` into a separate function `mkukefiesp`, since it
applies to any image involving an `EFI System Partition` with the
`Unikraft` `EFI` stub.
Next, create the usual disk image formatted with a `GPT` and a single
partition, that of the `EFI System Partition`, which has the same layout
as the `ISO` image.
Furthermore, clarify in the usage message that we now support disk
images for `ukefi` only and add the corresponding `OPTFORMAT` case.
To avoid ambiguity in the `OPTFORMAT` cases' messages, specify the
type of of bootloader that is not supported for the respective image
format.
Signed-off-by: Sergiu Moga <sergiu.moga@protonmail.com> Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #910
Sergiu Moga [Sat, 20 May 2023 18:40:09 +0000 (21:40 +0300)]
support/scripts: Allow building `UEFI` `ISO`'s
Give the script the ability to build `UEFI` bootable `ISO`'s.
The `FAT32` image contained within the `ISO` will have the
following layout:
```
└── EFI
└── BOOT
├── BOOT${OPTARCH}.EFI
├── ${OPTINITRD}
└── ${OPTCMDLINE}
```
Add two new options:
- b: to differentiate between possible bootloaders
- a: to differentiate between possible architectures
Furthermore, rename the script to highlight the fact that this is no
longer `GRUB` only.
Signed-off-by: Sergiu Moga <sergiu.moga@protonmail.com> Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #910
plat/common/efi: Add support for `TCG`'s `Reset Attack Mitigation`
Add `Trusted Computing Group`'s `Reset Attack Mitigation` mechanism.
Whenever a machine shuts down or reboots, due to lack of electric
charge, the contents of RAM may dissipate after a short amount of
time. However this may be enough for an attacker to quickly boot
again into a custom program and dump memory contents. Thus, by using
this, the OS instructs POST BIOS to overwrite memory contents before
continuing to boot into the rest of the BIOS code.
Since this is not really implemented in `OVMF`'s `NVRAM` variables
we disable this by default.
plat/kvm/shutdown.c: If on a `UEFI` system, rely on Runtime Services
Preferably, a UEFI system is also an ACPI system and thus these
functionalities should be implemented through ACPI methods. But for
now, make use of UEFI's Runtime Services for resetting the system,
since they are more reliable than what we have at the moment.
Sergiu Moga [Mon, 27 Mar 2023 10:00:30 +0000 (13:00 +0300)]
plat/kvm/arm: Enable the Unikernel to be built as an UEFI application
If `CONFIG_EFI_STUB` is enabled, add to the build system the ARM UEFI
entry stub and the ARM specific post-EFI stub that applies finishing
touches to the platform initialization.
Add a configuration entry `KVM_BOOT_QEMU_VIRT` to explicitly
indicate that we are booting from the default `QEMU virt`
environment. This will help us differentiate between UEFI and
non-UEFI ARM builds.
Sergiu Moga [Mon, 27 Mar 2023 09:51:22 +0000 (12:51 +0300)]
plat/kvm/arm: Add architecture specific post-EFI stub
Implement a stub that comes after the architecture generic EFI stub
calls the routine that exits `Boot Services`.
This is supposed to finish the architecture specific setupin order
to be able to have a Unikraft valid initial environment state before
`_libkvmplat_start` is execited.
Thus, the interrupt flags are masked, the data cache is invalidated
in the range of this image's instance and then default, warm reset
values are placed into the system registers that EFI would have
otherwise left modified.
Sergiu Moga [Mon, 27 Mar 2023 10:00:30 +0000 (13:00 +0300)]
plat/kvm/x86: Enable the Unikernel to be built as an UEFI application
If `CONFIG_EFI_STUB` is enabled, add to the build system the fake PE
header, the architecture generic EFI stub, and the x86 specific
post-EFI stub that applies finishing touches to the platform
initialization.
Sergiu Moga [Mon, 27 Mar 2023 09:51:22 +0000 (12:51 +0300)]
plat/kvm/x86: Add architecture specific post-EFI stub
Implement a stub that comes after the architecture generic EFI stub
calls the routine that exits `Boot Services`.
This is supposed to finish the architecture specific setupin order
to be able to have a Unikraft valid initial environment state before
`_ukplat_entry` is execited.
Thus, begin by disabling the `Interrupt Flag`, updating the root of
the page tables with our in-image static page tables, unmask the
legacy `8259 PIC`, since, at this point, we do not have `I/O APIC`
support, disable the `LAPIC Timer` initially setup by `UEFI`, set the
legacy shared PCI IRQ's as level triggered since UEFI does not do it
for us (unless we boot in `CSM`) and we do not, at this moment have a
proper IRQ subsystem and, finally, jump to `lcpu_start64` with the
entry function as `_ukplat_entry` and a statically allocated
page-sized stack.
Implements the small x86 specific UEFI entry point which will call
the early self relocator, adjust the initially unaligned stack and
finally jump to the architecture generic EFI stub.
Sergiu Moga [Mon, 27 Mar 2023 09:26:10 +0000 (12:26 +0300)]
support/scripts: Add `python3` script to patch fake PE header
This script allows patching of the architecture specific fake PE
headers. It only fills in the fields that UEFI firmware looks for
when validating and loading the image. Specifically, it does the
following:
- Write MS-DOS signature in the first bytes of the binary
- Write at the standard MS-DOS file offset `0x3c` the offset to the
beginning in file of the fake PE header
- Append the original ELF file that also contains the PE header
- Fill in the following fields of the Optional Header: SizeOfCode,
AddressOfEntryPoint, BaseOfCode, SizeOfImage
- Fill in the dummy PE sections, as PE, unlike ELF, is loaded by
sections:
- dummy .reloc section pointing to itsel with all fields
zeroed out except the VirtualAddress and PointerToRawData
fields which point to the section itself, to fool UEFI into
thinking this is a valid relocation.
- All PT_LOAD ELF Program Headers will be encapsulated into
PE sections with all permissions enabled (RWX)
For these sections, only the following fields are required to be filed
in: VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData.
Thus, the script fills in the bare-minimum fields, according to EDKII,
the most complete and official UEFI implementation, that are required
by an UEFI application's PE header to be considered valid and loadable.
Sergiu Moga [Tue, 28 Mar 2023 14:20:01 +0000 (17:20 +0300)]
plat/kvm/efi.c: Add support for Devicetree Blob file
This enables the EFI stub to load a Devicetree Blob file from the
same filesystem that the Unikraft image was loaded from (the EFI
System Partition) and register it as a `Memory Region Descriptor`.
The name of the `dtb` file is given through the
`CONFIG_UK_EFI_STUB_DTB_FNAME` configuration entry and it tells
the loader the name of the file to load from the `\EFI\BOOT` directory
of the EFI System Partition.
Sergiu Moga [Tue, 28 Mar 2023 14:20:01 +0000 (17:20 +0300)]
plat/kvm/efi.c: Add support for initial RAM disk file
This enables the EFI stub to load an initial RAM disk file from the
same filesystem that the Unikraft image was loaded from (the EFI
System Partition) and register it as a `Memory Region Descriptor`.
The name of the `initrd` file is given through the
`CONFIG_UK_EFI_STUB_INITRD_FNAME` configuration entry and it tells
the loader the name of the file to load from the `\EFI\BOOT` directory
of the EFI System Partition.
Sergiu Moga [Mon, 27 Mar 2023 10:08:34 +0000 (13:08 +0300)]
plat/kvm/efi.c: Add command-line arguments support
Implement support to pass command-line arguments through Unikraft's
`struct ukplat_bootinfo`.
This can be done in two ways:
1. Through the UEFI Shell when launching the image or through `qemu`'s
`-append` option.
2. Through the filesystem of the same partition (the EFI System
Partition) that the image was launched from. The loader will look
for a file with the name configured through the
`UK_EFI_STUB_CMDLINE_FNAME` in the `\EFI\BOOT' directory.
The first way, if applicable, takes priority over the second.
Sergiu Moga [Tue, 21 Mar 2023 13:31:02 +0000 (15:31 +0200)]
plat/kvm: Implement architecture generic EFI stub
Add an architecture generic EFI stub that sets up a
`struct ukplat_bootinfo`'s memory region descriptors, `bootloader`
and `bootprotocol` fields. Furthermore, the memory region descriptors
corresponding to the UEFI `Runtime Services` are gathered separately,
through UEFI's `Memory Attribute Table`, since they have to be
treated differently, in order for the `Runtime Services` to be
used properly after `exit_boot_services`.
At the end, the stub calls `uk_efi_jmp_to_kern` which each architecture
is supposed to independently implement the remaining setup for its
platform.
Sergiu Moga [Mon, 27 Mar 2023 09:44:46 +0000 (12:44 +0300)]
plat/kvm: Add `EFI_STUB` configuration entry
Add a configuration option to build the Unikernel as a valid,
loadable UEFI application. Make it depend on `ACPI` and, obviously,
on not having `PLAT_LINUXU` enabled.
Furthermore, remove default selection of the Multiboot boot protocol
if QEMU VMM is selected, now that a QEMU image can also be an EFI
image.
Add a description and proper dependencies for the
`KVM_BOOT_PROTO_LXBOOT` configuration entry. Since `Firecracker`
only supports the `Linux` 64-bit boot protocol and we do not yet
support booting through it on `QEMU`, make the dependencies
reflect that.
Add a description and proper dependencies for the
`KVM_BOOT_PROTO_MULTIBOOT` configuration entry. Since `Firecracker`
only supports the `Linux` 64-bit boot protocol and `Multiboot` is
x86 specific (not taking into consideration the `Multiboot` ported
to `ARM` for `Xen`), make the configuration entry reflect that.
Simon Kuenzer [Thu, 27 Jul 2023 20:27:42 +0000 (22:27 +0200)]
support/qemu-guest: Darwin support
This commit introduces native support for QEMU installations on
Darwin (MacOS). Apple's hypervisor framework is used for guest
acceleration instead of KVM on Linux hosts.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Simon Kuenzer [Thu, 27 Jul 2023 10:56:27 +0000 (12:56 +0200)]
support/qemu-guest: Remove SGA bios parameter and warning
Starting with QEMU version 8.0, the `-device sga` parameter is removed from
the command line because it is no longer needed. These versions include a
SeaBIOS version that contains native support for serial consoles. If an
older version of QEMU is used with `qemu-guest`, the BIOS output may no
longer be visible but the guest would still be able to boot.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Simon Kuenzer [Thu, 19 Jan 2023 00:58:27 +0000 (01:58 +0100)]
support/qemu-guest: Enable X2APIC for TCG mode
Enables X2APIC when TCG mode is selected. As soon as QEMU is available,
this should enable running a recent x86_64 version of Unikraft on devices
without x86 hardware virtualization support (e.g., Arm).
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Simon Kuenzer [Thu, 27 Jul 2023 20:44:50 +0000 (22:44 +0200)]
build: Print actual build directory name with `properclean`
This commit corrects the output of the `properclean` make target. Instead
of just outputting `RM build/`, the currently configured build directory is
printed.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
This commit introduces a replacement for `build/config-submenu.sh`. The
main reason for the rewrite was the incompatibilities on Darwin. The new
script mainly uses `bash`-internal functions to avoid incompatibilities
with third-party commands called by the script.
Checkpatch-Ignore: LONG_LINE_STRING
Checkpatch-Ignore: LONG_LINE Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Simon Kuenzer [Thu, 27 Jul 2023 07:46:00 +0000 (09:46 +0200)]
build: Robust version checking helpers with `printf`
This commit updates the compiler version checking helpers so that they also
work under environments like Darwin. It turns out that the behavior of
`echo` can be different in different environments, while `printf` seems to
be well defined.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Simon Kuenzer [Wed, 11 Jan 2023 00:51:41 +0000 (01:51 +0100)]
build: Use gsed on Darwin (MacOS)
The build system depends on the GNU version of `sed`. Since this is
typically installed with `gsed` on Darwin environments, we call `gsed`
in such a case.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Simon Kuenzer [Wed, 11 Jan 2023 00:47:53 +0000 (01:47 +0100)]
build: Detect host environment
This commit intorduces thwe build variable $(HOSTOSENV) which contains the
host environmenrt (e.g., Linux, Darwin) so that the build system is able to
behave appropriately to the details of the host environment.
Checkpatch-Ignore: FSF_MAILING_ADDRESS Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
This commit creates the build folder substructure ealier, except that a
target was called that does not require any KConfig involvement. This
allows us to move generated Config.uk snippets under `build/kconfig` in
order to clean up the root of the build folder.
Additionally, this commit corrects
commit b8872a6b572c ("build: first level subdirectories only with `mk_sub_build_dir`")
where the `uk` subdirectory was no longer created under
`$(BUILD_ROOT)/include`. The commit also introduces consistent use
of the `$(MKDIR)` command alias.
Signed-off-by: Simon Kuenzer <simon@unikraft.io> Reviewed-by: Alexander Jung <alex@unikraft.io> Approved-by: Razvan Deaconescu <razvand@unikraft.io> Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #1034
Sergiu Moga [Mon, 15 May 2023 06:08:16 +0000 (09:08 +0300)]
plat/kvm/x86: Make sure we allocate the `SIPI Vector` as reserved
Now that we can dynamically decide the `SIPI Vector`, make sure
we do this allocation when all the memory regions are properly
setup in the `Multiboot1` memory region setup method.
Sergiu Moga [Mon, 15 May 2023 06:05:29 +0000 (09:05 +0300)]
plat/kvm/x86: Make sure we have the legacy x86 high memory reserved
Since there is a chance that the previous boot phase did not mark
this area as reserved through a memory region descriptor, make sure
we do it ourselved.
Since this memory region is very low, we do this insertion when this
list is empty to avoid unnecessary iterations.
Sergiu Moga [Mon, 15 May 2023 06:02:07 +0000 (09:02 +0300)]
plat/kvm/x86: Keep `Multiboot1` memory regions below `1 MiB`
Keep the `e820` enries below `1 MiB` that we were passed through
`Multiboot1` and rely on the unmappings memory region descriptor to
tell us later what to unmap.
plat/linuxu: Drop no longer used `liblinuxuplat_opts` structure
Now that we rely on `ukplat_memregion` generic API's, we have no
more need for linuxu configuration specific structures when it comes
to memory regions.
plat: Integrate `ukplat_memregion` API's into `ARM64` builds
Rely on the generic `ukplat_memregion` API's for memory region
management and drop `_libkvmplat_cfg` usage in favor of the
`bootinfo` getters.
Now that `ukplat_memregion`'s are usable on `ARM64`, proper
paging support can be used instead of the overly-complicated
memory re-adjustment that was previously done in `_init_dtb_mem`.
Instead, we rely on `ukplat_memregion_alloc` for proper memory
region management.
Another important, notable change, is that of changing
`arm64_bpt_l0_pt0` to contain only one, unified, entry of `pte_fill`.
This reduced page permission granularity allows us further flexibility
in where the Kernel is placed so that we are truly position independent.
One may be right in saying that this looks not so secure, having all that
memory mapped with all permissions, however this is not as important when
the two existing possible use-cases are taken into consideration:
- Paging API is disabled and we will either way have wrong permissions
everywhere anyway
- Paging API is enabled and this area will be unmapped anyway and new
proper permissions will be used instead
Therefore, until the time comes when we manage to dynamically get rid
of the static boot page tables, we will align ARM with x86 and have the
static boot page tables all mapped with all permissions w.r.t. to
Kernel placement.
Furthermore, now that ARM64 can also use the heap base
`CONFIG_LIBUKBOOT_HEAP_BASE` configuration option, drop the x86
dependency.
Sergiu Moga [Sun, 21 May 2023 12:52:01 +0000 (15:52 +0300)]
plat/common/paging.c: For `ARM64`, don't map outside unmap region
Since on `ARM64` we map all of the peripherals' I/O space statically,
make sure that we do not map the regions in the list that are outside
our globally declared unmap memory region descriptor.
Sergiu Moga [Mon, 15 May 2023 05:58:44 +0000 (08:58 +0300)]
plat/kvm/arm: Hardcode a memory region descriptor for unmappings
Add a memory region descriptor to indicate the range we are meant to
unmap when paging is initialized and we are getting rid of the
initial static boot page tables.
Sergiu Moga [Sat, 20 May 2023 14:28:36 +0000 (17:28 +0300)]
plat/common/paging.c: Do not ignore `EEXIST` errors while mapping
Commit f0ae44de725f ("plat/kvm/x86: Workaround re-mapping low-mem areas")
introduced this check to ignore `EEXIST` errors while mapping the
memory regions marked as `UKPLAT_MEMRF_MAP` due to the fact that,
before the previous commit ("plat: Generalize memory initialization"),
Unikraft was ignoring all memory regions in the first 1 MiB and was
manually hardcoding the mappings in the static boot page tables.
This was done because the `multiboot` boot protocol would not report
the legacy mapped `BIOS ROM` area or the `VGA Framebuffer` in its
e820 map's reserved regions.
We no longer need this anymore and, if anything, it helps
us ensure that the setup of the boot environment's mappings is done
as we expect it to be.
Sergiu Moga [Mon, 15 May 2023 05:44:45 +0000 (08:44 +0300)]
plat: Generalize memory initialization
Re-define `mem_init` into `ukplat_mem_init` that does the same thing,
but does not assume what regions to keep or unmap. Instead, it relies
on the platform/architecture defined unmap memory region to do this.
plat/common/paging.c: Flush TLB only if we are modifying current PT
Flushing the TLB introduces an unnecessary performance penalty if we
are modifying a page table that is different from our current one.
Therefore, ensure that the TLB is flushed only if the page table we
are currently modifying is the same as the one we currently have
active.
plat: Move paging initialization to a platform common location
Since the `paging_init` function of the x86 KVM subsystem is written
in a generic manner, it can be reused by other architectures or
platforms. Thus, move it to a platform generic location and rename
it with a more intuitive name to align it with the other function
declarations of `paging.c`.
Furthermore, only call `ukplat_pt_set_active` at the very end, to avoid
unnecessary `TLB` flushes.
Sergiu Moga [Mon, 15 May 2023 05:40:52 +0000 (08:40 +0300)]
plat/kvm/x86: Hardcode a memory region descriptor for unmappings
Add a memory region descriptor to indicate the range we are meant to
unmap when paging is initialized and we are getting rid of the
initial static boot page tables.
Sergiu Moga [Mon, 15 May 2023 05:32:57 +0000 (08:32 +0300)]
plat/common: Implement method to dynamically assign `SIPI Vector`
Add an inline function that simply allocates a reserved memory region
meant for the `SIPI Vector`. If this function fails we wouldn"t have
been able to do this properly with the old way anyway (hardcoded
`SIPI Vector` at `0x8000`).
This should only be called after the memory region list has been
fully built and coalesced.
plat/common: Make `ukplat_memregion_alloc` aware of memory holes
In case we are somehow able to allocate memory from an in-image
memory hole, make sure we do not give it the `UKPLAT_MEMRF_MAP`
flag, since it is already mapped, which causes the paging
initialization phase to exit with an `-EEXIST` error code.
plat/common/arm: Make `lcpu_arch_jump_to` not SMP dependent
Since `lcpu_arch_jump_to` can be used with and without
`CONFIG_HAVE_SMP`, move it to a place where the preprocessing
phase does not remove the function from the final image.
plat/kvm: Move `ukplat_memregion` API's to platform common location
Since these API's can be used on any platform and any architecture
subsystem that integrates `struct ukplat_bootinfo` structure, move
their definitions to a platform common place in the tree.
plat/linuxu: Move `initrd` and `heap` initialization to `setup.c`
Initialize the `heap` and `initrd` as soon as possible and move the
respective functions to `setup.c`, as that is the only place where
they are to be used.
plat/kvm/x86: Coalesce the memory region descriptor list
Ensure that there are no overlapping memory regions in the memory
region descriptor list by coalescing them after finishing the
insertion phase of the memory regions reported through the multiboot
protocol.
plat/common: Add a memory region descriptor coalescing method
Implement a function that, given a list of memory region descriptors,
coalesces them based on a priority. The lowest priority is that of
the free memory regions, while the highest is that of the reserved
memory regions. This priority is required whenever it comes to
splitting memory regions that overlap. Thus, a memory region whose
priority is higher, gets to keep its overlapping fragment, while the
other is either split or reduced.
plat/kvm/x86: Mark the thrashed command-line as a kernel resource
Since this buffer is only meant for `ukplat_entry_argp`, which will
thrash it as a result of parsing it to obtain `argc`/`argv`, mark it
as a kernel related memory region instead (`UKPLAT_MEMRT_KERNEL`).
Since `bootmemory_palloc` can be used by any platform and
architecture and can come in handy when wanting to allocate a memory
region descriptor on the spot, that is not part of the original
memory map, move it to a more general location.
Furthermore, rename the function to `ukplat_memregion_alloc` to make
its usage-case more intuitive.
plat/kvm/x86: Fix `bootmemory_palloc` keeping empty memory region
Whenever a memory region allocation request done through
`bootmemory_palloc` would require a length equal to one of the
available memory regions, a new, equivalent, memory region would
be created and the original one would be left empty, thus breaking
the memory allocator.
Sergiu Moga [Tue, 21 Mar 2023 10:49:59 +0000 (12:49 +0200)]
plat/common: Make the amount of Memory Region Descriptors configurable
Sice `bootinfo` statically allocates space in the final image to store
Memory Region Descriptors at runtime and their actual amount is highly
variable depending on the platform, allow the user to configure a
precise maximum amount of such descriptors.
This allows flexibility in the size of the final image. One can check
at runtime whether `-ENOMEM` is returned by the memory region insertion
function or not and adjust `CONFIG_UKPLAT_MEMREGION_MAX_COUNT` accordingly.