Commit Graph
33 Commits
Author SHA1 Message Date
Tamas K Lengyel 01a8a51412 x86/mem_sharing: don't lock parent during fork reset
During fork reset operation the parent domain doesn't need to be gathered using
rcu_lock_live_remote_domain_by_id, the fork already has the parent pointer.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2021-09-22 16:17:54 +02:00
Tamas K Lengyel f10c415371 x86/mem_sharing: copy parent VM's hostp2m's max_mapped_pfn during forking
When creating a VM fork copy the parent VM's hostp2m max_mapped_pfn value. Some
toolstack relies on the XENMEM_maximum_gpfn value to establish the maximum
addressable physical memory in the VM and for forks that have not yet been
unpaused that value is not going to reflect the correct max gpfn that's
possible to populate into the p2m. This patch fixes the issue.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Ian Jackson <iwj@xenproject.org>
2021-03-26 16:17:07 +01:00
Tamas K Lengyel ca82d3fecc x86/vm_event: add response flag to reset vmtrace buffer
Allow resetting the vmtrace buffer in response to a vm_event. This can be used
to optimize a use-case where detecting a looped vmtrace buffer is important.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Ian Jackson <iwj@xenproject.org>
2021-02-05 17:37:28 +00:00
Tamas K Lengyel c5866ab931 x86/vm_event: Carry the vmtrace buffer position in vm_event
Add vmtrace_pos field to x86 regs in vm_event. Initialized to ~0 if
vmtrace is not in use.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Release-Acked-by: Ian Jackson <iwj@xenproject.org>
2021-02-05 17:37:28 +00:00
Tamas K Lengyel 9744611991 xen/vmtrace: support for VM forks
Implement vmtrace_reset_pt function. Properly set IPT
state for VM forks.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Release-Acked-by: Ian Jackson <iwj@xenproject.org>
2021-02-05 17:37:28 +00:00
Tamas K Lengyel bc70924c79 x86/mem_sharing: fix wrong field name used in 2c5119d
The arch_domain struct has "msr", not "msrs".

Spotted by a TravisCI Randconfig build.

Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
2021-01-13 19:30:50 +00:00
Tamas K Lengyel 3e6c560ea1 x86/mem_sharing: resolve mm-lock order violations when forking VMs with nested p2m
Several lock-order violations have been encountered while attempting to fork
VMs with nestedhvm=1 set. This patch resolves the issues.

The order violations stems from a call to p2m_flush_nestedp2m being performed
whenever the hostp2m changes. This functions always takes the p2m lock for the
nested_p2m. However, with sharing the p2m locks always have to be taken before
the sharing lock. To resolve this issue we avoid taking the sharing lock where
possible (and was actually unecessary to begin with). But we also make
p2m_flush_nestedp2m aware that the p2m lock may have already been taken and
preemptively take all nested_p2m locks before unsharing a page where taking the
sharing lock is necessary.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2021-01-08 11:51:36 +01:00
Tamas K Lengyel 2c5119d637 x86/mem_sharing: Copy CPUID and MSR configuration during vm forking
Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
2021-01-05 23:00:27 +00:00
Tamas K Lengyel b67e859d08 x86/vmx: use P2M_ALLOC in vmx_load_pdptrs instead of P2M_UNSHARE
While forking VMs running a small RTOS system (Zephyr) a Xen crash has been
observed due to a mm-lock order violation while copying the HVM CPU context
from the parent. This issue has been identified to be due to
hap_update_paging_modes first getting a lock on the gfn using get_gfn. This
call also creates a shared entry in the fork's memory map for the cr3 gfn. The
function later calls hap_update_cr3 while holding the paging_lock, which
results in the lock-order violation in vmx_load_pdptrs when it tries to unshare
the above entry when it grabs the page with the P2M_UNSHARE flag set.

Since vmx_load_pdptrs only reads from the page its usage of P2M_UNSHARE was
unnecessary to start with. Using P2M_ALLOC is the appropriate flag to ensure
the p2m is properly populated.

Note that the lock order violation is avoided because before the paging_lock is
taken a lookup is performed with P2M_ALLOC that forks the page, thus the second
lookup in vmx_load_pdptrs succeeds without having to perform the fork. We keep
P2M_ALLOC in vmx_load_pdptrs because there are code-paths leading up to it
which don't take the paging_lock and that have no previous lookup. Currently no
other code-path exists leading there with the paging_lock taken, thus no
further adjustments are necessary.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Release-acked-by: Paul Durrant <paul@xen.org>
2020-06-19 15:24:55 +02:00
Tamas K Lengyel 05f488e418 libxc: xc_memshr_fork with interrupts blocked
Toolstack side for creating forks with interrupt injection blocked.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Wei Liu <wl@xen.org>
Release-acked-by: Paul Durrant <paul@xen.org>
2020-06-16 10:30:48 +02:00
Tamas K Lengyel 3371ced37c x86/mem_sharing: block interrupt injection for forks
When running VM forks without device models (QEMU), it may
be undesirable for Xen to inject interrupts. When creating such forks from
Windows VMs we have observed the kernel trying to process interrupts
immediately after the fork is executed. However without QEMU running such
interrupt handling may not be possible because it may attempt to interact with
devices that are not emulated by a backend. In the best case scenario such
interrupt handling would only present a detour in the VM forks' execution
flow, but in the worst case as we actually observed can completely stall it.
By disabling interrupt injection a fuzzer can exercise the target code without
interference. For other use-cases this option probably doesn't make sense,
that's why this is not enabled by default.

Forks & memory sharing are only available on Intel CPUs so this only applies
to vmx. Note that this is part of the experimental VM forking feature that's
completely disabled by default and can only be enabled by using
XEN_CONFIG_EXPERT during compile time.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Wei Liu <wl@xen.org>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Release-acked-by: Paul Durrant <paul@xen.org>
2020-06-16 10:29:16 +02:00
Tamas K Lengyel caf745fdf8 tools/libxc: add VM forking functions
Add functions to issue VM forking hypercalls

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Wei Liu <wl@xen.org>
2020-05-06 17:42:03 +01:00
Tamas K Lengyel 1a0000ac77 mem_sharing: map shared_info page to same gfn during fork
During a VM fork we copy the shared_info page; however, we also need to ensure
that the page is mapped into the same GFN in the fork as its in the parent.

Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
2020-04-30 10:43:52 +02:00
Tamas K Lengyel f5500c3196 mem_sharing: fix sharability check during fork reset
When resetting a VM fork we ought to only remove pages that were allocated for
the fork during it's execution and the contents copied over from the parent.
This can be determined if the page is sharable as special pages used by the
fork for other purposes will not pass this test. Unfortunately during the fork
reset loop we only partially check whether that's the case. A page's type may
indicate it is sharable (pass p2m_is_sharable) but that's not a sufficient
check by itself. All checks that are normally performed before a page is
converted to the sharable type need to be performed to avoid removing pages
from the p2m that may be used for other purposes. For example, currently the
reset loop also removes the vcpu info pages from the p2m, potentially putting
the guest into infinite page-fault loops.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
2020-04-24 15:05:33 +02:00
Tamas K Lengyel bb215898d4 mem_sharing: allow forking domain with IOMMU enabled
The memory sharing subsystem by default doesn't allow a domain to share memory
if it has an IOMMU active for obvious security reasons. However, when fuzzing a
VM fork, the same security restrictions don't necessarily apply. While it makes
no sense to try to create a full fork of a VM that has an IOMMU attached as only
one domain can own the pass-through device at a time, creating a shallow fork
without a device model is still very useful for fuzzing kernel-mode drivers.

By allowing the parent VM to initialize the kernel-mode driver with a real
device that's pass-through, the driver can enter into a state more suitable for
fuzzing. Some of these initialization steps are quite complex and are easier to
perform when a real device is present. After the initialization, shallow forks
can be utilized for fuzzing code-segments in the device driver that don't
directly interact with the device.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
2020-04-23 10:03:18 +02:00
Tamas K Lengyel c8dbdb32ce mem_sharing: reset a fork
Implement hypercall that allows a fork to shed all memory that got allocated
for it during its execution and re-load its vCPU context from the parent VM.
This allows the forked VM to reset into the same state the parent VM is in a
faster way then creating a new fork would be. Measurements show about a 2x
speedup during normal fuzzing operations. Performance may vary depending how
much memory got allocated for the forked VM. If it has been completely
deduplicated from the parent VM then creating a new fork would likely be more
performant.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
2020-04-08 13:03:50 +02:00
Tamas K Lengyel 41548c5472 mem_sharing: VM forking
VM forking is the process of creating a domain with an empty memory space and a
parent domain specified from which to populate the memory when necessary. For
the new domain to be functional the VM state is copied over as part of the fork
operation (HVM params, hap allocation, etc).

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Julien Grall <jgrall@amazon.com>
2020-04-08 12:59:58 +02:00
Tamas K Lengyel c1739b8ccd x86/p2m: Allow p2m_get_page_from_gfn to return shared entries
The owner domain of shared pages is dom_cow, use that for get_page
otherwise the function fails to return the correct page under some
situations. The check if dom_cow should be used was only performed in
a subset of use-cases. Fixing the error and simplifying the existing check
since we can't have any shared entries with dom_cow being NULL.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
2020-02-21 13:22:55 +00:00
Tamas K Lengyel 2575d77a67 x86/mem_sharing: use default_access in add_to_physmap
When plugging a hole in the target physmap don't use the access permission
returned by __get_gfn_type_access as it is non-sensical (p2m_access_n) in
the use-case add_to_physmap was intended to be used in. It leads to vm_events
being sent out for access violations at unexpected locations. Make use of
p2m->default_access instead and document the ambiguity surrounding "hole"
types and corner-cases with custom mem_access being set on holes.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-02-05 13:53:14 +01:00
Tamas K Lengyel 3537448300 x86/hvm: introduce hvm_copy_context_and_params
Currently the hvm parameters are only accessible via the HVMOP hypercalls. In
this patch we introduce a new function that can copy both the hvm context and
parameters directly into a target domain.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-02-05 13:52:29 +01:00
Tamas K Lengyel 9b71d6a759 x86/mem_access: use __get_gfn_type_access in set_mem_access
Use __get_gfn_type_access instead of p2m->get_entry to trigger page-forking
when the mem_access permission is being set on a page that has not yet been
copied over from the parent.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-01-29 15:06:50 +01:00
Tamas K Lengyel 81a3080a3f x86/mem_sharing: replace MEM_SHARING_DEBUG with gdprintk
Using XENLOG_ERR level since this is only used in debug paths (ie. it's
expected the user already has loglvl=all set). Also use %pd to print the domain
ids.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2020-01-29 14:48:15 +01:00
Tamas K Lengyel 67de3c5df0 x86/mem_sharing: Skip xen heap pages in memshr nominate
Trying to share these would fail anyway, better to skip them early.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-01-24 10:28:56 +01:00
Tamas K Lengyel 72f8d45d69 x86/mem_sharing: enable mem_sharing on first memop
It is wasteful to require separate hypercalls to enable sharing on both the
parent and the client domain during VM forking. To speed things up we enable
sharing on the first memop in case it wasn't already enabled.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-01-24 10:28:22 +01:00
Tamas K Lengyel 96d4621f96 x86/mem_sharing: convert MEM_SHARING_DESTROY_GFN to a bool
MEM_SHARING_DESTROY_GFN is used on the 'flags' bitfield during unsharing.
However, the bitfield is not used for anything else, so just convert it to a
bool instead.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-01-24 10:27:35 +01:00
Tamas K Lengyel 1e470e1609 x86/mem_sharing: make add_to_physmap static and shorten name
It's not being called from outside mem_sharing.c

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-01-24 10:25:47 +01:00
Tamas K Lengyel 5a9185c395 x86/mem_sharing: use INVALID_MFN and p2m_is_shared in relinquish_shared_pages
While using _mfn(0) is of no consequence during teardown, INVALID_MFN is the
correct value that should be used.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2020-01-24 10:25:12 +01:00
Tamas K Lengyel 7f8d062d98 x86/mem_sharing: define mem_sharing_domain to hold some scattered variables
Create struct mem_sharing_domain under hvm_domain and move mem sharing
variables into it from p2m_domain and hvm_domain.

Expose the mem_sharing_enabled macro to be used consistently across Xen.

Remove some duplicate calls to mem_sharing_enabled in mem_sharing.c

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: George Dunlap <george.dunlap@citrix.com>
2020-01-24 10:24:18 +01:00
Tamas K Lengyel e6fcf0efe4 x86/mem_sharing: don't try to unshare twice during page fault
The page was already tried to be unshared in get_gfn_type_access. If that
didn't work, then trying again is pointless. Don't try to send vm_event again
either, simply check if there is a ring or not.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2020-01-24 10:21:16 +01:00
Tamas K Lengyel f268900fbc x86/mem_sharing: drop flags from mem_sharing_unshare_page
All callers pass 0 in.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Reviewed-by: Wei Liu <wl@xen.org>
Acked-by: George Dunlap <george.dunlap@citrix.com>
2020-01-24 10:19:42 +01:00
Tamas K Lengyel 26bcc12f3a x86/mem_sharing: make get_two_gfns take locks conditionally
During VM forking the client lock will already be taken.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: George Dunlap <george.dunlap@citrix.com>
2020-01-24 10:18:10 +01:00
Tamas K Lengyel ca14eba3cc x86/mem_sharing: cleanup code and comments in various locations
No functional changes.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
[Further cleanup]
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
2019-12-19 18:05:11 +00:00
Tamas K Lengyel e09aa1dbf3 tools/libxc: clean up memory sharing files
No functional changes.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com>
Acked-by: Wei Liu <wl@xen.org>
[Further cleanup]
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
2019-12-19 18:05:11 +00:00