Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
60fc6c2bc4 | ||
|
a737902715 | ||
|
27aee66f88 | ||
|
11d7c0dcb3 | ||
|
bff0493d25 | ||
|
ef49283e51 | ||
|
e8b100aab2 | ||
|
95859dea34 | ||
|
b55440dce9 | ||
|
9d7f14e783 | ||
|
4d2537aafe | ||
|
8aca9eb12f | ||
|
dbc3ff39aa | ||
|
fcffdf8dbd | ||
|
7d15cc5255 | ||
|
eae668268e | ||
|
17c4ce75a1 | ||
|
1571a6d5f2 | ||
|
9a4c41cdc4 | ||
|
fa1f2ba7df | ||
|
0198edf145 | ||
|
e07a9618f9 | ||
|
aba53e78ef | ||
|
436cb9cddf | ||
|
172c56fe0a | ||
|
48a102e6b0 | ||
|
95bfc87eec | ||
|
ce96ba3fae | ||
|
88cf1229a7 | ||
|
4e552b0785 | ||
|
5c351bee0f | ||
|
65f84d6ae6 | ||
|
069afc6519 | ||
|
2474421fba | ||
|
81529af1ca | ||
|
f189d773c7 | ||
|
17d67247dc | ||
|
fa2b8fcfbe | ||
|
cb431d9df4 | ||
|
4924766b67 | ||
|
2dc56a8f23 | ||
|
c4ea248bc9 | ||
|
44a603a579 |
@ -15,7 +15,7 @@
|
||||
Makefile @terryzouhao @NanlinXie
|
||||
/hypervisor/ @dongyaozu @lifeix @junjiemao1
|
||||
/devicemodel/ @ywan170 @chejianj
|
||||
/doc/ @dbkinder @NanlinXie
|
||||
/doc/ @NanlinXie
|
||||
/misc/debug_tools/acrn_crashlog/ @ywan170 @lifeix
|
||||
/misc/debug_tools/acrn_log/ @ywan170 @lifeix
|
||||
/misc/debug_tools/acrn_trace/ @ywan170 @lifeix
|
||||
@ -27,4 +27,4 @@ Makefile @terryzouhao @NanlinXie
|
||||
/misc/packaging/ @terryzouhao @NanlinXie
|
||||
/misc/hv_prebuild/ @terryzouhao @NanlinXie
|
||||
|
||||
*.rst @dbkinder @NanlinXie
|
||||
*.rst @NanlinXie
|
||||
|
@ -48,7 +48,7 @@ the TSC and its membership, are described in the project's `technical-charter`_.
|
||||
|
||||
These are the current TSC voting members and chair person:
|
||||
|
||||
- Junjie Mao (chair): junjie.mao@intel.com
|
||||
- Yu Wang (chair): yu1.wang@intel.com
|
||||
- Helmut Buchsbaum: helmut.buchsbaum@tttech-industrial.com
|
||||
- Thomas Gleixner: thomas.gleixner@intel.com
|
||||
|
||||
|
2
VERSION
@ -1,3 +1,3 @@
|
||||
MAJOR_VERSION=3
|
||||
MINOR_VERSION=3
|
||||
MINOR_VERSION=4
|
||||
EXTRA_VERSION=-unstable
|
||||
|
@ -555,8 +555,13 @@ bool init_hugetlb(void)
|
||||
path[i] = 0;
|
||||
if (access(path, F_OK) != 0) {
|
||||
if (mkdir(path, 0755) < 0) {
|
||||
pr_err("mkdir %s failed.\n", path);
|
||||
return -1;
|
||||
/* We might have multiple acrn-dm instances booting VMs at
|
||||
* the same time
|
||||
*/
|
||||
if (errno != EEXIST) {
|
||||
pr_err("mkdir %s failed: %s\n", path, errormsg(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
path[i] = '/';
|
||||
|
@ -883,6 +883,7 @@ basl_fwrite_dsdt(FILE *fp, struct vmctx *ctx)
|
||||
|
||||
acpi_dev_write_dsdt(ctx);
|
||||
|
||||
osc_write_ospm_dsdt(ctx, basl_ncpu);
|
||||
pm_write_dsdt(ctx, basl_ncpu);
|
||||
|
||||
dsdt_line("}");
|
||||
|
@ -430,3 +430,62 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu)
|
||||
dsdt_line(" }");
|
||||
}
|
||||
}
|
||||
|
||||
/* _OSC: Operating System Capabilities
|
||||
* Currently only support CPPC v2 capability.
|
||||
* CPPC v2 capability: revision 2 of the _CPC object.
|
||||
* If all vcpus don't support _CPC object, no need to add _OSC in DSDT.
|
||||
*/
|
||||
void osc_write_ospm_dsdt(struct vmctx *ctx, int ncpu)
|
||||
{
|
||||
int ret;
|
||||
bool support_cpc = false;
|
||||
uint8_t px_cnt;
|
||||
|
||||
/* check px_cnt on vBSP */
|
||||
ret = get_vcpu_px_cnt(ctx, 0, &px_cnt);
|
||||
if (ret == 0 && px_cnt == 0) {
|
||||
/* px_cnt = 0 Indicates vcpu supports continuous pstate.
|
||||
*/
|
||||
support_cpc = true;
|
||||
}
|
||||
if (support_cpc) {
|
||||
/* Scope (_SB._OSC) */
|
||||
dsdt_line("");
|
||||
dsdt_line(" Scope (_SB)");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" Method (_OSC, 4, NotSerialized) // _OSC: Operating System Capabilities");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" CreateDWordField (Arg3, 0x00, STS0)");
|
||||
dsdt_line(" CreateDWordField (Arg3, 0x04, CAP0)");
|
||||
dsdt_line(" If ((Arg0 == ToUUID (\"0811b06e-4a27-44f9-8d60-3cbbc22e7b48\") /* Platform-wide OSPM Capabilities */))");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" If ((Arg1 == One))");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" If ((CAP0 & 0x40))");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" CAP0 &= 0x00000040");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" Else");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" STS0 &= 0xFFFFFF00");
|
||||
dsdt_line(" STS0 |= 0x02");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" Else");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" STS0 &= 0xFFFFFF00");
|
||||
dsdt_line(" STS0 |= 0x0A");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" Else");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" STS0 &= 0xFFFFFF00");
|
||||
dsdt_line(" STS0 |= 0x06");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" Return (Arg3)");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" }");
|
||||
dsdt_line("");
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
@ -94,6 +95,8 @@ static struct {
|
||||
{ COM5_BASE, COM5_IRQ, false},
|
||||
};
|
||||
|
||||
static bool stdio_ctrl_a_pressed = false;
|
||||
|
||||
#define UART_NLDEVS (ARRAY_SIZE(uart_lres))
|
||||
|
||||
enum uart_be_type {
|
||||
@ -717,6 +720,18 @@ uart_backend_read(struct uart_backend *be)
|
||||
|
||||
switch (be->be_type) {
|
||||
case UART_BE_STDIO:
|
||||
rc = read(be->fd, &rb, 1);
|
||||
if (rb == 0x01) { // Ctrl-a
|
||||
DPRINTF(("%s: Got Ctrl-a\n", __func__));
|
||||
stdio_ctrl_a_pressed = true;
|
||||
} else if (stdio_ctrl_a_pressed) {
|
||||
if (rb == 'x') {
|
||||
DPRINTF(("%s: Got Ctrl-a x\n", __func__));
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
stdio_ctrl_a_pressed = false;
|
||||
}
|
||||
break;
|
||||
case UART_BE_TTY:
|
||||
/* fd is used to read */
|
||||
rc = read(be->fd, &rb, 1);
|
||||
|
@ -127,4 +127,6 @@ int acrn_parse_iasl(char *arg);
|
||||
int get_iasl_compiler(void);
|
||||
int check_iasl_version(void);
|
||||
|
||||
void osc_write_ospm_dsdt(struct vmctx *ctx, int ncpu);
|
||||
|
||||
#endif /* _ACPI_H_ */
|
||||
|
@ -241,6 +241,8 @@ TAB_SIZE = 4
|
||||
# Allow for rst directives and advanced functions e.g. grid tables
|
||||
ALIASES = "rst=\verbatim embed:rst:leading-asterisk"
|
||||
ALIASES += "endrst=\endverbatim"
|
||||
ALIASES += consistency="\par consistency:^^"
|
||||
ALIASES += alignment="\par alignment:^^"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
|
@ -38,15 +38,15 @@ Before you begin, make sure your machines have the following prerequisites:
|
||||
|
||||
* Software specifications
|
||||
|
||||
- Ubuntu Desktop 24.04 LTS (ACRN development is not supported on Windows.)
|
||||
- Ubuntu Desktop 22.04 LTS (ACRN development is not supported on Windows.)
|
||||
|
||||
**Target system**:
|
||||
|
||||
* Hardware specifications
|
||||
|
||||
- Target board (see :ref:`hardware_tested`)
|
||||
- Ubuntu Desktop 24.04 LTS bootable USB disk: download the latest `Ubuntu
|
||||
Desktop 24.04 LTS ISO image <https://releases.ubuntu.com/noble/>`__ and
|
||||
- Ubuntu Desktop 22.04 LTS bootable USB disk: download the latest `Ubuntu
|
||||
Desktop 22.04 LTS ISO image <https://releases.ubuntu.com/jammy/>`__ and
|
||||
follow the `Ubuntu documentation
|
||||
<https://ubuntu.com/tutorials/create-a-usb-stick-on-ubuntu#1-overview>`__
|
||||
for creating the USB disk.
|
||||
@ -75,7 +75,7 @@ Prepare the Development Computer
|
||||
To set up the ACRN build environment on the development computer:
|
||||
|
||||
#. On the development computer, run the following command to confirm that Ubuntu
|
||||
Desktop 24.04 is running:
|
||||
Desktop 22.04 is running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -119,8 +119,8 @@ To set up the ACRN build environment on the development computer:
|
||||
xsltproc clang-format bc libpixman-1-dev libsdl2-dev libegl-dev \
|
||||
libgles-dev libdrm-dev gnu-efi libelf-dev liburing-dev \
|
||||
build-essential git-buildpackage devscripts dpkg-dev equivs lintian \
|
||||
apt-utils pristine-tar dh-python acpica-tools
|
||||
sudo pip3 install "elementpath==2.5.0" lxml "xmlschema==1.9.2" defusedxml tqdm
|
||||
apt-utils pristine-tar dh-python acpica-tools python3-tqdm \
|
||||
python3-elementpath python3-lxml python3-xmlschema python3-defusedxml
|
||||
|
||||
|
||||
#. Get the ACRN hypervisor and ACRN kernel source code, and check out the
|
||||
@ -172,7 +172,7 @@ To set up the target hardware environment:
|
||||
|
||||
#. Connect the monitor and power supply cable.
|
||||
|
||||
#. Connect the target system to the LAN with the Ethernet cable.
|
||||
#. Connect the target system to the LAN with the Ethernet cable or wifi.
|
||||
|
||||
Example of a target system with cables connected:
|
||||
|
||||
@ -182,13 +182,13 @@ Example of a target system with cables connected:
|
||||
Install OS on the Target
|
||||
============================
|
||||
|
||||
The target system needs Ubuntu Desktop 24.04 LTS to run the Board Inspector
|
||||
The target system needs Ubuntu Desktop 22.04 LTS to run the Board Inspector
|
||||
tool. You can read the full instructions to download, create a bootable USB
|
||||
drive, and `Install Ubuntu desktop
|
||||
<https://ubuntu.com/tutorials/install-ubuntu-desktop#1-overview>`_ on the Ubuntu
|
||||
site. We'll provide a summary here:
|
||||
|
||||
To install Ubuntu 24.04:
|
||||
To install Ubuntu 22.04:
|
||||
|
||||
#. Insert the Ubuntu bootable USB disk into the target system.
|
||||
|
||||
@ -248,9 +248,10 @@ Configure Target BIOS Settings
|
||||
#. Boot your target and enter the BIOS configuration editor.
|
||||
|
||||
Tip: When you are booting your target, you'll see an option (quickly) to
|
||||
enter the BIOS configuration editor, typically by pressing :kbd:`F2` or :kbd:`DEL` during
|
||||
the boot and before the GRUB menu (or Ubuntu login screen) appears. If you
|
||||
are not quick enough, you can still choose ``UEFI settings`` in the GRUB menu.
|
||||
enter the BIOS configuration editor, typically by pressing :kbd:`F2`
|
||||
or :kbd:`DEL` during the boot and before the GRUB menu (or Ubuntu login
|
||||
screen) appears. If you are not quick enough, you can still choose
|
||||
``UEFI settings`` in the GRUB menu or just reboot the system to try again.
|
||||
|
||||
#. Configure these BIOS settings:
|
||||
|
||||
@ -467,9 +468,9 @@ post-launched User VM. Each User VM has its own launch script.
|
||||
#. Confirm that the **VM type** is ``Standard``. In the previous step,
|
||||
``STD`` in the VM name is short for Standard.
|
||||
|
||||
#. Scroll down to **Memory size (MB)** and change the value to ``4096``. For
|
||||
this example, we will use Ubuntu 24.04 to boot the post-launched VM.
|
||||
Ubuntu 24.04 needs at least 4096 MB to boot.
|
||||
#. Scroll down to **Memory size (MB)** and change the value to ``2048``. For
|
||||
this example, we will use Ubuntu 22.04 to boot the post-launched VM.
|
||||
Ubuntu 22.04 needs at least 2048 MB to boot.
|
||||
|
||||
#. For **Physical CPU affinity**, select pCPU ID ``0``, then click **+** and
|
||||
select pCPU ID ``1`` to affine (or pin) the VM to CPU cores 0 and 1. (That will
|
||||
@ -479,17 +480,17 @@ post-launched User VM. Each User VM has its own launch script.
|
||||
default options.
|
||||
|
||||
#. For **Virtio block device**, click **+** and enter
|
||||
``/home/acrn/acrn-work/user-vm1.img``. This parameter
|
||||
``/home/acrn/acrn-work/ubuntu-22.04.4-desktop-amd64.iso``. This parameter
|
||||
specifies the VM's OS image and its location on the target system. Later
|
||||
in this guide, you will create the image file to that directory. (If you used
|
||||
in this guide, you will save the ISO file to that directory. (If you used
|
||||
a different username when installing Ubuntu on the target system, here's
|
||||
where you'll need to change the ``acrn`` username to the username you used.)
|
||||
|
||||
.. image:: images/configurator-postvm01.png
|
||||
.. image:: images/configurator_postvm01.png
|
||||
:align: center
|
||||
:class: drop-shadow
|
||||
|
||||
.. image:: images/configurator-postvm02.png
|
||||
.. image:: images/configurator_postvm02.png
|
||||
:align: center
|
||||
:class: drop-shadow
|
||||
|
||||
@ -574,7 +575,6 @@ Build ACRN
|
||||
ls *acrn-service-vm*.deb
|
||||
linux-headers-6.1.80-acrn-service-vm_6.1.80-acrn-service-vm-1_amd64.deb
|
||||
linux-image-6.1.80-acrn-service-vm_6.1.80-acrn-service-vm-1_amd64.deb
|
||||
linux-image-6.1.80-acrn-service-vm-dbg_6.1.80-acrn-service-vm-1_amd64.deb
|
||||
linux-libc-dev_6.1.80-acrn-service-vm-1_amd64.deb
|
||||
|
||||
#. Use the ``scp`` command to copy files from your development computer to the
|
||||
@ -634,11 +634,11 @@ Install ACRN
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
Ubuntu
|
||||
Advanced options for Ubuntu
|
||||
Ubuntu-ACRN Board Inspector, with Linux 6.8.0-35-generic
|
||||
Ubuntu-ACRN Board Inspector, with Linux 6.5.0-18-generic
|
||||
Ubuntu-ACRN Board Inspector, with Linux 6.1.80-acrn-service-vm
|
||||
Memory test (memtest86+x64.efi)
|
||||
Memory test (memtest86+x64.efi, serial console)
|
||||
Ubuntu with ACRN hypervisor, with Linux 6.8.0-35-generic (ACRN 3.3)
|
||||
Ubuntu with ACRN hypervisor, with Linux 6.5.0-18-generic (ACRN 3.3)
|
||||
*Ubuntu with ACRN hypervisor, with Linux 6.1.80-acrn-service-vm (ACRN 3.3)
|
||||
UEFI Firmware Settings
|
||||
|
||||
@ -688,24 +688,21 @@ The ACRN hypervisor boots the Ubuntu Service VM automatically.
|
||||
Launch the User VM
|
||||
*******************
|
||||
|
||||
#. On the target system, download the Ubuntu cloud images ``noble-server-cloudimg-amd64.img``
|
||||
for the User VM into the ``~/acrn-work/`` directory (the location we said
|
||||
in the ACRN Configurator for the scenario configuration for the VM):
|
||||
#. On the target system, use the web browser to visit the `official Ubuntu website <https://releases.ubuntu.com/jammy/>`__ and
|
||||
get the Ubuntu Desktop 22.04 LTS ISO image
|
||||
``ubuntu-22.04.4-desktop-amd64.iso`` for the User VM. (The same image you
|
||||
specified earlier in the ACRN Configurator UI.) Alternatively, instead of
|
||||
downloading it again, you could use ``scp`` to copy the ISO
|
||||
image file from the development system to the ``~/acrn-work`` directory on the target system.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd ~/acrn-work/
|
||||
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img ./
|
||||
|
||||
#. We need to do some steps before booting into cloud image User VM: Set up username and password both to ``acrn``;
|
||||
Change the image format to ``raw`` and change the image size:
|
||||
#. If you downloaded the ISO file on the target system, copy it from the
|
||||
Downloads directory to the ``~/acrn-work/`` directory (the location we said
|
||||
in the ACRN Configurator for the scenario configuration for the VM), for
|
||||
example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt install qemu-utils guestfs-tools
|
||||
sudo virt-customize -a ./noble-server-cloudimg-amd64.img --run-command 'useradd -m -s /bin/bash acrn' --run-command 'echo "acrn:acrn" | chpasswd' --run-command 'systemctl disable systemd-networkd-wait-online.service'
|
||||
qemu-img convert -f qcow2 -O raw ./noble-server-cloudimg-amd64.img ./user-vm1.img
|
||||
qemu-img -f raw ./user-vm1.img 16G
|
||||
cp ~/Downloads/ubuntu-22.04.4-desktop-amd64.iso ~/acrn-work
|
||||
|
||||
#. Launch the User VM:
|
||||
|
||||
@ -720,9 +717,34 @@ Launch the User VM
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Ubuntu 24.04 LTS ubuntu hvc0
|
||||
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-18-generic x86_64)
|
||||
|
||||
ubuntu login:
|
||||
* Documentation: https://help.ubuntu.com
|
||||
* Management: https://landscape.canonical.com
|
||||
* Support: https://ubuntu.com/advantage
|
||||
|
||||
Expanded Security Maintenance for Applications is not enabled.
|
||||
|
||||
0 updates can be applied immediately.
|
||||
|
||||
Enable ESM Apps to receive additional future security updates.
|
||||
See https://ubuntu.com/esm or run: sudo pro status
|
||||
|
||||
|
||||
The list of available updates is more than a week old.
|
||||
To check for new updates run: sudo apt update
|
||||
|
||||
The programs included with the Ubuntu system are free software;
|
||||
the exact distribution terms for each program are described in the
|
||||
individual files in /usr/share/doc/*/copyright.
|
||||
|
||||
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
|
||||
applicable law.
|
||||
|
||||
To run a command as administrator (user "root"), use "sudo <command>".
|
||||
See "man sudo_root" for details.
|
||||
|
||||
ubuntu@ubuntu:~$
|
||||
|
||||
#. This User VM and the Service VM are running different Ubuntu images. Use this
|
||||
command to see that the User VM is running the downloaded Ubuntu image:
|
||||
@ -730,7 +752,7 @@ Launch the User VM
|
||||
.. code-block:: console
|
||||
|
||||
acrn@ubuntu:~$ uname -r
|
||||
6.8.0-36-generic
|
||||
6.5.0-18-generic
|
||||
|
||||
Then open a new terminal window and use the command to see that the Service
|
||||
VM is running the ``acrn-kernel`` Service VM image:
|
||||
|
Before Width: | Height: | Size: 156 KiB |
Before Width: | Height: | Size: 101 KiB |
BIN
doc/getting-started/images/configurator_postvm02.png
Normal file
After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 418 KiB After Width: | Height: | Size: 84 KiB |
@ -117,7 +117,7 @@ As a normal (e.g., **acrn**) user, follow these steps:
|
||||
|
||||
cd ~/acrn-work/acrn-hypervisor
|
||||
git fetch --all
|
||||
git checkout release_3.2
|
||||
git checkout release_3.3
|
||||
|
||||
#. Build the ACRN sample application source code::
|
||||
|
||||
@ -522,6 +522,7 @@ Install and Run ACRN on the Target System
|
||||
|
||||
and then the ``histapp.py`` application::
|
||||
|
||||
pip install "numpy<2"
|
||||
sudo python3 /root/histapp.py
|
||||
|
||||
At this point, the HMI_VM is running and we've started the HMI parts of
|
||||
|
@ -74,52 +74,52 @@ level includes the activities described in the lower levels.
|
||||
|
||||
.. # Note For easier editing, I'm using unicode non-printing spaces in this table to help force the width of the first two columns to help prevent wrapping (using isn't compact enough)
|
||||
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| | | .. rst-class:: |
|
||||
| | | centered |
|
||||
| | | |
|
||||
| | | ACRN Version |
|
||||
| | +-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
|
||||
| Intel Processor Family | Tested Products | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| Code Name | | centered | centered | centered | centered | centered | centered | centered | centered | centered |
|
||||
| | | | | | | | | | | |
|
||||
| | | v1.0 | v1.6.1 | v2.0 | v2.5 | v2.6 | v2.7 | v3.0 | v3.1 | v3.2 |
|
||||
+========================+=================================+===================+===================+===================+===================+===================+===================+===================+===================+===================+
|
||||
| Raptor Lake | `ASUS PN64-E1`_ | | .. rst-class:: |
|
||||
| | | | centered |
|
||||
| | | | |
|
||||
| | | | Community |
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------+-------------------+-------------------+-------------------+
|
||||
| Alder Lake | | `ASRock iEPF-9010S-EY4`_, | | .. rst-class:: | .. rst-class:: |
|
||||
| | | `ASRock iEP-9010E`_ | | centered | centered |
|
||||
| | | | | |
|
||||
| | | | Release | Community |
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------+-------------------+---------------------------------------+
|
||||
| Tiger Lake | `Vecow SPC-7100`_ | | .. rst-class:: |
|
||||
| | | | centered |
|
||||
| | | | |
|
||||
| | | | Maintenance |
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------+-------------------+---------------------------------------+-----------------------------------------------------------+
|
||||
| Tiger Lake | `NUC11TNHi5`_ | | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered | centered |
|
||||
| | | | | | |
|
||||
| | | | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+---------------------------------------+-------------------+-------------------+-------------------+-------------------+-----------------------------------------------------------+
|
||||
| Whiskey Lake | `WHL-IPC-I5`_ | | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered | centered |
|
||||
| | | | | | |
|
||||
| | | | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------------------------------------------------------------------+
|
||||
| Kaby Lake | `NUC7i7DNHE`_ | | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered | centered |
|
||||
| | | | | | |
|
||||
| | | | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-------------------+-------------------+---------------------------------------+---------------------------------------------------------------------------------------------------+
|
||||
| Apollo Lake | | `NUC6CAYH`_, | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | `UP2-N3350`_, | centered | centered | centered |
|
||||
| | | `UP2-N4200`_, | | | |
|
||||
| | | `UP2-x5-E3940`_ | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| | | .. rst-class:: |
|
||||
| | | centered |
|
||||
| | | |
|
||||
| | | ACRN Version |
|
||||
| | +-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
|
||||
| Intel Processor Family | Tested Products | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| Code Name | | centered | centered | centered | centered | centered | centered | centered | centered | centered | centered |
|
||||
| | | | | | | | | | | | |
|
||||
| | | v1.0 | v1.6.1 | v2.0 | v2.5 | v2.6 | v2.7 | v3.0 | v3.1 | v3.2 | v3.3 |
|
||||
+========================+=================================+===================+===================+===================+===================+===================+===================+===================+===================+===================+===================+
|
||||
| Raptor Lake | `ASUS PN64-E1`_ | | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered |
|
||||
| | | | | |
|
||||
| | | | Community | Maintenance |
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------+-------------------+-------------------+-------------------+-------------------+
|
||||
| Alder Lake | | `ASRock iEPF-9010S-EY4`_, | | .. rst-class:: | .. rst-class:: |
|
||||
| | | `ASRock iEP-9010E`_ | | centered | centered |
|
||||
| | | | | |
|
||||
| | | | Release | Community |
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------+-------------------+---------------------------------------+-------------------+
|
||||
| Tiger Lake | `Vecow SPC-7100`_ | | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered |
|
||||
| | | | | |
|
||||
| | | | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-----------------------------------------------------------+-------------------+---------------------------------------+-----------------------------------------------------------+-------------------+
|
||||
| Tiger Lake | `NUC11TNHi5`_ | | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered | centered |
|
||||
| | | | | | |
|
||||
| | | | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+---------------------------------------+-------------------+-------------------+-------------------+-------------------+-------------------------------------------------------------------------------+
|
||||
| Whiskey Lake | `WHL-IPC-I5`_ | | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered | centered |
|
||||
| | | | | | |
|
||||
| | | | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-------------------+-------------------+-------------------+-------------------+-------------------+---------------------------------------------------------------------------------------------------+
|
||||
| Kaby Lake | `NUC7i7DNHE`_ | | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | | centered | centered | centered |
|
||||
| | | | | | |
|
||||
| | | | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-------------------+-------------------+---------------------------------------+-----------------------------------------------------------------------------------------------------------------------+
|
||||
| Apollo Lake | | `NUC6CAYH`_, | .. rst-class:: | .. rst-class:: | .. rst-class:: |
|
||||
| | | `UP2-N3350`_, | centered | centered | centered |
|
||||
| | | `UP2-N4200`_, | | | |
|
||||
| | | `UP2-x5-E3940`_ | Release | Maintenance | Community |
|
||||
+------------------------+---------------------------------+-------------------+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
* **Release**: New ACRN features are complete and tested for the listed product.
|
||||
This product is recommended for this ACRN version. Support for older products
|
||||
|
199
doc/release_notes/release_notes_3.3.rst
Executable file
@ -0,0 +1,199 @@
|
||||
.. _release_notes_3.3:
|
||||
|
||||
ACRN v3.3 (Aug 2024)
|
||||
####################
|
||||
|
||||
We are pleased to announce the release of the Project ACRN hypervisor
|
||||
version 3.3.
|
||||
|
||||
ACRN is a flexible, lightweight reference hypervisor that is built with
|
||||
real-time and safety-criticality in mind. It is optimized to streamline
|
||||
embedded development through an open-source platform. See the
|
||||
:ref:`introduction` introduction for more information.
|
||||
|
||||
All project ACRN source code is maintained in the
|
||||
https://github.com/projectacrn/acrn-hypervisor repository and includes
|
||||
folders for the ACRN hypervisor, the ACRN device model, tools, and
|
||||
documentation. You can download this source code either as a zip or
|
||||
tar.gz file (see the `ACRN v3.3 GitHub release page
|
||||
<https://github.com/projectacrn/acrn-hypervisor/releases/tag/v3.3>`_) or
|
||||
use Git ``clone`` and ``checkout`` commands::
|
||||
|
||||
git clone https://github.com/projectacrn/acrn-hypervisor
|
||||
cd acrn-hypervisor
|
||||
git checkout v3.3
|
||||
|
||||
The project's online technical documentation is also tagged to
|
||||
correspond with a specific release: generated v3.3 documents can be
|
||||
found at https://projectacrn.github.io/3.3/. Documentation for the
|
||||
latest development branch is found at https://projectacrn.github.io/latest/.
|
||||
|
||||
ACRN v3.3 requires Ubuntu 22.04. Follow the instructions in the
|
||||
:ref:`gsg` to get started with ACRN.
|
||||
|
||||
|
||||
What's New in v3.3
|
||||
******************
|
||||
|
||||
Generic Main VM Support
|
||||
The v3.3 release now supports a new scenario called "Main VM". A "Service VM"
|
||||
has two characteristics: (1) it is the default owner of physical resources
|
||||
and (2) it can invoke VM management hypercalls. This release adds support
|
||||
to configure a VM with only the physical resource ownership characteristic
|
||||
and calling this a "Main VM". An example scenario is a pre-launched TEE
|
||||
(Trusted Execution Environment) VM and a main REE (Rich Execution Environment)
|
||||
VM.
|
||||
|
||||
Enabling Celadon as User VM
|
||||
The acrn hypervisor now supports Celadon as User VM OS. Celadon is an
|
||||
open-source project by Intel that provides a reference software stack for Android
|
||||
on Intel architecture platforms, aiming to enable developers to optimize and test
|
||||
Android on Intel-based devices.
|
||||
|
||||
Virtual Processor Performance Controls (vHWP)
|
||||
The v3.3 release provides virtual HWP feature to a VM so that the VM can check
|
||||
hardware performance ranges and adjust performance levels for performance or
|
||||
power consumption.
|
||||
|
||||
Virtual Thermal Monitor and Software Controlled Clock Facilities
|
||||
This release is able to virtualize processor thermal sensors and
|
||||
controls for thermal management in VMs.
|
||||
|
||||
Hypervisor Runtime Core PM
|
||||
The v3.3 release enhances processor power management in the hypervisor
|
||||
at runtime to reduce power consumption when a core is idle.
|
||||
|
||||
Guest S3 Support
|
||||
The v3.3 release supports suspend-to-RAM of post-launched VMs running
|
||||
with OVMF.
|
||||
|
||||
System Performance Optimization - Virtio-blk Multi-Virtqueue Support
|
||||
This release optimizes the virtio-block backend performance by allowing
|
||||
multiple virtqueues between a frontend driver and the backend.
|
||||
|
||||
Notification of VM Events
|
||||
Emit events (such as RTC changes and power cycles) to the monitor socket for
|
||||
customizing further actions upon such events.
|
||||
|
||||
Enhance device model passthrough
|
||||
This release support passthrough PCI device with legacy interrupt, some ACPI device like
|
||||
GPIO controller, legacy UART.
|
||||
|
||||
ServiceVM supervisor role
|
||||
User can config ServicVM as supervisor role in result it can manage the power status of
|
||||
any guest VM.
|
||||
|
||||
|
||||
Upgrading to v3.3 from Previous Releases
|
||||
****************************************
|
||||
|
||||
We recommend you generate a new board XML for your target system with the v3.3
|
||||
Board Inspector. You should also use the v3.3 Configurator to generate a new
|
||||
scenario XML file and launch scripts. Scenario XML files and launch scripts
|
||||
created by previous ACRN versions will not work with the v3.3 ACRN hypervisor
|
||||
build process and could produce unexpected errors during the build.
|
||||
|
||||
Given the scope of changes for the v3.3 release, we have recommendations for how
|
||||
to upgrade from prior ACRN versions:
|
||||
|
||||
1. Start fresh from our :ref:`gsg`. This is the best way to ensure you have a
|
||||
v3.3-ready board XML file from your target system and generate a new scenario
|
||||
XML and launch scripts from the new ACRN Configurator that are consistent and
|
||||
will work for the v3.3 build system.
|
||||
#. Use the :ref:`upgrader tool <upgrading_configuration>` to attempt upgrading
|
||||
your configuration files that worked with prior releases. You'll need the
|
||||
matched pair of scenario XML and launch XML files from a prior configuration,
|
||||
and use them to create a new merged scenario XML file. See
|
||||
:ref:`upgrading_configuration` for details.
|
||||
#. Manually edit your previous older scenario XML and launch XML files to make them
|
||||
compatible with v3.3. This is not our recommended approach.
|
||||
|
||||
Here are some additional details about upgrading to the v3.3 release.
|
||||
|
||||
Generate New Board XML
|
||||
======================
|
||||
|
||||
Board XML files, generated by ACRN Board Inspector, contain board information
|
||||
that is essential for building the ACRN hypervisor and setting up User VMs.
|
||||
Compared to previous versions, ACRN v3.3 adds the following information to the
|
||||
board XML file for supporting new features and fixes:
|
||||
|
||||
* Fix typo in PCIe PTM Capability name (See :acrn-pr:`8607`)
|
||||
* Support motherboard which exposes MCFG1/MCFG2 instad of one ACPI MCFG
|
||||
table. (See :acrn-pr:`8513`)
|
||||
|
||||
See the :ref:`board_inspector_tool` documentation for a complete list of steps
|
||||
to install and run the tool.
|
||||
|
||||
Update Configuration Options
|
||||
============================
|
||||
|
||||
As explained in this :ref:`upgrading_configuration` document, we do provide a
|
||||
tool that can assist upgrading your existing pre-v3.3 scenario XML files in the
|
||||
new merged v3.3 format. From there, you can use the v3.3 ACRN Configurator UI to
|
||||
open the upgraded scenario file for viewing and further editing if the upgrader
|
||||
tool lost meaningful data during the conversion.
|
||||
|
||||
The ACRN Configurator adds the following features and fixes to improve the user
|
||||
experience:
|
||||
|
||||
* Support Main VM configuration. (See :acrn-pr:`8658`)
|
||||
* Change Service VM to supervisor role. (See :acrn-pr:`8630`)
|
||||
* Fix Vue3 version and update braces version (See :acrn-pr:`8627`)
|
||||
* Fix openssl's vulnerability for tauri (See :acrn-pr:`8670`)
|
||||
* Fix v-model used on props for Vue3 making strictly checking (See :acrn-pr:`8597`)
|
||||
* Support vUART two options in configurator (See :acrn-pr:`8649`)
|
||||
* Add checking cpu affinity and serial port for post-launch VM and hypervisor
|
||||
while the user click to append a new VM. (See :acrn-pr:`8602`)
|
||||
|
||||
See the :ref:`scenario-config-options` documentation for details about all the
|
||||
available configuration options in the new Configurator.
|
||||
|
||||
|
||||
Document Updates
|
||||
****************
|
||||
|
||||
Here are some of the more significant documentation updates from the v3.2 release:
|
||||
|
||||
.. rst-class:: rst-columns2
|
||||
|
||||
* :ref:`gsg`
|
||||
* :ref:`using_celadon_as_user_vm`
|
||||
* :ref:`release_notes_3.3`
|
||||
* :ref:`hv-config`
|
||||
* :ref:`acrn_configurator_tool`
|
||||
* :ref:`GSG_sample_app`
|
||||
* :ref:`acrnshell`
|
||||
|
||||
|
||||
Fixed Issues Details
|
||||
********************
|
||||
|
||||
.. comment example item
|
||||
- :acrn-issue:`5626` - Host Call Trace once detected
|
||||
|
||||
- :acrn-issue:`8608` - hybrid vcpuid support
|
||||
- :acrn-issue:`8590` - Hypervisor crashes after rebooting post-launched vm with passthrogh device for lots of times
|
||||
- :acrn-issue:`8599` - Should clear pcpu_active_bitmap in start_pcpu
|
||||
- :acrn-issue:`8590` - Hypervisor crashes after rebooting post-launched vm with passthrogh device for lots of times
|
||||
- :acrn-issue:`8576` - Update-grub failed with GRUB 2.12
|
||||
- :acrn-issue:`8518` - Initial boot log is lost in vm_console
|
||||
- :acrn-issue:`8509` - S3 feature of Service VM OS is not available
|
||||
- :acrn-issue:`8506` - Unable to passthrough USB device on bus 5 to guest
|
||||
- :acrn-issue:`8500` - Add weight support for BVT scheduler
|
||||
- :acrn-issue:`8495` - Service VM dead loops when booting up on platform with reserved memory as the last e820 entry
|
||||
- :acrn-issue:`8492` - passthru multifunction device at function 0 will cause sub-function devices lost
|
||||
- :acrn-issue:`8537` - Emulate COM3/4 in devicemodel
|
||||
- :acrn-issue:`8491` - need to expose service vm config pointer
|
||||
- :acrn-issue:`8579` - debian: fix broken grub config with grub 2.12
|
||||
- :acrn-issue:`6631` - Fix Kata support with modify network configuration
|
||||
|
||||
Known Issues
|
||||
************
|
||||
|
||||
- :acrn-issue:`6978` - openstack failed since ACRN v2.7
|
||||
- :acrn-issue:`7827` - Pre_launched standard VMs cannot share CPU with Service VM in configurator
|
||||
- :acrn-issue:`8471` - PTM enabling failure on i225 NIC
|
||||
- :acrn-issue:`8472` - Failed to clear memory for post-launched standard VM
|
||||
|
||||
|
@ -67,6 +67,9 @@ For the shared memory region:
|
||||
#. Enter a name for the shared memory region.
|
||||
#. Select the source of the emulation, either Hypervisor or Device Model.
|
||||
#. Select the size of the shared memory region.
|
||||
#. **Enter shared memory region ID, which can be in hexadecimal or decimal format**.
|
||||
.. note::
|
||||
Default value is 0 and IDs in 0x001 ~ 0xFFF are reserved, 0x1000 ~ 0xFFFF are available.
|
||||
#. Select at least two VMs that can use the shared memory region.
|
||||
#. Enter a virtual Board:Device.Function (BDF) address for each VM or leave it
|
||||
blank. If the field is blank, the tool provides an address when the
|
||||
@ -88,4 +91,4 @@ Learn More
|
||||
ACRN supports multiple inter-VM communication methods. For a comparison, see
|
||||
:ref:`inter-vm_communication`.
|
||||
|
||||
For details on ACRN IVSHMEM high-level design, see :ref:`ivshmem-hld`.
|
||||
For details on ACRN IVSHMEM high-level design, see :ref:`ivshmem-hld`.
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 65 KiB |
@ -65,7 +65,6 @@ static int32_t local_gva2gpa_common(struct acrn_vcpu *vcpu, const struct page_wa
|
||||
int32_t ret = 0;
|
||||
int32_t fault = 0;
|
||||
bool is_user_mode_addr = true;
|
||||
bool is_page_rw_flags_on = true;
|
||||
|
||||
if (pw_info->level < 1U) {
|
||||
ret = -EINVAL;
|
||||
@ -108,7 +107,6 @@ static int32_t local_gva2gpa_common(struct acrn_vcpu *vcpu, const struct page_wa
|
||||
* Case2: Usermode */
|
||||
fault = 1;
|
||||
}
|
||||
is_page_rw_flags_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,34 +140,8 @@ static int32_t local_gva2gpa_common(struct acrn_vcpu *vcpu, const struct page_wa
|
||||
*/
|
||||
/* if smap is enabled and supervisor-mode access */
|
||||
if ((fault == 0) && pw_info->is_smap_on && (!pw_info->is_user_mode_access) &&
|
||||
is_user_mode_addr) {
|
||||
bool acflag = ((vcpu_get_rflags(vcpu) & RFLAGS_AC) != 0UL);
|
||||
|
||||
/* read from user mode address, eflags.ac = 0 */
|
||||
if ((!pw_info->is_write_access) && (!acflag)) {
|
||||
fault = 1;
|
||||
} else if (pw_info->is_write_access) {
|
||||
/* write to user mode address */
|
||||
|
||||
/* cr0.wp = 0, eflags.ac = 0 */
|
||||
if ((!pw_info->wp) && (!acflag)) {
|
||||
fault = 1;
|
||||
}
|
||||
|
||||
/* cr0.wp = 1, eflags.ac = 1, r/w flag is 0
|
||||
* on any paging structure entry
|
||||
*/
|
||||
if (pw_info->wp && acflag && (!is_page_rw_flags_on)) {
|
||||
fault = 1;
|
||||
}
|
||||
|
||||
/* cr0.wp = 1, eflags.ac = 0 */
|
||||
if (pw_info->wp && (!acflag)) {
|
||||
fault = 1;
|
||||
}
|
||||
} else {
|
||||
/* do nothing */
|
||||
}
|
||||
is_user_mode_addr && ((vcpu_get_rflags(vcpu) & RFLAGS_AC) == 0UL)) {
|
||||
fault = 1;
|
||||
}
|
||||
|
||||
/* instruction fetch from user-mode address, smep on */
|
||||
|
@ -309,3 +309,14 @@ hyperv_init_vcpuid_entry(uint32_t leaf, uint32_t subleaf, uint32_t flags,
|
||||
dev_dbg(DBG_LEVEL_HYPERV, "hv: %s: leaf=%x subleaf=%x flags=%x eax=%x ebx=%x ecx=%x edx=%x",
|
||||
__func__, leaf, subleaf, flags, entry->eax, entry->ebx, entry->ecx, entry->edx);
|
||||
}
|
||||
|
||||
void
|
||||
hyperv_page_destory(struct acrn_vm *vm)
|
||||
{
|
||||
/* Reset the hypercall page */
|
||||
vm->arch_vm.hyperv.hypercall_page.enabled = 0U;
|
||||
/* Reset OS id */
|
||||
vm->arch_vm.hyperv.guest_os_id.val64 = 0UL;
|
||||
/* Reset the TSC page */
|
||||
vm->arch_vm.hyperv.ref_tsc_page.enabled = 0UL;
|
||||
}
|
||||
|
@ -120,66 +120,6 @@ static void init_vcpuid_entry(uint32_t leaf, uint32_t subleaf,
|
||||
entry->flags = flags;
|
||||
|
||||
switch (leaf) {
|
||||
case 0x07U:
|
||||
if (subleaf == 0U) {
|
||||
uint64_t cr4_reserved_mask = get_cr4_reserved_bits();
|
||||
|
||||
cpuid_subleaf(leaf, subleaf, &entry->eax, &entry->ebx, &entry->ecx, &entry->edx);
|
||||
|
||||
entry->ebx &= ~(CPUID_EBX_PQM | CPUID_EBX_PQE);
|
||||
|
||||
/* mask LA57 */
|
||||
entry->ecx &= ~CPUID_ECX_LA57;
|
||||
|
||||
/* mask SGX and SGX_LC */
|
||||
entry->ebx &= ~CPUID_EBX_SGX;
|
||||
entry->ecx &= ~CPUID_ECX_SGX_LC;
|
||||
|
||||
/* mask MPX */
|
||||
entry->ebx &= ~CPUID_EBX_MPX;
|
||||
|
||||
/* mask Intel Processor Trace, since 14h is disabled */
|
||||
entry->ebx &= ~CPUID_EBX_PROC_TRC;
|
||||
|
||||
/* mask CET shadow stack and indirect branch tracking */
|
||||
entry->ecx &= ~CPUID_ECX_CET_SS;
|
||||
entry->edx &= ~CPUID_EDX_CET_IBT;
|
||||
|
||||
if ((cr4_reserved_mask & CR4_FSGSBASE) != 0UL) {
|
||||
entry->ebx &= ~CPUID_EBX_FSGSBASE;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_SMEP) != 0UL) {
|
||||
entry->ebx &= ~CPUID_EBX_SMEP;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_SMAP) != 0UL) {
|
||||
entry->ebx &= ~CPUID_EBX_SMAP;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_UMIP) != 0UL) {
|
||||
entry->ecx &= ~CPUID_ECX_UMIP;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_PKE) != 0UL) {
|
||||
entry->ecx &= ~CPUID_ECX_PKE;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_LA57) != 0UL) {
|
||||
entry->ecx &= ~CPUID_ECX_LA57;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_PKS) != 0UL) {
|
||||
entry->ecx &= ~CPUID_ECX_PKS;
|
||||
}
|
||||
} else {
|
||||
entry->eax = 0U;
|
||||
entry->ebx = 0U;
|
||||
entry->ecx = 0U;
|
||||
entry->edx = 0U;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x16U:
|
||||
cpu_info = get_pcpu_info();
|
||||
if (cpu_info->cpuid_level >= 0x16U) {
|
||||
@ -480,6 +420,93 @@ static int32_t set_vcpuid_cache(struct acrn_vm *vm)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int32_t set_vcpuid_extfeat(struct acrn_vm *vm)
|
||||
{
|
||||
uint64_t cr4_reserved_mask = get_cr4_reserved_bits();
|
||||
int32_t result = 0;
|
||||
struct vcpuid_entry entry;
|
||||
uint32_t i, sub_leaves;
|
||||
|
||||
/* cpuid.07h.0h */
|
||||
cpuid_subleaf(CPUID_EXTEND_FEATURE, 0U, &entry.eax, &entry.ebx, &entry.ecx, &entry.edx);
|
||||
|
||||
entry.ebx &= ~(CPUID_EBX_PQM | CPUID_EBX_PQE);
|
||||
if (is_vsgx_supported(vm->vm_id)) {
|
||||
entry.ebx |= CPUID_EBX_SGX;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
if (is_vcat_configured(vm)) {
|
||||
/* Bit 15: Supports Intel Resource Director Technology (Intel RDT) Allocation capability if 1 */
|
||||
entry.ebx |= CPUID_EBX_PQE;
|
||||
}
|
||||
#endif
|
||||
/* mask LA57 */
|
||||
entry.ecx &= ~CPUID_ECX_LA57;
|
||||
|
||||
/* mask SGX and SGX_LC */
|
||||
entry.ebx &= ~CPUID_EBX_SGX;
|
||||
entry.ecx &= ~CPUID_ECX_SGX_LC;
|
||||
|
||||
/* mask MPX */
|
||||
entry.ebx &= ~CPUID_EBX_MPX;
|
||||
|
||||
/* mask Intel Processor Trace, since 14h is disabled */
|
||||
entry.ebx &= ~CPUID_EBX_PROC_TRC;
|
||||
|
||||
/* mask CET shadow stack and indirect branch tracking */
|
||||
entry.ecx &= ~CPUID_ECX_CET_SS;
|
||||
entry.edx &= ~CPUID_EDX_CET_IBT;
|
||||
|
||||
/* mask WAITPKG */
|
||||
entry.ecx &= ~CPUID_ECX_WAITPKG;
|
||||
|
||||
if ((cr4_reserved_mask & CR4_FSGSBASE) != 0UL) {
|
||||
entry.ebx &= ~CPUID_EBX_FSGSBASE;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_SMEP) != 0UL) {
|
||||
entry.ebx &= ~CPUID_EBX_SMEP;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_SMAP) != 0UL) {
|
||||
entry.ebx &= ~CPUID_EBX_SMAP;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_UMIP) != 0UL) {
|
||||
entry.ecx &= ~CPUID_ECX_UMIP;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_PKE) != 0UL) {
|
||||
entry.ecx &= ~CPUID_ECX_PKE;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_LA57) != 0UL) {
|
||||
entry.ecx &= ~CPUID_ECX_LA57;
|
||||
}
|
||||
|
||||
if ((cr4_reserved_mask & CR4_PKS) != 0UL) {
|
||||
entry.ecx &= ~CPUID_ECX_PKS;
|
||||
}
|
||||
|
||||
entry.leaf = CPUID_EXTEND_FEATURE;
|
||||
entry.subleaf = 0U;
|
||||
entry.flags = CPUID_CHECK_SUBLEAF;
|
||||
result = set_vcpuid_entry(vm, &entry);
|
||||
if (result == 0) {
|
||||
sub_leaves = entry.eax;
|
||||
for (i = 1U; i <= sub_leaves; i++) {
|
||||
cpuid_subleaf(CPUID_EXTEND_FEATURE, i, &entry.eax, &entry.ebx, &entry.ecx, &entry.edx);
|
||||
entry.subleaf = i;
|
||||
result = set_vcpuid_entry(vm, &entry);
|
||||
if (result != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void guest_cpuid_06h(struct acrn_vm *vm, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
cpuid_subleaf(CPUID_THERMAL_POWER, *ecx, eax, ebx, ecx, edx);
|
||||
@ -644,23 +671,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
|
||||
break;
|
||||
/* 0x07U */
|
||||
case CPUID_EXTEND_FEATURE:
|
||||
init_vcpuid_entry(i, 0U, CPUID_CHECK_SUBLEAF, &entry);
|
||||
if (entry.eax != 0U) {
|
||||
pr_warn("vcpuid: only support subleaf 0 for cpu leaf 07h");
|
||||
entry.eax = 0U;
|
||||
}
|
||||
if (is_vsgx_supported(vm->vm_id)) {
|
||||
entry.ebx |= CPUID_EBX_SGX;
|
||||
}
|
||||
entry.ecx &= ~CPUID_ECX_WAITPKG;
|
||||
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
if (is_vcat_configured(vm)) {
|
||||
/* Bit 15: Supports Intel Resource Director Technology (Intel RDT) Allocation capability if 1 */
|
||||
entry.ebx |= CPUID_EBX_PQE;
|
||||
}
|
||||
#endif
|
||||
result = set_vcpuid_entry(vm, &entry);
|
||||
result = set_vcpuid_extfeat(vm);
|
||||
break;
|
||||
/* 0x12U */
|
||||
case CPUID_SGX_CAP:
|
||||
|
@ -177,10 +177,8 @@ bool is_stateful_vm(const struct acrn_vm *vm)
|
||||
{
|
||||
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
|
||||
|
||||
/* TEE VM doesn't has its own state. The TAs will do the content
|
||||
* flush by themselves, HV and OS doesn't need to care about the state.
|
||||
*/
|
||||
return ((vm_config->guest_flags & GUEST_FLAG_TEE) == 0U);
|
||||
/* TEE VM has GUEST_FLAG_STATELESS set implicitly */
|
||||
return ((vm_config->guest_flags & GUEST_FLAG_STATELESS) == 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -959,6 +957,10 @@ int32_t shutdown_vm(struct acrn_vm *vm)
|
||||
offline_vcpu(vcpu);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HYPERV_ENABLED
|
||||
hyperv_page_destory(vm);
|
||||
#endif
|
||||
|
||||
/* after guest_flags not used, then clear it */
|
||||
vm_config = get_vm_config(vm->vm_id);
|
||||
vm_config->guest_flags &= ~DM_OWNED_GUEST_FLAG_MASK;
|
||||
@ -1087,7 +1089,6 @@ void resume_vm_from_s3(struct acrn_vm *vm, uint32_t wakeup_vec)
|
||||
start_vm(vm);
|
||||
}
|
||||
|
||||
static uint8_t loaded_pre_vm_nr = 0U;
|
||||
/**
|
||||
* Prepare to create vm/vcpu for vm
|
||||
*
|
||||
@ -1095,7 +1096,7 @@ static uint8_t loaded_pre_vm_nr = 0U;
|
||||
*/
|
||||
int32_t prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config)
|
||||
{
|
||||
int32_t err = 0;
|
||||
int32_t err = -1;
|
||||
struct acrn_vm *vm = NULL;
|
||||
|
||||
#ifdef CONFIG_SECURITY_VM_FIXUP
|
||||
@ -1103,41 +1104,15 @@ int32_t prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config)
|
||||
#endif
|
||||
if (get_vmid_by_name(vm_config->name) != vm_id) {
|
||||
pr_err("Invalid VM name: %s", vm_config->name);
|
||||
err = -1;
|
||||
} else {
|
||||
/* Service VM and pre-launched VMs launch on all pCPUs defined in vm_config->cpu_affinity */
|
||||
err = create_vm(vm_id, vm_config->cpu_affinity, vm_config, &vm);
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
if (is_prelaunched_vm(vm)) {
|
||||
build_vrsdp(vm);
|
||||
}
|
||||
|
||||
if (is_service_vm(vm)) {
|
||||
/* We need to ensure all modules of pre-launched VMs have been loaded already
|
||||
* before loading Service VM modules, otherwise the module of pre-launched VMs could
|
||||
* be corrupted because Service VM kernel might pick any usable RAM to extract kernel
|
||||
* when KASLR enabled.
|
||||
* In case the pre-launched VMs aren't loaded successfuly that cause deadlock here,
|
||||
* use a 10000ms timer to break the waiting loop.
|
||||
*/
|
||||
uint64_t start_tick = cpu_ticks();
|
||||
|
||||
while (loaded_pre_vm_nr != PRE_VM_NUM) {
|
||||
uint64_t timeout = ticks_to_ms(cpu_ticks() - start_tick);
|
||||
|
||||
if (timeout > 10000U) {
|
||||
pr_err("Loading pre-launched VMs timeout!");
|
||||
break;
|
||||
}
|
||||
if (err == 0) {
|
||||
if (is_prelaunched_vm(vm)) {
|
||||
build_vrsdp(vm);
|
||||
}
|
||||
}
|
||||
|
||||
err = prepare_os_image(vm);
|
||||
|
||||
if (is_prelaunched_vm(vm)) {
|
||||
loaded_pre_vm_nr++;
|
||||
err = prepare_os_image(vm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,16 +73,13 @@ static bool handle_reset_reg_read(struct acrn_vcpu *vcpu, __unused uint16_t addr
|
||||
__unused size_t bytes)
|
||||
{
|
||||
bool ret = true;
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
|
||||
if (is_postlaunched_vm(vcpu->vm)) {
|
||||
if (is_postlaunched_vm(vm)) {
|
||||
/* re-inject to DM */
|
||||
ret = false;
|
||||
} else {
|
||||
/*
|
||||
* - reset control register 0xcf9: hide this from guests for now.
|
||||
* - FADT reset register: the read behavior is not defined in spec, keep it simple to return all '1'.
|
||||
*/
|
||||
vcpu->req.reqs.pio_request.value = ~0U;
|
||||
vcpu->req.reqs.pio_request.value = vm->reset_control;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -91,7 +88,7 @@ static bool handle_reset_reg_read(struct acrn_vcpu *vcpu, __unused uint16_t addr
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset)
|
||||
static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset, bool warm)
|
||||
{
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
bool ret = true;
|
||||
@ -101,7 +98,7 @@ static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset)
|
||||
poweroff_if_rt_vm(vm);
|
||||
|
||||
if (get_highest_severity_vm(true) == vm) {
|
||||
reset_host();
|
||||
reset_host(warm);
|
||||
} else if (is_postlaunched_vm(vm)) {
|
||||
/* re-inject to DM */
|
||||
ret = false;
|
||||
@ -138,7 +135,7 @@ static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset)
|
||||
static bool handle_kb_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, size_t bytes, uint32_t val)
|
||||
{
|
||||
/* ignore commands other than system reset */
|
||||
return handle_common_reset_reg_write(vcpu, ((bytes == 1U) && (val == 0xfeU)));
|
||||
return handle_common_reset_reg_write(vcpu, ((bytes == 1U) && (val == 0xfeU)), false);
|
||||
}
|
||||
|
||||
static bool handle_kb_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes)
|
||||
@ -168,9 +165,12 @@ static bool handle_kb_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes)
|
||||
*/
|
||||
static bool handle_cf9_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, size_t bytes, uint32_t val)
|
||||
{
|
||||
/* We don't differentiate among hard/soft/warm/cold reset */
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
|
||||
vm->reset_control = val & 0xeU;
|
||||
return handle_common_reset_reg_write(vcpu,
|
||||
((bytes == 1U) && ((val & 0x4U) == 0x4U) && ((val & 0xaU) != 0U)));
|
||||
((bytes == 1U) && ((val & 0x4U) == 0x4U) && ((val & 0xaU) != 0U)),
|
||||
((val & 0x8U) == 0U));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,7 +185,7 @@ static bool handle_reset_reg_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t
|
||||
struct acpi_reset_reg *reset_reg = get_host_reset_reg_data();
|
||||
|
||||
if (val == reset_reg->val) {
|
||||
ret = handle_common_reset_reg_write(vcpu, true);
|
||||
ret = handle_common_reset_reg_write(vcpu, true, false);
|
||||
} else {
|
||||
/*
|
||||
* ACPI defines the reset value but doesn't specify the meaning of other values.
|
||||
|
@ -257,7 +257,7 @@ static int32_t dispatch_hypercall(struct acrn_vcpu *vcpu)
|
||||
*/
|
||||
int32_t vmcall_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
int32_t ret;
|
||||
int32_t ret = -EACCES;
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
/* hypercall ID from guest*/
|
||||
uint64_t hypcall_id = vcpu_get_gpreg(vcpu, CPU_REG_R8);
|
||||
@ -275,17 +275,13 @@ int32_t vmcall_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
*/
|
||||
if (!is_service_vm(vm) && !is_guest_hypercall(vm)) {
|
||||
vcpu_inject_ud(vcpu);
|
||||
ret = -ENODEV;
|
||||
} else if (!is_hypercall_from_ring0()) {
|
||||
vcpu_inject_gp(vcpu, 0U);
|
||||
ret = -EACCES;
|
||||
} else {
|
||||
ret = dispatch_hypercall(vcpu);
|
||||
}
|
||||
|
||||
if ((ret != -EACCES) && (ret != -ENODEV)) {
|
||||
vcpu_set_gpreg(vcpu, CPU_REG_RAX, (uint64_t)ret);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("ret=%d hypercall=0x%lx failed in %s\n", ret, hypcall_id, __func__);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 NetApp, Inc.
|
||||
* Copyright (c) 2017-2022 Intel Corporation.
|
||||
* Copyright (c) 2017-2024 Intel Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -41,6 +41,11 @@
|
||||
|
||||
static uint64_t hv_ram_size;
|
||||
static void *ppt_mmu_pml4_addr;
|
||||
/**
|
||||
* @brief The sanitized page
|
||||
*
|
||||
* The sanitized page is used to mitigate l1tf.
|
||||
*/
|
||||
static uint8_t sanitized_page[PAGE_SIZE] __aligned(PAGE_SIZE);
|
||||
|
||||
/* PPT VA and PA are identical mapping */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation.
|
||||
* Copyright (C) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -8,6 +8,19 @@
|
||||
#include <asm/page.h>
|
||||
#include <logmsg.h>
|
||||
|
||||
/**
|
||||
* @addtogroup hwmgmt_page
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of page management.
|
||||
*
|
||||
* This file provides the core functionality required for allocating and freeing memory pages. It's a fundamental
|
||||
* support to manage memory resources.
|
||||
*/
|
||||
|
||||
struct page *alloc_page(struct page_pool *pool)
|
||||
{
|
||||
@ -57,3 +70,7 @@ void free_page(struct page_pool *pool, struct page *page)
|
||||
bitmap_clear_nolock(bit, pool->bitmap + idx);
|
||||
spinlock_release(&pool->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation.
|
||||
* Copyright (C) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -11,8 +11,29 @@
|
||||
#include <asm/mmu.h>
|
||||
#include <logmsg.h>
|
||||
|
||||
/**
|
||||
* @addtogroup hwmgmt_page
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation page table management.
|
||||
*
|
||||
* This file implements the external APIs to establish, modify, delete, or look for the mapping information. It also
|
||||
* defines some helper functions to implement the features that are commonly used in this file.
|
||||
*
|
||||
*/
|
||||
|
||||
#define DBG_LEVEL_MMU 6U
|
||||
|
||||
/**
|
||||
* @brief Host physical address of the sanitized page.
|
||||
*
|
||||
* The sanitized page is used to mitigate l1tf. This variable is used to store the host physical address of the
|
||||
* sanitized page.
|
||||
*/
|
||||
static uint64_t sanitized_page_hpa;
|
||||
|
||||
static void sanitize_pte_entry(uint64_t *ptep, const struct pgtable *table)
|
||||
@ -28,6 +49,26 @@ static void sanitize_pte(uint64_t *pt_page, const struct pgtable *table)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes a sanitized page.
|
||||
*
|
||||
* This function is responsible for initializing a sanitized page. It sets the page table entries in this sanitized page
|
||||
* to point to the host physical address of the sanitized page itself.
|
||||
*
|
||||
* The static variable 'sanitized_page_hpa' will be set and the `sanitized_page` will be initialized.
|
||||
*
|
||||
* @param[out] sanitized_page The page to be sanitized.
|
||||
* @param[in] hpa The host physical address that the page table entries in the sanitized page will point to.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre sanitized_page != NULL
|
||||
* @pre ((uint64_t)sanitized_page & (PAGE_SIZE - 1)) == 0x0U
|
||||
* @pre hpa != 0U
|
||||
* @pre (hpa & (PAGE_SIZE - 1)) == 0x0U
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void init_sanitized_page(uint64_t *sanitized_page, uint64_t hpa)
|
||||
{
|
||||
uint64_t i;
|
||||
@ -256,18 +297,62 @@ static void modify_or_del_pdpte(const uint64_t *pml4e, uint64_t vaddr_start, uin
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* type: MR_MODIFY
|
||||
* modify [vaddr, vaddr + size ) memory type or page access right.
|
||||
* prot_clr - memory type or page access right want to be clear
|
||||
* prot_set - memory type or page access right want to be set
|
||||
* @pre: the prot_set and prot_clr should set before call this function.
|
||||
* If you just want to modify access rights, you can just set the prot_clr
|
||||
* to what you want to set, prot_clr to what you want to clear. But if you
|
||||
* want to modify the MT, you should set the prot_set to what MT you want
|
||||
* to set, prot_clr to the MT mask.
|
||||
* type: MR_DEL
|
||||
* delete [vaddr_base, vaddr_base + size ) memory region page table mapping.
|
||||
/**
|
||||
* @brief Modify or delete the mappings associated with the specified address range.
|
||||
*
|
||||
* This function modifies the properties of an existing mapping or deletes it entirely from the page table. The input
|
||||
* address range is specified by [vaddr_base, vaddr_base + size). It is used when changing the access permissions of a
|
||||
* memory region or when freeing a previously mapped region. This operation is critical for dynamic memory management,
|
||||
* allowing the system to adapt to changes in memory usage patterns or to reclaim resources.
|
||||
*
|
||||
* For error case behaviors:
|
||||
* - If the 'type' is MR_MODIFY and any page referenced by the PML4E in the specified address range is not present, the
|
||||
* function asserts that the operation is invalid.
|
||||
* For normal case behaviors(when the error case conditions are not satisfied):
|
||||
* - If any page referenced by the PDPTE/PDE/PTE in the specified address range is not present, there is no change to
|
||||
* the corresponding mapping and it continues the operation.
|
||||
* - If any PDPTE/PDE in the specified address range maps a large page and the large page address exceeds the specified
|
||||
* address range, the function splits the large page into next level page to allow for the modification or deletion of
|
||||
* the mappings and the execute right will be recovered by the callback function table->recover_exe_right() when a 2MB
|
||||
* page is split to 4KB pages.
|
||||
* - If the 'type' is MR_MODIFY, the function modifies the properties of the existing mapping to match the specified
|
||||
* properties.
|
||||
* - If the 'type' is MR_DEL, the function will set corresponding page table entries to point to the sanitized page.
|
||||
*
|
||||
* @param[inout] pml4_page A pointer to the specified PML4 table.
|
||||
* @param[in] vaddr_base The specified input address determining the start of the input address range whose mapping
|
||||
* information is to be updated.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
* @param[in] size The size of the specified input address range whose mapping information is to be updated.
|
||||
* @param[in] prot_set Bit positions representing the specified properties which need to be set.
|
||||
* Bits specified by prot_clr are cleared before each bit specified by prot_set is set to 1.
|
||||
* @param[in] prot_clr Bit positions representing the specified properties which need to be cleared.
|
||||
* Bits specified by prot_clr are cleared before each bit specified by prot_set is set to 1.
|
||||
* @param[in] table A pointer to the struct pgtable containing the information of the specified memory operations.
|
||||
* @param[in] type The type of operation to perform (MR_MODIFY or MR_DEL).
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre pml4_page != NULL
|
||||
* @pre table != NULL
|
||||
* @pre (type == MR_MODIFY) || (type == MR_DEL)
|
||||
* @pre For x86 hypervisor, the following conditions shall be met if "type == MR_MODIFY".
|
||||
* - (prot_set & ~(PAGE_RW | PAGE_USER | PAGE_PWT | PAGE_PCD | PAGE_ACCESSED | PAGE_DIRTY | PAGE_PSE | PAGE_GLOBAL
|
||||
* | PAGE_PAT_LARGE | PAGE_NX) == 0)
|
||||
* - (prot_clr & ~(PAGE_RW | PAGE_USER | PAGE_PWT | PAGE_PCD | PAGE_ACCESSED | PAGE_DIRTY | PAGE_PSE | PAGE_GLOBAL
|
||||
* | PAGE_PAT_LARGE | PAGE_NX) == 0)
|
||||
* @pre For the VM EPT mappings, the following conditions shall be met if "type == MR_MODIFY".
|
||||
* - (prot_set & ~(EPT_RD | EPT_WR | EPT_EXE | EPT_MT_MASK) == 0)
|
||||
* - (prot_set & EPT_MT_MASK) == EPT_UNCACHED || (prot_set & EPT_MT_MASK) == EPT_WC ||
|
||||
* (prot_set & EPT_MT_MASK) == EPT_WT || (prot_set & EPT_MT_MASK) == EPT_WP || (prot_set & EPT_MT_MASK) == EPT_WB
|
||||
* - (prot_clr & ~(EPT_RD | EPT_WR | EPT_EXE | EPT_MT_MASK) == 0)
|
||||
* - (prot_clr & EPT_MT_MASK) == EPT_UNCACHED || (prot_clr & EPT_MT_MASK) == EPT_WC ||
|
||||
* (prot_clr & EPT_MT_MASK) == EPT_WT || (prot_clr & EPT_MT_MASK) == EPT_WP || (prot_clr & EPT_MT_MASK) == EPT_WB
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
void pgtable_modify_or_del_map(uint64_t *pml4_page, uint64_t vaddr_base, uint64_t size,
|
||||
uint64_t prot_set, uint64_t prot_clr, const struct pgtable *table, uint32_t type)
|
||||
@ -422,10 +507,46 @@ static void add_pdpte(const uint64_t *pml4e, uint64_t paddr_start, uint64_t vadd
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* action: MR_ADD
|
||||
* add [vaddr_base, vaddr_base + size ) memory region page table mapping.
|
||||
* @pre: the prot should set before call this function.
|
||||
/**
|
||||
* @brief Add new page table mappings.
|
||||
*
|
||||
* This function maps a virtual address range specified by [vaddr_base, vaddr_base + size) to a physical address range
|
||||
* starting from 'paddr_base'.
|
||||
*
|
||||
* - If any subrange within [vaddr_base, vaddr_base + size) is already mapped, there is no change to the corresponding
|
||||
* mapping and it continues the operation.
|
||||
* - When a new 1GB or 2MB mapping is established, the callback function table->tweak_exe_right() is invoked to tweak
|
||||
* the execution bit.
|
||||
* - When a new page table referenced by a new PDPTE/PDE is created, all entries in the page table are initialized to
|
||||
* point to the sanitized page by default.
|
||||
* - Finally, the new mappings are established and initialized according to the specified address range and properties.
|
||||
*
|
||||
* @param[inout] pml4_page A pointer to the specified PML4 table hierarchy.
|
||||
* @param[in] paddr_base The specified physical address determining the start of the physical memory region.
|
||||
* It is the host physical address.
|
||||
* @param[in] vaddr_base The specified input address determining the start of the input address space.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
* @param[in] size The size of the specified input address space.
|
||||
* @param[in] prot Bit positions representing the specified properties which need to be set.
|
||||
* @param[in] table A pointer to the struct pgtable containing the information of the specified memory operations.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre pml4_page != NULL
|
||||
* @pre Any subrange within [vaddr_base, vaddr_base + size) shall already be unmapped.
|
||||
* @pre For x86 hypervisor mapping, the following condition shall be met.
|
||||
* - prot & ~(PAGE_PRESENT| PAGE_RW | PAGE_USER | PAGE_PWT | PAGE_PCD | PAGE_ACCESSED | PAGE_DIRTY | PAGE_PSE |
|
||||
* PAGE_GLOBAL | PAGE_PAT_LARGE | PAGE_NX) == 0
|
||||
* @pre For VM EPT mapping, the following conditions shall be met.
|
||||
* - prot & ~(EPT_RD | EPT_WR | EPT_EXE | EPT_MT_MASK | EPT_IGNORE_PAT) == 0
|
||||
* - (prot & EPT_MT_MASK) == EPT_UNCACHED || (prot & EPT_MT_MASK) == EPT_WC || (prot & EPT_MT_MASK) == EPT_WT ||
|
||||
* (prot & EPT_MT_MASK) == EPT_WP || (prot & EPT_MT_MASK) == EPT_WB
|
||||
* @pre table != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
void pgtable_add_map(uint64_t *pml4_page, uint64_t paddr_base, uint64_t vaddr_base,
|
||||
uint64_t size, uint64_t prot, const struct pgtable *table)
|
||||
@ -455,6 +576,24 @@ void pgtable_add_map(uint64_t *pml4_page, uint64_t paddr_base, uint64_t vaddr_ba
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new root page table.
|
||||
*
|
||||
* This function initializes and returns a new root page table. It is typically used during the setup of a new execution
|
||||
* context, such as initializing a hypervisor PML4 table or creating a virtual machine. The root page table is essential
|
||||
* for defining the virtual memory layout for the context.
|
||||
*
|
||||
* It creates a new root page table and every entries in the page table are initialized to point to the sanitized page.
|
||||
* Finally, the function returns the root page table pointer.
|
||||
*
|
||||
* @param[in] table A pointer to the struct pgtable containing the information of the specified memory operations.
|
||||
*
|
||||
* @return A pointer to the newly created root page table.
|
||||
*
|
||||
* @pre table != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void *pgtable_create_root(const struct pgtable *table)
|
||||
{
|
||||
uint64_t *page = (uint64_t *)alloc_page(table->pool);
|
||||
@ -462,6 +601,31 @@ void *pgtable_create_root(const struct pgtable *table)
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a root page table for Secure World.
|
||||
*
|
||||
* This function initializes a new root page table for Secure World. It is intended to be used during the initialization
|
||||
* phase of Trusty, setting up isolated memory regions for secure execution. Secure world can access Normal World's
|
||||
* memory, but Normal World cannot access Secure World's memory. The PML4T/PDPT for Secure World are separated from
|
||||
* Normal World. PDT/PT are shared in both Secure World's EPT and Normal World's EPT. So this function copies the PDPTEs
|
||||
* from the Normal World to the Secure World.
|
||||
*
|
||||
* - It creates a new root page table and every entries are initialized to point to the sanitized page by default.
|
||||
* - The access right specified by prot_clr is cleared for Secure World PDPTEs.
|
||||
* - Finally, the function returns the new root page table pointer.
|
||||
*
|
||||
* @param[in] table A pointer to the struct pgtable containing the information of the specified memory operations.
|
||||
* @param[in] nworld_pml4_page A pointer to pml4 table hierarchy in Normal World.
|
||||
* @param[in] prot_table_present Mask indicating the page referenced is present.
|
||||
* @param[in] prot_clr Bit positions representing the specified properties which need to be cleared.
|
||||
*
|
||||
* @return A pointer to the newly created root page table for Secure World.
|
||||
*
|
||||
* @pre table != NULL
|
||||
* @pre nworld_pml4_page != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void *pgtable_create_trusty_root(const struct pgtable *table,
|
||||
void *nworld_pml4_page, uint64_t prot_table_present, uint64_t prot_clr)
|
||||
{
|
||||
@ -474,7 +638,7 @@ void *pgtable_create_trusty_root(const struct pgtable *table,
|
||||
* Secure world can access Normal World's memory,
|
||||
* but Normal World can not access Secure World's memory.
|
||||
* The PML4/PDPT for Secure world are separated from
|
||||
* Normal World.PD/PT are shared in both Secure world's EPT
|
||||
* Normal World. PD/PT are shared in both Secure world's EPT
|
||||
* and Normal World's EPT
|
||||
*/
|
||||
pml4_base = pgtable_create_root(table);
|
||||
@ -508,7 +672,39 @@ void *pgtable_create_trusty_root(const struct pgtable *table,
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre (pml4_page != NULL) && (pg_size != NULL)
|
||||
* @brief Look for the paging-structure entry that contains the mapping information for the specified input address.
|
||||
*
|
||||
* This function looks for the paging-structure entry that contains the mapping information for the specified input
|
||||
* address of the translation process. It is used to search the page table hierarchy for the entry corresponding to the
|
||||
* given virtual address. The function traverses the page table hierarchy from the PML4 down to the appropriate page
|
||||
* table level, returning the entry if found.
|
||||
*
|
||||
* - If specified address is mapped in the page table hierarchy, it will return a pointer to the page table entry that
|
||||
* maps the specified address.
|
||||
* - If the specified address is not mapped in the page table hierarchy, it will return NULL.
|
||||
*
|
||||
* @param[in] pml4_page A pointer to the specified PML4 table hierarchy.
|
||||
* @param[in] addr The specified input address whose mapping information is to be searched.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
* @param[out] pg_size A pointer to the size of the page controlled by the returned paging-structure entry.
|
||||
* @param[in] table A pointer to the struct pgtable which provides the page pool and callback functions to be used when
|
||||
* creating the new page.
|
||||
*
|
||||
* @return A pointer to the paging-structure entry that maps the specified input address.
|
||||
*
|
||||
* @retval non-NULL There is a paging-structure entry that contains the mapping information for the specified input
|
||||
* address.
|
||||
* @retval NULL There is no paging-structure entry that contains the mapping information for the specified input
|
||||
* address.
|
||||
*
|
||||
* @pre pml4_page != NULL
|
||||
* @pre pg_size != NULL
|
||||
* @pre table != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
const uint64_t *pgtable_lookup_entry(uint64_t *pml4_page, uint64_t addr, uint64_t *pg_size, const struct pgtable *table)
|
||||
{
|
||||
@ -548,3 +744,7 @@ const uint64_t *pgtable_lookup_entry(uint64_t *pml4_page, uint64_t addr, uint64_
|
||||
|
||||
return pret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -244,10 +244,10 @@ void host_enter_s3(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_
|
||||
resume_console();
|
||||
}
|
||||
|
||||
void reset_host(void)
|
||||
void reset_host(bool warm)
|
||||
{
|
||||
struct acrn_acpi_generic_address *gas = &(host_reset_reg.reg);
|
||||
|
||||
uint8_t reboot_code = warm ? CF9_RESET_WARM : CF9_RESET_COLD;
|
||||
|
||||
/* TODO: gracefully shut down all guests before doing host reset. */
|
||||
|
||||
@ -256,11 +256,6 @@ void reset_host(void)
|
||||
* The platform we are running must support at least one of reset method:
|
||||
* - ACPI reset
|
||||
* - 0xcf9 reset
|
||||
*
|
||||
* UEFI more likely sets the reset value as 0x6 (not 0xe) for 0xcf9 port.
|
||||
* This asserts PLTRST# to reset devices on the platform, but not the
|
||||
* SLP_S3#/4#/5# signals, which power down the systems. This might not be
|
||||
* enough for us.
|
||||
*/
|
||||
if ((gas->space_id == SPACE_SYSTEM_IO) &&
|
||||
(gas->bit_width == 8U) && (gas->bit_offset == 0U) &&
|
||||
@ -270,7 +265,8 @@ void reset_host(void)
|
||||
/* making sure bit 2 (RST_CPU) is '0', when the reset command is issued. */
|
||||
pio_write8(0x2U, 0xcf9U);
|
||||
udelay(50U);
|
||||
pio_write8(0xeU, 0xcf9U);
|
||||
pio_write8(reboot_code, 0xcf9U);
|
||||
udelay(50U);
|
||||
}
|
||||
|
||||
pr_fatal("%s(): can't reset host.", __func__);
|
||||
|
@ -156,30 +156,30 @@ struct intr_remap_table {
|
||||
struct page tables[MAX_IR_ENTRIES/DMAR_NUM_IR_ENTRIES_PER_PAGE];
|
||||
};
|
||||
|
||||
static struct page root_tables[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
static inline uint8_t *get_root_table(uint32_t dmar_index)
|
||||
{
|
||||
static struct page root_tables[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
return root_tables[dmar_index].contents;
|
||||
}
|
||||
|
||||
static struct context_table ctx_tables[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
static inline uint8_t *get_ctx_table(uint32_t dmar_index, uint8_t bus_no)
|
||||
{
|
||||
static struct context_table ctx_tables[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
return ctx_tables[dmar_index].buses[bus_no].contents;
|
||||
}
|
||||
|
||||
/*
|
||||
* @pre dmar_index < CONFIG_MAX_IOMMU_NUM
|
||||
*/
|
||||
static struct page qi_queues[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
static inline void *get_qi_queue(uint32_t dmar_index)
|
||||
{
|
||||
static struct page qi_queues[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
return (void *)qi_queues[dmar_index].contents;
|
||||
}
|
||||
|
||||
static struct intr_remap_table ir_tables[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
static inline void *get_ir_table(uint32_t dmar_index)
|
||||
{
|
||||
static struct intr_remap_table ir_tables[CONFIG_MAX_IOMMU_NUM] __aligned(PAGE_SIZE);
|
||||
return (void *)ir_tables[dmar_index].tables[0].contents;
|
||||
}
|
||||
|
||||
@ -1158,9 +1158,9 @@ static void do_action_for_iommus(void (*action)(struct dmar_drhd_rt *))
|
||||
}
|
||||
}
|
||||
|
||||
static struct iommu_domain iommu_domains[MAX_DOMAIN_NUM];
|
||||
struct iommu_domain *create_iommu_domain(uint16_t vm_id, uint64_t translation_table, uint32_t addr_width)
|
||||
{
|
||||
static struct iommu_domain iommu_domains[MAX_DOMAIN_NUM];
|
||||
struct iommu_domain *domain;
|
||||
|
||||
/* TODO: check if a domain with the vm_id exists */
|
||||
|
@ -61,7 +61,7 @@ static void *get_initrd_load_addr(struct acrn_vm *vm, uint64_t kernel_start)
|
||||
kernel_init_size = zeropage->hdr.init_size;
|
||||
kernel_align = zeropage->hdr.kernel_alignment;
|
||||
initrd_addr_max = zeropage->hdr.initrd_addr_max;
|
||||
stac();
|
||||
clac();
|
||||
kernel_end = roundup(kernel_start, kernel_align) + kernel_init_size;
|
||||
|
||||
if (initrd_addr_max != 0U) {
|
||||
|
@ -109,7 +109,8 @@ static void *do_load_elf64(struct acrn_vm *vm)
|
||||
*/
|
||||
(void)copy_to_gpa(vm, p_elf_img + p_prg_tbl_head64->p_offset,
|
||||
p_prg_tbl_head64->p_paddr, (uint32_t)p_prg_tbl_head64->p_filesz);
|
||||
/* copy_to_gpa has it's stac/clac inside. So call stac again here. */
|
||||
/* copy_to_gpa has its own stac/clac inside. Call stac again here to keep
|
||||
* the context. */
|
||||
stac();
|
||||
}
|
||||
p_prg_tbl_head64++;
|
||||
@ -174,7 +175,8 @@ static void *do_load_elf32(struct acrn_vm *vm)
|
||||
*/
|
||||
(void)copy_to_gpa(vm, p_elf_img + p_prg_tbl_head32->p_offset,
|
||||
p_prg_tbl_head32->p_paddr, p_prg_tbl_head32->p_filesz);
|
||||
/* copy_to_gpa has it's stac/clac inside. So call stac again here. */
|
||||
/* copy_to_gpa has its own stac/clac inside. Call stac again here to keep
|
||||
* the context. */
|
||||
stac();
|
||||
}
|
||||
p_prg_tbl_head32++;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef MULTIBOOT_PRIV_H
|
||||
#define MULTIBOOT_PRIV_H
|
||||
|
||||
#include <multiboot_std.h>
|
||||
|
||||
#ifdef CONFIG_MULTIBOOT2
|
||||
/*
|
||||
* @post boot_regs[1] stores the address pointer that point to a valid multiboot2 info
|
||||
|
@ -1102,7 +1102,7 @@ int32_t hcall_get_cpu_pm_state(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm
|
||||
int32_t ret = -1;
|
||||
uint64_t cmd = param1;
|
||||
|
||||
if (is_created_vm(target_vm)) {
|
||||
if (is_created_vm(target_vm) || is_paused_vm(target_vm)) {
|
||||
switch (cmd & PMCMD_TYPE_MASK) {
|
||||
case ACRN_PMCMD_GET_PX_CNT: {
|
||||
uint8_t px_cnt;
|
||||
|
@ -1531,7 +1531,7 @@ static int32_t shell_cpuid(int32_t argc, char **argv)
|
||||
|
||||
static int32_t shell_reboot(__unused int32_t argc, __unused char **argv)
|
||||
{
|
||||
reset_host();
|
||||
reset_host(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Intel Corporation.
|
||||
* Copyright (C) 2020-2024 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -14,6 +14,20 @@
|
||||
#include <ivshmem_cfg.h>
|
||||
#include "vpci_priv.h"
|
||||
|
||||
/**
|
||||
* @addtogroup vp-dm_vperipheral
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of Inter-VM shared memory device (ivshmem).
|
||||
*
|
||||
* This file defines marcos, data structure and functions to support ivshmem devices. It also implements necessary
|
||||
* functions to model a ivshmem device as a PCI device.
|
||||
*/
|
||||
|
||||
/* config space of ivshmem device */
|
||||
#define IVSHMEM_CLASS 0x05U
|
||||
#define IVSHMEM_REV 0x01U
|
||||
@ -69,6 +83,25 @@ struct ivshmem_device {
|
||||
static struct ivshmem_device ivshmem_dev[IVSHMEM_DEV_NUM];
|
||||
static spinlock_t ivshmem_dev_lock = { .head = 0U, .tail = 0U, };
|
||||
|
||||
/**
|
||||
* @brief Initialize the shared memory regions for all ivshmem devices.
|
||||
*
|
||||
* An ivshmem device is used to transfer data between VMs based on shared memory region. Basic ivshmem information is
|
||||
* configured in scenario file. After compilation, every shared memory region is stored in struct ivshmem_shm_region.
|
||||
* This function initializes all shared memory regions for ivshmem devices and it is usually called before all VMs are
|
||||
* created.
|
||||
*
|
||||
* IVSHMEM_SHM_SIZE is the sum of all ivshmem shared memory regions in bytes. It rounds IVSHMEM_SHM_SIZE up to PDE_SIZE
|
||||
* (1 GiB) and allocates a contiguous block of memory for these memory regions from host e820. For detailed allocation
|
||||
* operations, refer to e820_alloc_memory(). The function then iterates over the memory regions and assigns the
|
||||
* allocated physical addresses to each region.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void init_ivshmem_shared_memory()
|
||||
{
|
||||
uint32_t i;
|
||||
@ -186,8 +219,36 @@ static void create_ivshmem_device(struct pci_vdev *vdev)
|
||||
memset(&ivshmem_dev[i].mmio, 0U, sizeof(uint32_t) * 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* @pre vdev->priv_data != NULL
|
||||
/**
|
||||
* @brief Handle MMIO (Memory-Mapped I/O) operations for the ivshmem device.
|
||||
*
|
||||
* BAR0 is used for device registers. This function handles MMIO read and write operations to the ivshmem device BAR0.
|
||||
*
|
||||
* Per the specification, the access offset within should be 4-byte aligned, the access size should be 4 bytes, and the
|
||||
* access offset exceeds 16 bytes are reserved. So the request needs to meet these conditions, otherwise, it does
|
||||
* nothing and directly returns 0.
|
||||
* - For a read operation, the read value is stored in the input mmio request structure:
|
||||
* - Doorbell register is a write-only register, so it sets the read value to 0.
|
||||
* - Otherwise, it reads specified register value of the ivshmem device.
|
||||
* - For a write operation:
|
||||
* - IVPosition register is a read-only register, so it does nothing if writing to IVPosition.
|
||||
* - Writing to the Doorbell register requests to interrupt a peer. It extracts the peer ID and vector index from the
|
||||
* input mmio value. If the peer is valid (peer ivshmem device exists, MSI-X is enabled, the MSI-X table entry
|
||||
* corresponding to the vector index exists and is not masked), it injects an MSI to the peer VM. For more details
|
||||
* about the MSI injection, refer to vlapic_inject_msi().
|
||||
* - Otherwise, it writes the value to the specified register of the ivshmem device.
|
||||
* - Finally, it returns 0.
|
||||
*
|
||||
* @param[inout] io_req Pointer to the I/O request structure that contains the MMIO request information.
|
||||
* @param[inout] data Pointer to the pci_vdev structure that is treated as an ivshmem device.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre io_req != NULL
|
||||
* @pre data != NULL
|
||||
* @pre data->priv_data != NULL
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t ivshmem_mmio_handler(struct io_request *io_req, void *data)
|
||||
{
|
||||
@ -227,6 +288,27 @@ static int32_t ivshmem_mmio_handler(struct io_request *io_req, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the PCI configuration space of the ivshmem device.
|
||||
*
|
||||
* This function reads the configuration space of the specified virtual PCI device that is configured as a ivshmem
|
||||
* device. It is used to retrieve the configuration data of the ivshmem device for further processing or validation.
|
||||
*
|
||||
* It directly reads the configuration space of the ivshmem device by calling pci_vdev_read_vcfg().
|
||||
*
|
||||
* @param[in] vdev Pointer to the virtual PCI device whose configuration is to be read.
|
||||
* @param[in] offset Offset within the configuration space to start reading from.
|
||||
* @param[in] bytes Number of bytes to read from the configuration space.
|
||||
* @param[inout] val Pointer to the buffer where the read configuration data will be stored.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre val != NULL
|
||||
* @pre offset + bytes <= 0x1000
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t read_ivshmem_vdev_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val)
|
||||
{
|
||||
*val = pci_vdev_read_vcfg(vdev, offset, bytes);
|
||||
@ -234,6 +316,30 @@ static int32_t read_ivshmem_vdev_cfg(struct pci_vdev *vdev, uint32_t offset, uin
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unmap the specified BAR for the ivshmem device.
|
||||
*
|
||||
* This function unmaps the specified BAR for the ivshmem device. It is typically called during the destroy phase of the
|
||||
* ivshmem device or when guest updates the BAR register.
|
||||
*
|
||||
* - BAR0 and BAR1 are used for device registers and MSI-X table and PBA, respectively. If the specified idx is 0 or 1
|
||||
* and the field base_gpa in the specified vBAR is not 0, it unregisters the mmio range handler for the BAR by calling
|
||||
* unregister_mmio_emulation_handler().
|
||||
* - BAR2 maps the shared memory object. If the specified idx is 2 and the field base_gpa in vBAR2 is not 0, it releases
|
||||
* the ept memory mapping for the shared memory region by calling ept_del_mr().
|
||||
* - Otherwise, it does nothing.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the PCI device that is treated as an ivshmem device.
|
||||
* @param[in] idx Index of the BAR to be unmapped.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
* @pre idx < PCI_BAR_COUNT
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void ivshmem_vbar_unmap(struct pci_vdev *vdev, uint32_t idx)
|
||||
{
|
||||
struct acrn_vm *vm = vpci2vm(vdev->vpci);
|
||||
@ -246,9 +352,35 @@ static void ivshmem_vbar_unmap(struct pci_vdev *vdev, uint32_t idx)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief Map the virtual BAR for the ivshmem device.
|
||||
*
|
||||
* This function maps the specified virtual BAR for the ivshmem device. It is typically called when guest updates the
|
||||
* BAR register.
|
||||
*
|
||||
* - BAR0 is used for device registers. If the specified idx is 0 and the field base_gpa in the specified vBAR is not 0,
|
||||
* it registers the mmio range handler (via the callback ivshmem_mmio_handler) for the BAR and deletes the 4KB ept
|
||||
* memory mapping for the BAR by calling ept_del_mr().
|
||||
* - BAR1 is used for MSI-X table and PBA. If the specified idx is 1 and the field base_gpa in the specified vBAR is not
|
||||
* 0, it registers the mmio range handler (via the callback vmsix_handle_table_mmio_access) for the BAR and deletes
|
||||
* the ept memory mapping for the BAR by calling ept_del_mr(). It also sets the mmio_gpa field in the vdev->msix to
|
||||
* the GPA of the BAR for MSI-X table access.
|
||||
* - BAR2 maps the shared memory object. If the specified idx is 2, the field base_gpa in vBAR2 is not 0 and the field
|
||||
* base_hpa in vBAR2 is not INVALID_HPA, it adds the ept memory mapping as (EPT_RD|EPT_WR|EPT_WB|EPT_IGNORE_PAT) for
|
||||
* the BAR by calling ept_add_mr().
|
||||
* - Otherwise, it does nothing.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the PCI device that is treated as an ivshmem device.
|
||||
* @param[in] idx Index of the BAR to be mapped.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->priv_data != NULL
|
||||
* @pre msix->table_offset == 0U
|
||||
* @pre bar_idx < PCI_BAR_COUNT
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void ivshmem_vbar_map(struct pci_vdev *vdev, uint32_t idx)
|
||||
{
|
||||
@ -270,6 +402,32 @@ static void ivshmem_vbar_map(struct pci_vdev *vdev, uint32_t idx)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to the virtual ivshmem device configuration space.
|
||||
*
|
||||
* This function handles writes to the configuration space of the specified virtual PCI device that is configured as an
|
||||
* ivshmem device. It is typically called when the guest writes to the ivshmem device's configuration space.
|
||||
*
|
||||
* - If the write request is for a BAR register, it updates the BAR with the provided value. It also needs to update the
|
||||
* ept mapping and mmio emulation handler based on the bar information. For detailed operations, refer to
|
||||
* vpci_update_one_vbar(), ivshmem_vbar_map() and ivshmem_vbar_unmap().
|
||||
* - If the write request is for the MSI-X capability register, it specially handles the write request. For detailed
|
||||
* operations, refer to write_vmsix_cap_reg().
|
||||
* - Otherwise, the function writes the provided value to the specified configuration space register.
|
||||
* - Finally, the function returns 0.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device whose configuration is to be written.
|
||||
* @param[in] offset Offset within the configuration space to start writing to.
|
||||
* @param[in] bytes Number of bytes to write.
|
||||
* @param[in] val The value to be written to the register.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre offset + bytes <= 0x1000
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t write_ivshmem_vdev_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val)
|
||||
{
|
||||
if (vbar_access(vdev, offset)) {
|
||||
@ -284,9 +442,30 @@ static int32_t write_ivshmem_vdev_cfg(struct pci_vdev *vdev, uint32_t offset, ui
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief Initialize the specified BAR for the ivshmem device.
|
||||
*
|
||||
* The ivshmem PCI device has three BARs: BAR0, BAR1, and BAR2. BAR0/BAR1 is a 32-bit memory BAR and BAR2 is a 64-bit
|
||||
* memory BAR. This function initializes a specified BAR for the ivshmem device. It is typically called during the
|
||||
* initialization phase of the ivshmem device.
|
||||
*
|
||||
* - If bar_idx exceeds 2, the function does nothing.
|
||||
* - For BAR2, it finds the shared memory region based on the shared memory region name. If the shared memory region is
|
||||
* not found, the function does nothing.
|
||||
* - It updates corresponding fields in the pci_vbar structure of specified bar_idx.
|
||||
* - It configures the Base Address Register in the device's configuration space.
|
||||
* - For a 64-bit memory BAR (BAR2 for now), it also sets up the next Base Address Register as the high 32 bits.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the PCI device that is treated as an ivshmem device.
|
||||
* @param[in] bar_idx Index of the BAR to be initialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->pci_dev_config != NULL
|
||||
* @pre bar_idx < PCI_BAR_COUNT
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void init_ivshmem_bar(struct pci_vdev *vdev, uint32_t bar_idx)
|
||||
{
|
||||
@ -327,6 +506,40 @@ static void init_ivshmem_bar(struct pci_vdev *vdev, uint32_t bar_idx)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a virtual ivshmem device.
|
||||
*
|
||||
* This function initializes the specified virtual PCI device as an ivshmem device. It sets up the device to follow the
|
||||
* specifications. Because the ivshmem is introduced by QEMU, the spec link is
|
||||
* https://www.qemu.org/docs/master/specs/ivshmem-spec.html. This function is usually used in the initialization phase
|
||||
* of VM.
|
||||
*
|
||||
* - It sets the pcidev field in ivshmem_device (all ivshmem devices emulated by hypervisor are static stored based on
|
||||
* the configuration) to the vdev and sets the priv_data field in the specified vdev to new ivshmem_device structure
|
||||
* data, indicating the association between the virtual PCI device and the ivshmem device.
|
||||
* - Per the ivshmem specification and PCI Express Base Specification, it initializes the ivshmem device configuration
|
||||
* space with appropriate values:
|
||||
* - The device ID and Vendor ID is 0x11101af4.
|
||||
* - It sets subsystem vendor ID to 0x8086 (Intel) and subsystem ID to the region ID of the shared memory region.
|
||||
* - It sets up the MSI-X capability with 8 MSI-X table entries and maps the table and PBA into BAR1. For detailed
|
||||
* operations, refer to add_vmsix_capability().
|
||||
* - It initializes BAR0 for the device to hold device registers (256 Byte MMIO).
|
||||
* - It initializes BAR1 for the device to hold MSI-X table and PBA.
|
||||
* - It initializes BAR2 for the device to map the shared memory object. Because BAR2 is a 64-bit memory BAR, it also
|
||||
* sets up the next Base Address Register as the high 32 bits and the total number of bars is set to 4.
|
||||
* - It binds the device to the ivshmem server (hosts in hypervisor) for inter-VM communication.
|
||||
* - Finally, it sets the user field to vdev, indicating that this ivshmem is used by a VM.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device to be initialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->pci_dev_config != NULL
|
||||
* @pre vdev->pci != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void init_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
{
|
||||
struct acrn_vm_pci_dev_config *dev_config = vdev->pci_dev_config;
|
||||
@ -359,8 +572,25 @@ static void init_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
vdev->user = vdev;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief Deinitialize a virtual ivshmem device.
|
||||
*
|
||||
* This function deinitializes the specified virtual PCI device that was previously initialized as an ivshmem device.
|
||||
*
|
||||
* - It unbinds the device from the ivshmem server (hosts in hypervisor).
|
||||
* - It sets the priv_data field in the specified vdev to NULL and sets the pcidev field in ivshmem_device to NULL,
|
||||
* indicating the disassociation between the virtual PCI device and the ivshmem device.
|
||||
* - It sets the user field to NULL, indicating that this virtual device is not owned by any VM.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device to be deinitialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->priv_data != NULL
|
||||
* @pre vdev->pci != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void deinit_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
{
|
||||
@ -376,8 +606,39 @@ static void deinit_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a virtual ivshmem device based on the specified device information.
|
||||
*
|
||||
* Basic ivshmem information is configured in the scenario file. After compilation, some device configurations of every
|
||||
* ivshmem PCI device are stored in struct acrn_vm_pci_dev_config and every shared memory region is stored in struct
|
||||
* ivshmem_shm_region. This function creates one virtual ivshmem device based on the input device information. The
|
||||
* user-space tool(such as acrn-dm) may add an ivshmem device for a post-launch VM and this device is emulated in
|
||||
* hypervisor. This function is used for the case for now and it is usually used in the initialization phase of a
|
||||
* post-launch VM.
|
||||
*
|
||||
* - Per the ivshmem specification, BAR2 maps the shared memory object. For the ivshmem device to be created, the shared
|
||||
* memory region name is stored in dev->args and the size of the shared memory region is stored in
|
||||
* dev->io_size[IVSHMEM_SHM_BAR].
|
||||
* - It traverses all configured PCI devices of the specified VM. Based on the input shared memory region name, it finds
|
||||
* corresponding acrn_vm_pci_dev_config and ivshmem_shm_region.
|
||||
* - If the acrn_vm_pci_dev_config is not found or the ivshmem_shm_region is not found or the size of ivshmem_shm_region
|
||||
* is not equal to the size specified in dev->io_size[IVSHMEM_SHM_BAR], the function returns -EINVAL.
|
||||
* - Otherwise, update the acrn_vm_pci_dev_config with input device information specified in dev and initializes a new
|
||||
* virtual PCI device as an ivshmem device. For detailed operations, refer to vpci_init_vdev(). The function returns
|
||||
* -EINVAL if the vpci_init_vdev() fails.
|
||||
* - Finally, it returns 0 on success.
|
||||
*
|
||||
* @param[inout] vm Pointer to the VM that owns the ivshmem device.
|
||||
* @param[in] dev Pointer to the device information to create an ivshmem device.
|
||||
*
|
||||
* @return A int32_t value to indicate the status of the ivshmem device creation.
|
||||
*
|
||||
* @retval 0 On success.
|
||||
* @retval -EINVAL If the ivshmem device creation fails.
|
||||
*
|
||||
* @pre vm != NULL
|
||||
* @pre dev != NULL
|
||||
*
|
||||
* @post retval <= 0
|
||||
*/
|
||||
int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_vdev *dev)
|
||||
{
|
||||
@ -403,7 +664,7 @@ int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_vdev *dev)
|
||||
if (vdev != NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -415,6 +676,27 @@ int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_vdev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the virtual ivshmem device.
|
||||
*
|
||||
* This function is the counterpart of create_ivshmem_vdev(). This function destroys the specified virtual PCI device
|
||||
* that was previously initialized as an ivshmem device. It is usually used for a post-launch VM to destroy the ivshmem
|
||||
* device.
|
||||
*
|
||||
* - It updates all BARs of the specified vdev. For detailed operations, refer to vpci_update_one_vbar() and the
|
||||
* function ivshmem_vbar_unmap().
|
||||
* - It deinitializes the specified virtual PCI device. For detailed operations, refer to vpci_deinit_vdev().
|
||||
* - Finally, it returns 0.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device to be destroyed.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
int32_t destroy_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
{
|
||||
uint32_t i;
|
||||
@ -431,10 +713,26 @@ int32_t destroy_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data structure implementation for virtual Inter-VM shared memory device (ivshmem) operations.
|
||||
*
|
||||
* The ivshmem is actually first introduced by QEMU to share a memory region between multiple VMs and host. It is
|
||||
* modeled as a PCI device exposing said memory to the VM as a PCI BAR. ACRN also introduces it to transfer data between
|
||||
* VMs based on the shared memory region. Struct pci_vdev_ops is used to define the operations of virtual PCI device and
|
||||
* definition here is used to support ivshmem device.
|
||||
*
|
||||
* @consistency N/A
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
const struct pci_vdev_ops vpci_ivshmem_ops = {
|
||||
.init_vdev = init_ivshmem_vdev,
|
||||
.deinit_vdev = deinit_ivshmem_vdev,
|
||||
.write_vdev_cfg = write_ivshmem_vdev_cfg,
|
||||
.read_vdev_cfg = read_ivshmem_vdev_cfg,
|
||||
};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 NetApp, Inc.
|
||||
* Copyright (c) 2018-2022 Intel Corporation.
|
||||
* Copyright (c) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -39,75 +39,131 @@
|
||||
#include <vacpi.h>
|
||||
|
||||
/**
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
* @addtogroup vp-dm_vperipheral
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/* The chart below shows the hostbridge DID high-byte of the platform later than broadwell, whose PCIEXBAR are always
|
||||
located in the PCI hostbridge config space at the offset 0x60. This chart may need further extension in the future
|
||||
--------------------------------------------------------------------------------------
|
||||
platform | hostbridge DID high-byte
|
||||
--------------------------------------------------------------------------------------
|
||||
SKL(6-gen) | 0x19
|
||||
APL(6-gen Atom) | 0x5a
|
||||
KBL(7/8-gen) | 0x59
|
||||
CFL/CFL-R(8/9-gen) | 0x3e
|
||||
ICL(10-gen) | 0x9b
|
||||
EHL(11-gen) | 0x45
|
||||
TGL(11-gen) | 0x9a
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of virtual PCI host bridge.
|
||||
*
|
||||
* This file defines operations to support virtual PCI host bridge. All the operation related APIs are registered as the
|
||||
* callbacks in the global variable "struct pci_vdev_ops vhostbridge_ops".
|
||||
*/
|
||||
|
||||
/*
|
||||
The chart below shows the hostbridge DID high-byte of the platform later than broadwell, whose PCIEXBAR are always
|
||||
located in the PCI hostbridge config space at the offset 0x60. This chart may need further extension in the future
|
||||
--------------------------------------------------------------------------------------
|
||||
platform | hostbridge DID high-byte
|
||||
--------------------------------------------------------------------------------------
|
||||
SKL(6-gen) | 0x19
|
||||
APL(6-gen Atom) | 0x5a
|
||||
KBL(7/8-gen) | 0x59
|
||||
CFL/CFL-R(8/9-gen) | 0x3e
|
||||
ICL(10-gen) | 0x9b
|
||||
EHL(11-gen) | 0x45
|
||||
TGL(11-gen) | 0x9a
|
||||
--------------------------------------------------------------------------------------
|
||||
*/
|
||||
static const uint32_t hostbridge_did_highbytes[] = {0x19U, 0x5aU, 0x59U, 0x3eU, 0x9aU, 0x45U, 0x9bU};
|
||||
|
||||
/*
|
||||
The vhostbridge we currently emulated is "Celeron N3350/Pentium N4200/Atom E3900 Series Host Bridge",
|
||||
which belongs to Intel Appollo Lake processors family, and the device id is 5af0
|
||||
TODO:
|
||||
1. In the future, we may add one or more virtual hostbridges for CPUs that are incompatible in layout with the current
|
||||
one
|
||||
2. Besides PCIEXBAR(0x60), there are also some registers needs to be emulated more precisely rather than be treated as
|
||||
read-only and hard-coded, listed below:
|
||||
|
||||
TODO:
|
||||
1. In the future, we may add one or more virtual hostbridges for CPUs that are incompatible in layout with the current one
|
||||
2. Besides PCIEXBAR(0x60), there are also some registers needs to be emulated more precisely rather than be treated as read-only and hard-coded, listed below:
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
reg | offset | length | current status | remark
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
STATUS_COMMAND | 0x8 | dword | unemulated | pci status and command
|
||||
SVID_SID | 0x2C | dword | unemulated | subsys id and subsys vendor id
|
||||
MCHBAR | 0x48 | qword | hard-coded | BAR of memory controller hub
|
||||
GGC | 0x50 | dword | hard-coded | graphics & mem controller hub graphics CR
|
||||
DEVEN | 0x54 | dword | hard-coded | device enable register
|
||||
PAVPC | 0x58 | dword | hard-coded | protected audio video path control
|
||||
TOUUD | 0xA8 | qword | hard-coded | top of upper usable DRAM
|
||||
BDSM | 0xB0 | dword | hard-coded | base of data stolen memory
|
||||
BGSM | 0xB4 | dword | hard-coded | base of graphics stolen memory
|
||||
TSEGMB | 0xB8 | dword | hard-coded | top segmentmemory base
|
||||
TOLUD | 0xBC | dword | hard-coded | top of lower usable dram
|
||||
SKPD | 0xDC | dword | unemulated | scratchpad
|
||||
CAPID0_CAPCTRL0 | 0xe0 | dword | hard-coded | capability 0 control
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
-----------------------------------------------------------------------------------------------
|
||||
reg |offset |length |current status |remark
|
||||
-----------------------------------------------------------------------------------------------
|
||||
STATUS_COMMAND |0x8 |dword |unemulated |pci status and command
|
||||
SVID_SID |0x2C |dword |unemulated |subsys id and subsys vendor id
|
||||
MCHBAR |0x48 |qword |hard-coded |BAR of memory controller hub
|
||||
GGC |0x50 |dword |hard-coded |graphics & mem controller hub graphics CR
|
||||
DEVEN |0x54 |dword |hard-coded |device enable register
|
||||
PAVPC |0x58 |dword |hard-coded |protected audio video path control
|
||||
TOUUD |0xA8 |qword |hard-coded |top of upper usable DRAM
|
||||
BDSM |0xB0 |dword |hard-coded |base of data stolen memory
|
||||
BGSM |0xB4 |dword |hard-coded |base of graphics stolen memory
|
||||
TSEGMB |0xB8 |dword |hard-coded |top segmentmemory base
|
||||
TOLUD |0xBC |dword |hard-coded |top of lower usable dram
|
||||
SKPD |0xDC |dword |unemulated |scratchpad
|
||||
CAPID0_CAPCTRL0 |0xe0 |dword |hard-coded |capability 0 control
|
||||
-----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the virtual host bridge.
|
||||
*
|
||||
* A host bridge is a PCI device that is used to support the pci devices under it. This function initializes the
|
||||
* specified virtual PCI device as a host bridge. It's usually called during the initialization of a VM.
|
||||
*
|
||||
* This function emulates the virtual host bridge as a "Celeron N3350/Pentium N4200/Atom E3900 Series Host Bridge",
|
||||
* which belongs to Intel Apollo Lake processors family, and the device id is 0x5af0. Per "Section 9 C-Unit in Intel®
|
||||
* Pentium® and Celeron® Processor N- and J- Series, Datasheet Volume 2", it initializes related type info registers in
|
||||
* configuration space.
|
||||
* PCI Express Enhanced Configuration Range Base Address Register (PCIEXBAR) is emulated differently for pre-launched
|
||||
* VMs and Service VM, to support PCI Express Enhanced Configuration Access Mechanism (ECAM).
|
||||
* - For a pre-launched VM, it is emulated as 'USER_VM_VIRT_PCI_MMCFG_BASE | 0x1'. USER_VM_VIRT_PCI_MMCFG_BASE
|
||||
* (0xE0000000) is the hard-coded virtual PCI MMCFG address base for pre/post-launched VMs. Bit 0 is set to 1 to
|
||||
* indicate that the base address defined in the PCIEXBAR register is active.
|
||||
* - For a Service VM, it is emulated to be the same value as the physical PCIEXBAR. It is not used for now, mainly for
|
||||
* feature extension in the future.
|
||||
* Finally, it sets the field parent_user to NULL and the field user to vdev, indicating that this vPCI bridge is used
|
||||
* by a VM.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device to be initialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void init_vhostbridge(struct pci_vdev *vdev)
|
||||
{
|
||||
union pci_bdf hostbridge_bdf = {.value = 0x0U};
|
||||
uint32_t pciexbar_low = 0x0U, pciexbar_high = 0x0U, phys_did, i;
|
||||
/* Refer to Section 9 C-Unit in Intel® Pentium® and Celeron® Processor N- and J- Series, Datasheet Volume 2 */
|
||||
/* PCI config space */
|
||||
pci_vdev_write_vcfg(vdev, PCIR_VENDOR, 2U, 0x8086U);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_DEVICE, 2U, 0x5af0U);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_REVID, 1U, 0xbU);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_HDRTYPE, 1U, (PCIM_HDRTYPE_NORMAL | PCIM_MFDEV));
|
||||
pci_vdev_write_vcfg(vdev, PCIR_CLASS, 1U, PCIC_BRIDGE);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_SUBCLASS, 1U, PCIS_BRIDGE_HOST);
|
||||
pci_vdev_write_vcfg(vdev, 0x34U, 1U, 0xe0U);
|
||||
pci_vdev_write_vcfg(vdev, 0x3cU, 1U, 0xe0U);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_CLASS, 1U, PCIC_BRIDGE);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_HDRTYPE, 1U, (PCIM_HDRTYPE_NORMAL | PCIM_MFDEV));
|
||||
/* First Capability Register is CAPID0_CAPCTRL0 */
|
||||
pci_vdev_write_vcfg(vdev, PCIR_CAP_PTR, 1U, 0xe0U);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_INTERRUPT_LINE, 1U, 0xe0U);
|
||||
|
||||
/* Memory Controller Hub Base Address Register, MCHBAR_LO */
|
||||
/* MCHBAR[38:15] is {MCHBAR_HI[6:0],MCHBAR_LO[31:15]} */
|
||||
pci_vdev_write_vcfg(vdev, 0x48U, 4U, 0xfed10001U);
|
||||
/* Graphics and Memory Controller Hub Graphics Control Register, GGC */
|
||||
/* [15:8] is Graphics Memory Select (GMS), 512MB */
|
||||
pci_vdev_write_vcfg(vdev, 0x50U, 4U, 0x000002c1U);
|
||||
/* Device Enable Register, DEVEN */
|
||||
pci_vdev_write_vcfg(vdev, 0x54U, 4U, 0x00000033U);
|
||||
/* Protected Audio Video Path Control, PAVPC */
|
||||
pci_vdev_write_vcfg(vdev, 0x58U, 4U, 0x7ff00007U);
|
||||
/* Top of Upper Usable DRAM Low, TOUUD_LO */
|
||||
pci_vdev_write_vcfg(vdev, 0xa8U, 4U, 0x80000000U);
|
||||
/* Top of Upper Usable DRAM High, TOUUD_HI */
|
||||
pci_vdev_write_vcfg(vdev, 0xacU, 4U, 0x00000002U);
|
||||
/* Base of Data Stolen Memory, BDSM */
|
||||
pci_vdev_write_vcfg(vdev, 0xb0U, 4U, 0x7c000001U);
|
||||
/* Base of Graphics Stolen Memory, BGSM */
|
||||
pci_vdev_write_vcfg(vdev, 0xb4U, 4U, 0x7b800001U);
|
||||
/* Top Segment Memory Base, TSEGMB */
|
||||
pci_vdev_write_vcfg(vdev, 0xb8U, 4U, 0x7b000001U);
|
||||
/* Top of Lower Usable DRAM, TOLUD */
|
||||
pci_vdev_write_vcfg(vdev, 0xbcU, 4U, 0x80000001U);
|
||||
/* Capability ID0 Capability Control, CAPID0_CAPCTRL0 */
|
||||
/* CAP_ID: 9h, NEXT_CAP: 0h, CAPIDLEN: Ch, CAPID_VER: 1h */
|
||||
pci_vdev_write_vcfg(vdev, 0xe0U, 4U, 0x010c0009U);
|
||||
pci_vdev_write_vcfg(vdev, 0xf4U, 4U, 0x011c0f00U);
|
||||
|
||||
@ -117,34 +173,69 @@ static void init_vhostbridge(struct pci_vdev *vdev)
|
||||
*/
|
||||
pciexbar_low = USER_VM_VIRT_PCI_MMCFG_BASE | 0x1U;
|
||||
} else {
|
||||
/*Inject physical ECAM value to Service VM vhostbridge since Service VM may check PCIe-MMIO Base Address with it */
|
||||
/* Inject physical ECAM value to Service VM vhostbridge since Service VM may check PCIe-MMIO Base
|
||||
Address with it */
|
||||
phys_did = pci_pdev_read_cfg(hostbridge_bdf, PCIR_DEVICE, 2);
|
||||
for (i = 0U; i < (sizeof(hostbridge_did_highbytes) / sizeof(uint32_t)); i++) {
|
||||
if (((phys_did & 0xff00U) >> 8) == hostbridge_did_highbytes[i]) {
|
||||
/* The offset of PCIEXBAR register is 0x60 on Intel platforms, and no counter-case is encountered yet */
|
||||
/* The offset of PCIEXBAR register is 0x60 on Intel platforms, and no counter-case is
|
||||
encountered yet */
|
||||
pciexbar_low = pci_pdev_read_cfg(hostbridge_bdf, 0x60U, 4);
|
||||
pciexbar_high = pci_pdev_read_cfg(hostbridge_bdf, 0x64U, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PCI Express Enhanced Configuration Range Base Address Low, PCIEXBAR_LO */
|
||||
pci_vdev_write_vcfg(vdev, 0x60U, 4, pciexbar_low);
|
||||
/* PCI Express Enhanced Configuration Range Base Address High, PCIEXBAR_HI */
|
||||
pci_vdev_write_vcfg(vdev, 0x64U, 4, pciexbar_high);
|
||||
vdev->parent_user = NULL;
|
||||
vdev->user = vdev;
|
||||
}
|
||||
|
||||
static void deinit_vhostbridge(__unused struct pci_vdev *vdev)
|
||||
/**
|
||||
* @brief Deinitialize the virtual host bridge.
|
||||
*
|
||||
* This function deinitializes the specified virtual PCI device that was previously initialized as a host bridge.
|
||||
*
|
||||
* For the specified vdev, it sets the fields parent_user and user to NULL, indicating that this virtual device is not
|
||||
* owned by any VM.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void deinit_vhostbridge(struct pci_vdev *vdev)
|
||||
{
|
||||
vdev->parent_user = NULL;
|
||||
vdev->user = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the configuration space of the virtual host bridge.
|
||||
*
|
||||
* This function reads the configuration space of the specified virtual PCI device that is configured as a host bridge.
|
||||
* It is used to retrieve specific configuration data of the virtual host bridge for further processing or validation.
|
||||
*
|
||||
* It reads the configuration space of the virtual host bridge and stores the read configuration data in the provided
|
||||
* buffer.
|
||||
*
|
||||
* @param[in] vdev Pointer to the virtual PCI device whose configuration space is to be read.
|
||||
* @param[in] offset Offset within the configuration space to read from.
|
||||
* @param[in] bytes Number of bytes to read from the configuration space.
|
||||
* @param[inout] val Pointer to the buffer where the read configuration data will be stored.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
* @pre val != NULL
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t read_vhostbridge_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
uint32_t bytes, uint32_t *val)
|
||||
@ -153,10 +244,25 @@ static int32_t read_vhostbridge_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write to the virtual host bridge configuration space.
|
||||
*
|
||||
* This function writes to the configuration space of the specified virtual PCI device that is configured as a host
|
||||
* bridge. It is used to update specific configuration settings based on the provided parameters.
|
||||
*
|
||||
* For the non-BAR configuration space, it writes the provided value to the configuration space of the virtual host
|
||||
* bridge. For the BAR configuration space, it is read-only and the write operation is ignored.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device whose configuration space is to be written.
|
||||
* @param[in] offset Offset within the configuration space to start writing to.
|
||||
* @param[in] bytes Number of bytes to write to the configuration space.
|
||||
* @param[in] val Value to be written to the configuration space.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t write_vhostbridge_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
uint32_t bytes, uint32_t val)
|
||||
@ -167,9 +273,27 @@ static int32_t write_vhostbridge_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data structure implementation for virtual host bridge operations.
|
||||
*
|
||||
* Struct pci_vdev_ops is used to define the operations of virtual PCI device and definition here is used to support
|
||||
* virtual host bridge.
|
||||
*
|
||||
* A pre-launched VM may have some pci devices and a host bridge is needed to support these devices. This struct is used
|
||||
* to define the operations of virtual host bridge in this case for now.
|
||||
*
|
||||
* @consistency N/A
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
const struct pci_vdev_ops vhostbridge_ops = {
|
||||
.init_vdev = init_vhostbridge,
|
||||
.deinit_vdev = deinit_vhostbridge,
|
||||
.write_vdev_cfg = write_vhostbridge_cfg,
|
||||
.read_vdev_cfg = read_vhostbridge_cfg,
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2011 NetApp, Inc.
|
||||
* Copyright (c) 2019-2022 Intel Corporation.
|
||||
* Copyright (c) 2019-2024 Intel Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -50,6 +50,41 @@
|
||||
#include <pci.h>
|
||||
#include "vpci_priv.h"
|
||||
|
||||
/**
|
||||
* @addtogroup vp-dm_vperipheral
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of virtual PCI bridge.
|
||||
*
|
||||
* This file defines operations to support virtual PCI bridge. It implements struct pci_vdev_ops and related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the vPCI bridge.
|
||||
*
|
||||
* A PCI bridge is also a PCI device. This function initializes the specified virtual PCI device as a PCI bridge. A vPCI
|
||||
* bridge is based on a physical PCI bridge and is used for Service VM. It's usually used in the initialization phase of
|
||||
* Service VM, when the pre-launched VM exists.
|
||||
*
|
||||
* It initializes most of the virtual PCI configuration space registers based on the physical PCI bridge registers,
|
||||
* except those that specify the type information, which is emulated. Such type related registers include Vendor ID,
|
||||
* Device ID, Revision ID, Header Type, class and sub-class code. Finally, it sets the field parent_user to NULL and
|
||||
* the field user to vdev, indicating that this vPCI bridge is used by a VM.
|
||||
* Note that the physical PCI bridge registers are already initialized and configured during the initialization of the
|
||||
* physical PCI hierarchy.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device to be initialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void init_vpci_bridge(struct pci_vdev *vdev)
|
||||
{
|
||||
uint32_t offset, val;
|
||||
@ -74,12 +109,51 @@ static void init_vpci_bridge(struct pci_vdev *vdev)
|
||||
vdev->user = vdev;
|
||||
}
|
||||
|
||||
static void deinit_vpci_bridge(__unused struct pci_vdev *vdev)
|
||||
/**
|
||||
* @brief Deinitializes the vPCI bridge.
|
||||
*
|
||||
* This function deinitializes the specified virtual PCI device that was previously initialized as a PCI bridge.
|
||||
*
|
||||
* For the specified vdev, it sets the fields parent_user and user to NULL, indicating that this virtual device is not
|
||||
* owned by any VM.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the virtual PCI device to be deinitialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static void deinit_vpci_bridge(struct pci_vdev *vdev)
|
||||
{
|
||||
vdev->parent_user = NULL;
|
||||
vdev->user = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads the configuration of the vPCI bridge.
|
||||
*
|
||||
* This function reads the configuration space of the specified virtual PCI device that is configured as a PCI bridge.
|
||||
* It is used to retrieve the configuration data of the vPCI bridge for further processing or validation.
|
||||
*
|
||||
* - For PCI configuration space (offset <= 0x100U), it reads the configuration space of the vPCI bridge.
|
||||
* - For PCI Express Extended configuration space (offset > 0x100U), it simply passthrough by reading directly from the
|
||||
* physical device.
|
||||
* - The read configuration data is stored in the buffer pointed to by val.
|
||||
*
|
||||
* @param[in] vdev Pointer to the virtual PCI device whose configuration is to be read.
|
||||
* @param[in] offset Offset within the configuration space to start reading from.
|
||||
* @param[in] bytes Number of bytes to read from the configuration space.
|
||||
* @param[inout] val Pointer to the buffer where the read configuration data will be stored.
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre val != NULL
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t read_vpci_bridge_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
uint32_t bytes, uint32_t *val)
|
||||
{
|
||||
@ -93,15 +167,54 @@ static int32_t read_vpci_bridge_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes the configuration of the vPCI bridge.
|
||||
*
|
||||
* This function writes to the configuration space of the specified virtual PCI device that is configured as a PCI
|
||||
* bridge. It is used to update the configuration data of the vPCI bridge. However, the configuration space of the vPCI
|
||||
* bridge is read-only, so this function does not perform any operation.
|
||||
*
|
||||
* It just returns 0 without any operation.
|
||||
*
|
||||
* @param[in] vdev Pointer to the virtual PCI device whose configuration is to be written (unused in this function).
|
||||
* @param[in] offset Offset within the configuration space to start writing to (unused in this function).
|
||||
* @param[in] bytes Number of bytes to write to the configuration space (unused in this function).
|
||||
* @param[in] val Value to be written to the configuration space (unused in this function).
|
||||
*
|
||||
* @return Always return 0.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
*
|
||||
* @post retval == 0
|
||||
*/
|
||||
static int32_t write_vpci_bridge_cfg(__unused struct pci_vdev *vdev, __unused uint32_t offset,
|
||||
__unused uint32_t bytes, __unused uint32_t val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data structure implementation for virtual PCI bridge operations.
|
||||
*
|
||||
* Struct pci_vdev_ops is used to define the operations of virtual PCI device and definition here is used to support PCI
|
||||
* bridge.
|
||||
*
|
||||
* All PCI devices (including PCI bridge) on platform are passed to Service VM by default. But PCI bridges should be
|
||||
* emulated by hypervisor if pre-launched VM exists. This struct is used to define the operations of virtual PCI bridge
|
||||
* in this case.
|
||||
*
|
||||
* @consistency N/A
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
const struct pci_vdev_ops vpci_bridge_ops = {
|
||||
.init_vdev = init_vpci_bridge,
|
||||
.deinit_vdev = deinit_vpci_bridge,
|
||||
.write_vdev_cfg = write_vpci_bridge_cfg,
|
||||
.read_vdev_cfg = read_vpci_bridge_cfg,
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Neel Natu (neel@freebsd.org)
|
||||
* Copyright (c) 2022 Intel Corporation.
|
||||
* Copyright (c) 2024 Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -34,6 +34,20 @@
|
||||
|
||||
#include "mc146818rtc.h"
|
||||
|
||||
/**
|
||||
* @addtogroup vp-dm_vperipheral
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of virtual RTC device.
|
||||
*
|
||||
* This file provides the implementation of the virtual RTC device. The virtual RTC device is used to provide the RTC
|
||||
* service to the guest VMs. It is a part of the virtual peripheral devices.
|
||||
*/
|
||||
|
||||
/* #define DEBUG_RTC */
|
||||
#ifdef DEBUG_RTC
|
||||
# define RTC_DEBUG pr_info
|
||||
@ -489,8 +503,34 @@ static void vrtc_set_reg_b(struct acrn_vrtc *vrtc, uint8_t newval)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read from the virtual RTC device.
|
||||
*
|
||||
* This function reads the value from the RTC register specified by the address port. To read from the virtual RTC
|
||||
* device, the guest writes the register index to the RTC address port and then reads the register value from the RTC
|
||||
* data port. This function is used to simulate the behavior of reading in a virtualized environment.
|
||||
*
|
||||
* - If the accessed port is CMOS_ADDR_PORT, it will set the value as index cached in last write (0 by default) and
|
||||
* return.
|
||||
* - If the accessed port is CMOS_DATA_PORT,
|
||||
* - For Service VM, it will directly read the value from the physical CMOS register.
|
||||
* - For a non-Service VM, it will return false indicating the read operation failed if the address is greater than
|
||||
* RTC_CENTURY. Otherwise, the read operation will be emulated.
|
||||
*
|
||||
* @param[inout] vcpu Pointer to the virtual CPU that is reading from the virtual RTC. The value read from the virtual
|
||||
* RTC will be stored in the PIO request.
|
||||
* @param[in] addr The address port to read from.
|
||||
* @param[in] width The width of the data to be read. This is not used in this function.
|
||||
*
|
||||
* @return A boolean value indicating whether the read operation is successful.
|
||||
*
|
||||
* @retval true Successfully read from the virtual RTC device.
|
||||
* @retval false Failed to read from the virtual RTC device.
|
||||
*
|
||||
* @pre vcpu != NULL
|
||||
* @pre vcpu->vm != NULL
|
||||
* @pre addr == 0x70U || addr == 0x71U
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static bool vrtc_read(struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t width)
|
||||
{
|
||||
@ -536,8 +576,39 @@ static inline bool vrtc_is_time_register(uint32_t offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value to the virtual RTC.
|
||||
*
|
||||
* This function writes a specified value to the virtual RTC at a given offset. To write to the virtual RTC, the guest
|
||||
* writes the register index to the RTC address port and then writes the register value to the RTC data port. This
|
||||
* function is used to simulate the behavior of writing in a virtualized environment.
|
||||
*
|
||||
* - If the accessed port is CMOS_ADDR_PORT and the width is 1 byte, it will store the value as the index and return.
|
||||
* - If the accessed port is CMOS_DATA_PORT,
|
||||
* - For Service VM, it will directly write the value to the physical CMOS register. If the physical date/time is
|
||||
* changed, for RT VMs and pre-launched VMs, the RTC/TSC snapshots will be updated. Those snapshots are used to
|
||||
* emulate the virtual date/time for non-Service VM.
|
||||
* - For a non-Service VM, it will ignore the write to the RTC_STATUSA, RTC_INTR and RTC_STATUSD. Otherwise, it will
|
||||
* update the virtual register value and RTC time. And for Post-launched VM, it will send a VM event to notify the
|
||||
* VM of the change in the RTC time if the address port is in the range of the time registers.
|
||||
*
|
||||
* @param[inout] vcpu Pointer to the virtual CPU that is writing to the virtual RTC.
|
||||
* @param[in] addr The address port to write to.
|
||||
* @param[in] width Width of the value to be written to the virtual RTC.
|
||||
* @param[in] value Value to be written to the virtual RTC.
|
||||
*
|
||||
* @return A boolean value indicating whether the write operation is handled successfully, which is always true in
|
||||
* current design. It either updates the physical registers, updates the virtual registers, or ignores the
|
||||
* write.
|
||||
*
|
||||
* @retval true The write operation is handled successfully.
|
||||
*
|
||||
* @pre vcpu != NULL
|
||||
* @pre vcpu->vm != NULL
|
||||
* @pre addr == 0x70U || addr == 0x71U
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
static bool vrtc_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t width,
|
||||
uint32_t value)
|
||||
@ -707,6 +778,29 @@ void resume_vrtc(void)
|
||||
calibrate_setup_timer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the virtual RTC.
|
||||
*
|
||||
* This function initializes the virtual RTC (Real-Time Clock) device for the given virtual machine. It sets up the
|
||||
* necessary data structures and state required for the RTC to function correctly. This function should be called during
|
||||
* the initialization phase of the virtual machine.
|
||||
*
|
||||
* - When Service VM's vRTC device is initialized, a periodic timer (every 3 hours) is set up to calibrate the virtual
|
||||
* date/time of other VMs. When the calibration timer is triggered, for RT VMs and pre-launched VMs, the TSC/RTC
|
||||
* snapshots are updated to reflect the physical TSC/RTC-time at that moment.
|
||||
* - When non-Service VM's vRTC device is initialized, the TSC/RTC snapshots are initialized to reflect the physical
|
||||
* TSC/RTC-time at the moment.
|
||||
*
|
||||
* @param[inout] vm The virtual machine that contains the virtual RTC to be initialized.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
void vrtc_init(struct acrn_vm *vm)
|
||||
{
|
||||
struct vm_io_range range = {
|
||||
@ -725,3 +819,7 @@ void vrtc_init(struct acrn_vm *vm)
|
||||
vm->vrtc.base_tsc = cpu_ticks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 NetApp, Inc.
|
||||
* Copyright (c) 2013 Neel Natu <neel@freebsd.org>
|
||||
* Copyright (c) 2018-2022 Intel Corporation.
|
||||
* Copyright (c) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -36,6 +36,20 @@
|
||||
#include <asm/guest/vm.h>
|
||||
#include <logmsg.h>
|
||||
|
||||
/**
|
||||
* @addtogroup vp-dm_vperipheral
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of virtual UART device.
|
||||
*
|
||||
* This file implements all the APIs to support virtual UART device. It also defines some helper functions to simulate
|
||||
* the device that are commonly used in this file.
|
||||
*/
|
||||
|
||||
#define init_vuart_lock(vu) spinlock_init(&((vu)->lock))
|
||||
#define obtain_vuart_lock(vu, flags) spinlock_irqsave_obtain(&((vu)->lock), &(flags))
|
||||
#define release_vuart_lock(vu, flags) spinlock_irqrestore_release(&((vu)->lock), (flags))
|
||||
@ -376,8 +390,31 @@ static void write_reg(struct acrn_vuart *vu, uint16_t reg, uint8_t value_u8)
|
||||
release_vuart_lock(vu, rflags);
|
||||
}
|
||||
|
||||
/*
|
||||
* @pre: vu != NULL
|
||||
/**
|
||||
* @brief Write a value to a register in the virtual UART.
|
||||
*
|
||||
* This function writes a 8-bit value to a specified register in the virtual UART (vUART). It is a basic function used
|
||||
* for port I/O write or MMIO write.
|
||||
*
|
||||
* - When the following conditions are met, data is sent to the target vUART's RXFIFO:
|
||||
* 1) The target vUART exists for the specified vUART, which is used for communication.
|
||||
* 2) The accessed register is the THR (Transmitter Holding Register).
|
||||
* 3) Loopback mode is not enabled.
|
||||
* 4) DLAB (Divisor Latch Access Bit) is not set.
|
||||
* - Additionally, to ensure reliable communication, it raises the THRE interrupt (indicating that more data can be
|
||||
* processed) only if the target vUART's RXFIFO is not full.
|
||||
* - If these conditions are not met, the virtual registers specified by the offset are updated according to the 16550
|
||||
* UART specification.
|
||||
*
|
||||
* @param[inout] vu The virtual UART structure to which the register value is to be written.
|
||||
* @param[in] offset The offset of the register within the vUART.
|
||||
* @param[in] value_u8 The 8-bit value to be written to the register.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vu != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void vuart_write_reg(struct acrn_vuart *vu, uint16_t offset, uint8_t value_u8)
|
||||
{
|
||||
@ -401,8 +438,28 @@ void vuart_write_reg(struct acrn_vuart *vu, uint16_t offset, uint8_t value_u8)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value to a port in the legacy virtual UART.
|
||||
*
|
||||
* This function writes a value to the legacy virtual UART (vUART) based on the specified port address. It is used to
|
||||
* handle I/O port write operations in the VM by updating the vUART's register. This function is typically called when
|
||||
* the vCPU needs to write data to the vUART during emulation of I/O port operations.
|
||||
*
|
||||
* - Based on the specified port address, it first finds the vUART device within the VM corresponding to the given vCPU.
|
||||
* - If the vUART is found, the value is written to the corresponding register. For detailed write operations, refer to
|
||||
* vuart_write_reg().
|
||||
* - If the vUART is not found, the write operation is ignored.
|
||||
*
|
||||
* @param[inout] vcpu A pointer to the vCPU that initiates the write operation.
|
||||
* @param[in] offset_arg The port address to write to.
|
||||
* @param[in] width The width of the write operation (unused in this function).
|
||||
* @param[in] value The value to be written to the register.
|
||||
*
|
||||
* @return Always returns true.
|
||||
*
|
||||
* @pre vcpu != NULL
|
||||
* @pre vcpu->vm != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static bool vuart_write(struct acrn_vcpu *vcpu, uint16_t offset_arg,
|
||||
__unused size_t width, uint32_t value)
|
||||
@ -435,7 +492,28 @@ static void notify_target(const struct acrn_vuart *vu)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a register from the virtual UART.
|
||||
*
|
||||
* This function returns the 8-bit value of a specified register. It is a basic function used for port I/O read or MMIO
|
||||
* read. The registers in the UART will affect each other, such as reading the LSR register will clear some bits in it.
|
||||
* This function carefully simulates this behavior.
|
||||
*
|
||||
* - If the DLAB bit in LCR is set, only the DLL and DLH registers are accessed. Other registers are considered as 0.
|
||||
* - Otherwise, according to the UART16550 specification, set and read the corresponding register. For registers greater
|
||||
* than 0x07 (SCR), the value will be 0xFF.
|
||||
* - It will toggle the interrupt.
|
||||
* - For communication vUART, when the data in FIFO is read out (read from RBR), it will notify the target vUART to send
|
||||
* more data.
|
||||
* - Finally, it will return the value of the specified register.
|
||||
*
|
||||
* @param[inout] vu Pointer to the virtual UART device.
|
||||
* @param[in] offset The specified offset of the register to read.
|
||||
*
|
||||
* @return The value of the specified register.
|
||||
*
|
||||
* @pre vu != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
uint8_t vuart_read_reg(struct acrn_vuart *vu, uint16_t offset)
|
||||
{
|
||||
@ -529,8 +607,27 @@ uint8_t vuart_read_reg(struct acrn_vuart *vu, uint16_t offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a value from a port in the legacy virtual UART.
|
||||
*
|
||||
* This function reads a value from the legacy virtual UART (vUART) based on the specified port address. It is used to
|
||||
* handle I/O port read operations in the VM by retrieving the value from the vUART's registers. This function is
|
||||
* typically called when the vCPU needs to read data from the vUART during emulation of I/O port operations.
|
||||
*
|
||||
* - Based on the specified port address, it first finds the vUART device within the VM corresponding to the given vCPU.
|
||||
* - If the vUART is found, the value is read from the corresponding virtual register and stored in the vCPU's PIO
|
||||
* request. For detailed read operations, refer to vuart_read_reg().
|
||||
* - If the vUART is not found, the vCPU's PIO request remains unchanged.
|
||||
*
|
||||
* @param[inout] vcpu A pointer to the vCPU that initiates the read operation.
|
||||
* @param[in] offset_arg The port address to read from.
|
||||
* @param[in] width The width of the read operation (unused in this function).
|
||||
*
|
||||
* @return Always returns true.
|
||||
*
|
||||
* @pre vcpu != NULL
|
||||
* @pre vcpu->vm != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static bool vuart_read(struct acrn_vcpu *vcpu, uint16_t offset_arg, __unused size_t width)
|
||||
{
|
||||
@ -628,6 +725,27 @@ static void vuart_deinit_connection(struct acrn_vuart *vu)
|
||||
vu->target_vu = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if any of the vUARTs in the given VM uses the specified INTx interrupt.
|
||||
*
|
||||
* This function checks whether the INTx interrupt is already used by vUART. It's usually used when the hypervisor
|
||||
* tries to add a new INTx remapping.
|
||||
*
|
||||
* It will check all the vUARTs in the VM to see if any of them uses the specified INTx interrupt. If any of the vUARTs
|
||||
* is active and using the specified INTx interrupt, the function will return true. Otherwise, it will return false.
|
||||
*
|
||||
* @param[in] vm Pointer to the VM.
|
||||
* @param[in] intx_gsi The INTx interrupt number to check against the vUART configurations.
|
||||
*
|
||||
* @return A boolean value indicating if any of the vUARTs in the VM uses the specified INTx interrupt.
|
||||
*
|
||||
* @retval true If any of the vUARTs in the VM uses the specified INTx interrupt.
|
||||
* @retval false If none of the vUARTs in the VM uses the specified INTx interrupt.
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_gsi)
|
||||
{
|
||||
uint8_t i;
|
||||
@ -641,6 +759,28 @@ bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_gsi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize legacy virtual UART devices.
|
||||
*
|
||||
* This function initializes the legacy virtual UARTs (vUARTs) in hypervisor. A vUART is emulated as a 16550 UART device
|
||||
* and can exchange data between the hypervisor and a VM or between two VMs. It sets up the necessary configurations and
|
||||
* resources required for the vUARTs to function correctly. This function is usually called during VM creation.
|
||||
*
|
||||
* A VM can have several vUARTs (including legacy and PCI vUARTs). The first vUART is used for the VM console, and the
|
||||
* rest are used for communication between VMs. Every legacy vUART device defined in the vUART configuration list is
|
||||
* initialized and configured. It will also register port I/O handlers for every vUART device and set up the connection
|
||||
* between vUARTs for communication.
|
||||
*
|
||||
* @param[inout] vm Pointer to the VM that owns the vUART devices.
|
||||
* @param[in] vu_config Pointer to the vUART configuration structure list that contains the configuration information.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vm != NULL
|
||||
* @pre vu_config != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void init_legacy_vuarts(struct acrn_vm *vm, const struct vuart_config *vu_config)
|
||||
{
|
||||
uint8_t i;
|
||||
@ -668,6 +808,24 @@ void init_legacy_vuarts(struct acrn_vm *vm, const struct vuart_config *vu_config
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize legacy virtual UART devices.
|
||||
*
|
||||
* This function deinitializes the legacy virtual UARTs (vUARTs) in hypervisor. It cleans up the resources and
|
||||
* configurations that were set up for the vUARTs during initialization. This function should be called when the vUARTs
|
||||
* are no longer needed, such as when a VM is being destroyed.
|
||||
*
|
||||
* The function will deinitialize all vUARTs associated with the given VM. It will set the active flag to false and
|
||||
* remove the connection between vUARTs for communication.
|
||||
*
|
||||
* @param[inout] vm Pointer to the VM that owns the vUART devices.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vm != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void deinit_legacy_vuarts(struct acrn_vm *vm)
|
||||
{
|
||||
uint8_t i;
|
||||
@ -683,6 +841,26 @@ void deinit_legacy_vuarts(struct acrn_vm *vm)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a PCI virtual UART device.
|
||||
*
|
||||
* This function initializes a PCI-based virtual UART (vUART) in hypervisor. A MCS9900 controller is emulated as a PCI
|
||||
* device, and the vUART device is a part of the MCS9900 controller. This function is usually called during the VM
|
||||
* creation and after the MCS9900 controller device is initialized.
|
||||
*
|
||||
* A VM can have several vUARTs (including legacy and PCI vUARTs). The first vUART is used for the VM console, and the
|
||||
* rest are used for communication between VMs. The PCI vUARTs are only used for communication between VMs for now. It
|
||||
* will initialize the vUART associated with the given PCI device and set up the connection between vUARTs for
|
||||
* communication.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the PCI device that owns the vUART.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void init_pci_vuart(struct pci_vdev *vdev)
|
||||
{
|
||||
struct acrn_vuart *vu = vdev->priv_data;
|
||||
@ -705,6 +883,24 @@ void init_pci_vuart(struct pci_vdev *vdev)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize a PCI virtual UART device.
|
||||
*
|
||||
* This function deinitializes a PCI virtual UART (vUART) in hypervisor. It cleans up the resources and configurations
|
||||
* that were set up for the vUART during initialization. This function should be called when the vUART is no longer
|
||||
* needed, such as when a VM is being destroyed.
|
||||
*
|
||||
* The function will deinitialize the vUART associated with the given PCI device. It will set the active flag to false
|
||||
* and remove the connection between vUARTs for communication.
|
||||
*
|
||||
* @param[inout] vdev Pointer to the PCI device that owns the vUART.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
void deinit_pci_vuart(struct pci_vdev *vdev)
|
||||
{
|
||||
struct acrn_vuart *vu = vdev->priv_data;
|
||||
@ -715,3 +911,7 @@ void deinit_pci_vuart(struct pci_vdev *vdev)
|
||||
vuart_deinit_connection(vu);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -111,7 +111,7 @@
|
||||
/* CPUID.07H:ECX.PKE */
|
||||
#define CPUID_ECX_PKE (1U<<3U)
|
||||
/* CPUID.07H:ECX.WAITPKG */
|
||||
#define CPUID_ECX_WAITPKG (1U<<5U)
|
||||
#define CPUID_ECX_WAITPKG (1U<<5U)
|
||||
/* CPUID.07H:ECX.CET_SS */
|
||||
#define CPUID_ECX_CET_SS (1U<<7U)
|
||||
/* CPUID.07H:ECX.LA57 */
|
||||
|
@ -64,4 +64,5 @@ int32_t hyperv_rdmsr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *rval);
|
||||
void hyperv_init_time(struct acrn_vm *vm);
|
||||
void hyperv_init_vcpuid_entry(uint32_t leaf, uint32_t subleaf, uint32_t flags,
|
||||
struct vcpuid_entry *entry);
|
||||
void hyperv_page_destory(struct acrn_vm *vm);
|
||||
#endif
|
||||
|
@ -181,6 +181,7 @@ struct acrn_vm {
|
||||
struct acrn_vrtc vrtc;
|
||||
|
||||
uint64_t intr_inject_delay_delta; /* delay of intr injection */
|
||||
uint32_t reset_control;
|
||||
} __aligned(PAGE_SIZE);
|
||||
|
||||
/*
|
||||
|
@ -12,6 +12,9 @@
|
||||
#define BIT_SLP_EN 13U
|
||||
#define BIT_WAK_STS 15U
|
||||
|
||||
#define CF9_RESET_WARM 0x6
|
||||
#define CF9_RESET_COLD 0xE
|
||||
|
||||
struct cpu_state_info {
|
||||
uint8_t px_cnt; /* count of all Px states */
|
||||
const struct acrn_pstate_data *px_data;
|
||||
@ -38,7 +41,7 @@ extern void asm_enter_s3(const struct pm_s_state_data *sstate_data, uint32_t pm1
|
||||
extern void restore_s3_context(void);
|
||||
struct cpu_state_info *get_cpu_pm_state_info(void);
|
||||
struct acpi_reset_reg *get_host_reset_reg_data(void);
|
||||
void reset_host(void);
|
||||
void reset_host(bool warm);
|
||||
void init_frequency_policy(void);
|
||||
void apply_frequency_policy(void);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation.
|
||||
* Copyright (C) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -10,6 +10,28 @@
|
||||
#include <asm/lib/spinlock.h>
|
||||
#include <board_info.h>
|
||||
|
||||
/**
|
||||
* @defgroup hwmgmt_page hwmgmt.page
|
||||
* @ingroup hwmgmt
|
||||
* @brief Support the basic paging mechanism.
|
||||
*
|
||||
* This module mainly provides the interfaces to manipulate the paging structures.
|
||||
* These operations are commonly used by:
|
||||
* 1. hypervisor's MMU (Memory Management Unit) to manage the host page tables;
|
||||
* 2. EPT to manage the extended page tables for guest.
|
||||
* It also provides the interfaces to conduct the address translation between Host Physical Address and Host Virtual
|
||||
* Address.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief All APIs to support page management.
|
||||
*
|
||||
* This file defines macros, structures and function declarations for managing memory pages.
|
||||
*/
|
||||
|
||||
#define PAGE_SHIFT 12U
|
||||
#define PAGE_SIZE (1U << PAGE_SHIFT)
|
||||
#define PAGE_MASK 0xFFFFFFFFFFFFF000UL
|
||||
@ -22,26 +44,96 @@
|
||||
/* size of the high MMIO address space: 1GB */
|
||||
#define PLATFORM_HI_MMIO_SIZE 0x40000000UL
|
||||
|
||||
/**
|
||||
* @brief Calculate the number of page map level-4(PML4) that is requested to control the memory region with the
|
||||
* specified size.
|
||||
*
|
||||
* Page map level-4(PML4) table is the top-level table in the x86-64 paging hierarchy. Each entry in the PML4 table can
|
||||
* potentially map a 512 GiB region, with the entire PML4 table capable of addressing up to 256 TiB. So 1 PML4 table is
|
||||
* enough to control the entire physical address space.
|
||||
*/
|
||||
#define PML4_PAGE_NUM(size) 1UL
|
||||
/**
|
||||
* @brief Calculate the number of page directory pointer tables(PDPT) that is requested to control the memory region
|
||||
* with the specified size.
|
||||
*
|
||||
* A page directory pointer table(PDPT) can be referenced by a PML4E and each PML4E controls access to a 512-GByte
|
||||
* region. It is supposed to be called when hypervisor allocates the page-directory-pointer tables for hypervisor and
|
||||
* all VMs.
|
||||
*/
|
||||
#define PDPT_PAGE_NUM(size) (((size) + PML4E_SIZE - 1UL) >> PML4E_SHIFT)
|
||||
/**
|
||||
* @brief Calculate the number of page directories(PD) that is requested to control the memory region with the specified
|
||||
* size.
|
||||
*
|
||||
* A page directory(PD) can be referenced by a PDPTE and each PDPTE controls access to a 1-GByte region. It is supposed
|
||||
* to be called when hypervisor allocates the page directories for hypervisor and all VMs.
|
||||
*/
|
||||
#define PD_PAGE_NUM(size) (((size) + PDPTE_SIZE - 1UL) >> PDPTE_SHIFT)
|
||||
/**
|
||||
* @brief Calculate the number of page tables(PT) that is requested to control the memory region with the specified
|
||||
* size.
|
||||
*
|
||||
* A page table(PT) can be referenced by a PDE and each PDE controls access to a 2-MByte region. It is supposed to be
|
||||
* called when hypervisor allocates the page tables for hypervisor and all VMs.
|
||||
*/
|
||||
#define PT_PAGE_NUM(size) (((size) + PDE_SIZE - 1UL) >> PDE_SHIFT)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Data structure to illustrate a 4-KByte memory region with an alignment of 4-KByte.
|
||||
*
|
||||
* This data structure is used to illustrate a 4-KByte memory region with an alignment of 4-KByte, calling it a 4-KByte
|
||||
* page. It can be used to support the memory management in hypervisor and the extended page-table mechanism for VMs. It
|
||||
* can also be used when hypervisor accesses the 4-KByte aligned memory region whose size is a multiple of 4-KByte.
|
||||
*
|
||||
* @consistency N/A
|
||||
* @alignment 4096
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
struct page {
|
||||
uint8_t contents[PAGE_SIZE];
|
||||
uint8_t contents[PAGE_SIZE]; /**< A 4-KByte page in the memory. */
|
||||
} __aligned(PAGE_SIZE);
|
||||
|
||||
/**
|
||||
* @brief Data structure that contains a pool of memory pages.
|
||||
*
|
||||
* This structure is designed to manage a collection of memory pages, facilitating efficient allocation,
|
||||
* deallocation, and reuse of pages. It is typically used in scenarios where memory allocation performance
|
||||
* is critical, such as in operating systems or high-performance applications. The page pool aims to minimize
|
||||
* the overhead associated with frequent memory page allocations by maintaining a ready-to-use pool of pages.
|
||||
* It is used to support the memory management in hypervisor and the extended page-table mechanism for VMs.
|
||||
*
|
||||
* @consistency N/A
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
struct page_pool {
|
||||
struct page *start_page;
|
||||
spinlock_t lock;
|
||||
uint64_t bitmap_size;
|
||||
uint64_t *bitmap;
|
||||
uint64_t last_hint_id;
|
||||
|
||||
struct page *dummy_page;
|
||||
struct page *start_page; /**< The first page in the pool. */
|
||||
spinlock_t lock; /**< The spinlock to protect simultaneous access of the page pool. */
|
||||
/**
|
||||
* @brief A pointer to the bitmap that represents the allocation status of each page in the pool.
|
||||
*
|
||||
* The bitmap is a data structure that represents the allocation status of each page in the pool. Each bit in
|
||||
* the bitmap corresponds to a page in the pool. If the bit is set to 1, the page is allocated; otherwise, the
|
||||
* page is free. The bitmap is used to track the allocation status of each page in the pool.
|
||||
*/
|
||||
uint64_t *bitmap;
|
||||
uint64_t bitmap_size; /**< The number of bitmap. */
|
||||
uint64_t last_hint_id; /**< The last bitmap ID that is used to allocate a page. */
|
||||
/**
|
||||
* @brief A pointer to the dummy page
|
||||
*
|
||||
* This is used when there's no page available in the pool.
|
||||
*/
|
||||
struct page *dummy_page;
|
||||
};
|
||||
|
||||
struct page *alloc_page(struct page_pool *pool);
|
||||
void free_page(struct page_pool *pool, struct page *page);
|
||||
#endif /* PAGE_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -1,18 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation.
|
||||
* Copyright (C) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/**
|
||||
* @file pgtable.h
|
||||
*
|
||||
* @brief Address translation and page table operations
|
||||
*/
|
||||
#ifndef PGTABLE_H
|
||||
#define PGTABLE_H
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
/**
|
||||
* @addtogroup hwmgmt_page
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief All APIs to support page table management
|
||||
*
|
||||
* This file defines macros, structures, declarations and functions related for managing page tables.
|
||||
*
|
||||
*/
|
||||
|
||||
#define PAGE_PRESENT (1UL << 0U)
|
||||
#define PAGE_RW (1UL << 1U)
|
||||
#define PAGE_USER (1UL << 2U)
|
||||
@ -148,65 +157,129 @@
|
||||
|
||||
/**
|
||||
* @brief Page tables level in IA32 paging mode
|
||||
*
|
||||
* 4-level paging in IA32 mode may map linear addresses to 4-KByte pages, 2-MByte pages, or 1-GByte pages. The 4 levels
|
||||
* are PML4, PDPT, PD, and PT. The value to present each level is fixed.
|
||||
*/
|
||||
enum _page_table_level {
|
||||
/**
|
||||
* @brief The PML4 level in the page tables
|
||||
*/
|
||||
IA32E_PML4 = 0,
|
||||
/**
|
||||
* @brief The Page-Directory-Pointer-Table level in the page tables
|
||||
*/
|
||||
IA32E_PDPT = 1,
|
||||
/**
|
||||
* @brief The Page-Directory level in the page tables
|
||||
*/
|
||||
IA32E_PD = 2,
|
||||
/**
|
||||
* @brief The Page-Table level in the page tables
|
||||
*/
|
||||
IA32E_PT = 3,
|
||||
IA32E_PML4 = 0, /**< The Page-Map-Level-4(PML4) level in the page tables.
|
||||
* The value is fixed to 0. */
|
||||
IA32E_PDPT = 1, /**< The Page-Directory-Pointer-Table(PDPT) level in the page tables. */
|
||||
IA32E_PD = 2, /**< The Page-Directory(PD) level in the page tables. */
|
||||
IA32E_PT = 3, /**< The Page-Table(PT) level in the page tables. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Data structure that contains the related operations and properties of page table.
|
||||
*
|
||||
* This structure is used to add/modify/delete page table.
|
||||
*
|
||||
* @consistency N/A
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
struct pgtable {
|
||||
/**
|
||||
* @brief Default memory access rights.
|
||||
*
|
||||
* A linear address can be translated to a physical address by the page tables. The translation is controlled by
|
||||
* the memory access rights, as defined by the architecture's memory system design. The default memory access
|
||||
* rights can be used to set the memory access rights for a page table entry when the page table is created.
|
||||
*/
|
||||
uint64_t default_access_right;
|
||||
/**
|
||||
* @brief Mask to check if the page referenced by entry is present.
|
||||
*
|
||||
* The presence of a page is indicated by specific bits in the entry, as defined by the architecture's memory
|
||||
* system design. For example, in ept table entry it's indicated by bit0|bit1|bit2, and in mmu table entry it's
|
||||
* indicated by bit 0.
|
||||
*/
|
||||
uint64_t pgentry_present_mask;
|
||||
struct page_pool *pool;
|
||||
struct page_pool *pool; /**< Pointer to the page pool used for managing pages. */
|
||||
/**
|
||||
* @brief Function to check if large pages are supported.
|
||||
*
|
||||
* This function is used to check if large pages are supported for a specific page table level and memory access
|
||||
* rights.
|
||||
*/
|
||||
bool (*large_page_support)(enum _page_table_level level, uint64_t prot);
|
||||
void (*clflush_pagewalk)(const void *p);
|
||||
void (*tweak_exe_right)(uint64_t *entry);
|
||||
void (*recover_exe_right)(uint64_t *entry);
|
||||
void (*clflush_pagewalk)(const void *p); /**< Function to flush a page table entry from the cache. */
|
||||
void (*tweak_exe_right)(uint64_t *entry); /**< Function to tweak execution rights for an entry. */
|
||||
void (*recover_exe_right)(uint64_t *entry); /**< Function to recover execution rights for an entry. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Check whether the page referenced by the specified paging-structure entry is present or not.
|
||||
*
|
||||
* This function is used to check if the page referenced is present. A paging-structure entry references a page. The
|
||||
* presence of a page is indicated by specific bits in the entry, as defined by the architecture's memory system design.
|
||||
* For example, in ept table entry it's indicated by bit0|bit1|bit2, and in mmu table entry it's indicated by bit 0.
|
||||
*
|
||||
* This function checks whether the page referenced exists based on specific bits.
|
||||
*
|
||||
* @param[in] table A pointer to the structure pgtable which provides the mask to check whether page referenced is
|
||||
* present or not.
|
||||
* @param[in] pte The paging-structure entry to check.
|
||||
*
|
||||
* @return A boolean value indicating if the page referenced by the specified paging-structure entry is present
|
||||
*
|
||||
* @retval true Indicates the page referenced is present.
|
||||
* @retval false Indicates the page referenced is not present.
|
||||
*
|
||||
* @pre table != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline bool pgentry_present(const struct pgtable *table, uint64_t pte)
|
||||
{
|
||||
return ((table->pgentry_present_mask & (pte)) != 0UL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Address space translation
|
||||
* @brief Translate a host physical address to a host virtual address before paging mode enabled.
|
||||
*
|
||||
* @addtogroup acrn_mem ACRN Memory Management
|
||||
* @{
|
||||
*/
|
||||
/* hpa <--> hva, now it is 1:1 mapping */
|
||||
/**
|
||||
* @brief Translate host-physical address to host-virtual address
|
||||
* This function is used to translate a host physical address to a host virtual address before paging mode enabled. HPA
|
||||
* is 1:1 mapping to HVA.
|
||||
*
|
||||
* @param[in] x The specified host-physical address
|
||||
* It returns the host virtual address that corresponds to the given host physical address.
|
||||
*
|
||||
* @return The translated host-virtual address
|
||||
* @param[in] x The host physical address
|
||||
*
|
||||
* @return The translated host virtual address
|
||||
*
|
||||
* @retval NULL if x == 0
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark This function is used before paging mode enabled.
|
||||
*/
|
||||
static inline void *hpa2hva_early(uint64_t x)
|
||||
{
|
||||
return (void *)x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translate host-virtual address to host-physical address
|
||||
* @brief Translate a host virtual address to a host physical address before paging mode enabled.
|
||||
*
|
||||
* @param[in] x The specified host-virtual address
|
||||
* This function is used to translate a host virtual address to a host physical address before paging mode enabled. HVA
|
||||
* is 1:1 mapping to HPA.
|
||||
*
|
||||
* @return The translated host-physical address
|
||||
* It returns the host physical address that corresponds to the given host virtual address.
|
||||
*
|
||||
* @param[in] x The host virtual address to be translated
|
||||
*
|
||||
* @return The translated host physical address
|
||||
*
|
||||
* @retval 0 if x == NULL
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark This function is used before paging mode enabled.
|
||||
*/
|
||||
static inline uint64_t hva2hpa_early(void *x)
|
||||
{
|
||||
@ -214,22 +287,47 @@ static inline uint64_t hva2hpa_early(void *x)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translate host-physical address to host-virtual address
|
||||
* @brief Translate a host physical address to a host virtual address.
|
||||
*
|
||||
* @param[in] x The specified host-physical address
|
||||
* This function is used to translate a host physical address to a host virtual address. HPA is 1:1 mapping to HVA.
|
||||
*
|
||||
* @return The translated host-virtual address
|
||||
* It returns the host virtual address that corresponds to the given host physical address.
|
||||
*
|
||||
* @param[in] x The host physical address to be translated.
|
||||
*
|
||||
* @return The translated host virtual address
|
||||
*
|
||||
* @retval NULL if x == 0
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark This function is used after paging mode enabled.
|
||||
*/
|
||||
static inline void *hpa2hva(uint64_t x)
|
||||
{
|
||||
return (void *)x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translate host-virtual address to host-physical address
|
||||
* @brief Translate a host virtual address to a host physical address.
|
||||
*
|
||||
* @param[in] x The specified host-virtual address
|
||||
* This function is used to translate a host virtual address to a host physical address. HVA is 1:1 mapping to HPA.
|
||||
*
|
||||
* @return The translated host-physical address
|
||||
* It returns the host physical address that corresponds to the given host virtual address.
|
||||
*
|
||||
* @param[in] x The host virtual address to be translated.
|
||||
*
|
||||
* @return The translated host physical address.
|
||||
*
|
||||
* @retval 0 if x == NULL
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*
|
||||
* @remark This function is used after paging mode enabled.
|
||||
*/
|
||||
static inline uint64_t hva2hpa(const void *x)
|
||||
{
|
||||
@ -271,21 +369,101 @@ static inline uint64_t *pde_page_vaddr(uint64_t pde)
|
||||
return hpa2hva(pde & PDE_PFN_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the page map level-4 table entry(PML4E) for a specified input address.
|
||||
*
|
||||
* The page map level-4 table(PML4T) contains 512 entries, each of which points to a page directory pointer table(PDPT).
|
||||
* Address has the index to the PML4E in PML4T. This function is used to calculate the address of PML4E. It is typically
|
||||
* used during the page translation process.
|
||||
*
|
||||
* It will return a pointer to the page map level-4 table entry(PML4E).
|
||||
*
|
||||
* @param[in] pml4_page A pointer to a page map level-4 table(PML4T) page.
|
||||
* @param[in] addr The address value for which the page map level-4 table entry(PML4E) address is to be calculated.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
*
|
||||
* @return A pointer to the PML4E.
|
||||
*
|
||||
* @pre pml4_page != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline uint64_t *pml4e_offset(uint64_t *pml4_page, uint64_t addr)
|
||||
{
|
||||
return pml4_page + pml4e_index(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the page directory pointer table entry(PDPTE) for a specified input address.
|
||||
*
|
||||
* The page directory pointer table(PDPT) is referenced by a page map level-4 table entry(PML4E) and echo entry(PDPTE)
|
||||
* in PDPT points to a page directory table(PDT). Address has the index to the PDPTE in PDPT. This function is used to
|
||||
* calculate the address of PDPTE. It is typically used during the page translation process.
|
||||
*
|
||||
* It will return a pointer to the page directory pointer table entry(PDPTE).
|
||||
*
|
||||
* @param[in] pml4e A pointer to a page map level-4 table entry(PML4E).
|
||||
* @param[in] addr The address for which the page directory pointer table entry(PDPTE) address is to be calculated.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
*
|
||||
* @return A pointer to the PDPTE.
|
||||
*
|
||||
* @pre pml4e != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline uint64_t *pdpte_offset(const uint64_t *pml4e, uint64_t addr)
|
||||
{
|
||||
return pml4e_page_vaddr(*pml4e) + pdpte_index(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the page directory table entry(PDE) for a specified input address.
|
||||
*
|
||||
* The page directory table(PDT) is referenced by a page directory pointer table entry(PDPTE) and echo entry(PDE) in PDT
|
||||
* points to a page table(PT). Address has the index to the PDE in PDT. This function is used to calculate the address
|
||||
* of PDE. It is typically used during the page translation process.
|
||||
*
|
||||
* It will return a pointer to the page directory table entry(PDE).
|
||||
*
|
||||
* @param[in] pdpte A pointer to a page directory pointer table entry(PDPTE).
|
||||
* @param[in] addr The address for which the page directory table entry(PDE) address is to be calculated.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
*
|
||||
* @return A pointer to the PDE.
|
||||
*
|
||||
* @pre pdpte != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline uint64_t *pde_offset(const uint64_t *pdpte, uint64_t addr)
|
||||
{
|
||||
return pdpte_page_vaddr(*pdpte) + pde_index(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the page table entry(PTE) for a specified input address.
|
||||
*
|
||||
* The page table entry(PTE) is the entry that maps a page. This function is used to calculate the address of the PTE.
|
||||
* It is typically used during the page translation process. The function is essential for managing memory access
|
||||
* permissions and for implementing memory systems.
|
||||
*
|
||||
* It will return the address of a page table entry(PTE).
|
||||
*
|
||||
* @param[in] pde A pointer to a page directory entry(PDE).
|
||||
* @param[in] addr The address for which the page table entry(PTE) address is to be calculated.
|
||||
* For hypervisor's MMU, it is the host virtual address.
|
||||
* For each VM's EPT, it is the guest physical address.
|
||||
*
|
||||
* @return A pointer to the page table entry(PTE).
|
||||
*
|
||||
* @pre pde != NULL
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline uint64_t *pte_offset(const uint64_t *pde, uint64_t addr)
|
||||
{
|
||||
return pde_page_vaddr(*pde) + pte_index(addr);
|
||||
@ -308,11 +486,51 @@ static inline void set_pgentry(uint64_t *ptep, uint64_t pte, const struct pgtabl
|
||||
table->clflush_pagewalk(ptep);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the PS flag of the specified page directory table entry(PDE) is 1 or not.
|
||||
*
|
||||
* PS(Page Size) flag in PDE indicates whether maps a 2-MByte page or references a page table. This function checks this
|
||||
* flag. This function is typically used in the context of setting up or modifying page tables where it's necessary to
|
||||
* distinguish between large and regular page mappings.
|
||||
*
|
||||
* It returns the value that bit 7 is 1 if the specified PDE maps a 2-MByte page, or 0 if references a page table.
|
||||
*
|
||||
* @param[in] pde The page directory table entry(PDE) to check.
|
||||
*
|
||||
* @return The value of PS flag in the PDE.
|
||||
*
|
||||
* @retval PAGE_PSE indicating mapping to a 2-MByte page.
|
||||
* @retval 0 indicating reference to a page table.
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline uint64_t pde_large(uint64_t pde)
|
||||
{
|
||||
return pde & PAGE_PSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the PS flag of the specified page directory pointer table entry(PDPTE) is 1 or not.
|
||||
*
|
||||
* PS(Page Size) flag in PDPTE indicates whether maps a 1-GByte page or references a page directory table. This function
|
||||
* checks this flag. This function is typically used in the context of setting up or modifying page tables where it's
|
||||
* necessary to distinguish between large and regular page mappings.
|
||||
*
|
||||
* It returns the value that bit 7 is 1 if the specified PDPTE maps a 1-GByte page, and 0 if references a page table.
|
||||
*
|
||||
* @param[in] pdpte The page directory pointer table entry(PDPTE) to check.
|
||||
*
|
||||
* @return The value of PS flag in the PDPTE.
|
||||
*
|
||||
* @retval PAGE_PSE indicating mapping to a 1-GByte page.
|
||||
* @retval 0 indicating reference to a page directory table.
|
||||
*
|
||||
* @pre N/A
|
||||
*
|
||||
* @post N/A
|
||||
*/
|
||||
static inline uint64_t pdpte_large(uint64_t pdpte)
|
||||
{
|
||||
return pdpte & PAGE_PSE;
|
||||
@ -335,7 +553,8 @@ void pgtable_add_map(uint64_t *pml4_page, uint64_t paddr_base,
|
||||
void pgtable_modify_or_del_map(uint64_t *pml4_page, uint64_t vaddr_base,
|
||||
uint64_t size, uint64_t prot_set, uint64_t prot_clr,
|
||||
const struct pgtable *table, uint32_t type);
|
||||
#endif /* PGTABLE_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* PGTABLE_H */
|
||||
*/
|
@ -473,7 +473,7 @@ static inline uint16_t dma_frcd_up_sid(uint64_t up_sid)
|
||||
}
|
||||
|
||||
#define MAX_DRHDS DRHD_COUNT
|
||||
#define MAX_DRHD_DEVSCOPES 16U
|
||||
#define MAX_DRHD_DEVSCOPES DRHD_MAX_DEVSCOPE_COUNT
|
||||
|
||||
#define DMAR_CONTEXT_TRANSLATION_TYPE_TRANSLATED 0x00U
|
||||
#define DMAR_CONTEXT_TRANSLATION_TYPE_RESERVED 0x01U
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
* Copyright (C) 2024 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -7,6 +7,25 @@
|
||||
#ifndef VRTC_H
|
||||
#define VRTC_H
|
||||
|
||||
/**
|
||||
* @defgroup vp-dm_vperipheral vp-dm.vperipheral
|
||||
* @ingroup vp-dm
|
||||
* @brief Implementation of virtual peripheral devices in hypervisor.
|
||||
*
|
||||
* This module implements the virtualization of all peripheral devices in hypervisor. The virtual device initial
|
||||
* function is usually called by the VM initialization function and registers their port IO and memory IO access
|
||||
* functions. So when a guest VM accesses its peripheral device by port IO or memory IO, it would cause VM exit and then
|
||||
* call their registered functions.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Definitions for the virtual RTC device.
|
||||
*
|
||||
* This file defines types and data structure for the virtual RTC device.
|
||||
*/
|
||||
|
||||
typedef int32_t time_t;
|
||||
|
||||
/* Register layout of the RTC */
|
||||
@ -29,17 +48,34 @@ struct rtcdev {
|
||||
uint8_t century;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Data structure to illustrate a virtual RTC device.
|
||||
*
|
||||
* This structure contains the information of a virtual RTC device.
|
||||
*
|
||||
* @consistency self.vm->vrtc == self
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
struct acrn_vrtc {
|
||||
struct acrn_vm *vm;
|
||||
uint32_t addr; /* RTC register to read or write */
|
||||
|
||||
time_t base_rtctime; /* Base time calulated from physical rtc register. */
|
||||
time_t offset_rtctime; /* RTC offset against base time. */
|
||||
time_t last_rtctime; /* Last RTC time, to keep monotonicity. */
|
||||
|
||||
uint64_t base_tsc; /* Base tsc value */
|
||||
|
||||
struct rtcdev rtcdev; /* RTC register */
|
||||
struct acrn_vm *vm; /**< Pointer to the VM that owns the virtual RTC device. */
|
||||
/**
|
||||
* @brief The RTC register to read or write.
|
||||
*
|
||||
* To access RTC registers, the guest writes the register index to the RTC address port and then reads/writes
|
||||
* the register value from/to the RTC data port. This field is used to store the register index.
|
||||
*/
|
||||
uint32_t addr;
|
||||
time_t base_rtctime; /**< Base time calculated from physical RTC register. */
|
||||
time_t offset_rtctime; /**< RTC offset against base time. */
|
||||
time_t last_rtctime; /**< Last RTC time, to keep monotonicity. */
|
||||
uint64_t base_tsc; /**< Base TSC value. */
|
||||
struct rtcdev rtcdev; /**< Register layout of RTC. */
|
||||
};
|
||||
|
||||
#endif /* VRTC_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Neel Natu <neel@freebsd.org>
|
||||
* Copyright (c) 2018-2022 Intel Corporation.
|
||||
* Copyright (c) 2018-2024 Intel Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -32,6 +32,19 @@
|
||||
#include <asm/lib/spinlock.h>
|
||||
#include <asm/vm_config.h>
|
||||
|
||||
/**
|
||||
* @addtogroup vp-dm_vperipheral
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief All APIs to support virtual UART device.
|
||||
*
|
||||
* This file defines macros, structures and function declarations for emulating virtual UART device.
|
||||
*/
|
||||
|
||||
#define RX_BUF_SIZE CONFIG_VUART_RX_BUF_SIZE
|
||||
#define TX_BUF_SIZE CONFIG_VUART_TX_BUF_SIZE
|
||||
#define VUART_TIMER_CPU CONFIG_VUART_TIMER_PCPU
|
||||
@ -56,31 +69,41 @@ struct vuart_fifo {
|
||||
uint32_t size; /* size of the fifo */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Data structure to illustrate a virtual UART device.
|
||||
*
|
||||
* This structure contains the information of a virtual UART device.
|
||||
*
|
||||
* @consistency self.vm->vuart[X] == self
|
||||
* @alignment N/A
|
||||
*
|
||||
* @remark N/A
|
||||
*/
|
||||
struct acrn_vuart {
|
||||
uint8_t data; /* Data register (R/W) */
|
||||
uint8_t ier; /* Interrupt enable register (R/W) */
|
||||
uint8_t lcr; /* Line control register (R/W) */
|
||||
uint8_t mcr; /* Modem control register (R/W) */
|
||||
uint8_t lsr; /* Line status register (R/W) */
|
||||
uint8_t msr; /* Modem status register (R/W) */
|
||||
uint8_t fcr; /* FIFO control register (W) */
|
||||
uint8_t scr; /* Scratch register (R/W) */
|
||||
uint8_t dll; /* Baudrate divisor latch LSB */
|
||||
uint8_t dlh; /* Baudrate divisor latch MSB */
|
||||
uint8_t data; /**< Data register (R/W). */
|
||||
uint8_t ier; /**< Interrupt enable register (R/W). */
|
||||
uint8_t lcr; /**< Line control register (R/W). */
|
||||
uint8_t mcr; /**< Modem control register (R/W). */
|
||||
uint8_t lsr; /**< Line status register (R/W). */
|
||||
uint8_t msr; /**< Modem status register (R/W). */
|
||||
uint8_t fcr; /**< FIFO control register (W). */
|
||||
uint8_t scr; /**< Scratch register (R/W). */
|
||||
uint8_t dll; /**< Baudrate divisor latch LSB. */
|
||||
uint8_t dlh; /**< Baudrate divisor latch MSB. */
|
||||
|
||||
struct vuart_fifo rxfifo;
|
||||
struct vuart_fifo txfifo;
|
||||
uint16_t port_base;
|
||||
uint32_t irq;
|
||||
char vuart_rx_buf[RX_BUF_SIZE];
|
||||
char vuart_tx_buf[TX_BUF_SIZE];
|
||||
bool thre_int_pending; /* THRE interrupt pending */
|
||||
bool active;
|
||||
bool escaping; /* in escaping sequence, for console vuarts */
|
||||
struct acrn_vuart *target_vu; /* Pointer to target vuart */
|
||||
struct acrn_vm *vm;
|
||||
struct pci_vdev *vdev; /* pci vuart */
|
||||
spinlock_t lock; /* protects all softc elements */
|
||||
struct vuart_fifo rxfifo; /**< FIFO queue for received data. */
|
||||
struct vuart_fifo txfifo; /**< FIFO queue for transmitted data. */
|
||||
uint16_t port_base; /**< Base port address of the virtual UART device. */
|
||||
uint32_t irq; /**< IRQ number of the virtual UART device. */
|
||||
char vuart_rx_buf[RX_BUF_SIZE]; /**< Buffer for received data. */
|
||||
char vuart_tx_buf[TX_BUF_SIZE]; /**< Buffer for transmitted data. */
|
||||
bool thre_int_pending; /**< Whether Transmitter Holding Register Empty(THRE) interrupt is pending. */
|
||||
bool active; /**< Whether the vuart is active. */
|
||||
bool escaping; /**< Whether in escaping sequence, only for console vuarts. */
|
||||
struct acrn_vuart *target_vu; /**< Pointer to target vuart */
|
||||
struct acrn_vm *vm; /**< Pointer to the VM that owns the virtual UART device. */
|
||||
struct pci_vdev *vdev; /**< Pointer to the PCI device, only for a PCI vuart. */
|
||||
spinlock_t lock; /**< The spinlock to protect simultaneous access of all elements. */
|
||||
};
|
||||
|
||||
void init_legacy_vuarts(struct acrn_vm *vm, const struct vuart_config *vu_config);
|
||||
@ -97,3 +120,7 @@ bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_gsi);
|
||||
uint8_t vuart_read_reg(struct acrn_vuart *vu, uint16_t offset);
|
||||
void vuart_write_reg(struct acrn_vuart *vu, uint16_t offset, uint8_t value);
|
||||
#endif /* VUART_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -65,6 +65,7 @@
|
||||
#define GUEST_FLAG_PMU_PASSTHROUGH (1UL << 11U) /* Whether PMU is passed through */
|
||||
#define GUEST_FLAG_VHWP (1UL << 12U) /* Whether the VM supports vHWP */
|
||||
#define GUEST_FLAG_VTM (1UL << 13U) /* Whether the VM supports virtual thermal monitor */
|
||||
#define GUEST_FLAG_STATELESS (1UL << 14U) /* Whether the VM is stateless (can be forcefully shutdown with no data loss) */
|
||||
|
||||
/* TODO: We may need to get this addr from guest ACPI instead of hardcode here */
|
||||
#define VIRTUAL_SLEEP_CTL_ADDR 0x400U /* Pre-launched VM uses ACPI reduced HW mode and sleep control register */
|
||||
|
@ -11,6 +11,6 @@ void uart16550_init(__unused bool early_boot) {}
|
||||
|
||||
bool is_pci_dbg_uart(__unused union pci_bdf bdf_value) { return false; }
|
||||
|
||||
bool get_pio_dbg_uart_cfg(__unused uint64_t *pio_address, __unused uint64_t *nbytes) {
|
||||
bool get_pio_dbg_uart_cfg(__unused uint16_t *pio_address, __unused uint32_t *nbytes) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
import board_cfg_lib
|
||||
import acrn_config_utilities
|
||||
|
||||
@ -190,7 +192,7 @@ def drhd_info_parser(config):
|
||||
Parse DRHD information
|
||||
:param config: it is a file pointer to write acpi information
|
||||
"""
|
||||
prev_num = 0
|
||||
has_drhd_max_devscope_count = False
|
||||
|
||||
drhd_lines = board_cfg_lib.get_info(
|
||||
acrn_config_utilities.BOARD_INFO_FILE, "<DRHD_INFO>", "</DRHD_INFO>")
|
||||
@ -200,7 +202,18 @@ def drhd_info_parser(config):
|
||||
|
||||
if not drhd_lines:
|
||||
print("\n#define DRHD_COUNT\t\t8U", file=config)
|
||||
print("\n#define DRHD_MAX_DEVSCOPE_COUNT\t16U", file=config)
|
||||
return
|
||||
|
||||
for drhd in drhd_lines:
|
||||
if "DRHD_MAX_DEVSCOPE_COUNT" in drhd:
|
||||
has_drhd_max_devscope_count = True
|
||||
break
|
||||
|
||||
if not has_drhd_max_devscope_count:
|
||||
logging.warning("DRHD_MAX_DEVSCOPE_COUNT is not defined in board.xml, using default 16U. "
|
||||
"Generate board.xml with latest board inspector to remove this warning.")
|
||||
print("\n#define DRHD_MAX_DEVSCOPE_COUNT\t16U", file=config)
|
||||
|
||||
for drhd in drhd_lines:
|
||||
print(drhd.strip(), file=config)
|
||||
|
@ -360,6 +360,7 @@ def write_dmar_data(sysnode, config):
|
||||
dmar_tbl, dmar_hw_list, dmar_dev_list, sysnode)
|
||||
|
||||
print("\t#define DRHD_COUNT {0}U".format(drhd_cnt), file=config)
|
||||
print("\t#define DRHD_MAX_DEVSCOPE_COUNT {0}U".format(max(dmar_dev_list.dev_scope_cnt_list)), file=config)
|
||||
print("", file=config)
|
||||
prev_dev_scope_num = 0
|
||||
for drhd_hw_i in range(drhd_cnt):
|
||||
|
@ -40,12 +40,17 @@
|
||||
"chokidar": {
|
||||
"braces": "3.0.3"
|
||||
}
|
||||
},
|
||||
"vue": {
|
||||
"postcss": {
|
||||
"nanoid": "3.3.8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1.0.0-rc.10",
|
||||
"@types/node": "^16.11.33",
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
"vite": "^2.9.16"
|
||||
"vite": ">=3.2.11"
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,19 @@ version = 3
|
||||
name = "acrn-configurator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"dirs",
|
||||
"glob",
|
||||
"idna",
|
||||
"itertools",
|
||||
"log",
|
||||
"openssl",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -159,7 +164,7 @@ dependencies = [
|
||||
"polling",
|
||||
"rustix",
|
||||
"slab",
|
||||
"socket2",
|
||||
"socket2 0.4.9",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
@ -609,22 +614,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.8"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
@ -800,6 +801,17 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.1"
|
||||
@ -1004,9 +1016,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
|
||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
@ -1568,7 +1580,7 @@ dependencies = [
|
||||
"httpdate",
|
||||
"itoa 1.0.9",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.4.9",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@ -1621,6 +1633,124 @@ dependencies = [
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_locid"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"litemap",
|
||||
"tinystr",
|
||||
"writeable",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_locid_transform"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_locid",
|
||||
"icu_locid_transform_data",
|
||||
"icu_provider",
|
||||
"tinystr",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_locid_transform_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_normalizer_data",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"smallvec",
|
||||
"utf16_iter",
|
||||
"utf8_iter",
|
||||
"write16",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_locid_transform",
|
||||
"icu_properties_data",
|
||||
"icu_provider",
|
||||
"tinystr",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_locid",
|
||||
"icu_provider_macros",
|
||||
"stable_deref_trait",
|
||||
"tinystr",
|
||||
"writeable",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider_macros"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@ -1629,12 +1759,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
||||
checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
"icu_normalizer",
|
||||
"icu_properties",
|
||||
"smallvec",
|
||||
"utf8_iter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1836,9 +1968,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
version = "0.2.171"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||
|
||||
[[package]]
|
||||
name = "line-wrap"
|
||||
@ -1855,6 +1987,12 @@ version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.10"
|
||||
@ -2000,13 +2138,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2155,16 +2293,6 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.11"
|
||||
@ -2252,9 +2380,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.60"
|
||||
version = "0.10.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800"
|
||||
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
@ -2284,9 +2412,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.96"
|
||||
version = "0.9.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f"
|
||||
checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@ -2393,9 +2521,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
@ -2543,9 +2671,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.10"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@ -3249,9 +3377,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.0"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
@ -3263,6 +3391,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soup2"
|
||||
version = "0.2.1"
|
||||
@ -3372,6 +3510,17 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-locale"
|
||||
version = "0.2.4"
|
||||
@ -3796,35 +3945,28 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
name = "tinystr"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
"displaydoc",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.43.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
checksum = "492a604e2fd7f814268a378409e6c92b5525d747d10db9a229723f55a417958c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"windows-sys 0.48.0",
|
||||
"socket2 0.5.9",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3998,27 +4140,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.1"
|
||||
@ -4027,9 +4154,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.4.0"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
|
||||
checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
@ -4043,6 +4170,18 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf16_iter"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.4.1"
|
||||
@ -4821,6 +4960,18 @@ dependencies = [
|
||||
"wayland-protocols",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "write16"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||
|
||||
[[package]]
|
||||
name = "wry"
|
||||
version = "0.24.10"
|
||||
@ -4927,6 +5078,30 @@ version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
"yoke-derive",
|
||||
"zerofrom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke-derive"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "3.14.1"
|
||||
@ -4993,6 +5168,49 @@ dependencies = [
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
|
||||
dependencies = [
|
||||
"zerofrom-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom-derive"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
|
||||
dependencies = [
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerovec-derive"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "3.15.0"
|
||||
|
@ -15,6 +15,11 @@ rust-version = "1.57"
|
||||
tauri-build = { version = "1.5.2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
openssl = "0.10.72" # fix vulnerability only
|
||||
idna = "=1.0.0" # fix vulnerability only
|
||||
url = "=2.5.1" # fix vulnerability only
|
||||
tokio = "=1.43.1" # fix vulnerability only
|
||||
crossbeam-channel = "=0.5.15" # fix vulnerability only
|
||||
serde_json = "1.0.81"
|
||||
serde = { version = "1.0.137", features = ["derive"] }
|
||||
tauri = { version = "1.6.7", features = ["api-all", "devtools"] }
|
||||
|
@ -303,12 +303,18 @@ def generate_for_one_vm(board_etree, hv_scenario_etree, vm_scenario_etree, vm_id
|
||||
for ivshmem in eval_xpath_all(vm_scenario_etree, f"//IVSHMEM_REGION[PROVIDED_BY = 'Device Model' and .//VM_NAME = '{vm_name}']"):
|
||||
vbdf = eval_xpath(ivshmem, f".//VBDF/text()")
|
||||
slot = get_slot_by_vbdf(vbdf)
|
||||
script.add_virtual_device("ivshmem", slot, options=f"dm:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text}")
|
||||
if ivshmem.find('IVSHMEM_REGION_ID') is not None:
|
||||
script.add_virtual_device("ivshmem", slot, options=f"dm:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text},{ivshmem.find('IVSHMEM_REGION_ID').text}")
|
||||
else:
|
||||
script.add_virtual_device("ivshmem", slot, options=f"dm:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text},{0}")
|
||||
|
||||
for ivshmem in eval_xpath_all(vm_scenario_etree, f"//IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor' and .//VM_NAME = '{vm_name}']"):
|
||||
vbdf = eval_xpath(ivshmem, f".//VBDF/text()")
|
||||
slot = get_slot_by_vbdf(vbdf)
|
||||
script.add_virtual_device("ivshmem", slot, options=f"hv:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text}")
|
||||
if ivshmem.find('IVSHMEM_REGION_ID') is not None:
|
||||
script.add_virtual_device("ivshmem", slot, options=f"hv:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text},{ivshmem.find('IVSHMEM_REGION_ID').text}")
|
||||
else:
|
||||
script.add_virtual_device("ivshmem", slot, options=f"hv:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text},{0}")
|
||||
|
||||
if eval_xpath(vm_scenario_etree, ".//console_vuart/text()") == "PCI":
|
||||
script.add_virtual_device("uart", options="vuart_idx:0")
|
||||
|
@ -216,7 +216,7 @@ If your VM is not a security VM, leave this option unchecked. </xs:documentation
|
||||
<xs:documentation>Maximum number of User VMs allowed.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="MAX_IOAPIC_NUM" default="1">
|
||||
<xs:element name="MAX_IOAPIC_NUM" minOccurs="0">
|
||||
<xs:annotation acrn:views="">
|
||||
<xs:documentation>Maximum number of IOAPICs.</xs:documentation>
|
||||
</xs:annotation>
|
||||
@ -250,7 +250,7 @@ If your VM is not a security VM, leave this option unchecked. </xs:documentation
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="MAX_IOAPIC_LINES" default="120">
|
||||
<xs:element name="MAX_IOAPIC_LINES" minOccurs="0">
|
||||
<xs:annotation acrn:views="">
|
||||
<xs:documentation>Maximum number of interrupt lines per IOAPIC.</xs:documentation>
|
||||
</xs:annotation>
|
||||
@ -487,6 +487,11 @@ These settings can only be changed at build time.</xs:documentation>
|
||||
<xs:documentation>Specify TPM2 FIXUP for VM.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="stateless" type="Boolean" default="n" minOccurs="0">
|
||||
<xs:annotation acrn:title="Stateless VM" acrn:applicable-vms="pre-launched" acrn:views="advanced">
|
||||
<xs:documentation>Indicate the VM is running a stateless operating system and it can be shutdown forcefully with no data loss.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="epc_section" type="EPCSection" minOccurs="0">
|
||||
<xs:annotation acrn:title="SGX Enclave Page Cache" acrn:views="advanced" acrn:applicable-vms="pre-launched">
|
||||
<xs:documentation>Specify the Intel Software Guard Extensions (SGX) enclave page cache (EPC) section settings.</xs:documentation>
|
||||
|
@ -286,7 +286,7 @@ in megabytes. The value should be a power of 2
|
||||
and no more than 512.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="IVSHMEM_REGION_ID" type="xs:integer" default="0">
|
||||
<xs:element name="IVSHMEM_REGION_ID" type="xs:string" default="0">
|
||||
<xs:annotation acrn:title="IVSHMEM Region ID">
|
||||
<xs:documentation>A stable identification when multiple shared memory regions are provided.</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
@ -27,6 +27,7 @@ policies = [
|
||||
GuestFlagPolicy(".//vm_type = 'RTVM' and .//load_order = 'PRE_LAUNCHED_VM' and //hv/BUILD_TYPE= 'debug'", "GUEST_FLAG_PMU_PASSTHROUGH"),
|
||||
GuestFlagPolicy(".//vm_type = 'TEE_VM'", "GUEST_FLAG_TEE"),
|
||||
GuestFlagPolicy(".//vm_type = 'REE_VM'", "GUEST_FLAG_REE"),
|
||||
GuestFlagPolicy("(.//load_order = 'PRE_LAUNCHED_VM' and .//stateless = 'y') or (.//vm_type = 'TEE_VM')", "GUEST_FLAG_STATELESS"),
|
||||
]
|
||||
|
||||
def fn(board_etree, scenario_etree, allocation_etree):
|
||||
|
@ -18,12 +18,12 @@
|
||||
<xsl:call-template name="integer-by-key-value">
|
||||
<xsl:with-param name="key" select="'MAX_IOAPIC_NUM'" />
|
||||
<xsl:with-param name="value" select="//config-data//MAX_IOAPIC_NUM/text()" />
|
||||
<xsl:with-param name="default" select="count(.//ioapic)" />
|
||||
<xsl:with-param name="default" select="acrn:max(1, count(.//ioapic))" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="integer-by-key-value">
|
||||
<xsl:with-param name="key" select="'MAX_IOAPIC_LINES'" />
|
||||
<xsl:with-param name="value" select="//config-data//MAX_IOAPIC_LINES/text()" />
|
||||
<xsl:with-param name="default" select="math:max(.//ioapic/gsi_number/text() | exslt:node-set(0))" />
|
||||
<xsl:with-param name="default" select="math:max(.//ioapic/gsi_number/text() | exslt:node-set(48))" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="msi-msix-max" />
|
||||
</xsl:template>
|
||||
|