forked from SLFO-pool/xen
Compare commits
6 Commits
Author | SHA256 | Date | |
---|---|---|---|
13b8259b5d | |||
b8bb876dbd | |||
5be7b338bb | |||
4ce9e75764 | |||
245e26a41b | |||
8b440090d6 |
@@ -1,45 +0,0 @@
|
||||
# Commit d0a718a45f14b86471d8eb3083acd72760963470
|
||||
# Date 2024-04-11 13:23:08 +0100
|
||||
# Author Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
# Committer Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
x86/hvm: Fix Misra Rule 19.1 regression
|
||||
|
||||
Despite noticing an impending Rule 19.1 violation, the adjustment made (the
|
||||
uint32_t cast) wasn't sufficient to avoid it. Try again.
|
||||
|
||||
Subsequently noticed by Coverity too.
|
||||
|
||||
Fixes: 6a98383b0877 ("x86/HVM: clear upper halves of GPRs upon entry from 32-bit code")
|
||||
Coverity-IDs: 1596289 thru 1596298
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
|
||||
|
||||
--- a/xen/arch/x86/include/asm/hvm/hvm.h
|
||||
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
|
||||
@@ -585,16 +585,16 @@ static inline void hvm_sanitize_regs_fie
|
||||
if ( compat )
|
||||
{
|
||||
/* Clear GPR upper halves, to counteract guests playing games. */
|
||||
- regs->rbp = (uint32_t)regs->ebp;
|
||||
- regs->rbx = (uint32_t)regs->ebx;
|
||||
- regs->rax = (uint32_t)regs->eax;
|
||||
- regs->rcx = (uint32_t)regs->ecx;
|
||||
- regs->rdx = (uint32_t)regs->edx;
|
||||
- regs->rsi = (uint32_t)regs->esi;
|
||||
- regs->rdi = (uint32_t)regs->edi;
|
||||
- regs->rip = (uint32_t)regs->eip;
|
||||
- regs->rflags = (uint32_t)regs->eflags;
|
||||
- regs->rsp = (uint32_t)regs->esp;
|
||||
+ regs->rbp = (uint32_t)regs->rbp;
|
||||
+ regs->rbx = (uint32_t)regs->rbx;
|
||||
+ regs->rax = (uint32_t)regs->rax;
|
||||
+ regs->rcx = (uint32_t)regs->rcx;
|
||||
+ regs->rdx = (uint32_t)regs->rdx;
|
||||
+ regs->rsi = (uint32_t)regs->rsi;
|
||||
+ regs->rdi = (uint32_t)regs->rdi;
|
||||
+ regs->rip = (uint32_t)regs->rip;
|
||||
+ regs->rflags = (uint32_t)regs->rflags;
|
||||
+ regs->rsp = (uint32_t)regs->rsp;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
40
README.SUSE
40
README.SUSE
@@ -32,7 +32,6 @@ and Tools" installs all the packages below:
|
||||
virt-install (Optional, to install VMs)
|
||||
virt-manager (Optional, to manage VMs graphically)
|
||||
virt-viewer (Optional, to view VMs outside virt-manager)
|
||||
vm-install (Optional, to install VMs with xl only)
|
||||
|
||||
You then need to reboot your machine. Instead of booting a normal Linux
|
||||
kernel, you will boot the Xen hypervisor and a slightly changed Linux kernel.
|
||||
@@ -174,35 +173,6 @@ details. The installation of an OS within the VM can be automated if the OS
|
||||
supports it.
|
||||
|
||||
|
||||
Creating a VM with vm-install
|
||||
-----------------------------
|
||||
The vm-install program is also provided to create VMs. Like virt-install,
|
||||
this optional program handles creating both the VM's libvirt XML definition
|
||||
and disk(s). It also creates a legacy configuration file for use with 'xl'.
|
||||
It can help install any operating system, not just SUSE.
|
||||
|
||||
From the command line, run "vm-install". If the DISPLAY environment variable
|
||||
is set and the supporting packages (python-gtk) are installed, a graphical
|
||||
wizard will start. Otherwise, a text wizard will start. If vm-install is
|
||||
started with the '--use-xl' flag, it will not require libvirt nor attempt
|
||||
to communicate with libvirt when creating a VM and instead will only use the
|
||||
'xl' toolstack to start VM installations.
|
||||
|
||||
Once you have the VM configured, click "OK". The wizard will now create a
|
||||
configuration file for the VM, and create a disk image. The disk image will
|
||||
exist in /var/lib/xen/images, and a corresponding configuration file will exist
|
||||
in /etc/xen/vm. The operating system's installation program will then run
|
||||
within the VM.
|
||||
|
||||
When the VM shuts down (because the installation -- or at least the first
|
||||
stage of it -- is done), the wizard finalizes the VM's configuration and
|
||||
restarts the VM.
|
||||
|
||||
The creation of VMs can be automated; read the vm-install man page for more
|
||||
details. The installation of an OS within the VM can be automated if the OS
|
||||
supports it.
|
||||
|
||||
|
||||
Creating a VM Manually
|
||||
----------------------
|
||||
If you create a VM manually (as opposed to using virt-install, which is the
|
||||
@@ -231,11 +201,11 @@ Managing Virtual Machines
|
||||
-------------------------
|
||||
VMs can be managed from the command line using 'virsh' or from virt-manager.
|
||||
|
||||
VMs created by virt-install or vm-install (without vm-install's --use-xl flag)
|
||||
will automatically be defined in libvirt. VMs defined in libvirt may be managed
|
||||
by virt-manager or from the command line using the 'virsh' command. However,
|
||||
if you copy a VM from another machine and manually create a VM XML configuration
|
||||
file, you will need to import it into libvirt with a command like:
|
||||
VMs created by virt-install will automatically be defined in libvirt. VMs
|
||||
defined in libvirt may be managed by virt-manager or from the command line
|
||||
using the 'virsh' command. However, if you copy a VM from another machine
|
||||
and manually create a VM XML configuration file, you will need to import it
|
||||
into libvirt with a command like:
|
||||
virsh define <path to>/my-vm.xml
|
||||
This imports the configuration into libvirt (and therefore virt-manager becomes
|
||||
aware of it, also).
|
||||
|
@@ -1,50 +0,0 @@
|
||||
Index: xen-4.18.0-testing/tools/misc/xencov_split
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/misc/xencov_split
|
||||
+++ xen-4.18.0-testing/tools/misc/xencov_split
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
from __future__ import print_function
|
||||
from builtins import str
|
||||
Index: xen-4.18.0-testing/tools/python/scripts/convert-legacy-stream
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/scripts/convert-legacy-stream
|
||||
+++ xen-4.18.0-testing/tools/python/scripts/convert-legacy-stream
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/scripts/verify-stream-v2
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/scripts/verify-stream-v2
|
||||
+++ xen-4.18.0-testing/tools/python/scripts/verify-stream-v2
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Verify a v2 format migration stream """
|
||||
Index: xen-4.18.0-testing/tools/xenmon/xenmon.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/xenmon/xenmon.py
|
||||
+++ xen-4.18.0-testing/tools/xenmon/xenmon.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
#####################################################################
|
||||
# xenmon is a front-end for xenbaked.
|
||||
Index: xen-4.18.0-testing/tools/xentrace/xentrace_format
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/xentrace/xentrace_format
|
||||
+++ xen-4.18.0-testing/tools/xentrace/xentrace_format
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
# by Mark Williamson, (C) 2004 Intel Research Cambridge
|
||||
|
@@ -1,201 +0,0 @@
|
||||
Index: xen-4.18.3-testing/Config.mk
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/Config.mk
|
||||
+++ xen-4.18.3-testing/Config.mk
|
||||
@@ -77,7 +77,7 @@ EXTRA_INCLUDES += $(EXTRA_PREFIX)/includ
|
||||
EXTRA_LIB += $(EXTRA_PREFIX)/lib
|
||||
endif
|
||||
|
||||
-PYTHON ?= python
|
||||
+PYTHON ?= python3
|
||||
PYTHON_PREFIX_ARG ?= --prefix="$(prefix)"
|
||||
# The above requires that prefix contains *no spaces*. This variable is here
|
||||
# to permit the user to set PYTHON_PREFIX_ARG to '' to workaround this bug:
|
||||
Index: xen-4.18.3-testing/tools/configure
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/configure
|
||||
+++ xen-4.18.3-testing/tools/configure
|
||||
@@ -7382,15 +7382,15 @@ if test x"${PYTHONPATH}" = x"no"
|
||||
then
|
||||
as_fn_error $? "Unable to find $PYTHON, please install $PYTHON" "$LINENO" 5
|
||||
fi
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python version >= 2.6 " >&5
|
||||
-$as_echo_n "checking for python version >= 2.6 ... " >&6; }
|
||||
-`$PYTHON -c 'import sys; sys.exit(eval("sys.version_info < (2, 6)"))'`
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python3 version >= 3.0 " >&5
|
||||
+$as_echo_n "checking for python3 version >= 3.0 ... " >&6; }
|
||||
+`$PYTHON -c 'import sys; sys.exit(eval("sys.version_info < (3, 0)"))'`
|
||||
if test "$?" != "0"
|
||||
then
|
||||
python_version=`$PYTHON -V 2>&1`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
- as_fn_error $? "$python_version is too old, minimum required version is 2.6" "$LINENO" 5
|
||||
+ as_fn_error $? "$python_version is too old, minimum required version is 3.0" "$LINENO" 5
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
Index: xen-4.18.3-testing/tools/configure.ac
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/configure.ac
|
||||
+++ xen-4.18.3-testing/tools/configure.ac
|
||||
@@ -385,7 +385,7 @@ PYTHONPATH=$PYTHON
|
||||
PYTHON=`basename $PYTHONPATH`
|
||||
|
||||
AX_PATH_PROG_OR_FAIL([PYTHONPATH], [$PYTHON])
|
||||
-AX_CHECK_PYTHON_VERSION([2], [6])
|
||||
+AX_CHECK_PYTHON_VERSION([3], [0])
|
||||
|
||||
AS_IF([test "$cross_compiling" != yes], [
|
||||
AX_CHECK_PYTHON_DEVEL()
|
||||
Index: xen-4.18.3-testing/tools/libs/light/idl.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/libs/light/idl.py
|
||||
+++ xen-4.18.3-testing/tools/libs/light/idl.py
|
||||
@@ -271,7 +271,7 @@ class KeyedUnion(Aggregate):
|
||||
if not isinstance(keyvar_type, Enumeration):
|
||||
raise ValueError
|
||||
|
||||
- kv_kwargs = dict([(x.lstrip('keyvar_'),y) for (x,y) in kwargs.items() if x.startswith('keyvar_')])
|
||||
+ kv_kwargs = dict([(x.lstrip('keyvar_'),y) for (x,y) in list(kwargs.items()) if x.startswith('keyvar_')])
|
||||
|
||||
self.keyvar = Field(keyvar_type, keyvar_name, **kv_kwargs)
|
||||
|
||||
@@ -317,7 +317,7 @@ class Array(Type):
|
||||
kwargs.setdefault('json_parse_type', 'JSON_ARRAY')
|
||||
Type.__init__(self, namespace=elem_type.namespace, typename=elem_type.rawname + " *", **kwargs)
|
||||
|
||||
- lv_kwargs = dict([(x.lstrip('lenvar_'),y) for (x,y) in kwargs.items() if x.startswith('lenvar_')])
|
||||
+ lv_kwargs = dict([(x.lstrip('lenvar_'),y) for (x,y) in list(kwargs.items()) if x.startswith('lenvar_')])
|
||||
|
||||
self.lenvar = Field(integer, lenvar_name, **lv_kwargs)
|
||||
self.elem_type = elem_type
|
||||
@@ -353,7 +353,7 @@ def parse(f):
|
||||
globs = {}
|
||||
locs = OrderedDict()
|
||||
|
||||
- for n,t in globals().items():
|
||||
+ for n,t in list(globals().items()):
|
||||
if isinstance(t, Type):
|
||||
globs[n] = t
|
||||
elif isinstance(t,type(object)) and issubclass(t, Type):
|
||||
Index: xen-4.18.3-testing/tools/libs/light/gentest.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/libs/light/gentest.py
|
||||
+++ xen-4.18.3-testing/tools/libs/light/gentest.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
Index: xen-4.18.3-testing/tools/libs/light/gentypes.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/libs/light/gentypes.py
|
||||
+++ xen-4.18.3-testing/tools/libs/light/gentypes.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
Index: xen-4.18.3-testing/tools/include/xen-foreign/mkheader.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/include/xen-foreign/mkheader.py
|
||||
+++ xen-4.18.3-testing/tools/include/xen-foreign/mkheader.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
Index: xen-4.18.3-testing/tools/include/xen-foreign/mkchecker.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/include/xen-foreign/mkchecker.py
|
||||
+++ xen-4.18.3-testing/tools/include/xen-foreign/mkchecker.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
import sys;
|
||||
from structs import structs, compat_arches;
|
||||
Index: xen-4.18.3-testing/xen/tools/gen-cpuid.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/xen/tools/gen-cpuid.py
|
||||
+++ xen-4.18.3-testing/xen/tools/gen-cpuid.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys, os, re
|
||||
Index: xen-4.18.3-testing/xen/tools/compat-build-source.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/xen/tools/compat-build-source.py
|
||||
+++ xen-4.18.3-testing/xen/tools/compat-build-source.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
import re,sys
|
||||
|
||||
Index: xen-4.18.3-testing/xen/tools/compat-build-header.py
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/xen/tools/compat-build-header.py
|
||||
+++ xen-4.18.3-testing/xen/tools/compat-build-header.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
import re,sys
|
||||
|
||||
Index: xen-4.18.3-testing/tools/misc/xensymoops
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/misc/xensymoops
|
||||
+++ xen-4.18.3-testing/tools/misc/xensymoops
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/env python
|
||||
+#!/usr/bin/python3
|
||||
|
||||
# An oops analyser for Xen
|
||||
# Usage: xensymoops path-to-xen.s < oops-message
|
||||
@@ -43,12 +43,12 @@ def read_oops():
|
||||
return (eip_addr, stack_addresses)
|
||||
|
||||
def usage():
|
||||
- print >> sys.stderr, """Usage: %s path-to-asm < oops-msg
|
||||
+ print("""Usage: %s path-to-asm < oops-msg
|
||||
The oops message should be fed to the standard input. The
|
||||
command-line argument specifies the path to the Xen assembly dump
|
||||
produced by \"make debug\". The location of EIP and the backtrace
|
||||
will be output to standard output.
|
||||
- """ % sys.argv[0]
|
||||
+ """ % sys.argv[0], file=sys.stderr)
|
||||
sys.exit()
|
||||
|
||||
##### main
|
||||
@@ -99,7 +99,7 @@ while True:
|
||||
|
||||
# if this address was seen as a potential code address in the backtrace then
|
||||
# record it in the backtrace list
|
||||
- if stk_addrs.has_key(address):
|
||||
+ if address in stk_addrs:
|
||||
backtrace.append((stk_addrs[address], address, func))
|
||||
|
||||
# if this was the address that EIP...
|
||||
@@ -107,12 +107,12 @@ while True:
|
||||
eip_func = func
|
||||
|
||||
|
||||
-print "EIP %s in function %s" % (eip_addr, eip_func)
|
||||
-print "Backtrace:"
|
||||
+print("EIP %s in function %s" % (eip_addr, eip_func))
|
||||
+print("Backtrace:")
|
||||
|
||||
# sorting will order primarily by the first element of each tuple,
|
||||
# i.e. the order in the original oops
|
||||
backtrace.sort()
|
||||
|
||||
for (i, a, f) in backtrace:
|
||||
- print "%s in function %s" % ( a, f )
|
||||
+ print("%s in function %s" % ( a, f ))
|
11
disable-pv-support.patch
Normal file
11
disable-pv-support.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- a/xen/arch/x86/Kconfig
|
||||
+++ b/xen/arch/x86/Kconfig
|
||||
@@ -62,7 +62,7 @@ source "arch/x86/Kconfig.cpu"
|
||||
source "arch/Kconfig"
|
||||
|
||||
config PV
|
||||
- def_bool y
|
||||
+ def_bool n
|
||||
prompt "PV support"
|
||||
help
|
||||
Interfaces to support PV domains. These require guest kernel support
|
@@ -1,81 +0,0 @@
|
||||
References: bsc#1225953
|
||||
|
||||
Compiling against gcc14.
|
||||
../../../../../newlib-1.16.0/newlib/libc/stdlib/wcstoull.c: In function ‘wcstoull’:
|
||||
../../../../../newlib-1.16.0/newlib/libc/stdlib/wcstoull.c:136:16: error: implicit declaration of function ‘_wcstoull_r’; did you mean ‘wcstoull’? [-Wimplicit-function-declaration]
|
||||
136 | return _wcstoull_r (_REENT, s, ptr, base);
|
||||
| ^~~~~~~~~~~
|
||||
| wcstoull
|
||||
|
||||
In file included from ../../../../../newlib-1.16.0/newlib/libc/reent/signalr.c:7:
|
||||
../../../../../newlib-1.16.0/newlib/libc/reent/signalr.c: In function ‘_kill_r’:
|
||||
../../../../../newlib-1.16.0/newlib/libc/reent/signalr.c:61:14: error: implicit declaration of function ‘kill’; did you mean ‘_kill’? [-Wimplicit-function-declaration]
|
||||
61 | if ((ret = _kill (pid, sig)) == -1 && errno != 0)
|
||||
| ^~~~~
|
||||
|
||||
|
||||
Index: xen-4.18.2-testing/stubdom/Makefile
|
||||
===================================================================
|
||||
--- xen-4.18.2-testing.orig/stubdom/Makefile
|
||||
+++ xen-4.18.2-testing/stubdom/Makefile
|
||||
@@ -97,6 +97,7 @@ newlib-$(NEWLIB_VERSION): newlib-$(NEWLI
|
||||
patch -d $@ -p1 < newlib-disable-texinfo.patch
|
||||
patch -d $@ -p1 < newlib-cygmon-gmon.patch
|
||||
patch -d $@ -p1 < newlib-makedoc.patch
|
||||
+ patch -d $@ -p1 < newlib-gcc14-pragmas.patch
|
||||
find $@ -type f | xargs perl -i.bak \
|
||||
-pe 's/\b_(tzname|daylight|timezone)\b/$$1/g'
|
||||
touch $@
|
||||
Index: xen-4.18.2-testing/stubdom/newlib-gcc14-pragmas.patch
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ xen-4.18.2-testing/stubdom/newlib-gcc14-pragmas.patch
|
||||
@@ -0,0 +1,36 @@
|
||||
+--- newlib-1.16.0/newlib/libc/stdlib/wcstoull.c.orig 2024-06-04 15:32:01.495146632 -0600
|
||||
++++ newlib-1.16.0/newlib/libc/stdlib/wcstoull.c 2024-06-04 15:38:56.627156524 -0600
|
||||
+@@ -127,6 +127,10 @@ PORTABILITY
|
||||
+
|
||||
+ #ifndef _REENT_ONLY
|
||||
+
|
||||
++#if __GNUC__ >= 14
|
||||
++#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
||||
++#endif
|
||||
++
|
||||
+ unsigned long long
|
||||
+ _DEFUN (wcstoull, (s, ptr, base),
|
||||
+ _CONST wchar_t *s _AND
|
||||
+--- newlib-1.16.0/newlib/libc/reent/signalr.c.orig 2024-06-04 15:39:15.139156966 -0600
|
||||
++++ newlib-1.16.0/newlib/libc/reent/signalr.c 2024-06-04 15:40:24.899158628 -0600
|
||||
+@@ -49,6 +49,10 @@ DESCRIPTION
|
||||
+ <<errno>>.
|
||||
+ */
|
||||
+
|
||||
++#if __GNUC__ >= 14
|
||||
++#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
||||
++#endif
|
||||
++
|
||||
+ int
|
||||
+ _DEFUN (_kill_r, (ptr, pid, sig),
|
||||
+ struct _reent *ptr _AND
|
||||
+--- newlib-1.16.0/newlib/doc/makedoc.c.orig 2024-06-04 16:07:54.423197934 -0600
|
||||
++++ newlib-1.16.0/newlib/doc/makedoc.c 2024-06-04 16:15:15.395208441 -0600
|
||||
+@@ -798,6 +798,7 @@ DEFUN( iscommand,(ptr, idx),
|
||||
+ }
|
||||
+
|
||||
+
|
||||
++static unsigned int
|
||||
+ DEFUN(copy_past_newline,(ptr, idx, dst),
|
||||
+ string_type *ptr AND
|
||||
+ unsigned int idx AND
|
||||
--- xen-4.18.2-testing/extras/mini-os-remote/include/posix/sys/mman.h.orig 2024-06-04 16:27:35.155226069 -0600
|
||||
+++ xen-4.18.2-testing/extras/mini-os-remote/include/posix/sys/mman.h 2024-06-04 16:31:46.591232060 -0600
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) asm("mmap64");
|
||||
int munmap(void *start, size_t length);
|
||||
-static inline mlock(const void *addr, size_t len) { return 0; }
|
||||
-static inline munlock(const void *addr, size_t len) { return 0; }
|
||||
+static inline int mlock(const void *addr, size_t len) { return 0; }
|
||||
+static inline int munlock(const void *addr, size_t len) { return 0; }
|
||||
|
||||
#endif /* _POSIX_SYS_MMAN_H */
|
@@ -11,44 +11,42 @@ host console or also by inserting a sleep before each ip command
|
||||
and executing it manually at the command line. This seems to be
|
||||
an artifact of using 'set -e' everywhere.
|
||||
|
||||
Index: xen-4.15.0-testing/tools/hotplug/Linux/xen-network-common.sh
|
||||
===================================================================
|
||||
--- xen-4.15.0-testing.orig/tools/hotplug/Linux/xen-network-common.sh
|
||||
+++ xen-4.15.0-testing/tools/hotplug/Linux/xen-network-common.sh
|
||||
@@ -90,7 +90,7 @@ _setup_bridge_port() {
|
||||
---
|
||||
tools/hotplug/Linux/xen-network-common.sh | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/tools/hotplug/Linux/xen-network-common.sh
|
||||
+++ b/tools/hotplug/Linux/xen-network-common.sh
|
||||
@@ -84,7 +84,7 @@
|
||||
local virtual="$2"
|
||||
|
||||
# take interface down ...
|
||||
- ip link set dev ${dev} down
|
||||
+ (ip link set dev ${dev} down || true)
|
||||
+ ip link set dev ${dev} down || true
|
||||
|
||||
if [ $virtual -ne 0 ] ; then
|
||||
# Initialise a dummy MAC address. We choose the numerically
|
||||
@@ -101,7 +101,7 @@ _setup_bridge_port() {
|
||||
@@ -95,7 +95,7 @@
|
||||
fi
|
||||
|
||||
# ... and configure it
|
||||
- ip address flush dev ${dev}
|
||||
+ (ip address flush dev ${dev} || true)
|
||||
+ ip address flush dev ${dev} || true
|
||||
}
|
||||
|
||||
setup_physical_bridge_port() {
|
||||
@@ -136,15 +136,15 @@ add_to_bridge () {
|
||||
@@ -123,12 +123,12 @@
|
||||
# Don't add $dev to $bridge if it's already on the bridge.
|
||||
if [ ! -e "/sys/class/net/${bridge}/brif/${dev}" ]; then
|
||||
log debug "adding $dev to bridge $bridge"
|
||||
if which brctl >&/dev/null; then
|
||||
- brctl addif ${bridge} ${dev}
|
||||
+ (brctl addif ${bridge} ${dev} || true)
|
||||
else
|
||||
- ip link set ${dev} master ${bridge}
|
||||
+ (ip link set ${dev} master ${bridge} || true)
|
||||
fi
|
||||
+ ip link set ${dev} master ${bridge} || true
|
||||
else
|
||||
log debug "$dev already on bridge $bridge"
|
||||
fi
|
||||
|
||||
- ip link set dev ${dev} up
|
||||
+ (ip link set dev ${dev} up || true)
|
||||
+ ip link set dev ${dev} up || true
|
||||
}
|
||||
|
||||
remove_from_bridge () {
|
||||
|
@@ -1,64 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Wed, 9 Dec 2020 16:40:00 +0100
|
||||
Subject: libxc sr bitmap long
|
||||
|
||||
tools: add API to work with sevaral bits at once
|
||||
|
||||
Introduce new API to test if a fixed number of bits is clear or set,
|
||||
and clear or set them all at once.
|
||||
|
||||
The caller has to make sure the input bitnumber is a multiple of BITS_PER_LONG.
|
||||
|
||||
This API avoids the loop over each bit in a known range just to see
|
||||
if all of them are either clear or set.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
|
||||
v02:
|
||||
- change return type from int to bool (jgross)
|
||||
---
|
||||
tools/libs/ctrl/xc_bitops.h | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
--- a/tools/libs/ctrl/xc_bitops.h
|
||||
+++ b/tools/libs/ctrl/xc_bitops.h
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
/* bitmap operations for single threaded access */
|
||||
|
||||
+#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -81,4 +82,31 @@ static inline void bitmap_or(void *_dst,
|
||||
dst[i] |= other[i];
|
||||
}
|
||||
|
||||
+static inline bool test_bit_long_set(unsigned long nr_base, const void *_addr)
|
||||
+{
|
||||
+ const unsigned long *addr = _addr;
|
||||
+ unsigned long val = addr[nr_base / BITS_PER_LONG];
|
||||
+
|
||||
+ return val == ~0;
|
||||
+}
|
||||
+
|
||||
+static inline bool test_bit_long_clear(unsigned long nr_base, const void *_addr)
|
||||
+{
|
||||
+ const unsigned long *addr = _addr;
|
||||
+ unsigned long val = addr[nr_base / BITS_PER_LONG];
|
||||
+
|
||||
+ return val == 0;
|
||||
+}
|
||||
+
|
||||
+static inline void clear_bit_long(unsigned long nr_base, void *_addr)
|
||||
+{
|
||||
+ unsigned long *addr = _addr;
|
||||
+ addr[nr_base / BITS_PER_LONG] = 0;
|
||||
+}
|
||||
+
|
||||
+static inline void set_bit_long(unsigned long nr_base, void *_addr)
|
||||
+{
|
||||
+ unsigned long *addr = _addr;
|
||||
+ addr[nr_base / BITS_PER_LONG] = ~0;
|
||||
+}
|
||||
#endif /* XC_BITOPS_H */
|
@@ -1,144 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Thu, 7 Jan 2021 15:58:30 +0100
|
||||
Subject: libxc sr LIBXL_HAVE_DOMAIN_SUSPEND_PROPS
|
||||
|
||||
tools: adjust libxl_domain_suspend to receive a struct props
|
||||
|
||||
Upcoming changes will pass more knobs down to xc_domain_save.
|
||||
Adjust the libxl_domain_suspend API to allow easy adding of additional knobs.
|
||||
|
||||
No change in behavior intented.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Christian Lindig <christian.lindig@citrix.com>
|
||||
---
|
||||
tools/include/libxl.h | 26 +++++++++++++++++++++++---
|
||||
tools/libs/light/libxl_domain.c | 7 ++++---
|
||||
tools/xl/xl_migrate.c | 9 ++++++---
|
||||
tools/xl/xl_saverestore.c | 3 ++-
|
||||
4 files changed, 35 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/tools/include/libxl.h
|
||||
+++ b/tools/include/libxl.h
|
||||
@@ -1811,13 +1811,28 @@ static inline int libxl_retrieve_domain_
|
||||
libxl_retrieve_domain_configuration_0x041200
|
||||
#endif
|
||||
|
||||
-int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd,
|
||||
- int flags, /* LIBXL_SUSPEND_* */
|
||||
- const libxl_asyncop_how *ao_how)
|
||||
- LIBXL_EXTERNAL_CALLERS_ONLY;
|
||||
+/*
|
||||
+ * LIBXL_HAVE_DOMAIN_SUSPEND_PROPS indicates that the
|
||||
+ * libxl_domain_suspend_props() function takes a props struct.
|
||||
+ */
|
||||
+#define LIBXL_HAVE_DOMAIN_SUSPEND_PROPS 1
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint32_t flags; /* LIBXL_SUSPEND_* */
|
||||
+} libxl_domain_suspend_suse_properties;
|
||||
#define LIBXL_SUSPEND_DEBUG 1
|
||||
#define LIBXL_SUSPEND_LIVE 2
|
||||
|
||||
+#define LIBXL_HAVE_DOMAIN_SUSPEND_SUSE
|
||||
+int libxl_domain_suspend_suse(libxl_ctx *ctx, uint32_t domid, int fd,
|
||||
+ const libxl_domain_suspend_suse_properties *props, /* optional */
|
||||
+ const libxl_asyncop_how *ao_how)
|
||||
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
||||
+
|
||||
+int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
|
||||
+ const libxl_asyncop_how *ao_how)
|
||||
+ LIBXL_EXTERNAL_CALLERS_ONLY;
|
||||
+
|
||||
/*
|
||||
* Only suspend domain, do not save its state to file, do not destroy it.
|
||||
* Suspended domain can be resumed with libxl_domain_resume()
|
||||
--- a/tools/libs/light/libxl_domain.c
|
||||
+++ b/tools/libs/light/libxl_domain.c
|
||||
@@ -502,7 +502,8 @@ static void domain_suspend_cb(libxl__egc
|
||||
|
||||
}
|
||||
|
||||
-int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
|
||||
+static int do_libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd,
|
||||
+ const libxl_domain_suspend_suse_properties *props,
|
||||
const libxl_asyncop_how *ao_how)
|
||||
{
|
||||
AO_CREATE(ctx, domid, ao_how);
|
||||
@@ -523,8 +524,8 @@ int libxl_domain_suspend(libxl_ctx *ctx,
|
||||
dss->domid = domid;
|
||||
dss->fd = fd;
|
||||
dss->type = type;
|
||||
- dss->live = flags & LIBXL_SUSPEND_LIVE;
|
||||
- dss->debug = flags & LIBXL_SUSPEND_DEBUG;
|
||||
+ dss->live = props->flags & LIBXL_SUSPEND_LIVE;
|
||||
+ dss->debug = props->flags & LIBXL_SUSPEND_DEBUG;
|
||||
dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE;
|
||||
|
||||
rc = libxl__fd_flags_modify_save(gc, dss->fd,
|
||||
@@ -539,6 +540,21 @@ int libxl_domain_suspend(libxl_ctx *ctx,
|
||||
return AO_CREATE_FAIL(rc);
|
||||
}
|
||||
|
||||
+int libxl_domain_suspend_suse(libxl_ctx *ctx, uint32_t domid, int fd,
|
||||
+ const libxl_domain_suspend_suse_properties *props,
|
||||
+ const libxl_asyncop_how *ao_how)
|
||||
+{
|
||||
+ return do_libxl_domain_suspend(ctx, domid, fd, props, ao_how);
|
||||
+}
|
||||
+
|
||||
+int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
|
||||
+ const libxl_asyncop_how *ao_how)
|
||||
+{
|
||||
+ libxl_domain_suspend_suse_properties props = { .flags = flags };
|
||||
+
|
||||
+ return do_libxl_domain_suspend(ctx, domid, fd, &props, ao_how);
|
||||
+}
|
||||
+
|
||||
static void domain_suspend_empty_cb(libxl__egc *egc,
|
||||
libxl__domain_suspend_state *dss, int rc)
|
||||
{
|
||||
--- a/tools/xl/xl_migrate.c
|
||||
+++ b/tools/xl/xl_migrate.c
|
||||
@@ -186,7 +186,10 @@ static void migrate_domain(uint32_t domi
|
||||
char *away_domname;
|
||||
char rc_buf;
|
||||
uint8_t *config_data;
|
||||
- int config_len, flags = LIBXL_SUSPEND_LIVE;
|
||||
+ int config_len;
|
||||
+ libxl_domain_suspend_suse_properties props = {
|
||||
+ .flags = LIBXL_SUSPEND_LIVE,
|
||||
+ };
|
||||
|
||||
save_domain_core_begin(domid, preserve_domid, override_config_file,
|
||||
&config_data, &config_len);
|
||||
@@ -205,8 +208,8 @@ static void migrate_domain(uint32_t domi
|
||||
xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
|
||||
|
||||
if (debug)
|
||||
- flags |= LIBXL_SUSPEND_DEBUG;
|
||||
- rc = libxl_domain_suspend(ctx, domid, send_fd, flags, NULL);
|
||||
+ props.flags |= LIBXL_SUSPEND_DEBUG;
|
||||
+ rc = libxl_domain_suspend_suse(ctx, domid, send_fd, &props, NULL);
|
||||
if (rc) {
|
||||
fprintf(stderr, "migration sender: libxl_domain_suspend failed"
|
||||
" (rc=%d)\n", rc);
|
||||
--- a/tools/xl/xl_saverestore.c
|
||||
+++ b/tools/xl/xl_saverestore.c
|
||||
@@ -130,6 +130,7 @@ static int save_domain(uint32_t domid, i
|
||||
int fd;
|
||||
uint8_t *config_data;
|
||||
int config_len;
|
||||
+ libxl_domain_suspend_suse_properties props = {};
|
||||
|
||||
save_domain_core_begin(domid, preserve_domid, override_config_file,
|
||||
&config_data, &config_len);
|
||||
@@ -146,7 +147,7 @@ static int save_domain(uint32_t domid, i
|
||||
|
||||
save_domain_core_writeconfig(fd, filename, config_data, config_len);
|
||||
|
||||
- int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
|
||||
+ int rc = libxl_domain_suspend_suse(ctx, domid, fd, &props, NULL);
|
||||
close(fd);
|
||||
|
||||
if (rc < 0) {
|
@@ -1,238 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Thu, 7 Jan 2021 20:25:28 +0100
|
||||
Subject: libxc sr abort_if_busy
|
||||
|
||||
tools: add --abort_if_busy to libxl_domain_suspend
|
||||
|
||||
Provide a knob to the host admin to abort the live migration of a
|
||||
running domU if the downtime during final transit will be too long
|
||||
for the workload within domU.
|
||||
|
||||
Adjust error reporting. Add ERROR_MIGRATION_ABORTED to allow callers of
|
||||
libxl_domain_suspend to distinguish between errors and the requested
|
||||
constraint.
|
||||
|
||||
Adjust precopy_policy to simplify reporting of remaining dirty pages.
|
||||
The loop in send_memory_live populates ->dirty_count in a different
|
||||
place than ->iteration. Let it proceeed one more time to provide the
|
||||
desired information before leaving the loop.
|
||||
|
||||
This patch adjusts xl(1) and the libxl API.
|
||||
External users check LIBXL_HAVE_DOMAIN_SUSPEND_PROPS for the availibility
|
||||
of the new .abort_if_busy property.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
docs/man/xl.1.pod.in | 8 +++++++
|
||||
tools/include/libxl.h | 1 +
|
||||
tools/libs/light/libxl_dom_save.c | 7 ++++++-
|
||||
tools/libs/light/libxl_domain.c | 1 +
|
||||
tools/libs/light/libxl_internal.h | 2 ++
|
||||
tools/libs/light/libxl_stream_write.c | 9 +++++++-
|
||||
tools/libs/light/libxl_types.idl | 1 +
|
||||
tools/xl/xl_cmdtable.c | 6 +++++-
|
||||
tools/xl/xl_migrate.c | 30 ++++++++++++++++++++-------
|
||||
9 files changed, 55 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/docs/man/xl.1.pod.in
|
||||
+++ b/docs/man/xl.1.pod.in
|
||||
@@ -513,6 +513,14 @@ low, the guest is suspended and the domU
|
||||
This allows the host admin to control for how long the domU will likely
|
||||
be suspended during transit.
|
||||
|
||||
+=item B<--abort_if_busy>
|
||||
+
|
||||
+Abort migration instead of doing final suspend/move/resume if the
|
||||
+guest produced more than I<min_remaining> dirty pages during th number
|
||||
+of I<max_iters> iterations.
|
||||
+This avoids long periods of time where the guest is suspended, which
|
||||
+may confuse the workload within domU.
|
||||
+
|
||||
=back
|
||||
|
||||
=item B<remus> [I<OPTIONS>] I<domain-id> I<host>
|
||||
--- a/tools/include/libxl.h
|
||||
+++ b/tools/include/libxl.h
|
||||
@@ -1824,6 +1824,7 @@ typedef struct {
|
||||
} libxl_domain_suspend_suse_properties;
|
||||
#define LIBXL_SUSPEND_DEBUG 1
|
||||
#define LIBXL_SUSPEND_LIVE 2
|
||||
+#define LIBXL_SUSPEND_ABORT_IF_BUSY 4
|
||||
|
||||
#define LIBXL_HAVE_DOMAIN_SUSPEND_SUSE
|
||||
int libxl_domain_suspend_suse(libxl_ctx *ctx, uint32_t domid, int fd,
|
||||
--- a/tools/libs/light/libxl_dom_save.c
|
||||
+++ b/tools/libs/light/libxl_dom_save.c
|
||||
@@ -383,11 +383,16 @@ static int libxl__domain_save_precopy_po
|
||||
stats.iteration, stats.dirty_count, stats.total_written);
|
||||
if (stats.dirty_count >= 0 && stats.dirty_count < dss->min_remaining)
|
||||
goto stop_copy;
|
||||
- if (stats.iteration >= dss->max_iters)
|
||||
+ if (stats.dirty_count >= 0 && stats.iteration >= dss->max_iters)
|
||||
goto stop_copy;
|
||||
return XGS_POLICY_CONTINUE_PRECOPY;
|
||||
|
||||
stop_copy:
|
||||
+ if (dss->abort_if_busy)
|
||||
+ {
|
||||
+ dss->remaining_dirty_pages = stats.dirty_count;
|
||||
+ return XGS_POLICY_ABORT;
|
||||
+ }
|
||||
return XGS_POLICY_STOP_AND_COPY;
|
||||
}
|
||||
|
||||
--- a/tools/libs/light/libxl_domain.c
|
||||
+++ b/tools/libs/light/libxl_domain.c
|
||||
@@ -526,6 +526,7 @@ static int do_libxl_domain_suspend(libxl
|
||||
dss->type = type;
|
||||
dss->max_iters = props->max_iters ?: LIBXL_XGS_POLICY_MAX_ITERATIONS;
|
||||
dss->min_remaining = props->min_remaining ?: LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT;
|
||||
+ dss->abort_if_busy = props->flags & LIBXL_SUSPEND_ABORT_IF_BUSY;
|
||||
dss->live = props->flags & LIBXL_SUSPEND_LIVE;
|
||||
dss->debug = props->flags & LIBXL_SUSPEND_DEBUG;
|
||||
dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE;
|
||||
--- a/tools/libs/light/libxl_internal.h
|
||||
+++ b/tools/libs/light/libxl_internal.h
|
||||
@@ -3655,9 +3655,11 @@ struct libxl__domain_save_state {
|
||||
libxl_domain_type type;
|
||||
int live;
|
||||
int debug;
|
||||
+ int abort_if_busy;
|
||||
int checkpointed_stream;
|
||||
uint32_t max_iters;
|
||||
uint32_t min_remaining;
|
||||
+ long remaining_dirty_pages;
|
||||
const libxl_domain_remus_info *remus;
|
||||
/* private */
|
||||
int rc;
|
||||
--- a/tools/libs/light/libxl_stream_write.c
|
||||
+++ b/tools/libs/light/libxl_stream_write.c
|
||||
@@ -344,11 +344,18 @@ void libxl__xc_domain_save_done(libxl__e
|
||||
goto err;
|
||||
|
||||
if (retval) {
|
||||
+ if (dss->remaining_dirty_pages) {
|
||||
+ LOGD(NOTICE, dss->domid, "saving domain: aborted,"
|
||||
+ " %ld remaining dirty pages.", dss->remaining_dirty_pages);
|
||||
+ } else {
|
||||
LOGEVD(ERROR, errnoval, dss->domid, "saving domain: %s",
|
||||
dss->dsps.guest_responded ?
|
||||
"domain responded to suspend request" :
|
||||
"domain did not respond to suspend request");
|
||||
- if (!dss->dsps.guest_responded)
|
||||
+ }
|
||||
+ if (dss->remaining_dirty_pages)
|
||||
+ rc = ERROR_MIGRATION_ABORTED;
|
||||
+ else if(!dss->dsps.guest_responded)
|
||||
rc = ERROR_GUEST_TIMEDOUT;
|
||||
else if (dss->rc)
|
||||
rc = dss->rc;
|
||||
--- a/tools/libs/light/libxl_types.idl
|
||||
+++ b/tools/libs/light/libxl_types.idl
|
||||
@@ -76,6 +76,7 @@ libxl_error = Enumeration("error", [
|
||||
(-30, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
|
||||
(-31, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
|
||||
(-32, "QEMU_API"), # QEMU's replies don't contains expected members
|
||||
+ (-33, "MIGRATION_ABORTED"),
|
||||
], value_namespace = "")
|
||||
|
||||
libxl_domain_type = Enumeration("domain_type", [
|
||||
--- a/tools/xl/xl_cmdtable.c
|
||||
+++ b/tools/xl/xl_cmdtable.c
|
||||
@@ -177,7 +177,11 @@ const struct cmd_spec cmd_table[] = {
|
||||
"-p Do not unpause domain after migrating it.\n"
|
||||
"-D Preserve the domain id\n"
|
||||
"--max_iters N Number of copy iterations before final stop+move\n"
|
||||
- "--min_remaining N Number of remaining dirty pages before final stop+move"
|
||||
+ "--min_remaining N Number of remaining dirty pages before final stop+move\n"
|
||||
+ "--abort_if_busy Abort migration instead of doing final stop+move,\n"
|
||||
+ " if the number of dirty pages is higher than <min_remaining>\n"
|
||||
+ " after <max_iters> iterations. Otherwise the amount of memory\n"
|
||||
+ " to be transfered would exceed maximum allowed domU downtime."
|
||||
},
|
||||
{ "restore",
|
||||
&main_restore, 0, 1,
|
||||
--- a/tools/xl/xl_migrate.c
|
||||
+++ b/tools/xl/xl_migrate.c
|
||||
@@ -177,7 +177,7 @@ static void migrate_do_preamble(int send
|
||||
}
|
||||
|
||||
static void migrate_domain(uint32_t domid, int preserve_domid,
|
||||
- const char *rune, int debug,
|
||||
+ const char *rune, int debug, int abort_if_busy,
|
||||
uint32_t max_iters,
|
||||
uint32_t min_remaining,
|
||||
const char *override_config_file)
|
||||
@@ -213,14 +213,20 @@ static void migrate_domain(uint32_t domi
|
||||
|
||||
if (debug)
|
||||
props.flags |= LIBXL_SUSPEND_DEBUG;
|
||||
+ if (abort_if_busy)
|
||||
+ props.flags |= LIBXL_SUSPEND_ABORT_IF_BUSY;
|
||||
rc = libxl_domain_suspend_suse(ctx, domid, send_fd, &props, NULL);
|
||||
if (rc) {
|
||||
fprintf(stderr, "migration sender: libxl_domain_suspend failed"
|
||||
" (rc=%d)\n", rc);
|
||||
- if (rc == ERROR_GUEST_TIMEDOUT)
|
||||
- goto failed_suspend;
|
||||
- else
|
||||
- goto failed_resume;
|
||||
+ switch (rc) {
|
||||
+ case ERROR_GUEST_TIMEDOUT:
|
||||
+ goto failed_suspend;
|
||||
+ case ERROR_MIGRATION_ABORTED:
|
||||
+ goto failed_busy;
|
||||
+ default:
|
||||
+ goto failed_resume;
|
||||
+ }
|
||||
}
|
||||
|
||||
//fprintf(stderr, "migration sender: Transfer complete.\n");
|
||||
@@ -302,6 +308,12 @@ static void migrate_domain(uint32_t domi
|
||||
fprintf(stderr, "Migration failed, failed to suspend at sender.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
+ failed_busy:
|
||||
+ close(send_fd);
|
||||
+ migration_child_report(recv_fd);
|
||||
+ fprintf(stderr, "Migration aborted as requested, domain is too busy.\n");
|
||||
+ exit(EXIT_FAILURE);
|
||||
+
|
||||
failed_resume:
|
||||
close(send_fd);
|
||||
migration_child_report(recv_fd);
|
||||
@@ -545,13 +557,14 @@ int main_migrate(int argc, char **argv)
|
||||
char *rune = NULL;
|
||||
char *host;
|
||||
int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
|
||||
- int preserve_domid = 0;
|
||||
+ int preserve_domid = 0, abort_if_busy = 0;
|
||||
uint32_t max_iters = 0;
|
||||
uint32_t min_remaining = 0;
|
||||
static struct option opts[] = {
|
||||
{"debug", 0, 0, 0x100},
|
||||
{"max_iters", 1, 0, 0x101},
|
||||
{"min_remaining", 1, 0, 0x102},
|
||||
+ {"abort_if_busy", 0, 0, 0x103},
|
||||
{"live", 0, 0, 0x200},
|
||||
COMMON_LONG_OPTS
|
||||
};
|
||||
@@ -585,6 +598,9 @@ int main_migrate(int argc, char **argv)
|
||||
case 0x102: /* --min_remaining */
|
||||
min_remaining = atoi(optarg);
|
||||
break;
|
||||
+ case 0x103: /* --abort_if_busy */
|
||||
+ abort_if_busy = 1;
|
||||
+ break;
|
||||
case 0x200: /* --live */
|
||||
/* ignored for compatibility with xm */
|
||||
break;
|
||||
@@ -619,7 +635,7 @@ int main_migrate(int argc, char **argv)
|
||||
pause_after_migration ? " -p" : "");
|
||||
}
|
||||
|
||||
- migrate_domain(domid, preserve_domid, rune, debug,
|
||||
+ migrate_domain(domid, preserve_domid, rune, debug, abort_if_busy,
|
||||
max_iters, min_remaining, config_filename);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@@ -1,148 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Sat, 9 Jan 2021 11:32:17 +0100
|
||||
Subject: libxc sr max_iters
|
||||
|
||||
tools: add --max_iters to libxl_domain_suspend
|
||||
|
||||
Migrating a large, and potentially busy, domU will take more
|
||||
time than neccessary due to excessive number of copying iterations.
|
||||
|
||||
Allow to host admin to control the number of iterations which
|
||||
copy cumulated domU dirty pages to the target host.
|
||||
|
||||
The default remains 5, which means one initial iteration to copy the
|
||||
entire domU memory, and up to 4 additional iterations to copy dirty
|
||||
memory from the still running domU. After the given number of iterations
|
||||
the domU is suspended, remaining dirty memory is copied and the domU is
|
||||
finally moved to the target host.
|
||||
|
||||
This patch adjusts xl(1) and the libxl API.
|
||||
External users check LIBXL_HAVE_DOMAIN_SUSPEND_PROPS for the availibility
|
||||
of the new .max_iters property.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
docs/man/xl.1.pod.in | 4 ++++
|
||||
tools/include/libxl.h | 1 +
|
||||
tools/libs/light/libxl_dom_save.c | 2 +-
|
||||
tools/libs/light/libxl_domain.c | 1 +
|
||||
tools/libs/light/libxl_internal.h | 1 +
|
||||
tools/xl/xl_cmdtable.c | 3 ++-
|
||||
tools/xl/xl_migrate.c | 10 +++++++++-
|
||||
7 files changed, 19 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/docs/man/xl.1.pod.in
|
||||
+++ b/docs/man/xl.1.pod.in
|
||||
@@ -501,6 +501,10 @@ such that it will be identical on the de
|
||||
configuration is overridden using the B<-C> option. Note that it is not
|
||||
possible to use this option for a 'localhost' migration.
|
||||
|
||||
+=item B<--max_iters> I<iterations>
|
||||
+
|
||||
+Number of copy iterations before final suspend+move (default: 5)
|
||||
+
|
||||
=back
|
||||
|
||||
=item B<remus> [I<OPTIONS>] I<domain-id> I<host>
|
||||
--- a/tools/include/libxl.h
|
||||
+++ b/tools/include/libxl.h
|
||||
@@ -1819,6 +1819,7 @@ static inline int libxl_retrieve_domain_
|
||||
|
||||
typedef struct {
|
||||
uint32_t flags; /* LIBXL_SUSPEND_* */
|
||||
+ uint32_t max_iters;
|
||||
} libxl_domain_suspend_suse_properties;
|
||||
#define LIBXL_SUSPEND_DEBUG 1
|
||||
#define LIBXL_SUSPEND_LIVE 2
|
||||
--- a/tools/libs/light/libxl_dom_save.c
|
||||
+++ b/tools/libs/light/libxl_dom_save.c
|
||||
@@ -383,7 +383,7 @@ static int libxl__domain_save_precopy_po
|
||||
stats.iteration, stats.dirty_count, stats.total_written);
|
||||
if (stats.dirty_count >= 0 && stats.dirty_count < LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT)
|
||||
goto stop_copy;
|
||||
- if (stats.iteration >= LIBXL_XGS_POLICY_MAX_ITERATIONS)
|
||||
+ if (stats.iteration >= dss->max_iters)
|
||||
goto stop_copy;
|
||||
return XGS_POLICY_CONTINUE_PRECOPY;
|
||||
|
||||
--- a/tools/libs/light/libxl_domain.c
|
||||
+++ b/tools/libs/light/libxl_domain.c
|
||||
@@ -524,6 +524,7 @@ static int do_libxl_domain_suspend(libxl
|
||||
dss->domid = domid;
|
||||
dss->fd = fd;
|
||||
dss->type = type;
|
||||
+ dss->max_iters = props->max_iters ?: LIBXL_XGS_POLICY_MAX_ITERATIONS;
|
||||
dss->live = props->flags & LIBXL_SUSPEND_LIVE;
|
||||
dss->debug = props->flags & LIBXL_SUSPEND_DEBUG;
|
||||
dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE;
|
||||
--- a/tools/libs/light/libxl_internal.h
|
||||
+++ b/tools/libs/light/libxl_internal.h
|
||||
@@ -3656,6 +3656,7 @@ struct libxl__domain_save_state {
|
||||
int live;
|
||||
int debug;
|
||||
int checkpointed_stream;
|
||||
+ uint32_t max_iters;
|
||||
const libxl_domain_remus_info *remus;
|
||||
/* private */
|
||||
int rc;
|
||||
--- a/tools/xl/xl_cmdtable.c
|
||||
+++ b/tools/xl/xl_cmdtable.c
|
||||
@@ -175,7 +175,8 @@ const struct cmd_spec cmd_table[] = {
|
||||
" of the domain.\n"
|
||||
"--debug Enable verification mode.\n"
|
||||
"-p Do not unpause domain after migrating it.\n"
|
||||
- "-D Preserve the domain id"
|
||||
+ "-D Preserve the domain id\n"
|
||||
+ "--max_iters N Number of copy iterations before final stop+move"
|
||||
},
|
||||
{ "restore",
|
||||
&main_restore, 0, 1,
|
||||
--- a/tools/xl/xl_migrate.c
|
||||
+++ b/tools/xl/xl_migrate.c
|
||||
@@ -178,6 +178,7 @@ static void migrate_do_preamble(int send
|
||||
|
||||
static void migrate_domain(uint32_t domid, int preserve_domid,
|
||||
const char *rune, int debug,
|
||||
+ uint32_t max_iters,
|
||||
const char *override_config_file)
|
||||
{
|
||||
pid_t child = -1;
|
||||
@@ -189,6 +190,7 @@ static void migrate_domain(uint32_t domi
|
||||
int config_len;
|
||||
libxl_domain_suspend_suse_properties props = {
|
||||
.flags = LIBXL_SUSPEND_LIVE,
|
||||
+ .max_iters = max_iters,
|
||||
};
|
||||
|
||||
save_domain_core_begin(domid, preserve_domid, override_config_file,
|
||||
@@ -542,8 +544,10 @@ int main_migrate(int argc, char **argv)
|
||||
char *host;
|
||||
int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
|
||||
int preserve_domid = 0;
|
||||
+ uint32_t max_iters = 0;
|
||||
static struct option opts[] = {
|
||||
{"debug", 0, 0, 0x100},
|
||||
+ {"max_iters", 1, 0, 0x101},
|
||||
{"live", 0, 0, 0x200},
|
||||
COMMON_LONG_OPTS
|
||||
};
|
||||
@@ -571,6 +575,9 @@ int main_migrate(int argc, char **argv)
|
||||
case 0x100: /* --debug */
|
||||
debug = 1;
|
||||
break;
|
||||
+ case 0x101: /* --max_iters */
|
||||
+ max_iters = atoi(optarg);
|
||||
+ break;
|
||||
case 0x200: /* --live */
|
||||
/* ignored for compatibility with xm */
|
||||
break;
|
||||
@@ -605,7 +612,8 @@ int main_migrate(int argc, char **argv)
|
||||
pause_after_migration ? " -p" : "");
|
||||
}
|
||||
|
||||
- migrate_domain(domid, preserve_domid, rune, debug, config_filename);
|
||||
+ migrate_domain(domid, preserve_domid, rune, debug,
|
||||
+ max_iters, config_filename);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -1,173 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Thu, 7 Jan 2021 19:39:28 +0100
|
||||
Subject: libxc sr min_remaining
|
||||
|
||||
tools: add --min_remaining to libxl_domain_suspend
|
||||
|
||||
The decision to stop+move a domU to the new host must be based on two factors:
|
||||
- the available network bandwidth for the migration stream
|
||||
- the maximum time a workload within a domU can be savely suspended
|
||||
|
||||
Both values define how many dirty pages a workload may produce prior the
|
||||
final stop+move.
|
||||
|
||||
The default value of 50 pages is much too low with todays network bandwidths.
|
||||
On an idle 1GiB link these 200K will be transferred within ~2ms.
|
||||
|
||||
Give the admin a knob to adjust the point when the final stop+move will
|
||||
be done, so he can base this decision on his own needs.
|
||||
|
||||
This patch adjusts xl(1) and the libxl API.
|
||||
External users check LIBXL_HAVE_DOMAIN_SUSPEND_PROPS for the availibility
|
||||
of the new .min_remaining property.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
docs/man/xl.1.pod.in | 8 ++++++++
|
||||
tools/include/libxl.h | 1 +
|
||||
tools/libs/light/libxl_dom_save.c | 2 +-
|
||||
tools/libs/light/libxl_domain.c | 1 +
|
||||
tools/libs/light/libxl_internal.h | 1 +
|
||||
tools/xl/xl_cmdtable.c | 23 ++++++++++++-----------
|
||||
tools/xl/xl_migrate.c | 9 ++++++++-
|
||||
7 files changed, 32 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/docs/man/xl.1.pod.in
|
||||
+++ b/docs/man/xl.1.pod.in
|
||||
@@ -505,6 +505,14 @@ possible to use this option for a 'local
|
||||
|
||||
Number of copy iterations before final suspend+move (default: 5)
|
||||
|
||||
+=item B<--min_remaing> I<pages>
|
||||
+
|
||||
+Number of remaining dirty pages. If the number of dirty pages drops that
|
||||
+low, the guest is suspended and the domU will finally be moved to I<host>.
|
||||
+
|
||||
+This allows the host admin to control for how long the domU will likely
|
||||
+be suspended during transit.
|
||||
+
|
||||
=back
|
||||
|
||||
=item B<remus> [I<OPTIONS>] I<domain-id> I<host>
|
||||
--- a/tools/include/libxl.h
|
||||
+++ b/tools/include/libxl.h
|
||||
@@ -1820,6 +1820,7 @@ static inline int libxl_retrieve_domain_
|
||||
typedef struct {
|
||||
uint32_t flags; /* LIBXL_SUSPEND_* */
|
||||
uint32_t max_iters;
|
||||
+ uint32_t min_remaining;
|
||||
} libxl_domain_suspend_suse_properties;
|
||||
#define LIBXL_SUSPEND_DEBUG 1
|
||||
#define LIBXL_SUSPEND_LIVE 2
|
||||
--- a/tools/libs/light/libxl_dom_save.c
|
||||
+++ b/tools/libs/light/libxl_dom_save.c
|
||||
@@ -381,7 +381,7 @@ static int libxl__domain_save_precopy_po
|
||||
|
||||
LOGD(DEBUG, shs->domid, "iteration %u dirty_count %ld total_written %lu",
|
||||
stats.iteration, stats.dirty_count, stats.total_written);
|
||||
- if (stats.dirty_count >= 0 && stats.dirty_count < LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT)
|
||||
+ if (stats.dirty_count >= 0 && stats.dirty_count < dss->min_remaining)
|
||||
goto stop_copy;
|
||||
if (stats.iteration >= dss->max_iters)
|
||||
goto stop_copy;
|
||||
--- a/tools/libs/light/libxl_domain.c
|
||||
+++ b/tools/libs/light/libxl_domain.c
|
||||
@@ -525,6 +525,7 @@ static int do_libxl_domain_suspend(libxl
|
||||
dss->fd = fd;
|
||||
dss->type = type;
|
||||
dss->max_iters = props->max_iters ?: LIBXL_XGS_POLICY_MAX_ITERATIONS;
|
||||
+ dss->min_remaining = props->min_remaining ?: LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT;
|
||||
dss->live = props->flags & LIBXL_SUSPEND_LIVE;
|
||||
dss->debug = props->flags & LIBXL_SUSPEND_DEBUG;
|
||||
dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE;
|
||||
--- a/tools/libs/light/libxl_internal.h
|
||||
+++ b/tools/libs/light/libxl_internal.h
|
||||
@@ -3657,6 +3657,7 @@ struct libxl__domain_save_state {
|
||||
int debug;
|
||||
int checkpointed_stream;
|
||||
uint32_t max_iters;
|
||||
+ uint32_t min_remaining;
|
||||
const libxl_domain_remus_info *remus;
|
||||
/* private */
|
||||
int rc;
|
||||
--- a/tools/xl/xl_cmdtable.c
|
||||
+++ b/tools/xl/xl_cmdtable.c
|
||||
@@ -166,17 +166,18 @@ const struct cmd_spec cmd_table[] = {
|
||||
&main_migrate, 0, 1,
|
||||
"Migrate a domain to another host",
|
||||
"[options] <Domain> <host>",
|
||||
- "-h Print this help.\n"
|
||||
- "-C <config> Send <config> instead of config file from creation.\n"
|
||||
- "-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
|
||||
- " to sh. If empty, run <host> instead of ssh <host> xl\n"
|
||||
- " migrate-receive [-d -e]\n"
|
||||
- "-e Do not wait in the background (on <host>) for the death\n"
|
||||
- " of the domain.\n"
|
||||
- "--debug Enable verification mode.\n"
|
||||
- "-p Do not unpause domain after migrating it.\n"
|
||||
- "-D Preserve the domain id\n"
|
||||
- "--max_iters N Number of copy iterations before final stop+move"
|
||||
+ "-h Print this help.\n"
|
||||
+ "-C <config> Send <config> instead of config file from creation.\n"
|
||||
+ "-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
|
||||
+ " to sh. If empty, run <host> instead of ssh <host> xl\n"
|
||||
+ " migrate-receive [-d -e]\n"
|
||||
+ "-e Do not wait in the background (on <host>) for the death\n"
|
||||
+ " of the domain.\n"
|
||||
+ "--debug Enable verification mode.\n"
|
||||
+ "-p Do not unpause domain after migrating it.\n"
|
||||
+ "-D Preserve the domain id\n"
|
||||
+ "--max_iters N Number of copy iterations before final stop+move\n"
|
||||
+ "--min_remaining N Number of remaining dirty pages before final stop+move"
|
||||
},
|
||||
{ "restore",
|
||||
&main_restore, 0, 1,
|
||||
--- a/tools/xl/xl_migrate.c
|
||||
+++ b/tools/xl/xl_migrate.c
|
||||
@@ -179,6 +179,7 @@ static void migrate_do_preamble(int send
|
||||
static void migrate_domain(uint32_t domid, int preserve_domid,
|
||||
const char *rune, int debug,
|
||||
uint32_t max_iters,
|
||||
+ uint32_t min_remaining,
|
||||
const char *override_config_file)
|
||||
{
|
||||
pid_t child = -1;
|
||||
@@ -191,6 +192,7 @@ static void migrate_domain(uint32_t domi
|
||||
libxl_domain_suspend_suse_properties props = {
|
||||
.flags = LIBXL_SUSPEND_LIVE,
|
||||
.max_iters = max_iters,
|
||||
+ .min_remaining = min_remaining,
|
||||
};
|
||||
|
||||
save_domain_core_begin(domid, preserve_domid, override_config_file,
|
||||
@@ -545,9 +547,11 @@ int main_migrate(int argc, char **argv)
|
||||
int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
|
||||
int preserve_domid = 0;
|
||||
uint32_t max_iters = 0;
|
||||
+ uint32_t min_remaining = 0;
|
||||
static struct option opts[] = {
|
||||
{"debug", 0, 0, 0x100},
|
||||
{"max_iters", 1, 0, 0x101},
|
||||
+ {"min_remaining", 1, 0, 0x102},
|
||||
{"live", 0, 0, 0x200},
|
||||
COMMON_LONG_OPTS
|
||||
};
|
||||
@@ -578,6 +582,9 @@ int main_migrate(int argc, char **argv)
|
||||
case 0x101: /* --max_iters */
|
||||
max_iters = atoi(optarg);
|
||||
break;
|
||||
+ case 0x102: /* --min_remaining */
|
||||
+ min_remaining = atoi(optarg);
|
||||
+ break;
|
||||
case 0x200: /* --live */
|
||||
/* ignored for compatibility with xm */
|
||||
break;
|
||||
@@ -613,7 +620,7 @@ int main_migrate(int argc, char **argv)
|
||||
}
|
||||
|
||||
migrate_domain(domid, preserve_domid, rune, debug,
|
||||
- max_iters, config_filename);
|
||||
+ max_iters, min_remaining, config_filename);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -1,24 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Mon, 4 Jan 2021 20:58:42 +0200
|
||||
Subject: libxc sr number of iterations
|
||||
|
||||
Reduce default value of --max_iters from 5 to 1.
|
||||
The workload within domU will continue to produce dirty pages.
|
||||
It is unreasonable to expect any slowdown during migration.
|
||||
Now there is one initial copy of all memory, one instead of five
|
||||
iterations for dirty memory, and a final copy iteration prior move.
|
||||
---
|
||||
tools/libs/light/libxl_internal.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/tools/libs/light/libxl_internal.h
|
||||
+++ b/tools/libs/light/libxl_internal.h
|
||||
@@ -124,7 +124,7 @@
|
||||
#define DOMID_XS_PATH "domid"
|
||||
#define PVSHIM_BASENAME "xen-shim"
|
||||
#define PVSHIM_CMDLINE "pv-shim console=xen,pv"
|
||||
-#define LIBXL_XGS_POLICY_MAX_ITERATIONS 5
|
||||
+#define LIBXL_XGS_POLICY_MAX_ITERATIONS 1
|
||||
#define LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT 50
|
||||
|
||||
/* Size macros. */
|
@@ -1,90 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 8 Jan 2021 18:19:49 +0100
|
||||
Subject: libxc sr precopy_policy
|
||||
|
||||
tools: add callback to libxl for precopy_policy and precopy_stats
|
||||
|
||||
This duplicates simple_precopy_policy. To recap its purpose:
|
||||
- do up to 5 iterations of copying dirty domU memory to target,
|
||||
including the initial copying of all domU memory, excluding
|
||||
the final copying while the domU is suspended
|
||||
- do fewer iterations in case the domU dirtied less than 50 pages
|
||||
|
||||
Take the opportunity to also move xen_pfn_t into qw().
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
|
||||
v02:
|
||||
- use plain struct precopy_stats instead of inventing
|
||||
a new precopy_stats_t (anthony)
|
||||
---
|
||||
tools/libs/light/libxl_dom_save.c | 19 +++++++++++++++++++
|
||||
tools/libs/light/libxl_internal.h | 2 ++
|
||||
tools/libs/light/libxl_save_msgs_gen.pl | 3 ++-
|
||||
3 files changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/tools/libs/light/libxl_dom_save.c
|
||||
+++ b/tools/libs/light/libxl_dom_save.c
|
||||
@@ -373,6 +373,24 @@ int libxl__save_emulator_xenstore_data(l
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int libxl__domain_save_precopy_policy(struct precopy_stats stats, void *user)
|
||||
+{
|
||||
+ libxl__save_helper_state *shs = user;
|
||||
+ libxl__domain_save_state *dss = shs->caller_state;
|
||||
+ STATE_AO_GC(dss->ao);
|
||||
+
|
||||
+ LOGD(DEBUG, shs->domid, "iteration %u dirty_count %ld total_written %lu",
|
||||
+ stats.iteration, stats.dirty_count, stats.total_written);
|
||||
+ if (stats.dirty_count >= 0 && stats.dirty_count < LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT)
|
||||
+ goto stop_copy;
|
||||
+ if (stats.iteration >= LIBXL_XGS_POLICY_MAX_ITERATIONS)
|
||||
+ goto stop_copy;
|
||||
+ return XGS_POLICY_CONTINUE_PRECOPY;
|
||||
+
|
||||
+stop_copy:
|
||||
+ return XGS_POLICY_STOP_AND_COPY;
|
||||
+}
|
||||
+
|
||||
/*----- main code for saving, in order of execution -----*/
|
||||
|
||||
void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
|
||||
@@ -430,6 +448,7 @@ void libxl__domain_save(libxl__egc *egc,
|
||||
callbacks->suspend = libxl__domain_suspend_callback;
|
||||
|
||||
callbacks->switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty;
|
||||
+ callbacks->precopy_policy = libxl__domain_save_precopy_policy;
|
||||
|
||||
dss->sws.ao = dss->ao;
|
||||
dss->sws.dss = dss;
|
||||
--- a/tools/libs/light/libxl_internal.h
|
||||
+++ b/tools/libs/light/libxl_internal.h
|
||||
@@ -124,6 +124,8 @@
|
||||
#define DOMID_XS_PATH "domid"
|
||||
#define PVSHIM_BASENAME "xen-shim"
|
||||
#define PVSHIM_CMDLINE "pv-shim console=xen,pv"
|
||||
+#define LIBXL_XGS_POLICY_MAX_ITERATIONS 5
|
||||
+#define LIBXL_XGS_POLICY_TARGET_DIRTY_COUNT 50
|
||||
|
||||
/* Size macros. */
|
||||
#define MB(_mb) (_AC(_mb, ULL) << 20)
|
||||
--- a/tools/libs/light/libxl_save_msgs_gen.pl
|
||||
+++ b/tools/libs/light/libxl_save_msgs_gen.pl
|
||||
@@ -23,6 +23,7 @@ our @msgs = (
|
||||
STRING doing_what),
|
||||
'unsigned long', 'done',
|
||||
'unsigned long', 'total'] ],
|
||||
+ [ 'scxW', "precopy_policy", ['struct precopy_stats', 'stats'] ],
|
||||
[ 'srcxA', "suspend", [] ],
|
||||
[ 'srcxA', "postcopy", [] ],
|
||||
[ 'srcxA', "checkpoint", [] ],
|
||||
@@ -142,7 +143,7 @@ static void bytes_put(unsigned char *con
|
||||
|
||||
END
|
||||
|
||||
-foreach my $simpletype (qw(int uint16_t uint32_t unsigned), 'unsigned long', 'xen_pfn_t') {
|
||||
+foreach my $simpletype (qw(int uint16_t uint32_t unsigned xen_pfn_t), 'struct precopy_stats', 'unsigned long') {
|
||||
my $typeid = typeid($simpletype);
|
||||
$out_body{'callout'} .= <<END;
|
||||
static int ${typeid}_get(const unsigned char **msg,
|
@@ -1,103 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Wed, 28 Oct 2020 12:07:36 +0100
|
||||
Subject: libxc sr readv_exact
|
||||
|
||||
tools: add readv_exact to libxenctrl
|
||||
|
||||
Read a batch of iovec's.
|
||||
|
||||
Short reads are the common case, finish the trailing iov with read_exact.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
|
||||
v2:
|
||||
- add comment to short-read handling
|
||||
---
|
||||
tools/libs/ctrl/xc_private.c | 57 +++++++++++++++++++++++++++++++++++-
|
||||
tools/libs/ctrl/xc_private.h | 1 +
|
||||
2 files changed, 57 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/tools/libs/ctrl/xc_private.c
|
||||
+++ b/tools/libs/ctrl/xc_private.c
|
||||
@@ -699,8 +699,23 @@ int write_exact(int fd, const void *data
|
||||
|
||||
#if defined(__MINIOS__)
|
||||
/*
|
||||
- * MiniOS's libc doesn't know about writev(). Implement it as multiple write()s.
|
||||
+ * MiniOS's libc doesn't know about readv/writev().
|
||||
+ * Implement it as multiple read/write()s.
|
||||
*/
|
||||
+int readv_exact(int fd, const struct iovec *iov, int iovcnt)
|
||||
+{
|
||||
+ int rc, i;
|
||||
+
|
||||
+ for ( i = 0; i < iovcnt; ++i )
|
||||
+ {
|
||||
+ rc = read_exact(fd, iov[i].iov_base, iov[i].iov_len);
|
||||
+ if ( rc )
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int writev_exact(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
int rc, i;
|
||||
@@ -715,6 +730,46 @@ int writev_exact(int fd, const struct io
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
+int readv_exact(int fd, const struct iovec *iov, int iovcnt)
|
||||
+{
|
||||
+ int rc = 0, idx = 0;
|
||||
+ ssize_t len;
|
||||
+
|
||||
+ while ( idx < iovcnt )
|
||||
+ {
|
||||
+ len = readv(fd, &iov[idx], min(iovcnt - idx, IOV_MAX));
|
||||
+ if ( len == -1 && errno == EINTR )
|
||||
+ continue;
|
||||
+ if ( len <= 0 )
|
||||
+ {
|
||||
+ rc = -1;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* Finish a potential short read in the last iov */
|
||||
+ while ( len > 0 && idx < iovcnt )
|
||||
+ {
|
||||
+ if ( len >= iov[idx].iov_len )
|
||||
+ {
|
||||
+ len -= iov[idx].iov_len;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ void *p = iov[idx].iov_base + len;
|
||||
+ size_t l = iov[idx].iov_len - len;
|
||||
+
|
||||
+ rc = read_exact(fd, p, l);
|
||||
+ if ( rc )
|
||||
+ goto out;
|
||||
+ len = 0;
|
||||
+ }
|
||||
+ idx++;
|
||||
+ }
|
||||
+ }
|
||||
+out:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
int writev_exact(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
struct iovec *local_iov = NULL;
|
||||
--- a/tools/libs/ctrl/xc_private.h
|
||||
+++ b/tools/libs/ctrl/xc_private.h
|
||||
@@ -395,6 +395,7 @@ int xc_flush_mmu_updates(xc_interface *x
|
||||
|
||||
/* Return 0 on success; -1 on error setting errno. */
|
||||
int read_exact(int fd, void *data, size_t size); /* EOF => -1, errno=0 */
|
||||
+int readv_exact(int fd, const struct iovec *iov, int iovcnt);
|
||||
int write_exact(int fd, const void *data, size_t size);
|
||||
int writev_exact(int fd, const struct iovec *iov, int iovcnt);
|
||||
|
@@ -1,435 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Tue, 27 Oct 2020 19:21:50 +0100
|
||||
Subject: libxc sr restore handle_buffered_page_data
|
||||
|
||||
tools: restore: split handle_page_data
|
||||
|
||||
handle_page_data must be able to read directly into mapped guest memory.
|
||||
This will avoid unneccesary memcpy calls for data that can be consumed verbatim.
|
||||
|
||||
Split the various steps of record processing:
|
||||
- move processing to handle_buffered_page_data
|
||||
- adjust xenforeignmemory_map to set errno in case of failure
|
||||
- adjust verify mode to set errno in case of failure
|
||||
|
||||
This change is preparation for future changes in handle_page_data,
|
||||
no change in behavior is intended.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 4 +
|
||||
tools/libs/guest/xg_sr_restore.c | 320 ++++++++++++++++++++-----------
|
||||
2 files changed, 207 insertions(+), 117 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -262,6 +262,10 @@ struct xc_sr_context
|
||||
int *map_errs;
|
||||
xen_pfn_t *pp_pfns;
|
||||
xen_pfn_t *pp_mfns;
|
||||
+ void **guest_data;
|
||||
+
|
||||
+ void *guest_mapping;
|
||||
+ uint32_t nr_mapped_pages;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -183,121 +183,18 @@ int populate_pfns(struct xc_sr_context *
|
||||
return rc;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Given a list of pfns, their types, and a block of page data from the
|
||||
- * stream, populate and record their types, map the relevant subset and copy
|
||||
- * the data into the guest.
|
||||
- */
|
||||
-static int process_page_data(struct xc_sr_context *ctx, unsigned int count,
|
||||
- xen_pfn_t *pfns, uint32_t *types, void *page_data)
|
||||
+static int handle_static_data_end_v2(struct xc_sr_context *ctx)
|
||||
{
|
||||
- xc_interface *xch = ctx->xch;
|
||||
- int rc;
|
||||
- void *mapping = NULL, *guest_page = NULL;
|
||||
- unsigned int i, /* i indexes the pfns from the record. */
|
||||
- j, /* j indexes the subset of pfns we decide to map. */
|
||||
- nr_pages = 0;
|
||||
-
|
||||
- rc = populate_pfns(ctx, count, pfns, types);
|
||||
- if ( rc )
|
||||
- {
|
||||
- ERROR("Failed to populate pfns for batch of %u pages", count);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- for ( i = 0; i < count; ++i )
|
||||
- {
|
||||
- ctx->restore.ops.set_page_type(ctx, pfns[i], types[i]);
|
||||
-
|
||||
- if ( page_type_has_stream_data(types[i]) )
|
||||
- ctx->restore.mfns[nr_pages++] = ctx->restore.ops.pfn_to_gfn(ctx, pfns[i]);
|
||||
- }
|
||||
-
|
||||
- /* Nothing to do? */
|
||||
- if ( nr_pages == 0 )
|
||||
- goto done;
|
||||
-
|
||||
- mapping = guest_page = xenforeignmemory_map(
|
||||
- xch->fmem, ctx->domid, PROT_READ | PROT_WRITE,
|
||||
- nr_pages, ctx->restore.mfns, ctx->restore.map_errs);
|
||||
- if ( !mapping )
|
||||
- {
|
||||
- rc = -1;
|
||||
- PERROR("Unable to map %u mfns for %u pages of data",
|
||||
- nr_pages, count);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- for ( i = 0, j = 0; i < count; ++i )
|
||||
- {
|
||||
- if ( !page_type_has_stream_data(types[i]) )
|
||||
- continue;
|
||||
-
|
||||
- if ( ctx->restore.map_errs[j] )
|
||||
- {
|
||||
- rc = -1;
|
||||
- ERROR("Mapping pfn %#"PRIpfn" (mfn %#"PRIpfn", type %#"PRIx32") failed with %d",
|
||||
- pfns[i], ctx->restore.mfns[j], types[i], ctx->restore.map_errs[j]);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- /* Undo page normalisation done by the saver. */
|
||||
- rc = ctx->restore.ops.localise_page(ctx, types[i], page_data);
|
||||
- if ( rc )
|
||||
- {
|
||||
- ERROR("Failed to localise pfn %#"PRIpfn" (type %#"PRIx32")",
|
||||
- pfns[i], types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- if ( ctx->restore.verify )
|
||||
- {
|
||||
- /* Verify mode - compare incoming data to what we already have. */
|
||||
- if ( memcmp(guest_page, page_data, PAGE_SIZE) )
|
||||
- ERROR("verify pfn %#"PRIpfn" failed (type %#"PRIx32")",
|
||||
- pfns[i], types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Regular mode - copy incoming data into place. */
|
||||
- memcpy(guest_page, page_data, PAGE_SIZE);
|
||||
- }
|
||||
-
|
||||
- ++j;
|
||||
- guest_page += PAGE_SIZE;
|
||||
- page_data += PAGE_SIZE;
|
||||
- }
|
||||
-
|
||||
- done:
|
||||
- rc = 0;
|
||||
-
|
||||
- err:
|
||||
- if ( mapping )
|
||||
- xenforeignmemory_unmap(xch->fmem, mapping, nr_pages);
|
||||
-
|
||||
- return rc;
|
||||
-}
|
||||
+ int rc = 0;
|
||||
|
||||
-/*
|
||||
- * Validate a PAGE_DATA record from the stream, and pass the results to
|
||||
- * process_page_data() to actually perform the legwork.
|
||||
- */
|
||||
-static int handle_page_data(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
-{
|
||||
+#if defined(__i386__) || defined(__x86_64__)
|
||||
xc_interface *xch = ctx->xch;
|
||||
- struct xc_sr_rec_page_data_header *pages = rec->data;
|
||||
- unsigned int i, pages_of_data = 0;
|
||||
- int rc = -1;
|
||||
-
|
||||
- xen_pfn_t pfn;
|
||||
- uint32_t type;
|
||||
-
|
||||
/*
|
||||
* v2 compatibility only exists for x86 streams. This is a bit of a
|
||||
* bodge, but it is less bad than duplicating handle_page_data() between
|
||||
* different architectures.
|
||||
*/
|
||||
-#if defined(__i386__) || defined(__x86_64__)
|
||||
+
|
||||
/* v2 compat. Infer the position of STATIC_DATA_END. */
|
||||
if ( ctx->restore.format_version < 3 && !ctx->restore.seen_static_data_end )
|
||||
{
|
||||
@@ -315,12 +212,26 @@ static int handle_page_data(struct xc_sr
|
||||
ERROR("No STATIC_DATA_END seen");
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ rc = 0;
|
||||
+err:
|
||||
#endif
|
||||
|
||||
- if ( rec->length < sizeof(*pages) )
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static bool verify_rec_page_hdr(struct xc_sr_context *ctx, uint32_t rec_length,
|
||||
+ struct xc_sr_rec_page_data_header *pages)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ bool ret = false;
|
||||
+
|
||||
+ errno = EINVAL;
|
||||
+
|
||||
+ if ( rec_length < sizeof(*pages) )
|
||||
{
|
||||
ERROR("PAGE_DATA record truncated: length %u, min %zu",
|
||||
- rec->length, sizeof(*pages));
|
||||
+ rec_length, sizeof(*pages));
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -330,13 +241,28 @@ static int handle_page_data(struct xc_sr
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if ( rec->length < sizeof(*pages) + (pages->count * sizeof(uint64_t)) )
|
||||
+ if ( rec_length < sizeof(*pages) + (pages->count * sizeof(uint64_t)) )
|
||||
{
|
||||
ERROR("PAGE_DATA record (length %u) too short to contain %u"
|
||||
- " pfns worth of information", rec->length, pages->count);
|
||||
+ " pfns worth of information", rec_length, pages->count);
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ ret = true;
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static bool verify_rec_page_pfns(struct xc_sr_context *ctx, uint32_t rec_length,
|
||||
+ struct xc_sr_rec_page_data_header *pages)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ uint32_t i, pages_of_data = 0;
|
||||
+ xen_pfn_t pfn;
|
||||
+ uint32_t type;
|
||||
+ bool ret = false;
|
||||
+
|
||||
for ( i = 0; i < pages->count; ++i )
|
||||
{
|
||||
pfn = pages->pfn[i] & PAGE_DATA_PFN_MASK;
|
||||
@@ -363,19 +289,177 @@ static int handle_page_data(struct xc_sr
|
||||
ctx->restore.types[i] = type;
|
||||
}
|
||||
|
||||
- if ( rec->length != (sizeof(*pages) +
|
||||
+ if ( rec_length != (sizeof(*pages) +
|
||||
(sizeof(uint64_t) * pages->count) +
|
||||
(PAGE_SIZE * pages_of_data)) )
|
||||
{
|
||||
ERROR("PAGE_DATA record wrong size: length %u, expected "
|
||||
- "%zu + %zu + %lu", rec->length, sizeof(*pages),
|
||||
+ "%zu + %zu + %lu", rec_length, sizeof(*pages),
|
||||
(sizeof(uint64_t) * pages->count), (PAGE_SIZE * pages_of_data));
|
||||
goto err;
|
||||
}
|
||||
|
||||
- rc = process_page_data(ctx, pages->count, ctx->restore.pfns,
|
||||
- ctx->restore.types, &pages->pfn[pages->count]);
|
||||
+ ret = true;
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Populate pfns, if required
|
||||
+ * Fill guest_data with either mapped address or NULL
|
||||
+ * The caller must unmap guest_mapping
|
||||
+ */
|
||||
+static int map_guest_pages(struct xc_sr_context *ctx,
|
||||
+ struct xc_sr_rec_page_data_header *pages)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ uint32_t i, p;
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = populate_pfns(ctx, pages->count, ctx->restore.pfns, ctx->restore.types);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ ERROR("Failed to populate pfns for batch of %u pages", pages->count);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ctx->restore.nr_mapped_pages = 0;
|
||||
+
|
||||
+ for ( i = 0; i < pages->count; i++ )
|
||||
+ {
|
||||
+ ctx->restore.ops.set_page_type(ctx, ctx->restore.pfns[i], ctx->restore.types[i]);
|
||||
+
|
||||
+ if ( page_type_has_stream_data(ctx->restore.types[i]) == false )
|
||||
+ {
|
||||
+ ctx->restore.guest_data[i] = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ctx->restore.mfns[ctx->restore.nr_mapped_pages++] = ctx->restore.ops.pfn_to_gfn(ctx, ctx->restore.pfns[i]);
|
||||
+ }
|
||||
+
|
||||
+ /* Nothing to do? */
|
||||
+ if ( ctx->restore.nr_mapped_pages == 0 )
|
||||
+ goto done;
|
||||
+
|
||||
+ ctx->restore.guest_mapping = xenforeignmemory_map(xch->fmem, ctx->domid,
|
||||
+ PROT_READ | PROT_WRITE, ctx->restore.nr_mapped_pages,
|
||||
+ ctx->restore.mfns, ctx->restore.map_errs);
|
||||
+ if ( !ctx->restore.guest_mapping )
|
||||
+ {
|
||||
+ rc = -1;
|
||||
+ PERROR("Unable to map %u mfns for %u pages of data",
|
||||
+ ctx->restore.nr_mapped_pages, pages->count);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify mapping, and assign address to pfn data */
|
||||
+ for ( i = 0, p = 0; i < pages->count; i++ )
|
||||
+ {
|
||||
+ if ( !page_type_has_stream_data(ctx->restore.types[i]) )
|
||||
+ continue;
|
||||
+
|
||||
+ if ( ctx->restore.map_errs[p] == 0 )
|
||||
+ {
|
||||
+ ctx->restore.guest_data[i] = ctx->restore.guest_mapping + (p * PAGE_SIZE);
|
||||
+ p++;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ errno = ctx->restore.map_errs[p];
|
||||
+ rc = -1;
|
||||
+ PERROR("Mapping pfn %#"PRIpfn" (mfn %#"PRIpfn", type %#"PRIx32") failed",
|
||||
+ ctx->restore.pfns[i], ctx->restore.mfns[p], ctx->restore.types[i]);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+ rc = 0;
|
||||
+
|
||||
+err:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Handle PAGE_DATA record from an existing buffer
|
||||
+ * Given a list of pfns, their types, and a block of page data from the
|
||||
+ * stream, populate and record their types, map the relevant subset and copy
|
||||
+ * the data into the guest.
|
||||
+ */
|
||||
+static int handle_buffered_page_data(struct xc_sr_context *ctx,
|
||||
+ struct xc_sr_record *rec)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ struct xc_sr_rec_page_data_header *pages = rec->data;
|
||||
+ void *p;
|
||||
+ uint32_t i;
|
||||
+ int rc = -1, idx;
|
||||
+
|
||||
+ rc = handle_static_data_end_v2(ctx);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+
|
||||
+ /* First read and verify the header */
|
||||
+ if ( !verify_rec_page_hdr(ctx, rec->length, pages) )
|
||||
+ {
|
||||
+ rc = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Then read and verify the pfn numbers */
|
||||
+ if ( !verify_rec_page_pfns(ctx, rec->length, pages) )
|
||||
+ {
|
||||
+ rc = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Map the target pfn */
|
||||
+ rc = map_guest_pages(ctx, pages);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+
|
||||
+ for ( i = 0, idx = 0; i < pages->count; i++ )
|
||||
+ {
|
||||
+ if ( !ctx->restore.guest_data[i] )
|
||||
+ continue;
|
||||
+
|
||||
+ p = &pages->pfn[pages->count] + (idx * PAGE_SIZE);
|
||||
+ rc = ctx->restore.ops.localise_page(ctx, ctx->restore.types[i], p);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ ERROR("Failed to localise pfn %#"PRIpfn" (type %#"PRIx32")",
|
||||
+ ctx->restore.pfns[i], ctx->restore.types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
|
||||
+ goto err;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if ( ctx->restore.verify )
|
||||
+ {
|
||||
+ if ( memcmp(ctx->restore.guest_data[i], p, PAGE_SIZE) )
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ ERROR("verify pfn %#"PRIpfn" failed (type %#"PRIx32")",
|
||||
+ ctx->restore.pfns[i], ctx->restore.types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ memcpy(ctx->restore.guest_data[i], p, PAGE_SIZE);
|
||||
+ }
|
||||
+
|
||||
+ idx++;
|
||||
+ }
|
||||
+
|
||||
+ rc = 0;
|
||||
+
|
||||
err:
|
||||
+ if ( ctx->restore.guest_mapping )
|
||||
+ {
|
||||
+ xenforeignmemory_unmap(xch->fmem, ctx->restore.guest_mapping, ctx->restore.nr_mapped_pages);
|
||||
+ ctx->restore.guest_mapping = NULL;
|
||||
+ }
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -623,7 +707,7 @@ static int process_buffered_record(struc
|
||||
break;
|
||||
|
||||
case REC_TYPE_PAGE_DATA:
|
||||
- rc = handle_page_data(ctx, rec);
|
||||
+ rc = handle_buffered_page_data(ctx, rec);
|
||||
break;
|
||||
|
||||
case REC_TYPE_VERIFY:
|
||||
@@ -703,9 +787,10 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->restore.map_errs = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.map_errs));
|
||||
ctx->restore.pp_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_pfns));
|
||||
ctx->restore.pp_mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_mfns));
|
||||
+ ctx->restore.guest_data = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.guest_data));
|
||||
if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns ||
|
||||
!ctx->restore.map_errs || !ctx->restore.pp_pfns ||
|
||||
- !ctx->restore.pp_mfns )
|
||||
+ !ctx->restore.pp_mfns || !ctx->restore.guest_data )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -742,6 +827,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.guest_data);
|
||||
free(ctx->restore.pp_mfns);
|
||||
free(ctx->restore.pp_pfns);
|
||||
free(ctx->restore.map_errs);
|
@@ -1,230 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Thu, 29 Oct 2020 16:13:10 +0100
|
||||
Subject: libxc sr restore handle_incoming_page_data
|
||||
|
||||
tools: restore: write data directly into guest
|
||||
|
||||
Read incoming migration stream directly into the guest memory.
|
||||
This avoids the memory allocation and copying, and the resulting
|
||||
performance penalty.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 3 +
|
||||
tools/libs/guest/xg_sr_restore.c | 155 ++++++++++++++++++++++++++++++-
|
||||
2 files changed, 153 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -263,6 +263,8 @@ struct xc_sr_context
|
||||
xen_pfn_t *pp_pfns;
|
||||
xen_pfn_t *pp_mfns;
|
||||
void **guest_data;
|
||||
+ struct iovec *iov;
|
||||
+ struct xc_sr_rec_page_data_header *pages;
|
||||
|
||||
void *guest_mapping;
|
||||
uint32_t nr_mapped_pages;
|
||||
@@ -311,6 +313,7 @@ struct xc_sr_context
|
||||
|
||||
/* Sender has invoked verify mode on the stream. */
|
||||
bool verify;
|
||||
+ void *verify_buf;
|
||||
} restore;
|
||||
};
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -382,6 +382,129 @@ err:
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Handle PAGE_DATA record from the stream.
|
||||
+ * Given a list of pfns, their types, and a block of page data from the
|
||||
+ * stream, populate and record their types, map the relevant subset and copy
|
||||
+ * the data into the guest.
|
||||
+ */
|
||||
+static int handle_incoming_page_data(struct xc_sr_context *ctx,
|
||||
+ struct xc_sr_rhdr *rhdr)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ struct xc_sr_rec_page_data_header *pages = ctx->restore.pages;
|
||||
+ uint64_t *pfn_nums = &pages->pfn[0];
|
||||
+ uint32_t i;
|
||||
+ int rc, iov_idx;
|
||||
+
|
||||
+ rc = handle_static_data_end_v2(ctx);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+
|
||||
+ /* First read and verify the header */
|
||||
+ rc = read_exact(ctx->fd, pages, sizeof(*pages));
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ PERROR("Could not read rec_pfn header");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if ( !verify_rec_page_hdr(ctx, rhdr->length, pages) )
|
||||
+ {
|
||||
+ rc = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Then read and verify the incoming pfn numbers */
|
||||
+ rc = read_exact(ctx->fd, pfn_nums, sizeof(*pfn_nums) * pages->count);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ PERROR("Could not read rec_pfn data");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if ( !verify_rec_page_pfns(ctx, rhdr->length, pages) )
|
||||
+ {
|
||||
+ rc = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Finally read and verify the incoming pfn data */
|
||||
+ rc = map_guest_pages(ctx, pages);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+
|
||||
+ /* Prepare read buffers, either guest or throw-away memory */
|
||||
+ for ( i = 0, iov_idx = 0; i < pages->count; i++ )
|
||||
+ {
|
||||
+ struct iovec *iov;
|
||||
+
|
||||
+ if ( !ctx->restore.guest_data[i] )
|
||||
+ continue;
|
||||
+
|
||||
+ iov = &ctx->restore.iov[iov_idx];
|
||||
+ iov->iov_len = PAGE_SIZE;
|
||||
+ if ( ctx->restore.verify )
|
||||
+ iov->iov_base = ctx->restore.verify_buf + (i * PAGE_SIZE);
|
||||
+ else
|
||||
+ iov->iov_base = ctx->restore.guest_data[i];
|
||||
+ iov_idx++;
|
||||
+ }
|
||||
+
|
||||
+ if ( !iov_idx )
|
||||
+ goto done;
|
||||
+
|
||||
+ rc = readv_exact(ctx->fd, ctx->restore.iov, iov_idx);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ PERROR("read of %d pages failed", iov_idx);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Post-processing of pfn data */
|
||||
+ for ( i = 0, iov_idx = 0; i < pages->count; i++ )
|
||||
+ {
|
||||
+ void *addr;
|
||||
+
|
||||
+ if ( !ctx->restore.guest_data[i] )
|
||||
+ continue;
|
||||
+
|
||||
+ addr = ctx->restore.iov[iov_idx].iov_base;
|
||||
+ rc = ctx->restore.ops.localise_page(ctx, ctx->restore.types[i], addr);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ ERROR("Failed to localise pfn %#"PRIpfn" (type %#"PRIx32")",
|
||||
+ ctx->restore.pfns[i],
|
||||
+ ctx->restore.types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
|
||||
+ goto err;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if ( ctx->restore.verify )
|
||||
+ {
|
||||
+ if ( memcmp(ctx->restore.guest_data[i], addr, PAGE_SIZE) )
|
||||
+ {
|
||||
+ ERROR("verify pfn %#"PRIpfn" failed (type %#"PRIx32")",
|
||||
+ ctx->restore.pfns[i],
|
||||
+ ctx->restore.types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ iov_idx++;
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+ rc = 0;
|
||||
+
|
||||
+err:
|
||||
+ if ( ctx->restore.guest_mapping )
|
||||
+ {
|
||||
+ xenforeignmemory_unmap(xch->fmem, ctx->restore.guest_mapping, ctx->restore.nr_mapped_pages);
|
||||
+ ctx->restore.guest_mapping = NULL;
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Handle PAGE_DATA record from an existing buffer
|
||||
* Given a list of pfns, their types, and a block of page data from the
|
||||
* stream, populate and record their types, map the relevant subset and copy
|
||||
@@ -713,6 +836,15 @@ static int process_buffered_record(struc
|
||||
case REC_TYPE_VERIFY:
|
||||
DPRINTF("Verify mode enabled");
|
||||
ctx->restore.verify = true;
|
||||
+ if ( !ctx->restore.verify_buf )
|
||||
+ {
|
||||
+ ctx->restore.verify_buf = malloc(MAX_BATCH_SIZE * PAGE_SIZE);
|
||||
+ if ( !ctx->restore.verify_buf )
|
||||
+ {
|
||||
+ PERROR("Unable to allocate verify_buf");
|
||||
+ rc = -1;
|
||||
+ }
|
||||
+ }
|
||||
break;
|
||||
|
||||
case REC_TYPE_CHECKPOINT:
|
||||
@@ -739,11 +871,19 @@ static int process_incoming_record_heade
|
||||
struct xc_sr_record rec;
|
||||
int rc;
|
||||
|
||||
- rc = read_record_data(ctx, ctx->fd, rhdr, &rec);
|
||||
- if ( rc )
|
||||
- return rc;
|
||||
+ switch ( rhdr->type )
|
||||
+ {
|
||||
+ case REC_TYPE_PAGE_DATA:
|
||||
+ rc = handle_incoming_page_data(ctx, rhdr);
|
||||
+ break;
|
||||
+ default:
|
||||
+ rc = read_record_data(ctx, ctx->fd, rhdr, &rec);
|
||||
+ if ( rc == 0 )
|
||||
+ rc = process_buffered_record(ctx, &rec);;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
- return process_buffered_record(ctx, &rec);
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -788,9 +928,12 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->restore.pp_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_pfns));
|
||||
ctx->restore.pp_mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_mfns));
|
||||
ctx->restore.guest_data = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.guest_data));
|
||||
+ ctx->restore.iov = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.iov));
|
||||
+ ctx->restore.pages = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pages->pfn) + sizeof(*ctx->restore.pages));
|
||||
if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns ||
|
||||
!ctx->restore.map_errs || !ctx->restore.pp_pfns ||
|
||||
- !ctx->restore.pp_mfns || !ctx->restore.guest_data )
|
||||
+ !ctx->restore.pp_mfns || !ctx->restore.guest_data ||
|
||||
+ !ctx->restore.iov || !ctx->restore.pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -827,6 +970,8 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.pages);
|
||||
+ free(ctx->restore.iov);
|
||||
free(ctx->restore.guest_data);
|
||||
free(ctx->restore.pp_mfns);
|
||||
free(ctx->restore.pp_pfns);
|
@@ -1,701 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Mon, 7 Aug 2017 12:58:02 +0000
|
||||
Subject: libxc sr restore hvm legacy superpage
|
||||
|
||||
tools: use superpages during restore of HVM guest
|
||||
|
||||
bsc#1035231 - migration of HVM domU does not use superpages on destination dom0
|
||||
bsc#1055695 - XEN: 11SP4 and 12SP3 HVM guests can not be restored
|
||||
|
||||
During creating of a HVM domU meminit_hvm() tries to map superpages.
|
||||
After save/restore or migration this mapping is lost, everything is
|
||||
allocated in single pages. This causes a performance degradation after
|
||||
migration.
|
||||
|
||||
Add neccessary code to preallocate a superpage for an incoming chunk of
|
||||
pfns. In case a pfn was not populated on the sending side, it must be
|
||||
freed on the receiving side to avoid over-allocation.
|
||||
|
||||
The existing code for x86_pv is moved unmodified into its own file.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_dom_x86.c | 5 -
|
||||
tools/libs/guest/xg_private.h | 5 +
|
||||
tools/libs/guest/xg_sr_common.h | 28 +-
|
||||
tools/libs/guest/xg_sr_restore.c | 60 +---
|
||||
tools/libs/guest/xg_sr_restore_x86_hvm.c | 381 ++++++++++++++++++++++-
|
||||
tools/libs/guest/xg_sr_restore_x86_pv.c | 61 +++-
|
||||
6 files changed, 467 insertions(+), 73 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_dom_x86.c
|
||||
+++ b/tools/libs/guest/xg_dom_x86.c
|
||||
@@ -44,11 +44,6 @@
|
||||
|
||||
#define SUPERPAGE_BATCH_SIZE 512
|
||||
|
||||
-#define SUPERPAGE_2MB_SHIFT 9
|
||||
-#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT)
|
||||
-#define SUPERPAGE_1GB_SHIFT 18
|
||||
-#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT)
|
||||
-
|
||||
#define X86_CR0_PE 0x01
|
||||
#define X86_CR0_ET 0x10
|
||||
|
||||
--- a/tools/libs/guest/xg_private.h
|
||||
+++ b/tools/libs/guest/xg_private.h
|
||||
@@ -180,4 +180,9 @@ struct xc_cpu_policy {
|
||||
};
|
||||
#endif /* x86 */
|
||||
|
||||
+#define SUPERPAGE_2MB_SHIFT 9
|
||||
+#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT)
|
||||
+#define SUPERPAGE_1GB_SHIFT 18
|
||||
+#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT)
|
||||
+
|
||||
#endif /* XG_PRIVATE_H */
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -208,6 +208,16 @@ struct xc_sr_restore_ops
|
||||
int (*setup)(struct xc_sr_context *ctx);
|
||||
|
||||
/**
|
||||
+ * Populate PFNs
|
||||
+ *
|
||||
+ * Given a set of pfns, obtain memory from Xen to fill the physmap for the
|
||||
+ * unpopulated subset.
|
||||
+ */
|
||||
+ int (*populate_pfns)(struct xc_sr_context *ctx, unsigned count,
|
||||
+ const xen_pfn_t *original_pfns, const uint32_t *types);
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
* Process an individual record from the stream. The caller shall take
|
||||
* care of processing common records (e.g. END, PAGE_DATA).
|
||||
*
|
||||
@@ -338,6 +348,8 @@ struct xc_sr_context
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
+ unsigned long max_pages;
|
||||
+ unsigned long tot_pages;
|
||||
xc_hypercall_buffer_t dirty_bitmap_hbuf;
|
||||
|
||||
/* From Image Header. */
|
||||
@@ -471,6 +483,14 @@ struct xc_sr_context
|
||||
{
|
||||
/* HVM context blob. */
|
||||
struct xc_sr_blob context;
|
||||
+
|
||||
+ /* Bitmap of currently allocated PFNs during restore. */
|
||||
+ struct sr_bitmap attempted_1g;
|
||||
+ struct sr_bitmap attempted_2m;
|
||||
+ struct sr_bitmap allocated_pfns;
|
||||
+ xen_pfn_t prev_populated_pfn;
|
||||
+ xen_pfn_t iteration_tracker_pfn;
|
||||
+ unsigned long iteration;
|
||||
} restore;
|
||||
};
|
||||
} hvm;
|
||||
@@ -535,14 +555,6 @@ int read_record_header(struct xc_sr_cont
|
||||
int read_record_data(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr,
|
||||
struct xc_sr_record *rec);
|
||||
|
||||
-/*
|
||||
- * This would ideally be private in restore.c, but is needed by
|
||||
- * x86_pv_localise_page() if we receive pagetables frames ahead of the
|
||||
- * contents of the frames they point at.
|
||||
- */
|
||||
-int populate_pfns(struct xc_sr_context *ctx, unsigned int count,
|
||||
- const xen_pfn_t *original_pfns, const uint32_t *types);
|
||||
-
|
||||
/* Handle a STATIC_DATA_END record. */
|
||||
int handle_static_data_end(struct xc_sr_context *ctx);
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -71,60 +71,6 @@ static int read_headers(struct xc_sr_con
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Given a set of pfns, obtain memory from Xen to fill the physmap for the
|
||||
- * unpopulated subset. If types is NULL, no page type checking is performed
|
||||
- * and all unpopulated pfns are populated.
|
||||
- */
|
||||
-int populate_pfns(struct xc_sr_context *ctx, unsigned int count,
|
||||
- const xen_pfn_t *original_pfns, const uint32_t *types)
|
||||
-{
|
||||
- xc_interface *xch = ctx->xch;
|
||||
- unsigned int i, nr_pfns = 0;
|
||||
- int rc = -1;
|
||||
-
|
||||
- for ( i = 0; i < count; ++i )
|
||||
- {
|
||||
- if ( (!types || page_type_to_populate(types[i])) &&
|
||||
- !pfn_is_populated(ctx, original_pfns[i]) )
|
||||
- {
|
||||
- rc = pfn_set_populated(ctx, original_pfns[i]);
|
||||
- if ( rc )
|
||||
- goto err;
|
||||
- ctx->restore.pp_pfns[nr_pfns] = ctx->restore.pp_mfns[nr_pfns] = original_pfns[i];
|
||||
- ++nr_pfns;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if ( nr_pfns )
|
||||
- {
|
||||
- rc = xc_domain_populate_physmap_exact(
|
||||
- xch, ctx->domid, nr_pfns, 0, 0, ctx->restore.pp_mfns);
|
||||
- if ( rc )
|
||||
- {
|
||||
- PERROR("Failed to populate physmap");
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- for ( i = 0; i < nr_pfns; ++i )
|
||||
- {
|
||||
- if ( ctx->restore.pp_mfns[i] == INVALID_MFN )
|
||||
- {
|
||||
- ERROR("Populate physmap failed for pfn %u", i);
|
||||
- rc = -1;
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- ctx->restore.ops.set_gfn(ctx, ctx->restore.pp_pfns[i], ctx->restore.pp_mfns[i]);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- rc = 0;
|
||||
-
|
||||
- err:
|
||||
- return rc;
|
||||
-}
|
||||
-
|
||||
static int handle_static_data_end_v2(struct xc_sr_context *ctx)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -259,7 +205,8 @@ static int map_guest_pages(struct xc_sr_
|
||||
uint32_t i, p;
|
||||
int rc;
|
||||
|
||||
- rc = populate_pfns(ctx, pages->count, ctx->restore.pfns, ctx->restore.types);
|
||||
+ rc = ctx->restore.ops.populate_pfns(ctx, pages->count, ctx->restore.pfns,
|
||||
+ ctx->restore.types);
|
||||
if ( rc )
|
||||
{
|
||||
ERROR("Failed to populate pfns for batch of %u pages", pages->count);
|
||||
@@ -1074,6 +1021,9 @@ int xc_domain_restore(xc_interface *xch,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ /* See xc_domain_getinfo */
|
||||
+ ctx.restore.max_pages = ctx.dominfo.max_pages;
|
||||
+ ctx.restore.tot_pages = ctx.dominfo.tot_pages;
|
||||
ctx.restore.p2m_size = nr_pfns;
|
||||
ctx.restore.ops = hvm ? restore_ops_x86_hvm : restore_ops_x86_pv;
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_restore_x86_hvm.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore_x86_hvm.c
|
||||
@@ -130,6 +130,33 @@ static int x86_hvm_localise_page(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static bool x86_hvm_expand_sp_bitmaps(struct xc_sr_context *ctx, unsigned long max_pfn)
|
||||
+{
|
||||
+ struct sr_bitmap *bm;
|
||||
+
|
||||
+ bm = &ctx->x86.hvm.restore.attempted_1g;
|
||||
+ if ( !sr_bitmap_expand(bm, max_pfn >> SUPERPAGE_1GB_SHIFT) )
|
||||
+ return false;
|
||||
+
|
||||
+ bm = &ctx->x86.hvm.restore.attempted_2m;
|
||||
+ if ( !sr_bitmap_expand(bm, max_pfn >> SUPERPAGE_2MB_SHIFT) )
|
||||
+ return false;
|
||||
+
|
||||
+ bm = &ctx->x86.hvm.restore.allocated_pfns;
|
||||
+ if ( !sr_bitmap_expand(bm, max_pfn) )
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static void x86_hvm_no_superpage(struct xc_sr_context *ctx, unsigned long addr)
|
||||
+{
|
||||
+ unsigned long pfn = addr >> XC_PAGE_SHIFT;
|
||||
+
|
||||
+ sr_set_bit(pfn >> SUPERPAGE_1GB_SHIFT, &ctx->x86.hvm.restore.attempted_1g);
|
||||
+ sr_set_bit(pfn >> SUPERPAGE_2MB_SHIFT, &ctx->x86.hvm.restore.attempted_2m);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* restore_ops function. Confirms the stream matches the domain.
|
||||
*/
|
||||
@@ -164,12 +191,24 @@ static int x86_hvm_setup(struct xc_sr_co
|
||||
|
||||
max_pfn = max(ctx->restore.p2m_size, max_pages);
|
||||
if ( !sr_bitmap_expand(&ctx->restore.populated_pfns, max_pfn) )
|
||||
- {
|
||||
- PERROR("Unable to allocate memory for populated_pfns bitmap");
|
||||
- return -1;
|
||||
- }
|
||||
+ goto out;
|
||||
+
|
||||
+ if ( !x86_hvm_expand_sp_bitmaps(ctx, max_pfn) )
|
||||
+ goto out;
|
||||
+
|
||||
+ /* FIXME: distinguish between PVH and HVM */
|
||||
+ /* No superpage in 1st 2MB due to VGA hole */
|
||||
+ x86_hvm_no_superpage(ctx, 0xA0000u);
|
||||
+#define LAPIC_BASE_ADDRESS 0xfee00000u
|
||||
+#define ACPI_INFO_PHYSICAL_ADDRESS 0xfc000000u
|
||||
+ x86_hvm_no_superpage(ctx, LAPIC_BASE_ADDRESS);
|
||||
+ x86_hvm_no_superpage(ctx, ACPI_INFO_PHYSICAL_ADDRESS);
|
||||
|
||||
return 0;
|
||||
+
|
||||
+out:
|
||||
+ PERROR("Unable to allocate memory for pfn bitmaps");
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -250,6 +289,9 @@ static int x86_hvm_stream_complete(struc
|
||||
static int x86_hvm_cleanup(struct xc_sr_context *ctx)
|
||||
{
|
||||
sr_bitmap_free(&ctx->restore.populated_pfns);
|
||||
+ sr_bitmap_free(&ctx->x86.hvm.restore.attempted_1g);
|
||||
+ sr_bitmap_free(&ctx->x86.hvm.restore.attempted_2m);
|
||||
+ sr_bitmap_free(&ctx->x86.hvm.restore.allocated_pfns);
|
||||
free(ctx->x86.hvm.restore.context.ptr);
|
||||
|
||||
free(ctx->x86.restore.cpuid.ptr);
|
||||
@@ -258,6 +300,336 @@ static int x86_hvm_cleanup(struct xc_sr_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Set a range of pfns as allocated
|
||||
+ */
|
||||
+static void pfn_set_long_allocated(struct xc_sr_context *ctx, xen_pfn_t base_pfn)
|
||||
+{
|
||||
+ sr_set_long_bit(base_pfn, &ctx->x86.hvm.restore.allocated_pfns);
|
||||
+}
|
||||
+
|
||||
+static void pfn_set_allocated(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
+{
|
||||
+ sr_set_bit(pfn, &ctx->x86.hvm.restore.allocated_pfns);
|
||||
+}
|
||||
+
|
||||
+struct x86_hvm_sp {
|
||||
+ xen_pfn_t pfn;
|
||||
+ xen_pfn_t base_pfn;
|
||||
+ unsigned long index;
|
||||
+ unsigned long count;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Try to allocate a 1GB page for this pfn, but avoid Over-allocation.
|
||||
+ * If this succeeds, mark the range of 2MB pages as busy.
|
||||
+ */
|
||||
+static bool x86_hvm_alloc_1g(struct xc_sr_context *ctx, struct x86_hvm_sp *sp)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ unsigned int order;
|
||||
+ int i, done;
|
||||
+ xen_pfn_t extent;
|
||||
+
|
||||
+ /* Only one attempt to avoid overlapping allocation */
|
||||
+ if ( sr_test_and_set_bit(sp->index, &ctx->x86.hvm.restore.attempted_1g) )
|
||||
+ return false;
|
||||
+
|
||||
+ order = SUPERPAGE_1GB_SHIFT;
|
||||
+ sp->count = SUPERPAGE_1GB_NR_PFNS;
|
||||
+
|
||||
+ /* Allocate only if there is room for another superpage */
|
||||
+ if ( ctx->restore.tot_pages + sp->count > ctx->restore.max_pages )
|
||||
+ return false;
|
||||
+
|
||||
+ extent = sp->base_pfn = (sp->pfn >> order) << order;
|
||||
+ done = xc_domain_populate_physmap(xch, ctx->domid, 1, order, 0, &extent);
|
||||
+ if ( done < 0 ) {
|
||||
+ PERROR("populate_physmap failed.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if ( done == 0 )
|
||||
+ return false;
|
||||
+
|
||||
+ DPRINTF("1G %" PRI_xen_pfn "\n", sp->base_pfn);
|
||||
+
|
||||
+ /* Mark all 2MB pages as done to avoid overlapping allocation */
|
||||
+ for ( i = 0; i < (SUPERPAGE_1GB_NR_PFNS/SUPERPAGE_2MB_NR_PFNS); i++ )
|
||||
+ sr_set_bit((sp->base_pfn >> SUPERPAGE_2MB_SHIFT) + i, &ctx->x86.hvm.restore.attempted_2m);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* Allocate a 2MB page if x86_hvm_alloc_1g failed, avoid Over-allocation. */
|
||||
+static bool x86_hvm_alloc_2m(struct xc_sr_context *ctx, struct x86_hvm_sp *sp)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ unsigned int order;
|
||||
+ int done;
|
||||
+ xen_pfn_t extent;
|
||||
+
|
||||
+ /* Only one attempt to avoid overlapping allocation */
|
||||
+ if ( sr_test_and_set_bit(sp->index, &ctx->x86.hvm.restore.attempted_2m) )
|
||||
+ return false;
|
||||
+
|
||||
+ order = SUPERPAGE_2MB_SHIFT;
|
||||
+ sp->count = SUPERPAGE_2MB_NR_PFNS;
|
||||
+
|
||||
+ /* Allocate only if there is room for another superpage */
|
||||
+ if ( ctx->restore.tot_pages + sp->count > ctx->restore.max_pages )
|
||||
+ return false;
|
||||
+
|
||||
+ extent = sp->base_pfn = (sp->pfn >> order) << order;
|
||||
+ done = xc_domain_populate_physmap(xch, ctx->domid, 1, order, 0, &extent);
|
||||
+ if ( done < 0 ) {
|
||||
+ PERROR("populate_physmap failed.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if ( done == 0 )
|
||||
+ return false;
|
||||
+
|
||||
+ DPRINTF("2M %" PRI_xen_pfn "\n", sp->base_pfn);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* Allocate a single page if x86_hvm_alloc_2m failed. */
|
||||
+static bool x86_hvm_alloc_4k(struct xc_sr_context *ctx, struct x86_hvm_sp *sp)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ unsigned int order;
|
||||
+ int done;
|
||||
+ xen_pfn_t extent;
|
||||
+
|
||||
+ order = 0;
|
||||
+ sp->count = 1UL;
|
||||
+
|
||||
+ /* Allocate only if there is room for another page */
|
||||
+ if ( ctx->restore.tot_pages + sp->count > ctx->restore.max_pages ) {
|
||||
+ errno = E2BIG;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ extent = sp->base_pfn = (sp->pfn >> order) << order;
|
||||
+ done = xc_domain_populate_physmap(xch, ctx->domid, 1, order, 0, &extent);
|
||||
+ if ( done < 0 ) {
|
||||
+ PERROR("populate_physmap failed.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if ( done == 0 ) {
|
||||
+ errno = ENOMEM;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ DPRINTF("4K %" PRI_xen_pfn "\n", sp->base_pfn);
|
||||
+ return true;
|
||||
+}
|
||||
+/*
|
||||
+ * Attempt to allocate a superpage where the pfn resides.
|
||||
+ */
|
||||
+static int x86_hvm_allocate_pfn(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
+{
|
||||
+ bool success;
|
||||
+ unsigned long idx_1g, idx_2m;
|
||||
+ struct x86_hvm_sp sp = {
|
||||
+ .pfn = pfn
|
||||
+ };
|
||||
+
|
||||
+ if ( sr_test_bit(pfn, &ctx->x86.hvm.restore.allocated_pfns) )
|
||||
+ return 0;
|
||||
+
|
||||
+ idx_1g = pfn >> SUPERPAGE_1GB_SHIFT;
|
||||
+ idx_2m = pfn >> SUPERPAGE_2MB_SHIFT;
|
||||
+
|
||||
+ sp.index = idx_1g;
|
||||
+ success = x86_hvm_alloc_1g(ctx, &sp);
|
||||
+
|
||||
+ if ( success == false ) {
|
||||
+ sp.index = idx_2m;
|
||||
+ success = x86_hvm_alloc_2m(ctx, &sp);
|
||||
+ }
|
||||
+
|
||||
+ if ( success == false ) {
|
||||
+ sp.index = 0;
|
||||
+ success = x86_hvm_alloc_4k(ctx, &sp);
|
||||
+ }
|
||||
+
|
||||
+ if ( success == false )
|
||||
+ return -1;
|
||||
+
|
||||
+ do {
|
||||
+ if ( sp.count >= BITS_PER_LONG && (sp.count % BITS_PER_LONG) == 0 ) {
|
||||
+ sp.count -= BITS_PER_LONG;
|
||||
+ ctx->restore.tot_pages += BITS_PER_LONG;
|
||||
+ pfn_set_long_allocated(ctx, sp.base_pfn + sp.count);
|
||||
+ } else {
|
||||
+ sp.count--;
|
||||
+ ctx->restore.tot_pages++;
|
||||
+ pfn_set_allocated(ctx, sp.base_pfn + sp.count);
|
||||
+ }
|
||||
+ } while ( sp.count );
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Deallocate memory.
|
||||
+ * There was likely an optimistic superpage allocation.
|
||||
+ * This means more pages may have been allocated past gap_end.
|
||||
+ * This range is not freed now. Incoming higher pfns will release it.
|
||||
+ */
|
||||
+static int x86_hvm_punch_hole(struct xc_sr_context *ctx,
|
||||
+ xen_pfn_t gap_start, xen_pfn_t gap_end)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ xen_pfn_t _pfn, pfn;
|
||||
+ uint32_t domid, freed = 0;
|
||||
+ int rc;
|
||||
+
|
||||
+ pfn = gap_start >> SUPERPAGE_1GB_SHIFT;
|
||||
+ do
|
||||
+ {
|
||||
+ sr_set_bit(pfn, &ctx->x86.hvm.restore.attempted_1g);
|
||||
+ } while (++pfn <= gap_end >> SUPERPAGE_1GB_SHIFT);
|
||||
+
|
||||
+ pfn = gap_start >> SUPERPAGE_2MB_SHIFT;
|
||||
+ do
|
||||
+ {
|
||||
+ sr_set_bit(pfn, &ctx->x86.hvm.restore.attempted_2m);
|
||||
+ } while (++pfn <= gap_end >> SUPERPAGE_2MB_SHIFT);
|
||||
+
|
||||
+ pfn = gap_start;
|
||||
+
|
||||
+ while ( pfn <= gap_end )
|
||||
+ {
|
||||
+ if ( sr_test_and_clear_bit(pfn, &ctx->x86.hvm.restore.allocated_pfns) )
|
||||
+ {
|
||||
+ domid = ctx->domid;
|
||||
+ _pfn = pfn;
|
||||
+ rc = xc_domain_decrease_reservation_exact(xch, domid, 1, 0, &_pfn);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ PERROR("Failed to release pfn %" PRI_xen_pfn, pfn);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ctx->restore.tot_pages--;
|
||||
+ freed++;
|
||||
+ }
|
||||
+ pfn++;
|
||||
+ }
|
||||
+ if ( freed )
|
||||
+ DPRINTF("freed %u between %" PRI_xen_pfn " %" PRI_xen_pfn "\n",
|
||||
+ freed, gap_start, gap_end);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int x86_hvm_unpopulate_page(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
+{
|
||||
+ sr_clear_bit(pfn, &ctx->restore.populated_pfns);
|
||||
+ return x86_hvm_punch_hole(ctx, pfn, pfn);
|
||||
+}
|
||||
+
|
||||
+static int x86_hvm_populate_page(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
+{
|
||||
+ xen_pfn_t gap_start, gap_end;
|
||||
+ bool has_gap, first_iteration;
|
||||
+ int rc;
|
||||
+
|
||||
+ /*
|
||||
+ * Check for a gap between the previous populated pfn and this pfn.
|
||||
+ * In case a gap exists, it is required to punch a hole to release memory,
|
||||
+ * starting after the previous pfn and before this pfn.
|
||||
+ *
|
||||
+ * But: this can be done only during the first iteration, which is the
|
||||
+ * only place where superpage allocations are attempted. All following
|
||||
+ * iterations lack the info to properly maintain prev_populated_pfn.
|
||||
+ */
|
||||
+ has_gap = ctx->x86.hvm.restore.prev_populated_pfn + 1 < pfn;
|
||||
+ first_iteration = ctx->x86.hvm.restore.iteration == 0;
|
||||
+ if ( has_gap && first_iteration )
|
||||
+ {
|
||||
+ gap_start = ctx->x86.hvm.restore.prev_populated_pfn + 1;
|
||||
+ gap_end = pfn - 1;
|
||||
+
|
||||
+ rc = x86_hvm_punch_hole(ctx, gap_start, gap_end);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ rc = x86_hvm_allocate_pfn(ctx, pfn);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+ pfn_set_populated(ctx, pfn);
|
||||
+ ctx->x86.hvm.restore.prev_populated_pfn = pfn;
|
||||
+
|
||||
+ rc = 0;
|
||||
+err:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Try to allocate superpages.
|
||||
+ * This works without memory map because the pfns arrive in incremental order.
|
||||
+ * All pfn numbers and their type are submitted.
|
||||
+ * Only pfns with data will have also pfn content transmitted.
|
||||
+ */
|
||||
+static int x86_hvm_populate_pfns(struct xc_sr_context *ctx, unsigned count,
|
||||
+ const xen_pfn_t *original_pfns,
|
||||
+ const uint32_t *types)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ xen_pfn_t pfn, min_pfn, max_pfn;
|
||||
+ bool to_populate, populated;
|
||||
+ unsigned i = count;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ min_pfn = count ? original_pfns[0] : 0;
|
||||
+ max_pfn = count ? original_pfns[count - 1] : 0;
|
||||
+ DPRINTF("batch of %u pfns between %" PRI_xen_pfn " %" PRI_xen_pfn "\n",
|
||||
+ count, min_pfn, max_pfn);
|
||||
+
|
||||
+ if ( !x86_hvm_expand_sp_bitmaps(ctx, max_pfn) )
|
||||
+ {
|
||||
+ ERROR("Unable to allocate memory for pfn bitmaps");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * There is no indicator for a new iteration.
|
||||
+ * Simulate it by checking if a lower pfn is coming in.
|
||||
+ * In the end it matters only to know if this iteration is the first one.
|
||||
+ */
|
||||
+ if ( min_pfn < ctx->x86.hvm.restore.iteration_tracker_pfn )
|
||||
+ ctx->x86.hvm.restore.iteration++;
|
||||
+ ctx->x86.hvm.restore.iteration_tracker_pfn = min_pfn;
|
||||
+
|
||||
+ for ( i = 0; i < count; ++i )
|
||||
+ {
|
||||
+ pfn = original_pfns[i];
|
||||
+
|
||||
+ to_populate = page_type_to_populate(types[i]);
|
||||
+ populated = pfn_is_populated(ctx, pfn);
|
||||
+
|
||||
+ /*
|
||||
+ * page has data, pfn populated: nothing to do
|
||||
+ * page has data, pfn not populated: likely never seen before
|
||||
+ * page has no data, pfn populated: likely ballooned out during migration
|
||||
+ * page has no data, pfn not populated: nothing to do
|
||||
+ */
|
||||
+ if ( to_populate && !populated )
|
||||
+ {
|
||||
+ rc = x86_hvm_populate_page(ctx, pfn);
|
||||
+ } else if ( !to_populate && populated )
|
||||
+ {
|
||||
+ rc = x86_hvm_unpopulate_page(ctx, pfn);
|
||||
+ }
|
||||
+ if ( rc )
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+
|
||||
struct xc_sr_restore_ops restore_ops_x86_hvm =
|
||||
{
|
||||
.pfn_is_valid = x86_hvm_pfn_is_valid,
|
||||
@@ -266,6 +638,7 @@ struct xc_sr_restore_ops restore_ops_x86
|
||||
.set_page_type = x86_hvm_set_page_type,
|
||||
.localise_page = x86_hvm_localise_page,
|
||||
.setup = x86_hvm_setup,
|
||||
+ .populate_pfns = x86_hvm_populate_pfns,
|
||||
.process_record = x86_hvm_process_record,
|
||||
.static_data_complete = x86_static_data_complete,
|
||||
.stream_complete = x86_hvm_stream_complete,
|
||||
--- a/tools/libs/guest/xg_sr_restore_x86_pv.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore_x86_pv.c
|
||||
@@ -960,6 +960,64 @@ static void x86_pv_set_gfn(struct xc_sr_
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Given a set of pfns, obtain memory from Xen to fill the physmap for the
|
||||
+ * unpopulated subset. If types is NULL, no page type checking is performed
|
||||
+ * and all unpopulated pfns are populated.
|
||||
+ */
|
||||
+static int x86_pv_populate_pfns(struct xc_sr_context *ctx, unsigned count,
|
||||
+ const xen_pfn_t *original_pfns,
|
||||
+ const uint32_t *types)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ xen_pfn_t *mfns = ctx->restore.pp_mfns,
|
||||
+ *pfns = ctx->restore.pp_pfns;
|
||||
+ unsigned int i, nr_pfns = 0;
|
||||
+ int rc = -1;
|
||||
+
|
||||
+ for ( i = 0; i < count; ++i )
|
||||
+ {
|
||||
+ if ( (!types ||
|
||||
+ (types && page_type_has_stream_data(types[i]) == true)) &&
|
||||
+ !pfn_is_populated(ctx, original_pfns[i]) )
|
||||
+ {
|
||||
+ rc = pfn_set_populated(ctx, original_pfns[i]);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+ pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i];
|
||||
+ ++nr_pfns;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ( nr_pfns )
|
||||
+ {
|
||||
+ rc = xc_domain_populate_physmap_exact(
|
||||
+ xch, ctx->domid, nr_pfns, 0, 0, mfns);
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ PERROR("Failed to populate physmap");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ for ( i = 0; i < nr_pfns; ++i )
|
||||
+ {
|
||||
+ if ( mfns[i] == INVALID_MFN )
|
||||
+ {
|
||||
+ ERROR("Populate physmap failed for pfn %u", i);
|
||||
+ rc = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ctx->restore.ops.set_gfn(ctx, pfns[i], mfns[i]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ rc = 0;
|
||||
+
|
||||
+ err:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* restore_ops function. Convert pfns back to mfns in pagetables. Possibly
|
||||
* needs to populate new frames if a PTE is found referring to a frame which
|
||||
* hasn't yet been seen from PAGE_DATA records.
|
||||
@@ -1003,7 +1061,7 @@ static int x86_pv_localise_page(struct x
|
||||
}
|
||||
}
|
||||
|
||||
- if ( to_populate && populate_pfns(ctx, to_populate, pfns, NULL) )
|
||||
+ if ( to_populate && x86_pv_populate_pfns(ctx, to_populate, pfns, NULL) )
|
||||
return -1;
|
||||
|
||||
for ( i = 0; i < (PAGE_SIZE / sizeof(uint64_t)); ++i )
|
||||
@@ -1200,6 +1258,7 @@ struct xc_sr_restore_ops restore_ops_x86
|
||||
.set_gfn = x86_pv_set_gfn,
|
||||
.localise_page = x86_pv_localise_page,
|
||||
.setup = x86_pv_setup,
|
||||
+ .populate_pfns = x86_pv_populate_pfns,
|
||||
.process_record = x86_pv_process_record,
|
||||
.static_data_complete = x86_static_data_complete,
|
||||
.stream_complete = x86_pv_stream_complete,
|
@@ -1,101 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 14:44:09 +0200
|
||||
Subject: libxc sr restore map_errs
|
||||
|
||||
tools: restore: preallocate map_errs array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in an incoming batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_restore.c | 22 +++++++---------------
|
||||
2 files changed, 8 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -259,6 +259,7 @@ struct xc_sr_context
|
||||
xen_pfn_t *pfns;
|
||||
uint32_t *types;
|
||||
xen_pfn_t *mfns;
|
||||
+ int *map_errs;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -204,21 +204,12 @@ static int process_page_data(struct xc_s
|
||||
xen_pfn_t *pfns, uint32_t *types, void *page_data)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- int *map_errs = malloc(count * sizeof(*map_errs));
|
||||
int rc;
|
||||
void *mapping = NULL, *guest_page = NULL;
|
||||
unsigned int i, /* i indexes the pfns from the record. */
|
||||
j, /* j indexes the subset of pfns we decide to map. */
|
||||
nr_pages = 0;
|
||||
|
||||
- if ( !map_errs )
|
||||
- {
|
||||
- rc = -1;
|
||||
- ERROR("Failed to allocate %zu bytes to process page data",
|
||||
- count * sizeof(*map_errs));
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
rc = populate_pfns(ctx, count, pfns, types);
|
||||
if ( rc )
|
||||
{
|
||||
@@ -240,7 +231,7 @@ static int process_page_data(struct xc_s
|
||||
|
||||
mapping = guest_page = xenforeignmemory_map(
|
||||
xch->fmem, ctx->domid, PROT_READ | PROT_WRITE,
|
||||
- nr_pages, ctx->restore.mfns, map_errs);
|
||||
+ nr_pages, ctx->restore.mfns, ctx->restore.map_errs);
|
||||
if ( !mapping )
|
||||
{
|
||||
rc = -1;
|
||||
@@ -254,11 +245,11 @@ static int process_page_data(struct xc_s
|
||||
if ( !page_type_has_stream_data(types[i]) )
|
||||
continue;
|
||||
|
||||
- if ( map_errs[j] )
|
||||
+ if ( ctx->restore.map_errs[j] )
|
||||
{
|
||||
rc = -1;
|
||||
ERROR("Mapping pfn %#"PRIpfn" (mfn %#"PRIpfn", type %#"PRIx32") failed with %d",
|
||||
- pfns[i], ctx->restore.mfns[j], types[i], map_errs[j]);
|
||||
+ pfns[i], ctx->restore.mfns[j], types[i], ctx->restore.map_errs[j]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -296,8 +287,6 @@ static int process_page_data(struct xc_s
|
||||
if ( mapping )
|
||||
xenforeignmemory_unmap(xch->fmem, mapping, nr_pages);
|
||||
|
||||
- free(map_errs);
|
||||
-
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -704,7 +693,9 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->restore.pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pfns));
|
||||
ctx->restore.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.types));
|
||||
ctx->restore.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.mfns));
|
||||
- if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns )
|
||||
+ ctx->restore.map_errs = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.map_errs));
|
||||
+ if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns ||
|
||||
+ !ctx->restore.map_errs )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -741,6 +732,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.map_errs);
|
||||
free(ctx->restore.mfns);
|
||||
free(ctx->restore.types);
|
||||
free(ctx->restore.pfns);
|
@@ -1,103 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 14:42:19 +0200
|
||||
Subject: libxc sr restore mfns
|
||||
|
||||
tools: restore: preallocate mfns array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in an incoming batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_restore.c | 16 ++++++++--------
|
||||
2 files changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -258,6 +258,7 @@ struct xc_sr_context
|
||||
struct restore_callbacks *callbacks;
|
||||
xen_pfn_t *pfns;
|
||||
uint32_t *types;
|
||||
+ xen_pfn_t *mfns;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -204,7 +204,6 @@ static int process_page_data(struct xc_s
|
||||
xen_pfn_t *pfns, uint32_t *types, void *page_data)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- xen_pfn_t *mfns = malloc(count * sizeof(*mfns));
|
||||
int *map_errs = malloc(count * sizeof(*map_errs));
|
||||
int rc;
|
||||
void *mapping = NULL, *guest_page = NULL;
|
||||
@@ -212,11 +211,11 @@ static int process_page_data(struct xc_s
|
||||
j, /* j indexes the subset of pfns we decide to map. */
|
||||
nr_pages = 0;
|
||||
|
||||
- if ( !mfns || !map_errs )
|
||||
+ if ( !map_errs )
|
||||
{
|
||||
rc = -1;
|
||||
ERROR("Failed to allocate %zu bytes to process page data",
|
||||
- count * (sizeof(*mfns) + sizeof(*map_errs)));
|
||||
+ count * sizeof(*map_errs));
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -232,7 +231,7 @@ static int process_page_data(struct xc_s
|
||||
ctx->restore.ops.set_page_type(ctx, pfns[i], types[i]);
|
||||
|
||||
if ( page_type_has_stream_data(types[i]) )
|
||||
- mfns[nr_pages++] = ctx->restore.ops.pfn_to_gfn(ctx, pfns[i]);
|
||||
+ ctx->restore.mfns[nr_pages++] = ctx->restore.ops.pfn_to_gfn(ctx, pfns[i]);
|
||||
}
|
||||
|
||||
/* Nothing to do? */
|
||||
@@ -241,7 +240,7 @@ static int process_page_data(struct xc_s
|
||||
|
||||
mapping = guest_page = xenforeignmemory_map(
|
||||
xch->fmem, ctx->domid, PROT_READ | PROT_WRITE,
|
||||
- nr_pages, mfns, map_errs);
|
||||
+ nr_pages, ctx->restore.mfns, map_errs);
|
||||
if ( !mapping )
|
||||
{
|
||||
rc = -1;
|
||||
@@ -259,7 +258,7 @@ static int process_page_data(struct xc_s
|
||||
{
|
||||
rc = -1;
|
||||
ERROR("Mapping pfn %#"PRIpfn" (mfn %#"PRIpfn", type %#"PRIx32") failed with %d",
|
||||
- pfns[i], mfns[j], types[i], map_errs[j]);
|
||||
+ pfns[i], ctx->restore.mfns[j], types[i], map_errs[j]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -298,7 +297,6 @@ static int process_page_data(struct xc_s
|
||||
xenforeignmemory_unmap(xch->fmem, mapping, nr_pages);
|
||||
|
||||
free(map_errs);
|
||||
- free(mfns);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -705,7 +703,8 @@ static int setup(struct xc_sr_context *c
|
||||
|
||||
ctx->restore.pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pfns));
|
||||
ctx->restore.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.types));
|
||||
- if ( !ctx->restore.pfns || !ctx->restore.types )
|
||||
+ ctx->restore.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.mfns));
|
||||
+ if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -742,6 +741,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.mfns);
|
||||
free(ctx->restore.types);
|
||||
free(ctx->restore.pfns);
|
||||
|
@@ -1,108 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 14:39:30 +0200
|
||||
Subject: libxc sr restore pfns
|
||||
|
||||
tools: restore: preallocate pfns array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in an incoming batch.
|
||||
Allocate the space once.
|
||||
|
||||
Adjust the verification for page count. It must be at least one page,
|
||||
but not more than MAX_BATCH_SIZE.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_restore.c | 23 +++++++++++++++--------
|
||||
2 files changed, 16 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -256,6 +256,7 @@ struct xc_sr_context
|
||||
{
|
||||
struct xc_sr_restore_ops ops;
|
||||
struct restore_callbacks *callbacks;
|
||||
+ xen_pfn_t *pfns;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -314,7 +314,7 @@ static int handle_page_data(struct xc_sr
|
||||
unsigned int i, pages_of_data = 0;
|
||||
int rc = -1;
|
||||
|
||||
- xen_pfn_t *pfns = NULL, pfn;
|
||||
+ xen_pfn_t pfn;
|
||||
uint32_t *types = NULL, type;
|
||||
|
||||
/*
|
||||
@@ -349,9 +349,9 @@ static int handle_page_data(struct xc_sr
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if ( pages->count < 1 )
|
||||
+ if ( !pages->count || pages->count > MAX_BATCH_SIZE )
|
||||
{
|
||||
- ERROR("Expected at least 1 pfn in PAGE_DATA record");
|
||||
+ ERROR("Unexpected pfn count %u in PAGE_DATA record", pages->count);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -362,9 +362,8 @@ static int handle_page_data(struct xc_sr
|
||||
goto err;
|
||||
}
|
||||
|
||||
- pfns = malloc(pages->count * sizeof(*pfns));
|
||||
types = malloc(pages->count * sizeof(*types));
|
||||
- if ( !pfns || !types )
|
||||
+ if ( !types )
|
||||
{
|
||||
ERROR("Unable to allocate enough memory for %u pfns",
|
||||
pages->count);
|
||||
@@ -393,7 +392,7 @@ static int handle_page_data(struct xc_sr
|
||||
* have a page worth of data in the record. */
|
||||
pages_of_data++;
|
||||
|
||||
- pfns[i] = pfn;
|
||||
+ ctx->restore.pfns[i] = pfn;
|
||||
types[i] = type;
|
||||
}
|
||||
|
||||
@@ -407,11 +406,10 @@ static int handle_page_data(struct xc_sr
|
||||
goto err;
|
||||
}
|
||||
|
||||
- rc = process_page_data(ctx, pages->count, pfns, types,
|
||||
+ rc = process_page_data(ctx, pages->count, ctx->restore.pfns, types,
|
||||
&pages->pfn[pages->count]);
|
||||
err:
|
||||
free(types);
|
||||
- free(pfns);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -715,6 +713,14 @@ static int setup(struct xc_sr_context *c
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ ctx->restore.pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pfns));
|
||||
+ if ( !ctx->restore.pfns )
|
||||
+ {
|
||||
+ ERROR("Unable to allocate memory");
|
||||
+ rc = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
ctx->restore.buffered_records = malloc(
|
||||
DEFAULT_BUF_RECORDS * sizeof(struct xc_sr_record));
|
||||
if ( !ctx->restore.buffered_records )
|
||||
@@ -745,6 +751,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.pfns);
|
||||
|
||||
if ( ctx->restore.ops.cleanup(ctx) )
|
||||
PERROR("Failed to clean up");
|
@@ -1,111 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 14:54:12 +0200
|
||||
Subject: libxc sr restore populate_pfns mfns
|
||||
|
||||
tools: restore: preallocate populate_pfns mfns array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in an incoming batch.
|
||||
Allocate the space once.
|
||||
|
||||
Use some prefix to avoid conflict with an array used in handle_page_data.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_restore.c | 23 ++++++++---------------
|
||||
2 files changed, 9 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -261,6 +261,7 @@ struct xc_sr_context
|
||||
xen_pfn_t *mfns;
|
||||
int *map_errs;
|
||||
xen_pfn_t *pp_pfns;
|
||||
+ xen_pfn_t *pp_mfns;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -138,17 +138,9 @@ int populate_pfns(struct xc_sr_context *
|
||||
const xen_pfn_t *original_pfns, const uint32_t *types)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- xen_pfn_t *mfns = malloc(count * sizeof(*mfns));
|
||||
unsigned int i, nr_pfns = 0;
|
||||
int rc = -1;
|
||||
|
||||
- if ( !mfns )
|
||||
- {
|
||||
- ERROR("Failed to allocate %zu bytes for populating the physmap",
|
||||
- 2 * count * sizeof(*mfns));
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
for ( i = 0; i < count; ++i )
|
||||
{
|
||||
if ( (!types || page_type_to_populate(types[i])) &&
|
||||
@@ -157,7 +149,7 @@ int populate_pfns(struct xc_sr_context *
|
||||
rc = pfn_set_populated(ctx, original_pfns[i]);
|
||||
if ( rc )
|
||||
goto err;
|
||||
- ctx->restore.pp_pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i];
|
||||
+ ctx->restore.pp_pfns[nr_pfns] = ctx->restore.pp_mfns[nr_pfns] = original_pfns[i];
|
||||
++nr_pfns;
|
||||
}
|
||||
}
|
||||
@@ -165,7 +157,7 @@ int populate_pfns(struct xc_sr_context *
|
||||
if ( nr_pfns )
|
||||
{
|
||||
rc = xc_domain_populate_physmap_exact(
|
||||
- xch, ctx->domid, nr_pfns, 0, 0, mfns);
|
||||
+ xch, ctx->domid, nr_pfns, 0, 0, ctx->restore.pp_mfns);
|
||||
if ( rc )
|
||||
{
|
||||
PERROR("Failed to populate physmap");
|
||||
@@ -174,22 +166,20 @@ int populate_pfns(struct xc_sr_context *
|
||||
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
- if ( mfns[i] == INVALID_MFN )
|
||||
+ if ( ctx->restore.pp_mfns[i] == INVALID_MFN )
|
||||
{
|
||||
ERROR("Populate physmap failed for pfn %u", i);
|
||||
rc = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
- ctx->restore.ops.set_gfn(ctx, ctx->restore.pp_pfns[i], mfns[i]);
|
||||
+ ctx->restore.ops.set_gfn(ctx, ctx->restore.pp_pfns[i], ctx->restore.pp_mfns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
err:
|
||||
- free(mfns);
|
||||
-
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -693,8 +683,10 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->restore.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.mfns));
|
||||
ctx->restore.map_errs = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.map_errs));
|
||||
ctx->restore.pp_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_pfns));
|
||||
+ ctx->restore.pp_mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_mfns));
|
||||
if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns ||
|
||||
- !ctx->restore.map_errs || !ctx->restore.pp_pfns )
|
||||
+ !ctx->restore.map_errs || !ctx->restore.pp_pfns ||
|
||||
+ !ctx->restore.pp_mfns )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -731,6 +723,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.pp_mfns);
|
||||
free(ctx->restore.pp_pfns);
|
||||
free(ctx->restore.map_errs);
|
||||
free(ctx->restore.mfns);
|
@@ -1,89 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 14:58:53 +0200
|
||||
Subject: libxc sr restore populate_pfns pfns
|
||||
|
||||
tools: restore: preallocate populate_pfns pfns array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in an incoming batch.
|
||||
Allocate the space once.
|
||||
|
||||
Use some prefix to avoid conflict with an array used in handle_page_data.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_restore.c | 14 +++++++-------
|
||||
2 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -260,6 +260,7 @@ struct xc_sr_context
|
||||
uint32_t *types;
|
||||
xen_pfn_t *mfns;
|
||||
int *map_errs;
|
||||
+ xen_pfn_t *pp_pfns;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -138,12 +138,11 @@ int populate_pfns(struct xc_sr_context *
|
||||
const xen_pfn_t *original_pfns, const uint32_t *types)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- xen_pfn_t *mfns = malloc(count * sizeof(*mfns)),
|
||||
- *pfns = malloc(count * sizeof(*pfns));
|
||||
+ xen_pfn_t *mfns = malloc(count * sizeof(*mfns));
|
||||
unsigned int i, nr_pfns = 0;
|
||||
int rc = -1;
|
||||
|
||||
- if ( !mfns || !pfns )
|
||||
+ if ( !mfns )
|
||||
{
|
||||
ERROR("Failed to allocate %zu bytes for populating the physmap",
|
||||
2 * count * sizeof(*mfns));
|
||||
@@ -158,7 +157,7 @@ int populate_pfns(struct xc_sr_context *
|
||||
rc = pfn_set_populated(ctx, original_pfns[i]);
|
||||
if ( rc )
|
||||
goto err;
|
||||
- pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i];
|
||||
+ ctx->restore.pp_pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i];
|
||||
++nr_pfns;
|
||||
}
|
||||
}
|
||||
@@ -182,14 +181,13 @@ int populate_pfns(struct xc_sr_context *
|
||||
goto err;
|
||||
}
|
||||
|
||||
- ctx->restore.ops.set_gfn(ctx, pfns[i], mfns[i]);
|
||||
+ ctx->restore.ops.set_gfn(ctx, ctx->restore.pp_pfns[i], mfns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
err:
|
||||
- free(pfns);
|
||||
free(mfns);
|
||||
|
||||
return rc;
|
||||
@@ -694,8 +692,9 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->restore.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.types));
|
||||
ctx->restore.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.mfns));
|
||||
ctx->restore.map_errs = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.map_errs));
|
||||
+ ctx->restore.pp_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pp_pfns));
|
||||
if ( !ctx->restore.pfns || !ctx->restore.types || !ctx->restore.mfns ||
|
||||
- !ctx->restore.map_errs )
|
||||
+ !ctx->restore.map_errs || !ctx->restore.pp_pfns )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -732,6 +731,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.pp_pfns);
|
||||
free(ctx->restore.map_errs);
|
||||
free(ctx->restore.mfns);
|
||||
free(ctx->restore.types);
|
@@ -1,272 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Mon, 26 Oct 2020 12:19:17 +0100
|
||||
Subject: libxc sr restore read_record
|
||||
|
||||
tools: restore: split record processing
|
||||
|
||||
handle_page_data must be able to read directly into mapped guest memory.
|
||||
This will avoid unneccesary memcpy calls for data which can be consumed verbatim.
|
||||
|
||||
Rearrange the code to allow decisions based on the incoming record.
|
||||
|
||||
This change is preparation for future changes in handle_page_data,
|
||||
no change in behavior is intended.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Reviewed-by: Juergen Gross <jgross@suse.com>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.c | 33 ++++++++++++---------
|
||||
tools/libs/guest/xg_sr_common.h | 4 ++-
|
||||
tools/libs/guest/xg_sr_restore.c | 49 ++++++++++++++++++++++----------
|
||||
tools/libs/guest/xg_sr_save.c | 7 ++++-
|
||||
4 files changed, 63 insertions(+), 30 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.c
|
||||
+++ b/tools/libs/guest/xg_sr_common.c
|
||||
@@ -91,26 +91,33 @@ int write_split_record(struct xc_sr_cont
|
||||
return -1;
|
||||
}
|
||||
|
||||
-int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec)
|
||||
+int read_record_header(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- struct xc_sr_rhdr rhdr;
|
||||
- size_t datasz;
|
||||
|
||||
- if ( read_exact(fd, &rhdr, sizeof(rhdr)) )
|
||||
+ if ( read_exact(fd, rhdr, sizeof(*rhdr)) )
|
||||
{
|
||||
PERROR("Failed to read Record Header from stream");
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if ( rhdr.length > REC_LENGTH_MAX )
|
||||
+ if ( rhdr->length > REC_LENGTH_MAX )
|
||||
{
|
||||
- ERROR("Record (0x%08x, %s) length %#x exceeds max (%#x)", rhdr.type,
|
||||
- rec_type_to_str(rhdr.type), rhdr.length, REC_LENGTH_MAX);
|
||||
+ ERROR("Record (0x%08x, %s) length %#x exceeds max (%#x)", rhdr->type,
|
||||
+ rec_type_to_str(rhdr->type), rhdr->length, REC_LENGTH_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
- datasz = ROUNDUP(rhdr.length, REC_ALIGN_ORDER);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int read_record_data(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr,
|
||||
+ struct xc_sr_record *rec)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ size_t datasz;
|
||||
+
|
||||
+ datasz = ROUNDUP(rhdr->length, REC_ALIGN_ORDER);
|
||||
|
||||
if ( datasz )
|
||||
{
|
||||
@@ -119,7 +126,7 @@ int read_record(struct xc_sr_context *ct
|
||||
if ( !rec->data )
|
||||
{
|
||||
ERROR("Unable to allocate %zu bytes for record data (0x%08x, %s)",
|
||||
- datasz, rhdr.type, rec_type_to_str(rhdr.type));
|
||||
+ datasz, rhdr->type, rec_type_to_str(rhdr->type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -128,18 +135,18 @@ int read_record(struct xc_sr_context *ct
|
||||
free(rec->data);
|
||||
rec->data = NULL;
|
||||
PERROR("Failed to read %zu bytes of data for record (0x%08x, %s)",
|
||||
- datasz, rhdr.type, rec_type_to_str(rhdr.type));
|
||||
+ datasz, rhdr->type, rec_type_to_str(rhdr->type));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
rec->data = NULL;
|
||||
|
||||
- rec->type = rhdr.type;
|
||||
- rec->length = rhdr.length;
|
||||
+ rec->type = rhdr->type;
|
||||
+ rec->length = rhdr->length;
|
||||
|
||||
return 0;
|
||||
-};
|
||||
+}
|
||||
|
||||
static void __attribute__((unused)) build_assertions(void)
|
||||
{
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -458,7 +458,9 @@ static inline int write_record(struct xc
|
||||
*
|
||||
* On failure, the contents of the record structure are undefined.
|
||||
*/
|
||||
-int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec);
|
||||
+int read_record_header(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr);
|
||||
+int read_record_data(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr,
|
||||
+ struct xc_sr_record *rec);
|
||||
|
||||
/*
|
||||
* This would ideally be private in restore.c, but is needed by
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -453,7 +453,7 @@ static int send_checkpoint_dirty_pfn_lis
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec);
|
||||
+static int process_buffered_record(struct xc_sr_context *ctx, struct xc_sr_record *rec);
|
||||
static int handle_checkpoint(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
@@ -492,7 +492,7 @@ static int handle_checkpoint(struct xc_s
|
||||
|
||||
for ( i = 0; i < ctx->restore.buffered_rec_num; i++ )
|
||||
{
|
||||
- rc = process_record(ctx, &ctx->restore.buffered_records[i]);
|
||||
+ rc = process_buffered_record(ctx, &ctx->restore.buffered_records[i]);
|
||||
if ( rc )
|
||||
goto err;
|
||||
}
|
||||
@@ -553,10 +553,11 @@ static int handle_checkpoint(struct xc_s
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int buffer_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
+static int buffer_record(struct xc_sr_context *ctx, struct xc_sr_rhdr *rhdr)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
unsigned int new_alloc_num;
|
||||
+ struct xc_sr_record rec;
|
||||
struct xc_sr_record *p;
|
||||
|
||||
if ( ctx->restore.buffered_rec_num >= ctx->restore.allocated_rec_num )
|
||||
@@ -574,8 +575,13 @@ static int buffer_record(struct xc_sr_co
|
||||
ctx->restore.allocated_rec_num = new_alloc_num;
|
||||
}
|
||||
|
||||
+ if ( read_record_data(ctx, ctx->fd, rhdr, &rec) )
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
memcpy(&ctx->restore.buffered_records[ctx->restore.buffered_rec_num++],
|
||||
- rec, sizeof(*rec));
|
||||
+ &rec, sizeof(rec));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -606,7 +612,7 @@ int handle_static_data_end(struct xc_sr_
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
+static int process_buffered_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
int rc = 0;
|
||||
@@ -644,6 +650,19 @@ static int process_record(struct xc_sr_c
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int process_incoming_record_header(struct xc_sr_context *ctx, struct xc_sr_rhdr *rhdr)
|
||||
+{
|
||||
+ struct xc_sr_record rec;
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = read_record_data(ctx, ctx->fd, rhdr, &rec);
|
||||
+ if ( rc )
|
||||
+ return rc;
|
||||
+
|
||||
+ return process_buffered_record(ctx, &rec);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int setup(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
@@ -740,7 +759,7 @@ static void cleanup(struct xc_sr_context
|
||||
static int restore(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- struct xc_sr_record rec;
|
||||
+ struct xc_sr_rhdr rhdr;
|
||||
int rc, saved_rc = 0, saved_errno = 0;
|
||||
|
||||
IPRINTF("Restoring domain");
|
||||
@@ -751,7 +770,7 @@ static int restore(struct xc_sr_context
|
||||
|
||||
do
|
||||
{
|
||||
- rc = read_record(ctx, ctx->fd, &rec);
|
||||
+ rc = read_record_header(ctx, ctx->fd, &rhdr);
|
||||
if ( rc )
|
||||
{
|
||||
if ( ctx->restore.buffer_all_records )
|
||||
@@ -761,25 +780,25 @@ static int restore(struct xc_sr_context
|
||||
}
|
||||
|
||||
if ( ctx->restore.buffer_all_records &&
|
||||
- rec.type != REC_TYPE_END &&
|
||||
- rec.type != REC_TYPE_CHECKPOINT )
|
||||
+ rhdr.type != REC_TYPE_END &&
|
||||
+ rhdr.type != REC_TYPE_CHECKPOINT )
|
||||
{
|
||||
- rc = buffer_record(ctx, &rec);
|
||||
+ rc = buffer_record(ctx, &rhdr);
|
||||
if ( rc )
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
- rc = process_record(ctx, &rec);
|
||||
+ rc = process_incoming_record_header(ctx, &rhdr);
|
||||
if ( rc == RECORD_NOT_PROCESSED )
|
||||
{
|
||||
- if ( rec.type & REC_TYPE_OPTIONAL )
|
||||
+ if ( rhdr.type & REC_TYPE_OPTIONAL )
|
||||
DPRINTF("Ignoring optional record %#x (%s)",
|
||||
- rec.type, rec_type_to_str(rec.type));
|
||||
+ rhdr.type, rec_type_to_str(rhdr.type));
|
||||
else
|
||||
{
|
||||
ERROR("Mandatory record %#x (%s) not handled",
|
||||
- rec.type, rec_type_to_str(rec.type));
|
||||
+ rhdr.type, rec_type_to_str(rhdr.type));
|
||||
rc = -1;
|
||||
goto err;
|
||||
}
|
||||
@@ -790,7 +809,7 @@ static int restore(struct xc_sr_context
|
||||
goto err;
|
||||
}
|
||||
|
||||
- } while ( rec.type != REC_TYPE_END );
|
||||
+ } while ( rhdr.type != REC_TYPE_END );
|
||||
|
||||
remus_failover:
|
||||
if ( ctx->stream_type == XC_STREAM_COLO )
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -590,6 +590,7 @@ static int send_memory_live(struct xc_sr
|
||||
static int colo_merge_secondary_dirty_bitmap(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
+ struct xc_sr_rhdr rhdr;
|
||||
struct xc_sr_record rec;
|
||||
uint64_t *pfns = NULL;
|
||||
uint64_t pfn;
|
||||
@@ -598,7 +599,11 @@ static int colo_merge_secondary_dirty_bi
|
||||
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
|
||||
&ctx->save.dirty_bitmap_hbuf);
|
||||
|
||||
- rc = read_record(ctx, ctx->save.recv_fd, &rec);
|
||||
+ rc = read_record_header(ctx, ctx->save.recv_fd, &rhdr);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+
|
||||
+ rc = read_record_data(ctx, ctx->save.recv_fd, &rhdr, &rec);
|
||||
if ( rc )
|
||||
goto err;
|
||||
|
@@ -1,93 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 14:39:31 +0200
|
||||
Subject: libxc sr restore types
|
||||
|
||||
tools: restore: preallocate types array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in an incoming batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_restore.c | 22 +++++++---------------
|
||||
2 files changed, 8 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -257,6 +257,7 @@ struct xc_sr_context
|
||||
struct xc_sr_restore_ops ops;
|
||||
struct restore_callbacks *callbacks;
|
||||
xen_pfn_t *pfns;
|
||||
+ uint32_t *types;
|
||||
|
||||
int send_back_fd;
|
||||
unsigned long p2m_size;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -315,7 +315,7 @@ static int handle_page_data(struct xc_sr
|
||||
int rc = -1;
|
||||
|
||||
xen_pfn_t pfn;
|
||||
- uint32_t *types = NULL, type;
|
||||
+ uint32_t type;
|
||||
|
||||
/*
|
||||
* v2 compatibility only exists for x86 streams. This is a bit of a
|
||||
@@ -362,14 +362,6 @@ static int handle_page_data(struct xc_sr
|
||||
goto err;
|
||||
}
|
||||
|
||||
- types = malloc(pages->count * sizeof(*types));
|
||||
- if ( !types )
|
||||
- {
|
||||
- ERROR("Unable to allocate enough memory for %u pfns",
|
||||
- pages->count);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
for ( i = 0; i < pages->count; ++i )
|
||||
{
|
||||
pfn = pages->pfn[i] & PAGE_DATA_PFN_MASK;
|
||||
@@ -393,7 +385,7 @@ static int handle_page_data(struct xc_sr
|
||||
pages_of_data++;
|
||||
|
||||
ctx->restore.pfns[i] = pfn;
|
||||
- types[i] = type;
|
||||
+ ctx->restore.types[i] = type;
|
||||
}
|
||||
|
||||
if ( rec->length != (sizeof(*pages) +
|
||||
@@ -406,11 +398,9 @@ static int handle_page_data(struct xc_sr
|
||||
goto err;
|
||||
}
|
||||
|
||||
- rc = process_page_data(ctx, pages->count, ctx->restore.pfns, types,
|
||||
- &pages->pfn[pages->count]);
|
||||
+ rc = process_page_data(ctx, pages->count, ctx->restore.pfns,
|
||||
+ ctx->restore.types, &pages->pfn[pages->count]);
|
||||
err:
|
||||
- free(types);
|
||||
-
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -714,7 +704,8 @@ static int setup(struct xc_sr_context *c
|
||||
}
|
||||
|
||||
ctx->restore.pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pfns));
|
||||
- if ( !ctx->restore.pfns )
|
||||
+ ctx->restore.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.types));
|
||||
+ if ( !ctx->restore.pfns || !ctx->restore.types )
|
||||
{
|
||||
ERROR("Unable to allocate memory");
|
||||
rc = -1;
|
||||
@@ -751,6 +742,7 @@ static void cleanup(struct xc_sr_context
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
free(ctx->restore.populated_pfns);
|
||||
+ free(ctx->restore.types);
|
||||
free(ctx->restore.pfns);
|
||||
|
||||
if ( ctx->restore.ops.cleanup(ctx) )
|
@@ -1,109 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 11:26:05 +0200
|
||||
Subject: libxc sr save errors
|
||||
|
||||
tools: save: preallocate errors array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_save.c | 20 ++++++++++----------
|
||||
2 files changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -246,6 +246,7 @@ struct xc_sr_context
|
||||
xen_pfn_t *batch_pfns;
|
||||
xen_pfn_t *mfns;
|
||||
xen_pfn_t *types;
|
||||
+ int *errors;
|
||||
unsigned int nr_batch_pfns;
|
||||
unsigned long *deferred_pages;
|
||||
unsigned long nr_deferred_pages;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -91,7 +91,7 @@ static int write_batch(struct xc_sr_cont
|
||||
void *guest_mapping = NULL;
|
||||
void **guest_data = NULL;
|
||||
void **local_pages = NULL;
|
||||
- int *errors = NULL, rc = -1;
|
||||
+ int rc = -1;
|
||||
unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
|
||||
unsigned int nr_pfns = ctx->save.nr_batch_pfns;
|
||||
void *page, *orig_page;
|
||||
@@ -104,8 +104,6 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
assert(nr_pfns != 0);
|
||||
|
||||
- /* Errors from attempting to map the gfns. */
|
||||
- errors = malloc(nr_pfns * sizeof(*errors));
|
||||
/* Pointers to page data to send. Mapped gfns or local allocations. */
|
||||
guest_data = calloc(nr_pfns, sizeof(*guest_data));
|
||||
/* Pointers to locally allocated pages. Need freeing. */
|
||||
@@ -113,7 +111,7 @@ static int write_batch(struct xc_sr_cont
|
||||
/* iovec[] for writev(). */
|
||||
iov = malloc((nr_pfns + 4) * sizeof(*iov));
|
||||
|
||||
- if ( !errors || !guest_data || !local_pages || !iov )
|
||||
+ if ( !guest_data || !local_pages || !iov )
|
||||
{
|
||||
ERROR("Unable to allocate arrays for a batch of %u pages",
|
||||
nr_pfns);
|
||||
@@ -158,8 +156,8 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
if ( nr_pages > 0 )
|
||||
{
|
||||
- guest_mapping = xenforeignmemory_map(
|
||||
- xch->fmem, ctx->domid, PROT_READ, nr_pages, ctx->save.mfns, errors);
|
||||
+ guest_mapping = xenforeignmemory_map(xch->fmem, ctx->domid, PROT_READ,
|
||||
+ nr_pages, ctx->save.mfns, ctx->save.errors);
|
||||
if ( !guest_mapping )
|
||||
{
|
||||
PERROR("Failed to map guest pages");
|
||||
@@ -172,10 +170,11 @@ static int write_batch(struct xc_sr_cont
|
||||
if ( !page_type_has_stream_data(ctx->save.types[i]) )
|
||||
continue;
|
||||
|
||||
- if ( errors[p] )
|
||||
+ if ( ctx->save.errors[p] )
|
||||
{
|
||||
ERROR("Mapping of pfn %#"PRIpfn" (mfn %#"PRIpfn") failed %d",
|
||||
- ctx->save.batch_pfns[i], ctx->save.mfns[p], errors[p]);
|
||||
+ ctx->save.batch_pfns[i], ctx->save.mfns[p],
|
||||
+ ctx->save.errors[p]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -271,7 +270,6 @@ static int write_batch(struct xc_sr_cont
|
||||
free(iov);
|
||||
free(local_pages);
|
||||
free(guest_data);
|
||||
- free(errors);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -846,10 +844,11 @@ static int setup(struct xc_sr_context *c
|
||||
sizeof(*ctx->save.batch_pfns));
|
||||
ctx->save.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.mfns));
|
||||
ctx->save.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.types));
|
||||
+ ctx->save.errors = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.errors));
|
||||
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
|
||||
|
||||
if ( !ctx->save.batch_pfns || !ctx->save.mfns || !ctx->save.types ||
|
||||
- !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
+ !ctx->save.errors || !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
|
||||
" deferred pages");
|
||||
@@ -880,6 +879,7 @@ static void cleanup(struct xc_sr_context
|
||||
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
|
||||
NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
free(ctx->save.deferred_pages);
|
||||
+ free(ctx->save.errors);
|
||||
free(ctx->save.types);
|
||||
free(ctx->save.mfns);
|
||||
free(ctx->save.batch_pfns);
|
@@ -1,123 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 11:40:45 +0200
|
||||
Subject: libxc sr save guest_data
|
||||
|
||||
tools: save: preallocate guest_data array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch.
|
||||
Allocate the space once.
|
||||
|
||||
Because this was allocated with calloc:
|
||||
Adjust the loop to clear unused entries as needed.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_save.c | 20 +++++++++++---------
|
||||
2 files changed, 12 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -249,6 +249,7 @@ struct xc_sr_context
|
||||
int *errors;
|
||||
struct iovec *iov;
|
||||
uint64_t *rec_pfns;
|
||||
+ void **guest_data;
|
||||
unsigned int nr_batch_pfns;
|
||||
unsigned long *deferred_pages;
|
||||
unsigned long nr_deferred_pages;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -89,7 +89,6 @@ static int write_batch(struct xc_sr_cont
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
void *guest_mapping = NULL;
|
||||
- void **guest_data = NULL;
|
||||
void **local_pages = NULL;
|
||||
int rc = -1;
|
||||
unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
|
||||
@@ -103,12 +102,10 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
assert(nr_pfns != 0);
|
||||
|
||||
- /* Pointers to page data to send. Mapped gfns or local allocations. */
|
||||
- guest_data = calloc(nr_pfns, sizeof(*guest_data));
|
||||
/* Pointers to locally allocated pages. Need freeing. */
|
||||
local_pages = calloc(nr_pfns, sizeof(*local_pages));
|
||||
|
||||
- if ( !guest_data || !local_pages )
|
||||
+ if ( !local_pages )
|
||||
{
|
||||
ERROR("Unable to allocate arrays for a batch of %u pages",
|
||||
nr_pfns);
|
||||
@@ -165,7 +162,10 @@ static int write_batch(struct xc_sr_cont
|
||||
for ( i = 0, p = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
if ( !page_type_has_stream_data(ctx->save.types[i]) )
|
||||
+ {
|
||||
+ ctx->save.guest_data[i] = NULL;
|
||||
continue;
|
||||
+ }
|
||||
|
||||
if ( ctx->save.errors[p] )
|
||||
{
|
||||
@@ -183,6 +183,7 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
if ( rc )
|
||||
{
|
||||
+ ctx->save.guest_data[i] = NULL;
|
||||
if ( rc == -1 && errno == EAGAIN )
|
||||
{
|
||||
set_bit(ctx->save.batch_pfns[i], ctx->save.deferred_pages);
|
||||
@@ -194,7 +195,7 @@ static int write_batch(struct xc_sr_cont
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
- guest_data[i] = page;
|
||||
+ ctx->save.guest_data[i] = page;
|
||||
|
||||
rc = -1;
|
||||
++p;
|
||||
@@ -232,9 +233,9 @@ static int write_batch(struct xc_sr_cont
|
||||
{
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
- if ( guest_data[i] )
|
||||
+ if ( ctx->save.guest_data[i] )
|
||||
{
|
||||
- ctx->save.iov[iovcnt].iov_base = guest_data[i];
|
||||
+ ctx->save.iov[iovcnt].iov_base = ctx->save.guest_data[i];
|
||||
ctx->save.iov[iovcnt].iov_len = PAGE_SIZE;
|
||||
iovcnt++;
|
||||
--nr_pages;
|
||||
@@ -258,7 +259,6 @@ static int write_batch(struct xc_sr_cont
|
||||
for ( i = 0; local_pages && i < nr_pfns; ++i )
|
||||
free(local_pages[i]);
|
||||
free(local_pages);
|
||||
- free(guest_data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -836,11 +836,12 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->save.errors = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.errors));
|
||||
ctx->save.iov = malloc((4 + MAX_BATCH_SIZE) * sizeof(*ctx->save.iov));
|
||||
ctx->save.rec_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.rec_pfns));
|
||||
+ ctx->save.guest_data = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.guest_data));
|
||||
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
|
||||
|
||||
if ( !ctx->save.batch_pfns || !ctx->save.mfns || !ctx->save.types ||
|
||||
!ctx->save.errors || !ctx->save.iov || !ctx->save.rec_pfns ||
|
||||
- !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
+ !ctx->save.guest_data ||!dirty_bitmap || !ctx->save.deferred_pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
|
||||
" deferred pages");
|
||||
@@ -871,6 +872,7 @@ static void cleanup(struct xc_sr_context
|
||||
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
|
||||
NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
free(ctx->save.deferred_pages);
|
||||
+ free(ctx->save.guest_data);
|
||||
free(ctx->save.rec_pfns);
|
||||
free(ctx->save.iov);
|
||||
free(ctx->save.errors);
|
@@ -1,124 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 11:30:41 +0200
|
||||
Subject: libxc sr save iov
|
||||
|
||||
tools: save: preallocate iov array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_save.c | 34 ++++++++++++++++-----------------
|
||||
2 files changed, 18 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -247,6 +247,7 @@ struct xc_sr_context
|
||||
xen_pfn_t *mfns;
|
||||
xen_pfn_t *types;
|
||||
int *errors;
|
||||
+ struct iovec *iov;
|
||||
unsigned int nr_batch_pfns;
|
||||
unsigned long *deferred_pages;
|
||||
unsigned long nr_deferred_pages;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -96,7 +96,7 @@ static int write_batch(struct xc_sr_cont
|
||||
unsigned int nr_pfns = ctx->save.nr_batch_pfns;
|
||||
void *page, *orig_page;
|
||||
uint64_t *rec_pfns = NULL;
|
||||
- struct iovec *iov = NULL; int iovcnt = 0;
|
||||
+ int iovcnt = 0;
|
||||
struct xc_sr_rec_page_data_header hdr = { 0 };
|
||||
struct xc_sr_record rec = {
|
||||
.type = REC_TYPE_PAGE_DATA,
|
||||
@@ -108,10 +108,8 @@ static int write_batch(struct xc_sr_cont
|
||||
guest_data = calloc(nr_pfns, sizeof(*guest_data));
|
||||
/* Pointers to locally allocated pages. Need freeing. */
|
||||
local_pages = calloc(nr_pfns, sizeof(*local_pages));
|
||||
- /* iovec[] for writev(). */
|
||||
- iov = malloc((nr_pfns + 4) * sizeof(*iov));
|
||||
|
||||
- if ( !guest_data || !local_pages || !iov )
|
||||
+ if ( !guest_data || !local_pages )
|
||||
{
|
||||
ERROR("Unable to allocate arrays for a batch of %u pages",
|
||||
nr_pfns);
|
||||
@@ -221,17 +219,17 @@ static int write_batch(struct xc_sr_cont
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
rec_pfns[i] = ((uint64_t)(ctx->save.types[i]) << 32) | ctx->save.batch_pfns[i];
|
||||
|
||||
- iov[0].iov_base = &rec.type;
|
||||
- iov[0].iov_len = sizeof(rec.type);
|
||||
+ ctx->save.iov[0].iov_base = &rec.type;
|
||||
+ ctx->save.iov[0].iov_len = sizeof(rec.type);
|
||||
|
||||
- iov[1].iov_base = &rec.length;
|
||||
- iov[1].iov_len = sizeof(rec.length);
|
||||
+ ctx->save.iov[1].iov_base = &rec.length;
|
||||
+ ctx->save.iov[1].iov_len = sizeof(rec.length);
|
||||
|
||||
- iov[2].iov_base = &hdr;
|
||||
- iov[2].iov_len = sizeof(hdr);
|
||||
+ ctx->save.iov[2].iov_base = &hdr;
|
||||
+ ctx->save.iov[2].iov_len = sizeof(hdr);
|
||||
|
||||
- iov[3].iov_base = rec_pfns;
|
||||
- iov[3].iov_len = nr_pfns * sizeof(*rec_pfns);
|
||||
+ ctx->save.iov[3].iov_base = rec_pfns;
|
||||
+ ctx->save.iov[3].iov_len = nr_pfns * sizeof(*rec_pfns);
|
||||
|
||||
iovcnt = 4;
|
||||
ctx->save.pages_sent += nr_pages;
|
||||
@@ -243,15 +241,15 @@ static int write_batch(struct xc_sr_cont
|
||||
{
|
||||
if ( guest_data[i] )
|
||||
{
|
||||
- iov[iovcnt].iov_base = guest_data[i];
|
||||
- iov[iovcnt].iov_len = PAGE_SIZE;
|
||||
+ ctx->save.iov[iovcnt].iov_base = guest_data[i];
|
||||
+ ctx->save.iov[iovcnt].iov_len = PAGE_SIZE;
|
||||
iovcnt++;
|
||||
--nr_pages;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- if ( writev_exact(ctx->fd, iov, iovcnt) )
|
||||
+ if ( writev_exact(ctx->fd, ctx->save.iov, iovcnt) )
|
||||
{
|
||||
PERROR("Failed to write page data to stream");
|
||||
goto err;
|
||||
@@ -267,7 +265,6 @@ static int write_batch(struct xc_sr_cont
|
||||
xenforeignmemory_unmap(xch->fmem, guest_mapping, nr_pages_mapped);
|
||||
for ( i = 0; local_pages && i < nr_pfns; ++i )
|
||||
free(local_pages[i]);
|
||||
- free(iov);
|
||||
free(local_pages);
|
||||
free(guest_data);
|
||||
|
||||
@@ -845,10 +842,12 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->save.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.mfns));
|
||||
ctx->save.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.types));
|
||||
ctx->save.errors = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.errors));
|
||||
+ ctx->save.iov = malloc((4 + MAX_BATCH_SIZE) * sizeof(*ctx->save.iov));
|
||||
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
|
||||
|
||||
if ( !ctx->save.batch_pfns || !ctx->save.mfns || !ctx->save.types ||
|
||||
- !ctx->save.errors || !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
+ !ctx->save.errors || !ctx->save.iov || !dirty_bitmap ||
|
||||
+ !ctx->save.deferred_pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
|
||||
" deferred pages");
|
||||
@@ -879,6 +878,7 @@ static void cleanup(struct xc_sr_context
|
||||
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
|
||||
NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
free(ctx->save.deferred_pages);
|
||||
+ free(ctx->save.iov);
|
||||
free(ctx->save.errors);
|
||||
free(ctx->save.types);
|
||||
free(ctx->save.mfns);
|
@@ -1,218 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 12:47:56 +0200
|
||||
Subject: libxc sr save local_pages
|
||||
|
||||
tools: save: preallocate local_pages array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch.
|
||||
Allocate the space once.
|
||||
|
||||
Adjust the code to use the unmodified src page in case of HVM.
|
||||
In case of PV the page may need to be normalised, use a private memory
|
||||
area for this purpose.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 22 ++++++++++---------
|
||||
tools/libs/guest/xg_sr_save.c | 26 ++++------------------
|
||||
tools/libs/guest/xg_sr_save_x86_hvm.c | 5 +++--
|
||||
tools/libs/guest/xg_sr_save_x86_pv.c | 31 ++++++++++++++++++---------
|
||||
4 files changed, 40 insertions(+), 44 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -33,16 +33,12 @@ struct xc_sr_save_ops
|
||||
* Optionally transform the contents of a page from being specific to the
|
||||
* sending environment, to being generic for the stream.
|
||||
*
|
||||
- * The page of data at the end of 'page' may be a read-only mapping of a
|
||||
- * running guest; it must not be modified. If no transformation is
|
||||
- * required, the callee should leave '*pages' untouched.
|
||||
+ * The page of data '*src' may be a read-only mapping of a running guest;
|
||||
+ * it must not be modified. If no transformation is required, the callee
|
||||
+ * should leave '*src' untouched, and return it via '**ptr'.
|
||||
*
|
||||
- * If a transformation is required, the callee should allocate themselves
|
||||
- * a local page using malloc() and return it via '*page'.
|
||||
- *
|
||||
- * The caller shall free() '*page' in all cases. In the case that the
|
||||
- * callee encounters an error, it should *NOT* free() the memory it
|
||||
- * allocated for '*page'.
|
||||
+ * If a transformation is required, the callee should provide the
|
||||
+ * transformed page in a private buffer and return it via '**ptr'.
|
||||
*
|
||||
* It is valid to fail with EAGAIN if the transformation is not able to be
|
||||
* completed at this point. The page shall be retried later.
|
||||
@@ -50,7 +46,7 @@ struct xc_sr_save_ops
|
||||
* @returns 0 for success, -1 for failure, with errno appropriately set.
|
||||
*/
|
||||
int (*normalise_page)(struct xc_sr_context *ctx, xen_pfn_t type,
|
||||
- void **page);
|
||||
+ void *src, unsigned int idx, void **ptr);
|
||||
|
||||
/**
|
||||
* Set up local environment to save a domain. (Typically querying
|
||||
@@ -359,6 +355,12 @@ struct xc_sr_context
|
||||
{
|
||||
struct
|
||||
{
|
||||
+ /* Used by write_batch for modified pages. */
|
||||
+ void *normalised_pages;
|
||||
+ } save;
|
||||
+
|
||||
+ struct
|
||||
+ {
|
||||
/* State machine for the order of received records. */
|
||||
bool seen_pv_info;
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -89,11 +89,10 @@ static int write_batch(struct xc_sr_cont
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
void *guest_mapping = NULL;
|
||||
- void **local_pages = NULL;
|
||||
int rc = -1;
|
||||
unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
|
||||
unsigned int nr_pfns = ctx->save.nr_batch_pfns;
|
||||
- void *page, *orig_page;
|
||||
+ void *src;
|
||||
int iovcnt = 0;
|
||||
struct xc_sr_rec_page_data_header hdr = { 0 };
|
||||
struct xc_sr_record rec = {
|
||||
@@ -102,16 +101,6 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
assert(nr_pfns != 0);
|
||||
|
||||
- /* Pointers to locally allocated pages. Need freeing. */
|
||||
- local_pages = calloc(nr_pfns, sizeof(*local_pages));
|
||||
-
|
||||
- if ( !local_pages )
|
||||
- {
|
||||
- ERROR("Unable to allocate arrays for a batch of %u pages",
|
||||
- nr_pfns);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
ctx->save.types[i] = ctx->save.mfns[i] = ctx->save.ops.pfn_to_gfn(ctx,
|
||||
@@ -175,11 +164,9 @@ static int write_batch(struct xc_sr_cont
|
||||
goto err;
|
||||
}
|
||||
|
||||
- orig_page = page = guest_mapping + (p * PAGE_SIZE);
|
||||
- rc = ctx->save.ops.normalise_page(ctx, ctx->save.types[i], &page);
|
||||
-
|
||||
- if ( orig_page != page )
|
||||
- local_pages[i] = page;
|
||||
+ src = guest_mapping + (p * PAGE_SIZE);
|
||||
+ rc = ctx->save.ops.normalise_page(ctx, ctx->save.types[i], src, i,
|
||||
+ &ctx->save.guest_data[i]);
|
||||
|
||||
if ( rc )
|
||||
{
|
||||
@@ -194,8 +181,6 @@ static int write_batch(struct xc_sr_cont
|
||||
else
|
||||
goto err;
|
||||
}
|
||||
- else
|
||||
- ctx->save.guest_data[i] = page;
|
||||
|
||||
rc = -1;
|
||||
++p;
|
||||
@@ -256,9 +241,6 @@ static int write_batch(struct xc_sr_cont
|
||||
err:
|
||||
if ( guest_mapping )
|
||||
xenforeignmemory_unmap(xch->fmem, guest_mapping, nr_pages_mapped);
|
||||
- for ( i = 0; local_pages && i < nr_pfns; ++i )
|
||||
- free(local_pages[i]);
|
||||
- free(local_pages);
|
||||
|
||||
return rc;
|
||||
}
|
||||
--- a/tools/libs/guest/xg_sr_save_x86_hvm.c
|
||||
+++ b/tools/libs/guest/xg_sr_save_x86_hvm.c
|
||||
@@ -129,9 +129,10 @@ static xen_pfn_t x86_hvm_pfn_to_gfn(cons
|
||||
return pfn;
|
||||
}
|
||||
|
||||
-static int x86_hvm_normalise_page(struct xc_sr_context *ctx,
|
||||
- xen_pfn_t type, void **page)
|
||||
+static int x86_hvm_normalise_page(struct xc_sr_context *ctx, xen_pfn_t type,
|
||||
+ void *src, unsigned int idx, void **ptr)
|
||||
{
|
||||
+ *ptr = src;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_save_x86_pv.c
|
||||
+++ b/tools/libs/guest/xg_sr_save_x86_pv.c
|
||||
@@ -999,29 +999,31 @@ static xen_pfn_t x86_pv_pfn_to_gfn(const
|
||||
* save_ops function. Performs pagetable normalisation on appropriate pages.
|
||||
*/
|
||||
static int x86_pv_normalise_page(struct xc_sr_context *ctx, xen_pfn_t type,
|
||||
- void **page)
|
||||
+ void *src, unsigned int idx, void **ptr)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- void *local_page;
|
||||
+ void *dst;
|
||||
int rc;
|
||||
|
||||
type &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
|
||||
|
||||
if ( type < XEN_DOMCTL_PFINFO_L1TAB || type > XEN_DOMCTL_PFINFO_L4TAB )
|
||||
+ {
|
||||
+ *ptr = src;
|
||||
return 0;
|
||||
+ }
|
||||
|
||||
- local_page = malloc(PAGE_SIZE);
|
||||
- if ( !local_page )
|
||||
+ if ( idx >= MAX_BATCH_SIZE )
|
||||
{
|
||||
- ERROR("Unable to allocate scratch page");
|
||||
- rc = -1;
|
||||
- goto out;
|
||||
+ ERROR("idx %u out of range", idx);
|
||||
+ errno = ERANGE;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
- rc = normalise_pagetable(ctx, *page, local_page, type);
|
||||
- *page = local_page;
|
||||
+ dst = ctx->x86.pv.save.normalised_pages + (idx * PAGE_SIZE);
|
||||
+ rc = normalise_pagetable(ctx, src, dst, type);
|
||||
+ *ptr = dst;
|
||||
|
||||
- out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1031,8 +1033,16 @@ static int x86_pv_normalise_page(struct
|
||||
*/
|
||||
static int x86_pv_setup(struct xc_sr_context *ctx)
|
||||
{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
int rc;
|
||||
|
||||
+ ctx->x86.pv.save.normalised_pages = malloc(MAX_BATCH_SIZE * PAGE_SIZE);
|
||||
+ if ( !ctx->x86.pv.save.normalised_pages )
|
||||
+ {
|
||||
+ PERROR("Failed to allocate normalised_pages");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
rc = x86_pv_domain_info(ctx);
|
||||
if ( rc )
|
||||
return rc;
|
||||
@@ -1118,6 +1128,7 @@ static int x86_pv_check_vm_state(struct
|
||||
|
||||
static int x86_pv_cleanup(struct xc_sr_context *ctx)
|
||||
{
|
||||
+ free(ctx->x86.pv.save.normalised_pages);
|
||||
free(ctx->x86.pv.p2m_pfns);
|
||||
|
||||
if ( ctx->x86.pv.p2m )
|
@@ -1,132 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 11:20:36 +0200
|
||||
Subject: libxc sr save mfns
|
||||
|
||||
tools: save: preallocate mfns array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch, see add_to_batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_save.c | 25 +++++++++++++------------
|
||||
2 files changed, 14 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -244,6 +244,7 @@ struct xc_sr_context
|
||||
struct precopy_stats stats;
|
||||
|
||||
xen_pfn_t *batch_pfns;
|
||||
+ xen_pfn_t *mfns;
|
||||
unsigned int nr_batch_pfns;
|
||||
unsigned long *deferred_pages;
|
||||
unsigned long nr_deferred_pages;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -88,7 +88,7 @@ static int write_checkpoint_record(struc
|
||||
static int write_batch(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- xen_pfn_t *mfns = NULL, *types = NULL;
|
||||
+ xen_pfn_t *types = NULL;
|
||||
void *guest_mapping = NULL;
|
||||
void **guest_data = NULL;
|
||||
void **local_pages = NULL;
|
||||
@@ -105,8 +105,6 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
assert(nr_pfns != 0);
|
||||
|
||||
- /* Mfns of the batch pfns. */
|
||||
- mfns = malloc(nr_pfns * sizeof(*mfns));
|
||||
/* Types of the batch pfns. */
|
||||
types = malloc(nr_pfns * sizeof(*types));
|
||||
/* Errors from attempting to map the gfns. */
|
||||
@@ -118,7 +116,7 @@ static int write_batch(struct xc_sr_cont
|
||||
/* iovec[] for writev(). */
|
||||
iov = malloc((nr_pfns + 4) * sizeof(*iov));
|
||||
|
||||
- if ( !mfns || !types || !errors || !guest_data || !local_pages || !iov )
|
||||
+ if ( !types || !errors || !guest_data || !local_pages || !iov )
|
||||
{
|
||||
ERROR("Unable to allocate arrays for a batch of %u pages",
|
||||
nr_pfns);
|
||||
@@ -127,11 +125,11 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
- types[i] = mfns[i] = ctx->save.ops.pfn_to_gfn(ctx,
|
||||
+ types[i] = ctx->save.mfns[i] = ctx->save.ops.pfn_to_gfn(ctx,
|
||||
ctx->save.batch_pfns[i]);
|
||||
|
||||
/* Likely a ballooned page. */
|
||||
- if ( mfns[i] == INVALID_MFN )
|
||||
+ if ( ctx->save.mfns[i] == INVALID_MFN )
|
||||
{
|
||||
set_bit(ctx->save.batch_pfns[i], ctx->save.deferred_pages);
|
||||
++ctx->save.nr_deferred_pages;
|
||||
@@ -150,20 +148,21 @@ static int write_batch(struct xc_sr_cont
|
||||
{
|
||||
if ( !is_known_page_type(types[i]) )
|
||||
{
|
||||
- ERROR("Unknown type %#"PRIpfn" for pfn %#"PRIpfn, types[i], mfns[i]);
|
||||
+ ERROR("Unknown type %#"PRIpfn" for pfn %#"PRIpfn,
|
||||
+ types[i], ctx->save.mfns[i]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ( !page_type_has_stream_data(types[i]) )
|
||||
continue;
|
||||
|
||||
- mfns[nr_pages++] = mfns[i];
|
||||
+ ctx->save.mfns[nr_pages++] = ctx->save.mfns[i];
|
||||
}
|
||||
|
||||
if ( nr_pages > 0 )
|
||||
{
|
||||
guest_mapping = xenforeignmemory_map(
|
||||
- xch->fmem, ctx->domid, PROT_READ, nr_pages, mfns, errors);
|
||||
+ xch->fmem, ctx->domid, PROT_READ, nr_pages, ctx->save.mfns, errors);
|
||||
if ( !guest_mapping )
|
||||
{
|
||||
PERROR("Failed to map guest pages");
|
||||
@@ -179,7 +178,7 @@ static int write_batch(struct xc_sr_cont
|
||||
if ( errors[p] )
|
||||
{
|
||||
ERROR("Mapping of pfn %#"PRIpfn" (mfn %#"PRIpfn") failed %d",
|
||||
- ctx->save.batch_pfns[i], mfns[p], errors[p]);
|
||||
+ ctx->save.batch_pfns[i], ctx->save.mfns[p], errors[p]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -277,7 +276,6 @@ static int write_batch(struct xc_sr_cont
|
||||
free(guest_data);
|
||||
free(errors);
|
||||
free(types);
|
||||
- free(mfns);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -850,9 +848,11 @@ static int setup(struct xc_sr_context *c
|
||||
xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
ctx->save.batch_pfns = malloc(MAX_BATCH_SIZE *
|
||||
sizeof(*ctx->save.batch_pfns));
|
||||
+ ctx->save.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.mfns));
|
||||
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
|
||||
|
||||
- if ( !ctx->save.batch_pfns || !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
+ if ( !ctx->save.batch_pfns || !ctx->save.mfns ||
|
||||
+ !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
|
||||
" deferred pages");
|
||||
@@ -883,6 +883,7 @@ static void cleanup(struct xc_sr_context
|
||||
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
|
||||
NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
free(ctx->save.deferred_pages);
|
||||
+ free(ctx->save.mfns);
|
||||
free(ctx->save.batch_pfns);
|
||||
}
|
||||
|
@@ -1,110 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 11:34:00 +0200
|
||||
Subject: libxc sr save rec_pfns
|
||||
|
||||
tools: save: preallocate rec_pfns array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_save.c | 28 +++++++++++-----------------
|
||||
2 files changed, 12 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -248,6 +248,7 @@ struct xc_sr_context
|
||||
xen_pfn_t *types;
|
||||
int *errors;
|
||||
struct iovec *iov;
|
||||
+ uint64_t *rec_pfns;
|
||||
unsigned int nr_batch_pfns;
|
||||
unsigned long *deferred_pages;
|
||||
unsigned long nr_deferred_pages;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -95,7 +95,6 @@ static int write_batch(struct xc_sr_cont
|
||||
unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
|
||||
unsigned int nr_pfns = ctx->save.nr_batch_pfns;
|
||||
void *page, *orig_page;
|
||||
- uint64_t *rec_pfns = NULL;
|
||||
int iovcnt = 0;
|
||||
struct xc_sr_rec_page_data_header hdr = { 0 };
|
||||
struct xc_sr_record rec = {
|
||||
@@ -202,22 +201,15 @@ static int write_batch(struct xc_sr_cont
|
||||
}
|
||||
}
|
||||
|
||||
- rec_pfns = malloc(nr_pfns * sizeof(*rec_pfns));
|
||||
- if ( !rec_pfns )
|
||||
- {
|
||||
- ERROR("Unable to allocate %zu bytes of memory for page data pfn list",
|
||||
- nr_pfns * sizeof(*rec_pfns));
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
hdr.count = nr_pfns;
|
||||
|
||||
rec.length = sizeof(hdr);
|
||||
- rec.length += nr_pfns * sizeof(*rec_pfns);
|
||||
+ rec.length += nr_pfns * sizeof(*ctx->save.rec_pfns);
|
||||
rec.length += nr_pages * PAGE_SIZE;
|
||||
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
- rec_pfns[i] = ((uint64_t)(ctx->save.types[i]) << 32) | ctx->save.batch_pfns[i];
|
||||
+ ctx->save.rec_pfns[i] = ((uint64_t)(ctx->save.types[i]) << 32) |
|
||||
+ ctx->save.batch_pfns[i];
|
||||
|
||||
ctx->save.iov[0].iov_base = &rec.type;
|
||||
ctx->save.iov[0].iov_len = sizeof(rec.type);
|
||||
@@ -228,12 +220,13 @@ static int write_batch(struct xc_sr_cont
|
||||
ctx->save.iov[2].iov_base = &hdr;
|
||||
ctx->save.iov[2].iov_len = sizeof(hdr);
|
||||
|
||||
- ctx->save.iov[3].iov_base = rec_pfns;
|
||||
- ctx->save.iov[3].iov_len = nr_pfns * sizeof(*rec_pfns);
|
||||
+ ctx->save.iov[3].iov_base = ctx->save.rec_pfns;
|
||||
+ ctx->save.iov[3].iov_len = nr_pfns * sizeof(*ctx->save.rec_pfns);
|
||||
|
||||
iovcnt = 4;
|
||||
ctx->save.pages_sent += nr_pages;
|
||||
- ctx->save.overhead_sent += sizeof(rec) + sizeof(hdr) + nr_pfns * sizeof(*rec_pfns);
|
||||
+ ctx->save.overhead_sent += sizeof(rec) + sizeof(hdr) +
|
||||
+ nr_pfns * sizeof(*ctx->save.rec_pfns);
|
||||
|
||||
if ( nr_pages )
|
||||
{
|
||||
@@ -260,7 +253,6 @@ static int write_batch(struct xc_sr_cont
|
||||
rc = ctx->save.nr_batch_pfns = 0;
|
||||
|
||||
err:
|
||||
- free(rec_pfns);
|
||||
if ( guest_mapping )
|
||||
xenforeignmemory_unmap(xch->fmem, guest_mapping, nr_pages_mapped);
|
||||
for ( i = 0; local_pages && i < nr_pfns; ++i )
|
||||
@@ -843,11 +835,12 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->save.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.types));
|
||||
ctx->save.errors = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.errors));
|
||||
ctx->save.iov = malloc((4 + MAX_BATCH_SIZE) * sizeof(*ctx->save.iov));
|
||||
+ ctx->save.rec_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.rec_pfns));
|
||||
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
|
||||
|
||||
if ( !ctx->save.batch_pfns || !ctx->save.mfns || !ctx->save.types ||
|
||||
- !ctx->save.errors || !ctx->save.iov || !dirty_bitmap ||
|
||||
- !ctx->save.deferred_pages )
|
||||
+ !ctx->save.errors || !ctx->save.iov || !ctx->save.rec_pfns ||
|
||||
+ !dirty_bitmap || !ctx->save.deferred_pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
|
||||
" deferred pages");
|
||||
@@ -878,6 +871,7 @@ static void cleanup(struct xc_sr_context
|
||||
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
|
||||
NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
free(ctx->save.deferred_pages);
|
||||
+ free(ctx->save.rec_pfns);
|
||||
free(ctx->save.iov);
|
||||
free(ctx->save.errors);
|
||||
free(ctx->save.types);
|
@@ -1,116 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 15:39:59 +0200
|
||||
Subject: libxc sr save show_transfer_rate
|
||||
|
||||
tools: show migration transfer rate in send_dirty_pages
|
||||
|
||||
Show how fast domU pages are transferred in each iteration.
|
||||
|
||||
The relevant data is how fast the pfns travel, not so much how much
|
||||
protocol overhead exists. So the reported MiB/sec is just for pfns.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
|
||||
v02:
|
||||
- rearrange MiB_sec calculation (jgross)
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 2 ++
|
||||
tools/libs/guest/xg_sr_save.c | 46 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 48 insertions(+)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -238,6 +238,8 @@ struct xc_sr_context
|
||||
bool debug;
|
||||
|
||||
unsigned long p2m_size;
|
||||
+ size_t pages_sent;
|
||||
+ size_t overhead_sent;
|
||||
|
||||
struct precopy_stats stats;
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <arpa/inet.h>
|
||||
+#include <time.h>
|
||||
|
||||
#include "xg_sr_common.h"
|
||||
|
||||
@@ -238,6 +239,8 @@ static int write_batch(struct xc_sr_cont
|
||||
iov[3].iov_len = nr_pfns * sizeof(*rec_pfns);
|
||||
|
||||
iovcnt = 4;
|
||||
+ ctx->save.pages_sent += nr_pages;
|
||||
+ ctx->save.overhead_sent += sizeof(rec) + sizeof(hdr) + nr_pfns * sizeof(*rec_pfns);
|
||||
|
||||
if ( nr_pages )
|
||||
{
|
||||
@@ -356,6 +359,42 @@ static int suspend_domain(struct xc_sr_c
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void show_transfer_rate(struct xc_sr_context *ctx, struct timespec *start)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ struct timespec end = {}, diff = {};
|
||||
+ size_t ms, MiB_sec;
|
||||
+
|
||||
+ if (!ctx->save.pages_sent)
|
||||
+ return;
|
||||
+
|
||||
+ if ( clock_gettime(CLOCK_MONOTONIC, &end) )
|
||||
+ PERROR("clock_gettime");
|
||||
+
|
||||
+ if ( (end.tv_nsec - start->tv_nsec) < 0 )
|
||||
+ {
|
||||
+ diff.tv_sec = end.tv_sec - start->tv_sec - 1;
|
||||
+ diff.tv_nsec = end.tv_nsec - start->tv_nsec + (1000U*1000U*1000U);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ diff.tv_sec = end.tv_sec - start->tv_sec;
|
||||
+ diff.tv_nsec = end.tv_nsec - start->tv_nsec;
|
||||
+ }
|
||||
+
|
||||
+ ms = (diff.tv_nsec / (1000U*1000U));
|
||||
+ ms += (diff.tv_sec * 1000U);
|
||||
+ if (!ms)
|
||||
+ ms = 1;
|
||||
+
|
||||
+ MiB_sec = (ctx->save.pages_sent * PAGE_SIZE * 1000U) / ms / (1024U*1024U);
|
||||
+
|
||||
+ errno = 0;
|
||||
+ IPRINTF("%s: %zu bytes + %zu pages in %ld.%09ld sec, %zu MiB/sec", __func__,
|
||||
+ ctx->save.overhead_sent, ctx->save.pages_sent,
|
||||
+ diff.tv_sec, diff.tv_nsec, MiB_sec);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Send a subset of pages in the guests p2m, according to the dirty bitmap.
|
||||
* Used for each subsequent iteration of the live migration loop.
|
||||
@@ -369,9 +408,15 @@ static int send_dirty_pages(struct xc_sr
|
||||
xen_pfn_t p;
|
||||
unsigned long written;
|
||||
int rc;
|
||||
+ struct timespec start = {};
|
||||
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
|
||||
&ctx->save.dirty_bitmap_hbuf);
|
||||
|
||||
+ ctx->save.pages_sent = 0;
|
||||
+ ctx->save.overhead_sent = 0;
|
||||
+ if ( clock_gettime(CLOCK_MONOTONIC, &start) )
|
||||
+ PERROR("clock_gettime");
|
||||
+
|
||||
for ( p = 0, written = 0; p < ctx->save.p2m_size; ++p )
|
||||
{
|
||||
if ( !test_bit(p, dirty_bitmap) )
|
||||
@@ -395,6 +440,7 @@ static int send_dirty_pages(struct xc_sr
|
||||
if ( written > entries )
|
||||
DPRINTF("Bitmap contained more entries than expected...");
|
||||
|
||||
+ show_transfer_rate(ctx, &start);
|
||||
xc_report_progress_step(xch, entries, entries);
|
||||
|
||||
return ctx->save.ops.check_vm_state(ctx);
|
@@ -1,154 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 23 Oct 2020 11:23:51 +0200
|
||||
Subject: libxc sr save types
|
||||
|
||||
tools: save: preallocate types array
|
||||
|
||||
Remove repeated allocation from migration loop. There will never be
|
||||
more than MAX_BATCH_SIZE pages to process in a batch.
|
||||
Allocate the space once.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 1 +
|
||||
tools/libs/guest/xg_sr_save.c | 28 +++++++++++++---------------
|
||||
2 files changed, 14 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -245,6 +245,7 @@ struct xc_sr_context
|
||||
|
||||
xen_pfn_t *batch_pfns;
|
||||
xen_pfn_t *mfns;
|
||||
+ xen_pfn_t *types;
|
||||
unsigned int nr_batch_pfns;
|
||||
unsigned long *deferred_pages;
|
||||
unsigned long nr_deferred_pages;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -88,7 +88,6 @@ static int write_checkpoint_record(struc
|
||||
static int write_batch(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- xen_pfn_t *types = NULL;
|
||||
void *guest_mapping = NULL;
|
||||
void **guest_data = NULL;
|
||||
void **local_pages = NULL;
|
||||
@@ -105,8 +104,6 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
assert(nr_pfns != 0);
|
||||
|
||||
- /* Types of the batch pfns. */
|
||||
- types = malloc(nr_pfns * sizeof(*types));
|
||||
/* Errors from attempting to map the gfns. */
|
||||
errors = malloc(nr_pfns * sizeof(*errors));
|
||||
/* Pointers to page data to send. Mapped gfns or local allocations. */
|
||||
@@ -116,7 +113,7 @@ static int write_batch(struct xc_sr_cont
|
||||
/* iovec[] for writev(). */
|
||||
iov = malloc((nr_pfns + 4) * sizeof(*iov));
|
||||
|
||||
- if ( !types || !errors || !guest_data || !local_pages || !iov )
|
||||
+ if ( !errors || !guest_data || !local_pages || !iov )
|
||||
{
|
||||
ERROR("Unable to allocate arrays for a batch of %u pages",
|
||||
nr_pfns);
|
||||
@@ -125,7 +122,7 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
- types[i] = ctx->save.mfns[i] = ctx->save.ops.pfn_to_gfn(ctx,
|
||||
+ ctx->save.types[i] = ctx->save.mfns[i] = ctx->save.ops.pfn_to_gfn(ctx,
|
||||
ctx->save.batch_pfns[i]);
|
||||
|
||||
/* Likely a ballooned page. */
|
||||
@@ -136,7 +133,7 @@ static int write_batch(struct xc_sr_cont
|
||||
}
|
||||
}
|
||||
|
||||
- rc = xc_get_pfn_type_batch(xch, ctx->domid, nr_pfns, types);
|
||||
+ rc = xc_get_pfn_type_batch(xch, ctx->domid, nr_pfns, ctx->save.types);
|
||||
if ( rc )
|
||||
{
|
||||
PERROR("Failed to get types for pfn batch");
|
||||
@@ -146,14 +143,14 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
- if ( !is_known_page_type(types[i]) )
|
||||
+ if ( !is_known_page_type(ctx->save.types[i]) )
|
||||
{
|
||||
ERROR("Unknown type %#"PRIpfn" for pfn %#"PRIpfn,
|
||||
- types[i], ctx->save.mfns[i]);
|
||||
+ ctx->save.types[i], ctx->save.mfns[i]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if ( !page_type_has_stream_data(types[i]) )
|
||||
+ if ( !page_type_has_stream_data(ctx->save.types[i]) )
|
||||
continue;
|
||||
|
||||
ctx->save.mfns[nr_pages++] = ctx->save.mfns[i];
|
||||
@@ -172,7 +169,7 @@ static int write_batch(struct xc_sr_cont
|
||||
|
||||
for ( i = 0, p = 0; i < nr_pfns; ++i )
|
||||
{
|
||||
- if ( !page_type_has_stream_data(types[i]) )
|
||||
+ if ( !page_type_has_stream_data(ctx->save.types[i]) )
|
||||
continue;
|
||||
|
||||
if ( errors[p] )
|
||||
@@ -183,7 +180,7 @@ static int write_batch(struct xc_sr_cont
|
||||
}
|
||||
|
||||
orig_page = page = guest_mapping + (p * PAGE_SIZE);
|
||||
- rc = ctx->save.ops.normalise_page(ctx, types[i], &page);
|
||||
+ rc = ctx->save.ops.normalise_page(ctx, ctx->save.types[i], &page);
|
||||
|
||||
if ( orig_page != page )
|
||||
local_pages[i] = page;
|
||||
@@ -194,7 +191,7 @@ static int write_batch(struct xc_sr_cont
|
||||
{
|
||||
set_bit(ctx->save.batch_pfns[i], ctx->save.deferred_pages);
|
||||
++ctx->save.nr_deferred_pages;
|
||||
- types[i] = XEN_DOMCTL_PFINFO_XTAB;
|
||||
+ ctx->save.types[i] = XEN_DOMCTL_PFINFO_XTAB;
|
||||
--nr_pages;
|
||||
}
|
||||
else
|
||||
@@ -223,7 +220,7 @@ static int write_batch(struct xc_sr_cont
|
||||
rec.length += nr_pages * PAGE_SIZE;
|
||||
|
||||
for ( i = 0; i < nr_pfns; ++i )
|
||||
- rec_pfns[i] = ((uint64_t)(types[i]) << 32) | ctx->save.batch_pfns[i];
|
||||
+ rec_pfns[i] = ((uint64_t)(ctx->save.types[i]) << 32) | ctx->save.batch_pfns[i];
|
||||
|
||||
iov[0].iov_base = &rec.type;
|
||||
iov[0].iov_len = sizeof(rec.type);
|
||||
@@ -275,7 +272,6 @@ static int write_batch(struct xc_sr_cont
|
||||
free(local_pages);
|
||||
free(guest_data);
|
||||
free(errors);
|
||||
- free(types);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -849,9 +845,10 @@ static int setup(struct xc_sr_context *c
|
||||
ctx->save.batch_pfns = malloc(MAX_BATCH_SIZE *
|
||||
sizeof(*ctx->save.batch_pfns));
|
||||
ctx->save.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.mfns));
|
||||
+ ctx->save.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.types));
|
||||
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
|
||||
|
||||
- if ( !ctx->save.batch_pfns || !ctx->save.mfns ||
|
||||
+ if ( !ctx->save.batch_pfns || !ctx->save.mfns || !ctx->save.types ||
|
||||
!dirty_bitmap || !ctx->save.deferred_pages )
|
||||
{
|
||||
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
|
||||
@@ -883,6 +880,7 @@ static void cleanup(struct xc_sr_context
|
||||
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
|
||||
NRPAGES(bitmap_size(ctx->save.p2m_size)));
|
||||
free(ctx->save.deferred_pages);
|
||||
+ free(ctx->save.types);
|
||||
free(ctx->save.mfns);
|
||||
free(ctx->save.batch_pfns);
|
||||
}
|
@@ -1,263 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Thu, 4 Feb 2021 20:33:53 +0100
|
||||
Subject: libxc sr track migration time
|
||||
|
||||
Track live migration state unconditionally in logfiles to see how long a domU was suspended.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/include/xentoollog.h | 1 +
|
||||
tools/libs/ctrl/xc_domain.c | 12 +++++--
|
||||
tools/libs/ctrl/xc_private.h | 9 +++++
|
||||
tools/libs/guest/xg_resume.c | 5 ++-
|
||||
tools/libs/guest/xg_sr_common.c | 59 ++++++++++++++++++++++++++++++++
|
||||
tools/libs/guest/xg_sr_common.h | 3 ++
|
||||
tools/libs/guest/xg_sr_restore.c | 3 ++
|
||||
tools/libs/guest/xg_sr_save.c | 6 +++-
|
||||
tools/xl/xl.c | 2 ++
|
||||
9 files changed, 96 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/tools/include/xentoollog.h
|
||||
+++ b/tools/include/xentoollog.h
|
||||
@@ -133,6 +133,7 @@ const char *xtl_level_to_string(xentooll
|
||||
});
|
||||
|
||||
|
||||
+#define XL_NO_SUSEINFO "XL_NO_SUSEINFO"
|
||||
#endif /* XENTOOLLOG_H */
|
||||
|
||||
/*
|
||||
--- a/tools/libs/ctrl/xc_domain.c
|
||||
+++ b/tools/libs/ctrl/xc_domain.c
|
||||
@@ -66,20 +66,28 @@ int xc_domain_cacheflush(xc_interface *x
|
||||
int xc_domain_pause(xc_interface *xch,
|
||||
uint32_t domid)
|
||||
{
|
||||
+ int ret;
|
||||
DECLARE_DOMCTL;
|
||||
domctl.cmd = XEN_DOMCTL_pausedomain;
|
||||
domctl.domain = domid;
|
||||
- return do_domctl(xch, &domctl);
|
||||
+ ret = do_domctl(xch, &domctl);
|
||||
+ if (getenv(XL_NO_SUSEINFO) == NULL)
|
||||
+ SUSEINFO("domid %u: %s returned %d", domid, __func__, ret);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
|
||||
int xc_domain_unpause(xc_interface *xch,
|
||||
uint32_t domid)
|
||||
{
|
||||
+ int ret;
|
||||
DECLARE_DOMCTL;
|
||||
domctl.cmd = XEN_DOMCTL_unpausedomain;
|
||||
domctl.domain = domid;
|
||||
- return do_domctl(xch, &domctl);
|
||||
+ ret = do_domctl(xch, &domctl);
|
||||
+ if (getenv(XL_NO_SUSEINFO) == NULL)
|
||||
+ SUSEINFO("domid %u: %s returned %d", domid, __func__, ret);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
|
||||
--- a/tools/libs/ctrl/xc_private.h
|
||||
+++ b/tools/libs/ctrl/xc_private.h
|
||||
@@ -42,6 +42,15 @@
|
||||
|
||||
#include <xen-tools/common-macros.h>
|
||||
|
||||
+/*
|
||||
+ * Using loglevel ERROR to make sure the intended informational messages appear
|
||||
+ * in libvirts libxl-driver.log
|
||||
+ */
|
||||
+#define SUSEINFO(_m, _a...) do { int ERROR_errno = errno; \
|
||||
+ xc_report(xch, xch->error_handler, XTL_ERROR, XC_ERROR_NONE, "SUSEINFO: " _m , ## _a ); \
|
||||
+ errno = ERROR_errno; \
|
||||
+ } while (0)
|
||||
+
|
||||
#if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG) && !defined(__MINIOS__)
|
||||
/* Compile in Valgrind client requests? */
|
||||
#include <valgrind/memcheck.h>
|
||||
--- a/tools/libs/guest/xg_resume.c
|
||||
+++ b/tools/libs/guest/xg_resume.c
|
||||
@@ -259,7 +259,10 @@ out:
|
||||
*/
|
||||
int xc_domain_resume(xc_interface *xch, uint32_t domid, int fast)
|
||||
{
|
||||
- return (fast
|
||||
+ int ret = (fast
|
||||
? xc_domain_resume_cooperative(xch, domid)
|
||||
: xc_domain_resume_any(xch, domid));
|
||||
+ if (getenv(XL_NO_SUSEINFO) == NULL)
|
||||
+ SUSEINFO("domid %u: %s%s returned %d", domid, __func__, fast ? " fast" : "", ret);
|
||||
+ return ret;
|
||||
}
|
||||
--- a/tools/libs/guest/xg_sr_common.c
|
||||
+++ b/tools/libs/guest/xg_sr_common.c
|
||||
@@ -163,6 +163,65 @@ static void __attribute__((unused)) buil
|
||||
BUILD_BUG_ON(sizeof(struct xc_sr_rec_hvm_params) != 8);
|
||||
}
|
||||
|
||||
+/* Write a two-character hex representation of 'byte' to digits[].
|
||||
+ Pre-condition: sizeof(digits) >= 2 */
|
||||
+static void byte_to_hex(char *digits, const uint8_t byte)
|
||||
+{
|
||||
+ uint8_t nybbel = byte >> 4;
|
||||
+
|
||||
+ if ( nybbel > 9 )
|
||||
+ digits[0] = 'a' + nybbel-10;
|
||||
+ else
|
||||
+ digits[0] = '0' + nybbel;
|
||||
+
|
||||
+ nybbel = byte & 0x0f;
|
||||
+ if ( nybbel > 9 )
|
||||
+ digits[1] = 'a' + nybbel-10;
|
||||
+ else
|
||||
+ digits[1] = '0' + nybbel;
|
||||
+}
|
||||
+
|
||||
+/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
|
||||
+ string.
|
||||
+
|
||||
+ Pre-condition: sizeof(dest) >= 37 */
|
||||
+void sr_uuid_to_string(char *dest, const uint8_t *uuid)
|
||||
+{
|
||||
+ int i = 0;
|
||||
+ char *p = dest;
|
||||
+
|
||||
+ for (; i < 4; i++ )
|
||||
+ {
|
||||
+ byte_to_hex(p, uuid[i]);
|
||||
+ p += 2;
|
||||
+ }
|
||||
+ *p++ = '-';
|
||||
+ for (; i < 6; i++ )
|
||||
+ {
|
||||
+ byte_to_hex(p, uuid[i]);
|
||||
+ p += 2;
|
||||
+ }
|
||||
+ *p++ = '-';
|
||||
+ for (; i < 8; i++ )
|
||||
+ {
|
||||
+ byte_to_hex(p, uuid[i]);
|
||||
+ p += 2;
|
||||
+ }
|
||||
+ *p++ = '-';
|
||||
+ for (; i < 10; i++ )
|
||||
+ {
|
||||
+ byte_to_hex(p, uuid[i]);
|
||||
+ p += 2;
|
||||
+ }
|
||||
+ *p++ = '-';
|
||||
+ for (; i < 16; i++ )
|
||||
+ {
|
||||
+ byte_to_hex(p, uuid[i]);
|
||||
+ p += 2;
|
||||
+ }
|
||||
+ *p = '\0';
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Expand the tracking structures as needed.
|
||||
* To avoid realloc()ing too excessively, the size increased to the nearest
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -294,6 +294,7 @@ struct xc_sr_context
|
||||
xc_stream_type_t stream_type;
|
||||
|
||||
xc_domaininfo_t dominfo;
|
||||
+ char uuid[16*2+4+1];
|
||||
|
||||
union /* Common save or restore data. */
|
||||
{
|
||||
@@ -505,6 +506,8 @@ extern struct xc_sr_save_ops save_ops_x8
|
||||
extern struct xc_sr_restore_ops restore_ops_x86_pv;
|
||||
extern struct xc_sr_restore_ops restore_ops_x86_hvm;
|
||||
|
||||
+extern void sr_uuid_to_string(char *dest, const uint8_t *uuid);
|
||||
+
|
||||
struct xc_sr_record
|
||||
{
|
||||
uint32_t type;
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -871,6 +871,8 @@ static int restore(struct xc_sr_context
|
||||
struct xc_sr_rhdr rhdr;
|
||||
int rc, saved_rc = 0, saved_errno = 0;
|
||||
|
||||
+ SUSEINFO("domid %u: %s %s start", ctx->domid, ctx->uuid, __func__);
|
||||
+ DPRINTF("domid %u: max_pages %lx tot_pages %lx p2m_size %lx", ctx->domid, ctx->restore.max_pages, ctx->restore.tot_pages, ctx->restore.p2m_size);
|
||||
IPRINTF("Restoring domain");
|
||||
|
||||
rc = setup(ctx);
|
||||
@@ -946,6 +948,7 @@ static int restore(struct xc_sr_context
|
||||
PERROR("Restore failed");
|
||||
|
||||
done:
|
||||
+ SUSEINFO("domid %u: %s done", ctx->domid, __func__);
|
||||
cleanup(ctx);
|
||||
|
||||
if ( saved_rc )
|
||||
@@ -1011,6 +1014,7 @@ int xc_domain_restore(xc_interface *xch,
|
||||
io_fd, dom, hvm, stream_type);
|
||||
|
||||
ctx.domid = dom;
|
||||
+ sr_uuid_to_string(ctx.uuid, ctx.dominfo.handle);
|
||||
|
||||
if ( read_headers(&ctx) )
|
||||
return -1;
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -353,7 +353,7 @@ static void show_transfer_rate(struct xc
|
||||
MiB_sec = (ctx->save.pages_sent * PAGE_SIZE * 1000U) / ms / (1024U*1024U);
|
||||
|
||||
errno = 0;
|
||||
- IPRINTF("%s: %zu bytes + %zu pages in %ld.%09ld sec, %zu MiB/sec", __func__,
|
||||
+ SUSEINFO("domid %u: %zu bytes + %zu pages in %ld.%09ld sec, %zu MiB/sec", ctx->domid,
|
||||
ctx->save.overhead_sent, ctx->save.pages_sent,
|
||||
diff.tv_sec, diff.tv_nsec, MiB_sec);
|
||||
}
|
||||
@@ -875,13 +875,16 @@ static int save(struct xc_sr_context *ct
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
int rc, saved_rc = 0, saved_errno = 0;
|
||||
+ unsigned long tot_pages = ctx->dominfo.tot_pages;
|
||||
|
||||
+ SUSEINFO("domid %u: %s %s start, %lu pages allocated", ctx->domid, ctx->uuid, __func__, tot_pages);
|
||||
IPRINTF("Saving domain %d, type %s",
|
||||
ctx->domid, dhdr_type_to_str(guest_type));
|
||||
|
||||
rc = setup(ctx);
|
||||
if ( rc )
|
||||
goto err;
|
||||
+ SUSEINFO("domid %u: p2m_size %lx", ctx->domid, ctx->save.p2m_size);
|
||||
|
||||
xc_report_progress_single(xch, "Start of stream");
|
||||
|
||||
@@ -995,6 +998,7 @@ static int save(struct xc_sr_context *ct
|
||||
PERROR("Save failed");
|
||||
|
||||
done:
|
||||
+ SUSEINFO("domid %u: %s done", ctx->domid, __func__);
|
||||
cleanup(ctx);
|
||||
|
||||
if ( saved_rc )
|
||||
@@ -1054,6 +1058,7 @@ int xc_domain_save(xc_interface *xch, in
|
||||
io_fd, dom, flags, hvm);
|
||||
|
||||
ctx.domid = dom;
|
||||
+ sr_uuid_to_string(ctx.uuid, ctx.dominfo.handle);
|
||||
|
||||
if ( hvm )
|
||||
{
|
||||
--- a/tools/xl/xl.c
|
||||
+++ b/tools/xl/xl.c
|
||||
@@ -424,6 +424,8 @@ int main(int argc, char **argv)
|
||||
logger = xtl_createlogger_stdiostream(stderr, minmsglevel, xtl_flags);
|
||||
if (!logger) exit(EXIT_FAILURE);
|
||||
|
||||
+ /* Provide context to libxl and libxc: no SUSEINFO() from xl */
|
||||
+ setenv(XL_NO_SUSEINFO, "1", 0);
|
||||
xl_ctx_alloc();
|
||||
|
||||
atexit(xl_ctx_free);
|
@@ -1,197 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 5 Feb 2021 20:16:02 +0100
|
||||
Subject: libxc sr xg_sr_bitmap populated_pfns
|
||||
|
||||
tools: use xg_sr_bitmap for populated_pfns
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.h | 20 ++++++-
|
||||
tools/libs/guest/xg_sr_restore.c | 69 ------------------------
|
||||
tools/libs/guest/xg_sr_restore_x86_hvm.c | 9 ++++
|
||||
tools/libs/guest/xg_sr_restore_x86_pv.c | 7 +++
|
||||
4 files changed, 34 insertions(+), 71 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -375,8 +375,7 @@ struct xc_sr_context
|
||||
uint32_t xenstore_domid, console_domid;
|
||||
|
||||
/* Bitmap of currently populated PFNs during restore. */
|
||||
- unsigned long *populated_pfns;
|
||||
- xen_pfn_t max_populated_pfn;
|
||||
+ struct sr_bitmap populated_pfns;
|
||||
|
||||
/* Sender has invoked verify mode on the stream. */
|
||||
bool verify;
|
||||
@@ -632,6 +631,23 @@ static inline bool page_type_has_stream_
|
||||
}
|
||||
}
|
||||
|
||||
+static inline bool pfn_is_populated(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
+{
|
||||
+ return sr_test_bit(pfn, &ctx->restore.populated_pfns);
|
||||
+}
|
||||
+
|
||||
+static inline int pfn_set_populated(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+
|
||||
+ if ( sr_set_bit(pfn, &ctx->restore.populated_pfns) == false )
|
||||
+ {
|
||||
+ PERROR("Failed to realloc populated_pfns bitmap");
|
||||
+ errno = ENOMEM;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
#endif
|
||||
/*
|
||||
* Local variables:
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -72,64 +72,6 @@ static int read_headers(struct xc_sr_con
|
||||
}
|
||||
|
||||
/*
|
||||
- * Is a pfn populated?
|
||||
- */
|
||||
-static bool pfn_is_populated(const struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
-{
|
||||
- if ( pfn > ctx->restore.max_populated_pfn )
|
||||
- return false;
|
||||
- return test_bit(pfn, ctx->restore.populated_pfns);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Set a pfn as populated, expanding the tracking structures if needed. To
|
||||
- * avoid realloc()ing too excessively, the size increased to the nearest power
|
||||
- * of two large enough to contain the required pfn.
|
||||
- */
|
||||
-static int pfn_set_populated(struct xc_sr_context *ctx, xen_pfn_t pfn)
|
||||
-{
|
||||
- xc_interface *xch = ctx->xch;
|
||||
-
|
||||
- if ( pfn > ctx->restore.max_populated_pfn )
|
||||
- {
|
||||
- xen_pfn_t new_max;
|
||||
- size_t old_sz, new_sz;
|
||||
- unsigned long *p;
|
||||
-
|
||||
- /* Round up to the nearest power of two larger than pfn, less 1. */
|
||||
- new_max = pfn;
|
||||
- new_max |= new_max >> 1;
|
||||
- new_max |= new_max >> 2;
|
||||
- new_max |= new_max >> 4;
|
||||
- new_max |= new_max >> 8;
|
||||
- new_max |= new_max >> 16;
|
||||
-#ifdef __x86_64__
|
||||
- new_max |= new_max >> 32;
|
||||
-#endif
|
||||
-
|
||||
- old_sz = bitmap_size(ctx->restore.max_populated_pfn + 1);
|
||||
- new_sz = bitmap_size(new_max + 1);
|
||||
- p = realloc(ctx->restore.populated_pfns, new_sz);
|
||||
- if ( !p )
|
||||
- {
|
||||
- ERROR("Failed to realloc populated bitmap");
|
||||
- errno = ENOMEM;
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- memset((uint8_t *)p + old_sz, 0x00, new_sz - old_sz);
|
||||
-
|
||||
- ctx->restore.populated_pfns = p;
|
||||
- ctx->restore.max_populated_pfn = new_max;
|
||||
- }
|
||||
-
|
||||
- assert(!test_bit(pfn, ctx->restore.populated_pfns));
|
||||
- set_bit(pfn, ctx->restore.populated_pfns);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
* Given a set of pfns, obtain memory from Xen to fill the physmap for the
|
||||
* unpopulated subset. If types is NULL, no page type checking is performed
|
||||
* and all unpopulated pfns are populated.
|
||||
@@ -911,16 +853,6 @@ static int setup(struct xc_sr_context *c
|
||||
if ( rc )
|
||||
goto err;
|
||||
|
||||
- ctx->restore.max_populated_pfn = (32 * 1024 / 4) - 1;
|
||||
- ctx->restore.populated_pfns = bitmap_alloc(
|
||||
- ctx->restore.max_populated_pfn + 1);
|
||||
- if ( !ctx->restore.populated_pfns )
|
||||
- {
|
||||
- ERROR("Unable to allocate memory for populated_pfns bitmap");
|
||||
- rc = -1;
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
ctx->restore.pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pfns));
|
||||
ctx->restore.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.types));
|
||||
ctx->restore.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.mfns));
|
||||
@@ -969,7 +901,6 @@ static void cleanup(struct xc_sr_context
|
||||
xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->restore.p2m_size)));
|
||||
|
||||
free(ctx->restore.buffered_records);
|
||||
- free(ctx->restore.populated_pfns);
|
||||
free(ctx->restore.pages);
|
||||
free(ctx->restore.iov);
|
||||
free(ctx->restore.guest_data);
|
||||
--- a/tools/libs/guest/xg_sr_restore_x86_hvm.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore_x86_hvm.c
|
||||
@@ -136,6 +136,7 @@ static int x86_hvm_localise_page(struct
|
||||
static int x86_hvm_setup(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
+ unsigned long max_pfn, max_pages = ctx->dominfo.max_pages;
|
||||
|
||||
if ( ctx->restore.guest_type != DHDR_TYPE_X86_HVM )
|
||||
{
|
||||
@@ -161,6 +162,13 @@ static int x86_hvm_setup(struct xc_sr_co
|
||||
}
|
||||
#endif
|
||||
|
||||
+ max_pfn = max(ctx->restore.p2m_size, max_pages);
|
||||
+ if ( !sr_bitmap_expand(&ctx->restore.populated_pfns, max_pfn) )
|
||||
+ {
|
||||
+ PERROR("Unable to allocate memory for populated_pfns bitmap");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -241,6 +249,7 @@ static int x86_hvm_stream_complete(struc
|
||||
|
||||
static int x86_hvm_cleanup(struct xc_sr_context *ctx)
|
||||
{
|
||||
+ sr_bitmap_free(&ctx->restore.populated_pfns);
|
||||
free(ctx->x86.hvm.restore.context.ptr);
|
||||
|
||||
free(ctx->x86.restore.cpuid.ptr);
|
||||
--- a/tools/libs/guest/xg_sr_restore_x86_pv.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore_x86_pv.c
|
||||
@@ -1060,6 +1060,12 @@ static int x86_pv_setup(struct xc_sr_con
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
+ if ( !sr_bitmap_expand(&ctx->restore.populated_pfns, 32 * 1024 / 4) )
|
||||
+ {
|
||||
+ PERROR("Unable to allocate memory for populated_pfns bitmap");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
ctx->x86.pv.restore.nr_vcpus = ctx->dominfo.max_vcpu_id + 1;
|
||||
ctx->x86.pv.restore.vcpus = calloc(sizeof(struct xc_sr_x86_pv_restore_vcpu),
|
||||
ctx->x86.pv.restore.nr_vcpus);
|
||||
@@ -1153,6 +1159,7 @@ static int x86_pv_stream_complete(struct
|
||||
*/
|
||||
static int x86_pv_cleanup(struct xc_sr_context *ctx)
|
||||
{
|
||||
+ sr_bitmap_free(&ctx->restore.populated_pfns);
|
||||
free(ctx->x86.pv.p2m);
|
||||
free(ctx->x86.pv.p2m_pfns);
|
||||
|
@@ -1,141 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Fri, 5 Feb 2021 19:50:03 +0100
|
||||
Subject: libxc sr xg_sr_bitmap
|
||||
|
||||
tools: add API for expandable bitmaps
|
||||
|
||||
Since the incoming migration stream lacks info about what the highest pfn
|
||||
will be, some data structures can not be allocated upfront.
|
||||
|
||||
Add an API for expandable bitmaps, loosely based on pfn_set_populated.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.c | 39 +++++++++++++++++++
|
||||
tools/libs/guest/xg_sr_common.h | 67 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 106 insertions(+)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.c
|
||||
+++ b/tools/libs/guest/xg_sr_common.c
|
||||
@@ -164,6 +164,45 @@ static void __attribute__((unused)) buil
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Expand the tracking structures as needed.
|
||||
+ * To avoid realloc()ing too excessively, the size increased to the nearest
|
||||
+ * power of two large enough to contain the required number of bits.
|
||||
+ */
|
||||
+bool _sr_bitmap_expand(struct sr_bitmap *bm, unsigned long bits)
|
||||
+{
|
||||
+ size_t new_max;
|
||||
+ size_t old_sz, new_sz;
|
||||
+ void *p;
|
||||
+
|
||||
+ if (bits <= bm->bits)
|
||||
+ return true;
|
||||
+
|
||||
+ /* Round up to the nearest power of two larger than bit, less 1. */
|
||||
+ new_max = bits;
|
||||
+ new_max |= new_max >> 1;
|
||||
+ new_max |= new_max >> 2;
|
||||
+ new_max |= new_max >> 4;
|
||||
+ new_max |= new_max >> 8;
|
||||
+ new_max |= new_max >> 16;
|
||||
+ new_max |= sizeof(unsigned long) > 4 ? new_max >> 32 : 0;
|
||||
+
|
||||
+ /* Allocate units of unsigned long */
|
||||
+ new_max = (new_max + BITS_PER_LONG - 1) & ~(BITS_PER_LONG - 1);
|
||||
+
|
||||
+ old_sz = bitmap_size(bm->bits);
|
||||
+ new_sz = bitmap_size(new_max);
|
||||
+ p = realloc(bm->p, new_sz);
|
||||
+ if (!p)
|
||||
+ return false;
|
||||
+
|
||||
+ memset(p + old_sz, 0, new_sz - old_sz);
|
||||
+ bm->p = p;
|
||||
+ bm->bits = new_max;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -18,6 +18,73 @@ const char *rec_type_to_str(uint32_t typ
|
||||
struct xc_sr_context;
|
||||
struct xc_sr_record;
|
||||
|
||||
+struct sr_bitmap
|
||||
+{
|
||||
+ void *p;
|
||||
+ unsigned long bits;
|
||||
+};
|
||||
+
|
||||
+extern bool _sr_bitmap_expand(struct sr_bitmap *bm, unsigned long bits);
|
||||
+
|
||||
+static inline bool sr_bitmap_expand(struct sr_bitmap *bm, unsigned long bits)
|
||||
+{
|
||||
+ if (bits > bm->bits)
|
||||
+ return _sr_bitmap_expand(bm, bits);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static inline void sr_bitmap_free(struct sr_bitmap *bm)
|
||||
+{
|
||||
+ free(bm->p);
|
||||
+ bm->p = NULL;
|
||||
+}
|
||||
+
|
||||
+static inline bool sr_set_bit(unsigned long bit, struct sr_bitmap *bm)
|
||||
+{
|
||||
+ if (sr_bitmap_expand(bm, bit + 1) == false)
|
||||
+ return false;
|
||||
+
|
||||
+ set_bit(bit, bm->p);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static inline bool sr_test_bit(unsigned long bit, struct sr_bitmap *bm)
|
||||
+{
|
||||
+ if (bit + 1 > bm->bits)
|
||||
+ return false;
|
||||
+ return !!test_bit(bit, bm->p);
|
||||
+}
|
||||
+
|
||||
+static inline void sr_clear_bit(unsigned long bit, struct sr_bitmap *bm)
|
||||
+{
|
||||
+ if (bit + 1 <= bm->bits)
|
||||
+ clear_bit(bit, bm->p);
|
||||
+}
|
||||
+
|
||||
+static inline bool sr_test_and_clear_bit(unsigned long bit, struct sr_bitmap *bm)
|
||||
+{
|
||||
+ if (bit + 1 > bm->bits)
|
||||
+ return false;
|
||||
+ return !!test_and_clear_bit(bit, bm->p);
|
||||
+}
|
||||
+
|
||||
+/* No way to report potential allocation error, bitmap must be expanded prior usage */
|
||||
+static inline bool sr_test_and_set_bit(unsigned long bit, struct sr_bitmap *bm)
|
||||
+{
|
||||
+ if (bit + 1 > bm->bits)
|
||||
+ return false;
|
||||
+ return !!test_and_set_bit(bit, bm->p);
|
||||
+}
|
||||
+
|
||||
+static inline bool sr_set_long_bit(unsigned long base_bit, struct sr_bitmap *bm)
|
||||
+{
|
||||
+ if (sr_bitmap_expand(bm, base_bit + BITS_PER_LONG) == false)
|
||||
+ return false;
|
||||
+
|
||||
+ set_bit_long(base_bit, bm->p);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* Save operations. To be implemented for each type of guest, for use by the
|
||||
* common save algorithm.
|
@@ -1,46 +0,0 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Thu, 29 Oct 2020 17:00:19 +0100
|
||||
Subject: libxc sr xl migration debug
|
||||
|
||||
xl: fix description of migrate --debug
|
||||
|
||||
xl migrate --debug used to track every pfn in every batch of pages.
|
||||
But these times are gone. The code in xc_domain_save is the consumer
|
||||
of this knob, now may enable verification mode.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
|
||||
v03:
|
||||
- adjust to describe what --debug would do when the code which
|
||||
consumes this knob is fixed.
|
||||
v02:
|
||||
- the option has no effect anymore
|
||||
---
|
||||
docs/man/xl.1.pod.in | 4 +++-
|
||||
tools/xl/xl_cmdtable.c | 2 +-
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/docs/man/xl.1.pod.in
|
||||
+++ b/docs/man/xl.1.pod.in
|
||||
@@ -486,7 +486,9 @@ domain.
|
||||
|
||||
=item B<--debug>
|
||||
|
||||
-Display huge (!) amount of debug information during the migration process.
|
||||
+This enables verification mode, which will transfer the entire domU memory
|
||||
+once more to the receiving host to make sure the content is identical on
|
||||
+both sides.
|
||||
|
||||
=item B<-p>
|
||||
|
||||
--- a/tools/xl/xl_cmdtable.c
|
||||
+++ b/tools/xl/xl_cmdtable.c
|
||||
@@ -173,7 +173,7 @@ const struct cmd_spec cmd_table[] = {
|
||||
" migrate-receive [-d -e]\n"
|
||||
"-e Do not wait in the background (on <host>) for the death\n"
|
||||
" of the domain.\n"
|
||||
- "--debug Print huge (!) amount of debug during the migration process.\n"
|
||||
+ "--debug Enable verification mode.\n"
|
||||
"-p Do not unpause domain after migrating it.\n"
|
||||
"-D Preserve the domain id"
|
||||
},
|
@@ -85,7 +85,7 @@ the execution time of each script.
|
||||
|
||||
--- a/tools/libs/light/libxl_create.c
|
||||
+++ b/tools/libs/light/libxl_create.c
|
||||
@@ -1323,6 +1323,7 @@ static void initiate_domain_create(libxl
|
||||
@@ -1363,6 +1363,7 @@ static void initiate_domain_create(libxl
|
||||
* build info around just to know if the domain has a device model or not.
|
||||
*/
|
||||
store_libxl_entry(gc, domid, &d_config->b_info);
|
||||
@@ -95,7 +95,7 @@ the execution time of each script.
|
||||
ret = libxl__disk_devtype.set_default(gc, domid, &d_config->disks[i],
|
||||
--- a/tools/libs/light/libxl_device.c
|
||||
+++ b/tools/libs/light/libxl_device.c
|
||||
@@ -1296,7 +1296,7 @@ static void device_hotplug(libxl__egc *e
|
||||
@@ -1309,7 +1309,7 @@ static void device_hotplug(libxl__egc *e
|
||||
}
|
||||
|
||||
aes->ao = ao;
|
||||
@@ -104,7 +104,7 @@ the execution time of each script.
|
||||
aes->env = env;
|
||||
aes->args = args;
|
||||
aes->callback = device_hotplug_child_death_cb;
|
||||
@@ -1305,6 +1305,15 @@ static void device_hotplug(libxl__egc *e
|
||||
@@ -1318,6 +1318,15 @@ static void device_hotplug(libxl__egc *e
|
||||
aes->stdfds[1] = 2;
|
||||
aes->stdfds[2] = -1;
|
||||
|
||||
@@ -278,7 +278,7 @@ the execution time of each script.
|
||||
|
||||
#include <xenevtchn.h>
|
||||
#include <xenstore.h>
|
||||
@@ -1629,6 +1630,7 @@ struct libxl__xswait_state {
|
||||
@@ -1624,6 +1625,7 @@ struct libxl__xswait_state {
|
||||
const char *what; /* for error msgs: noun phrase, what we're waiting for */
|
||||
const char *path;
|
||||
int timeout_ms; /* as for poll(2) */
|
||||
@@ -286,7 +286,7 @@ the execution time of each script.
|
||||
libxl__xswait_callback *callback;
|
||||
/* remaining fields are private to xswait */
|
||||
libxl__ev_time time_ev;
|
||||
@@ -2707,6 +2709,7 @@ struct libxl__async_exec_state {
|
||||
@@ -2701,6 +2703,7 @@ struct libxl__async_exec_state {
|
||||
char **args; /* execution arguments */
|
||||
char **env; /* execution environment */
|
||||
|
||||
@@ -294,7 +294,7 @@ the execution time of each script.
|
||||
/* private */
|
||||
libxl__ev_time time;
|
||||
libxl__ev_child child;
|
||||
@@ -4896,6 +4899,9 @@ _hidden int userlookup_helper_getpwuid(l
|
||||
@@ -4893,6 +4896,9 @@ _hidden int userlookup_helper_getpwuid(l
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -7,11 +7,11 @@ https://bugzilla.novell.com/show_bug.cgi?id=879425
|
||||
tools/libxl/libxlu_disk_l.l | 1 +
|
||||
5 files changed, 18 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: xen-4.18.0-testing/docs/man/xl-disk-configuration.5.pod.in
|
||||
Index: xen-4.20.0-testing/docs/man/xl-disk-configuration.5.pod.in
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/docs/man/xl-disk-configuration.5.pod.in
|
||||
+++ xen-4.18.0-testing/docs/man/xl-disk-configuration.5.pod.in
|
||||
@@ -337,6 +337,32 @@ No
|
||||
--- xen-4.20.0-testing.orig/docs/man/xl-disk-configuration.5.pod.in
|
||||
+++ xen-4.20.0-testing/docs/man/xl-disk-configuration.5.pod.in
|
||||
@@ -339,6 +339,32 @@ No
|
||||
|
||||
discard
|
||||
|
||||
@@ -44,13 +44,13 @@ Index: xen-4.18.0-testing/docs/man/xl-disk-configuration.5.pod.in
|
||||
=back
|
||||
|
||||
An advisory setting for the backend driver, specifying whether to
|
||||
Index: xen-4.18.0-testing/tools/include/libxl.h
|
||||
Index: xen-4.20.0-testing/tools/include/libxl.h
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/include/libxl.h
|
||||
+++ xen-4.18.0-testing/tools/include/libxl.h
|
||||
@@ -584,6 +584,21 @@
|
||||
*/
|
||||
#define LIBXL_HAVE_CONSOLE_ADD_XENSTORE 1
|
||||
--- xen-4.20.0-testing.orig/tools/include/libxl.h
|
||||
+++ xen-4.20.0-testing/tools/include/libxl.h
|
||||
@@ -603,6 +603,21 @@
|
||||
#define LIBXL_HAVE_P9_ADD 1
|
||||
|
||||
/*
|
||||
+ * The libxl_device_disk has no way to indicate that cache=unsafe is
|
||||
+ * supposed to be used. Provide this knob without breaking the ABI.
|
||||
@@ -70,11 +70,11 @@ Index: xen-4.18.0-testing/tools/include/libxl.h
|
||||
* libxl ABI compatibility
|
||||
*
|
||||
* The only guarantee which libxl makes regarding ABI compatibility
|
||||
Index: xen-4.18.0-testing/tools/libs/light/libxl_disk.c
|
||||
Index: xen-4.20.0-testing/tools/libs/light/libxl_disk.c
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/libs/light/libxl_disk.c
|
||||
+++ xen-4.18.0-testing/tools/libs/light/libxl_disk.c
|
||||
@@ -422,6 +422,8 @@ static void device_disk_add(libxl__egc *
|
||||
--- xen-4.20.0-testing.orig/tools/libs/light/libxl_disk.c
|
||||
+++ xen-4.20.0-testing/tools/libs/light/libxl_disk.c
|
||||
@@ -464,6 +464,8 @@ static void device_disk_add(libxl__egc *
|
||||
flexarray_append_pair(back, "discard-enable",
|
||||
libxl_defbool_val(disk->discard_enable) ?
|
||||
"1" : "0");
|
||||
@@ -83,11 +83,11 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_disk.c
|
||||
flexarray_append(back, "specification");
|
||||
flexarray_append(back, libxl__device_disk_string_of_specification(disk->specification));
|
||||
if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
|
||||
Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
Index: xen-4.20.0-testing/tools/libs/light/libxl_dm.c
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/libs/light/libxl_dm.c
|
||||
+++ xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
@@ -1019,14 +1019,27 @@ enum {
|
||||
--- xen-4.20.0-testing.orig/tools/libs/light/libxl_dm.c
|
||||
+++ xen-4.20.0-testing/tools/libs/light/libxl_dm.c
|
||||
@@ -1003,14 +1003,27 @@ enum {
|
||||
LIBXL__COLO_SECONDARY,
|
||||
};
|
||||
|
||||
@@ -117,7 +117,7 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
const char *exportname = disk->colo_export;
|
||||
const char *active_disk = disk->active_disk;
|
||||
const char *hidden_disk = disk->hidden_disk;
|
||||
@@ -1085,8 +1098,8 @@ static char *qemu_disk_ide_drive_string(
|
||||
@@ -1069,8 +1082,8 @@ static char *qemu_disk_ide_drive_string(
|
||||
switch (colo_mode) {
|
||||
case LIBXL__COLO_NONE:
|
||||
drive = GCSPRINTF
|
||||
@@ -128,7 +128,7 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
break;
|
||||
case LIBXL__COLO_PRIMARY:
|
||||
/*
|
||||
@@ -1099,13 +1112,14 @@ static char *qemu_disk_ide_drive_string(
|
||||
@@ -1083,13 +1096,14 @@ static char *qemu_disk_ide_drive_string(
|
||||
* vote-threshold=1
|
||||
*/
|
||||
drive = GCSPRINTF(
|
||||
@@ -145,7 +145,7 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
break;
|
||||
case LIBXL__COLO_SECONDARY:
|
||||
/*
|
||||
@@ -1119,7 +1133,7 @@ static char *qemu_disk_ide_drive_string(
|
||||
@@ -1103,7 +1117,7 @@ static char *qemu_disk_ide_drive_string(
|
||||
* file.backing.backing=exportname,
|
||||
*/
|
||||
drive = GCSPRINTF(
|
||||
@@ -154,7 +154,7 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
"driver=replication,"
|
||||
"mode=secondary,"
|
||||
"top-id=top-colo,"
|
||||
@@ -1128,7 +1142,8 @@ static char *qemu_disk_ide_drive_string(
|
||||
@@ -1112,7 +1126,8 @@ static char *qemu_disk_ide_drive_string(
|
||||
"file.backing.driver=qcow2,"
|
||||
"file.backing.file.filename=%s,"
|
||||
"file.backing.backing=%s",
|
||||
@@ -164,7 +164,7 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
@@ -1998,8 +2013,8 @@ static int libxl__build_device_model_arg
|
||||
@@ -1985,8 +2000,8 @@ static int libxl__build_device_model_arg
|
||||
return ERROR_INVAL;
|
||||
}
|
||||
flexarray_vappend(dm_args, "-drive",
|
||||
@@ -175,10 +175,10 @@ Index: xen-4.18.0-testing/tools/libs/light/libxl_dm.c
|
||||
"-device", GCSPRINTF("ide-hd,bus=ahci0.%d,unit=0,drive=ahcidisk-%d",
|
||||
disk, disk), NULL);
|
||||
continue;
|
||||
Index: xen-4.18.0-testing/tools/libs/util/libxlu_disk.c
|
||||
Index: xen-4.20.0-testing/tools/libs/util/libxlu_disk.c
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/libs/util/libxlu_disk.c
|
||||
+++ xen-4.18.0-testing/tools/libs/util/libxlu_disk.c
|
||||
--- xen-4.20.0-testing.orig/tools/libs/util/libxlu_disk.c
|
||||
+++ xen-4.20.0-testing/tools/libs/util/libxlu_disk.c
|
||||
@@ -78,6 +78,8 @@ int xlu_disk_parse(XLU_Config *cfg,
|
||||
if (!disk->pdev_path || !strcmp(disk->pdev_path, ""))
|
||||
disk->format = LIBXL_DISK_FORMAT_EMPTY;
|
||||
@@ -188,10 +188,10 @@ Index: xen-4.18.0-testing/tools/libs/util/libxlu_disk.c
|
||||
|
||||
if (!disk->vdev) {
|
||||
xlu__disk_err(&dpc,0, "no vdev specified");
|
||||
Index: xen-4.18.0-testing/tools/libs/util/libxlu_disk_i.h
|
||||
Index: xen-4.20.0-testing/tools/libs/util/libxlu_disk_i.h
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/libs/util/libxlu_disk_i.h
|
||||
+++ xen-4.18.0-testing/tools/libs/util/libxlu_disk_i.h
|
||||
--- xen-4.20.0-testing.orig/tools/libs/util/libxlu_disk_i.h
|
||||
+++ xen-4.20.0-testing/tools/libs/util/libxlu_disk_i.h
|
||||
@@ -10,7 +10,7 @@ typedef struct {
|
||||
void *scanner;
|
||||
YY_BUFFER_STATE buf;
|
||||
@@ -201,10 +201,10 @@ Index: xen-4.18.0-testing/tools/libs/util/libxlu_disk_i.h
|
||||
const char *spec;
|
||||
} DiskParseContext;
|
||||
|
||||
Index: xen-4.18.0-testing/tools/libs/util/libxlu_disk_l.l
|
||||
Index: xen-4.20.0-testing/tools/libs/util/libxlu_disk_l.l
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/libs/util/libxlu_disk_l.l
|
||||
+++ xen-4.18.0-testing/tools/libs/util/libxlu_disk_l.l
|
||||
--- xen-4.20.0-testing.orig/tools/libs/util/libxlu_disk_l.l
|
||||
+++ xen-4.20.0-testing/tools/libs/util/libxlu_disk_l.l
|
||||
@@ -216,6 +216,7 @@ colo-port=[^,]*,? { STRIP(','); setcolop
|
||||
colo-export=[^,]*,? { STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
|
||||
active-disk=[^,]*,? { STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
|
||||
|
@@ -1,63 +0,0 @@
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/legacy.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/legacy.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/legacy.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/libxc.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/libxc.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/libxc.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/libxl.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/libxl.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/libxl.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/public.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/public.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/public.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/tests.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/tests.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/tests.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/verify.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/verify.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/verify.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Index: xen-4.18.0-testing/tools/python/xen/migration/xl.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/python/xen/migration/xl.py
|
||||
+++ xen-4.18.0-testing/tools/python/xen/migration/xl.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
BIN
mini-os.tar.bz2
(Stored with Git LFS)
BIN
mini-os.tar.bz2
(Stored with Git LFS)
Binary file not shown.
@@ -1,63 +0,0 @@
|
||||
Index: xen-4.17.2-testing/tools/pygrub/src/pygrub
|
||||
===================================================================
|
||||
--- xen-4.17.2-testing.orig/tools/pygrub/src/pygrub
|
||||
+++ xen-4.17.2-testing/tools/pygrub/src/pygrub
|
||||
@@ -579,7 +579,7 @@ class Grub:
|
||||
self.cf.filename = f
|
||||
break
|
||||
if self.__dict__.get('cf', None) is None:
|
||||
- raise RuntimeError("couldn't find bootloader config file in the image provided.")
|
||||
+ return
|
||||
f = fs.open_file(self.cf.filename)
|
||||
# limit read size to avoid pathological cases
|
||||
buf = f.read(FS_READ_MAX)
|
||||
@@ -754,6 +754,20 @@ def run_grub(file, entry, fs, cfg_args):
|
||||
|
||||
g = Grub(file, fs)
|
||||
|
||||
+ # If missing config or grub has no menu entries to select, look for
|
||||
+ # vmlinuz-xen and initrd-xen in /boot
|
||||
+ if g.__dict__.get('cf', None) is None or len(g.cf.images) == 0 or re.search(r"xen(-pae)?\.gz",g.cf.images[0].kernel[1]):
|
||||
+ if not list_entries:
|
||||
+ chosencfg = { "kernel": None, "ramdisk": None, "args": "" }
|
||||
+ chosencfg = sniff_xen_kernel(fs, incfg)
|
||||
+ if chosencfg["kernel"] and chosencfg["ramdisk"]:
|
||||
+ chosencfg["args"] = cfg_args
|
||||
+ return chosencfg
|
||||
+ if g.__dict__.get('cf', None) is None:
|
||||
+ raise RuntimeError("couldn't find bootloader config file in the image provided.")
|
||||
+ else:
|
||||
+ return
|
||||
+
|
||||
if list_entries:
|
||||
for i in range(len(g.cf.images)):
|
||||
img = g.cf.images[i]
|
||||
@@ -840,6 +854,19 @@ def sniff_netware(fs, cfg):
|
||||
|
||||
return cfg
|
||||
|
||||
+def sniff_xen_kernel(fs, cfg):
|
||||
+ if not cfg["kernel"]:
|
||||
+ if fs.file_exists('/boot/vmlinuz-xen'):
|
||||
+ cfg["kernel"] = '/boot/vmlinuz-xen'
|
||||
+ elif fs.file_exists('/boot/vmlinuz-xenpae'):
|
||||
+ cfg["kernel"] = '/boot/vmlinuz-xenpae'
|
||||
+ if cfg["kernel"] and not cfg["ramdisk"]:
|
||||
+ if fs.file_exists('/boot/initrd-xen'):
|
||||
+ cfg["ramdisk"] = '/boot/initrd-xen'
|
||||
+ elif fs.file_exists('/boot/initrd-xenpae'):
|
||||
+ cfg["ramdisk"] = '/boot/initrd-xenpae'
|
||||
+ return cfg
|
||||
+
|
||||
def format_sxp(kernel, ramdisk, args):
|
||||
s = "linux (kernel %s)" % repr(kernel)
|
||||
if ramdisk:
|
||||
@@ -918,7 +945,7 @@ if __name__ == "__main__":
|
||||
debug = False
|
||||
not_really = False
|
||||
output_format = "sxp"
|
||||
- output_directory = "/var/run/xen/pygrub/"
|
||||
+ output_directory = "/var/run/xen"
|
||||
uid = None
|
||||
|
||||
# what was passed in
|
@@ -1,59 +0,0 @@
|
||||
References: bsc#978413
|
||||
|
||||
The parsing code can't handle a single line menu entry.
|
||||
For example: menuentry 'halt' { halt }
|
||||
Force it to fall through where it will handle the closing brace.
|
||||
Also change warning to debug to cut down on verbose output.
|
||||
|
||||
Index: xen-4.18.0-testing/tools/pygrub/src/GrubConf.py
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/tools/pygrub/src/GrubConf.py
|
||||
+++ xen-4.18.0-testing/tools/pygrub/src/GrubConf.py
|
||||
@@ -150,7 +150,7 @@ class GrubImage(_GrubImage):
|
||||
else:
|
||||
logging.info("Ignored image directive %s" %(com,))
|
||||
else:
|
||||
- logging.warning("Unknown image directive %s" %(com,))
|
||||
+ logging.debug("Unknown image directive %s" %(com,))
|
||||
|
||||
# now put the line in the list of lines
|
||||
if replace is None:
|
||||
@@ -309,7 +309,7 @@ class GrubConfigFile(_GrubConfigFile):
|
||||
else:
|
||||
logging.info("Ignored directive %s" %(com,))
|
||||
else:
|
||||
- logging.warning("Unknown directive %s" %(com,))
|
||||
+ logging.debug("Unknown directive %s" %(com,))
|
||||
|
||||
if img:
|
||||
self.add_image(GrubImage(title, img))
|
||||
@@ -343,7 +343,7 @@ class Grub2Image(_GrubImage):
|
||||
elif com.startswith('set:'):
|
||||
pass
|
||||
else:
|
||||
- logging.warning("Unknown image directive %s" %(com,))
|
||||
+ logging.debug("Unknown image directive %s" %(com,))
|
||||
|
||||
# now put the line in the list of lines
|
||||
if replace is None:
|
||||
@@ -408,7 +408,10 @@ class Grub2ConfigFile(_GrubConfigFile):
|
||||
raise RuntimeError("syntax error: cannot nest menuentry (%d %s)" % (len(img),img))
|
||||
img = []
|
||||
title = title_match.group(1)
|
||||
- continue
|
||||
+ if not l.endswith('}'):
|
||||
+ continue
|
||||
+ # One line menuentry, Ex. menuentry 'halt' { halt }
|
||||
+ l = '}'
|
||||
|
||||
if l.startswith("submenu"):
|
||||
menu_level += 1
|
||||
@@ -447,7 +450,7 @@ class Grub2ConfigFile(_GrubConfigFile):
|
||||
elif com.startswith('set:'):
|
||||
pass
|
||||
else:
|
||||
- logging.warning("Unknown directive %s" %(com,))
|
||||
+ logging.debug("Unknown directive %s" %(com,))
|
||||
|
||||
if img is not None:
|
||||
raise RuntimeError("syntax error: end of file with open menuentry(%d %s)" % (len(img),img))
|
@@ -6,105 +6,97 @@ Subject: [PATCH] replace obsolete network configuration commands in scripts
|
||||
Some scripts still use obsolete network configuration commands ifconfig and
|
||||
brctl. Replace them by commands from iproute2 package.
|
||||
---
|
||||
README | 3 +--
|
||||
tools/hotplug/Linux/colo-proxy-setup | 14 ++++++--------
|
||||
tools/hotplug/Linux/remus-netbuf-setup | 3 ++-
|
||||
tools/hotplug/Linux/vif-bridge | 7 ++++---
|
||||
tools/hotplug/Linux/colo-proxy-setup | 14 --------------
|
||||
tools/hotplug/Linux/remus-netbuf-setup | 2 +-
|
||||
tools/hotplug/Linux/vif-bridge | 6 +-----
|
||||
tools/hotplug/Linux/vif-nat | 2 +-
|
||||
tools/hotplug/Linux/vif-route | 6 ++++--
|
||||
tools/hotplug/Linux/xen-network-common.sh | 6 ++----
|
||||
.../i386-dm/qemu-ifup-Linux | 5 +++--
|
||||
9 files changed, 26 insertions(+), 26 deletions(-)
|
||||
tools/hotplug/Linux/xen-network-common.sh | 15 +--------------
|
||||
6 files changed, 8 insertions(+), 37 deletions(-)
|
||||
|
||||
Index: xen-4.17.0-testing/README
|
||||
===================================================================
|
||||
--- xen-4.17.0-testing.orig/README
|
||||
+++ xen-4.17.0-testing/README
|
||||
@@ -61,8 +61,7 @@ provided by your OS distributor:
|
||||
* Development install of GLib v2.0 (e.g. libglib2.0-dev)
|
||||
* Development install of Pixman (e.g. libpixman-1-dev)
|
||||
* pkg-config
|
||||
- * bridge-utils package (/sbin/brctl)
|
||||
- * iproute package (/sbin/ip)
|
||||
+ * iproute package (/sbin/ip, /sbin/bridge)
|
||||
* GNU bison and GNU flex
|
||||
* ACPI ASL compiler (iasl)
|
||||
--- a/tools/hotplug/Linux/colo-proxy-setup
|
||||
+++ b/tools/hotplug/Linux/colo-proxy-setup
|
||||
@@ -76,17 +76,10 @@
|
||||
|
||||
Index: xen-4.17.0-testing/tools/hotplug/Linux/remus-netbuf-setup
|
||||
===================================================================
|
||||
--- xen-4.17.0-testing.orig/tools/hotplug/Linux/remus-netbuf-setup
|
||||
+++ xen-4.17.0-testing/tools/hotplug/Linux/remus-netbuf-setup
|
||||
@@ -76,6 +76,7 @@
|
||||
#specific setup code such as renaming.
|
||||
dir=$(dirname "$0")
|
||||
. "$dir/xen-hotplug-common.sh"
|
||||
+. "$dir/xen-network-common.sh"
|
||||
function setup_secondary()
|
||||
{
|
||||
- if which brctl >&/dev/null; then
|
||||
- do_without_error brctl delif $bridge $vifname
|
||||
- do_without_error brctl addbr $forwardbr
|
||||
- do_without_error brctl addif $forwardbr $vifname
|
||||
- do_without_error brctl addif $forwardbr $forwarddev
|
||||
- else
|
||||
do_without_error ip link set $vifname nomaster
|
||||
do_without_error ip link add name $forwardbr type bridge
|
||||
do_without_error ip link set $vifname master $forwardbr
|
||||
do_without_error ip link set $forwarddev master $forwardbr
|
||||
- fi
|
||||
do_without_error ip link set dev $forwardbr up
|
||||
do_without_error modprobe xt_SECCOLO
|
||||
|
||||
findCommand "$@"
|
||||
@@ -98,17 +91,10 @@
|
||||
|
||||
@@ -139,8 +140,16 @@ check_ifb() {
|
||||
function teardown_secondary()
|
||||
{
|
||||
- if which brctl >&/dev/null; then
|
||||
- do_without_error brctl delif $forwardbr $forwarddev
|
||||
- do_without_error brctl delif $forwardbr $vifname
|
||||
- do_without_error brctl delbr $forwardbr
|
||||
- do_without_error brctl addif $bridge $vifname
|
||||
- else
|
||||
do_without_error ip link set $forwarddev nomaster
|
||||
do_without_error ip link set $vifname nomaster
|
||||
do_without_error ip link delete $forwardbr type bridge
|
||||
do_without_error ip link set $vifname master $bridge
|
||||
- fi
|
||||
|
||||
do_without_error iptables -t mangle -D PREROUTING -m physdev --physdev-in \
|
||||
$vifname -j SECCOLO --index $index
|
||||
--- a/tools/hotplug/Linux/remus-netbuf-setup
|
||||
+++ b/tools/hotplug/Linux/remus-netbuf-setup
|
||||
@@ -139,7 +139,7 @@
|
||||
|
||||
setup_ifb() {
|
||||
|
||||
- for ifb in `ifconfig -a -s|egrep ^ifb|cut -d ' ' -f1`
|
||||
+ if [ "$legacy_tools" ]; then
|
||||
+ ifbs=`ifconfig -a -s|egrep ^ifb|cut -d ' ' -f1`
|
||||
+ else
|
||||
+ ifbs=$(ip --oneline link show type ifb | cut -d ' ' -f2)
|
||||
+ fi
|
||||
+ for ifb in $ifbs
|
||||
+ for ifb in $(ip --oneline link show type ifb | awk -F : '(NR == 1) { print $2; }')
|
||||
do
|
||||
+ if [ ! "$legacy_tools" ]; then
|
||||
+ ifb="${ifb%:}"
|
||||
+ fi
|
||||
check_ifb "$ifb" || continue
|
||||
REMUS_IFB="$ifb"
|
||||
break
|
||||
Index: xen-4.17.0-testing/tools/hotplug/Linux/vif-bridge
|
||||
===================================================================
|
||||
--- xen-4.17.0-testing.orig/tools/hotplug/Linux/vif-bridge
|
||||
+++ xen-4.17.0-testing/tools/hotplug/Linux/vif-bridge
|
||||
@@ -42,7 +42,8 @@ if [ -z "$bridge" ]; then
|
||||
if which brctl >&/dev/null; then
|
||||
bridge=$(brctl show | awk 'NR==2{print$1}')
|
||||
else
|
||||
--- a/tools/hotplug/Linux/vif-bridge
|
||||
+++ b/tools/hotplug/Linux/vif-bridge
|
||||
@@ -39,11 +39,7 @@
|
||||
bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")
|
||||
|
||||
if [ -z "$bridge" ]; then
|
||||
- if which brctl >&/dev/null; then
|
||||
- bridge=$(brctl show | awk 'NR==2{print$1}')
|
||||
- else
|
||||
- bridge=$(bridge link | cut -d" " -f7)
|
||||
+ bridge=$(ip --oneline link show type bridge | awk '(NR == 1) { print $2; }')
|
||||
+ bridge="${bridge%:}"
|
||||
fi
|
||||
- fi
|
||||
+ read bridge < <(ip --oneline link show type bridge | awk -F : '(NR == 1) { print $2; }')
|
||||
if [ -z "$bridge" ]
|
||||
then
|
||||
Index: xen-4.17.0-testing/tools/hotplug/Linux/vif-nat
|
||||
===================================================================
|
||||
--- xen-4.17.0-testing.orig/tools/hotplug/Linux/vif-nat
|
||||
+++ xen-4.17.0-testing/tools/hotplug/Linux/vif-nat
|
||||
@@ -172,7 +172,11 @@ case "$command" in
|
||||
fatal "Could not find bridge, and none was specified"
|
||||
--- a/tools/hotplug/Linux/vif-nat
|
||||
+++ b/tools/hotplug/Linux/vif-nat
|
||||
@@ -172,7 +172,7 @@
|
||||
;;
|
||||
offline)
|
||||
[ "$dhcp" != 'no' ] && dhcp_down
|
||||
- do_without_error ifconfig "${dev}" down
|
||||
+ if [ "$legacy_tools" ]; then
|
||||
+ do_without_error ifconfig "${dev}" down
|
||||
+ else
|
||||
+ do_without_error ip link set "${dev}" down
|
||||
+ fi
|
||||
;;
|
||||
esac
|
||||
|
||||
Index: xen-4.17.0-testing/tools/hotplug/Linux/vif-route
|
||||
===================================================================
|
||||
--- xen-4.17.0-testing.orig/tools/hotplug/Linux/vif-route
|
||||
+++ xen-4.17.0-testing/tools/hotplug/Linux/vif-route
|
||||
@@ -23,13 +23,23 @@ main_ip=$(dom0_ip)
|
||||
--- a/tools/hotplug/Linux/vif-route
|
||||
+++ b/tools/hotplug/Linux/vif-route
|
||||
@@ -23,13 +23,15 @@
|
||||
|
||||
case "${command}" in
|
||||
add|online)
|
||||
- ifconfig ${dev} ${main_ip} netmask 255.255.255.255 up
|
||||
+ if [ "$legacy_tools" ]; then
|
||||
+ ifconfig ${dev} ${main_ip} netmask 255.255.255.255 up
|
||||
+ else
|
||||
+ ip addr add "${main_ip}/32" dev "$dev"
|
||||
+ fi
|
||||
+ ip link set "dev" up
|
||||
echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp
|
||||
ipcmd='add'
|
||||
@@ -112,40 +104,49 @@ Index: xen-4.17.0-testing/tools/hotplug/Linux/vif-route
|
||||
;;
|
||||
remove|offline)
|
||||
- do_without_error ifdown ${dev}
|
||||
+ if [ "$legacy_tools" ]; then
|
||||
+ do_without_error ifdown ${dev}
|
||||
+ else
|
||||
+ do_without_error ip addr flush dev "$dev"
|
||||
+ do_without_error ip link set "$dev" down
|
||||
+ fi
|
||||
ipcmd='del'
|
||||
cmdprefix='do_without_error'
|
||||
;;
|
||||
Index: xen-4.17.0-testing/tools/hotplug/Linux/xen-network-common.sh
|
||||
===================================================================
|
||||
--- xen-4.17.0-testing.orig/tools/hotplug/Linux/xen-network-common.sh
|
||||
+++ xen-4.17.0-testing/tools/hotplug/Linux/xen-network-common.sh
|
||||
@@ -15,6 +15,12 @@
|
||||
#
|
||||
--- a/tools/hotplug/Linux/xen-network-common.sh
|
||||
+++ b/tools/hotplug/Linux/xen-network-common.sh
|
||||
@@ -111,13 +111,7 @@
|
||||
|
||||
|
||||
+# Use brctl and ifconfig on older systems
|
||||
+legacy_tools=
|
||||
+if [ -f /sbin/brctl -a -f /sbin/ifconfig ]; then
|
||||
+ legacy_tools="true"
|
||||
+fi
|
||||
+
|
||||
# Gentoo doesn't have ifup/ifdown, so we define appropriate alternatives.
|
||||
|
||||
# Other platforms just use ifup / ifdown directly.
|
||||
@@ -152,8 +158,10 @@ remove_from_bridge () {
|
||||
log debug "removing $dev from bridge $bridge"
|
||||
if which brctl >&/dev/null; then
|
||||
do_without_error brctl delif ${bridge} ${dev}
|
||||
+ do_without_error ifconfig "$dev" down
|
||||
else
|
||||
do_without_error ip link set ${dev} nomaster
|
||||
+ do_without_error ip link set "$dev" down
|
||||
# Don't create the bridge if it already exists.
|
||||
if [ ! -e "/sys/class/net/${bridge}/bridge" ]; then
|
||||
- if which brctl >&/dev/null; then
|
||||
- brctl addbr ${bridge}
|
||||
- brctl stp ${bridge} off
|
||||
- brctl setfd ${bridge} 0
|
||||
- else
|
||||
ip link add name ${bridge} type bridge stp_state 0 forward_delay 0
|
||||
- fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -129,11 +123,7 @@
|
||||
# Don't add $dev to $bridge if it's already on the bridge.
|
||||
if [ ! -e "/sys/class/net/${bridge}/brif/${dev}" ]; then
|
||||
log debug "adding $dev to bridge $bridge"
|
||||
- if which brctl >&/dev/null; then
|
||||
- brctl addif ${bridge} ${dev}
|
||||
- else
|
||||
ip link set ${dev} master ${bridge}
|
||||
- fi
|
||||
else
|
||||
log debug "$dev already on bridge $bridge"
|
||||
fi
|
||||
@@ -150,11 +140,8 @@
|
||||
# Don't remove $dev from $bridge if it's not on the bridge.
|
||||
if [ -e "/sys/class/net/${bridge}/brif/${dev}" ]; then
|
||||
log debug "removing $dev from bridge $bridge"
|
||||
- if which brctl >&/dev/null; then
|
||||
- do_without_error brctl delif ${bridge} ${dev}
|
||||
- else
|
||||
do_without_error ip link set ${dev} nomaster
|
||||
- fi
|
||||
+ do_without_error ip link set "$dev" down
|
||||
else
|
||||
log debug "$dev not on bridge $bridge"
|
||||
fi
|
||||
|
@@ -1,16 +0,0 @@
|
||||
Index: xen-4.18.0-testing/xen/arch/x86/hvm/stdvga.c
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/xen/arch/x86/hvm/stdvga.c
|
||||
+++ xen-4.18.0-testing/xen/arch/x86/hvm/stdvga.c
|
||||
@@ -165,7 +165,10 @@ static int stdvga_outb(uint64_t addr, ui
|
||||
|
||||
/* When in standard vga mode, emulate here all writes to the vram buffer
|
||||
* so we can immediately satisfy reads without waiting for qemu. */
|
||||
- s->stdvga = (s->sr[7] == 0x00);
|
||||
+ s->stdvga =
|
||||
+ (s->sr[7] == 0x00) && /* standard vga mode */
|
||||
+ (s->gr[6] == 0x05); /* misc graphics register w/ MemoryMapSelect=1
|
||||
+ * 0xa0000-0xaffff (64k region), AlphaDis=1 */
|
||||
|
||||
if ( !prev_stdvga && s->stdvga )
|
||||
{
|
BIN
stubdom.tar.bz2
(Stored with Git LFS)
BIN
stubdom.tar.bz2
(Stored with Git LFS)
Binary file not shown.
@@ -1,20 +0,0 @@
|
||||
xendomains: remove libvirtd conflict
|
||||
|
||||
Conflicting with libvirtd is fine for upstream, where xl/libxl is king.
|
||||
But down the SUSE stream, we promote libvirt and all the libvirt-based
|
||||
tools. If a user installs libvirt on their SUSE Xen host, then libvirt
|
||||
should be king and override xendomains.
|
||||
|
||||
bsc#1015348
|
||||
Index: xen-4.8.0-testing/tools/hotplug/Linux/systemd/xendomains.service.in
|
||||
===================================================================
|
||||
--- xen-4.8.0-testing.orig/tools/hotplug/Linux/systemd/xendomains.service.in
|
||||
+++ xen-4.8.0-testing/tools/hotplug/Linux/systemd/xendomains.service.in
|
||||
@@ -5,7 +5,6 @@ After=proc-xen.mount xenstored.service x
|
||||
After=network-online.target
|
||||
After=remote-fs.target
|
||||
ConditionPathExists=/proc/xen/capabilities
|
||||
-Conflicts=libvirtd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
@@ -1,25 +0,0 @@
|
||||
References: bsc#985503
|
||||
|
||||
Index: xen-4.15.1-testing/tools/hotplug/Linux/vif-route
|
||||
===================================================================
|
||||
--- xen-4.15.1-testing.orig/tools/hotplug/Linux/vif-route
|
||||
+++ xen-4.15.1-testing/tools/hotplug/Linux/vif-route
|
||||
@@ -57,11 +57,13 @@ case "${type_if}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
-# If we've been given a list of IP addresses, then add routes from dom0 to
|
||||
-# the guest using those addresses.
|
||||
-for addr in ${ip} ; do
|
||||
- ${cmdprefix} ip route ${ipcmd} ${addr} dev ${dev} src ${main_ip} metric ${metric}
|
||||
-done
|
||||
+if [ "${ip}" ] && [ "${ipcmd}" ] ; then
|
||||
+ # If we've been given a list of IP addresses, then add routes from dom0 to
|
||||
+ # the guest using those addresses.
|
||||
+ for addr in ${ip} ; do
|
||||
+ ${cmdprefix} ip route ${ipcmd} ${addr} dev ${dev} src ${main_ip} metric ${metric}
|
||||
+ done
|
||||
+fi
|
||||
|
||||
handle_iptable
|
||||
|
@@ -2,7 +2,7 @@ Change default IO-APIC ack mode for single IO-APIC systems to old-style.
|
||||
|
||||
--- a/xen/arch/x86/io_apic.c
|
||||
+++ b/xen/arch/x86/io_apic.c
|
||||
@@ -2076,7 +2076,10 @@ void __init setup_IO_APIC(void)
|
||||
@@ -2152,7 +2152,10 @@ void __init setup_IO_APIC(void)
|
||||
io_apic_irqs = ~PIC_IRQS;
|
||||
|
||||
printk("ENABLING IO-APIC IRQs\n");
|
||||
|
BIN
xen-4.18.3-testing-src.tar.bz2
(Stored with Git LFS)
BIN
xen-4.18.3-testing-src.tar.bz2
(Stored with Git LFS)
Binary file not shown.
BIN
xen-4.20.1-testing-src.tar.bz2
(Stored with Git LFS)
Normal file
BIN
xen-4.20.1-testing-src.tar.bz2
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -1,13 +1,13 @@
|
||||
Index: xen-4.18.0-testing/xen/arch/Kconfig
|
||||
Index: xen-4.20.0-testing/xen/arch/Kconfig
|
||||
===================================================================
|
||||
--- xen-4.18.0-testing.orig/xen/arch/Kconfig
|
||||
+++ xen-4.18.0-testing/xen/arch/Kconfig
|
||||
@@ -7,7 +7,7 @@ config PHYS_ADDR_T_32
|
||||
config NR_CPUS
|
||||
--- xen-4.20.0-testing.orig/xen/arch/Kconfig
|
||||
+++ xen-4.20.0-testing/xen/arch/Kconfig
|
||||
@@ -8,7 +8,7 @@ config NR_CPUS
|
||||
int "Maximum number of CPUs"
|
||||
range 1 4095
|
||||
range 1 1 if ARM && MPU
|
||||
range 1 16383
|
||||
- default "256" if X86
|
||||
+ default "1024" if X86
|
||||
default "1" if ARM && MPU
|
||||
default "8" if ARM && RCAR3
|
||||
default "4" if ARM && QEMU
|
||||
default "4" if ARM && MPSOC
|
||||
|
@@ -1,7 +1,5 @@
|
||||
Index: xen-4.18.3-testing/tools/xs-clients/Makefile
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/xs-clients/Makefile
|
||||
+++ xen-4.18.3-testing/tools/xs-clients/Makefile
|
||||
--- a/tools/xs-clients/Makefile
|
||||
+++ b/tools/xs-clients/Makefile
|
||||
@@ -29,7 +29,7 @@ all: $(TARGETS)
|
||||
clients: xenstore $(CLIENTS) xenstore-control
|
||||
|
||||
@@ -20,10 +18,8 @@ Index: xen-4.18.3-testing/tools/xs-clients/Makefile
|
||||
done
|
||||
|
||||
.PHONY: uninstall
|
||||
Index: xen-4.18.3-testing/tools/xenstored/Makefile
|
||||
===================================================================
|
||||
--- xen-4.18.3-testing.orig/tools/xenstored/Makefile
|
||||
+++ xen-4.18.3-testing/tools/xenstored/Makefile
|
||||
--- a/tools/xenstored/Makefile
|
||||
+++ b/tools/xenstored/Makefile
|
||||
@@ -32,6 +32,7 @@ TAGS:
|
||||
install: all
|
||||
$(INSTALL_DIR) $(DESTDIR)$(sbindir)
|
||||
|
@@ -60,11 +60,15 @@ conf_files $OF "$XEN_CONF_FILES"
|
||||
log_cmd $OF "xl list --long"
|
||||
log_cmd $OF "xl dmesg"
|
||||
# network-related info often useful for debugging
|
||||
if [ systemctl is-enabled NetworkManager.service 2>&1 > /dev/null ]; then
|
||||
if systemctl is-enabled NetworkManager.service &> /dev/null ; then
|
||||
log_write $OF "NOTE: NetworkManager should not be enabled on a Xen host"
|
||||
fi
|
||||
log_cmd $OF "route -n"
|
||||
log_cmd $OF "arp -v"
|
||||
for proto in '-4' '-6'
|
||||
do
|
||||
log_cmd $OF "ip $proto neighbor show"
|
||||
log_cmd $OF "ip $proto route show"
|
||||
log_cmd $OF "ip $proto address show"
|
||||
done
|
||||
log_cmd $OF "ip link show type bridge"
|
||||
log_cmd $OF "bridge link show"
|
||||
# list contents of common config and image directories
|
||||
|
@@ -20,7 +20,7 @@ actually handle. The default is zero tolerance.
|
||||
unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */
|
||||
DEFINE_SPINLOCK(rtc_lock);
|
||||
unsigned long pit0_ticks;
|
||||
@@ -2720,6 +2723,8 @@ int tsc_set_info(struct domain *d,
|
||||
@@ -2926,6 +2929,8 @@ int tsc_set_info(struct domain *d,
|
||||
|
||||
switch ( tsc_mode )
|
||||
{
|
||||
@@ -29,7 +29,7 @@ actually handle. The default is zero tolerance.
|
||||
case XEN_CPUID_TSC_MODE_DEFAULT:
|
||||
case XEN_CPUID_TSC_MODE_ALWAYS_EMULATE:
|
||||
d->arch.vtsc_offset = get_s_time() - elapsed_nsec;
|
||||
@@ -2733,8 +2738,25 @@ int tsc_set_info(struct domain *d,
|
||||
@@ -2939,8 +2944,25 @@ int tsc_set_info(struct domain *d,
|
||||
* When a guest is created, gtsc_khz is passed in as zero, making
|
||||
* d->arch.tsc_khz == cpu_khz. Thus no need to check incarnation.
|
||||
*/
|
||||
|
490
xen.changes
490
xen.changes
@@ -1,3 +1,472 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu Jul 10 05:25:48 MDT 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.1 bug fix release (jsc#PED-8907)
|
||||
* No upstream changelog found in sources or webpage
|
||||
- bsc#1246112 - VUL-0: xen: More AMD transient execution attacks
|
||||
(XSA-471)
|
||||
Patches contained in new tarball for 4.20.1
|
||||
- Drop patches contained in new tarball
|
||||
67c818d4-x86-log-unhandled-mem-accesses-for-PVH-dom0.patch
|
||||
67c818d5-x86-fixup-p2m-page-faults-for-PVH-dom0.patch
|
||||
67c818d6-x86-PVH-dom0-correct-iomem_caps-bound.patch
|
||||
67c818d7-x86-IOMMU-account-for-IOMEM-caps-when-populating.patch
|
||||
67c818d8-x86-Dom0-relax-Interrupt-Address-Range.patch
|
||||
67c86fc1-xl-fix-channel-configuration-setting.patch
|
||||
67cb03e0-x86-vlapic-ESR-write-handling.patch
|
||||
67d17edd-x86-expose-MSR_FAM10H_MMIO_CONF_BASE-on-AMD.patch
|
||||
67d17ede-VT-x-PI-usage-of-msi_desc-msg-field.patch
|
||||
67d2a3fe-libxl-avoid-infinite-loop-in-libxl__remove_directory.patch
|
||||
67dada68-x86-mm-IS_ALIGNED-in-IS_LnE_ALIGNED.patch
|
||||
67ea4268-x86-P2M-sync-fast-slow-p2m_get_page_from_gfn.patch
|
||||
67ea428e-percpu-dont-init-on-resume.patch
|
||||
67f8ecda-rangeset-incorrect-subtraction.patch
|
||||
6800b54f-x86-HVM-update-repeat-count-upon.patch
|
||||
68076044-x86emul-clip-rep-count-for-STOS.patch
|
||||
6808f549-x86-Intel-work-around-MONITOR-MWAIT-errata.patch
|
||||
68221f20-x86-alternative-when-feature-not-present.patch
|
||||
68221f21-x86-guest-remove-Xen-hypercall_page.patch
|
||||
68221f22-x86-misalign-__x86_indirect_thunk.patch
|
||||
68221f23-x86-misalign-RETs-in-clear_bhb_loops.patch
|
||||
68221f24-x86-stubs-introduce-place_ret.patch
|
||||
68221f25-x86-build-with-Return-Thunks.patch
|
||||
68221f26-x86-spec-ctrl-synthesise-ITS_NO.patch
|
||||
682dff83-x86-vPCI-BAR-overlaps-with-non-holes.patch
|
||||
6835a042-VMX-VMEntry-failure-on-ADL-SPR-with-shadow.patch
|
||||
6835a043-x86-PV-breakpoint-reporting.patch
|
||||
xsa470.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jun 16 15:58:00 CEST 2025 - jbeulich@suse.com
|
||||
|
||||
- bsc#1244644 - VUL-0: CVE-2025-27465: xen: x86: Incorrect stubs
|
||||
exception handling for flags recovery (XSA-470)
|
||||
xsa470.patch
|
||||
- Upstream bug fixes (bsc#1027519)
|
||||
682dff83-x86-vPCI-BAR-overlaps-with-non-holes.patch
|
||||
6835a042-VMX-VMEntry-failure-on-ADL-SPR-with-shadow.patch
|
||||
6835a043-x86-PV-breakpoint-reporting.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue May 13 13:48:00 CEST 2025 - jbeulich@suse.com
|
||||
|
||||
- bsc#1243117 - VUL-0: CVE-2024-28956: xen: Intel CPU: Indirect
|
||||
Target Selection (ITS) (XSA-469)
|
||||
68221f20-x86-alternative-when-feature-not-present.patch
|
||||
68221f21-x86-guest-remove-Xen-hypercall_page.patch
|
||||
68221f22-x86-misalign-__x86_indirect_thunk.patch
|
||||
68221f23-x86-misalign-RETs-in-clear_bhb_loops.patch
|
||||
68221f24-x86-stubs-introduce-place_ret.patch
|
||||
68221f25-x86-build-with-Return-Thunks.patch
|
||||
68221f26-x86-spec-ctrl-synthesise-ITS_NO.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon May 12 09:07:55 MDT 2025 - carnold@suse.com
|
||||
|
||||
- Default to running xenstored in pvh mode
|
||||
xenstore-run-in-pvh-mode.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Apr 28 12:55:00 CEST 2025 - jbeulich@suse.com
|
||||
|
||||
- Upstream bug fixes (bsc#1027519)
|
||||
67dada68-x86-mm-IS_ALIGNED-in-IS_LnE_ALIGNED.patch
|
||||
67ea4268-x86-P2M-sync-fast-slow-p2m_get_page_from_gfn.patch
|
||||
67ea428e-percpu-dont-init-on-resume.patch
|
||||
67f8ecda-rangeset-incorrect-subtraction.patch
|
||||
6800b54f-x86-HVM-update-repeat-count-upon.patch
|
||||
68076044-x86emul-clip-rep-count-for-STOS.patch
|
||||
6808f549-x86-Intel-work-around-MONITOR-MWAIT-errata.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Apr 14 10:38:51 MDT 2025 - carnold@suse.com
|
||||
|
||||
- Disable pv support for PVH only systems.
|
||||
disable-pv-support.patch
|
||||
- Updated the spec file by removing what isn't needed to support
|
||||
PVH only systems
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Mar 31 14:37:13 MDT 2025 - carnold@suse.com
|
||||
|
||||
- Drop legacy patches supporting deprecated features
|
||||
suse-xendomains-service.patch
|
||||
build-python3-conversion.patch
|
||||
pygrub-boot-legacy-sles.patch
|
||||
pygrub-handle-one-line-menu-entries.patch
|
||||
xen2libvirt.py
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Mar 13 12:50:00 CET 2025 - jbeulich@suse.com
|
||||
|
||||
- bsc#1219354 - xen channels and domU console
|
||||
67c86fc1-xl-fix-channel-configuration-setting.patch
|
||||
- bsc#1227301 - Kernel boot crashes on Thinkpad P14s Gen 3 AMD
|
||||
67c818d4-x86-log-unhandled-mem-accesses-for-PVH-dom0.patch
|
||||
67c818d5-x86-fixup-p2m-page-faults-for-PVH-dom0.patch
|
||||
67c818d6-x86-PVH-dom0-correct-iomem_caps-bound.patch
|
||||
67c818d7-x86-IOMMU-account-for-IOMEM-caps-when-populating.patch
|
||||
67c818d8-x86-Dom0-relax-Interrupt-Address-Range.patch
|
||||
- bsc#1237692 - When attempting to start guest vm's libxl fills disk with errors
|
||||
67d2a3fe-libxl-avoid-infinite-loop-in-libxl__remove_directory.patch
|
||||
- bsc#1241206 - xen fv domU failed to migrate from sle15SP6 host
|
||||
to sle15SP7 host
|
||||
67cb03e0-x86-vlapic-ESR-write-handling.patch
|
||||
- Upstream bug fixes (bsc#1027519)
|
||||
67d17edd-x86-expose-MSR_FAM10H_MMIO_CONF_BASE-on-AMD.patch
|
||||
67d17ede-VT-x-PI-usage-of-msi_desc-msg-field.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Mar 5 06:18:13 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 FCS release (jsc#PED-8907)
|
||||
* See release candidate changelog entries below for 4.20.0
|
||||
* Reduce xenstore library dependencies.
|
||||
* Enable CONFIG_UBSAN (Arm64, x86, PPC, RISC-V) for GitLab CI.
|
||||
* Support for Intel EPT Paging-Write Feature.
|
||||
* AMD Zen 5 CPU support, including for new hardware mitigations
|
||||
for the SRSO speculative vulnerability.
|
||||
- bsc#1238043 - VUL-0: CVE-2025-1713: xen: deadlock potential with
|
||||
VT-d and legacy PCI device pass-through (XSA-467)
|
||||
This fix is part of the final tarball
|
||||
- Remove references to vm-install from README.SUSE
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Feb 28 09:09:09 UTC 2025 - ohering@suse.de
|
||||
|
||||
- refresh replace-obsolete-network-configuration-commands-in-s.patch
|
||||
to not accidently enter untested brctl code paths
|
||||
- bsc#985503 - vif-route.patch is obsolete since Xen 4.15
|
||||
- bsc#1035231 - remove SUSE specific changes for save/restore/migrate
|
||||
to reduce future maintainence overhead. The bottleneck during
|
||||
migration is the overhead of mapping HVM domU pages into dom0,
|
||||
which was not addressed by these changes.
|
||||
The options --abort_if_busy --max_iters --min_remaining will not
|
||||
be recognized anymore by xl or virsh.
|
||||
libxc-bitmap-long.patch
|
||||
libxc-sr-xl-migration-debug.patch
|
||||
libxc-sr-readv_exact.patch
|
||||
libxc-sr-save-show_transfer_rate.patch
|
||||
libxc-sr-save-mfns.patch
|
||||
libxc-sr-save-types.patch
|
||||
libxc-sr-save-errors.patch
|
||||
libxc-sr-save-iov.patch
|
||||
libxc-sr-save-rec_pfns.patch
|
||||
libxc-sr-save-guest_data.patch
|
||||
libxc-sr-save-local_pages.patch
|
||||
libxc-sr-restore-pfns.patch
|
||||
libxc-sr-restore-types.patch
|
||||
libxc-sr-restore-mfns.patch
|
||||
libxc-sr-restore-map_errs.patch
|
||||
libxc-sr-restore-populate_pfns-pfns.patch
|
||||
libxc-sr-restore-populate_pfns-mfns.patch
|
||||
libxc-sr-restore-read_record.patch
|
||||
libxc-sr-restore-handle_buffered_page_data.patch
|
||||
libxc-sr-restore-handle_incoming_page_data.patch
|
||||
libxc-sr-LIBXL_HAVE_DOMAIN_SUSPEND_PROPS.patch
|
||||
libxc-sr-precopy_policy.patch
|
||||
libxc-sr-max_iters.patch
|
||||
libxc-sr-min_remaining.patch
|
||||
libxc-sr-abort_if_busy.patch
|
||||
libxc-sr-xg_sr_bitmap.patch
|
||||
libxc-sr-xg_sr_bitmap-populated_pfns.patch
|
||||
libxc-sr-restore-hvm-legacy-superpage.patch
|
||||
libxc-sr-track-migration-time.patch
|
||||
libxc-sr-number-of-iterations.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Feb 20 10:09:41 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 RC5 release
|
||||
* x86/shutdown: offline APs with interrupts disabled on all CPUs
|
||||
* x86/smp: perform disabling on interrupts ahead of AP shutdown
|
||||
* x86/pci: disable MSI(-X) on all devices at shutdown
|
||||
* x86/iommu: disable interrupts at shutdown
|
||||
* x86/HVM: use XVFREE() in hvmemul_cache_destroy()
|
||||
* xen/console: Fix truncation of panic() messages
|
||||
* xen/memory: Make resource_max_frames() to return 0 on unknown
|
||||
type
|
||||
* x86/svm: Separate STI and VMRUN instructions in
|
||||
svm_asm_do_resume()
|
||||
* x86/MCE-telem: adjust cookie definition
|
||||
- Drop patch contained in new tarball
|
||||
x86-shutdown-offline-APs-with-interrupts-disabled-on-all-CPUs.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Feb 11 09:43:18 MST 2025 - carnold@suse.com
|
||||
|
||||
- bsc#1233796 - [XEN][15-SP7-BEAT3] Xen call trace and APIC Error
|
||||
found after reboot operation on AMD machine.
|
||||
x86-shutdown-offline-APs-with-interrupts-disabled-on-all-CPUs.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Feb 10 06:02:04 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 RC4 release
|
||||
* AMD/IOMMU: log IVHD contents
|
||||
* AMD/IOMMU: drop stray MSI enabling
|
||||
* radix-tree: introduce RADIX_TREE{,_INIT}()
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Jan 31 09:59:45 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 RC3 release
|
||||
* x86/HVM: correct MMIO emulation cache bounds check
|
||||
* x86/HVM: allocate emulation cache entries dynamically
|
||||
* x86/HVM: correct read/write split at page boundaries
|
||||
* x86/iommu: check for CMPXCHG16B when enabling IOMMU
|
||||
* iommu/vtd: remove non-CX16 logic from interrupt remapping
|
||||
* x86/iommu: remove non-CX16 logic from DMA remapping
|
||||
* iommu/amd: atomically update IRTE
|
||||
* x86emul: further correct 64-bit mode zero count repeated string
|
||||
insn handling
|
||||
* x86/PV: further harden guest memory accesses against speculative
|
||||
abuse
|
||||
* x86/intel: Fix PERF_GLOBAL fixup when virtualised
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Jan 31 08:49:14 UTC 2025 - Markéta Machová <mmachova@suse.com>
|
||||
|
||||
- Add explicit build dependency on python3-setuptools, needed by python313
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jan 20 05:46:51 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 RC2 release
|
||||
* xen/arm: Fully initialise struct membanks_hdr fields
|
||||
* build: Set DATE to SOURCE_DATE_EPOCH if available (for
|
||||
reproducible builds)
|
||||
* x86: Add Support for Paging-Write Feature
|
||||
* x86/time: introduce command line option to select wallclock
|
||||
* x86/time: prefer CMOS over EFI_GET_TIME
|
||||
* xentrace: free CPU mask string before overwriting pointer
|
||||
* xl: properly dispose of vTPM struct instance
|
||||
* xl: properly dispose of libxl_dominfo struct instances
|
||||
* Various documentation fixes and updates (including ppc and
|
||||
riscv additions)
|
||||
* Various MISRA compliance improvements.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Jan 10 12:43:42 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 RC1 release
|
||||
* x86/amd: Misc setup for Fam1Ah processors
|
||||
* xen/perfc cleanups and adjustments
|
||||
* libxl: drop setting XEN_QEMU_CONSOLE_LIMIT in the environment
|
||||
(XSA-180 / CVE-2014-3672)
|
||||
* x86emul: VCVT{,U}DQ2PD ignores embedded rounding
|
||||
* x86emul: correct put_fpu()'s segment selector handling
|
||||
* xen/flask: Wire up XEN_DOMCTL_dt_overlay and XEN_DOMCTL_set_llc_colors
|
||||
* xen/events: fix race with set_global_virq_handler()
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jan 6 06:01:11 MST 2025 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.20.0 pre-release (jsc#PED-8907)
|
||||
xen-4.20.0-testing-src.tar.bz2
|
||||
- New Features
|
||||
* On Arm:
|
||||
- Experimental support for Armv8-R.
|
||||
- Support for NXP S32G3 Processors Family and NXP LINFlexD UART driver.
|
||||
- Basic handling for SCMI requests over SMC using Shared Memory, by allowing
|
||||
forwarding the calls to EL3 FW if coming from hwdom.
|
||||
- Support for LLC (Last Level Cache) coloring.
|
||||
* On x86:
|
||||
- xl suspend/resume subcommands.
|
||||
- Support for SRSO_U/S_NO and SRSO_MSR_FIX
|
||||
- Changed Features
|
||||
* Fixed blkif protocol specification for sector sizes different than 512b.
|
||||
* The dombuilder in libxenguest no longer un-gzips secondary modules, instead
|
||||
leaving this to the guest kernel to do in guest context.
|
||||
* On x86:
|
||||
- Prefer ACPI reboot over UEFI ResetSystem() run time service call.
|
||||
- Switched the xAPIC flat driver to use physical destination mode for external
|
||||
interrupts instead of logical destination mode.
|
||||
- Removed Features
|
||||
* On x86:
|
||||
- Support for running on Xeon Phi processors.
|
||||
- Removed the `ucode=allow-same` command line option.
|
||||
- Removed x2APIC Cluster Mode for external interrupts. x2APIC Physical and
|
||||
Mixed Modes are still available.
|
||||
- Dropped patches
|
||||
xsa466.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Dec 11 11:11:11 UTC 2024 - ohering@suse.de
|
||||
|
||||
- Move /etc/bash_completion.d/xl back to %_datadir/bash-completion/completions
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Dec 9 10:13:51 MST 2024 - carnold@suse.com
|
||||
|
||||
- bsc#1234282 - VUL-0: xen: XSA-466: Xen hypercall page unsafe
|
||||
against speculative attacks
|
||||
xsa466.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Dec 4 09:16:24 MST 2024 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.19.1 bug fix release (jsc#PED-8907)
|
||||
xen-4.19.1-testing-src.tar.bz2
|
||||
* No upstream changelog found in sources or webpage
|
||||
- Dropped patches
|
||||
66a8b8ac-bunzip2-rare-failure.patch
|
||||
66bb6f78-x86-IOMMU-move-tracking-in-iommu_identity_mapping.patch
|
||||
66bb6fa5-x86-pass-through-document-as-security-unsupported.patch
|
||||
66cf737b-x86-Dom0-disable-SMAP-for-PV-only.patch
|
||||
66d02b69-Arm64-adjust-irq_to_desc-to-fix-build-with-gcc14.patch
|
||||
66d6dca8-libxl-nul-termination-in-xen_console_read_line.patch
|
||||
66d8690f-SUPPORT-split-XSM-from-Flask.patch
|
||||
66e29480-x86-HVM-properly-reject-indirect-VRAM-writes.patch
|
||||
66e44ae2-x86-ucode-AMD-buffer-underrun.patch
|
||||
66f2af41-x86-vLAPIC-undue-recursion-of-vlapic_error.patch
|
||||
66f2fd92-x86-ucode-Intel-stricter-sanity-check.patch
|
||||
xsa463-01.patch
|
||||
xsa463-02.patch
|
||||
xsa463-03.patch
|
||||
xsa463-04.patch
|
||||
xsa463-05.patch
|
||||
xsa463-06.patch
|
||||
xsa463-07.patch
|
||||
xsa463-08.patch
|
||||
xsa463-09.patch
|
||||
xsa464.patch
|
||||
gcc14-fixes.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Oct 30 09:34:38 MDT 2024 - carnold@suse.com
|
||||
|
||||
- bsc#1232622 - VUL-0: CVE-2024-45818: xen: Deadlock in x86 HVM
|
||||
standard VGA handling (XSA-463)
|
||||
xsa463-01.patch
|
||||
xsa463-02.patch
|
||||
xsa463-03.patch
|
||||
xsa463-04.patch
|
||||
xsa463-05.patch
|
||||
xsa463-06.patch
|
||||
xsa463-07.patch
|
||||
xsa463-08.patch
|
||||
xsa463-09.patch
|
||||
- bsc#1232624 - VUL-0: CVE-2024-45819: xen: libxl leaks data to PVH
|
||||
guests via ACPI tables (XSA-464)
|
||||
xsa464.patch
|
||||
- Drop stdvga-cache.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Oct 29 12:34:56 UTC 2024 - ohering@suse.de
|
||||
|
||||
- bsc#1232542 - remove usage of net-tools-deprecated from supportconfig plugin
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Sep 26 11:30:00 CEST 2024 - jbeulich@suse.com
|
||||
|
||||
- bsc#1230366 - VUL-0: CVE-2024-45817: xen: x86: Deadlock in
|
||||
vlapic_error() (XSA-462)
|
||||
66f2af41-x86-vLAPIC-undue-recursion-of-vlapic_error.patch
|
||||
Drop xsa462.patch
|
||||
- Upstream bug fixes (bsc#1027519)
|
||||
66cf737b-x86-Dom0-disable-SMAP-for-PV-only.patch
|
||||
66d6dca8-libxl-nul-termination-in-xen_console_read_line.patch
|
||||
66d8690f-SUPPORT-split-XSM-from-Flask.patch
|
||||
66e29480-x86-HVM-properly-reject-indirect-VRAM-writes.patch
|
||||
66e44ae2-x86-ucode-AMD-buffer-underrun.patch
|
||||
66f2fd92-x86-ucode-Intel-stricter-sanity-check.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Sep 10 09:54:34 MDT 2024 - carnold@suse.com
|
||||
|
||||
- bsc#1230366 - VUL-0: CVE-2024-45817: xen: x86: Deadlock in
|
||||
vlapic_error() (XSA-462)
|
||||
xsa462.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Aug 30 07:32:58 UTC 2024 - Guillaume GARDET <guillaume.gardet@opensuse.org>
|
||||
|
||||
- Fix build on aarch64 with gcc14 (bsc#1225953)
|
||||
66d02b69-Arm64-adjust-irq_to_desc-to-fix-build-with-gcc14.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Aug 15 15:13:42 MDT 2024 - carnold@suse.com
|
||||
|
||||
- Update to Xen 4.19.0 FCS release (jsc#PED-8907)
|
||||
xen-4.19.0-testing-src.tar.bz2
|
||||
- New Features
|
||||
* On x86:
|
||||
- Introduce a new x2APIC driver that uses Cluster Logical addressing mode
|
||||
for IPIs and Physical addressing mode for external interrupts.
|
||||
* On Arm:
|
||||
- FF-A notification support.
|
||||
- Introduction of dynamic node programming using overlay dtbo.
|
||||
* Add a new 9pfs backend running as a daemon in dom0. First user is
|
||||
Xenstore-stubdom now being able to support full Xenstore trace capability.
|
||||
* libxl support for backendtype=tap with tapback.
|
||||
- Changed Features
|
||||
* Changed flexible array definitions in public I/O interface headers to not
|
||||
use "1" as the number of array elements.
|
||||
* The minimum supported OCaml toolchain version is now 4.05
|
||||
* On x86:
|
||||
- HVM PIRQs are disabled by default.
|
||||
- Reduce IOMMU setup time for hardware domain.
|
||||
- Allow HVM/PVH domains to map foreign pages.
|
||||
- Declare PVH dom0 supported with caveats.
|
||||
* xl/libxl configures vkb=[] for HVM domains with priority over vkb_device.
|
||||
* Increase the maximum number of CPUs Xen can be built for from 4095 to
|
||||
16383.
|
||||
* When building with Systemd support (./configure --enable-systemd), remove
|
||||
libsystemd as a build dependency. Systemd Notify support is retained, now
|
||||
using a standalone library implementation.
|
||||
* xenalyze no longer requires `--svm-mode` when analyzing traces
|
||||
generated on AMD CPUs
|
||||
* Code symbol annotations and MISRA compliance improvements.
|
||||
- Removed Features
|
||||
* caml-stubdom. It hasn't built since 2014, was pinned to Ocaml 4.02, and has
|
||||
been superseded by the MirageOS/SOLO5 projects.
|
||||
* /usr/bin/pygrub symlink. This was deprecated in Xen 4.2 (2012) but left for
|
||||
compatibility reasons. VMs configured with bootloader="/usr/bin/pygrub"
|
||||
should be updated to just bootloader="pygrub".
|
||||
* The Xen gdbstub on x86.
|
||||
* xentrace_format has been removed; use xenalyze instead.
|
||||
- Dropped patches contained in new tarball
|
||||
6617d62c-x86-hvm-Misra-Rule-19-1-regression.patch
|
||||
6627a4ee-vRTC-UIP-set-for-longer-than-expected.patch
|
||||
6627a5fc-x86-MTRR-inverted-WC-check.patch
|
||||
662a6a4c-x86-spec-reporting-of-BHB-clearing.patch
|
||||
662a6a8d-x86-spec-adjust-logic-to-elide-LFENCE.patch
|
||||
663090fd-x86-gen-cpuid-syntax.patch
|
||||
663a383c-libxs-open-xenbus-fds-as-O_CLOEXEC.patch
|
||||
663a4f3e-x86-cpu-policy-migration-IceLake-to-CascadeLake.patch
|
||||
663d05b5-x86-ucode-distinguish-up-to-date.patch
|
||||
663eaa27-libxl-XenStore-error-handling-in-device-creation.patch
|
||||
66450626-sched-set-all-sched_resource-data-inside-locked.patch
|
||||
66450627-x86-respect-mapcache_domain_init-failing.patch
|
||||
6646031f-x86-ucode-further-identify-already-up-to-date.patch
|
||||
6666ba52-x86-irq-remove-offline-CPUs-from-old-CPU-mask-when.patch
|
||||
666994ab-x86-SMP-no-shorthand-IPI-in-hotplug.patch
|
||||
666994f0-x86-IRQ-limit-interrupt-movement-in-fixup_irqs.patch
|
||||
666b07ee-x86-EPT-special-page-in-epte_get_entry_emt.patch
|
||||
666b0819-x86-EPT-avoid-marking-np-ents-for-reconfig.patch
|
||||
666b085a-x86-EPT-drop-questionable-mfn_valid-from-.patch
|
||||
667187cc-x86-Intel-unlock-CPUID-earlier.patch
|
||||
66718849-x86-IRQ-old_cpu_mask-in-fixup_irqs.patch
|
||||
6671885e-x86-IRQ-handle-moving-in-_assign_irq_vector.patch
|
||||
6672c846-x86-xstate-initialisation-of-XSS-cache.patch
|
||||
6672c847-x86-CPUID-XSAVE-dynamic-leaves.patch
|
||||
6673ffdc-x86-IRQ-forward-pending-to-new-dest-in-fixup_irqs.patch
|
||||
xsa458.patch
|
||||
- Dropped patches no longer necessary
|
||||
bin-python3-conversion.patch
|
||||
migration-python3-conversion.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Aug 14 14:10:47 MDT 2024 - carnold@suse.com
|
||||
|
||||
- bsc#1228574 - VUL-0: CVE-2024-31145: xen: error handling in x86
|
||||
IOMMU identity mapping (XSA-460)
|
||||
66bb6f78-x86-IOMMU-move-tracking-in-iommu_identity_mapping.patch
|
||||
- bsc#1228575 - VUL-0: CVE-2024-31146: xen: PCI device pass-through
|
||||
with shared resources (XSA-461)
|
||||
66bb6fa5-x86-pass-through-document-as-security-unsupported.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Aug 14 11:33:39 MDT 2024 - carnold@suse.com
|
||||
|
||||
@@ -35,6 +504,17 @@ Wed Aug 14 11:33:39 MDT 2024 - carnold@suse.com
|
||||
6673ffdc-x86-IRQ-forward-pending-to-new-dest-in-fixup_irqs.patch
|
||||
xsa458.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Aug 7 08:06:00 CEST 2024 - jbeulich@suse.com
|
||||
|
||||
- Upstream bug fixes (bsc#1027519)
|
||||
66a8b8ac-bunzip2-rare-failure.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Jul 23 09:43:13 UTC 2024 - Franz Sirl <franz.sirl-obs@lauterbach.com>
|
||||
|
||||
- Enable support for ZSTD and LZO compression formats
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jul 3 12:41:39 MDT 2024 - carnold@suse.com
|
||||
|
||||
@@ -5642,7 +6122,7 @@ Thu Nov 19 07:38:06 UTC 2015 - ohering@suse.de
|
||||
- Remove xenalyze.hg, its part of xen-4.6
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Nov 10 16:16:24 MDT 2015 - carnold@suse.com
|
||||
Wed Nov 11 16:16:24 MST 2015 - carnold@suse.com
|
||||
|
||||
- Update to Xen Version 4.6.0
|
||||
xen-4.6.0-testing-src.tar.bz2
|
||||
@@ -7258,7 +7738,7 @@ Mon Nov 11 10:22:20 MST 2013 - carnold@suse.com
|
||||
5280aae0-x86-idle-reduce-contention-on-ACPI-register-accesses.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Nov 4 09:42:36 MDT 2013 - carnold@suse.com
|
||||
Mon Nov 4 09:42:36 MST 2013 - carnold@suse.com
|
||||
|
||||
- bnc#848657 - VUL-0: xen: CVE-2013-4494: XSA-73: Lock order
|
||||
reversal between page allocation and grant table locks
|
||||
@@ -8129,7 +8609,7 @@ Fri Nov 9 10:29:51 MST 2012 - carnold@novell.com
|
||||
xen-max-free-mem.diff
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Nov 6 17:41:34 MDT 2012 - carnold@novell.com
|
||||
Tue Nov 6 17:41:34 MST 2012 - carnold@novell.com
|
||||
|
||||
- fate#311966: Fix XEN VNC implementation to correctly map keyboard
|
||||
layouts
|
||||
@@ -9789,7 +10269,7 @@ Wed Apr 20 17:50:04 CEST 2011 - ohering@suse.de
|
||||
- bnc#688519: correct indention in xend-domain-lock.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Apr 19 06:43:19 MST 2011 - jfehlig@novell.com
|
||||
Tue Apr 19 06:43:19 MDT 2011 - jfehlig@novell.com
|
||||
|
||||
- bnc#687981 - L3: mistyping model type when defining VIF crashes
|
||||
VM
|
||||
@@ -10382,7 +10862,7 @@ Tue Nov 9 10:00:48 MST 2010 - jfehlig@novell.com
|
||||
modified block-iscsi script
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Nov 8 13:11:02 MDT 2010 - jfehlig@novell.com
|
||||
Mon Nov 8 13:11:02 MST 2010 - jfehlig@novell.com
|
||||
|
||||
- bnc#649277 - Fix pci passthru in xend interface used by libvirt
|
||||
22369-xend-pci-passthru-fix.patch
|
||||
|
@@ -9,7 +9,7 @@ References: bsc#954872
|
||||
|
||||
--- a/tools/libs/light/libxl_disk.c
|
||||
+++ b/tools/libs/light/libxl_disk.c
|
||||
@@ -203,7 +203,7 @@ static int libxl__device_disk_setdefault
|
||||
@@ -237,7 +237,7 @@ static int libxl__device_disk_setdefault
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ References: bsc#954872
|
||||
const libxl_device_disk *disk,
|
||||
libxl__device *device)
|
||||
{
|
||||
@@ -372,6 +372,10 @@ static void device_disk_add(libxl__egc *
|
||||
rc = ERROR_FAIL;
|
||||
goto out;
|
||||
@@ -414,6 +414,10 @@ static void device_disk_add(libxl__egc *
|
||||
assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD3);
|
||||
break;
|
||||
case LIBXL_DISK_BACKEND_QDISK:
|
||||
+ if (disk->script) {
|
||||
+ script = libxl__abs_path(gc, disk->script, libxl__xen_script_dir_path());
|
||||
@@ -31,8 +31,8 @@ References: bsc#954872
|
||||
libxl__device_disk_string_of_format(disk->format),
|
||||
--- a/tools/libs/light/libxl_device.c
|
||||
+++ b/tools/libs/light/libxl_device.c
|
||||
@@ -351,7 +351,8 @@ static int disk_try_backend(disk_try_bac
|
||||
return 0;
|
||||
@@ -361,7 +361,8 @@ static int disk_try_backend(disk_try_bac
|
||||
return backend;
|
||||
|
||||
case LIBXL_DISK_BACKEND_QDISK:
|
||||
- if (a->disk->script) goto bad_script;
|
||||
@@ -43,7 +43,7 @@ References: bsc#954872
|
||||
case LIBXL_DISK_BACKEND_STANDALONE:
|
||||
--- a/tools/libs/light/libxl_dm.c
|
||||
+++ b/tools/libs/light/libxl_dm.c
|
||||
@@ -1197,6 +1197,30 @@ out:
|
||||
@@ -1181,6 +1181,30 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ References: bsc#954872
|
||||
static int libxl__build_device_model_args_new(libxl__gc *gc,
|
||||
const char *dm, int guest_domid,
|
||||
const libxl_domain_config *guest_config,
|
||||
@@ -1885,9 +1909,11 @@ static int libxl__build_device_model_arg
|
||||
@@ -1873,9 +1897,11 @@ static int libxl__build_device_model_arg
|
||||
libxl__device_disk_dev_number(disks[i].vdev, &disk, &part);
|
||||
const char *format;
|
||||
char *drive;
|
||||
@@ -89,7 +89,7 @@ References: bsc#954872
|
||||
disks[i].vdev);
|
||||
--- a/tools/libs/util/libxlu_disk_l.l
|
||||
+++ b/tools/libs/util/libxlu_disk_l.l
|
||||
@@ -253,6 +253,8 @@ target=.* { STRIP(','); SAVESTRING("targ
|
||||
@@ -256,6 +256,8 @@ target=.* { STRIP(','); SAVESTRING("targ
|
||||
free(newscript);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ References: bsc#954872
|
||||
aio:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
||||
--- a/tools/libs/light/libxl_internal.h
|
||||
+++ b/tools/libs/light/libxl_internal.h
|
||||
@@ -2073,6 +2073,10 @@ _hidden char *libxl__object_to_json(libx
|
||||
@@ -2068,6 +2068,10 @@ _hidden char *libxl__object_to_json(libx
|
||||
_hidden int libxl__cpuid_legacy(libxl_ctx *ctx, uint32_t domid, bool retore,
|
||||
libxl_domain_build_info *info);
|
||||
|
||||
|
283
xen.spec
283
xen.spec
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package xen
|
||||
#
|
||||
# Copyright (c) 2024 SUSE LLC
|
||||
# Copyright (c) 2025 SUSE LLC
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@@ -26,59 +26,25 @@
|
||||
# Keep it at the original location (/usr/lib) for backward compatibility
|
||||
%define _libexecdir /usr/lib
|
||||
|
||||
%{?!primary_python:%define primary_python python3}
|
||||
|
||||
Name: xen
|
||||
ExclusiveArch: %ix86 x86_64 aarch64
|
||||
%define xen_build_dir xen-4.18.3-testing
|
||||
ExclusiveArch: x86_64
|
||||
%define xen_build_dir xen-4.20.1-testing
|
||||
#
|
||||
%define with_gdbsx 0
|
||||
%define with_dom0_support 0
|
||||
%ifarch x86_64
|
||||
%bcond_without xen_debug
|
||||
%bcond_without xen_stubdom
|
||||
%else
|
||||
%bcond_with xen_debug
|
||||
%bcond_with xen_stubdom
|
||||
%endif
|
||||
#
|
||||
%define qemu_arch i386
|
||||
%ifarch x86_64
|
||||
%define with_gdbsx 1
|
||||
%define with_dom0_support 1
|
||||
%endif
|
||||
#
|
||||
%ifarch %arm aarch64
|
||||
%define with_dom0_support 1
|
||||
%define qemu_arch aarch64
|
||||
%endif
|
||||
#
|
||||
%define xen_install_suffix %{nil}
|
||||
%ifarch x86_64
|
||||
%define xen_install_suffix .gz
|
||||
%endif
|
||||
# EFI requires gcc 4.6 or newer
|
||||
# gcc46 is available in 12.1 or sles11sp2
|
||||
# gcc47 is available in sles11sp3
|
||||
# gcc48 is available in sles11sp4
|
||||
# 12.2+ have gcc 4.7 as default compiler
|
||||
%define with_gcc47 0
|
||||
%define with_gcc48 0
|
||||
%define _fwdefdir /etc/sysconfig/SuSEfirewall2.d/services
|
||||
%systemd_requires
|
||||
BuildRequires: pkgconfig(libsystemd)
|
||||
%define with_systemd_modules_load %{_prefix}/lib/modules-load.d
|
||||
PreReq: %fillup_prereq
|
||||
%ifarch %arm aarch64
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?suse_version} == 1315 && 0%{?sle_version} > 120200 )
|
||||
BuildRequires: libfdt-devel
|
||||
%else
|
||||
BuildRequires: libfdt1-devel
|
||||
%endif
|
||||
%endif
|
||||
BuildRequires: bison
|
||||
BuildRequires: fdupes
|
||||
%if 0%{?suse_version} > 1315
|
||||
BuildRequires: figlet
|
||||
%endif
|
||||
BuildRequires: flex
|
||||
BuildRequires: glib2-devel
|
||||
BuildRequires: libaio-devel
|
||||
@@ -89,42 +55,32 @@ BuildRequires: libuuid-devel
|
||||
BuildRequires: libxml2-devel
|
||||
BuildRequires: libyajl-devel
|
||||
%if %{with xen_stubdom}
|
||||
%if 0%{?suse_version} < 1230
|
||||
BuildRequires: texinfo
|
||||
%else
|
||||
BuildRequires: makeinfo
|
||||
%endif
|
||||
%endif
|
||||
BuildRequires: acpica
|
||||
BuildRequires: libzstd-devel
|
||||
BuildRequires: lzo-devel
|
||||
BuildRequires: ncurses-devel
|
||||
BuildRequires: openssl-devel
|
||||
BuildRequires: python3-devel
|
||||
BuildRequires: python3-setuptools
|
||||
BuildRequires: xz-devel
|
||||
BuildRequires: pkgconfig(systemd)
|
||||
%ifarch x86_64
|
||||
BuildRequires: gcc-32bit
|
||||
BuildRequires: gcc-c++
|
||||
%if %{?with_gcc47}0
|
||||
BuildRequires: gcc47
|
||||
%endif
|
||||
%if %{?with_gcc48}0
|
||||
BuildRequires: gcc48
|
||||
%endif
|
||||
BuildRequires: glibc-32bit
|
||||
BuildRequires: glibc-devel-32bit
|
||||
BuildRequires: makeinfo
|
||||
%endif
|
||||
%ifarch x86_64
|
||||
BuildRequires: pesign-obs-integration
|
||||
%endif
|
||||
BuildRequires: python-rpm-macros
|
||||
Provides: installhint(reboot-needed)
|
||||
|
||||
Version: 4.18.3_02
|
||||
Version: 4.20.1_02
|
||||
Release: 0
|
||||
Summary: Xen Virtualization: Hypervisor (aka VMM aka Microkernel)
|
||||
License: GPL-2.0-only
|
||||
Group: System/Kernel
|
||||
Source0: xen-4.18.3-testing-src.tar.bz2
|
||||
Source0: xen-4.20.1-testing-src.tar.bz2
|
||||
Source1: stubdom.tar.bz2
|
||||
Source2: mini-os.tar.bz2
|
||||
Source9: xen.changes
|
||||
@@ -143,7 +99,6 @@ Source31: xenapiusers
|
||||
# Init script and sysconf file for pciback
|
||||
Source34: init.pciback
|
||||
Source35: sysconfig.pciback
|
||||
Source36: xen2libvirt.py
|
||||
# Systemd service files
|
||||
Source41: xencommons.service
|
||||
Source42: xen-dom0-modules.service
|
||||
@@ -154,39 +109,7 @@ Source10183: xen_maskcalc.py
|
||||
# For xen-libs
|
||||
Source99: baselibs.conf
|
||||
# Upstream patches
|
||||
Patch1: 6617d62c-x86-hvm-Misra-Rule-19-1-regression.patch
|
||||
# EMBARGOED security fixes
|
||||
# libxc
|
||||
Patch301: libxc-bitmap-long.patch
|
||||
Patch302: libxc-sr-xl-migration-debug.patch
|
||||
Patch303: libxc-sr-readv_exact.patch
|
||||
Patch304: libxc-sr-save-show_transfer_rate.patch
|
||||
Patch305: libxc-sr-save-mfns.patch
|
||||
Patch306: libxc-sr-save-types.patch
|
||||
Patch307: libxc-sr-save-errors.patch
|
||||
Patch308: libxc-sr-save-iov.patch
|
||||
Patch309: libxc-sr-save-rec_pfns.patch
|
||||
Patch310: libxc-sr-save-guest_data.patch
|
||||
Patch311: libxc-sr-save-local_pages.patch
|
||||
Patch312: libxc-sr-restore-pfns.patch
|
||||
Patch313: libxc-sr-restore-types.patch
|
||||
Patch314: libxc-sr-restore-mfns.patch
|
||||
Patch315: libxc-sr-restore-map_errs.patch
|
||||
Patch316: libxc-sr-restore-populate_pfns-pfns.patch
|
||||
Patch317: libxc-sr-restore-populate_pfns-mfns.patch
|
||||
Patch318: libxc-sr-restore-read_record.patch
|
||||
Patch319: libxc-sr-restore-handle_buffered_page_data.patch
|
||||
Patch320: libxc-sr-restore-handle_incoming_page_data.patch
|
||||
Patch321: libxc-sr-LIBXL_HAVE_DOMAIN_SUSPEND_PROPS.patch
|
||||
Patch322: libxc-sr-precopy_policy.patch
|
||||
Patch323: libxc-sr-max_iters.patch
|
||||
Patch324: libxc-sr-min_remaining.patch
|
||||
Patch325: libxc-sr-abort_if_busy.patch
|
||||
Patch326: libxc-sr-xg_sr_bitmap.patch
|
||||
Patch327: libxc-sr-xg_sr_bitmap-populated_pfns.patch
|
||||
Patch328: libxc-sr-restore-hvm-legacy-superpage.patch
|
||||
Patch329: libxc-sr-track-migration-time.patch
|
||||
Patch330: libxc-sr-number-of-iterations.patch
|
||||
# Our platform specific patches
|
||||
Patch400: xen-destdir.patch
|
||||
Patch401: vif-bridge-no-iptables.patch
|
||||
@@ -194,36 +117,28 @@ Patch402: vif-bridge-tap-fix.patch
|
||||
Patch403: xl-conf-default-bridge.patch
|
||||
Patch404: xl-conf-disable-autoballoon.patch
|
||||
Patch405: xen-arch-kconfig-nr_cpus.patch
|
||||
Patch406: suse-xendomains-service.patch
|
||||
Patch407: replace-obsolete-network-configuration-commands-in-s.patch
|
||||
Patch408: ignore-ip-command-script-errors.patch
|
||||
Patch406: replace-obsolete-network-configuration-commands-in-s.patch
|
||||
Patch407: ignore-ip-command-script-errors.patch
|
||||
# Needs to go upstream
|
||||
Patch420: suspend_evtchn_lock.patch
|
||||
Patch421: vif-route.patch
|
||||
Patch422: gcc14-fixes.patch
|
||||
# Other bug fixes or features
|
||||
Patch450: xen.sysconfig-fillup.patch
|
||||
Patch451: xenconsole-no-multiple-connections.patch
|
||||
Patch452: hibernate.patch
|
||||
Patch453: stdvga-cache.patch
|
||||
Patch454: xl-save-pc.patch
|
||||
Patch455: pygrub-boot-legacy-sles.patch
|
||||
Patch456: pygrub-handle-one-line-menu-entries.patch
|
||||
Patch453: xl-save-pc.patch
|
||||
Patch461: libxl.max_event_channels.patch
|
||||
Patch463: libxl.add-option-to-disable-disk-cache-flushes-in-qdisk.patch
|
||||
Patch464: xen.libxl.dmmd.patch
|
||||
Patch465: xenstore-run-in-studomain.patch
|
||||
Patch466: libxl.helper_done-crash.patch
|
||||
Patch467: libxl.LIBXL_HOTPLUG_TIMEOUT.patch
|
||||
# python3 conversion patches
|
||||
Patch500: build-python3-conversion.patch
|
||||
Patch501: migration-python3-conversion.patch
|
||||
Patch502: bin-python3-conversion.patch
|
||||
Patch466: xenstore-run-in-pvh-mode.patch
|
||||
Patch467: libxl.helper_done-crash.patch
|
||||
Patch468: libxl.LIBXL_HOTPLUG_TIMEOUT.patch
|
||||
# Hypervisor and PV driver Patches
|
||||
Patch600: xen.bug1026236.suse_vtsc_tolerance.patch
|
||||
Patch601: x86-ioapic-ack-default.patch
|
||||
Patch602: xenwatchdogd-restart.patch
|
||||
Patch621: xen.build-compare.doc_html.patch
|
||||
Patch622: disable-pv-support.patch
|
||||
# Build patches
|
||||
URL: http://www.cl.cam.ac.uk/Research/SRG/netos/xen/
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
@@ -238,6 +153,7 @@ This package contains the Xen Hypervisor. (tm)
|
||||
|
||||
[Hypervisor is a trademark of IBM]
|
||||
|
||||
|
||||
%package libs
|
||||
Summary: Xen Virtualization: Libraries
|
||||
License: GPL-2.0-only
|
||||
@@ -260,8 +176,6 @@ Authors:
|
||||
Ian Pratt <ian.pratt@cl.cam.ac.uk>
|
||||
|
||||
|
||||
%if %{?with_dom0_support}0
|
||||
|
||||
%package tools
|
||||
Summary: Xen Virtualization: Control tools for domain 0
|
||||
License: GPL-2.0-only
|
||||
@@ -269,28 +183,11 @@ Group: System/Kernel
|
||||
%if 0%{?suse_version} > 1500
|
||||
BuildRequires: pam-devel
|
||||
%endif
|
||||
%ifarch x86_64
|
||||
%if 0%{?suse_version} >= 1315
|
||||
Requires: grub2-x86_64-xen
|
||||
%endif
|
||||
Recommends: qemu-ovmf-x86_64
|
||||
Requires: qemu-x86
|
||||
%endif
|
||||
%ifarch %arm aarch64
|
||||
Requires: qemu-arm
|
||||
%endif
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: %{name}-libs = %{version}-%{release}
|
||||
Recommends: multipath-tools
|
||||
Requires: python3
|
||||
Requires: python3-curses
|
||||
%ifarch %{ix86} x86_64
|
||||
Requires: qemu-seabios
|
||||
%endif
|
||||
# subpackage existed in 10.3
|
||||
Provides: xen-tools-ioemu = %{version}
|
||||
Obsoletes: xen-tools-ioemu < %{version}
|
||||
Conflicts: libvirt < 1.0.5
|
||||
Requires: %{primary_python}
|
||||
Requires: %{primary_python}-curses
|
||||
|
||||
%description tools
|
||||
Xen is a virtual machine monitor for x86 that supports execution of
|
||||
@@ -309,7 +206,6 @@ Authors:
|
||||
Ian Pratt <ian.pratt@cl.cam.ac.uk>
|
||||
|
||||
|
||||
%ifarch x86_64
|
||||
%package tools-xendomains-wait-disk
|
||||
Summary: Adds a new xendomains-wait-disks.service
|
||||
License: GPL-3.0-or-later
|
||||
@@ -332,9 +228,7 @@ xendomains.service, but it adds itself as a Wanted service for xendomains.
|
||||
If xendomains-wait-disks.service fails, xendomains.service is launched anyway.
|
||||
|
||||
https://github.com/luizluca/xen-tools-xendomains-wait-disk
|
||||
%endif
|
||||
|
||||
%endif
|
||||
|
||||
%package tools-domU
|
||||
Summary: Xen Virtualization: Control tools for domain U
|
||||
@@ -352,11 +246,11 @@ This package contains tools that allow unprivileged domains to query
|
||||
the virtualized environment.
|
||||
|
||||
|
||||
|
||||
Authors:
|
||||
--------
|
||||
Ian Pratt <ian.pratt@cl.cam.ac.uk>
|
||||
|
||||
|
||||
%package devel
|
||||
Summary: Xen Virtualization: Headers and libraries for development
|
||||
License: GPL-2.0-only
|
||||
@@ -373,12 +267,10 @@ This package contains the libraries and header files needed to create
|
||||
tools to control virtual machines.
|
||||
|
||||
|
||||
|
||||
Authors:
|
||||
--------
|
||||
Ian Pratt <ian.pratt@cl.cam.ac.uk>
|
||||
|
||||
%if %{?with_dom0_support}0
|
||||
|
||||
%package doc-html
|
||||
Summary: Xen Virtualization: HTML documentation
|
||||
@@ -394,11 +286,10 @@ xen-doc-html contains the online documentation in HTML format. Point
|
||||
your browser at file:/usr/share/doc/packages/xen/html/
|
||||
|
||||
|
||||
|
||||
Authors:
|
||||
--------
|
||||
Ian Pratt <ian.pratt@cl.cam.ac.uk>
|
||||
%endif
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %xen_build_dir -a 1 -a 2
|
||||
@@ -435,12 +326,6 @@ cat > .our_xenversion <<_EOV_
|
||||
export WGET=$(type -P false)
|
||||
export FTP=$(type -P false)
|
||||
export GIT=$(type -P false)
|
||||
%ifarch aarch64
|
||||
# GCC10+ enables outline-atomics option by default and breaks the build, so disable it
|
||||
%if 0%{?suse_version} >= 1550
|
||||
export CFLAGS="%{optflags} -mno-outline-atomics"
|
||||
%endif
|
||||
%endif
|
||||
export EXTRA_CFLAGS_XEN_TOOLS="%{optflags}"
|
||||
export EXTRA_CFLAGS_QEMU_TRADITIONAL="%{optflags}"
|
||||
export SMBIOS_REL_DATE="$SMBIOS_REL_DATE"
|
||||
@@ -475,8 +360,8 @@ configure_flags="${configure_flags} --enable-stubdom"
|
||||
sed -i~ 's/ XENSTORETYPE=domain$/ XENSTORETYPE=daemon/' tools/hotplug/Linux/launch-xenstore.in
|
||||
configure_flags="${configure_flags} --disable-stubdom"
|
||||
%endif
|
||||
export PYTHON="/usr/bin/python3"
|
||||
configure_flags="${configure_flags} --disable-qemu-traditional"
|
||||
export PYTHON=$(realpath /usr/bin/python3)
|
||||
configure_flags="${configure_flags} --disable-qemu-traditional --disable-seabios --disable-pygrub"
|
||||
./configure \
|
||||
--disable-xen \
|
||||
--disable-pvshim \
|
||||
@@ -498,8 +383,6 @@ configure_flags="${configure_flags} --disable-qemu-traditional"
|
||||
--enable-systemd \
|
||||
--with-systemd=%{_unitdir} \
|
||||
--with-systemd-modules-load=%{with_systemd_modules_load} \
|
||||
--with-system-ovmf=%{_datadir}/qemu/ovmf-x86_64-xen-4m.bin \
|
||||
--with-system-seabios=%{_datadir}/qemu/bios-256k.bin \
|
||||
${configure_flags}
|
||||
make -C tools/include/xen-foreign %{?_smp_mflags}
|
||||
make %{?_smp_mflags}
|
||||
@@ -512,6 +395,7 @@ make \
|
||||
DESTDIR=%{buildroot} \
|
||||
SYSCONFIG_DIR=%{_fillupdir} \
|
||||
PKG_INSTALLDIR=%{_libdir}/pkgconfig \
|
||||
BASH_COMPLETION_DIR=%{_datadir}/bash-completion/completions \
|
||||
%{?_smp_mflags} \
|
||||
install
|
||||
find %{buildroot} -ls
|
||||
@@ -604,7 +488,6 @@ _EOR_
|
||||
tee ${udev_rulesdir}/80-%{name}-channel-setup.rules <<'_EOF_'
|
||||
SUBSYSTEM=="xen", DEVPATH=="/devices/console-[0-9]", IMPORT{program}=="xen-channel-setup.sh $attr{nodename} %%n"
|
||||
|
||||
SUBSYSTEM=="xen", DEVPATH=="/devices/console-[0-9]", ENV{XEN_CHANNEL_NAME}=="org.qemu.guest_agent.0", TAG+="systemd", ENV{SYSTEMD_WANTS}+="qemu-ga@hvc%%n.service"
|
||||
_EOF_
|
||||
#
|
||||
dracut_moduledir=%{buildroot}/usr/lib/dracut/modules.d/50%{name}-tools-domU
|
||||
@@ -672,10 +555,6 @@ channel_num="$2"
|
||||
name="`xenstore-read \"$channel_path\"/name`"
|
||||
test -z "$name" && exit 1
|
||||
|
||||
if test $name != "org.qemu.guest_agent.0"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p /dev/xenchannel
|
||||
devname=/dev/xenchannel/$name
|
||||
# Xen's console devices are used for channels. See xen-pv-channel(7)
|
||||
@@ -687,7 +566,6 @@ _EOF_
|
||||
chmod 755 ${udev_programdir}/*.sh
|
||||
|
||||
# EFI
|
||||
%if %{?with_dom0_support}0
|
||||
arch=`uname -m`
|
||||
install_xen()
|
||||
{
|
||||
@@ -725,12 +603,6 @@ install_xen()
|
||||
}
|
||||
export BRP_PESIGN_FILES="*.efi /lib/firmware"
|
||||
CC=gcc
|
||||
%if %{?with_gcc47}0
|
||||
CC=gcc-4.7
|
||||
%endif
|
||||
%if %{?with_gcc48}0
|
||||
CC=gcc-4.8
|
||||
%endif
|
||||
rm -fv xen/.config
|
||||
echo CONFIG_REQUIRE_NX=y > xen/.config
|
||||
echo CONFIG_DIT_DEFAULT=y >> xen/.config
|
||||
@@ -748,23 +620,6 @@ yes '' | make -C xen oldconfig
|
||||
make -C xen install XEN_BUILD_DATE="$XEN_BUILD_DATE" XEN_BUILD_TIME="$XEN_BUILD_TIME" DEBUG_DIR=/boot DESTDIR=%{buildroot} CC=$CC %{?_smp_mflags}
|
||||
install_xen
|
||||
make -C xen clean
|
||||
%endif
|
||||
|
||||
# On x86_64, qemu-xen was installed as /usr/lib/xen/bin/qemu-system-i386
|
||||
# and advertised as the <emulator> in libvirt capabilities. Tool such as
|
||||
# virt-install include <emulator> in domXML they produce, so we need to
|
||||
# preserve the path. For x86_64, create a simple wrapper that invokes
|
||||
# /usr/bin/qemu-system-i386
|
||||
# Using qemu-system-x86_64 will result in an incompatible VM
|
||||
%ifarch x86_64 aarch64
|
||||
hardcoded_path_in_existing_domU_xml='%{_libexecdir}/%{name}/bin'
|
||||
mkdir -vp %{buildroot}${hardcoded_path_in_existing_domU_xml}
|
||||
tee %{buildroot}${hardcoded_path_in_existing_domU_xml}/qemu-system-%{qemu_arch} << 'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
exec %{_bindir}/qemu-system-%{qemu_arch} "$@"
|
||||
EOF
|
||||
chmod 0755 %{buildroot}${hardcoded_path_in_existing_domU_xml}/qemu-system-%{qemu_arch}
|
||||
|
||||
#
|
||||
unit='%{_libexecdir}/%{name}/bin/xendomains-wait-disks'
|
||||
@@ -792,10 +647,8 @@ TimeoutSec=5min
|
||||
WantedBy=xendomains.service
|
||||
_EOS_
|
||||
#
|
||||
%endif
|
||||
|
||||
# Stubdom
|
||||
%if %{?with_dom0_support}0
|
||||
# Docs
|
||||
mkdir -p %{buildroot}/%{_defaultdocdir}/xen/misc
|
||||
for name in COPYING %SOURCE10 %SOURCE11 %SOURCE12; do
|
||||
@@ -807,15 +660,14 @@ for name in vtpm-platforms.txt crashdb.txt xenpaging.txt \
|
||||
done
|
||||
|
||||
# Xen utilities
|
||||
install -m755 %SOURCE36 %{buildroot}/usr/sbin/xen2libvirt
|
||||
install -m755 %SOURCE10183 %{buildroot}/usr/sbin/xen_maskcalc
|
||||
%python3_fix_shebang
|
||||
|
||||
rm -f %{buildroot}/etc/xen/README*
|
||||
# Example config
|
||||
mkdir -p %{buildroot}/etc/xen/{vm,examples,scripts}
|
||||
mv %{buildroot}/etc/xen/xlexample* %{buildroot}/etc/xen/examples
|
||||
rm -f %{buildroot}/etc/xen/examples/*nbd
|
||||
install -m644 tools/xentrace/formats %{buildroot}/etc/xen/examples/xentrace_formats.txt
|
||||
|
||||
# Scripts
|
||||
rm -f %{buildroot}/etc/xen/scripts/block-*nbd
|
||||
@@ -898,18 +750,18 @@ find %{buildroot} \( \
|
||||
-name qcow-create -o \
|
||||
-name img2qcow -o \
|
||||
-name qcow2raw -o \
|
||||
-name qemu-bridge-helper -o \
|
||||
-name qemu-img-xen -o \
|
||||
-name qemu-nbd-xen -o \
|
||||
-name palcode-clipper -o \
|
||||
-name "*.dtb" -o \
|
||||
-name "openbios-*" -o \
|
||||
-name "petalogix*" -o \
|
||||
-name "ppc*" -o \
|
||||
-name "*.pyc" -o \
|
||||
-name "s390*" -o \
|
||||
-name "slof*" -o \
|
||||
-name "spapr*" -o \
|
||||
-name "PKG-INFO" -o \
|
||||
-name "SOURCES.txt" -o \
|
||||
-name "dependency_links.txt" -o \
|
||||
-name "top_level.txt" -o \
|
||||
-name "*.egg-info" \) \
|
||||
-print -delete
|
||||
# Wipe empty directories
|
||||
@@ -925,34 +777,6 @@ find %{buildroot} -name xendriverdomain.service -print -delete
|
||||
%fdupes %{buildroot}/%{_prefix}
|
||||
find %{buildroot} -type f -size 0 -delete -print
|
||||
|
||||
%else
|
||||
# !with_dom0_support
|
||||
|
||||
# 32 bit hypervisor no longer supported. Remove dom0 tools.
|
||||
rm -rf %{buildroot}/%{_datadir}/doc
|
||||
rm -rf %{buildroot}/%{_datadir}/man
|
||||
rm -rf %{buildroot}/%{_libexecdir}/%{name}
|
||||
rm -rf %{buildroot}/%{_libdir}/python*
|
||||
rm -rf %{buildroot}/%{_unitdir}
|
||||
rm -rf %{buildroot}/%{_fillupdir}
|
||||
rm -rf %{buildroot}/%{with_systemd_modules_load}
|
||||
rm -rf %{buildroot}/usr/sbin
|
||||
rm -rf %{buildroot}/etc/xen
|
||||
rm -rf %{buildroot}/var
|
||||
rm -f %{buildroot}/%{_sysconfdir}/bash_completion.d/xl
|
||||
rm -f %{buildroot}/%{_sysconfdir}/init.d/xen*
|
||||
rm -f %{buildroot}/%{_bindir}/*trace*
|
||||
rm -f %{buildroot}/%{_bindir}/vchan-socket-proxy
|
||||
rm -f %{buildroot}/%{_bindir}/xenalyze*
|
||||
rm -f %{buildroot}/%{_bindir}/xenco*
|
||||
rm -f %{buildroot}/%{_bindir}/xen-cpuid
|
||||
rm -f %{buildroot}/%{_bindir}/pygrub
|
||||
rm -f %{buildroot}/%{_bindir}/remus
|
||||
rm -f %{buildroot}/usr/etc/qemu/target-x86_64.conf
|
||||
rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%endif
|
||||
|
||||
%if %{?with_dom0_support}0
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
@@ -960,26 +784,17 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%{_libdir}/efi
|
||||
%{_datadir}/efi
|
||||
|
||||
%endif
|
||||
|
||||
%files libs
|
||||
%defattr(-,root,root)
|
||||
%{_libdir}/xenfsimage/
|
||||
%{_libdir}/*.so.*
|
||||
|
||||
%if %{?with_dom0_support}0
|
||||
|
||||
%files tools
|
||||
%defattr(-,root,root)
|
||||
/usr/bin/xenalyze
|
||||
/usr/bin/xenstore*
|
||||
/usr/bin/pygrub
|
||||
/usr/bin/vchan-socket-proxy
|
||||
/usr/bin/xencov_split
|
||||
/usr/bin/xentrace_format
|
||||
%ifarch x86_64
|
||||
/usr/bin/xen-cpuid
|
||||
%endif
|
||||
/usr/sbin/xenbaked
|
||||
/usr/sbin/xenconsoled
|
||||
/usr/sbin/xencov
|
||||
@@ -1000,14 +815,10 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
/usr/sbin/flask-loadpolicy
|
||||
/usr/sbin/flask-set-bool
|
||||
/usr/sbin/flask-setenforce
|
||||
%if %{?with_gdbsx}0
|
||||
/usr/sbin/gdbsx
|
||||
%endif
|
||||
/usr/sbin/xl
|
||||
/usr/sbin/xen2libvirt
|
||||
/usr/sbin/xen-access
|
||||
/usr/sbin/xen_maskcalc
|
||||
%ifarch %ix86 x86_64
|
||||
/usr/sbin/xen-hptool
|
||||
/usr/sbin/xen-hvmcrash
|
||||
/usr/sbin/xen-hvmctx
|
||||
@@ -1017,7 +828,6 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
/usr/sbin/xen-ucode
|
||||
/usr/sbin/xen-mceinj
|
||||
/usr/sbin/xen-vmtrace
|
||||
%endif
|
||||
/usr/sbin/xenhypfs
|
||||
/usr/sbin/xen-livepatch
|
||||
/usr/sbin/xen-diag
|
||||
@@ -1042,10 +852,8 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%dir %{_libexecdir}/%{name}
|
||||
%{_libexecdir}/%{name}/bin
|
||||
%exclude %{_libexecdir}/%{name}-tools-domU
|
||||
%ifarch x86_64
|
||||
%{_libexecdir}/%{name}/boot
|
||||
%exclude %{_libexecdir}/%{name}/bin/xendomains-wait-disks
|
||||
%endif
|
||||
%{_fillupdir}/sysconfig.pciback
|
||||
%{_fillupdir}/sysconfig.xencommons
|
||||
%{_fillupdir}/sysconfig.xendomains
|
||||
@@ -1053,9 +861,7 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%dir %attr(700,root,root) /var/lib/xen/images
|
||||
%dir %attr(700,root,root) /var/lib/xen/save
|
||||
%dir %attr(700,root,root) /var/lib/xen/dump
|
||||
%ifarch %ix86 x86_64
|
||||
%dir %attr(700,root,root) /var/lib/xen/xenpaging
|
||||
%endif
|
||||
%dir /var/lib/xenstored
|
||||
%dir /var/log/xen
|
||||
%dir /var/log/xen/console
|
||||
@@ -1076,16 +882,13 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%exclude %{_unitdir}/%{name}-vcpu-watch.service
|
||||
%exclude %{_unitdir}/xendomains-wait-disks.service
|
||||
%config %{with_systemd_modules_load}
|
||||
/etc/bash_completion.d/xl
|
||||
%dir %{_libdir}/python%{pyver}/site-packages/grub
|
||||
%{_datadir}/bash-completion/completions/xl
|
||||
%dir %{_libdir}/python%{pyver}/site-packages/xen
|
||||
%dir %{_libdir}/python%{pyver}/site-packages/xen/lowlevel
|
||||
%dir %{_libdir}/python%{pyver}/site-packages/xen/migration
|
||||
%{_libdir}/python%{pyver}/site-packages/grub/*
|
||||
%{_libdir}/python%{pyver}/site-packages/xen/util.py
|
||||
%{_libdir}/python%{pyver}/site-packages/xen/lowlevel/*
|
||||
%{_libdir}/python%{pyver}/site-packages/xen/migration/*
|
||||
%{_libdir}/python%{pyver}/site-packages/*.so
|
||||
%dir %{_defaultdocdir}/xen
|
||||
%{_defaultdocdir}/xen/COPYING
|
||||
%{_defaultdocdir}/xen/README.SUSE
|
||||
@@ -1093,29 +896,21 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%{_defaultdocdir}/xen/boot.xen
|
||||
%{_mandir}/man*/*
|
||||
|
||||
%ifarch x86_64
|
||||
%files tools-xendomains-wait-disk
|
||||
%license xendomains-wait-disk/LICENSE
|
||||
%doc xendomains-wait-disk/README.md
|
||||
%config %{_unitdir}/xendomains-wait-disks.service
|
||||
%config %attr(0755,root,root) %{_libexecdir}/%{name}/bin/xendomains-wait-disks
|
||||
%endif
|
||||
# with_dom0_support
|
||||
%endif
|
||||
|
||||
%posttrans -n %{name}-tools-domU
|
||||
%{?regenerate_initrd_posttrans}
|
||||
|
||||
%files tools-domU
|
||||
%defattr(-,root,root)
|
||||
%ifarch %ix86 x86_64
|
||||
/usr/bin/xen-detect
|
||||
%exclude /usr/bin/xenstore-control
|
||||
%endif
|
||||
/usr/bin/xenstore*
|
||||
%if %{?with_dom0_support}0
|
||||
%config %{_unitdir}/%{name}-vcpu-watch.service
|
||||
%endif
|
||||
%{_libexecdir}/%{name}-tools-domU
|
||||
/usr/lib/udev
|
||||
/usr/lib/dracut
|
||||
@@ -1141,8 +936,6 @@ rm -f %{buildroot}/usr/libexec/qemu-bridge-helper
|
||||
%{_libdir}/pkgconfig/xentoollog.pc
|
||||
%{_libdir}/pkgconfig/xenvchan.pc
|
||||
|
||||
%if %{?with_dom0_support}0
|
||||
|
||||
%files doc-html
|
||||
%defattr(-,root,root)
|
||||
%dir %{_defaultdocdir}/xen
|
||||
@@ -1162,7 +955,6 @@ fi
|
||||
%service_add_pre xen-dom0-modules.service
|
||||
%service_add_pre xenconsoled.service
|
||||
%service_add_pre xen-init-dom0.service
|
||||
%service_add_pre xen-qemu-dom0-disk-backend.service
|
||||
%if 0%{?suse_version} > 1500
|
||||
# Prepare for migration to /usr/etc; save any old .rpmsave
|
||||
for i in logrotate.d/xen pam.d/xen-api ; do
|
||||
@@ -1188,16 +980,12 @@ done
|
||||
%service_add_post xen-dom0-modules.service
|
||||
%service_add_post xenconsoled.service
|
||||
%service_add_post xen-init-dom0.service
|
||||
%service_add_post xen-qemu-dom0-disk-backend.service
|
||||
|
||||
if [ -f /etc/default/grub ] && ! (/usr/bin/grep GRUB_CMDLINE_XEN /etc/default/grub >/dev/null); then
|
||||
echo '# Xen boot parameters for all Xen boots' >> /etc/default/grub
|
||||
echo 'GRUB_CMDLINE_XEN=""' >> /etc/default/grub
|
||||
echo '# Xen boot parameters for non-recovery Xen boots (in addition to GRUB_CMDLINE_XEN)' >> /etc/default/grub
|
||||
echo 'GRUB_CMDLINE_XEN_DEFAULT=""' >> /etc/default/grub
|
||||
fi
|
||||
if [ -f %{_datadir}/grub2/i386-xen/grub.xen ] && [ ! -f %{_libexecdir}/%{name}/boot/pvgrub32.bin ]; then
|
||||
ln -sv %{_datadir}/grub2/i386-xen/grub.xen %{_libexecdir}/%{name}/boot/pvgrub32.bin
|
||||
echo 'GRUB_CMDLINE_XEN_DEFAULT="dom0=pvh"' >> /etc/default/grub
|
||||
fi
|
||||
if [ -f %{_datadir}/grub2/x86_64-xen/grub.xen ] && [ ! -f %{_libexecdir}/%{name}/boot/pvgrub64.bin ]; then
|
||||
ln -sv %{_datadir}/grub2/x86_64-xen/grub.xen %{_libexecdir}/%{name}/boot/pvgrub64.bin
|
||||
@@ -1211,7 +999,6 @@ fi
|
||||
%service_del_preun xen-dom0-modules.service
|
||||
%service_del_preun xenconsoled.service
|
||||
%service_del_preun xen-init-dom0.service
|
||||
%service_del_preun xen-qemu-dom0-disk-backend.service
|
||||
|
||||
%postun tools
|
||||
%if %{defined service_del_postun_without_restart}
|
||||
@@ -1222,7 +1009,6 @@ fi
|
||||
%service_del_postun_without_restart xen-dom0-modules.service
|
||||
%service_del_postun_without_restart xenconsoled.service
|
||||
%service_del_postun_without_restart xen-init-dom0.service
|
||||
%service_del_postun_without_restart xen-qemu-dom0-disk-backend.service
|
||||
%else
|
||||
export DISABLE_RESTART_ON_UPDATE=yes
|
||||
%service_del_postun xencommons.service
|
||||
@@ -1232,9 +1018,6 @@ export DISABLE_RESTART_ON_UPDATE=yes
|
||||
%service_del_postun xen-dom0-modules.service
|
||||
%service_del_postun xenconsoled.service
|
||||
%service_del_postun xen-init-dom0.service
|
||||
%service_del_postun xen-qemu-dom0-disk-backend.service
|
||||
%endif
|
||||
|
||||
%endif
|
||||
|
||||
%post libs -p /sbin/ldconfig
|
||||
|
@@ -18,10 +18,10 @@ Basically fillup removed all comments, and also the two added key=value lines.
|
||||
|
||||
Prevent this by defining all keys, with empty values, so that consumers
|
||||
of the values will continue to use the built-in defaults.
|
||||
Index: xen-4.16.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
Index: xen-4.19.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
===================================================================
|
||||
--- xen-4.16.0-testing.orig/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
+++ xen-4.16.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
--- xen-4.19.0-testing.orig/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
+++ xen-4.19.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
@@ -3,7 +3,9 @@
|
||||
## Default: "none"
|
||||
#
|
||||
@@ -55,20 +55,19 @@ Index: xen-4.16.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
|
||||
## Type: string
|
||||
## Default: unlimited
|
||||
@@ -57,9 +59,10 @@ XENSTORED_ARGS=
|
||||
@@ -57,8 +59,9 @@ XENSTORED_ARGS=
|
||||
## Type: string
|
||||
## Default: Not defined, tracing off
|
||||
#
|
||||
-# Log xenstored messages
|
||||
+# Log xenstored messages if a non-empty value is assigned.
|
||||
# Only evaluated if XENSTORETYPE is "daemon".
|
||||
-#XENSTORED_TRACE=[yes|on|1]
|
||||
+# Log xenstored messages if a non-empty value is assigned.
|
||||
+#
|
||||
+XENSTORED_TRACE=
|
||||
|
||||
## Type: integer
|
||||
## Default: 50
|
||||
@@ -75,14 +78,14 @@ XENSTORED_ARGS=
|
||||
@@ -74,14 +77,14 @@ XENSTORED_ARGS=
|
||||
#
|
||||
# xenstore domain kernel.
|
||||
# Only evaluated if XENSTORETYPE is "domain".
|
||||
@@ -85,7 +84,7 @@ Index: xen-4.16.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
|
||||
## Type: string
|
||||
## Default: not set, no autoballooning of xenstore domain
|
||||
@@ -93,7 +96,7 @@ XENSTORED_ARGS=
|
||||
@@ -92,7 +95,7 @@ XENSTORED_ARGS=
|
||||
# - combination of both in form of <val>:<frac> (e.g. 8:1/100), resulting
|
||||
# value will be the higher of both specifications
|
||||
# Only evaluated if XENSTORETYPE is "domain".
|
||||
@@ -94,7 +93,7 @@ Index: xen-4.16.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
|
||||
## Type: string
|
||||
## Default: ""
|
||||
@@ -106,4 +109,4 @@ XENSTORE_DOMAIN_ARGS=
|
||||
@@ -105,4 +108,4 @@ XENSTORE_DOMAIN_ARGS=
|
||||
#QEMU_XEN=@qemu_xen_path@
|
||||
|
||||
# Dom0 UUID
|
||||
|
137
xen2libvirt.py
137
xen2libvirt.py
@@ -1,137 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Authors:
|
||||
# Jim Fehlig <jfehlig@suse.com>
|
||||
#
|
||||
# Read native Xen configuration format, convert to libvirt domXML, and
|
||||
# import (virsh define <xml>) into libvirt.
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import re
|
||||
from xml.etree import ElementTree
|
||||
|
||||
try:
|
||||
import libvirt
|
||||
except ImportError:
|
||||
print('Unable to import the libvirt module. Is libvirt-python installed?')
|
||||
sys.exit(1)
|
||||
|
||||
parser = argparse.ArgumentParser(description='Import Xen domain configuration into libvirt')
|
||||
parser.add_argument('-c', '--convert-only', help='Convert Xen domain configuration into libvirt domXML, but do not import into libvirt', action='store_true', dest='convert_only')
|
||||
parser.add_argument('-r', '--recursive', help='Operate recursivelly on all Xen domain configuration rooted at path', action='store_true')
|
||||
parser.add_argument('-f', '--format', help='Format of Xen domain configuration. Supported formats are xm and sexpr', choices=['xm', 'sexpr'], default=None)
|
||||
parser.add_argument('-v', '--verbose', help='Print information about the import process', action='store_true')
|
||||
parser.add_argument('path', help='Path to Xen domain configuration')
|
||||
|
||||
|
||||
def print_verbose(msg):
|
||||
if args.verbose:
|
||||
print(msg)
|
||||
|
||||
|
||||
def check_config(path, config):
|
||||
isbinary = os.system('file -b ' + path + ' | grep text > /dev/null')
|
||||
|
||||
if isbinary:
|
||||
print('Skipping %s (not a valid Xen configuration file)' % path)
|
||||
return 'unknown'
|
||||
|
||||
for line in config.splitlines():
|
||||
if len(line) == 0 or line.startswith('#'):
|
||||
continue
|
||||
if line.startswith('<domain'):
|
||||
# XML is not a supported conversion format
|
||||
break
|
||||
if line.startswith('(domain'):
|
||||
print('Found sexpr formatted file %s' % path)
|
||||
return 'sexpr'
|
||||
if '=' in line:
|
||||
print('Found xm formatted file %s' % path)
|
||||
return 'xm'
|
||||
break
|
||||
|
||||
print('Skipping %s (not a valid Xen configuration file)' % path)
|
||||
return 'unknown'
|
||||
|
||||
|
||||
def import_domain(conn, path, format=None, convert_only=False):
|
||||
|
||||
f = open(path, 'r')
|
||||
config = f.read()
|
||||
print_verbose('Xen domain configuration read from %s:\n %s' % (path, config))
|
||||
if format is None:
|
||||
format = check_config(path, config)
|
||||
|
||||
if format == 'sexpr':
|
||||
print_verbose('scrubbing domid from configuration')
|
||||
config = re.sub("\(domid [0-9]*\)", "", config)
|
||||
print_verbose('scrubbed sexpr:\n %s' % config)
|
||||
xml = conn.domainXMLFromNative('xen-sxpr', config, 0)
|
||||
elif format == 'xm':
|
||||
xml = conn.domainXMLFromNative('xen-xm', config, 0)
|
||||
else:
|
||||
# Return to continue on to next file (if recursive)
|
||||
return
|
||||
|
||||
f.close()
|
||||
|
||||
# domUloader is no longer available in SLES12, replace with pygrub
|
||||
tree = ElementTree.fromstring(xml)
|
||||
bl = tree.find('.//bootloader')
|
||||
if bl is not None and bl.text is not None and 'domUloader' in bl.text:
|
||||
bl.text = 'pygrub'
|
||||
xml = ElementTree.tostring(tree)
|
||||
|
||||
print_verbose('Successfully converted Xen domain configuration to '
|
||||
'libvirt domXML:\n %s' % xml)
|
||||
if convert_only:
|
||||
print(xml)
|
||||
else:
|
||||
print_verbose('Importing converted libvirt domXML into libvirt...')
|
||||
dom = conn.defineXML(xml.decode("utf-8"))
|
||||
if dom is None:
|
||||
print('Failed to define domain from converted domXML')
|
||||
sys.exit(1)
|
||||
print_verbose('domXML successfully imported into libvirt')
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
path = args.path
|
||||
|
||||
# Connect to libvirt
|
||||
conn = libvirt.open(None)
|
||||
if conn is None:
|
||||
print('Failed to open connection to the hypervisor')
|
||||
sys.exit(1)
|
||||
|
||||
if args.recursive:
|
||||
try:
|
||||
for root, dirs, files in os.walk(path):
|
||||
for name in files:
|
||||
abs_name = os.path.join(root, name)
|
||||
print_verbose('Processing file %s' % abs_name)
|
||||
import_domain(conn, abs_name, args.format, args.convert_only)
|
||||
except IOError:
|
||||
print('Failed to open/read path %s' % path)
|
||||
sys.exit(1)
|
||||
else:
|
||||
import_domain(conn, args.path, args.format, args.convert_only)
|
26
xenstore-run-in-pvh-mode.patch
Normal file
26
xenstore-run-in-pvh-mode.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
Index: xen-4.20.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
===================================================================
|
||||
--- xen-4.20.0-testing.orig/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
+++ xen-4.20.0-testing/tools/hotplug/Linux/init.d/sysconfig.xencommons.in
|
||||
@@ -73,7 +73,7 @@ XENSTORED_TRACE=
|
||||
#XENSTORED_OOM_MEM_THRESHOLD=50
|
||||
|
||||
## Type: string
|
||||
-## Default: @LIBEXEC@/boot/xenstore-stubdom.gz
|
||||
+## Default: @LIBEXEC@/boot/xenstorepvh-stubdom.gz
|
||||
#
|
||||
# xenstore domain kernel.
|
||||
# Only evaluated if XENSTORETYPE is "domain".
|
||||
Index: xen-4.20.0-testing/tools/hotplug/Linux/launch-xenstore.in
|
||||
===================================================================
|
||||
--- xen-4.20.0-testing.orig/tools/hotplug/Linux/launch-xenstore.in
|
||||
+++ xen-4.20.0-testing/tools/hotplug/Linux/launch-xenstore.in
|
||||
@@ -93,7 +93,7 @@ test -f @CONFIG_DIR@/@CONFIG_LEAF_DIR@/x
|
||||
}
|
||||
|
||||
[ "$XENSTORETYPE" = "domain" ] && {
|
||||
- [ -z "$XENSTORE_DOMAIN_KERNEL" ] && XENSTORE_DOMAIN_KERNEL=@LIBEXEC@/boot/xenstore-stubdom.gz
|
||||
+ [ -z "$XENSTORE_DOMAIN_KERNEL" ] && XENSTORE_DOMAIN_KERNEL=@LIBEXEC@/boot/xenstorepvh-stubdom.gz
|
||||
XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS --kernel $XENSTORE_DOMAIN_KERNEL"
|
||||
[ -z "$XENSTORE_DOMAIN_SIZE" ] && XENSTORE_DOMAIN_SIZE=32
|
||||
XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS --memory $XENSTORE_DOMAIN_SIZE"
|
@@ -9,9 +9,9 @@ References: fate#323663 - Run Xenstore in stubdomain
|
||||
-## Default: daemon
|
||||
+## Default: domain
|
||||
#
|
||||
# Select type of xentore service.
|
||||
# Select type of xenstore service.
|
||||
#
|
||||
@@ -81,14 +81,14 @@ XENSTORED_TRACE=
|
||||
@@ -80,14 +80,14 @@ XENSTORED_TRACE=
|
||||
XENSTORE_DOMAIN_KERNEL=
|
||||
|
||||
## Type: integer
|
||||
@@ -49,6 +49,6 @@ References: fate#323663 - Run Xenstore in stubdomain
|
||||
- [ -z "$XENSTORE_MAX_DOMAIN_SIZE" ] || XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS --maxmem $XENSTORE_MAX_DOMAIN_SIZE"
|
||||
+ [ -z "$XENSTORE_MAX_DOMAIN_SIZE" ] && XENSTORE_MAX_DOMAIN_SIZE="1/100"
|
||||
+ XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS --maxmem $XENSTORE_MAX_DOMAIN_SIZE"
|
||||
[ -z "$XENSTORED_TRACE" ] || XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS -T xenstored-trace.log"
|
||||
|
||||
echo -n Starting $XENSTORE_DOMAIN_KERNEL...
|
||||
${LIBEXEC_BIN}/init-xenstore-domain $XENSTORE_DOMAIN_ARGS || exit 1
|
||||
|
@@ -1,93 +1,104 @@
|
||||
References: bsc#1178736
|
||||
|
||||
Allow restart of xenwatchdogd in case it terminated unexpectetly.
|
||||
Index: xen-4.14.0-testing/tools/misc/xenwatchdogd.c
|
||||
Index: xen-4.19.0-testing/tools/misc/xenwatchdogd.c
|
||||
===================================================================
|
||||
--- xen-4.14.0-testing.orig/tools/misc/xenwatchdogd.c
|
||||
+++ xen-4.14.0-testing/tools/misc/xenwatchdogd.c
|
||||
@@ -9,12 +9,16 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
--- xen-4.19.0-testing.orig/tools/misc/xenwatchdogd.c
|
||||
+++ xen-4.19.0-testing/tools/misc/xenwatchdogd.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <getopt.h>
|
||||
+#include <libgen.h>
|
||||
+#include <syslog.h>
|
||||
|
||||
xc_interface *h;
|
||||
int id = 0;
|
||||
#define WDOG_MIN_TIMEOUT 2
|
||||
#define WDOG_MIN_SLEEP 1
|
||||
@@ -29,9 +31,11 @@
|
||||
static xc_interface *h;
|
||||
static volatile bool safeexit = false;
|
||||
static volatile bool done = false;
|
||||
+static const char id_file[] = "/run/xenwatchdog_id.txt";
|
||||
|
||||
-void daemonize(void)
|
||||
-static void daemonize(void)
|
||||
+static void daemonize(const char *str)
|
||||
{
|
||||
+ const char *err_str = "";
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
err(1, "fork");
|
||||
@@ -23,7 +27,9 @@ void daemonize(void)
|
||||
err(EXIT_FAILURE, "fork");
|
||||
@@ -40,7 +44,9 @@ static void daemonize(void)
|
||||
default:
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
- umask(0);
|
||||
+#define err(x,s) do { err_str = (s); goto out; } while (0)
|
||||
+ openlog(str, LOG_CONS, LOG_DAEMON);
|
||||
+ umask(~(S_IRUSR|S_IWUSR));
|
||||
if (setsid() < 0)
|
||||
err(1, "setsid");
|
||||
err(EXIT_FAILURE, "setsid");
|
||||
if (chdir("/") < 0)
|
||||
@@ -34,6 +40,10 @@ void daemonize(void)
|
||||
err(1, "reopen stdout");
|
||||
@@ -51,6 +57,10 @@ static void daemonize(void)
|
||||
err(EXIT_FAILURE, "reopen stdout");
|
||||
if(freopen("/dev/null", "w", stderr) == NULL)
|
||||
err(1, "reopen stderr");
|
||||
err(EXIT_FAILURE, "reopen stderr");
|
||||
+ return;
|
||||
+out:
|
||||
+ syslog(LOG_ERR, "%s: %m", err_str);
|
||||
+ exit(1);
|
||||
}
|
||||
|
||||
void catch_exit(int sig)
|
||||
@@ -47,18 +57,21 @@ void catch_usr1(int sig)
|
||||
static void catch_exit(int sig)
|
||||
@@ -62,6 +72,7 @@ static void catch_usr1(int sig)
|
||||
{
|
||||
if (id)
|
||||
xc_watchdog(h, id, 0);
|
||||
safeexit = true;
|
||||
done = true;
|
||||
+ unlink(id_file);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn)) usage(int exit_code)
|
||||
@@ -98,10 +109,12 @@ static int parse_secs(const char *arg, c
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
+ FILE *f;
|
||||
int id;
|
||||
int t, s;
|
||||
int ret;
|
||||
bool daemon = true;
|
||||
+ const char *err_str = "";
|
||||
|
||||
if (argc < 2)
|
||||
errx(1, "usage: %s <timeout> <sleep>", argv[0]);
|
||||
for ( ;; )
|
||||
{
|
||||
@@ -160,7 +173,7 @@ int main(int argc, char **argv)
|
||||
s = t / 2;
|
||||
|
||||
if (daemon)
|
||||
- daemonize();
|
||||
+ daemonize(basename(argv[0]));
|
||||
|
||||
h = xc_interface_open(NULL, NULL, 0);
|
||||
if (h == NULL)
|
||||
@@ -86,9 +99,25 @@ int main(int argc, char **argv)
|
||||
@@ -177,9 +190,25 @@ int main(int argc, char **argv)
|
||||
if (signal(SIGUSR1, &catch_usr1) == SIG_ERR)
|
||||
err(1, "signal");
|
||||
err(EXIT_FAILURE, "signal");
|
||||
|
||||
- id = xc_watchdog(h, 0, t);
|
||||
- if (id <= 0)
|
||||
- err(1, "xc_watchdog setup");
|
||||
- err(EXIT_FAILURE, "xc_watchdog setup");
|
||||
+ f = fopen(id_file, "r");
|
||||
+ if (f) {
|
||||
+ if (fscanf(f, "%d", &id) != 1)
|
||||
+ id = -1;
|
||||
+ if (id <= 0)
|
||||
+ err(1, "xc_watchdog setup");
|
||||
+ err(EXIT_FAILURE, "xc_watchdog setup");
|
||||
+ syslog(LOG_INFO, "reusing id %d", id);
|
||||
+ fclose(f);
|
||||
+ } else {
|
||||
+ id = xc_watchdog(h, 0, t);
|
||||
+ syslog(LOG_INFO, "obtained id %d", id);
|
||||
+ if (id <= 0)
|
||||
+ err(1, "xc_watchdog setup");
|
||||
+ err(EXIT_FAILURE, "xc_watchdog setup");
|
||||
+ f = fopen(id_file, "w");
|
||||
+ if (f) {
|
||||
+ fprintf(f, "%d\n", id);
|
||||
@@ -95,14 +106,14 @@ Index: xen-4.14.0-testing/tools/misc/xenwatchdogd.c
|
||||
+ }
|
||||
+ }
|
||||
|
||||
for (;;) {
|
||||
while (!done) {
|
||||
sleep(s);
|
||||
@@ -96,4 +125,8 @@ int main(int argc, char **argv)
|
||||
if (ret != 0)
|
||||
err(1, "xc_watchdog");
|
||||
}
|
||||
@@ -191,4 +220,8 @@ int main(int argc, char **argv)
|
||||
// Zero seconds timeout will disarm the watchdog timer
|
||||
xc_watchdog(h, id, safeexit ? 0 : WDOG_EXIT_TIMEOUT);
|
||||
return 0;
|
||||
+
|
||||
+out:
|
||||
+ syslog(LOG_ERR, "%s: %m", err_str);
|
||||
+ exit(1);
|
||||
+ exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@@ -40,8 +40,8 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
install: all
|
||||
--- a/tools/xl/xl.h
|
||||
+++ b/tools/xl/xl.h
|
||||
@@ -303,6 +303,7 @@ typedef enum {
|
||||
DOMAIN_RESTART_SOFT_RESET, /* Soft reset should be performed */
|
||||
@@ -306,6 +306,7 @@ typedef enum {
|
||||
DOMAIN_RESTART_SUSPENDED, /* Domain suspended - keep looping */
|
||||
} domain_restart_type;
|
||||
|
||||
+#define XL_SAVE_PAUSE_CHECKPOINT "suse-xl-save-pc"
|
||||
@@ -67,7 +67,7 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
int fd;
|
||||
uint8_t *config_data;
|
||||
int config_len;
|
||||
@@ -144,12 +147,24 @@ static int save_domain(uint32_t domid, i
|
||||
@@ -143,12 +146,24 @@ static int save_domain(uint32_t domid, i
|
||||
fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
|
||||
save_domain_core_writeconfig(fd, filename, config_data, config_len);
|
||||
|
||||
int rc = libxl_domain_suspend_suse(ctx, domid, fd, &props, NULL);
|
||||
int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
|
||||
close(fd);
|
||||
|
||||
+ if (xsh) {
|
||||
@@ -102,7 +102,7 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
#include <libxl.h>
|
||||
#include <libxl_utils.h>
|
||||
#include <libxlutil.h>
|
||||
@@ -668,6 +669,10 @@ int create_domain(struct domain_create *
|
||||
@@ -706,6 +707,10 @@ int create_domain(struct domain_create *
|
||||
int migrate_fd = dom_info->migrate_fd;
|
||||
bool config_in_json;
|
||||
|
||||
@@ -113,7 +113,7 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
int i;
|
||||
int need_daemon = daemonize;
|
||||
int ret, rc;
|
||||
@@ -1034,6 +1039,24 @@ start:
|
||||
@@ -1073,6 +1078,24 @@ start:
|
||||
ret = domain_wait_event(domid, &event);
|
||||
if (ret) goto out;
|
||||
|
||||
@@ -138,7 +138,7 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
switch (event->type) {
|
||||
|
||||
case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
|
||||
@@ -1095,14 +1118,39 @@ start:
|
||||
@@ -1134,10 +1157,34 @@ start:
|
||||
goto start;
|
||||
|
||||
case DOMAIN_RESTART_NONE:
|
||||
@@ -171,10 +171,5 @@ Keep going if the event type and shutdown reason remains the same.
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
+ break;
|
||||
|
||||
case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
|
||||
LOG("Domain %u has been destroyed.", domid);
|
||||
case DOMAIN_RESTART_SUSPENDED:
|
||||
LOG("Continue waiting for domain %u", domid);
|
||||
|
Reference in New Issue
Block a user