mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 09:23:25 +00:00
Refactor OSDK and Asterinas Docker build systems
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
149c00f5fc
commit
a14d5a5017
1
osdk/tools/docker/.gitignore
vendored
1
osdk/tools/docker/.gitignore
vendored
@ -1 +0,0 @@
|
||||
**/Dockerfile
|
172
osdk/tools/docker/Dockerfile
Normal file
172
osdk/tools/docker/Dockerfile
Normal file
@ -0,0 +1,172 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
FROM ubuntu:22.04 AS build-base
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
git \
|
||||
python3-pip \
|
||||
python-is-python3 \
|
||||
wget
|
||||
|
||||
RUN pip3 install iq tomli
|
||||
|
||||
#= Build QEMU =================================================================
|
||||
|
||||
FROM build-base AS build-qemu
|
||||
|
||||
RUN apt update && apt-get install -y --no-install-recommends \
|
||||
libgcrypt-dev `# optional build dependency` \
|
||||
libglib2.0-dev `# build dependency` \
|
||||
libpixman-1-dev `# build dependency` \
|
||||
libusb-dev `# optional build dependency` \
|
||||
meson \
|
||||
ninja-build
|
||||
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM build-qemu AS qemu
|
||||
|
||||
# Fetch and install QEMU from the official source
|
||||
#
|
||||
# The QEMU version in the Ubuntu 22.04 repository is 6.*, which has a bug to cause OVMF debug to fail.
|
||||
# The libslirp dependency is for QEMU's network backend.
|
||||
WORKDIR /root
|
||||
|
||||
RUN wget -O qemu.tar.xz https://download.qemu.org/qemu-9.1.0.tar.xz \
|
||||
&& mkdir /root/qemu \
|
||||
&& tar xf qemu.tar.xz --strip-components=1 -C /root/qemu \
|
||||
&& rm qemu.tar.xz
|
||||
WORKDIR /root/qemu
|
||||
RUN ./configure --target-list=x86_64-softmmu --prefix=/usr/local/qemu --enable-slirp \
|
||||
&& make -j \
|
||||
&& make install
|
||||
WORKDIR /root
|
||||
RUN rm -rf /root/qemu
|
||||
|
||||
#= Build OVMF =================================================================
|
||||
|
||||
FROM build-base AS build-ovmf
|
||||
|
||||
RUN apt update && apt-get install -y --no-install-recommends \
|
||||
bison \
|
||||
flex \
|
||||
iasl \
|
||||
nasm \
|
||||
uuid-dev
|
||||
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||
RUN git --version
|
||||
|
||||
FROM build-ovmf AS ovmf
|
||||
|
||||
# Fetch and build OVMF from the EDK2 official source
|
||||
WORKDIR /root
|
||||
RUN git clone --depth 1 --branch stable/202408 --recurse-submodules --shallow-submodules https://github.com/tianocore/edk2.git
|
||||
WORKDIR /root/edk2
|
||||
RUN /bin/bash -c "source ./edksetup.sh \
|
||||
&& make -C BaseTools \
|
||||
&& build -a X64 -t GCC5 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc -D DEBUG_ON_SERIAL_PORT \
|
||||
&& build -a X64 -t GCC5 -b RELEASE -p OvmfPkg/OvmfPkgX64.dsc"
|
||||
|
||||
#= Build GRUB =================================================================
|
||||
|
||||
FROM build-base AS build-grub
|
||||
|
||||
RUN apt update && apt-get install -y --no-install-recommends \
|
||||
autoconf \
|
||||
automake \
|
||||
autopoint \
|
||||
bison \
|
||||
flex \
|
||||
gawk \
|
||||
gettext \
|
||||
libfreetype6-dev \
|
||||
pkg-config
|
||||
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM build-grub AS grub
|
||||
|
||||
# Fetch and install GRUB from the GNU official source
|
||||
#
|
||||
# We have installed grub-efi-amd64-bin just for the unicode.pf2 file, which is not included
|
||||
# in the GRUB release. The Ubuntu release notoriously modifies the GRUB source code and enforce
|
||||
# EFI handover boot, which is deprecated. So we have to build GRUB from source.
|
||||
WORKDIR /root
|
||||
# See also: https://github.com/asterinas/asterinas/pull/1710
|
||||
RUN git clone --single-branch -b asterinas/2.12 https://github.com/asterinas/grub.git \
|
||||
&& git -C grub checkout 0633bc8
|
||||
# Fetch and install the Unicode font data for grub.
|
||||
RUN wget -O unifont.pcf.gz https://unifoundry.com/pub/unifont/unifont-15.1.04/font-builds/unifont-15.1.04.pcf.gz \
|
||||
&& mkdir -pv /usr/share/fonts/unifont \
|
||||
&& gunzip -c unifont.pcf.gz > /usr/share/fonts/unifont/unifont.pcf \
|
||||
&& rm unifont.pcf.gz
|
||||
WORKDIR /root/grub
|
||||
|
||||
RUN echo depends bli part_gpt > grub-core/extra_deps.lst \
|
||||
&& ./bootstrap \
|
||||
&& ./configure \
|
||||
--target=x86_64 \
|
||||
--disable-efiemu \
|
||||
--with-platform=efi \
|
||||
--enable-grub-mkfont \
|
||||
--prefix=/usr/local/grub \
|
||||
--disable-werror \
|
||||
&& make -j \
|
||||
&& make install
|
||||
WORKDIR /root
|
||||
RUN rm -rf /root/grub
|
||||
|
||||
#= The final stages to produce the OSDK development image ====================
|
||||
|
||||
FROM build-base AS rust
|
||||
|
||||
# Install all OSDK dependent packages
|
||||
RUN apt update \
|
||||
&& apt install -y \
|
||||
build-essential \
|
||||
curl \
|
||||
gdb \
|
||||
grub-efi-amd64 \
|
||||
grub2-common \
|
||||
libpixman-1-dev `# running dependency for QEMU` \
|
||||
mtools `# used by grub-mkrescue` \
|
||||
xorriso \
|
||||
&& apt clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Rust with both nightly and stable
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
ARG ASTER_RUST_VERSION
|
||||
RUN curl https://sh.rustup.rs -sSf | \
|
||||
sh -s -- --default-toolchain ${ASTER_RUST_VERSION} -y \
|
||||
&& rustup toolchain install stable \
|
||||
&& rm -rf /root/.cargo/registry && rm -rf /root/.cargo/git \
|
||||
&& cargo -V \
|
||||
&& rustup component add rust-src rustc-dev llvm-tools-preview
|
||||
|
||||
# Install cargo tools
|
||||
RUN cargo install \
|
||||
cargo-binutils \
|
||||
mdbook \
|
||||
typos-cli
|
||||
|
||||
# Install QEMU built from the previous stages
|
||||
COPY --from=qemu /usr/local/qemu /usr/local/qemu
|
||||
ENV PATH="/usr/local/qemu/bin:${PATH}"
|
||||
ENV LD_LIBRARY_PATH="/usr/local/qemu/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}"
|
||||
|
||||
# Install OVMF built from the previous stages
|
||||
COPY --from=ovmf /root/edk2/Build/OvmfX64/DEBUG_GCC5/FV/ /root/ovmf/debug
|
||||
COPY --from=ovmf /root/edk2/Build/OvmfX64/RELEASE_GCC5/FV/ /root/ovmf/release
|
||||
|
||||
# Install GRUB built from the previous stages
|
||||
COPY --from=grub /usr/local/grub /usr/local/grub
|
||||
ENV PATH="/usr/local/grub/bin:${PATH}"
|
||||
# Make a symbolic link for `unicode.pf2` from Ubuntu 22.04 package
|
||||
RUN ln -sf /usr/share/grub/unicode.pf2 /usr/local/grub/share/grub/unicode.pf2
|
||||
|
||||
VOLUME [ "/root/asterinas" ]
|
||||
|
||||
WORKDIR /root/asterinas
|
@ -1,36 +0,0 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
FROM {% base_image %}
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt update \
|
||||
&& apt install -y \
|
||||
build-essential \
|
||||
curl \
|
||||
gdb \
|
||||
grub-efi-amd64 \
|
||||
grub2-common \
|
||||
libpixman-1-dev `# running dependency for QEMU` \
|
||||
mtools `# used by grub-mkrescue` \
|
||||
xorriso \
|
||||
{% qemu_ovmf_installation %} \
|
||||
&& apt clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Rust of both nightly and stable channel
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
ARG ASTER_RUST_VERSION
|
||||
RUN curl https://sh.rustup.rs -sSf | \
|
||||
sh -s -- --default-toolchain ${ASTER_RUST_VERSION} -y \
|
||||
&& rustup toolchain install stable \
|
||||
&& rm -rf /root/.cargo/registry && rm -rf /root/.cargo/git \
|
||||
&& cargo -V \
|
||||
&& rustup component add rust-src rustc-dev llvm-tools-preview
|
||||
|
||||
# Install cargo-binutils
|
||||
RUN cargo install cargo-binutils
|
||||
|
||||
VOLUME [ "/root/asterinas" ]
|
||||
|
||||
WORKDIR /root/asterinas
|
40
osdk/tools/docker/README.md
Normal file
40
osdk/tools/docker/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# OSDK Development Docker Images
|
||||
|
||||
The OSDK development Docker images provide the development environment for using and developing OSDK.
|
||||
|
||||
## Building Docker Images
|
||||
|
||||
To build an OSDK development Docker image and test it on your local machine, navigate to the root directory of the Asterinas source code tree and execute the following command:
|
||||
|
||||
```bash
|
||||
cd <asterinas dir>
|
||||
# Build Docker image
|
||||
docker buildx build \
|
||||
-f osdk/tools/docker/Dockerfile \
|
||||
--build-arg ASTER_RUST_VERSION=$(grep "channel" rust-toolchain.toml | awk -F '"' '{print $2}') \
|
||||
-t asterinas/osdk:$(cat DOCKER_IMAGE_VERSION) \
|
||||
.
|
||||
```
|
||||
|
||||
Intel TDX has some special requirements on the development environment such as QEMU.
|
||||
So we offer a TDX-specific version of the OSDK development Docker image.
|
||||
You need to build the general-purpose Docker image before building the TDX-specific one
|
||||
as the former is used by the latter one as the base image.
|
||||
|
||||
```bash
|
||||
cd <asterinas dir>
|
||||
# Build Intel TDX Docker image
|
||||
docker buildx build \
|
||||
-f osdk/tools/docker/tdx/Dockerfile \
|
||||
--build-arg ASTER_RUST_VERSION=$(grep "channel" rust-toolchain.toml | awk -F '"' '{print $2}') \
|
||||
--build-arg BASE_VERSION=$(cat DOCKER_IMAGE_VERSION) \
|
||||
-t asterinas/osdk:$(cat DOCKER_IMAGE_VERSION)-tdx \
|
||||
.
|
||||
```
|
||||
|
||||
## Tagging and Uploading Docker Images
|
||||
|
||||
The Docker images are tagged according to the version specified
|
||||
in the `DOCKER_IMAGE_VERSION` file at the project root.
|
||||
Check out the [version bump](https://asterinas.github.io/book/to-contribute/version-bump.html) documentation
|
||||
on how new versions of the Docker images are released.
|
@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
ASTER_ROOT_DIR=${SCRIPT_DIR}/../../..
|
||||
ASTER_RUST_VERSION=$( grep -m1 -o 'nightly-[0-9]\+-[0-9]\+-[0-9]\+' ${ASTER_ROOT_DIR}/rust-toolchain.toml )
|
||||
VERSION=$( cat ${ASTER_ROOT_DIR}/VERSION )
|
||||
DOCKERFILE=${SCRIPT_DIR}/Dockerfile
|
||||
|
||||
if [ "$1" = "intel-tdx" ]; then
|
||||
IMAGE_NAME="asterinas/osdk:${VERSION}-tdx"
|
||||
python3 gen_dockerfile.py --intel-tdx
|
||||
else
|
||||
IMAGE_NAME="asterinas/osdk:${VERSION}"
|
||||
python3 gen_dockerfile.py
|
||||
fi
|
||||
|
||||
docker build \
|
||||
-t ${IMAGE_NAME} \
|
||||
--build-arg ASTER_RUST_VERSION=${ASTER_RUST_VERSION} \
|
||||
-f ${DOCKERFILE} \
|
||||
${SCRIPT_DIR}
|
@ -1,78 +0,0 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
import re
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(description='The Dockerfile generator for OSDK.')
|
||||
parser.add_argument('--intel-tdx', action='store_true', help='Include Intel TDX support')
|
||||
parser.add_argument(
|
||||
'--out-dir',
|
||||
type=str,
|
||||
default='.',
|
||||
help='Output the Dockerfile under this directory. \
|
||||
By default, the output directory is the current working directory.'
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
def validate_out_dir(out_dir):
|
||||
if os.path.isabs(out_dir):
|
||||
print("Error: The --out-dir argument must be a relative path.")
|
||||
sys.exit(1)
|
||||
|
||||
def setup_output_directory(out_dir):
|
||||
template_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
if out_dir == '.':
|
||||
return template_dir
|
||||
output_directory_path = os.path.join(template_dir, out_dir)
|
||||
if not os.path.exists(output_directory_path):
|
||||
os.makedirs(output_directory_path)
|
||||
return output_directory_path
|
||||
|
||||
def load_template(template_dir):
|
||||
template_file = os.path.join(template_dir, 'Dockerfile.template')
|
||||
if not os.path.isfile(template_file):
|
||||
logging.error(f"Template file {template_file} does not exist.")
|
||||
sys.exit(1)
|
||||
with open(template_file, 'r') as file:
|
||||
return file.read()
|
||||
|
||||
def generate_dockerfile_content(variables, template_content):
|
||||
for var_name, var_value in variables.items():
|
||||
template_content = re.sub(r'{%\s*' + var_name + r'\s*%}', var_value, template_content)
|
||||
return template_content
|
||||
|
||||
def write_dockerfile(output_directory, content):
|
||||
output_path = os.path.join(output_directory, 'Dockerfile')
|
||||
with open(output_path, 'w') as file:
|
||||
file.write(content)
|
||||
logging.info(f'Dockerfile has been generated at {output_path}.')
|
||||
|
||||
def main():
|
||||
args = parse_arguments()
|
||||
validate_out_dir(args.out_dir)
|
||||
|
||||
variables = {
|
||||
'base_image': r'ubuntu:22.04',
|
||||
'qemu_ovmf_installation': r"""ovmf \
|
||||
qemu-system-x86""",
|
||||
}
|
||||
|
||||
if args.intel_tdx:
|
||||
variables['base_image'] = r'intelcczoo/tdvm:ubuntu22.04-mvp_2023ww15'
|
||||
variables['qemu_ovmf_installation'] = r''
|
||||
|
||||
template_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
output_directory = setup_output_directory(args.out_dir)
|
||||
template_content = load_template(template_dir)
|
||||
dockerfile_content = generate_dockerfile_content(variables, template_content)
|
||||
write_dockerfile(output_directory, dockerfile_content)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
38
osdk/tools/docker/tdx/Dockerfile
Normal file
38
osdk/tools/docker/tdx/Dockerfile
Normal file
@ -0,0 +1,38 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
ARG BASE_VERSION
|
||||
FROM asterinas/osdk:${BASE_VERSION} AS build-base
|
||||
|
||||
# Fetch and install QEMU from the intel-staging/qemu-tdx source
|
||||
FROM build-base AS build-qemu-tdx
|
||||
|
||||
RUN apt update && apt-get install -y --no-install-recommends \
|
||||
libgcrypt-dev `# optional build dependency` \
|
||||
libglib2.0-dev `# build dependency` \
|
||||
libpixman-1-dev `# build dependency` \
|
||||
libusb-dev `# optional build dependency` \
|
||||
meson \
|
||||
ninja-build
|
||||
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM build-qemu-tdx AS qemu-tdx
|
||||
|
||||
WORKDIR /root
|
||||
RUN git clone -b tdx-qemu-upstream-2024.02.29-v8.2.0 https://github.com/intel-staging/qemu-tdx.git
|
||||
WORKDIR /root/qemu-tdx
|
||||
COPY osdk/tools/docker/tdx/tdx_qemu.patch /root/qemu-tdx
|
||||
RUN git apply tdx_qemu.patch \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& ../configure --enable-kvm --target-list=x86_64-softmmu --prefix=/usr/local/qemu --enable-slirp \
|
||||
&& make -j \
|
||||
&& make install
|
||||
WORKDIR /root
|
||||
RUN rm -rf /root/qemu-tdx
|
||||
|
||||
FROM build-base
|
||||
|
||||
# Install QEMU built from the previous stages
|
||||
COPY --from=qemu-tdx /usr/local/qemu /usr/local/qemu
|
||||
|
||||
WORKDIR /root/asterinas
|
251
osdk/tools/docker/tdx/tdx_qemu.patch
Normal file
251
osdk/tools/docker/tdx/tdx_qemu.patch
Normal file
@ -0,0 +1,251 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2025 Intel Corporation
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 2c83b6d270..b9aebe1ea6 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -2983,6 +2983,8 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
|
||||
addr = memory_region_get_ram_ptr(mr) + section.offset_within_region;
|
||||
rb = qemu_ram_block_from_host(addr, false, &offset);
|
||||
|
||||
+ memory_region_convert_mem_attr(§ion, !to_private);
|
||||
+
|
||||
if (to_private) {
|
||||
if (rb->page_size != qemu_host_page_size) {
|
||||
/*
|
||||
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
|
||||
index 745ead0034..6cef1b5ff2 100644
|
||||
--- a/backends/hostmem-memfd.c
|
||||
+++ b/backends/hostmem-memfd.c
|
||||
@@ -56,6 +56,7 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||
+ ram_flags |= m->hugetlb ? RAM_GUEST_MEMFD_HUGETLB : 0;
|
||||
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||
backend->size, ram_flags, fd, 0, errp);
|
||||
}
|
||||
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
|
||||
index 059bfdc07a..d3f7cc93e7 100644
|
||||
--- a/hw/vfio/common.c
|
||||
+++ b/hw/vfio/common.c
|
||||
@@ -251,6 +251,7 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section)
|
||||
return (!memory_region_is_ram(section->mr) &&
|
||||
!memory_region_is_iommu(section->mr)) ||
|
||||
memory_region_is_protected(section->mr) ||
|
||||
+ memory_region_has_guest_memfd(section->mr) ||
|
||||
/*
|
||||
* Sizing an enabled 64-bit BAR can cause spurious mappings to
|
||||
* addresses in the upper part of the 64-bit address space. These
|
||||
@@ -347,12 +348,9 @@ out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
-static void vfio_ram_discard_notify_discard(RamDiscardListener *rdl,
|
||||
- MemoryRegionSection *section)
|
||||
+static void vfio_notify_discard_generic(VFIOContainerBase *bcontainer,
|
||||
+ MemoryRegionSection *section)
|
||||
{
|
||||
- VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
|
||||
- listener);
|
||||
- VFIOContainerBase *bcontainer = vrdl->bcontainer;
|
||||
const hwaddr size = int128_get64(section->size);
|
||||
const hwaddr iova = section->offset_within_address_space;
|
||||
int ret;
|
||||
@@ -365,12 +363,10 @@ static void vfio_ram_discard_notify_discard(RamDiscardListener *rdl,
|
||||
}
|
||||
}
|
||||
|
||||
-static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl,
|
||||
- MemoryRegionSection *section)
|
||||
+static int vfio_notify_populate_generic(VFIOContainerBase *bcontainer,
|
||||
+ MemoryRegionSection *section,
|
||||
+ uint64_t granularity)
|
||||
{
|
||||
- VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
|
||||
- listener);
|
||||
- VFIOContainerBase *bcontainer = vrdl->bcontainer;
|
||||
const hwaddr end = section->offset_within_region +
|
||||
int128_get64(section->size);
|
||||
hwaddr start, next, iova;
|
||||
@@ -382,7 +378,7 @@ static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl,
|
||||
* unmap in minimum granularity later.
|
||||
*/
|
||||
for (start = section->offset_within_region; start < end; start = next) {
|
||||
- next = ROUND_UP(start + 1, vrdl->granularity);
|
||||
+ next = ROUND_UP(start + 1, granularity);
|
||||
next = MIN(next, end);
|
||||
|
||||
iova = start - section->offset_within_region +
|
||||
@@ -393,13 +389,31 @@ static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl,
|
||||
vaddr, section->readonly);
|
||||
if (ret) {
|
||||
/* Rollback */
|
||||
- vfio_ram_discard_notify_discard(rdl, section);
|
||||
+ vfio_notify_discard_generic(bcontainer, section);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void vfio_ram_discard_notify_discard(RamDiscardListener *rdl,
|
||||
+ MemoryRegionSection *section)
|
||||
+{
|
||||
+ VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
|
||||
+ listener);
|
||||
+
|
||||
+ vfio_notify_discard_generic(vrdl->bcontainer, section);
|
||||
+}
|
||||
+
|
||||
+static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl,
|
||||
+ MemoryRegionSection *section)
|
||||
+{
|
||||
+ VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
|
||||
+ listener);
|
||||
+
|
||||
+ return vfio_notify_populate_generic(vrdl->bcontainer, section, vrdl->granularity);
|
||||
+}
|
||||
+
|
||||
static void vfio_register_ram_discard_listener(VFIOContainerBase *bcontainer,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
@@ -1353,6 +1367,19 @@ static void vfio_listener_log_sync(MemoryListener *listener,
|
||||
}
|
||||
}
|
||||
|
||||
+static void vfio_listener_convert_mem_attr(MemoryListener *listener,
|
||||
+ MemoryRegionSection *section,
|
||||
+ bool shared)
|
||||
+{
|
||||
+ VFIOContainerBase *bcontainer = container_of(listener, VFIOContainerBase, listener);
|
||||
+
|
||||
+ if (shared)
|
||||
+ vfio_notify_populate_generic(bcontainer, section,
|
||||
+ 1ULL << (63 - clz64(bcontainer->pgsizes)));
|
||||
+ else
|
||||
+ vfio_notify_discard_generic(bcontainer, section);
|
||||
+}
|
||||
+
|
||||
const MemoryListener vfio_memory_listener = {
|
||||
.name = "vfio",
|
||||
.region_add = vfio_listener_region_add,
|
||||
@@ -1360,6 +1387,7 @@ const MemoryListener vfio_memory_listener = {
|
||||
.log_global_start = vfio_listener_log_global_start,
|
||||
.log_global_stop = vfio_listener_log_global_stop,
|
||||
.log_sync = vfio_listener_log_sync,
|
||||
+ .convert_mem_attr = vfio_listener_convert_mem_attr,
|
||||
};
|
||||
|
||||
void vfio_reset_handler(void *opaque)
|
||||
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
||||
index 1e351f6fc8..d17acdb2ea 100644
|
||||
--- a/include/exec/memory.h
|
||||
+++ b/include/exec/memory.h
|
||||
@@ -246,6 +246,9 @@ typedef struct IOMMUTLBEvent {
|
||||
/* RAM can be private that has kvm guest memfd backend */
|
||||
#define RAM_GUEST_MEMFD (1 << 12)
|
||||
|
||||
+/* Hugetlb can be private that has kvm guest memfd backend */
|
||||
+#define RAM_GUEST_MEMFD_HUGETLB (1 << 13)
|
||||
+
|
||||
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
|
||||
IOMMUNotifierFlag flags,
|
||||
hwaddr start, hwaddr end,
|
||||
@@ -1086,6 +1089,19 @@ struct MemoryListener {
|
||||
*/
|
||||
void (*coalesced_io_del)(MemoryListener *listener, MemoryRegionSection *section,
|
||||
hwaddr addr, hwaddr len);
|
||||
+
|
||||
+ /**
|
||||
+ * @convert_mem_attr:
|
||||
+ *
|
||||
+ * Called during the memory attribute conversion.
|
||||
+ *
|
||||
+ * @listener: The #MemoryListener
|
||||
+ * @section: The MemoryRegionSection
|
||||
+ * @shared: convert memory attribute from private to shared
|
||||
+ */
|
||||
+ void (*convert_mem_attr)(MemoryListener *listener, MemoryRegionSection *section,
|
||||
+ bool shared);
|
||||
+
|
||||
/**
|
||||
* @priority:
|
||||
*
|
||||
@@ -2541,6 +2557,14 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
|
||||
*/
|
||||
void memory_global_dirty_log_sync(bool last_stage);
|
||||
|
||||
+/**
|
||||
+ * memory_region_convert_mem_attr: convert the memory attribute
|
||||
+ * @section: the #MemoryRegionSection to be converted
|
||||
+ * @shared: if true, convert attribute from private to shared;
|
||||
+ * if false, convert from shared to private
|
||||
+ */
|
||||
+void memory_region_convert_mem_attr(MemoryRegionSection *section, bool shared);
|
||||
+
|
||||
/**
|
||||
* memory_global_dirty_log_sync: synchronize the dirty log for all memory
|
||||
*
|
||||
diff --git a/system/memory.c b/system/memory.c
|
||||
index 85a22408e9..e9a94e1654 100644
|
||||
--- a/system/memory.c
|
||||
+++ b/system/memory.c
|
||||
@@ -3009,6 +3009,21 @@ void memory_global_dirty_log_stop(unsigned int flags)
|
||||
memory_global_dirty_log_do_stop(flags);
|
||||
}
|
||||
|
||||
+void memory_region_convert_mem_attr(MemoryRegionSection *section, bool shared)
|
||||
+{
|
||||
+ MemoryListener *listener;
|
||||
+ if (!section->mr || !memory_region_has_guest_memfd(section->mr)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ QTAILQ_FOREACH(listener, &memory_listeners, link) {
|
||||
+ if (!listener->convert_mem_attr) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ listener->convert_mem_attr(listener, section, shared);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void listener_add_address_space(MemoryListener *listener,
|
||||
AddressSpace *as)
|
||||
{
|
||||
diff --git a/system/physmem.c b/system/physmem.c
|
||||
index 8c9368bc99..688f76e425 100644
|
||||
--- a/system/physmem.c
|
||||
+++ b/system/physmem.c
|
||||
@@ -1803,6 +1803,10 @@ static void dirty_memory_extend(ram_addr_t old_ram_size,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_KVM
|
||||
+#define KVM_GUEST_MEMFD_HUGETLB (1 << 1)
|
||||
+#endif
|
||||
+
|
||||
static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||
{
|
||||
const bool noreserve = qemu_ram_is_noreserve(new_block);
|
||||
@@ -1844,8 +1848,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||
if (kvm_enabled() && (new_block->flags & RAM_GUEST_MEMFD)) {
|
||||
assert(new_block->guest_memfd < 0);
|
||||
|
||||
- new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
||||
- 0, errp);
|
||||
+ new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
||||
+ (new_block->flags & RAM_GUEST_MEMFD_HUGETLB) ? KVM_GUEST_MEMFD_HUGETLB : 0, errp);
|
||||
if (new_block->guest_memfd < 0) {
|
||||
qemu_mutex_unlock_ramlist();
|
||||
return;
|
||||
@@ -1914,7 +1918,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
||||
/* Just support these ram flags by now. */
|
||||
assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
|
||||
RAM_PROTECTED | RAM_NAMED_FILE | RAM_READONLY |
|
||||
- RAM_READONLY_FD | RAM_GUEST_MEMFD)) == 0);
|
||||
+ RAM_READONLY_FD | RAM_GUEST_MEMFD |RAM_GUEST_MEMFD_HUGETLB)) == 0);
|
||||
|
||||
if (xen_enabled()) {
|
||||
error_setg(errp, "-mem-path not supported with Xen");
|
Reference in New Issue
Block a user