Compare commits

..

29 Commits
master ... v3.2

Author SHA1 Message Date
wenlingz
01e0ff077b version:v3.2
Signed-off-by: wenlingz <wenling.zhang@intel.com>
2023-08-08 10:29:30 +08:00
David B. Kinder
7e28a17a53 doc: update release branch with changed docs
After the release branch is made, we continue with documentation up to
the release date.  This PR includes all those changes for the v3.2
release.

Signed-off-by: David B. Kinder <david.b.kinder@intel.com>
2023-08-07 09:30:50 -07:00
Kunhui-Li
6ad053fc88 configurator: update tauri version
update tauri version to 1.4.1 fix security vulnerability for configurator
dependent library.

Tracked-On: #8445
Signed-off-by: Kunhui-Li <kunhuix.li@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-07-19 10:40:20 +08:00
Jiaqing Zhao
cee2579e35 dm: virtio-gpu: fix uninitialized memory access
In virtio_gpu_cmd_create_blob() and virtio_gpu_cmd_resource_attach_
backing(), entries may be accessed before initialization. Fix it by
using calloc() to allocate it instead of malloc().

Tracked-On: #8439
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
2023-07-18 13:47:14 +08:00
Wu Zhou
a9860fad05 hv: bugfix: skip invalid ffs64 return value
ffs64() returns INVALID_BIT_INDEX (0xffffU) when it tries to deal with
zero input value. This may happen In calculate_logical_dest_mask() when
the guest tries to write some illegal destination IDs to MSI config
registers of a pt-device. The ffs64() return value is used as per_cpu
array index, and it would cause a page fault.

This patch adds protection to the per_cpu array, making this function
return zero on illegal value. As in logical destination's definition, a
zero logical designation would point to no CPU.

Fixes: 1334349f8
Tracked-On: #8454
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-07-14 17:05:17 +08:00
Jiaqing Zhao
b38003b870 misc: sample_application: fix setup_hmi_vm.sh for Ubuntu 22.04
In chroot environment, the running kernel is the host kernel, so uname
command cannot get the kernel verison in image. Since hmi-vm uses
GVT-d, and kernel 5.15 does not support newer iGPUs in 13th Gen
processors, this patch installs the linux-generic-hwe kernel (5.19)
instead of linux-modules-extra package.

In Ubuntu 22.04, package needrestart is installed by default to
interactively prompt user there is a pending kernel upgrade or serivces
need to be restarted in apt. This patch removes it.

Also, this patch expands hmi-vm image by 2GB to hold the new kernel and
runs 'apt autoremove' after everything is installed.

Tracked-On: #8448
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
2023-07-10 15:04:38 +08:00
David B. Kinder
3a001f9be6 Update sample app scripts for Ubuntu 22.04
The switch to Ubuntu 22.04 for ACRN v3.2 requires a few changes to the
sample application scripts:

- user _apt cannot access debian packages in user directories, so copy
  them to /tmp to install
- HMI-VM image size needs to be bigger (running out of space during
  image update)

Tracked-On: #8352

Signed-off-by: David B. Kinder <david.b.kinder@intel.com>
2023-07-10 15:04:38 +08:00
Jiaqing Zhao
1c8396abef dm: vdisplay_sdl: fix command line option parsing
strcasestr() returns NULL if specified substring is not found, which
should be handled when parsing the command line options.

Tracked-On: #8439
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
2023-07-05 18:13:23 +08:00
Jiaqing Zhao
ce3f31dcb6 dm: passthrough: check romfile path length in command
This patch checks the romfile path length in command line to avoid
possible buffer overflow, maximum path supported is 255 characters.

Tracked-On: #8439
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
2023-07-05 18:13:23 +08:00
Jiaqing Zhao
b6cea37b49 dm: fix uninitialized heap access risk in virtio GPU
This patch fix potential uninitialized heap use in virtio_gpu.c file.

Tracked-On: #8439
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
2023-07-05 18:13:23 +08:00
Jiaqing Zhao
31fb783879 dm: fix NULL pointer dereference risk in vdisplay
This patch fix several issues that NULL pointers possibly be
dereferenced in display module.

Tracked-On: #8439
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
2023-07-05 18:13:23 +08:00
Jiaqing Zhao
d98901a890 dm: fix NULL pointer dereference risk in vhost vsock
Pointer 'vsock->vhost_vsock' returned from call to function
'vhost_vsock_init' may be NULL and will be dereferenced when
calling 'vhost_vsock_set_guest_cid()'.

Tracked-On: #8439
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
2023-07-05 18:13:23 +08:00
Wu Zhou
1334349f89 hv: bugfix: fix the ptdev irq destination issue
According to SDM Vol3 11.12.10, in x2APIC mode, Logical Destination has
two parts:
  - Cluster ID (LDR[31:16])
  - Logical ID (LDR[15:0])
Cluster ID is a numerical address, while Logical ID is a 16bit mask. We
can only use Logical ID to address multi destinations within a Cluster.

So we can't just 'or' all the Logical Destination in LDR registers to
get one mask for all target pCPUs. This would get a wrong destination
mask if the target Destinations are from different Clusters.

For example in ADL/RPL x2APIC LDRs for core 2-5 are 0x10001 0x10100
0x20001 0x20100. If we 'or' them together, we would get a Logical
Destination of 0x30101, which points to core 6 and another core.
If core 6 is running a RTVM, then the irq is unable to get to
core 2-5, causing the guest on core 2-5 driver fail.

Guests working in xAPIC mode may use 'Flat Model' to select an
arbitrary list of CPUs as its irq destination. HV may not be able to
include them all when transfering to physical destinations, because
the HW is working in x2APIC mode and can only use 'Cluster Model'.

There would be no perfect fix for this issue. This patch is a simple
fix, by just keep the first Cluster of all target Logical Destinations.

Tracked-On: #8435
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-07-05 17:06:09 +08:00
Jiaqing Zhao
feb1afbc3c dm: passthrough DSM region for ADL-N and RPL
The Data of Stolen Memory (DSM) region on Alder Lake-N and Raptor Lake
platform is indicated by the BDSM register (0xC0 and 0xC4 in PCI config
space), which is the same as Gen 11 (Tiger Lake) iGPU. This patch adds
ADL-N and RPL iGPU device id to passthrough the DSM region properly
when using GVT-d.

The PCI device ids are taken from i915 kernel driver.

Tracked-On: #8432
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
2023-06-25 10:33:53 +08:00
Jiaqing Zhao
080f43216c hv: sgx: refactor partition_epc()
This patch refactors partition_epc() to make the code easier to
understand, also fixes the maybe-uninitialized warning for gcc-13.

Initializing 'vm_config' to get_vm_config(0) is okay here as scenario
validator ensures CONFIG_MAX_VM_NUM to be always larger than 0.

Tracked-On: #8413
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
2023-06-13 15:43:48 +08:00
Jiaqing Zhao
56446fe366 dm: gvt: add bound check in gvt_init_config()
gvt_init_config() may perform out-of-range read on host_config, add
bound check before accessing it.

Tracked-On: #8382
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
2023-06-13 15:43:48 +08:00
Jiaqing Zhao
0016a64655 misc: life_mngr: fix use-after-free in uart channel
LIST_FOREACH() doesn't allow var to be removed or freed within the
loop, but c_dev is freed inside the loop here. gcc 12 also reports
error on it. This patch uses list_foreach_safe() macro instead for
freeing var within the loop safely.

Tracked-On: #8382
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-06-13 15:43:48 +08:00
Kunhui-Li
b1b4bc98af config_tools: fix the issue that fail to generate config_summary.rst if enable CAT
currently, configurator will fail to generate config_summary.rst file if
user enable the "Cache Allocation Technology" because note function in rstcloth
is replaced by self.doc.note.

So this patch updates function and usage to fix this issue.

fixs: 9c2d0f8 ("config_tools: replace RstCloth library with class.")
Tracked-On: #8422
Signed-off-by: Kunhui-Li <kunhuix.li@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-06-09 18:56:47 +08:00
Jiaqing Zhao
2cf158994b config_tools: remove rstcloth package
9c2d0f8858 ("config_tools: replace RstCloth library with class.")
removes all usage of rstcloth in code, but the rstcloth package is not
removed from acrn-configurator and it will still download dependencies
for rstcloth. This patch simply removes it.

Tracked-On: #8395
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-05-16 12:29:04 +08:00
Kunhui-Li
151305e8c9 config_tools: replace RstCloth library with class.
Currently, Configurator load fail because it needs to download
RstCloth related packages. This patch defines Doc class to replace
RstCloth library to fix this issue.

Tracked-On: #8395
Signed-off-by: Kunhui-Li <kunhuix.li@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-05-11 14:49:59 +08:00
wenlingz
ca99bb58a2 update CODEOWNERS in release_3.2
Tracked-On:#5581
Signed-off-by: wenlingz <wenling.zhang@intel.com>
2023-05-09 01:35:09 +08:00
Kunhui-Li
de188258f6 config_tools: capture the IOError exception
If no TURBO_RATIO_LIMIT and TURBO_ACTIVATION_RATIO MSRs info
on target, board inspector will crash because of the IOError exception.

This patch captures the IOError exception to handle this error.

Tracked-On: #8380
Signed-off-by: Kunhui-Li <kunhuix.li@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-05-04 15:10:44 +08:00
Kunhui-Li
d83d0fed47 config_tools: filter non-ascii characters in iomem infomation
If we use 5.15 kernel on rpl-p platform, some iomem info dumped with
non-ascii characters, then tool will raise a decode error.

So this patch filters non-ascii characters to handle this error.

Tracked-On: #8388
Signed-off-by: Kunhui-Li <kunhuix.li@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2023-04-25 18:05:26 +08:00
Chenli Wei
31c0362ac4 misc: fix the summary issue after update board xml
The new board xml have add a "module" node under the "processors/die"
which has cause an issue when we run the summary, this patch  use "//"
to select all "cpu_id" under the "processors".

Tracked-On: #8385
Signed-off-by: Chenli Wei <chenli.wei@intel.com>
2023-04-24 23:03:05 +08:00
Min Yang
7315ff3cf9 debian: modify kernel version display to GRUB menuentry
Tracked-On:#8359
Signed-off-by: Min Yang <minx.yang@intel.com>
2023-04-06 14:58:02 +08:00
Min Yang
5d3702af77 debian: add kernel version to GRUB menuentry
1. add kernel version to menuentry "Ubuntu-ACRN Board Inspector"
2. add kernel version and acrn version to menuentry "Ubuntu with ACRN hypervisor"

Tracked-On:#8359
Signed-off-by: Min Yang <minx.yang@intel.com>
2023-04-06 14:58:02 +08:00
Junjie Mao
c34649aafa debian/rules: change default BOARDLIST and SCENARIOLIST to empty
The variables BOARDLIST and SCENARIOLIST serve as filters of XMLs that are
found under the user-given directories, and there is no need to assume any
filter if a user does not specify that explicitly.

Update the default filters to none so that all found XMLs will be used if a
user does not state otherwise.

Tracked-On: #8246
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
2022-11-29 22:27:49 +08:00
Junjie Mao
0bde54613b debian/rules: search for XML files only
When searching for scenario XMLs that are saved under the same directory as
a board XML, debian/rules uses the wildcard `*` which includes other
non-XML files. That causes some non-XML files to be considered as scenario
XMLs as well and will cause build-time errors when the build system
attempts to parse them as XMLs.

Change the wildcard expression to `*.xml` to restrict the found files to be
XML.

Tracked-On: #8344
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
2022-11-29 22:27:49 +08:00
Jian Jun Chen
dde388d82c misc: life_mngr: revise try_receive_message_by_uart
Revise try_receive_message_by_uart to read one char from uart one time.
With this implementation each char can be checked. This can be used to
address the following 2 problems:
1) nosie data: it is found that there is noise data in the uart from
   guest VM when guest startup.
2) split multiple commands

Tracked-On: #8111
Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com>
2022-11-24 09:41:51 +08:00
258 changed files with 2661 additions and 10118 deletions

1
.gitignore vendored
View File

@ -31,7 +31,6 @@ debian/acrn-lifemngr
debian/acrn-system
debian/acrn-tools
debian/acrnd
debian/changelog
debian/debhelper-build-stamp
debian/files
debian/grub-acrn

View File

@ -13,9 +13,9 @@
* @dongyaozu @NanlinXie
Makefile @terryzouhao @NanlinXie
/hypervisor/ @dongyaozu @lifeix @junjiemao1
/hypervisor/ @dongyaozu @lifeix
/devicemodel/ @ywan170 @chejianj
/doc/ @NanlinXie
/doc/ @dbkinder @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 @NanlinXie
*.rst @dbkinder @NanlinXie

View File

@ -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:
- Yu Wang (chair): yu1.wang@intel.com
- Junjie Mao (chair): junjie.mao@intel.com
- Helmut Buchsbaum: helmut.buchsbaum@tttech-industrial.com
- Thomas Gleixner: thomas.gleixner@intel.com

View File

@ -1,3 +1,3 @@
MAJOR_VERSION=3
MINOR_VERSION=4
EXTRA_VERSION=-unstable
MINOR_VERSION=2
EXTRA_VERSION=

53
debian/changelog vendored Normal file
View File

@ -0,0 +1,53 @@
acrn-hypervisor (3.0~3.gbp9074bb) UNRELEASED; urgency=medium
** SNAPSHOT build @9074bb42223cf0a18a01ca7f5b481834ba79fc6a **
* Initial native packaging release for ACRN.
* d/rules: Update regarding config detection
* d/control: Pin elementpath and xmlschema
* debian: Add docker build helpers
* debian: Create local apt repo after build
* debian: Update and rename README.md
* debian: Add nuc7i7dnh/shared+initrd
* debian: Add kontron-COMe-mAL10/shared+initrd
* debian: Update changelog for UNRELEASED package build
* debian: Preinstall build requirements in docker helper
* debian: Silence build user creation
* life_mngr: Makefile: Use sysconfdir
* life_mngr: Makefile: Fix install path creation of CONF_DIR
* life_mngr: Makefile: Fix permission of life_mngr.conf
* debian: Fixup ACRN lifemngr package build
* debian/rules: Store board and scenario xml
* debian/grub: Adapt Linux commandline to ACRN scenario settings
* debian/grub: Remove override variable support
* debian: Use original acrnd.service
* acrn_log: Fix log path to comply with Linux FSSTD
* doc: Adapt documentation to change of acrnlog log path
* debian: Install acrnprobe.xml
* debian: linitian suppression rule update
* debian/control: Use compat level 12
* debian/rules: override_dh_strip: Fix wrong parameter
* debian: Trigger grub-acrn on acrn-hypervisor install
* debian/rules: Do not start services on install
* debian: acrn-tools: Add helper scripts
* debian: acrn-hypervisor: Refactor debconf
* debian: nuc7i7dnh/shared+initrd: Add boot parameters
* debian/configs: Add simatic-ipc227g/shared+initrd
* debian/rules: Add simatic-ipc227g
* debian: Add default configuration for acrnlog
* debian/configs: Add kontron-COMe-mAL10:shared
* debian/configs: Add nuc7i7dnh:shared
* debian/configs: Add simatic-ipc227g:shared
* debian: Separate build config items to acrn-hypervisor.conf.mk
* debian/rules: Generate launch scripts
* debian: Switch to elementpath 2.5.0-1 and xmlschema 1.10.0-1
* debian/docker: Add source package handling for local apt repository
* debian: Add build and installation description
* debian: Update README.md
* debian: Update changelog for UNRELEASED package build
* debian: Convert README.md to README.rst
* debian: Convert INSTALL.md to INSTALL.rst
* debian/acrn-doc.doc-base: Fix typo
* debian/configs: Remove proprietary configs, just provide a hook directory
-- Helmut Buchsbaum <helmut.buchsbaum@opensource.tttech-industrial.com> Mon, 09 May 2022 14:00:35 +0200

View File

@ -8,7 +8,6 @@ usage() {
echo "Usage: $0 [--board_list ACRN_BOARDLIST] [--scenario_list ACRN_SCENARIOLIST] [--config_path CONFIGDIRS] [--release n|y] [acrn | board_inspector | clean]"
echo "Optional arguments:"
echo " -h, --help show this help message and exit"
echo " -v, --verbose show verbose output"
echo " -b, --board_list list the boards to build, seperated by blank; build all scanned boards in the config path if specified as \"\"; build the default boards in debian rules if not specified"
echo " -s, --scenario_list list the scenarios to build, seperated by blank; build all scanned scenarios in the config path if specified as \"\"; build the default scenarios in debian rules if not specified"
echo " -c, --config_path specify the config path for the board and scenario configuration files, default use misc/config_tools/data if not specified"
@ -60,10 +59,6 @@ while [[ $# -gt 0 ]]; do
release="$2"
shift 2
;;
-v|--verbose)
verbose=1
shift
;;
-h|--help)
usage
exit 0
@ -81,9 +76,6 @@ done
set -- "${POSITIONAL_ARGS[@]}"
cmd="debuild"
if [ -n "$verbose" ]; then
cmd="$cmd -eDH_VERBOSE=1"
fi
if [ "$board_list" != "default" ]; then
echo "ACRN_BOARDLIST = ${board_list@Q}"
cmd="$cmd -eACRN_BOARDLIST=${board_list@Q}"

View File

@ -181,7 +181,7 @@ prepare_root_cache=
boot_device_id=
while [ "x$list" != "x" ] ; do
linux=$(echo ${list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | LC_ALL=C sort -V -r | sed -e 's/ 1$/.old/; s/ 2$//' | head -n 1)
linux=`version_find_latest $list`
case $linux in
*.efi.signed)
# We handle these in linux_entry.

View File

@ -311,7 +311,7 @@ boot_device_id=
acrn_first_entry=
while [ "x${acrn_list}" != "x" ] ; do
current_acrn=$(echo ${acrn_list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | LC_ALL=C sort -V -r | sed -e 's/ 1$/.old/; s/ 2$//' | head -n 1)
current_acrn=$(version_find_latest $acrn_list)
acrn_basename=$(basename ${current_acrn})
acrn_dirname=$(dirname ${current_acrn})
rel_acrn_dirname=$(make_system_path_relative_to_its_root $acrn_dirname)
@ -342,7 +342,7 @@ EOF
# only if we have at least one ACRN capable kernel and a Service VM entry defined
while [ "x$list" != "x" ] && [ "x${ACRN_SERVICE_VM_ID}" != "x" ] ; do
linux=$(echo ${list} | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | LC_ALL=C sort -V -r | sed -e 's/ 1$/.old/; s/ 2$//' | head -n 1)
linux=$(version_find_latest $list)
gettext_printf "Found ACRN linux image: %s\n" "$linux" >&2
basename=$(basename $linux)
dirname=$(dirname $linux)

View File

@ -80,7 +80,6 @@ LDFLAGS += -L$(TOOLS_OUT)/services
LIBS = -lrt
LIBS += -lpthread
LIBS += -lcrypto
LIBS += -luring
LIBS += -lpciaccess
LIBS += -lusb-1.0
LIBS += -lacrn-mngr
@ -188,8 +187,6 @@ SRCS += core/cmd_monitor/socket.c
SRCS += core/cmd_monitor/command.c
SRCS += core/cmd_monitor/command_handler.c
SRCS += core/cmd_monitor/cmd_monitor.c
SRCS += core/sbuf.c
SRCS += core/vm_event.c
# arch
SRCS += arch/x86/pm.c

View File

@ -42,7 +42,6 @@
#include "lpc.h"
#include "monitor.h"
#include "log.h"
#include "vm_event.h"
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
static struct mevent *power_button;
@ -193,7 +192,7 @@ void
pm_backto_wakeup(struct vmctx *ctx)
{
/* According to ACPI 5.0 Table 4-16: bit 15, WAK_STS should be
* set when system transition to the working state
* set when system trasition to the working state
*/
pm1_status |= PM1_WAK_STS;
}
@ -243,14 +242,6 @@ power_button_handler(int signal, enum ev_type type, void *arg)
inject_power_button_event(arg);
}
static void
send_poweroff_event(void)
{
struct vm_event event;
event.type = VM_EVENT_POWEROFF;
dm_send_vm_event(&event);
}
static int
pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, void *arg)
@ -274,7 +265,6 @@ pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
*/
if (*eax & VIRTUAL_PM1A_SLP_EN) {
if ((pm1_control & VIRTUAL_PM1A_SLP_TYP) >> 10 == 5) {
send_poweroff_event();
vm_suspend(ctx, VM_SUSPEND_POWEROFF);
}

View File

@ -1,5 +1,5 @@
16c698cb5e6354f514e307eb016237dd OVMF_CODE_debug.fd
e4b15beab40a0482bbe821e151c96d75 OVMF_CODE.fd
0166b812b014a4c1809d22199823132a OVMF_debug.fd
bf8d9d3c85ba06ac940ee9d6d6f9f811 OVMF.fd
3102701dfdaeab846577e139398af5b8 OVMF.fd
75f5f310da41cd7bd1dd96ddcbcff8cf OVMF_debug.fd
dca1ed6265062454a9c445d6e6e33d05 OVMF_CODE.fd
c2e1d7a8e1e4036a1d3f203dfc66bac0 OVMF_CODE_debug.fd
aa9703e68b787f1a391bcbf201c84e02 OVMF_VARS.fd

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
ed00f44b07d375d036b67d9b50b878c9c5b1bee59082b08f9e0126c06dd91914f6e9e2dc248fb1bc61350c377da284fa4150ffd2028a4daa34a6c3217047e32e OVMF_CODE_debug.fd
a958f4f5dbe8ad98565e3ac4883fcac40a67bbdd184b2e3d7c1a7974181628c20498159dec64596879af12e0710e8e70748c27337060aab7da164a83b0124f08 OVMF_CODE.fd
05e4996dd3d7a1e83aca8176ea0da4a92ea704116ea21f9b2df59f386b8bdbdb9e697731a111eaa31d994c66b66b732c105b979e4c5a7e8b6f7960145ebdf898 OVMF_debug.fd
4647bfe6a4bc0430e0c751d51d06665b5500eeaf0170826abbc6f38f94c19946a6683ce4fc2f9c2e09753546e2f4f30d65643d5b511ecd28a9e73a362db133cc OVMF.fd
6a29eba62832a4e94aec79fb726cfd507b019e5c9039e0abf2efa023fd21373f911e8e7ba0ca1e20c495409b738d513ac9ac7912c05ef7db7159569af3cb3da8 OVMF.fd
91bdb40d49a994a4b45e25144917fbedefa0710d9d95aedf633197ab3cd7d6ca9c3a075bf120c15667f863840f48612297bd48275080a31d84217da076f2b629 OVMF_debug.fd
ffbce1003d166751f842c34cdde6ae67df02a27f4388c58707d8ec3ca6da692cdeb6bae9b5eae8a8f0c55709be1852bfc84af8a2c6a8ab8e45fb0b84c3c383fd OVMF_CODE.fd
24e927b075be8071efcb5ca988537bd6593205bee5a5750e6036370a08add296d4e4966e2e326700a096167d6a8a55e0078936ae3dedd3492c9d46cc9bb0ac4a OVMF_CODE_debug.fd
6c5f0629cda9a950dd76ea4162c3e7d3483615fa6e9918da365900dbdcb84681192df70c4629237f0db19d0a27fbc574bb3d9f38a522246e5b91356cd5e5a1e5 OVMF_VARS.fd

View File

@ -1,12 +1,3 @@
OVMF release v3.3
- OvmfPkg: resolve AcrnS3Lib
- OvmfPkg: add AcrnS3Lib to support S3
- OvmfPkg: introduce AcrnS3Lib class
- OVMF:ACRN:PCI: Try to load ROM image for the PCI device with PCI_ROM
- OVMF:ACRN:PCI: Add LoadOpRomImageLight to Load the PCI Rom
- OVMF:ACRN:PCI: Write back the original value of PCI ROM
OVMF release v3.0
- VGA interface of virtio-gpu adapter support

View File

@ -99,7 +99,6 @@ static void register_socket_message_handlers(struct vmctx *ctx)
arg.ctx_arg = ctx;
register_command_handler(user_vm_destroy_handler, &arg, DESTROY);
register_command_handler(user_vm_blkrescan_handler, &arg, BLKRESCAN);
register_command_handler(user_vm_register_vm_event_client_handler, &arg, REGISTER_VM_EVENT_CLIENT);
}
int init_cmd_monitor(struct vmctx *ctx)

View File

@ -26,7 +26,6 @@
#define CMD_OBJS \
GEN_CMD_OBJ(DESTROY), \
GEN_CMD_OBJ(BLKRESCAN), \
GEN_CMD_OBJ(REGISTER_VM_EVENT_CLIENT), \
struct command dm_command_list[CMDS_NUM] = {CMD_OBJS};

View File

@ -10,9 +10,8 @@
#define DESTROY "destroy"
#define BLKRESCAN "blkrescan"
#define REGISTER_VM_EVENT_CLIENT "register_vm_event_client"
#define CMDS_NUM 3U
#define CMDS_NUM 2U
#define CMD_NAME_MAX 32U
#define CMD_ARG_MAX 320U

View File

@ -67,78 +67,6 @@ static int send_socket_ack(struct socket_dev *sock, int fd, bool normal)
return ret;
}
static struct socket_client *vm_event_client = NULL;
static pthread_mutex_t vm_event_client_mutex = PTHREAD_MUTEX_INITIALIZER;
static void vm_event_free_cb(struct socket_client *self)
{
vm_event_client = NULL;
}
static int set_vm_event_client(struct socket_client *client)
{
if (vm_event_client != NULL) {
pr_err("vm event client already registerred.\n");
return -1;
} else {
vm_event_client = client;
client->per_client_mutex = &vm_event_client_mutex;
client->free_client_cb = vm_event_free_cb;
return 0;
}
}
int vm_monitor_send_vm_event(const char *msg)
{
int ret = -1;
struct socket_client *client;
pthread_mutex_t *per_client_mutex = &vm_event_client_mutex;
pthread_mutex_lock(per_client_mutex);
client = vm_event_client;
if (msg == NULL || client == NULL) {
pthread_mutex_unlock(per_client_mutex);
return -1;
}
memset(client->buf, 0, CLIENT_BUF_LEN);
memcpy(client->buf, msg, strlen(msg));
client->len = strlen(msg);
ret = write_socket_char(client);
pthread_mutex_unlock(per_client_mutex);
return ret;
}
/* When a client issues the REGISTER_VM_EVENT_CLIENT command,
* this handler will register that client as this VM's only vm_event receiver,
* and keeps the socket connection. Then vm events will be sent to
* the client through this connection.
*/
int user_vm_register_vm_event_client_handler(void *arg, void *command_para)
{
int ret;
struct command_parameters *cmd_para = (struct command_parameters *)command_para;
struct handler_args *hdl_arg = (struct handler_args *)arg;
struct socket_dev *sock = (struct socket_dev *)hdl_arg->channel_arg;
struct socket_client *client = NULL;
bool cmd_completed = false;
client = find_socket_client(sock, cmd_para->fd);
if (client == NULL)
return -1;
if (set_vm_event_client(client) == 0) {
cmd_completed = true;
}
pr_dbg("%s: client with fd %d registerred\n", __func__, client->fd);
ret = send_socket_ack(sock, cmd_para->fd, cmd_completed);
if (ret < 0) {
pr_err("%s: Failed to send ACK message by socket.\n", __func__);
}
return ret;
}
int user_vm_destroy_handler(void *arg, void *command_para)
{
int ret;

View File

@ -9,6 +9,4 @@ extern struct socket_dev *sock_server;
int user_vm_destroy_handler(void *arg, void *command_para);
int user_vm_blkrescan_handler(void *arg, void *command_para);
int user_vm_register_vm_event_client_handler(void *arg, void *command_para);
#endif

View File

@ -47,23 +47,13 @@ err:
}
static void free_socket_client(struct socket_dev *sock, struct socket_client *client)
{
pthread_mutex_t *per_client_mutex = client->per_client_mutex;
pthread_mutex_lock(&sock->client_mtx);
LIST_REMOVE(client, list);
pthread_mutex_unlock(&sock->client_mtx);
if (per_client_mutex) {
pthread_mutex_lock(per_client_mutex);
}
if (client->free_client_cb) {
client->free_client_cb(client);
}
close(client->fd);
client->fd = -1;
free(client);
if (per_client_mutex) {
pthread_mutex_unlock(per_client_mutex);
}
}
int write_socket_char(struct socket_client *client)
@ -152,8 +142,7 @@ static struct socket_client *new_socket_client(struct socket_dev *sock)
__func__);
goto alloc_client;
}
/* If per client mutex is needed, init in callback */
client->per_client_mutex = NULL;
client->addr_len = sizeof(client->addr);
client->fd =
accept(sock->sock_fd, (struct sockaddr *)&client->addr,
@ -164,6 +153,7 @@ static struct socket_client *new_socket_client(struct socket_dev *sock)
__func__, sock->sock_fd, strerror(errno));
goto accept_con;
}
pthread_mutex_lock(&sock->client_mtx);
LIST_INSERT_HEAD(&sock->client_head, client, list);
pthread_mutex_unlock(&sock->client_mtx);

View File

@ -21,11 +21,7 @@ struct socket_client {
socklen_t addr_len;
char buf[CLIENT_BUF_LEN];
int len; /* buf len */
/* When a client is registered as vm_event receiver, we need this per_client_mutex
* to make sure it is safe to free the client when client disconnects.
*/
pthread_mutex_t *per_client_mutex;
void (*free_client_cb)(struct socket_client *self);
LIST_ENTRY(socket_client) list;
};

View File

@ -446,7 +446,7 @@ static bool release_larger_freepage(int level_limit)
if (hugetlb_priv[level].pages_delta >= 0)
continue;
/* free one un-used larger page */
/* free one unsed larger page */
orig_pages = read_sys_info(hugetlb_priv[level].nr_pages_path);
total_pages = orig_pages - 1;
snprintf(cmd_buf, MAX_PATH_LEN, "echo %d > %s",
@ -483,7 +483,7 @@ static bool release_larger_freepage(int level_limit)
*.D.enough higher level free pages, but not enough free memory for
* lower level gap pages, so release some higher level free pages for that.
* other info:
*. even enough free memory, it is easier to reserve smaller pages than
*. even enough free memory, it is eaiser to reserve smaller pages than
* lager ones, for example:2MB easier than 1GB. One flow of current solution:
*.it could leave Service VM very small free memory.
*.return value: true: success; false: failure
@ -507,8 +507,8 @@ static bool hugetlb_reserve_pages(void)
/* probably system allocates fewer pages than needed
* especially for larger page like 1GB, even there is enough
* free memory, it still can fail to allocate 1GB huge page.
* so if that, it needs the next level to handle it.
* free memory, it stil can fail to allocate 1GB huge page.
* so if that,it needs the next level to handle it.
*/
if (level > HUGETLB_LV1) {
left_gap = hugetlb_priv[level].pages_delta;
@ -555,13 +555,8 @@ bool init_hugetlb(void)
path[i] = 0;
if (access(path, F_OK) != 0) {
if (mkdir(path, 0755) < 0) {
/* 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;
}
pr_err("mkdir %s failed.\n", path);
return -1;
}
}
path[i] = '/';
@ -906,7 +901,7 @@ bool vm_allow_dmabuf(struct vmctx *ctx)
}
if (ctx->lowmem) {
/* Check the lowmem is used by HUGETLB_LV1/HUGETLB_LV2 */
/* Check the lowhmem is used by HUGETLB_LV1/HUGETLB_LV2 */
mem_flags = 0;
if ((hugetlb_priv[HUGETLB_LV1].fd > 0) &&
(hugetlb_priv[HUGETLB_LV1].lowmem))

View File

@ -14,45 +14,46 @@
#include <sys/queue.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include "iothread.h"
#include "log.h"
#include "mevent.h"
#include "dm.h"
#define MEVENT_MAX 64
static struct iothread_ctx ioctxes[IOTHREAD_NUM];
static int ioctx_active_cnt;
/* mutex to protect the free ioctx slot allocation */
static pthread_mutex_t ioctxes_mutex = PTHREAD_MUTEX_INITIALIZER;
#define MAX_EVENT_NUM 64
struct iothread_ctx {
pthread_t tid;
int epfd;
bool started;
pthread_mutex_t mtx;
};
static struct iothread_ctx ioctx;
static void *
io_thread(void *arg)
{
struct epoll_event eventlist[MEVENT_MAX];
struct iothread_mevent *aevp;
int i, n;
struct iothread_ctx *ioctx_x = (struct iothread_ctx *)arg;
int i, n, status;
char buf[MAX_EVENT_NUM];
set_thread_priority(PRIO_IOTHREAD, true);
while(ioctx_x->started) {
n = epoll_wait(ioctx_x->epfd, eventlist, MEVENT_MAX, -1);
while(ioctx.started) {
n = epoll_wait(ioctx.epfd, eventlist, MEVENT_MAX, -1);
if (n < 0) {
if (errno == EINTR) {
/* EINTR may happen when io_uring fd is monitored, it is harmless. */
continue;
} else {
if (errno == EINTR)
pr_info("%s: exit from epoll_wait\n", __func__);
else
pr_err("%s: return from epoll wait with errno %d\r\n", __func__, errno);
break;
}
break;
}
for (i = 0; i < n; i++) {
aevp = eventlist[i].data.ptr;
if (aevp && aevp->run) {
/* Mitigate the epoll_wait repeat cycles by reading out the events as more as possile.*/
do {
status = read(aevp->fd, buf, sizeof(buf));
} while (status == MAX_EVENT_NUM);
(*aevp->run)(aevp->arg);
}
}
@ -62,54 +63,36 @@ io_thread(void *arg)
}
static int
iothread_start(struct iothread_ctx *ioctx_x)
iothread_start(void)
{
int ret;
pthread_mutex_lock(&ioctx.mtx);
pthread_mutex_lock(&ioctx_x->mtx);
if (ioctx_x->started) {
pthread_mutex_unlock(&ioctx_x->mtx);
if (ioctx.started) {
pthread_mutex_unlock(&ioctx.mtx);
return 0;
}
if (pthread_create(&ioctx_x->tid, NULL, io_thread, ioctx_x) != 0) {
pthread_mutex_unlock(&ioctx_x->mtx);
if (pthread_create(&ioctx.tid, NULL, io_thread, NULL) != 0) {
pthread_mutex_unlock(&ioctx.mtx);
pr_err("%s", "iothread create failed\r\n");
return -1;
}
ioctx_x->started = true;
pthread_setname_np(ioctx_x->tid, ioctx_x->name);
if (CPU_COUNT(&(ioctx_x->cpuset)) != 0) {
ret = pthread_setaffinity_np(ioctx_x->tid, sizeof(cpuset_t), &(ioctx_x->cpuset));
if (ret != 0) {
pr_err("pthread_setaffinity_np fails %d \n", ret);
}
}
pthread_mutex_unlock(&ioctx_x->mtx);
pr_info("%s started\n", ioctx_x->name);
ioctx.started = true;
pthread_setname_np(ioctx.tid, "iothread");
pthread_mutex_unlock(&ioctx.mtx);
pr_info("iothread started\n");
return 0;
}
int
iothread_add(struct iothread_ctx *ioctx_x, int fd, struct iothread_mevent *aevt)
iothread_add(int fd, struct iothread_mevent *aevt)
{
struct epoll_event ee;
int ret;
if (ioctx_x == NULL) {
pr_err("%s: ioctx_x is NULL \n", __func__);
return -1;
}
/* Create a epoll instance before the first fd is added.*/
ee.events = EPOLLIN;
ee.data.ptr = aevt;
ret = epoll_ctl(ioctx_x->epfd, EPOLL_CTL_ADD, fd, &ee);
ret = epoll_ctl(ioctx.epfd, EPOLL_CTL_ADD, fd, &ee);
if (ret < 0) {
pr_err("%s: failed to add fd, error is %d\n",
__func__, errno);
@ -117,7 +100,7 @@ iothread_add(struct iothread_ctx *ioctx_x, int fd, struct iothread_mevent *aevt)
}
/* Start the iothread after the first fd is added.*/
ret = iothread_start(ioctx_x);
ret = iothread_start();
if (ret < 0) {
pr_err("%s: failed to start iothread thread\n",
__func__);
@ -126,17 +109,12 @@ iothread_add(struct iothread_ctx *ioctx_x, int fd, struct iothread_mevent *aevt)
}
int
iothread_del(struct iothread_ctx *ioctx_x, int fd)
iothread_del(int fd)
{
int ret = 0;
if (ioctx_x == NULL) {
pr_err("%s: ioctx_x is NULL \n", __func__);
return -1;
}
if (ioctx_x->epfd) {
ret = epoll_ctl(ioctx_x->epfd, EPOLL_CTL_DEL, fd, NULL);
if (ioctx.epfd) {
ret = epoll_ctl(ioctx.epfd, EPOLL_CTL_DEL, fd, NULL);
if (ret < 0)
pr_err("%s: failed to delete fd from epoll fd, error is %d\n",
__func__, errno);
@ -148,215 +126,40 @@ void
iothread_deinit(void)
{
void *jval;
int i;
struct iothread_ctx *ioctx_x;
pthread_mutex_lock(&ioctxes_mutex);
for (i = 0; i < ioctx_active_cnt; i++) {
ioctx_x = &ioctxes[i];
if (ioctx_x->tid > 0) {
pthread_mutex_lock(&ioctx_x->mtx);
ioctx_x->started = false;
pthread_mutex_unlock(&ioctx_x->mtx);
pthread_kill(ioctx_x->tid, SIGCONT);
pthread_join(ioctx_x->tid, &jval);
}
if (ioctx_x->epfd > 0) {
close(ioctx_x->epfd);
ioctx_x->epfd = -1;
}
pthread_mutex_destroy(&ioctx_x->mtx);
pr_info("%s stop \n", ioctx_x->name);
if (ioctx.tid > 0) {
pthread_mutex_lock(&ioctx.mtx);
ioctx.started = false;
pthread_mutex_unlock(&ioctx.mtx);
pthread_kill(ioctx.tid, SIGCONT);
pthread_join(ioctx.tid, &jval);
}
ioctx_active_cnt = 0;
pthread_mutex_unlock(&ioctxes_mutex);
if (ioctx.epfd > 0) {
close(ioctx.epfd);
ioctx.epfd = -1;
}
pthread_mutex_destroy(&ioctx.mtx);
pr_info("iothread stop\n");
}
/*
* Create @ioctx_num iothread context instances
* Return NULL if fails. Otherwise, return the base of those iothread context instances.
*
* Notes:
* The caller of iothread_create() shall call iothread_free_options() afterwards to free the resources that
* are dynamically allocated during iothread_parse_options(), such as iothr_opt->cpusets.
*
* A general calling sequence from the virtual device owner is like:
* 1. Call iothread_parse_options() to parse the options from the user.
* 2. Call iothread_create() to create the iothread instances.
* 3. Call iothread_free_options() to free the dynamic resources.
*/
struct iothread_ctx *
iothread_create(struct iothreads_option *iothr_opt)
int
iothread_init(void)
{
pthread_mutexattr_t attr;
int i, ret, base, end;
struct iothread_ctx *ioctx_x;
struct iothread_ctx *ioctx_base = NULL;
ret = 0;
if (iothr_opt == NULL) {
pr_err("%s: iothr_opt is NULL \n", __func__);
return ioctx_base;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&ioctx.mtx, &attr);
pthread_mutexattr_destroy(&attr);
ioctx.tid = 0;
ioctx.started = false;
ioctx.epfd = epoll_create1(0);
if (ioctx.epfd < 0) {
pr_err("%s: failed to create epoll fd, error is %d\r\n",
__func__, errno);
return -1;
}
pthread_mutex_lock(&ioctxes_mutex);
base = ioctx_active_cnt;
end = base + iothr_opt->num;
if (end > IOTHREAD_NUM) {
ret = -1;
pr_err("%s: fails to create new iothread context, max number of instances is %d \n",
__func__, IOTHREAD_NUM);
} else {
for (i = base; i < end; i++) {
ioctx_x = &ioctxes[i];
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&(ioctx_x->mtx), &attr);
pthread_mutexattr_destroy(&attr);
ioctx_x->idx = i;
ioctx_x->tid = 0;
ioctx_x->started = false;
ioctx_x->epfd = epoll_create1(0);
CPU_ZERO(&(ioctx_x->cpuset));
if (iothr_opt->cpusets != NULL) {
memcpy(&(ioctx_x->cpuset), iothr_opt->cpusets + (i - base), sizeof(cpu_set_t));
}
if (snprintf(ioctx_x->name, PTHREAD_NAME_MAX_LEN,
"iothr-%d-%s", ioctx_x->idx, iothr_opt->tag) >= PTHREAD_NAME_MAX_LEN) {
pr_err("%s: iothread name too long \n", __func__);
}
if (ioctx_x->epfd < 0) {
ret = -1;
pr_err("%s: failed to create epoll fd, error is %d\r\n",
__func__, errno);
break;
}
}
if (ret == 0) {
ioctx_base = &ioctxes[base];
ioctx_active_cnt = end;
}
}
pthread_mutex_unlock(&ioctxes_mutex);
return ioctx_base;
}
/*
* Parse the iothread options from @str and fill the options in @iothr_opt if successes.
* Return -1 if fails to parse. Otherwise, return 0.
*/
int
iothread_parse_options(char *str, struct iothreads_option *iothr_opt)
{
char *tmp_num = NULL;
char *tmp_cpusets = NULL;
char *tmp_cpux = NULL;
int service_vm_cpuid, iothread_sub_idx, num;
cpu_set_t *cpuset_list = NULL;
/*
* Create one iothread instance if DM parameters contain 'iothread', but the number is not specified.
*/
num = 1;
/*
* Valid 'iothread' setting examples:
* - create 1 iothread instance for virtio-blk
* ... virtio-blk iothread,...
*
* - create 1 iothread instance for virtio-blk
* ... virtio-blk iothread=1,...
*
* - create 3 iothread instances for virtio-blk
* ... virtio-blk iothread=3,...
*
* - create 3 iothread instances for virtio-blk with CPU affinity settings
* ... virtio-blk iothread=3@0:1:2/0:1,...
* CPU affinity of iothread instances for this virtio-blk device:
* - 1st iothread instance <-> Service VM CPU 0,1,2
* - 2nd iothread instance <-> Service VM CPU 0,1
* - 3rd iothread instance <-> No CPU affinity settings
*
*/
if (str != NULL) {
/*
* "@" is used to separate the following two settings:
* - the number of iothread instances
* - the CPU affinity settings for each iothread instance.
*/
tmp_num = strsep(&str, "@");
if (tmp_num != NULL) {
if (dm_strtoi(tmp_num, &tmp_num, 10, &num) || (num <= 0)) {
pr_err("%s: invalid iothread number %s \n", __func__, tmp_num);
return -1;
}
cpuset_list = calloc(num, sizeof(cpu_set_t));
if (cpuset_list == NULL) {
pr_err("%s: calloc cpuset_list returns NULL \n", __func__);
return -1;
}
iothread_sub_idx = 0;
while ((str != NULL) && (*str !='\0') && (iothread_sub_idx < num)) {
/* "/" is used to separate the CPU affinity setting for each iothread instance. */
tmp_cpusets = strsep(&str, "/");
CPU_ZERO(cpuset_list + iothread_sub_idx);
while ((tmp_cpusets != NULL) && (*tmp_cpusets !='\0')) {
/* ":" is used to separate different CPU cores. */
tmp_cpux = strsep(&tmp_cpusets, ":");
/*
* char '*' can be used to skip the setting for the
* specific iothread instance.
*/
if (*tmp_cpux == '*') {
break;
}
if (dm_strtoi(tmp_cpux, &tmp_cpux, 10, &service_vm_cpuid) ||
(service_vm_cpuid < 0)) {
pr_err("%s: invalid CPU affinity setting %s \n",
__func__, tmp_cpux);
free(cpuset_list);
return -1;
}
CPU_SET(service_vm_cpuid, cpuset_list + iothread_sub_idx);
pr_err("%s: iothread[%d]: set service_vm_cpuid %d \n",
__func__, iothread_sub_idx, service_vm_cpuid);
}
iothread_sub_idx++;
}
}
}
iothr_opt->num = num;
iothr_opt->cpusets = cpuset_list;
return 0;
}
/*
* This interface is used to free the elements that are allocated dynamically in iothread_parse_options(),
* such as iothr_opt->cpusets.
*/
void iothread_free_options(struct iothreads_option *iothr_opt)
{
if ((iothr_opt != NULL) && (iothr_opt->cpusets != NULL)) {
free(iothr_opt->cpusets);
iothr_opt->cpusets = NULL;
}
return;
}

View File

@ -71,7 +71,6 @@
#include "cmd_monitor.h"
#include "vdisplay.h"
#include "iothread.h"
#include "vm_event.h"
#define VM_MAXCPU 16 /* maximum virtual cpus */
@ -102,7 +101,6 @@ bool vtpm2;
bool is_winvm;
bool skip_pci_mem64bar_workaround = false;
bool gfx_ui = false;
bool ovmf_loaded = false;
static int guest_ncpus;
static int virtio_msix = 1;
@ -168,7 +166,7 @@ usage(int code)
" -v: version\n"
" --ovmf: ovmf file path\n"
" --iasl: iasl compiler path\n"
" --ssram: Configure Software SRAM parameters\n"
" --ssram: Congfiure Software SRAM parameters\n"
" --cpu_affinity: list of Service VM vCPUs assigned to this User VM, the vCPUs are"
" identified by their local APIC IDs.\n"
" --enable_trusty: enable trusty for guest\n"
@ -178,7 +176,7 @@ usage(int code)
" --cmd_monitor: enable command monitor\n"
" its params: unix domain socket path\n"
" --virtio_poll: enable virtio poll mode with poll interval with ns\n"
" --acpidev_pt: ACPI device ID args: HID in ACPI Table\n"
" --acpidev_pt: acpi device ID args: HID in ACPI Table\n"
" --mmiodev_pt: MMIO resources args: physical MMIO regions\n"
" --vtpm2: Virtual TPM2 args: sock_path=$PATH_OF_SWTPM_SOCKET\n"
" --lapic_pt: enable local apic passthrough\n"
@ -234,12 +232,6 @@ virtio_uses_msix(void)
return virtio_msix;
}
int
guest_cpu_num(void)
{
return guest_ncpus;
}
size_t
high_bios_size(void)
{
@ -248,64 +240,6 @@ high_bios_size(void)
return roundup2(size, 2 * MB);
}
/*
* set nice value of current pthread
* input range: [-20, 19]
* Lower priorities cause more favorable scheduling.
*/
void
set_thread_priority(int priority, bool reset_on_fork)
{
int ret, policy;
char tname[MAXCOMLEN + 1];
struct sched_param sp = { .sched_priority = 0 };
memset(tname, 0, sizeof(tname));
pthread_getname_np(pthread_self(), tname, sizeof(tname));
policy = sched_getscheduler(0);
if (policy == -1) {
pr_err("%s(%s), sched_getscheduler failed, errno = %d\n",
__func__, tname, errno);
}
if ((policy & SCHED_RESET_ON_FORK) && !reset_on_fork)
policy &= ~SCHED_RESET_ON_FORK;
else if (((policy & SCHED_RESET_ON_FORK) == 0) && reset_on_fork)
policy |= SCHED_RESET_ON_FORK;
ret = sched_setscheduler(0, policy, &sp);
if (ret == -1) {
pr_err("%s(%s), sched_setscheduler failed, errno = %d\n",
__func__, tname, errno);
}
errno = 0;
ret = getpriority(PRIO_PROCESS, 0);
if (errno && (ret == -1)) {
pr_err("%s(%s), getpriority failed, errno = %d\n",
__func__, tname, errno);
} else {
pr_info("%s(%s), orig prio = %d\n",
__func__, tname, ret);
}
ret = setpriority(PRIO_PROCESS, 0, priority);
if (ret) {
pr_err("%s(%s), setpriority failed, errno = %d\n",
__func__, tname, errno);
}
ret = getpriority(PRIO_PROCESS, 0);
if (ret != priority) {
pr_err("%s(%s), getpriority(%d) != setpriority(%d)\n",
__func__, tname, ret, priority);
} else {
pr_info("%s(%s), new priority = %d\n",
__func__, tname, ret);
}
}
static void *
start_thread(void *param)
{
@ -675,8 +609,6 @@ vm_reset_vdevs(struct vmctx *ctx)
pci_irq_deinit(ctx);
ioapic_deinit();
iothread_deinit();
pci_irq_init(ctx);
atkbdc_init(ctx);
vrtc_init(ctx);
@ -742,7 +674,6 @@ vm_system_reset(struct vmctx *ctx)
static void
vm_suspend_resume(struct vmctx *ctx)
{
struct acrn_vcpu_regs bsp_regs;
/*
* If we get warm reboot request, we don't want to exit the
* vcpu_loop/vm_loop/mevent_loop. So we do:
@ -754,8 +685,6 @@ vm_suspend_resume(struct vmctx *ctx)
* 6. hypercall restart vm
*/
vm_pause(ctx);
if (ovmf_loaded)
vrtc_suspend(ctx);
vm_clear_ioreq(ctx);
vm_stop_watchdog(ctx);
@ -765,32 +694,8 @@ vm_suspend_resume(struct vmctx *ctx)
vm_reset_watchdog(ctx);
vm_reset(ctx);
bsp_regs = ctx->bsp_regs;
/* for bzImage or elf */
if (!ovmf_loaded) {
uint32_t *guest_wakeup_vec32;
/* 64BIT_WAKE_SUPPORTED_F is not set */
guest_wakeup_vec32 = paddr_guest2host(ctx,
get_acpi_wakingvector_offset(),
get_acpi_wakingvector_length());
/* set the BSP waking vector */
bsp_regs.vcpu_regs.cs_sel = (uint16_t)((*guest_wakeup_vec32 >> 4U) & 0xFFFFU);
bsp_regs.vcpu_regs.cs_base = bsp_regs.vcpu_regs.cs_sel << 4U;
/* real mode code segment */
bsp_regs.vcpu_regs.cs_ar = 0x009FU;
bsp_regs.vcpu_regs.cs_limit = 0xFFFFU;
bsp_regs.vcpu_regs.rip = 0x0U;
/* CR0_ET | CR0_NE */
bsp_regs.vcpu_regs.cr0 = 0x30;
/* real mode gdt */
bsp_regs.vcpu_regs.gdt.limit = 0xFFFFU;
bsp_regs.vcpu_regs.gdt.base = 0UL;
/* real mode idt */
bsp_regs.vcpu_regs.idt.limit = 0xFFFFU;
bsp_regs.vcpu_regs.idt.base = 0UL;
}
/* set the BSP init state */
vm_set_vcpu_regs(ctx, &bsp_regs);
vm_set_vcpu_regs(ctx, &ctx->bsp_regs);
vm_run(ctx);
}
@ -830,7 +735,8 @@ vm_loop(struct vmctx *ctx)
break;
}
if (VM_SUSPEND_SYSTEM_RESET == vm_get_suspend_mode()) {
/* RTVM can't be reset */
if ((VM_SUSPEND_SYSTEM_RESET == vm_get_suspend_mode()) && (!is_rtvm)) {
vm_system_reset(ctx);
}
@ -946,7 +852,7 @@ vm_init_asyncio(struct vmctx *ctx, uint64_t base)
sbuf->overrun_cnt = 0;
sbuf->head = 0;
sbuf->tail = 0;
return vm_setup_asyncio(ctx, base);
return vm_setup_sbuf(ctx, ACRN_ASYNCIO, base);
}
int
@ -1043,7 +949,6 @@ main(int argc, char *argv[])
case CMD_OPT_OVMF:
if (!vsbl_file_name && acrn_parse_ovmf(optarg) != 0)
errx(EX_USAGE, "invalid ovmf param %s", optarg);
ovmf_loaded = true;
skip_pci_mem64bar_workaround = true;
break;
case CMD_OPT_IASL:
@ -1227,18 +1132,18 @@ main(int argc, char *argv[])
goto mevent_fail;
}
error = iothread_init();
if (error) {
pr_err("Unable to initialize iothread (%d)\n", errno);
goto iothread_fail;
}
pr_notice("vm_init_vdevs\n");
if (vm_init_vdevs(ctx) < 0) {
pr_err("Unable to init vdev (%d)\n", errno);
goto dev_fail;
}
pr_notice("vm setup vm event\n");
error = vm_event_init(ctx);
if (error) {
pr_warn("VM_EVENT is not supported by kernel or hyperviosr!\n");
}
/*
* build the guest tables, MP etc.
*/
@ -1293,7 +1198,6 @@ main(int argc, char *argv[])
break;
}
vm_event_deinit();
vm_deinit_vdevs(ctx);
mevent_deinit();
iothread_deinit();
@ -1306,14 +1210,13 @@ main(int argc, char *argv[])
}
vm_fail:
vm_event_deinit();
vm_deinit_vdevs(ctx);
if (ssram)
clean_vssram_configs();
dev_fail:
iothread_deinit();
iothread_fail:
mevent_deinit();
mevent_fail:
vm_unsetup_memory(ctx);

View File

@ -72,7 +72,7 @@ struct mevent {
};
static LIST_HEAD(listhead, mevent) global_head;
/* List holds the mevent node which is requested to be deleted */
/* List holds the mevent node which is requested to deleted */
static LIST_HEAD(del_listhead, mevent) del_head;
static void

View File

@ -124,10 +124,10 @@ static void *intr_storm_monitor_thread(void *arg)
}
/*
* calculate the delta of the two times count of interrupt;
* compare the IRQ number first, if not same just drop it,
* for it just happens rarely when devices dynamically
* allocation in Service VM or User VM, it can be calculated next time
* calc the delta of the two times count of interrupt;
* compare the IRQ num first, if not same just drop it,
* for it just happens rarelly when devices dynamically
* allocation in Service VM or User VM, it can be calc next time
*/
for (i = 0; i < hdr->buf_cnt; i += 2) {
if (hdr->buffer[i] != intr_cnt_buf[i])
@ -350,7 +350,7 @@ static void handle_stop(struct mngr_msg *msg, int client_fd, void *param)
ack.msgid = msg->msgid;
ack.timestamp = msg->timestamp;
if (msg->data.acrnd_stop.force) {
if (msg->data.acrnd_stop.force && !is_rtvm) {
pr_info("%s: setting VM state to %s\n", __func__, vm_state_to_str(VM_SUSPEND_POWEROFF));
vm_set_suspend_mode(VM_SUSPEND_POWEROFF);
ack.data.err = 0;

View File

@ -1,125 +0,0 @@
/*
* Copyright (C) 2018-2023 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm/errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include "sbuf.h"
#include <errno.h>
static inline uint32_t sbuf_next_ptr(uint32_t pos_arg,
uint32_t span, uint32_t scope)
{
uint32_t pos = pos_arg;
pos += span;
pos = (pos >= scope) ? (pos - scope) : pos;
return pos;
}
uint32_t sbuf_get(struct shared_buf *sbuf, uint8_t *data)
{
const void *from;
if ((sbuf == NULL) || (data == NULL))
return -EINVAL;
if (sbuf_is_empty(sbuf)) {
/* no data available */
return 0;
}
from = (void *)sbuf + SBUF_HEAD_SIZE + sbuf->head;
memcpy(data, from, sbuf->ele_size);
mb();
sbuf->head = sbuf_next_ptr(sbuf->head, sbuf->ele_size, sbuf->size);
return sbuf->ele_size;
}
int sbuf_clear_buffered(struct shared_buf *sbuf)
{
if (sbuf == NULL)
return -EINVAL;
sbuf->head = sbuf->tail;
return 0;
}
/**
* The high caller should guarantee each time there must have
* sbuf->ele_size data can be write form data.
* Caller should provide the max length of the data for safety reason.
*
* And this function should guarantee execution atomically.
*
* flag:
* If OVERWRITE_EN set, buf can store (ele_num - 1) elements at most.
* Should use lock to guarantee that only one read or write at
* the same time.
* if OVERWRITE_EN not set, buf can store (ele_num - 1) elements
* at most. Shouldn't modify the sbuf->head.
*
* return:
* ele_size: write succeeded.
* 0: no write, buf is full
* UINT32_MAX: failed, sbuf corrupted.
*/
uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data, uint32_t max_len)
{
uint32_t ele_size = sbuf->ele_size;
void *to;
uint32_t next_tail;
uint32_t ret;
bool trigger_overwrite = false;
next_tail = sbuf_next_ptr(sbuf->tail, ele_size, sbuf->size);
if ((next_tail == sbuf->head) && ((sbuf->flags & OVERWRITE_EN) == 0U)) {
/* if overrun is not enabled, return 0 directly */
ret = 0U;
} else if (ele_size <= max_len) {
if (next_tail == sbuf->head) {
/* accumulate overrun count if necessary */
sbuf->overrun_cnt += sbuf->flags & OVERRUN_CNT_EN;
trigger_overwrite = true;
}
to = (void *)sbuf + SBUF_HEAD_SIZE + sbuf->tail;
memcpy(to, data, ele_size);
/* make sure write data before update head */
mb();
if (trigger_overwrite) {
sbuf->head = sbuf_next_ptr(sbuf->head,
ele_size, sbuf->size);
}
sbuf->tail = next_tail;
ret = ele_size;
} else {
/* there must be something wrong */
ret = UINT32_MAX;
}
return ret;
}
void sbuf_init(struct shared_buf *sbuf, uint32_t total_size, uint32_t ele_size)
{
sbuf->magic = SBUF_MAGIC;
sbuf->ele_size = ele_size;
sbuf->ele_num = (total_size - SBUF_HEAD_SIZE) / sbuf->ele_size;
sbuf->size = sbuf->ele_size * sbuf->ele_num;
sbuf->flags = 0;
sbuf->overrun_cnt = 0;
sbuf->head = 0;
sbuf->tail = 0;
}

View File

@ -297,7 +297,7 @@ acrn_sw_load(struct vmctx *ctx)
{
if (vsbl_file_name)
return acrn_sw_load_vsbl(ctx);
else if (ovmf_loaded)
else if ((ovmf_file_name != NULL) ^ (ovmf_code_file_name && ovmf_vars_file_name))
return acrn_sw_load_ovmf(ctx);
else if (kernel_file_name)
return acrn_sw_load_bzimage(ctx);

View File

@ -1,510 +0,0 @@
/*
* Copyright (C) 2018-2023 Intel Corporation.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/queue.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/eventfd.h>
#include <acrn_common.h>
#include "vm_event.h"
#include "hsm_ioctl_defs.h"
#include "sbuf.h"
#include "log.h"
#include <cjson/cJSON.h>
#include "monitor.h"
#include "timer.h"
#define VM_EVENT_ELE_SIZE (sizeof(struct vm_event))
#define HV_VM_EVENT_TUNNEL 0
#define DM_VM_EVENT_TUNNEL 1
#define MAX_VM_EVENT_TUNNELS 2
#define MAX_EPOLL_EVENTS MAX_VM_EVENT_TUNNELS
#define THROTTLE_WINDOW 1U /* time window for throttle counter, in secs*/
#define BROKEN_TIME ((time_t)-1)
typedef void (*vm_event_handler)(struct vmctx *ctx, struct vm_event *event);
typedef void (*vm_event_generate_jdata)(cJSON *event_obj, struct vm_event *event);
static int epoll_fd;
static bool started = false;
static char hv_vm_event_page[4096] __aligned(4096);
static char dm_vm_event_page[4096] __aligned(4096);
static pthread_t vm_event_tid;
static void general_event_handler(struct vmctx *ctx, struct vm_event *event);
static void rtc_chg_event_handler(struct vmctx *ctx, struct vm_event *event);
static void gen_rtc_chg_jdata(cJSON *event_obj, struct vm_event *event);
enum event_source_type {
EVENT_SOURCE_TYPE_HV,
EVENT_SOURCE_TYPE_DM,
};
struct vm_event_tunnel {
enum event_source_type type;
struct shared_buf *sbuf;
uint32_t sbuf_size;
int kick_fd;
pthread_mutex_t mtx;
bool enabled;
};
struct event_throttle_ctl {
struct acrn_timer timer;
pthread_mutex_t mtx;
uint32_t event_counter;
uint32_t throttle_count; /* how many events has been throttled(dropped) */
bool is_up;
};
struct vm_event_proc {
vm_event_handler ve_handler;
uint32_t throttle_rate; /* how many events allowed per sec */
struct event_throttle_ctl throttle_ctl;
vm_event_generate_jdata gen_jdata_handler; /* how to transtfer vm_event data to json txt */
};
static struct vm_event_proc ve_proc[VM_EVENT_COUNT] = {
[VM_EVENT_RTC_CHG] = {
.ve_handler = rtc_chg_event_handler,
.gen_jdata_handler = gen_rtc_chg_jdata,
.throttle_rate = 1,
},
[VM_EVENT_POWEROFF] = {
.ve_handler = general_event_handler,
.gen_jdata_handler = NULL,
.throttle_rate = 1,
},
[VM_EVENT_TRIPLE_FAULT] = {
.ve_handler = general_event_handler,
.gen_jdata_handler = NULL,
.throttle_rate = 1,
},
};
static inline struct vm_event_proc *get_vm_event_proc(struct vm_event *event)
{
struct vm_event_proc *proc = NULL;
if (event->type < VM_EVENT_COUNT) {
proc = &ve_proc[event->type];
}
return proc;
}
static bool event_throttle(struct vm_event *event)
{
struct vm_event_proc *proc;
struct event_throttle_ctl *ctl;
uint32_t current_rate;
bool ret = false;
proc = get_vm_event_proc(event);
if (proc) {
ctl = &proc->throttle_ctl;
if (ctl->is_up) {
pthread_mutex_lock(&ctl->mtx);
current_rate = ctl->event_counter / THROTTLE_WINDOW;
if (current_rate < proc->throttle_rate) {
ctl->event_counter++;
ret = false;
} else {
ret = true;
ctl->throttle_count++;
pr_notice("event %d throttle: %d dropped\n",
event->type, ctl->throttle_count);
}
pthread_mutex_unlock(&ctl->mtx);
}
}
return ret;
}
void throttle_timer_cb(void *arg, uint64_t nexp)
{
struct event_throttle_ctl *ctl = (struct event_throttle_ctl *)arg;
pthread_mutex_lock(&ctl->mtx);
ctl->event_counter = 0;
pthread_mutex_unlock(&ctl->mtx);
}
static void vm_event_throttle_init(struct vmctx *ctx)
{
int i;
struct event_throttle_ctl *ctl;
int ret = 0;
struct itimerspec timer_spec;
for (i = 0; i < ARRAY_SIZE(ve_proc); i++) {
ctl = &ve_proc[i].throttle_ctl;
ctl->event_counter = 0U;
ctl->throttle_count = 0U;
ctl->is_up = false;
pthread_mutex_init(&ctl->mtx, NULL);
ctl->timer.clockid = CLOCK_MONOTONIC;
ret = acrn_timer_init(&ctl->timer, throttle_timer_cb, ctl);
if (ret < 0) {
pr_warn("failed to create timer for vm_event %d, throttle disabled\n", i);
continue;
}
timer_spec.it_value.tv_sec = THROTTLE_WINDOW;
timer_spec.it_value.tv_nsec = 0;
timer_spec.it_interval.tv_sec = THROTTLE_WINDOW;
timer_spec.it_interval.tv_nsec = 0;
ret = acrn_timer_settime(&ctl->timer, &timer_spec);
if (ret < 0) {
pr_warn("failed to set timer for vm_event %d, throttle disabled\n", i);
continue;
}
ctl->is_up = true;
}
}
static void vm_event_throttle_deinit(void)
{
int i;
struct event_throttle_ctl *ctl;
for (i = 0; i < ARRAY_SIZE(ve_proc); i++) {
ctl = &ve_proc[i].throttle_ctl;
if (ctl->timer.fd != -1) {
acrn_timer_deinit(&ctl->timer);
}
}
}
static char *generate_vm_event_message(struct vm_event *event)
{
char *event_msg = NULL;
cJSON *val;
cJSON *event_obj = cJSON_CreateObject();
struct vm_event_proc *proc;
if (event_obj == NULL)
return NULL;
val = cJSON_CreateNumber(event->type);
if (val == NULL)
return NULL;
cJSON_AddItemToObject(event_obj, "vm_event", val);
proc = get_vm_event_proc(event);
if (proc && proc->gen_jdata_handler) {
(proc->gen_jdata_handler)(event_obj, event);
}
event_msg = cJSON_Print(event_obj);
if (event_msg == NULL)
fprintf(stderr, "Failed to generate vm_event message.\n");
cJSON_Delete(event_obj);
return event_msg;
}
static void emit_vm_event(struct vmctx *ctx, struct vm_event *event)
{
if (!event_throttle(event)) {
char *msg = generate_vm_event_message(event);
if (msg != NULL) {
vm_monitor_send_vm_event(msg);
free(msg);
}
}
}
static void general_event_handler(struct vmctx *ctx, struct vm_event *event)
{
emit_vm_event(ctx, event);
}
static void gen_rtc_chg_jdata(cJSON *event_obj, struct vm_event *event)
{
struct rtc_change_event_data *data = (struct rtc_change_event_data *)event->event_data;
cJSON *val;
val = cJSON_CreateNumber(data->delta_time);
if (val != NULL) {
cJSON_AddItemToObject(event_obj, "delta_time", val);
}
val = cJSON_CreateNumber(data->last_time);
if (val != NULL) {
cJSON_AddItemToObject(event_obj, "last_time", val);
}
}
/* assume we only have one unique rtc source */
static struct acrn_timer rtc_chg_event_timer = {
.clockid = CLOCK_MONOTONIC,
};
static pthread_mutex_t rtc_chg_mutex = PTHREAD_MUTEX_INITIALIZER;
static struct timespec time_window_start;
static time_t last_time_cached = BROKEN_TIME;
static time_t delta_time_sum = 0;
#define RTC_CHG_WAIT_TIME 1 /* 1 second */
static void rtc_chg_event_handler(struct vmctx *ctx, struct vm_event *event)
{
struct itimerspec timer_spec;
struct rtc_change_event_data *data = (struct rtc_change_event_data *)event->event_data;
/*
* RTC time is not reliable until guest finishes updating all RTC date/time regs.
* So wait for some time, if no more change happens, we can conclude that the RTC
* change has been done.
*/
timer_spec.it_value.tv_sec = RTC_CHG_WAIT_TIME;
timer_spec.it_value.tv_nsec = 0;
timer_spec.it_interval.tv_sec = 0;
timer_spec.it_interval.tv_nsec = 0;
pthread_mutex_lock(&rtc_chg_mutex);
if (last_time_cached == BROKEN_TIME) {
last_time_cached = data->last_time;
}
delta_time_sum += data->delta_time;
/* The last timer will be overwriten if it is not triggered yet. */
acrn_timer_settime(&rtc_chg_event_timer, &timer_spec);
clock_gettime(CLOCK_MONOTONIC, &time_window_start);
pthread_mutex_unlock(&rtc_chg_mutex);
}
static void rtc_chg_timer_cb(void *arg, uint64_t nexp)
{
struct timespec now, delta;
struct timespec time_window_size = {RTC_CHG_WAIT_TIME, 0};
struct vmctx *ctx = arg;
struct vm_event send_event;
struct rtc_change_event_data *data = (struct rtc_change_event_data *)send_event.event_data;
pthread_mutex_lock(&rtc_chg_mutex);
clock_gettime(CLOCK_MONOTONIC, &now);
delta = now;
timespecsub(&delta, &time_window_start);
/* possible racing problem here. make sure this is the right timer cb for the vm_event */
if (timespeccmp(&delta, &time_window_size, >=)) {
data->delta_time = delta_time_sum;
data->last_time = last_time_cached;
emit_vm_event(ctx, &send_event);
last_time_cached = BROKEN_TIME;
delta_time_sum = 0;
}
pthread_mutex_unlock(&rtc_chg_mutex);
}
static void *vm_event_thread(void *param)
{
int n, i;
struct vm_event ve;
eventfd_t val;
struct vm_event_tunnel *tunnel;
struct vmctx *ctx = param;
struct epoll_event eventlist[MAX_EPOLL_EVENTS];
while (started) {
n = epoll_wait(epoll_fd, eventlist, MAX_EPOLL_EVENTS, -1);
if (n < 0) {
if (errno != EINTR) {
pr_err("%s: epoll failed %d\n", __func__, errno);
}
continue;
}
for (i = 0; i < n; i++) {
if (i < MAX_EPOLL_EVENTS) {
tunnel = eventlist[i].data.ptr;
eventfd_read(tunnel->kick_fd, &val);
if (tunnel && tunnel->enabled) {
while (!sbuf_is_empty(tunnel->sbuf)) {
struct vm_event_proc *proc;
sbuf_get(tunnel->sbuf, (uint8_t*)&ve);
pr_dbg("%ld vm event from%d %d\n", val, tunnel->type, ve.type);
proc = get_vm_event_proc(&ve);
if (proc && proc->ve_handler) {
(proc->ve_handler)(ctx, &ve);
} else {
pr_warn("%s: unhandled vm event type %d\n", __func__, ve.type);
}
}
}
}
}
}
return NULL;
}
static struct vm_event_tunnel ve_tunnel[MAX_VM_EVENT_TUNNELS] = {
{
.type = EVENT_SOURCE_TYPE_HV,
.sbuf = (struct shared_buf *)hv_vm_event_page,
.sbuf_size = 4096,
.enabled = false,
},
{
.type = EVENT_SOURCE_TYPE_DM,
.sbuf = (struct shared_buf *)dm_vm_event_page,
.sbuf_size = 4096,
.enabled = false,
},
};
static int create_event_tunnel(struct vmctx *ctx, struct vm_event_tunnel *tunnel, int epoll_fd)
{
struct epoll_event ev;
enum event_source_type type = tunnel->type;
struct shared_buf *sbuf = tunnel->sbuf;
int kick_fd = -1;
int error;
sbuf_init(sbuf, tunnel->sbuf_size, VM_EVENT_ELE_SIZE);
if (type == EVENT_SOURCE_TYPE_HV) {
error = ioctl(ctx->fd, ACRN_IOCTL_SETUP_VM_EVENT_RING, sbuf);
if (error) {
pr_err("%s: Setting vm_event ring failed %d\n", __func__, error);
goto out;
}
}
kick_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (kick_fd < 0) {
pr_err("%s: eventfd failed %d\n", __func__, errno);
goto out;
}
if (type == EVENT_SOURCE_TYPE_HV) {
error = ioctl(ctx->fd, ACRN_IOCTL_SETUP_VM_EVENT_FD, kick_fd);
if (error) {
pr_err("%s: Setting vm_event fd failed %d\n", __func__, error);
goto out;
}
}
ev.events = EPOLLIN;
ev.data.ptr = tunnel;
error = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, kick_fd, &ev);
if (error < 0) {
pr_err("%s: failed to add fd, error is %d\n", __func__, errno);
goto out;
}
tunnel->kick_fd = kick_fd;
pthread_mutex_init(&tunnel->mtx, NULL);
tunnel->enabled = true;
return 0;
out:
if (kick_fd >= 0) {
close(kick_fd);
}
return -1;
}
void destory_event_tunnel(struct vm_event_tunnel *tunnel)
{
if (tunnel->enabled) {
close(tunnel->kick_fd);
tunnel->enabled = false;
pthread_mutex_destroy(&tunnel->mtx);
}
}
int vm_event_init(struct vmctx *ctx)
{
int error;
epoll_fd = epoll_create1(0);
if (epoll_fd < 0) {
pr_err("%s: failed to create epoll %d\n", __func__, errno);
goto out;
}
error = create_event_tunnel(ctx, &ve_tunnel[HV_VM_EVENT_TUNNEL], epoll_fd);
if (error) {
goto out;
}
error = create_event_tunnel(ctx, &ve_tunnel[DM_VM_EVENT_TUNNEL], epoll_fd);
if (error) {
goto out;
}
vm_event_throttle_init(ctx);
error = pthread_create(&vm_event_tid, NULL, vm_event_thread, ctx);
if (error) {
pr_err("%s: vm_event create failed %d\n", __func__, errno);
goto out;
}
acrn_timer_init(&rtc_chg_event_timer, rtc_chg_timer_cb, ctx);
started = true;
return 0;
out:
if (epoll_fd >= 0) {
close(epoll_fd);
}
destory_event_tunnel(&ve_tunnel[HV_VM_EVENT_TUNNEL]);
destory_event_tunnel(&ve_tunnel[DM_VM_EVENT_TUNNEL]);
return -1;
}
int vm_event_deinit(void)
{
void *jval;
if (started) {
started = false;
vm_event_throttle_deinit();
pthread_kill(vm_event_tid, SIGCONT);
pthread_join(vm_event_tid, &jval);
close(epoll_fd);
destory_event_tunnel(&ve_tunnel[HV_VM_EVENT_TUNNEL]);
destory_event_tunnel(&ve_tunnel[DM_VM_EVENT_TUNNEL]);
}
return 0;
}
/* Send a dm generated vm_event by putting it to sbuf.
* A thread will receive and process those events.
* Events will be dropped if sbuf is full.
* They also maight be dropped due to event throttle control in receive thread.
*/
int dm_send_vm_event(struct vm_event *event)
{
struct vm_event_tunnel *tunnel = &ve_tunnel[DM_VM_EVENT_TUNNEL];
struct shared_buf *sbuf;
int32_t ret = -1;
uint32_t size_sent;
if (!tunnel->enabled) {
return -1;
}
sbuf = tunnel->sbuf;
if (sbuf != NULL) {
pthread_mutex_lock(&tunnel->mtx);
size_sent = sbuf_put(sbuf, (uint8_t *)event, sizeof(*event));
pthread_mutex_unlock(&tunnel->mtx);
if (size_sent == VM_EVENT_ELE_SIZE) {
eventfd_write(tunnel->kick_fd, 1UL);
ret = 0;
}
}
return ret;
}

View File

@ -295,14 +295,19 @@ vm_destroy(struct vmctx *ctx)
}
int
vm_setup_asyncio(struct vmctx *ctx, uint64_t base)
vm_setup_sbuf(struct vmctx *ctx, uint32_t sbuf_id, uint64_t base)
{
int error;
struct acrn_sbuf sbuf_param;
error = ioctl(ctx->fd, ACRN_IOCTL_SETUP_ASYNCIO, base);
bzero(&sbuf_param, sizeof(sbuf_param));
sbuf_param.sbuf_id = sbuf_id;
sbuf_param.base = base;
error = ioctl(ctx->fd, ACRN_IOCTL_SETUP_SBUF, &sbuf_param);
if (error) {
pr_err("ACRN_IOCTL_SETUP_ASYNCIO ioctl() returned an error: %s\n", errormsg(errno));
pr_err("ACRN_IOCTL_SBUF_PAGE ioctl() returned an error: %s\n", errormsg(errno));
}
return error;

File diff suppressed because it is too large Load Diff

View File

@ -2405,7 +2405,7 @@ pci_ahci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts, int atapi)
*/
snprintf(bident, sizeof(bident), "%02x:%02x:%02x", dev->slot,
dev->func, p);
bctxt = blockif_open(opts, bident, 1, NULL);
bctxt = blockif_open(opts, bident);
if (bctxt == NULL) {
ahci_dev->ports = p;
ret = 1;

View File

@ -1918,29 +1918,31 @@ pci_bus_write_dsdt(int bus)
dsdt_line(" ,, , AddressRangeMemory, TypeStatic)");
dsdt_line(" })");
count = pci_count_lintr(bus);
if (count != 0) {
dsdt_indent(2);
dsdt_line("Name (PPRT, Package ()");
dsdt_line("{");
pci_walk_lintr(bus, pci_pirq_prt_entry, NULL);
dsdt_line("})");
dsdt_line("Name (APRT, Package ()");
dsdt_line("{");
pci_walk_lintr(bus, pci_apic_prt_entry, NULL);
dsdt_line("})");
dsdt_line("Method (_PRT, 0, NotSerialized)");
dsdt_line("{");
dsdt_line(" If (PICM)");
dsdt_line(" {");
dsdt_line(" Return (APRT)");
dsdt_line(" }");
dsdt_line(" Else");
dsdt_line(" {");
dsdt_line(" Return (PPRT)");
dsdt_line(" }");
dsdt_line("}");
dsdt_unindent(2);
if (!is_rtvm) {
count = pci_count_lintr(bus);
if (count != 0) {
dsdt_indent(2);
dsdt_line("Name (PPRT, Package ()");
dsdt_line("{");
pci_walk_lintr(bus, pci_pirq_prt_entry, NULL);
dsdt_line("})");
dsdt_line("Name (APRT, Package ()");
dsdt_line("{");
pci_walk_lintr(bus, pci_apic_prt_entry, NULL);
dsdt_line("})");
dsdt_line("Method (_PRT, 0, NotSerialized)");
dsdt_line("{");
dsdt_line(" If (PICM)");
dsdt_line(" {");
dsdt_line(" Return (APRT)");
dsdt_line(" }");
dsdt_line(" Else");
dsdt_line(" {");
dsdt_line(" Return (PPRT)");
dsdt_line(" }");
dsdt_line("}");
dsdt_unindent(2);
}
}
dsdt_indent(2);
@ -2010,6 +2012,8 @@ pci_msix_enabled(struct pci_vdev *dev)
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param index MSIx table entry index.
*
* @return None
*/
void
pci_generate_msix(struct pci_vdev *dev, int index)
@ -2037,6 +2041,8 @@ pci_generate_msix(struct pci_vdev *dev, int index)
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param index Message data index.
*
* @return None
*/
void
pci_generate_msi(struct pci_vdev *dev, int index)
@ -2157,6 +2163,8 @@ pci_lintr_route(struct pci_vdev *dev)
* @brief Assert INTx pin of virtual PCI device
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
*
* @return None
*/
void
pci_lintr_assert(struct pci_vdev *dev)
@ -2181,6 +2189,8 @@ pci_lintr_assert(struct pci_vdev *dev)
* @brief Deassert INTx pin of virtual PCI device
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
*
* @return None
*/
void
pci_lintr_deassert(struct pci_vdev *dev)

View File

@ -53,7 +53,6 @@
#define IVSHMEM_DEVICE_ID 0x1110
#define IVSHMEM_CLASS 0x05
#define IVSHMEM_REV 0x01
#define IVSHMEM_INTEL_SUBVENDOR_ID 0x8086U
/* IVSHMEM MMIO Registers */
@ -250,13 +249,13 @@ pci_ivshmem_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
static int
pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
uint32_t size, region_id = 0;
char *tmp, *name, *size_str, *orig;
uint32_t size;
char *tmp, *name, *orig;
struct pci_ivshmem_vdev *ivshmem_vdev = NULL;
bool is_hv_land;
int rc;
/* ivshmem device usage: "-s N,ivshmem,shm_name,shm_size,region_id" */
/* ivshmem device usage: "-s N,ivshmem,shm_name,shm_size" */
tmp = orig = strdup(opts);
if (!orig) {
pr_warn("No memory for strdup\n");
@ -278,9 +277,8 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
goto err;
}
size_str = strsep(&tmp, ",");
if (dm_strtoui(size_str, &size_str, 10, &size) != 0) {
pr_warn("the shared memory size is incorrect, %s\n", size_str);
if (dm_strtoui(tmp, &tmp, 10, &size) != 0) {
pr_warn("the shared memory size is incorrect, %s\n", tmp);
goto err;
}
size *= 0x100000; /* convert to megabytes */
@ -291,13 +289,6 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
goto err;
}
if (tmp) {
if (dm_strtoui(tmp, &tmp, 10, &region_id) != 0) {
pr_warn("shared memory region ID is incorrect, %s, 0 will used.\n", tmp);
region_id = 0;
}
}
ivshmem_vdev = calloc(1, sizeof(struct pci_ivshmem_vdev));
if (!ivshmem_vdev) {
pr_warn("failed to allocate ivshmem device\n");
@ -313,8 +304,6 @@ pci_ivshmem_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
pci_set_cfgdata16(dev, PCIR_DEVICE, IVSHMEM_DEVICE_ID);
pci_set_cfgdata16(dev, PCIR_REVID, IVSHMEM_REV);
pci_set_cfgdata8(dev, PCIR_CLASS, IVSHMEM_CLASS);
pci_set_cfgdata16(dev, PCIR_SUBDEV_0, (uint16_t)region_id);
pci_set_cfgdata16(dev, PCIR_SUBVEND_0, IVSHMEM_INTEL_SUBVENDOR_ID);
pci_emul_alloc_bar(dev, IVSHMEM_MMIO_BAR, PCIBAR_MEM32, IVSHMEM_REG_SIZE);
pci_emul_alloc_bar(dev, IVSHMEM_MSIX_BAR, PCIBAR_MEM32, IVSHMEM_MSIX_PBA_SIZE);

View File

@ -59,31 +59,27 @@ SYSRES_IO(NMISC_PORT, 1);
static struct pci_vdev *lpc_bridge;
#define LPC_UART_NUM 5
#define LPC_UART_NUM 2
static struct lpc_uart_vdev {
struct uart_vdev *uart;
const char *opts;
int iobase;
int irq;
int enabled; /* enabled/configured by user */
int enabled;
} lpc_uart_vdev[LPC_UART_NUM];
#define LPC_S5_UART_NAME "COM5"
static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2", "COM3", "COM4", LPC_S5_UART_NAME};
static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2" };
/*
* LPC device configuration is in the following form:
* <lpc_device_name>[,<options>]
* For e.g. "com1,stdio"
* For S5 e.g. "com5,/dev/pts/0,0x9000,5"
*/
int
lpc_device_parse(const char *opts)
{
int unit, error;
char *str, *cpy, *lpcdev;
char *lpcopt, *lpcport, *endptr;
int s5_port = 0, s5_irq = 0;
error = -1;
str = cpy = strdup(opts);
@ -91,26 +87,7 @@ lpc_device_parse(const char *opts)
if (lpcdev != NULL) {
for (unit = 0; unit < LPC_UART_NUM; unit++) {
if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) {
lpc_uart_vdev[unit].enabled = 1;
if(strcasecmp(lpcdev,LPC_S5_UART_NAME) == 0){
lpcopt = strsep(&str,",");
if(lpcopt != NULL){
lpc_uart_vdev[unit].opts = lpcopt;
}
lpcport = strsep(&str, ",");
if(lpcport != NULL){
if(dm_strtoul(lpcport, &endptr, 0, (long unsigned int*)&s5_port))
goto done;
if(dm_strtoul(str, &endptr, 0, (long unsigned int*)&s5_irq))
goto done;
}
if((s5_port != 0) && (s5_irq != 0)){
uart_legacy_reinit_res(unit, s5_port, s5_irq);
}
}
else{
lpc_uart_vdev[unit].opts = str;
}
lpc_uart_vdev[unit].opts = str;
error = 0;
goto done;
}
@ -207,6 +184,7 @@ lpc_deinit(struct vmctx *ctx)
uart_release_backend(lpc_uart->uart, lpc_uart->opts);
uart_legacy_dealloc(unit);
lpc_uart->uart = NULL;
lpc_uart->enabled = 0;
}
}
@ -224,9 +202,6 @@ lpc_init(struct vmctx *ctx)
lpc_uart = &lpc_uart_vdev[unit];
name = lpc_uart_names[unit];
if (lpc_uart->enabled == 0)
continue;
if (uart_legacy_alloc(unit,
&lpc_uart->iobase,
&lpc_uart->irq) != 0) {
@ -254,6 +229,7 @@ lpc_init(struct vmctx *ctx)
error = register_inout(&iop);
if (error)
goto init_failed;
lpc_uart->enabled = 1;
}
return 0;

View File

@ -48,7 +48,6 @@
#include "dm.h"
#include "passthru.h"
#include "ptm.h"
#include "igd_pciids.h"
/* Some audio drivers get topology data from ACPI NHLT table.
* For such drivers, we need to copy the host NHLT table to make it
@ -61,9 +60,8 @@
extern uint64_t audio_nhlt_len;
uint64_t gpu_dsm_hpa = 0;
uint64_t gpu_dsm_gpa = 0;
uint32_t gpu_dsm_size = 0;
uint32_t gpu_dsm_hpa = 0;
uint32_t gpu_dsm_gpa = 0;
uint32_t gpu_opregion_hpa = 0;
uint32_t gpu_opregion_gpa = 0;
@ -554,62 +552,7 @@ get_gpu_rsvmem_base_gpa()
uint32_t
get_gpu_rsvmem_size()
{
return GPU_OPREGION_SIZE + gpu_dsm_size;
}
static const struct igd_device igd_device_tbl[] = {
IGD_RPLP_DEVICE_IDS,
IGD_RPLS_DEVICE_IDS,
IGD_ADLN_DEVICE_IDS,
IGD_ADLP_DEVICE_IDS,
IGD_ADLS_DEVICE_IDS,
IGD_RKL_DEVICE_IDS,
IGD_TGL_DEVICE_IDS,
IGD_JSL_DEVICE_IDS,
IGD_EHL_DEVICE_IDS,
IGD_ICL_DEVICE_IDS,
IGD_CFL_DEVICE_IDS,
IGD_KBL_DEVICE_IDS,
IGD_GLK_DEVICE_IDS,
IGD_BXT_DEVICE_IDS,
IGD_SKL_DEVICE_IDS,
{ 0 }
};
int igd_gen(uint16_t device) {
const struct igd_device *entry;
for (entry = igd_device_tbl; entry->device != 0; entry++) {
if (entry->device == device) {
return entry->gen;
}
}
return 0;
}
uint32_t igd_dsm_region_size(struct pci_device *igddev)
{
uint16_t ggc;
uint8_t gms;
ggc = read_config(igddev, PCIR_GGC, 2);
gms = ggc >> PCIR_GGC_GMS_SHIFT;
switch (gms) {
case 0x00 ... 0x10:
return gms * 32 * MB;
case 0x20:
return 1024 * MB;
case 0x30:
return 1536 * MB;
case 0x40:
return 2048 * MB;
case 0xf0 ... 0xfe:
return (gms - 0xf0 + 1) * 4 * MB;
}
pr_err("%s: Invalid GMS value in GGC register. GGC = %04x\n", __func__, ggc);
return 0; /* Should never reach here */
return GPU_OPREGION_SIZE + GPU_DSM_SIZE;
}
/*
@ -620,26 +563,80 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
struct acrn_pcidev *pcidev, uint16_t device)
{
uint32_t opregion_phys, dsm_mask_val;
int gen;
/* get opregion hpa */
opregion_phys = read_config(ptdev->phys_dev, PCIR_ASLS_CTL, 4);
gpu_opregion_hpa = opregion_phys & PCIM_ASLS_OPREGION_MASK;
gen = igd_gen(device);
if (!gen) {
pr_warn("Device 8086:%04x is not an igd device in allowlist, assuming it is gen 11+. " \
"GVT-d may not working properly\n", device);
gen = 11;
}
gpu_dsm_size = igd_dsm_region_size(ptdev->phys_dev);
if (!gpu_dsm_size) {
pr_err("Invalid igd dsm region size, check DVMT Pre-Allocated option in BIOS\n");
return;
}
if (gen >= 11) {
switch (device) {
/* ElkhartLake */
case 0x4500:
case 0x4541:
case 0x4551:
case 0x4571:
/* TigerLake */
case 0x9a40:
case 0x9a49:
case 0x9a59:
case 0x9a60:
case 0x9a68:
case 0x9a70:
case 0x9a78:
case 0x9ac0:
case 0x9ac9:
case 0x9ad9:
case 0x9af8:
/* AlderLake */
case 0x4680:
case 0x4681:
case 0x4682:
case 0x4683:
case 0x4690:
case 0x4691:
case 0x4692:
case 0x4693:
case 0x4698:
case 0x4699:
/* ADL-P GT graphics */
case 0x4626:
case 0x4628:
case 0x462a:
case 0x46a0:
case 0x46a1:
case 0x46a2:
case 0x46a3:
case 0x46a6:
case 0x46a8:
case 0x46aa:
case 0x46b0:
case 0x46b1:
case 0x46b2:
case 0x46b3:
case 0x46c0:
case 0x46c1:
case 0x46c2:
case 0x46c3:
/* Alder Lake-N */
case 0x46d0:
case 0x46d1:
case 0x46d2:
/* Raptor Lake-S */
case 0xa780:
case 0xa781:
case 0xa782:
case 0xa783:
case 0xa788:
case 0xa789:
case 0xa78a:
case 0xa78b:
/* Raptor Lake-U */
case 0xa721:
case 0xa7a1:
case 0xa7a9:
/* Raptor Lake-P */
case 0xa720:
case 0xa7a0:
case 0xa7a8:
/* BDSM register has 64 bits.
* bits 63:20 contains the base address of stolen memory
*/
@ -658,7 +655,9 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
pci_set_cfgdata32(ptdev->dev, PCIR_GEN11_BDSM_DW1, 0);
ptdev->has_virt_pcicfg_regs = &has_virt_pcicfg_regs_on_ehl_gpu;
} else {
break;
/* If on default platforms, such as KBL,WHL */
default:
/* bits 31:20 contains the base address of stolen memory */
gpu_dsm_hpa = read_config(ptdev->phys_dev, PCIR_BDSM, 4);
dsm_mask_val = gpu_dsm_hpa & ~PCIM_BDSM_MASK;
@ -668,14 +667,15 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
pci_set_cfgdata32(ptdev->dev, PCIR_BDSM, gpu_dsm_gpa | dsm_mask_val);
ptdev->has_virt_pcicfg_regs = &has_virt_pcicfg_regs_on_def_gpu;
break;
}
gpu_opregion_gpa = gpu_dsm_gpa - GPU_OPREGION_SIZE;
pci_set_cfgdata32(ptdev->dev, PCIR_ASLS_CTL, gpu_opregion_gpa | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK));
/* initialize the EPT mapping for passthrough GPU dsm region */
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, gpu_dsm_size, gpu_dsm_hpa);
vm_map_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, gpu_dsm_size, gpu_dsm_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, GPU_DSM_SIZE, gpu_dsm_hpa);
vm_map_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, GPU_DSM_SIZE, gpu_dsm_hpa);
/* initialize the EPT mapping for passthrough GPU opregion */
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_opregion_gpa, GPU_OPREGION_SIZE, gpu_opregion_hpa);
@ -714,25 +714,22 @@ parse_vmsix_on_msi_bar_id(char *s, int *id, int base)
static int
passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
int bus, slot, func, idx, irq, error;
int bus, slot, func, idx, error;
struct passthru_dev *ptdev;
struct pci_device_iterator *iter;
struct pci_device *phys_dev;
char *opt, *s_irq;
char *opt;
bool keep_gsi = false;
bool need_reset = true;
bool d3hot_reset = false;
bool enable_ptm = false;
bool enable_irq = false;
int vrp_sec_bus = 0;
int vmsix_on_msi_bar_id = -1;
struct acrn_pcidev pcidev = {};
uint16_t vendor = 0, device = 0;
uint8_t class = 0;
char rom_file[256];
char dsdt_path[256];
bool need_rombar = false;
bool need_dsdt = false;
ptdev = NULL;
error = -EINVAL;
@ -749,7 +746,6 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
}
memset(rom_file, 0, sizeof(rom_file));
memset(dsdt_path, 0, sizeof(dsdt_path));
while ((opt = strsep(&opts, ",")) != NULL) {
if (!strncmp(opt, "keep_gsi", 8))
keep_gsi = true;
@ -774,25 +770,6 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
return -EINVAL;
}
strncpy(rom_file, opt, sizeof(rom_file));
} else if (!strncmp(opt, "irq=", 4)) {
if(dm_strtoi(opt + 4, &s_irq, 10, &irq) == 0) {
enable_irq = true;
pr_warn("IRQ %d might be shared by multiple devices!\n", irq);
}
else {
pr_err("Input IRQ number cannnot be recognized.\n");
return -EINVAL;
}
} else if (!strncmp(opt, "dsdt=", 5)) {
need_dsdt = true;
opt += 5;
if (strlen(opt) >= sizeof(dsdt_path)) {
pr_err("dsdt file path too long, max supported path length is %d\n",
sizeof(dsdt_path)-1);
return -EINVAL;
}
strncpy(dsdt_path, opt, sizeof(dsdt_path) - 1);
pr_info("dsdt file path is %s\n", dsdt_path);
} else
pr_warn("Invalid passthru options:%s", opt);
}
@ -916,12 +893,7 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
/* Allocates the virq if ptdev only support INTx */
pci_lintr_request(dev);
if(enable_irq) {
ptdev->phys_pin = irq;
}
else {
ptdev->phys_pin = read_config(ptdev->phys_dev, PCIR_INTLINE, 1);
}
ptdev->phys_pin = read_config(ptdev->phys_dev, PCIR_INTLINE, 1);
if (ptdev->phys_pin == -1 || ptdev->phys_pin > 256) {
pr_err("ptdev %x/%x/%x has wrong phys_pin %d, likely fail!",
@ -931,10 +903,6 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
}
}
ptdev->need_dsdt = need_dsdt;
memset(ptdev->dsdt_path, 0, sizeof(ptdev->dsdt_path));
strncpy(ptdev->dsdt_path, dsdt_path, sizeof(ptdev->dsdt_path) - 1);
if (enable_ptm) {
error = ptm_probe(ctx, ptdev, &vrp_sec_bus);
@ -1003,7 +971,7 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
phys_bdf = ptdev->phys_bdf;
if (is_intel_graphics_dev(dev)) {
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, gpu_dsm_size, gpu_dsm_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, GPU_DSM_SIZE, gpu_dsm_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_opregion_gpa, GPU_OPREGION_SIZE, gpu_opregion_hpa);
}
@ -1012,10 +980,13 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
pciaccess_cleanup();
free(ptdev);
/*Let device model to deassign pt device for all VMs, including RTVM if the Service VM plays
*supervisor role.*/
vm_deassign_pcidev(ctx, &pcidev);
if (phys_bdf) {
if (!is_rtvm) {
/* Let the HV to deassign the pt device for RTVM, In this case, the RTVM
* could still be alive if DM died.
*/
vm_deassign_pcidev(ctx, &pcidev);
}
if (!is_rtvm && phys_bdf) {
memset(reset_path, 0, sizeof(reset_path));
snprintf(reset_path, 40,
"/sys/bus/pci/devices/0000:%02x:%02x.%x/reset",
@ -1838,38 +1809,9 @@ write_dsdt_tsn(struct pci_vdev *dev, uint16_t device)
dsdt_line("");
}
static void
write_dsdt_file(struct pci_vdev *dev)
{
struct passthru_dev *ptdev = NULL;
FILE *fp;
char *line = NULL;
char *dsdt_path = NULL;
size_t len = 0;
ssize_t read;
ptdev = (struct passthru_dev *) dev->arg;
dsdt_path = ptdev->dsdt_path;
fp = fopen(dsdt_path, "r");
if (fp == NULL) {
pr_err("Cannot open dsdt file %s", dsdt_path);
return;
}
dsdt_line("");
/* Read each line of dsdt file */
while ((read = getline(&line, &len, fp)) != -1) {
dsdt_line(line);
}
if (line)
free(line);
fclose(fp);
}
static void
passthru_write_dsdt(struct pci_vdev *dev)
{
struct passthru_dev *ptdev = NULL;
uint16_t vendor = 0, device = 0;
vendor = pci_get_cfgdata16(dev, PCIR_VENDOR);
@ -1878,7 +1820,6 @@ passthru_write_dsdt(struct pci_vdev *dev)
return;
device = pci_get_cfgdata16(dev, PCIR_DEVICE);
ptdev = (struct passthru_dev *) dev->arg;
/* Provides ACPI extra info */
if (device == 0x5aaa)
@ -1901,9 +1842,6 @@ passthru_write_dsdt(struct pci_vdev *dev)
write_dsdt_sdc(dev);
else if ((device == 0x4b32) || (device == 0x4ba0) || (device == 0x4bb0))
write_dsdt_tsn(dev, device);
else if (ptdev->need_dsdt)
/* load DSDT by input file */
write_dsdt_file(dev);
}
struct pci_vdev_ops passthru = {

View File

@ -66,19 +66,13 @@ void iothread_handler(void *arg)
struct virtio_base *base = viothrd->base;
int idx = viothrd->idx;
struct virtio_vq_info *vq = &base->queues[idx];
eventfd_t val;
/* Mitigate the epoll_wait repeat cycles by reading out the event */
if (eventfd_read(vq->viothrd.iomvt.fd, &val) == -1) {
pr_err("%s: eventfd_read fails \r\n", __func__);
return;
}
if (viothrd->iothread_run) {
pthread_mutex_lock(&vq->mtx);
/* only vq specific data can be accessed in qnotify callback */
if (base->mtx)
pthread_mutex_lock(base->mtx);
(*viothrd->iothread_run)(base, vq);
pthread_mutex_unlock(&vq->mtx);
if (base->mtx)
pthread_mutex_unlock(base->mtx);
}
}
@ -112,12 +106,12 @@ virtio_set_iothread(struct virtio_base *base,
vq->viothrd.iomvt.run = iothread_handler;
vq->viothrd.iomvt.fd = vq->viothrd.kick_fd;
if (!iothread_add(vq->viothrd.ioctx, vq->viothrd.kick_fd, &vq->viothrd.iomvt))
if (!iothread_add(vq->viothrd.kick_fd, &vq->viothrd.iomvt))
if (!virtio_register_ioeventfd(base, idx, true, vq->viothrd.kick_fd))
vq->viothrd.ioevent_started = true;
} else {
if (!virtio_register_ioeventfd(base, idx, false, vq->viothrd.kick_fd))
if (!iothread_del(vq->viothrd.ioctx, vq->viothrd.kick_fd)) {
if (!iothread_del(vq->viothrd.kick_fd)) {
vq->viothrd.ioevent_started = false;
if (vq->viothrd.kick_fd) {
close(vq->viothrd.kick_fd);
@ -193,6 +187,8 @@ virtio_poll_timer(void *arg, uint64_t nexp)
* @param pci_virtio_dev Pointer to instance of certain virtio device.
* @param dev Pointer to struct pci_vdev which emulates a PCI device.
* @param queues Pointer to struct virtio_vq_info, normally an array.
*
* @return None
*/
void
virtio_linkup(struct virtio_base *base, struct virtio_ops *vops,
@ -200,27 +196,13 @@ virtio_linkup(struct virtio_base *base, struct virtio_ops *vops,
struct virtio_vq_info *queues,
int backend_type)
{
int i, rc;
pthread_mutexattr_t attr;
int i;
/* base and pci_virtio_dev addresses must match */
if ((void *)base != pci_virtio_dev) {
pr_err("virtio_base and pci_virtio_dev addresses don't match!\n");
return;
}
rc = pthread_mutexattr_init(&attr);
if (rc) {
pr_err("%s, pthread_mutexattr_init failed\n", __func__);
return;
}
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if (rc) {
pr_err("%s, pthread_mutexattr_settype failed\n", __func__);
return;
}
base->vops = vops;
base->dev = dev;
dev->arg = base;
@ -230,11 +212,6 @@ virtio_linkup(struct virtio_base *base, struct virtio_ops *vops,
for (i = 0; i < vops->nvq; i++) {
queues[i].base = base;
queues[i].num = i;
rc = pthread_mutex_init(&queues[i].mtx, &attr);
if (rc) {
pr_err("%s, pthread_mutex_init failed\n", __func__);
return;
}
}
}
@ -249,6 +226,8 @@ virtio_linkup(struct virtio_base *base, struct virtio_ops *vops,
* If MSI-X is enabled, this also resets all the vectors to NO_VECTOR.
*
* @param base Pointer to struct virtio_base.
*
* @return None
*/
void
virtio_reset_dev(struct virtio_base *base)
@ -296,6 +275,8 @@ virtio_reset_dev(struct virtio_base *base)
*
* @param base Pointer to struct virtio_base.
* @param barnum Which BAR[0..5] to use.
*
* @return None
*/
void
virtio_set_io_bar(struct virtio_base *base, int barnum)
@ -784,6 +765,8 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
*
* @param base Pointer to struct virtio_base.
* @param vq Pointer to struct virtio_vq_info.
*
* @return None
*/
void vq_clear_used_ring_flags(struct virtio_base *base, struct virtio_vq_info *vq)
{
@ -1946,6 +1929,8 @@ virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
* @param offset Register offset in bytes within a BAR region.
* @param size Access range in bytes.
* @param value Data value to be written into register.
*
* @return None
*/
void
virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
@ -2013,12 +1998,12 @@ int virtio_register_ioeventfd(struct virtio_base *base, int idx, bool is_registe
int rc = 0;
if (!is_register)
ioeventfd.flags |= ACRN_IOEVENTFD_FLAG_DEASSIGN;
if (base->iothread)
ioeventfd.flags = ACRN_IOEVENTFD_FLAG_DEASSIGN;
else if (base->iothread)
/* Enable ASYNCIO by default. If ASYNCIO is not supported by kernel
* or hyperviosr, this flag will be ignored.
*/
ioeventfd.flags |= ACRN_IOEVENTFD_FLAG_ASYNCIO;
ioeventfd.flags = ACRN_IOEVENTFD_FLAG_ASYNCIO;
/* register ioeventfd for kick */
if (base->device_caps & (1UL << VIRTIO_F_VERSION_1)) {
/*

View File

@ -61,7 +61,7 @@
/* Device can toggle its cache between writeback and writethrough modes */
#define VIRTIO_BLK_F_CONFIG_WCE (1 << 11)
#define VIRTIO_BLK_F_MQ (1 << 12) /* support more than one vq */
#define VIRTIO_BLK_F_DISCARD (1 << 13)
/*
@ -101,8 +101,8 @@ struct virtio_blk_config {
} topology;
uint8_t writeback;
uint8_t unused;
/* num_queues when VIRTIO_BLK_F_MQ is support*/
uint16_t num_queues;
/* Reserve for num_queues when VIRTIO_BLK_F_MQ is support*/
uint16_t reserve;
/* The maximum discard sectors (in 512-byte sectors) for one segment */
uint32_t max_discard_sectors;
/* The maximum number of discard segments */
@ -156,16 +156,13 @@ struct virtio_blk_ioreq {
struct virtio_blk {
struct virtio_base base;
pthread_mutex_t mtx;
struct virtio_vq_info *vqs;
struct virtio_vq_info vq;
struct virtio_blk_config cfg;
bool dummy_bctxt; /* Used in blockrescan. Indicate if the bctxt can be used */
struct blockif_ctxt *bc;
char ident[VIRTIO_BLK_BLK_ID_BYTES + 1];
struct virtio_blk_ioreq *ios;
struct virtio_blk_ioreq ios[VIRTIO_BLK_RINGSZ];
uint8_t original_wce;
int num_vqs;
struct iothreads_info iothrds_info;
struct virtio_ops ops;
};
static void virtio_blk_reset(void *);
@ -173,6 +170,18 @@ static void virtio_blk_notify(void *, struct virtio_vq_info *);
static int virtio_blk_cfgread(void *, int, int, uint32_t *);
static int virtio_blk_cfgwrite(void *, int, int, uint32_t);
static struct virtio_ops virtio_blk_ops = {
"virtio_blk", /* our name */
1, /* we support 1 virtqueue */
sizeof(struct virtio_blk_config), /* config reg size */
virtio_blk_reset, /* reset */
virtio_blk_notify, /* device-wide qnotify */
virtio_blk_cfgread, /* read PCI config */
virtio_blk_cfgwrite, /* write PCI config */
NULL, /* apply negotiated features */
NULL, /* called on guest set status */
};
static void
virtio_blk_reset(void *vdev)
{
@ -190,7 +199,6 @@ virtio_blk_done(struct blockif_req *br, int err)
{
struct virtio_blk_ioreq *io = br->param;
struct virtio_blk *blk = io->blk;
struct virtio_vq_info *vq = blk->vqs + br->qidx;
if (err)
DPRINTF(("virtio_blk: done with error = %d\n\r", err));
@ -207,10 +215,10 @@ virtio_blk_done(struct blockif_req *br, int err)
* Return the descriptor back to the host.
* We wrote 1 byte (our status) to host.
*/
pthread_mutex_lock(&vq->mtx);
vq_relchain(vq, io->idx, 1);
vq_endchains(vq, !vq_has_descs(vq));
pthread_mutex_unlock(&vq->mtx);
pthread_mutex_lock(&blk->mtx);
vq_relchain(&blk->vq, io->idx, 1);
vq_endchains(&blk->vq, !vq_has_descs(&blk->vq));
pthread_mutex_unlock(&blk->mtx);
}
static void
@ -227,14 +235,13 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
{
struct virtio_blk_hdr *vbh;
struct virtio_blk_ioreq *io;
int i, n, qidx;
int i, n;
int err;
ssize_t iolen;
int writeop, type;
struct iovec iov[BLOCKIF_IOV_MAX + 2];
uint16_t idx, flags[BLOCKIF_IOV_MAX + 2];
qidx = vq - blk->vqs;
idx = vq->qsize;
n = vq_getchain(vq, &idx, iov, BLOCKIF_IOV_MAX + 2, flags);
@ -252,7 +259,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
return;
}
io = &blk->ios[qidx * VIRTIO_BLK_RINGSZ + idx];
io = &blk->ios[idx];
if ((flags[0] & VRING_DESC_F_WRITE) != 0) {
WPRINTF(("%s: the type for hdr should not be VRING_DESC_F_WRITE\n", __func__));
virtio_blk_abort(vq, idx);
@ -413,9 +420,6 @@ virtio_blk_get_caps(struct virtio_blk *blk, bool wb)
if (blockif_is_ro(blk->bc))
caps |= VIRTIO_BLK_F_RO;
if (blk->num_vqs > 1)
caps |= VIRTIO_BLK_F_MQ;
return caps;
}
@ -443,7 +447,6 @@ virtio_blk_update_config_space(struct virtio_blk *blk)
(sto != 0) ? ((sts - sto) / sectsz) : 0;
blk->cfg.topology.min_io_size = 0;
blk->cfg.writeback = blockif_get_wce(blk->bc);
blk->cfg.num_queues = (uint16_t)blk->num_vqs;
blk->original_wce = blk->cfg.writeback; /* save for reset */
if (blockif_candiscard(blk->bc)) {
blk->cfg.max_discard_sectors = blockif_max_discard_sectors(blk->bc);
@ -453,18 +456,6 @@ virtio_blk_update_config_space(struct virtio_blk *blk)
blk->base.device_caps =
virtio_blk_get_caps(blk, !!blk->cfg.writeback);
}
static void
virtio_blk_init_ops(struct virtio_blk *blk, int num_vqs)
{
blk->ops.name = "virtio_blk";
blk->ops.nvq = num_vqs;
blk->ops.cfgsize = sizeof(struct virtio_blk_config);
blk->ops.reset = virtio_blk_reset;
blk->ops.cfgread = virtio_blk_cfgread;
blk->ops.cfgwrite = virtio_blk_cfgwrite;
}
static int
virtio_blk_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
@ -477,21 +468,14 @@ virtio_blk_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
u_char digest[16];
struct virtio_blk *blk;
bool use_iothread;
struct iothread_ctx *ioctx_base = NULL;
struct iothreads_info iothrds_info;
int num_vqs;
int i, j;
int i;
pthread_mutexattr_t attr;
int rc;
struct iothreads_option iot_opt;
memset(&iot_opt, 0, sizeof(iot_opt));
bctxt = NULL;
/* Assume the bctxt is valid, until identified otherwise */
dummy_bctxt = false;
use_iothread = false;
num_vqs = 1;
if (opts == NULL) {
pr_err("virtio_blk: backing device required\n");
@ -517,75 +501,17 @@ virtio_blk_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
return -1;
}
if (strstr(opts, "nodisk") == NULL) {
/*
* both ",iothread" and ",mq=int" are consumed by virtio-blk
* and must be specified before any other opts which will
* be used by blockif_open.
*/
char *p = opts_start;
while (opts_tmp != NULL) {
opt = strsep(&opts_tmp, ",");
if (!strncmp(opt, "iothread", strlen("iothread"))) {
use_iothread = true;
strsep(&opt, "=");
if (iothread_parse_options(opt, &iot_opt) < 0) {
free(opts_start);
return -1;
}
p = opts_tmp;
} else if (!strncmp(opt, "mq", strlen("mq"))) {
strsep(&opt, "=");
if (opt != NULL) {
if (dm_strtoi(opt, &opt, 10, &num_vqs) ||
(num_vqs <= 0)) {
WPRINTF(("%s: incorrect num queues %s\n",
__func__, opt));
free(opts_start);
return -1;
}
/* the max vq number allowed by FE is guest cpu num */
if (num_vqs > guest_cpu_num())
num_vqs = guest_cpu_num();
}
p = opts_tmp;
} else {
/* The opts_start is truncated by strsep, opts_tmp is also
* changed by strsetp, so use opts which points to the
* original parameter string
*/
p = opts + (p - opts_start);
break;
}
}
if (use_iothread) {
/*
* Creating more iothread instances than the number of virtqueues is not necessary.
* - One or more vqs can be handled in one iothread.
* - The mapping between virtqueues and iothreads is based on round robin.
opt = strsep(&opts_tmp, ",");
if (strcmp("iothread", opt) == 0) {
use_iothread = true;
} else {
/* The opts_start is truncated by strsep, opts_tmp is also
* changed by strsetp, so use opts which points to the
* original parameter string
*/
if (iot_opt.num > num_vqs) {
iot_opt.num = num_vqs;
}
if (snprintf(iot_opt.tag, sizeof(iot_opt.tag), "blk%s", bident) >= sizeof(iot_opt.tag)) {
pr_err("%s: virtio-blk ioctx_tag too long \n", __func__);
}
ioctx_base = iothread_create(&iot_opt);
iothread_free_options(&iot_opt);
if (ioctx_base == NULL) {
pr_err("%s: Fails to create iothread context instance \n", __func__);
return -1;
}
opts_tmp = opts;
}
iothrds_info.ioctx_base = ioctx_base;
iothrds_info.num = iot_opt.num;
bctxt = blockif_open(p, bident, num_vqs, &iothrds_info);
bctxt = blockif_open(opts_tmp, bident);
if (bctxt == NULL) {
pr_err("Could not open backing file");
free(opts_start);
@ -604,39 +530,17 @@ virtio_blk_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
return -1;
}
blk->iothrds_info.ioctx_base = ioctx_base;
blk->iothrds_info.num = iot_opt.num;
blk->bc = bctxt;
/* Update virtio-blk device struct of dummy ctxt*/
blk->dummy_bctxt = dummy_bctxt;
blk->num_vqs = num_vqs;
blk->vqs = calloc(blk->num_vqs, sizeof(struct virtio_vq_info));
if (!blk->vqs) {
WPRINTF(("virtio_blk: calloc vqs returns NULL\n"));
free(blk);
return -1;
}
blk->ios = calloc(blk->num_vqs * VIRTIO_BLK_RINGSZ,
sizeof(struct virtio_blk_ioreq));
if (!blk->ios) {
WPRINTF(("virtio_blk: calloc ios returns NULL\n"));
free(blk->vqs);
free(blk);
return -1;
}
for (i = 0; i < VIRTIO_BLK_RINGSZ; i++) {
struct virtio_blk_ioreq *io = &blk->ios[i];
for (j = 0; j < num_vqs; j++) {
for (i = 0; i < VIRTIO_BLK_RINGSZ; i++) {
struct virtio_blk_ioreq *io = &blk->ios[j * VIRTIO_BLK_RINGSZ + i];
io->req.callback = virtio_blk_done;
io->req.param = io;
io->req.qidx = j;
io->blk = blk;
io->idx = i;
}
io->req.callback = virtio_blk_done;
io->req.param = io;
io->blk = blk;
io->idx = i;
}
/* init mutex attribute properly to avoid deadlock */
@ -653,20 +557,13 @@ virtio_blk_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
DPRINTF(("virtio_blk: pthread_mutex_init failed with "
"error %d!\n", rc));
virtio_blk_init_ops(blk, num_vqs);
/* init virtio struct and virtqueues */
virtio_linkup(&blk->base, &(blk->ops), blk, dev, blk->vqs, BACKEND_VBSU);
virtio_linkup(&blk->base, &virtio_blk_ops, blk, dev, &blk->vq, BACKEND_VBSU);
blk->base.iothread = use_iothread;
blk->base.mtx = &blk->mtx;
for (j = 0; j < num_vqs; j++) {
blk->vqs[j].qsize = VIRTIO_BLK_RINGSZ;
blk->vqs[j].notify = virtio_blk_notify;
if (use_iothread) {
blk->vqs[j].viothrd.ioctx = ioctx_base + j % (iot_opt.num);
}
}
blk->vq.qsize = VIRTIO_BLK_RINGSZ;
/* blk->vq.vq_notify = we have no per-queue notify */
/*
* Create an identifier for the backing file. Use parts of the
@ -748,10 +645,6 @@ virtio_blk_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
blockif_close(bctxt);
}
virtio_reset_dev(&blk->base);
if (blk->ios)
free(blk->ios);
if (blk->vqs)
free(blk->vqs);
free(blk);
}
}
@ -851,7 +744,7 @@ virtio_blk_rescan(struct vmctx *ctx, struct pci_vdev *dev, char *newpath)
pr_err("name=%s, Path=%s, ident=%s\n", dev->name, newpath, bident);
/* update the bctxt for the virtio-blk device */
bctxt = blockif_open(newpath, bident, blk->num_vqs, &blk->iothrds_info);
bctxt = blockif_open(newpath, bident);
if (bctxt == NULL) {
pr_err("Error opening backing file\n");
goto end;

View File

@ -384,12 +384,6 @@ struct pci_xhci_vbdp_dev_state {
uint8_t state;
};
struct pci_xhci_async_request_node {
STAILQ_ENTRY(pci_xhci_async_request_node) link;
uint64_t offset;
uint64_t value;
};
struct pci_xhci_vdev {
struct pci_vdev *dev;
pthread_mutex_t mtx;
@ -430,12 +424,6 @@ struct pci_xhci_vdev {
int vbdp_dev_num;
struct pci_xhci_vbdp_dev_state vbdp_devs[XHCI_MAX_VIRT_PORTS];
pthread_t async_thread;
bool async_transfer;
pthread_cond_t async_cond;
pthread_mutex_t async_tmx;
STAILQ_HEAD(, pci_xhci_async_request_node) async_head;
/*
* native_ports uses for record the command line assigned native root
* hub ports and its child external hub ports.
@ -497,7 +485,6 @@ static int pci_xhci_parse_extcap(struct pci_xhci_vdev *xdev, char *opts);
static int pci_xhci_convert_speed(int lspeed);
static void pci_xhci_free_usb_xfer(struct pci_xhci_dev_emu *dev, struct usb_xfer *xfer);
static void pci_xhci_isoc_handler(void *arg, uint64_t param);
static void pci_xhci_async_enqueue(struct pci_xhci_vdev *xdev, uint64_t offset, uint64_t value);
#define XHCI_OPT_MAX_LEN 32
static struct pci_xhci_option_elem xhci_option_table[] = {
@ -1995,9 +1982,7 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
slot, di->path.bus, usb_dev_path(&di->path));
/* release all the resource allocated for virtual device */
pthread_mutex_unlock(&xdev->mtx);
pci_xhci_dev_destroy(dev);
pthread_mutex_lock(&xdev->mtx);
} else
UPRINTF(LWRN, "invalid slot %d\r\n", slot);
@ -2071,7 +2056,6 @@ pci_xhci_cmd_address_device(struct pci_xhci_vdev *xdev,
struct usb_native_devinfo *di;
uint32_t cmderr;
uint8_t rh_port;
int ret;
input_ctx = XHCI_GADDR(xdev, trb->qwTrb0 & ~0xFUL);
if (!input_ctx) {
@ -2126,10 +2110,7 @@ pci_xhci_cmd_address_device(struct pci_xhci_vdev *xdev,
"port %d\r\n", di->path.bus,
usb_dev_path(&di->path), rh_port);
pthread_mutex_unlock(&xdev->mtx);
dev = pci_xhci_dev_create(xdev, di);
pthread_mutex_lock(&xdev->mtx);
if (!dev) {
UPRINTF(LFTL, "fail to create device for %d-%s\r\n",
di->path.bus,
@ -2161,15 +2142,8 @@ pci_xhci_cmd_address_device(struct pci_xhci_vdev *xdev,
dev->hci.hci_address = slot;
dev->dev_ctx = dev_ctx;
if (dev->dev_ue->ue_reset == NULL) {
cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON;
goto done;
}
pthread_mutex_unlock(&xdev->mtx);
ret = dev->dev_ue->ue_reset(dev->dev_instance);
pthread_mutex_lock(&xdev->mtx);
if (ret < 0) {
if (dev->dev_ue->ue_reset == NULL ||
dev->dev_ue->ue_reset(dev->dev_instance) < 0) {
cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON;
goto done;
}
@ -2417,7 +2391,6 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_vdev *xdev,
devep = &dev->eps[epid];
pthread_mutex_lock(&devep->mtx);
pthread_mutex_unlock(&xdev->mtx);
xfer = devep->ep_xfer;
for (i = 0; i < xfer->max_blk_cnt; ++i) {
@ -2440,7 +2413,6 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_vdev *xdev,
UPRINTF(LDBG, "reset ep[%u] %08x %08x %016lx %08x\r\n",
epid, ep_ctx->dwEpCtx0, ep_ctx->dwEpCtx1, ep_ctx->qwEpCtx2,
ep_ctx->dwEpCtx4);
pthread_mutex_lock(&xdev->mtx);
pthread_mutex_unlock(&devep->mtx);
done:
@ -3050,10 +3022,8 @@ pci_xhci_try_usb_xfer(struct pci_xhci_vdev *xdev,
/* outstanding requests queued up */
if (dev->dev_ue->ue_data != NULL) {
pthread_mutex_unlock(&xdev->mtx);
err = dev->dev_ue->ue_data(dev->dev_instance, xfer, epid & 0x1 ?
USB_XFER_IN : USB_XFER_OUT, epid/2);
pthread_mutex_lock(&xdev->mtx);
if (err == USB_ERR_CANCELLED) {
if (USB_DATA_GET_ERRCODE(&xfer->data[xfer->head]) ==
USB_NAK)
@ -3316,11 +3286,8 @@ retry:
if (epid == 1) {
err = USB_ERR_NOT_STARTED;
if (dev->dev_ue->ue_request != NULL) {
pthread_mutex_unlock(&xdev->mtx);
if (dev->dev_ue->ue_request != NULL)
err = dev->dev_ue->ue_request(dev->dev_instance, xfer);
pthread_mutex_lock(&xdev->mtx);
}
setup_trb = NULL;
} else {
/* handle data transfer */
@ -3691,24 +3658,21 @@ pci_xhci_write(struct vmctx *ctx,
xdev = dev->arg;
pthread_mutex_lock(&xdev->mtx);
if (offset < XHCI_CAPLEN) /* read only registers */
UPRINTF(LWRN, "write RO-CAPs offset %ld\r\n", offset);
else if (offset < xdev->dboff) {
pthread_mutex_lock(&xdev->mtx);
else if (offset < xdev->dboff)
pci_xhci_hostop_write(xdev, offset, value);
pthread_mutex_unlock(&xdev->mtx);
} else if (offset < xdev->rtsoff) {
pci_xhci_async_enqueue(xdev, offset, value);
} else if (offset < xdev->rtsend) {
pthread_mutex_lock(&xdev->mtx);
else if (offset < xdev->rtsoff)
pci_xhci_dbregs_write(xdev, offset, value);
else if (offset < xdev->rtsend)
pci_xhci_rtsregs_write(xdev, offset, value);
pthread_mutex_unlock(&xdev->mtx);
} else if (offset < xdev->regsend) {
pthread_mutex_lock(&xdev->mtx);
else if (offset < xdev->regsend)
pci_xhci_excap_write(xdev, offset, value);
pthread_mutex_unlock(&xdev->mtx);
} else
else
UPRINTF(LWRN, "write invalid offset %ld\r\n", offset);
pthread_mutex_unlock(&xdev->mtx);
}
static uint64_t
@ -3937,29 +3901,25 @@ pci_xhci_read(struct vmctx *ctx,
uint32_t value;
xdev = dev->arg;
if (offset < XHCI_CAPLEN) {
pthread_mutex_lock(&xdev->mtx);
pthread_mutex_lock(&xdev->mtx);
if (offset < XHCI_CAPLEN)
value = pci_xhci_hostcap_read(xdev, offset);
pthread_mutex_unlock(&xdev->mtx);
} else if (offset < xdev->dboff) {
pthread_mutex_lock(&xdev->mtx);
else if (offset < xdev->dboff)
value = pci_xhci_hostop_read(xdev, offset);
pthread_mutex_unlock(&xdev->mtx);
} else if (offset < xdev->rtsoff) {
else if (offset < xdev->rtsoff)
value = pci_xhci_dbregs_read(xdev, offset);
} else if (offset < xdev->rtsend) {
pthread_mutex_lock(&xdev->mtx);
else if (offset < xdev->rtsend)
value = pci_xhci_rtsregs_read(xdev, offset);
pthread_mutex_unlock(&xdev->mtx);
} else if (offset < xdev->regsend) {
pthread_mutex_lock(&xdev->mtx);
else if (offset < xdev->regsend)
value = pci_xhci_excap_read(xdev, offset);
pthread_mutex_unlock(&xdev->mtx);
} else {
else {
value = 0;
UPRINTF(LDBG, "read invalid offset %ld\r\n", offset);
}
pthread_mutex_unlock(&xdev->mtx);
switch (size) {
case 1:
value &= 0xFF;
@ -4045,7 +4005,6 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
struct xhci_endp_ctx *ep_ctx;
int dir_in;
int epid;
int ret = 0;
dir_in = epctx & 0x80;
epid = epctx & ~0x80;
@ -4059,11 +4018,10 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
xdev = dev->xdev;
/* check if device is ready; OS has to initialise it */
pthread_mutex_lock(&xdev->mtx);
if (xdev->rtsregs.erstba_p == NULL ||
(xdev->opregs.usbcmd & XHCI_CMD_RS) == 0 ||
dev->dev_ctx == NULL)
goto out;
return 0;
p = XHCI_PORTREG_PTR(xdev, hci->hci_port);
@ -4072,18 +4030,16 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
p->portsc &= ~XHCI_PS_PLS_MASK;
p->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RESUME);
if ((p->portsc & XHCI_PS_PLC) != 0)
goto out;
return 0;
p->portsc |= XHCI_PS_PLC;
pci_xhci_set_evtrb(&evtrb, hci->hci_port,
XHCI_TRB_ERROR_SUCCESS,
XHCI_TRB_EVENT_PORT_STS_CHANGE);
if (pci_xhci_insert_event(xdev, &evtrb, 0) != 0) {
UPRINTF(LFTL, "Failed to inject port status change event!\r\n");
ret = -ENAVAIL;
goto out;
return -ENAVAIL;
}
}
@ -4092,15 +4048,14 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
if ((ep_ctx->dwEpCtx0 & 0x7) == XHCI_ST_EPCTX_DISABLED) {
UPRINTF(LWRN, "device interrupt on disabled endpoint %d\r\n",
epid);
goto out;
return 0;
}
UPRINTF(LDBG, "device interrupt on endpoint %d\r\n", epid);
pci_xhci_device_doorbell(xdev, hci->hci_port, epid, 0);
out:
pthread_mutex_unlock(&xdev->mtx);
return ret;
return 0;
}
static int
@ -4172,6 +4127,11 @@ pci_xhci_parse_bus_port(struct pci_xhci_vdev *xdev, char *opts)
goto errout;
}
if (bus >= USB_NATIVE_NUM_BUS || port >= USB_NATIVE_NUM_PORT) {
rc = -1;
goto errout;
}
if (!usb_native_is_bus_existed(bus) ||
!usb_native_is_port_existed(bus, port)) {
rc = -2;
@ -4458,55 +4418,6 @@ pci_xhci_isoc_handler(void *arg, uint64_t param)
? "under" : "over", pdata->slot, pdata->epnum);
}
static void
pci_xhci_async_enqueue(struct pci_xhci_vdev *xdev, uint64_t offset, uint64_t value)
{
struct pci_xhci_async_request_node *request;
request = malloc(sizeof(struct pci_xhci_async_request_node));
if (request == NULL) {
UPRINTF(LFTL, "%s: malloc memory fail\r\n", __func__);
return;
}
request->offset = offset;
request->value = value;
pthread_mutex_lock(&xdev->async_tmx);
if (STAILQ_EMPTY(&xdev->async_head)) {
STAILQ_INSERT_HEAD(&xdev->async_head, request, link);
} else {
STAILQ_INSERT_TAIL(&xdev->async_head, request, link);
}
pthread_cond_signal(&xdev->async_cond);
pthread_mutex_unlock(&xdev->async_tmx);
}
static void *
pci_xhci_ansyc_thread(void *data)
{
struct pci_xhci_vdev *xdev;
struct pci_xhci_async_request_node *request;
xdev = data;
pthread_mutex_lock(&xdev->async_tmx);
while (xdev->async_transfer || !STAILQ_EMPTY(&xdev->async_head)) {
if(STAILQ_EMPTY(&xdev->async_head))
pthread_cond_wait(&xdev->async_cond, &xdev->async_tmx);
if ((request = STAILQ_FIRST(&xdev->async_head)) == NULL) {
continue;
}
pthread_mutex_unlock(&xdev->async_tmx);
pthread_mutex_lock(&xdev->mtx);
pci_xhci_dbregs_write(xdev, request->offset, request->value);
pthread_mutex_unlock(&xdev->mtx);
pthread_mutex_lock(&xdev->async_tmx);
STAILQ_REMOVE_HEAD(&xdev->async_head, link);
free(request);
}
pthread_mutex_unlock(&xdev->async_tmx);
return NULL;
}
static int
pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
@ -4637,15 +4548,6 @@ pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
if (error)
goto done;
xdev->async_transfer = true;
pthread_cond_init(&xdev->async_cond, NULL);
pthread_mutex_init(&xdev->async_tmx, NULL);
STAILQ_INIT(&xdev->async_head);
error = pthread_create(&xdev->async_thread, NULL, pci_xhci_ansyc_thread,
(void *)xdev);
if (error)
goto done;
xhci_in_use = 1;
done:
if (error) {
@ -4701,14 +4603,6 @@ pci_xhci_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
pthread_join(xdev->vbdp_thread, NULL);
sem_close(&xdev->vbdp_sem);
pthread_mutex_lock(&xdev->async_tmx);
xdev->async_transfer = false;
pthread_cond_signal(&xdev->async_cond);
pthread_mutex_unlock(&xdev->async_tmx);
pthread_join(xdev->async_thread, NULL);
pthread_cond_destroy(&xdev->async_cond);
pthread_mutex_destroy(&xdev->async_tmx);
pthread_mutex_destroy(&xdev->mtx);
free(xdev);
xhci_in_use = 0;

View File

@ -93,10 +93,6 @@
#define RTCT_OFFSET 0xF00
#define DSDT_OFFSET 0x1100
/* Define the byte offset and byte length in FACS table */
#define WAKING_VECTOR_OFFSET 12
#define WAKING_VECTOR_LEN 4
#define ASL_TEMPLATE "dm.XXXXXXX"
#define ASL_SUFFIX ".aml"
@ -883,7 +879,6 @@ 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("}");
@ -1117,18 +1112,6 @@ get_acpi_table_length(void)
return ACPI_LENGTH;
}
uint32_t
get_acpi_wakingvector_offset(void)
{
return basl_acpi_base + FACS_OFFSET + WAKING_VECTOR_OFFSET;
}
uint32_t
get_acpi_wakingvector_length(void)
{
return WAKING_VECTOR_LEN;
}
int
get_default_iasl_compiler(void)
{

View File

@ -22,15 +22,15 @@ static inline int get_vcpu_pm_info(struct vmctx *ctx, int vcpu_id,
return vm_get_cpu_state(ctx, pm_info);
}
static inline int get_vcpu_px_cnt(struct vmctx *ctx, int vcpu_id, uint8_t *px_cnt)
static inline uint8_t get_vcpu_px_cnt(struct vmctx *ctx, int vcpu_id)
{
uint64_t px_cnt_u64;
int ret;
uint64_t px_cnt;
ret = get_vcpu_pm_info(ctx, vcpu_id, ACRN_PMCMD_GET_PX_CNT, &px_cnt_u64);
*px_cnt = (uint8_t)px_cnt_u64;
if (get_vcpu_pm_info(ctx, vcpu_id, ACRN_PMCMD_GET_PX_CNT, &px_cnt)) {
return 0;
}
return ret;
return (uint8_t)px_cnt;
}
uint8_t get_vcpu_cx_cnt(struct vmctx *ctx, int vcpu_id)
@ -259,13 +259,9 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id)
uint8_t vcpu_px_cnt;
int i;
struct acrn_pstate_data *vcpu_px_data;
int ret;
ret = get_vcpu_px_cnt(ctx, vcpu_id, &vcpu_px_cnt);
/* vcpu_px_cnt = 0 Indicates vcpu supports continuous pstate.
* Then we should write _CPC instate of _PSS
*/
if (ret || !vcpu_px_cnt) {
vcpu_px_cnt = get_vcpu_px_cnt(ctx, vcpu_id);
if (!vcpu_px_cnt) {
return -1;
}
@ -320,49 +316,10 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id)
return 0;
}
/* _CPC: Continuous Performance Control
* Hard code a V3 CPC table, describing HWP register interface.
*/
static void dsdt_write_cpc(void)
{
dsdt_line("");
dsdt_line(" Method (_CPC, 0, NotSerialized)");
dsdt_line(" {");
dsdt_line(" Return (Package (0x17)");
dsdt_line(" {");
dsdt_line(" 0x17,");
dsdt_line(" 0x03,");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x00000000000000CE, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},");
dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},");
dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E7, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E8, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x02, 0x01, 0x0000000000000777, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x01, 0x00, 0x0000000000000770, 0x04, )},");
dsdt_line(" One,");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x0A, 0x20, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000774, 0x04, )},");
dsdt_line(" Zero,");
dsdt_line(" Zero,");
dsdt_line(" Zero");
dsdt_line(" })");
dsdt_line(" }");
}
void pm_write_dsdt(struct vmctx *ctx, int ncpu)
{
int i;
int ret;
bool is_cpc = false;
uint8_t px_cnt;
/* Scope (_PR) */
dsdt_line("");
@ -407,85 +364,6 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu)
}
}
ret = get_vcpu_px_cnt(ctx, i, &px_cnt);
if (ret == 0 && px_cnt == 0) {
/* px_cnt = 0 Indicates vcpu supports continuous pstate.
* Then we can write _CPC
*/
is_cpc = true;
}
if (is_cpc) {
if (i == 0) {
dsdt_write_cpc();
} else {
dsdt_line(" Method (_CPC, 0, NotSerialized)");
dsdt_line(" {");
dsdt_line(" Return (^^PR00._CPC)");
dsdt_line(" }");
dsdt_line("");
}
}
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("");
}
}

View File

@ -202,7 +202,7 @@ vhpet_counter(struct vhpet *vhpet, struct timespec *nowptr)
val = vhpet->countbase;
if (vhpet_counter_enabled(vhpet)) {
if (clock_gettime(CLOCK_MONOTONIC, &now))
if (clock_gettime(CLOCK_REALTIME, &now))
pr_dbg("clock_gettime returned: %s", strerror(errno));
/* delta = now - countbase_ts */
@ -225,7 +225,7 @@ vhpet_counter(struct vhpet *vhpet, struct timespec *nowptr)
*/
if (nowptr) {
pr_warn("vhpet unexpected nowptr");
if (clock_gettime(CLOCK_MONOTONIC, nowptr))
if (clock_gettime(CLOCK_REALTIME, nowptr))
pr_dbg("clock_gettime returned: %s", strerror(errno));
}
}
@ -366,7 +366,7 @@ vhpet_timer_handler(void *a, uint64_t nexp)
vhpet_timer_interrupt(vhpet, n);
if (clock_gettime(CLOCK_MONOTONIC, &now))
if (clock_gettime(CLOCK_REALTIME, &now))
pr_dbg("clock_gettime returned: %s", strerror(errno));
if (acrn_timer_gettime(vhpet_tmr(vhpet, n), &tmrts))
@ -548,7 +548,7 @@ vhpet_start_counting(struct vhpet *vhpet)
{
int i;
if (clock_gettime(CLOCK_MONOTONIC, &vhpet->countbase_ts))
if (clock_gettime(CLOCK_REALTIME, &vhpet->countbase_ts))
pr_dbg("clock_gettime returned: %s", strerror(errno));
/* Restart the timers based on the main counter base value */
@ -639,7 +639,7 @@ vhpet_timer_update_config(struct vhpet *vhpet, int n, uint64_t data,
* - Timer remains in periodic mode
*/
if (!vhpet_timer_enabled(vhpet, n)) {
if (clock_gettime(CLOCK_MONOTONIC, &now))
if (clock_gettime(CLOCK_REALTIME, &now))
pr_dbg("clock_gettime returned: %s", strerror(errno));
vhpet_stop_timer(vhpet, n, &now, true);
} else if (!(oldval & (HPET_TCNF_TYPE | HPET_TCNF_INT_ENB)) ||
@ -998,7 +998,7 @@ vhpet_init(struct vmctx *ctx)
arg->timer_num = i;
tmr = &vhpet->timer[i].tmrlst[j].t;
tmr->clockid = CLOCK_MONOTONIC;
tmr->clockid = CLOCK_REALTIME;
error = acrn_timer_init(tmr, vhpet_timer_handler, arg);
if (error) {

View File

@ -107,7 +107,7 @@ ticks_elapsed_since(const struct timespec *since)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
if (clock_gettime(CLOCK_REALTIME, &ts))
pr_dbg("clock_gettime returned: %s", strerror(errno));
if (timespeccmp(&ts, since, <=))
@ -192,7 +192,7 @@ pit_load_ce(struct channel *c)
c->nullcnt = false;
c->crbyte = 0;
if (clock_gettime(CLOCK_MONOTONIC, &c->start_ts))
if (clock_gettime(CLOCK_REALTIME, &c->start_ts))
pr_dbg("clock_gettime returned: %s", strerror(errno));
if (c->initial == 0 || c->initial > 0x10000) {
@ -330,7 +330,7 @@ pit_timer_start_cntr0(struct vpit *vpit)
sigevt.sigev_notify = SIGEV_THREAD;
sigevt.sigev_notify_function = vpit_timer_handler;
if (timer_create(CLOCK_MONOTONIC, &sigevt, &c->timer_id))
if (timer_create(CLOCK_REALTIME, &sigevt, &c->timer_id))
pr_dbg("timer_create returned: %s", strerror(errno));
vpit_timer_arg[c->timer_idx].active = true;
@ -360,7 +360,7 @@ pit_update_counter(struct vpit *vpit, struct channel *c, bool latch,
c->initial = PIT_HZ_TO_TICKS(100);
delta_ticks = 0;
if (clock_gettime(CLOCK_MONOTONIC, &c->start_ts))
if (clock_gettime(CLOCK_REALTIME, &c->start_ts))
pr_dbg("clock_gettime returned: %s", strerror(errno));
} else
delta_ticks = ticks_elapsed_since(&c->start_ts);

View File

@ -41,7 +41,6 @@
#include "timer.h"
#include "acpi.h"
#include "lpc.h"
#include "vm_event.h"
#include "log.h"
@ -81,7 +80,6 @@ struct vrtc {
u_int addr; /* RTC register to read or write */
time_t base_uptime;
time_t base_rtctime;
time_t halted_rtctime;
struct rtcdev rtcdev;
};
@ -222,17 +220,6 @@ update_enabled(struct vrtc *vrtc)
return true;
}
/* monotonic time is number of seconds that the system has been running
* since it was booted. It is none setable. It is more suitable to be used
* as base time.
*/
static time_t monotonic_time(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec;
}
static time_t
vrtc_curtime(struct vrtc *vrtc, time_t *basetime)
{
@ -242,7 +229,7 @@ vrtc_curtime(struct vrtc *vrtc, time_t *basetime)
t = vrtc->base_rtctime;
*basetime = vrtc->base_uptime;
if (update_enabled(vrtc)) {
now = monotonic_time();
now = time(NULL);
delta = now - vrtc->base_uptime;
secs = delta;
t += secs;
@ -727,18 +714,6 @@ vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval)
}
}
static void
send_rtc_chg_event(time_t newtime, time_t lasttime)
{
struct vm_event event;
struct rtc_change_event_data *data = (struct rtc_change_event_data *)event.event_data;
event.type = VM_EVENT_RTC_CHG;
data->delta_time = newtime - lasttime;
data->last_time = lasttime;
dm_send_vm_event(&event);
}
static int
vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval)
{
@ -761,23 +736,16 @@ vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval)
if (changed & RTCSB_HALT) {
if ((newval & RTCSB_HALT) == 0) {
rtctime = rtc_to_secs(vrtc);
basetime = monotonic_time();
basetime = time(NULL);
if (rtctime == VRTC_BROKEN_TIME) {
if (rtc_flag_broken_time)
return -1;
} else {
/* send rtc change event if rtc time changed during halt */
if (vrtc->halted_rtctime != VRTC_BROKEN_TIME &&
rtctime != vrtc->halted_rtctime) {
send_rtc_chg_event(rtctime, vrtc->halted_rtctime);
vrtc->halted_rtctime = VRTC_BROKEN_TIME;
}
}
} else {
curtime = vrtc_curtime(vrtc, &basetime);
if (curtime != vrtc->base_rtctime)
return -1;
vrtc->halted_rtctime = curtime;
/*
* Force a refresh of the RTC date/time fields so
* they reflect the time right before the guest set
@ -842,7 +810,7 @@ vrtc_set_reg_a(struct vrtc *vrtc, uint8_t newval)
* maintain the illusion that the RTC date/time was frozen
* while the dividers were disabled.
*/
vrtc->base_uptime = monotonic_time();
vrtc->base_uptime = time(NULL);
RTC_DEBUG("RTC divider out of reset at %#lx/%#lx\n",
vrtc->base_rtctime, vrtc->base_uptime);
} else {
@ -914,12 +882,6 @@ vrtc_addr_handler(struct vmctx *ctx, int vcpu, int in, int port,
return 0;
}
static inline bool vrtc_is_time_register(uint32_t offset)
{
return ((offset == RTC_SEC) || (offset == RTC_MIN) || (offset == RTC_HRS) || (offset == RTC_DAY)
|| (offset == RTC_MONTH) || (offset == RTC_YEAR) || (offset == RTC_CENTURY));
}
int
vrtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port,
int bytes, uint32_t *eax, void *arg)
@ -998,23 +960,14 @@ vrtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port,
}
/*
* Some guests (e.g. OpenBSD) write the century byte outside of RTCSB_HALT,
* and some guests (e.g. WaaG) write all date/time outside of RTCSB_HALT,
* so re-calculate the RTC date/time.
* XXX some guests (e.g. OpenBSD) write the century byte
* outside of RTCSB_HALT so re-calculate the RTC date/time.
*/
if (vrtc_is_time_register(offset) && !rtc_halted(vrtc)) {
time_t last_time = curtime;
if (offset == RTC_CENTURY && !rtc_halted(vrtc)) {
curtime = rtc_to_secs(vrtc);
error = vrtc_time_update(vrtc, curtime, monotonic_time());
if ((error != 0) || (curtime == VRTC_BROKEN_TIME && rtc_flag_broken_time)) {
error = vrtc_time_update(vrtc, curtime, time(NULL));
if ((error != 0) || (curtime == VRTC_BROKEN_TIME && rtc_flag_broken_time))
error = -1;
} else {
/* We don't know when the Guest has finished the RTC change action.
* So send an event each time the date/time regs has been updated.
* The event handler will process those events.
*/
send_rtc_chg_event(rtc_to_secs(vrtc), last_time);
}
}
}
@ -1029,7 +982,7 @@ vrtc_set_time(struct vrtc *vrtc, time_t secs)
int error;
pthread_mutex_lock(&vrtc->mtx);
error = vrtc_time_update(vrtc, secs, monotonic_time());
error = vrtc_time_update(vrtc, secs, time(NULL));
pthread_mutex_unlock(&vrtc->mtx);
if (error)
@ -1040,17 +993,6 @@ vrtc_set_time(struct vrtc *vrtc, time_t secs)
return error;
}
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
* BIOS will read it and start S3 resume at POST Entry
*/
void vrtc_suspend(struct vmctx *ctx)
{
struct vrtc *vrtc = ctx->vrtc;
struct rtcdev *rtc = &vrtc->rtcdev;
*((uint8_t *)rtc + 0xF) = 0xFE;
}
int
vrtc_init(struct vmctx *ctx)
{
@ -1145,7 +1087,6 @@ vrtc_init(struct vmctx *ctx)
/* Reset the index register to a safe value. */
vrtc->addr = RTC_STATUSD;
vrtc->halted_rtctime = VRTC_BROKEN_TIME;
/*
* Initialize RTC time to 00:00:00 Jan 1, 1970 if curtime = 0
*/
@ -1154,16 +1095,16 @@ vrtc_init(struct vmctx *ctx)
pthread_mutex_lock(&vrtc->mtx);
vrtc->base_rtctime = VRTC_BROKEN_TIME;
vrtc_time_update(vrtc, curtime, monotonic_time());
vrtc_time_update(vrtc, curtime, time(NULL));
secs_to_rtc(curtime, vrtc, 0);
pthread_mutex_unlock(&vrtc->mtx);
/* init periodic interrupt timer */
vrtc->periodic_timer.clockid = CLOCK_MONOTONIC;
vrtc->periodic_timer.clockid = CLOCK_REALTIME;
acrn_timer_init(&vrtc->periodic_timer, vrtc_periodic_timer, vrtc);
/* init update interrupt timer(1s)*/
vrtc->update_timer.clockid = CLOCK_MONOTONIC;
vrtc->update_timer.clockid = CLOCK_REALTIME;
acrn_timer_init(&vrtc->update_timer, vrtc_update_timer, vrtc);
vrtc_start_timer(&vrtc->update_timer, 1, 0);

View File

@ -29,7 +29,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
@ -53,12 +52,6 @@
#define COM1_IRQ 4
#define COM2_BASE 0x2F8
#define COM2_IRQ 3
#define COM3_BASE 0x3E8
#define COM3_IRQ 6
#define COM4_BASE 0x2E8
#define COM4_IRQ 7
#define COM5_BASE 0x9000 /*for S5 connection*/
#define COM5_IRQ 10
#define DEFAULT_RCLK 1843200
#define DEFAULT_BAUD 9600
@ -90,13 +83,8 @@ static struct {
} uart_lres[] = {
{ COM1_BASE, COM1_IRQ, false},
{ COM2_BASE, COM2_IRQ, false},
{ COM3_BASE, COM3_IRQ, false},
{ COM4_BASE, COM4_IRQ, false},
{ COM5_BASE, COM5_IRQ, false},
};
static bool stdio_ctrl_a_pressed = false;
#define UART_NLDEVS (ARRAY_SIZE(uart_lres))
enum uart_be_type {
@ -630,18 +618,6 @@ uart_legacy_alloc(int which, int *baseaddr, int *irq)
return 0;
}
int
uart_legacy_reinit_res(int which, int baseaddr, int irq)
{
if (which < 0 || which >= UART_NLDEVS || uart_lres[which].inuse)
return -1;
uart_lres[which].baseaddr = baseaddr;
uart_lres[which].irq = irq;
return 0;
}
void
uart_legacy_dealloc(int which)
{
@ -720,18 +696,6 @@ 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);

View File

@ -99,8 +99,6 @@ struct acpi_madt_local_apic {
void acpi_table_enable(int num);
uint32_t get_acpi_base(void);
uint32_t get_acpi_table_length(void);
uint32_t get_acpi_wakingvector_offset(void);
uint32_t get_acpi_wakingvector_length(void);
struct vmctx;
@ -127,6 +125,4 @@ 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_ */

View File

@ -39,68 +39,19 @@
#include <sys/uio.h>
#include <sys/unistd.h>
#include "iothread.h"
#define BLOCKIF_IOV_MAX 256 /* not practical to be IOV_MAX */
/*
* |<------------------------------------- bounced_size --------------------------------->|
* |<-------- alignment ------->| |<-------- alignment ------->|
* |<--- head --->|<------------------------ org_size ---------------------->|<-- tail -->|
* | | | | | |
* *--------------$-------------*----------- ... ------------*---------------$------------*
* | | | | | |
* | start end |
* aligned_dn_start aligned_dn_end
* |__________head_area_________| |__________tail_area_________|
* |<--- head --->| | |<-- end_rmd -->|<-- tail -->|
* |<-------- alignment ------->| |<-------- alignment ------->|
*
*/
struct br_align_info {
uint32_t alignment;
bool is_iov_base_aligned;
bool is_iov_len_aligned;
bool is_offset_aligned;
/*
* Needs to convert the misaligned request to an aligned one when
* O_DIRECT is used, but the request (either buffer address/length, or offset) is not aligned.
*/
bool need_conversion;
uint32_t head;
uint32_t tail;
uint32_t org_size;
uint32_t bounced_size;
off_t aligned_dn_start;
off_t aligned_dn_end;
/*
* A bounce_iov for aligned read/write access.
* bounce_iov.iov_base is aligned to @alignment
* bounce_iov.iov_len is @bounced_size (@head + @org_size + @tail)
*/
struct iovec bounce_iov;
};
struct blockif_req {
struct iovec iov[BLOCKIF_IOV_MAX];
int iovcnt;
off_t offset;
ssize_t resid;
void (*callback)(struct blockif_req *req, int err);
void *param;
int qidx;
struct br_align_info align_info;
struct iovec iov[BLOCKIF_IOV_MAX];
int iovcnt;
off_t offset;
ssize_t resid;
void (*callback)(struct blockif_req *req, int err);
void *param;
};
struct blockif_ctxt;
struct blockif_ctxt *blockif_open(const char *optstr, const char *ident, int queue_num,
struct iothreads_info *iothrds_info);
struct blockif_ctxt *blockif_open(const char *optstr, const char *ident);
off_t blockif_size(struct blockif_ctxt *bc);
void blockif_chs(struct blockif_ctxt *bc, uint16_t *c, uint8_t *h,
uint8_t *s);

View File

@ -30,8 +30,6 @@
#define _DM_H_
#include <stdbool.h>
#include <sys/resource.h>
#include "types.h"
#include "dm_string.h"
#include "acrn_common.h"
@ -53,15 +51,6 @@ extern bool pt_tpm2;
extern bool ssram;
extern bool vtpm2;
extern bool is_winvm;
extern bool ovmf_loaded;
enum acrn_thread_prio {
PRIO_VCPU = PRIO_MIN,
PRIO_IOTHREAD = PRIO_MIN,
PRIO_VIRTIO_SND,
PRIO_VIRTIO_IPU,
PRIO_VIRTIO_GPU
};
/**
* @brief Convert guest physical address to host virtual address
@ -74,9 +63,7 @@ enum acrn_thread_prio {
*/
void *paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len);
int virtio_uses_msix(void);
int guest_cpu_num(void);
size_t high_bios_size(void);
void init_debugexit(void);
void deinit_debugexit(void);
void set_thread_priority(int priority, bool reset_on_fork);
#endif

View File

@ -1,273 +0,0 @@
/*
* Copyright (C) 2023 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Device ids are available in linux kernel source tree and Intel website.
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/drm/i915_pciids.h
* https://dgpu-docs.intel.com/devices/hardware-table.html
*/
#ifndef _IGD_PCIIDS_H_
#define _IGD_PCIIDS_H_
#include <stdint.h>
struct igd_device {
uint16_t device;
int gen;
};
#define IGD_DEVICE_ENTRY(id, gen) \
{ id, gen }
/* Skylake, Gen 9 */
#define IGD_SKL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x1906, 9), \
IGD_DEVICE_ENTRY(0x1913, 9), \
IGD_DEVICE_ENTRY(0x190E, 9), \
IGD_DEVICE_ENTRY(0x1915, 9), \
IGD_DEVICE_ENTRY(0x1902, 9), \
IGD_DEVICE_ENTRY(0x190A, 9), \
IGD_DEVICE_ENTRY(0x190B, 9), \
IGD_DEVICE_ENTRY(0x1917, 9), \
IGD_DEVICE_ENTRY(0x1916, 9), \
IGD_DEVICE_ENTRY(0x1921, 9), \
IGD_DEVICE_ENTRY(0x191E, 9), \
IGD_DEVICE_ENTRY(0x1912, 9), \
IGD_DEVICE_ENTRY(0x191A, 9), \
IGD_DEVICE_ENTRY(0x191B, 9), \
IGD_DEVICE_ENTRY(0x191D, 9), \
IGD_DEVICE_ENTRY(0x1923, 9), \
IGD_DEVICE_ENTRY(0x1926, 9), \
IGD_DEVICE_ENTRY(0x1927, 9), \
IGD_DEVICE_ENTRY(0x192A, 9), \
IGD_DEVICE_ENTRY(0x192B, 9), \
IGD_DEVICE_ENTRY(0x192D, 9), \
IGD_DEVICE_ENTRY(0x1932, 9), \
IGD_DEVICE_ENTRY(0x193A, 9), \
IGD_DEVICE_ENTRY(0x193B, 9), \
IGD_DEVICE_ENTRY(0x193D, 9)
/* Apollo Lake, Gen 9 */
#define IGD_BXT_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x0A84, 9), \
IGD_DEVICE_ENTRY(0x1A84, 9), \
IGD_DEVICE_ENTRY(0x1A85, 9), \
IGD_DEVICE_ENTRY(0x5A84, 9), \
IGD_DEVICE_ENTRY(0x5A85, 9)
/* Gemini Lake, Gen 9 */
#define IGD_GLK_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x3184, 9), \
IGD_DEVICE_ENTRY(0x3185, 9)
/* Kaby Lake, Gen 9 */
#define IGD_KBL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x5906, 9), \
IGD_DEVICE_ENTRY(0x5913, 9), \
IGD_DEVICE_ENTRY(0x590E, 9), \
IGD_DEVICE_ENTRY(0x5915, 9), \
IGD_DEVICE_ENTRY(0x5902, 9), \
IGD_DEVICE_ENTRY(0x5908, 9), \
IGD_DEVICE_ENTRY(0x590A, 9), \
IGD_DEVICE_ENTRY(0x590B, 9), \
IGD_DEVICE_ENTRY(0x5916, 9), \
IGD_DEVICE_ENTRY(0x5921, 9), \
IGD_DEVICE_ENTRY(0x591E, 9), \
IGD_DEVICE_ENTRY(0x5912, 9), \
IGD_DEVICE_ENTRY(0x5917, 9), \
IGD_DEVICE_ENTRY(0x591A, 9), \
IGD_DEVICE_ENTRY(0x591B, 9), \
IGD_DEVICE_ENTRY(0x591D, 9), \
IGD_DEVICE_ENTRY(0x5926, 9), \
IGD_DEVICE_ENTRY(0x5923, 9), \
IGD_DEVICE_ENTRY(0x5927, 9), \
IGD_DEVICE_ENTRY(0x593B, 9), \
IGD_DEVICE_ENTRY(0x591C, 9), \
IGD_DEVICE_ENTRY(0x87C0, 9)
/* Coffee Lake/Comet Lake, Gen 9 */
#define IGD_CFL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x87CA, 9), \
IGD_DEVICE_ENTRY(0x9BA2, 9), \
IGD_DEVICE_ENTRY(0x9BA4, 9), \
IGD_DEVICE_ENTRY(0x9BA5, 9), \
IGD_DEVICE_ENTRY(0x9BA8, 9), \
IGD_DEVICE_ENTRY(0x9B21, 9), \
IGD_DEVICE_ENTRY(0x9BAA, 9), \
IGD_DEVICE_ENTRY(0x9BAC, 9), \
IGD_DEVICE_ENTRY(0x9BC2, 9), \
IGD_DEVICE_ENTRY(0x9BC4, 9), \
IGD_DEVICE_ENTRY(0x9BC5, 9), \
IGD_DEVICE_ENTRY(0x9BC6, 9), \
IGD_DEVICE_ENTRY(0x9BC8, 9), \
IGD_DEVICE_ENTRY(0x9BE6, 9), \
IGD_DEVICE_ENTRY(0x9BF6, 9), \
IGD_DEVICE_ENTRY(0x9B41, 9), \
IGD_DEVICE_ENTRY(0x9BCA, 9), \
IGD_DEVICE_ENTRY(0x9BCC, 9), \
IGD_DEVICE_ENTRY(0x3E90, 9), \
IGD_DEVICE_ENTRY(0x3E93, 9), \
IGD_DEVICE_ENTRY(0x3E99, 9), \
IGD_DEVICE_ENTRY(0x3E91, 9), \
IGD_DEVICE_ENTRY(0x3E92, 9), \
IGD_DEVICE_ENTRY(0x3E96, 9), \
IGD_DEVICE_ENTRY(0x3E98, 9), \
IGD_DEVICE_ENTRY(0x3E9A, 9), \
IGD_DEVICE_ENTRY(0x3E9C, 9), \
IGD_DEVICE_ENTRY(0x3E94, 9), \
IGD_DEVICE_ENTRY(0x3E9B, 9), \
IGD_DEVICE_ENTRY(0x3EA9, 9), \
IGD_DEVICE_ENTRY(0x3EA5, 9), \
IGD_DEVICE_ENTRY(0x3EA6, 9), \
IGD_DEVICE_ENTRY(0x3EA7, 9), \
IGD_DEVICE_ENTRY(0x3EA8, 9), \
IGD_DEVICE_ENTRY(0x3EA1, 9), \
IGD_DEVICE_ENTRY(0x3EA4, 9), \
IGD_DEVICE_ENTRY(0x3EA0, 9), \
IGD_DEVICE_ENTRY(0x3EA3, 9), \
IGD_DEVICE_ENTRY(0x3EA2, 9)
/* Ice Lake, Gen 11 */
#define IGD_ICL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x8A50, 11), \
IGD_DEVICE_ENTRY(0x8A52, 11), \
IGD_DEVICE_ENTRY(0x8A53, 11), \
IGD_DEVICE_ENTRY(0x8A54, 11), \
IGD_DEVICE_ENTRY(0x8A56, 11), \
IGD_DEVICE_ENTRY(0x8A57, 11), \
IGD_DEVICE_ENTRY(0x8A58, 11), \
IGD_DEVICE_ENTRY(0x8A59, 11), \
IGD_DEVICE_ENTRY(0x8A5A, 11), \
IGD_DEVICE_ENTRY(0x8A5B, 11), \
IGD_DEVICE_ENTRY(0x8A5C, 11), \
IGD_DEVICE_ENTRY(0x8A70, 11), \
IGD_DEVICE_ENTRY(0x8A71, 11), \
IGD_DEVICE_ENTRY(0x8A51, 11), \
IGD_DEVICE_ENTRY(0x8A5D, 11)
/* Elkhart Lake, Gen 12 */
#define IGD_EHL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x4541, 12), \
IGD_DEVICE_ENTRY(0x4551, 12), \
IGD_DEVICE_ENTRY(0x4555, 12), \
IGD_DEVICE_ENTRY(0x4557, 12), \
IGD_DEVICE_ENTRY(0x4570, 12), \
IGD_DEVICE_ENTRY(0x4571, 12)
/* Jasper Lake, Gen 12 */
#define IGD_JSL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x4E51, 12), \
IGD_DEVICE_ENTRY(0x4E55, 12), \
IGD_DEVICE_ENTRY(0x4E57, 12), \
IGD_DEVICE_ENTRY(0x4E61, 12), \
IGD_DEVICE_ENTRY(0x4E71, 12)
/* Tiger Lake, Gen 12 */
#define IGD_TGL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x9A60, 12), \
IGD_DEVICE_ENTRY(0x9A68, 12), \
IGD_DEVICE_ENTRY(0x9A70, 12), \
IGD_DEVICE_ENTRY(0x9A40, 12), \
IGD_DEVICE_ENTRY(0x9A49, 12), \
IGD_DEVICE_ENTRY(0x9A59, 12), \
IGD_DEVICE_ENTRY(0x9A78, 12), \
IGD_DEVICE_ENTRY(0x9AC0, 12), \
IGD_DEVICE_ENTRY(0x9AC9, 12), \
IGD_DEVICE_ENTRY(0x9AD9, 12), \
IGD_DEVICE_ENTRY(0x9AF8, 12)
/* Rocket Lake, Gen 12 */
#define IGD_RKL_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x4C80, 12), \
IGD_DEVICE_ENTRY(0x4C8A, 12), \
IGD_DEVICE_ENTRY(0x4C8B, 12), \
IGD_DEVICE_ENTRY(0x4C8C, 12), \
IGD_DEVICE_ENTRY(0x4C90, 12), \
IGD_DEVICE_ENTRY(0x4C9A, 12)
/* Alder Lake-S, Gen 12 */
#define IGD_ADLS_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x4680, 12), \
IGD_DEVICE_ENTRY(0x4682, 12), \
IGD_DEVICE_ENTRY(0x4688, 12), \
IGD_DEVICE_ENTRY(0x468A, 12), \
IGD_DEVICE_ENTRY(0x468B, 12), \
IGD_DEVICE_ENTRY(0x4690, 12), \
IGD_DEVICE_ENTRY(0x4692, 12), \
IGD_DEVICE_ENTRY(0x4693, 12)
/* Alder Lake-P, Gen 12 */
#define IGD_ADLP_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x46A0, 12), \
IGD_DEVICE_ENTRY(0x46A1, 12), \
IGD_DEVICE_ENTRY(0x46A2, 12), \
IGD_DEVICE_ENTRY(0x46A3, 12), \
IGD_DEVICE_ENTRY(0x46A6, 12), \
IGD_DEVICE_ENTRY(0x46A8, 12), \
IGD_DEVICE_ENTRY(0x46AA, 12), \
IGD_DEVICE_ENTRY(0x462A, 12), \
IGD_DEVICE_ENTRY(0x4626, 12), \
IGD_DEVICE_ENTRY(0x4628, 12), \
IGD_DEVICE_ENTRY(0x46B0, 12), \
IGD_DEVICE_ENTRY(0x46B1, 12), \
IGD_DEVICE_ENTRY(0x46B2, 12), \
IGD_DEVICE_ENTRY(0x46B3, 12), \
IGD_DEVICE_ENTRY(0x46C0, 12), \
IGD_DEVICE_ENTRY(0x46C1, 12), \
IGD_DEVICE_ENTRY(0x46C2, 12), \
IGD_DEVICE_ENTRY(0x46C3, 12)
/* Alder Lake-N, Gen 12 */
#define IGD_ADLN_DEVICE_IDS \
IGD_DEVICE_ENTRY(0x46D0, 12), \
IGD_DEVICE_ENTRY(0x46D1, 12), \
IGD_DEVICE_ENTRY(0x46D2, 12), \
IGD_DEVICE_ENTRY(0x46D3, 12), \
IGD_DEVICE_ENTRY(0x46D4, 12)
/* Raptor Lake-S, Gen 12 */
#define IGD_RPLS_DEVICE_IDS \
IGD_DEVICE_ENTRY(0xA780, 12), \
IGD_DEVICE_ENTRY(0xA781, 12), \
IGD_DEVICE_ENTRY(0xA782, 12), \
IGD_DEVICE_ENTRY(0xA783, 12), \
IGD_DEVICE_ENTRY(0xA788, 12), \
IGD_DEVICE_ENTRY(0xA789, 12), \
IGD_DEVICE_ENTRY(0xA78A, 12), \
IGD_DEVICE_ENTRY(0xA78B, 12)
/* Raptor Lake-P, Gen 12 */
#define IGD_RPLP_DEVICE_IDS \
IGD_DEVICE_ENTRY(0xA721, 12), \
IGD_DEVICE_ENTRY(0xA7A1, 12), \
IGD_DEVICE_ENTRY(0xA7A9, 12), \
IGD_DEVICE_ENTRY(0xA7AC, 12), \
IGD_DEVICE_ENTRY(0xA7AD, 12), \
IGD_DEVICE_ENTRY(0xA720, 12), \
IGD_DEVICE_ENTRY(0xA7A0, 12), \
IGD_DEVICE_ENTRY(0xA7A8, 12), \
IGD_DEVICE_ENTRY(0xA7AA, 12), \
IGD_DEVICE_ENTRY(0xA7AB, 12)
#endif

View File

@ -7,48 +7,14 @@
#ifndef _iothread_CTX_H_
#define _iothread_CTX_H_
#define IOTHREAD_NUM 40
/*
* The pthread_setname_np() function can be used to set a unique name for a thread,
* which can be useful for debugging multithreaded applications.
* The thread name is a meaningful C language string,
* whose length is restricted to 16 characters, including the terminating null byte ('\0').
*/
#define PTHREAD_NAME_MAX_LEN 16
struct iothread_mevent {
void (*run)(void *);
void *arg;
int fd;
};
struct iothread_ctx {
pthread_t tid;
int epfd;
bool started;
pthread_mutex_t mtx;
int idx;
cpu_set_t cpuset;
char name[PTHREAD_NAME_MAX_LEN];
};
struct iothreads_option {
char tag[PTHREAD_NAME_MAX_LEN];
int num;
cpu_set_t *cpusets;
};
struct iothreads_info {
struct iothread_ctx *ioctx_base;
int num;
};
int iothread_add(struct iothread_ctx *ioctx_x, int fd, struct iothread_mevent *aevt);
int iothread_del(struct iothread_ctx *ioctx_x, int fd);
int iothread_add(int fd, struct iothread_mevent *aevt);
int iothread_del(int fd);
int iothread_init(void);
void iothread_deinit(void);
struct iothread_ctx *iothread_create(struct iothreads_option *iothr_opt);
int iothread_parse_options(char *str, struct iothreads_option *iothr_opt);
void iothread_free_options(struct iothreads_option *iothr_opt);
#endif

View File

@ -36,7 +36,4 @@ unsigned get_wakeup_reason(void);
int set_wakeup_timer(time_t t);
int acrn_parse_intr_monitor(const char *opt);
int vm_monitor_blkrescan(void *arg, char *devargs);
int vm_monitor_send_vm_event(const char *msg);
#endif

View File

@ -9,7 +9,6 @@
#define __PASSTHRU_H__
#include <types.h>
#include <limits.h>
#include "pciaccess.h"
#include "pci_core.h"
@ -38,9 +37,7 @@ struct passthru_dev {
bool need_reset;
bool d3hot_reset;
bool need_rombar;
bool need_dsdt;
char *rom_buffer;
char dsdt_path[256];
bool (*has_virt_pcicfg_regs)(int offset);
};

View File

@ -296,6 +296,7 @@ void destory_io_rsvd_rgns(struct pci_vdev *vdev);
* For OpRegion 2.0: ASLE.rvda = physical address, not support currently
*/
#define GPU_DSM_GPA 0x7C000000
#define GPU_DSM_SIZE 0x4000000
#define GPU_OPREGION_SIZE 0x5000
/*
* TODO: Forced DSM/OPREGION size requires native BIOS configuration.
@ -349,6 +350,8 @@ int pci_emul_add_pciecap(struct pci_vdev *pi, int pcie_device_type);
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param index Message data index.
*
* @return None
*/
void pci_generate_msi(struct pci_vdev *dev, int index);
@ -357,6 +360,8 @@ void pci_generate_msi(struct pci_vdev *dev, int index);
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param index MSIs table entry index.
*
* @return None
*/
void pci_generate_msix(struct pci_vdev *dev, int index);
@ -364,6 +369,8 @@ void pci_generate_msix(struct pci_vdev *dev, int index);
* @brief Assert INTx pin of virtual PCI device
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
*
* @return None
*/
void pci_lintr_assert(struct pci_vdev *dev);
@ -371,6 +378,8 @@ void pci_lintr_assert(struct pci_vdev *dev);
* @brief Deassert INTx pin of virtual PCI device
*
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
*
* @return None
*/
void pci_lintr_deassert(struct pci_vdev *dev);
@ -408,6 +417,8 @@ struct pci_vdev *pci_get_vdev_info(int slot);
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param offset Offset in configuration space.
* @param val Value in 1 byte.
*
* @return None
*/
static inline void
pci_set_cfgdata8(struct pci_vdev *dev, int offset, uint8_t val)
@ -425,6 +436,8 @@ pci_set_cfgdata8(struct pci_vdev *dev, int offset, uint8_t val)
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param offset Offset in configuration space.
* @param val Value in 2 bytes.
*
* @return None
*/
static inline void
pci_set_cfgdata16(struct pci_vdev *dev, int offset, uint16_t val)
@ -442,6 +455,8 @@ pci_set_cfgdata16(struct pci_vdev *dev, int offset, uint16_t val)
* @param dev Pointer to struct pci_vdev representing virtual PCI device.
* @param offset Offset in configuration space.
* @param val Value in 4 bytes.
*
* @return None
*/
static inline void
pci_set_cfgdata32(struct pci_vdev *dev, int offset, uint32_t val)

View File

@ -1066,8 +1066,6 @@
#define PCIM_OSC_CTL_PCIE_CAP_STRUCT 0x10 /* Various Capability Structures */
/* Graphics definitions */
#define PCIR_GGC 0x50 /* GMCH Graphics Control */
#define PCIR_GGC_GMS_SHIFT 8 /* Bit 15:8 Graphics Memory Size (GMS) */
#define PCIR_BDSM 0x5C /* BDSM graphics base data of stolen memory register */
#define PCIR_GEN11_BDSM_DW0 0xC0
#define PCIR_GEN11_BDSM_DW1 0xC4

View File

@ -107,6 +107,8 @@
_IOW(ACRN_IOCTL_TYPE, 0x41, struct acrn_vm_memmap)
#define ACRN_IOCTL_UNSET_MEMSEG \
_IOW(ACRN_IOCTL_TYPE, 0x42, struct acrn_vm_memmap)
#define ACRN_IOCTL_SETUP_SBUF \
_IOW(ACRN_IOCTL_TYPE, 0x43, struct acrn_sbuf)
/* PCI assignment*/
#define ACRN_IOCTL_SET_PTDEV_INTR \
@ -136,15 +138,6 @@
#define ACRN_IOCTL_IRQFD \
_IOW(ACRN_IOCTL_TYPE, 0x71, struct acrn_irqfd)
/* Asynchronous IO */
#define ACRN_IOCTL_SETUP_ASYNCIO \
_IOW(ACRN_IOCTL_TYPE, 0x90, __u64)
/* VM EVENT */
#define ACRN_IOCTL_SETUP_VM_EVENT_RING \
_IOW(ACRN_IOCTL_TYPE, 0xa0, __u64)
#define ACRN_IOCTL_SETUP_VM_EVENT_FD \
_IOW(ACRN_IOCTL_TYPE, 0xa1, int)
#define ACRN_MEM_ACCESS_RIGHT_MASK 0x00000007U
#define ACRN_MEM_ACCESS_READ 0x00000001U
@ -257,4 +250,13 @@ struct acrn_irqfd {
struct acrn_msi_entry msi;
};
/**
* @brief data structure to register a share buffer by ioctl
*/
struct acrn_sbuf {
/** Type of the sbuf. */
uint32_t sbuf_id;
/** Base address of the sbuf. */
uint64_t base;
};
#endif /* VHM_IOCTL_DEFS_H */

View File

@ -43,7 +43,6 @@ struct vrtc;
struct vmctx;
int vrtc_init(struct vmctx *ctx);
void vrtc_suspend(struct vmctx *ctx);
void vrtc_enable_localtime(int l_time);
void vrtc_deinit(struct vmctx *ctx);
int vrtc_set_time(struct vrtc *vrtc, time_t secs);

View File

@ -1,39 +0,0 @@
/*
* Copyright (C) 2018-2023 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SHARED_BUF_H
#define SHARED_BUF_H
#include <linux/types.h>
#include "acrn_common.h"
static inline bool sbuf_is_empty(struct shared_buf *sbuf)
{
return (sbuf->head == sbuf->tail);
}
static inline void sbuf_clear_flags(struct shared_buf *sbuf, uint64_t flags)
{
sbuf->flags &= ~flags;
}
static inline void sbuf_set_flags(struct shared_buf *sbuf, uint64_t flags)
{
sbuf->flags = flags;
}
static inline void sbuf_add_flags(struct shared_buf *sbuf, uint64_t flags)
{
sbuf->flags |= flags;
}
uint32_t sbuf_get(struct shared_buf *sbuf, uint8_t *data);
uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data, uint32_t max_len);
int sbuf_clear_buffered(struct shared_buf *sbuf);
void sbuf_init(struct shared_buf *sbuf, uint32_t total_size, uint32_t ele_size);
#endif /* SHARED_BUF_H */

View File

@ -36,7 +36,6 @@ struct uart_vdev;
typedef void (*uart_intr_func_t)(void *arg);
int uart_legacy_alloc(int unit, int *ioaddr, int *irq);
int uart_legacy_reinit_res(int which, int baseaddr, int irq);
void uart_legacy_dealloc(int which);
uint8_t uart_read(struct uart_vdev *uart, int offset);
void uart_write(struct uart_vdev *uart, int offset, uint8_t value);

View File

@ -221,6 +221,12 @@ enum USB_ERRCODE {
do { if (lvl <= usb_log_level) pr_dbg(LOG_TAG fmt, ##args); } while (0)
#define NATIVE_USBSYS_DEVDIR "/sys/bus/usb/devices"
#define NATIVE_USB2_SPEED "480"
#define NATIVE_USB3_SPEED "5000"
#define USB_NATIVE_NUM_PORT 20
#define USB_NATIVE_NUM_BUS 5
#define USB_DROPPED_XFER_MAGIC 0xaaaaaaaa55555555
inline bool
index_valid(int head, int tail, int maxcnt, int idx) {

View File

@ -427,7 +427,6 @@ struct virtio_iothread {
int idx;
int kick_fd;
bool ioevent_started;
struct iothread_ctx *ioctx;
struct iothread_mevent iomvt;
void (*iothread_run)(void *, struct virtio_vq_info *);
};
@ -440,7 +439,6 @@ struct virtio_vq_info {
struct virtio_base *base;
/**< backpointer to virtio_base */
uint16_t num; /**< the num'th queue in the virtio_base */
pthread_mutex_t mtx; /**< per queue mutex */
uint16_t flags; /**< flags (see above) */
uint16_t last_avail; /**< a recent value of avail->idx */
@ -512,6 +510,8 @@ vq_has_descs(struct virtio_vq_info *vq)
*
* @param vb Pointer to struct virtio_base.
* @param vq Pointer to struct virtio_vq_info.
*
* @return None
*/
static inline void
vq_interrupt(struct virtio_base *vb, struct virtio_vq_info *vq)
@ -533,6 +533,8 @@ vq_interrupt(struct virtio_base *vb, struct virtio_vq_info *vq)
* MSI-X or a generic MSI interrupt with config changed event.
*
* @param vb Pointer to struct virtio_base.
*
* @return None
*/
static inline void
virtio_config_changed(struct virtio_base *vb)
@ -565,6 +567,8 @@ struct iovec;
* @param dev Pointer to struct pci_vdev which emulates a PCI device.
* @param queues Pointer to struct virtio_vq_info, normally an array.
* @param backend_type can be VBSU, VBSK or VHOST
*
* @return None
*/
void virtio_linkup(struct virtio_base *base, struct virtio_ops *vops,
void *pci_virtio_dev, struct pci_vdev *dev,
@ -620,6 +624,8 @@ int virtio_intr_init(struct virtio_base *base, int barnum, int use_msix);
* If MSI-X is enabled, this also resets all the vectors to NO_VECTOR.
*
* @param base Pointer to struct virtio_base.
*
* @return None
*/
void virtio_reset_dev(struct virtio_base *base);
@ -628,6 +634,8 @@ void virtio_reset_dev(struct virtio_base *base);
*
* @param base Pointer to struct virtio_base.
* @param barnum Which BAR[0..5] to use.
*
* @return None
*/
void virtio_set_io_bar(struct virtio_base *base, int barnum);
@ -652,6 +660,8 @@ int vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
* available ring.
*
* @param vq Pointer to struct virtio_vq_info.
*
* @return None
*/
void vq_retchain(struct virtio_vq_info *vq);
@ -662,6 +672,8 @@ void vq_retchain(struct virtio_vq_info *vq);
* @param vq Pointer to struct virtio_vq_info.
* @param idx Pointer to available ring position, returned by vq_getchain().
* @param iolen Number of data bytes to be returned to frontend.
*
* @return None
*/
void vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen);
@ -673,6 +685,8 @@ void vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen);
*
* @param vq Pointer to struct virtio_vq_info.
* @param used_all_avail Flag indicating if driver used all available chains.
*
* @return None
*/
void vq_endchains(struct virtio_vq_info *vq, int used_all_avail);
@ -685,6 +699,8 @@ void vq_endchains(struct virtio_vq_info *vq, int used_all_avail);
*
* @param base Pointer to struct virtio_base.
* @param vq Pointer to struct virtio_vq_info.
*
* @return None
*/
void vq_clear_used_ring_flags(struct virtio_base *base, struct virtio_vq_info *vq);
@ -719,6 +735,8 @@ uint64_t virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
* @param offset Register offset in bytes within a BAR region.
* @param size Access range in bytes.
* @param value Data value to be written into register.
*
* @return None
*/
void virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
int baridx, uint64_t offset, int size, uint64_t value);

View File

@ -1,18 +0,0 @@
/*
* Copyright (C) 2019-2023 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef VM_EVENT_H
#define VM_EVENT_H
#include <types.h>
#include "vmmapi.h"
int vm_event_init(struct vmctx *ctx);
int vm_event_deinit(void);
int dm_send_vm_event(struct vm_event *event);
uint32_t get_dm_vm_event_overrun_count(void);
#endif /* VM_EVENT_H */

View File

@ -107,7 +107,7 @@ int vm_create_ioreq_client(struct vmctx *ctx);
int vm_destroy_ioreq_client(struct vmctx *ctx);
int vm_attach_ioreq_client(struct vmctx *ctx);
int vm_notify_request_done(struct vmctx *ctx, int vcpu);
int vm_setup_asyncio(struct vmctx *ctx, uint64_t base);
int vm_setup_sbuf(struct vmctx *ctx, uint32_t sbuf_type, uint64_t base);
void vm_clear_ioreq(struct vmctx *ctx);
const char *vm_state_to_str(enum vm_suspend_how idx);
void vm_set_suspend_mode(enum vm_suspend_how how);

View File

@ -5,7 +5,7 @@
<p class="admonition-title">Important</p>
<p>This is the latest documentation for the unstable development branch of
Project ACRN (master).<br/>Use the drop-down menu on the left to select
documentation for a stable release such as <a href="/3.2/">v3.2</a> or
documentation for a stable release such as <a href="/3.1/">v3.1</a> or
<a href="/3.0/">v3.0</a>.</p>
</div>
{% endif %}

View File

@ -241,8 +241,6 @@ 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"

View File

@ -199,7 +199,6 @@ html_context = {
'docs_title': docs_title,
'is_release': is_release,
'versions': ( ("latest", "/latest/"),
("3.2", "/3.2/"),
("3.1", "/3.1/"),
("3.0", "/3.0/"),
("2.7", "/2.7/"),

View File

@ -29,7 +29,6 @@ User VM Tutorials
tutorials/using_xenomai_as_user_vm
tutorials/using_vxworks_as_user_vm
tutorials/using_zephyr_as_user_vm
tutorials/using_celadon_as_user_vm
Configuration Tutorials
***********************

View File

@ -70,24 +70,10 @@ Specifically:
the hypervisor shell. Inputs to the physical UART will be
redirected to the vUART starting from the next timer event.
- The vUART enters escaping mode after a BREAK character is received from
the physical UART. When in escaping mode, next received character will
be a command. After processing this command, the vUART exits the escaping
mode. So far, following escaping commands are supported:
- BREAK charater. If user sends break charater again in escaping mode,
one break charater will be sent to vUART.
- Character "e". This will deactive vUART. Inputs to the physical UART will
be handled by the hypervisor shell starting from the next timer event.
Other characters are not supported. The physical UART will prompt out an
"Unknown escaping key" message and the active vUART exits escaping mode.
Note that the BREAK character is a control character and different serial
terminals have different ways to send it, for example, `<Ctrl-A> + F`
in minicom, `<Ctrl-a> + <Ctrl-\>` in picocom, right click -> special
command -> break in putty serial terminal.
- The vUART is deactivated after a :kbd:`Ctrl` + :kbd:`Space` hotkey is received
from the physical UART. Inputs to the physical UART will be
handled by the hypervisor shell starting from the next timer
event.
The workflows are described as follows:

View File

@ -106,12 +106,12 @@ MMIO Registers Definition
* - IVSHMEM\_IRQ\_MASK\_REG
- 0x0
- R/W
- Interrupt Mask register is used for legacy interrupt.
- Interrupt Status register is used for legacy interrupt.
ivshmem doesn't support interrupts, so this register is reserved.
* - IVSHMEM\_IRQ\_STA\_REG
- 0x4
- R/W
- Interrupt Status register is used for legacy interrupt.
- Interrupt Mask register is used for legacy interrupt.
ivshmem doesn't support interrupts, so this register is reserved.
* - IVSHMEM\_IV\_POS\_REG
- 0x8

View File

@ -117,11 +117,10 @@ To set up the ACRN build environment on the development computer:
python3 python3-pip libblkid-dev e2fslibs-dev \
pkg-config libnuma-dev libcjson-dev liblz4-tool flex bison \
xsltproc clang-format bc libpixman-1-dev libsdl2-dev libegl-dev \
libgles-dev libdrm-dev gnu-efi libelf-dev liburing-dev \
libgles-dev libdrm-dev gnu-efi libelf-dev \
build-essential git-buildpackage devscripts dpkg-dev equivs lintian \
apt-utils pristine-tar dh-python acpica-tools python3-tqdm \
python3-elementpath python3-lxml python3-xmlschema python3-defusedxml
apt-utils pristine-tar dh-python python3-lxml python3-defusedxml \
python3-tqdm python3-xmlschema python3-elementpath acpica-tools
#. Get the ACRN hypervisor and ACRN kernel source code, and check out the
current release branch.
@ -131,12 +130,12 @@ To set up the ACRN build environment on the development computer:
cd ~/acrn-work
git clone https://github.com/projectacrn/acrn-hypervisor.git
cd acrn-hypervisor
git checkout release_3.3
git checkout release_3.2
cd ..
git clone https://github.com/projectacrn/acrn-kernel.git
cd acrn-kernel
git checkout release_3.3
git checkout release_3.2
.. _gsg-board-setup:
@ -172,11 +171,11 @@ 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 or wifi.
#. Connect the target system to the LAN with the Ethernet cable.
Example of a target system with cables connected:
.. image:: ./images/gsg_asus_minipc64.png
.. image:: ./images/gsg_vecow.png
:align: center
Install OS on the Target
@ -248,10 +247,9 @@ 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 or just reboot the system to try again.
enter the BIOS configuration editor, typically by pressing :kbd:`F2` during
the boot and before the GRUB menu (or Ubuntu login screen) appears. If you
are not quick enough, you can reboot the system to try again.
#. Configure these BIOS settings:
@ -341,7 +339,7 @@ Generate a Scenario Configuration File and Launch Script
********************************************************
In this step, you will download, install, and use the `ACRN Configurator
<https://github.com/projectacrn/acrn-hypervisor/releases/download/v3.3/acrn-configurator-3.3.deb>`__
<https://github.com/projectacrn/acrn-hypervisor/releases/download/v3.2/acrn-configurator-3.2.deb>`__
to generate a scenario configuration file and launch script.
A **scenario configuration file** is an XML file that holds the parameters of
@ -357,7 +355,7 @@ post-launched User VM. Each User VM has its own launch script.
.. code-block:: bash
cd ~/acrn-work
wget https://github.com/projectacrn/acrn-hypervisor/releases/download/v3.3/acrn-configurator-3.3.deb -P /tmp
wget https://github.com/projectacrn/acrn-hypervisor/releases/download/v3.2/acrn-configurator-3.2.deb -P /tmp
If you already have a previous version of the acrn-configurator installed,
you should first remove it:
@ -370,7 +368,7 @@ post-launched User VM. Each User VM has its own launch script.
.. code-block:: bash
sudo apt install -y /tmp/acrn-configurator-3.3.deb
sudo apt install -y /tmp/acrn-configurator-3.2.deb
#. Launch the ACRN Configurator:
@ -435,7 +433,7 @@ post-launched User VM. Each User VM has its own launch script.
:class: drop-shadow
The Configurator does consistency and validation checks when you load or save
a scenario. Notice the Hypervisor and VM1 tabs both have an error icon,
a scenario. Notice the Hypervisor and VM1 tabs both have an error icon,
meaning there are issues with configuration options in two areas. Since the
Hypervisor tab is currently highlighted, we're seeing an issue we can resolve
on the Hypervisor settings. Once we resolve all the errors and save the
@ -477,10 +475,11 @@ post-launched User VM. Each User VM has its own launch script.
resolve the missing physical CPU affinity assignment error.)
#. For **Virtio console device**, click **+** to add a device and keep the
default options.
default options. This parameter specifies the console that you will use to
log in to the User VM later in this guide.
#. For **Virtio block device**, click **+** and enter
``/home/acrn/acrn-work/ubuntu-22.04.4-desktop-amd64.iso``. This parameter
``/home/acrn/acrn-work/ubuntu-22.04.2-desktop-amd64.iso``. This parameter
specifies the VM's OS image and its location on the target system. Later
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
@ -490,7 +489,7 @@ post-launched User VM. Each User VM has its own launch script.
:align: center
:class: drop-shadow
.. image:: images/configurator_postvm02.png
.. image:: images/configurator-postvm02.png
:align: center
:class: drop-shadow
@ -573,9 +572,10 @@ Build ACRN
cd ..
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-libc-dev_6.1.80-acrn-service-vm-1_amd64.deb
linux-headers-5.15.71-acrn-service-vm_5.15.71-acrn-service-vm-1_amd64.deb
linux-image-5.15.71-acrn-service-vm_5.15.71-acrn-service-vm-1_amd64.deb
linux-image-5.15.71-acrn-service-vm-dbg_5.15.71-acrn-service-vm-1_amd64.deb
linux-libc-dev_5.15.71-acrn-service-vm-1_amd64.deb
#. Use the ``scp`` command to copy files from your development computer to the
target system. Replace ``10.0.0.200`` with the target system's IP address
@ -617,13 +617,13 @@ Install ACRN
.. code-block:: bash
sudo reboot
reboot
The target system will reboot into the ACRN hypervisor and
start the Ubuntu Service VM.
#. Confirm that you see the GRUB menu with "Ubuntu with ACRN hypervisor, with Linux 6.1.80-acrn-service-vm (ACRN 3.3)"
entry. Select it and proceed to booting ACRN. (It may be auto-selected, in which case it
#. Confirm that you see the GRUB menu with "Ubuntu-ACRN Board Inspector, with 5.15.0-56-generic" entry.
Select it and proceed to booting ACRN. (It may be auto-selected, in which case it
will boot with this option automatically in 5 seconds.)
Example grub menu shown as below:
@ -634,12 +634,10 @@ Install ACRN
────────────────────────────────────────────────────────────────────────────────
Ubuntu
Advanced options for Ubuntu
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.5.0-18-generic (ACRN 3.3)
*Ubuntu with ACRN hypervisor, with Linux 6.1.80-acrn-service-vm (ACRN 3.3)
Ubuntu-ACRN Board Inspector, with Linux 5.15.71-acrn-service-vm
*Ubuntu-ACRN Board Inspector, with Linux 5.15.0-56-generic
Ubuntu with ACRN hypervisor, with Linux 5.15.71-acrn-service-vm (ACRN 3.2)
Ubuntu with ACRN hypervisor, with Linux 5.15.0-56-generic (ACRN 3.2)
UEFI Firmware Settings
.. _gsg-run-acrn:
@ -678,7 +676,7 @@ The ACRN hypervisor boots the Ubuntu Service VM automatically.
.. code-block:: bash
sudo cp /usr/share/doc/acrnd/examples/* /etc/systemd/network
cp /usr/share/doc/acrnd/examples/* /etc/systemd/network
sudo systemctl enable --now systemd-networkd
.. _gsg-user-vm:
@ -690,7 +688,7 @@ Launch the User 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
``ubuntu-22.04.2-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.
@ -702,7 +700,7 @@ Launch the User VM
.. code-block:: bash
cp ~/Downloads/ubuntu-22.04.4-desktop-amd64.iso ~/acrn-work
cp ~/Downloads/ubuntu-22.04.2-desktop-amd64.iso ~/acrn-work
#. Launch the User VM:
@ -712,12 +710,23 @@ Launch the User VM
sudo ~/acrn-work/launch_user_vm_id1.sh
#. It may take about a minute for the User VM to boot and start running the
Ubuntu image. You will see a lot of output, then the console of the User VM
Ubuntu image. You will see a lot of output, then the console of the User VM
will appear as follows:
.. code-block:: console
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-18-generic x86_64)
Ubuntu 22.04.2 LTS ubuntu hvc0
ubuntu login:
#. Log in to the User VM. For the Ubuntu 22.04 ISO, the user is ``ubuntu``, and
there's no password.
#. Confirm that you see output similar to this example:
.. code-block:: console
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.19.0-32-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
@ -747,20 +756,20 @@ Launch the User VM
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:
command to see that the User VM is running the downloaded Ubuntu ISO image:
.. code-block:: console
acrn@ubuntu:~$ uname -r
6.5.0-18-generic
ubuntu@ubuntu:~$ uname -r
5.19.0-32-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:
.. code-block:: console
acrn@asus-MINIPC-PN64:~$ uname -r
6.1.80-acrn-service-vm
acrn@vecow:~$ uname -r
5.15.71-acrn-service-vm
The User VM has launched successfully. You have completed this ACRN setup.

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 KiB

View File

@ -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.3
git checkout release_3.2
#. Build the ACRN sample application source code::
@ -522,7 +522,6 @@ 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

View File

@ -78,7 +78,6 @@ license.
contribute
release_notes/index
asa
projects/index
glossary
genindex

View File

@ -1,13 +0,0 @@
.. _projects:
Projects
########
Here is documentation for projects that build on the initial and continuing work
from the ACRN development team at Intel.
.. toctree::
:maxdepth: 1
multi-arch-support

View File

@ -1,38 +0,0 @@
.. _multi-arch-support:
Hypervisor Multi-Architecture and RISC-V Support
################################################
.. note:: This is a preliminary draft of a planned and as yet unreleased effort
to port the ACRN Hypervisor to non-Intel architectures.
From its first release in July 2018, the ACRN Hypervisor was designed for and
targeted to Intel platforms and relied on Intel Virtualization Technology (Intel
VT). From that base, we're expanding support to enable the ACRN hypervisor to
RISC-V64 architecture with a Hypervisor Extension.
RISC-V Support
**************
Adding multi-architecture support begins by refining the current architecture
abstraction layer and defining architecture-neutral APIs covering the management
of cores, caches, memory, interrupts, timers, and hardware virtualization
facilities. Then an implementation of those APIs for RISC-V will be introduced.
Based on its wide availability and flexibility, QEMU is the first RISC-V
(virtual) platform this project targets. Real platforms may be selected later
based on business and community interests.
Current State
=============
This project is currently under development and is not yet ready for production.
Once this support is implemented and has sufficient quality, this port will
become a part of the upstream ACRN project and we'll continue development there
and encourage contributions by the ACRN community.
License
=======
This project will be released under the BSD-3-Clause license, the same as the
rest of project ACRN.

View File

@ -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 &nbsp; 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:: | .. 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 |
+------------------------+---------------------------------+-------------------+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | | .. 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 |
+------------------------+---------------------------------+-------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
* **Release**: New ACRN features are complete and tested for the listed product.
This product is recommended for this ACRN version. Support for older products

View File

@ -79,7 +79,7 @@ to upgrade from prior ACRN versions:
#. Manually edit your previous older scenario XML and launch XML files to make them
compatible with v3.2. This is not our recommended approach.
Here are some additional details about upgrading to the v3.2 release.
Here are some additional details about upgrading to the v3.22 release.
Generate New Board XML
======================

View File

@ -1,199 +0,0 @@
.. _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

View File

@ -444,18 +444,16 @@ how to build the Debian package from source code.
.. code-block:: bash
sudo apt install -y build-essential \
sudo apt install -y libwebkit2gtk-4.0-dev \
build-essential \
curl \
wget \
libssl-dev \
libgtk-3-dev \
libappindicator3-dev \
librsvg2-dev \
python3-venv
cd /tmp/
wget http://security.ubuntu.com/ubuntu/pool/main/w/webkit2gtk/libwebkit2gtk-4.0-37_2.44.2-0ubuntu0.22.04.1_amd64.deb http://mirrors.kernel.org/ubuntu/pool/main/i/icu/libicu70_70.1-2_amd64.deb http://security.ubuntu.com/ubuntu/pool/main/w/webkit2gtk/libjavascriptcoregtk-4.0-18_2.44.2-0ubuntu0.22.04.1_amd64.deb
sudo apt install ./libwebkit2gtk-4.0-37_2.44.2-0ubuntu0.22.04.1_amd64.deb ./libicu70_70.1-2_amd64.deb ./libjavascriptcoregtk-4.0-18_2.44.2-0ubuntu0.22.04.1_amd64.deb
#. Install Node.js (npm included) as follows:
a. We recommend using nvm to manage your Node.js runtime. It allows you to

View File

@ -67,9 +67,6 @@ 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
@ -91,4 +88,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`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -168,7 +168,6 @@ when using one of these OSs:
* :ref:`using_ubuntu_as_user_vm`
* :ref:`using_windows_as_user_vm`
* :ref:`using_celadon_as_user_vm`
Real-time VM OS Considerations
******************************

View File

@ -1,197 +0,0 @@
.. _using_celadon_as_user_vm:
Run Celadon as the User VM OS
#############################
Introduction to Celadon
***********************
`Celadon`_ ---- An open source Android software reference stack for Intel architecture.
This tutorial describes how to run Celadon Android as the User VM OS on ACRN hypervisor.
If you want to learn more about Celadon, refer to the
official `Celadon documentation <https://projectceladon.github.io>`__.
.. _Celadon:
http://github.com/projectceladon
Build Celadon Image from Source
*******************************
Before building the Celadon image, please make sure your development workstation
meets the following requirements: A 64-bit workstation running Ubuntu with **64GB memory** and
**350GB of free disk space**. If your workstation does not meet these requirements,
you may encouter unexpected errors.
Follow these instructions to build the Celadon images:
#. Install the repo tools:
.. code-block:: none
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
#. Install the required building packages:
.. code-block:: none
sudo apt update
sudo apt install openjdk-8-jdk git ccache automake \
lzop bison gperf build-essential zip curl \
zlib1g-dev g++-multilib python3-networkx \
libxml2-utils bzip2 libbz2-dev libbz2-1.0 \
libghc-bzlib-dev squashfs-tools pngcrush \
schedtool dpkg-dev liblz4-tool make optipng maven \
libssl-dev bc bsdmainutils gettext python3-mako \
libelf-dev sbsigntool dosfstools mtools efitools \
python3-pystache git-lfs python3 flex clang libncurses5 \
fakeroot ncurses-dev xz-utils python3-pip ninja-build \
cryptsetup-bin cutils cmake pkg-config xorriso mtools
sudo pip3 install mako==1.1.0 meson==0.60.0 dataclasses
sudo su
cd /usr/local/
wget https://github.com/KhronosGroup/glslang/releases/download/SDK-candidate-26-Jul-2020/glslang-master-linux-Release.zip && \
unzip glslang-master-linux-Release.zip bin/glslangValidator
#. Download the source code
.. code-block:: none
mkdir ~/civ
cd ~/civ
We choose Celadon Android 14 Base Releases `CIV_00.23.04.51_A14 <https://projectceladon.github.io/celadon-documentation/release-notes/base-releases-A14.html#civ-00-23-04-51-a14>`__.
Repo tool will download the entire source code into your local environments and it will cost several hours depending on your network.
.. code-block:: none
repo init -u https://github.com/projectceladon/manifest -b master -m stable-build/CIV_00.23.04.51_A14.xml
repo sync -c -q -j5
#. Disable Trusty:
Trusty is a mandatory component since Android Oreo Desert onwards. However, it's easier to boot Celadon as VM without Trusty feature.
So we recommend to **disable trusty**. To disable, set the 'trusty' and 'tpm' options to false in the mixins config file
``civ/device/intel/projectceladon/caas/mixins.spec`` as follows:
.. code-block:: none
[groups]
device-specific: celadon
treble: true
....
tpm: false
....
trusty: false
After modifing ``mixins.spec``, you must run the ``civ/device/intel/mixins/mixin-update`` script to apply the changes.
Enter the following commands to initialize your build variables and specifiy your celadon lunch target using ``lunch`` target:
.. code-block:: none
source build/envsetup.sh
lunch caas
Meanwhile, the following trusty related configs in **Android kernel** at
``device/intel/mixins/groups/kernel/gmin64/config-lts/linux-intel-lts2022/x86_64_defconfig``
should be disabled as:
.. code-block:: none
# CONFIG_TCG_TPM is not set
# CONFIG_HW_RANDOM_TPM is not set
# CONFIG_TRUSTY is not set
# CONFIG_TRUSTY_LOG is not set
# CONFIG_TRUSTY_VIRTIO is not set
# CONFIG_TRUSTY_VIRTIO_IPC is not set
# CONFIG_TRUSTY_X86_64 is not set
# CONFIG_TRUSTY_BACKUP_TIMER is not set
Run `mixin` command to apply this changes:
.. code-block:: none
cd ~/civ
mixin
#. Build Celadon flash image:
Then you are ready to build Celadon images. Build progress may cost several hours or even more depends on your building system:
.. code-block:: none
make flashfiles -j $(nproc)
#. Flash Celadon image into disk:
Caution: Please **remain only one hard disk** (the disk will be entirely removed and flashed) in your destination platform, otherwise
Celadon may flash into the wrong disk and cause data loss. There are two ways to do: i. Physically
remove the hard disk. ii. Disable the sata(or nvme) slot in the BIOS settings.
We test this VM in an ASUS MiniPC with two disk slots: one is a m.2 nvme slot and one is a sata slot. We run service OS
(Ubuntu) on a sata disk and run guest OS(Celadon Android) on a nvme disk.
Prepare an empty USB disk and plug it into your **development platform**, run ``lsblk`` command to find it. Assume it's ``/dev/sdc`` here.
.. code-block:: none
cd ~/civ/out/target/product/caas
unzip caas-flashfile-eng.dot.iso.zip
sudo dd if=~/civ/caas-flashfile-eng.dot.iso of=/dev/sdc status=progress
sudo eject /dev/sdc
Unplug the USB disk and plug it into your **destination platform**. Power on your destination platform and boot into this USB disk via BIOS settings. The flash progress
will require you press :kbd:`UP` or :kbd:`PgUp` to continue. When flash done, you can boot into Celadon Android.
#. ACRN Service VM Setup
Follow the steps in this :ref:`gsg` to set up ACRN based Ubuntu and launch the Service VM.
Modifiy the ACRN device model parameters in ``launch_user_vm_id1.sh`` as follows:
.. code-block:: none
dm_params=(
`add_cpus 8 9 16 17`
-m 8192M
--ovmf /usr/share/acrn/bios/OVMF.fd
`add_virtual_device 1:0 lpc`
`add_virtual_device 0:0 hostbridge`
`add_virtual_device 3 virtio-console @stdio:stdio_port`
`add_passthrough_device 2 0000:00:02.0`
`add_passthrough_device 4 0000:00:14.0`
`add_interrupt_storm_monitor 10000 10 1 100`
`add_passthrough_device 5 0000:01:00.0`
`add_logger_settings console=4 kmsg=3 disk=5`
VM1
)
#. Boot Celadon VM
Remotely connect to the target system via SSH and Boot Celadon VM via the launch script ``launch_user_vm_id1``:
.. code-block:: none
sudo chmod +x ./launch_user_vm_id1.sh
sudo ./launch_user_vm_id1.sh
Then the screen will temperatory go off. Wait for about one minute and the Android UI will appear as:
.. figure:: images/celadon_uservm_01.png
:align: center
:name: Android-screenlock
:class: drop-shadow
.. figure:: images/celadon_uservm_02.png
:align: center
:name: Android-desktop
:class: drop-shadow

View File

@ -167,9 +167,7 @@ vm_console
The ``vm_console <vm_id>`` command switches the ACRN's console to become the
VM's console.
Send a BREAK character to enter escaping mode and a character e to return to
the ACRN shell console. For details on how the hypervisor console works,
refer to :ref:`hv-console`.
Press :kbd:`Ctrl` + :kbd:`Alt` + :kbd:`Space` to return to the ACRN shell console.
vioapic
=======

View File

@ -219,7 +219,6 @@ HW_C_SRCS += arch/x86/exception.c
HW_C_SRCS += arch/x86/irq.c
HW_C_SRCS += arch/x86/tsc.c
HW_C_SRCS += arch/x86/tsc_deadline_timer.c
HW_C_SRCS += arch/x86/hw_thermal.c
HW_C_SRCS += arch/x86/vmx.c
HW_C_SRCS += arch/x86/cpu_state_tbl.c
HW_C_SRCS += arch/x86/pm.c
@ -231,14 +230,12 @@ HW_C_SRCS += arch/x86/sgx.c
HW_C_SRCS += common/ticks.c
HW_C_SRCS += common/delay.c
HW_C_SRCS += common/timer.c
HW_C_SRCS += common/thermal.c
HW_C_SRCS += common/irq.c
HW_C_SRCS += common/softirq.c
HW_C_SRCS += common/schedule.c
HW_C_SRCS += common/event.c
HW_C_SRCS += common/efi_mmap.c
HW_C_SRCS += common/sbuf.c
HW_C_SRCS += common/vm_event.c
ifeq ($(CONFIG_SCHED_NOOP),y)
HW_C_SRCS += common/sched_noop.c
endif
@ -318,7 +315,6 @@ VP_DM_C_SRCS += dm/vpci/vpci.c
VP_DM_C_SRCS += dm/vpci/vhostbridge.c
VP_DM_C_SRCS += dm/vpci/vroot_port.c
VP_DM_C_SRCS += dm/vpci/vpci_bridge.c
VP_DM_C_SRCS += dm/vpci/vpci_mf_dev.c
VP_DM_C_SRCS += dm/vpci/ivshmem.c
VP_DM_C_SRCS += dm/vpci/pci_pt.c
VP_DM_C_SRCS += dm/vpci/vmsi.c

View File

@ -12,7 +12,7 @@
/*
* @pre pdev != NULL;
*/
static bool allocate_to_prelaunched_vm(struct pci_pdev *pdev)
static bool is_allocated_to_prelaunched_vm(struct pci_pdev *pdev)
{
bool found = false;
uint16_t vmid;
@ -52,46 +52,38 @@ static bool allocate_to_prelaunched_vm(struct pci_pdev *pdev)
*/
struct acrn_vm_pci_dev_config *init_one_dev_config(struct pci_pdev *pdev)
{
uint16_t vmid;
struct acrn_vm_config *vm_config;
struct acrn_vm_pci_dev_config *dev_config = NULL;
bool is_allocated_to_prelaunched_vm = allocate_to_prelaunched_vm(pdev);
bool is_allocated_to_hv = is_hv_owned_pdev(pdev->bdf);
if (service_vm_config != NULL) {
dev_config = &service_vm_config->pci_devs[service_vm_config->pci_dev_num];
if (is_allocated_to_hv) {
/* Service VM need to emulate the type1 pdevs owned by HV */
dev_config->emu_type = PCI_DEV_TYPE_SERVICE_VM_EMUL;
if (is_bridge(pdev)) {
dev_config->vdev_ops = &vpci_bridge_ops;
} else if (is_host_bridge(pdev)) {
dev_config->vdev_ops = &vhostbridge_ops;
} else {
/* May have type0 device, E.g. debug pci uart */
dev_config = NULL;
if (!is_allocated_to_prelaunched_vm(pdev)) {
for (vmid = 0U; vmid < CONFIG_MAX_VM_NUM; vmid++) {
vm_config = get_vm_config(vmid);
if (vm_config->load_order != SERVICE_VM) {
continue;
}
} else if (is_allocated_to_prelaunched_vm) {
dev_config = NULL;
} else {
dev_config->emu_type = PCI_DEV_TYPE_PTDEV;
}
if ((is_allocated_to_hv || is_allocated_to_prelaunched_vm)
&& (dev_config == NULL)
&& is_pci_cfg_multifunction(pdev->hdr_type)
&& (pdev->bdf.bits.f == 0U))
{
dev_config = &service_vm_config->pci_devs[service_vm_config->pci_dev_num];
dev_config->emu_type = PCI_DEV_TYPE_DUMMY_MF_EMUL;
dev_config->vdev_ops = &vpci_mf_dev_ops;
}
}
dev_config = &vm_config->pci_devs[vm_config->pci_dev_num];
if (is_hv_owned_pdev(pdev->bdf)) {
/* Service VM need to emulate the type1 pdevs owned by HV */
dev_config->emu_type = PCI_DEV_TYPE_SERVICE_VM_EMUL;
if (is_bridge(pdev)) {
dev_config->vdev_ops = &vpci_bridge_ops;
} else if (is_host_bridge(pdev)) {
dev_config->vdev_ops = &vhostbridge_ops;
} else {
/* May have type0 device, E.g. debug pci uart */
break;
}
} else {
dev_config->emu_type = PCI_DEV_TYPE_PTDEV;
}
if (dev_config != NULL) {
dev_config->vbdf.value = pdev->bdf.value;
dev_config->pbdf.value = pdev->bdf.value;
dev_config->pdev = pdev;
service_vm_config->pci_dev_num++;
dev_config->vbdf.value = pdev->bdf.value;
dev_config->pbdf.value = pdev->bdf.value;
dev_config->pdev = pdev;
vm_config->pci_dev_num++;
}
}
return dev_config;
}

View File

@ -37,7 +37,6 @@
#include <asm/tsc.h>
#include <ticks.h>
#include <delay.h>
#include <thermal.h>
#define CPU_UP_TIMEOUT 100U /* millisecond */
#define CPU_DOWN_TIMEOUT 100U /* millisecond */
@ -269,7 +268,6 @@ void init_pcpu_post(uint16_t pcpu_id)
init_interrupt(BSP_CPU_ID);
timer_init();
thermal_init();
setup_notification();
setup_pi_notification();
@ -311,7 +309,6 @@ void init_pcpu_post(uint16_t pcpu_id)
init_interrupt(pcpu_id);
timer_init();
thermal_init();
ptdev_init();
}
@ -465,25 +462,7 @@ void stop_pcpus(void)
void cpu_do_idle(void)
{
#ifdef CONFIG_KEEP_IRQ_DISABLED
asm_pause();
#else
uint16_t pcpu_id = get_pcpu_id();
if (per_cpu(mode_to_idle, pcpu_id) == IDLE_MODE_HLT) {
asm_safe_hlt();
} else {
struct acrn_vcpu *vcpu = get_ever_run_vcpu(pcpu_id);
if ((vcpu != NULL) && !is_lapic_pt_enabled(vcpu)) {
CPU_IRQ_ENABLE_ON_CONFIG();
}
asm_pause();
if ((vcpu != NULL) && !is_lapic_pt_enabled(vcpu)) {
CPU_IRQ_DISABLE_ON_CONFIG();
}
}
#endif
}
/**

View File

@ -119,6 +119,43 @@ static void insert_e820_entry(uint32_t index, uint64_t addr, uint64_t length, ui
hv_e820[index].type = type;
}
static uint64_t e820_alloc_region(uint64_t addr, uint64_t size)
{
uint32_t i;
uint64_t entry_start;
uint64_t entry_end;
uint64_t start_pa = round_page_down(addr);
uint64_t end_pa = round_page_up(addr + size);
struct e820_entry *entry;
for (i = 0U; i < hv_e820_entries_nr; i++) {
entry = &hv_e820[i];
entry_start = entry->baseaddr;
entry_end = entry->baseaddr + entry->length;
/* No need handle in these cases*/
if ((entry->type != E820_TYPE_RAM) || (entry_end <= start_pa) || (entry_start >= end_pa)) {
continue;
}
if ((entry_start <= start_pa) && (entry_end >= end_pa)) {
entry->length = start_pa - entry_start;
/*
* .......|start_pa... ....................End_pa|.....
* |entry_start..............................entry_end|
*/
if (end_pa < entry_end) {
insert_e820_entry(i + 1, end_pa, entry_end - end_pa, E820_TYPE_RAM);
break;
}
} else {
pr_err("This region not in one entry!");
}
}
return addr;
}
static void init_e820_from_efi_mmap(void)
{
uint32_t i, e820_idx = 0U;
@ -234,57 +271,14 @@ static void calculate_e820_ram_size(void)
static void alloc_mods_memory(void)
{
uint32_t mod_index, e820_index, target_index;
uint64_t mod_start, mod_end;
uint64_t entry_start, entry_end;
uint32_t i;
int64_t mod_start = 0UL;
struct acrn_boot_info *abi = get_acrn_boot_info();
/* 1st pass: remove the exact region */
for (mod_index = 0; mod_index < abi->mods_count; mod_index++) {
mod_start = hva2hpa(abi->mods[mod_index].start);
mod_end = hva2hpa(abi->mods[mod_index].start) + abi->mods[mod_index].size;
for (e820_index = 0; e820_index < hv_e820_entries_nr; e820_index++) {
entry_start = hv_e820[e820_index].baseaddr;
entry_end = hv_e820[e820_index].baseaddr + hv_e820[e820_index].length;
/* No need handle in these cases*/
if ((hv_e820[e820_index].type != E820_TYPE_RAM) || (entry_end <= mod_start) || (entry_start >= mod_end)) {
continue;
}
if ((entry_start <= mod_start) && (entry_end >= mod_end)) {
hv_e820[e820_index].length = mod_start - entry_start;
if (mod_end < entry_end) {
/*
* .......|start_pa... ....................end_pa|.....
* |entry_start..............................entry_end|
*/
insert_e820_entry(e820_index + 1, mod_end, entry_end - mod_end, E820_TYPE_RAM);
}
} else {
panic("%s: region 0x%016x-0x%016x crosses multiple e820 entries, check your bootloader!",
__func__, entry_start, entry_end);
}
}
for (i = 0; i < abi->mods_count; i++) {
mod_start = hva2hpa(abi->mods[i].start);
e820_alloc_region(mod_start, abi->mods[i].size);
}
/* 2nd pass: shrink the entries to page boundary */
target_index = 0;
for (e820_index = 0; e820_index < hv_e820_entries_nr; e820_index++) {
entry_start = round_page_up(hv_e820[e820_index].baseaddr);
entry_end = round_page_down(hv_e820[e820_index].baseaddr + hv_e820[e820_index].length);
if (entry_start < entry_end) {
hv_e820[target_index].baseaddr = entry_start;
hv_e820[target_index].length = entry_end - entry_start;
hv_e820[target_index].type = hv_e820[e820_index].type;
target_index++;
}
}
memset(&hv_e820[target_index], 0, (hv_e820_entries_nr - target_index) * sizeof(struct e820_entry));
hv_e820_entries_nr = target_index;
}

View File

@ -400,9 +400,15 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
pr_err("INTX re-add vpin %d", virt_gsi);
}
} else if (entry->vm != vm) {
pr_err("INTX gsi%d already in vm%d with vgsi%d, not able to add into vm%d with vgsi%d",
phys_gsi, entry->vm->vm_id, entry->virt_sid.intx_id.gsi, vm->vm_id, virt_gsi);
entry = NULL;
if (is_service_vm(entry->vm)) {
entry->vm = vm;
entry->virt_sid.value = virt_sid.value;
entry->polarity = 0U;
} else {
pr_err("INTX gsi%d already in vm%d with vgsi%d, not able to add into vm%d with vgsi%d",
phys_gsi, entry->vm->vm_id, entry->virt_sid.intx_id.gsi, vm->vm_id, virt_gsi);
entry = NULL;
}
} else {
/* The mapping has already been added to the VM. No action
* required.
@ -422,24 +428,15 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
return entry;
}
/* deactivate & remove mapping entry of vpin for vm */
static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t gsi, enum intx_ctlr gsi_ctlr, bool is_phy_gsi)
/* deactive & remove mapping entry of vpin for vm */
static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr)
{
uint32_t phys_irq;
struct ptirq_remapping_info *entry;
struct intr_source intr_src;
DEFINE_INTX_SID(virt_sid, virt_gsi, vgsi_ctlr);
if (is_phy_gsi) {
DEFINE_INTX_SID(sid, gsi, INTX_CTLR_IOAPIC);
entry = find_ptirq_entry(PTDEV_INTR_INTX, &sid, NULL);
if ((entry != NULL) && (entry->vm != vm)) {
entry = NULL;
}
} else {
DEFINE_INTX_SID(sid, gsi, gsi_ctlr);
entry = find_ptirq_entry(PTDEV_INTR_INTX, &sid, vm);
}
entry = find_ptirq_entry(PTDEV_INTR_INTX, &virt_sid, vm);
if (entry != NULL) {
if (is_entry_active(entry)) {
phys_irq = entry->allocated_pirq;
@ -452,11 +449,11 @@ static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t gsi, enum i
dmar_free_irte(&intr_src, entry->irte_idx);
dev_dbg(DBG_LEVEL_IRQ,
"deactivate %s intx entry:pgsi=%d, pirq=%d ",
(entry->virt_sid.intx_id.ctlr == INTX_CTLR_PIC) ? "vPIC" : "vIOAPIC",
"deactive %s intx entry:pgsi=%d, pirq=%d ",
(vgsi_ctlr == INTX_CTLR_PIC) ? "vPIC" : "vIOAPIC",
entry->phys_sid.intx_id.gsi, phys_irq);
dev_dbg(DBG_LEVEL_IRQ, "from vm%d vgsi=%d\n",
entry->vm->vm_id, entry->virt_sid.intx_id.gsi);
entry->vm->vm_id, virt_gsi);
}
ptirq_release_entry(entry);
@ -756,7 +753,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ct
uint32_t phys_gsi = virt_gsi;
remove_intx_remapping(vm, alt_virt_sid.intx_id.gsi,
alt_virt_sid.intx_id.ctlr, false);
alt_virt_sid.intx_id.ctlr);
entry = add_intx_remapping(vm, virt_gsi, phys_gsi, vgsi_ctlr);
if (entry == NULL) {
pr_err("%s, add intx remapping failed", __func__);
@ -827,12 +824,12 @@ int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_gsi, uint32_t
/*
* @pre vm != NULL
*/
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t gsi, bool pic_pin, bool is_phy_gsi)
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, bool pic_pin)
{
enum intx_ctlr vgsi_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
spinlock_obtain(&ptdev_lock);
remove_intx_remapping(vm, gsi, vgsi_ctlr, is_phy_gsi);
remove_intx_remapping(vm, virt_gsi, vgsi_ctlr);
spinlock_release(&ptdev_lock);
}
@ -860,6 +857,6 @@ void ptirq_remove_configured_intx_remappings(const struct acrn_vm *vm)
uint16_t i;
for (i = 0; i < vm_config->pt_intx_num; i++) {
ptirq_remove_intx_remapping(vm, vm_config->pt_intx[i].virt_gsi, false, false);
ptirq_remove_intx_remapping(vm, vm_config->pt_intx[i].virt_gsi, false);
}
}

View File

@ -86,7 +86,7 @@ static void reserve_ept_bitmap(void)
bitmap_size = (get_ept_page_num() * CONFIG_MAX_VM_NUM) / 8;
bitmap_offset = get_ept_page_num() / 8;
bitmap_base = e820_alloc_memory(bitmap_size, MEM_SIZE_MAX);
bitmap_base = e820_alloc_memory(bitmap_size, ~0UL);
set_paging_supervisor(bitmap_base, bitmap_size);
for(i = 0; i < CONFIG_MAX_VM_NUM; i++){
@ -103,7 +103,7 @@ void reserve_buffer_for_ept_pages(void)
uint16_t vm_id;
uint32_t offset = 0U;
page_base = e820_alloc_memory(get_total_ept_4k_pages_size(), MEM_SIZE_MAX);
page_base = e820_alloc_memory(get_total_ept_4k_pages_size(), ~0UL);
set_paging_supervisor(page_base, get_total_ept_4k_pages_size());
for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
ept_pages[vm_id] = (struct page *)(void *)(page_base + offset);

View File

@ -65,6 +65,7 @@ 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;
@ -107,6 +108,7 @@ static int32_t local_gva2gpa_common(struct acrn_vcpu *vcpu, const struct page_wa
* Case2: Usermode */
fault = 1;
}
is_page_rw_flags_on = false;
}
}
@ -140,8 +142,34 @@ 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 && ((vcpu_get_rflags(vcpu) & RFLAGS_AC) == 0UL)) {
fault = 1;
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 */
}
}
/* instruction fetch from user-mode address, smep on */

View File

@ -309,14 +309,3 @@ 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;
}

View File

@ -528,22 +528,9 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
per_cpu(ever_run_vcpu, pcpu_id) = vcpu;
if (is_lapic_pt_configured(vm) || is_using_init_ipi()) {
/* Lapic_pt pCPU does not enable irq in root mode. So it
* should be set to PAUSE idle mode.
* At this point the pCPU is possibly in HLT idle. And the
* kick mode is to be set to INIT kick, which will not be
* able to wake root mode HLT. So a kick(if pCPU is in HLT
* idle, the kick mode is certainly ipi kick) will change
* it to PAUSE idle right away.
*/
if (per_cpu(mode_to_idle, pcpu_id) == IDLE_MODE_HLT) {
per_cpu(mode_to_idle, pcpu_id) = IDLE_MODE_PAUSE;
kick_pcpu(pcpu_id);
}
per_cpu(mode_to_kick_pcpu, pcpu_id) = DEL_MODE_INIT;
} else {
per_cpu(mode_to_kick_pcpu, pcpu_id) = DEL_MODE_IPI;
per_cpu(mode_to_idle, pcpu_id) = IDLE_MODE_HLT;
}
pr_info("pcpu=%d, kick-mode=%d, use_init_flag=%d", pcpu_id,
per_cpu(mode_to_kick_pcpu, pcpu_id), is_using_init_ipi());
@ -572,16 +559,6 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
*/
vcpu->arch.vpid = ALLOCATED_MIN_L1_VPID + (vm->vm_id * MAX_VCPUS_PER_VM) + vcpu->vcpu_id;
/*
* There are two locally independent writing operations, namely the
* assignment of vcpu->vm and vcpu_array[]. Compilers may optimize
* and reorder writing operations while users of vcpu_array[] may
* assume the presence of vcpu->vm. A compiler barrier is added here
* to prevent compiler reordering, ensuring that assignments to
* vcpu->vm precede vcpu_array[].
*/
cpu_compiler_barrier();
/*
* ACRN uses the following approach to manage VT-d PI notification vectors:
* Allocate unique Activation Notification Vectors (ANV) for each vCPU that
@ -996,7 +973,8 @@ int32_t prepare_vcpu(struct acrn_vm *vm, uint16_t pcpu_id)
vcpu->thread_obj.host_sp = build_stack_frame(vcpu);
vcpu->thread_obj.switch_out = context_switch_out;
vcpu->thread_obj.switch_in = context_switch_in;
init_thread_data(&vcpu->thread_obj, &get_vm_config(vm->vm_id)->sched_params);
vcpu->thread_obj.priority = get_vm_config(vm->vm_id)->vm_prio;
init_thread_data(&vcpu->thread_obj);
for (i = 0; i < VCPU_EVENT_NUM; i++) {
init_event(&vcpu->events[i]);
}
@ -1058,8 +1036,8 @@ void vcpu_handle_pi_notification(uint32_t vcpu_index)
* Record this request as ACRN_REQUEST_EVENT,
* so that vlapic_inject_intr() will sync PIR to vIRR
*/
vcpu_make_request(vcpu, ACRN_REQUEST_EVENT);
signal_event(&vcpu->events[VCPU_EVENT_VIRTUAL_INTERRUPT]);
vcpu_make_request(vcpu, ACRN_REQUEST_EVENT);
}
}
}

View File

@ -18,11 +18,6 @@
#include <asm/rdt.h>
#include <asm/guest/vcat.h>
static struct percpu_cpuids {
uint32_t leaf_nr;
uint32_t leaves[MAX_VM_VCPUID_ENTRIES];
} pcpu_cpuids;
static inline const struct vcpuid_entry *local_find_vcpuid_entry(const struct acrn_vcpu *vcpu,
uint32_t leaf, uint32_t subleaf)
{
@ -120,6 +115,73 @@ static void init_vcpuid_entry(uint32_t leaf, uint32_t subleaf,
entry->flags = flags;
switch (leaf) {
case 0x06U:
cpuid_subleaf(leaf, subleaf, &entry->eax, &entry->ebx, &entry->ecx, &entry->edx);
entry->eax &= ~(CPUID_EAX_HWP | CPUID_EAX_HWP_N | CPUID_EAX_HWP_AW | CPUID_EAX_HWP_EPP | CPUID_EAX_HWP_PLR);
entry->ecx &= ~CPUID_ECX_HCFC;
break;
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) {
@ -376,165 +438,6 @@ static int32_t set_vcpuid_vcat_10h(struct acrn_vm *vm)
}
#endif
static void guest_cpuid_04h(__unused struct acrn_vm *vm, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
struct vcpuid_entry entry;
cpuid_subleaf(CPUID_CACHE, *ecx, &entry.eax, &entry.ebx, &entry.ecx, &entry.edx);
if (entry.eax != 0U) {
#ifdef CONFIG_VCAT_ENABLED
if (is_vcat_configured(vm)) {
/* set_vcpuid_vcat_04h will not change entry.eax */
result = set_vcpuid_vcat_04h(vm, &entry);
}
#endif
}
*eax = entry.eax;
*ebx = entry.ebx;
*ecx = entry.ecx;
*edx = entry.edx;
}
static int32_t set_vcpuid_cache(struct acrn_vm *vm)
{
int32_t result = 0;
struct vcpuid_entry entry;
uint32_t i;
entry.leaf = CPUID_CACHE;
entry.flags = CPUID_CHECK_SUBLEAF;
for (i = 0U; ; i++) {
entry.subleaf = i;
entry.ecx = i;
guest_cpuid_04h(vm, &entry.eax, &entry.ebx, &entry.ecx, &entry.edx);
if (entry.eax == 0U) {
break;
}
result = set_vcpuid_entry(vm, &entry);
if (result != 0) {
/* wants to break out of switch */
break;
}
}
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);
/* Always hide package level HWP controls and HWP interrupt*/
*eax &= ~(CPUID_EAX_HWP_CTL | CPUID_EAX_HWP_PLR | CPUID_EAX_HWP_N);
*eax &= ~(CPUID_EAX_HFI | CPUID_EAX_ITD);
/* Since HFI is hidden, hide the edx too */
*edx = 0U;
if (!is_vhwp_configured(vm)) {
*eax &= ~(CPUID_EAX_HWP | CPUID_EAX_HWP_AW | CPUID_EAX_HWP_EPP);
*ecx &= ~CPUID_ECX_HCFC;
}
}
static int32_t set_vcpuid_thermal_power(struct acrn_vm *vm)
{
struct vcpuid_entry entry;
entry.leaf = CPUID_THERMAL_POWER;
entry.subleaf = 0;
entry.ecx = 0;
entry.flags = CPUID_CHECK_SUBLEAF;
guest_cpuid_06h(vm, &entry.eax, &entry.ebx, &entry.ecx, &entry.edx);
return set_vcpuid_entry(vm, &entry);
}
static int32_t set_vcpuid_extended_function(struct acrn_vm *vm)
{
uint32_t i, limit;
@ -596,40 +499,7 @@ static int32_t set_vcpuid_extended_function(struct acrn_vm *vm)
static inline bool is_percpu_related(uint32_t leaf)
{
uint32_t i;
bool ret = false;
for (i = 0; i < pcpu_cpuids.leaf_nr; i++) {
if (leaf == pcpu_cpuids.leaves[i]) {
ret = true;
break;
}
}
return ret;
}
static inline void percpu_cpuid_init(void)
{
/* 0x1U, 0xBU, 0xDU, 0x19U, 0x1FU, 0x80000001U */
uint32_t percpu_leaves[] = {CPUID_FEATURES, CPUID_EXTEND_TOPOLOGY,
CPUID_XSAVE_FEATURES, CPUID_KEY_LOCKER,
CPUID_V2_EXTEND_TOPOLOGY, CPUID_EXTEND_FUNCTION_1};
pcpu_cpuids.leaf_nr = sizeof(percpu_leaves)/sizeof(uint32_t);
memcpy_s(pcpu_cpuids.leaves, sizeof(percpu_leaves),
percpu_leaves, sizeof(percpu_leaves));
/* hybrid related percpu leaves*/
if (pcpu_has_cap(X86_FEATURE_HYBRID)) {
/* 0x2U, 0x4U, 0x6U, 0x14U, 0x16U, 0x18U, 0x1A, 0x1C, 0x80000006U */
uint32_t hybrid_leaves[] = {CPUID_TLB, CPUID_CACHE,
CPUID_THERMAL_POWER, CPUID_TRACE, CPUID_FREQ,
CPUID_ADDR_TRANS, CPUID_MODEL_ID, CPUID_LAST_BRANCH_RECORD,
CPUID_EXTEND_CACHE};
memcpy_s(pcpu_cpuids.leaves + pcpu_cpuids.leaf_nr,
sizeof(hybrid_leaves), hybrid_leaves, sizeof(hybrid_leaves));
pcpu_cpuids.leaf_nr += sizeof(hybrid_leaves)/sizeof(uint32_t);
}
return ((leaf == 0x1U) || (leaf == 0xbU) || (leaf == 0xdU) || (leaf == 0x19U) || (leaf == 0x80000001U) || (leaf == 0x2U) || (leaf == 0x1aU));
}
int32_t set_vcpuid_entries(struct acrn_vm *vm)
@ -637,7 +507,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
int32_t result;
struct vcpuid_entry entry;
uint32_t limit;
uint32_t i;
uint32_t i, j;
struct cpuinfo_x86 *cpu_info = get_pcpu_info();
init_vcpuid_entry(0U, 0U, 0U, &entry);
@ -647,8 +517,6 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
}
result = set_vcpuid_entry(vm, &entry);
if (result == 0) {
percpu_cpuid_init();
limit = entry.eax;
vm->vcpuid_level = limit;
@ -658,40 +526,64 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
}
switch (i) {
/* 0x4U */
case CPUID_CACHE:
result = set_vcpuid_cache(vm);
case 0x04U:
for (j = 0U; ; j++) {
init_vcpuid_entry(i, j, CPUID_CHECK_SUBLEAF, &entry);
if (entry.eax == 0U) {
break;
}
#ifdef CONFIG_VCAT_ENABLED
if (is_vcat_configured(vm)) {
result = set_vcpuid_vcat_04h(vm, &entry);
}
#endif
result = set_vcpuid_entry(vm, &entry);
if (result != 0) {
/* wants to break out of switch */
break;
}
}
break;
/* MONITOR/MWAIT */
case 0x05U:
break;
/* 0x06U */
case CPUID_THERMAL_POWER:
result = set_vcpuid_thermal_power(vm);
case 0x07U:
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);
break;
/* 0x07U */
case CPUID_EXTEND_FEATURE:
result = set_vcpuid_extfeat(vm);
break;
/* 0x12U */
case CPUID_SGX_CAP:
case 0x12U:
result = set_vcpuid_sgx(vm);
break;
/* These features are disabled */
/* PMU is not supported except for core partition VM, like RTVM */
/* 0x0aU */
case CPUID_ARCH_PERF_MON:
case 0x0aU:
if (is_pmu_pt_configured(vm)) {
init_vcpuid_entry(i, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
}
break;
/* 0xFU, Intel RDT */
case CPUID_RDT_MONITOR:
/* Intel RDT */
case 0x0fU:
break;
/* 0x10U, Intel RDT */
case CPUID_RDT_ALLOCATION:
/* Intel RDT */
case 0x10U:
#ifdef CONFIG_VCAT_ENABLED
if (is_vcat_configured(vm)) {
result = set_vcpuid_vcat_10h(vm);
@ -699,10 +591,12 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
#endif
break;
/* 0x14U, Intel Processor Trace */
case CPUID_TRACE:
/* 0x1BU, PCONFIG */
case CPUID_PCONFIG:
/* Intel Processor Trace */
case 0x14U:
/* PCONFIG */
case 0x1bU:
/* V2 Extended Topology Enumeration Leaf */
case 0x1fU:
break;
default:
init_vcpuid_entry(i, 0U, 0U, &entry);
@ -873,14 +767,6 @@ static void guest_cpuid_19h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
}
}
static void guest_cpuid_1fh(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
cpuid_subleaf(0x1fU, *ecx, eax, ebx, ecx, edx);
/* Patching X2APIC */
*edx = vlapic_get_apicid(vcpu_vlapic(vcpu));
}
static void guest_cpuid_80000001h(const struct acrn_vcpu *vcpu,
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
@ -948,56 +834,29 @@ void guest_cpuid(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t
} else {
/* percpu related */
switch (leaf) {
/* 0x01U */
case CPUID_FEATURES:
case 0x01U:
guest_cpuid_01h(vcpu, eax, ebx, ecx, edx);
break;
/* 0x04U for hybrid arch */
case CPUID_CACHE:
guest_cpuid_04h(vcpu->vm, eax, ebx, ecx, edx);
break;
/* 0x06U for hybrid arch */
case CPUID_THERMAL_POWER:
guest_cpuid_06h(vcpu->vm, eax, ebx, ecx, edx);
break;
/* 0x0BU */
case CPUID_EXTEND_TOPOLOGY:
case 0x0bU:
guest_cpuid_0bh(vcpu, eax, ebx, ecx, edx);
break;
/* 0x0dU */
case CPUID_XSAVE_FEATURES:
case 0x0dU:
guest_cpuid_0dh(vcpu, eax, ebx, ecx, edx);
break;
/* 0x14U for hybrid arch */
case CPUID_TRACE:
*eax = 0U;
*ebx = 0U;
*ecx = 0U;
*edx = 0U;
break;
/* 0x19U */
case CPUID_KEY_LOCKER:
case 0x19U:
guest_cpuid_19h(vcpu, eax, ebx, ecx, edx);
break;
/* 0x1fU */
case CPUID_V2_EXTEND_TOPOLOGY:
guest_cpuid_1fh(vcpu, eax, ebx, ecx, edx);
break;
/* 0x80000001U */
case CPUID_EXTEND_FUNCTION_1:
case 0x80000001U:
guest_cpuid_80000001h(vcpu, eax, ebx, ecx, edx);
break;
default:
/*
* In this switch statement, leaf 0x01/0x04/0x06/0x0b/0x0d/0x19/0x1f/0x80000001
* In this switch statement, leaf 0x01/0x0b/0x0d/0x19/0x80000001
* shall be handled specifically. All the other cases
* just return physical value.
*/

Some files were not shown because too many files have changed in this diff Show More